mirror of
https://github.com/simh/simh.git
synced 2026-02-14 19:57:19 +00:00
AltairZ80: Adds Cromemco TUART devices
Adds the following devices to AltairZ80: TUART0: Cromemco FDC controller TUART console port at I/O address 0x00. TUART1: Cromemco TU-ART port A at I/O address 0x20. TUART2: Cromemco TU-ART port B at I/I address 0x50. These devices are fully TMXR capable.
This commit is contained in:
committed by
Mark Pizzolato
parent
b2ec2bfd26
commit
0d705c98d5
@@ -215,18 +215,24 @@ static UNIT tuart2_unit[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static REG tuart0_reg[] = {
|
static REG tuart0_reg[] = {
|
||||||
|
{ HRDATAD (TXP0, tuart0_ctx.txp, 1, "TU-ART port 0 transmit pending"), },
|
||||||
|
{ HRDATAD (STB0, tuart0_ctx.stb, 8, "TU-ART port 0 status buffer"), },
|
||||||
{ HRDATAD (INTMASK0, tuart0_ctx.intmask, 8, "TU-ART port 0 interrupt mask"), },
|
{ HRDATAD (INTMASK0, tuart0_ctx.intmask, 8, "TU-ART port 0 interrupt mask"), },
|
||||||
{ DRDATAD (INTVEC0, tuart0_ctx.intvector, 8, "TU-ART port 0 interrupt vector"), },
|
{ DRDATAD (INTVEC0, tuart0_ctx.intvector, 8, "TU-ART port 0 interrupt vector"), },
|
||||||
{ HRDATAD (INTADR0, tuart0_ctx.intadr, 8, "TU-ART port 0 interrupt address"), },
|
{ HRDATAD (INTADR0, tuart0_ctx.intadr, 8, "TU-ART port 0 interrupt address"), },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
static REG tuart1_reg[] = {
|
static REG tuart1_reg[] = {
|
||||||
|
{ HRDATAD (TXP1, tuart1_ctx.txp, 1, "TU-ART port 1/A transmit pending"), },
|
||||||
|
{ HRDATAD (STB1, tuart1_ctx.stb, 8, "TU-ART port 1/A status buffer"), },
|
||||||
{ HRDATAD (INTMASK1, tuart1_ctx.intmask, 8, "TU-ART port 1/A interrupt mask"), },
|
{ HRDATAD (INTMASK1, tuart1_ctx.intmask, 8, "TU-ART port 1/A interrupt mask"), },
|
||||||
{ DRDATAD (INTVEC1, tuart1_ctx.intvector, 8, "TU-ART port 1/A interrupt vector"), },
|
{ DRDATAD (INTVEC1, tuart1_ctx.intvector, 8, "TU-ART port 1/A interrupt vector"), },
|
||||||
{ HRDATAD (INTADR1, tuart1_ctx.intadr, 8, "TU-ART port 1/A interrupt address"), },
|
{ HRDATAD (INTADR1, tuart1_ctx.intadr, 8, "TU-ART port 1/A interrupt address"), },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
static REG tuart2_reg[] = {
|
static REG tuart2_reg[] = {
|
||||||
|
{ HRDATAD (TXP2, tuart2_ctx.txp, 1, "TU-ART port 2/B transmit pending"), },
|
||||||
|
{ HRDATAD (STB2, tuart2_ctx.stb, 8, "TU-ART port 2/B status buffer"), },
|
||||||
{ HRDATAD (INTMASK2, tuart2_ctx.intmask, 8, "TU-ART port 2/B interrupt mask"), },
|
{ HRDATAD (INTMASK2, tuart2_ctx.intmask, 8, "TU-ART port 2/B interrupt mask"), },
|
||||||
{ DRDATAD (INTVEC2, tuart2_ctx.intvector, 8, "TU-ART port 2/B interrupt vector"), },
|
{ DRDATAD (INTVEC2, tuart2_ctx.intvector, 8, "TU-ART port 2/B interrupt vector"), },
|
||||||
{ HRDATAD (INTADR2, tuart2_ctx.intadr, 8, "TU-ART port 2/B interrupt address"), },
|
{ HRDATAD (INTADR2, tuart2_ctx.intadr, 8, "TU-ART port 2/B interrupt address"), },
|
||||||
@@ -356,7 +362,7 @@ static t_stat tuart_reset(DEVICE *dptr, int32 (*routine)(const int32, const int3
|
|||||||
dptr->units[0].dptr = dptr;
|
dptr->units[0].dptr = dptr;
|
||||||
|
|
||||||
/* Reset registers */
|
/* Reset registers */
|
||||||
xptr->stb = 0x00;
|
xptr->stb = TUART_TBE;
|
||||||
xptr->txp = FALSE;
|
xptr->txp = FALSE;
|
||||||
xptr->hbd = 1;
|
xptr->hbd = 1;
|
||||||
xptr->baud = 9600;
|
xptr->baud = 9600;
|
||||||
@@ -364,8 +370,8 @@ static t_stat tuart_reset(DEVICE *dptr, int32 (*routine)(const int32, const int3
|
|||||||
|
|
||||||
tuart_config_line(&dptr->units[0]);
|
tuart_config_line(&dptr->units[0]);
|
||||||
|
|
||||||
if (!(dptr->flags & DEV_DIS) && dptr->units[0].flags & UNIT_TUART_CONSOLE) {
|
if (!(dptr->flags & DEV_DIS)) {
|
||||||
sim_activate_after_abs(&dptr->units[0], dptr->units[0].wait);
|
sim_activate_abs(&dptr->units[0], dptr->units[0].wait);
|
||||||
} else {
|
} else {
|
||||||
sim_cancel(&dptr->units[0]);
|
sim_cancel(&dptr->units[0]);
|
||||||
}
|
}
|
||||||
@@ -381,6 +387,7 @@ static t_stat tuart_svc(UNIT *uptr)
|
|||||||
TUART_CTX *xptr;
|
TUART_CTX *xptr;
|
||||||
int32 c;
|
int32 c;
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
t_bool dr = TRUE;
|
||||||
|
|
||||||
xptr = (TUART_CTX *) uptr->dptr->ctxt;
|
xptr = (TUART_CTX *) uptr->dptr->ctxt;
|
||||||
|
|
||||||
@@ -389,32 +396,27 @@ static t_stat tuart_svc(UNIT *uptr)
|
|||||||
if (tmxr_poll_conn(xptr->tmxr) >= 0) { /* poll connection */
|
if (tmxr_poll_conn(xptr->tmxr) >= 0) { /* poll connection */
|
||||||
|
|
||||||
xptr->conn = TRUE; /* set connected */
|
xptr->conn = TRUE; /* set connected */
|
||||||
|
xptr->tmln->rcve = 1;
|
||||||
|
|
||||||
sim_debug(STATUS_MSG, uptr->dptr, "new connection.\n");
|
sim_debug(STATUS_MSG, uptr->dptr, "new connection.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update incoming modem status bits */
|
|
||||||
if (uptr->flags & UNIT_ATT) {
|
|
||||||
xptr->stb = 0x00;
|
|
||||||
|
|
||||||
/* Enable receiver if DCD is active low */
|
|
||||||
xptr->tmln->rcve = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TX data */
|
/* TX data */
|
||||||
if (xptr->txp) {
|
if (xptr->txp) {
|
||||||
if (uptr->flags & UNIT_ATT) {
|
if (uptr->flags & UNIT_ATT) {
|
||||||
r = tmxr_putc_ln(xptr->tmln, xptr->txb);
|
r = tmxr_putc_ln(xptr->tmln, xptr->txb);
|
||||||
xptr->txp = FALSE; /* Reset TX Pending */
|
xptr->txp = FALSE; /* Reset TX Pending */
|
||||||
|
|
||||||
|
if (r == SCPE_LOST) {
|
||||||
|
xptr->conn = FALSE; /* Connection was lost */
|
||||||
|
sim_debug(STATUS_MSG, uptr->dptr, "lost connection.\n");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
r = sim_putchar(xptr->txb);
|
r = sim_putchar(xptr->txb);
|
||||||
xptr->txp = FALSE; /* Reset TX Pending */
|
xptr->txp = FALSE; /* Reset TX Pending */
|
||||||
}
|
xptr->stb |= TUART_TBE; /* Xmit buffer empty */
|
||||||
|
dr = FALSE; /* Skip read */
|
||||||
if (r == SCPE_LOST) {
|
|
||||||
xptr->conn = FALSE; /* Connection was lost */
|
|
||||||
sim_debug(STATUS_MSG, uptr->dptr, "lost connection.\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If TX buffer now empty, send interrupt */
|
/* If TX buffer now empty, send interrupt */
|
||||||
@@ -422,21 +424,16 @@ static t_stat tuart_svc(UNIT *uptr)
|
|||||||
xptr->intadr = TUART_TBSIA;
|
xptr->intadr = TUART_TBSIA;
|
||||||
tuart_int(uptr);
|
tuart_int(uptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update TBE if not set and no character pending */
|
/* Update TBE if not set and no character pending */
|
||||||
if (!xptr->txp && !(xptr->stb & TUART_TBE)) {
|
if (!xptr->txp && !(xptr->stb & TUART_TBE) && uptr->flags & UNIT_ATT) {
|
||||||
if (uptr->flags & UNIT_ATT) {
|
tmxr_poll_tx(xptr->tmxr);
|
||||||
tmxr_poll_tx(xptr->tmxr);
|
xptr->stb |= (tmxr_txdone_ln(xptr->tmln) && xptr->conn) ? TUART_TBE : 0;
|
||||||
xptr->stb |= (tmxr_txdone_ln(xptr->tmln) && xptr->conn) ? TUART_TBE : 0;
|
|
||||||
} else {
|
|
||||||
xptr->stb |= TUART_TBE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for Data if RX buffer empty */
|
/* Check for Data if RX buffer empty */
|
||||||
if (!(xptr->stb & TUART_RDA)) {
|
if (dr && !(xptr->stb & TUART_RDA)) {
|
||||||
if (uptr->flags & UNIT_ATT) {
|
if (uptr->flags & UNIT_ATT) {
|
||||||
tmxr_poll_rx(xptr->tmxr);
|
tmxr_poll_rx(xptr->tmxr);
|
||||||
|
|
||||||
@@ -451,6 +448,7 @@ static t_stat tuart_svc(UNIT *uptr)
|
|||||||
xptr->rxb = c & 0xff;
|
xptr->rxb = c & 0xff;
|
||||||
xptr->stb |= TUART_RDA;
|
xptr->stb |= TUART_RDA;
|
||||||
xptr->stb &= ~(TUART_FME | TUART_ORE);
|
xptr->stb &= ~(TUART_FME | TUART_ORE);
|
||||||
|
|
||||||
if (xptr->intmask & TUART_RDAIE) {
|
if (xptr->intmask & TUART_RDAIE) {
|
||||||
xptr->intadr = TUART_RDAIA;
|
xptr->intadr = TUART_RDAIA;
|
||||||
tuart_int(uptr);
|
tuart_int(uptr);
|
||||||
@@ -458,12 +456,11 @@ static t_stat tuart_svc(UNIT *uptr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sim_activate_after_abs(uptr, uptr->wait);
|
sim_activate_abs(uptr, uptr->wait);
|
||||||
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Attach routine */
|
/* Attach routine */
|
||||||
static t_stat tuart_attach(UNIT *uptr, CONST char *cptr)
|
static t_stat tuart_attach(UNIT *uptr, CONST char *cptr)
|
||||||
{
|
{
|
||||||
@@ -478,8 +475,6 @@ static t_stat tuart_attach(UNIT *uptr, CONST char *cptr)
|
|||||||
xptr->tmln->rcve = 1;
|
xptr->tmln->rcve = 1;
|
||||||
|
|
||||||
r = tuart_config_line(uptr);
|
r = tuart_config_line(uptr);
|
||||||
|
|
||||||
sim_activate_after_abs(uptr, uptr->wait);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
@@ -500,11 +495,7 @@ static t_stat tuart_detach(UNIT *uptr)
|
|||||||
if (uptr->flags & UNIT_ATT) {
|
if (uptr->flags & UNIT_ATT) {
|
||||||
xptr = (TUART_CTX *) uptr->dptr->ctxt;
|
xptr = (TUART_CTX *) uptr->dptr->ctxt;
|
||||||
|
|
||||||
if (uptr->flags & UNIT_TUART_CONSOLE) {
|
sim_cancel(uptr);
|
||||||
uptr->wait = TUART_WAIT;
|
|
||||||
} else {
|
|
||||||
sim_cancel(uptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (tmxr_detach(xptr->tmxr, uptr));
|
return (tmxr_detach(xptr->tmxr, uptr));
|
||||||
}
|
}
|
||||||
@@ -575,17 +566,8 @@ static t_stat tuart_config_line(UNIT *uptr)
|
|||||||
if (xptr != NULL) {
|
if (xptr != NULL) {
|
||||||
sprintf(config, "%d-8N%d", TUART_BAUD(xptr), xptr->sbits);
|
sprintf(config, "%d-8N%d", TUART_BAUD(xptr), xptr->sbits);
|
||||||
|
|
||||||
if (uptr->flags & UNIT_ATT) {
|
if ((uptr->flags & UNIT_ATT) && (xptr->tmln->serport)) {
|
||||||
r = tmxr_set_config_line(xptr->tmln, config);
|
r = tmxr_set_config_line(xptr->tmln, config);
|
||||||
|
|
||||||
if (xptr->tmln->serport) {
|
|
||||||
uptr->wait = 9600000 / TUART_BAUD(xptr);
|
|
||||||
} else {
|
|
||||||
uptr->wait = TUART_WAIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
xptr->tmln->txbps = 0; /* Get TMXR's timing out of our way */
|
|
||||||
xptr->tmln->rxbps = 0; /* Get TMXR's timing out of our way */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sim_debug(STATUS_MSG, uptr->dptr, "Port configuration set to '%s'.\n", config);
|
sim_debug(STATUS_MSG, uptr->dptr, "Port configuration set to '%s'.\n", config);
|
||||||
@@ -689,8 +671,8 @@ static int32 tuart_data(DEVICE *dptr, int32 io, int32 data)
|
|||||||
xptr->stb &= ~(TUART_RDA | TUART_FME | TUART_ORE | TUART_IPG);
|
xptr->stb &= ~(TUART_RDA | TUART_FME | TUART_ORE | TUART_IPG);
|
||||||
} else {
|
} else {
|
||||||
xptr->txb = data;
|
xptr->txb = data;
|
||||||
xptr->stb &= ~(TUART_TBE | TUART_IPG);
|
|
||||||
xptr->txp = TRUE;
|
xptr->txp = TRUE;
|
||||||
|
xptr->stb &= ~(TUART_TBE | TUART_IPG);
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
Reference in New Issue
Block a user