From 5a963a00976b1899a2d9ba72ab57b108cf357166 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 8 Oct 2015 23:15:55 +0100 Subject: [PATCH] dragon-nx-32: add autoprobe of HDBDOS We now identify the HDBDOS ROM by the signature, and then pull out the MMIO port, SCSI LUN and identify the controller type so that we can set the cartridge type nicely. Do need to move most of main.c into discard as its getting a bit big, but it's all discardable so that's fine. --- Kernel/platform-dragon-nx32/carts.h | 11 ++++ Kernel/platform-dragon-nx32/device.h | 5 ++ Kernel/platform-dragon-nx32/dragon.s | 92 +++++++++++++++++++++++++--- Kernel/platform-dragon-nx32/main.c | 52 ++++++++++++++++ 4 files changed, 152 insertions(+), 8 deletions(-) diff --git a/Kernel/platform-dragon-nx32/carts.h b/Kernel/platform-dragon-nx32/carts.h index 3e3f4016..738accaf 100644 --- a/Kernel/platform-dragon-nx32/carts.h +++ b/Kernel/platform-dragon-nx32/carts.h @@ -2,5 +2,16 @@ #define CART_DELTADOS 2 /* DeltaDOS floppy */ #define CART_RSDOS 3 /* RSDOS Cartridge */ #define CART_ORCH90 4 /* Orchestra Sound */ +#define CART_HDBDOS 5 /* Something with HDBDOS */ +#define CART_IDE 6 /* Glenside compatible IDE port */ +#define CART_TC3 7 /* Cloud 9 TC^3 SCSI */ +#define CART_KENTON 8 /* KenTon SCSI */ +#define CART_LRTECH 9 /* LR-Tech Super Board and possibly + Owlware */ +#define CART_HDII 10 /* Disto H Disk SCSI */ +#define CART_4N1 11 /* 4 in 1 card */ +#define CART_DRIVEWIRE 12 /* Drivewire card */ +#define CART_BECKER 13 /* Becker card */ +#define CART_JMCP 14 /* J&M */ extern int cart_find(int id); diff --git a/Kernel/platform-dragon-nx32/device.h b/Kernel/platform-dragon-nx32/device.h index e57c6a38..9c6231d6 100644 --- a/Kernel/platform-dragon-nx32/device.h +++ b/Kernel/platform-dragon-nx32/device.h @@ -5,6 +5,11 @@ extern uint8_t system_id; extern uint8_t mpi_present(void); extern uint8_t mpi_set_slot(uint8_t slot); extern uint16_t cart_hash(void); +extern uint16_t cart_analyze_hdb(void); + +extern uint16_t hdb_port; +extern uint8_t hdb_timeout; +extern uint8_t hdb_id; extern uint8_t spi_setup(void); diff --git a/Kernel/platform-dragon-nx32/dragon.s b/Kernel/platform-dragon-nx32/dragon.s index 7f1d92b3..d599696d 100644 --- a/Kernel/platform-dragon-nx32/dragon.s +++ b/Kernel/platform-dragon-nx32/dragon.s @@ -8,6 +8,11 @@ .globl _mpi_present .globl _mpi_set_slot .globl _cart_hash + .globl _cart_analyze_hdb + .globl _hdb_offset + .globl _hdb_id + .globl _hdb_port + .globl _hdb_timeout ; imported .globl unix_syscall_entry @@ -114,7 +119,7 @@ _irqrestore: ; B holds the data ; and is not banked out. ; _program_vectors: - rts + rts ; ; Helpers for the MPI and Cartridge Detect @@ -175,6 +180,77 @@ hashl: tfr d,x clr $FFBF ; Return to normality puls cc,pc + +_cart_analyze_hdb: + pshs cc + orcc #0x10 + clr $FFBE + ldd 0xD93B ; I/O port + std _hdb_port + ldd 0xD93D ; Timeout and ID if SCSI + std _hdb_timeout + ; Shortly after that fixed block we will find the sign on and + ; copyright, which tell us what interface we are for. + ldx #0xD940 +hdb_s_next: + cmpx #0xE000 + beq no_sign ; No sign of the sign on ! + lda ,x+ + cmpa #'H' + bne hdb_s_next + lda ,x+ + cmpa #'D' ; This is safe as we know the bytes before + bne hdb_s_next ; our match are AUTOEXEC.BAS so won't partially + lda ,x+ ; match ! + cmpa #'B' + bne hdb_s_next + lda ,x+ + cmpa #'-' + bne hdb_s_next + ; + ; We have found the HDB-. X now points at the D of DOS + ; + leax 6,x ; Skip version + ; + ; We now have to find a space + ; +hdb_s_spc: + cmpx #0xE000 + beq no_sign + lda ,x+ + cmpa #0x20 + bne hdb_s_spc + ; + ; This is followed by a string. For those we care about the first + ; letters are sufficient to tell them apart + ; + ; LB : IDE LBA + ; ID : IDE CHS + ; TC : TC^3 SCSI + ; KE : Kenton + ; LR : LR Tech + ; HD : HD-II + ; 4- : 4-N-1 + ; DW : Drivewire stuff } Need more identification but are not + ; BE : Becker ports } interesting to us anyway + ; J& : J&M CP + ldx ,x +ret1: + clr $FFBF + puls cc,pc +no_sign: + ldx #-1 + bra ret1 + +; Need to be here so they can be written with cart paged in +_hdb_port: + .dw 0 +_hdb_timeout: + .db 0 +_hdb_id: + .db 0 +_hdb_type: + .db 0 ; ; FIXME: ; @@ -186,13 +262,13 @@ badswi_handler: ; debug via printer port ; outchar: - sta 0xFF02 - lda 0xFF20 - ora #0x02 - sta 0xFF20 - anda #0xFD - sta 0xFF20 - rts + sta 0xFF02 + lda 0xFF20 + ora #0x02 + sta 0xFF20 + anda #0xFD + sta 0xFF20 + rts .area .common diff --git a/Kernel/platform-dragon-nx32/main.c b/Kernel/platform-dragon-nx32/main.c index 6ed6de1c..58ab0b78 100644 --- a/Kernel/platform-dragon-nx32/main.c +++ b/Kernel/platform-dragon-nx32/main.c @@ -56,10 +56,33 @@ struct cart_rom_id carts[] = { { 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) { @@ -81,6 +104,21 @@ static struct cart_rom_id *cart_lookup(uint16_t 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; @@ -109,6 +147,20 @@ void map_init(void) 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; + } else + kprintf("??%x\n", t); + } } mpi_set_slot(bootslot); } -- 2.34.1