From 06691afed240ea185c5958ec7e4085a27736c1c8 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sun, 6 Dec 2020 13:34:58 +0200 Subject: [PATCH] Hardital Synthesis and MAST Fireball HD controller emulation. --- expansion.cpp | 15 +++ include/rommgr.h | 2 + include/scsi.h | 6 ++ rommgr.cpp | 6 +- scsi.cpp | 239 +++++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 258 insertions(+), 10 deletions(-) diff --git a/expansion.cpp b/expansion.cpp index 396a81e6..ee157c26 100644 --- a/expansion.cpp +++ b/expansion.cpp @@ -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, diff --git a/include/rommgr.h b/include/rommgr.h index 74bc441f..1d160124 100644 --- a/include/rommgr.h +++ b/include/rommgr.h @@ -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 diff --git a/include/scsi.h b/include/scsi.h index 2f0e1a44..0646b25c 100644 --- a/include/scsi.h +++ b/include/scsi.h @@ -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); diff --git a/rommgr.cpp b/rommgr.cpp index f25ee9ca..f0f656ef 100644 --- a/rommgr.cpp +++ b/rommgr.cpp @@ -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") }, diff --git a/scsi.cpp b/scsi.cpp index 78c9f0bb..a92f7d24 100644 --- 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) -- 2.47.3