mirror of
https://github.com/holub/mame
synced 2025-04-24 01:11:11 +03:00
ncr5380n: better DRQ support, fixed arbitration-in-progress bit [R. Belmont]
This commit is contained in:
parent
c11f83ad16
commit
645af63020
@ -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<<win)); win--);
|
||||
// printf("data %02x win %02x scsi_id %02x\n", data, win, scsi_id);
|
||||
// printf("arb complete: data %02x win %02x scsi_id %02x\n", data, win, scsi_id);
|
||||
if(win != scsi_id) {
|
||||
scsi_bus->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;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user