ubee: further updates
authorAlan Cox <alan@linux.intel.com>
Sun, 6 May 2018 22:42:41 +0000 (23:42 +0100)
committerAlan Cox <alan@linux.intel.com>
Sun, 6 May 2018 22:42:41 +0000 (23:42 +0100)
At this point 256TC seems to be reasonably solid. The 128K boots to the point
it runs out of memory (not swap tested yet). The 256/512 hang somewhere after
doing a bit of forking.

Kernel/platform-ubee/README
Kernel/platform-ubee/devhd.c
Kernel/platform-ubee/devhd.h
Kernel/platform-ubee/devices.c
Kernel/platform-ubee/devlpr.c
Kernel/platform-ubee/discard.c
Kernel/platform-ubee/kernel.def
Kernel/platform-ubee/main.c
Kernel/platform-ubee/ubee.h
Kernel/platform-ubee/ubee.s

index b612786..4cce871 100644 (file)
@@ -29,12 +29,23 @@ Then run either
 
        ubee512 --model=256tc -a fuzix.ss80 -b root.ds82
        ubee512 --model=p512k -a fuzix.ss80 -b root.ds82
-       ubee512 --model=p128k -a fuzix.ss80 -b root.ds82 --rtc=1
+       ubee512 --model=p128k -a fuzix.ss80 -b root.ds82 --rtc=1 --piob7=rtc
 
 (as an RTC is required).
 
 and when asked for the root file system reply 1
 
+For a full on test of everything try something like
+
+ubee512 --model=p128k -a /tmp/fuzix.ss80 --hdd3=/tmp/root.ds82 --hdd0=$(pwd)/rootfs.hd3 --port58h --modio=+hdd --modio=+mem --rtc=1 --modio=+ide --piob7=rtc
+
+with a valid partitioned disk image including an 0x7F type partition that is
+512K or so for swap. The disk image needs to be a .hd3 type as the kernel right
+now assumes .hd3 geometry for ST506 drives (ie 62720 sectors)
+
+Don't expect the IDE to work - it may work on the real box but not the emulator.
+
+
 
 Done so far:
 
@@ -76,14 +87,15 @@ Done so far:
 - Bank the video
 - Debug TC keyboard code: shift/ctrl are busted
 - Non TC keyboard (lightpen keyboard)
-
-
-To Do:
-- Floppy - media detect/sectors per track etc/ hard skew
 - Hard disk driver debug
 - IDE driver (note the ubee512 emulator ide appears to be very busted as
   of 5.8.0)
 - If we have wd1002-5 and fd wtf do we put IDE in major/minors ?
+
+In Progress
+
+To Do:
+- Floppy - media detect/sectors per track etc/ hard skew
 - Fix reboot/panic logic
 - Keyboard repeat
 - Graphics not just vt interfaces
@@ -171,4 +183,4 @@ Currently in progress
 - Copy ROM font to RAM, support RAM font setting
 - Figure out how I broke the 6545 cursor               DONE
 
-Currently debugging scrolling
+Currently debugging scrolling, swap
index feffe65..68dbfcf 100644 (file)
@@ -20,6 +20,7 @@
 #include <printf.h>
 #include <devhd.h>
 #include <ubee.h>
+#include <blkdev.h>
 
 __sfr __at 0x40 hd_data;
 __sfr __at 0x41 hd_precomp;    /* W/O */
@@ -90,160 +91,173 @@ static uint8_t hd_waitidle(void)
        return st;
 }
 
-static uint8_t hd_xfer(bool is_read, uint16_t addr)
-{
-       /* Error ? */
-       if (hd_status & 0x01)
-               return hd_status;
-       if (is_read)
-               hd_xfer_in(addr);
-       else
-               hd_xfer_out(addr);
-       /* Should be returning READY, and maybe SEEKDONE */
-       return hd_status;
-}
-
 /*
- *     We only support normal block I/O for the moment. We do need to
- *     add swapping!
+ *     Transfer for routine for the WD1010 (ST-506) interface.
  */
 
