3b2: Initial CONTTY support

This commit is contained in:
Seth Morabito 2017-12-09 21:30:25 -08:00
parent 7cd1b27b08
commit d5f8a84493
4 changed files with 247 additions and 212 deletions

View file

@ -55,8 +55,8 @@ DEVICE dmac_dev = {
dmac_drq_handler dmac_drq_handlers[] = {
{DMA_ID_CHAN, IDBASE+ID_DATA_REG, &id_drq, id_drq_handled},
{DMA_IF_CHAN, IFBASE+IF_DATA_REG, &if_state.drq, if_drq_handled},
{DMA_IUA_CHAN, IUBASE+IUA_DATA_REG, &iu_port_a.drq, iua_drq_handled},
{DMA_IUB_CHAN, IUBASE+IUB_DATA_REG, &iu_port_b.drq, iub_drq_handled},
{DMA_IUA_CHAN, IUBASE+IUA_DATA_REG, &iu_console.drq, iua_drq_handled},
{DMA_IUB_CHAN, IUBASE+IUB_DATA_REG, &iu_contty.drq, iub_drq_handled},
{0, 0, NULL, NULL }
};

View file

@ -29,6 +29,7 @@
*/
#include "3b2_iu.h"
#include "sim_tmxr.h"
/*
* The 3B2/400 has two on-board serial ports, labeled CONSOLE and
@ -42,12 +43,11 @@
* In addition to the two TX/RX ports, the SCN27681A also has one
* programmable timer.
*
* The SCN2681A UART is represented here by five devices:
* The SCN2681A UART is represented here by four devices:
*
* - Console TTI (Input, port A)
* - Console TTO (Output, port A)
* - Contty TTI (Input, port B)
* - Contty TTO (Output, port B)
* - Contty (I/O, port B. Terminal multiplexer with one line)
* - IU Timer
*/
@ -60,8 +60,8 @@
IU_STATE iu_state;
/* The tx/rx state for ports A and B */
IU_PORT iu_port_a;
IU_PORT iu_port_b;
IU_PORT iu_console;
IU_PORT iu_contty;
/* The timer state */
IU_TIMER_STATE iu_timer_state;
@ -112,84 +112,89 @@ BITFIELD conf_bits[] = {
ENDBITS
};
/* TTI (Port A) data structures */
/* TTI (Console) data structures */
REG tti_a_reg[] = {
{ HRDATADF(STAT, iu_port_a.stat, 8, "Status", sr_bits) },
{ HRDATADF(CONF, iu_port_a.conf, 8, "Config", conf_bits) },
{ BRDATAD(DATA, iu_port_a.rxbuf, 16, 8, IU_BUF_SIZE, "Data") },
REG tti_reg[] = {
{ HRDATADF(STAT, iu_console.stat, 8, "Status", sr_bits) },
{ HRDATADF(CONF, iu_console.conf, 8, "Config", conf_bits) },
{ BRDATAD(DATA, iu_console.rxbuf, 16, 8, IU_BUF_SIZE, "Data") },
{ NULL }
};
UNIT tti_a_unit = { UDATA(&iu_svc_tti_a, UNIT_IDLE, 0), TMLN_SPD_9600_BPS };
UNIT tti_unit = { UDATA(&iu_svc_tti, UNIT_IDLE, 0), TMLN_SPD_9600_BPS };
DEVICE tti_a_dev = {
"TTIA", &tti_a_unit, tti_a_reg, NULL,
DEVICE tti_dev = {
"TTI", &tti_unit, tti_reg, NULL,
1, 8, 32, 1, 8, 8,
NULL, NULL, &tti_a_reset,
NULL, NULL, &tti_reset,
NULL, NULL, NULL, NULL,
DEV_DEBUG, 0, sys_deb_tab
};
/* TTO (Port A) data structures */
/* TTO (Console) data structures */
REG tto_a_reg[] = {
{ HRDATADF(STAT, iu_port_a.stat, 8, "Status", sr_bits) },
REG tto_reg[] = {
{ HRDATADF(STAT, iu_console.stat, 8, "Status", sr_bits) },
{ HRDATADF(ISTAT, iu_state.istat, 8, "Interrupt Status", isr_bits) },
{ HRDATAD(IMR, iu_state.imr, 8, "Interrupt Mask") },
{ HRDATADF(ACR, iu_state.acr, 8, "Auxiliary Control Register", acr_bits) },
{ HRDATAD(DATA, iu_port_a.txbuf, 8, "Data") },
{ HRDATAD(DATA, iu_console.txbuf, 8, "Data") },
{ NULL }
};
UNIT tto_a_unit = { UDATA(&iu_svc_tto_a, TT_MODE_8B, 0), SERIAL_OUT_WAIT };
UNIT tto_unit = { UDATA(&iu_svc_tto, TT_MODE_8B, 0), SERIAL_OUT_WAIT };
DEVICE tto_a_dev = {
"TTOA", &tto_a_unit, tto_a_reg, NULL,
DEVICE tto_dev = {
"TTO", &tto_unit, tto_reg, NULL,
1, 8, 32, 1, 8, 8,
NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
DEV_DEBUG, 0, sys_deb_tab
};
/* TTI (Port B) data structures */
/* CONTTY data structures */
REG tti_b_reg[] = {
{ HRDATADF(STAT, iu_port_b.stat, 8, "Status", sr_bits) },
{ HRDATADF(CONF, iu_port_b.conf, 8, "Config", conf_bits) },
{ BRDATAD(DATA, iu_port_b.rxbuf, 16, 8, IU_BUF_SIZE, "Data") },
{ NULL }
};
/*
* The CONTTY "multiplexer" is a bit unusual in that it serves only a
* single line, representing the built-in CONTTY port. On a real
* 3B2/400, the system board's dual UART serves both CONSOLE and
* CONTTY lines, giving support for two terminals. In the simulator,
* the CONSOLE is served by TTI and TTO devices, whereas the CONTTY is
* served by a TMXR multiplexer.
*/
UNIT tti_b_unit = { UDATA(&iu_svc_tti_b, UNIT_IDLE, 0), TMLN_SPD_9600_BPS };
TMLN *contty_ldsc = NULL;
TMXR contty_desc = { 1, 0, 0, NULL };
DEVICE tti_b_dev = {
"TTIB", &tti_b_unit, tti_b_reg, NULL,
1, 8, 32, 1, 8, 8,
NULL, NULL, &tti_b_reset,
NULL, NULL, NULL, NULL,
DEV_DEBUG, 0, sys_deb_tab
};
/* TTO (Port B) data structures */
REG tto_b_reg[] = {
{ HRDATADF(STAT, iu_port_b.stat, 8, "Status", sr_bits) },
REG contty_reg[] = {
{ HRDATADF(STAT, iu_contty.stat, 8, "Status", sr_bits) },
{ HRDATADF(CONF, iu_contty.conf, 8, "Config", conf_bits) },
{ BRDATAD(RXDATA, iu_contty.rxbuf, 16, 8, IU_BUF_SIZE, "RX Data") },
{ HRDATAD(TXDATA, iu_contty.txbuf, 8, "TX Data") },
{ HRDATADF(ISTAT, iu_state.istat, 8, "Interrupt Status", isr_bits) },
{ HRDATAD(IMR, iu_state.imr, 8, "Interrupt Mask") },
{ HRDATADF(ACR, iu_state.acr, 8, "Auxiliary Control Register", acr_bits) },
{ HRDATAD(DATA, iu_port_b.txbuf, 8, "Data") },
{ NULL }
};
UNIT tto_b_unit = { UDATA(&iu_svc_tto_b, TT_MODE_8B, 0), SERIAL_OUT_WAIT };
UNIT contty_unit[2] = {
{ UDATA(&iu_svc_contty, UNIT_IDLE|UNIT_ATTABLE, 0) },
{ UDATA(&iu_svc_contty_xmt, UNIT_DIS, 0), SERIAL_OUT_WAIT }
};
DEVICE tto_b_dev = {
"TTOB", &tto_b_unit, tto_b_reg, NULL,
UNIT *contty_rcv_unit = &contty_unit[0];
UNIT *contty_xmt_unit = &contty_unit[1];
DEVICE contty_dev = {
"CONTTY", contty_unit, contty_reg, NULL,
1, 8, 32, 1, 8, 8,
NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
DEV_DEBUG, 0, sys_deb_tab
&tmxr_ex, &tmxr_dep, &contty_reset,
NULL, &contty_attach, &contty_detach,
NULL, DEV_DISABLE|DEV_DEBUG|DEV_MUX,
0, sys_deb_tab, NULL, NULL,
NULL, NULL,
(void *)&contty_desc,
NULL
};
/* IU Timer data structures */
@ -209,68 +214,95 @@ DEVICE iu_timer_dev = {
DEV_DEBUG, 0, sys_deb_tab
};
t_stat contty_attach(UNIT *uptr, CONST char *cptr)
{
t_stat r = tmxr_attach(&contty_desc, uptr, cptr);
TMLN *lp;
if (r != SCPE_OK) {
tmxr_clear_modem_control_passthru(&contty_desc);
return r;
}
lp = &contty_ldsc[0];
tmxr_set_get_modem_bits(lp, TMXR_MDM_DTR|TMXR_MDM_RTS, 0, NULL);
return SCPE_OK;
}
t_stat contty_detach(UNIT *uptr)
{
t_stat r = tmxr_detach(&contty_desc, uptr);
tmxr_clear_modem_control_passthru(&contty_desc);
return r;
}
void increment_modep_a()
{
iu_increment_a = FALSE;
iu_port_a.modep++;
iu_console.modep++;
if (iu_port_a.modep > 1) {
iu_port_a.modep = 0;
if (iu_console.modep > 1) {
iu_console.modep = 0;
}
}
void increment_modep_b()
{
iu_increment_b = FALSE;
iu_port_b.modep++;
iu_contty.modep++;
if (iu_port_b.modep > 1) {
iu_port_b.modep = 0;
if (iu_contty.modep > 1) {
iu_contty.modep = 0;
}
}
void iu_txrdy_a_irq() {
if ((iu_state.imr & ISTS_TAI) &&
(iu_port_a.conf & TX_EN) &&
(iu_port_a.stat & STS_TXR)) {
sim_debug(EXECUTE_MSG, &tto_a_dev,
"Firing IU TTY IRQ 13 ON TX/State Change: PORT A\n");
(iu_console.conf & TX_EN) &&
(iu_console.stat & STS_TXR)) {
csr_data |= CSRUART;
}
}
void iu_txrdy_b_irq() {
if ((iu_state.imr & ISTS_TBI) &&
(iu_port_b.conf & TX_EN) &&
(iu_port_b.stat & STS_TXR)) {
sim_debug(EXECUTE_MSG, &tto_b_dev,
"Firing IU TTY IRQ 13 ON TX/State Change: PORT B\n");
(iu_contty.conf & TX_EN) &&
(iu_contty.stat & STS_TXR)) {
csr_data |= CSRUART;
}
}
t_stat tti_a_reset(DEVICE *dptr)
t_stat tti_reset(DEVICE *dptr)
{
memset(&iu_state, 0, sizeof(IU_STATE));
memset(&iu_port_a, 0, sizeof(IU_PORT));
memset(&iu_console, 0, sizeof(IU_PORT));
/* Start the TTI A polling loop */
if (!sim_is_active(&tti_a_unit)) {
sim_activate(&tti_a_unit, tti_a_unit.wait);
tmxr_set_console_units(&tti_unit, &tto_unit);
/* Input Port logic is inverted - 0 means set */
iu_state.inprt = ~(IU_DCDA);
/* Start the Console TTI polling loop */
if (!sim_is_active(&tti_unit)) {
sim_activate(&tti_unit, tti_unit.wait);
}
return SCPE_OK;
}
t_stat tti_b_reset(DEVICE *dtpr)
t_stat contty_reset(DEVICE *dtpr)
{
memset(&iu_state, 0, sizeof(IU_STATE));
memset(&iu_port_b, 0, sizeof(IU_PORT));
if (contty_ldsc == NULL) {
contty_desc.ldsc =
contty_ldsc =
(TMLN *)calloc(1, sizeof(*contty_ldsc));
}
/* Start the TTI B polling loop */
if (!sim_is_active(&tti_b_unit)) {
sim_activate(&tti_b_unit, tti_b_unit.wait);
/* Start the CONTTY polling loop */
if (!sim_is_active(contty_rcv_unit)) {
sim_activate(contty_rcv_unit, contty_rcv_unit->wait);
}
return SCPE_OK;
@ -285,7 +317,7 @@ t_stat iu_timer_reset(DEVICE *dptr)
/* Service routines */
t_stat iu_svc_tti_a(UNIT *uptr)
t_stat iu_svc_tti(UNIT *uptr)
{
int32 temp;
@ -305,26 +337,17 @@ t_stat iu_svc_tti_a(UNIT *uptr)
return temp;
}
sim_debug(READ_MSG, &tti_a_dev,
">>> TTIA: Receive %02x (%c)\n",
temp & 0xff, temp & 0xff);
if (iu_port_a.conf & RX_EN) {
if ((iu_port_a.stat & STS_FFL) == 0) {
iu_port_a.rxbuf[iu_port_a.w_p] = (temp & 0xff);
iu_port_a.w_p = (iu_port_a.w_p + 1) % IU_BUF_SIZE;
if (iu_port_a.w_p == iu_port_b.w_p) {
sim_debug(READ_MSG, &tti_a_dev,
">>> FIFO FULL ON KEYBOARD READ!!!! <<<\n");
iu_port_a.stat |= STS_FFL;
if (iu_console.conf & RX_EN) {
if ((iu_console.stat & STS_FFL) == 0) {
iu_console.rxbuf[iu_console.w_p] = (temp & 0xff);
iu_console.w_p = (iu_console.w_p + 1) % IU_BUF_SIZE;
if (iu_console.w_p == iu_contty.w_p) {
iu_console.stat |= STS_FFL;
}
}
iu_port_a.stat |= STS_RXR;
iu_console.stat |= STS_RXR;
iu_state.istat |= ISTS_RAI;
if (iu_state.imr & 0x02) {
sim_debug(EXECUTE_MSG, &tti_a_dev,
"Firing IRQ 13 ON TTI A RECEIVE (%c)\n",
(temp & 0xff));
csr_data |= CSRUART;
}
}
@ -332,23 +355,63 @@ t_stat iu_svc_tti_a(UNIT *uptr)
return SCPE_OK;
}
t_stat iu_svc_tti_b(UNIT *uptr)
{
sim_clock_coschedule_tmr_abs(uptr, TMR_CLK, 2);
/* TODO: Handle TTIB as a terminal */
return SCPE_OK;
}
t_stat iu_svc_tto_a(UNIT *uptr)
t_stat iu_svc_tto(UNIT *uptr)
{
iu_txrdy_a_irq();
return SCPE_OK;
}
t_stat iu_svc_tto_b(UNIT *uptr)
t_stat iu_svc_contty(UNIT *uptr)
{
int32 temp, ln;
if ((uptr->flags & UNIT_ATT) == 0) {
return SCPE_OK;
}
ln = tmxr_poll_conn(&contty_desc);
if (ln >= 0) {
contty_ldsc[ln].rcve = 1;
/* Set DCR */
iu_state.inprt &= ~(IU_DCDB);
iu_state.ipcr = IU_DCDB;
/* Cause an interrupt */
csr_data |= CSRUART;
}
tmxr_poll_rx(&contty_desc);
if (contty_ldsc[0].conn) {
temp = tmxr_getc_ln(&contty_ldsc[0]);
if (temp & SCPE_BREAK) {
sim_debug(EXECUTE_MSG, &contty_dev,
"*** BREAK RECEIVED ON CONTTY!\n");
}
if (temp) {
if (iu_contty.conf & RX_EN) {
if ((iu_contty.stat & STS_FFL) == 0) {
iu_contty.rxbuf[iu_contty.w_p] = (temp & 0xff);
iu_contty.w_p = (iu_contty.w_p + 1) % IU_BUF_SIZE;
if (iu_contty.w_p == iu_contty.w_p) {
iu_contty.stat |= STS_FFL;
}
}
iu_contty.stat |= STS_RXR;
iu_state.istat |= ISTS_RBI;
if (iu_state.imr & 0x02) {
csr_data |= CSRUART;
}
}
}
}
return sim_clock_coschedule_tmr(uptr, TMR_CLK, 2);
}
t_stat iu_svc_contty_xmt(UNIT *uptr)
{
tmxr_poll_tx(&contty_desc);
iu_txrdy_b_irq();
return SCPE_OK;
}
@ -395,27 +458,24 @@ uint32 iu_read(uint32 pa, size_t size)
switch (reg) {
case MR12A:
modep = iu_port_a.modep;
data = iu_port_a.mode[modep];
modep = iu_console.modep;
data = iu_console.mode[modep];
iu_increment_a = TRUE;
break;
case SRA:
data = iu_port_a.stat;
data = iu_console.stat;
break;
case RHRA:
data = iu_port_a.rxbuf[iu_port_a.r_p];
iu_port_a.r_p = (iu_port_a.r_p + 1) % IU_BUF_SIZE;
sim_debug(READ_MSG, &tti_a_dev,
"[%08x] RHRA = %02x (%c)\n",
R[NUM_PC], (data & 0xff), (data & 0xff));
iu_port_a.stat &= ~(STS_RXR|STS_FFL);
data = iu_console.rxbuf[iu_console.r_p];
iu_console.r_p = (iu_console.r_p + 1) % IU_BUF_SIZE;
iu_console.stat &= ~(STS_RXR|STS_FFL);
iu_state.istat &= ~ISTS_RAI;
csr_data &= ~CSRUART;
break;
case IPCR:
data = iu_state.ipcr;
/* Reading the port resets the upper four bits */
iu_state.ipcr &= 0x0f;
/* Reading the port resets it */
iu_state.ipcr = 0;
csr_data &= ~CSRUART;
break;
case ISR:
@ -428,52 +488,38 @@ uint32 iu_read(uint32 pa, size_t size)
data = iu_timer_state.c_set & 0xff;
break;
case MR12B:
modep = iu_port_b.modep;
data = iu_port_b.mode[modep];
modep = iu_contty.modep;
data = iu_contty.mode[modep];
iu_increment_b = TRUE;
break;
case SRB:
data = iu_port_b.stat;
sim_debug(READ_MSG, &tti_b_dev,
"[%08x] SRB = %02x\n",
R[NUM_PC], (data & 0xff));
data = iu_contty.stat;
break;
case RHRB:
data = iu_port_b.rxbuf[iu_port_b.r_p];
iu_port_b.r_p = (iu_port_b.r_p + 1) % IU_BUF_SIZE;
sim_debug(READ_MSG, &tti_b_dev,
"[%08x] RHRB = %02x (%c)\n",
R[NUM_PC], (data & 0xff), (data & 0xff));
iu_port_b.stat &= ~(STS_RXR|STS_FFL);
data = iu_contty.rxbuf[iu_contty.r_p];
iu_contty.r_p = (iu_contty.r_p + 1) % IU_BUF_SIZE;
iu_contty.stat &= ~(STS_RXR|STS_FFL);
iu_state.istat &= ~ISTS_RBI;
break;
case INPRT:
/* TODO: Correct behavior for DCD on contty */
/* For now, this enables DCD/DTR on console only */
data = 0x8e;
data = iu_state.inprt;
break;
case START_CTR:
data = 0;
iu_state.istat &= ~ISTS_CRI;
delay = (uint32) (IU_TIMER_STP * iu_timer_state.c_set);
sim_activate_abs(&iu_timer_unit, (int32) DELAY_US(delay));
sim_debug(READ_MSG, &iu_timer_dev,
"[%08x] Activating IU timer to fire in %04x steps\n",
R[NUM_PC], iu_timer_state.c_set);
break;
case STOP_CTR:
data = 0;
iu_state.istat &= ~ISTS_CRI;
csr_data &= ~CSRUART;
sim_cancel(&iu_timer_unit);
sim_debug(READ_MSG, &iu_timer_dev,
"[%08x] Cancelling IU timer\n",
R[NUM_PC]);
break;
case 17: /* Clear DMAC interrupt */
data = 0;
iu_port_a.drq = FALSE;
iu_port_b.drq = FALSE;
iu_console.drq = FALSE;
iu_contty.drq = FALSE;
csr_data &= ~CSRDMA;
break;
default:
@ -493,39 +539,31 @@ void iu_write(uint32 pa, uint32 val, size_t size)
switch (reg) {
case MR12A:
modep = iu_port_a.modep;
iu_port_a.mode[modep] = val & 0xff;
modep = iu_console.modep;
iu_console.mode[modep] = val & 0xff;
iu_increment_a = TRUE;
break;
case CSRA:
/* Set baud rate - not implemented */
break;
case CRA: /* Command A */
sim_debug(WRITE_MSG, &tti_a_dev,
"[%08x] CRA = %02x\n",
R[NUM_PC], (val & 0xff));
iu_w_cmd(PORT_A, (uint8) val);
break;
case THRA: /* TX/RX Buf A */
sim_debug(WRITE_MSG, &tto_a_dev,
"[%08x] THRA = %02x (%c)\n",
R[NUM_PC], (val & 0xff), (val & 0xff));
/* Loopback mode */
if ((iu_port_a.mode[1] & 0xc0) == 0x80) {
iu_port_a.txbuf = (uint8) val;
if ((iu_console.mode[1] & 0xc0) == 0x80) {
iu_console.txbuf = (uint8) val;
/* This is also a Receive */
if ((iu_port_a.stat & STS_FFL) == 0) {
iu_port_a.rxbuf[iu_port_a.w_p] = (uint8) val;
iu_port_a.w_p = (iu_port_a.w_p + 1) % IU_BUF_SIZE;
if (iu_port_a.w_p == iu_port_a.r_p) {
sim_debug(WRITE_MSG, &tto_a_dev,
">>> FIFO FULL ON LOOPBACK THRA! <<<");
iu_port_a.stat |= STS_FFL;
if ((iu_console.stat & STS_FFL) == 0) {
iu_console.rxbuf[iu_console.w_p] = (uint8) val;
iu_console.w_p = (iu_console.w_p + 1) % IU_BUF_SIZE;
if (iu_console.w_p == iu_contty.r_p) {
iu_console.stat |= STS_FFL;
}
}
iu_port_a.stat |= STS_RXR;
iu_console.stat |= STS_RXR;
iu_state.istat |= ISTS_RAI;
} else {
iu_tx(PORT_A, (uint8) val);
@ -536,9 +574,6 @@ void iu_write(uint32 pa, uint32 val, size_t size)
iu_state.acr = (uint8) val;
break;
case IMR:
sim_debug(WRITE_MSG, &tti_a_dev,
"[%08x] IMR = %02x\n",
R[NUM_PC], (val & 0xff));
iu_state.imr = (uint8) val;
csr_data &= ~CSRUART;
/* Possibly cause an interrupt */
@ -558,49 +593,50 @@ void iu_write(uint32 pa, uint32 val, size_t size)
iu_timer_state.c_set |= (val & 0xff);
break;
case MR12B:
modep = iu_port_b.modep;
iu_port_b.mode[modep] = val & 0xff;
modep = iu_contty.modep;
iu_contty.mode[modep] = val & 0xff;
iu_increment_b = TRUE;
break;
case CRB: /* Command B */
sim_debug(WRITE_MSG, &tti_b_dev,
"[%08x] CRB = %02x\n",
R[NUM_PC], (val & 0xff));
iu_w_cmd(PORT_B, (uint8) val);
break;
case CSRB:
break;
case THRB: /* TX/RX Buf B */
sim_debug(WRITE_MSG, &tto_b_dev,
"[%08x] THRB = %02x (%c)\n",
R[NUM_PC], (val & 0xff), (val & 0xff));
/* Loopback mode */
if ((iu_port_b.mode[1] & 0xc0) == 0x80) {
iu_port_a.txbuf = (uint8) val;
if ((iu_contty.mode[1] & 0xc0) == 0x80) {
iu_contty.txbuf = (uint8) val;
/* This is also a Receive */
if ((iu_port_b.stat & STS_FFL) == 0) {
iu_port_b.rxbuf[iu_port_b.w_p] = (uint8) val;
iu_port_b.w_p = (iu_port_b.w_p + 1) % IU_BUF_SIZE;
if (iu_port_b.w_p == iu_port_b.r_p) {
sim_debug(WRITE_MSG, &tto_b_dev,
">>> FIFO FULL ON LOOPBACK THRB! <<<");
iu_port_b.stat |= STS_FFL;
if ((iu_contty.stat & STS_FFL) == 0) {
iu_contty.rxbuf[iu_contty.w_p] = (uint8) val;
iu_contty.w_p = (iu_contty.w_p + 1) % IU_BUF_SIZE;
if (iu_contty.w_p == iu_contty.r_p) {
iu_contty.stat |= STS_FFL;
}
}
iu_port_b.stat |= STS_RXR;
iu_contty.stat |= STS_RXR;
iu_state.istat |= ISTS_RBI;
} else {
iu_tx(PORT_B, (uint8) val);
}
break;
case OPCR:
sim_debug(EXECUTE_MSG, &contty_dev,
">>> OPCR written: %02x\n",
(uint8) val);
iu_state.opcr = (uint8) val;
break;
case SOPR:
sim_debug(EXECUTE_MSG, &contty_dev,
">>> SOPR written: %02x\n",
(uint8) val);
break;
case ROPR:
sim_debug(EXECUTE_MSG, &contty_dev,
">>> ROPR written: %02x\n",
(uint8) val);
break;
default:
break;
@ -609,15 +645,11 @@ void iu_write(uint32 pa, uint32 val, size_t size)
void iua_drq_handled()
{
sim_debug(EXECUTE_MSG, &tto_a_dev,
"Firing IU IRQ 13 on DRQ (A) Hanlded\n");
csr_data |= CSRDMA;
}
void iub_drq_handled()
{
sim_debug(EXECUTE_MSG, &tto_a_dev,
"Firing IU IRQ 13 on DRQ (B) Hanlded\n");
csr_data |= CSRDMA;
}
@ -625,13 +657,14 @@ static SIM_INLINE void iu_tx(uint8 portno, uint8 val)
{
IU_PORT *p;
UNIT *uptr;
TMLN *lp;
if (portno == 0) {
p = &iu_port_a;
uptr = &tto_a_unit;
p = &iu_console;
uptr = &tto_unit;
} else {
p = &iu_port_b;
uptr = &tto_b_unit;
p = &iu_contty;
uptr = contty_xmt_unit;
}
p->txbuf = val;
@ -643,6 +676,9 @@ static SIM_INLINE void iu_tx(uint8 portno, uint8 val)
if (portno == PORT_A) {
/* Write the character to the SIMH console */
sim_putchar(val);
} else {
lp = &contty_ldsc[0];
tmxr_putc_ln(lp, val);
}
/* The buffer is now empty, we've transmitted, so set TXR */
@ -660,9 +696,9 @@ static SIM_INLINE void iu_w_cmd(uint8 portno, uint8 cmd)
IU_PORT *p;
if (portno == 0) {
p = &iu_port_a;
p = &iu_console;
} else {
p = &iu_port_b;
p = &iu_contty;
}
/* Enable or disable transmitter */

View file

@ -94,10 +94,6 @@
#define SOPR 14
#define ROPR 15
#define UNIT_CONSOLE_TTI 0
#define UNIT_CONSOLE_TTO 1
#define UNIT_IU_TIMER 2
/* Registers - R/W */
#define MR12A 0
#define MR12B 8
@ -122,10 +118,9 @@
#define IU_MODE(x) ((x & UM_MASK) >> UM_SHIFT)
extern DEVICE tti_a_dev;
extern DEVICE tto_a_dev;
extern DEVICE tti_b_dev;
extern DEVICE tto_b_dev;
extern DEVICE tti_dev;
extern DEVICE tto_dev;
extern DEVICE contty_dev;
extern DEVICE iu_timer_dev;
#define IUBASE 0x49000
@ -150,6 +145,9 @@ extern DEVICE iu_timer_dev;
#define IU_BUF_SIZE 3
#define IU_DCDA 0x01
#define IU_DCDB 0x02
typedef struct iu_port {
uint8 stat; /* Port Status */
uint8 cmd; /* Command */
@ -177,17 +175,19 @@ typedef struct iu_timer_state {
t_bool c_en;
} IU_TIMER_STATE;
extern IU_PORT iu_port_a;
extern IU_PORT iu_port_b;
extern IU_PORT iu_console;
extern IU_PORT iu_contty;
/* Function prototypes */
t_stat tti_a_reset(DEVICE *dptr);
t_stat tti_b_reset(DEVICE *dptr);
t_stat contty_attach(UNIT *uptr, CONST char *cptr);
t_stat contty_detach(UNIT *uptr);
t_stat tti_reset(DEVICE *dptr);
t_stat contty_reset(DEVICE *dptr);
t_stat iu_timer_reset(DEVICE *dptr);
t_stat iu_svc_tti_a(UNIT *uptr);
t_stat iu_svc_tto_a(UNIT *uptr);
t_stat iu_svc_tti_b(UNIT *uptr);
t_stat iu_svc_tto_b(UNIT *uptr);
t_stat iu_svc_tti(UNIT *uptr);
t_stat iu_svc_tto(UNIT *uptr);
t_stat iu_svc_contty(UNIT *uptr);
t_stat iu_svc_contty_xmt(UNIT *uptr);
t_stat iu_svc_timer(UNIT *uptr);
uint32 iu_read(uint32 pa, size_t size);
void iu_write(uint32 pa, uint32 val, size_t size);

View file

@ -54,10 +54,9 @@ DEVICE *sim_devices[] = {
&tod_dev,
&nvram_dev,
&csr_dev,
&tti_a_dev,
&tto_a_dev,
&tti_b_dev,
&tto_b_dev,
&tti_dev,
&tto_dev,
&contty_dev,
&iu_timer_dev,
&dmac_dev,
&if_dev,
@ -79,8 +78,8 @@ const char *sim_stop_messages[] = {
void full_reset()
{
cpu_reset(&cpu_dev);
tti_a_reset(&tti_a_dev);
tti_b_reset(&tti_b_dev);
tti_reset(&tti_dev);
contty_reset(&contty_dev);
iu_timer_reset(&iu_timer_dev);
timer_reset(&timer_dev);
if_reset(&if_dev);