diff options
Diffstat (limited to 'src/devices/machine/mb87030.cpp')
-rw-r--r-- | src/devices/machine/mb87030.cpp | 797 |
1 files changed, 797 insertions, 0 deletions
diff --git a/src/devices/machine/mb87030.cpp b/src/devices/machine/mb87030.cpp new file mode 100644 index 00000000000..39e306866a6 --- /dev/null +++ b/src/devices/machine/mb87030.cpp @@ -0,0 +1,797 @@ +// license:BSD-3-Clause +// copyright-holders:Sven Schnelle + +#include "emu.h" +#define VERBOSE 0 +#include "logmacro.h" +#include "mb87030.h" + +DEFINE_DEVICE_TYPE(MB87030, mb87030_device, "MB87030", "Fujitsu MB87030 SCSI controller") + +mb87030_device::mb87030_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + mb87030_device(mconfig, MB87030, tag, owner, clock) +{ + +} + +mb87030_device::mb87030_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + nscsi_device(mconfig, type, tag, owner, clock), + m_irq_handler(*this), + m_dreq_handler(*this) +{ + +} + +void mb87030_device::map(address_map &map) +{ + map(0x00, 0x00).rw(FUNC(mb87030_device::bdid_r), FUNC(mb87030_device::bdid_w)); + map(0x01, 0x01).rw(FUNC(mb87030_device::sctl_r), FUNC(mb87030_device::sctl_w)); + map(0x02, 0x02).rw(FUNC(mb87030_device::scmd_r), FUNC(mb87030_device::scmd_w)); + map(0x03, 0x03).rw(FUNC(mb87030_device::tmod_r), FUNC(mb87030_device::tmod_w)); + map(0x04, 0x04).rw(FUNC(mb87030_device::ints_r), FUNC(mb87030_device::ints_w)); + map(0x05, 0x05).rw(FUNC(mb87030_device::psns_r), FUNC(mb87030_device::sdgc_w)); + map(0x06, 0x06).r(FUNC(mb87030_device::ssts_r)); + map(0x07, 0x07).r(FUNC(mb87030_device::serr_r)); + map(0x08, 0x08).rw(FUNC(mb87030_device::pctl_r), FUNC(mb87030_device::pctl_w)); + map(0x09, 0x09).r(FUNC(mb87030_device::mbc_r)); + map(0x0a, 0x0a).rw(FUNC(mb87030_device::dreg_r), FUNC(mb87030_device::dreg_w)); + map(0x0b, 0x0b).rw(FUNC(mb87030_device::temp_r), FUNC(mb87030_device::temp_w)); + map(0x0c, 0x0c).rw(FUNC(mb87030_device::tch_r), FUNC(mb87030_device::tch_w)); + map(0x0d, 0x0d).rw(FUNC(mb87030_device::tcm_r), FUNC(mb87030_device::tcm_w)); + map(0x0e, 0x0e).rw(FUNC(mb87030_device::tcl_r), FUNC(mb87030_device::tcl_w)); + map(0x0f, 0x0f).rw(FUNC(mb87030_device::exbf_r), FUNC(mb87030_device::exbf_w)); +} + +void mb87030_device::device_reset() +{ + m_bdid = 0; + m_sctl = SCTL_RESET_AND_DISABLE; + m_scmd = 0; + m_tmod = 0; + m_ints = 0; + m_sdgc = 0; + m_ssts = 0; + m_serr = 0; + m_pctl = 0; + m_mbc = 0; + m_dreg = 0; + m_temp = 0; + m_tch = 0; + m_tcm = 0; + m_tc = 0; + m_exbf = 0; + m_fifo.clear(); + 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); + scsi_bus->data_w(scsi_refid, 0); + update_ssts(); + update_ints(); +} + +auto mb87030_device::get_state_name(State state) const +{ + switch(state) { + case State::Idle: + return "Idle"; + case State::ArbitrationWaitBusFree: + return "ArbitrationWaitBusFree"; + case State::ArbitrationAssertBSY: + return "ArbitrationAssertBSY"; + case State::ArbitrationWait: + return "ArbitrationWait"; + case State::ArbitrationAssertSEL: + return "ArbitrationAssertSEL"; + case State::ArbitrationDeAssertBSY: + return "ArbitrationDeAssertBSY"; + case State::SelectionWaitBusFree: + return "SelectionWaitBusFree"; + case State::SelectionWaitBSY: + return "SelectionWaitBSY"; + case State::SelectionAssertSEL: + return "SelectionAssertSEL"; + case State::Selection: + return "Selection"; + case State::TransferWaitReq: + return "TransferWaitReq"; + case State::TransferSendAck: + 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"; + case State::TransferDeassertACK: + return "TransferDeassertACK"; + } + return "Unknown state"; +} + +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); + m_state = new_state; + if (delay) + m_delay_timer->adjust(clocks_to_attotime(delay)); + else + m_delay_timer->reset(); + if (timeout) + m_timer->adjust(clocks_to_attotime(timeout)); + else + m_timer->reset(); +} + +void mb87030_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + switch(id) { + case TimerId::Delay: + m_delay_timer->reset(); + step(false); + break; + case TimerId::Timeout: + m_timer->reset(); + step(true); + break; + } +} + +void mb87030_device::scsi_command_complete() +{ + 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); + m_ssts &= ~(SSTS_INIT_CONNECTED|SSTS_TARG_CONNECTED|SSTS_SPC_BUSY|SSTS_XFER_IN_PROGRESS); + m_ints = INTS_DISCONNECTED; + if (m_pctl & PCTL_BUS_FREE_IE) { + LOG("disconnect IE\n"); + m_ints |= INTS_DISCONNECTED; + } + update_ints(); + update_state(State::Idle); +} + +void mb87030_device::scsi_set_ctrl(uint32_t value, uint32_t mask) +{ + if (m_sctl & SCTL_DIAG_MODE) { + m_scsi_ctrl &= ~mask; + m_scsi_ctrl |= value; + logerror("update m_scsi_ctrl: %02X%s%s%s%s%s%s\n", m_scsi_ctrl, + (m_scsi_ctrl & S_REQ) ? " REQ" : "", + (m_scsi_ctrl & S_ACK) ? " ACK" : "", + (m_scsi_ctrl & S_BSY) ? " BSY" : "", + (m_scsi_ctrl & S_MSG) ? " MSG" : "", + (m_scsi_ctrl & S_CTL) ? " CTL" : "", + (m_scsi_ctrl & S_INP) ? " INP" : ""); + } else { + scsi_bus->ctrl_w(scsi_refid, value, mask); + } +} + +uint32_t mb87030_device::scsi_get_ctrl(void) +{ + if (m_sctl & SCTL_DIAG_MODE) { + uint32_t ret = 0; + if ((m_sdgc & SDGC_DIAG_IO) || (m_scsi_ctrl & S_INP)) + ret |= S_INP; + if ((m_sdgc & SDGC_DIAG_CD) || (m_scsi_ctrl & S_CTL)) + ret |= S_CTL; + if ((m_sdgc & SDGC_DIAG_MSG) || (m_scsi_ctrl & S_MSG)) + ret |= S_MSG; + if ((m_sdgc & SDGC_DIAG_BSY) || (m_scsi_ctrl & S_BSY)) + ret |= S_BSY; + if ((m_sdgc & SDGC_DIAG_ACK) || (m_scsi_ctrl & S_ACK)) + ret |= S_ACK; + if ((m_sdgc & SDGC_DIAG_REQ) || (m_scsi_ctrl & S_REQ)) + ret |= S_REQ; + if (m_scsi_ctrl & S_SEL) + ret |= S_SEL; + if (m_scsi_ctrl & S_ATN) + ret |= S_ATN; + + return ret; + } else { + return scsi_bus->ctrl_r(); + } +} + +void mb87030_device::step(bool timeout) +{ + uint32_t ctrl = scsi_get_ctrl(); + uint32_t data = scsi_bus->data_r(); + + LOG("%s: %d %s,%s data %02X ctrl %02X TC %d\n", __FUNCTION__, + scsi_refid, get_state_name(m_state), + timeout ? " timeout" : "", data, + ctrl, m_tc); + + if (m_sctl & SCTL_RESET_AND_DISABLE && m_state != State::Idle) { + scsi_set_ctrl(0, S_ALL); + update_state(State::Idle); + return; + } + + + if ((m_ssts & SSTS_INIT_CONNECTED) && !(ctrl & S_BSY)) { + LOG("SCSI disconnect\n"); + scsi_disconnect(); + scsi_set_ctrl(0, S_ALL); + } + + + switch(m_state) { + case State::Idle: + + if (ctrl == 0 && (m_pctl & PCTL_BUS_FREE_IE)) { + m_ints |= INTS_DISCONNECTED; + update_ints(); + } + break; + 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); + break; + + case State::ArbitrationWait: + + for (int id = (2 << m_bdid); id <= 0x80; id <<= 1) { + LOG("check %d\n", id); + if (data & id) { + LOG("arbitration lost, winner %d\n", id); + scsi_disconnect_timeout(); + break; + } + } + LOG("Arbitration won\n"); + update_state(State::ArbitrationAssertSEL, 1); + break; + + 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); + break; + + case State::SelectionWaitBusFree: + if (!(ctrl & (S_BSY|S_SEL))) + update_state(State::SelectionAssertSEL, 10); + break; + + case State::SelectionAssertSEL: + scsi_bus->data_w(scsi_refid, m_temp); + scsi_set_ctrl(0, S_SEL); //XXX: needed? + 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); + break; + + case State::SelectionWaitBSY: + if (timeout) { + LOG("select timeout\n"); + scsi_disconnect_timeout(); + 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: + 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_fifo.empty() || m_dma_transfer)) { + LOG("TransferWaitReq: tc == 0\n"); + scsi_bus->data_w(scsi_refid, 0); + scsi_command_complete(); + break; + } + + if (m_tc < 0) + break; + + if (m_scsi_phase != (ctrl & S_PHASE_MASK)) { + LOG("SCSI phase change during transfer\n"); + m_ints |= INTS_SERVICE_REQUIRED; + m_ssts &= ~SSTS_SPC_BUSY; + update_ints(); + break; + } + + if (!(ctrl & S_REQ)) { + scsi_bus->ctrl_wait(scsi_refid, S_REQ, S_REQ); + break; + } + + if (!m_dma_transfer) { + update_state((ctrl & S_INP) ? State::TransferRecvData : State::TransferSendData, 1); + } else { + update_state((ctrl & S_INP) ? State::TransferRecvDataDMAReq : State::TransferSendDataDMAReq, 1); + } + break; + + case State::TransferRecvData: + if (!m_tc || m_fifo.full()) + break; + + LOG("pushing read data: %02X\n", data); + m_fifo.enqueue(data); + m_tc--; + + update_state(State::TransferSendAck, 10); + break; + + case State::TransferRecvDataDMAReq: + m_hdb = data; + m_hdb_loaded = true; + update_state(State::TransferRecvDataDMAResp, 10); + m_tc--; + m_dreq_handler(true); + break; + + case State::TransferRecvDataDMAResp: + if (m_hdb_loaded) + break; + update_state(State::TransferSendAck, 10); + m_dreq_handler(false); + break; + + case State::TransferSendData: + + if (m_tc < 0 || m_fifo.empty()) { + LOG("fifo empty or m_tc(%d) zero\n", m_tc); + break; + } + + scsi_bus->data_w(scsi_refid, m_fifo.dequeue()); + m_tc--; + update_state(State::TransferSendAck, 10); + 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); + m_tc--; + update_state(State::TransferSendAck, 10); + break; + + case State::TransferSendAck: + + scsi_set_ctrl(S_ACK, S_ACK); + scsi_bus->ctrl_wait(scsi_refid, 0, S_REQ); + + update_state(State::TransferWaitDeassertREQ, 10); + break; + + case State::TransferWaitDeassertREQ: + if (!(ctrl & S_REQ)) + update_state(State::TransferDeassertACK, 10); + break; + + case State::TransferDeassertACK: + scsi_set_ctrl(0, S_ACK); + scsi_bus->ctrl_wait(scsi_refid, S_REQ, S_REQ); + update_state(State::TransferWaitReq, 10); + break; + + } +} + +void mb87030_device::device_start() +{ + m_timer = timer_alloc(TimerId::Timeout); + m_delay_timer = timer_alloc(TimerId::Delay); + m_irq_handler.resolve_safe(); + m_dreq_handler.resolve_safe(); + + save_item(NAME(m_bdid)); + save_item(NAME(m_sctl)); + save_item(NAME(m_scmd)); + save_item(NAME(m_tmod)); + save_item(NAME(m_ints)); + save_item(NAME(m_sdgc)); + save_item(NAME(m_ssts)); + save_item(NAME(m_serr)); + save_item(NAME(m_pctl)); + save_item(NAME(m_mbc)); + save_item(NAME(m_dreg)); + save_item(NAME(m_temp)); + save_item(NAME(m_tch)); + 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_state)); +} + +void mb87030_device::scsi_ctrl_changed() +{ + if (m_delay_timer->remaining() == attotime::never) + step(false); +} + +WRITE_LINE_MEMBER(mb87030_device::reset_w) +{ + LOG("%s: %s\n", __FUNCTION__, state); + if (state) + device_reset(); +} + +void mb87030_device::update_ssts() +{ + if (!m_tc) + m_ssts |= SSTS_TC_ZERO; + else + m_ssts &= ~SSTS_TC_ZERO; + + if (m_fifo.empty()) + m_ssts |= SSTS_DREQ_EMPTY; + else + m_ssts &= ~SSTS_DREQ_EMPTY; + + if (m_fifo.full()) + m_ssts |= SSTS_DREQ_FULL; + else + m_ssts &= ~SSTS_DREQ_FULL; +} + +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)); +} + +READ8_MEMBER(mb87030_device::bdid_r) +{ + LOG("%s %02X\n", __FUNCTION__, (1 << m_bdid)); + return (1 << m_bdid); +} + +WRITE8_MEMBER(mb87030_device::bdid_w) +{ + LOG("%s: %02X\n", __FUNCTION__, data); + m_bdid = data & 0x7; +} + +READ8_MEMBER(mb87030_device::sctl_r) +{ + LOG("%s: %02X\n", __FUNCTION__, m_sctl); + return m_sctl; +} + +WRITE8_MEMBER(mb87030_device::sctl_w) +{ + LOG("%s: %02X\n", __FUNCTION__, data); + m_sctl = data; + update_ints(); +} + +READ8_MEMBER(mb87030_device::scmd_r) +{ + LOG("%s: %02X\n", __FUNCTION__, m_scmd); + return m_scmd; +} + +WRITE8_MEMBER(mb87030_device::scmd_w) +{ + LOG("%s: %02X\n", __FUNCTION__, data); + m_scmd = data; + + switch(m_scmd & SCMD_CMD_MASK) { + case SCMD_CMD_BUS_RELEASE: + LOG("%s: Bus release\n", __FUNCTION__); + break; + case SCMD_CMD_SELECT: + LOG("%s: Select\n", __FUNCTION__); + if (m_sctl & SCTL_ARBITRATION_ENABLE) + update_state(State::ArbitrationWaitBusFree, 10); + else + update_state(State::SelectionWaitBusFree, 10); + step(false); + break; + case SCMD_CMD_RESET_ATN: + LOG("%s: Reset ATN\n", __FUNCTION__); +// if (m_state == State::Idle) + m_send_atn_during_selection = false; +// else + scsi_set_ctrl(0, S_ATN); + break; + case SCMD_CMD_SET_ATN: + LOG("%s: Set ATN\n", __FUNCTION__); + if (m_state == State::Idle) + m_send_atn_during_selection = true; + else + scsi_set_ctrl(S_ATN, S_ATN); + break; + case SCMD_CMD_TRANSFER: + if (!(m_ssts & (SSTS_INIT_CONNECTED|SSTS_TARG_CONNECTED))) + break; + + m_dma_transfer = !(data & 0x04); + LOG("%s Transfer\n", m_dma_transfer ? "DMA" : "Program"); + m_ssts |= SSTS_SPC_BUSY|SSTS_XFER_IN_PROGRESS; + update_state(State::TransferWaitReq, 5); + break; + case SCMD_CMD_TRANSFER_PAUSE: + LOG("%s: Transfer Pause\n", __FUNCTION__); + break; + case SCMD_CMD_RESET_ACK_REQ: + LOG("%s: Reset ACK/REQ\n", __FUNCTION__); + if (m_ssts & SSTS_INIT_CONNECTED) + scsi_set_ctrl(0, S_ACK); + if (m_ssts & SSTS_TARG_CONNECTED) + scsi_set_ctrl(0, S_REQ); + break; + case SCMD_CMD_SET_ACK_REQ: + LOG("%s: Set ACK/REQ\n", __FUNCTION__); + if (m_ssts & SSTS_INIT_CONNECTED) { + if (m_pctl & 1) { + m_temp = scsi_bus->data_r(); + } else { + scsi_bus->data_w(scsi_refid, m_temp); + } + LOG("set ACK\n"); + scsi_set_ctrl(S_ACK, S_ACK); + } else { + logerror("not connected\n"); + } + if (m_ssts & SSTS_TARG_CONNECTED) + scsi_set_ctrl(S_REQ, S_REQ); + break; + } +} + +READ8_MEMBER(mb87030_device::tmod_r) +{ + LOG("%s: %02X\n", __FUNCTION__, m_tmod); + return m_tmod; +} + +WRITE8_MEMBER(mb87030_device::tmod_w) +{ + LOG("%s: %02X\n", __FUNCTION__, data); + m_tmod = data; +} + +READ8_MEMBER(mb87030_device::ints_r) +{ + LOG("%s: %02X\n", __FUNCTION__, m_ints); + return m_ints; +} + +WRITE8_MEMBER(mb87030_device::ints_w) +{ + LOG("%s: %02X\n", __FUNCTION__, data); + m_ints &= ~(data); + update_ints(); +} + +READ8_MEMBER(mb87030_device::psns_r) +{ + uint32_t ctrl = scsi_get_ctrl(); + uint8_t ret = (!!(ctrl & S_REQ) << 7) | + (!!(ctrl & S_ACK) << 6) | + (!!(ctrl & S_ATN) << 5) | + (!!(ctrl & S_SEL) << 4) | + (!!(ctrl & S_BSY) << 3) | + (!!(ctrl & S_MSG) << 2) | + (!!(ctrl & S_CTL) << 1) | + (!!(ctrl & S_INP)); + LOG("%s: %02X\n", __FUNCTION__, ret); + return ret; +} + +WRITE8_MEMBER(mb87030_device::sdgc_w) +{ + LOG("%s: %02X\n", __FUNCTION__, data); + m_sdgc = data; + scsi_ctrl_changed(); +} + +READ8_MEMBER(mb87030_device::ssts_r) +{ + LOG("%s: %02X\n", __FUNCTION__, m_ssts); + update_ssts(); + return m_ssts; +} + +READ8_MEMBER(mb87030_device::serr_r) +{ + LOG("%s: %02X\n", __FUNCTION__, m_serr); + return m_serr; +} + +READ8_MEMBER(mb87030_device::pctl_r) +{ + LOG("%s: %02X\n", __FUNCTION__, m_pctl); + return m_pctl; +} + +WRITE8_MEMBER(mb87030_device::pctl_w) +{ + LOG("%s: %02X\n", __FUNCTION__, data); + m_pctl = data; + m_scsi_phase = m_pctl & 7; + if (m_pctl & PCTL_BUS_FREE_IE) + step(false); + +} + +READ8_MEMBER(mb87030_device::mbc_r) +{ + LOG("%s: %02X\n", __FUNCTION__, m_mbc); + return m_mbc; +} + +READ8_MEMBER(mb87030_device::dreg_r) +{ + + step(false); + if (!m_fifo.empty()) + m_dreg = m_fifo.dequeue(); + LOG("%s: %02X\n", __FUNCTION__, m_dreg); + return m_dreg; +} + +WRITE8_MEMBER(mb87030_device::dreg_w) +{ + LOG("%s: %02X\n", __FUNCTION__, data); + m_dreg = data; + if (!m_fifo.full()) + m_fifo.enqueue(data); + step(false); +} + +READ8_MEMBER(mb87030_device::temp_r) +{ + m_temp = scsi_bus->data_r(); + LOG("%s: %02X\n", __FUNCTION__, m_temp); + return m_temp; + +} + +WRITE8_MEMBER(mb87030_device::temp_w) +{ + LOG("%s: %02X\n", __FUNCTION__, data); + m_temp = data; + step(false); +} + +READ8_MEMBER(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 ret = (m_tc >> 8) & 0xff; + LOG("%s: %02X\n", __FUNCTION__, ret); + return ret; +} + +READ8_MEMBER(mb87030_device::tcl_r) +{ + uint8_t ret = m_tc & 0xff; + LOG("%s: %02X\n", __FUNCTION__, ret); + return ret; +} + + +WRITE8_MEMBER(mb87030_device::tch_w) +{ + LOG("%s: %02X\n", __FUNCTION__, data); + m_tc &= 0x00ffff; + m_tc |= data << 16; + update_ssts(); +} + +WRITE8_MEMBER(mb87030_device::tcm_w) +{ + LOG("%s: %02X\n", __FUNCTION__, data); + m_tc &= 0xff00ff; + m_tc |= data << 8; + update_ssts(); +} + +WRITE8_MEMBER(mb87030_device::tcl_w) +{ + LOG("%s: %02X\n", __FUNCTION__, data); + m_tc &= 0xffff00; + m_tc |= data; + update_ssts(); +} + +READ8_MEMBER(mb87030_device::exbf_r) +{ + LOG("%s: %02X\n", __FUNCTION__, m_exbf); + return m_exbf; +} + +WRITE8_MEMBER(mb87030_device::exbf_w) +{ + LOG("%s: %02X\n", __FUNCTION__, data); + m_exbf = data; +} + +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; + step(false); +} + +uint8_t mb87030_device::dma_r(void) +{ + uint8_t val = m_hdb; + + if (machine().side_effects_disabled()) + return 0; + LOG("dma_r: %02X\n", val); + m_hdb_loaded = false; + step(false); + return val; +} |