mtx: Fix up the consoles and serial
authorAlan Cox <alan@linux.intel.com>
Sun, 14 Dec 2014 18:26:09 +0000 (18:26 +0000)
committerAlan Cox <alan@linux.intel.com>
Sun, 14 Dec 2014 18:26:09 +0000 (18:26 +0000)
We now have four tty devices, 1 is the 6845, 2 is the VDP, 3 and 4 the
serial ports. The serial isn't finished and the IRQ logic hasn't been tackled.

The keyboard works.

Kernel/platform-mtx/config.h
Kernel/platform-mtx/devtty.c
Kernel/platform-mtx/devtty.h
Kernel/platform-mtx/mtx.s
Kernel/platform-mtx/vdp.s

index e4364b5..a17889d 100644 (file)
@@ -12,6 +12,8 @@
 #define CONFIG_CPM_EMU
 /* Video terminal, not a serial tty */
 #define CONFIG_VT
+/* Multiple VT support */
+#define CONFIG_VT_MULTI
 /* Fixed banking */
 #define CONFIG_BANK_FIXED
 /* 10 48K banks, 1 is kernel */
@@ -39,7 +41,7 @@
 #define CMDLINE        NULL      /* Location of root dev name */
 
 /* Device parameters */
-#define NUM_DEV_TTY 2  /* Will be 4 two monitors, two serial */
+#define NUM_DEV_TTY 4  /* Will be 4 two monitors, two serial */
 
 #define TTYDEV   BOOT_TTY /* Device used by kernel for messages, panics */
 #define SWAPDEV  ((8*256) + 0)  /* Device for swapping. - first silicon disk */
@@ -47,7 +49,7 @@
 #define NMOUNTS         4        /* Number of mounts at a time */
 
 /* Terminal definitions */
-#define VT_WIDTH       40
+#define VT_WIDTH       vt_twidth[curtty]
 #define VT_HEIGHT      24
-#define VT_RIGHT       39
+#define VT_RIGHT       vt_tright[curtty]
 #define VT_BOTTOM      23
index 12ae04b..2b59a3c 100644 (file)
@@ -9,17 +9,30 @@
 #undef  DEBUG                  /* UNdefine to delete debug code sequences */
 
 __sfr __at 0x0C serialAd;
-__sfr __at 0x0D serialAc;
-__sfr __at 0x0E serialBd;
+__sfr __at 0x0D serialBd;
+__sfr __at 0x0E serialAc;
 __sfr __at 0x0F serialBc;
 
+__sfr __at 0x09 ctc1;
+__sfr __at 0x0A ctc2;
+
+signed char vt_twidth[2] = { 80, 40 };
+signed char vt_tright[2] = { 79, 39 };
+uint8_t curtty;                /* output side */
+uint8_t inputtty;      /* input side */
+static struct vt_switch ttysave[2];
+
 char tbuf1[TTYSIZ];
 char tbuf2[TTYSIZ];
+char tbuf3[TTYSIZ];
+char tbuf4[TTYSIZ];
 
 struct s_queue ttyinq[NUM_DEV_TTY + 1] = {     /* ttyinq[0] is never used */
        {NULL, NULL, NULL, 0, 0, 0},
        {tbuf1, tbuf1, tbuf1, TTYSIZ, 0, TTYSIZ / 2},
-       {tbuf2, tbuf2, tbuf2, TTYSIZ, 0, TTYSIZ / 2}
+       {tbuf2, tbuf2, tbuf2, TTYSIZ, 0, TTYSIZ / 2},
+       {tbuf3, tbuf3, tbuf3, TTYSIZ, 0, TTYSIZ / 2},
+       {tbuf4, tbuf4, tbuf4, TTYSIZ, 0, TTYSIZ / 2}
 };
 
 /* tty1 is the screen tty2 is the debug port */
@@ -29,39 +42,81 @@ void kputchar(char c)
 {
        /* Debug port for bringup */
        if (c == '\n')
-               tty_putc(2, '\r');
-       tty_putc(2, c);
+               tty_putc(1, '\r');
+       tty_putc(1, c);
 }
 
