mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
cxd1185: new device
This commit is contained in:
parent
1b472fde8b
commit
5693fa0691
@ -4268,3 +4268,15 @@ if (MACHINES["I3002"]~=null) then
|
||||
MAME_DIR .. "src/devices/machine/i3002.h",
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
--
|
||||
--@src/devices/machine/cxd1185.h,MACHINES["CXD1185"] = true
|
||||
---------------------------------------------------
|
||||
|
||||
if (MACHINES["CXD1185"]~=null) then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/machine/cxd1185.cpp",
|
||||
MAME_DIR .. "src/devices/machine/cxd1185.h",
|
||||
}
|
||||
end
|
||||
|
@ -748,6 +748,7 @@ MACHINES["I82357"] = true
|
||||
MACHINES["XC1700E"] = true
|
||||
MACHINES["EDLC"] = true
|
||||
MACHINES["WTL3132"] = true
|
||||
MACHINES["CXD1185"] = true
|
||||
|
||||
--------------------------------------------------
|
||||
-- specify available bus cores
|
||||
|
875
src/devices/machine/cxd1185.cpp
Normal file
875
src/devices/machine/cxd1185.cpp
Normal file
@ -0,0 +1,875 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Patrick Mackinlay
|
||||
|
||||
/*
|
||||
* Sony CXD1185 SCSI 1 Protocol Controller.
|
||||
*
|
||||
* Sources:
|
||||
* - https://datasheetspdf.com/pdf-file/199633/SonyCorporation/CXD1185CQ/1
|
||||
*
|
||||
* TODO:
|
||||
* - target mode
|
||||
* - pio mode testing
|
||||
* - cq/aq variants
|
||||
* - synchronous mode
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
#include "cxd1185.h"
|
||||
|
||||
#define LOG_GENERAL (1U << 0)
|
||||
#define LOG_CMD (1U << 1)
|
||||
#define LOG_REG (1U << 2)
|
||||
#define LOG_STATE (1U << 3)
|
||||
#define LOG_CONFIG (1U << 4)
|
||||
#define LOG_INT (1U << 5)
|
||||
#define LOG_SCSI (1U << 6)
|
||||
#define LOG_DMA (1U << 7)
|
||||
|
||||
//#define VERBOSE (LOG_GENERAL|LOG_CMD|LOG_REG|LOG_STATE|LOG_CONFIG|LOG_INT|LOG_SCSI|LOG_DMA)
|
||||
|
||||
#include "logmacro.h"
|
||||
|
||||
DEFINE_DEVICE_TYPE(CXD1185, cxd1185_device, "cxd1185", "Sony CXD1185 SCSI 1 Protocol Controller")
|
||||
|
||||
static char const *const nscsi_phase[] = { "DATA OUT", "DATA IN", "COMMAND", "STATUS", "*", "*", "MESSAGE OUT", "MESSAGE IN" };
|
||||
|
||||
// FIXME: would be better to reuse from nscsi_full_device
|
||||
static unsigned const SCSI_ARB_DELAY = 2'400;
|
||||
static unsigned const SCSI_BUS_CLEAR = 800;
|
||||
static unsigned const SCSI_BUS_FREE = 800;
|
||||
static unsigned const SCSI_BUS_SETTLE = 400;
|
||||
static unsigned const SCSI_BUS_SKEW = 10;
|
||||
static unsigned const SCSI_RST_HOLD = 25'000;
|
||||
|
||||
ALLOW_SAVE_TYPE(cxd1185_device::state);
|
||||
|
||||
cxd1185_device::cxd1185_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
|
||||
: nscsi_device(mconfig, CXD1185, tag, owner, clock)
|
||||
, nscsi_slot_card_interface(mconfig, *this, DEVICE_SELF)
|
||||
, m_irq_out_cb(*this)
|
||||
, m_drq_out_cb(*this)
|
||||
, m_port_out_cb(*this)
|
||||
{
|
||||
}
|
||||
|
||||
void cxd1185_device::map(address_map &map)
|
||||
{
|
||||
map(0x0, 0x0).rw(FUNC(cxd1185_device::status_r), FUNC(cxd1185_device::command_w));
|
||||
map(0x1, 0x1).rw(FUNC(cxd1185_device::scsi_data_r), FUNC(cxd1185_device::scsi_data_w));
|
||||
map(0x2, 0x2).r(FUNC(cxd1185_device::int_req_r<0>));
|
||||
map(0x3, 0x3).rw(FUNC(cxd1185_device::int_req_r<1>), FUNC(cxd1185_device::environ_w));
|
||||
map(0x4, 0x4).rw(FUNC(cxd1185_device::scsi_ctrl_monitor_r), FUNC(cxd1185_device::timer_w));
|
||||
map(0x5, 0x5).r(FUNC(cxd1185_device::fifo_status_r));
|
||||
map(0x6, 0x6).rw(FUNC(cxd1185_device::scsi_id_r), FUNC(cxd1185_device::scsi_id_w));
|
||||
map(0x7, 0x7).rw(FUNC(cxd1185_device::count_r<0>), FUNC(cxd1185_device::count_w<0>));
|
||||
map(0x8, 0x8).rw(FUNC(cxd1185_device::count_r<1>), FUNC(cxd1185_device::count_w<1>));
|
||||
map(0x9, 0x9).rw(FUNC(cxd1185_device::count_r<2>), FUNC(cxd1185_device::count_w<2>));
|
||||
map(0xa, 0xa).rw(FUNC(cxd1185_device::int_auth_r<0>), FUNC(cxd1185_device::int_auth_w<0>));
|
||||
map(0xb, 0xb).rw(FUNC(cxd1185_device::int_auth_r<1>), FUNC(cxd1185_device::int_auth_w<1>));
|
||||
map(0xc, 0xc).rw(FUNC(cxd1185_device::mode_r), FUNC(cxd1185_device::mode_w));
|
||||
map(0xd, 0xd).rw(FUNC(cxd1185_device::sync_ctrl_r), FUNC(cxd1185_device::sync_ctrl_w));
|
||||
map(0xe, 0xe).rw(FUNC(cxd1185_device::scsi_ctrl_r), FUNC(cxd1185_device::scsi_ctrl_w));
|
||||
map(0xf, 0xf).rw(FUNC(cxd1185_device::ioport_r), FUNC(cxd1185_device::ioport_w));
|
||||
}
|
||||
|
||||
void cxd1185_device::device_start()
|
||||
{
|
||||
m_irq_out_cb.resolve_safe();
|
||||
m_drq_out_cb.resolve_safe();
|
||||
m_port_out_cb.resolve_safe();
|
||||
|
||||
save_item(NAME(m_state));
|
||||
save_item(NAME(m_irq_asserted));
|
||||
save_item(NAME(m_drq_asserted));
|
||||
save_item(NAME(m_pio_data_mode));
|
||||
save_item(NAME(m_pio_ctrl_mode));
|
||||
//save_item(NAME(m_fifo));
|
||||
save_item(NAME(m_scsi_ctrl_state));
|
||||
|
||||
save_item(NAME(m_status));
|
||||
save_item(NAME(m_command));
|
||||
save_item(NAME(m_int_req));
|
||||
save_item(NAME(m_environ));
|
||||
save_item(NAME(m_sel_time));
|
||||
save_item(NAME(m_rst_time));
|
||||
save_item(NAME(m_scsi_id));
|
||||
save_item(NAME(m_int_auth));
|
||||
save_item(NAME(m_mode));
|
||||
save_item(NAME(m_count));
|
||||
save_item(NAME(m_sync_ctrl));
|
||||
save_item(NAME(m_scsi_ctrl));
|
||||
save_item(NAME(m_ioport));
|
||||
|
||||
m_state_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(cxd1185_device::state_timer), this));
|
||||
m_state = IDLE;
|
||||
|
||||
m_irq_asserted = false;
|
||||
m_drq_asserted = false;
|
||||
|
||||
// monitor all scsi bus control lines
|
||||
scsi_bus->ctrl_wait(scsi_refid, S_ALL, S_ALL);
|
||||
}
|
||||
|
||||
void cxd1185_device::device_reset()
|
||||
{
|
||||
m_environ = 0;
|
||||
|
||||
reset_chip();
|
||||
}
|
||||
|
||||
void cxd1185_device::reset_chip()
|
||||
{
|
||||
m_pio_data_mode = false;
|
||||
m_pio_ctrl_mode = false;
|
||||
|
||||
// clear all except environment register
|
||||
m_status = 0;
|
||||
m_command = 0;
|
||||
m_int_req[0] = 0;
|
||||
m_int_req[1] = 0;
|
||||
m_sel_time = 0;
|
||||
m_rst_time = SCSI_RST_HOLD;
|
||||
m_scsi_id = 0;
|
||||
m_int_auth[0] = 0;
|
||||
m_int_auth[1] = 0;
|
||||
m_mode = 0;
|
||||
m_count = 0;
|
||||
m_sync_ctrl = 0;
|
||||
m_scsi_ctrl = 0;
|
||||
m_ioport = 0;
|
||||
|
||||
// clear drq and irq
|
||||
reset_fifo();
|
||||
int_check();
|
||||
|
||||
// clear scsi bus
|
||||
scsi_bus->data_w(scsi_refid, 0);
|
||||
scsi_bus->ctrl_w(scsi_refid, 0, S_ALL);
|
||||
}
|
||||
|
||||
void cxd1185_device::reset_fifo()
|
||||
{
|
||||
m_fifo.clear();
|
||||
set_drq(false);
|
||||
}
|
||||
|
||||
u8 cxd1185_device::status_r()
|
||||
{
|
||||
u8 const data = (scsi_bus->ctrl_r() & S_RST) ? MRST : 0;
|
||||
|
||||
LOGMASKED(LOG_REG, "status_r 0x%02x\n", data | m_status);
|
||||
|
||||
return data | m_status;
|
||||
}
|
||||
|
||||
u8 cxd1185_device::scsi_data_r()
|
||||
{
|
||||
u8 data = 0;
|
||||
|
||||
if (!m_pio_data_mode)
|
||||
{
|
||||
data = m_fifo.dequeue();
|
||||
|
||||
if (m_state != IDLE && !m_state_timer->enabled())
|
||||
m_state_timer->adjust(attotime::zero);
|
||||
}
|
||||
else
|
||||
data = scsi_bus->data_r();
|
||||
|
||||
LOGMASKED(LOG_REG, "scsi_data_r 0x%02x (%s)\n", data, machine().describe_context());
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
template <unsigned Register> u8 cxd1185_device::int_req_r()
|
||||
{
|
||||
u8 const data = m_int_req[Register];
|
||||
|
||||
LOGMASKED(LOG_REG, "int_req_r<%d> 0x%02x\n", Register, data);
|
||||
|
||||
m_int_req[Register] = 0;
|
||||
int_check();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
u8 cxd1185_device::scsi_ctrl_monitor_r()
|
||||
{
|
||||
u32 const ctrl = scsi_bus->ctrl_r();
|
||||
|
||||
u8 const data =
|
||||
((ctrl & S_BSY) ? MBSY : 0) |
|
||||
((ctrl & S_SEL) ? MSEL : 0) |
|
||||
((ctrl & S_MSG) ? MMSG : 0) |
|
||||
((ctrl & S_CTL) ? MCD : 0) |
|
||||
((ctrl & S_INP) ? MIO : 0) |
|
||||
((ctrl & S_REQ) ? MREQ : 0) |
|
||||
((ctrl & S_ACK) ? MACK : 0) |
|
||||
((ctrl & S_ATN) ? MATN : 0);
|
||||
|
||||
LOGMASKED(LOG_REG, "scsi_ctrl_monitor_r 0x%02x\n", data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
u8 cxd1185_device::fifo_status_r()
|
||||
{
|
||||
u8 const data =
|
||||
(m_fifo.empty() ? FIE : 0) |
|
||||
(m_fifo.full() ? FIF : 0) |
|
||||
(m_fifo.queue_length() & FC);
|
||||
|
||||
LOGMASKED(LOG_REG, "fifo_status_r 0x%02x\n", data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void cxd1185_device::command_w(u8 data)
|
||||
{
|
||||
LOGMASKED(LOG_REG, "command_w 0x%02x\n", data);
|
||||
|
||||
// check command in progress
|
||||
if ((m_status & CIP) && (data != CMD_RESET))
|
||||
return;
|
||||
|
||||
// check command mode/category
|
||||
switch (data & CAT)
|
||||
{
|
||||
case 0x00:
|
||||
// commands valid in any state
|
||||
break;
|
||||
case 0x40:
|
||||
// commands valid in disconnected state
|
||||
if (m_status & (INIT | TARG))
|
||||
return;
|
||||
break;
|
||||
case 0x80:
|
||||
// commands valid in target state
|
||||
if ((m_status & (INIT | TARG)) != TARG)
|
||||
return;
|
||||
fatalerror("cxd1185_device: target mode not implemented\n");
|
||||
break;
|
||||
case 0xc0:
|
||||
// commands valid in initiator state
|
||||
if ((m_status & (INIT | TARG)) != INIT)
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
m_command = data;
|
||||
m_status |= CIP;
|
||||
|
||||
switch (data & (CAT | CMD))
|
||||
{
|
||||
case 0x00:
|
||||
LOGMASKED(LOG_CMD, "no operation\n");
|
||||
break;
|
||||
case 0x01:
|
||||
LOGMASKED(LOG_CMD, "reset chip\n");
|
||||
reset_chip();
|
||||
break;
|
||||
case 0x02:
|
||||
LOGMASKED(LOG_CMD, "assert scsi reset\n");
|
||||
m_state = BUS_RESET;
|
||||
break;
|
||||
case 0x03:
|
||||
LOGMASKED(LOG_CMD, "flush fifo\n");
|
||||
reset_fifo();
|
||||
break;
|
||||
case 0x04:
|
||||
LOGMASKED(LOG_CMD, "assert scsi control\n");
|
||||
m_pio_ctrl_mode = true;
|
||||
m_scsi_ctrl = 0;
|
||||
if ((m_status & (INIT | TARG)) == TARG)
|
||||
scsi_bus->ctrl_w(scsi_refid, 0, S_ALL & ~S_BSY);
|
||||
break;
|
||||
case 0x05:
|
||||
LOGMASKED(LOG_CMD, "deassert scsi control\n");
|
||||
m_pio_ctrl_mode = false;
|
||||
break;
|
||||
case 0x06:
|
||||
LOGMASKED(LOG_CMD, "assert scsi data\n");
|
||||
m_pio_data_mode = true;
|
||||
break;
|
||||
case 0x07:
|
||||
LOGMASKED(LOG_CMD, "deassert scsi data\n");
|
||||
m_pio_data_mode = false;
|
||||
break;
|
||||
|
||||
case 0x40: LOGMASKED(LOG_CMD, "reselect\n"); break;
|
||||
case 0x41:
|
||||
LOGMASKED(LOG_CMD, "select without atn\n");
|
||||
m_status |= INIT;
|
||||
m_state = ARB_BUS_FREE;
|
||||
break;
|
||||
case 0x42:
|
||||
LOGMASKED(LOG_CMD, "select with atn\n");
|
||||
m_status |= INIT;
|
||||
m_state = ARB_BUS_FREE;
|
||||
break;
|
||||
case 0x43: LOGMASKED(LOG_CMD, "enable selection/reselection\n"); break;
|
||||
case 0x44: LOGMASKED(LOG_CMD, "disable selection/reselection\n"); break;
|
||||
|
||||
// TODO: not implemented
|
||||
case 0x80: LOGMASKED(LOG_CMD, "send message\n"); break;
|
||||
case 0x81: LOGMASKED(LOG_CMD, "send status\n"); break;
|
||||
case 0x82: LOGMASKED(LOG_CMD, "send data\n"); break;
|
||||
case 0x83: LOGMASKED(LOG_CMD, "disconnect\n"); break;
|
||||
case 0x84: LOGMASKED(LOG_CMD, "receive message out\n"); break;
|
||||
case 0x85: LOGMASKED(LOG_CMD, "receive command\n"); break;
|
||||
case 0x86: LOGMASKED(LOG_CMD, "receive data\n"); break;
|
||||
|
||||
case 0xc0:
|
||||
LOGMASKED(LOG_CMD, "transfer information\n");
|
||||
m_state = XFR_INFO;
|
||||
break;
|
||||
case 0xc1:
|
||||
LOGMASKED(LOG_CMD, "transfer pad\n");
|
||||
m_state = XFR_INFO;
|
||||
break;
|
||||
case 0xc2:
|
||||
LOGMASKED(LOG_CMD, "deassert ack\n");
|
||||
scsi_bus->ctrl_w(scsi_refid, 0, S_ACK);
|
||||
break;
|
||||
case 0xc3:
|
||||
LOGMASKED(LOG_CMD, "assert atn\n");
|
||||
scsi_bus->ctrl_w(scsi_refid, S_ATN, S_ATN);
|
||||
break;
|
||||
case 0xc4:
|
||||
LOGMASKED(LOG_CMD, "deassert atn\n");
|
||||
scsi_bus->ctrl_w(scsi_refid, 0, S_ATN);
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_state == IDLE)
|
||||
{
|
||||
// command completes immediately
|
||||
LOGMASKED(LOG_CMD, "command complete immediate\n");
|
||||
|
||||
m_command = 0;
|
||||
m_status &= ~CIP;
|
||||
|
||||
if (data != CMD_RESET)
|
||||
{
|
||||
m_int_req[1] |= FNC;
|
||||
int_check();
|
||||
}
|
||||
}
|
||||
else
|
||||
m_state_timer->adjust(attotime::zero);
|
||||
}
|
||||
|
||||
void cxd1185_device::scsi_data_w(u8 data)
|
||||
{
|
||||
LOGMASKED(LOG_REG, "scsi_data_w 0x%02x (%s)\n", data, machine().describe_context());
|
||||
|
||||
if (!m_pio_data_mode)
|
||||
{
|
||||
m_fifo.enqueue(data);
|
||||
|
||||
if (m_state != IDLE && !m_state_timer->enabled())
|
||||
m_state_timer->adjust(attotime::zero);
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 const ctrl = scsi_bus->ctrl_r();
|
||||
|
||||
if (!(m_int_req[1] & PHC) &&
|
||||
(((m_status & (INIT | TARG)) == INIT && !(ctrl & S_INP)) ||
|
||||
((m_status & (INIT | TARG)) == TARG && (ctrl & S_INP))))
|
||||
scsi_bus->data_w(scsi_refid, data);
|
||||
}
|
||||
}
|
||||
|
||||
void cxd1185_device::environ_w(u8 data)
|
||||
{
|
||||
bool const polarity = (data ^ m_environ) & SIRM;
|
||||
|
||||
LOGMASKED(LOG_REG, "environ_w 0x%02x\n", data);
|
||||
if (data ^ m_environ)
|
||||
LOGMASKED(LOG_CONFIG, "%s mode, %s data bus parity, %s irq polarity, divider %d\n",
|
||||
(data & DIFE) ? "differential" : "single-ended",
|
||||
(data & DPEN) ? ((data & SDPM) ? "even" : "odd") : "no",
|
||||
(data & SIRM) ? "negative" : "positive",
|
||||
(data & FS) ? ((data & FS1) ? 2 : 3) : 4);
|
||||
|
||||
m_environ = data;
|
||||
|
||||
// update irq line if polarity changed
|
||||
if (polarity)
|
||||
m_irq_out_cb((m_environ & SIRM) ? !m_irq_asserted : m_irq_asserted);
|
||||
}
|
||||
|
||||
void cxd1185_device::timer_w(u8 data)
|
||||
{
|
||||
LOGMASKED(LOG_REG, "timer_w 0x%02x\n", data);
|
||||
|
||||
unsigned const divisor = (m_environ & FS) ? ((m_environ & FS1) ? 2 : 3) : 4;
|
||||
if (m_mode & TMSL)
|
||||
{
|
||||
m_rst_time = double(divisor * (32 * data + 38)) / clock() * 1E+9;
|
||||
|
||||
LOGMASKED(LOG_CONFIG, "reset timer %d ns\n", m_rst_time);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sel_time = double(divisor * (data + 1) * 8192) / clock() * 1E+9;
|
||||
|
||||
LOGMASKED(LOG_CONFIG, "selection timer %d ns\n", m_sel_time);
|
||||
}
|
||||
}
|
||||
|
||||
template <unsigned Register> void cxd1185_device::int_auth_w(u8 data)
|
||||
{
|
||||
LOGMASKED(LOG_REG, "int_auth_w<%d> 0x%02x\n", Register, data);
|
||||
|
||||
m_int_auth[Register] = data;
|
||||
|
||||
int_check();
|
||||
}
|
||||
|
||||
void cxd1185_device::scsi_ctrl_w(u8 data)
|
||||
{
|
||||
LOGMASKED(LOG_REG, "scsi_ctrl_w 0x%02x (%s)\n", data, machine().describe_context());
|
||||
|
||||
if (m_pio_ctrl_mode)
|
||||
{
|
||||
u32 nscsi_mask = S_BSY | S_SEL;
|
||||
|
||||
if ((m_status & (INIT | TARG)) == TARG)
|
||||
nscsi_mask |= S_MSG | S_CTL | S_INP | S_REQ;
|
||||
else if ((m_status & (INIT | TARG)) == INIT)
|
||||
nscsi_mask |= S_ACK | S_ATN;
|
||||
|
||||
u32 const nscsi_data =
|
||||
((data & ABSY) ? S_BSY : 0) |
|
||||
((data & ASEL) ? S_SEL : 0) |
|
||||
((data & AMSG) ? S_MSG : 0) |
|
||||
((data & ACD) ? S_CTL : 0) |
|
||||
((data & AIO) ? S_INP : 0) |
|
||||
((data & AREQ) ? S_REQ : 0) |
|
||||
((data & AACK) ? S_ACK : 0) |
|
||||
((data & AATN) ? S_ATN : 0);
|
||||
|
||||
scsi_bus->ctrl_w(scsi_refid, nscsi_data, nscsi_mask);
|
||||
}
|
||||
else
|
||||
m_scsi_ctrl = data;
|
||||
}
|
||||
|
||||
void cxd1185_device::ioport_w(u8 data)
|
||||
{
|
||||
LOGMASKED(LOG_REG, "ioport_w 0x%02x\n", data);
|
||||
|
||||
// update direction bits first
|
||||
m_ioport &= ~PCN;
|
||||
m_ioport |= data & PCN;
|
||||
|
||||
u8 const mask = (m_ioport & PCN) >> 4;
|
||||
|
||||
// update output bits
|
||||
m_ioport &= ~mask;
|
||||
m_ioport |= data & mask;
|
||||
|
||||
m_port_out_cb(0, m_ioport & mask, mask);
|
||||
}
|
||||
|
||||
void cxd1185_device::state_timer(void *ptr, s32 param)
|
||||
{
|
||||
// step state machine
|
||||
int delay = state_step();
|
||||
|
||||
// check for interrupts
|
||||
int_check();
|
||||
|
||||
// check for data stall
|
||||
if (delay < 0)
|
||||
return;
|
||||
|
||||
if (m_state == IDLE)
|
||||
{
|
||||
LOGMASKED(LOG_CMD, "command complete\n");
|
||||
m_status &= ~CIP;
|
||||
m_command = 0;
|
||||
}
|
||||
else
|
||||
m_state_timer->adjust(attotime::from_nsec(delay));
|
||||
}
|
||||
|
||||
int cxd1185_device::state_step()
|
||||
{
|
||||
int delay = 0;
|
||||
|
||||
u8 const oid = 1 << ((m_scsi_id & OID) >> 0);
|
||||
u8 const tid = 1 << ((m_scsi_id & TID) >> 5);
|
||||
|
||||
switch (m_state)
|
||||
{
|
||||
case IDLE:
|
||||
break;
|
||||
|
||||
case ARB_BUS_FREE:
|
||||
LOGMASKED(LOG_STATE, "arbitration: waiting for bus free\n");
|
||||
if (!(scsi_bus->ctrl_r() & (S_SEL | S_BSY | S_RST)))
|
||||
{
|
||||
m_state = ARB_START;
|
||||
delay = SCSI_BUS_FREE;
|
||||
}
|
||||
break;
|
||||
case ARB_START:
|
||||
LOGMASKED(LOG_STATE, "arbitration: started\n");
|
||||
m_state = ARB_EVALUATE;
|
||||
delay = SCSI_ARB_DELAY;
|
||||
|
||||
// assert own ID and BSY
|
||||
scsi_bus->data_w(scsi_refid, oid);
|
||||
scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY);
|
||||
break;
|
||||
case ARB_EVALUATE:
|
||||
// check if SEL asserted, or if there's a higher ID on the bus
|
||||
if ((scsi_bus->ctrl_r() & S_SEL) || (scsi_bus->data_r() & ~((oid - 1) | oid)))
|
||||
{
|
||||
LOGMASKED(LOG_STATE, "arbitration: lost\n");
|
||||
m_int_req[0] |= ARBF;
|
||||
m_status &= ~INIT;
|
||||
|
||||
m_state = COMPLETE;
|
||||
|
||||
// clear data and BSY
|
||||
scsi_bus->data_w(scsi_refid, 0);
|
||||
scsi_bus->ctrl_w(scsi_refid, 0, S_BSY);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGMASKED(LOG_STATE, "arbitration: won\n");
|
||||
m_state = SEL_START;
|
||||
delay = SCSI_BUS_CLEAR + SCSI_BUS_SETTLE;
|
||||
}
|
||||
break;
|
||||
|
||||
case SEL_START:
|
||||
LOGMASKED(LOG_STATE, "selection: SEL asserted\n");
|
||||
m_state = SEL_DELAY;
|
||||
delay = SCSI_BUS_SKEW * 2;
|
||||
|
||||
// assert own and target ID and SEL
|
||||
scsi_bus->data_w(scsi_refid, oid | tid);
|
||||
scsi_bus->ctrl_w(scsi_refid, S_SEL, S_SEL);
|
||||
break;
|
||||
case SEL_DELAY:
|
||||
LOGMASKED(LOG_STATE, "selection: BSY cleared\n");
|
||||
m_state = SEL_WAIT_BSY;
|
||||
delay = std::max(m_sel_time, SCSI_BUS_SETTLE);
|
||||
|
||||
// clear BSY, optionally assert ATN
|
||||
if (m_command == CMD_SEL_ATN)
|
||||
scsi_bus->ctrl_w(scsi_refid, S_ATN, S_BSY | S_ATN);
|
||||
else
|
||||
scsi_bus->ctrl_w(scsi_refid, 0, S_BSY);
|
||||
break;
|
||||
case SEL_WAIT_BSY:
|
||||
if (scsi_bus->ctrl_r() & S_BSY)
|
||||
{
|
||||
LOGMASKED(LOG_STATE, "selection: BSY asserted by target\n");
|
||||
m_state = SEL_COMPLETE;
|
||||
delay = SCSI_BUS_SKEW * 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGMASKED(LOG_STATE, "selection: timed out\n");
|
||||
m_int_req[0] |= STO;
|
||||
m_state = COMPLETE;
|
||||
}
|
||||
break;
|
||||
case SEL_COMPLETE:
|
||||
LOGMASKED(LOG_STATE, "selection: complete\n");
|
||||
m_state = COMPLETE;
|
||||
|
||||
// clear data and SEL
|
||||
scsi_bus->data_w(scsi_refid, 0);
|
||||
scsi_bus->ctrl_w(scsi_refid, 0, S_SEL);
|
||||
break;
|
||||
|
||||
case XFR_INFO:
|
||||
LOGMASKED(LOG_STATE, "transfer: count %d waiting for REQ\n", m_count);
|
||||
if (scsi_bus->ctrl_r() & S_REQ)
|
||||
m_state = scsi_bus->ctrl_r() & S_INP ? XFR_IN : XFR_OUT;
|
||||
break;
|
||||
case XFR_IN:
|
||||
// FIXME: datasheet says ACK should be asserted when TRBE & FIF
|
||||
if (!m_fifo.full())
|
||||
{
|
||||
u8 const data = ((m_command & CMD) == (CMD_XFR_PAD & CMD)) ? 0 : scsi_bus->data_r();
|
||||
LOGMASKED(LOG_STATE, "transfer in: data 0x%02x\n", data);
|
||||
|
||||
m_fifo.enqueue(data);
|
||||
if (m_command & TRBE)
|
||||
m_count--;
|
||||
|
||||
m_state = XFR_IN_NEXT;
|
||||
|
||||
// assert ACK
|
||||
scsi_bus->ctrl_w(scsi_refid, S_ACK, S_ACK);
|
||||
}
|
||||
else
|
||||
{
|
||||
delay = -1;
|
||||
if (m_command & DMA)
|
||||
set_drq(true);
|
||||
}
|
||||
break;
|
||||
case XFR_IN_NEXT:
|
||||
if (!(scsi_bus->ctrl_r() & S_REQ))
|
||||
{
|
||||
LOGMASKED(LOG_STATE, "transfer in: count %d\n", m_count);
|
||||
if (!m_count)
|
||||
{
|
||||
m_status |= TRBZ;
|
||||
m_state = XFR_IN_DRAIN;
|
||||
}
|
||||
else
|
||||
m_state = XFR_IN_REQ;
|
||||
|
||||
// clear ACK except for single-byte message-in
|
||||
if (!((scsi_bus->ctrl_r() & S_PHASE_MASK) == S_PHASE_MSG_IN && !(m_command & TRBE)))
|
||||
scsi_bus->ctrl_w(scsi_refid, 0, S_ACK);
|
||||
}
|
||||
break;
|
||||
case XFR_IN_REQ:
|
||||
if (scsi_bus->ctrl_r() & S_REQ)
|
||||
m_state = XFR_IN;
|
||||
break;
|
||||
case XFR_IN_DRAIN:
|
||||
// TODO: not sure whether commands complete before fifo is empty
|
||||
#if 0
|
||||
if (!m_fifo.empty())
|
||||
{
|
||||
delay = -1;
|
||||
if (m_command & DMA)
|
||||
set_drq(true);
|
||||
}
|
||||
else
|
||||
m_state = XFR_INFO_DONE;
|
||||
#else
|
||||
if (!m_fifo.empty() && (m_command & DMA))
|
||||
set_drq(true);
|
||||
m_state = XFR_INFO_DONE;
|
||||
#endif
|
||||
break;
|
||||
case XFR_OUT:
|
||||
if (!m_fifo.empty() || (m_command & CMD) == (CMD_XFR_PAD & CMD))
|
||||
{
|
||||
u8 const data = ((m_command & CMD) == (CMD_XFR_PAD & CMD)) ? 0 : m_fifo.dequeue();
|
||||
|
||||
LOGMASKED(LOG_STATE, "transfer out: data 0x%02x\n", data);
|
||||
m_state = XFR_OUT_NEXT;
|
||||
|
||||
// assert data and ACK
|
||||
scsi_bus->data_w(scsi_refid, data);
|
||||
scsi_bus->ctrl_w(scsi_refid, S_ACK, S_ACK);
|
||||
}
|
||||
else
|
||||
delay = -1;
|
||||
break;
|
||||
case XFR_OUT_NEXT:
|
||||
if (!(scsi_bus->ctrl_r() & S_REQ))
|
||||
{
|
||||
LOGMASKED(LOG_STATE, "transfer out: data accepted\n");
|
||||
if (m_command & TRBE)
|
||||
{
|
||||
if (!--m_count)
|
||||
{
|
||||
m_status |= TRBZ;
|
||||
m_state = XFR_INFO_DONE;
|
||||
}
|
||||
else
|
||||
m_state = XFR_OUT_REQ;
|
||||
}
|
||||
else
|
||||
m_state = XFR_INFO_DONE;
|
||||
|
||||
// clear data and ACK
|
||||
scsi_bus->data_w(scsi_refid, 0);
|
||||
scsi_bus->ctrl_w(scsi_refid, 0, S_ACK);
|
||||
}
|
||||
break;
|
||||
case XFR_OUT_REQ:
|
||||
LOGMASKED(LOG_STATE, "transfer out: waiting for REQ\n");
|
||||
if (scsi_bus->ctrl_r() & S_REQ)
|
||||
m_state = XFR_OUT;
|
||||
break;
|
||||
case XFR_INFO_DONE:
|
||||
LOGMASKED(LOG_STATE, "transfer: complete\n");
|
||||
m_state = COMPLETE;
|
||||
break;
|
||||
|
||||
case BUS_RESET:
|
||||
LOGMASKED(LOG_STATE, "bus reset: asserted\n");
|
||||
m_int_req[1] |= SRST;
|
||||
m_status &= ~(INIT | TARG);
|
||||
|
||||
m_state = BUS_RESET_DONE;
|
||||
delay = m_rst_time;
|
||||
|
||||
// clear data and assert RST
|
||||
scsi_bus->data_w(scsi_refid, 0);
|
||||
scsi_bus->ctrl_w(scsi_refid, S_RST, S_ALL);
|
||||
break;
|
||||
case BUS_RESET_DONE:
|
||||
LOGMASKED(LOG_STATE, "bus reset: complete\n");
|
||||
m_state = COMPLETE;
|
||||
|
||||
// clear RST
|
||||
scsi_bus->ctrl_w(scsi_refid, 0, S_RST);
|
||||
break;
|
||||
|
||||
case COMPLETE:
|
||||
LOGMASKED(LOG_STATE, "function complete\n");
|
||||
m_int_req[1] |= FNC;
|
||||
m_state = IDLE;
|
||||
break;
|
||||
}
|
||||
|
||||
return delay;
|
||||
}
|
||||
|
||||
void cxd1185_device::scsi_ctrl_changed()
|
||||
{
|
||||
u32 const ctrl = scsi_bus->ctrl_r();
|
||||
|
||||
if ((ctrl & S_BSY) && !(ctrl & S_SEL))
|
||||
LOGMASKED(LOG_SCSI, "scsi_ctrl_changed 0x%x phase %s%s%s\n", ctrl, nscsi_phase[ctrl & S_PHASE_MASK],
|
||||
ctrl & S_REQ ? " REQ" : "", ctrl & S_ACK ? " ACK" : "");
|
||||
else if (ctrl & S_BSY)
|
||||
LOGMASKED(LOG_SCSI, "scsi_ctrl_changed 0x%x arbitration/selection\n", ctrl);
|
||||
else if (ctrl & S_RST)
|
||||
LOGMASKED(LOG_SCSI, "scsi_ctrl_changed 0x%x BUS RESET\n", ctrl);
|
||||
else
|
||||
LOGMASKED(LOG_SCSI, "scsi_ctrl_changed 0x%x BUS FREE\n", ctrl);
|
||||
|
||||
if (ctrl & S_RST)
|
||||
{
|
||||
m_int_req[1] |= SRST;
|
||||
m_status &= ~(INIT | TARG);
|
||||
|
||||
// clear data and ctrl
|
||||
scsi_bus->data_w(scsi_refid, 0);
|
||||
scsi_bus->ctrl_w(scsi_refid, 0, S_ALL);
|
||||
}
|
||||
else if ((m_status & (TARG | INIT)) == INIT)
|
||||
{
|
||||
|
||||
if ((m_scsi_ctrl_state & S_BSY) && !(ctrl & S_BSY))
|
||||
{
|
||||
LOGMASKED(LOG_SCSI, "target disconnected\n");
|
||||
|
||||
m_status &= ~INIT;
|
||||
m_int_req[1] |= DCNT;
|
||||
}
|
||||
else if ((ctrl ^ m_scsi_ctrl_state) & S_PHASE_MASK)
|
||||
{
|
||||
if (ctrl & S_REQ)
|
||||
{
|
||||
LOGMASKED(LOG_SCSI, "target changed phase\n");
|
||||
|
||||
m_int_req[1] |= PHC;
|
||||
if (ctrl & S_MSG)
|
||||
m_int_req[1] |= RMSG;
|
||||
}
|
||||
else
|
||||
// ignore until req asserted
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if ((m_status & (TARG | INIT)) == TARG)
|
||||
{
|
||||
if (!(m_scsi_ctrl_state & S_ATN) && (ctrl & S_ATN))
|
||||
{
|
||||
LOGMASKED(LOG_SCSI, "initiator asserted attention\n");
|
||||
|
||||
m_int_req[1] |= DATN;
|
||||
}
|
||||
}
|
||||
|
||||
// record state
|
||||
m_scsi_ctrl_state = ctrl;
|
||||
|
||||
int_check();
|
||||
}
|
||||
|
||||
void cxd1185_device::int_check()
|
||||
{
|
||||
bool irq_asserted = false;
|
||||
|
||||
// update mirq
|
||||
if (m_int_req[0] || m_int_req[1])
|
||||
{
|
||||
m_status |= MIRQ;
|
||||
|
||||
irq_asserted = (m_int_req[0] & m_int_auth[0]) || (m_int_req[1] & m_int_auth[1]);
|
||||
}
|
||||
else
|
||||
m_status &= ~MIRQ;
|
||||
|
||||
// update irq line
|
||||
if (m_irq_asserted != irq_asserted)
|
||||
{
|
||||
LOGMASKED(LOG_INT, "irq_check interrupt %s\n", irq_asserted ? "asserted" : "cleared");
|
||||
|
||||
m_irq_asserted = irq_asserted;
|
||||
m_irq_out_cb((m_environ & SIRM) ? !m_irq_asserted : m_irq_asserted);
|
||||
}
|
||||
}
|
||||
|
||||
void cxd1185_device::set_drq(bool asserted)
|
||||
{
|
||||
if (m_drq_asserted != asserted)
|
||||
{
|
||||
LOGMASKED(LOG_DMA, "set_drq %s\n", asserted ? "asserted" : "deasserted");
|
||||
m_drq_asserted = asserted;
|
||||
m_drq_out_cb(m_drq_asserted);
|
||||
}
|
||||
}
|
||||
|
||||
u8 cxd1185_device::dma_r()
|
||||
{
|
||||
u8 const data = m_fifo.dequeue();
|
||||
|
||||
LOGMASKED(LOG_DMA, "dma_r 0x%02x\n", data);
|
||||
|
||||
if (m_fifo.empty())
|
||||
{
|
||||
set_drq(false);
|
||||
|
||||
if (m_count)
|
||||
m_state_timer->adjust(attotime::zero);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void cxd1185_device::dma_w(u8 data)
|
||||
{
|
||||
LOGMASKED(LOG_DMA, "dma_w 0x%02x\n", data);
|
||||
|
||||
m_fifo.enqueue(data);
|
||||
|
||||
if (m_fifo.full() || m_fifo.queue_length() >= m_count)
|
||||
{
|
||||
set_drq(false);
|
||||
|
||||
if (m_count)
|
||||
m_state_timer->adjust(attotime::zero);
|
||||
}
|
||||
}
|
||||
|
||||
void cxd1185_device::port_w(u8 data)
|
||||
{
|
||||
u8 const mask = ~(PCN | ((m_ioport & PCN) >> 4));
|
||||
|
||||
LOGMASKED(LOG_GENERAL, "port_w 0x%02x mask 0x%02x\n", data, mask);
|
||||
|
||||
m_ioport &= ~mask;
|
||||
m_ioport |= data & mask;
|
||||
}
|
249
src/devices/machine/cxd1185.h
Normal file
249
src/devices/machine/cxd1185.h
Normal file
@ -0,0 +1,249 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Patrick Mackinlay
|
||||
|
||||
#ifndef MAME_MACHINE_CXD1185_H
|
||||
#define MAME_MACHINE_CXD1185_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "machine/nscsi_bus.h"
|
||||
|
||||
class cxd1185_device
|
||||
: public nscsi_device
|
||||
, public nscsi_slot_card_interface
|
||||
{
|
||||
public:
|
||||
cxd1185_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
|
||||
|
||||
// device configuration
|
||||
auto irq_out_cb() { return m_irq_out_cb.bind(); }
|
||||
auto drq_out_cb() { return m_drq_out_cb.bind(); }
|
||||
auto port_out_cb() { return m_port_out_cb.bind(); }
|
||||
|
||||
void map(address_map &map);
|
||||
|
||||
// dma and port handlers
|
||||
u8 dma_r();
|
||||
void dma_w(u8 data);
|
||||
void port_w(u8 data);
|
||||
|
||||
protected:
|
||||
// device_t overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
// ncsci_device overrides
|
||||
virtual void scsi_ctrl_changed() override;
|
||||
|
||||
// register handlers
|
||||
u8 status_r();
|
||||
u8 scsi_data_r();
|
||||
template <unsigned Register> u8 int_req_r();
|
||||
u8 scsi_ctrl_monitor_r();
|
||||
u8 fifo_status_r();
|
||||
u8 scsi_id_r() { return m_scsi_id; }
|
||||
template <unsigned Byte> u8 count_r() { return u8(m_count >> (Byte * 8)); }
|
||||
template <unsigned Register> u8 int_auth_r() { return m_int_auth[Register]; }
|
||||
u8 mode_r() { return m_mode; }
|
||||
u8 sync_ctrl_r() { return m_sync_ctrl; }
|
||||
u8 scsi_ctrl_r() { return m_scsi_ctrl; }
|
||||
u8 ioport_r() { return m_ioport; }
|
||||
|
||||
void command_w(u8 data);
|
||||
void scsi_data_w(u8 data);
|
||||
void environ_w(u8 data);
|
||||
void timer_w(u8 data);
|
||||
void scsi_id_w(u8 data) { m_scsi_id = data; }
|
||||
template <unsigned Byte> void count_w(u8 data) { m_count &= ~(0xffU << (Byte * 8)); m_count |= u32(data) << (Byte * 8); }
|
||||
template <unsigned Register> void int_auth_w(u8 data);
|
||||
void mode_w(u8 data) { m_mode = data; }
|
||||
void sync_ctrl_w(u8 data) { m_sync_ctrl = data; }
|
||||
void scsi_ctrl_w(u8 data);
|
||||
void ioport_w(u8 data);
|
||||
|
||||
// state machine
|
||||
void state_timer(void *ptr, s32 param);
|
||||
int state_step();
|
||||
|
||||
// other logic
|
||||
void reset_chip();
|
||||
void reset_fifo();
|
||||
void int_check();
|
||||
void set_drq(bool asserted);
|
||||
|
||||
private:
|
||||
devcb_write_line m_irq_out_cb;
|
||||
devcb_write_line m_drq_out_cb;
|
||||
devcb_write8 m_port_out_cb;
|
||||
|
||||
emu_timer *m_state_timer;
|
||||
enum state : unsigned
|
||||
{
|
||||
IDLE,
|
||||
|
||||
// arbitration
|
||||
ARB_BUS_FREE,
|
||||
ARB_START,
|
||||
ARB_EVALUATE,
|
||||
|
||||
// selection
|
||||
SEL_START,
|
||||
SEL_DELAY,
|
||||
SEL_WAIT_BSY,
|
||||
SEL_COMPLETE,
|
||||
|
||||
// information transfer
|
||||
XFR_INFO,
|
||||
XFR_IN,
|
||||
XFR_IN_NEXT,
|
||||
XFR_IN_REQ,
|
||||
XFR_IN_DRAIN,
|
||||
XFR_OUT,
|
||||
XFR_OUT_NEXT,
|
||||
XFR_OUT_REQ,
|
||||
XFR_INFO_DONE,
|
||||
|
||||
// scsi bus reset
|
||||
BUS_RESET,
|
||||
BUS_RESET_DONE,
|
||||
|
||||
COMPLETE,
|
||||
}
|
||||
m_state;
|
||||
|
||||
// internal state
|
||||
bool m_irq_asserted;
|
||||
bool m_drq_asserted;
|
||||
util::fifo <u8, 16> m_fifo;
|
||||
bool m_pio_data_mode;
|
||||
bool m_pio_ctrl_mode;
|
||||
u32 m_scsi_ctrl_state;
|
||||
|
||||
enum status_mask : u8
|
||||
{
|
||||
CIP = 0x01, // command in progress
|
||||
MIRQ = 0x02, // monitor irq
|
||||
TRBZ = 0x04, // transfer byte count zero
|
||||
TARG = 0x08, // target
|
||||
INIT = 0x10, // initiator
|
||||
|
||||
MDBP = 0x40, // monitor scsi bus DBP
|
||||
MRST = 0x80, // monitor scsi bus RST
|
||||
};
|
||||
enum command_mask : u8
|
||||
{
|
||||
CMD = 0x0f, // command code
|
||||
TRBE = 0x10, // transfer byte counter enable
|
||||
DMA = 0x20, // dma mode
|
||||
CAT = 0xc0, // command category
|
||||
|
||||
CMD_RESET = 0x01,
|
||||
CMD_SEL_ATN = 0x42,
|
||||
CMD_XFR_PAD = 0xc1,
|
||||
};
|
||||
enum int_req1 : u8
|
||||
{
|
||||
ARBF = 0x01, // arbitration fail
|
||||
SWOA = 0x02, // selection without atn
|
||||
SWA = 0x04, // selection with atn
|
||||
RSL = 0x08, // reselected
|
||||
STO = 0x10, // selection time over
|
||||
};
|
||||
enum int_req2 : u8
|
||||
{
|
||||
RMSG = 0x01, // req in message phase
|
||||
SPE = 0x02, // scsi bus parity error
|
||||
DPE = 0x04, // data bus parity error
|
||||
DATN = 0x08, // drive atn
|
||||
PHC = 0x10, // phase change
|
||||
SRST = 0x20, // scsi reset
|
||||
DCNT = 0x40, // disconnected
|
||||
FNC = 0x80, // function complete
|
||||
};
|
||||
enum fifo_status_mask : u8
|
||||
{
|
||||
FC = 0x0f, // fifo count
|
||||
FIF = 0x10, // fifo is full
|
||||
|
||||
FIE = 0x80, // fifo is empty
|
||||
};
|
||||
enum environ_mask : u8
|
||||
{
|
||||
FS0 = 0x01,
|
||||
FS1 = 0x02,
|
||||
FS = 0x03, // clock division ratio
|
||||
|
||||
SIRM = 0x10, // irq active low
|
||||
DPEN = 0x20, // data bus parity enable
|
||||
SDPM = 0x40, // data bus parity even
|
||||
DIFE = 0x80, // differential mode
|
||||
};
|
||||
enum scsi_ctrl_monitor_mask : u8
|
||||
{
|
||||
MATN = 0x01,
|
||||
MACK = 0x02,
|
||||
MREQ = 0x04,
|
||||
MIO = 0x08,
|
||||
MCD = 0x10,
|
||||
MMSG = 0x20,
|
||||
MSEL = 0x40,
|
||||
MBSY = 0x80,
|
||||
};
|
||||
enum scsi_id_mask : u8
|
||||
{
|
||||
OID = 0x07, // owner id
|
||||
SMOD = 0x10, // single initiator mode
|
||||
SID = 0xe0, // selecting id
|
||||
TID = 0xe0, // target id
|
||||
};
|
||||
enum mode_mask : u8
|
||||
{
|
||||
BDMA = 0x01, // burst dma mode
|
||||
SSPE = 0x04, // ignore selection scsi parity error
|
||||
SPHI = 0x08, // scsi phase change ignore
|
||||
TMSL = 0x10, // scsi reset timer enable
|
||||
HATN = 0x20, // halt on atn
|
||||
HSPE = 0x40, // halt on scsi parity error
|
||||
HDPE = 0x80, // halt on data bus parity error
|
||||
};
|
||||
enum sync_ctrl_mask : u8
|
||||
{
|
||||
TOF = 0x0f, // transfer offset
|
||||
TPD = 0xf0, // transfer cycle
|
||||
};
|
||||
enum io_port_mask : u8
|
||||
{
|
||||
PRT = 0x0f, // i/o port data
|
||||
PCN = 0xf0, // i/o port control
|
||||
};
|
||||
enum scsi_ctrl_mask : u8
|
||||
{
|
||||
AATN = 0x01,
|
||||
AACK = 0x02,
|
||||
AREQ = 0x04,
|
||||
AIO = 0x08,
|
||||
ACD = 0x10,
|
||||
AMSG = 0x20,
|
||||
ASEL = 0x40,
|
||||
ABSY = 0x80,
|
||||
};
|
||||
|
||||
// registers
|
||||
u8 m_status;
|
||||
u8 m_command;
|
||||
u8 m_int_req[2];
|
||||
u8 m_environ;
|
||||
unsigned m_sel_time;
|
||||
unsigned m_rst_time;
|
||||
u8 m_scsi_id;
|
||||
u8 m_int_auth[2];
|
||||
u8 m_mode;
|
||||
u32 m_count;
|
||||
u8 m_sync_ctrl;
|
||||
u8 m_scsi_ctrl;
|
||||
u8 m_ioport;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(CXD1185, cxd1185_device)
|
||||
|
||||
#endif // MAME_MACHINE_CXD1185_H
|
Loading…
Reference in New Issue
Block a user