summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/wd33c9x.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/wd33c9x.cpp')
-rw-r--r--src/devices/machine/wd33c9x.cpp1064
1 files changed, 532 insertions, 532 deletions
diff --git a/src/devices/machine/wd33c9x.cpp b/src/devices/machine/wd33c9x.cpp
index d425a9249b9..2ef063ad449 100644
--- a/src/devices/machine/wd33c9x.cpp
+++ b/src/devices/machine/wd33c9x.cpp
@@ -29,7 +29,8 @@
#define LOG_REGS (LOG_READS | LOG_WRITES)
#define LOG_ALL (LOG_REGS | LOG_COMMANDS | LOG_ERRORS | LOG_MISC | LOG_LINES | LOG_STATE | LOG_STEP)
-#define VERBOSE (0)
+#define VERBOSE (LOG_COMMANDS | LOG_ERRORS | LOG_STATE)
+#define LOG_OUTPUT_FUNC printf
#include "logmacro.h"
enum register_addresses_e : uint8_t {
@@ -278,27 +279,6 @@ enum : uint16_t {
INIT_CPT_RECV_BYTE_NACK
};
-const char *const wd33c9x_base_device::state_names[] = {
- "-",
- "IDLE",
- "FINISHED",
- "DISC_SEL_ARBITRATION",
- "INIT_MSG_WAIT_REQ",
- "INIT_XFR",
- "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_FUNCTION_COMPLETE",
- "INIT_XFR_BUS_COMPLETE",
- "INIT_XFR_WAIT_REQ",
- "INIT_CPT_RECV_BYTE_ACK",
- "INIT_CPT_RECV_WAIT_REQ",
- "INIT_CPT_RECV_BYTE_NACK",
-};
-
enum : uint16_t {
// Arbitration
ARB_WAIT_BUS_FREE = 1,
@@ -319,24 +299,6 @@ enum : uint16_t {
RECV_WAIT_REQ_0
};
-const char *const wd33c9x_base_device::substate_names[] = {
- "-",
- "ARB_WAIT_BUS_FREE",
- "ARB_CHECK_FREE",
- "ARB_EXAMINE_BUS",
- "ARB_ASSERT_SEL",
- "ARB_SET_DEST",
- "ARB_RELEASE_BUSY",
- "ARB_TIMEOUT_BUSY",
- "ARB_TIMEOUT_ABORT",
- "ARB_DESKEW_WAIT",
- "SEND_WAIT_SETTLE",
- "SEND_WAIT_REQ_0",
- "RECV_WAIT_REQ_1",
- "RECV_WAIT_SETTLE",
- "RECV_WAIT_REQ_0",
-};
-
enum : uint16_t {
STATE_MASK = 0x00ff,
SUB_SHIFT = 8,
@@ -348,8 +310,8 @@ enum : uint16_t {
// LIVE DEVICE
//**************************************************************************
-DEFINE_DEVICE_TYPE(WD33C92, wd33c92_device, "wd33c92", "Western Digital WD33C92 SCSI Controller")
-DEFINE_DEVICE_TYPE(WD33C93, wd33c93_device, "wd33c93", "Western Digital WD33C93 SCSI Controller")
+DEFINE_DEVICE_TYPE(WD33C92, wd33c92_device, "wd33c92", "Western Digital WD33C92 SCSI Controller")
+DEFINE_DEVICE_TYPE(WD33C93N, wd33c93n_device, "wd33c93", "Western Digital WD33C93 SCSI Controller")
DEFINE_DEVICE_TYPE(WD33C93A, wd33c93a_device, "wd33c93a", "Western Digital WD33C93A SCSI Controller")
DEFINE_DEVICE_TYPE(WD33C93B, wd33c93b_device, "wd33c93b", "Western Digital WD33C93B SCSI Controller")
@@ -362,10 +324,10 @@ wd33c9x_base_device::wd33c9x_base_device(const machine_config &mconfig, device_t
, m_addr{ 0 }
, m_regs{ 0 }
, m_command_length{ 0 }
- , m_last_message{ 0 }
, m_scsi_state{ IDLE }
, m_mode{ MODE_D }
, m_xfr_phase{ 0 }
+ , m_step_count{ 0 }
, m_transfer_count{ 0 }
, m_data_fifo{ 0 }
, m_data_fifo_pos{ 0 }
@@ -393,10 +355,10 @@ void wd33c9x_base_device::device_start()
save_item(NAME(m_addr));
save_item(NAME(m_regs));
save_item(NAME(m_command_length));
- save_item(NAME(m_last_message));
save_item(NAME(m_mode));
save_item(NAME(m_scsi_state));
save_item(NAME(m_xfr_phase));
+ save_item(NAME(m_step_count));
save_item(NAME(m_transfer_count));
save_item(NAME(m_data_fifo));
save_item(NAME(m_data_fifo_pos));
@@ -422,10 +384,10 @@ void wd33c9x_base_device::device_reset()
m_regs[reg] = (QUEUE_TAG <= reg && reg <= INVALID_1E) ? 0xff : 0;
}
m_command_length = 0;
- m_last_message = 0;
set_scsi_state(IDLE);
m_mode = MODE_D;
m_xfr_phase = 0;
+ m_step_count = 0;
m_transfer_count = 0;
data_fifo_reset();
irq_fifo_reset();
@@ -470,10 +432,10 @@ void wd33c9x_base_device::scsi_ctrl_changed()
// dir_r
//-------------------------------------------------
-uint8_t wd33c9x_base_device::dir_r(offs_t offset)
+READ8_MEMBER(wd33c9x_base_device::dir_r)
{
m_addr = offset & REGS_MASK;
- return indir_reg_r();
+ return indir_reg_r(space, 0, mem_mask);
}
@@ -481,10 +443,10 @@ uint8_t wd33c9x_base_device::dir_r(offs_t offset)
// dir_w
//-------------------------------------------------
-void wd33c9x_base_device::dir_w(offs_t offset, uint8_t data)
+WRITE8_MEMBER(wd33c9x_base_device::dir_w)
{
m_addr = offset & REGS_MASK;
- indir_reg_w(data);
+ indir_reg_w(space, 0, data, mem_mask);
}
@@ -492,15 +454,15 @@ void wd33c9x_base_device::dir_w(offs_t offset, uint8_t data)
// indir_r
//-------------------------------------------------
-uint8_t wd33c9x_base_device::indir_r(offs_t offset)
+READ8_MEMBER(wd33c9x_base_device::indir_r)
{
switch (offset) {
case 0:
- return indir_addr_r();
+ return indir_addr_r(space, 0, mem_mask);
case 1:
- return indir_reg_r();
+ return indir_reg_r(space, 0, mem_mask);
default:
- LOGMASKED(LOG_READS | LOG_ERRORS, "Read from invalid offset %d\n", offset);
+ LOGMASKED(LOG_READS | LOG_ERRORS, "%s: Read from invalid offset %d\n", shortname(), offset);
break;
}
return 0;
@@ -511,17 +473,17 @@ uint8_t wd33c9x_base_device::indir_r(offs_t offset)
// indir_w
//-------------------------------------------------
-void wd33c9x_base_device::indir_w(offs_t offset, uint8_t data)
+WRITE8_MEMBER(wd33c9x_base_device::indir_w)
{
switch (offset) {
case 0:
- indir_addr_w(data);
+ indir_addr_w(space, 0, data, mem_mask);
break;
case 1:
- indir_reg_w(data);
+ indir_reg_w(space, 0, data, mem_mask);
break;
default:
- LOGMASKED(LOG_WRITES | LOG_ERRORS, "Write to invalid offset %d (data=%02x)\n", offset, data);
+ LOGMASKED(LOG_WRITES | LOG_ERRORS, "%s: Write to invalid offset %d (data=%02x)\n", shortname(), offset, data);
break;
}
}
@@ -531,10 +493,13 @@ void wd33c9x_base_device::indir_w(offs_t offset, uint8_t data)
// indir_addr_r
//-------------------------------------------------
-uint8_t wd33c9x_base_device::indir_addr_r()
+READ8_MEMBER(wd33c9x_base_device::indir_addr_r)
{
- // Trick to push the interrupt flag after the fifo is empty to help cps3
- return m_regs[AUXILIARY_STATUS] & 0x01 ? m_regs[AUXILIARY_STATUS] & 0x7f : m_regs[AUXILIARY_STATUS];
+ if (offset != 0) {
+ fatalerror("%s: Read from invalid address offset %d\n", shortname(), offset);
+ }
+ step(false);
+ return m_regs[AUXILIARY_STATUS];
}
@@ -542,8 +507,11 @@ uint8_t wd33c9x_base_device::indir_addr_r()
// indir_addr_w
//-------------------------------------------------
-void wd33c9x_base_device::indir_addr_w(uint8_t data)
+WRITE8_MEMBER(wd33c9x_base_device::indir_addr_w)
{
+ if (offset != 0) {
+ fatalerror("%s: Write to invalid address offset %d (data=%02x)\n", shortname(), offset, data);
+ }
m_addr = data & REGS_MASK;
}
@@ -552,11 +520,15 @@ void wd33c9x_base_device::indir_addr_w(uint8_t data)
// indir_reg_r
//-------------------------------------------------
-uint8_t wd33c9x_base_device::indir_reg_r()
+READ8_MEMBER(wd33c9x_base_device::indir_reg_r)
{
+ if (offset != 0) {
+ fatalerror("%s: Read from invalid indirect register offset %d\n", shortname(), offset);
+ }
+
uint8_t ret;
switch (m_addr) {
- case DATA: {
+ case DATA:
if (!(m_regs[AUXILIARY_STATUS] & AUXILIARY_STATUS_DBR)) {
// The processor, except in one case, should only
// access the Data Register when the DBR bit in the
@@ -567,14 +539,9 @@ uint8_t wd33c9x_base_device::indir_reg_r()
// Data Register.
fatalerror("%s: The host should never access the data register without DBR set.\n", shortname());
}
- bool was_full = data_fifo_full();
ret = data_fifo_pop();
- if (data_fifo_empty())
- m_regs[AUXILIARY_STATUS] &= ~AUXILIARY_STATUS_DBR;
- if (was_full)
- step(false);
+ m_regs[AUXILIARY_STATUS] &= ~AUXILIARY_STATUS_DBR;
break;
- }
default:
if (m_addr == OWN_ID) {
@@ -604,8 +571,12 @@ uint8_t wd33c9x_base_device::indir_reg_r()
// indir_reg_w
//-------------------------------------------------
-void wd33c9x_base_device::indir_reg_w(uint8_t data)
+WRITE8_MEMBER(wd33c9x_base_device::indir_reg_w)
{
+ if (offset != 0) {
+ fatalerror("%s: Write to invalid indirect register offset %d (data=%02x)\n", shortname(), offset, data);
+ }
+
switch (m_addr) {
case SCSI_STATUS:
case QUEUE_TAG: // Only for 92/93 and 93A
@@ -614,7 +585,7 @@ void wd33c9x_base_device::indir_reg_w(uint8_t data)
case INVALID_1D:
case INVALID_1E:
case AUXILIARY_STATUS:
- LOGMASKED(LOG_WRITES | LOG_ERRORS, "Write to read-only register address %d (data=%02x)\n", m_addr, data);
+ LOGMASKED(LOG_WRITES | LOG_ERRORS, "%s: Write to read-only register address %d (data=%02x)\n", shortname(), m_addr, data);
break;
case COMMAND: {
@@ -666,7 +637,7 @@ void wd33c9x_base_device::indir_reg_w(uint8_t data)
WRITE_LINE_MEMBER(wd33c9x_base_device::reset_w)
{
if (state) {
- LOGMASKED(LOG_LINES, "Reset via MR line\n");
+ LOGMASKED(LOG_LINES, "%s: Reset via MR line\n", shortname());
device_reset();
}
}
@@ -724,7 +695,7 @@ void wd33c9x_base_device::start_command()
switch (cc) {
case COMMAND_CC_RESET:
- LOGMASKED(LOG_COMMANDS, "Reset Command\n");
+ LOGMASKED(LOG_COMMANDS, "%s: Reset Command\n", shortname());
scsi_bus->ctrl_w(scsi_refid, 0, S_ALL);
scsi_bus->ctrl_wait(scsi_refid, S_SEL|S_BSY|S_RST, S_ALL);
m_regs[OWN_ID] = m_command_length;
@@ -738,18 +709,17 @@ void wd33c9x_base_device::start_command()
set_scsi_state(FINISHED);
irq_fifo_push((m_regs[OWN_ID] & OWN_ID_EAF) ? SCSI_STATUS_RESET_EAF : SCSI_STATUS_RESET);
scsi_id = (m_regs[OWN_ID] & OWN_ID_SCSI_ID);
- step(false);
break;
case COMMAND_CC_ABORT:
- LOGMASKED(LOG_COMMANDS, "Abort Command\n");
+ LOGMASKED(LOG_COMMANDS, "%s: Abort Command\n", shortname());
set_scsi_state(FINISHED);
// FIXME
irq_fifo_push((m_regs[OWN_ID] & OWN_ID_EAF) ? SCSI_STATUS_RESET_EAF : SCSI_STATUS_RESET);
break;
case COMMAND_CC_ASSERT_ATN:
- LOGMASKED(LOG_COMMANDS, "Assert ATN Command\n");
+ LOGMASKED(LOG_COMMANDS, "%s: Assert ATN Command\n", shortname());
if (m_mode != MODE_I) {
fatalerror("%s: ASSERT_ATN command only valid in the Initiator state.", shortname());
}
@@ -757,7 +727,7 @@ void wd33c9x_base_device::start_command()
return;
case COMMAND_CC_NEGATE_ACK:
- LOGMASKED(LOG_COMMANDS, "Negate ACK Command\n");
+ LOGMASKED(LOG_COMMANDS, "%s: Negate ACK Command\n", shortname());
// FIXME - This is causing problems, so ignore for now.
//if (m_mode != MODE_I) {
// fatalerror("NEGATE_ACK command only valid in the Initiator state.");
@@ -766,27 +736,26 @@ void wd33c9x_base_device::start_command()
return;
case COMMAND_CC_DISCONNECT:
- LOGMASKED(LOG_COMMANDS, "Disconnect Command\n");
+ LOGMASKED(LOG_COMMANDS, "%s: Disconnect Command\n", shortname());
scsi_bus->ctrl_w(scsi_refid, 0, S_ALL);
scsi_bus->ctrl_wait(scsi_refid, S_SEL|S_BSY|S_RST, S_ALL);
m_mode = MODE_D;
- set_scsi_state(IDLE);
- m_regs[AUXILIARY_STATUS] &= ~(AUXILIARY_STATUS_CIP | AUXILIARY_STATUS_BSY);
+ set_scsi_state(FINISHED);
+ irq_fifo_push(SCSI_STATUS_DISCONNECT);
break;
case COMMAND_CC_SELECT:
case COMMAND_CC_SELECT_ATN:
- LOGMASKED(LOG_COMMANDS, "%s Command\n", select_strings[cc - COMMAND_CC_SELECT_ATN]);
+ LOGMASKED(LOG_COMMANDS, "%s: %s Command\n", shortname(), select_strings[cc - COMMAND_CC_SELECT_ATN]);
if (m_mode != MODE_D) {
fatalerror("Select commands only valid in the Disconnected state.");
}
set_scsi_state((ARB_WAIT_BUS_FREE << SUB_SHIFT) | DISC_SEL_ARBITRATION);
- step(false);
break;
case COMMAND_CC_SELECT_TRANSFER:
case COMMAND_CC_SELECT_ATN_TRANSFER:
- LOGMASKED(LOG_COMMANDS, "%s Command\n", select_strings[cc - COMMAND_CC_SELECT_ATN]);
+ LOGMASKED(LOG_COMMANDS, "%s: %s Command\n", shortname(), select_strings[cc - COMMAND_CC_SELECT_ATN]);
if (m_mode == MODE_D) {
set_scsi_state((ARB_WAIT_BUS_FREE << SUB_SHIFT) | DISC_SEL_ARBITRATION);
m_regs[COMMAND_PHASE] = COMMAND_PHASE_ZERO;
@@ -799,11 +768,10 @@ void wd33c9x_base_device::start_command()
}
set_command_length(cc);
load_transfer_count();
- step(false);
break;
case COMMAND_CC_TRANSFER_INFO:
- LOGMASKED(LOG_COMMANDS, "Transfer Info Command\n");
+ LOGMASKED(LOG_COMMANDS, "%s: Transfer Info Command\n", shortname());
if (m_mode != MODE_I) {
fatalerror("%s: TRANSFER_INFO command only valid in the Initiator state.", shortname());
}
@@ -819,6 +787,8 @@ void wd33c9x_base_device::start_command()
fatalerror("%s: Unimplemented command: 0x%02x", shortname(), cc);
break;
}
+
+ delay(1);
}
@@ -840,533 +810,563 @@ static const char * phase_strings[8] = {
void wd33c9x_base_device::step(bool timeout)
{
+ if (++m_step_count > 1) {
+ return;
+ }
+
const uint8_t cc = (m_regs[COMMAND] & COMMAND_CC);
const bool sat = (cc == COMMAND_CC_SELECT_TRANSFER || cc == COMMAND_CC_SELECT_ATN_TRANSFER);
- const uint32_t ctrl = scsi_bus->ctrl_r();
- const uint32_t data = scsi_bus->data_r();
-
- LOGMASKED(LOG_STEP,
- "%s: step - PHASE:%s BSY:%x SEL:%x REQ:%x ACK:%x ATN:%x RST:%x DATA:%02x (%s.%s) %s\n",
- shortname(),
- phase_strings[ctrl & S_PHASE_MASK],
- (ctrl & S_BSY) ? 1 : 0,
- (ctrl & S_SEL) ? 1 : 0,
- (ctrl & S_REQ) ? 1 : 0,
- (ctrl & S_ACK) ? 1 : 0,
- (ctrl & S_ATN) ? 1 : 0,
- (ctrl & S_RST) ? 1 : 0,
- data,
- state_names[m_scsi_state & STATE_MASK], substate_names[m_scsi_state >> SUB_SHIFT],
- (timeout) ? "timeout" : "change"
- );
-
- if (m_mode == MODE_I) {
- if (ctrl & S_BSY) {
- if (ctrl & S_REQ) {
- uint8_t xfr_phase = (ctrl & S_PHASE_MASK);
- switch (m_scsi_state) {
- case DISC_SEL_ARBITRATION:
- m_xfr_phase = xfr_phase;
- break;
+ uint32_t cycles = 0;
+ do {
+ const uint32_t ctrl = scsi_bus->ctrl_r();
+ const uint32_t data = scsi_bus->data_r();
+
+ m_step_count = 1;
+
+ LOGMASKED(LOG_STEP,
+ "%s: step - PHASE:%s BSY:%x SEL:%x REQ:%x ACK:%x ATN:%x RST:%x DATA:%x (%d.%d) %s\n",
+ shortname(),
+ phase_strings[ctrl & S_PHASE_MASK],
+ (ctrl & S_BSY) ? 1 : 0,
+ (ctrl & S_SEL) ? 1 : 0,
+ (ctrl & S_REQ) ? 1 : 0,
+ (ctrl & S_ACK) ? 1 : 0,
+ (ctrl & S_ATN) ? 1 : 0,
+ (ctrl & S_RST) ? 1 : 0,
+ data,
+ m_scsi_state & STATE_MASK, m_scsi_state >> SUB_SHIFT,
+ (timeout) ? "timeout" : "change"
+ );
- case INIT_XFR_WAIT_REQ:
- break;
+ if (m_mode == MODE_I) {
+ if (ctrl & S_BSY) {
+ if (ctrl & S_REQ) {
+ uint8_t xfr_phase = (ctrl & S_PHASE_MASK);
+ switch (m_scsi_state) {
+ case DISC_SEL_ARBITRATION:
+ m_xfr_phase = xfr_phase;
+ break;
- default:
- if (m_xfr_phase != xfr_phase) {
- fatalerror("%s: Unexpected phase change during state.\n", shortname());
+ case INIT_XFR_WAIT_REQ:
+ break;
+
+ default:
+ if (m_xfr_phase != xfr_phase) {
+ fatalerror("%s: Unexpected phase change during state.\n", shortname());
+ }
+ break;
}
- break;
}
}
- } else {
- LOGMASKED(LOG_STATE, "Target disconnected\n");
- if (sat) {
- switch (m_regs[COMMAND_PHASE]) {
- case COMMAND_PHASE_DISCONNECT_MESSAGE:
- set_scsi_state(FINISHED);
- m_regs[COMMAND_PHASE] = COMMAND_PHASE_DISCONNECTED;
- break;
-
- case COMMAND_PHASE_COMMAND_COMPLETE:
- if (m_regs[CONTROL] & CONTROL_EDI) {
+ else {
+ LOGMASKED(LOG_STATE, "%s: Target disconnected\n", shortname());
+ if (sat) {
+ switch (m_regs[COMMAND_PHASE]) {
+ case COMMAND_PHASE_DISCONNECT_MESSAGE:
set_scsi_state(FINISHED);
- irq_fifo_push(SCSI_STATUS_SELECT_TRANSFER_SUCCESS);
- } else {
- // Makes very little sense, but the previous code did it and warzard seems to need it - XXX
- m_regs[CONTROL] |= CONTROL_EDI;
- }
- break;
+ m_regs[COMMAND_PHASE] = COMMAND_PHASE_DISCONNECTED;
+ break;
- default:
- fatalerror("%s: Unhandled command phase during Select-and-Transfer disconnect.\n", shortname());
- break;
+ case COMMAND_PHASE_COMMAND_COMPLETE:
+ if (m_regs[CONTROL] & CONTROL_EDI) {
+ set_scsi_state(FINISHED);
+ irq_fifo_push(SCSI_STATUS_SELECT_TRANSFER_SUCCESS);
+ }
+ break;
+
+ default:
+ fatalerror("%s: Unhandled command phase during Select-and-Transfer disconnect.\n", shortname());
+ break;
+ }
}
- } else {
- set_scsi_state(FINISHED);
- irq_fifo_push(SCSI_STATUS_DISCONNECT);
+ else {
+ set_scsi_state(FINISHED);
+ irq_fifo_push(SCSI_STATUS_DISCONNECT);
+ }
+ m_mode = MODE_D;
+ scsi_bus->ctrl_w(scsi_refid, 0, S_ALL);
+ scsi_bus->ctrl_wait(scsi_refid, S_SEL|S_BSY|S_RST, S_ALL);
+ continue;
}
- m_mode = MODE_D;
- scsi_bus->ctrl_w(scsi_refid, 0, S_ALL);
- scsi_bus->ctrl_wait(scsi_refid, S_SEL|S_BSY|S_RST, S_ALL);
}
- }
- switch (m_scsi_state & SUB_MASK ? m_scsi_state & SUB_MASK : m_scsi_state & STATE_MASK) {
- case IDLE:
- break;
+ switch (m_scsi_state & SUB_MASK ? m_scsi_state & SUB_MASK : m_scsi_state & STATE_MASK) {
+ case IDLE:
+ break;
- case FINISHED:
- set_scsi_state(IDLE);
- m_regs[AUXILIARY_STATUS] &= ~(AUXILIARY_STATUS_CIP | AUXILIARY_STATUS_BSY);
- update_irq();
- break;
+ case FINISHED:
+ set_scsi_state(IDLE);
+ m_regs[AUXILIARY_STATUS] &= ~(AUXILIARY_STATUS_CIP | AUXILIARY_STATUS_BSY);
+ update_irq();
+ break;
- case ARB_WAIT_BUS_FREE << SUB_SHIFT:
- if (!(ctrl & (S_BSY | S_SEL))) {
- set_scsi_state_sub(ARB_CHECK_FREE);
- delay(1);
- }
- break;
+ case ARB_WAIT_BUS_FREE << SUB_SHIFT:
+ if (timeout) {
+ if (!(ctrl & (S_BSY | S_SEL))) {
+ set_scsi_state_sub(ARB_CHECK_FREE);
+ }
+ cycles = 1;
+ }
+ break;
- case ARB_CHECK_FREE << SUB_SHIFT:
- if (ctrl & (S_BSY | S_SEL)) {
- set_scsi_state_sub(ARB_CHECK_FREE);
+ case ARB_CHECK_FREE << SUB_SHIFT:
+ if (timeout) {
+ uint8_t next_state;
+ if (ctrl & (S_BSY | S_SEL)) {
+ next_state = ARB_WAIT_BUS_FREE;
+ cycles = 1;
+ }
+ else {
+ scsi_bus->data_w(scsi_refid, 1 << scsi_id);
+ scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY);
+ next_state = ARB_EXAMINE_BUS;
+ cycles = 1;
+ }
+ set_scsi_state_sub(next_state);
+ }
break;
- }
- if (timeout) {
- scsi_bus->data_w(scsi_refid, 1 << scsi_id);
- scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY);
- set_scsi_state_sub(ARB_EXAMINE_BUS);
- delay(1);
- }
- break;
- case ARB_EXAMINE_BUS << SUB_SHIFT:
- if (timeout) {
- if (ctrl & S_SEL) {
- scsi_bus->ctrl_w(scsi_refid, 0, S_BSY);
- scsi_bus->data_w(scsi_refid, 0);
- set_scsi_state_sub(ARB_WAIT_BUS_FREE);
- } else {
- int win;
- for (win = 7; win >=0 && !(data & (1 << win)); win--);
- if (win == scsi_id) {
- scsi_bus->ctrl_w(scsi_refid, S_SEL, S_SEL);
- set_scsi_state_sub(ARB_ASSERT_SEL);
- delay(1);
- } else {
+ case ARB_EXAMINE_BUS << SUB_SHIFT:
+ if (timeout) {
+ if (ctrl & S_SEL) {
+ scsi_bus->ctrl_w(scsi_refid, 0, S_BSY);
scsi_bus->data_w(scsi_refid, 0);
- scsi_bus->ctrl_w(scsi_refid, 0, S_ALL);
- set_scsi_state_sub(ARB_CHECK_FREE);
+ set_scsi_state_sub(ARB_WAIT_BUS_FREE);
}
+ else {
+ int win;
+ for (win = 7; win >=0 && !(data & (1 << win)); win--) {};
+ if (win == scsi_id) {
+ scsi_bus->ctrl_w(scsi_refid, S_SEL, S_SEL);
+ set_scsi_state_sub(ARB_ASSERT_SEL);
+ }
+ else {
+ scsi_bus->data_w(scsi_refid, 0);
+ scsi_bus->ctrl_w(scsi_refid, 0, S_ALL);
+ }
+ }
+ cycles = 1;
}
- }
- break;
+ break;
- case ARB_ASSERT_SEL << SUB_SHIFT:
- if (timeout) {
- scsi_bus->data_w(scsi_refid, (1 << scsi_id) | (1 << (m_regs[DESTINATION_ID] & DESTINATION_ID_DI)));
- set_scsi_state_sub(ARB_SET_DEST);
- delay(1);
- }
- break;
+ case ARB_ASSERT_SEL << SUB_SHIFT:
+ if (timeout) {
+ scsi_bus->data_w(scsi_refid, (1 << scsi_id) | (1 << (m_regs[DESTINATION_ID] & DESTINATION_ID_DI)));
+ set_scsi_state_sub(ARB_SET_DEST);
+ cycles = 1;
+ }
+ break;
- case ARB_SET_DEST << SUB_SHIFT:
- if (timeout) {
- scsi_bus->ctrl_w(scsi_refid, (cc == COMMAND_CC_SELECT_ATN || cc == COMMAND_CC_SELECT_ATN_TRANSFER) ? S_ATN : 0, S_ATN | S_BSY);
- set_scsi_state_sub(ARB_RELEASE_BUSY);
- delay(1);
- }
- break;
+ case ARB_SET_DEST << SUB_SHIFT:
+ if (timeout) {
+ scsi_bus->ctrl_w(scsi_refid, (cc == COMMAND_CC_SELECT_ATN || cc == COMMAND_CC_SELECT_ATN_TRANSFER) ? S_ATN : 0, S_ATN | S_BSY);
+ set_scsi_state_sub(ARB_RELEASE_BUSY);
+ cycles = 1;
+ }
+ break;
- case ARB_RELEASE_BUSY << SUB_SHIFT:
- if (timeout) {
- if (ctrl & S_BSY) {
- set_scsi_state_sub(ARB_DESKEW_WAIT);
- if (cc == COMMAND_CC_RESELECT) {
- scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY);
+ case ARB_RELEASE_BUSY << SUB_SHIFT:
+ if (timeout) {
+ if (ctrl & S_BSY) {
+ set_scsi_state_sub(ARB_DESKEW_WAIT);
+ if (cc == COMMAND_CC_RESELECT) {
+ scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY);
+ }
+ cycles = 1;
+ }
+ else {
+ set_scsi_state_sub(ARB_TIMEOUT_BUSY);
+ cycles = 1;
}
- delay(1);
- } else {
- set_scsi_state_sub(ARB_TIMEOUT_BUSY);
- delay(1); // Should be the select timeout...
}
- }
- break;
-
- case ARB_DESKEW_WAIT << SUB_SHIFT:
- if (timeout) {
- scsi_bus->data_w(scsi_refid, 0);
- scsi_bus->ctrl_w(scsi_refid, 0, S_SEL);
- m_mode = (cc == COMMAND_CC_RESELECT) ? MODE_T : MODE_I;
- set_scsi_state_sub(0);
- step(true);
- }
- break;
+ break;
- case ARB_TIMEOUT_BUSY << SUB_SHIFT:
- if (timeout) {
- scsi_bus->data_w(scsi_refid, 0);
- set_scsi_state_sub(ARB_TIMEOUT_ABORT);
- delay(1000);
- } else if (ctrl & S_BSY) {
- set_scsi_state_sub(ARB_DESKEW_WAIT);
- if (cc == COMMAND_CC_RESELECT) {
- scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY);
+ case ARB_DESKEW_WAIT << SUB_SHIFT:
+ if (timeout) {
+ scsi_bus->data_w(scsi_refid, 0);
+ scsi_bus->ctrl_w(scsi_refid, 0, S_SEL);
+ m_mode = (cc == COMMAND_CC_RESELECT) ? MODE_T : MODE_I;
+ set_scsi_state_sub(0);
+ ++m_step_count;
}
- delay(1);
- }
- break;
+ break;
- case ARB_TIMEOUT_ABORT << SUB_SHIFT:
- if (timeout) {
- if (ctrl & S_BSY) {
+ case ARB_TIMEOUT_BUSY << SUB_SHIFT:
+ if (timeout) {
+ scsi_bus->data_w(scsi_refid, 0);
+ set_scsi_state_sub(ARB_TIMEOUT_ABORT);
+ cycles = 1000;
+ }
+ else if (ctrl & S_BSY) {
set_scsi_state_sub(ARB_DESKEW_WAIT);
if (cc == COMMAND_CC_RESELECT) {
scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY);
}
- delay(1);
- } else {
- scsi_bus->ctrl_w(scsi_refid, 0, S_ALL);
- scsi_bus->ctrl_wait(scsi_refid, S_SEL|S_BSY|S_RST, S_ALL);
- m_regs[AUXILIARY_STATUS] &= ~(AUXILIARY_STATUS_CIP | AUXILIARY_STATUS_BSY);
- m_mode = MODE_D;
- set_scsi_state(IDLE);
- irq_fifo_push(SCSI_STATUS_SELECTION_TIMEOUT);
- update_irq();
+ cycles = 1;
}
- }
- break;
+ break;
- case SEND_WAIT_SETTLE << SUB_SHIFT:
- if (timeout) {
- set_scsi_state_sub(SEND_WAIT_REQ_0);
- step(false);
- }
- break;
+ case ARB_TIMEOUT_ABORT << SUB_SHIFT:
+ if (timeout) {
+ if (ctrl & S_BSY) {
+ set_scsi_state_sub(ARB_DESKEW_WAIT);
+ if (cc == COMMAND_CC_RESELECT) {
+ scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY);
+ }
+ cycles = 1;
+ }
+ else {
+ scsi_bus->ctrl_w(scsi_refid, 0, S_ALL);
+ scsi_bus->ctrl_wait(scsi_refid, S_SEL|S_BSY|S_RST, S_ALL);
+ m_regs[AUXILIARY_STATUS] &= ~(AUXILIARY_STATUS_CIP | AUXILIARY_STATUS_BSY);
+ m_mode = MODE_D;
+ set_scsi_state(IDLE);
+ irq_fifo_push(SCSI_STATUS_SELECTION_TIMEOUT);
+ update_irq();
+ }
+ }
+ break;
- case SEND_WAIT_REQ_0 << SUB_SHIFT:
- if (!(ctrl & S_REQ)) {
- set_scsi_state_sub(0);
- scsi_bus->data_w(scsi_refid, 0);
- scsi_bus->ctrl_w(scsi_refid, 0, S_ACK);
- if (sat) {
- switch (m_xfr_phase) {
- case S_PHASE_COMMAND:
- ++m_regs[COMMAND_PHASE];
- break;
+ case SEND_WAIT_SETTLE << SUB_SHIFT:
+ if (timeout) {
+ set_scsi_state_sub(SEND_WAIT_REQ_0);
+ ++m_step_count;
+ }
+ break;
+
+ case SEND_WAIT_REQ_0 << SUB_SHIFT:
+ if (!(ctrl & S_REQ)) {
+ set_scsi_state_sub(0);
+ scsi_bus->data_w(scsi_refid, 0);
+ scsi_bus->ctrl_w(scsi_refid, 0, S_ACK);
+ if (sat) {
+ switch (m_xfr_phase) {
+ case S_PHASE_COMMAND:
+ ++m_regs[COMMAND_PHASE];
+ break;
+ }
}
+ ++m_step_count;
}
- step(false);
- }
- break;
+ break;
- case RECV_WAIT_REQ_1 << SUB_SHIFT:
- if (ctrl & S_REQ) {
- set_scsi_state_sub(RECV_WAIT_SETTLE);
- delay(1);
- }
- break;
+ case RECV_WAIT_REQ_1 << SUB_SHIFT:
+ if (ctrl & S_REQ) {
+ set_scsi_state_sub(RECV_WAIT_SETTLE);
+ cycles = 1;
+ }
+ break;
- case RECV_WAIT_SETTLE << SUB_SHIFT:
- if (timeout) {
- if (sat) {
- switch (m_xfr_phase) {
- case S_PHASE_DATA_IN:
+ case RECV_WAIT_SETTLE << SUB_SHIFT:
+ if (timeout) {
+ if (sat) {
+ switch (m_xfr_phase) {
+ case S_PHASE_DATA_IN:
+ data_fifo_push(data);
+ if ((m_regs[CONTROL] & CONTROL_DM) != CONTROL_DM_POLLED) {
+ set_drq();
+ }
+ else {
+ decrement_transfer_count();
+ m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_DBR;
+ }
+ break;
+
+ case S_PHASE_STATUS:
+ m_regs[TARGET_LUN] = data;
+ m_regs[COMMAND_PHASE] = COMMAND_PHASE_STATUS_RECEIVED;
+ break;
+
+ case S_PHASE_MSG_IN:
+ data_fifo_push(data);
+ break;
+
+ default:
+ fatalerror("%s: Unexpected phase in RECV_WAIT_SETTLE.\n", shortname());
+ break;
+ }
+ }
+ else {
data_fifo_push(data);
- if ((m_regs[CONTROL] & CONTROL_DM) != CONTROL_DM_POLLED) {
+ if (m_xfr_phase == S_PHASE_DATA_IN && (m_regs[CONTROL] & CONTROL_DM) != CONTROL_DM_POLLED) {
set_drq();
- } else {
+ }
+ else {
decrement_transfer_count();
m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_DBR;
}
- break;
-
- case S_PHASE_STATUS:
- m_regs[TARGET_LUN] = data;
- m_regs[COMMAND_PHASE] = COMMAND_PHASE_STATUS_RECEIVED;
- break;
-
- case S_PHASE_MSG_IN:
- m_last_message = data;
- break;
-
- default:
- fatalerror("%s: Unexpected phase in RECV_WAIT_SETTLE.\n", shortname());
- break;
- }
- } else {
- data_fifo_push(data);
- if (m_xfr_phase == S_PHASE_DATA_IN && (m_regs[CONTROL] & CONTROL_DM) != CONTROL_DM_POLLED) {
- set_drq();
- } else {
- decrement_transfer_count();
- m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_DBR;
}
+ set_scsi_state_sub(RECV_WAIT_REQ_0);
+ scsi_bus->ctrl_w(scsi_refid, S_ACK, S_ACK);
+ ++m_step_count;
}
- set_scsi_state_sub(RECV_WAIT_REQ_0);
- scsi_bus->ctrl_w(scsi_refid, S_ACK, S_ACK);
- step(false);
- }
- break;
-
- case RECV_WAIT_REQ_0 << SUB_SHIFT:
- if (!(ctrl & S_REQ)) {
- set_scsi_state_sub(0);
- step(false);
- }
- break;
+ break;
- case DISC_SEL_ARBITRATION:
- scsi_bus->ctrl_wait(scsi_refid, S_REQ, S_REQ);
- if (cc == COMMAND_CC_SELECT || cc == COMMAND_CC_SELECT_ATN) {
- set_scsi_state(FINISHED);
- irq_fifo_push(SCSI_STATUS_SELECT_SUCCESS);
- if (ctrl & S_REQ) {
- irq_fifo_push(SCSI_STATUS_REQ | m_xfr_phase);
+ case RECV_WAIT_REQ_0 << SUB_SHIFT:
+ if (!(ctrl & S_REQ)) {
+ set_scsi_state_sub(0);
+ ++m_step_count;
}
- } else {
- if(cc == COMMAND_CC_SELECT_TRANSFER) {
- m_regs[COMMAND_PHASE] = COMMAND_PHASE_CP_BYTES_0;
- std::string cmd;
- for (uint8_t i = 0; i < m_command_length; ++i) {
- const uint8_t command_byte = m_regs[CDB_1 + i];
- cmd += util::string_format(" %02x", command_byte);
- data_fifo_push(command_byte);
+ break;
+
+ case DISC_SEL_ARBITRATION:
+ scsi_bus->ctrl_wait(scsi_refid, S_REQ, S_REQ);
+ if (cc == COMMAND_CC_SELECT || cc == COMMAND_CC_SELECT_ATN) {
+ set_scsi_state(FINISHED);
+ irq_fifo_push(SCSI_STATUS_SELECT_SUCCESS);
+ if (ctrl & S_REQ) {
+ irq_fifo_push(SCSI_STATUS_REQ | m_xfr_phase);
}
- LOGMASKED(LOG_COMMANDS, "Sending command:%s (%d)\n", cmd, m_transfer_count);
- } else
+ }
+ else {
+ set_scsi_state(INIT_XFR);
m_regs[COMMAND_PHASE] = COMMAND_PHASE_SELECTED;
- set_scsi_state(INIT_XFR);
- }
- step(false);
- break;
+ }
+ ++m_step_count;
+ break;
- case INIT_XFR:
- if (ctrl & S_REQ) {
- switch (m_xfr_phase) {
- case S_PHASE_DATA_OUT:
- if ((m_regs[CONTROL] & CONTROL_DM) != CONTROL_DM_POLLED) {
- if(!data_fifo_full() && m_transfer_count > 0)
- set_drq();
- }
- if (!data_fifo_empty()) {
- set_scsi_state(INIT_XFR_WAIT_REQ);
- delay(send_byte());
- } else if ((m_regs[CONTROL] & CONTROL_DM) == CONTROL_DM_POLLED) {
- m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_DBR;
- }
- break;
+ case INIT_XFR:
+ if (ctrl & S_REQ) {
+ switch (m_xfr_phase) {
+ case S_PHASE_DATA_OUT:
+ if ((m_regs[CONTROL] & CONTROL_DM) != CONTROL_DM_POLLED) {
+ while (!data_fifo_full() && m_transfer_count > 0) {
+ set_drq();
+ }
+ }
+ if (!data_fifo_empty()) {
+ set_scsi_state(INIT_XFR_WAIT_REQ);
+ cycles = send_byte();
+ }
+ else if ((m_regs[CONTROL] & CONTROL_DM) == CONTROL_DM_POLLED) {
+ m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_DBR;
+ }
+ break;
- case S_PHASE_COMMAND:
- if (!data_fifo_empty()) {
- uint32_t mask;
- if (sat) {
- mask = 0;
- } else {
+ case S_PHASE_COMMAND:
+ if (!data_fifo_empty()) {
+ uint32_t mask;
+ if (sat) {
+ mask = 0;
+ }
+ else {
+ m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_DBR;
+ mask = (m_transfer_count == 0 && m_data_fifo_size == 1) ? S_ATN : 0;
+ }
+ set_scsi_state(INIT_XFR_WAIT_REQ);
+ cycles = send_byte(0, mask);
+ }
+ else if (!sat) {
m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_DBR;
- mask = (m_transfer_count == 0 && m_data_fifo_size == 1) ? S_ATN : 0;
}
- set_scsi_state(INIT_XFR_WAIT_REQ);
- delay(send_byte(0, mask));
- } else if (!sat) {
- m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_DBR;
- }
- break;
+ break;
- case S_PHASE_MSG_OUT:
- if (sat) {
- data_fifo_push(get_msg_out());
- }
- if (!data_fifo_empty()) {
- uint32_t mask;
+ case S_PHASE_MSG_OUT:
if (sat) {
- mask = S_ATN;
- } else {
+ data_fifo_push(get_msg_out());
+ }
+ if (!data_fifo_empty()) {
+ uint32_t mask;
+ if (sat) {
+ mask = S_ATN;
+ }
+ else {
+ m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_DBR;
+ mask = (m_transfer_count == 0 && m_data_fifo_size == 1) ? S_ATN : 0;
+ }
+ set_scsi_state(INIT_XFR_WAIT_REQ);
+ cycles = send_byte(0, mask);
+ }
+ else if (!sat) {
m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_DBR;
- mask = (m_transfer_count == 0 && m_data_fifo_size == 1) ? S_ATN : 0;
}
- set_scsi_state(INIT_XFR_WAIT_REQ);
- delay(send_byte(0, mask));
- } else if (!sat) {
- m_regs[AUXILIARY_STATUS] |= AUXILIARY_STATUS_DBR;
- }
- break;
+ break;
- case S_PHASE_DATA_IN:
- case S_PHASE_STATUS:
- case S_PHASE_MSG_IN:
- if (!data_fifo_full()) {
- // if it's the last message byte, ACK remains asserted, terminate with function_complete()
- //state = (m_xfr_phase == S_PHASE_MSG_IN && (!dma_command || tcounter == 1)) ? INIT_XFR_RECV_BYTE_NACK : INIT_XFR_RECV_BYTE_ACK;
- scsi_bus->ctrl_wait(scsi_refid, S_REQ, S_REQ);
- set_scsi_state((RECV_WAIT_REQ_1 << SUB_SHIFT) | INIT_XFR_RECV_BYTE_ACK);
- step(false);
- }
- break;
+ case S_PHASE_DATA_IN:
+ case S_PHASE_STATUS:
+ case S_PHASE_MSG_IN:
+ if (!data_fifo_full()) {
+ // if it's the last message byte, ACK remains asserted, terminate with function_complete()
+ //state = (m_xfr_phase == S_PHASE_MSG_IN && (!dma_command || tcounter == 1)) ? INIT_XFR_RECV_BYTE_NACK : INIT_XFR_RECV_BYTE_ACK;
+ scsi_bus->ctrl_wait(scsi_refid, S_REQ, S_REQ);
+ set_scsi_state((RECV_WAIT_REQ_1 << SUB_SHIFT) | INIT_XFR_RECV_BYTE_ACK);
+ if (ctrl & S_REQ) {
+ ++m_step_count;
+ }
+ }
+ break;
- default:
- fatalerror("%s: Invalid phase during INIT_XFR.\n", shortname());
- break;
+ default:
+ fatalerror("%s: Invalid phase during INIT_XFR.\n", shortname());
+ break;
+ }
}
- }
- break;
+ break;
- case INIT_XFR_WAIT_REQ:
- if (ctrl & S_REQ) {
- uint16_t next_state = m_scsi_state;
+ case INIT_XFR_WAIT_REQ:
+ if (ctrl & S_REQ) {
+ uint16_t next_state = m_scsi_state;
- const uint8_t xfr_phase = (ctrl & S_PHASE_MASK);
+ const uint8_t xfr_phase = (ctrl & S_PHASE_MASK);
- switch ((m_xfr_phase << 3) | xfr_phase) {
- case ((S_PHASE_MSG_OUT << 3) | S_PHASE_MSG_OUT):
- case ((S_PHASE_COMMAND << 3) | S_PHASE_COMMAND):
- case ((S_PHASE_MSG_IN << 3) | S_PHASE_MSG_IN):
- next_state = INIT_XFR;
- break;
+ switch ((m_xfr_phase << 3) | xfr_phase) {
+ case ((S_PHASE_MSG_OUT << 3) | S_PHASE_MSG_OUT):
+ case ((S_PHASE_COMMAND << 3) | S_PHASE_COMMAND):
+ case ((S_PHASE_MSG_IN << 3) | S_PHASE_MSG_IN):
+ next_state = INIT_XFR;
+ break;
- case ((S_PHASE_DATA_IN << 3) | S_PHASE_DATA_IN):
- case ((S_PHASE_DATA_OUT << 3) | S_PHASE_DATA_OUT):
- if (sat || cc == COMMAND_CC_TRANSFER_INFO) {
- if (m_transfer_count > 0 || (m_xfr_phase == S_PHASE_DATA_OUT && !data_fifo_empty())) {
- next_state = INIT_XFR;
+ case ((S_PHASE_DATA_IN << 3) | S_PHASE_DATA_IN):
+ case ((S_PHASE_DATA_OUT << 3) | S_PHASE_DATA_OUT):
+ if (sat || cc == COMMAND_CC_TRANSFER_INFO) {
+ if (m_transfer_count > 0 || (m_xfr_phase == S_PHASE_DATA_OUT && !data_fifo_empty())) {
+ next_state = INIT_XFR;
+ }
+ else {
+ next_state = FINISHED;
+ uint8_t scsi_status;
+ if (sat) {
+ m_regs[COMMAND_PHASE] = COMMAND_PHASE_TRANSFER_COUNT;
+ scsi_status = SCSI_STATUS_UNEXPECTED_PHASE;
+ }
+ else {
+ scsi_status = SCSI_STATUS_TRANSFER_SUCCESS;
+ }
+ irq_fifo_push(scsi_status | m_xfr_phase);
+ }
}
else {
+ fatalerror("%s: Unhandled command in data phase.\n", shortname());
next_state = FINISHED;
- uint8_t scsi_status;
- if (sat) {
- m_regs[COMMAND_PHASE] = COMMAND_PHASE_TRANSFER_COUNT;
- scsi_status = SCSI_STATUS_UNEXPECTED_PHASE;
- }
- else {
- scsi_status = SCSI_STATUS_TRANSFER_SUCCESS;
+ }
+ break;
+
+ case ((S_PHASE_MSG_OUT << 3) | S_PHASE_COMMAND):
+ case ((S_PHASE_COMMAND << 3) | S_PHASE_DATA_OUT):
+ case ((S_PHASE_COMMAND << 3) | S_PHASE_DATA_IN):
+ case ((S_PHASE_COMMAND << 3) | S_PHASE_STATUS):
+ case ((S_PHASE_COMMAND << 3) | S_PHASE_MSG_IN):
+ case ((S_PHASE_DATA_OUT << 3) | S_PHASE_STATUS):
+ case ((S_PHASE_DATA_IN << 3) | S_PHASE_STATUS):
+ case ((S_PHASE_STATUS << 3) | S_PHASE_MSG_IN):
+ if (!(m_xfr_phase & 1) && !data_fifo_empty()) {
+ fatalerror("%s: Data FIFO is not empty on phase transition.\n", shortname());
+ }
+
+ if (sat) {
+ switch (xfr_phase) {
+ case S_PHASE_MSG_OUT:
+ next_state = INIT_XFR;
+ break;
+
+ case S_PHASE_COMMAND:
+ next_state = INIT_XFR;
+ m_regs[COMMAND_PHASE] = COMMAND_PHASE_CP_BYTES_0;
+ LOGMASKED(LOG_COMMANDS, "%s: Sending Command:", shortname());
+ for (uint8_t i = 0; i < m_command_length; ++i) {
+ const uint8_t command_byte = m_regs[CDB_1 + i];
+ LOGMASKED(LOG_COMMANDS, " %02x", command_byte);
+ data_fifo_push(command_byte);
+ }
+ LOGMASKED(LOG_COMMANDS, " (%d)\n", m_transfer_count);
+ break;
+
+ case S_PHASE_DATA_OUT:
+ case S_PHASE_DATA_IN:
+ next_state = INIT_XFR;
+ break;
+
+ case S_PHASE_STATUS:
+ next_state = INIT_XFR;
+ m_regs[COMMAND_PHASE] = COMMAND_PHASE_RECEIVE_STATUS;
+ break;
+
+ case S_PHASE_MSG_IN:
+ next_state = INIT_XFR;
+ break;
+
+ default:
+ fatalerror("%s: Unhandled phase in Select-w/Atn-and-Transfer.\n", shortname());
+ next_state = FINISHED;
+ break;
}
- irq_fifo_push(scsi_status | m_xfr_phase);
}
- }
- else {
- fatalerror("%s: Unhandled command in data phase.\n", shortname());
+ else if (cc == COMMAND_CC_TRANSFER_INFO) {
+ next_state = FINISHED;
+ irq_fifo_push(SCSI_STATUS_TRANSFER_SUCCESS | xfr_phase);
+ }
+ else {
+ fatalerror("%s: Unhandled command in data phase.\n", shortname());
+ next_state = FINISHED;
+ }
+ break;
+
+ default:
+ fatalerror("%s: Unhandled phase transition in INIT_XFR_WAIT_REQ.\n", shortname());
next_state = FINISHED;
+ break;
}
- break;
- case ((S_PHASE_MSG_OUT << 3) | S_PHASE_COMMAND):
- case ((S_PHASE_COMMAND << 3) | S_PHASE_DATA_OUT):
- case ((S_PHASE_COMMAND << 3) | S_PHASE_DATA_IN):
- case ((S_PHASE_COMMAND << 3) | S_PHASE_STATUS):
- case ((S_PHASE_COMMAND << 3) | S_PHASE_MSG_IN):
- case ((S_PHASE_DATA_OUT << 3) | S_PHASE_STATUS):
- case ((S_PHASE_DATA_IN << 3) | S_PHASE_STATUS):
- case ((S_PHASE_STATUS << 3) | S_PHASE_MSG_IN):
- if (!(m_xfr_phase & 1) && !data_fifo_empty()) {
- fatalerror("%s: Data FIFO is not empty on phase transition.\n", shortname());
+ if (next_state != m_scsi_state) {
+ set_scsi_state(next_state);
+ ++m_step_count;
+ m_xfr_phase = xfr_phase;
}
+ }
+ break;
- if (sat) {
- switch (xfr_phase) {
- case S_PHASE_MSG_OUT:
- next_state = INIT_XFR;
- break;
-
- case S_PHASE_COMMAND: {
- next_state = INIT_XFR;
- m_regs[COMMAND_PHASE] = COMMAND_PHASE_CP_BYTES_0;
- std::string cmd;
- for (uint8_t i = 0; i < m_command_length; ++i) {
- const uint8_t command_byte = m_regs[CDB_1 + i];
- cmd += util::string_format(" %02x", command_byte);
- data_fifo_push(command_byte);
- }
- LOGMASKED(LOG_COMMANDS, "Sending command:%s (%d)\n", cmd, m_transfer_count);
+ case INIT_XFR_RECV_BYTE_ACK:
+ if (sat && m_xfr_phase == S_PHASE_MSG_IN) {
+ const uint8_t msg = data_fifo_pop();
+ if (m_regs[COMMAND_PHASE] <= COMMAND_PHASE_CP_BYTES_C) {
+ switch (msg) {
+ case SM_SAVE_DATA_PTR:
+ set_scsi_state(FINISHED);
+ irq_fifo_push(SCSI_STATUS_SAVE_DATA_POINTERS);
+ m_regs[COMMAND_PHASE] = COMMAND_PHASE_SAVE_DATA_POINTER;
break;
- }
- case S_PHASE_DATA_OUT:
- case S_PHASE_DATA_IN:
- next_state = INIT_XFR;
+ case SM_DISCONNECT:
+ m_regs[COMMAND_PHASE] = COMMAND_PHASE_DISCONNECT_MESSAGE;
break;
- case S_PHASE_STATUS:
- next_state = INIT_XFR;
- m_regs[COMMAND_PHASE] = COMMAND_PHASE_RECEIVE_STATUS;
+ default:
+ fatalerror("%s: Unhandled MSG_IN.\n", shortname());
break;
-
- case S_PHASE_MSG_IN:
- next_state = INIT_XFR;
+ }
+ }
+ else if (m_regs[COMMAND_PHASE] < COMMAND_PHASE_COMMAND_COMPLETE) {
+ switch (msg) {
+ case SM_COMMAND_COMPLETE:
+ set_scsi_state(FINISHED);
+ irq_fifo_push(SCSI_STATUS_SELECT_TRANSFER_SUCCESS);
+ m_regs[COMMAND_PHASE] = COMMAND_PHASE_COMMAND_COMPLETE;
break;
-
default:
- fatalerror("%s: Unhandled phase in Select-w/Atn-and-Transfer.\n", shortname());
- next_state = FINISHED;
+ fatalerror("%s: Unhandled MSG_IN.\n", shortname());
break;
}
}
- else if (cc == COMMAND_CC_TRANSFER_INFO) {
- next_state = FINISHED;
- irq_fifo_push(SCSI_STATUS_TRANSFER_SUCCESS | xfr_phase);
- }
- else {
- fatalerror("%s: Unhandled command in data phase.\n", shortname());
- next_state = FINISHED;
- }
- break;
-
- default:
- fatalerror("%s: Unhandled phase transition in INIT_XFR_WAIT_REQ.\n", shortname());
- next_state = FINISHED;
- break;
}
-
- if (next_state != m_scsi_state) {
- set_scsi_state(next_state);
- m_xfr_phase = xfr_phase;
- step(false);
+ else {
+ set_scsi_state(INIT_XFR_WAIT_REQ);
}
- }
- break;
+ scsi_bus->ctrl_w(scsi_refid, 0, S_ACK);
+ ++m_step_count;
+ break;
- case INIT_XFR_RECV_BYTE_ACK:
- if (sat && m_xfr_phase == S_PHASE_MSG_IN) {
- if (m_regs[COMMAND_PHASE] <= COMMAND_PHASE_CP_BYTES_C) {
- switch (m_last_message) {
- case SM_SAVE_DATA_PTR:
- set_scsi_state(FINISHED);
- irq_fifo_push(SCSI_STATUS_SAVE_DATA_POINTERS);
- m_regs[COMMAND_PHASE] = COMMAND_PHASE_SAVE_DATA_POINTER;
- break;
+ default:
+ fatalerror("%s: Unhandled state in step.\n", shortname());
+ break;
+ }
- case SM_DISCONNECT:
- m_regs[COMMAND_PHASE] = COMMAND_PHASE_DISCONNECT_MESSAGE;
- break;
+ timeout = false;
- default:
- fatalerror("%s: Unhandled MSG_IN %02x.\n", shortname(), m_last_message);
- break;
- }
- } else if (m_regs[COMMAND_PHASE] < COMMAND_PHASE_COMMAND_COMPLETE) {
- switch (m_last_message) {
- case SM_COMMAND_COMPLETE:
- set_scsi_state(FINISHED);
- irq_fifo_push(SCSI_STATUS_SELECT_TRANSFER_SUCCESS);
- m_regs[COMMAND_PHASE] = COMMAND_PHASE_COMMAND_COMPLETE;
- break;
- default:
- fatalerror("%s: Unhandled MSG_IN %02x.\n", shortname(), m_last_message);
- break;
- }
- }
- } else {
- set_scsi_state(INIT_XFR_WAIT_REQ);
- }
- scsi_bus->ctrl_w(scsi_refid, 0, S_ACK);
- step(false);
- break;
+ } while (--m_step_count);
- default:
- fatalerror("%s: Unhandled state in step.\n", shortname());
- break;
+ if (cycles) {
+ delay(cycles);
}
}
@@ -1390,7 +1390,7 @@ void wd33c9x_base_device::load_transfer_count()
m_transfer_count = 1;
}
}
- LOGMASKED(LOG_COMMANDS, "Transfer Count %d bytes\n", m_transfer_count);
+ LOGMASKED(LOG_COMMANDS, "%s: Transfer Count %d bytes\n", shortname(), m_transfer_count);
}
@@ -1499,9 +1499,7 @@ uint32_t wd33c9x_base_device::send_byte(const uint32_t value, const uint32_t mas
void wd33c9x_base_device::set_scsi_state(uint16_t state)
{
- LOGMASKED(LOG_STEP, "SCSI state change: %s.%s to %s.%s\n",
- state_names[m_scsi_state & STATE_MASK], substate_names[m_scsi_state >> SUB_SHIFT],
- state_names[state & STATE_MASK], substate_names[state >> SUB_SHIFT]);
+ LOGMASKED(LOG_STEP, "%s: SCSI state change: %x to %x\n", shortname(), m_scsi_state, state);
m_scsi_state = state;
}
@@ -1590,7 +1588,7 @@ void wd33c9x_base_device::update_irq()
{
if (m_regs[AUXILIARY_STATUS] & AUXILIARY_STATUS_INT) {
m_regs[AUXILIARY_STATUS] &= ~AUXILIARY_STATUS_INT;
- LOGMASKED(LOG_LINES, "Clearing IRQ\n");
+ LOGMASKED(LOG_LINES, "%s: Clearing IRQ\n", shortname());
m_irq_cb(CLEAR_LINE);
}
if (!irq_fifo_empty()) {
@@ -1614,7 +1612,7 @@ void wd33c9x_base_device::update_irq()
}
}
- LOGMASKED(LOG_LINES, "Asserting IRQ - SCSI Status (%02x)\n", m_regs[SCSI_STATUS]);
+ LOGMASKED(LOG_LINES, "%s: Asserting IRQ - SCSI Status (%02x)\n", shortname(), m_regs[SCSI_STATUS]);
m_irq_cb(ASSERT_LINE);
}
}
@@ -1627,7 +1625,7 @@ void wd33c9x_base_device::update_irq()
void wd33c9x_base_device::set_drq()
{
if (!m_drq_state) {
- LOGMASKED(LOG_LINES, "Asserting DRQ\n");
+ LOGMASKED(LOG_LINES, "%s: Asserting DRQ\n", shortname());
m_drq_state = true;
m_drq_cb(ASSERT_LINE);
}
@@ -1641,7 +1639,7 @@ void wd33c9x_base_device::set_drq()
void wd33c9x_base_device::clear_drq()
{
if (m_drq_state) {
- LOGMASKED(LOG_LINES, "Clearing DRQ\n");
+ LOGMASKED(LOG_LINES, "%s: Clearing DRQ\n", shortname());
m_drq_state = false;
m_drq_cb(CLEAR_LINE);
}
@@ -1680,13 +1678,15 @@ bool wd33c9x_base_device::set_command_length(const uint8_t cc)
if (eaf && (cc == COMMAND_CC_SELECT_TRANSFER || cc == COMMAND_CC_SELECT_ATN_TRANSFER)) {
m_command_length &= OWN_ID_CDB_SIZE;
ret = true;
- } else if (eaf && cc == COMMAND_CC_WAIT_SELECT_RECEIVE_DATA) {
+ }
+ else if (eaf && cc == COMMAND_CC_WAIT_SELECT_RECEIVE_DATA) {
m_command_length = 6;
m_regs[COMMAND_PHASE] = COMMAND_PHASE_CP_BYTES_1;
irq_fifo_push(SCSI_STATUS_NEED_COMMAND_SIZE);
update_irq();
ret = false;
- } else {
+ }
+ else {
switch (m_regs[CDB_1] >> 5) {
default:
case 0: m_command_length = 6; break;
@@ -1695,7 +1695,7 @@ bool wd33c9x_base_device::set_command_length(const uint8_t cc)
}
ret = true;
}
- LOGMASKED(LOG_COMMANDS, "SCSI Command Length %d bytes\n", m_command_length);
+ LOGMASKED(LOG_COMMANDS, "%s: SCSI Command Length %d bytes\n", shortname(), m_command_length);
return ret;
}
@@ -1715,8 +1715,8 @@ wd33c92_device::wd33c92_device(const machine_config &mconfig, const char *tag, d
{
}
-wd33c93_device::wd33c93_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : wd33c9x_base_device(mconfig, WD33C93, tag, owner, clock)
+wd33c93n_device::wd33c93n_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : wd33c9x_base_device(mconfig, WD33C93N, tag, owner, clock)
{
}