-/* Both console and debug port are always ready */
 bool tty_writeready(uint8_t minor)
 {
-       minor;
-       return 1;
+       uint8_t reg = 0xFF;
+       if (minor == 3)
+               reg = serialAc;
+       if (minor == 4)
+               reg = serialBc;
+       return reg & 4;
 }
 
 void tty_putc(uint8_t minor, unsigned char c)
 {
        minor;
 
-       if (minor == 1) {
+       if (minor < 3) {
+               if (curtty != minor - 1) {
+                       vt_save(&ttysave[curtty]);
+                       curtty = minor - 1;
+                       vt_load(&ttysave[curtty]);
+               }
                vtoutput(&c, 1);
                return;
        }
-       serialAd = c;
+       if (minor == 3)
+               serialAd = c;
+       else
+               serialBd = c;
 }
 
 int tty_carrier(uint8_t minor)
 {
-       minor;
-       return 1;
+       uint8_t reg = 0xFF;
+       if (minor == 3)
+               reg = serialAc;
+       if (minor == 4)
+               reg = serialBc;
+       return (reg & 8) ? 1 : 0;
 }
 
+static uint8_t dart_setup[] = {
+       1, 0x19,
+       2, 0x00,
+       3, 0xC1,        /* 8bit */
+       4, 0x04,        /* 8N1 */
+       5, 0x72,        /* Tx 8bit, enabled, rts on */
+};
+
 void tty_setup(uint8_t minor)
 {
-       minor;
+       irqflags_t flags;
+       int i;
+       char *p = dart_setup;
+
+       if (minor == 1) {
+               ctc1 = 0x7F;
+               ctc1 = 0x02;    /* FIXME set by baud rate */
+       } else {
+               ctc2 = 0x7F;
+               ctc2 = 0x02;
+       }
+       flags = di();
+       for (i = 0; i < 10; i++) {
+               if (minor == 3)
+                       serialAc = *p++;
+               else
+                       serialBc = *p++;
+       }
+       irqrestore(flags);
 }
 
+
 static uint16_t keymap[8];
 static uint16_t keyin[8];
 static uint8_t keybyte, keybit;
@@ -108,9 +163,9 @@ static void keyproc(void)
 }
 
 static uint8_t keyboard[8][10] = {
-       {'1', '3', '5', '7', '9' , '-', '\\', 0/*page */, 3/*brk*/, 0/*f1*/},
+       {'1', '3', '5', '7', '9' , '-', '\\', 0/*page */, 3/*brk*/, 0xF1/*f1*/},
        { 27, '2', '4', '6', '8', '0', '^', 0/*eol*/, 8, 0/*f5*/},
-       { 0/*ctrl*/, 'w', 'r', 'y', 'i', 'p', '[', 0/*up*/, 9, 0/*f2*/ },
+       { 0/*ctrl*/, 'w', 'r', 'y', 'i', 'p', '[', 0/*up*/, 9, 0xF2/*f2*/ },
        {'q', 'e', 't' , 'u', 'o', '@', 10, 8/*left*/, 127, 0 /* f6 */ },
        { 0/*capsl*/, 's', 'f', 'h', 'k', ';', ']', 0/*right*/, 0, 0/*f7*/ },
        { 'a', 'd', 'g', 'j', 'l', ':', 13, 12/*home*/, 0, 0 /*f3 */ },
@@ -135,6 +190,13 @@ static void keydecode(void)
 {
        uint8_t c;
 
+       if ((keybyte == 0xF1 || keybyte == 0xF2)
+                                       && inputtty != keybyte - 0xF1) {
+               inputtty = keybyte - 0xF1;
+               vt_save(&ttysave[inputtty]);
+               vt_load(&ttysave[inputtty]);
+               return;
+       }
        if (keybyte == 4 && keybit == 0) {
                capslock = 1 - capslock;
                return;
@@ -150,7 +212,7 @@ static void keydecode(void)
        }
        if (capslock && c >= 'a' && c <= 'z')
                c -= 'a' - 'A';
-       tty_inproc(1, c);
+       tty_inproc(inputtty + 1, c);
 }
 
 void kbd_interrupt(void)
@@ -161,6 +223,27 @@ void kbd_interrupt(void)
                keydecode();
 }
 
+void serial_interrupt(void)
+{
+       uint8_t r;
+
+       r = serialAc;
+       if (r & 0x02) {
+               while (r & 0x01) {
+                       r = serialAd;
+                       tty_inproc(3, r);
+                       r = serialAc;
+               }
+               r = serialBc;
+               while (r & 0x01) {
+                       r = serialBd;
+                       tty_inproc(4, r);
+                       r = serialBc;
+               }
+       }
+       serialAc = 0x07 << 3;   /* Return from interrupt */
+}
+
 /* This is used by the vt asm code, but needs to live in the kernel */
 uint16_t cursorpos;
 
index f3fa258..dc0e2a6 100644 (file)
@@ -3,4 +3,8 @@
 
 extern void kbd_interrupt(void);
 
+extern signed char vt_twidth[2];
+extern signed char vt_tright[2];
+extern uint8_t curtty;
+
 #endif
