mtx: Clean up the port and tidy loose ends
authorAlan Cox <alan@linux.intel.com>
Mon, 15 Dec 2014 22:45:52 +0000 (22:45 +0000)
committerAlan Cox <alan@linux.intel.com>
Mon, 15 Dec 2014 22:45:52 +0000 (22:45 +0000)
Memory sizing
DART setup
Better CTC configuration
Use IM2 so we can tell CTC and DART interrupts apart

Kernel/platform-mtx/devfd.c
Kernel/platform-mtx/devices.c
Kernel/platform-mtx/devtty.c
Kernel/platform-mtx/devtty.h
Kernel/platform-mtx/main.c
Kernel/platform-mtx/mtx.s

index 23e5658..7e124a8 100644 (file)
@@ -48,7 +48,7 @@ static int fd_transfer(uint8_t minor, bool is_read, uint8_t rawflag)
     dptr = (uint16_t)udata.u_buf->bf_data;
     block = udata.u_buf->bf_blk;
 
-    kprintf("Issue command: drive %d block %d\n", minor, block);
+//    kprintf("Issue command: drive %d block %d\n", minor, block);
     cmd[0] = is_read ? FD_READ : FD_WRITE;
     cmd[1] = block / 16;               /* 2 sectors per block */
     cmd[2] = ((block & 15) << 1); /* 0 - 1 base is corrected in asm */
@@ -58,7 +58,7 @@ static int fd_transfer(uint8_t minor, bool is_read, uint8_t rawflag)
 
     while (ct < 2) {
         for (tries = 0; tries < 4 ; tries++) {
-            kprintf("Sector: %d Track %d\n", cmd[2]+1, cmd[1]);
+//            kprintf("Sector: %d Track %d\n", cmd[2]+1, cmd[1]);
             err = fd_operation(cmd, driveptr);
             if (err == 0)
                 break;
index 8fa0f48..48ec6d8 100644 (file)
@@ -17,7 +17,7 @@ struct devsw dev_tab[] =  /* The device driver switch table */
   /* 1: /dev/hd                Hard disc block devices (hdx - not supported yet) */
   {  no_open,      no_close,    no_rdwr,  no_rdwr,   no_ioctl   },
   /* 2: /dev/tty       TTY devices */
-  {  tty_open,     tty_close,   tty_read, tty_write,  tty_ioctl },
+  {  tty_open,     mtxtty_close,tty_read, tty_write,  tty_ioctl },
   /* 3: /dev/lpr       Printer devices */
   {  lpr_open,     lpr_close,   no_rdwr,  lpr_write,  no_ioctl  },
   /* 4: /dev/mem etc   System devices (one offs) */
index 2b59a3c..6f50f46 100644 (file)
@@ -87,10 +87,20 @@ int tty_carrier(uint8_t minor)
 
 static uint8_t dart_setup[] = {
        1, 0x19,
-       2, 0x00,
-       3, 0xC1,        /* 8bit */
-       4, 0x04,        /* 8N1 */
-       5, 0x72,        /* Tx 8bit, enabled, rts on */
+       2, 0x04,        /* Vector */
+       3, 0x00,
+       4, 0x00,
+       5, 0x00,
+};
+
+/* Baud rates for Z80 DART */
+static uint8_t dartbaud[] = {
+       0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x80, 0x40, 0x20,
+       0x10, 0x08, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00
+};
+
+static uint8_t dartbits[] = {
+       0x00, 0x40, 0x80, 0xC0
 };
 
 void tty_setup(uint8_t minor)
@@ -98,13 +108,36 @@ void tty_setup(uint8_t minor)
        irqflags_t flags;
        int i;
        char *p = dart_setup;
+       struct tty *t = &ttydata[minor];
+       uint8_t cf = t->termios.c_cflag;
+       uint8_t r;
+
+       if ((cf & CBAUD) < B150) {
+               cf &= ~CBAUD;
+               cf |= B150;
+       }
+       if ((cf & CBAUD) > B19200) {
+               cf &= ~CBAUD;
+               cf |= B19200;
+       }
+       r = dartbits[(cf & CSIZE) >> 4];
+       dart_setup[5] = 0x01 | r;
+       dart_setup[9] = 0x8A | r >> 1;
+       r = 0x04;
+       if (cf & PARENB) {
+               r |= 1;
+               if (!(cf & PARODD))
+                       r|=2;
+       }
+       dart_setup[7] = r;
+       dart_setup[7] = r;
 
        if (minor == 1) {
-               ctc1 = 0x7F;
-               ctc1 = 0x02;    /* FIXME set by baud rate */
+               ctc1 = 0x45;
+               ctc1 = dartbaud[cf & CBAUD];
        } else {
-               ctc2 = 0x7F;
-               ctc2 = 0x02;
+               ctc2 = 0x45;
+               ctc1 = dartbaud[cf & CBAUD];
        }
        flags = di();
        for (i = 0; i < 10; i++) {
@@ -116,6 +149,23 @@ void tty_setup(uint8_t minor)
        irqrestore(flags);
 }
 
+int mtxtty_close(uint8_t minor)
+{
+       irqflags_t flags;
+       int err = tty_close(minor);
+
+       flags = di();
+       if (minor == 3) {
+               serialAc = 0x05;
+               serialAc = 0x00;        /* Drop DTR/RTS */
+       }
+       if (minor == 4) {
+               serialBc = 0x05;
+               serialBc = 0x00;        /* Drop DTR/RTS */
+       }
+       irqrestore(flags);
+       return err;
+}
 
 static uint16_t keymap[8];
 static uint16_t keyin[8];
@@ -223,7 +273,7 @@ void kbd_interrupt(void)
                keydecode();
 }
 
-void serial_interrupt(void)
+void tty_interrupt(void)
 {
        uint8_t r;
 
@@ -234,14 +284,18 @@ void serial_interrupt(void)
                        tty_inproc(3, r);
                        r = serialAc;
                }
+               if (!(r & 0x08))
+                       tty_carrier_drop(3);
                r = serialBc;
                while (r & 0x01) {
                        r = serialBd;
                        tty_inproc(4, r);
                        r = serialBc;
                }
+               serialAc = 0x07 << 3;   /* Return from interrupt */
+               if (!(r & 0x08))
+                       tty_carrier_drop(4);
        }
