mirror of
https://github.com/holub/mame
synced 2025-05-04 21:43:05 +03:00
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
This commit is contained in:
parent
af30346e3e
commit
33b04cec42
@ -174,12 +174,12 @@ z80scc_device::z80scc_device(const machine_config &mconfig, device_type type, co
|
|||||||
m_out_txda_cb(*this),
|
m_out_txda_cb(*this),
|
||||||
m_out_dtra_cb(*this),
|
m_out_dtra_cb(*this),
|
||||||
m_out_rtsa_cb(*this),
|
m_out_rtsa_cb(*this),
|
||||||
m_out_wrdya_cb(*this),
|
m_out_wreqa_cb(*this),
|
||||||
m_out_synca_cb(*this),
|
m_out_synca_cb(*this),
|
||||||
m_out_txdb_cb(*this),
|
m_out_txdb_cb(*this),
|
||||||
m_out_dtrb_cb(*this),
|
m_out_dtrb_cb(*this),
|
||||||
m_out_rtsb_cb(*this),
|
m_out_rtsb_cb(*this),
|
||||||
m_out_wrdyb_cb(*this),
|
m_out_wreqb_cb(*this),
|
||||||
m_out_syncb_cb(*this),
|
m_out_syncb_cb(*this),
|
||||||
m_out_int_cb(*this),
|
m_out_int_cb(*this),
|
||||||
m_out_rxdrqa_cb(*this),
|
m_out_rxdrqa_cb(*this),
|
||||||
@ -249,12 +249,12 @@ void z80scc_device::device_start()
|
|||||||
m_out_txda_cb.resolve_safe();
|
m_out_txda_cb.resolve_safe();
|
||||||
m_out_dtra_cb.resolve_safe();
|
m_out_dtra_cb.resolve_safe();
|
||||||
m_out_rtsa_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_synca_cb.resolve_safe();
|
||||||
m_out_txdb_cb.resolve_safe();
|
m_out_txdb_cb.resolve_safe();
|
||||||
m_out_dtrb_cb.resolve_safe();
|
m_out_dtrb_cb.resolve_safe();
|
||||||
m_out_rtsb_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_syncb_cb.resolve_safe();
|
||||||
m_out_int_cb.resolve_safe();
|
m_out_int_cb.resolve_safe();
|
||||||
m_out_rxdrqa_cb.resolve_safe();
|
m_out_rxdrqa_cb.resolve_safe();
|
||||||
@ -1136,6 +1136,8 @@ void z80scc_channel::tra_complete()
|
|||||||
set_rts(1);
|
set_rts(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_waitrequest();
|
||||||
|
|
||||||
if (m_wr1 & WR1_TX_INT_ENABLE && m_tx_int_disarm == 0)
|
if (m_wr1 & WR1_TX_INT_ENABLE && m_tx_int_disarm == 0)
|
||||||
{
|
{
|
||||||
if ((m_uart->m_variant & z80scc_device::SET_ESCC) &&
|
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("- 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("- 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("- 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/DMA Request Enable %u\n", (data & WR1_WREQ_ENABLE) ? 1 : 0);
|
||||||
LOG("- Wait/Ready Function %s\n", (data & WR1_WRDY_FUNCTION) ? "Ready" : "Wait");
|
LOG("- Wait/DMA Request Function %s\n", (data & WR1_WREQ_FUNCTION) ? "Request" : "Wait");
|
||||||
LOG("- Wait/Ready on %s\n", (data & WR1_WRDY_ON_RX_TX) ? "Receive" : "Transmit");
|
LOG("- Wait/DMA Request on %s\n", (data & WR1_WREQ_ON_RX_TX) ? "Receive" : "Transmit");
|
||||||
|
|
||||||
|
check_waitrequest();
|
||||||
|
|
||||||
switch (data & WR1_RX_INT_MODE_MASK)
|
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
|
m_rr1 &= ~RR1_ALL_SENT; // All is definitelly not sent anymore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_waitrequest();
|
||||||
|
|
||||||
/* Transmitter enabled? */
|
/* Transmitter enabled? */
|
||||||
if (m_wr5 & WR5_TX_ENABLE)
|
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)
|
if(m_rxc != 0 || m_brg_rate != 0)
|
||||||
device_serial_interface::rx_w(state);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -98,8 +98,8 @@
|
|||||||
#define MCFG_Z80SCC_OUT_RTSA_CB(_devcb) \
|
#define MCFG_Z80SCC_OUT_RTSA_CB(_devcb) \
|
||||||
devcb = &z80scc_device::set_out_rtsa_callback(*device, DEVCB_##_devcb);
|
devcb = &z80scc_device::set_out_rtsa_callback(*device, DEVCB_##_devcb);
|
||||||
|
|
||||||
#define MCFG_Z80SCC_OUT_WRDYA_CB(_devcb) \
|
#define MCFG_Z80SCC_OUT_WREQA_CB(_devcb) \
|
||||||
devcb = &z80scc_device::set_out_wrdya_callback(*device, DEVCB_##_devcb);
|
devcb = &z80scc_device::set_out_wreqa_callback(*device, DEVCB_##_devcb);
|
||||||
|
|
||||||
#define MCFG_Z80SCC_OUT_SYNCA_CB(_devcb) \
|
#define MCFG_Z80SCC_OUT_SYNCA_CB(_devcb) \
|
||||||
devcb = &z80scc_device::set_out_synca_callback(*device, DEVCB_##_devcb);
|
devcb = &z80scc_device::set_out_synca_callback(*device, DEVCB_##_devcb);
|
||||||
@ -120,8 +120,8 @@
|
|||||||
#define MCFG_Z80SCC_OUT_RTSB_CB(_devcb) \
|
#define MCFG_Z80SCC_OUT_RTSB_CB(_devcb) \
|
||||||
devcb = &z80scc_device::set_out_rtsb_callback(*device, DEVCB_##_devcb);
|
devcb = &z80scc_device::set_out_rtsb_callback(*device, DEVCB_##_devcb);
|
||||||
|
|
||||||
#define MCFG_Z80SCC_OUT_WRDYB_CB(_devcb) \
|
#define MCFG_Z80SCC_OUT_WREQB_CB(_devcb) \
|
||||||
devcb = &z80scc_device::set_out_wrdyb_callback(*device, DEVCB_##_devcb);
|
devcb = &z80scc_device::set_out_wreqb_callback(*device, DEVCB_##_devcb);
|
||||||
|
|
||||||
#define MCFG_Z80SCC_OUT_SYNCB_CB(_devcb) \
|
#define MCFG_Z80SCC_OUT_SYNCB_CB(_devcb) \
|
||||||
devcb = &z80scc_device::set_out_syncb_callback(*device, DEVCB_##_devcb);
|
devcb = &z80scc_device::set_out_syncb_callback(*device, DEVCB_##_devcb);
|
||||||
@ -412,9 +412,9 @@ protected:
|
|||||||
WR1_RX_INT_FIRST = 0x08,
|
WR1_RX_INT_FIRST = 0x08,
|
||||||
WR1_RX_INT_ALL = 0x10,
|
WR1_RX_INT_ALL = 0x10,
|
||||||
WR1_RX_INT_PARITY = 0x18,
|
WR1_RX_INT_PARITY = 0x18,
|
||||||
WR1_WRDY_ON_RX_TX = 0x20,
|
WR1_WREQ_ON_RX_TX = 0x20,
|
||||||
WR1_WRDY_FUNCTION = 0x40,
|
WR1_WREQ_FUNCTION = 0x40,
|
||||||
WR1_WRDY_ENABLE = 0x80
|
WR1_WREQ_ENABLE = 0x80
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
@ -587,6 +587,7 @@ protected:
|
|||||||
int get_rx_word_length();
|
int get_rx_word_length();
|
||||||
int get_tx_word_length();
|
int get_tx_word_length();
|
||||||
void safe_transmit_register_reset();
|
void safe_transmit_register_reset();
|
||||||
|
void check_waitrequest();
|
||||||
|
|
||||||
// receiver state
|
// receiver state
|
||||||
uint8_t m_rx_data_fifo[8]; // receive data FIFO
|
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_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_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_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_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_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_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_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_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_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)); }
|
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_txda_cb;
|
||||||
devcb_write_line m_out_dtra_cb;
|
devcb_write_line m_out_dtra_cb;
|
||||||
devcb_write_line m_out_rtsa_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_synca_cb;
|
||||||
|
|
||||||
devcb_write_line m_out_txdb_cb;
|
devcb_write_line m_out_txdb_cb;
|
||||||
devcb_write_line m_out_dtrb_cb;
|
devcb_write_line m_out_dtrb_cb;
|
||||||
devcb_write_line m_out_rtsb_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_syncb_cb;
|
||||||
|
|
||||||
devcb_write_line m_out_int_cb;
|
devcb_write_line m_out_int_cb;
|
||||||
|
Loading…
Reference in New Issue
Block a user