index d8fbcf1..5a14ec8 100644 (file)
@@ -65,9 +65,28 @@ _trap_reboot:
 ; -----------------------------------------------------------------------------
 ; KERNEL MEMORY BANK (below 0xC000, only accessible when the kernel is mapped)
 ; -----------------------------------------------------------------------------
+
+           .area _CONST
+crtcmap:
+           .db    0x77, 0x50, 0x5c, 0x09, 0x1e, 0x03, 0x18, 0x1b
+           .db    0x00, 0x09, 0x60, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00
+
             .area _CODE
 
 init_early:
+;
+;      Bring up the 80 column card early so it can be used for debug
+;
+           ld hl, #crtcmap
+           xor a
+           ld bc, #0x1139              ; 17 commands to port 0x38/39
+init6845:
+           dec c
+           out (c), a
+           inc c
+           inc a
+           outi
+           jr nz, init6845
             ret
 
 init_hardware:
@@ -92,7 +111,15 @@ init_hardware:
             ; 09 is channel 1, output for DART ser 0 } fed 4MHz/13
             ; 0A is channel 2, output for DATA ser 1 }
            ; 0B is channel 3, counting CSTTE edges (cpu clocks) at 4MHz
-           ; 0C-0F are A data, B data, A ctrl, B ctrl 
+
+           xor a
+           out (0x08), a               ; vector 0
+           ld a, #0x97
+           out (0x08), a               ; CTC 0 as our IRQ source
+           ld a, #0x05
+           out (0x08), a               ; Timer constant (gives us 10Hz)
+                                       ; should be 0x06 for NTSC boxes
+                                       ; FIXME - how to tell ?
 
             im 1 ; set CPU interrupt mode
 
@@ -185,7 +212,7 @@ map_kernel:
            push af
            ld a, #0x80         ; ROM off bank 0
            ; the map port is write only, so keep a local stash
-           ld (map_save), a
+           ld (map_copy), a
            out (0), a
            pop af
             ret
index dd7dd3b..44c6b8f 100644 (file)
@@ -5,9 +5,122 @@
 
            .include "../dev/vdp1.s"
 
+           .globl _curtty
+           .globl _scroll_up
+           .globl _scroll_down
+           .globl _clear_across
+           .globl _clear_lines
+           .globl _cursor_off
+           .globl _cursor_on
+           .globl _plot_char
+
+
+;
+;      Don't provide the global vt hooks in vdp1.s, we want to wrap them
+;      for our dual monitor setup
+;
+VDP_DIRECT   equ       0
 
            .area _COMMONMEM
 
+;
+;      Turn co-ordinates D,E into offset HL
+;
+videopos6:
+            ld a, e
+            add a
+            add a
+            add a                      ; x 8 (max 24 x 8 - 192)
+            ld l, a
+            ld h, #0
+            add hl, hl                 ; x 16
+            push hl
+            add hl, hl                 ; x 32
+            add hl, hl                 ; x 64
+            ld a, d
+            pop de                     ; + x 16 = x 80
+            add hl, de
+            ld e, a
+            ld d, #0
+            add hl, de                 ; and X
+            ret
+
+
+;
+;      This is a bit different as we support both the vdp1 and the 6845
+; port
+;
+
+_cursor_on:  ld a, (_curtty)
+            or a
+            jp nz,  cursor_on          ; VDP
+            pop hl
+            pop de
+            push de
+            push hl
+            call videopos6
+            ld a, #14
+            ld c, #0x39
+            out (0x38), a
+            out (c), h
+            inc a
+            out (0x38), a
+            out (c), l
+            ret
+
+_cursor_off: ld a, (_curtty)
+            or a
+            jp nz, cursor_off          ; VDP
+            ret
+
+_clear_across:
+            ld a, (_curtty)
+            or a
+            jp nz, clear_across
+            ret
+
+_clear_lines:
+            ld a, (_curtty)
+            or a
+            jp nz, clear_lines
+            ret
+
+_scroll_up:  ld a, (_curtty)
+            or a
+            jp nz, scroll_up
+            ret
+
+_scroll_down:
+            ld a, (_curtty)
+            or a
+            jp nz, scroll_down
+            ret
+
+_plot_char:
+            ld a, (_curtty)
+            or a
+            jp nz, plot_char
+            ; Plot via 6845
+            pop hl
+            pop de                     ; D = x E = y
+            pop bc
+            push bc
+            push de
+            push hl
+            ld a, c                    ; char
+            out (0x32), a
+            ld a, #0x7                 ; white on black
+            out (0x33), a
+            call videopos6
+            ld a, h
+            or #0xE0                   ; write
+            out (0x31), a
+            ld a,l
+            out (0x30), a
+            ret
+
+
+;
 ;
 ;      FIXME: should use vdpport, but right now vdpport is in data not
 ;      common space.