]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Hardital Synthesis and MAST Fireball HD controller emulation.
authorToni Wilen <twilen@winuae.net>
Sun, 6 Dec 2020 11:34:58 +0000 (13:34 +0200)
committerToni Wilen <twilen@winuae.net>
Sun, 6 Dec 2020 11:34:58 +0000 (13:34 +0200)
expansion.cpp
include/rommgr.h
include/scsi.h
rommgr.cpp
scsi.cpp

index 396a81e6728f414cc46a4e9daa5e1534a81ded9f..ee157c26573dd89621a3f2f6cb4611e430afcb68 100644 (file)
@@ -5380,6 +5380,12 @@ const struct expansionromtype expansionroms[] = {
                NULL, 0,
                true, EXPANSIONTYPE_IDE
        },
+       {
+               _T("synthesis"), _T("Synthesis"), _T("Hardital"),
+               NULL, synthesis_init, NULL, synthesis_add_scsi_unit, ROMTYPE_SYNTHESIS, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+               NULL, 0,
+               true, EXPANSIONTYPE_SCSI
+       },
        {
                _T("vector"), _T("Vector Falcon 8000"), _T("HK-Computer"),
                NULL, vector_init, NULL, vector_add_scsi_unit, ROMTYPE_VECTOR, 0, 0, BOARD_AUTOCONFIG_Z2, false,
@@ -5485,6 +5491,15 @@ const struct expansionromtype expansionroms[] = {
                false, EXPANSIONTYPE_SCSI,
                18260, 8, 0, true
        },
+       {
+               _T("mastfb"), _T("Fireball"), _T("M.A.S.T."),
+               NULL, fireball_init, NULL, fireball_add_scsi_unit, ROMTYPE_MASTFB, 0, 0, BOARD_AUTOCONFIG_Z2, false,
+               NULL, 0,
+               true, EXPANSIONTYPE_SCSI,
+               0, 0, 0, false, NULL,
+               false, 0, NULL,
+               { 0xd1, 8, 0x40, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00 }
+       },
        {
                _T("scram8490"), _T("SCRAM (DP8490V)"), _T("MegaMicro"),
                NULL, scram5380_init, NULL, scram5380_add_scsi_unit, ROMTYPE_SCRAM5380, 0, 0, BOARD_AUTOCONFIG_Z2, false,
index 74bc441f141a892e1b0cd626554bbeb244c8bbef..1d16012484f8d3723aefef511b2aba2f92d2460c 100644 (file)
@@ -195,6 +195,8 @@ extern int decode_cloanto_rom_do (uae_u8 *mem, int size, int real_size);
 #define ROMTYPE_MASTERCARD     0x00100083
 #define ROMTYPE_DOTTO          0x00100084
 #define ROMTYPE_ALF2           0x00100085
+#define ROMTYPE_SYNTHESIS      0x00100086
+#define ROMTYPE_MASTFB         0x00100087
 
 #define ROMTYPE_NOT                    0x00800000
 #define ROMTYPE_QUAD           0x01000000
index 2f0e1a44317f4c01135929db49f5bafdaead18ad..0646b25c7bd1d8eb65ef574b6c9867a7f4b6db5d 100644 (file)
@@ -306,6 +306,12 @@ void fasttrak_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romcon
 bool overdrive_init(struct autoconfig_info *aci);
 void overdrive_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
 
+bool synthesis_init(struct autoconfig_info* aci);
+void synthesis_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc);
+
+bool fireball_init(struct autoconfig_info* aci);
+void fireball_add_scsi_unit(int ch, struct uaedev_config_info* ci, struct romconfig* rc);
+
 uae_u8 idescsi_scsi_get(uaecptr addr);
 void idescsi_scsi_put(uaecptr addr, uae_u8 v);
 
index f25ee9ca1f532510b9f72388c324dc7a888ed319..f0f656ef3d4343370805cfec5e7e50ce899b482d 100644 (file)
@@ -95,7 +95,7 @@ struct romdata *getromdatabypath (const TCHAR *path)
        return NULL;
 }
 
-#define NEXT_ROM_ID 265
+#define NEXT_ROM_ID 267
 
 #define ALTROM(id,grp,num,size,flags,crc32,a,b,c,d,e) \
 { _T("X"), 0, 0, 0, 0, 0, size, id, 0, 0, flags, (grp << 16) | num, 0, NULL, crc32, a, b, c, d, e },
