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/
$(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
../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
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);
--- /dev/null
+#include <kernel.h>
+#include <timer.h>
+#include <kdata.h>
+#include <printf.h>
+#include <device.h>
+#include <devtty.h>
+#include <carts.h>
+
+/*
+ * 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);
+}
}
-/* ------------- 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);
-}
--- /dev/null
+ .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