From: Toni Wilen Date: Tue, 12 May 2015 16:10:32 +0000 (+0300) Subject: 53C80 emulation improvements, C-Ltd A1000/A2000, Preferred Technologies Nexus and... X-Git-Tag: 3100~38 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=e909792c8263f4b1ee2bd7922564adb0c2cb6142;p=francis%2Fwinuae.git 53C80 emulation improvements, C-Ltd A1000/A2000, Preferred Technologies Nexus and DataFlyer 1200/4000 SCSI. --- diff --git a/a2091.cpp b/a2091.cpp index 4213b1f5..0d12c479 100644 --- a/a2091.cpp +++ b/a2091.cpp @@ -642,9 +642,9 @@ static bool do_dma_commodore_8727(struct wd_state *wd, struct scsi_data *scsi) for (;;) { uae_u8 v1 = 0, v2 = 0; int status; - status = scsi_receive_data (scsi, &v1); + status = scsi_receive_data (scsi, &v1, true); if (!status) - status = scsi_receive_data (scsi, &v2); + status = scsi_receive_data(scsi, &v2, true); put_word((wd->cdmac.dmac_acr << 1) & 0xffffff, (v1 << 8) | v2); if (wd->wc.wd_dataoffset < sizeof wd->wc.wd_data) { wd->wc.wd_data[wd->wc.wd_dataoffset++] = v1; @@ -709,7 +709,7 @@ static bool do_dma_commodore(struct wd_state *wd, struct scsi_data *scsi) bool run = true; while (run) { uae_u8 v; - int status = scsi_receive_data (scsi, &v); + int status = scsi_receive_data(scsi, &v, true); put_byte(wd->cdmac.dmac_acr, v); if (wd->wc.wd_dataoffset < sizeof wd->wc.wd_data) wd->wc.wd_data[wd->wc.wd_dataoffset++] = v; @@ -755,7 +755,7 @@ static bool do_dma_gvp_s1(struct wd_state *wd, struct scsi_data *scsi) if (scsi->direction < 0) { for (;;) { uae_u8 v; - int status = scsi_receive_data (scsi, &v); + int status = scsi_receive_data(scsi, &v, true); wd->gdmac.buffer[wd->wc.wd_dataoffset++] = v; wd->wc.wd_dataoffset &= wd->gdmac.s1_rammask; if (decreasetc (&wd->wc)) @@ -803,7 +803,7 @@ static bool do_dma_gvp_s2(struct wd_state *wd, struct scsi_data *scsi) } for (;;) { uae_u8 v; - int status = scsi_receive_data (scsi, &v); + int status = scsi_receive_data(scsi, &v, true); put_byte(wd->gdmac.addr, v); if (wd->wc.wd_dataoffset < sizeof wd->wc.wd_data) wd->wc.wd_data[wd->wc.wd_dataoffset++] = v; @@ -1517,7 +1517,7 @@ uae_u8 wdscsi_get (struct wd_chip_state *wd, struct wd_state *wds) write_log (_T("%s WD_DATA READ without data request!?\n"), WD33C93); return 0; } - int status = scsi_receive_data (wd->scsi, &v); + int status = scsi_receive_data(wd->scsi, &v, true); #if WD33C93_DEBUG_PIO write_log (_T("%s WD_DATA READ %02x %d/%d\n"), WD33C93, v, wd->scsi->offset, wd->scsi->data_len); #endif diff --git a/expansion.cpp b/expansion.cpp index 07354a7c..6f6a6bce 100644 --- a/expansion.cpp +++ b/expansion.cpp @@ -2242,7 +2242,26 @@ static const struct expansionsubromtype supra_sub[] = { NULL } }; - +static const struct expansionsubromtype nexus_sub[] = { + { + _T("2M Fast (Product ID 2)"), _T("fast2m"), + 2102, 2, 0, + { 0xd1, 0x01, 0x00, 0x00, 0x08, 0x36, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 }, + }, + { + _T("4M Fast (Product ID 4)"), _T("fast4m"), + 2102, 4, 0, + { 0xd1, 0x01, 0x00, 0x00, 0x08, 0x36, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 }, + }, + { + _T("8M Fast (Product ID 8)"), _T("fast8m"), + 2102, 8, 0, + { 0xd1, 0x01, 0x00, 0x00, 0x08, 0x36, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 }, + }, + { + NULL + } +}; static const struct expansionboardsettings adscsi2000_settings[] = { { _T("Cache (B)"), @@ -2415,6 +2434,30 @@ const struct expansionromtype expansionroms[] = { true, EXPANSIONTYPE_IDE | EXPANSIONTYPE_SCSI | EXPANSIONTYPE_IDE_PORT_DOUBLED, 2144, 2, 0 }, + { + _T("a1000scsi"), _T("A1000/A2000 SCSI"), _T("C-Ltd"), + cltda1000scsi_init, cltda1000scsi_add_scsi_unit, ROMTYPE_CLTDSCSI | ROMTYPE_NONE, 0, 0, 2, false, + NULL, 0, + false, EXPANSIONTYPE_SCSI, + 0, 0, 0, + false, NULL, + { 0xc1, 0x0c, 0x00, 0x00, 0x03, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + }, + { + _T("ptnexus"), _T("Nexus"), _T("Preferred Technologies"), + ptnexus_init, ptnexus_add_scsi_unit, ROMTYPE_PTNEXUS | ROMTYPE_NONE, 0, 0, 2, false, + nexus_sub, 0, + false, EXPANSIONTYPE_SCSI, + 2102, 4, 0, + false, NULL, + { 0xd1, 0x01, 0x00, 0x00, 0x08, 0x36, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 }, + }, + { + _T("dataflyerscsiplus"), _T("DataFlyer SCSI+"), _T("Expansion Systems"), + dataflyer_init, dataflyer_add_scsi_unit, ROMTYPE_DATAFLYER | ROMTYPE_NONE, 0, 0, 1, true, + NULL, 0, + false, EXPANSIONTYPE_SCSI, + }, #if 0 { _T("kronos"), _T("Kronos"), _T("C-Ltd"), diff --git a/gayle.cpp b/gayle.cpp index 60c8a9a8..a9fb69a5 100644 --- a/gayle.cpp +++ b/gayle.cpp @@ -29,6 +29,8 @@ #include "blkdev.h" #include "scsi.h" #include "ide.h" +#include "idecontrollers.h" +#include "debug.h" #define PCMCIA_SRAM 1 #define PCMCIA_IDE 2 @@ -153,6 +155,10 @@ static int ide_splitter; static struct ide_thread_state gayle_its; +static int dataflyer_state; +static int dataflyer_disable_irq; +static uae_u8 dataflyer_byte; + static void pcmcia_reset (void) { memset (pcmcia_configuration, 0, sizeof pcmcia_configuration); @@ -177,6 +183,10 @@ static uae_u8 checkgayleideirq (void) int i; bool irq = false; + if (dataflyer_disable_irq) { + gayle_irq &= ~GAYLE_IRQ_IDE; + return 0; + } for (i = 0; i < 2; i++) { if (idedrive[i]) { if (!(idedrive[i]->regs.ide_devcon & 2) && (idedrive[i]->irq || (idedrive[i + 2] && idedrive[i + 2]->irq))) @@ -390,7 +400,7 @@ static void gayle_write2 (uaecptr addr, uae_u32 val) struct ide_hdf *ide = NULL; int ide_reg; - if ((GAYLE_LOG > 3 && (addr != 0x2000 && addr != 0x2001 && addr != 0x2020 && addr != 0x2021 && addr != GAYLE_IRQ_1200)) || GAYLE_LOG > 5) + if ((GAYLE_LOG > 3 && (addr != 0x2000 && addr != 0x2001 && addr != 0x3020 && addr != 0x3021 && addr != GAYLE_IRQ_1200)) || GAYLE_LOG > 5) write_log (_T("IDE_WRITE %08X=%02X PC=%X\n"), addr, (uae_u32)val & 0xff, M68K_GETPC); if (currprefs.cs_ide <= 0) return; @@ -501,6 +511,77 @@ addrbank gayle_bank = { dummy_lgeti, dummy_wgeti, ABFLAG_IO }; +void gayle_dataflyer_enable(bool enable) +{ + if (!enable) { + dataflyer_state = 0; + dataflyer_disable_irq = 0; + return; + } + dataflyer_state = 1; +} + +static bool isdataflyerscsiplus(uaecptr addr, uae_u32 *v, int size) +{ + if (!dataflyer_state) + return false; + uaecptr addrmask = addr & 0xffff; + if (addrmask >= GAYLE_IRQ_4000 && addrmask <= GAYLE_IRQ_4000 + 1 && currprefs.cs_ide == IDE_A4000) + return false; + uaecptr addrbase = (addr & ~0xff) & ~0x1020; + int reg = ((addr & 0xffff) & ~0x2020) >> 2; + if (reg >= IDE_SECONDARY) { + reg &= ~IDE_SECONDARY; + if (reg >= 6) // normal IDE registers + return false; + if (size < 0) { + switch (reg) + { + case 0: // 53C80 fake dma port + soft_scsi_put(addrbase | 8, 1, *v); + break; + case 3: + dataflyer_byte = *v; + break; + } + } else { + switch (reg) + { + case 0: // 53C80 fake dma port + *v = soft_scsi_get(addrbase | 8, 1); + break; + case 3: + *v = 0; + if (ide_irq_check(idedrive[0])) + *v = dataflyer_byte; + break; + case 4: // select SCSI + dataflyer_disable_irq = 1; + dataflyer_state |= 2; + break; + case 5: // select IDE + dataflyer_disable_irq = 1; + dataflyer_state &= ~2; + break; + } + } +#if 0 + if (size < 0) + write_log(_T("SECONDARY BASE PUT(%d) %08x %08x PC=%08x\n"), -size, addr, *v, M68K_GETPC); + else + write_log(_T("SECONDARY BASE GET(%d) %08x PC=%08x\n"), size, addr, M68K_GETPC); +#endif + return true; + } + if (!(dataflyer_state & 2)) + return false; + if (size < 0) + soft_scsi_put(addrbase | reg, -size, *v); + else + *v = soft_scsi_get(addrbase | reg, size); + return true; +} + static bool isa4000t (uaecptr *paddr) { if (currprefs.cs_mbdmac != 2) @@ -524,6 +605,9 @@ static uae_u32 REGPARAM2 gayle_lget (uaecptr addr) #ifdef NCR if (currprefs.cs_mbdmac == 2 && (addr & 0xffff) == 0x3000) return 0xffffffff; // NCR DIP BANK + if (isdataflyerscsiplus(addr, &v, 4)) { + return v; + } if (isa4000t (&addr)) { if (addr >= NCR_ALT_OFFSET) { addr &= NCR_MASK; @@ -551,14 +635,17 @@ static uae_u32 REGPARAM2 gayle_wget (uaecptr addr) { struct ide_hdf *ide = NULL; int ide_reg; - uae_u16 v; + uae_u32 v; #ifdef JIT special_mem |= S_READ; #endif #ifdef NCR if (currprefs.cs_mbdmac == 2 && (addr & (0xffff - 1)) == 0x3000) return 0xffff; // NCR DIP BANK - if (isa4000t (&addr)) { + if (isdataflyerscsiplus(addr, &v, 2)) { + return v; + } + if (isa4000t(&addr)) { if (addr >= NCR_OFFSET) { addr &= NCR_MASK; v = (ncr710_io_bget_a4000t(addr) << 8) | ncr710_io_bget_a4000t(addr + 1); @@ -575,13 +662,17 @@ static uae_u32 REGPARAM2 gayle_wget (uaecptr addr) } static uae_u32 REGPARAM2 gayle_bget (uaecptr addr) { + uae_u32 v; #ifdef JIT special_mem |= S_READ; #endif #ifdef NCR if (currprefs.cs_mbdmac == 2 && (addr & (0xffff - 3)) == 0x3000) return 0xff; // NCR DIP BANK - if (isa4000t (&addr)) { + if (isdataflyerscsiplus(addr, &v, 1)) { + return v; + } + if (isa4000t(&addr)) { if (addr >= NCR_OFFSET) { addr &= NCR_MASK; return ncr710_io_bget_a4000t(addr); @@ -589,7 +680,8 @@ static uae_u32 REGPARAM2 gayle_bget (uaecptr addr) return 0; } #endif - return gayle_read (addr); + v = gayle_read (addr); + return v; } static void REGPARAM2 gayle_lput (uaecptr addr, uae_u32 value) @@ -599,7 +691,10 @@ static void REGPARAM2 gayle_lput (uaecptr addr, uae_u32 value) #ifdef JIT special_mem |= S_WRITE; #endif - if (isa4000t (&addr)) { + if (isdataflyerscsiplus(addr, &value, -4)) { + return; + } + if (isa4000t(&addr)) { if (addr >= NCR_ALT_OFFSET) { addr &= NCR_MASK; ncr710_io_bput_a4000t(addr + 3, value >> 0); @@ -632,7 +727,10 @@ static void REGPARAM2 gayle_wput (uaecptr addr, uae_u32 value) special_mem |= S_WRITE; #endif #ifdef NCR - if (isa4000t (&addr)) { + if (isdataflyerscsiplus(addr, &value, -2)) { + return; + } + if (isa4000t(&addr)) { if (addr >= NCR_OFFSET) { addr &= NCR_MASK; ncr710_io_bput_a4000t(addr, value >> 8); @@ -656,7 +754,10 @@ static void REGPARAM2 gayle_bput (uaecptr addr, uae_u32 value) special_mem |= S_WRITE; #endif #ifdef NCR - if (isa4000t (&addr)) { + if (isdataflyerscsiplus(addr, &value, -1)) { + return; + } + if (isa4000t(&addr)) { if (addr >= NCR_OFFSET) { addr &= NCR_MASK; ncr710_io_bput_a4000t(addr, value); @@ -1687,6 +1788,7 @@ void gayle_reset (int hardreset) } #endif gayle_bank.name = bankname; + gayle_dataflyer_enable(false); } uae_u8 *restore_gayle (uae_u8 *src) diff --git a/include/gayle.h b/include/gayle.h index 06b17d5a..3cb18f9a 100644 --- a/include/gayle.h +++ b/include/gayle.h @@ -16,3 +16,5 @@ extern int gary_timeout; // non-existing memory access = delay #define PCMCIA_COMMON_START 0x600000 #define PCMCIA_COMMON_SIZE 0x400000 + +extern void gayle_dataflyer_enable(bool); \ No newline at end of file diff --git a/include/rommgr.h b/include/rommgr.h index d77b2388..e1d21313 100644 --- a/include/rommgr.h +++ b/include/rommgr.h @@ -69,6 +69,9 @@ extern int decode_cloanto_rom_do (uae_u8 *mem, int size, int real_size); #define ROMTYPE_KRONOS 0x00100018 #define ROMTYPE_ADSCSI 0x00100019 #define ROMTYPE_ROCHARD 0x0010001a +#define ROMTYPE_CLTDSCSI 0x0010001b +#define ROMTYPE_PTNEXUS 0x0010001c +#define ROMTYPE_DATAFLYER 0x0010001d #define ROMTYPE_QUAD 0x01000000 #define ROMTYPE_EVEN 0x02000000 diff --git a/include/scsi.h b/include/scsi.h index f15ab8d2..358c900e 100644 --- a/include/scsi.h +++ b/include/scsi.h @@ -56,7 +56,7 @@ extern void scsi_reset(void); extern void scsi_start_transfer(struct scsi_data*); extern int scsi_send_data(struct scsi_data*, uae_u8); -extern int scsi_receive_data(struct scsi_data*, uae_u8*); +extern int scsi_receive_data(struct scsi_data*, uae_u8*, bool next); extern void scsi_emulate_cmd(struct scsi_data *sd); extern void scsi_illegal_lun(struct scsi_data *sd); extern void scsi_clear_sense(struct scsi_data *sd); @@ -148,6 +148,9 @@ static uae_u32 REGPARAM2 x ## _lget(uaecptr addr) \ return y ## _lget(& ## z, addr); \ } +void soft_scsi_put(uaecptr addr, int size, uae_u32 v); +uae_u32 soft_scsi_get(uaecptr addr, int size); + void ncr80_rethink(void); void apollo_scsi_bput(uaecptr addr, uae_u8 v); @@ -188,3 +191,12 @@ void rochard_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconf bool rochard_scsi_init(struct romconfig *rc, uaecptr baseaddress); uae_u8 rochard_scsi_get(uaecptr addr); void rochard_scsi_put(uaecptr addr, uae_u8 v); + +addrbank *cltda1000scsi_init(struct romconfig *rc); +void cltda1000scsi_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc); + +addrbank *ptnexus_init(struct romconfig *rc); +void ptnexus_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc); + +addrbank *dataflyer_init(struct romconfig *rc); +void dataflyer_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc); diff --git a/rommgr.cpp b/rommgr.cpp index f609b6d9..3bf63280 100644 --- a/rommgr.cpp +++ b/rommgr.cpp @@ -95,7 +95,7 @@ struct romdata *getromdatabypath (const TCHAR *path) return NULL; } -#define NEXT_ROM_ID 139 +#define NEXT_ROM_ID 140 static struct romheader romheaders[] = { { _T("Freezer Cartridges"), 1 }, @@ -369,8 +369,10 @@ static struct romdata roms[] = { { _T("Kupke Golem 030"), 0, 0, 0, 0, _T("GOLEM030\0"), 8192, 126, 0, 0, ROMTYPE_CB_GOLEM030, 0, 0, NULL, 0x05d473f4, 0x574ec567,0xcc67e06f,0x91dcecb9,0x8c204399,0x5fe2a09f, NULL, NULL }, + { _T("Preferred Technologies Nexus"), 1, 0, 1, 0, _T("PTNEXUS\0"), 8192, 139, 0, 0, ROMTYPE_PTNEXUS, 0, 0, NULL, + 0xf495879a, 0xa3bd0202, 0xe14aa5b6, 0x49d3ce88, 0x22975950, 0x6500dbc2, NULL, NULL }, { _T("ICD AdSCSI 2000"), 1, 6, 1, 6, _T("ADSCSI\0"), 32768, 133, 0, 0, ROMTYPE_ADSCSI, 0, 0, NULL, - 0x7dba3e1f, 0x1e05f284,0xd59a1e5d,0x4e4de44e,0x6f075175,0x625cd6c0, NULL, NULL }, + 0x7dba3e1f, 0x1e05f284, 0xd59a1e5d, 0x4e4de44e, 0x6f075175, 0x625cd6c0, NULL, NULL }, { _T("Archos ADD-500"), 1, 21, 1, 21, _T("ADD\0"), 16384, 132, 0, 0, ROMTYPE_ADD500, 0, 0, NULL, 0x3f4e4a74, 0x9ed96fc0,0xd6381dc3,0x3192b0af,0xdfae4b74,0x576c3a69, NULL, NULL }, { _T("Protar A500HD"), 1, 193, 1, 193, _T("PROTAR\0"), 32768, 131, 0, 0, ROMTYPE_PROTAR, 0, 0, NULL, @@ -1705,6 +1707,8 @@ struct boardromconfig *get_device_rom(struct uae_prefs *p, int romtype, int devn *index = ert->parentromtype ? 1 : 0; for (int i = 0; i < MAX_EXPANSION_BOARDS; i++) { struct boardromconfig *brc = &p->expansionboard[i]; + if (!brc->device_type) + continue; if ((brc->device_type & ROMTYPE_MASK) == (parentrom & ROMTYPE_MASK) && brc->device_num == devnum) return brc; } @@ -1778,6 +1782,8 @@ struct boardromconfig *get_boardromconfig(struct uae_prefs *p, int romtype, int { for (int i = 0; i < MAX_EXPANSION_BOARDS; i++) { struct boardromconfig *brc = &p->expansionboard[i]; + if (!brc->device_type) + continue; if ((brc->device_type & ROMTYPE_MASK) == (romtype & ROMTYPE_MASK)) { for (int j = 0; j < MAX_BOARD_ROMS; j++) { if (brc->roms[j].romfile[0]) { @@ -1842,4 +1848,4 @@ bool load_rom_rc(struct romconfig *rc, const int *roms, int maxfilesize, int fil oldpos = 0; } return true; -} \ No newline at end of file +} diff --git a/scsi.cpp b/scsi.cpp index 194f9b3e..79437b7d 100644 --- a/scsi.cpp +++ b/scsi.cpp @@ -21,10 +21,12 @@ #include "rommgr.h" #include "newcpu.h" #include "custom.h" +#include "gayle.h" #define SCSI_EMU_DEBUG 0 #define RAW_SCSI_DEBUG 1 #define NCR5380_DEBUG 0 +#define NCR5380_DEBUG_IRQ 0 #define NCR5380_SUPRA 1 #define NONCR_GOLEM 2 @@ -37,7 +39,10 @@ #define NCR5380_KRONOS 9 #define NCR5380_ADSCSI 10 #define NCR5380_ROCHARD 11 -#define NCR_LAST 12 +#define NCR5380_CLTD 12 +#define NCR5380_PTNEXUS 13 +#define NCR5380_DATAFLYER 14 +#define NCR_LAST 15 extern int log_scsiemu; @@ -171,8 +176,20 @@ bool scsi_emulate_analyze (struct scsi_data *sd) sd->direction = 0; } return true; + case 0x15: // MODE SELECT + case 0x55: + if (sd->device_type != UAEDEV_CD && sd->device_type != UAEDEV_TAPE) + goto nocmd; + break; + } + if (data_len < 0) { + if (cmd_len == 6) + sd->data_len = sd->cmd[4]; + else + sd->data_len = (sd->cmd[7] << 8) | sd->cmd[8]; + } else { + sd->data_len = data_len; } - sd->data_len = data_len; sd->direction = scsi_data_dir (sd); return true; nocmd: @@ -434,13 +451,16 @@ int scsi_send_data(struct scsi_data *sd, uae_u8 b) return 0; } -int scsi_receive_data(struct scsi_data *sd, uae_u8 *b) +int scsi_receive_data(struct scsi_data *sd, uae_u8 *b, bool next) { if (!sd->data_len) return -1; - *b = sd->buffer[sd->offset++]; - if (sd->offset == sd->data_len) - return 1; // requested length got + *b = sd->buffer[sd->offset]; + if (next) { + sd->offset++; + if (sd->offset == sd->data_len) + return 1; // requested length got + } return 0; } @@ -576,9 +596,8 @@ struct raw_scsi int bus_phase; bool atn; bool ack; - bool use_ack; bool wait_ack; - uae_u8 data; + uae_u8 data_write; uae_u8 status; bool databusoutput; int initiator_id, target_id; @@ -589,14 +608,14 @@ struct raw_scsi struct soft_scsi { - uae_u8 regs[8]; - bool c400; + uae_u8 regs[8 + 1]; uae_u8 regs_400[2]; int c400_count; struct raw_scsi rscsi; bool irq; bool intena; bool enabled; + bool delayed_irq; bool configured; uae_u8 acmemory[128]; uaecptr baseaddress; @@ -609,6 +628,8 @@ struct soft_scsi int type; int subtype; int dma_direction; + bool dma_active; + bool dma_controller; struct romconfig *rc; struct soft_scsi **self_ptr; @@ -824,22 +845,30 @@ void raw_scsi_set_signal_phase(struct raw_scsi *rs, bool busy, bool select, bool { case SCSI_SIGNAL_PHASE_FREE: if (busy && !select && !rs->databusoutput) { + if (countbits(rs->data_write) != 1) { +#if RAW_SCSI_DEBUG + write_log(_T("raw_scsi: invalid arbitration scsi id mask! (%02x)\n"), rs->data_write); +#endif + return; + } rs->bus_phase = SCSI_SIGNAL_PHASE_ARBIT; - rs->initiator_id = getbit(rs->data); + rs->initiator_id = getbit(rs->data_write); #if RAW_SCSI_DEBUG - write_log(_T("raw_scsi: arbitration initiator id %d\n"), rs->initiator_id); + write_log(_T("raw_scsi: arbitration initiator id %d (%02x)\n"), rs->initiator_id, rs->data_write); #endif } else if (!busy && select) { - if (countbits(rs->data) == 1) { - // In SCSI-1 initiator ID is optional. - rs->data |= 0x80; + if (countbits(rs->data_write) > 2 || rs->data_write == 0) { +#if RAW_SCSI_DEBUG + write_log(_T("raw_scsi: invalid scsi id selected mask (%02x)\n"), rs->data_write); +#endif + return; } - rs->initiator_id = getbit(rs->data); + rs->initiator_id = -1; rs->bus_phase = SCSI_SIGNAL_PHASE_SELECT_1; - raw_scsi_set_signal_phase(rs, busy, select, atn); #if RAW_SCSI_DEBUG - write_log(_T("raw_scsi: selected initiator id %d\n"), rs->initiator_id); + write_log(_T("raw_scsi: selected scsi id mask (%02x)\n"), rs->data_write); #endif + raw_scsi_set_signal_phase(rs, busy, select, atn); } break; case SCSI_SIGNAL_PHASE_ARBIT: @@ -852,23 +881,31 @@ void raw_scsi_set_signal_phase(struct raw_scsi *rs, bool busy, bool select, bool case SCSI_SIGNAL_PHASE_SELECT_1: rs->atn = atn; rs->msglun = -1; + rs->target_id = -1; if (!busy) { - uae_u8 data = rs->data & ~(1 << rs->initiator_id); - rs->target_id = getbit(data); - if (rs->target_id >= 0) { - rs->target = rs->device[rs->target_id]; - if (rs->target) { + for (int i = 0; i < 8; i++) { + if (i == rs->initiator_id) + continue; + if ((rs->data_write & (1 << i)) && rs->device[i]) { + rs->target_id = i; + rs->target = rs->device[rs->target_id]; #if RAW_SCSI_DEBUG write_log(_T("raw_scsi: selected id %d\n"), rs->target_id); #endif rs->io |= SCSI_IO_BUSY; - } else { + } + } #if RAW_SCSI_DEBUG - write_log(_T("raw_scsi: selected non-existing id %d\n"), rs->target_id); -#endif - rs->target_id = -1; + if (rs->target_id < 0) { + for (int i = 0; i < 8; i++) { + if (i == rs->initiator_id) + continue; + if ((rs->data_write & (1 << i)) && !rs->device[i]) { + write_log(_T("raw_scsi: selected non-existing id %d\n"), i); + } } } +#endif if (rs->target_id >= 0) { rs->bus_phase = SCSI_SIGNAL_PHASE_SELECT_2; } else { @@ -888,7 +925,7 @@ void raw_scsi_set_signal_phase(struct raw_scsi *rs, bool busy, bool select, bool } } -uae_u8 raw_scsi_get_signal_phase(struct raw_scsi *rs) +static uae_u8 raw_scsi_get_signal_phase(struct raw_scsi *rs) { uae_u8 v = rs->io; if (rs->bus_phase >= 0) @@ -898,7 +935,7 @@ uae_u8 raw_scsi_get_signal_phase(struct raw_scsi *rs) return v; } -uae_u8 raw_scsi_get_data(struct raw_scsi *rs) +static uae_u8 raw_scsi_get_data_2(struct raw_scsi *rs, bool next, bool nodebug) { struct scsi_data *sd = rs->target; uae_u8 v = 0; @@ -912,31 +949,39 @@ uae_u8 raw_scsi_get_data(struct raw_scsi *rs) #if RAW_SCSI_DEBUG write_log(_T("raw_scsi: arbitration\n")); #endif - v = rs->data; + v = rs->data_write; break; case SCSI_SIGNAL_PHASE_DATA_IN: - if (scsi_receive_data(sd, & v)) { - rs->bus_phase = SCSI_SIGNAL_PHASE_STATUS; -#if RAW_SCSI_DEBUG - write_log(_T("raw_scsi: data in finished, %d bytes: status phase\n"), sd->offset); +#if RAW_SCSI_DEBUG > 2 + scsi_receive_data(sd, &v, false); + write_log(_T("raw_scsi: read data byte %02x (%d/%d)\n"), v, sd->offset, sd->data_len); #endif + if (scsi_receive_data(sd, &v, next)) { + write_log(_T("raw_scsi: data in finished, %d bytes: status phase\n"), sd->offset); + rs->bus_phase = SCSI_SIGNAL_PHASE_STATUS; } break; case SCSI_SIGNAL_PHASE_STATUS: #if RAW_SCSI_DEBUG - write_log(_T("raw_scsi: status byte read %02x\n"), sd->status); + if (!nodebug) + write_log(_T("raw_scsi: status byte read %02x\n"), sd->status); #endif v = sd->status; - sd->status = 0; - rs->bus_phase = SCSI_SIGNAL_PHASE_MESSAGE_IN; + if (next) { + sd->status = 0; + rs->bus_phase = SCSI_SIGNAL_PHASE_MESSAGE_IN; + } break; case SCSI_SIGNAL_PHASE_MESSAGE_IN: #if RAW_SCSI_DEBUG - write_log(_T("raw_scsi: message byte read %02x\n"), sd->status); + if (!nodebug) + write_log(_T("raw_scsi: message byte read %02x\n"), sd->status); #endif v = sd->status; rs->status = v; - bus_free(rs); + if (next) { + bus_free(rs); + } break; default: write_log(_T("raw_scsi_get_data but bus phase is %d!\n"), rs->bus_phase); @@ -946,6 +991,12 @@ uae_u8 raw_scsi_get_data(struct raw_scsi *rs) return v; } +uae_u8 raw_scsi_get_data(struct raw_scsi *rs, bool next) +{ + return raw_scsi_get_data_2(rs, next, true); +} + + static int getmsglen(uae_u8 *msgp, int len) { uae_u8 msg = msgp[0]; @@ -1007,6 +1058,9 @@ static void raw_scsi_write_data(struct raw_scsi *rs, uae_u8 data) } break; case SCSI_SIGNAL_PHASE_DATA_OUT: +#if RAW_SCSI_DEBUG > 2 + write_log(_T("raw_scsi: write data byte %02x (%d/%d)\n"), data, sd->offset, sd->data_len); +#endif if (scsi_send_data(sd, data)) { #if RAW_SCSI_DEBUG write_log(_T("raw_scsi: data out finished, %d bytes\n"), sd->data_len); @@ -1033,20 +1087,28 @@ static void raw_scsi_write_data(struct raw_scsi *rs, uae_u8 data) } } -void raw_scsi_put_data(struct raw_scsi *rs, uae_u8 data, bool databusoutput, bool noack) +static void raw_scsi_put_data(struct raw_scsi *rs, uae_u8 data, bool databusoutput) { - rs->data = data; - if (((!rs->use_ack || noack) && (rs->bus_phase >= 0 && !(rs->io & SCSI_IO_REQ))) || !databusoutput) + rs->data_write = data; + if (!databusoutput) return; raw_scsi_write_data(rs, data); } -void raw_scsi_set_ack(struct raw_scsi *rs, bool ack) +static void raw_scsi_set_ack(struct raw_scsi *rs, bool ack) { if (rs->ack != ack) { rs->ack = ack; - if (ack && rs->use_ack && rs->bus_phase >= 0 && (rs->io & SCSI_IO_REQ) && !(rs->bus_phase & 1)) { - raw_scsi_write_data(rs, rs->data); + if (!ack) + return; + if (rs->bus_phase < 0) + return; + if (!(rs->bus_phase & SCSI_IO_DIRECTION)) { + if (rs->databusoutput) { + raw_scsi_write_data(rs, rs->data_write); + } + } else { + raw_scsi_get_data_2(rs, true, false); } } } @@ -1062,7 +1124,7 @@ void apollo_scsi_bput(uaecptr addr, uae_u8 v) struct raw_scsi *rs = &as->rscsi; addr &= 0x3fff; if (bank == 0) { - raw_scsi_put_data(rs, v, true, true); + raw_scsi_put_data(rs, v, true); } else if (bank == 0xc00 && !(addr & 1)) { as->irq = (v & 64) != 0; raw_scsi_set_signal_phase(rs, @@ -1070,7 +1132,7 @@ void apollo_scsi_bput(uaecptr addr, uae_u8 v) (v & 32) != 0, false); } else if (bank == 0x400 && (addr & 1)) { - raw_scsi_put_data(rs, v, true, true); + raw_scsi_put_data(rs, v, true); raw_scsi_set_signal_phase(rs, true, false, false); } //write_log(_T("apollo scsi put %04x = %02x\n"), addr, v); @@ -1086,7 +1148,7 @@ uae_u8 apollo_scsi_bget(uaecptr addr) uae_u8 v = 0xff; addr &= 0x3fff; if (bank == 0) { - v = raw_scsi_get_data(rs); + v = raw_scsi_get_data(rs, true); } else if (bank == 0x800 && (addr & 1)) { uae_u8 t = raw_scsi_get_signal_phase(rs); v = 1; // disable switch off @@ -1165,11 +1227,30 @@ void ncr80_rethink(void) static void ncr5380_set_irq(struct soft_scsi *scsi) { - if (scsi->irq && (scsi->regs[5] & (1 << 4))) + if (scsi->irq) return; scsi->irq = true; - scsi->regs[5] |= 1 << 4; ncr80_rethink(); + if (scsi->delayed_irq) + x_do_cycles(2 * CYCLE_UNIT); +#if NCR5380_DEBUG_IRQ + write_log(_T("IRQ\n")); +#endif +} + +static void ncr5380_databusoutput(struct soft_scsi *scsi) +{ + bool databusoutput = (scsi->regs[1] & 1) != 0; + struct raw_scsi *r = &scsi->rscsi; + + if (r->bus_phase >= 0 && (r->bus_phase & SCSI_IO_DIRECTION)) + databusoutput = false; + raw_scsi_set_databus(r, databusoutput); +} + +static void ncr5380_check(struct soft_scsi *scsi) +{ + ncr5380_databusoutput(scsi); } static void ncr5380_check_phase(struct soft_scsi *scsi) @@ -1179,8 +1260,10 @@ static void ncr5380_check_phase(struct soft_scsi *scsi) if (scsi->regs[2] & 0x40) return; if (scsi->rscsi.bus_phase != (scsi->regs[3] & 7)) { - scsi->regs[5] |= 0x80; // end of dma - scsi->regs[3] |= 0x80; // last byte sent + if (scsi->dma_controller) { + scsi->regs[5] |= 0x80; // end of dma + scsi->regs[3] |= 0x80; // last byte sent + } ncr5380_set_irq(scsi); } } @@ -1197,7 +1280,8 @@ static void ncr5380_reset(struct soft_scsi *scsi) uae_u8 ncr5380_bget(struct soft_scsi *scsi, int reg) { - reg &= 7; + if (reg > 8) + return 0; uae_u8 v = scsi->regs[reg]; struct raw_scsi *r = &scsi->rscsi; switch(reg) @@ -1232,47 +1316,64 @@ uae_u8 ncr5380_bget(struct soft_scsi *scsi, int reg) if (scsi->irq) { v |= 1 << 4; } - if ((t & SCSI_IO_REQ) && !scsi->c400) { + if (scsi->dma_active && !scsi->dma_controller) { v |= 1 << 6; } } break; case 0: + v = raw_scsi_get_data(r, false); + break; case 6: - v = raw_scsi_get_data(r); + v = raw_scsi_get_data(r, scsi->dma_active); + ncr5380_check_phase(scsi); break; case 7: scsi->irq = false; break; + case 8: // fake dma port + v = raw_scsi_get_data(r, true); + ncr5380_check_phase(scsi); + break; } - ncr5380_check_phase(scsi); + ncr5380_check(scsi); return v; } void ncr5380_bput(struct soft_scsi *scsi, int reg, uae_u8 v) { + if (reg > 8) + return; struct raw_scsi *r = &scsi->rscsi; - reg &= 7; uae_u8 old = scsi->regs[reg]; scsi->regs[reg] = v; switch(reg) { case 0: - raw_scsi_put_data(r, v, scsi->regs[1] & 1, false); + { + r->data_write = v; + // assert data bus can be only active if direction is out + // and bus phase matches + if (r->databusoutput) { + if (((scsi->regs[2] & 2) && scsi->dma_active) || r->bus_phase < 0) { + raw_scsi_write_data(r, v); + ncr5380_check_phase(scsi); + } + } + } break; case 1: scsi->regs[reg] &= ~((1 << 5) | (1 << 6)); scsi->regs[reg] |= old & ((1 << 5) | (1 << 6)); // AIP, LA if (!(v & 0x80)) { bool init = r->bus_phase < 0; - raw_scsi_set_databus(r, (v & 1) != 0); + ncr5380_databusoutput(scsi); raw_scsi_set_signal_phase(r, (v & (1 << 3)) != 0, (v & (1 << 2)) != 0, (v & (1 << 1)) != 0); - raw_scsi_set_ack(r, (v & (1 << 4)) != 0); -// if ((v & 1) && !(old & 1) && !(scsi->regs[2] & 2) && !init && !r->use_ack) -// raw_scsi_write_data(r, r->data); + if (!(scsi->regs[2] & 2)) + raw_scsi_set_ack(r, (v & (1 << 4)) != 0); } if (v & 0x80) { // RST ncr5380_reset(scsi); @@ -1288,33 +1389,48 @@ void ncr5380_bput(struct soft_scsi *scsi, int reg, uae_u8 v) scsi->regs[1] &= ~(1 << 6); } if (!(v & 2)) { - scsi->regs[2] &= ~(0x80 | 0x40); + // end of dma and dma request + scsi->regs[5] &= ~(0x80 | 0x40); scsi->dma_direction = 0; + scsi->dma_active = false; } break; case 5: scsi->regs[reg] = old; - scsi->dma_direction = 1; + if (scsi->regs[2] & 2) { + scsi->dma_direction = 1; + scsi->dma_active = true; + dma_check(scsi); + } #if NCR5380_DEBUG write_log(_T("DMA send\n")); #endif - dma_check(scsi); break; case 6: - scsi->dma_direction = 1; + if (scsi->regs[2] & 2) { + scsi->dma_direction = 1; + scsi->dma_active = true; + } #if NCR5380_DEBUG write_log(_T("DMA target recv\n")); #endif break; case 7: - scsi->dma_direction = -1; + if (scsi->regs[2] & 2) { + scsi->dma_direction = -1; + scsi->dma_active = true; + dma_check(scsi); + } #if NCR5380_DEBUG write_log(_T("DMA initiator recv\n")); #endif - dma_check(scsi); + break; + case 8: // fake dma port + raw_scsi_put_data(r, v, true); + ncr5380_check_phase(scsi); break; } - ncr5380_check_phase(scsi); + ncr5380_check(scsi); } static bool ncr53400_5380(struct soft_scsi *scsi) @@ -1349,7 +1465,7 @@ static uae_u8 ncr53400_bget(struct soft_scsi *scsi, int reg) return v; } if (reg & 0x80) { - v = raw_scsi_get_data(rs); + v = raw_scsi_get_data(rs, true); ncr53400_dmacount(scsi); } else if (reg & 0x100) { switch (reg) { @@ -1385,7 +1501,7 @@ static void ncr53400_bput(struct soft_scsi *scsi, int reg, uae_u8 v) return; } if (reg & 0x80) { - raw_scsi_put_data(rs, v, true, true); + raw_scsi_put_data(rs, v, true); ncr53400_dmacount(scsi); } else if (reg & 0x100) { switch (reg) { @@ -1412,10 +1528,7 @@ static int suprareg(struct soft_scsi *ncr, uaecptr addr, bool write) int reg = (addr & 0x0f) >> 1; if ((addr & 0x20) && ncr->subtype == 0) { // "dma" data in/out space - if (!write) - reg = 6; - else - reg = 0; + reg = 8; if (!(ncr->regs[2] & 2)) cpu_halt(6); } @@ -1426,7 +1539,7 @@ static int stardrivereg(struct soft_scsi *ncr, uaecptr addr) { if ((addr & 0x0191) == 0x191) { // "dma" data in/out register - return 0; + return 8; } if ((addr & 0x0181) != 0x181) return -1; @@ -1434,12 +1547,21 @@ static int stardrivereg(struct soft_scsi *ncr, uaecptr addr) return reg; } +static int cltdreg(struct soft_scsi *ncr, uaecptr addr) +{ + if (!(addr & 1)) { + return -1; + } + int reg = (addr >> 1) & 7; + return reg; +} + static int protarreg(struct soft_scsi *ncr, uaecptr addr) { int reg = -1; if ((addr & 0x24) == 0x20) { // "fake dma" data port - reg = 0; + reg = 8; } else if ((addr & 0x20) == 0x00) { reg = (addr >> 2) & 7; } @@ -1450,7 +1572,7 @@ static int add500reg(struct soft_scsi *ncr, uaecptr addr) { int reg = -1; if ((addr & 0x8048) == 0x8000) { - reg = 0; + reg = 8; } else if ((addr & 0x8040) == 0x8040) { reg = (addr >> 1) & 7; } @@ -1461,15 +1583,24 @@ static int adscsireg(struct soft_scsi *ncr, uaecptr addr, bool write) { int reg = -1; if ((addr == 0x38 || addr == 0x39) && !write) { - reg = 0; + reg = 8; } else if ((addr == 0x20 || addr == 0x21) && write) { - reg = 0; + reg = 8; } else if (addr < 0x20) { reg = (addr >> 2) & 7; } return reg; } +static int ptnexusreg(struct soft_scsi *ncr, uaecptr addr) +{ + int reg = -1; + if ((addr & 0x8ff0) == 0) { + reg = (addr >> 1) & 7; + } + return reg; +} + static uae_u8 read_supra_dma(struct soft_scsi *ncr, uaecptr addr) { @@ -1532,7 +1663,7 @@ static void vector_scsi_status(struct raw_scsi *rs) { // Vector Falcon 8000 FPGA seems to handle this internally while (rs->bus_phase == SCSI_SIGNAL_PHASE_STATUS || rs->bus_phase == SCSI_SIGNAL_PHASE_MESSAGE_IN) { - raw_scsi_get_data(rs); + raw_scsi_get_data(rs, true); } } @@ -1585,10 +1716,10 @@ static uae_u32 ncr80_bget2(struct soft_scsi *ncr, uaecptr addr, int size) case 0x8001: case 0x8002: case 0x8003: - v = raw_scsi_get_data(rs); + v = raw_scsi_get_data(rs, true); // message is not retrieved by driver, perhaps hardware does it? if (rs->bus_phase == SCSI_SIGNAL_PHASE_MESSAGE_IN) - raw_scsi_get_data(rs); + raw_scsi_get_data(rs, true); break; case 0x8200: { @@ -1637,6 +1768,34 @@ static uae_u32 ncr80_bget2(struct soft_scsi *ncr, uaecptr addr, int size) } } + } else if (ncr->type == NCR5380_CLTD) { + + struct raw_scsi *rs = &ncr->rscsi; + if (!ncr->configured && addr < sizeof ncr->acmemory) { + v = ncr->acmemory[addr]; + } else { + reg = cltdreg(ncr, addr); + if (reg >= 0) + v = ncr5380_bget(ncr, reg); + } + + } else if (ncr->type == NCR5380_PTNEXUS) { + + struct raw_scsi *rs = &ncr->rscsi; + if (!ncr->configured && addr < sizeof ncr->acmemory) { + v = ncr->acmemory[addr]; + } else if (addr & 0x8000) { + v = ncr->rom[addr & 16383]; + } else { + reg = ptnexusreg(ncr, addr); + if (reg >= 0) { + v = ncr5380_bget(ncr, reg); + } else if (addr == 0x11) { + // fake dma status + v = 0; + } + } + } else if (ncr->type == NONCR_KOMMOS) { struct raw_scsi *rs = &ncr->rscsi; @@ -1644,7 +1803,7 @@ static uae_u32 ncr80_bget2(struct soft_scsi *ncr, uaecptr addr, int size) v = ncr->rom[addr & 0x7fff]; } else if ((origddr & 0xf00000) != 0xf00000) { if (!(addr & 8)) { - v = raw_scsi_get_data(rs); + v = raw_scsi_get_data(rs, true); } else { uae_u8 t = raw_scsi_get_signal_phase(rs); v = 0; @@ -1686,7 +1845,7 @@ static uae_u32 ncr80_bget2(struct soft_scsi *ncr, uaecptr addr, int size) } else if ((addr & 0x300) == 0x000) { if (size > 1) { - v = raw_scsi_get_data(rs); + v = raw_scsi_get_data(rs, true); vector_scsi_status(rs); } else { v = rs->status >= 2 ? 2 : 0; @@ -1721,12 +1880,12 @@ static uae_u32 ncr80_bget2(struct soft_scsi *ncr, uaecptr addr, int size) if (!(addr & 1)) { if (t & SCSI_IO_REQ) { ncr->databuffer[0] = ncr->databuffer[1]; - ncr->databuffer[1] = raw_scsi_get_data(rs) << 8; - ncr->databuffer[1] |= raw_scsi_get_data(rs); + ncr->databuffer[1] = raw_scsi_get_data(rs, true) << 8; + ncr->databuffer[1] |= raw_scsi_get_data(rs, true); if (ncr->databuffer_empty) { ncr->databuffer[0] = ncr->databuffer[1]; - ncr->databuffer[1] = raw_scsi_get_data(rs) << 8; - ncr->databuffer[1] |= raw_scsi_get_data(rs); + ncr->databuffer[1] = raw_scsi_get_data(rs, true) << 8; + ncr->databuffer[1] |= raw_scsi_get_data(rs, true); } ncr->databuffer_empty = false; } else { @@ -1773,7 +1932,6 @@ static uae_u32 ncr80_bget2(struct soft_scsi *ncr, uaecptr addr, int size) } } - } else if (ncr->type == NCR5380_KRONOS) { struct raw_scsi *rs = &ncr->rscsi; @@ -1797,11 +1955,17 @@ static uae_u32 ncr80_bget2(struct soft_scsi *ncr, uaecptr addr, int size) v = ncr53400_bget(ncr, reg | 0x80); else v = ncr53400_bget(ncr, reg); + + } else if (ncr->type == NCR5380_DATAFLYER) { + + reg = addr & 0xff; + v = ncr5380_bget(ncr, reg); + } #if NCR5380_DEBUG > 1 //if (addr >= 0x8000) - write_log(_T("GET %08x %02x %d %08x\n"), addr, v, reg, M68K_GETPC); + write_log(_T("GET %08x %02x %d %08x %d\n"), addr, v, reg, M68K_GETPC, regs.intmask); #endif return v; @@ -1848,11 +2012,11 @@ static void ncr80_bput2(struct soft_scsi *ncr, uaecptr addr, uae_u32 val, int si case 0x8081: case 0x8082: case 0x8083: - raw_scsi_put_data(rs, val, true, true); + raw_scsi_put_data(rs, val, true); break; case 0x8380: { - raw_scsi_put_data(rs, val, true, true); + raw_scsi_put_data(rs, val, true); raw_scsi_set_signal_phase(rs, false, true, false); uae_u8 t = raw_scsi_get_signal_phase(rs); if (t & SCSI_IO_BUSY) @@ -1867,12 +2031,31 @@ static void ncr80_bput2(struct soft_scsi *ncr, uaecptr addr, uae_u32 val, int si if (reg >= 0) ncr5380_bput(ncr, reg, val); + } else if (ncr->type == NCR5380_CLTD) { + + if (ncr->configured) { + reg = cltdreg(ncr, addr); + if (reg >= 0) + ncr5380_bput(ncr, reg, val); + } + + } else if (ncr->type == NCR5380_PTNEXUS) { + + if (ncr->configured) { + reg = ptnexusreg(ncr, addr); + if (reg >= 0) { + ncr5380_bput(ncr, reg, val); + } else if (addr == 0x11) { + ncr->chip_state = val; + } + } + } else if (ncr->type == NONCR_KOMMOS) { struct raw_scsi *rs = &ncr->rscsi; if (!(addr & 0x8000) && (origddr & 0xf00000) != 0xf00000) { if (!(addr & 8)) { - raw_scsi_put_data(rs, val, true, true); + raw_scsi_put_data(rs, val, true); } else { // select? if (val & 4) { @@ -1889,13 +2072,13 @@ static void ncr80_bput2(struct soft_scsi *ncr, uaecptr addr, uae_u32 val, int si struct raw_scsi *rs = &ncr->rscsi; if (addr & 0x8000) { if ((addr & 0x300) == 0x300) { - raw_scsi_put_data(rs, val, false, true); + raw_scsi_put_data(rs, val, false); raw_scsi_set_signal_phase(rs, false, true, false); uae_u8 t = raw_scsi_get_signal_phase(rs); if (t & SCSI_IO_BUSY) raw_scsi_set_signal_phase(rs, true, false, false); } else if ((addr & 0x300) == 0x000) { - raw_scsi_put_data(rs, val, true, true); + raw_scsi_put_data(rs, val, true); vector_scsi_status(rs); } @@ -1943,10 +2126,15 @@ static void ncr80_bput2(struct soft_scsi *ncr, uaecptr addr, uae_u32 val, int si else ncr53400_bput(ncr, reg, val); + } else if (ncr->type == NCR5380_DATAFLYER) { + + reg = addr & 0xff; + ncr5380_bput(ncr, reg, val); + } #if NCR5380_DEBUG > 1 - write_log(_T("PUT %08x %02x %d %08x\n"), addr, val, reg, M68K_GETPC); + write_log(_T("PUT %08x %02x %d %08x %d\n"), addr, val, reg, M68K_GETPC, regs.intmask); #endif } @@ -2107,7 +2295,26 @@ addrbank soft_bank_generic = { soft_generic_lget, soft_generic_wget, ABFLAG_IO | ABFLAG_SAFE }; - +void soft_scsi_put(uaecptr addr, int size, uae_u32 v) +{ + if (size == 4) + soft_generic_lput(addr, v); + else if (size == 2) + soft_generic_wput(addr, v); + else + soft_generic_bput(addr, v); +} +uae_u32 soft_scsi_get(uaecptr addr, int size) +{ + uae_u32 v; + if (size == 4) + v = soft_generic_lget(addr); + else if (size == 2) + v = soft_generic_wget(addr); + else + v = soft_generic_bget(addr); + return v; +} /* $8380 select unit (unit mask) @@ -2186,8 +2393,6 @@ addrbank *stardrive_init(struct romconfig *rc) if (!scsi) return &expamem_null; - scsi->rscsi.use_ack = true; - const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_STARDRIVE); for (int i = 0; i < 16; i++) { uae_u8 b = ert->autoconfig[i]; @@ -2288,8 +2493,6 @@ addrbank *add500_init(struct romconfig *rc) roms[0] = 132; roms[1] = -1; - scsi->rscsi.use_ack = true; - load_rom_rc(rc, roms, 16384, 0, scsi->rom, 32768, LOADROM_EVENONLY_ODDONE | LOADROM_FILL); memcpy(scsi->acmemory, scsi->rom, sizeof scsi->acmemory); return scsi->bank; @@ -2347,8 +2550,7 @@ bool rochard_scsi_init(struct romconfig *rc, uaecptr baseaddress) { struct soft_scsi *scsi = getscsi(rc); scsi->configured = 1; - scsi->rscsi.use_ack = true; - scsi->c400 = true; + scsi->dma_controller = true; scsi->baseaddress = baseaddress; return scsi != NULL; } @@ -2367,6 +2569,76 @@ void rochard_scsi_put(uaecptr addr, uae_u8 v) soft_generic_bput(addr, v); } +addrbank *cltda1000scsi_init(struct romconfig *rc) { + struct soft_scsi *scsi = getscsi(rc); + + if (!scsi) + return &expamem_null; + + scsi->intena = true; + scsi->delayed_irq = true; + + const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_CLTDSCSI); + for (int i = 0; i < 16; i++) { + uae_u8 b = ert->autoconfig[i]; + ew(scsi, i * 4, b); + } + return scsi->bank; +} + +void cltda1000scsi_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc) { + generic_soft_scsi_add(ch, ci, rc, NCR5380_CLTD, 65536, 0, ROMTYPE_CLTDSCSI); +} + +addrbank *ptnexus_init(struct romconfig *rc) +{ + struct soft_scsi *scsi = getscsi(rc); + int roms[2]; + + if (!scsi) + return &expamem_null; + + roms[0] = -1; + roms[1] = -1; + + scsi->intena = true; + scsi->delayed_irq = true; + + const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_PTNEXUS); + for (int i = 0; i < 16; i++) { + uae_u8 b = ert->autoconfig[i]; + ew(scsi, i * 4, b); + } + + load_rom_rc(rc, roms, 8192, 0, scsi->rom, 65536, LOADROM_EVENONLY_ODDONE | LOADROM_FILL); + return scsi->bank; +} + +void ptnexus_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc) +{ + generic_soft_scsi_add(ch, ci, rc, NCR5380_PTNEXUS, 65536, 65536, ROMTYPE_PTNEXUS); +} + +addrbank *dataflyer_init(struct romconfig *rc) +{ + struct soft_scsi *scsi = getscsi(rc); + + if (!scsi) + return &expamem_null; + + scsi->baseaddress = (currprefs.cs_ide == IDE_A4000) ? 0xdd2000 : 0xda0000; + scsi->configured = true; + + gayle_dataflyer_enable(true); + + return NULL; +} + +void dataflyer_add_scsi_unit(int ch, struct uaedev_config_info *ci, struct romconfig *rc) +{ + generic_soft_scsi_add(ch, ci, rc, NCR5380_DATAFLYER, 4096, 0, ROMTYPE_DATAFLYER); +} + void soft_scsi_free(void) { @@ -2382,5 +2654,3 @@ void soft_scsi_reset(void) raw_scsi_reset(&soft_scsi_devices[i]->rscsi); } } - -