mirror of
https://github.com/holub/mame
synced 2025-07-07 19:03:29 +03:00
-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:
parent
228d08d486
commit
fd6c192c2e
@ -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;
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user