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:
- 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
- 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
#include <printf.h>
#include <devhd.h>
#include <ubee.h>
+#include <blkdev.h>
__sfr __at 0x40 hd_data;
__sfr __at 0x41 hd_precomp; /* W/O */
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;
}
#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__ */
#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 */
};
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);
-}
#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;
}
irqrestore(irq);
lpready = 0;
lpdata = ugetc(udata.u_base++);
+ udata.u_done++;
}
return udata.u_done;
}
#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 */
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();
+}
CONFIG_SWAP .equ 1
-NBUFS .equ 7
+NBUFS .equ 6
#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 */
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;
#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
.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
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
_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