@@ -646,6 +646,10 @@ static struct romdata roms[] = {
        0xee803484, 0x62822cb9,0x0b095efa,0x455496ea,0xd5b22740,0x77d86375, NULL, NULL },
        { _T("A.L.F. 2"), 0, 0, 0, 0, _T("ALF2\0"), 65536, 264, 0, 0, ROMTYPE_ALF2, 0, 0, NULL,
        0x9cf8a7b7, 0x3df4667c,0xd3436367,0x7896da65,0x94994769,0x13bc6746, NULL, NULL },
+       { _T("M.A.S.T. Fireball"), 0, 0, 0, 0, _T("MASTFB\0"), 8192, 265, 0, 0, ROMTYPE_MASTFB, 0, 0, NULL,
+       0xb475ff5f, 0x63609553,0x98b06812,0x23ade9ac,0x6ee31364,0x5375fce3, NULL, NULL },
+       { _T("Hardital Synthesis"), 0, 0, 0, 0, _T("SYNTHESIS\0"), 32768, 266, 0, 0, ROMTYPE_SYNTHESIS, 0, 0, NULL,
+       0x667c7616, 0x0eb1cb38,0x3133f070,0x7cb57944,0xc516f236,0xbad4d4f6, NULL, NULL },
 
        { _T("CyberStorm MK I 68040"), 0, 0, 0, 0, _T("CSMKI\0"), 32768, 95, 0, 0, ROMTYPE_CB_CSMK1, 0, 0, NULL,
          0, 0, 0, 0, 0, 0, NULL, _T("cyberstormmk1_040.rom") },
index 78c9f0bbbbd42525079b653ee3540db947b55a61..a92f7d240359c404578761683d37d6bfc96d8f4b 100644 (file)
--- a/scsi.cpp
+++ b/scsi.cpp
@@ -77,7 +77,9 @@
 #define NCR5380_OVERDRIVE 42
 #define NCR5380_TRUMPCARD 43
 #define OMTI_ALF2 44
-#define NCR_LAST 45
+#define NCR5380_SYNTHESIS 45 // clone of ICD AdSCSI
+#define NCR5380_FIREBALL 46
+#define NCR_LAST 47
 
 extern int log_scsiemu;
 
@@ -817,6 +819,7 @@ struct soft_scsi
        uae_u8 scratch_400[64];
        int c400_count;
        bool c400;
+       bool dp8490v;
        uae_u8 aic_reg;
        struct raw_scsi rscsi;
        bool irq;
@@ -1506,6 +1509,20 @@ static void overdrive_do_dma(struct soft_scsi *ncr)
        }
 }
 
+static void fireball_do_dma(struct soft_scsi* ncr)
+{
+       struct raw_scsi* rs = &ncr->rscsi;
+       while (rs->bus_phase == SCSI_SIGNAL_PHASE_DATA_OUT || rs->bus_phase == SCSI_SIGNAL_PHASE_DATA_IN) {
+               if (rs->bus_phase == SCSI_SIGNAL_PHASE_DATA_IN) {
+                       dma_put_byte(ncr->dmac_address & ncr->dma_mask, ncr5380_bget(ncr, 8));
+                       ncr->dmac_address++;
+               } else if (rs->bus_phase == SCSI_SIGNAL_PHASE_DATA_OUT) {
+                       ncr5380_bput(ncr, 8, dma_get_byte(ncr->dmac_address & ncr->dma_mask));
+                       ncr->dmac_address++;
+               }
+       }
+}
+
 
 static void dma_check(struct soft_scsi *ncr)
 {
@@ -1540,6 +1557,12 @@ static void dma_check(struct soft_scsi *ncr)
 
                }
 
+               if (ncr->type == NCR5380_FIREBALL) {
+
+                       fireball_do_dma(ncr);
+
+               }
+
                ncr->dmac_active = 0;
        }
 }
