mirror of
https://github.com/holub/mame
synced 2025-04-22 08:22:15 +03:00
(MESS) Reimplemented the NCR5380 SCSI controller using nscsi. [R. Belmont]
This commit is contained in:
parent
ee72cf5471
commit
bff5a6cfa9
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -7319,6 +7319,8 @@ src/mess/machine/nascom1.c svneol=native#text/plain
|
||||
src/mess/machine/nc.c svneol=native#text/plain
|
||||
src/mess/machine/ncr5380.c svneol=native#text/plain
|
||||
src/mess/machine/ncr5380.h svneol=native#text/plain
|
||||
src/mess/machine/ncr5380n.c svneol=native#text/plain
|
||||
src/mess/machine/ncr5380n.h svneol=native#text/plain
|
||||
src/mess/machine/ncr5390.c svneol=native#text/plain
|
||||
src/mess/machine/ncr5390.h svneol=native#text/plain
|
||||
src/mess/machine/ne1000.c svneol=native#text/plain
|
||||
|
601
src/mess/machine/ncr5380n.c
Normal file
601
src/mess/machine/ncr5380n.c
Normal file
@ -0,0 +1,601 @@
|
||||
/*********************************************************************
|
||||
|
||||
ncr5380n.c
|
||||
|
||||
Implementation of the NCR 5380, aka the Zilog Z5380
|
||||
|
||||
TODO:
|
||||
- IRQs (Apple doesn't use 'em)
|
||||
- Target mode
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "ncr5380n.h"
|
||||
|
||||
const device_type NCR5380N = &device_creator<ncr5380n_device>;
|
||||
|
||||
DEVICE_ADDRESS_MAP_START(map, 8, ncr5380n_device)
|
||||
AM_RANGE(0x0, 0x0) AM_READWRITE(scsidata_r, outdata_w)
|
||||
AM_RANGE(0x1, 0x1) AM_READWRITE(icmd_r, icmd_w)
|
||||
AM_RANGE(0x2, 0x2) AM_READWRITE(mode_r, mode_w)
|
||||
AM_RANGE(0x3, 0x3) AM_READWRITE(command_r, command_w)
|
||||
AM_RANGE(0x4, 0x4) AM_READWRITE(status_r, selenable_w)
|
||||
AM_RANGE(0x5, 0x5) AM_READWRITE(busandstatus_r, startdmasend_w)
|
||||
AM_RANGE(0x6, 0x6) AM_READWRITE(indata_r, startdmatargetrx_w)
|
||||
AM_RANGE(0x7, 0x7) AM_READWRITE(resetparityirq_r, startdmainitrx_w)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
ncr5380n_device::ncr5380n_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: nscsi_device(mconfig, NCR5380N, "5380 SCSI (new)", tag, owner, clock)
|
||||
{
|
||||
}
|
||||
|
||||
void ncr5380n_device::device_start()
|
||||
{
|
||||
save_item(NAME(m_tcommand));
|
||||
save_item(NAME(m_icommand));
|
||||
save_item(NAME(status));
|
||||
save_item(NAME(istatus));
|
||||
save_item(NAME(m_busstatus));
|
||||
save_item(NAME(tcount));
|
||||
save_item(NAME(mode));
|
||||
save_item(NAME(irq));
|
||||
save_item(NAME(drq));
|
||||
save_item(NAME(clock_conv));
|
||||
save_item(NAME(m_dmalatch));
|
||||
|
||||
m_irq_func.resolve(m_irq_cb, *this);
|
||||
m_drq_func.resolve(m_drq_cb, *this);
|
||||
|
||||
tcount = 0;
|
||||
status = 0;
|
||||
bus_id = 0;
|
||||
select_timeout = 0;
|
||||
tm = timer_alloc(0);
|
||||
}
|
||||
|
||||
void ncr5380n_device::device_reset()
|
||||
{
|
||||
clock_conv = 2;
|
||||
sync_period = 5;
|
||||
sync_offset = 0;
|
||||
seq = 0;
|
||||
status = 0;
|
||||
m_tcommand = 0;
|
||||
m_icommand = 0;
|
||||
istatus = 0;
|
||||
m_busstatus = 0;
|
||||
irq = false;
|
||||
if(!m_irq_func.isnull())
|
||||
m_irq_func(irq);
|
||||
reset_soft();
|
||||
}
|
||||
|
||||
void ncr5380n_device::device_config_complete()
|
||||
{
|
||||
// inherit a copy of the static data
|
||||
const ncr5380n_interface *intf = reinterpret_cast<const ncr5380n_interface *>(static_config());
|
||||
if (intf != NULL)
|
||||
{
|
||||
*static_cast<ncr5380n_interface *>(this) = *intf;
|
||||
}
|
||||
|
||||
// or initialize to defaults if none provided
|
||||
else
|
||||
{
|
||||
memset(&m_irq_cb, 0, sizeof(m_irq_cb));
|
||||
memset(&m_drq_cb, 0, sizeof(m_drq_cb));
|
||||
}
|
||||
m_shortname = "ncr5380";
|
||||
}
|
||||
|
||||
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_wait(scsi_refid, S_ALL, S_ALL);
|
||||
status = 0;
|
||||
drq = false;
|
||||
if(!m_drq_func.isnull())
|
||||
m_drq_func(drq);
|
||||
reset_disconnect();
|
||||
}
|
||||
|
||||
void ncr5380n_device::reset_disconnect()
|
||||
{
|
||||
mode = MODE_D;
|
||||
}
|
||||
|
||||
//static int last_phase = -1;
|
||||
|
||||
void ncr5380n_device::scsi_ctrl_changed()
|
||||
{
|
||||
UINT32 ctrl = scsi_bus->ctrl_r();
|
||||
|
||||
// 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);
|
||||
}*/
|
||||
|
||||
// recalculate phase match
|
||||
m_busstatus &= ~BAS_PHASEMATCH;
|
||||
if ((ctrl & S_PHASE_MASK) == (m_tcommand & S_PHASE_MASK))
|
||||
{
|
||||
m_busstatus |= BAS_PHASEMATCH;
|
||||
}
|
||||
|
||||
if (m_mode & MODE_DMA)
|
||||
{
|
||||
// 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");
|
||||
m_mode &= ~MODE_DMA;
|
||||
m_busstatus |= BAS_ENDOFDMA;
|
||||
drq_clear();
|
||||
}
|
||||
}
|
||||
|
||||
if(ctrl & S_RST) {
|
||||
logerror("%s: scsi bus reset\n", tag());
|
||||
return;
|
||||
}
|
||||
|
||||
step(false);
|
||||
}
|
||||
|
||||
void ncr5380n_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
|
||||
{
|
||||
step(true);
|
||||
}
|
||||
|
||||
void ncr5380n_device::step(bool timeout)
|
||||
{
|
||||
UINT32 ctrl = scsi_bus->ctrl_r();
|
||||
UINT32 data = scsi_bus->data_r();
|
||||
|
||||
if(0)
|
||||
printf("%s: state=%d.%d %s\n",
|
||||
tag(), state & STATE_MASK, (state & SUB_MASK) >> SUB_SHIFT,
|
||||
timeout ? "timeout" : "change");
|
||||
|
||||
if(mode == MODE_I && !(ctrl & S_BSY)) {
|
||||
state = IDLE;
|
||||
reset_disconnect();
|
||||
check_irq();
|
||||
}
|
||||
switch(state & SUB_MASK ? state & SUB_MASK : state & STATE_MASK) {
|
||||
case IDLE:
|
||||
break;
|
||||
|
||||
case ARB_COMPLETE << SUB_SHIFT: {
|
||||
if(!timeout)
|
||||
break;
|
||||
|
||||
int win;
|
||||
for(win=7; win>=0 && !(data & (1<<win)); win--);
|
||||
// printf("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);
|
||||
fatalerror("need to wait for bus free\n");
|
||||
break;
|
||||
}
|
||||
|
||||
// arbitration no longer in progress
|
||||
m_icommand &= ~IC_ARBITRATION;
|
||||
|
||||
state &= STATE_MASK;
|
||||
step(true);
|
||||
break;
|
||||
}
|
||||
|
||||
case SEND_WAIT_SETTLE << SUB_SHIFT:
|
||||
if(!timeout)
|
||||
break;
|
||||
|
||||
state = (state & STATE_MASK) | (SEND_WAIT_REQ_0 << SUB_SHIFT);
|
||||
step(false);
|
||||
break;
|
||||
|
||||
case SEND_WAIT_REQ_0 << SUB_SHIFT:
|
||||
if(ctrl & S_REQ)
|
||||
break;
|
||||
state = state & STATE_MASK;
|
||||
scsi_bus->data_w(scsi_refid, 0);
|
||||
scsi_bus->ctrl_w(scsi_refid, 0, S_ACK);
|
||||
step(false);
|
||||
|
||||
// byte's done, ask for another if the target hasn't said otherwise
|
||||
if (m_mode & MODE_DMA)
|
||||
{
|
||||
drq_set();
|
||||
}
|
||||
break;
|
||||
|
||||
case RECV_WAIT_REQ_1 << SUB_SHIFT:
|
||||
if(!(ctrl & S_REQ))
|
||||
break;
|
||||
|
||||
state = (state & STATE_MASK) | (RECV_WAIT_SETTLE << SUB_SHIFT);
|
||||
delay_cycles(sync_period);
|
||||
break;
|
||||
|
||||
case RECV_WAIT_SETTLE << SUB_SHIFT:
|
||||
if(!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);
|
||||
break;
|
||||
|
||||
case RECV_WAIT_REQ_0 << SUB_SHIFT:
|
||||
if(ctrl & S_REQ)
|
||||
break;
|
||||
state = state & STATE_MASK;
|
||||
step(false);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("%s: step() unexpected state %d.%d\n",
|
||||
tag(),
|
||||
state & STATE_MASK, (state & SUB_MASK) >> SUB_SHIFT);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
void ncr5380n_device::send_byte()
|
||||
{
|
||||
state = (state & STATE_MASK) | (SEND_WAIT_SETTLE << SUB_SHIFT);
|
||||
scsi_bus->data_w(scsi_refid, m_dmalatch);
|
||||
|
||||
scsi_bus->ctrl_w(scsi_refid, S_ACK, S_ACK);
|
||||
scsi_bus->ctrl_wait(scsi_refid, S_REQ, S_REQ);
|
||||
delay_cycles(sync_period);
|
||||
}
|
||||
|
||||
void ncr5380n_device::recv_byte()
|
||||
{
|
||||
state = (state & STATE_MASK) | (RECV_WAIT_REQ_1 << SUB_SHIFT);
|
||||
step(false);
|
||||
}
|
||||
|
||||
void ncr5380n_device::function_bus_complete()
|
||||
{
|
||||
state = IDLE;
|
||||
// istatus |= I_FUNCTION|I_BUS;
|
||||
check_irq();
|
||||
}
|
||||
|
||||
void ncr5380n_device::function_complete()
|
||||
{
|
||||
state = IDLE;
|
||||
// istatus |= I_FUNCTION;
|
||||
check_irq();
|
||||
}
|
||||
|
||||
void ncr5380n_device::bus_complete()
|
||||
{
|
||||
state = IDLE;
|
||||
// istatus |= I_BUS;
|
||||
check_irq();
|
||||
}
|
||||
|
||||
void ncr5380n_device::delay(int cycles)
|
||||
{
|
||||
if(!clock_conv)
|
||||
return;
|
||||
cycles *= clock_conv;
|
||||
tm->adjust(clocks_to_attotime(cycles));
|
||||
}
|
||||
|
||||
void ncr5380n_device::delay_cycles(int cycles)
|
||||
{
|
||||
tm->adjust(clocks_to_attotime(cycles));
|
||||
}
|
||||
|
||||
READ8_MEMBER(ncr5380n_device::scsidata_r)
|
||||
{
|
||||
return scsi_bus->data_r();
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(ncr5380n_device::outdata_w)
|
||||
{
|
||||
m_outdata = data;
|
||||
|
||||
// are we driving the data bus?
|
||||
if (m_icommand & IC_DBUS)
|
||||
{
|
||||
scsi_bus->data_w(scsi_refid, data);
|
||||
}
|
||||
}
|
||||
|
||||
READ8_MEMBER(ncr5380n_device::icmd_r)
|
||||
{
|
||||
return m_icommand;
|
||||
}
|
||||
|
||||
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);
|
||||
scsi_bus->data_w(scsi_refid, m_outdata);
|
||||
delay(2);
|
||||
}
|
||||
|
||||
// any control lines changing?
|
||||
UINT8 mask = (data & IC_PHASEMASK) ^ (m_icommand & IC_PHASEMASK);
|
||||
if (mask)
|
||||
{
|
||||
// translate data to nscsi
|
||||
UINT8 newdata = 0;
|
||||
|
||||
newdata = (data & IC_RST ? S_RST : 0) |
|
||||
(data & IC_ACK ? S_ACK : 0) |
|
||||
(data & IC_BSY ? S_BSY : 0) |
|
||||
(data & IC_SEL ? S_SEL : 0) |
|
||||
(data & IC_ATN ? S_ATN : 0);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
m_icommand = (data & IC_WRITEMASK);
|
||||
delay(2);
|
||||
}
|
||||
|
||||
READ8_MEMBER(ncr5380n_device::mode_r)
|
||||
{
|
||||
return m_mode;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(ncr5380n_device::mode_w)
|
||||
{
|
||||
// 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
|
||||
// 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;
|
||||
arbitrate();
|
||||
}
|
||||
}
|
||||
|
||||
m_mode = data;
|
||||
}
|
||||
|
||||
READ8_MEMBER(ncr5380n_device::command_r)
|
||||
{
|
||||
// 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());
|
||||
m_tcommand = data;
|
||||
|
||||
// recalculate phase match
|
||||
m_busstatus &= ~BAS_PHASEMATCH;
|
||||
if ((scsi_bus->ctrl_r() & S_PHASE_MASK) == (m_tcommand & S_PHASE_MASK))
|
||||
{
|
||||
m_busstatus |= BAS_PHASEMATCH;
|
||||
}
|
||||
}
|
||||
|
||||
void ncr5380n_device::arbitrate()
|
||||
{
|
||||
m_icommand &= ~IC_ARBLOST;
|
||||
m_icommand |= IC_ARBITRATION;
|
||||
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);
|
||||
delay(11);
|
||||
}
|
||||
|
||||
void ncr5380n_device::check_irq()
|
||||
{
|
||||
#if 0
|
||||
bool oldirq = irq;
|
||||
irq = istatus != 0;
|
||||
if(irq != oldirq && !m_irq_func.isnull())
|
||||
m_irq_func(irq);
|
||||
#endif
|
||||
}
|
||||
|
||||
READ8_MEMBER(ncr5380n_device::status_r)
|
||||
{
|
||||
UINT32 ctrl = scsi_bus->ctrl_r();
|
||||
UINT8 res = status |
|
||||
(ctrl & S_RST ? ST_RST : 0) |
|
||||
(ctrl & S_BSY ? ST_BSY : 0) |
|
||||
(ctrl & S_REQ ? ST_REQ : 0) |
|
||||
(ctrl & S_MSG ? ST_MSG : 0) |
|
||||
(ctrl & S_CTL ? ST_CD : 0) |
|
||||
(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());
|
||||
return res;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(ncr5380n_device::selenable_w)
|
||||
{
|
||||
}
|
||||
|
||||
READ8_MEMBER(ncr5380n_device::busandstatus_r)
|
||||
{
|
||||
UINT32 ctrl = scsi_bus->ctrl_r();
|
||||
UINT8 res = m_busstatus |
|
||||
(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());
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(ncr5380n_device::startdmasend_w)
|
||||
{
|
||||
printf("%02x to start dma send\n", data);
|
||||
drq_set();
|
||||
}
|
||||
|
||||
READ8_MEMBER(ncr5380n_device::indata_r)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(ncr5380n_device::startdmatargetrx_w)
|
||||
{
|
||||
printf("%02x to start dma target Rx\n", data);
|
||||
}
|
||||
|
||||
READ8_MEMBER(ncr5380n_device::resetparityirq_r)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(ncr5380n_device::startdmainitrx_w)
|
||||
{
|
||||
// printf("%02x to start dma initiator Rx\n", data);
|
||||
recv_byte();
|
||||
}
|
||||
|
||||
void ncr5380n_device::dma_w(UINT8 val)
|
||||
{
|
||||
// drop DRQ until we're ready for another byte
|
||||
drq_clear();
|
||||
|
||||
if (m_mode & MODE_DMA)
|
||||
{
|
||||
m_dmalatch = val;
|
||||
send_byte();
|
||||
}
|
||||
}
|
||||
|
||||
UINT8 ncr5380n_device::dma_r()
|
||||
{
|
||||
// drop DRQ
|
||||
drq_clear();
|
||||
|
||||
// set up to receive our next byte if still in DMA mode
|
||||
scsi_bus->ctrl_w(scsi_refid, 0, S_ACK);
|
||||
if (m_mode & MODE_DMA)
|
||||
{
|
||||
recv_byte();
|
||||
}
|
||||
return m_dmalatch;
|
||||
}
|
||||
|
||||
void ncr5380n_device::drq_set()
|
||||
{
|
||||
if(!drq)
|
||||
{
|
||||
drq = true;
|
||||
m_busstatus |= BAS_DMAREQUEST;
|
||||
if(!m_drq_func.isnull())
|
||||
m_drq_func(drq);
|
||||
}
|
||||
}
|
||||
|
||||
void ncr5380n_device::drq_clear()
|
||||
{
|
||||
if(drq)
|
||||
{
|
||||
drq = false;
|
||||
m_busstatus &= ~BAS_DMAREQUEST;
|
||||
if(!m_drq_func.isnull())
|
||||
m_drq_func(drq);
|
||||
}
|
||||
}
|
||||
|
||||
READ8_MEMBER(ncr5380n_device::read)
|
||||
{
|
||||
switch (offset & 7)
|
||||
{
|
||||
case 0:
|
||||
return scsidata_r(space, offset);
|
||||
|
||||
case 1:
|
||||
return icmd_r(space, offset);
|
||||
|
||||
case 2:
|
||||
return mode_r(space, offset);
|
||||
|
||||
case 3:
|
||||
return command_r(space, offset);
|
||||
|
||||
case 4:
|
||||
return status_r(space, offset);
|
||||
|
||||
case 5:
|
||||
return busandstatus_r(space, offset);
|
||||
|
||||
case 6:
|
||||
return indata_r(space, offset);
|
||||
|
||||
case 7:
|
||||
return resetparityirq_r(space, offset);
|
||||
}
|
||||
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
WRITE8_MEMBER(ncr5380n_device::write)
|
||||
{
|
||||
switch (offset & 7)
|
||||
{
|
||||
case 0:
|
||||
outdata_w(space, offset, data);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
icmd_w(space, offset, data);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
mode_w(space, offset, data);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
command_w(space, offset, data);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
selenable_w(space, offset, data);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
startdmasend_w(space, offset, data);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
startdmatargetrx_w(space, offset, data);
|
||||
break;
|
||||
|
||||
case 7:
|
||||
startdmainitrx_w(space, offset, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
223
src/mess/machine/ncr5380n.h
Normal file
223
src/mess/machine/ncr5380n.h
Normal file
@ -0,0 +1,223 @@
|
||||
/*********************************************************************
|
||||
|
||||
ncr5380n.c
|
||||
|
||||
Implementation of the NCR 5380
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef NCR5380_H
|
||||
#define NCR5380_H
|
||||
|
||||
#include "machine/nscsi_bus.h"
|
||||
|
||||
struct ncr5380n_interface
|
||||
{
|
||||
devcb_write_line m_irq_cb;
|
||||
devcb_write_line m_drq_cb;
|
||||
};
|
||||
|
||||
class ncr5380n_device : public nscsi_device,
|
||||
public ncr5380n_interface
|
||||
{
|
||||
public:
|
||||
ncr5380n_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
|
||||
|
||||
DECLARE_ADDRESS_MAP(map, 8);
|
||||
|
||||
DECLARE_READ8_MEMBER(scsidata_r);
|
||||
DECLARE_WRITE8_MEMBER(outdata_w);
|
||||
DECLARE_READ8_MEMBER(icmd_r);
|
||||
DECLARE_WRITE8_MEMBER(icmd_w);
|
||||
DECLARE_READ8_MEMBER(mode_r);
|
||||
DECLARE_WRITE8_MEMBER(mode_w);
|
||||
DECLARE_READ8_MEMBER(command_r);
|
||||
DECLARE_WRITE8_MEMBER(command_w);
|
||||
DECLARE_READ8_MEMBER(status_r);
|
||||
DECLARE_WRITE8_MEMBER(selenable_w);
|
||||
DECLARE_READ8_MEMBER(busandstatus_r);
|
||||
DECLARE_WRITE8_MEMBER(startdmasend_w);
|
||||
DECLARE_READ8_MEMBER(indata_r);
|
||||
DECLARE_WRITE8_MEMBER(startdmatargetrx_w);
|
||||
DECLARE_READ8_MEMBER(resetparityirq_r);
|
||||
DECLARE_WRITE8_MEMBER(startdmainitrx_w);
|
||||
|
||||
DECLARE_READ8_MEMBER(read);
|
||||
DECLARE_WRITE8_MEMBER(write);
|
||||
|
||||
virtual void scsi_ctrl_changed();
|
||||
|
||||
UINT8 dma_r();
|
||||
void dma_w(UINT8 val);
|
||||
|
||||
protected:
|
||||
virtual void device_start();
|
||||
virtual void device_reset();
|
||||
virtual void device_config_complete();
|
||||
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
|
||||
|
||||
private:
|
||||
enum { MODE_D, MODE_T, MODE_I };
|
||||
enum { IDLE };
|
||||
|
||||
enum {
|
||||
// Bus initiated sequences
|
||||
BUSINIT_SETTLE_DELAY = 1,
|
||||
BUSINIT_ASSERT_BUS_SEL,
|
||||
BUSINIT_MSG_OUT,
|
||||
BUSINIT_RECV_BYTE,
|
||||
BUSINIT_ASSERT_BUS_RESEL,
|
||||
BUSINIT_WAIT_REQ,
|
||||
BUSINIT_RECV_BYTE_NACK,
|
||||
|
||||
// Bus SCSI Reset
|
||||
BUSRESET_WAIT_INT,
|
||||
BUSRESET_RESET_BOARD,
|
||||
|
||||
// Disconnected state commands
|
||||
DISC_SEL_ARBITRATION,
|
||||
DISC_SEL_ATN_WAIT_REQ,
|
||||
DISC_SEL_ATN_SEND_BYTE,
|
||||
DISC_SEL_WAIT_REQ,
|
||||
DISC_SEL_SEND_BYTE,
|
||||
DISC_REC_ARBITRATION,
|
||||
DISC_REC_MSG_IN,
|
||||
DISC_REC_SEND_BYTE,
|
||||
DISC_RESET,
|
||||
|
||||
// Command sequence
|
||||
CMDSEQ_CMD_PHASE,
|
||||
CMDSEQ_RECV_BYTE,
|
||||
|
||||
// Target commands
|
||||
TARGET_SEND_BYTE,
|
||||
TARGET_CMD_RECV_BYTE,
|
||||
TARGET_MSG_RECV_BYTE,
|
||||
TARGET_MSG_RECV_PAD,
|
||||
TARGET_DISC_SEND_BYTE,
|
||||
TARGET_DISC_MSG_IN,
|
||||
TARGET_DISC_SEND_BYTE_2,
|
||||
|
||||
// Initiator commands
|
||||
INIT_MSG_WAIT_REQ,
|
||||
INIT_XFR,
|
||||
INIT_XFR_SEND_BYTE,
|
||||
INIT_XFR_SEND_PAD_WAIT_REQ,
|
||||
INIT_XFR_SEND_PAD,
|
||||
INIT_XFR_RECV_PAD_WAIT_REQ,
|
||||
INIT_XFR_RECV_PAD,
|
||||
INIT_XFR_RECV_BYTE_ACK,
|
||||
INIT_XFR_RECV_BYTE_NACK,
|
||||
INIT_XFR_WAIT_REQ,
|
||||
INIT_CPT_RECV_BYTE_ACK,
|
||||
INIT_CPT_RECV_WAIT_REQ,
|
||||
INIT_CPT_RECV_BYTE_NACK,
|
||||
};
|
||||
|
||||
enum {
|
||||
// Arbitration
|
||||
ARB_WAIT_BUS_FREE = 1,
|
||||
ARB_COMPLETE,
|
||||
ARB_ASSERT_SEL,
|
||||
ARB_SET_DEST,
|
||||
ARB_RELEASE_BUSY,
|
||||
ARB_TIMEOUT_BUSY,
|
||||
ARB_TIMEOUT_ABORT,
|
||||
ARB_DESKEW_WAIT,
|
||||
|
||||
// Send/recieve byte
|
||||
SEND_WAIT_SETTLE,
|
||||
SEND_WAIT_REQ_0,
|
||||
RECV_WAIT_REQ_1,
|
||||
RECV_WAIT_SETTLE,
|
||||
RECV_WAIT_REQ_0,
|
||||
};
|
||||
|
||||
enum {
|
||||
STATE_MASK = 0x00ff,
|
||||
SUB_SHIFT = 8,
|
||||
SUB_MASK = 0xff00,
|
||||
};
|
||||
|
||||
enum { BUS_BUSY, BUS_FREE_WAIT, BUS_FREE };
|
||||
|
||||
enum {
|
||||
ST_RST = 0x80,
|
||||
ST_BSY = 0x40,
|
||||
ST_REQ = 0x20,
|
||||
ST_MSG = 0x10,
|
||||
ST_CD = 0x08,
|
||||
ST_IO = 0x04,
|
||||
ST_SEL = 0x02,
|
||||
ST_DBP = 0x01,
|
||||
|
||||
BAS_ENDOFDMA = 0x80,
|
||||
BAS_DMAREQUEST = 0x40,
|
||||
BAS_PARITYERROR = 0x20,
|
||||
BAS_IRQACTIVE = 0x10,
|
||||
BAS_PHASEMATCH = 0x08,
|
||||
BAS_BUSYERROR = 0x04,
|
||||
BAS_ATN = 0x02,
|
||||
BAS_ACK = 0x01,
|
||||
|
||||
IC_RST = 0x80,
|
||||
IC_ARBITRATION = 0x40,
|
||||
IC_ARBLOST = 0x20,
|
||||
IC_ACK = 0x10,
|
||||
IC_BSY = 0x08,
|
||||
IC_SEL = 0x04,
|
||||
IC_ATN = 0x02,
|
||||
IC_DBUS = 0x01,
|
||||
IC_PHASEMASK = 0x9e,
|
||||
IC_WRITEMASK = 0x9f,
|
||||
|
||||
MODE_BLOCKDMA = 0x80,
|
||||
MODE_TARGET = 0x40,
|
||||
MODE_PARITYCHK = 0x20,
|
||||
MODE_PARITYIRQ = 0x10,
|
||||
MODE_EOPIRQ = 0x08,
|
||||
MODE_BSYIRQ = 0x04,
|
||||
MODE_DMA = 0x02,
|
||||
MODE_ARBITRATE = 0x01,
|
||||
};
|
||||
|
||||
enum { DMA_NONE, DMA_IN, DMA_OUT };
|
||||
|
||||
emu_timer *tm;
|
||||
|
||||
UINT8 status, istatus, m_mode, m_outdata, m_busstatus, m_dmalatch;
|
||||
UINT8 m_icommand, m_tcommand;
|
||||
UINT8 clock_conv, sync_offset, sync_period, bus_id, select_timeout, seq;
|
||||
UINT16 tcount;
|
||||
int mode;
|
||||
int state, xfr_phase;
|
||||
|
||||
bool irq, drq;
|
||||
|
||||
devcb_resolved_write_line m_irq_func;
|
||||
devcb_resolved_write_line m_drq_func;
|
||||
|
||||
void drq_set();
|
||||
void drq_clear();
|
||||
|
||||
void step(bool timeout);
|
||||
void function_complete();
|
||||
void function_bus_complete();
|
||||
void bus_complete();
|
||||
|
||||
void arbitrate();
|
||||
void check_irq();
|
||||
|
||||
void reset_soft();
|
||||
void reset_disconnect();
|
||||
|
||||
void send_byte();
|
||||
void recv_byte();
|
||||
|
||||
void delay(int cycles);
|
||||
void delay_cycles(int cycles);
|
||||
};
|
||||
|
||||
extern const device_type NCR5380N;
|
||||
|
||||
#endif
|
@ -529,6 +529,7 @@ $(MESSOBJ)/shared.a: \
|
||||
$(MESS_MACHINE)/msm6222b.o \
|
||||
$(MESS_MACHINE)/serial.o \
|
||||
$(MESS_MACHINE)/ncr5380.o \
|
||||
$(MESS_MACHINE)/ncr5380n.o \
|
||||
$(MESS_MACHINE)/ncr5390.o \
|
||||
$(MESS_MACHINE)/pc_kbdc.o \
|
||||
$(MESS_MACHINE)/pc_lpt.o \
|
||||
|
Loading…
Reference in New Issue
Block a user