-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).
This commit is contained in:
987123879113 2023-02-12 03:06:59 +09:00 committed by GitHub
parent 228d08d486
commit fd6c192c2e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 101 additions and 30 deletions

View File

@ -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;
}

View File

@ -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)
// wait for dma transfer to complete and fifo to drain
if (dma_command && (!(status & S_TC0) || fifo_pos))
break;
if ((dma_dir == DMA_IN) && 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());
}

View File

@ -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