From 645af630200474ae1d6c79cce9f6b1813e0c6735 Mon Sep 17 00:00:00 2001 From: "R. Belmont" Date: Fri, 4 Oct 2013 02:53:07 +0000 Subject: [PATCH] ncr5380n: better DRQ support, fixed arbitration-in-progress bit [R. Belmont] --- src/mess/machine/ncr5380n.c | 79 ++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 37 deletions(-) diff --git a/src/mess/machine/ncr5380n.c b/src/mess/machine/ncr5380n.c index 3fd4bdde7bc..f05e26faf6c 100644 --- a/src/mess/machine/ncr5380n.c +++ b/src/mess/machine/ncr5380n.c @@ -3,11 +3,13 @@ ncr5380n.c Implementation of the NCR 5380, aka the Zilog Z5380 - + TODO: - - IRQs (Apple doesn't use 'em) + - IRQs - Target mode - + + 40801766 - IIx ROM waiting point for "next read fails" + *********************************************************************/ #include "emu.h" @@ -76,7 +78,7 @@ void ncr5380n_device::device_reset() void ncr5380n_device::reset_soft() { state = IDLE; - scsi_bus->ctrl_w(scsi_refid, 0, S_ALL); // clear any signals we're driving + scsi_bus->ctrl_w(scsi_refid, 0, S_ALL); // clear any signals we're driving scsi_bus->ctrl_wait(scsi_refid, S_ALL, S_ALL); status = 0; drq = false; @@ -95,13 +97,13 @@ void ncr5380n_device::scsi_ctrl_changed() { UINT32 ctrl = scsi_bus->ctrl_r(); -// printf("scsi_ctrl_changed: lines now %x\n", ctrl); +// printf("scsi_ctrl_changed: lines now %x\n", ctrl); -/* if ((ctrl & (S_PHASE_MASK|S_SEL|S_BSY)) != last_phase) - { - printf("phase now %d, SEL %x BSY %x\n", ctrl & S_PHASE_MASK, ctrl & S_SEL, ctrl & S_BSY); - last_phase = (S_PHASE_MASK|S_SEL|S_BSY); - }*/ +/* if ((ctrl & (S_PHASE_MASK|S_SEL|S_BSY)) != last_phase) + { + printf("phase now %d, REQ %x SEL %x BSY %x\n", ctrl & S_PHASE_MASK, ctrl & S_REQ, ctrl & S_SEL, ctrl & S_BSY); + last_phase = (S_PHASE_MASK|S_SEL|S_BSY); + }*/ // recalculate phase match m_busstatus &= ~BAS_PHASEMATCH; @@ -115,7 +117,7 @@ void ncr5380n_device::scsi_ctrl_changed() // if BSY drops or the phase goes mismatch, that terminates the DMA if ((!(ctrl & S_BSY)) || !(m_busstatus & BAS_PHASEMATCH)) { -// printf("BSY dropped or phase mismatch during DMA, ending DMA\n"); +// printf("BSY dropped or phase mismatch during DMA, ending DMA\n"); m_mode &= ~MODE_DMA; m_busstatus |= BAS_ENDOFDMA; drq_clear(); @@ -160,7 +162,7 @@ void ncr5380n_device::step(bool timeout) int win; for(win=7; win>=0 && !(data & (1<data_w(scsi_refid, 0); scsi_bus->ctrl_w(scsi_refid, 0, S_ALL); @@ -168,9 +170,6 @@ void ncr5380n_device::step(bool timeout) break; } - // arbitration no longer in progress - m_icommand &= ~IC_ARBITRATION; - state &= STATE_MASK; step(true); break; @@ -212,7 +211,6 @@ void ncr5380n_device::step(bool timeout) break; m_dmalatch = scsi_bus->data_r(); - drq_set(); scsi_bus->ctrl_w(scsi_refid, S_ACK, S_ACK); state = (state & STATE_MASK) | (RECV_WAIT_REQ_0 << SUB_SHIFT); step(false); @@ -223,6 +221,8 @@ void ncr5380n_device::step(bool timeout) break; state = state & STATE_MASK; step(false); + + drq_set(); // raise DRQ now that we've completed break; default: @@ -252,21 +252,21 @@ void ncr5380n_device::recv_byte() void ncr5380n_device::function_bus_complete() { state = IDLE; -// istatus |= I_FUNCTION|I_BUS; +// istatus |= I_FUNCTION|I_BUS; check_irq(); } void ncr5380n_device::function_complete() { state = IDLE; -// istatus |= I_FUNCTION; +// istatus |= I_FUNCTION; check_irq(); } void ncr5380n_device::bus_complete() { state = IDLE; -// istatus |= I_BUS; +// istatus |= I_BUS; check_irq(); } @@ -309,7 +309,7 @@ WRITE8_MEMBER(ncr5380n_device::icmd_w) // asserting to drive the data bus? if ((data & IC_DBUS) && !(m_icommand & IC_DBUS)) { -// printf("%s: driving data bus with %02x\n", tag(), m_outdata); +// printf("%s: driving data bus with %02x\n", tag(), m_outdata); scsi_bus->data_w(scsi_refid, m_outdata); delay(2); } @@ -327,7 +327,7 @@ WRITE8_MEMBER(ncr5380n_device::icmd_w) (data & IC_SEL ? S_SEL : 0) | (data & IC_ATN ? S_ATN : 0); -// printf("%s: changing control lines %04x\n", tag(), newdata); +// printf("%s: changing control lines %04x\n", tag(), newdata); scsi_bus->ctrl_w(scsi_refid, newdata, S_RST|S_ACK|S_BSY|S_SEL|S_ATN); } @@ -342,38 +342,41 @@ READ8_MEMBER(ncr5380n_device::mode_r) WRITE8_MEMBER(ncr5380n_device::mode_w) { -// printf("%s: mode_w %02x (%08x)\n", tag(), data, space.device().safe_pc()); +// printf("%s: mode_w %02x (%08x)\n", tag(), data, space.device().safe_pc()); // arbitration bit being set? if ((data & MODE_ARBITRATE) && !(m_mode & MODE_ARBITRATE)) { - // if SEL is selected and the assert SEL bit in the initiator + // if SEL is selected and the assert SEL bit in the initiator // command register is clear, fail if ((scsi_bus->ctrl_r() & S_SEL) && !(m_icommand & IC_SEL)) { -// printf("arbitration lost, ctrl = %x, m_icommand&IC_SEL = %x\n", scsi_bus->ctrl_r(), m_icommand & IC_SEL); - m_icommand &= ~IC_ARBITRATION; m_icommand |= IC_ARBLOST; } else { seq = 0; -// state = DISC_SEL_ARBITRATION; +// state = DISC_SEL_ARBITRATION; arbitrate(); } } - + else if (!(data & MODE_ARBITRATE) && (m_mode & MODE_ARBITRATE)) + { + // arbitration in progress bit ONLY clears when the host disables arbitration. (thanks, Zilog Z8530 manual!) + // the Apple II High Speed SCSI Card boot code explicitly requires this. + m_icommand &= ~ IC_ARBITRATION; + } m_mode = data; } READ8_MEMBER(ncr5380n_device::command_r) { -// logerror("%s: command_r %02x (%08x)\n", tag(), m_tcommand, space.device().safe_pc()); +// logerror("%s: command_r %02x (%08x)\n", tag(), m_tcommand, space.device().safe_pc()); return m_tcommand; } WRITE8_MEMBER(ncr5380n_device::command_w) { -// printf("%s: command_w %02x (%08x)\n", tag(), data, space.device().safe_pc()); +// printf("%s: command_w %02x (%08x)\n", tag(), data, space.device().safe_pc()); m_tcommand = data; // recalculate phase match @@ -387,7 +390,7 @@ WRITE8_MEMBER(ncr5380n_device::command_w) void ncr5380n_device::arbitrate() { m_icommand &= ~IC_ARBLOST; - m_icommand |= IC_ARBITRATION; + m_icommand |= IC_ARBITRATION; // set in progress flag state = (state & STATE_MASK) | (ARB_COMPLETE << SUB_SHIFT); scsi_bus->data_w(scsi_refid, m_outdata); scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY); @@ -407,7 +410,7 @@ void ncr5380n_device::check_irq() READ8_MEMBER(ncr5380n_device::status_r) { UINT32 ctrl = scsi_bus->ctrl_r(); - UINT8 res = status | + UINT8 res = status | (ctrl & S_RST ? ST_RST : 0) | (ctrl & S_BSY ? ST_BSY : 0) | (ctrl & S_REQ ? ST_REQ : 0) | @@ -416,7 +419,7 @@ READ8_MEMBER(ncr5380n_device::status_r) (ctrl & S_INP ? ST_IO : 0) | (ctrl & S_SEL ? ST_SEL : 0); -// printf("%s: status_r %02x (%08x)\n", tag(), res, space.device().safe_pc()); +// printf("%s: status_r %02x (%08x)\n", tag(), res, space.device().safe_pc()); return res; } @@ -431,7 +434,7 @@ READ8_MEMBER(ncr5380n_device::busandstatus_r) (ctrl & S_ATN ? BAS_ATN : 0) | (ctrl & S_ACK ? BAS_ACK : 0); -// printf("%s: busandstatus_r %02x (%08x)\n", tag(), res, space.device().safe_pc()); +// printf("%s: busandstatus_r %02x (%08x)\n", tag(), res, space.device().safe_pc()); return res; } @@ -444,7 +447,7 @@ WRITE8_MEMBER(ncr5380n_device::startdmasend_w) READ8_MEMBER(ncr5380n_device::indata_r) { - return 0; + return dma_r(); } WRITE8_MEMBER(ncr5380n_device::startdmatargetrx_w) @@ -459,7 +462,7 @@ READ8_MEMBER(ncr5380n_device::resetparityirq_r) WRITE8_MEMBER(ncr5380n_device::startdmainitrx_w) { -// printf("%02x to start dma initiator Rx\n", data); +// printf("%02x to start dma initiator Rx\n", data); recv_byte(); } @@ -491,7 +494,7 @@ UINT8 ncr5380n_device::dma_r() void ncr5380n_device::drq_set() { - if(!drq) + if(!drq) { drq = true; m_busstatus |= BAS_DMAREQUEST; @@ -501,7 +504,7 @@ void ncr5380n_device::drq_set() void ncr5380n_device::drq_clear() { - if(drq) + if(drq) { drq = false; m_busstatus &= ~BAS_DMAREQUEST; @@ -543,6 +546,7 @@ READ8_MEMBER(ncr5380n_device::read) WRITE8_MEMBER(ncr5380n_device::write) { +// printf("%x to 5380 @ %x\n", data, offset); switch (offset & 7) { case 0: @@ -578,3 +582,4 @@ WRITE8_MEMBER(ncr5380n_device::write) break; } } +