From be2b1200b3adf755b2908f3e7d8933e38b0ecd9a Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sat, 17 Nov 2018 15:42:02 +0000 Subject: [PATCH] sam: add graphics mode switching logic --- Kernel/platform-sam/devices.c | 2 +- Kernel/platform-sam/devtty.c | 110 ++++++++++++++++++++++++++++++---- Kernel/platform-sam/devtty.h | 2 + 3 files changed, 103 insertions(+), 11 deletions(-) diff --git a/Kernel/platform-sam/devices.c b/Kernel/platform-sam/devices.c index ae794caa..b9a3274d 100644 --- a/Kernel/platform-sam/devices.c +++ b/Kernel/platform-sam/devices.c @@ -15,7 +15,7 @@ struct devsw dev_tab[] = /* The device driver switch table */ /* 1: /dev/fd Floppy disk block devices */ { fd_open, no_close, fd_read, fd_write, no_ioctl }, /* 2: /dev/tty TTY devices */ - { tty_open, tty_close, tty_read, tty_write, tty_ioctl }, + { tty_open, tty_close, tty_read, tty_write, gfx_ioctl }, /* 3: /dev/lpr Printer devices */ { lpr_open, lpr_close, no_rdwr, lpr_write, no_ioctl }, /* 4: /dev/mem etc System devices (one offs) */ diff --git a/Kernel/platform-sam/devtty.c b/Kernel/platform-sam/devtty.c index b59cf069..a5f4c6c6 100644 --- a/Kernel/platform-sam/devtty.c +++ b/Kernel/platform-sam/devtty.c @@ -4,9 +4,14 @@ #include #include #include +#include #include #include +static uint8_t vmode = 2; + +__sfr __at 252 vmpr; + static char tbuf1[TTYSIZ]; static char tbuf2[TTYSIZ]; @@ -46,8 +51,10 @@ uint8_t tty_writeready(uint8_t minor) void tty_putc(uint8_t minor, unsigned char c) { - if (minor == 1) - vtoutput(&c, 1); + if (minor == 1) { + if (vmode == 2) + vtoutput(&c, 1); + } } void tty_interrupt(void) @@ -77,7 +84,7 @@ static uint8_t keybyte, keybit; static uint8_t newkey; static int keysdown = 0; static uint8_t shiftmask[9] = { - 0x80, 0, 0, 0, 0, 0, 0, 0x40, 0x80, + 0x01, 0, 0, 0, 0, 0, 0, 0x02, 0x01 }; static void keyproc(void) @@ -98,11 +105,12 @@ static void keyproc(void) keysdown--; } if ((key & m) && !(keymap[i] & m)) { - if (!(shiftmask[i] & m)) + if (!(shiftmask[i] & m)) { keysdown++; - keybyte = i; - keybit = n; - newkey = 1; + keybyte = i; + keybit = n; + newkey = 1; + } } m += m; @@ -178,6 +186,7 @@ static void keydecode(void) /* We don't do anything clever for both shifts or other weird combos This computer isn't going to run emacs after all */ + if (keymap[7] & 0x02) /* Symbol Shift */ c = altkeyboard[keybyte][keybit]; else if (keymap[0] & 0x01) @@ -189,15 +198,13 @@ static void keydecode(void) capslock = 1 - capslock; return; } - /* The keyboard lacks some rather important symbols so remap them - with control */ if (keymap[8] & 0x01) { /* control */ /* These map the SAM specific behaviours */ if (c == KEY_LEFT) c = KEY_HOME; else if (c == KEY_RIGHT) c = KEY_END; - else if (c > 31 && c < 96) + else c &= 31; } if (capslock && c >= 'a' && c <= 'z') @@ -223,3 +230,86 @@ void kbd_interrupt(void) } } +/* + * Graphics routines. Not yet very useful. + */ + +/* Should be const but then some sdcc's put it in the wrong segment */ +static struct display samdisplay[4] = { + /* Mode 1 (0 to us): Spectrum mode */ + { + 0, + 256, 192, + 256, 192, + 0xFF, 0xFF, + FMT_SPECTRUM, + HW_UNACCEL, + GFX_VBLANK, /* Deal with palette later */ + 0, /* To be added */ + }, + /* Mode 2 (attribute per character row mode) */ + { + 1, + 256, 192, + 256, 192, + 0xFF, 0xFF, + FMT_SAM2, + HW_UNACCEL, + GFX_VBLANK, + 0, + }, + /* Mode 3 (512 x 192 4 2bp) */ + { + 2, + 512, 192, + 512, 192, + 0xFF, 0xFF, + FMT_COLOUR4, + HW_UNACCEL, + GFX_VBLANK|GFX_TEXT, + 0, + }, + /* Mode 4 (256 x 192 16 colour) */ + { + 3, + 256, 192, + 256, 192, + 0xFF, 0xFF, + FMT_COLOUR16, + HW_UNACCEL, + GFX_VBLANK, + 0, + } +}; + +/* + * Graphics ioctls. At minimum we need to extend this to support + * GETPALETTE/SETPALETTE and some read/write/copy ops as we can't + * sanely map the video into a user process. + * + * We keep the full 24K allocated in a fixed place. When we switch modes + * we don't try and do any clever reclaiming. + */ +int gfx_ioctl(uint8_t minor, uarg_t arg, char *ptr) +{ + uint8_t m; + if (minor != 1 || arg >> 8 != 0x03) + return vt_ioctl(minor, arg, ptr); + switch(arg) { + case GFXIOC_GETINFO: + return uput(&samdisplay[vmode], ptr, sizeof(struct display)); + case GFXIOC_GETMODE: + case GFXIOC_SETMODE: + m = ugetc(ptr); + if (m > 3) { + udata.u_error = EINVAL; + return -1; + } + if (arg == GFXIOC_GETMODE) + return uput(&samdisplay[m], ptr, sizeof(struct display)); + vmode = m; + vmpr = (vmpr & 0x9F) | (m << 5); + return 0; + } + return -1; +} diff --git a/Kernel/platform-sam/devtty.h b/Kernel/platform-sam/devtty.h index d1831cfe..d011b945 100644 --- a/Kernel/platform-sam/devtty.h +++ b/Kernel/platform-sam/devtty.h @@ -12,4 +12,6 @@ extern uint8_t keymap[9]; extern uint8_t keyboard[9][8]; extern uint8_t shiftkeyboard[9][8]; +extern int gfx_ioctl(uint8_t minor, uarg_t arg, char *ptr); + #endif -- 2.34.1