From fd6c192c2e33c38763e6f5d7a6b530595f10eb5c Mon Sep 17 00:00:00 2001 From: 987123879113 <63495610+987123879113@users.noreply.github.com> Date: Sun, 12 Feb 2023 03:06:59 +0900 Subject: -machine/ncr53c90.cpp: Fixed issues with DMA transfers. (#10870) * Also added NCR53CF96 device as an alias. -nscsi/cd.cpp: Handle larger INQUIRY sizes (Solaris 2.6 requests 48 bytes). --- src/devices/bus/nscsi/cd.cpp | 4 +- src/devices/machine/ncr53c90.cpp | 100 ++++++++++++++++++++++++++++++--------- src/devices/machine/ncr53c90.h | 27 +++++++++-- 3 files changed, 101 insertions(+), 30 deletions(-) diff --git a/src/devices/bus/nscsi/cd.cpp b/src/devices/bus/nscsi/cd.cpp index db71c61a1e8..0ce5c343273 100644 --- a/src/devices/bus/nscsi/cd.cpp +++ b/src/devices/bus/nscsi/cd.cpp @@ -229,7 +229,7 @@ void nscsi_cdrom_device::scsi_command() int size = scsi_cmdbuf[4]; switch(page) { case 0: - std::fill_n(scsi_cmdbuf, 36, 0); + std::fill_n(scsi_cmdbuf, size, 0); if (lun != 0) scsi_cmdbuf[0] = 0x7f; @@ -249,8 +249,6 @@ void nscsi_cdrom_device::scsi_command() if(scsi_cmdbuf[i] == 0) scsi_cmdbuf[i] = 0x20; - if(size > 36) - size = 36; scsi_data_in(SBUF_MAIN, size); break; } diff --git a/src/devices/machine/ncr53c90.cpp b/src/devices/machine/ncr53c90.cpp index ec494f01a0f..cc9ed8fe1da 100644 --- a/src/devices/machine/ncr53c90.cpp +++ b/src/devices/machine/ncr53c90.cpp @@ -24,6 +24,7 @@ DEFINE_DEVICE_TYPE(NCR53C90, ncr53c90_device, "ncr53c90", "NCR 53C90 SCSI Contro DEFINE_DEVICE_TYPE(NCR53C90A, ncr53c90a_device, "ncr53c90a", "NCR 53C90A Advanced SCSI Controller") DEFINE_DEVICE_TYPE(NCR53C94, ncr53c94_device, "ncr53c94", "NCR 53C94 Advanced SCSI Controller") DEFINE_DEVICE_TYPE(NCR53CF94, ncr53cf94_device, "ncr53cf94", "NCR 53CF94-2 Fast SCSI Controller") // TODO: differences not emulated +DEFINE_DEVICE_TYPE(NCR53CF96, ncr53cf96_device, "ncr53cf96", "NCR 53CF96-2 Fast SCSI Controller") // TODO: differences not emulated void ncr53c90_device::map(address_map &map) { @@ -102,6 +103,8 @@ void ncr53c94_device::map(address_map &map) ncr53c90a_device::map(map); map(0xc, 0xc).rw(FUNC(ncr53c94_device::conf3_r), FUNC(ncr53c94_device::conf3_w)); + map(0xd, 0xd).rw(FUNC(ncr53c94_device::conf4_r), FUNC(ncr53c94_device::conf4_w)); + map(0xe, 0xe).rw(FUNC(ncr53c94_device::tcounter_hi2_r), FUNC(ncr53c94_device::tcount_hi2_w)); map(0xf, 0xf).w(FUNC(ncr53c94_device::fifo_align_w)); } @@ -109,13 +112,21 @@ uint8_t ncr53c94_device::read(offs_t offset) { if (offset == 12) return conf3_r(); + else if (offset == 13) + return conf4_r(); + else if (offset == 14) + return tcounter_hi2_r(); return ncr53c90a_device::read(offset); } void ncr53c94_device::write(offs_t offset, uint8_t data) { - if (offset == 11) + if (offset == 12) conf3_w(data); + else if (offset == 13) + conf4_w(data); + else if (offset == 14) + tcount_hi2_w(data); else if (offset == 15) fifo_align_w(data); else @@ -126,7 +137,7 @@ ncr53c90_device::ncr53c90_device(const machine_config &mconfig, device_type type : nscsi_device(mconfig, type, tag, owner, clock) , nscsi_slot_card_interface(mconfig, *this, DEVICE_SELF) , tm(nullptr), config(0), status(0), istatus(0), clock_conv(0), sync_offset(0), sync_period(0), bus_id(0) - , select_timeout(0), seq(0), tcount(0), tcounter(0), mode(0), fifo_pos(0), command_pos(0), state(0), xfr_phase(0), command_length(0), dma_dir(0), irq(false), drq(false), test_mode(false) + , select_timeout(0), seq(0), tcount(0), tcounter(0), tcounter_mask(0xffff), mode(0), fifo_pos(0), command_pos(0), state(0), xfr_phase(0), command_length(0), dma_dir(0), irq(false), drq(false), test_mode(false) , m_irq_handler(*this) , m_drq_handler(*this) { @@ -156,6 +167,9 @@ ncr53c94_device::ncr53c94_device(const machine_config &mconfig, const char *tag, ncr53c94_device::ncr53c94_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : ncr53c90a_device(mconfig, type, tag, owner, clock) , config3(0) + , config4(0) + , family_id(0x02) + , revision_level(0x02) , m_busmd(BUSMD_0) { } @@ -165,6 +179,11 @@ ncr53cf94_device::ncr53cf94_device(const machine_config &mconfig, const char *ta { } +ncr53cf96_device::ncr53cf96_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : ncr53c94_device(mconfig, NCR53CF96, tag, owner, clock) +{ +} + void ncr53c90_device::device_start() { nscsi_device::device_start(); @@ -182,6 +201,7 @@ void ncr53c90_device::device_start() save_item(NAME(fifo)); save_item(NAME(tcount)); save_item(NAME(tcounter)); + save_item(NAME(tcounter_mask)); save_item(NAME(mode)); save_item(NAME(fifo_pos)); save_item(NAME(command_pos)); @@ -226,6 +246,7 @@ void ncr53c90_device::device_reset() scsi_bus->ctrl_w(scsi_refid, 0, S_RST); tcount = 0; tcounter = 0; + tcounter_mask = 0xffff; reset_disconnect(); } @@ -423,8 +444,8 @@ void ncr53c90_device::step(bool timeout) if((state & STATE_MASK) != INIT_XFR_RECV_PAD) { fifo_push(scsi_bus->data_r()); - // in async mode data in phase, tcount is decremented on ACKO, not DACK - if ((sync_offset == 0) && ((ctrl & S_PHASE_MASK) == 0x01)) + // in async mode data in phase in initiator mode, tcount is decremented on ACKO, not DACK + if ((mode == MODE_I) && (sync_offset == 0) && ((ctrl & S_PHASE_MASK) == S_PHASE_DATA_IN)) { LOGMASKED(LOG_FIFO, "decrement_tcounter data in async, phase %02x\n", (ctrl & S_PHASE_MASK)); decrement_tcounter(); @@ -628,20 +649,15 @@ void ncr53c90_device::step(bool timeout) break; case INIT_XFR_FUNCTION_COMPLETE: - // wait for dma transfer to complete or fifo to drain - if ((dma_dir == DMA_OUT) && dma_command && !(status & S_TC0) && fifo_pos) - break; - if ((dma_dir == DMA_IN) && dma_command && (status & S_TC0) && fifo_pos) + // wait for dma transfer to complete and fifo to drain + if (dma_command && (!(status & S_TC0) || fifo_pos)) break; - function_complete(); break; case INIT_XFR_BUS_COMPLETE: - // wait for dma transfer to complete or fifo to drain - if ((dma_dir == DMA_OUT) && dma_command && !(status & S_TC0) && fifo_pos) - break; - if ((dma_dir == DMA_IN) && dma_command && (status & S_TC0) && fifo_pos) + // wait for dma transfer to complete and fifo to drain + if (dma_command && (!(status & S_TC0) || fifo_pos)) break; bus_complete(); break; @@ -774,27 +790,29 @@ uint8_t ncr53c90_device::tcounter_lo_r() void ncr53c90_device::tcount_lo_w(uint8_t data) { - tcount = (tcount & 0xff00) | data; + tcount = (tcount & ~uint32_t(0xff)) | data; LOG("tcount_lo_w %02x (%s)\n", data, machine().describe_context()); } uint8_t ncr53c90_device::tcounter_hi_r() { - LOG("tcounter_hi_r %02x (%s)\n", tcounter >> 8, machine().describe_context()); + LOG("tcounter_hi_r %02x (%s)\n", (tcounter >> 8) & 0xff, machine().describe_context()); return tcounter >> 8; } void ncr53c90_device::tcount_hi_w(uint8_t data) { - tcount = (tcount & 0x00ff) | (data << 8); + tcount = (tcount & ~uint32_t(0xff00)) | (uint32_t(data) << 8); LOG("tcount_hi_w %02x (%s)\n", data, machine().describe_context()); } uint8_t ncr53c90_device::fifo_pop() { uint8_t r = fifo[0]; - fifo_pos--; - memmove(fifo, fifo+1, fifo_pos); + if(fifo_pos) { + fifo_pos--; + memmove(fifo, fifo+1, fifo_pos); + } check_drq(); return r; } @@ -802,7 +820,8 @@ uint8_t ncr53c90_device::fifo_pop() void ncr53c90_device::fifo_push(uint8_t val) { LOGMASKED(LOG_FIFO, "Push %02x to FIFO at position %d\n", val, fifo_pos); - fifo[fifo_pos++] = val; + if(fifo_pos != 16) + fifo[fifo_pos++] = val; check_drq(); } @@ -1140,7 +1159,7 @@ uint8_t ncr53c90_device::dma_r() { uint8_t r = fifo_pop(); - if ((sync_offset != 0) || ((scsi_bus->ctrl_r() & S_PHASE_MASK) != 0x01)) + if ((sync_offset != 0) || ((scsi_bus->ctrl_r() & S_PHASE_MASK) != S_PHASE_DATA_IN)) { decrement_tcounter(); } @@ -1181,7 +1200,14 @@ void ncr53c90_device::decrement_tcounter(int count) if (!dma_command) return; - tcounter -= count; + // If tcounter is 0 but TC0 is not set yet then it should mean tcount is also 0. + // A tcount of 0 specifies the maximum length count (65536) so this should wrap + // from 0 to 65535 only once. + if (!(status & S_TC0)) + tcounter = (tcounter - count) & tcounter_mask; + else + tcounter = 0; + if (tcounter == 0) status |= S_TC0; @@ -1248,8 +1274,10 @@ bool ncr53c90a_device::check_valid_command(uint8_t cmd) void ncr53c94_device::device_start() { save_item(NAME(config3)); + save_item(NAME(config4)); config3 = 0; + config4 = 0; ncr53c90a_device::device_start(); } @@ -1257,6 +1285,7 @@ void ncr53c94_device::device_start() void ncr53c94_device::device_reset() { config3 = 0; + config4 = 0; ncr53c90a_device::device_reset(); } @@ -1273,7 +1302,7 @@ u16 ncr53c94_device::dma16_r() memmove(fifo, fifo + 2, fifo_pos); // update drq - if ((sync_offset != 0) || ((scsi_bus->ctrl_r() & S_PHASE_MASK) != 0x01)) + if ((sync_offset != 0) || ((scsi_bus->ctrl_r() & S_PHASE_MASK) != S_PHASE_DATA_IN)) { decrement_tcounter(2); } @@ -1313,7 +1342,10 @@ void ncr53c94_device::check_drq() break; case DMA_IN: // device to memory - drq_state = !(status & S_TC0) && fifo_pos > 1; + if (sync_offset == 0) + drq_state = (fifo_pos > 1); + else + drq_state = !(status & S_TC0) && fifo_pos > 1; break; case DMA_OUT: // memory to device @@ -1329,3 +1361,25 @@ void ncr53c94_device::check_drq() else ncr53c90_device::check_drq(); } + +void ncr53c94_device::conf2_w(uint8_t data) +{ + tcounter_mask = (data & S2FE) ? 0xffffff : 0xffff; + config2 = data; +} + +uint8_t ncr53c94_device::tcounter_hi2_r() +{ + // tcounter is 24-bit when the features bit is set, otherwise it returns the ID + if ((config2 & S2FE) == 0) + return (1 << 7) | (family_id << 3) | revision_level; + + LOG("tcounter_hi2_r %02x (%s)\n", (tcounter >> 16) & 0xff, machine().describe_context()); + return tcounter >> 16; +} + +void ncr53c94_device::tcount_hi2_w(uint8_t data) +{ + tcount = (tcount & ~uint32_t(0xff0000)) | (uint32_t(data) << 16); + LOG("tcount_hi2_w %02x (%s)\n", data, machine().describe_context()); +} diff --git a/src/devices/machine/ncr53c90.h b/src/devices/machine/ncr53c90.h index 666c9c7a8e4..1d908b8eb09 100644 --- a/src/devices/machine/ncr53c90.h +++ b/src/devices/machine/ncr53c90.h @@ -195,8 +195,8 @@ protected: uint8_t command[2], config, status, istatus; uint8_t clock_conv, sync_offset, sync_period, bus_id, select_timeout, seq; uint8_t fifo[16]; - uint16_t tcount; - uint16_t tcounter; + uint32_t tcount; + uint32_t tcounter, tcounter_mask; int mode, fifo_pos, command_pos; int state, xfr_phase; int command_length; @@ -247,7 +247,7 @@ public: virtual uint8_t status_r() override; uint8_t conf2_r() { return config2; } - void conf2_w(uint8_t data) { config2 = data; } + virtual void conf2_w(uint8_t data) { config2 = data; } virtual uint8_t read(offs_t offset) override; virtual void write(offs_t offset, uint8_t data) override; @@ -277,7 +277,7 @@ protected: DAE = 0x80, // data alignment enable }; -private: +protected: u8 config2; }; @@ -297,8 +297,17 @@ public: virtual void map(address_map &map) override; + virtual void conf2_w(uint8_t data) override; + uint8_t conf3_r() { return config3; } void conf3_w(uint8_t data) { config3 = data; } + + uint8_t conf4_r() { return config4; } + void conf4_w(uint8_t data) { config4 = data; } + + uint8_t tcounter_hi2_r(); + void tcount_hi2_w(uint8_t data); + void fifo_align_w(uint8_t data) { fifo_align = data; } virtual uint8_t read(offs_t offset) override; @@ -323,7 +332,10 @@ protected: private: u8 config3; + u8 config4; u8 fifo_align; + u8 family_id; + u8 revision_level; busmd_t m_busmd; }; @@ -333,9 +345,16 @@ public: ncr53cf94_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); }; +class ncr53cf96_device : public ncr53c94_device +{ +public: + ncr53cf96_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); +}; + DECLARE_DEVICE_TYPE(NCR53C90, ncr53c90_device) DECLARE_DEVICE_TYPE(NCR53C90A, ncr53c90a_device) DECLARE_DEVICE_TYPE(NCR53C94, ncr53c94_device) DECLARE_DEVICE_TYPE(NCR53CF94, ncr53cf94_device) +DECLARE_DEVICE_TYPE(NCR53CF96, ncr53cf96_device) #endif // MAME_MACHINE_NCR53C90_H -- cgit v1.2.3