WIP: Intergraph driver support: Enabled more Rx interrupts and fixed error fifo

This commit is contained in:
Joakim Larsson Edstrom 2016-11-30 17:30:00 +01:00
parent 7d401c1ad9
commit 86ca7dcf60

View File

@ -81,14 +81,15 @@ DONE (x) (p=partly) NMOS CMOS ESCC EMSCC
#define VERBOSE 0 #define VERBOSE 0
#define LOGPRINT(x) do { if (VERBOSE) logerror x; } while (0) #define LOGPRINT(x) do { if (VERBOSE) logerror x; } while (0)
#define LOG(x) {} LOGPRINT(x) #define LOG(x) {} LOGPRINT(x)
#define LOGR(x) {} LOGPRINT(x) #define LOGR(x) {}
#define LOGSETUP(x) {} LOGPRINT(x) #define LOGSETUP(x) {} LOGPRINT(x)
#define LOGINT(x) {} LOGPRINT(x) #define LOGINT(x) {}
#define LOGTX(x) {} LOGPRINT(x) #define LOGCMD(x) {}
#define LOGRCV(x) {} LOGPRINT(x) #define LOGTX(x) {}
#define LOGCTS(x) {} LOGPRINT(x) #define LOGRCV(x) {}
#define LOGDCD(x) {} LOGPRINT(x) #define LOGCTS(x) {}
#define LOGSYNC(x) {} LOGPRINT(x) #define LOGDCD(x) {}
#define LOGSYNC(x) {}
#if VERBOSE == 2 #if VERBOSE == 2
#define logerror printf #define logerror printf
#endif #endif
@ -1321,7 +1322,7 @@ uint8_t z80scc_channel::do_sccreg_rr0()
{ {
uint8_t rr0 = m_rr0; uint8_t rr0 = m_rr0;
LOGINT(("%s %c %s <- %02x\n",tag(), 'A' + m_index, FUNCNAME, m_rr0)); LOG(("%s %c %s <- %02x\n",tag(), 'A' + m_index, FUNCNAME, m_rr0));
if (m_extint_latch == 1) if (m_extint_latch == 1)
{ {
rr0 &= ((~m_wr15) | WR15_WR7PRIME | WR15_STATUS_FIFO); // clear enabled bits, saving 2 unrelated bits rr0 &= ((~m_wr15) | WR15_WR7PRIME | WR15_STATUS_FIFO); // clear enabled bits, saving 2 unrelated bits
@ -1330,7 +1331,7 @@ uint8_t z80scc_channel::do_sccreg_rr0()
} }
else else
{ {
LOGINT(("- %c returning unlatched value: %02x\n", 'A' + m_index, rr0)); LOG(("- %c returning unlatched value: %02x\n", 'A' + m_index, rr0));
} }
return rr0; return rr0;
@ -1626,30 +1627,6 @@ uint8_t z80scc_channel::control_read()
return data; return data;
} }
/* CRC Initialization Code handling - candidate for breaking out in a z80sio_base class
Handle the WR0 CRC Reset/Init bits separatelly, needed by derived devices separatelly from the commands */
void z80scc_channel::do_sccreg_wr0_resets(uint8_t data)
{
LOG(("%s(%02x) %s",FUNCNAME, data, tag()));
switch (data & WR0_CRC_RESET_CODE_MASK)
{
case WR0_CRC_RESET_NULL:
LOG((" CRC_RESET_NULL\n"));
break;
case WR0_CRC_RESET_RX: /* In Synchronous mode: all Os (zeros) (CCITT-O CRC-16) */
LOGSYNC((" CRC_RESET_RX - not implemented\n"));
break;
case WR0_CRC_RESET_TX: /* In HDLC mode: all 1s (ones) (CCITT-1) */
LOGSYNC((" CRC_RESET_TX - not implemented\n"));
break;
case WR0_CRC_RESET_TX_UNDERRUN: /* Resets Tx underrun/EOM bit (D6 of the RRO register) */
LOGSYNC((" CRC_RESET_TX_UNDERRUN - not implemented\n"));
break;
default: /* Will not happen unless someone messes with the mask */
logerror(" Wrong CRC reset/init command:%02x\n", data & WR0_CRC_RESET_CODE_MASK);
}
}
/**/ /**/
void z80scc_channel::do_sccreg_wr0(uint8_t data) void z80scc_channel::do_sccreg_wr0(uint8_t data)
{ {
@ -1688,7 +1665,7 @@ void z80scc_channel::do_sccreg_wr0(uint8_t data)
(there are two transitions), another interrupt is not generated. Exceptions to this (there are two transitions), another interrupt is not generated. Exceptions to this
rule are detailed in the RR0 description.*/ rule are detailed in the RR0 description.*/
LOGINT(("%s %s %c - Reset External/Status Interrupt, latch %s\n", m_owner->tag(), FUNCNAME, 'A' + m_index, LOGCMD(("%s %c - Reset External/Status Interrupt, latch %s\n", m_owner->tag(), 'A' + m_index,
m_extint_latch == 1? "is released" : "was already released")); m_extint_latch == 1? "is released" : "was already released"));
// Release latch if no other external or status sources are active // Release latch if no other external or status sources are active
if ((m_extint_latch = m_uart->update_extint(m_index)) == 0) if ((m_extint_latch = m_uart->update_extint(m_index)) == 0)
@ -1702,18 +1679,18 @@ void z80scc_channel::do_sccreg_wr0(uint8_t data)
if (m_uart->m_variant & (SET_NMOS)) if (m_uart->m_variant & (SET_NMOS))
{ {
logerror("WR0 SWI ack command not supported on NMOS\n"); logerror("WR0 SWI ack command not supported on NMOS\n");
LOGINT(("\"%s\" %s: %c : Reset Highest IUS command not available on NMOS!\n", m_owner->tag(), FUNCNAME, 'A' + m_index)); LOGCMD(("%s: %c : WR0_RESET_HIGHEST_IUS command not available on NMOS!\n", m_owner->tag(), 'A' + m_index));
} }
else else
{ {
LOGINT(("\"%s\" %s: %c : Reset Highest IUS\n", m_owner->tag(), FUNCNAME, 'A' + m_index)); LOGCMD(("%s: %c : Reset Highest IUS\n", m_owner->tag(), 'A' + m_index));
// loop over all interrupt sources // loop over all interrupt sources
for (auto & elem : m_uart->m_int_state) for (auto & elem : m_uart->m_int_state)
{ {
// find the first channel with an interrupt requested // find the first channel with an interrupt requested
if (elem & Z80_DAISY_INT) if (elem & Z80_DAISY_INT)
{ {
LOGINT(("- %c found IUS bit to clear\n", 'A' + m_index)); LOGCMD(("- %c found IUS bit to clear\n", 'A' + m_index));
elem = 0; // Clear IUS bit (called IEO in z80 daisy lingo) elem = 0; // Clear IUS bit (called IEO in z80 daisy lingo)
m_uart->check_interrupts(); m_uart->check_interrupts();
break; break;
@ -1727,30 +1704,44 @@ void z80scc_channel::do_sccreg_wr0(uint8_t data)
data with the special condition is held in the Receive FIFO until this command is issued. If either data with the special condition is held in the Receive FIFO until this command is issued. If either
of these modes is selected and this command is issued before the data has been read from the of these modes is selected and this command is issued before the data has been read from the
Receive FIFO, the data is lost */ Receive FIFO, the data is lost */
LOG(("\"%s\" %s: %c : WR0_ERROR_RESET\n", m_owner->tag(), FUNCNAME, 'A' + m_index)); LOGCMD(("%s: %c : WR0_ERROR_RESET - not implemented\n", m_owner->tag(), 'A' + m_index));
//do_sccreg_wr0(data); // reset status registers
m_rx_fifo_rp_step(); // Reset error state in fifo and unlock it. unlock == step to next slot in fifo. m_rx_fifo_rp_step(); // Reset error state in fifo and unlock it. unlock == step to next slot in fifo.
break; break;
case WR0_SEND_ABORT: case WR0_SEND_ABORT: // Flush transmitter and Send 8-13 bits of '1's, used with SDLC
data &= 0xef; // convert SCC SEND_ABORT command to a SIO SEND_ABORT command and fall through LOGCMD(("%s: %c : WR0_SEND_ABORT - not implemented\n", m_owner->tag(), 'A' + m_index));
/* The following commands relies on the SIO default behviour */
case WR0_NULL:
LOG(("\"%s\" Channel %c : Null\n", m_owner->tag(), 'A' + m_index));
break; break;
case WR0_ENABLE_INT_NEXT_RX: case WR0_NULL: // Do nothing
// enable interrupt on next receive character LOGCMD(("%s: %c : WR0_NULL\n", m_owner->tag(), 'A' + m_index));
LOG(("\"%s\" Channel %c : Enable Interrupt on Next Received Character\n", m_owner->tag(), 'A' + m_index)); break;
case WR0_ENABLE_INT_NEXT_RX: // enable interrupt on next receive character
LOGCMD(("%s: %c : WR0_ENABLE_INT_NEXT\n", m_owner->tag(), 'A' + m_index));
m_rx_first = 1; m_rx_first = 1;
break; break;
case WR0_RESET_TX_INT: case WR0_RESET_TX_INT: // reset transmitter interrupt pending
// reset transmitter interrupt pending LOGCMD(("%s: %c : WR0_RESET_TX_INT - not implemented\n", m_owner->tag(), 'A' + m_index));
LOG(("\"%s\" Channel %c : Reset Transmitter Interrupt Pending\n", m_owner->tag(), 'A' + m_index));
logerror("\"%s\" Channel %c : unsupported command: Reset Transmitter Interrupt Pending\n", m_owner->tag(), 'A' + m_index);
break; break;
default: default:
break; break;
} }
do_sccreg_wr0_resets(data);
/* CRC Initialization Code handling */
switch (data & WR0_CRC_RESET_CODE_MASK)
{
case WR0_CRC_RESET_NULL:
LOGCMD((" CRC_RESET_NULL\n"));
break;
case WR0_CRC_RESET_RX: /* In Synchronous mode: all Os (zeros) (CCITT-O CRC-16) */
LOGCMD((" CRC_RESET_RX - not implemented\n"));
break;
case WR0_CRC_RESET_TX: /* In HDLC mode: all 1s (ones) (CCITT-1) */
LOGCMD((" CRC_RESET_TX - not implemented\n"));
break;
case WR0_CRC_RESET_TX_UNDERRUN: /* Resets Tx underrun/EOM bit (D6 of the RRO register) */
LOGCMD((" CRC_RESET_TX_UNDERRUN - not implemented\n"));
break;
default: /* Will not happen unless someone messes with the mask */
logerror(" Wrong CRC reset/init command:%02x\n", data & WR0_CRC_RESET_CODE_MASK);
}
if ( m_uart->m_variant & SET_Z85X3X) if ( m_uart->m_variant & SET_Z85X3X)
{ {
@ -2278,26 +2269,13 @@ uint8_t z80scc_channel::data_read()
data = m_rx_fifo_rp_data(); data = m_rx_fifo_rp_data();
// load error status from the FIFO // 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_rp]; // TODO: Status FIFO needs to be fixed m_rr1 = (m_rr1 & ~(RR1_CRC_FRAMING_ERROR | RR1_RX_OVERRUN_ERROR | RR1_PARITY_ERROR)) | m_rx_error_fifo[m_rx_fifo_rp];
// trigger interrup and lock the fifo if an error is present // trigger interrupt and lock the fifo if an error is present
if (m_rr1 & (RR1_CRC_FRAMING_ERROR | RR1_RX_OVERRUN_ERROR | RR1_PARITY_ERROR)) if (m_rr1 & (RR1_CRC_FRAMING_ERROR | RR1_RX_OVERRUN_ERROR | RR1_PARITY_ERROR))
{ {
logerror("Rx Error %02x\n", m_rr1 & (RR1_CRC_FRAMING_ERROR | RR1_RX_OVERRUN_ERROR | RR1_PARITY_ERROR)); logerror("Rx Error %02x\n", m_rr1 & (RR1_CRC_FRAMING_ERROR | RR1_RX_OVERRUN_ERROR | RR1_PARITY_ERROR));
switch (m_wr1 & WR1_RX_INT_MODE_MASK) m_uart->trigger_interrupt(m_index, INT_SPECIAL);
{
case WR1_RX_INT_FIRST:
if (!m_rx_first)
{
m_uart->trigger_interrupt(m_index, INT_SPECIAL);
}
break;
case WR1_RX_INT_ALL_PARITY:
case WR1_RX_INT_ALL:
m_uart->trigger_interrupt(m_index, INT_SPECIAL);
break;
}
} }
else else
{ {
@ -2446,22 +2424,30 @@ void z80scc_channel::data_write(uint8_t data)
//------------------------------------------------- //-------------------------------------------------
// receive_data - receive data word into fifo // receive_data - put received data word into fifo
//------------------------------------------------- //-------------------------------------------------
void z80scc_channel::receive_data(uint8_t data) void z80scc_channel::receive_data(uint8_t data)
{ {
LOG(("\"%s\": %c : Receive Data Byte '%02x'\n", m_owner->tag(), 'A' + m_index, data)); LOG(("\"%s\": %c : Received Data Byte '%c'/%02x put into FIFO\n", m_owner->tag(), 'A' + m_index, isprint(data) ? data : ' ', data));
if (m_rx_fifo_wp + 1 == m_rx_fifo_rp || ( (m_rx_fifo_wp + 1 == m_rx_fifo_sz) && (m_rx_fifo_rp == 0) )) if (m_rx_fifo_wp + 1 == m_rx_fifo_rp || ( (m_rx_fifo_wp + 1 == m_rx_fifo_sz) && (m_rx_fifo_rp == 0) ))
{ {
// receive overrun error detected // receive overrun error detected
m_rx_error_fifo[m_rx_fifo_wp] |= RR1_RX_OVERRUN_ERROR; // = m_rx_error; TODO: Status FIFO needs to be fixed m_rx_error_fifo[m_rx_fifo_wp] |= RR1_RX_OVERRUN_ERROR;
// store received character but do not step the fifo
m_rx_data_fifo[m_rx_fifo_wp] = data;
logerror("Receive_data() Error %02x\n", m_rx_error_fifo[m_rx_fifo_wp] & (RR1_CRC_FRAMING_ERROR | RR1_RX_OVERRUN_ERROR | RR1_PARITY_ERROR)); logerror("Receive_data() Error %02x\n", m_rx_error_fifo[m_rx_fifo_wp] & (RR1_CRC_FRAMING_ERROR | RR1_RX_OVERRUN_ERROR | RR1_PARITY_ERROR));
} }
else else
{ {
m_rx_error_fifo[m_rx_fifo_wp] &= ~RR1_RX_OVERRUN_ERROR; // = m_rx_error; TODO: Status FIFO needs to be fixed m_rx_error_fifo[m_rx_fifo_wp] &= ~RR1_RX_OVERRUN_ERROR;
// store received character
m_rx_data_fifo[m_rx_fifo_wp] = data;
m_rx_fifo_wp++; m_rx_fifo_wp++;
if (m_rx_fifo_wp >= m_rx_fifo_sz) if (m_rx_fifo_wp >= m_rx_fifo_sz)
{ {
@ -2469,13 +2455,9 @@ void z80scc_channel::receive_data(uint8_t data)
} }
} }
// store received character
m_rx_data_fifo[m_rx_fifo_wp] = data;
m_rr0 |= RR0_RX_CHAR_AVAILABLE; m_rr0 |= RR0_RX_CHAR_AVAILABLE;
#if 0 // interrupt on exit from fifo // receive interrupt on FIRST and ALL character
// receive interrupt
switch (m_wr1 & WR1_RX_INT_MODE_MASK) switch (m_wr1 & WR1_RX_INT_MODE_MASK)
{ {
case WR1_RX_INT_FIRST: case WR1_RX_INT_FIRST:
@ -2487,12 +2469,10 @@ void z80scc_channel::receive_data(uint8_t data)
} }
break; break;
case WR1_RX_INT_ALL_PARITY:
case WR1_RX_INT_ALL: case WR1_RX_INT_ALL:
m_uart->trigger_interrupt(m_index, INT_RECEIVE); m_uart->trigger_interrupt(m_index, INT_RECEIVE);
break; break;
} }
#endif
} }