From 33b04cec42f3e260cc7f36f372c8531cb0b99a96 Mon Sep 17 00:00:00 2001 From: Patrick Mackinlay Date: Thu, 6 Jul 2017 14:00:31 +0700 Subject: z80scc: basic wait/dma request support (#2441) * improved initiator transfer information logic * split transfer count/counter * added rudimentary 53c90a/53c94 support * reworked initiator transfer information state machine: should now support all scsi phases * improved handling of dma/non-dma commands * added an undocumented hack to make InterPro work * match updated 5390 device * inherit memory map * z80scc: basic wait/dma request implementation * z80scc: renamed WRDY to WREQ to match datasheet, minor touch-up --- src/devices/machine/z80scc.cpp | 49 ++++++++++++++++++++++++++++++++++++------ src/devices/machine/z80scc.h | 23 ++++++++++---------- 2 files changed, 54 insertions(+), 18 deletions(-) diff --git a/src/devices/machine/z80scc.cpp b/src/devices/machine/z80scc.cpp index fc795d688a9..d0e1681c9de 100644 --- a/src/devices/machine/z80scc.cpp +++ b/src/devices/machine/z80scc.cpp @@ -174,12 +174,12 @@ z80scc_device::z80scc_device(const machine_config &mconfig, device_type type, co m_out_txda_cb(*this), m_out_dtra_cb(*this), m_out_rtsa_cb(*this), - m_out_wrdya_cb(*this), + m_out_wreqa_cb(*this), m_out_synca_cb(*this), m_out_txdb_cb(*this), m_out_dtrb_cb(*this), m_out_rtsb_cb(*this), - m_out_wrdyb_cb(*this), + m_out_wreqb_cb(*this), m_out_syncb_cb(*this), m_out_int_cb(*this), m_out_rxdrqa_cb(*this), @@ -249,12 +249,12 @@ void z80scc_device::device_start() m_out_txda_cb.resolve_safe(); m_out_dtra_cb.resolve_safe(); m_out_rtsa_cb.resolve_safe(); - m_out_wrdya_cb.resolve_safe(); + m_out_wreqa_cb.resolve_safe(); m_out_synca_cb.resolve_safe(); m_out_txdb_cb.resolve_safe(); m_out_dtrb_cb.resolve_safe(); m_out_rtsb_cb.resolve_safe(); - m_out_wrdyb_cb.resolve_safe(); + m_out_wreqb_cb.resolve_safe(); m_out_syncb_cb.resolve_safe(); m_out_int_cb.resolve_safe(); m_out_rxdrqa_cb.resolve_safe(); @@ -1136,6 +1136,8 @@ void z80scc_channel::tra_complete() set_rts(1); } + check_waitrequest(); + if (m_wr1 & WR1_TX_INT_ENABLE && m_tx_int_disarm == 0) { if ((m_uart->m_variant & z80scc_device::SET_ESCC) && @@ -1790,9 +1792,11 @@ void z80scc_channel::do_sccreg_wr1(uint8_t data) LOG("- External Interrupt Enable %u\n", (data & WR1_EXT_INT_ENABLE) ? 1 : 0); LOG("- Transmit Interrupt Enable %u\n", (data & WR1_TX_INT_ENABLE) ? 1 : 0); LOG("- Parity is special condition %u\n", (data & WR1_PARITY_IS_SPEC_COND) ? 1 : 0); - LOG("- Wait/Ready Enable %u\n", (data & WR1_WRDY_ENABLE) ? 1 : 0); - LOG("- Wait/Ready Function %s\n", (data & WR1_WRDY_FUNCTION) ? "Ready" : "Wait"); - LOG("- Wait/Ready on %s\n", (data & WR1_WRDY_ON_RX_TX) ? "Receive" : "Transmit"); + LOG("- Wait/DMA Request Enable %u\n", (data & WR1_WREQ_ENABLE) ? 1 : 0); + LOG("- Wait/DMA Request Function %s\n", (data & WR1_WREQ_FUNCTION) ? "Request" : "Wait"); + LOG("- Wait/DMA Request on %s\n", (data & WR1_WREQ_ON_RX_TX) ? "Receive" : "Transmit"); + + check_waitrequest(); switch (data & WR1_RX_INT_MODE_MASK) { @@ -2410,6 +2414,8 @@ void z80scc_channel::data_write(uint8_t data) m_rr1 &= ~RR1_ALL_SENT; // All is definitelly not sent anymore } + check_waitrequest(); + /* Transmitter enabled? */ if (m_wr5 & WR5_TX_ENABLE) { @@ -2857,3 +2863,32 @@ WRITE_LINE_MEMBER(z80scc_channel::write_rx) if(m_rxc != 0 || m_brg_rate != 0) device_serial_interface::rx_w(state); } + +/* + * This is a partial implementation of the "wait/dma request" functionality of the SCC controlled by + * bits D7, D6 and D5 in WR1. This implementation is sufficient to support DMA request on transmit + * used by the InterPro driver. + * + * TODO: + * - wait function (D6=0) + * - wait/request function on receive (D5=1) + */ +void z80scc_channel::check_waitrequest() +{ + // don't do anything if wait/request function is not enabled + if ((m_wr1 & WR1_WREQ_ENABLE) == 0) + return; + + // wait/request function for receive not implemented + if (m_wr1 & WR1_WREQ_ON_RX_TX) + return; + + // if dma request function is enabled + if (m_wr1 & WR1_WREQ_FUNCTION) + { + // assert /W//REQ if transmit buffer is empty, clear if it's not + int state = (m_rr0 & RR0_TX_BUFFER_EMPTY) ? ASSERT_LINE : CLEAR_LINE; + + (m_index ? m_uart->m_out_wreqb_cb : m_uart->m_out_wreqa_cb)(state); + } +} diff --git a/src/devices/machine/z80scc.h b/src/devices/machine/z80scc.h index c78d4775a17..2b0cae0ea76 100644 --- a/src/devices/machine/z80scc.h +++ b/src/devices/machine/z80scc.h @@ -98,8 +98,8 @@ #define MCFG_Z80SCC_OUT_RTSA_CB(_devcb) \ devcb = &z80scc_device::set_out_rtsa_callback(*device, DEVCB_##_devcb); -#define MCFG_Z80SCC_OUT_WRDYA_CB(_devcb) \ - devcb = &z80scc_device::set_out_wrdya_callback(*device, DEVCB_##_devcb); +#define MCFG_Z80SCC_OUT_WREQA_CB(_devcb) \ + devcb = &z80scc_device::set_out_wreqa_callback(*device, DEVCB_##_devcb); #define MCFG_Z80SCC_OUT_SYNCA_CB(_devcb) \ devcb = &z80scc_device::set_out_synca_callback(*device, DEVCB_##_devcb); @@ -120,8 +120,8 @@ #define MCFG_Z80SCC_OUT_RTSB_CB(_devcb) \ devcb = &z80scc_device::set_out_rtsb_callback(*device, DEVCB_##_devcb); -#define MCFG_Z80SCC_OUT_WRDYB_CB(_devcb) \ - devcb = &z80scc_device::set_out_wrdyb_callback(*device, DEVCB_##_devcb); +#define MCFG_Z80SCC_OUT_WREQB_CB(_devcb) \ + devcb = &z80scc_device::set_out_wreqb_callback(*device, DEVCB_##_devcb); #define MCFG_Z80SCC_OUT_SYNCB_CB(_devcb) \ devcb = &z80scc_device::set_out_syncb_callback(*device, DEVCB_##_devcb); @@ -412,9 +412,9 @@ protected: WR1_RX_INT_FIRST = 0x08, WR1_RX_INT_ALL = 0x10, WR1_RX_INT_PARITY = 0x18, - WR1_WRDY_ON_RX_TX = 0x20, - WR1_WRDY_FUNCTION = 0x40, - WR1_WRDY_ENABLE = 0x80 + WR1_WREQ_ON_RX_TX = 0x20, + WR1_WREQ_FUNCTION = 0x40, + WR1_WREQ_ENABLE = 0x80 }; enum @@ -587,6 +587,7 @@ protected: int get_rx_word_length(); int get_tx_word_length(); void safe_transmit_register_reset(); + void check_waitrequest(); // receiver state uint8_t m_rx_data_fifo[8]; // receive data FIFO @@ -647,12 +648,12 @@ public: template static devcb_base &set_out_txda_callback(device_t &device, Object &&cb) { return downcast(device).m_out_txda_cb.set_callback(std::forward(cb)); } template static devcb_base &set_out_dtra_callback(device_t &device, Object &&cb) { return downcast(device).m_out_dtra_cb.set_callback(std::forward(cb)); } template static devcb_base &set_out_rtsa_callback(device_t &device, Object &&cb) { return downcast(device).m_out_rtsa_cb.set_callback(std::forward(cb)); } - template static devcb_base &set_out_wrdya_callback(device_t &device, Object &&cb) { return downcast(device).m_out_wrdya_cb.set_callback(std::forward(cb)); } + template static devcb_base &set_out_wreqa_callback(device_t &device, Object &&cb) { return downcast(device).m_out_wreqa_cb.set_callback(std::forward(cb)); } template static devcb_base &set_out_synca_callback(device_t &device, Object &&cb) { return downcast(device).m_out_synca_cb.set_callback(std::forward(cb)); } template static devcb_base &set_out_txdb_callback(device_t &device, Object &&cb) { return downcast(device).m_out_txdb_cb.set_callback(std::forward(cb)); } template static devcb_base &set_out_dtrb_callback(device_t &device, Object &&cb) { return downcast(device).m_out_dtrb_cb.set_callback(std::forward(cb)); } template static devcb_base &set_out_rtsb_callback(device_t &device, Object &&cb) { return downcast(device).m_out_rtsb_cb.set_callback(std::forward(cb)); } - template static devcb_base &set_out_wrdyb_callback(device_t &device, Object &&cb) { return downcast(device).m_out_wrdyb_cb.set_callback(std::forward(cb)); } + template static devcb_base &set_out_wreqb_callback(device_t &device, Object &&cb) { return downcast(device).m_out_wreqb_cb.set_callback(std::forward(cb)); } template static devcb_base &set_out_syncb_callback(device_t &device, Object &&cb) { return downcast(device).m_out_syncb_cb.set_callback(std::forward(cb)); } template static devcb_base &set_out_int_callback(device_t &device, Object &&cb) { return downcast(device).m_out_int_cb.set_callback(std::forward(cb)); } template static devcb_base &set_out_rxdrqa_callback(device_t &device, Object &&cb) { return downcast(device).m_out_rxdrqa_cb.set_callback(std::forward(cb)); } @@ -777,13 +778,13 @@ protected: devcb_write_line m_out_txda_cb; devcb_write_line m_out_dtra_cb; devcb_write_line m_out_rtsa_cb; - devcb_write_line m_out_wrdya_cb; + devcb_write_line m_out_wreqa_cb; devcb_write_line m_out_synca_cb; devcb_write_line m_out_txdb_cb; devcb_write_line m_out_dtrb_cb; devcb_write_line m_out_rtsb_cb; - devcb_write_line m_out_wrdyb_cb; + devcb_write_line m_out_wreqb_cb; devcb_write_line m_out_syncb_cb; devcb_write_line m_out_int_cb; -- cgit v1.2.3