summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Patrick Mackinlay <pmackinlay@hotmail.com>2017-07-06 14:00:31 +0700
committer Vas Crabb <cuavas@users.noreply.github.com>2017-07-06 17:00:31 +1000
commit33b04cec42f3e260cc7f36f372c8531cb0b99a96 (patch)
treebd1743754d4a170b09a8336520cddabd324b4217
parentaf30346e3e84e3d268f5569f248cde0df55db418 (diff)
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
-rw-r--r--src/devices/machine/z80scc.cpp49
-rw-r--r--src/devices/machine/z80scc.h23
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 <class Object> static devcb_base &set_out_txda_callback(device_t &device, Object &&cb) { return downcast<z80scc_device &>(device).m_out_txda_cb.set_callback(std::forward<Object>(cb)); }
template <class Object> static devcb_base &set_out_dtra_callback(device_t &device, Object &&cb) { return downcast<z80scc_device &>(device).m_out_dtra_cb.set_callback(std::forward<Object>(cb)); }
template <class Object> static devcb_base &set_out_rtsa_callback(device_t &device, Object &&cb) { return downcast<z80scc_device &>(device).m_out_rtsa_cb.set_callback(std::forward<Object>(cb)); }
- template <class Object> static devcb_base &set_out_wrdya_callback(device_t &device, Object &&cb) { return downcast<z80scc_device &>(device).m_out_wrdya_cb.set_callback(std::forward<Object>(cb)); }
+ template <class Object> static devcb_base &set_out_wreqa_callback(device_t &device, Object &&cb) { return downcast<z80scc_device &>(device).m_out_wreqa_cb.set_callback(std::forward<Object>(cb)); }
template <class Object> static devcb_base &set_out_synca_callback(device_t &device, Object &&cb) { return downcast<z80scc_device &>(device).m_out_synca_cb.set_callback(std::forward<Object>(cb)); }
template <class Object> static devcb_base &set_out_txdb_callback(device_t &device, Object &&cb) { return downcast<z80scc_device &>(device).m_out_txdb_cb.set_callback(std::forward<Object>(cb)); }
template <class Object> static devcb_base &set_out_dtrb_callback(device_t &device, Object &&cb) { return downcast<z80scc_device &>(device).m_out_dtrb_cb.set_callback(std::forward<Object>(cb)); }
template <class Object> static devcb_base &set_out_rtsb_callback(device_t &device, Object &&cb) { return downcast<z80scc_device &>(device).m_out_rtsb_cb.set_callback(std::forward<Object>(cb)); }
- template <class Object> static devcb_base &set_out_wrdyb_callback(device_t &device, Object &&cb) { return downcast<z80scc_device &>(device).m_out_wrdyb_cb.set_callback(std::forward<Object>(cb)); }
+ template <class Object> static devcb_base &set_out_wreqb_callback(device_t &device, Object &&cb) { return downcast<z80scc_device &>(device).m_out_wreqb_cb.set_callback(std::forward<Object>(cb)); }
template <class Object> static devcb_base &set_out_syncb_callback(device_t &device, Object &&cb) { return downcast<z80scc_device &>(device).m_out_syncb_cb.set_callback(std::forward<Object>(cb)); }
template <class Object> static devcb_base &set_out_int_callback(device_t &device, Object &&cb) { return downcast<z80scc_device &>(device).m_out_int_cb.set_callback(std::forward<Object>(cb)); }
template <class Object> static devcb_base &set_out_rxdrqa_callback(device_t &device, Object &&cb) { return downcast<z80scc_device &>(device).m_out_rxdrqa_cb.set_callback(std::forward<Object>(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;