From c181cd32af53765d0c6c72bb104f0fa649448f74 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sun, 6 May 2018 23:42:41 +0100 Subject: [PATCH] ubee: further updates 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 | 24 ++- Kernel/platform-ubee/devhd.c | 270 +++++++++++++++++--------------- Kernel/platform-ubee/devhd.h | 9 +- Kernel/platform-ubee/devices.c | 32 ++-- Kernel/platform-ubee/devlpr.c | 4 +- Kernel/platform-ubee/discard.c | 59 ++++++- Kernel/platform-ubee/kernel.def | 2 +- Kernel/platform-ubee/main.c | 15 ++ Kernel/platform-ubee/ubee.h | 12 ++ Kernel/platform-ubee/ubee.s | 47 ++---- 10 files changed, 274 insertions(+), 200 deletions(-) diff --git a/Kernel/platform-ubee/README b/Kernel/platform-ubee/README index b6127866..4cce8719 100644 --- a/Kernel/platform-ubee/README +++ b/Kernel/platform-ubee/README @@ -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 diff --git a/Kernel/platform-ubee/devhd.c b/Kernel/platform-ubee/devhd.c index feffe65d..68dbfcff 100644 --- a/Kernel/platform-ubee/devhd.c +++ b/Kernel/platform-ubee/devhd.c @@ -20,6 +20,7 @@ #include #include #include +#include __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; } diff --git a/Kernel/platform-ubee/devhd.h b/Kernel/platform-ubee/devhd.h index 41200a76..c544f049 100644 --- a/Kernel/platform-ubee/devhd.h +++ b/Kernel/platform-ubee/devhd.h @@ -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__ */ diff --git a/Kernel/platform-ubee/devices.c b/Kernel/platform-ubee/devices.c index 8f992a6b..917343c2 100644 --- a/Kernel/platform-ubee/devices.c +++ b/Kernel/platform-ubee/devices.c @@ -7,20 +7,24 @@ #include #include #include +#include +#include +#include +#include #include 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); -} diff --git a/Kernel/platform-ubee/devlpr.c b/Kernel/platform-ubee/devlpr.c index 906a3e34..232fd709 100644 --- a/Kernel/platform-ubee/devlpr.c +++ b/Kernel/platform-ubee/devlpr.c @@ -2,13 +2,14 @@ #include #include #include +#include __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; } diff --git a/Kernel/platform-ubee/discard.c b/Kernel/platform-ubee/discard.c index 3cfe15fe..6ea5593f 100644 --- a/Kernel/platform-ubee/discard.c +++ b/Kernel/platform-ubee/discard.c @@ -3,11 +3,16 @@ #include #include #include +#include +#include +#include #include __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(); +} diff --git a/Kernel/platform-ubee/kernel.def b/Kernel/platform-ubee/kernel.def index b2d9ebc7..d07a89f4 100644 --- a/Kernel/platform-ubee/kernel.def +++ b/Kernel/platform-ubee/kernel.def @@ -14,4 +14,4 @@ Z80_MMU_HOOKS .equ 0 CONFIG_SWAP .equ 1 -NBUFS .equ 7 +NBUFS .equ 6 diff --git a/Kernel/platform-ubee/main.c b/Kernel/platform-ubee/main.c index 25466c46..44f7dc1f 100644 --- a/Kernel/platform-ubee/main.c +++ b/Kernel/platform-ubee/main.c @@ -5,7 +5,10 @@ #include #include +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; diff --git a/Kernel/platform-ubee/ubee.h b/Kernel/platform-ubee/ubee.h index a6323685..13350872 100644 --- a/Kernel/platform-ubee/ubee.h +++ b/Kernel/platform-ubee/ubee.h @@ -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 diff --git a/Kernel/platform-ubee/ubee.s b/Kernel/platform-ubee/ubee.s index 6486b909..1e29286c 100644 --- a/Kernel/platform-ubee/ubee.s +++ b/Kernel/platform-ubee/ubee.s @@ -19,12 +19,6 @@ .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 -- 2.34.1