Merge branch 'isbc2861_1' into isbc2861_2

This commit is contained in:
Joakim Larsson Edstrom 2017-03-19 01:16:38 +01:00
commit d0cda52d75
3 changed files with 436 additions and 201 deletions

View File

@ -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<z80sio_device>;
const device_type Z80SIO_CHANNEL = device_creator<z80sio_channel>;
const device_type UPD7201N = device_creator<upd7201N_device>; // Remove trailing N when z80dart.cpp's 7201 implementation is fully replaced
const device_type I8274N = device_creator<i8274N_device>; // 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<cpu_device>(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<char const *, 4>
{{"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<char const *, 3>
{{"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<char const *, 8>
{{"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

View File

@ -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<uint8_t, 3> m_rx_data_fifo;
util::fifo<uint8_t, 3> 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<class _Object> static devcb_base &set_out_rxdrqb_callback(device_t &device, _Object object) { return downcast<z80sio_device &>(device).m_out_rxdrqb_cb.set_callback(object); }
template<class _Object> static devcb_base &set_out_txdrqb_callback(device_t &device, _Object object) { return downcast<z80sio_device &>(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<z80sio_device &>(device);
dev.m_cputag = tag;
}
static void configure_channels(device_t &device, int rxa, int txa, int rxb, int txb)
{
z80sio_device &dev = downcast<z80sio_device &>(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

View File

@ -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<cpu_device> m_maincpu;
optional_device<i8251_device> m_uart8251;
optional_device<i8274_device> m_uart8274;
// optional_device<i8274_device> m_uart8274;
optional_device<i8274N_device> m_uart8274;
required_device<pic8259_device> m_pic_0;
optional_device<pic8259_device> m_pic_1;
optional_device<centronics_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, <DTR=0
* :uart8274 A Reg 03 <- c1 - Rx Enabled, Rx 8 bits, No Auto Enable
* :uart8274 B Reg 00 <- 18 - Channel reset command
* :uart8274 B Reg 04 <- 44 - x16 clock, 1 stop bit, no parity
* :uart8274 B Reg 05 <- ea - Tx Enabled, Transmitter Bits/Character 8, Send Break 0, RTS=0, DTR=0
* :uart8274 B Reg 03 <- c1 - Rx 8 bits, No Auto Enables, Rx Enabled,
* :uart8274 B Reg 00 <- 18 - Channel reset command
* :uart8274 B Reg 04 <- 4e - x16 clock, 2 stop bit, even parity but parity disabled
* :uart8274 B Reg 05 <- ea - Tx Enabled, Tx 8 bits, Send Break 0, RTS=0, DTR=0
* :uart8274 B Reg 03 <- c1 - Rx Enabled, Rx 8 bits, No Auto Enables
* :uart8274 B Reg 07 <- 00 - Hi SYNC bits
* :uart8274 B 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 B Reg 01 <- 00 - Rx INT/DMA int disabled, no vector modification
* :uart8274 B Reg 00 <- 18 - Channel reset command
* :uart8274 B Reg 00 <- 18 - Channel reset command
* :uart8274 B Reg 04 <- 44 - x16 clock, 1 stop bit, no parity
* :uart8274 B Reg 05 <- ea - Tx Enabled, Tx 8 bits, Send Break 0, RTS=0, DTR=0
* :uart8274 B Reg 03 <- c1 - Rx Enabled, Rx 8 bits, No Auto Enables
* :uart8274 B Reg 00 <- 28 - Reset Transmitter Interrupt Pending
* :uart8274 B Reg 00 <- 28 - Reset Transmitter Interrupt Pending
* :uart8274 B Reg 00 <- 28 - Reset Transmitter Interrupt Pending
* :uart8274 B Reg 00 <- 28 - Reset Transmitter Interrupt Pending
* :uart8274 A Reg 00 <- 18 - Channel reset command
* :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 01 -> ?? - 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" )