-static int hd_transfer(uint8_t minor, bool is_read, uint8_t rawflag)
+static uint8_t hd_transfer_sector(void)
 {
-       uint16_t dptr;
-       uint16_t ct = 0;
-       int tries;
-       uint8_t err = 0;
-       uint8_t cmd = HDCMD_READ;
-       uint8_t head;
-       uint8_t sector;
-
-       if (rawflag) {
-               if (rawflag == 1) {
-                       if (d_blkoff(9))
-                               return -1;
-                       /* TODO */
-                       hd_page = 0xFF;
-               } else {
-                       hd_page = swappage;
-               }
+       uint8_t drive = blk_op.blkdev->driver_data & 0x0F;
+       uint8_t sel = !!(drive & 0x08);
+
+       uint32_t b;
+       uint8_t sector, head;
+       uint8_t err;
+       uint8_t tries;
+
+       drive &= 0x07;
+
+       b = blk_op.lba / spt[drive];
+       sector = blk_op.lba % spt[drive];
+       head = b % heads[drive];
+       b /= heads[drive];
+
+       fdc_devsel = sel;
+
+       if (drive < MAX_HD) {
+               /* ECC, 512 bytes, head and drive */
+               hd_sdh = 0xA0 | head | (drive << 3);
+       } else {
+               /* Floppy setup */
+               hd_fdcside = head;
+               /* CRC, 512 bytes, head (0/1), FDC unit, fdc number */
+               hd_sdh = 0x38 | head | ((drive - MAX_HD) << 1);
        }
+       hd_secnum = sector + 1;
+
+       /* cylinder bits */
+       hd_cyllo = b;
+       hd_cylhi = b >> 8;
 
-       dptr = (uint16_t)udata.u_dptr;
-
-       if (!is_read)
-               cmd = HDCMD_WRITE;
-
-       /* We don't touch precomp and hope the firmware set it right */
-       hd_seccnt = 1;
-       
-       /* Get rid of port 58 selector */
-       minor &= 0x7F;
-       /* Reserve low bits for future partition tables */
-       minor >>= 4;
-
-       while (ct < udata.u_nblock) {
-               uint16_t b = udata.u_block / spt[minor];
-               sector = udata.u_block % spt[minor];
-               head = b % heads[minor];
-               if (minor < MAX_HD) {
-                       /* ECC, 512 bytes, head and drive */
-                       hd_sdh = 0xA0 | head | (minor << 3);
+       for (tries = 0; tries < 4; tries++) {
+               /* issue the command */
+               hd_cmd = blk_op.is_read ? HDCMD_READ : HDCMD_WRITE;
+               err = 0;
+               /* Wait for busy to drop if reading before xfer */
+               if (blk_op.is_read) {
+                       hd_waitidle();
+                       hd_xfer_in();
+                       err = hd_status;
                } else {
-                       /* Floppy setup */
-                       hd_fdcside = head;
-                       /* CRC, 512 bytes, head (0/1), FDC unit, fdc number */
-                       hd_sdh = 0x38 | head | ((minor - MAX_HD) << 1);
+                       hd_xfer_out();
+                       /* Wait for busy to drop after xfer if writing */
+                       err = hd_waitidle();
+                       /* Ready, no error, not busy ? */
                }
-               hd_secnum = sector + 1;
-
-               /* cylinder bits */
-               b /= heads[minor];
-               hd_cyllo = b;
-               hd_cylhi = b >> 8;
-
-               for (tries = 0; tries < 4; tries++) {
-                       /* issue the command */
-                       hd_cmd = cmd;
-                       err = 0;
-                       /* Wait for busy to drop if reading before xfer */
-                       if (is_read) {
-                               hd_waitidle();
-                               err = hd_status;
-                       }
-                       if (!(err & 1)) {
-                               err = hd_xfer(is_read, dptr);
-                               /* Wait for busy to drop after xfer if writing */
-                               if (!is_read)
-                                       err = hd_waitidle();
-                               /* Ready, no error, not busy ? */
-                               if ((err & 0xC1) == 0x40)
-                                       break;
-                       } else
-                               kprintf("hd%d: err %x\n", minor, err);
-
-                       if (tries > 1) {
-                               hd_cmd = HDCMD_RESTORE;
-                               if (hd_waitready() & 1)
-                                       kprintf("hd%d: restore error %z\n", minor, err);
-                       }
+               if ((err & 0xC1) == 0x40)
+                       return 1;
+
+               kprintf("hd%d: err %x\n", drive, err);
+
+               if (tries > 1) {
+                       hd_cmd = HDCMD_RESTORE | RATE_6MS;
+                       if (hd_waitready() & 1)
+                               kprintf("hd%d: restore error %x\n", drive, err);
                }
-               if (tries == 3)
-                       goto bad;
-               ct++;
-               dptr += 512;
-               udata.u_block ++;
        }
-       return ct << BLKSHIFT;
-bad:
        if (err & 1)
-               kprintf("hd%d: error %x\n", minor, hd_err);
+               kprintf("hd%d: error %x\n", drive, hd_err);
        else
-               kprintf("hd%d: status %x\n", minor, err);
-bad2:
-       udata.u_error = EIO;
-       return -1;
+               kprintf("hd%d: status %x\n", drive, err);
+       return 0;
 }
 
-int hd_open(uint8_t minor, uint16_t flag)
+static void hd_init_drive(uint8_t drive)
 {
-       uint8_t sel = (minor & 0x80) ? 1 : 0;
-       flag;
-       
-       minor &= 0x7F;
-       /* Reserve low bits for future partition table support */
-       minor >>= 4;
-
-       if (disk_type[sel] != DISK_TYPE_HDC || minor >= MAX_HD + MAX_FDC) {
-               udata.u_error = ENODEV;
-               return -1;
-       }
+       blkdev_t *blk;
+       uint8_t sel = !!(drive & 0x08);
+
+       /* Only probe controllers that are present */
+       if (disk_type[sel] != DISK_TYPE_HDC)
+               return;
+
        fdc_devsel = sel;
-       if (minor <= MAX_HD) {
-               hd_sdh = 0xA0 | (minor << 3);
+
+       drive &= 0x07;
+
+       if (drive < MAX_HD) {
+               hd_sdh = 0xA0 | (drive << 3);
                hd_cmd = HDCMD_RESTORE | RATE_2MS;
        } else {
-               hd_sdh = 0x38 | ((minor - MAX_HD) << 1);
+               hd_sdh = 0x38 | ((drive - MAX_HD) << 1);
                hd_cmd = HDCMD_RESTORE | RATE_6MS;
        }
        if (hd_waitready() & 1) {
-               if ((hd_err & 0x12) == 0x12) {
-                       return -ENODEV;
-               }
+               if ((hd_err & 0x12) == 0x12)
+                       return;
        }
-       return 0;
+       /* Found */
+       blk = blkdev_alloc();
+       if (blk == NULL) {
+               kputs("hd: too many drives.\n");
+               return;
+       }
+       blk->transfer = hd_transfer_sector;
+       blk->flush = NULL;
+       blk->driver_data = drive | (sel << 3);
+       blk->drive_lba_count = 0xFFFFFF;
+       /* No partitions on floppy disks thank you */
+       if (drive < MAX_HD)
+               blkdev_scan(blk, SWAPSCAN);
 }
 
-int hd_read(uint8_t minor, uint8_t rawflag, uint8_t flag)
+void hd_init(void)
+{
+       uint8_t d;
+       /* 0 1 2 are hard disks, 3-7 floppy appearing as hd */
+       /* 8+ because we also need to scan the other slot if present */
+       for (d = 0; d < 15; d++)
+               hd_init_drive(d);
+}
+
+COMMON_MEMORY
+
+void hd_xfer_in(void) __naked
 {
-       flag;
-       fdc_devsel = (minor & 0x80) ? 1 : 0;
-       return hd_transfer(minor, true, rawflag);
+    __asm
+            ld a, (_blk_op+BLKPARAM_IS_USER_OFFSET) ; blkparam.is_user
+            ld hl, (_blk_op+BLKPARAM_ADDR_OFFSET)   ; blkparam.addr
+            ld bc, #0x40                           ; setup port number
+#ifdef SWAPDEV
+           cp #2
+            jr nz, not_swapin
+            ld a, (_blk_op+BLKPARAM_SWAP_PAGE)     ; blkparam.swap_page
+            call map_for_swap
+            jr swapin
+not_swapin:
+#endif
+            or a                                    ; test is_user
+            call nz, map_process_always             ; map user memory first if required
+swapin:
+            inir                                    ; transfer first 256 bytes
+            inir                                    ; transfer second 256 bytes
+            or a                                    ; test is_user
+            ret z                                   ; done if kernel memory transfer
+            jp map_kernel                           ; else map kernel then return
+    __endasm;
 }
 
-int hd_write(uint8_t minor, uint8_t rawflag, uint8_t flag)
+void hd_xfer_out(void) __naked
 {
-       flag;
-       fdc_devsel = (minor & 0x80) ? 1 : 0;
-       return hd_transfer(minor, false, rawflag);
+    __asm
+            ld a, (_blk_op+BLKPARAM_IS_USER_OFFSET) ; blkparam.is_user
+            ld hl, (_blk_op+BLKPARAM_ADDR_OFFSET)   ; blkparam.addr
+            ld bc, #0x40                           ; setup port number
+#ifdef SWAPDEV
+           cp #2
+            jr nz, not_swapout
+            ld a, (_blk_op+BLKPARAM_SWAP_PAGE)     ; blkparam.swap_page
+            call map_for_swap
+            jr swapout
+not_swapout:
+#endif
+            or a                                    ; test is_user
+            call nz, map_process_always             ; else map user memory first if required
+swapout:
+            otir                                    ; transfer first 256 bytes
+            otir                                    ; transfer second 256 bytes
+            or a                                    ; test is_user
+            ret z                                   ; done if kernel memory transfer
+            jp map_kernel                           ; else map kernel then return
+    __endasm;
 }
index 41200a7..c544f04 100644 (file)
@@ -2,12 +2,11 @@
 #define __DEVHD_DOT_H__
 
 /* public interface */
-int hd_read(uint8_t minor, uint8_t rawflag, uint8_t flag);
-int hd_write(uint8_t minor, uint8_t rawflag, uint8_t flag);
-int hd_open(uint8_t minor, uint16_t flag);
+static uint8_t hd_transfer_sector(void);
+void hd_init(void);
 
 /* helpers in common memory for the block transfers */
-int hd_xfer_in(uint16_t addr);
-int hd_xfer_out(uint16_t addr);
+static void hd_xfer_in(void);
+static void hd_xfer_out(void);
 
 #endif /* __DEVHD_DOT_H__ */
index 8f992a6..917343c 100644 (file)
@@ -7,20 +7,24 @@
 #include <devsys.h>
 #include <devlpr.h>
 #include <devtty.h>
+#include <blkdev.h>
+#include <devhd.h>
+#include <devide.h>
+#include <printf.h>
 #include <ubee.h>
 
 struct devsw dev_tab[] =  /* The device driver switch table */
 {
-  /* 0: /dev/fd                Floppy disc block devices */
-  {  fd_open,     no_close,     fd_read,   fd_write,   no_ioctl  },
-  /* 1: /dev/hd                Hard disc block devices */
-  {  hd_open,     no_close,     hd_read,   hd_write,   no_ioctl  },
+  /* 0: /dev/hd                Hard disc block devices */
+  {  blkdev_open, no_close,     blkdev_read,   blkdev_write,   blkdev_ioctl  },
+  /* 1: /dev/fd                Floppy disc 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,  gfx_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  },
+  {  lpr_open,    lpr_close,    no_rdwr,       lpr_write,      no_ioctl  },
   /* 4: /dev/mem etc   System devices (one offs) */
-  {  no_open,     no_close,     sys_read,  sys_write,  sys_ioctl },
+  {  no_open,     no_close,     sys_read,      sys_write,      sys_ioctl },
   /* Pack to 7 with nxio if adding private devices and start at 8 */
 };
 
@@ -33,17 +37,3 @@ bool validdev(uint16_t dev)
     else
         return true;
 }
-
-void device_init(void)
-{
-  int i;
-  /* Time of day clock */
-  inittod();
-  /* Figure out what disks we have */
-  diskprobe();
-  /* IDE */
-  devide_init();
-  /* Add 64 swaps (2MB) */
-  for (i = MAX_SWAPS - 1 ; i >= 0; i--)
-    swapmap_init(i);
-}
index 906a3e3..232fd70 100644 (file)
@@ -2,13 +2,14 @@
 #include <version.h>
 #include <kdata.h>
 #include <devlpr.h>
+#include <ubee.h>
 
 __sfr __at 0x00 lpdata;                /* I/O 0 PIO A data */
 
 int lpr_open(uint8_t minor, uint16_t flag)
 {
     used(flag);
-    if (minor) {
+    if (ubee_parallel != UBEE_PARALLEL_LPR || minor) {
         udata.u_error = ENODEV;
         return -1;
     }
@@ -48,6 +49,7 @@ int lpr_write(uint8_t minor, uint8_t rawflag, uint8_t flag)
         irqrestore(irq);
         lpready = 0;
         lpdata = ugetc(udata.u_base++);
+        udata.u_done++;
     }
     return udata.u_done;
 }
index 3cfe15f..6ea5593 100644 (file)
@@ -3,11 +3,16 @@
 #include <kdata.h>
 #include <printf.h>
 #include <devtty.h>
+#include <blkdev.h>
+#include <devide.h>
+#include <devhd.h>
 #include <ubee.h>
 
 __sfr __at 0x04 cmos_reg;
 __sfr __at 0x07 cmos_read;
 
+extern int strcmp(const char *, const char *);
+
 void has_cmos_rtc(void)
 {
        /* See if the week looks valid - probably want a stronger check */
@@ -115,6 +120,58 @@ void pagemap_init(void)
 
 uint8_t platform_param(char *p)
 {
-       used(p);
+       /* Q: do we need to remember we are running at 6.75MHz anywhere ? */
+       if (strcmp(p, "turbo") == 0) {
+               engage_warp_drive();
+               return 1;
+       }
+       if (strcmp(p, "joystick") == 0) {
+               ubee_parallel = UBEE_PARALLEL_JOYSTICK;
+               return 1;
+       }
+       if (strcmp(p, "beetalker") == 0) {
+               ubee_parallel = UBEE_PARALLEL_BEETALKER;
+               return 1;
+       }
+       if (strcmp(p, "beethoven") == 0) {
+               ubee_parallel = UBEE_PARALLEL_BEETHOVEN;
+               return 1;
+       }
+       if (strcmp(p, "dac") == 0) {
+               ubee_parallel = UBEE_PARALLEL_DAC;
+               return 1;
+       }
+       if (strcmp(p, "compumuse") == 0) {
+               ubee_parallel = UBEE_PARALLEL_COMPUMUSE;
+               return 1;
+       }
        return 0;
 }
+
+void platform_swap_found(uint8_t letter, uint8_t m)
+{
+  blkdev_t *blk = blk_op.blkdev;
+  uint16_t n;
+  if (swap_dev != 0xFFFF)
+    return;
+  letter -= 'a';
+  kputs("(swap) ");
+  swap_dev = letter << 4 | m;
+  n = blk->lba_count[m - 1] / SWAP_SIZE;
+  if (n > MAX_SWAPS)
+    n = MAX_SWAPS;
+  while(n)
+    swapmap_add(n--);
+}
+
+void device_init(void)
+{
+  /* Time of day clock */
+  inittod();
+  /* Figure out what disks we have */
+  diskprobe();
+  /* IDE */
+  devide_init();
+  /* ST506 */
+  hd_init();
+}
index b2d9ebc..d07a89f 100644 (file)
@@ -14,4 +14,4 @@ Z80_MMU_HOOKS             .equ 0
 
 CONFIG_SWAP                .equ 1
 
-NBUFS                      .equ 7
+NBUFS                      .equ 6
index 25466c4..44f7dc1 100644 (file)
@@ -5,7 +5,10 @@
 #include <devtty.h>
 #include <ubee.h>
 
+uint8_t ubee_parallel;
+
 uint16_t ramtop = PROGTOP;
+uint16_t swap_dev = 0xFFFF;
 
 /* On idle we spin checking for the terminals. Gives us more responsiveness
    for the polled ports */
@@ -37,6 +40,18 @@ uint8_t platform_rtc_secs(void)
        return cmos_read;
 }
 
+/*
+ *     PIA0 bit 7 is variously connected to
+ *     - RTC
+ *     - Vertical blank
+ *     - Net
+ *     - Nothing (well actually a pull up resistor)
+ *
+ *     On machines with a vertical blank connection we get a 50Hz timer
+ *     from the PIA transitions. On machines with an RTC then the RTC is
+ *     normally on the pia bit. We only care about the RTC because the
+ *     machines we support normally don't have a vblank rtc
+ */
 void platform_interrupt(void)
 {
        static uint8_t icount;
index a632368..1335087 100644 (file)
@@ -6,10 +6,22 @@ extern uint8_t ubee_model;
 #define UBEE_PREMIUM   1
 #define UBEE_256TC     2
 
+extern uint8_t ubee_parallel;
+#define UBEE_PARALLEL_LPR      0
+#define UBEE_PARALLEL_JOYSTICK 1
+#define UBEE_PARALLEL_BEETALKER        2
+#define UBEE_PARALLEL_BEETHOVEN        3
+#define UBEE_PARALLEL_DAC      4
+#define UBEE_PARALLEL_COMPUMUSE        5
+
 extern void diskprobe(void);
 extern uint8_t disk_type[2];
 #define DISK_TYPE_FDC  1       /* Standard FDC */
 #define DISK_TYPE_FDC_D        2       /* Dreamdisc */
 #define DISK_TYPE_HDC  3       /* WD fd/hd controller */
 
+/* Turn on the turbo if fitted. There is no way to check if this worked
+   except clever timing tricks so we trust the user */
+extern void engage_warp_drive(void);
+
 #endif
index 6486b90..1e29286 100644 (file)
            .globl platform_interrupt_all
            .globl _kernel_flag
 
-           ; hard disk helpers
-           .globl _hd_xfer_in
-           .globl _hd_xfer_out
-           ; and the page from the C code
-           .globl _hd_page
-
             ; exported debugging tools
             .globl _platform_monitor
             .globl _platform_reboot
@@ -423,37 +417,6 @@ map_restore:
 outchar:
             ret
 
-;
-;      Swap helpers
-;
-_hd_xfer_in:
-           pop de
-           pop hl
-           push hl
-           push de
-           ld a, (_hd_page)
-           or a
-           call nz, map_process_a
-           ld bc, #0x40                        ; 512 bytes from 0x40
-           inir
-           inir
-           call map_kernel
-           ret
-
-_hd_xfer_out:
-           pop de
-           pop hl
-           push hl
-           push de
-           ld a, (_hd_page)
-           or a
-           call nz, map_process_a
-           ld bc, #0x40                        ; 512 bytes to 0x40
-           otir
-           otir
-           call map_kernel
-           ret
-
 ;
 ;      Ubee Keyboard. Except for the TC the Ubee pulls this crazy (or neat
 ;      depending how you look at it) trick of demuxing a keyboard with the
@@ -796,3 +759,13 @@ _vtcount:   .word 0
 _vtattrib:  .word 0
 _vtwidth:   .word 80                   ; FIXME should be variable
 _vtchar:    .byte 0
+
+;
+;      Double speed upgrade
+;
+           .globl _engage_warp_drive
+
+_engage_warp_drive:
+           ld a,#2
+           in a,(9)
+           ret