diff --git a/src/devices/machine/z80sio.cpp b/src/devices/machine/z80sio.cpp index e83907157cb..df8d22487bc 100644 --- a/src/devices/machine/z80sio.cpp +++ b/src/devices/machine/z80sio.cpp @@ -54,38 +54,40 @@ // MACROS / CONSTANTS //************************************************************************** -#define LOG_GENERAL 0x001 -#define LOG_SETUP 0x002 -#define LOG_PRINTF 0x004 -#define LOG_READ 0x008 -#define LOG_INT 0x010 -#define LOG_TX 0x020 -#define LOG_RCV 0x040 -#define LOG_CTS 0x080 -#define LOG_DCD 0x100 +//#define LOG_GENERAL (1U << 0) +#define LOG_SETUP (1U << 1) +#define LOG_READ (1U << 2) +#define LOG_INT (1U << 3) +#define LOG_CMD (1U << 4) +#define LOG_TX (1U << 5) +#define LOG_RCV (1U << 6) +#define LOG_CTS (1U << 7) +#define LOG_DCD (1U << 8) +#define LOG_SYNC (1U << 9) +#define LOG_BIT (1U << 10) -#define VERBOSE 0 //(LOG_PRINTF | LOG_SETUP | LOG_GENERAL) +//#define VERBOSE (LOG_INT|LOG_READ|LOG_SETUP|LOG_TX|LOG_CMD) //(LOG_SETUP|LOG_INT|LOG_CMD|LOG_DCD|LOG_CTS|LOG_TX) +//#define LOG_OUTPUT_FUNC printf -#define LOGMASK(mask, ...) do { if (VERBOSE & mask) logerror(__VA_ARGS__); } while (0) -#define LOGLEVEL(mask, level, ...) do { if ((VERBOSE & mask) >= level) logerror(__VA_ARGS__); } while (0) +#include "logmacro.h" -#define LOG(...) LOGMASK(LOG_GENERAL, __VA_ARGS__) -#define LOGR(...) LOGMASK(LOG_READ, __VA_ARGS__) -#define LOGSETUP(...) LOGMASK(LOG_SETUP, __VA_ARGS__) -#define LOGINT(...) LOGMASK(LOG_INT, __VA_ARGS__) -#define LOGTX(...) LOGMASK(LOG_TX, __VA_ARGS__) -#define LOGRCV(...) LOGMASK(LOG_RCV, __VA_ARGS__) -#define LOGCTS(...) LOGMASK(LOG_CTS, __VA_ARGS__) -#define LOGDCD(...) LOGMASK(LOG_DCD, __VA_ARGS__) - -#if VERBOSE & LOG_PRINTF -#define logerror printf -#endif +#define LOGSETUP(...) LOGMASKED(LOG_SETUP, __VA_ARGS__) +#define LOGR(...) LOGMASKED(LOG_READ, __VA_ARGS__) +#define LOGINT(...) LOGMASKED(LOG_INT, __VA_ARGS__) +#define LOGCMD(...) LOGMASKED(LOG_CMD, __VA_ARGS__) +#define LOGTX(...) LOGMASKED(LOG_TX, __VA_ARGS__) +#define LOGRCV(...) LOGMASKED(LOG_RCV, __VA_ARGS__) +#define LOGCTS(...) LOGMASKED(LOG_CTS, __VA_ARGS__) +#define LOGDCD(...) LOGMASKED(LOG_DCD, __VA_ARGS__) +#define LOGSYNC(...) LOGMASKED(LOG_SYNC, __VA_ARGS__) +#define LOGBIT(...) LOGMASKED(LOG_BIT, __VA_ARGS__) #ifdef _MSC_VER #define FUNCNAME __func__ +#define LLFORMAT "%I64d" #else #define FUNCNAME __PRETTY_FUNCTION__ +#define LLFORMAT "%lld" #endif #define CHANA_TAG "cha" @@ -99,6 +101,7 @@ const device_type Z80SIO = device_creator; const device_type Z80SIO_CHANNEL = device_creator; const device_type UPD7201N = device_creator; // Remove trailing N when z80dart.cpp's 7201 implementation is fully replaced +const device_type I8274N = device_creator; // Remove trailing N when z80dart.cpp's 8274 implementation is fully replaced //------------------------------------------------- // device_mconfig_additions - @@ -146,7 +149,8 @@ z80sio_device::z80sio_device(const machine_config &mconfig, device_type type, co m_out_txdrqa_cb(*this), m_out_rxdrqb_cb(*this), m_out_txdrqb_cb(*this), - m_variant(variant) + m_variant(variant), + m_cputag("maincpu") { for (auto & elem : m_int_state) elem = 0; @@ -176,7 +180,8 @@ z80sio_device::z80sio_device(const machine_config &mconfig, const char *tag, dev m_out_txdrqa_cb(*this), m_out_rxdrqb_cb(*this), m_out_txdrqb_cb(*this), - m_variant(TYPE_Z80SIO) + m_variant(TYPE_Z80SIO), + m_cputag("maincpu") { for (auto & elem : m_int_state) elem = 0; @@ -185,6 +190,9 @@ z80sio_device::z80sio_device(const machine_config &mconfig, const char *tag, dev upd7201N_device::upd7201N_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : z80sio_device(mconfig, UPD7201N, "UPD 7201", tag, owner, clock, TYPE_UPD7201, "upd7201n", __FILE__){ } +i8274N_device::i8274N_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : z80sio_device(mconfig, I8274N, "i8274", tag, owner, clock, TYPE_I8274, "i8274", __FILE__){ } + //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- @@ -218,6 +226,7 @@ void z80sio_device::device_start() // state saving save_item(NAME(m_int_state)); + save_item(NAME(m_int_source)); } @@ -238,23 +247,21 @@ void z80sio_device::device_reset() int z80sio_device::z80daisy_irq_state() { int state = 0; - int i; - - LOGINT("%s %s A:%d%d%d%d B:%d%d%d%d ",FUNCNAME, tag(), - m_int_state[0], m_int_state[1], m_int_state[2], m_int_state[3], - m_int_state[4], m_int_state[5], m_int_state[6], m_int_state[7]); + LOGINT("%s %s Hi->Lo:%d%d%d%d%d%d ", tag(), FUNCNAME, + m_int_state[0], m_int_state[1], m_int_state[2], + m_int_state[3], m_int_state[4], m_int_state[5]); // loop over all interrupt sources - for (i = 0; i < 8; i++) + for (auto & elem : m_int_state) { // if we're servicing a request, don't indicate more interrupts - if (m_int_state[i] & Z80_DAISY_IEO) + if (elem & Z80_DAISY_IEO) { state |= Z80_DAISY_IEO; break; } - state |= m_int_state[i]; + state |= elem; } LOGINT("Interrupt State %u\n", state); @@ -268,30 +275,29 @@ int z80sio_device::z80daisy_irq_state() //------------------------------------------------- int z80sio_device::z80daisy_irq_ack() { - int i; - - LOGINT("%s %s \n",FUNCNAME, tag()); + // default irq vector is -1 for 68000 but 0 for z80 for example... + int ret = owner()->subdevice(m_cputag)->default_irq_vector(); + LOGINT("%s %s \n",tag(), FUNCNAME); // loop over all interrupt sources - for (i = 0; i < 8; i++) + for (auto & elem : m_int_state) { // find the first channel with an interrupt requested - if (m_int_state[i] & Z80_DAISY_INT) + if (elem & Z80_DAISY_INT) { - // clear interrupt, switch to the IEO state, and update the IRQs - m_int_state[i] = Z80_DAISY_IEO; + elem = Z80_DAISY_IEO; // Set IUS bit (called IEO in z80 daisy lingo) m_chanA->m_rr0 &= ~z80sio_channel::RR0_INTERRUPT_PENDING; + LOGINT(" - Found an INT request, "); + LOGINT("returning RR2: %02x\n", m_chanB->m_rr2 ); check_interrupts(); - - //LOG("%s %s \n",FUNCNAME, tag(), m_chanB->m_rr2); - - return m_chanB->m_rr2; + return m_chanB->m_rr2; } } + ret = m_chanB->m_rr2; + LOGINT(" - failed to find an interrupt to ack, returning default IRQ vector: %02x\n", ret ); + logerror("z80sio_irq_ack: failed to find an interrupt to ack!\n"); - //logerror("z80sio_irq_ack: failed to find an interrupt to ack!\n"); - - return m_chanB->m_rr2; + return ret; } @@ -300,24 +306,27 @@ int z80sio_device::z80daisy_irq_ack() //------------------------------------------------- void z80sio_device::z80daisy_irq_reti() { - int i; + LOGINT("%s %s \n",tag(), FUNCNAME); - LOGINT("%s %s \n",FUNCNAME, tag()); + if((m_variant == TYPE_I8274) || (m_variant == TYPE_UPD7201)) + { + LOGINT(" - I8274 and UPD7201 lacks RETI detection, no action taken\n"); + return; + } // loop over all interrupt sources - for (i = 0; i < 8; i++) + for (auto & elem : m_int_state) { - // find the first channel with an IEO pending - if (m_int_state[i] & Z80_DAISY_IEO) + // find the first channel with an interrupt requested + if (elem & Z80_DAISY_IEO) { // clear the IEO state and update the IRQs - m_int_state[i] &= ~Z80_DAISY_IEO; + elem &= ~Z80_DAISY_IEO; check_interrupts(); return; } } - - //logerror("z80sio_irq_reti: failed to find an interrupt to clear IEO on!\n"); + LOGINT("z80sio_irq_reti: failed to find an interrupt to clear IEO on!\n"); } @@ -347,66 +356,95 @@ void z80sio_device::reset_interrupts() check_interrupts(); } - -//------------------------------------------------- -// trigger_interrupt - TODO: needs attention for SIO -//------------------------------------------------- -void z80sio_device::trigger_interrupt(int index, int state) +int z80sio_device::get_interrupt_prio(int index, int type) { - uint8_t vector = m_chanB->m_wr2; - int priority; + int prio_level = -1; + int priority = -1; - LOGINT("%s %s \n",FUNCNAME, tag()); +// LOGINT("prio_level: %02x priority:%02x ", prio_level, priority); + if ((m_variant == TYPE_I8274) || (m_variant == TYPE_UPD7201)) + { + /* These CPU variants use Bit 2 of WR2 of Channnel A to determine the priority Hi to Lo: + 0: RxA TxA RxB TxB ExtA ExtB + 1: RxA RxB TxA TxB ExtA ExtB */ + switch(type) + { + case z80sio_channel::INT_RECEIVE: + case z80sio_channel::INT_SPECIAL: prio_level = z80sio_channel::INT_RCV_SPC_PRI_LVL; break; // 0 + case z80sio_channel::INT_TRANSMIT: prio_level = z80sio_channel::INT_TRANSMIT_PRI_LVL; break; // 1 + case z80sio_channel::INT_EXTERNAL: prio_level = z80sio_channel::INT_EXTERNAL_PRI_LVL; break; // 2 + default: + logerror("Bad interrupt source being prioritized!"); + return -1; + } + // Assume that the PRIORITY bit is set + priority = (prio_level * 2) + index; -#if 0 + // Check if it actually was cleared + if ( (m_chanA->m_wr2 & z80sio_channel::WR2_PRIORITY) == 0) + { + // Adjust priority if needed, only affects TxA and RxB + if (index == CHANNEL_A && type == z80sio_channel::INT_TRANSMIT ) + priority--; + else if (index == CHANNEL_B && type == z80sio_channel::INT_RECEIVE ) + priority++; + } + } + else // Plain old z80sio + { + priority = (index << 2) | type; + } + return priority; +} + +/* + 8274: "RR2 contains the vector which gets modified to indicate the source of interrupt. However, the state of + the vector does not change if no new interrupts are generated. The contents of RR2 are only changed when + a new interrupt is generated. In order to get the correct information, RR2 must be read only after an + interrrupt is generated, otherwise it will indicate the previous state." + 8274: "If RR2 is specified but not read, no internal interrupts, regardless of priority, are accepted." +*/ +uint8_t z80sio_device::modify_vector(int index, int type) +{ + uint8_t vector = m_chanB->m_wr2; if((m_variant == TYPE_I8274) || (m_variant == TYPE_UPD7201)) { - int prio_level = 0; - switch(state) - { - case z80sio_channel::INT_TRANSMIT: - prio_level = 1; - break; - case z80sio_channel::INT_RECEIVE: - case z80sio_channel::INT_SPECIAL: - prio_level = 0; - break; - case z80sio_channel::INT_EXTERNAL: - prio_level = 2; - break; - } - - if(m_chanA->m_wr2 & z80sio_channel::WR2_PRIORITY) - { - priority = (prio_level * 2) + index; - } - else - { - priority = (prio_level == 2) ? index + 4 : ((index * 2) + prio_level); - } if (m_chanB->m_wr1 & z80sio_channel::WR1_STATUS_VECTOR) { - vector = (!index << 2) | state; + vector = (!index << 2) | type; if((m_chanA->m_wr1 & 0x18) == z80sio_channel::WR2_MODE_8086_8088) { - vector = (m_chanB->m_wr2 & 0xf8) | vector; + vector = (m_chanB->m_wr2 & 0xf8) | vector; // m_chanB->m_wr2; } else { - vector = (m_chanB->m_wr2 & 0xe3) | (vector << 2); + vector = (m_chanB->m_wr2 & 0xe3) | (vector << 2); //(m_chanB->m_wr2 << 2); } } } else { -#endif - priority = (index << 2) | state; if (m_chanB->m_wr1 & z80sio_channel::WR1_STATUS_VECTOR) { // status affects vector - vector = (m_chanB->m_wr2 & 0xf1) | (!index << 3) | (state << 1); + vector = (m_chanB->m_wr2 & 0xf1) | (!index << 3) | (type << 1); } -// } + } + return vector; +} + +//------------------------------------------------- +// trigger_interrupt - TODO: needs attention for SIO +//------------------------------------------------- +void z80sio_device::trigger_interrupt(int index, int type) +{ + uint8_t priority = get_interrupt_prio(index, type); + uint8_t vector = modify_vector(index, type); + + LOGINT("%s %s Chan:%c Type:%s\n", tag(), FUNCNAME, 'A' + index, std::array + {{"INT_TRANSMIT", "INT_EXTERNAL", "INT_RECEIVE", "INT_SPECIAL"}}[type]); + LOGINT(" - Priority:%02x Vector:%02x\n", priority, vector); + // update vector register m_chanB->m_rr2 = vector; @@ -414,6 +452,9 @@ void z80sio_device::trigger_interrupt(int index, int state) m_int_state[priority] |= Z80_DAISY_INT; m_chanA->m_rr0 |= z80sio_channel::RR0_INTERRUPT_PENDING; + // remember the source and channel + m_int_source[priority] = (type & 0xff) | (index << 8); + // check for interrupt check_interrupts(); } @@ -425,7 +466,10 @@ void z80sio_device::trigger_interrupt(int index, int state) int z80sio_device::m1_r() { LOGINT("%s %s \n",FUNCNAME, tag()); - return z80daisy_irq_ack(); + if((m_variant == TYPE_I8274) || (m_variant == TYPE_UPD7201)) + return 0; + else + return z80daisy_irq_ack(); } @@ -505,7 +549,6 @@ z80sio_channel::z80sio_channel(const machine_config &mconfig, const char *tag, d : device_t(mconfig, Z80SIO_CHANNEL, "Z80 SIO channel", tag, owner, clock, "z80sio_channel", __FILE__), device_serial_interface(mconfig, *this), m_rx_error(0), - m_rx_fifo(-1), m_rx_clock(0), m_rx_first(0), m_rx_break(0), @@ -524,12 +567,6 @@ z80sio_channel::z80sio_channel(const machine_config &mconfig, const char *tag, d // Reset all registers m_rr0 = m_rr1 = m_rr2 = 0; m_wr0 = m_wr1 = m_wr2 = m_wr3 = m_wr4 = m_wr5 = m_wr6 = m_wr7 = 0; - - for (int i = 0; i < 3; i++) - { - m_rx_data_fifo[i] = 0; - m_rx_error_fifo[i] = 0; - } } @@ -555,10 +592,7 @@ void z80sio_channel::device_start() save_item(NAME(m_wr5)); save_item(NAME(m_wr6)); save_item(NAME(m_wr7)); - save_item(NAME(m_rx_data_fifo)); - save_item(NAME(m_rx_error_fifo)); save_item(NAME(m_rx_error)); - save_item(NAME(m_rx_fifo)); save_item(NAME(m_rx_clock)); save_item(NAME(m_rx_first)); save_item(NAME(m_rx_break)); @@ -618,7 +652,7 @@ void z80sio_channel::tra_callback() { if (!(m_wr5 & WR5_TX_ENABLE)) { - LOG("%s() \"%s \"Channel %c transmit mark 1 m_wr5:%02x\n", FUNCNAME, m_owner->tag(), 'A' + m_index, m_wr5); + LOGBIT("%s() \"%s \"Channel %c transmit mark 1 m_wr5:%02x\n", FUNCNAME, m_owner->tag(), 'A' + m_index, m_wr5); // transmit mark if (m_index == z80sio_device::CHANNEL_A) m_uart->m_out_txda_cb(1); @@ -627,7 +661,7 @@ void z80sio_channel::tra_callback() } else if (m_wr5 & WR5_SEND_BREAK) { - LOG("%s() \"%s \"Channel %c send break 1 m_wr5:%02x\n", FUNCNAME, m_owner->tag(), 'A' + m_index, m_wr5); + LOGBIT("%s() \"%s \"Channel %c send break 1 m_wr5:%02x\n", FUNCNAME, m_owner->tag(), 'A' + m_index, m_wr5); // transmit break if (m_index == z80sio_device::CHANNEL_A) m_uart->m_out_txda_cb(0); @@ -638,7 +672,7 @@ void z80sio_channel::tra_callback() { int db = transmit_register_get_data_bit(); - LOG("%s() \"%s \"Channel %c transmit data bit %d m_wr5:%02x\n", FUNCNAME, m_owner->tag(), 'A' + m_index, db, m_wr5); + LOGBIT("%s() \"%s \"Channel %c transmit data bit %d m_wr5:%02x\n", FUNCNAME, m_owner->tag(), 'A' + m_index, db, m_wr5); // transmit data if (m_index == z80sio_device::CHANNEL_A) m_uart->m_out_txda_cb(db); @@ -647,7 +681,7 @@ void z80sio_channel::tra_callback() } else { - LOG("%s() \"%s \"Channel %c Failed to transmit m_wr5:%02x\n", FUNCNAME, m_owner->tag(), 'A' + m_index, m_wr5); + LOGBIT("%s() \"%s \"Channel %c Failed to transmit m_wr5:%02x\n", FUNCNAME, m_owner->tag(), 'A' + m_index, m_wr5); logerror("%s \"%s \"Channel %c Failed to transmit\n", FUNCNAME, m_owner->tag(), 'A' + m_index); } } @@ -661,7 +695,7 @@ void z80sio_channel::tra_complete() LOG("%s %s\n",FUNCNAME, tag()); if ((m_wr5 & WR5_TX_ENABLE) && !(m_wr5 & WR5_SEND_BREAK) && !(m_rr0 & RR0_TX_BUFFER_EMPTY)) { - LOG("%s() \"%s \"Channel %c Transmit Data Byte '%02x' m_wr5:%02x\n", FUNCNAME, m_owner->tag(), 'A' + m_index, m_tx_data, m_wr5); + LOGTX("%s() \"%s \"Channel %c Transmit Data Byte '%02x' m_wr5:%02x\n", FUNCNAME, m_owner->tag(), 'A' + m_index, m_tx_data, m_wr5); transmit_register_setup(m_tx_data); @@ -673,7 +707,7 @@ void z80sio_channel::tra_complete() } else if (m_wr5 & WR5_SEND_BREAK) { - LOG("%s() \"%s \"Channel %c Transmit Break 0 m_wr5:%02x\n", FUNCNAME, m_owner->tag(), 'A' + m_index, m_wr5); + LOGTX("%s() \"%s \"Channel %c Transmit Break 0 m_wr5:%02x\n", FUNCNAME, m_owner->tag(), 'A' + m_index, m_wr5); // transmit break if (m_index == z80sio_device::CHANNEL_A) m_uart->m_out_txda_cb(0); @@ -682,7 +716,7 @@ void z80sio_channel::tra_complete() } else { - LOG("%s() \"%s \"Channel %c Transmit Mark 1 m_wr5:%02x\n", FUNCNAME, m_owner->tag(), 'A' + m_index, m_wr5); + LOGTX("%s() \"%s \"Channel %c Transmit Mark 1 m_wr5:%02x\n", FUNCNAME, m_owner->tag(), 'A' + m_index, m_wr5); // transmit mark if (m_index == z80sio_device::CHANNEL_A) m_uart->m_out_txda_cb(1); @@ -693,7 +727,7 @@ void z80sio_channel::tra_complete() // if transmit buffer is empty if (m_rr0 & RR0_TX_BUFFER_EMPTY) { - LOG("%s() \"%s \"Channel %c Transmit buffer empty m_wr5:%02x\n", FUNCNAME, m_owner->tag(), 'A' + m_index, m_wr5); + LOGTX("%s() \"%s \"Channel %c Transmit buffer empty m_wr5:%02x\n", FUNCNAME, m_owner->tag(), 'A' + m_index, m_wr5); // then all characters have been sent m_rr1 |= RR1_ALL_SENT; @@ -711,16 +745,9 @@ void z80sio_channel::rcv_callback() { if (m_wr3 & WR3_RX_ENABLE) { - LOG("%s() \"%s \"Channel %c Received Data Bit %d\n", FUNCNAME, m_owner->tag(), 'A' + m_index, m_rxd); + LOGBIT("%s() \"%s \"Channel %c Received Data Bit %d\n", FUNCNAME, m_owner->tag(), 'A' + m_index, m_rxd); receive_register_update_bit(m_rxd); } -#if 0 - else - { - LOG("%s() \"%s \"Channel %c Received Data Bit but receiver is disabled\n", FUNCNAME, m_owner->tag(), 'A' + m_index); - logerror("Z80SIO %s() \"%s \"Channel %c Received data dit but receiver is disabled\n", __func__, m_owner->tag(), 'A' + m_index); - } -#endif } @@ -733,7 +760,7 @@ void z80sio_channel::rcv_complete() receive_register_extract(); data = get_received_char(); - LOG("%s() \"%s \"Channel %c Received Data %02x\n", FUNCNAME, m_owner->tag(), 'A' + m_index, data); + LOGRCV("%s() \"%s \"Channel %c Received Data %02x\n", FUNCNAME, m_owner->tag(), 'A' + m_index, data); receive_data(data); } @@ -863,30 +890,80 @@ int z80sio_channel::get_tx_word_length() * Break/Abort latch. */ uint8_t z80sio_channel::do_sioreg_rr0() { - LOG("%s %s\n",FUNCNAME, tag()); + LOGR("%s %s\n",FUNCNAME, tag()); return m_rr0; } + /* * This register contains the Special Receive condition status bits and Residue * codes for the I-Field in the SDLC Receive Mode. */ uint8_t z80sio_channel::do_sioreg_rr1() { - LOG("%s %s\n",FUNCNAME, tag()); + LOGR("%s %s\n",FUNCNAME, tag()); + // channel B only, channel A returns 0 + if (m_index == z80sio_device::CHANNEL_A) return 0; + return m_rr1; } -/* - * This register contains the interrupt vector written into WR2 if the Status -Affects Vector control bit is not set. If the control bit is set, it contains the -modified vector listed in the Status Affects Vector paragraph of the Write -Register 1 section. When this register is read, the vector returned is modi- -fied by the highest priority interrupting condition at the time of the read. If -no interrupts are pending, the vector is modified with V3 = 0, V2 = 1, and -V1 = 1. This register is read only through Channel B. */ + +/* Z80-SIO Technical Manual: "This register contains the interrupt vector + written into WR2 if the Status Affects Vector control bit is not set. + If the control bit is set, it contains the modified vector listed in + the Status Affects Vector paragraph of the Write Register 1 section. + When this register is read, the vector returned is modified by the + highest priority interrupting condition at the time of the read. If + no interrupts are pending, the vector is modified with V3 = 0, V2 = 1, and + V1 = 1. This register is read only through Channel B." + + Intel 8274 datasheet: "RR2 - Channel B: Interrupt Vector - Contains the interrupt + vector programmed in into WR2. If the status affects vector mode is selected (WR1:D2), + it containes the modified vector for the highest priority interrupt pending. + If no interrupts are pending the variable bits in the vector are set to one." + + NEC upd7201 MPSC2 Technical Manual: "When the MPSC2 is used in vectored mode, the + contents of this register are placed on the bus during the appropriate portion of + interrupt acknowledge sequence. You can read the value of CR2B at any time. + This is particularly useful in determining the cause of an interrup when using the + MPSC2 in Non-vectored mode." +*/ uint8_t z80sio_channel::do_sioreg_rr2() { - LOG("%s %s\n",FUNCNAME, tag()); - // channel B only - return m_index == z80sio_device::CHANNEL_B ? m_rr2 : 0; + LOGINT("%s %s Chan:%c\n", tag(), FUNCNAME, 'A' + m_index); + // channel B only, channel A returns 0 + if (m_index == z80sio_device::CHANNEL_A) return 0; + + LOGINT(" - Channel B so we might need to update the vector modification\n"); + // Assume the unmodified vector + m_rr2 = m_uart->m_chanB->m_wr2; + + if((m_variant == z80sio_device::TYPE_I8274) || (m_variant == z80sio_device::TYPE_UPD7201)) + { + int i = 0; + LOGINT(" - 8274 or 7201 requires special care\n"); + + // loop over all interrupt sources + for (auto & elem : m_uart->m_int_state) + { + // find the first channel with an interrupt requested + if (elem & Z80_DAISY_INT) + { + LOGINT(" - Checking an INT source %d\n", i); + m_rr2 = m_uart->modify_vector((m_uart->m_int_source[i] >> 8) & 1, m_uart->m_int_source[i] & 3); + LOGINT(" - Found an INT request to ack while reading RR2\n"); + elem = Z80_DAISY_IEO; // Set IUS bit (called IEO in z80 daisy lingo) + m_uart->check_interrupts(); + break; + } + i++; + } + // If no pending interrupt were found set variable bits to ones. + if (i >= 6) + { + m_rr2 |= 0x1F; + m_uart->m_chanA->m_rr0 &= ~z80sio_channel::RR0_INTERRUPT_PENDING; + } + } + return m_rr2; } @@ -916,6 +993,8 @@ uint8_t z80sio_channel::control_read() LOG("%s %s unsupported register:%02x\n",FUNCNAME, tag(), reg); } + LOGR(" * %s %c Reg %02x -> %02x - %s\n", tag(), 'A' + m_index, reg, data, std::array + {{"RR0 status register", "RR1 - Special Receive Conditions", "RR2 - Interrupt Vector"}}[reg]); return data; } @@ -946,47 +1025,84 @@ void z80sio_channel::do_sioreg_wr0_resets(uint8_t data) void z80sio_channel::do_sioreg_wr0(uint8_t data) { m_wr0 = data; + + if ((data & WR0_COMMAND_MASK) != WR0_NULL) + LOGSETUP(" * %s %c Reg %02x <- %02x \n", m_owner->tag(), 'A' + m_index, 0, data); switch (data & WR0_COMMAND_MASK) { case WR0_NULL: - LOG("Z80SIO \"%s\" Channel %c : Null\n", m_owner->tag(), 'A' + m_index); + LOGCMD("%s %s Ch:%c : Null command\n", FUNCNAME, tag(), 'A' + m_index); + break; + case WR0_SEND_ABORT: + LOGCMD("%s %s Ch:%c : Send abort command - not implemented\n", FUNCNAME, tag(), 'A' + m_index); break; case WR0_RESET_EXT_STATUS: // reset external/status interrupt + m_rr0 &= ~(RR0_DCD | RR0_SYNC_HUNT | RR0_CTS | RR0_BREAK_ABORT); // release the latch + m_rx_rr0_latch = 0; // update register to reflect wire values TODO: Check if this will fire new interrupts if (!m_dcd) m_rr0 |= RR0_DCD; if (m_sync) m_rr0 |= RR0_SYNC_HUNT; if (m_cts) m_rr0 |= RR0_CTS; - LOG("Z80SIO \"%s\" Channel %c : Reset External/Status Interrupt\n", m_owner->tag(), 'A' + m_index); + // Clear any pending External interrupt + m_uart->m_int_state[m_index == z80sio_device::CHANNEL_A ? 4 : 5] = 0; + + LOGINT("%s %s Ch:%c : Reset External/Status Interrupt\n", FUNCNAME, tag(), 'A' + m_index); break; case WR0_CHANNEL_RESET: // channel reset - LOG("Z80SIO \"%s\" Channel %c : Channel Reset\n", m_owner->tag(), 'A' + m_index); + LOGCMD("%s %s Ch:%c : Channel Reset\n", FUNCNAME, tag(), 'A' + m_index); device_reset(); break; case WR0_ENABLE_INT_NEXT_RX: // enable interrupt on next receive character - LOG("Z80SIO \"%s\" Channel %c : Enable Interrupt on Next Received Character\n", m_owner->tag(), 'A' + m_index); + LOGINT("%s %s Ch:%c : Enable Interrupt on Next Received Character\n", FUNCNAME, tag(), 'A' + m_index); m_rx_first = 1; break; case WR0_RESET_TX_INT: // reset transmitter interrupt pending - LOG("Z80SIO \"%s\" Channel %c : Reset Transmitter Interrupt Pending\n", m_owner->tag(), 'A' + m_index); - logerror("Z80SIO \"%s\" Channel %c : unsupported command: Reset Transmitter Interrupt Pending\n", m_owner->tag(), 'A' + m_index); + { + uint8_t priority = 3; // Assume TxB + // Check if it is TxA + if (m_index == z80sio_device::CHANNEL_A) + { + // Check if priority bit is cleared + priority = (m_uart->m_chanA->m_wr2 & z80sio_channel::WR2_PRIORITY) == 0 ? 1 : 2; + } + m_uart->m_int_state[priority] = 0; + LOGINT("%s %s Ch:%c : Reset TX Interrupt, priority:%d\n", FUNCNAME, tag(), 'A' + m_index, priority); + } + m_uart->check_interrupts(); + LOGCMD("%s %s Ch:%c : Reset Transmitter Interrupt Pending\n", FUNCNAME, tag(), 'A' + m_index); break; case WR0_ERROR_RESET: // error reset - LOG("Z80SIO \"%s\" Channel %c : Error Reset\n", m_owner->tag(), 'A' + m_index); + LOGCMD("%s %s Ch:%c : Error Reset\n", FUNCNAME, tag(), 'A' + m_index); m_rr1 &= ~(RR1_CRC_FRAMING_ERROR | RR1_RX_OVERRUN_ERROR | RR1_PARITY_ERROR); break; case WR0_RETURN_FROM_INT: - // return from interrupt - LOG("Z80SIO \"%s\" Channel %c : Return from Interrupt\n", m_owner->tag(), 'A' + m_index); - m_uart->z80daisy_irq_reti(); + LOGINT("%s %s Ch:%c : Return from interrupt\n", FUNCNAME, tag(), 'A' + m_index); + { + int found = 0; + // loop over all interrupt sources + for (auto & elem : m_uart->m_int_state) + { + // find the first channel with an interrupt requested + if (elem & (Z80_DAISY_IEO)) + { + // clear the IEO state and update the IRQs + elem &= ~(Z80_DAISY_IEO); + m_uart->check_interrupts(); + found = 1; + break; + } + } + LOGINT(" - %s\n", found == 0 ? "failed to find an interrupt to clear IEO on!" : "cleared IEO"); + } break; default: LOG("Z80SIO \"%s\" Channel %c : Unsupported WR0 command %02x mask %02x\n", m_owner->tag(), 'A' + m_index, data, WR0_REGISTER_MASK); @@ -1029,14 +1145,6 @@ void z80sio_channel::do_sioreg_wr1(uint8_t data) void z80sio_channel::do_sioreg_wr2(uint8_t data) { m_wr2 = data; - if (m_index == z80sio_device::CHANNEL_B) - { - if (m_wr1 & z80sio_channel::WR1_STATUS_VECTOR) - m_rr2 = ( m_rr2 & 0x0e ) | ( m_wr2 & 0xF1); - else - m_rr2 = m_wr2; - } - m_uart->check_interrupts(); LOG("Z80SIO \"%s\" Channel %c : Interrupt Vector %02x\n", m_owner->tag(), 'A' + m_index, data); } @@ -1088,7 +1196,8 @@ void z80sio_channel::control_write(uint8_t data) if (reg != 0) { - LOGSETUP(" * %s %c Reg %02x <- %02x \n", m_owner->tag(), 'A' + m_index, reg, data); + LOGSETUP(" * %s %c Reg %02x <- %02x - %s\n", tag(), 'A' + m_index, reg, data, std::array + {{"WR0", "WR1", "WR2", "WR3 - Async Rx setup", "WR4 - Async Clock, Parity and stop bits", "WR5 - Async Tx setup", "WR6", "WR7"}}[reg]); // mask out register index m_wr0 &= ~WR0_REGISTER_MASK; } @@ -1118,18 +1227,15 @@ uint8_t z80sio_channel::data_read() { uint8_t data = 0; - if (m_rx_fifo >= 0) + if (!m_rx_data_fifo.empty()) { // load data from the FIFO - data = m_rx_data_fifo[m_rx_fifo]; + data = m_rx_data_fifo.dequeue(); // load error status from the FIFO - m_rr1 = (m_rr1 & ~(RR1_CRC_FRAMING_ERROR | RR1_RX_OVERRUN_ERROR | RR1_PARITY_ERROR)) | m_rx_error_fifo[m_rx_fifo]; + m_rr1 = (m_rr1 & ~(RR1_CRC_FRAMING_ERROR | RR1_RX_OVERRUN_ERROR | RR1_PARITY_ERROR)) | m_rx_error_fifo.dequeue(); - // decrease FIFO pointer - m_rx_fifo--; - - if (m_rx_fifo < 0) + if (m_rx_data_fifo.empty()) { // no more characters available in the FIFO m_rr0 &= ~ RR0_RX_CHAR_AVAILABLE; @@ -1151,7 +1257,7 @@ void z80sio_channel::data_write(uint8_t data) if ((m_wr5 & WR5_TX_ENABLE) && is_transmit_register_empty()) { - LOG("Z80SIO \"%s\" Channel %c : Transmit Data Byte '%02x'\n", m_owner->tag(), 'A' + m_index, m_tx_data); + LOGTX("Z80SIO \"%s\" Channel %c : Transmit Data Byte '%02x'\n", m_owner->tag(), 'A' + m_index, m_tx_data); transmit_register_setup(m_tx_data); @@ -1163,7 +1269,7 @@ void z80sio_channel::data_write(uint8_t data) } else { - LOG(" Transmitter %s, data byte dropped\n", m_wr5 & WR5_TX_ENABLE ? "not enabled" : "not emptied"); + LOGTX(" Transmitter %s, data byte dropped\n", m_wr5 & WR5_TX_ENABLE ? "not enabled" : "not emptied"); m_rr0 &= ~RR0_TX_BUFFER_EMPTY; } @@ -1176,9 +1282,9 @@ void z80sio_channel::data_write(uint8_t data) //------------------------------------------------- void z80sio_channel::receive_data(uint8_t data) { - LOG("%s(%02x) %s:%c\n",FUNCNAME, data, tag(), 'A' + m_index); + LOGRCV("%s(%02x) %s:%c\n",FUNCNAME, data, tag(), 'A' + m_index); - if (m_rx_fifo == 2) + if (m_rx_data_fifo.full()) { LOG(" Overrun detected\n"); // receive overrun error detected @@ -1201,13 +1307,11 @@ void z80sio_channel::receive_data(uint8_t data) } else { - m_rx_fifo++; + // store received character and error status into FIFO + m_rx_data_fifo.enqueue(data); + m_rx_error_fifo.enqueue(m_rx_error); } - // store received character and error status into FIFO - m_rx_data_fifo[m_rx_fifo] = data; - m_rx_error_fifo[m_rx_fifo] = m_rx_error; - m_rr0 |= RR0_RX_CHAR_AVAILABLE; // receive interrupt diff --git a/src/devices/machine/z80sio.h b/src/devices/machine/z80sio.h index d9169c1285d..badc5501810 100644 --- a/src/devices/machine/z80sio.h +++ b/src/devices/machine/z80sio.h @@ -72,6 +72,10 @@ MCFG_DEVICE_ADD(_tag, UPD7201N, _clock) \ MCFG_Z80SIO_OFFSETS(_rxa, _txa, _rxb, _txb) +#define MCFG_I8274_ADD(_tag, _clock, _rxa, _txa, _rxb, _txb) \ + MCFG_DEVICE_ADD(_tag, I8274N, _clock) \ + MCFG_Z80SIO_OFFSETS(_rxa, _txa, _rxb, _txb) + /* Generic macros */ #define MCFG_Z80SIO_OFFSETS(_rxa, _txa, _rxb, _txb) \ z80sio_device::configure_channels(*device, _rxa, _txa, _rxb, _txb); @@ -79,6 +83,9 @@ #define MCFG_Z80SIO_OUT_INT_CB(_devcb) \ devcb = &z80sio_device::set_out_int_callback(*device, DEVCB_##_devcb); +#define MCFG_Z80SIO_CPU(_cputag) \ + z80sio_device::static_set_cputag(*device, _cputag); + // Port A callbacks #define MCFG_Z80SIO_OUT_TXDA_CB(_devcb) \ devcb = &z80sio_device::set_out_txda_callback(*device, DEVCB_##_devcb); @@ -212,6 +219,13 @@ protected: INT_SPECIAL }; + enum + { + INT_RCV_SPC_PRI_LVL = 0, + INT_TRANSMIT_PRI_LVL = 1, + INT_EXTERNAL_PRI_LVL = 2 + }; + // Read registers enum { @@ -256,30 +270,30 @@ protected: }; enum - { // TODO: overload SIO functionality - RR2_INT_VECTOR_MASK = 0xff, // SCC channel A, SIO channel B (special case) - RR2_INT_VECTOR_V1 = 0x02, // SIO (special case) /SCC Channel B - RR2_INT_VECTOR_V2 = 0x04, // SIO (special case) /SCC Channel B - RR2_INT_VECTOR_V3 = 0x08 // SIO (special case) /SCC Channel B + { + RR2_INT_VECTOR_MASK = 0xff, + RR2_INT_VECTOR_V1 = 0x02, + RR2_INT_VECTOR_V2 = 0x04, + RR2_INT_VECTOR_V3 = 0x08 }; enum { - WR0_REGISTER_MASK = 0x07, - WR0_COMMAND_MASK = 0x38, - WR0_NULL = 0x00, - WR0_SEND_ABORT = 0x08, // not supported - WR0_RESET_EXT_STATUS = 0x10, - WR0_CHANNEL_RESET = 0x18, - WR0_ENABLE_INT_NEXT_RX = 0x20, - WR0_RESET_TX_INT = 0x28, // not supported - WR0_ERROR_RESET = 0x30, - WR0_RETURN_FROM_INT = 0x38, // not supported - WR0_CRC_RESET_CODE_MASK = 0xc0, // not supported - WR0_CRC_RESET_NULL = 0x00, // not supported - WR0_CRC_RESET_RX = 0x40, // not supported - WR0_CRC_RESET_TX = 0x80, // not supported - WR0_CRC_RESET_TX_UNDERRUN = 0xc0 // not supported + WR0_REGISTER_MASK = 0x07, + WR0_COMMAND_MASK = 0x38, + WR0_NULL = 0x00, + WR0_SEND_ABORT = 0x08, + WR0_RESET_EXT_STATUS = 0x10, + WR0_CHANNEL_RESET = 0x18, + WR0_ENABLE_INT_NEXT_RX = 0x20, + WR0_RESET_TX_INT = 0x28, + WR0_ERROR_RESET = 0x30, + WR0_RETURN_FROM_INT = 0x38, + WR0_CRC_RESET_CODE_MASK = 0xc0, + WR0_CRC_RESET_NULL = 0x00, + WR0_CRC_RESET_RX = 0x40, + WR0_CRC_RESET_TX = 0x80, + WR0_CRC_RESET_TX_UNDERRUN = 0xc0 }; enum @@ -375,10 +389,9 @@ protected: int get_tx_word_length(); // receiver state - uint8_t m_rx_data_fifo[3]; // receive data FIFO - uint8_t m_rx_error_fifo[3]; // receive error FIFO + util::fifo m_rx_data_fifo; + util::fifo m_rx_error_fifo; uint8_t m_rx_error; // current receive error - int m_rx_fifo; // receive FIFO pointer int m_rx_clock; // receive clock pulse count int m_rx_first; // first character received @@ -433,7 +446,13 @@ public: template static devcb_base &set_out_rxdrqb_callback(device_t &device, _Object object) { return downcast(device).m_out_rxdrqb_cb.set_callback(object); } template static devcb_base &set_out_txdrqb_callback(device_t &device, _Object object) { return downcast(device).m_out_txdrqb_cb.set_callback(object); } - static void configure_channels(device_t &device, int rxa, int txa, int rxb, int txb) + static void static_set_cputag(device_t &device, const char *tag) + { + z80sio_device &dev = downcast(device); + dev.m_cputag = tag; + } + + static void configure_channels(device_t &device, int rxa, int txa, int rxb, int txb) { z80sio_device &dev = downcast(device); dev.m_rxca = rxa; @@ -490,13 +509,16 @@ protected: // internal interrupt management void check_interrupts(); void reset_interrupts(); + int get_interrupt_prio(int index, int type); + uint8_t modify_vector(int index, int type); void trigger_interrupt(int index, int state); int get_channel_index(z80sio_channel *ch) { return (ch == m_chanA) ? 0 : 1; } enum { TYPE_Z80SIO = 0x001, - TYPE_UPD7201 = 0x002 + TYPE_UPD7201 = 0x002, + TYPE_I8274 = 0x004 }; enum @@ -533,7 +555,9 @@ protected: devcb_write_line m_out_txdrqb_cb; int m_int_state[8]; // interrupt state + int m_int_source[8]; // interrupt source int m_variant; + const char *m_cputag; }; class upd7201N_device : public z80sio_device @@ -542,9 +566,16 @@ public : upd7201N_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); }; +class i8274N_device : public z80sio_device +{ +public : + i8274N_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); +}; + // device type definition extern const device_type Z80SIO; extern const device_type Z80SIO_CHANNEL; extern const device_type UPD7201N; +extern const device_type I8274N; #endif diff --git a/src/mame/drivers/isbc.cpp b/src/mame/drivers/isbc.cpp index 9e8d648e93d..9e0c9adc31b 100644 --- a/src/mame/drivers/isbc.cpp +++ b/src/mame/drivers/isbc.cpp @@ -25,7 +25,8 @@ able to deal with 256byte sectors so fails to load the irmx 512byte sector image #include "machine/pit8253.h" #include "machine/i8255.h" #include "machine/i8251.h" -#include "machine/z80dart.h" +//#include "machine/z80dart.h" +#include "machine/z80sio.h" #include "bus/centronics/ctronics.h" #include "bus/isbx/isbx.h" #include "machine/isbc_215g.h" @@ -48,7 +49,8 @@ public: required_device m_maincpu; optional_device m_uart8251; - optional_device m_uart8274; +// optional_device m_uart8274; + optional_device m_uart8274; required_device m_pic_0; optional_device m_pic_1; optional_device m_centronics; @@ -58,7 +60,7 @@ public: DECLARE_WRITE_LINE_MEMBER(isbc86_tmr2_w); DECLARE_WRITE_LINE_MEMBER(isbc286_tmr2_w); - DECLARE_WRITE_LINE_MEMBER(isbc_uart8274_irq); +// DECLARE_WRITE_LINE_MEMBER(isbc_uart8274_irq); DECLARE_READ8_MEMBER(get_slave_ack); DECLARE_WRITE8_MEMBER(ppi_c_w); protected: @@ -140,7 +142,7 @@ static ADDRESS_MAP_START(isbc286_io, AS_IO, 16, isbc_state) AM_RANGE(0x00c4, 0x00c7) AM_DEVREADWRITE8("pic_1", pic8259_device, read, write, 0x00ff) AM_RANGE(0x00c8, 0x00cf) AM_DEVREADWRITE8("ppi", i8255_device, read, write, 0x00ff) AM_RANGE(0x00d0, 0x00d7) AM_DEVREADWRITE8("pit", pit8254_device, read, write, 0x00ff) - AM_RANGE(0x00d8, 0x00df) AM_DEVREADWRITE8("uart8274", i8274_device, cd_ba_r, cd_ba_w, 0x00ff) + AM_RANGE(0x00d8, 0x00df) AM_DEVREADWRITE8("uart8274", i8274N_device, cd_ba_r, cd_ba_w, 0x00ff) AM_RANGE(0x0100, 0x0101) AM_DEVWRITE8("isbc_215g", isbc_215g_device, write, 0x00ff) ADDRESS_MAP_END @@ -216,11 +218,13 @@ WRITE8_MEMBER( isbc_state::ppi_c_w ) m_pic_1->ir7_w(0); } +#if 0 WRITE_LINE_MEMBER(isbc_state::isbc_uart8274_irq) { m_uart8274->m1_r(); // always set m_pic_0->ir6_w(state); } +#endif static MACHINE_CONFIG_START( isbc86, isbc_state ) /* basic machine hardware */ @@ -325,7 +329,8 @@ static MACHINE_CONFIG_START( isbc286, isbc_state ) MCFG_PIT8253_CLK0(XTAL_22_1184MHz/18) MCFG_PIT8253_OUT0_HANDLER(DEVWRITELINE("pic_0", pic8259_device, ir0_w)) MCFG_PIT8253_CLK1(XTAL_22_1184MHz/18) - MCFG_PIT8253_OUT1_HANDLER(DEVWRITELINE("uart8274", z80dart_device, rxtxcb_w)) +// MCFG_PIT8253_OUT1_HANDLER(DEVWRITELINE("uart8274", z80dart_device, rxtxcb_w)) + MCFG_PIT8253_OUT1_HANDLER(DEVWRITELINE("uart8274", i8274N_device, rxtxcb_w)) MCFG_PIT8253_CLK2(XTAL_22_1184MHz/18) MCFG_PIT8253_OUT2_HANDLER(WRITELINE(isbc_state, isbc286_tmr2_w)) @@ -344,6 +349,7 @@ static MACHINE_CONFIG_START( isbc286, isbc_state ) MCFG_CENTRONICS_OUTPUT_LATCH_ADD("cent_data_out", "centronics") MCFG_I8274_ADD("uart8274", XTAL_16MHz/4, 0, 0, 0, 0) +#if 0 MCFG_Z80DART_OUT_TXDA_CB(DEVWRITELINE("rs232a", rs232_port_device, write_txd)) MCFG_Z80DART_OUT_DTRA_CB(DEVWRITELINE("rs232a", rs232_port_device, write_dtr)) MCFG_Z80DART_OUT_RTSA_CB(DEVWRITELINE("rs232a", rs232_port_device, write_rts)) @@ -351,16 +357,38 @@ static MACHINE_CONFIG_START( isbc286, isbc_state ) MCFG_Z80DART_OUT_DTRB_CB(DEVWRITELINE("rs232b", rs232_port_device, write_dtr)) MCFG_Z80DART_OUT_RTSB_CB(DEVWRITELINE("rs232b", rs232_port_device, write_rts)) MCFG_Z80DART_OUT_INT_CB(WRITELINE(isbc_state, isbc_uart8274_irq)) +#else + MCFG_Z80SIO_OUT_TXDA_CB(DEVWRITELINE("rs232a", rs232_port_device, write_txd)) + MCFG_Z80SIO_OUT_DTRA_CB(DEVWRITELINE("rs232a", rs232_port_device, write_dtr)) + MCFG_Z80SIO_OUT_RTSA_CB(DEVWRITELINE("rs232a", rs232_port_device, write_rts)) + MCFG_Z80SIO_OUT_TXDB_CB(DEVWRITELINE("rs232b", rs232_port_device, write_txd)) + MCFG_Z80SIO_OUT_DTRB_CB(DEVWRITELINE("rs232b", rs232_port_device, write_dtr)) + MCFG_Z80SIO_OUT_RTSB_CB(DEVWRITELINE("rs232b", rs232_port_device, write_rts)) +// MCFG_Z80SIO_OUT_INT_CB(WRITELINE(isbc_state, isbc_uart8274_irq)) + MCFG_Z80SIO_OUT_INT_CB(DEVWRITELINE("pic_0", pic8259_device, ir6_w)) +#endif MCFG_RS232_PORT_ADD("rs232a", default_rs232_devices, nullptr) +#if 0 MCFG_RS232_RXD_HANDLER(DEVWRITELINE("uart8274", z80dart_device, rxa_w)) MCFG_RS232_DCD_HANDLER(DEVWRITELINE("uart8274", z80dart_device, dcda_w)) MCFG_RS232_CTS_HANDLER(DEVWRITELINE("uart8274", z80dart_device, ctsa_w)) +#else + MCFG_RS232_RXD_HANDLER(DEVWRITELINE("uart8274", i8274N_device, rxa_w)) + MCFG_RS232_DCD_HANDLER(DEVWRITELINE("uart8274", i8274N_device, dcda_w)) + MCFG_RS232_CTS_HANDLER(DEVWRITELINE("uart8274", i8274N_device, ctsa_w)) +#endif MCFG_RS232_PORT_ADD("rs232b", default_rs232_devices, "terminal") +#if 0 MCFG_RS232_RXD_HANDLER(DEVWRITELINE("uart8274", z80dart_device, rxb_w)) MCFG_RS232_DCD_HANDLER(DEVWRITELINE("uart8274", z80dart_device, dcdb_w)) MCFG_RS232_CTS_HANDLER(DEVWRITELINE("uart8274", z80dart_device, ctsb_w)) +#else + MCFG_RS232_RXD_HANDLER(DEVWRITELINE("uart8274", i8274N_device, rxb_w)) + MCFG_RS232_DCD_HANDLER(DEVWRITELINE("uart8274", i8274N_device, dcdb_w)) + MCFG_RS232_CTS_HANDLER(DEVWRITELINE("uart8274", i8274N_device, ctsb_w)) +#endif MCFG_DEVICE_CARD_DEVICE_INPUT_DEFAULTS("terminal", isbc286_terminal) MCFG_ISBX_SLOT_ADD("sbx1", 0, isbx_cards, nullptr) @@ -413,6 +441,78 @@ ROM_START( isbc286 ) ROM_LOAD16_BYTE( "u36.bin", 0x00000, 0x10000, CRC(22db075f) SHA1(fd29ea77f5fc0697c8f8b66aca549aad5b9db3ea)) ROM_END +/* + * :uart8274 A Reg 00 <- 18 - Channel reset command + * :uart8274 A Reg 04 <- 44 - x16 clock, 1 stop bit, no parity + * :uart8274 A Reg 05 <- ea - Tx Enabled, Tx 8 bits, Send Break 0, RTS=0, ?? - Read out Status Register 1 (Errors and All Sent flag) + * :uart8274 A Reg 05 <- e2 - Tx Disabled, Tx 8 bits, Send Break 0, RTS=0, DTR=0 + * :uart8274 A Reg 03 <- c0 - Rx Disabled, Rx 8 bits, No Auto Enables + * :uart8274 A Reg 05 <- ea - Tx Enabled, Tx 8 bits, Send Break 0, RTS=0, DTR=0 + * :uart8274 A Reg 04 <- 4e - x16 clock, 2 stop bit, even parity but parity disabled + * :uart8274 A Reg 05 <- ea - Tx Enabled, Tx 8 bits, Send Break 0, RTS=0, DTR=0 + * :uart8274 A Reg 03 <- c1 - Rx Enabled, Rx 8 bits, No Auto Enables + * :uart8274 A Reg 07 <- 00 - Hi SYNC bits + * :uart8274 A Reg 06 <- 00 - Lo SYNC bits + * :uart8274 A Reg 02 <- 04 - RTSB selected, non vectored mode, 85-1 mode selected, A over B interleaved int prios + * :uart8274 B Reg 02 <- 26 - interrupt vector 26 + * :uart8274 A Reg 01 <- 00 - Rx INT/DMA int disabled, no vector modification + * :uart8274 A Reg 02 <- 04 - RTSB selected, non vectored mode, 85-1 mode selected, A over B interleaved int prios + + * :uart8274 B Reg 02 <- a5 - interrupt vector a5 + * :uart8274 B Reg 02 <- 00 - interrupt vector 0 + + * :uart8274 B Reg 04 <- 44 - x16 clock, 1 stop bit, no parity + * :uart8274 B Reg 01 <- 1e - Wait disabled, Int mode 3, vector modified, Tx int/DMA enabled + * :uart8274 A Reg 04 <- 44 - x16 clock, 1 stop bit, no parity + * :uart8274 A Reg 01 <- 1e - Wait disabled, Int mode 3, vector modified, Tx int/DMA enabled + + * :uart8274 B Reg 04 <- 44 - x16 clock, 1 stop bit, no parity + * :uart8274 B Reg 01 <- 1e - Wait disabled, Int mode 3, vector modified, Tx int/DMA enabled + * :uart8274 B Reg 03 <- c1 - Rx Enabled, Rx 8 bits, No Auto Enables + * :uart8274 B Reg 05 <- ea - Tx Enabled, Tx 8 bits, Send Break 0, RTS=0, DTR=0 + + * :uart8274 B Reg 04 <- 44 - x16 clock, 1 stop bit, no parity + * :uart8274 B Reg 01 <- 1e - Wait disabled, Int mode 3, vector modified, Tx int/DMA enabled + * :uart8274 B Reg 03 <- c1 - Rx Enabled, Rx 8 bits, No Auto Enables + * :uart8274 B Reg 05 <- ea - Tx Enabled, Tx 8 bits, Send Break 0, RTS=0, DTR=0 +*/ ROM_START( isbc2861 ) ROM_REGION( 0x10000, "user1", ROMREGION_ERASEFF ) ROM_SYSTEM_BIOS( 0, "v11", "iSDM Monitor V1.1" )