@@ -1549,7 +1572,11 @@ static void ncr80_rethink(void)
 {
        for (int i = 0; soft_scsi_devices[i]; i++) {
                struct soft_scsi *s = soft_scsi_devices[i];
-               if (s->irq && s->intena && ((s->c400 && (s->regs_400[0] & 0x10) && !s->c400_count) || !s->c400)) {
+               if (s->irq && s->intena && (
+                       (s->c400 && (s->regs_400[0] & 0x10) && !s->c400_count) ||
+                       (s->dp8490v && (s->regs[18] & 0x20)) ||
+                       (!s->c400 && !s->dp8490v)))
+               {
                        if (soft_scsi_devices[i] == x86_hd_data) {
                                ;// x86_doirq(5);
                        } else {
@@ -1854,7 +1881,13 @@ static void ncr5380_reset(struct soft_scsi *scsi, bool busreset)
 {
        struct raw_scsi *r = &scsi->rscsi;
 
-       memset(scsi->regs, 0, sizeof scsi->regs);
+       if (scsi->dp8490v) {
+               // DP8490V manual says all registers are reset but that can't work
+               // with Fireball driver. It assumes IMR is not reset.
+               memset(scsi->regs, 0, 16);
+       } else {
+               memset(scsi->regs, 0, sizeof scsi->regs);
+       }
        if (busreset) {
                raw_scsi_reset_bus(scsi);
                scsi->regs[1] = 0x80;
@@ -1866,6 +1899,14 @@ uae_u8 ncr5380_bget(struct soft_scsi *scsi, int reg)
 {
        if (reg > 8)
                return 0;
+
+       if (scsi->dp8490v) {
+               if ((scsi->regs[1] & 0x40) && reg == 7) {
+                       reg = 17;
+               }
+       }
+
+
        uae_u8 v = scsi->regs[reg];
        struct raw_scsi *r = &scsi->rscsi;
        switch(reg)
@@ -1938,6 +1979,27 @@ uae_u8 ncr5380_bget(struct soft_scsi *scsi, int reg)
                case 7:
                scsi->irq = false;
                break;
+
+               case 17: // DP8490V MODE_E
+               {
+                       int efr = (scsi->regs[17] >> 1) & 3;
+                       if (efr == 3) {
+                               v = 0;
+                               uae_u8 t = raw_scsi_get_signal_phase(r);
+                               // End of DMA -> DMA Phase Mismatch
+                               if (scsi->regs[5] & 0x80) {
+                                       v = 0x10;
+                               }
+                               // Any Phase Mismatch
+                               if (r->bus_phase == (scsi->regs[3] & 7)) {
+                                       v |= 0x20;
+                               }
+                       } else {
+                               scsi->regs[17] &= ~(3 << 1);
+                       }
+               }
+               break;
+
                case 8: // fake dma port
                v = raw_scsi_get_data(r, true);
                ncr5380_check_phase(scsi);
@@ -1951,6 +2013,13 @@ void ncr5380_bput(struct soft_scsi *scsi, int reg, uae_u8 v)
 {
        if (reg > 8)
                return;
+
+       if (scsi->dp8490v) {
+               if ((scsi->regs[1] & 0x40) && reg == 7) {
+                       reg = 17;
+               }
+       }
+
        bool dataoutput = (scsi->regs[1] & 1) != 0;
        struct raw_scsi *r = &scsi->rscsi;
        uae_u8 old = scsi->regs[reg];
@@ -1990,6 +2059,10 @@ void ncr5380_bput(struct soft_scsi *scsi, int reg, uae_u8 v)
                        if (v & 0x80) { // RST
                                ncr5380_reset(scsi, true);
                        }
+                       if (scsi->dp8490v) {
+                               scsi->regs[reg] &= ~0x40;
+                               scsi->regs[reg] |= v & 0x40;
+                       }
                }
                break;
                case 2:
@@ -2036,11 +2109,39 @@ void ncr5380_bput(struct soft_scsi *scsi, int reg, uae_u8 v)
                        scsi->dma_active = true;
                        scsi->dma_started = true;
                        dma_check(scsi);
+#if NCR5380_DEBUG
+                       write_log(_T("DMA initiator recv PC=%08x\n"), M68K_GETPC);
+#endif
                }
+               break;
+
+               case 17: // DP8490V MODE_E
+               {
+                       int efr = (old >> 1) & 3;
+                       if (efr == 3) {
+                               scsi->regs[18] = v;
+                               scsi->regs[17] &= ~(3 << 1);
+                       } else {
+                               int efr = (v >> 1) & 3;
+                               if (efr == 1) {
+                                       scsi->irq = false;
+                               } else if (efr == 2) {
+                                       if (scsi->regs[2] & 2) {
+                                               // start DMA initiator receive
+                                               scsi->dma_direction = -1;
+                                               scsi->dma_active = true;
+                                               scsi->dma_started = true;
+                                               dma_check(scsi);
 #if NCR5380_DEBUG
-               write_log(_T("DMA initiator recv PC=%08x\n"), M68K_GETPC);
+                                               write_log(_T("DMA8490 initiator recv PC=%08x\n"), M68K_GETPC);
 #endif
+                                       }
+                               }
+                       }       
+               }
                break;
+
+
                case 8: // fake dma port
                if (r->bus_phase == (scsi->regs[3] & 7)) {
                        raw_scsi_put_data(r, v, true);
@@ -2760,6 +2861,13 @@ static int overdrive_reg(struct soft_scsi *ncr, uaecptr addr)
        return -1;
 }
 
+static int fireball_reg(struct soft_scsi* ncr, uaecptr addr)
+{
+       if ((addr & 0xc000) != 0x4000)
+               return -1;
+       return (addr >> 1) & 7;
+}
+
 static uae_u8 read_684xx_dma(struct soft_scsi *ncr, uaecptr addr)
 {
        uae_u8 val = 0;
@@ -3212,7 +3320,8 @@ static uae_u32 ncr80_bget2(struct soft_scsi *ncr, uaecptr addr, int size)
                        v = ncr->rom[addr];
                }
 
-       } else if (ncr->type == NCR5380_ADSCSI) {
+       } else if (ncr->type == NCR5380_ADSCSI || ncr->type == NCR5380_SYNTHESIS) {
+
 
                struct raw_scsi *rs = &ncr->rscsi;
                if (ncr->configured)
@@ -3491,10 +3600,21 @@ static uae_u32 ncr80_bget2(struct soft_scsi *ncr, uaecptr addr, int size)
                        v = ncr->rom[addr & 0x3fff];
                }
 
+       } else if (ncr->type == NCR5380_FIREBALL) {
+
+               reg = fireball_reg(ncr, addr);
+               if (reg >= 0) {
+                       v = ncr5380_bget(ncr, reg);
+               } else if ((addr & 0xc000) == 0xc000) {
+                       v = ncr->rom[addr & 0x3fff];
+               } else if (addr < 128) {
+                       v = ncr->acmemory[addr];
+               }
+
        }
 
 #if NCR5380_DEBUG > 1
-       if (0 || origaddr < 0x8000)
+       if (0 || (origaddr & 0xffff) <= 0x8100)
                write_log(_T("GET %08x %02x %d %08x %d\n"), origaddr, v, reg, M68K_GETPC, regs.intmask);
 #endif
 
@@ -3687,7 +3807,7 @@ static void ncr80_bput2(struct soft_scsi *ncr, uaecptr addr, uae_u32 val, int si
                        }
                }
 
-       } else if (ncr->type == NCR5380_ADSCSI) {
+       } else if (ncr->type == NCR5380_ADSCSI || ncr->type == NCR5380_SYNTHESIS) {
 
                if (ncr->configured)
                        reg = adscsi_reg(ncr, addr, true);
@@ -3908,10 +4028,57 @@ static void ncr80_bput2(struct soft_scsi *ncr, uaecptr addr, uae_u32 val, int si
                        else
                                ncr5380_bput(ncr, reg, val);
                }
+       
+       } else if (ncr->type == NCR5380_FIREBALL) {
+
+               if ((addr & 0xc000) == 0x8000) {
+                       // this is strange way to set up DMA address..
+                       if (val & 0x40) {
+                               ncr->dmac_address = 0x00777777;
+                               ncr->dmac_length = 1;
+                               ncr->dmac_active = 1;
+                       }
+                       if (!(val & 0xc0) && val && ncr->dmac_length > 0 && ncr->dmac_length <= 8) {
+                               // nybbles, value 0 to 7
+                               for (int i = 0; i < 6; i++) {
+                                       int shift = i * 4;
+                                       int bm = 1 << i;
+                                       if (!(val & bm)) {
+                                               uae_u8 n = (ncr->dmac_length - 1) & 0x0f;
+                                               uae_u8 v = (ncr->dmac_address >> shift) & 0x0f;
+                                               if (v > n)
+                                                       v = n;
+                                               ncr->dmac_address &= ~(0x0f << shift);
+                                               ncr->dmac_address |= (v & 0x0f) << shift;
+                                       }
+                               }
+                               ncr->dmac_length++;
+                       }
+                       if (ncr->dmac_length > 8 && !(val & 0xc0) && val) {
+                               // nybbles, value 8 to 15..
+                               for (int i = 0; i < 6; i++) {
+                                       int bm = 1 << i;
+                                       if (val & bm) {
+                                               int shift = i * 4;
+                                               uae_u8 v = (ncr->dmac_address >> shift) & 0x0f;
+                                               v++;
+                                               ncr->dmac_address &= ~(0x0f << shift);
+                                               ncr->dmac_address |= (v & 0x0f) << shift;
+                                       }
+                               }
+                       }
+                       ncr->dmac_direction = (val & 0x80) != 0;
+               } else {
+                       reg = fireball_reg(ncr, addr);
+                       if (reg >= 0) {
+                               ncr5380_bput(ncr, reg, val);
+                       }
+               }
+
        }
 
 #if NCR5380_DEBUG > 1
-       if (origaddr < 0x8000)
+       if ((origaddr & 0xffff) <= 0x8100)
                write_log(_T("PUT %08x %02x %d %08x %d\n"), origaddr, val, reg, M68K_GETPC, regs.intmask);
 #endif
 }
@@ -4439,6 +4606,60 @@ void adscsi_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfi
        generic_soft_scsi_add(ch, ci, rc, NCR5380_ADSCSI, 65536, 65536, ROMTYPE_ADSCSI);
 }
 
+bool synthesis_init(struct autoconfig_info* aci)
+{
+       scsi_add_reset();
+       if (!aci->doinit) {
+               load_rom_rc(aci->rc, ROMTYPE_SYNTHESIS, 32768, 0, aci->autoconfig_raw, 128, LOADROM_EVENONLY_ODDONE | LOADROM_FILL);
+               return true;
+       }
+
+       struct soft_scsi* scsi = getscsi(aci->rc);
+       if (!scsi)
+               return false;
+
+       load_rom_rc(aci->rc, ROMTYPE_SYNTHESIS, 32768, 0, scsi->rom, 65536, LOADROM_EVENONLY_ODDONE | LOADROM_FILL);
+       memcpy(scsi->acmemory, scsi->rom, sizeof scsi->acmemory);
+       aci->addrbank = scsi->bank;
+}
+
+void synthesis_add_scsi_unit(int ch, struct uaedev_config_info* ci, struct romconfig* rc)
+{
+       generic_soft_scsi_add(ch, ci, rc, NCR5380_SYNTHESIS, 65536, 65536, ROMTYPE_SYNTHESIS);
+}
+
+bool fireball_init(struct autoconfig_info* aci)
+{
+       const struct expansionromtype* ert = get_device_expansion_rom(ROMTYPE_MASTFB);
+       scsi_add_reset();
+       aci->autoconfigp = ert->autoconfig;
+       if (!aci->doinit)
+               return true;
+
+       struct soft_scsi* scsi = getscsi(aci->rc);
+       if (!scsi)
+               return false;
+
+       scsi->dp8490v = true;
+       scsi->intena = true;
+       scsi->dma_controller = true;
+
+       load_rom_rc(aci->rc, ROMTYPE_MASTFB, 8192, 0, scsi->rom, 16384, LOADROM_EVENONLY_ODDONE | LOADROM_FILL);
+
+       for (int i = 0; i < 16; i++) {
+               uae_u8 b = ert->autoconfig[i];
+               ew(scsi, i * 4, b);
+       }
+       aci->addrbank = scsi->bank;
+       return true;
+}
+
+void fireball_add_scsi_unit(int ch, struct uaedev_config_info* ci, struct romconfig* rc)
+{
+       generic_soft_scsi_add(ch, ci, rc, NCR5380_FIREBALL, 65536, 16384, ROMTYPE_MASTFB);
+}
+
+
 bool trumpcardpro_init(struct autoconfig_info *aci)
 {
        const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_IVSTPRO);
@@ -4465,7 +4686,7 @@ bool trumpcardpro_init(struct autoconfig_info *aci)
 
 void trumpcardpro_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc)
 {
-       generic_soft_scsi_add(ch, ci, rc, NCR5380_TRUMPCARDPRO, 65536, 32768, NCR5380_TRUMPCARDPRO);
+       generic_soft_scsi_add(ch, ci, rc, NCR5380_TRUMPCARDPRO, 65536, 32768, ROMTYPE_IVSTPRO);
 }
 
 bool trumpcard_init(struct autoconfig_info *aci)