-       serialAc = 0x07 << 3;   /* Return from interrupt */
 }
 
 /* This is used by the vt asm code, but needs to live in the kernel */
index dc0e2a6..0ddb268 100644 (file)
@@ -2,6 +2,8 @@
 #define __DEVTTY_DOT_H__
 
 extern void kbd_interrupt(void);
+extern void tty_interrupt(void);
+extern int mtxtty_close(uint8_t);
 
 extern signed char vt_twidth[2];
 extern signed char vt_tright[2];
index 8557082..0c1a7fd 100644 (file)
@@ -6,29 +6,37 @@
 
 uint16_t ramtop = PROGTOP;
 uint16_t vdpport = 0x02 + 256 * 40;    /* port and width */
+uint8_t membanks;
 
 void pagemap_init(void)
 {
  int i;
- /* Ten banks (should check memory size) FIXME */
- for (i = 0x81; i < 0x8A; i++)
+ /* Up to ten banks */
+ for (i = 0x81; i <= membanks; i++)
   pagemap_add(i);
 }
 
 /* On idle we spin checking for the terminals. Gives us more responsiveness
-   for the polled ports */
+   for the polled ports. We don't need this on MTX, but we probably do for
+   MEMU */
+
 void platform_idle(void)
 {
-  /* We don't want an idle poll and IRQ driven tty poll at the same moment */
   irqflags_t irq = di();
-//  tty_pollirq(); 
+  tty_interrupt();
   irqrestore(irq);
 }
 
 void platform_interrupt(void)
 {
- kbd_interrupt();
- timer_interrupt();
+  extern uint8_t irqvector;
+
+  if (irqvector == 1) {
+    tty_interrupt();
+    return;
+  }
+  kbd_interrupt();
+  timer_interrupt();
 }
 
 /* Nothing to do for the map of init */
