diff options
Diffstat (limited to 'src/devices/machine/mb87030.cpp')
-rw-r--r-- | src/devices/machine/mb87030.cpp | 380 |
1 files changed, 235 insertions, 145 deletions
diff --git a/src/devices/machine/mb87030.cpp b/src/devices/machine/mb87030.cpp index 25420dfad54..ad60af82e42 100644 --- a/src/devices/machine/mb87030.cpp +++ b/src/devices/machine/mb87030.cpp @@ -1,6 +1,12 @@ // license:BSD-3-Clause // copyright-holders:Sven Schnelle +/* + * The MB89351 and MB89352 are both based on the MB87030, with the main + * programmer-visible difference being an interrupt-driven option for the + * program transfer mode. +*/ + #include "emu.h" #include "mb87030.h" @@ -9,10 +15,24 @@ DEFINE_DEVICE_TYPE(MB87030, mb87030_device, "mb87030", "Fujitsu MB87030 SCSI controller") +DEFINE_DEVICE_TYPE(MB89351, mb89351_device, "mb89351", "Fujitsu MB89351 SCSI controller") +DEFINE_DEVICE_TYPE(MB89352, mb89352_device, "mb89352", "Fujitsu MB89352 SCSI controller") + +ALLOW_SAVE_TYPE(mb87030_device::State) mb87030_device::mb87030_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : mb87030_device(mconfig, MB87030, tag, owner, clock) { +} + +mb89351_device::mb89351_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + mb87030_device(mconfig, MB89351, tag, owner, clock) +{ +} + +mb89352_device::mb89352_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + mb87030_device(mconfig, MB89352, tag, owner, clock) +{ } @@ -20,7 +40,8 @@ mb87030_device::mb87030_device(const machine_config &mconfig, device_type type, nscsi_device(mconfig, type, tag, owner, clock), nscsi_slot_card_interface(mconfig, *this, DEVICE_SELF), m_irq_handler(*this), - m_dreq_handler(*this) + m_dreq_handler(*this), + m_irq_state(false) { } @@ -45,6 +66,46 @@ void mb87030_device::map(address_map &map) map(0x0f, 0x0f).rw(FUNC(mb87030_device::exbf_r), FUNC(mb87030_device::exbf_w)); } +void mb89351_device::map(address_map &map) +{ + map(0x00, 0x00).rw(FUNC(mb89351_device::bdid_r), FUNC(mb89351_device::bdid_w)); + map(0x01, 0x01).rw(FUNC(mb89351_device::sctl_r), FUNC(mb89351_device::sctl_w)); + map(0x02, 0x02).rw(FUNC(mb89351_device::scmd_r), FUNC(mb89351_device::scmd_w)); + // no TMOD + map(0x04, 0x04).rw(FUNC(mb89351_device::ints_r), FUNC(mb89351_device::ints_w)); + map(0x05, 0x05).rw(FUNC(mb89351_device::psns_r), FUNC(mb89351_device::sdgc_w)); + map(0x06, 0x06).r(FUNC(mb89351_device::ssts_r)); + map(0x07, 0x07).r(FUNC(mb89351_device::serr_r)); + map(0x08, 0x08).rw(FUNC(mb89351_device::pctl_r), FUNC(mb89351_device::pctl_w)); + map(0x09, 0x09).r(FUNC(mb89351_device::mbc_r)); + map(0x0a, 0x0a).rw(FUNC(mb89351_device::dreg_r), FUNC(mb89351_device::dreg_w)); + map(0x0b, 0x0b).rw(FUNC(mb89351_device::temp_r), FUNC(mb89351_device::temp_w)); + map(0x0c, 0x0c).rw(FUNC(mb89351_device::tch_r), FUNC(mb89351_device::tch_w)); + map(0x0d, 0x0d).rw(FUNC(mb89351_device::tcm_r), FUNC(mb89351_device::tcm_w)); + map(0x0e, 0x0e).rw(FUNC(mb89351_device::tcl_r), FUNC(mb89351_device::tcl_w)); + // no EXBF +} + +void mb89352_device::map(address_map &map) +{ + map(0x00, 0x00).rw(FUNC(mb89352_device::bdid_r), FUNC(mb89352_device::bdid_w)); + map(0x01, 0x01).rw(FUNC(mb89352_device::sctl_r), FUNC(mb89352_device::sctl_w)); + map(0x02, 0x02).rw(FUNC(mb89352_device::scmd_r), FUNC(mb89352_device::scmd_w)); + // no TMOD + map(0x04, 0x04).rw(FUNC(mb89352_device::ints_r), FUNC(mb89352_device::ints_w)); + map(0x05, 0x05).rw(FUNC(mb89352_device::psns_r), FUNC(mb89352_device::sdgc_w)); + map(0x06, 0x06).r(FUNC(mb89352_device::ssts_r)); + map(0x07, 0x07).r(FUNC(mb89352_device::serr_r)); + map(0x08, 0x08).rw(FUNC(mb89352_device::pctl_r), FUNC(mb89352_device::pctl_w)); + map(0x09, 0x09).r(FUNC(mb89352_device::mbc_r)); + map(0x0a, 0x0a).rw(FUNC(mb89352_device::dreg_r), FUNC(mb89352_device::dreg_w)); + map(0x0b, 0x0b).rw(FUNC(mb89352_device::temp_r), FUNC(mb89352_device::temp_w)); + map(0x0c, 0x0c).rw(FUNC(mb89352_device::tch_r), FUNC(mb89352_device::tch_w)); + map(0x0d, 0x0d).rw(FUNC(mb89352_device::tcm_r), FUNC(mb89352_device::tcm_w)); + map(0x0e, 0x0e).rw(FUNC(mb89352_device::tcl_r), FUNC(mb89352_device::tcl_w)); + // no EXBF +} + void mb87030_device::device_reset() { m_bdid = 0; @@ -64,6 +125,7 @@ void mb87030_device::device_reset() m_tc = 0; m_exbf = 0; m_fifo.clear(); + m_dreq_handler(false); scsi_bus->ctrl_wait(scsi_refid, S_SEL|S_BSY|S_RST, S_ALL); update_state(State::Idle, 0); scsi_set_ctrl(0, S_ALL); @@ -85,10 +147,10 @@ auto mb87030_device::get_state_name(State state) const return "ArbitrationWait"; case State::ArbitrationAssertSEL: return "ArbitrationAssertSEL"; - case State::ArbitrationDeAssertBSY: - return "ArbitrationDeAssertBSY"; case State::SelectionWaitBusFree: return "SelectionWaitBusFree"; + case State::SelectionAssertID: + return "SelectionAssertID"; case State::SelectionWaitBSY: return "SelectionWaitBSY"; case State::SelectionAssertSEL: @@ -101,16 +163,8 @@ auto mb87030_device::get_state_name(State state) const return "TransferSendAck"; case State::TransferSendData: return "TransferSendData"; - case State::TransferSendDataDMAReq: - return "TransferSendDataDMAReq"; - case State::TransferSendDataDMAResp: - return "TransferSendDataDMAResp"; case State::TransferRecvData: return "TransferRecvData"; - case State::TransferRecvDataDMAReq: - return "TransferRecvDataDMAReq"; - case State::TransferRecvDataDMAResp: - return "TransferRecvDataDMAResp"; case State::TransferWaitDeassertREQ: return "TransferWaitDeassertREQ"; @@ -122,8 +176,8 @@ auto mb87030_device::get_state_name(State state) const void mb87030_device::update_state(mb87030_device::State new_state, int delay, int timeout) { - LOG("new state: %s -> %s (delay %d, timeout %d)\n", get_state_name(m_state), - get_state_name(new_state), delay, timeout); + LOG("new state: %s -> %s (delay %d, timeout %d, %s)\n", get_state_name(m_state), + get_state_name(new_state), delay, timeout, machine().time().to_string()); m_state = new_state; if (delay) m_delay_timer->adjust(clocks_to_attotime(delay)); @@ -149,21 +203,13 @@ TIMER_CALLBACK_MEMBER(mb87030_device::delay_timeout) void mb87030_device::scsi_command_complete() { + LOG("%s\n", __FUNCTION__); m_ints |= INTS_COMMAND_COMPLETE; m_ssts &= ~(SSTS_SPC_BUSY|SSTS_XFER_IN_PROGRESS); update_ints(); update_state(State::Idle); } -void mb87030_device::scsi_disconnect_timeout() -{ - scsi_set_ctrl(0, S_ALL); - scsi_bus->data_w(scsi_refid, 0); - m_ints = INTS_SPC_TIMEOUT; - update_ints(); - update_state(State::Idle); -} - void mb87030_device::scsi_disconnect() { LOG("%s: m_tc %d\n", __FUNCTION__, m_tc); @@ -190,7 +236,7 @@ void mb87030_device::scsi_set_ctrl(uint32_t value, uint32_t mask) } } -uint32_t mb87030_device::scsi_get_ctrl(void) +uint32_t mb87030_device::scsi_get_ctrl() { if (m_sctl & SCTL_DIAG_MODE) { uint32_t ret = 0; @@ -227,13 +273,15 @@ void mb87030_device::step(bool timeout) timeout ? " timeout" : "", data, ctrl, m_tc); - if (m_sctl & SCTL_RESET_AND_DISABLE && m_state != State::Idle) { + if ((m_sctl & SCTL_RESET_AND_DISABLE) && m_state != State::Idle) { scsi_set_ctrl(0, S_ALL); + m_ssts &= ~SSTS_SPC_BUSY; update_state(State::Idle); return; } - if ((m_ssts & SSTS_INIT_CONNECTED) && !(ctrl & S_BSY)) { + // FIXME: bus free and disconnected interrupt logic is not correct + if ((m_ssts & SSTS_INIT_CONNECTED) && !(ctrl & S_BSY) && (m_state != State::SelectionAssertID) && (m_state != State::SelectionAssertSEL) && (m_state != State::SelectionWaitBSY)) { LOG("SCSI disconnect\n"); scsi_disconnect(); scsi_set_ctrl(0, S_ALL); @@ -250,12 +298,12 @@ void mb87030_device::step(bool timeout) case State::ArbitrationWaitBusFree: if (!(ctrl & (S_BSY|S_SEL))) update_state(State::ArbitrationAssertBSY, 1); - break; + case State::ArbitrationAssertBSY: scsi_set_ctrl(S_BSY, S_BSY); scsi_bus->data_w(scsi_refid, (1 << m_bdid)); - update_state(State::ArbitrationWait, 1); + update_state(State::ArbitrationWait, 32); break; case State::ArbitrationWait: @@ -263,7 +311,10 @@ void mb87030_device::step(bool timeout) LOG("check %d\n", id); if (data & id) { LOG("arbitration lost, winner %d\n", id); - scsi_disconnect_timeout(); + scsi_set_ctrl(0, S_BSY); + scsi_bus->data_w(scsi_refid, 0); + m_ssts &= ~SSTS_SPC_BUSY; + update_state(State::Idle); break; } } @@ -273,50 +324,57 @@ void mb87030_device::step(bool timeout) case State::ArbitrationAssertSEL: scsi_set_ctrl(S_SEL, S_SEL); - update_state(State::ArbitrationDeAssertBSY, 1); - break; - - case State::ArbitrationDeAssertBSY: - scsi_set_ctrl(0, S_BSY); - update_state(State::SelectionAssertSEL, 1); + update_state(State::SelectionAssertID, 10); break; case State::SelectionWaitBusFree: if (!(ctrl & (S_BSY|S_SEL))) - update_state(State::SelectionAssertSEL, 10); + update_state(State::SelectionAssertID, 10); break; - case State::SelectionAssertSEL: + case State::SelectionAssertID: + m_ssts |= SSTS_INIT_CONNECTED; + m_ssts &= ~SSTS_TARG_CONNECTED; scsi_bus->data_w(scsi_refid, m_temp); - scsi_set_ctrl(0, S_SEL); //XXX: needed? + update_state(State::SelectionAssertSEL, 10); + break; + + case State::SelectionAssertSEL: + // deassert BSY for arbitrating systems, assert SEL for non-arbitrating systems scsi_set_ctrl(S_SEL | (m_send_atn_during_selection ? S_ATN : 0), S_ATN|S_SEL|S_BSY); scsi_bus->ctrl_wait(scsi_refid, S_BSY, S_BSY); - update_state(State::SelectionWaitBSY, 0, m_tc / 8); + update_state(State::SelectionWaitBSY, 0, ((m_tc & ~0xff) + 15) * 2); break; case State::SelectionWaitBSY: - if (timeout) { + if (timeout || (m_ints & INTS_SPC_TIMEOUT)) { LOG("select timeout\n"); - scsi_disconnect_timeout(); + m_tc = 0; + m_ints = INTS_SPC_TIMEOUT; + update_ints(); break; } m_timer->reset(); if ((ctrl & (S_REQ|S_BSY|S_MSG|S_CTL|S_INP)) == S_BSY) update_state(State::Selection, 1); - break; case State::Selection: + // avoid duplicate command completion caused by deassertion of SEL + if (!(ctrl & S_SEL)) + break; + LOG("selection success\n"); scsi_set_ctrl(0, S_SEL); - m_ssts |= SSTS_INIT_CONNECTED|SSTS_XFER_IN_PROGRESS; - m_ssts &= ~(SSTS_TARG_CONNECTED|SSTS_SPC_BUSY); - update_ssts(); scsi_command_complete(); break; case State::TransferWaitReq: if (!m_tc && !(m_scmd & SCMD_TERM_MODE)) { + // transfer command completes only when fifo is empty + if (!m_fifo.empty()) + break; + LOG("TransferWaitReq: tc == 0\n"); scsi_bus->data_w(scsi_refid, 0); scsi_command_complete(); @@ -328,6 +386,7 @@ void mb87030_device::step(bool timeout) m_ints |= INTS_SERVICE_REQUIRED; m_ssts &= ~SSTS_SPC_BUSY; update_ints(); + update_state(State::Idle); break; } @@ -336,11 +395,10 @@ void mb87030_device::step(bool timeout) break; } - if (!m_dma_transfer || (m_scmd & SCMD_TERM_MODE)) { - update_state((ctrl & S_INP) ? State::TransferRecvData : State::TransferSendData, 1); - } else { - update_state((ctrl & S_INP) ? State::TransferRecvDataDMAReq : State::TransferSendDataDMAReq, 1); - } + if (m_dma_transfer && m_tc && !(ctrl & S_INP) && !m_fifo.full()) + m_dreq_handler(true); + + update_state((ctrl & S_INP) ? State::TransferRecvData : State::TransferSendData, 1); break; case State::TransferRecvData: @@ -352,53 +410,40 @@ void mb87030_device::step(bool timeout) if (!m_tc || m_fifo.full()) break; - m_bus_data = data; - update_state(State::TransferSendAck, 10); - break; + LOG("pushing read data: %02X (%d filled)\n", data, m_fifo.queue_length() + 1); + m_fifo.enqueue(data); + if (m_dma_transfer) + m_dreq_handler(true); - case State::TransferRecvDataDMAReq: - m_hdb = data; - m_hdb_loaded = true; - update_state(State::TransferRecvDataDMAResp, 10); - m_dreq_handler(true); - break; + if (m_sdgc & SDGC_XFER_ENABLE) { + m_serr |= SERR_XFER_OUT; + update_ints(); + } - case State::TransferRecvDataDMAResp: - if (m_hdb_loaded) - break; update_state(State::TransferSendAck, 10); - m_dreq_handler(false); break; case State::TransferSendData: + if (m_tc && m_fifo.empty() && (m_sdgc & SDGC_XFER_ENABLE)) { + m_serr |= SERR_XFER_OUT; + update_ints(); + break; + } + if (m_tc && !m_fifo.empty()) { - scsi_bus->data_w(scsi_refid, m_fifo.peek()); + LOG("pulling write data: %02X (%d left)\n", data, m_fifo.queue_length() - 1); + scsi_bus->data_w(scsi_refid, m_fifo.dequeue()); update_state(State::TransferSendAck, 10); break; } - if (!m_tc && (m_scmd & SCMD_TERM_MODE)) { + if (!m_tc && (m_scmd & SCMD_TERM_MODE)) { scsi_bus->data_w(scsi_refid, m_temp); update_state(State::TransferSendAck, 10); break; } break; - case State::TransferSendDataDMAReq: - m_hdb_loaded = false; - update_state(State::TransferSendDataDMAResp, 10); - m_dreq_handler(true); - break; - - case State::TransferSendDataDMAResp: - if (!m_hdb_loaded) - break; - m_hdb_loaded = false; - m_dreq_handler(false); - scsi_bus->data_w(scsi_refid, m_hdb); - update_state(State::TransferSendAck, 10); - break; - case State::TransferSendAck: if (!(m_scmd & SCMD_TERM_MODE) && !(ctrl & S_INP)) m_temp = data; @@ -415,17 +460,15 @@ void mb87030_device::step(bool timeout) case State::TransferDeassertACK: m_tc--; - if (!m_dma_transfer) { - if (!(ctrl & S_INP)) { - m_fifo.dequeue(); - } else { - LOG("pushing read data: %02X\n", m_bus_data); - m_fifo.enqueue(m_bus_data); - } - } update_state(State::TransferWaitReq, 10); scsi_bus->ctrl_wait(scsi_refid, S_REQ, S_REQ); - scsi_set_ctrl(0, S_ACK); + + // deassert ATN after last byte of message out phase + if (!m_tc && (ctrl & S_PHASE_MASK) == S_PHASE_MSG_OUT && m_send_atn_during_selection) + scsi_set_ctrl(0, S_ATN|S_ACK); + // deassert ACK except for last byte of message in phase + else if (m_tc || (ctrl & S_PHASE_MASK) != S_PHASE_MSG_IN) + scsi_set_ctrl(0, S_ACK); break; } @@ -433,10 +476,8 @@ void mb87030_device::step(bool timeout) void mb87030_device::device_start() { - m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mb87030_device::timeout), this)); - m_delay_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mb87030_device::delay_timeout), this)); - m_irq_handler.resolve_safe(); - m_dreq_handler.resolve_safe(); + m_timer = timer_alloc(FUNC(mb87030_device::timeout), this); + m_delay_timer = timer_alloc(FUNC(mb87030_device::delay_timeout), this); save_item(NAME(m_bdid)); save_item(NAME(m_sctl)); @@ -454,24 +495,23 @@ void mb87030_device::device_start() save_item(NAME(m_tcm)); save_item(NAME(m_tc)); save_item(NAME(m_exbf)); - save_item(NAME(m_hdb)); - save_item(NAME(m_hdb_loaded)); save_item(NAME(m_send_atn_during_selection)); // save_item(NAME(m_fifo)); save_item(NAME(m_scsi_phase)); save_item(NAME(m_scsi_ctrl)); save_item(NAME(m_dma_transfer)); - save_item(NAME(m_bus_data)); -// save_item(NAME(m_state)); + save_item(NAME(m_state)); + save_item(NAME(m_irq_state)); } void mb87030_device::scsi_ctrl_changed() { + LOG("%s: %02x\n", __FUNCTION__, scsi_bus->ctrl_r()); if (m_delay_timer->remaining() == attotime::never) step(false); } -WRITE_LINE_MEMBER(mb87030_device::reset_w) +void mb87030_device::reset_w(int state) { LOG("%s: %s\n", __FUNCTION__, state); if (state) @@ -498,42 +538,47 @@ void mb87030_device::update_ssts() void mb87030_device::update_ints() { - LOG("%s: %s\n", __FUNCTION__, (m_ints && (m_sctl & 1)) ? "true" : "false"); - m_irq_handler(m_ints && (m_sctl & 1));// || (m_ints & INTS_DISCONNECTED)); + bool const irq_state = (m_sctl & 1) && (m_ints || (m_serr & SERR_XFER_OUT)); + + if (irq_state != m_irq_state) { + m_irq_state = irq_state; + LOG("%s: %s\n", __FUNCTION__, m_irq_state ? "true" : "false"); + m_irq_handler(m_irq_state); + } } -READ8_MEMBER(mb87030_device::bdid_r) +uint8_t mb87030_device::bdid_r() { - LOG("%s %02X\n", __FUNCTION__, (1 << m_bdid)); + LOG("%s: %02X\n", __FUNCTION__, (1 << m_bdid)); return 1 << m_bdid; } -WRITE8_MEMBER(mb87030_device::bdid_w) +void mb87030_device::bdid_w(uint8_t data) { LOG("%s: %02X\n", __FUNCTION__, data); m_bdid = data & 0x7; } -READ8_MEMBER(mb87030_device::sctl_r) +uint8_t mb87030_device::sctl_r() { LOG("%s: %02X\n", __FUNCTION__, m_sctl); return m_sctl; } -WRITE8_MEMBER(mb87030_device::sctl_w) +void mb87030_device::sctl_w(uint8_t data) { LOG("%s: %02X\n", __FUNCTION__, data); m_sctl = data; update_ints(); } -READ8_MEMBER(mb87030_device::scmd_r) +uint8_t mb87030_device::scmd_r() { LOG("%s: %02X\n", __FUNCTION__, m_scmd); return m_scmd; } -WRITE8_MEMBER(mb87030_device::scmd_w) +void mb87030_device::scmd_w(uint8_t data) { LOG("%s: %02X\n", __FUNCTION__, data); m_scmd = data; @@ -541,10 +586,16 @@ WRITE8_MEMBER(mb87030_device::scmd_w) switch (m_scmd & SCMD_CMD_MASK) { case SCMD_CMD_BUS_RELEASE: LOG("%s: Bus release\n", __FUNCTION__); + m_send_atn_during_selection = false; + if (m_state == State::SelectionWaitBusFree) { + m_ssts &= ~(SSTS_INIT_CONNECTED|SSTS_TARG_CONNECTED|SSTS_SPC_BUSY|SSTS_XFER_IN_PROGRESS); + update_state(State::Idle); + } break; case SCMD_CMD_SELECT: LOG("%s: Select\n", __FUNCTION__); + m_ssts |= SSTS_SPC_BUSY; if (m_sctl & SCTL_ARBITRATION_ENABLE) update_state(State::ArbitrationWaitBusFree, 10); else @@ -574,6 +625,8 @@ WRITE8_MEMBER(mb87030_device::scmd_w) m_dma_transfer = !(data & 0x04); LOG("%s Transfer\n", m_dma_transfer ? "DMA" : "Program"); + if (!m_dma_transfer) + m_dreq_handler(false); m_ssts |= SSTS_SPC_BUSY|SSTS_XFER_IN_PROGRESS; update_state(State::TransferWaitReq, 5); break; @@ -609,32 +662,44 @@ WRITE8_MEMBER(mb87030_device::scmd_w) } } -READ8_MEMBER(mb87030_device::tmod_r) +uint8_t mb87030_device::tmod_r() { LOG("%s: %02X\n", __FUNCTION__, m_tmod); return m_tmod; } -WRITE8_MEMBER(mb87030_device::tmod_w) +void mb87030_device::tmod_w(uint8_t data) { LOG("%s: %02X\n", __FUNCTION__, data); m_tmod = data; } -READ8_MEMBER(mb87030_device::ints_r) +uint8_t mb87030_device::ints_r() { - LOG("%s: %02X\n", __FUNCTION__, m_ints); + //LOG("%s: %02X\n", __FUNCTION__, m_ints); return m_ints; } -WRITE8_MEMBER(mb87030_device::ints_w) +void mb87030_device::ints_w(uint8_t data) { LOG("%s: %02X\n", __FUNCTION__, data); + if (m_state == State::SelectionWaitBSY && (m_ints & data & INTS_SPC_TIMEOUT)) { + if (!m_tc) { + // terminate selection/reselection + m_ssts &= ~(SSTS_INIT_CONNECTED|SSTS_TARG_CONNECTED|SSTS_SPC_BUSY); + scsi_set_ctrl(0, S_ALL); + scsi_bus->data_w(scsi_refid, 0); + update_state(State::Idle); + } else { + // restart selection/reselection + update_state(State::SelectionAssertID, 1); + } + } m_ints &= ~(data); update_ints(); } -READ8_MEMBER(mb87030_device::psns_r) +uint8_t mb87030_device::psns_r() { uint32_t ctrl = scsi_get_ctrl(); uint8_t ret = (!!(ctrl & S_REQ) << 7) | @@ -649,33 +714,36 @@ READ8_MEMBER(mb87030_device::psns_r) return ret; } -WRITE8_MEMBER(mb87030_device::sdgc_w) +void mb87030_device::sdgc_w(uint8_t data) { LOG("%s: %02X\n", __FUNCTION__, data); + if (type() == MB87030) + data &= ~SDGC_XFER_ENABLE; m_sdgc = data; scsi_ctrl_changed(); + update_ints(); } -READ8_MEMBER(mb87030_device::ssts_r) +uint8_t mb87030_device::ssts_r() { - LOG("%s: %02X\n", __FUNCTION__, m_ssts); + //LOG("%s: %02X\n", __FUNCTION__, m_ssts); update_ssts(); return m_ssts; } -READ8_MEMBER(mb87030_device::serr_r) +uint8_t mb87030_device::serr_r() { LOG("%s: %02X\n", __FUNCTION__, m_serr); return m_serr; } -READ8_MEMBER(mb87030_device::pctl_r) +uint8_t mb87030_device::pctl_r() { LOG("%s: %02X\n", __FUNCTION__, m_pctl); return m_pctl; } -WRITE8_MEMBER(mb87030_device::pctl_w) +void mb87030_device::pctl_w(uint8_t data) { LOG("%s: %02X\n", __FUNCTION__, data); m_pctl = data; @@ -684,59 +752,75 @@ WRITE8_MEMBER(mb87030_device::pctl_w) step(false); } -READ8_MEMBER(mb87030_device::mbc_r) +uint8_t mb87030_device::mbc_r() { LOG("%s: %02X\n", __FUNCTION__, m_mbc); return m_mbc; } -READ8_MEMBER(mb87030_device::dreg_r) +uint8_t mb87030_device::dreg_r() { - step(false); + if (machine().side_effects_disabled()) + return m_fifo.peek(); + if (!m_fifo.empty()) - m_dreg = m_fifo.dequeue(); + m_dreg = m_fifo.dequeue(); LOG("%s: %02X\n", __FUNCTION__, m_dreg); + + if (m_serr & SERR_XFER_OUT) { + m_serr &= ~SERR_XFER_OUT; + update_ints(); + } + + step(false); + return m_dreg; } -WRITE8_MEMBER(mb87030_device::dreg_w) +void mb87030_device::dreg_w(uint8_t data) { LOG("%s: %02X\n", __FUNCTION__, data); m_dreg = data; if (!m_fifo.full()) m_fifo.enqueue(data); + + if (m_serr & SERR_XFER_OUT) { + m_serr &= ~SERR_XFER_OUT; + update_ints(); + } + step(false); } -READ8_MEMBER(mb87030_device::temp_r) +uint8_t mb87030_device::temp_r() { step(false); LOG("%s: %02X\n", __FUNCTION__, m_temp); return m_temp; } -WRITE8_MEMBER(mb87030_device::temp_w) +void mb87030_device::temp_w(uint8_t data) { LOG("%s: %02X\n", __FUNCTION__, data); m_temp = data; step(false); } -READ8_MEMBER(mb87030_device::tch_r) +uint8_t mb87030_device::tch_r() { uint8_t ret = (m_tc >> 16) & 0xff; LOG("%s: %02X\n", __FUNCTION__, ret); return ret; } -READ8_MEMBER(mb87030_device::tcm_r) +uint8_t mb87030_device::tcm_r() { uint8_t ret = (m_tc >> 8) & 0xff; LOG("%s: %02X\n", __FUNCTION__, ret); return ret; } -READ8_MEMBER(mb87030_device::tcl_r) +uint8_t mb87030_device::tcl_r() { uint8_t ret = m_tc & 0xff; LOG("%s: %02X\n", __FUNCTION__, ret); @@ -744,7 +828,7 @@ READ8_MEMBER(mb87030_device::tcl_r) } -WRITE8_MEMBER(mb87030_device::tch_w) +void mb87030_device::tch_w(uint8_t data) { LOG("%s: %02X\n", __FUNCTION__, data); m_tc &= 0x00ffff; @@ -752,7 +836,7 @@ WRITE8_MEMBER(mb87030_device::tch_w) update_ssts(); } -WRITE8_MEMBER(mb87030_device::tcm_w) +void mb87030_device::tcm_w(uint8_t data) { LOG("%s: %02X\n", __FUNCTION__, data); m_tc &= 0xff00ff; @@ -760,7 +844,7 @@ WRITE8_MEMBER(mb87030_device::tcm_w) update_ssts(); } -WRITE8_MEMBER(mb87030_device::tcl_w) +void mb87030_device::tcl_w(uint8_t data) { LOG("%s: %02X\n", __FUNCTION__, data); m_tc &= 0xffff00; @@ -768,13 +852,13 @@ WRITE8_MEMBER(mb87030_device::tcl_w) update_ssts(); } -READ8_MEMBER(mb87030_device::exbf_r) +uint8_t mb87030_device::exbf_r() { LOG("%s: %02X\n", __FUNCTION__, m_exbf); return m_exbf; } -WRITE8_MEMBER(mb87030_device::exbf_w) +void mb87030_device::exbf_w(uint8_t data) { LOG("%s: %02X\n", __FUNCTION__, data); m_exbf = data; @@ -782,22 +866,28 @@ WRITE8_MEMBER(mb87030_device::exbf_w) void mb87030_device::dma_w(uint8_t data) { - if (machine().side_effects_disabled()) - return; - LOG("dma_w: %02X\n", data); - m_hdb = data; - m_hdb_loaded = true; + LOG("dma_w: %02X (%d entered)\n", data, m_fifo.queue_length() + 1); + m_dreg = data; + if (!m_fifo.full()) { + m_fifo.enqueue(data); + if (m_fifo.full()) + m_dreq_handler(false); + } step(false); } -uint8_t mb87030_device::dma_r(void) +uint8_t mb87030_device::dma_r() { - uint8_t val = m_hdb; - if (machine().side_effects_disabled()) - return 0; - LOG("dma_r: %02X\n", val); - m_hdb_loaded = false; + return m_fifo.peek(); + + if (!m_fifo.empty()) { + m_dreg = m_fifo.dequeue(); + if (m_fifo.empty()) + m_dreq_handler(false); + } + + LOG("dma_r: %02X (%d left)\n", m_dreg, m_fifo.queue_length()); step(false); - return val; + return m_dreg; } |