From af34e3bf991c01a4dd9a2514f8c218bbf4748736 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sat, 10 Oct 2015 20:49:59 +0100 Subject: [PATCH] dragon-nx32: add first test bits of scsi support We now scan 0xFF7x for a TC3 controller and maybe even probe it properly but not yet tested out. Also sort out the discard segment properly. Right now it's not important but at some point we'll find a way to reuse that space nicely. Still lots to do including the proper autodetect for the TC3 and bank switching the TC3 in/out if (as it basically has to be) it's in an MPI, and handling swap or userspace I/O (so even running programs off it won't work yet in the unlikely event it gets that far) --- Kernel/platform-dragon-nx32/Makefile | 23 +++- Kernel/platform-dragon-nx32/device.h | 3 + Kernel/platform-dragon-nx32/discard.c | 150 +++++++++++++++++++++++++ Kernel/platform-dragon-nx32/main.c | 144 ------------------------ Kernel/platform-dragon-nx32/scsi_tc3.s | 128 +++++++++++++++++++++ 5 files changed, 299 insertions(+), 149 deletions(-) create mode 100644 Kernel/platform-dragon-nx32/discard.c create mode 100644 Kernel/platform-dragon-nx32/scsi_tc3.s diff --git a/Kernel/platform-dragon-nx32/Makefile b/Kernel/platform-dragon-nx32/Makefile index faffc344..b8ba89b0 100644 --- a/Kernel/platform-dragon-nx32/Makefile +++ b/Kernel/platform-dragon-nx32/Makefile @@ -2,17 +2,23 @@ CSRCS = devlpr.c devtty.c devfd.c CSRCS += devices.c main.c libc.c +CDSRCS = discard.c + DSRCS = ../dev/devdw.c ../dev/blkdev.c ../dev/devide.c \ - ../dev/devide_discard.c ../dev/mbr.c \ - ../dev/devsd.c ../dev/devsd_discard.c + ../dev/devsd.c ../dev/devscsi.c + +DDSRCS = ../dev/devide_discard.c ../dev/devscsi_discard.c ../dev/mbr.c \ + ../dev/devsd_discard.c -ASRCS = crt0.s dragon.s mem-nx32.s video.s ide.s spi.s +ASRCS = crt0.s dragon.s mem-nx32.s video.s ide.s spi.s scsi_tc3.s ASRCS += tricks.s commonmem.s usermem_sam.s floppy.s drivewire.s COBJS = $(CSRCS:.c=$(BINEXT)) +CDOBJS = $(CDSRCS:.c=$(BINEXT)) AOBJS = $(ASRCS:.s=$(BINEXT)) DOBJS = $(patsubst ../dev/%.c,%.o, $(DSRCS)) -OBJS = $(COBJS) $(AOBJS) $(DOBJS) +DDOBJS = $(patsubst ../dev/%.c,%.o, $(DDSRCS)) +OBJS = $(COBJS) $(CDOBJS) $(AOBJS) $(DOBJS) $(DDOBJS) CROSS_CCOPTS += -I../dev/ @@ -23,9 +29,15 @@ all: $(OBJS) $(COBJS): %$(BINEXT): %.c $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEG2) -c $< +$(CDOBJS): %$(BINEXT): %.c + $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEGDISC) -c $< + $(DOBJS): %$(BINEXT): ../dev/%.c $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEG2) -c $< +$(DDOBJS): %$(BINEXT): ../dev/%.c + $(CROSS_CC) $(CROSS_CCOPTS) $(CROSS_CC_SEGDISC) -c $< + $(AOBJS): %$(BINEXT): %.s $(CROSS_AS) $(ASOPTS) $< -o $*.o @@ -44,5 +56,6 @@ image: ../tty.o ../devsys.o ../usermem.o ../syscall_fs2.o ../syscall_exec16.o \ devlpr.o devtty.o libc.o ../vt.o video.o ../font8x8.o \ devide.o blkdev.o ide.o devide_discard.o mbr.o \ - devsd.o devsd_discard.o spi.o + devsd.o devsd_discard.o spi.o devscsi.o devscsi_discard.o \ + scsi_tc3.o discard.o ../tools/pad256 ../fuzix.bin diff --git a/Kernel/platform-dragon-nx32/device.h b/Kernel/platform-dragon-nx32/device.h index b75404e6..2687e750 100644 --- a/Kernel/platform-dragon-nx32/device.h +++ b/Kernel/platform-dragon-nx32/device.h @@ -12,7 +12,10 @@ extern uint8_t hdb_timeout; extern uint8_t hdb_id; extern uint16_t cartaddr[]; +extern uint8_t carttype[]; extern uint8_t cartslots; +extern uint8_t bootslot; +extern uint8_t membanks; extern uint8_t spi_setup(void); diff --git a/Kernel/platform-dragon-nx32/discard.c b/Kernel/platform-dragon-nx32/discard.c new file mode 100644 index 00000000..75493cd3 --- /dev/null +++ b/Kernel/platform-dragon-nx32/discard.c @@ -0,0 +1,150 @@ +#include +#include +#include +#include +#include +#include +#include + +/* + * Map handling: We have flexible paging. Each map table consists of a set of pages + * with the last page repeated to fill any holes. + */ + +void pagemap_init(void) +{ + int i; + /* map bank 1 last for init, leave 0 for kernel */ + for (i = membanks - 1; i > 0; i--) + pagemap_add(i); + +#ifdef SWAPDEV + for (i = 0; i < MAX_SWAPS; i++) + swapmap_add(i); +#endif +} + +static const char *sysname[] = {"Dragon", "COCO", "COCO3", "Unknown"}; + +struct cart_rom_id { + uint16_t hash; + uint8_t id; + const char *name; +}; + +static const char empty[] = "(empty)"; + +struct cart_rom_id carts[] = { + { 0x72B0, CART_DRAGONDOS, "DragonDOS" }, + { 0x9063, CART_DELTADOS, "DeltaDOS" }, + { 0xB400, 0, empty }, + { 0xC248, CART_RSDOS, "RS-DOS" }, + /* This one is an oddity - we need to do more to know what it drives + The great thing is we can extract the MMIO addresses from it */ + { 0xB61B, CART_HDBDOS, "HDBDOS" }, + { 0xE1BA, CART_ORCH90, "Orchestra-90 CC" }, + { 0x0000, 0, "No ROM" } +}; + +struct hdb_rom_id { + char key[2]; + uint8_t id; + const char *name; +}; + +static struct hdb_rom_id hdb[] = { + { "ID", CART_IDE, "IDE (CHS)" }, + { "LB", CART_IDE, "IDE (LBA)" }, + { "TC", CART_TC3, "TC^3" }, + { "KE", CART_KENTON, "KENTON" }, + { "LR", CART_LRTECH, "LRTECH" }, + { "HD", CART_HDII, "HD-II" }, + { "4-", CART_4N1, "4-N-1" }, + { "DW", CART_DRIVEWIRE, "Drivewire" }, + { "BE", CART_BECKER, "Becker" }, + { "J&", CART_JMCP, "J&M CP" }, + {} +}; + +/* Find a cartridge or it's slot */ +int cart_find(int id) +{ + int i; + for (i = 0; i < id; i++) { + if (carttype[i] == id) + return i; + } + return -1; +} + +static struct cart_rom_id *cart_lookup(uint16_t hash) +{ + struct cart_rom_id *cart = carts; + do { + if (cart->hash == hash) + return cart; + } while(cart++->hash); + return NULL; +} + +static inline int keycmp(uint16_t *k1, uint16_t *k2) +{ + return (*k1 == *k2); +} + +static struct hdb_rom_id *hdb_lookup(uint16_t key) +{ + struct hdb_rom_id *id = hdb; + do { + if (keycmp(&key, (uint16_t *)id->key)) + return id; + } while(id++->id); + return NULL; +} + +void map_init(void) +{ + uint8_t i; + uint8_t bslot = 0; + uint16_t hash; + struct cart_rom_id *rom; + + kprintf("%s system.\n", sysname[system_id]); + if (mpi_present()) { + kputs("MPI cartridge detected.\n"); + cartslots = 4; + bootslot = mpi_set_slot(0); + bslot = bootslot & 3; + } + for (i = 0; i < cartslots; i++) { + mpi_set_slot((i << 4) | i); + hash = cart_hash(); + rom = cart_lookup(hash); + if (rom) { + kprintf("%d: %s %c\n", + i, rom->name, + i == bootslot ? '*':' '); + carttype[i] = rom->id; + } + else + kprintf("%d: Unknown(%x) %c\n", + i, hash, + i == bslot ? '*':' '); + + /* The analysis needs to be in asm as we need to page in + the ROM to peer at it */ + if (rom->id == CART_HDBDOS) { + uint16_t t = cart_analyze_hdb(); + struct hdb_rom_id *hdb = hdb_lookup(t); + if (hdb) { + kprintf(" %s MMIO %x ID %d\n", + hdb->name, + hdb_port, hdb_id); + carttype[i] = hdb->id; + cartaddr[i] = hdb_port; + } else + kprintf("??%x\n", t); + } + } + mpi_set_slot(bootslot); +} diff --git a/Kernel/platform-dragon-nx32/main.c b/Kernel/platform-dragon-nx32/main.c index 8c89515e..0c2007e5 100644 --- a/Kernel/platform-dragon-nx32/main.c +++ b/Kernel/platform-dragon-nx32/main.c @@ -22,147 +22,3 @@ void do_beep(void) } -/* ------------- Below bits can all move to discard if needed ------------ */ - -/* - * Map handling: We have flexible paging. Each map table consists of a set of pages - * with the last page repeated to fill any holes. - */ - -void pagemap_init(void) -{ - int i; - /* map bank 1 last for init, leave 0 for kernel */ - for (i = membanks - 1; i > 0; i--) - pagemap_add(i); - -#ifdef SWAPDEV - for (i = 0; i < MAX_SWAPS; i++) - swapmap_add(i); -#endif -} - -static const char *sysname[] = {"Dragon", "COCO", "COCO3", "Unknown"}; - -struct cart_rom_id { - uint16_t hash; - uint8_t id; - const char *name; -}; - -static const char empty[] = "(empty)"; - -struct cart_rom_id carts[] = { - { 0x72B0, CART_DRAGONDOS, "DragonDOS" }, - { 0x9063, CART_DELTADOS, "DeltaDOS" }, - { 0xB400, 0, empty }, - { 0xC248, CART_RSDOS, "RS-DOS" }, - /* This one is an oddity - we need to do more to know what it drives - The great thing is we can extract the MMIO addresses from it */ - { 0xB61B, CART_HDBDOS, "HDBDOS" }, - { 0xE1BA, CART_ORCH90, "Orchestra-90 CC" }, - { 0x0000, 0, "No ROM" } -}; - -struct hdb_rom_id { - char key[2]; - uint8_t id; - const char *name; -}; - -static struct hdb_rom_id hdb[] = { - { "ID", CART_IDE, "IDE (CHS)" }, - { "LB", CART_IDE, "IDE (LBA)" }, - { "TC", CART_TC3, "TC^3" }, - { "KE", CART_KENTON, "KENTON" }, - { "LR", CART_LRTECH, "LRTECH" }, - { "HD", CART_HDII, "HD-II" }, - { "4-", CART_4N1, "4-N-1" }, - { "DW", CART_DRIVEWIRE, "Drivewire" }, - { "BE", CART_BECKER, "Becker" }, - { "J&", CART_JMCP, "J&M CP" }, - {} -}; - -/* Find a cartridge or it's slot */ -int cart_find(int id) -{ - int i; - for (i = 0; i < id; i++) { - if (carttype[i] == id) - return i; - } - return -1; -} - -static struct cart_rom_id *cart_lookup(uint16_t hash) -{ - struct cart_rom_id *cart = carts; - do { - if (cart->hash == hash) - return cart; - } while(cart++->hash); - return NULL; -} - -static inline int keycmp(uint16_t *k1, uint16_t *k2) -{ - return (*k1 == *k2); -} - -static struct hdb_rom_id *hdb_lookup(uint16_t key) -{ - struct hdb_rom_id *id = hdb; - do { - if (keycmp(&key, (uint16_t *)id->key)) - return id; - } while(id++->id); - return NULL; -} - -void map_init(void) -{ - uint8_t i; - uint8_t bslot = 0; - uint16_t hash; - struct cart_rom_id *rom; - - kprintf("%s system.\n", sysname[system_id]); - if (mpi_present()) { - kputs("MPI cartridge detected.\n"); - cartslots = 4; - bootslot = mpi_set_slot(0); - bslot = bootslot & 3; - } - for (i = 0; i < cartslots; i++) { - mpi_set_slot((i << 4) | i); - hash = cart_hash(); - rom = cart_lookup(hash); - if (rom) { - kprintf("%d: %s %c\n", - i, rom->name, - i == bootslot ? '*':' '); - carttype[i] = rom->id; - } - else - kprintf("%d: Unknown(%x) %c\n", - i, hash, - i == bslot ? '*':' '); - - /* The analysis needs to be in asm as we need to page in - the ROM to peer at it */ - if (rom->id == CART_HDBDOS) { - uint16_t t = cart_analyze_hdb(); - struct hdb_rom_id *hdb = hdb_lookup(t); - if (hdb) { - kprintf(" %s MMIO %x ID %d\n", - hdb->name, - hdb_port, hdb_id); - carttype[i] = hdb->id; - cartaddr[i] = hdb_port; - } else - kprintf("??%x\n", t); - } - } - mpi_set_slot(bootslot); -} diff --git a/Kernel/platform-dragon-nx32/scsi_tc3.s b/Kernel/platform-dragon-nx32/scsi_tc3.s new file mode 100644 index 00000000..38ff0fd3 --- /dev/null +++ b/Kernel/platform-dragon-nx32/scsi_tc3.s @@ -0,0 +1,128 @@ + .module scsi_tcs + + include "kernel.def" + include "../kernel09.def" + + .globl _si_read + .globl _si_write + .globl _si_writecmd + .globl _si_select + .globl _si_clear + .globl _si_reset + + .area .common + +; +; For the moment we only allow one scsi adapter compiled in. That +; wants tidying up some day +; +; +; FIXME: read/write need to honour user/kernel swap etc flags +; here. For now this will only work for simple testing stuff +; +_si_read: ; X is pointer + pshs y,u + tfr s,u ; u holds our frame pointer to throw + bsr waitreq ; an exception + ldx #_si_dcb + ldy #_si_dcb + 16 ; length word + bita #0x08 ; check CMD asserted + bne si_busfailw + lda $FF70 + sta ,x+ + leay -1,y + bne _si_read + ldx #0 ; Return 0 + puls y,u,pc + +_si_write: ; X is pointer, dcb block gives length + pshs y,u + tfr s,u ; u holds our frame pointer to throw + bsr waitreq ; an exception + ldx #_si_dcb + ldy _si_dcb + 16 ; length word + bita #0x08 ; check CMD asserted + bne si_busfailw + lda ,x+ + sta $FF70 + leay -1,y + bne _si_write + ldx #0 ; Return 0 + puls y,u,pc +timeout: + tfr u,s ; Throw an exception +si_busfailw: + ldx #-1 + puls y,u,pc + +; +; Must preserve B +; +waitreq: + pshs y + ldy #30000 ; Guess a timeout ! +waitreql: + leay -1,y + beq timeout + lda $FF71 ; errors back + bita #0x01 + bne waitreql + rts + + .area .text + +_si_writecmd: ; DCB, B is len (check B or X) + pshs y,u,pc + tfr s,u ; Required exception frame for waitreq + jsr waitreq + ldx #_si_dcb + bita #0x08 ; check CMD asserted + beq si_busfail + lda ,x+ + sta $FF70 + decb + bne _si_writecmd + ldx #0 ; Return 0 + puls y,u,pc +si_busfail: + ldx #-1 ; Error (should sort some codes for type!) + puls y,u,pc + +_si_select: ; Select device B + cmpb #7 + beq si_seltimeo ; FIXME: different errorcodes ? + ldx #0 + lda #1 + tstb ; Fast path the usual device 0 case + beq si_dobsyw +si_shiftdev: + rola + decb + bne si_shiftdev +si_dobsyw: + ora #0x80 ; We mus also assert our own device id on + ; the bus (7) +si_bsyw: + leax -1,x + beq si_seltimeo + lda $FF71 ; FIXME: needs timeouts + bita #0x02 + bne si_bsyw ; Wait for BSY to drop + stb $FF70 ; Put B on the data lines + stb $FF71 ; trigger a select +si_bsyc: + leax -1,x + beq si_seltimeo + lda $FF71 + bita #0x02 + beq si_bsyc ; The device asserts BSY for us + ldx #0 ; All good + rts +si_seltimeo: + ldx #-1 + rts + +_si_clear: + clr $FF70 +_si_reset: + rts -- 2.34.1