index f4aa211..789f53f 100644 (file)
@@ -22,6 +22,7 @@
            .globl _sil_memcpy
 
            .globl _kernel_flag
+           .globl _irqvector
 
             ; exported debugging tools
             .globl _trap_monitor
@@ -30,6 +31,7 @@
             ; imported symbols
             .globl _ramsize
             .globl _procmem
+           .globl _membanks
 
            .globl unix_syscall_entry
             .globl null_handler
 ; COMMON MEMORY BANK (0xC000 upwards)
 ; -----------------------------------------------------------------------------
             .area _COMMONMEM
+;
+;      This is linked straight after the udata block so is 256 byte
+; aligned. Put the im2 table first
+;
+            .globl intvectors
+
+intvectors:
+           .dw ctc0_int        ; VDP counting timer
+           .dw bogus_int       ; Baud generator
+           .dw bogus_int       ; Baud generator
+           .dw trace_int       ; can be used for CPU tracing etc
+           .dw serial_int      ; we don't use the vector mod functions
 
 _trap_monitor:
            di
@@ -63,6 +77,54 @@ _trap_reboot:
            out (0),a           ; ROM mode, we are in common so survive
            rst 0               ; kaboom
 
+_irqvector:
+           .db 0               ; used to identify the vector in question
+
+ctc0_int:   push af
+           xor a
+           ld (_irqvector), a
+           pop af
+           jp interrupt_handler
+trace_int:
+bogus_int:  reti
+serial_int:
+           push af
+           ld a, #1
+           ld (_irqvector), a
+           pop af
+           jp interrupt_handler
+
+; Kernel is in 0x80 so we just need to count the banks that differ
+size_ram:
+           ld hl, #0x1000      ; good as anywhere
+           ld bc, #0x8100      ; port 0 in c, b = 0x81
+size_next:
+           out (c), b
+           ld a, #0xA5
+           ld (hl), a
+           cp (hl)
+           jr nz, size_nonram
+           cpl
+           ld (hl), a
+           cp (hl)
+           jr nz, size_nonram
+           inc b
+           ld a, #0x8B
+           cp b
+           jr nz, size_next    ; All banks done
+size_nonram:
+           ld a, #0x80
+           out (c), a          ; Return to kernel
+           res 7,b             ; Clear the flag so we just have banks
+           dec b               ; Last valid bank
+           ld a, b
+           ld (_membanks), a
+           ld hl, #0
+           ld de, #48
+sizer:     add hl, de
+           djnz sizer
+           ret
+
 ; -----------------------------------------------------------------------------
 ; KERNEL MEMORY BANK (below 0xC000, only accessible when the kernel is mapped)
 ; -----------------------------------------------------------------------------
@@ -91,11 +153,12 @@ init6845:
             ret
 
 init_hardware:
+           call size_ram
            ; FIXME: do proper size checker
             ; set system RAM size (hardcoded for now)
-            ld hl, #480
             ld (_ramsize), hl
-            ld hl, #(480-48)           ; 64K for kernel
+           and a
+           sbc hl, de                  ; DE will hold 48 at this point
             ld (_procmem), hl
 
             ; set up interrupt vectors for the kernel (also sets up common memory in page 0x000F which is unused)
@@ -107,20 +170,22 @@ init_hardware:
            ; Program the video engine
            call vdpinit
 
-           ; FIXME: set up interrupt timer on the CTC
-           ; 08 is channel 0, which is input for vdp
+           ; 08 is channel 0, which is input from VDP
             ; 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
 
            xor a
            out (0x08), a               ; vector 0
-           ld a, #0xA5
+           ld a, #0xC5
            out (0x08), a               ; CTC 0 as our IRQ source
-           ld a, #0xFC
+           ld a, #0x01
            out (0x08), a               ; Timer constant
 
-            im 1 ; set CPU interrupt mode
+           ld hl, #intvectors          ; Work around SDCC crappiness
+           ld a, h
+           ld i, a
+            im 2 ; set CPU interrupt mode
 
            call _vtinit                ; init the console video