mirror of
https://github.com/rcornwell/sims.git
synced 2026-01-13 15:27:04 +00:00
KA10: Redid interrupt system for KS.
This commit is contained in:
parent
c8526dde8f
commit
265a4ae4a2
@ -77,7 +77,6 @@
|
||||
int ch11_write(DEVICE *dptr, t_addr addr, uint16 data, int32 access);
|
||||
int ch11_read(DEVICE *dptr, t_addr addr, uint16 *data, int32 access);
|
||||
uint16 ch11_checksum (const uint8 *p, int count);
|
||||
int ch11_test_int (struct pdp_dib *dibp);
|
||||
void ch11_validate (const uint8 *p, int count);
|
||||
t_stat ch11_transmit (struct pdp_dib *dibp);
|
||||
void ch11_receive (struct pdp_dib *dibp);
|
||||
@ -95,7 +94,7 @@ t_stat ch11_help_attach (FILE *, DEVICE *, UNIT *, int32, const char *);
|
||||
const char *ch11_description (DEVICE *);
|
||||
|
||||
static char peer[256];
|
||||
int address;
|
||||
static int address;
|
||||
static uint16 ch11_csr;
|
||||
static int rx_count;
|
||||
static int tx_count;
|
||||
@ -170,23 +169,26 @@ ch11_write(DEVICE *dptr, t_addr addr, uint16 data, int32 access)
|
||||
|
||||
switch (addr & 016) {
|
||||
case 000: /* CSR */
|
||||
if (data & CSR_RST) {
|
||||
sim_debug (DBG_REG, &ch11_dev, "Reset\n");
|
||||
ch11_clear (dibp);
|
||||
}
|
||||
ch11_csr &= ~(CSR_REN|CSR_TEN|CSR_SPY);
|
||||
ch11_csr |= data & (CSR_REN|CSR_TEN|CSR_SPY);
|
||||
if (data & CSR_RCL) {
|
||||
sim_debug (DBG_REG, &ch11_dev, "Clear RX\n");
|
||||
ch11_csr &= ~CSR_RDN;
|
||||
rx_count = 0;
|
||||
ch11_lines[0].rcve = TRUE;
|
||||
}
|
||||
if (data & CSR_RST) {
|
||||
sim_debug (DBG_REG, &ch11_dev, "Reset\n");
|
||||
ch11_clear (dibp);
|
||||
uba_clr_irq(dibp, dibp->uba_vect);
|
||||
}
|
||||
if (data & CSR_TCL) {
|
||||
sim_debug (DBG_REG, &ch11_dev, "Clear TX\n");
|
||||
tx_count = 0;
|
||||
ch11_csr |= CSR_TDN;
|
||||
if (ch11_csr & CSR_TEN)
|
||||
uba_set_irq(dibp, dibp->uba_vect);
|
||||
}
|
||||
ch11_csr &= ~(CSR_REN|CSR_TEN);
|
||||
ch11_csr |= data & (CSR_REN|CSR_TEN);
|
||||
break;
|
||||
|
||||
case 002: /* Write buffer */
|
||||
@ -237,6 +239,7 @@ ch11_read(DEVICE *dptr, t_addr addr, uint16 *data, int32 access)
|
||||
} else {
|
||||
i = 512-rx_count;
|
||||
ch11_csr &= ~CSR_RDN;
|
||||
uba_clr_irq(dibp, dibp->uba_vect);
|
||||
*data = ((uint64)(rx_buffer[i]) & 0xff) << 8;
|
||||
*data |= ((uint64)(rx_buffer[i+1]) & 0xff);
|
||||
rx_count-=2;
|
||||
@ -283,25 +286,6 @@ ch11_checksum (const uint8 *p, int count)
|
||||
return (~sum) & 0xffff;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ch11_test_int (struct pdp_dib *dibp)
|
||||
{
|
||||
if ((ch11_csr & (CSR_RDN|CSR_REN)) == (CSR_RDN|CSR_REN) ||
|
||||
(ch11_csr & (CSR_TDN|CSR_TEN)) == (CSR_TDN|CSR_TEN)) {
|
||||
sim_debug (DBG_INT, &ch11_dev, "%s %s Interrupt\n",
|
||||
ch11_csr & CSR_RDN ? "RX" : "",
|
||||
ch11_csr & CSR_TDN ? "TX" : "");
|
||||
uba_set_irq(dibp);
|
||||
} else {
|
||||
/* Nothing found, so clear any flags */
|
||||
sim_debug(DEBUG_DETAIL, &dz_dev, "Clr irq\n");
|
||||
uba_clr_irq(dibp);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
ch11_validate (const uint8 *p, int count)
|
||||
{
|
||||
@ -363,7 +347,6 @@ ch11_transmit (struct pdp_dib *dibp)
|
||||
ch11_csr |= CSR_TAB;
|
||||
}
|
||||
tx_count = 0;
|
||||
ch11_test_int (dibp);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@ -395,9 +378,12 @@ ch11_receive (struct pdp_dib *dibp)
|
||||
sim_debug (DBG_TRC, &ch11_dev, "Rx count, %d\n", rx_count);
|
||||
ch11_validate (p + CHUDP_HEADER, count - CHUDP_HEADER);
|
||||
ch11_csr |= CSR_RDN;
|
||||
if (ch11_csr & CSR_REN) {
|
||||
sim_debug (DBG_INT, &ch11_dev, "RX Interrupt\n");
|
||||
uba_set_irq(dibp, dibp->uba_vect);
|
||||
}
|
||||
ch11_lines[0].rcve = FALSE;
|
||||
sim_debug (DBG_TRC, &ch11_dev, "Rx off\n");
|
||||
ch11_test_int (dibp);
|
||||
} else {
|
||||
sim_debug (DBG_ERR, &ch11_dev, "Lost packet\n");
|
||||
if ((ch11_csr & CSR_LOS) != CSR_LOS)
|
||||
@ -418,7 +404,7 @@ ch11_clear (struct pdp_dib *dibp)
|
||||
tx_buffer[3] = 0;
|
||||
ch11_lines[0].rcve = TRUE;
|
||||
|
||||
ch11_test_int (dibp);
|
||||
uba_clr_irq(dibp, dibp->uba_vect);
|
||||
}
|
||||
|
||||
t_stat
|
||||
@ -432,9 +418,13 @@ ch11_svc(UNIT *uptr)
|
||||
if (ch11_lines[0].conn) {
|
||||
ch11_receive (dibp);
|
||||
}
|
||||
if (tx_count == 0)
|
||||
if (tx_count == 0) {
|
||||
ch11_csr |= CSR_TDN;
|
||||
ch11_test_int (dibp);
|
||||
if (ch11_csr & CSR_TEN) {
|
||||
sim_debug (DBG_INT, &ch11_dev, "RX Interrupt\n");
|
||||
uba_set_irq(dibp, dibp->uba_vect);
|
||||
}
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
136
PDP10/ks10_dup.c
136
PDP10/ks10_dup.c
@ -27,13 +27,13 @@
|
||||
dup DUP11 Unibus/DPV11 Qbus bit synchronous interface
|
||||
|
||||
This module implements a bit synchronous interface to support DDCMP. Other
|
||||
synchronous protocols which may have been supported on the DUP11/DPV11 bit
|
||||
synchronous protocols which may have been supported on the DUP11/DPV11 bit
|
||||
synchronous interface are explicitly not supported.
|
||||
|
||||
Connections are modeled with a tcp session with connection management and
|
||||
Connections are modeled with a tcp session with connection management and
|
||||
I/O provided by the tmxr library.
|
||||
|
||||
The wire protocol implemented is native DDCMP WITHOUT the DDCMP SYNC
|
||||
The wire protocol implemented is native DDCMP WITHOUT the DDCMP SYNC
|
||||
characters both initially and between DDCMP packets.
|
||||
|
||||
15-May-13 MP Initial implementation
|
||||
@ -82,7 +82,6 @@ static MODEM_CHANGE_CALLBACK dup_modem_change_callback[NUM_DEVS_DUP];
|
||||
|
||||
static int dup_rd (DEVICE *dptr, t_addr PA, uint16 *data, int32 access);
|
||||
static int dup_wr (DEVICE *dptr, t_addr PA, uint16 data, int32 access);
|
||||
static uint16 dup_irq(struct pdp_dib *dibp);
|
||||
static t_stat dup_set_modem (int32 dup, int32 rxcsr_bits);
|
||||
static t_stat dup_get_modem (int32 dup);
|
||||
static t_stat dup_svc (UNIT *uptr);
|
||||
@ -313,14 +312,14 @@ static BITFIELD dup_txdbuf_bits[] = {
|
||||
|
||||
#define IOLN_DUP 010
|
||||
|
||||
DIB dup_dib = { 0760300, 017, 0570, 5, 3, &dup_rd, &dup_wr, &dup_irq, 0, 0};
|
||||
DIB dup_dib = { 0760300, 017, 0570, 5, 3, &dup_rd, &dup_wr, 0, 0, 0};
|
||||
|
||||
static UNIT dup_unit_template = {
|
||||
UDATA (&dup_svc, UNIT_ATTABLE|UNIT_IDLE, 0),
|
||||
UDATA (&dup_svc, UNIT_ATTABLE|UNIT_IDLE, 0),
|
||||
};
|
||||
|
||||
static UNIT dup_poll_unit_template = {
|
||||
UDATA (&dup_poll_svc, UNIT_DIS|UNIT_IDLE, 0),
|
||||
UDATA (&dup_poll_svc, UNIT_DIS|UNIT_IDLE, 0),
|
||||
};
|
||||
|
||||
static UNIT dup_units[NUM_DEVS_DUP+1]; /* One unit per line and a polling unit */
|
||||
@ -391,6 +390,8 @@ static MTAB dup_mod[] = {
|
||||
};
|
||||
|
||||
/* debugging bitmaps */
|
||||
#define DBG_REG 0x0001 /* trace read/write registers */
|
||||
#define DBG_INT 0x0002 /* display transfer requests */
|
||||
#define DBG_PKT (TMXR_DBG_PXMT|TMXR_DBG_PRCV) /* display packets */
|
||||
#define DBG_XMT TMXR_DBG_XMT /* display Transmitted Data */
|
||||
#define DBG_RCV TMXR_DBG_RCV /* display Received Data */
|
||||
@ -400,8 +401,8 @@ static MTAB dup_mod[] = {
|
||||
#define DBG_ASY TMXR_DBG_ASY /* display Asynchronous Activities */
|
||||
|
||||
static DEBTAB dup_debug[] = {
|
||||
{"DETAIL", DEBUG_DETAIL},
|
||||
{"IRQ", DEBUG_IRQ},
|
||||
{"REG", DBG_REG},
|
||||
{"INT", DBG_INT},
|
||||
{"PKT", DBG_PKT},
|
||||
{"XMT", DBG_XMT},
|
||||
{"RCV", DBG_RCV},
|
||||
@ -413,20 +414,20 @@ static DEBTAB dup_debug[] = {
|
||||
};
|
||||
|
||||
/*
|
||||
We have two devices defined here (dup_dev and dpv_dev) which have the
|
||||
We have two devices defined here (dup_dev and dpv_dev) which have the
|
||||
same units. This would normally never be allowed since two devices can't
|
||||
actually share units. This problem is avoided in this case since both
|
||||
devices start out as disabled and the logic in dup_reset allows only
|
||||
one of these devices to be enabled at a time. The DUP device is allowed
|
||||
actually share units. This problem is avoided in this case since both
|
||||
devices start out as disabled and the logic in dup_reset allows only
|
||||
one of these devices to be enabled at a time. The DUP device is allowed
|
||||
on Unibus systems and the DPV device Qbus systems.
|
||||
This monkey business is necessary due to the fact that although both
|
||||
the DUP and DPV devices have almost the same functionality and almost
|
||||
the same register programming interface, they are different enough that
|
||||
they fall in different priorities in the autoconfigure address and vector
|
||||
rules.
|
||||
This 'shared' unit model therefore means we can't call the
|
||||
find_dev_from_unit api to uniquely determine the device structure.
|
||||
We define the DUPDPTR macro to return the active device pointer when
|
||||
This 'shared' unit model therefore means we can't call the
|
||||
find_dev_from_unit api to uniquely determine the device structure.
|
||||
We define the DUPDPTR macro to return the active device pointer when
|
||||
necessary.
|
||||
*/
|
||||
DEVICE dup_dev = {
|
||||
@ -435,7 +436,7 @@ DEVICE dup_dev = {
|
||||
NULL, NULL, &dup_reset,
|
||||
NULL, &dup_attach, &dup_detach,
|
||||
&dup_dib, DEV_DIS | DEV_DISABLE | DEV_DEBUG, 0,
|
||||
dup_debug, NULL, NULL, &dup_help, dup_help_attach, &dup_desc,
|
||||
dup_debug, NULL, NULL, &dup_help, dup_help_attach, &dup_desc,
|
||||
&dup_description
|
||||
};
|
||||
|
||||
@ -444,7 +445,7 @@ DEVICE dup_dev = {
|
||||
/* Register names for Debug tracing */
|
||||
static const char *dup_rd_regs[] =
|
||||
{"RXCSR ", "RXDBUF", "TXCSR ", "TXDBUF" };
|
||||
static const char *dup_wr_regs[] =
|
||||
static const char *dup_wr_regs[] =
|
||||
{"RXCSR ", "PARCSR", "TXCSR ", "TXDBUF"};
|
||||
|
||||
|
||||
@ -547,19 +548,19 @@ switch ((PA >> 1) & 03) { /* case on PA<2:1> */
|
||||
if (dup_rxcsr[dup] & RXCSR_M_RXIE)
|
||||
dup_set_rxint (dup);
|
||||
}
|
||||
if ((dup_rxcsr[dup] & RXCSR_M_RCVEN) &&
|
||||
if ((dup_rxcsr[dup] & RXCSR_M_RCVEN) &&
|
||||
(!(orig_val & RXCSR_M_RCVEN))) { /* Upward transition of receiver enable */
|
||||
dup_rcv_byte (dup); /* start any pending receive */
|
||||
}
|
||||
if ((!(dup_rxcsr[dup] & RXCSR_M_RCVEN)) &&
|
||||
if ((!(dup_rxcsr[dup] & RXCSR_M_RCVEN)) &&
|
||||
(orig_val & RXCSR_M_RCVEN)) { /* Downward transition of receiver enable */
|
||||
dup_rxdbuf[dup] &= ~RXDBUF_M_RXDBUF;
|
||||
dup_rxcsr[dup] &= ~RXCSR_M_RXACT;
|
||||
if ((dup_rcvpkinoff[dup] != 0) ||
|
||||
if ((dup_rcvpkinoff[dup] != 0) ||
|
||||
(dup_rcvpkbytes[dup] != 0))
|
||||
dup_rcvpkinoff[dup] = dup_rcvpkbytes[dup] = 0;
|
||||
}
|
||||
if ((!(dup_rxcsr[dup] & RXCSR_M_RXIE)) &&
|
||||
if ((!(dup_rxcsr[dup] & RXCSR_M_RXIE)) &&
|
||||
(orig_val & RXCSR_M_RXIE)) /* Downward transition of receiver interrupt enable */
|
||||
dup_clr_rxint (dup);
|
||||
if ((dup_rxcsr[dup] & RXCSR_M_RXIE) && (dup_rxcsr[dup] & RXCSR_M_RXDONE))
|
||||
@ -591,20 +592,20 @@ switch ((PA >> 1) & 03) { /* case on PA<2:1> */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((dup_txcsr[dup] & TXCSR_M_TXACT) &&
|
||||
(!(orig_val & TXCSR_M_TXACT)) &&
|
||||
if ((dup_txcsr[dup] & TXCSR_M_TXACT) &&
|
||||
(!(orig_val & TXCSR_M_TXACT)) &&
|
||||
(orig_val & TXCSR_M_TXDONE)) {
|
||||
dup_txcsr[dup] &= ~TXCSR_M_TXDONE;
|
||||
}
|
||||
if ((!(dup_txcsr[dup] & TXCSR_M_SEND)) &&
|
||||
if ((!(dup_txcsr[dup] & TXCSR_M_SEND)) &&
|
||||
(orig_val & TXCSR_M_SEND)) {
|
||||
dup_txcsr[dup] &= ~TXCSR_M_TXACT;
|
||||
dup_put_msg_bytes (dup, NULL, 0, FALSE, TRUE);
|
||||
}
|
||||
if ((dup_txcsr[dup] & TXCSR_M_HALFDUP) ^ (orig_val & TXCSR_M_HALFDUP))
|
||||
tmxr_set_line_halfduplex (dup_desc.ldsc+dup, dup_txcsr[dup] & TXCSR_M_HALFDUP);
|
||||
if ((dup_txcsr[dup] & TXCSR_M_TXIE) &&
|
||||
(!(orig_val & TXCSR_M_TXIE)) &&
|
||||
if ((dup_txcsr[dup] & TXCSR_M_TXIE) &&
|
||||
(!(orig_val & TXCSR_M_TXIE)) &&
|
||||
(dup_txcsr[dup] & TXCSR_M_TXDONE)) {
|
||||
dup_set_txint (dup);
|
||||
}
|
||||
@ -625,25 +626,6 @@ dup_get_modem (dup);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint16 dup_irq(struct pdp_dib *dibp)
|
||||
{
|
||||
int dup;
|
||||
|
||||
for (dup = 0; dup < dup_desc.lines; dup++) { /* find 1st mux */
|
||||
if (dup_rxi & (1 << dup)) {
|
||||
sim_debug(DEBUG_IRQ, DUPDPTR, "dup_rxinta(dup=%d)\n", dup);
|
||||
// dup_clr_rxint (dup); /* clear intr */
|
||||
return (dup_dib.uba_vect + (dup * 010)); /* return vector */
|
||||
}
|
||||
if (dup_txi & (1 << dup)) {
|
||||
sim_debug(DEBUG_IRQ, DUPDPTR, "dup_txinta(dup=%d)\n", dup);
|
||||
// dup_clr_txint (dup); /* clear intr */
|
||||
return (dup_dib.uba_vect + 4 + (dup * 010)); /* return vector */
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static t_stat dup_set_modem (int32 dup, int32 rxcsr_bits)
|
||||
{
|
||||
int32 bits_to_set, bits_to_clear;
|
||||
@ -717,7 +699,7 @@ int32 dup_csr_to_linenum (int32 CSRPA)
|
||||
DEVICE *dptr = DUPDPTR;
|
||||
DIB *dib = (DIB *)dptr->ctxt;
|
||||
|
||||
if ((dib->uba_addr < (uint32)CSRPA) ||
|
||||
if ((dib->uba_addr < (uint32)CSRPA) ||
|
||||
((uint32)CSRPA > (dib->uba_addr + (IOLN_DUP * dup_desc.lines))) ||
|
||||
(DUPDPTR->flags & DEV_DIS))
|
||||
return -1;
|
||||
@ -807,7 +789,7 @@ if ((dup < 0) || (dup >= dup_desc.lines) || (DUPDPTR->flags & DEV_DIS))
|
||||
orig_val = dup_rxcsr[dup];
|
||||
dup_rxcsr[dup] &= ~RXCSR_M_RCVEN;
|
||||
dup_rxcsr[dup] |= (state ? RXCSR_M_RCVEN : 0);
|
||||
if ((dup_rxcsr[dup] & RXCSR_M_RCVEN) &&
|
||||
if ((dup_rxcsr[dup] & RXCSR_M_RCVEN) &&
|
||||
(!(orig_val & RXCSR_M_RCVEN))) { /* Upward transition of receiver enable */
|
||||
UNIT *uptr = dup_units + dup;
|
||||
|
||||
@ -830,7 +812,7 @@ if (!protocol_DDCMP) {
|
||||
if (crc_inhibit) {
|
||||
return SCPE_ARG; /* Must enable CRC for DDCMP */
|
||||
}
|
||||
/* These settings reflect how RSX operates a bare DUP when used for
|
||||
/* These settings reflect how RSX operates a bare DUP when used for
|
||||
DECnet communications */
|
||||
dup_clear(dup, FALSE);
|
||||
dup_rxcsr[dup] |= RXCSR_M_STRSYN | RXCSR_M_RCVEN;
|
||||
@ -917,7 +899,7 @@ if (!tmxr_tpbusyln(&dup_ldsc[dup])) { /* Not Busy sending? */
|
||||
}
|
||||
breturn = TRUE;
|
||||
}
|
||||
sim_debug (DBG_TRC, DUPDPTR, "dup_put_msg_bytes(dup=%d, len=%d, start=%s, end=%s) %s\n",
|
||||
sim_debug (DBG_TRC, DUPDPTR, "dup_put_msg_bytes(dup=%d, len=%d, start=%s, end=%s) %s\n",
|
||||
dup, (int)len, start ? "TRUE" : "FALSE", end ? "TRUE" : "FALSE", breturn ? "Good" : "Busy");
|
||||
if (breturn && (tmxr_tpbusyln (&dup_ldsc[dup]) || dup_xmtpkbytes[dup])) {
|
||||
if (dup_xmt_complete_callback[dup])
|
||||
@ -941,20 +923,20 @@ if ((dup_rcvpkinoff[dup] == 0) && (dup_rcvpkbytes[dup] != 0)) {
|
||||
*pbuf = &dup_rcvpacket[dup][0];
|
||||
*psize = dup_rcvpkbytes[dup];
|
||||
}
|
||||
sim_debug (DBG_TRC, DUPDPTR, "dup_get_packet(dup=%d, psize=%d)\n",
|
||||
sim_debug (DBG_TRC, DUPDPTR, "dup_get_packet(dup=%d, psize=%d)\n",
|
||||
dup, (int)*psize);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
static t_stat dup_rcv_byte (int32 dup)
|
||||
{
|
||||
sim_debug (DBG_TRC, DUPDPTR, "dup_rcv_byte(dup=%d) - %s, byte %d of %d\n", dup,
|
||||
sim_debug (DBG_TRC, DUPDPTR, "dup_rcv_byte(dup=%d) - %s, byte %d of %d\n", dup,
|
||||
(dup_rxcsr[dup] & RXCSR_M_RCVEN) ? "enabled" : "disabled",
|
||||
dup_rcvpkinoff[dup], dup_rcvpkbytes[dup]);
|
||||
if (!(dup_rxcsr[dup] & RXCSR_M_RCVEN) || (dup_rcvpkbytes[dup] == 0) || (dup_rxcsr[dup] & RXCSR_M_RXDONE))
|
||||
return SCPE_OK;
|
||||
if (dup_rcv_packet_data_callback[dup]) {
|
||||
sim_debug (DBG_TRC, DUPDPTR, "dup_rcv_byte(dup=%d, psize=%d) - Invoking Receive Data callback\n",
|
||||
sim_debug (DBG_TRC, DUPDPTR, "dup_rcv_byte(dup=%d, psize=%d) - Invoking Receive Data callback\n",
|
||||
dup, (int)dup_rcvpkbytes[dup]);
|
||||
dup_rcv_packet_data_callback[dup](dup, dup_rcvpkbytes[dup]);
|
||||
return SCPE_OK;
|
||||
@ -964,7 +946,7 @@ dup_rxdbuf[dup] &= ~RXDBUF_M_RCRCER;
|
||||
dup_rxdbuf[dup] &= ~RXDBUF_M_RXDBUF;
|
||||
dup_rxdbuf[dup] |= dup_rcvpacket[dup][dup_rcvpkinoff[dup]++];
|
||||
dup_rxcsr[dup] |= RXCSR_M_RXDONE;
|
||||
if (((dup_rcvpkinoff[dup] == 8) ||
|
||||
if (((dup_rcvpkinoff[dup] == 8) ||
|
||||
(dup_rcvpkinoff[dup] >= dup_rcvpkbytes[dup])) &&
|
||||
(0 == ddcmp_crc16 (0, dup_rcvpacket[dup], dup_rcvpkinoff[dup])))
|
||||
dup_rxdbuf[dup] |= RXDBUF_M_RCRCER;
|
||||
@ -1086,7 +1068,7 @@ if (active)
|
||||
else {
|
||||
for (dup=0; dup < dup_desc.lines; dup++) {
|
||||
if (dup_speed[dup]/8) {
|
||||
dup_wait[dup] = (tmxr_poll)/(dup_speed[dup]/8);
|
||||
dup_wait[dup] = (tmxr_poll*2)/(dup_speed[dup]/8);
|
||||
if (dup_wait[dup] < DUP_WAIT)
|
||||
dup_wait[dup] = DUP_WAIT;
|
||||
}
|
||||
@ -1103,36 +1085,36 @@ return SCPE_OK;
|
||||
|
||||
static void dup_clr_rxint (int32 dup)
|
||||
{
|
||||
dup_rxi = dup_rxi & ~(1 << dup); /* clr mux rcv int */
|
||||
if (dup_rxi == 0 && dup_txi == 0) /* all clr? */
|
||||
uba_clr_irq(&dup_dib);
|
||||
else uba_set_irq(&dup_dib); /* no, set intr */
|
||||
return;
|
||||
int vect;
|
||||
vect = dup_dib.uba_vect + (dup * 010); /* return vector */
|
||||
uba_clr_irq(&dup_dib, vect);
|
||||
return;
|
||||
}
|
||||
|
||||
static void dup_set_rxint (int32 dup)
|
||||
{
|
||||
dup_rxi = dup_rxi | (1 << dup); /* set mux rcv int */
|
||||
uba_set_irq (&dup_dib); /* set master intr */
|
||||
sim_debug(DEBUG_IRQ, DUPDPTR, "dup_set_rxint(dup=%d)\n", dup);
|
||||
return;
|
||||
int vect;
|
||||
vect = dup_dib.uba_vect + (dup * 010); /* return vector */
|
||||
uba_set_irq(&dup_dib, vect);
|
||||
sim_debug(DEBUG_IRQ, DUPDPTR, "dup_set_rxint(dup=%d)\n", dup);
|
||||
return;
|
||||
}
|
||||
|
||||
static void dup_clr_txint (int32 dup)
|
||||
{
|
||||
dup_txi = dup_txi & ~(1 << dup); /* clr mux xmt int */
|
||||
if (dup_txi == 0 && dup_rxi == 0) /* all clr? */
|
||||
uba_clr_irq (&dup_dib);
|
||||
else uba_set_irq (&dup_dib); /* no, set intr */
|
||||
return;
|
||||
int vect;
|
||||
vect = dup_dib.uba_vect + 4 + (dup * 010); /* return vector */
|
||||
uba_clr_irq(&dup_dib, vect);
|
||||
return;
|
||||
}
|
||||
|
||||
static void dup_set_txint (int32 dup)
|
||||
{
|
||||
dup_txi = dup_txi | (1 << dup); /* set mux xmt int */
|
||||
uba_set_irq (&dup_dib); /* set master intr */
|
||||
sim_debug(DEBUG_IRQ, DUPDPTR, "dup_set_txint(dup=%d)\n", dup);
|
||||
return;
|
||||
int vect;
|
||||
vect = dup_dib.uba_vect + 4 + (dup * 010); /* return vector */
|
||||
uba_set_irq(&dup_dib, vect);
|
||||
sim_debug(DEBUG_IRQ, DUPDPTR, "dup_set_txint(dup=%d)\n", dup);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Device reset */
|
||||
@ -1189,8 +1171,12 @@ for (i = 0; i < dup_desc.lines; i++) { /* init each line */
|
||||
if (dup_units[i].flags & UNIT_ATT)
|
||||
++attached;
|
||||
}
|
||||
dup_rxi = dup_txi = 0; /* clr master int */
|
||||
uba_clr_irq (&dup_dib);
|
||||
for (i = 0; i < dup_desc.lines; i++) { /* Clear irq's */
|
||||
int vect = dup_dib.uba_vect + (i * 010);
|
||||
uba_clr_irq(&dup_dib, vect);
|
||||
vect += 4;
|
||||
uba_clr_irq(&dup_dib, vect);
|
||||
}
|
||||
tmxr_set_modem_control_passthru (&dup_desc); /* We always want Modem Control */
|
||||
dup_desc.notelnet = TRUE; /* We always want raw tcp socket */
|
||||
dup_desc.dptr = DUPDPTR; /* Connect appropriate device */
|
||||
|
||||
123
PDP10/ks10_dz.c
123
PDP10/ks10_dz.c
@ -124,7 +124,7 @@ t_stat dz_detach (UNIT *uptr);
|
||||
t_stat dz_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag,
|
||||
const char *cptr);
|
||||
const char *dz_description (DEVICE *dptr);
|
||||
DIB dz_dib = { 0760000, 077, 0340, 5, 3, &dz_read, &dz_write, &dz_vect, 0, 0 };
|
||||
DIB dz_dib = { 0760000, 077, 0340, 5, 3, &dz_read, &dz_write, 0, 0, 0 };
|
||||
|
||||
UNIT dz_unit = {
|
||||
UDATA (&dz_svc, TT_MODE_7B+UNIT_IDLE+UNIT_DISABLE+UNIT_ATTABLE, 0), KBD_POLL_WAIT
|
||||
@ -188,6 +188,8 @@ dz_write(DEVICE *dptr, t_addr addr, uint16 data, int32 access)
|
||||
TMLN *lp;
|
||||
int i;
|
||||
|
||||
if ((dptr->flags & DEV_DIS) != 0)
|
||||
return 1;
|
||||
if ((dptr->units[0].flags & UNIT_DIS) != 0)
|
||||
return 1;
|
||||
addr &= dibp->uba_mask;
|
||||
@ -221,6 +223,15 @@ dz_write(DEVICE *dptr, t_addr addr, uint16 data, int32 access)
|
||||
}
|
||||
dz_csr[base] &= ~(TIE|SAE|RIE|MSE|CLR|MAINT);
|
||||
dz_csr[base] |= data & (TIE|SAE|RIE|MSE|MAINT);
|
||||
if (((dz_csr[base] & (RDONE|RIE)) == (RDONE|RIE)) ||
|
||||
(dz_csr[base] & (SA|SAE)) == (SA|SAE))
|
||||
uba_set_irq(dibp, dibp->uba_vect + (010 * base));
|
||||
else
|
||||
uba_clr_irq(dibp, dibp->uba_vect + (010 * base));
|
||||
if ((dz_csr[base] & (TRDY|TIE)) == (TRDY|TIE))
|
||||
uba_set_irq(dibp, dibp->uba_vect + 4 + (010 * base));
|
||||
else
|
||||
uba_clr_irq(dibp, dibp->uba_vect + 4 + (010 * base));
|
||||
break;
|
||||
|
||||
case 2:
|
||||
@ -245,6 +256,7 @@ dz_write(DEVICE *dptr, t_addr addr, uint16 data, int32 access)
|
||||
else
|
||||
data = (temp & 0177400) | data;
|
||||
}
|
||||
dz_csr[base] &= ~(TRDY);
|
||||
for (i = 0; i < 8; i++) {
|
||||
lp = &dz_ldsc[ln + i];
|
||||
if ((data & (LINE_ENB << i)) != 0)
|
||||
@ -255,8 +267,9 @@ dz_write(DEVICE *dptr, t_addr addr, uint16 data, int32 access)
|
||||
tmxr_set_get_modem_bits(lp, TMXR_MDM_OUTGOING, 0, NULL);
|
||||
else
|
||||
tmxr_set_get_modem_bits(lp, 0, TMXR_MDM_OUTGOING, NULL);
|
||||
sim_debug(DEBUG_DETAIL, dptr, "DZ%o sstatus %07o %o %o\n", base, data, i, dz_flags[ln+i]);
|
||||
sim_debug(DEBUG_EXP, dptr, "DZ%o sstatus %07o %o %o\n", base, data, i, dz_flags[ln+i]);
|
||||
}
|
||||
uba_clr_irq(dibp, dibp->uba_vect + 4 + (010 * base));
|
||||
break;
|
||||
|
||||
case 6:
|
||||
@ -280,12 +293,11 @@ dz_write(DEVICE *dptr, t_addr addr, uint16 data, int32 access)
|
||||
if (r == SCPE_STALL)
|
||||
dz_xmit[ln] = TRDY | ch;
|
||||
}
|
||||
dz_csr[base] &= ~TRDY;
|
||||
uba_clr_irq(dibp, dibp->uba_vect + 4 + (010 * base));
|
||||
break;
|
||||
}
|
||||
|
||||
dz_csr[base] &= ~TRDY;
|
||||
if ((dz_csr[base] & MSE) == 0)
|
||||
return 0;
|
||||
dz_checkirq(dibp);
|
||||
return 0;
|
||||
}
|
||||
@ -300,6 +312,8 @@ dz_read(DEVICE *dptr, t_addr addr, uint16 *data, int32 access)
|
||||
TMLN *lp;
|
||||
int i;
|
||||
|
||||
if ((dptr->flags & DEV_DIS) != 0)
|
||||
return 1;
|
||||
if ((dptr->units[0].flags & UNIT_DIS) != 0)
|
||||
return 1;
|
||||
addr &= dibp->uba_mask;
|
||||
@ -318,26 +332,29 @@ dz_read(DEVICE *dptr, t_addr addr, uint16 *data, int32 access)
|
||||
if ((dz_csr[base] & MSE) == 0)
|
||||
return 0;
|
||||
dz_csr[base] &= ~(SA|RDONE);
|
||||
uba_clr_irq(dibp, dibp->uba_vect + (010 * base));
|
||||
if (!empty(&dz_recv[base])) {
|
||||
*data = dz_recv[base].buff[dz_recv[base].out_ptr];
|
||||
inco(&dz_recv[base]);
|
||||
dz_recv[base].len = 0;
|
||||
}
|
||||
if (!empty(&dz_recv[base]))
|
||||
if (!empty(&dz_recv[base])) {
|
||||
dz_csr[base] |= RDONE;
|
||||
dz_checkirq(dibp);
|
||||
if (dz_csr[base] & RIE) {
|
||||
uba_set_irq(dibp, dibp->uba_vect + (010 * base));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
temp = 0;
|
||||
ln = base << 3;
|
||||
base <<= 3;
|
||||
/* Set up the current status */
|
||||
for (i = 0; i < 8; i++) {
|
||||
sim_debug(DEBUG_DETAIL, dptr, "DZ%o status %o %o\n", base, i, dz_flags[ln+i]);
|
||||
if (dz_flags[ln + i] & LINE_EN)
|
||||
temp |= LINE_ENB << i;
|
||||
if (dz_flags[ln + i] & DTR_FLAG)
|
||||
temp |= DTR << i;
|
||||
for (ln = 0; ln < 8; ln++) {
|
||||
if (dz_flags[base + ln] & LINE_EN)
|
||||
temp |= LINE_ENB << ln;
|
||||
if (dz_flags[base + ln] & DTR_FLAG)
|
||||
temp |= DTR << ln;
|
||||
}
|
||||
*data = temp;
|
||||
break;
|
||||
@ -374,7 +391,8 @@ t_stat dz_svc (UNIT *uptr)
|
||||
ln = tmxr_poll_conn (&dz_desc); /* look for connect */
|
||||
if (ln >= 0) { /* got one? rcv enb*/
|
||||
dz_ring[(ln & 030) >> 3] |= (1 << (ln & 7));
|
||||
sim_debug(DEBUG_DETAIL, &dz_dev, "DC line connect %d\n", ln);
|
||||
sim_debug(DEBUG_DETAIL, &dz_dev, "DZ line connect %d\n", ln);
|
||||
dz_xmit[ln] = 0;
|
||||
}
|
||||
tmxr_poll_tx(&dz_desc);
|
||||
tmxr_poll_rx(&dz_desc);
|
||||
@ -392,7 +410,7 @@ t_stat dz_svc (UNIT *uptr)
|
||||
while (!full(&dz_recv[base])) {
|
||||
int32 ch = tmxr_getc_ln(lp);
|
||||
if ((ch & TMXR_VALID) != 0) {
|
||||
if (ch & SCPE_BREAK) { /* break? */
|
||||
if (ch & SCPE_BREAK) { /* break? */
|
||||
temp = FRM_ERR;
|
||||
} else {
|
||||
ch = sim_tt_inpcvt (ch, TT_GET_MODE(dz_unit.flags) | TTUF_KSR);
|
||||
@ -402,10 +420,15 @@ t_stat dz_svc (UNIT *uptr)
|
||||
inci(&dz_recv[base]);
|
||||
dz_recv[base].len++;
|
||||
dz_csr[base] |= RDONE;
|
||||
if (dz_recv[base].len > 16)
|
||||
if (dz_csr[base] & RIE)
|
||||
uba_set_irq(dibp, dibp->uba_vect + (010 * base));
|
||||
if (dz_recv[base].len > 16) {
|
||||
dz_csr[base] |= SA;
|
||||
sim_debug(DEBUG_DETAIL, dptr, "TTY recieve %d: %o\n",
|
||||
ln, ch);
|
||||
if (dz_csr[base] & SAE) {
|
||||
uba_set_irq(dibp, dibp->uba_vect + (010 * base));
|
||||
}
|
||||
}
|
||||
sim_debug(DEBUG_DETAIL, dptr, "TTY recieve %d: %o\n", ln, ch);
|
||||
} else
|
||||
break;
|
||||
}
|
||||
@ -423,56 +446,36 @@ dz_checkirq(struct pdp_dib *dibp)
|
||||
int j;
|
||||
int i;
|
||||
int ln;
|
||||
int stop;
|
||||
TMLN *lp;
|
||||
int irq = 0;
|
||||
|
||||
for (i = 0; i < NUM_DEVS_DZ; i++) {
|
||||
if ((dz_csr[i] & MSE) == 0)
|
||||
continue;
|
||||
ln = ((dz_csr[i] & TLINE) >> TLINE_V) + (i << 3);
|
||||
dz_csr[i] &= ~TRDY;
|
||||
/* See if there is another line ready */
|
||||
for (j = 0; j < 8; j++) {
|
||||
ln = (ln & 070) | ((ln + 1) & 07);
|
||||
lp = &dz_ldsc[ln];
|
||||
/* Connected and empty xmit_buffer */
|
||||
if ((dz_flags[ln] & LINE_EN) != 0 && dz_xmit[ln] == 0) {
|
||||
dz_csr[i] &= ~(TLINE);
|
||||
dz_csr[i] |= TRDY | ((ln & 07) << TLINE_V);
|
||||
break;
|
||||
}
|
||||
}
|
||||
stop = ln;
|
||||
if ((dz_csr[i] & TRDY) == 0) {
|
||||
/* See if there is another line ready */
|
||||
do {
|
||||
ln = (ln & 070) | ((ln + 1) & 07);
|
||||
lp = &dz_ldsc[ln];
|
||||
/* Connected and empty xmit_buffer */
|
||||
if ((dz_flags[ln] & LINE_EN) != 0 && dz_xmit[ln] == 0) {
|
||||
sim_debug(DEBUG_DETAIL, &dz_dev, "DZ line ready %o\n", ln);
|
||||
|
||||
/* Check flags to see if anything would generate an interrupt */
|
||||
if ((dz_csr[i] & (TIE|TRDY)) == (TIE|TRDY) ||
|
||||
(dz_csr[i] & (SA|SAE)) == (SA|SAE) ||
|
||||
(dz_csr[i] & (RDONE|SAE|RIE)) == (RDONE|RIE)) {
|
||||
sim_debug(DEBUG_DETAIL, &dz_dev, "Set irq %05o\n", dz_csr[i]);
|
||||
uba_set_irq(dibp);
|
||||
return;
|
||||
dz_csr[i] &= ~(TRDY|TLINE);
|
||||
dz_csr[i] |= TRDY | ((ln & 07) << TLINE_V);
|
||||
if (dz_csr[i] & TIE) {
|
||||
uba_set_irq(dibp, dibp->uba_vect + 4 + (010 * i));
|
||||
}
|
||||
break;
|
||||
}
|
||||
} while (ln != stop);
|
||||
}
|
||||
}
|
||||
sim_debug(DEBUG_DETAIL, &dz_dev, "Clr irq\n");
|
||||
/* Nothing found, so clear any flags */
|
||||
uba_clr_irq(dibp);
|
||||
}
|
||||
|
||||
/* Return the vector of first ready device */
|
||||
uint16
|
||||
dz_vect(struct pdp_dib *dibp)
|
||||
{
|
||||
int i;
|
||||
uint16 vect = dibp->uba_vect;
|
||||
for (i = 0; i < NUM_DEVS_DZ; i++) {
|
||||
if ((dz_csr[i] & (SA|SAE)) == (SA|SAE) ||
|
||||
(dz_csr[i] & (RDONE|SAE|RIE)) == (RDONE|RIE))
|
||||
return vect;
|
||||
if ((dz_csr[i] & (TIE|TRDY)) == (TIE|TRDY))
|
||||
return vect + 4;
|
||||
vect += 010;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat
|
||||
|
||||
210
PDP10/ks10_kmc.c
210
PDP10/ks10_kmc.c
@ -359,7 +359,7 @@ static int32 BintPending = 0;
|
||||
* For this to work, k, a uint32 must be in scope and valid.
|
||||
*
|
||||
* k can be found in several ways:
|
||||
* k is the offset into any of the tables.
|
||||
* k is the offset into any of the tables.
|
||||
* Given a UNIT pointer k = txup->unit_kmc.
|
||||
* The KMC assigned to control a DUP is stored it its dupstate.
|
||||
* k = dupState[dupno]->kmc; (-1 if not controlled by any KMC)
|
||||
@ -398,7 +398,7 @@ static int32 BintPending = 0;
|
||||
/* KMC event notifications are funneled through the small number of CSRs.
|
||||
* Since the CSRs may not be available when an event happens, events are
|
||||
* queued in these structures. An event is represented by the values to
|
||||
* be exposed in BSEL2, BSEL4, and BSEL6.
|
||||
* be exposed in BSEL2, BSEL4, and BSEL6.
|
||||
*
|
||||
* Queue overflow is signalled by setting the overflow bit in the entry
|
||||
* at the tail of the completion queue at the time a new entry fails to
|
||||
@ -489,15 +489,13 @@ static t_stat kmc_showLineSpeed (FILE *st, UNIT *txup, int32 val, CONST void *de
|
||||
static t_stat kmc_showStatus (FILE *st, UNIT *up, int32 v, CONST void *dp);
|
||||
|
||||
static t_stat kmc_help (FILE *st, DEVICE *dptr,
|
||||
UNIT *uptr, int32 flag, const char *cptr);
|
||||
UNIT *uptr, int32 flag, const char *cptr);
|
||||
static const char *kmc_description (DEVICE *dptr);
|
||||
|
||||
/* Global data */
|
||||
|
||||
extern int32 tmxr_poll; /* calibrated delay */
|
||||
|
||||
static uint16 kmc_intvect(DIB *dibp);
|
||||
|
||||
#define IOLN_KMC 010
|
||||
|
||||
static DIB kmc_dib = {
|
||||
@ -506,10 +504,10 @@ static DIB kmc_dib = {
|
||||
0540, /* Interrupt vector */
|
||||
5, /* Interrupt level */
|
||||
3, /* UBA Adaptor number */
|
||||
|
||||
|
||||
&kmc_readCsr, /* rd - read IO */
|
||||
&kmc_writeCsr, /* wr - write IO */
|
||||
&kmc_intvect, /* Return interrupt vector */
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* One UNIT for each (possible) active line for transmit, and another for receive */
|
||||
@ -529,7 +527,7 @@ static UNIT tx_units[MAX_ACTIVE][KMC_UNITS]; /* Line 0 is primary unit. txup re
|
||||
static UNIT rx_units[MAX_ACTIVE][KMC_UNITS]; /* Secondary unit, used for RX. rxup references */
|
||||
|
||||
DEVICE kmc_int_rxdev = {
|
||||
"KDP-RX", rx_units[0],
|
||||
"KDP-RX", rx_units[0],
|
||||
NULL, /* Register decode tables */
|
||||
NULL, /* Modifier table */
|
||||
INITIAL_KMCS, /* Number of units */
|
||||
@ -619,8 +617,8 @@ MTAB kmc_mod[] = {
|
||||
};
|
||||
|
||||
DEVICE kmc_dev = {
|
||||
"KDP",
|
||||
tx_units[0],
|
||||
"KDP",
|
||||
tx_units[0],
|
||||
kmc_reg, /* Register decode tables */
|
||||
kmc_mod, /* Modifier table */
|
||||
INITIAL_KMCS, /* Number of units */
|
||||
@ -753,7 +751,7 @@ static t_stat kmc_reset(DEVICE* dptr) {
|
||||
|
||||
if (sim_switches & SWMASK ('P'))
|
||||
gflags &= ~FLG_INIT;
|
||||
|
||||
|
||||
if (!(gflags & FLG_INIT)) { /* Power-up reset */
|
||||
sel0 = 0x00aa;
|
||||
sel2 = 0xa5a5;
|
||||
@ -773,7 +771,6 @@ static t_stat kmc_reset(DEVICE* dptr) {
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read registers:
|
||||
*/
|
||||
@ -809,7 +806,7 @@ static t_stat kmc_readCsr(DEVICE *dptr, t_addr PA, uint16* data, int32 access) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
sim_debug (DF_RGR, &kmc_dev, "KMC%u CSR rd: addr=0%06o SEL%d, data=%06o 0x%04x access=%d\n",
|
||||
k, PA, PA & 07, *data, *data, access);
|
||||
return SCPE_OK;
|
||||
@ -937,40 +934,6 @@ static t_stat kmc_writeCsr(DEVICE *dptr, t_addr PA, uint16 data, int32 access) {
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
static uint16
|
||||
kmc_intvect(DIB *dibp)
|
||||
{
|
||||
int32 vec = 0; /* no interrupt request active */
|
||||
int32 k;
|
||||
|
||||
for (k = 0; ((size_t)k) < DIM (kmc_gflags); k++) {
|
||||
if (gflags & FLG_AINT) {
|
||||
vec = dibp->uba_vect + (k*010);
|
||||
gflags &= ~FLG_AINT;
|
||||
--AintPending;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (vec == 0) {
|
||||
for (k = 0; ((size_t)k) < DIM (kmc_gflags); k++) {
|
||||
if (gflags & FLG_BINT) {
|
||||
vec = dibp->uba_vect + 4 + (k*010);
|
||||
gflags &= ~FLG_BINT;
|
||||
--BintPending;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (AintPending != 0 || BintPending != 0)
|
||||
uba_set_irq(dibp);
|
||||
// else
|
||||
// uba_clr_irq(dibp);
|
||||
|
||||
return vec;
|
||||
}
|
||||
|
||||
|
||||
/* Microengine simulator
|
||||
*
|
||||
@ -999,7 +962,7 @@ static void kmc_doMicroinstruction (int32 k, uint16 instr) {
|
||||
break;
|
||||
case 0121202: /* MOVE <NPR><BSEL2> */
|
||||
case 0021002: /* MOVE <IBUS 0><BSEL2> */
|
||||
sel2 = (sel2 & ~0xFF) | 0;
|
||||
sel2 = (sel2 & ~0xFF) | 0;
|
||||
break;
|
||||
default:
|
||||
if ((instr & 0160000) == 0000000) { /* MVI */
|
||||
@ -1053,7 +1016,7 @@ static void kmc_doMicroinstruction (int32 k, uint16 instr) {
|
||||
* o When a new buffer descriptor is delivered by the host
|
||||
* o When a state machine timeout expires
|
||||
* o When a DUP transmit completion occurs.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
static t_stat kmc_txService (UNIT *txup) {
|
||||
@ -1110,12 +1073,13 @@ static t_stat kmc_txService (UNIT *txup) {
|
||||
switch (d->txstate) {
|
||||
case TXDONE: /* Resume from completions */
|
||||
d->txstate = TXIDLE;
|
||||
/* Fall through */
|
||||
|
||||
case TXIDLE: /* Check for new BD */
|
||||
if (!kmc_txNewBdl(d)) {
|
||||
TXSTOP;
|
||||
}
|
||||
d->txmlen =
|
||||
d->txmlen =
|
||||
d->txslen = 0;
|
||||
d->txstate = TXRTS;
|
||||
|
||||
@ -1124,8 +1088,8 @@ static t_stat kmc_txService (UNIT *txup) {
|
||||
k, d->line, d->dupidx);
|
||||
kmc_ctrlOut (k, SEL6_CO_NXM, 0, d->line, 0);
|
||||
}
|
||||
/* Fall through */
|
||||
|
||||
|
||||
case TXRTS: /* Wait for CTS */
|
||||
if (dup_get_CTS (d->dupidx) <= 0) {
|
||||
TXDELAY (TXRTS, TXCTS_DELAY);
|
||||
@ -1135,6 +1099,8 @@ static t_stat kmc_txService (UNIT *txup) {
|
||||
|
||||
sim_debug (DF_BUF, &kmc_dev, "KMC%u line %u: transmitting bdl=%06o\n",
|
||||
k, txup->unit_line, d->tx.bda);
|
||||
/* Fall through */
|
||||
|
||||
case TXSOM: /* Start assembling a message */
|
||||
if (!(d->tx.bd[2] & BDL_SOM)) {
|
||||
sim_debug (DF_ERR, &kmc_dev, "KMC%u line %u: TX BDL not SOM\n", k, d->line);
|
||||
@ -1155,12 +1121,14 @@ static t_stat kmc_txService (UNIT *txup) {
|
||||
}
|
||||
|
||||
d->txstate = TXHDR;
|
||||
/* Fall through */
|
||||
|
||||
case TXHDR: /* Assemble the header */
|
||||
if (!kmc_txAppendBuffer(d)) { /* NXM - Try next list */
|
||||
TXDELAY (TXDONE, TXDONE_DELAY);
|
||||
}
|
||||
TXDELAY (TXHDRX, XTIME (d->tx.bd[1], d->linespeed));
|
||||
/* Fall through */
|
||||
|
||||
case TXHDRX: /* Report header descriptor done */
|
||||
if (!kmc_bufferAddressOut (k, 0, 0, d->line, d->tx.bda)) {
|
||||
@ -1185,7 +1153,7 @@ static t_stat kmc_txService (UNIT *txup) {
|
||||
/* EOM expecting data to follow.
|
||||
* However, if the OS computes and includes HRC in a data/MOP message, this can
|
||||
* be the last descriptor. In that case, this is EOM.
|
||||
*/
|
||||
*/
|
||||
if (d->tx.bd[2] & BDL_LDS) {
|
||||
TXSTATE (TXMRDY);
|
||||
break;
|
||||
@ -1203,12 +1171,14 @@ static t_stat kmc_txService (UNIT *txup) {
|
||||
TXSTOP;
|
||||
}
|
||||
d->txstate = TXDATA;
|
||||
/* Fall through */
|
||||
|
||||
case TXDATA: /* Assemble data/maint payload */
|
||||
if (!kmc_txAppendBuffer(d)) { /* NXM */
|
||||
TXDELAY (TXDONE, TXDONE_DELAY);
|
||||
}
|
||||
TXDELAY (TXDATAX, XTIME (d->tx.bd[1], d->linespeed));
|
||||
/* Fall through */
|
||||
|
||||
case TXDATAX: /* Report BD completion */
|
||||
if (!kmc_bufferAddressOut (k, 0, 0, d->line, d->tx.bda)) {
|
||||
@ -1221,13 +1191,14 @@ static t_stat kmc_txService (UNIT *txup) {
|
||||
TXDELAY (TXDONE, TXDONE_DELAY);
|
||||
}
|
||||
TXSTATE (TXDATA);
|
||||
/* Fall through */
|
||||
|
||||
/* These states hand-off the message to the DUP.
|
||||
* txService suspends until transmit complete.
|
||||
* Note that txComplete can happen within the calls to the DUP.
|
||||
*/
|
||||
case TXMRDY: /* Data with OS-embedded HCRC */
|
||||
d->txstate = TXACT;
|
||||
d->txstate = TXACT;
|
||||
ASSURE (d->txmsg[d->txslen + 0] != DDCMP_ENQ);
|
||||
ASSURE (((d->txmlen - d->txslen) > 8) && /* Data, length should match count */
|
||||
(((size_t)(((d->txmsg[d->txslen + 2] & 077) << 8) | d->txmsg[d->txslen + 1])) ==
|
||||
@ -1334,7 +1305,7 @@ static t_stat kmc_rxService (UNIT *rxup) {
|
||||
uint16 xrem, seglen;
|
||||
int i;
|
||||
t_addr ba;
|
||||
|
||||
|
||||
|
||||
ASSURE ((k >= 0) && (k < (int32) kmc_dev.numunits) && (d->kmc == k) &&
|
||||
(d->line == rxup->unit_line));
|
||||
@ -1349,7 +1320,7 @@ static t_stat kmc_rxService (UNIT *rxup) {
|
||||
|
||||
rxup->wait = RXPOLL_DELAY;
|
||||
|
||||
/* CAUTION: This switch statement uses fall-through cases
|
||||
/* CAUTION: This switch statement uses fall-through cases
|
||||
*
|
||||
* The KILL logic in kmc_rxBufferIn tracks these states.
|
||||
*/
|
||||
@ -1403,7 +1374,7 @@ static t_stat kmc_rxService (UNIT *rxup) {
|
||||
uint8 type = d->rxmsg[1];
|
||||
|
||||
sim_debug (DF_BUF, &kmc_dev, "KMC%u line %u: receiving %s\n",
|
||||
k, rxup->unit_line,
|
||||
k, rxup->unit_line,
|
||||
((type >= DIM (ctlnames))? "UNKNOWN" : ctlnames[type]));
|
||||
} else {
|
||||
sim_debug (DF_BUF, &kmc_dev, "KMC%u line %u: receiving %s len=%u\n",
|
||||
@ -1463,7 +1434,9 @@ static t_stat kmc_rxService (UNIT *rxup) {
|
||||
ASSURE (seglen > 0);
|
||||
|
||||
ba = d->rx.ba;
|
||||
sim_debug (DF_PKT, &kmc_dev, "Send to: ");
|
||||
for (i = 0; i < seglen; i++) {
|
||||
sim_debug (DF_PKT, &kmc_dev, "%02x ", d->rxmsg[d->rxused + i]);
|
||||
if (uba_write_npr_byte(ba, kmc_dib.uba_ctl, d->rxmsg[d->rxused + i]) == 0) {
|
||||
uint16 bd[3];
|
||||
memcpy(bd, &d->rx.bd, sizeof bd);
|
||||
@ -1476,9 +1449,10 @@ static t_stat kmc_rxService (UNIT *rxup) {
|
||||
}
|
||||
ba++;
|
||||
}
|
||||
sim_debug (DF_PKT, &kmc_dev, "\n");
|
||||
d->rx.ba += seglen;
|
||||
d->rxused += seglen;
|
||||
d->rx.rcvc += seglen;
|
||||
d->rxused += seglen;
|
||||
|
||||
if (d->rxused == 6) {
|
||||
if (0 != ddcmp_crc16 (0, d->rxmsg, 8)) {
|
||||
@ -1584,7 +1558,7 @@ static t_stat kmc_rxService (UNIT *rxup) {
|
||||
}
|
||||
rxup->wait = RXNEWBD_DELAY;
|
||||
break;
|
||||
|
||||
|
||||
case RXNOBUF:
|
||||
kmc_ctrlOut (k, SEL6_CO_NOBUF, SEL2_IOT, d->line, 0);
|
||||
d->rxstate = RXIDLE;
|
||||
@ -1723,7 +1697,7 @@ static void kmc_startUcode (int32 k) {
|
||||
initqueue (&d->rxqh, &d->rxavail, INIT_HDR_ONLY);
|
||||
initqueue (&d->txqh, &d->txavail, INIT_HDR_ONLY);
|
||||
initqueue (&d->bdqh, &d->bdavail, MAX_LIST_SIZE(d->bdq));
|
||||
|
||||
|
||||
d->rxstate = RXIDLE;
|
||||
d->txstate = TXIDLE;
|
||||
}
|
||||
@ -1738,7 +1712,7 @@ static void kmc_startUcode (int32 k) {
|
||||
kmc_updints (k);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Perform an input command
|
||||
*
|
||||
@ -1748,7 +1722,7 @@ static void kmc_startUcode (int32 k) {
|
||||
*
|
||||
* The microcode sets RDI by writing the entire BSEL2 with just RDI.
|
||||
* This works because RDO can not be set at the same time as RDI.
|
||||
*
|
||||
*
|
||||
* Mark P found that VMS drivers rely on this and BIS the command code.
|
||||
* The COM IOP-DUP manual does say that all bits of BSEL2 are
|
||||
* cleared on completion of a command. However, an output command could
|
||||
@ -1758,7 +1732,7 @@ static void kmc_startUcode (int32 k) {
|
||||
* clears RDI. Upon completion of a command, 'all bits of bsel2
|
||||
* are cleared by the KMC'. This is not implemented literally, since
|
||||
* the processing of a command can result in an immediate completion,
|
||||
* setting RDO and the other registers.
|
||||
* setting RDO and the other registers.
|
||||
* Thus, although all bits are cleared before dispatching, RDO
|
||||
* and the other other bits of BSEL2 may be set for a output command
|
||||
* due to a completion if the host has cleared RQI.
|
||||
@ -1769,7 +1743,7 @@ static void kmc_dispatchInputCmd(int32 k) {
|
||||
int32 ba;
|
||||
int16 cmdsel2 = sel2;
|
||||
dupstate* d;
|
||||
|
||||
|
||||
line = (cmdsel2 & SEL2_LINE) >> SEL2_V_LINE;
|
||||
|
||||
sel2 &= ~0xFF; /* Clear BSEL2. */
|
||||
@ -1783,10 +1757,10 @@ static void kmc_dispatchInputCmd(int32 k) {
|
||||
}
|
||||
d = line2dup[line];
|
||||
ba = ((sel6 & SEL6_CO_XAD) << (16-SEL6_V_CO_XAD)) | sel4;
|
||||
|
||||
|
||||
sim_debug (DF_CMD, &kmc_dev, "KMC%u line %u: INPUT COMMAND sel2=%06o sel4=%06o sel6=%06o ba=%06o\n", k, line,
|
||||
cmdsel2, sel4, sel6, ba);
|
||||
|
||||
|
||||
switch (cmdsel2 & (SEL2_IOT | SEL2_CMD)) {
|
||||
case CMD_BUFFIN: /* TX BUFFER IN */
|
||||
kmc_txBufferIn(d, ba, sel6);
|
||||
@ -1816,7 +1790,7 @@ static void kmc_dispatchInputCmd(int32 k) {
|
||||
* assigned by a KMC. The CSR address is expressed as bits <12:3>
|
||||
* only. <17:13> are all set for IO page addresses and added by ucode.
|
||||
* The DUP has 8 registers, so <2:1> must be zero. The other bits are
|
||||
* reserved and must be zero.
|
||||
* reserved and must be zero.
|
||||
*
|
||||
* There is no way to release a line, short of re-starting the microcode.
|
||||
*
|
||||
@ -1845,7 +1819,7 @@ static void kmc_baseIn (int32 k, dupstate *d, uint16 cmdsel2, uint8 line) {
|
||||
|
||||
dupidx = dup_csr_to_linenum (csraddress);
|
||||
if ((dupidx < 0) || (((size_t) dupidx) >= DIM(dupState))) { /* Call this a NXM so OS can recover */
|
||||
sim_debug (DF_ERR, &kmc_dev, "KMC%u line %u: BASE IN %06o 0x%05x is not an enabled DUP %d\n",
|
||||
sim_debug (DF_ERR, &kmc_dev, "KMC%u line %u: BASE IN %06o 0x%05x is not an enabled DUP %d\n",
|
||||
k, line, csraddress, csraddress, dupidx);
|
||||
kmc_ctrlOut (k, SEL6_CO_NXM, 0, line, 0);
|
||||
return;
|
||||
@ -1870,7 +1844,7 @@ static void kmc_baseIn (int32 k, dupstate *d, uint16 cmdsel2, uint8 line) {
|
||||
line2dup[line] = d;
|
||||
d->line = line;
|
||||
|
||||
/*
|
||||
/*
|
||||
* Jumper W3 Installed causes RTS,DTR, and SecTxD to be cleared on Device Reset or bus init.
|
||||
* Jumper W3 is installed in factory DUPs, and in the KS10 config.
|
||||
* Make sure the DUP emulation enables this option.
|
||||
@ -1891,7 +1865,7 @@ static void kmc_baseIn (int32 k, dupstate *d, uint16 cmdsel2, uint8 line) {
|
||||
|
||||
d->dupidx = dupidx;
|
||||
|
||||
sim_debug (DF_INF, &kmc_dev, "KMC%u line %u: BASE IN DUP%u address=%06o 0x%05x assigned\n",
|
||||
sim_debug (DF_INF, &kmc_dev, "KMC%u line %u: BASE IN DUP%u address=%06o 0x%05x assigned\n",
|
||||
k, line, d->dupidx,csraddress, csraddress);
|
||||
return;
|
||||
}
|
||||
@ -1916,7 +1890,7 @@ static void kmc_ctrlIn (int32 k, dupstate *d, int line) {
|
||||
if (!(sel6 & SEL6_CI_ENABLE)) {
|
||||
sim_debug (DF_CMD, &kmc_dev, "line disabled\n");
|
||||
} else {
|
||||
sim_debug (DF_CMD, &kmc_dev, "enabled for %s in %s duplex",
|
||||
sim_debug (DF_CMD, &kmc_dev, "enabled for %s in %s duplex",
|
||||
(sel6 & SEL6_CI_DDCMP)? "DDCMP":"Bit-stuffing",
|
||||
(sel6 & SEL6_CI_HDX)? "half" : "full");
|
||||
if (sel6 & SEL6_CI_ENASS) {
|
||||
@ -1929,17 +1903,17 @@ static void kmc_ctrlIn (int32 k, dupstate *d, int line) {
|
||||
|
||||
/* BSEL4 has the polling count, which isn't needed for emulation */
|
||||
|
||||
d->linkstate &= ~(LINK_DSR|LINK_SEL);/* Initialize modem state reporting. */
|
||||
d->linkstate &= ~(LINK_DSR|LINK_SEL);/* Initialize modem state reporting. */
|
||||
|
||||
d->ctrlFlags = sel6;
|
||||
|
||||
/* Initialize DUP interface in the appropriate mode
|
||||
* DTR will be turned on.
|
||||
*/
|
||||
r = dup_setup_dup (d->dupidx, (sel6 & SEL6_CI_ENABLE),
|
||||
(sel6 & SEL6_CI_DDCMP),
|
||||
(sel6 & SEL6_CI_NOCRC),
|
||||
(sel6 & SEL6_CI_HDX),
|
||||
r = dup_setup_dup (d->dupidx, (sel6 & SEL6_CI_ENABLE),
|
||||
(sel6 & SEL6_CI_DDCMP),
|
||||
(sel6 & SEL6_CI_NOCRC),
|
||||
(sel6 & SEL6_CI_HDX),
|
||||
(sel6 & SEL6_CI_ENASS) ? (sel6 & SEL6_CI_SADDR) : 0);
|
||||
|
||||
/* If setup succeeded, enable packet callbacks.
|
||||
@ -1962,14 +1936,14 @@ static void kmc_ctrlIn (int32 k, dupstate *d, int line) {
|
||||
* RX BUFFER IN delivers a buffer descriptor list from the host to
|
||||
* the KMC. It may also deassign a buffer descriptor list.
|
||||
*
|
||||
* A buffer descriptor list is a sequential list of three word blocks in
|
||||
* A buffer descriptor list is a sequential list of three word blocks in
|
||||
* host memory space. Each 3-word block points to and describes the
|
||||
* boundaries of a single buffer, which is also in host CPU memory.
|
||||
* boundaries of a single buffer, which is also in host CPU memory.
|
||||
*
|
||||
* A buffer descriptor list is defined by its starting address. The
|
||||
* end of a buffer descriptor list is marked in the list. A maximum of
|
||||
* MAXQUEUE transmit and MAXQUEUE receive lists can be assigned to each
|
||||
* COMM IOP-DUP communications line.
|
||||
* COMM IOP-DUP communications line.
|
||||
*
|
||||
* The starting address of a buffer descriptor list must be word aligned.
|
||||
*
|
||||
@ -2003,7 +1977,7 @@ void kmc_rxBufferIn(dupstate *d, int32 ba, uint16 sel6v) {
|
||||
|
||||
if (!kmc_printBufferIn (k, &kmc_dev, d->line, TRUE, d->rxavail, ba, sel6v))
|
||||
return;
|
||||
|
||||
|
||||
if (sel6v & SEL6_BI_KILL) {
|
||||
/* Kill all current RX buffers.
|
||||
* Resync the DUP receiver.
|
||||
@ -2044,7 +2018,7 @@ void kmc_rxBufferIn(dupstate *d, int32 ba, uint16 sel6v) {
|
||||
}
|
||||
qe->ba = ba;
|
||||
ASSURE (insqueue (&qe->hdr, d->rxqh.prev, &d->rxavail, MAXQUEUE));
|
||||
|
||||
|
||||
if (sel6v & SEL6_BI_KILL) { /* KILL & Replace - ENABLE is set too */
|
||||
kmc_ctrlOut (k, SEL6_CO_KDONE, SEL2_IOT, d->line, bda);
|
||||
}
|
||||
@ -2059,7 +2033,7 @@ void kmc_rxBufferIn(dupstate *d, int32 ba, uint16 sel6v) {
|
||||
|
||||
/* Message available callback
|
||||
*
|
||||
* The DUP calls this routine when a new message is available
|
||||
* The DUP calls this routine when a new message is available
|
||||
* to be read.
|
||||
*
|
||||
* If the line's receive thread is idle, it is called to start the
|
||||
@ -2122,7 +2096,7 @@ void kmc_txBufferIn(dupstate *d, int32 ba, uint16 sel6v) {
|
||||
|
||||
if (!kmc_printBufferIn (k, &kmc_dev, d->line, FALSE, d->txavail, ba, sel6v))
|
||||
return;
|
||||
|
||||
|
||||
if (sel6v & SEL6_BI_KILL) {
|
||||
/* Kill all current TX buffers. The DUP can't abort transmission in simulation, so
|
||||
* anything pending will stop when complete. The queue is reset here because
|
||||
@ -2152,7 +2126,7 @@ void kmc_txBufferIn(dupstate *d, int32 ba, uint16 sel6v) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!(qe = (BDL *)remqueue (d->bdqh.next, &d->bdavail))) {
|
||||
sim_debug (DF_ERR, &kmc_dev, "KMC%u line %u: Too many transmit buffers from host\n", k, d->line);
|
||||
kmc_halt (k, HALT_XMTOVF);
|
||||
@ -2161,13 +2135,13 @@ void kmc_txBufferIn(dupstate *d, int32 ba, uint16 sel6v) {
|
||||
qe->ba = ba;
|
||||
ASSURE (insqueue (&qe->hdr, d->txqh.prev, &d->txavail, MAXQUEUE));
|
||||
if (d->txstate == TXIDLE) {
|
||||
UNIT *txup = &tx_units[d->line][k];
|
||||
UNIT *txup = &tx_units[d->line][k];
|
||||
if (!sim_is_active (txup)) {
|
||||
txup->wait = TXSTART_DELAY;
|
||||
txup->wait = TXSTART_DELAY;
|
||||
sim_activate_after (txup, txup->wait);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2212,7 +2186,7 @@ static void kmc_txComplete (int32 dupidx, int status) {
|
||||
} else {
|
||||
if (d->tx.bd[2] & BDL_LDS)
|
||||
d->txstate = TXDONE;
|
||||
else
|
||||
else
|
||||
d->txstate = TXSOM;
|
||||
}
|
||||
sim_cancel (txup);
|
||||
@ -2225,13 +2199,13 @@ static void kmc_txComplete (int32 dupidx, int status) {
|
||||
|
||||
static t_bool kmc_txNewBdl(dupstate *d) {
|
||||
BDL *qe;
|
||||
|
||||
|
||||
if (!(qe = (BDL *)remqueue (d->txqh.next, &d->txavail))) {
|
||||
return FALSE;
|
||||
}
|
||||
d->tx.bda = qe->ba;
|
||||
ASSURE (insqueue (&qe->hdr, d->bdqh.prev, &d->bdavail, DIM(d->bdq)));
|
||||
|
||||
|
||||
d->tx.first = TRUE;
|
||||
d->tx.bd[1] = 0;
|
||||
return kmc_txNewBd(d);
|
||||
@ -2269,7 +2243,7 @@ static t_bool kmc_txNewBd(dupstate *d) {
|
||||
}
|
||||
ba += 2;
|
||||
}
|
||||
|
||||
|
||||
d->tx.ba = ((d->tx.bd[2] & BDL_XAD) << BDL_S_XAD) | d->tx.bd[0];
|
||||
return TRUE;
|
||||
}
|
||||
@ -2299,6 +2273,7 @@ static t_bool kmc_txAppendBuffer(dupstate *d) {
|
||||
}
|
||||
ba++;
|
||||
}
|
||||
kmc_updateBDCount (d->tx.bda, d->tx.bd);
|
||||
d->txmlen += d->tx.bd[1];
|
||||
return TRUE;
|
||||
}
|
||||
@ -2317,7 +2292,7 @@ static t_bool kmc_txAppendBuffer(dupstate *d) {
|
||||
* should be writing a command to them. Output is not possible.
|
||||
*
|
||||
* If neither is set, the KMC takes ownership of the CSRs and updates
|
||||
* them from the queue before setting RDO.
|
||||
* them from the queue before setting RDO.
|
||||
*
|
||||
* There is aditional prioitization of RDI/RDO in the logic that detects
|
||||
* RDO clearing. If RQI has been set by the host before clearing RDO,
|
||||
@ -2341,7 +2316,7 @@ static void kmc_processCompletions (int32 k) {
|
||||
sel6 = qe->bsel6;
|
||||
|
||||
sim_debug (DF_QUE, &kmc_dev, "KMC%u line %u: %s %s delivered: sel2=%06o sel4=%06o sel6=%06o\n",
|
||||
k, ((sel2 & SEL2_LINE)>>SEL2_V_LINE),
|
||||
k, ((sel2 & SEL2_LINE)>>SEL2_V_LINE),
|
||||
(sel2 & SEL2_IOT)? "RX":"TX",
|
||||
((sel2 & SEL2_CMD) == CMD_BUFFOUT)? "BUFFER OUT":"CONTROL OUT",
|
||||
sel2, sel4, sel6);
|
||||
@ -2456,7 +2431,7 @@ static t_bool kmc_bufferAddressOut (int32 k, uint16 flags, uint16 rx, uint8 line
|
||||
|
||||
sim_debug (DF_BFO, &kmc_dev, "KMC%u line %u: %s BUFFER OUT Flags=%06o Address=%06o\n",
|
||||
k, line, rx? "RX": "TX", flags, bda);
|
||||
|
||||
|
||||
if (!kmc_printBDL(k, DF_BFO, &kmc_dev, line, bda, rx? 6: 2))
|
||||
return FALSE;
|
||||
if (!(qe = (CQ *)remqueue (freecqHead.next, &freecqCount))) {
|
||||
@ -2504,7 +2479,7 @@ static int32 kmc_updateBDCount(uint32 bda, uint16 *bd) {
|
||||
if (uba_write_npr_word(bda, kmc_dib.uba_ctl, bd[1]) == 0) {
|
||||
return 1;
|
||||
}
|
||||
if ((bda & 2) == 0) {
|
||||
if ((bda & 2) != 0) {
|
||||
if (uba_write_npr_word(bda + 2, kmc_dib.uba_ctl, bd[2]) == 0) {
|
||||
return 1;
|
||||
}
|
||||
@ -2563,51 +2538,36 @@ static void kmc_halt (int32 k, int error) {
|
||||
*/
|
||||
|
||||
static void kmc_updints(int32 k) {
|
||||
uint16 vect = kmc_dib.uba_vect;
|
||||
if (!(gflags & FLG_UCINI)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((sel0 & SEL0_IEI) && (sel2 & SEL2_RDI)) {
|
||||
if (!(gflags & FLG_AINT)) {
|
||||
sim_debug (DF_INT, &kmc_dev, "KMC%u: set input interrupt pending\n", k);
|
||||
gflags |= FLG_AINT;
|
||||
AintPending++;
|
||||
}
|
||||
sim_debug (DF_INT, &kmc_dev, "KMC%u: set input interrupt pending\n", k);
|
||||
uba_set_irq(&kmc_dib, vect + (k*10));
|
||||
} else {
|
||||
if (gflags & FLG_AINT) {
|
||||
sim_debug (DF_INT, &kmc_dev, "KMC%u: cleared pending input interrupt\n", k);
|
||||
gflags &= ~FLG_AINT;
|
||||
--AintPending;
|
||||
}
|
||||
uba_clr_irq(&kmc_dib, vect + (k*10));
|
||||
sim_debug (DF_INT, &kmc_dev, "KMC%u: cleared pending input interrupt\n", k);
|
||||
}
|
||||
|
||||
if ((sel0 & SEL0_IEO) && (sel2 & SEL2_RDO)) {
|
||||
if (!(gflags & FLG_BINT)) {
|
||||
sim_debug (DF_INT, &kmc_dev, "KMC%u: set output interrupt\n", k);
|
||||
gflags |= FLG_BINT;
|
||||
BintPending++;
|
||||
}
|
||||
uba_set_irq(&kmc_dib, vect + 4 + (k*10));
|
||||
sim_debug (DF_INT, &kmc_dev, "KMC%u: set output interrupt\n", k);
|
||||
} else {
|
||||
if (gflags & FLG_BINT) {
|
||||
sim_debug (DF_INT, &kmc_dev, "KKMC%u: clear output interrupt\n", k);
|
||||
gflags &= ~FLG_BINT;
|
||||
--BintPending;
|
||||
}
|
||||
uba_clr_irq(&kmc_dib, vect + 4 + (k*10));
|
||||
sim_debug (DF_INT, &kmc_dev, "KKMC%u: clear output interrupt\n", k);
|
||||
}
|
||||
if (AintPending != 0 || BintPending != 0)
|
||||
uba_set_irq(&kmc_dib);
|
||||
else
|
||||
uba_clr_irq(&kmc_dib);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Debug: Log a BUFFER IN or BUFFER OUT command.
|
||||
* returns FALSE if print encounters a NXM as (a) it's fatal and
|
||||
* returns FALSE if print encounters a NXM as (a) it's fatal and
|
||||
* (b) only one completion per bdl.
|
||||
*/
|
||||
|
||||
static t_bool kmc_printBufferIn (int32 k, DEVICE *dev, uint8 line, t_bool rx,
|
||||
static t_bool kmc_printBufferIn (int32 k, DEVICE *dev, uint8 line, t_bool rx,
|
||||
int32 count, int32 ba, uint16 sel6v) {
|
||||
t_bool kill = ((sel6v & (SEL6_BI_KILL|SEL6_BI_ENABLE)) == SEL6_BI_KILL);
|
||||
const char *dir = rx? "RX": "TX";
|
||||
@ -2653,7 +2613,7 @@ static t_bool kmc_printBDL(int32 k, uint32 dbits, DEVICE *dev, uint8 line, int32
|
||||
}
|
||||
ba += 2;
|
||||
}
|
||||
|
||||
|
||||
dp = bd[0] | ((bd[2] & BDL_XAD) << BDL_S_XAD);
|
||||
sim_debug (dbits, dev, " bd[0] = %06o 0x%04X Adr=%06o\n", bd[0], bd[0], dp);
|
||||
sim_debug (dbits, dev, " bd[1] = %06o 0x%04X Len=%u.\n", bd[1], bd[1], bd[1]);
|
||||
@ -2685,8 +2645,8 @@ static t_bool kmc_printBDL(int32 k, uint32 dbits, DEVICE *dev, uint8 line, int32
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (prbuf != 5) { /* Don't print RX buffer in */
|
||||
|
||||
if (prbuf != 5) { /* Don't print RX buffer in */
|
||||
for (i = 0; i < bd[1] ; i++) {
|
||||
sim_debug (dbits, dev, " %02x", buf[i]);
|
||||
}
|
||||
@ -2817,7 +2777,7 @@ static t_stat kmc_setDeviceCount (UNIT *txup, int32 val, CONST char *cptr, void
|
||||
uint32 dupidx;
|
||||
t_stat r;
|
||||
DEVICE *dptr = find_dev_from_unit(txup);
|
||||
|
||||
|
||||
if (cptr == NULL)
|
||||
return SCPE_ARG;
|
||||
|
||||
@ -2948,7 +2908,7 @@ t_stat kmc_showStatus (FILE *st, UNIT *up, int32 v, CONST void *dp) {
|
||||
fprintf (st, "KMC%u ", k);
|
||||
|
||||
if (!(sel0 & SEL0_RUN)) {
|
||||
fprintf (st, "%s halted at uPC %04o\n",
|
||||
fprintf (st, "%s halted at uPC %04o\n",
|
||||
(ucname?ucname: "(No or unknown microcode)"), upc);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@ -551,9 +551,9 @@ lp20_update_chkirq (UNIT *uptr, int done, int irq)
|
||||
lp20_cs2 |= CS2_NRDY|CS2_OFFL;
|
||||
}
|
||||
if ((lp20_cs1 & CS1_IE) && (irq || (lp20_cs1 & CS1_DONE)))
|
||||
uba_set_irq(dibp);
|
||||
uba_set_irq(dibp, dibp->uba_vect);
|
||||
else
|
||||
uba_clr_irq(dibp);
|
||||
uba_clr_irq(dibp, dibp->uba_vect);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -568,8 +568,8 @@ lp20_update_ready(UNIT *uptr, uint16 setrdy, uint16 clrrdy)
|
||||
uint16 new_cs1 = (lp20_cs1 | setrdy) & ~clrrdy;
|
||||
|
||||
if ((new_cs1 ^ lp20_cs1) & (CS1_ONL|CS1_DVON) && !sim_is_active(uptr)) {
|
||||
if (new_cs1 & CS1_IE)
|
||||
uba_set_irq(dibp);
|
||||
if (new_cs1 & CS1_IE)
|
||||
uba_set_irq(dibp, dibp->uba_vect);
|
||||
}
|
||||
if (new_cs1 & CS1_DVON)
|
||||
lp20_cs2 &= ~CS2_DVOF;
|
||||
@ -871,7 +871,7 @@ t_stat lp20_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag,
|
||||
const char *cptr)
|
||||
{
|
||||
fprintf (st, "Line Printer (LPT)\n\n");
|
||||
fprintf (st, "The line printer (LPT) writes data to a disk file. \n");
|
||||
fprintf (st, "The line printer (LPT) writes data to a disk file. \n");
|
||||
fprintf (st, "The Line printer can be configured to any number of lines per page with the:\n");
|
||||
fprintf (st, " sim> SET %s LINESPERPAGE=n\n\n", dptr->name);
|
||||
fprintf (st, "The default is 66 lines per page.\n\n");
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
/* ks10_tcu.c: PDP-10
|
||||
/* ks10_tcu.c: PDP-10
|
||||
|
||||
Copyright (c) 2021, Richard Cornwell
|
||||
|
||||
|
||||
159
PDP10/ks10_uba.c
159
PDP10/ks10_uba.c
@ -45,11 +45,17 @@
|
||||
#define UBST_BAD 000000200000 /* Bad mem transfer */
|
||||
#define UBST_TIM 000000400000 /* UBA Timout */
|
||||
|
||||
#define VECT_L 0x10
|
||||
#define VECT_H 0x20
|
||||
#define VECT_CTR 0x0F
|
||||
|
||||
uint32 uba_map[2][64];
|
||||
uint32 uba_status[2];
|
||||
uint32 uba_status[2];
|
||||
int uba_device[16] = { -1, 0, -1, 1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1 };
|
||||
|
||||
int uba_irq_ctlr[128];
|
||||
|
||||
int
|
||||
uba_read(t_addr addr, int ctl, uint64 *data, int access)
|
||||
{
|
||||
@ -74,21 +80,15 @@ uba_read(t_addr addr, int ctl, uint64 *data, int access)
|
||||
return 0;
|
||||
} else if ((addr & 077) == 0) {
|
||||
int pih, pil;
|
||||
int irqf = 0;
|
||||
*data = (uint64)uba_status[ubm];
|
||||
pih = 0200 >> ((uba_status[ubm] >> 3) & 07);
|
||||
pil = 0200 >> (uba_status[ubm] & 07);
|
||||
for(i = 0; (dptr = sim_devices[i]) != NULL; i++) {
|
||||
DIB *dibp = (DIB *) dptr->ctxt;
|
||||
if (dibp == NULL)
|
||||
continue;
|
||||
/* If device is pending on this level save */
|
||||
if (dibp->uba_ctl == ctl) {
|
||||
if ((dibp->uba_irq_pend & pil) != 0)
|
||||
*data |= UBST_INTL;
|
||||
if ((dibp->uba_irq_pend & pih) != 0)
|
||||
*data |= UBST_INTH;
|
||||
}
|
||||
for (i = 0; i < 128; i++) {
|
||||
if ((uba_irq_ctlr[i] & VECT_CTR) == ctl)
|
||||
irqf |= uba_irq_ctlr[i];
|
||||
}
|
||||
*data |= (irqf & (VECT_L|VECT_H)) << 6;
|
||||
return 0;
|
||||
} else if ((addr & 077) == 1) {
|
||||
*data = 0;
|
||||
@ -104,7 +104,7 @@ uba_read(t_addr addr, int ctl, uint64 *data, int access)
|
||||
DIB *dibp = (DIB *) dptr->ctxt;
|
||||
if (dibp == NULL)
|
||||
continue;
|
||||
if (ctl == dibp->uba_ctl &&
|
||||
if (ctl == dibp->uba_ctl &&
|
||||
dibp->uba_addr == (addr & (~dibp->uba_mask))) {
|
||||
uint16 buf;
|
||||
int r = dibp->rd_io(dptr, addr, &buf, access);
|
||||
@ -154,7 +154,7 @@ uba_write(t_addr addr, int ctl, uint64 data, int access)
|
||||
uint32 map = (uint32)(data & 03777) << 9;
|
||||
map |= (uint32)(data & 0740000) << 13;
|
||||
uba_map[ubm][addr & 077] = map;
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "Wr MAP %02o %012llo %06o\n",
|
||||
sim_debug(DEBUG_EXP, &cpu_dev, "Wr MAP %02o %012llo %06o\n",
|
||||
addr & 077, data, map);
|
||||
return 0;
|
||||
} else if ((addr & 077) == 0) {
|
||||
@ -167,10 +167,13 @@ uba_write(t_addr addr, int ctl, uint64 data, int access)
|
||||
continue;
|
||||
if (ctl == dibp->uba_ctl && dptr->reset != NULL)
|
||||
(void)(dptr->reset)(dptr);
|
||||
if (ctl == dibp->uba_ctl)
|
||||
dibp->uba_irq_pend = 0;
|
||||
}
|
||||
clr_interrupt(ctl<<2);
|
||||
}
|
||||
for (i = 0; i < 128; i++) {
|
||||
if ((uba_irq_ctlr[i] & VECT_CTR) == ctl) {
|
||||
uba_irq_ctlr[i] = 0;
|
||||
clr_interrupt(i << 2);
|
||||
}
|
||||
}
|
||||
uba_status[ubm] |= (uint32)(0277 & data);
|
||||
return 0;
|
||||
@ -243,12 +246,12 @@ uba_read_npr_byte(t_addr addr, uint16 ctl, uint8 *data)
|
||||
return 0;
|
||||
addr = (map & PAGE_MASK) | (addr >> 2) & 0777;
|
||||
wd = M[addr];
|
||||
sim_debug(DEBUG_DATA, &cpu_dev, "RD NPR B %08o %08o %012llo ", oaddr, addr, wd);
|
||||
sim_debug(DEBUG_DATA, &kmc_dev, "RD NPR B %08o %08o %012llo ", oaddr, addr, wd);
|
||||
if ((oaddr & 02) == 0)
|
||||
wd >>= 18;
|
||||
if ((oaddr & 01))
|
||||
wd >>= 8;
|
||||
sim_debug(DEBUG_DATA, &cpu_dev, "%03llo ", wd & 0377);
|
||||
sim_debug(DEBUG_DATA, &kmc_dev, "%03llo\n", wd & 0377);
|
||||
*data = (uint8)(wd & 0377);
|
||||
return 1;
|
||||
}
|
||||
@ -270,6 +273,7 @@ uba_write_npr_byte(t_addr addr, uint16 ctl, uint8 data)
|
||||
msk = 0377;
|
||||
buf = (uint64)(data & msk);
|
||||
wd = M[addr];
|
||||
sim_debug(DEBUG_DATA, &kmc_dev, "WR NPR B %08o %08o %012llo ", oaddr, addr, wd);
|
||||
if ((oaddr & 02) == 0) {
|
||||
buf <<= 18;
|
||||
msk <<= 18;
|
||||
@ -281,6 +285,7 @@ uba_write_npr_byte(t_addr addr, uint16 ctl, uint8 data)
|
||||
wd &= ~msk;
|
||||
wd |= buf;
|
||||
M[addr] = wd;
|
||||
sim_debug(DEBUG_DATA, &kmc_dev, "%012llo\n", wd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -333,26 +338,31 @@ uba_write_npr_word(t_addr addr, uint16 ctl, uint16 data)
|
||||
}
|
||||
|
||||
void
|
||||
uba_set_irq(DIB *dibp)
|
||||
uba_set_irq(DIB *dibp, int vect)
|
||||
{
|
||||
int ubm = uba_device[dibp->uba_ctl];
|
||||
int pi;
|
||||
|
||||
int flg;
|
||||
|
||||
if (ubm < 0)
|
||||
return;
|
||||
/* Figure out what channel device should IRQ on */
|
||||
if (dibp->uba_br > 5) {
|
||||
pi = uba_status[ubm] >> 3;
|
||||
flg = VECT_H;
|
||||
} else {
|
||||
pi = uba_status[ubm];
|
||||
flg = VECT_L;
|
||||
}
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev, "set uba irq %06o %03o %o pi=%o\n",
|
||||
dibp->uba_addr, vect, dibp->uba_br, pi);
|
||||
/* Save in device temp the irq value */
|
||||
dibp->uba_irq_pend = 0200 >> (pi & 07);
|
||||
set_interrupt(dibp->uba_ctl<<2, pi);
|
||||
set_interrupt(vect, pi);
|
||||
uba_irq_ctlr[vect >> 2] = flg | dibp->uba_ctl;
|
||||
}
|
||||
|
||||
void
|
||||
uba_clr_irq(DIB *idev)
|
||||
uba_clr_irq(DIB *idev, int vect)
|
||||
{
|
||||
DEVICE *dptr;
|
||||
int ubm = uba_device[idev->uba_ctl];
|
||||
@ -361,35 +371,13 @@ uba_clr_irq(DIB *idev)
|
||||
int j;
|
||||
int lvl;
|
||||
int high = 0;
|
||||
|
||||
|
||||
if (ubm < 0)
|
||||
return;
|
||||
/* Figure out what channel device should IRQ on */
|
||||
if (idev->uba_br > 5) {
|
||||
pi = uba_status[ubm] >> 3;
|
||||
} else {
|
||||
pi = uba_status[ubm];
|
||||
}
|
||||
/* Save in device temp the irq value */
|
||||
idev->uba_irq_pend = 0;
|
||||
clr_interrupt(idev->uba_ctl<<2);
|
||||
for(i = 0; (dptr = sim_devices[i]) != NULL; i++) {
|
||||
DIB *dibp = (DIB *) dptr->ctxt;
|
||||
if (dibp == NULL)
|
||||
continue;
|
||||
/* If device is pending on this level save */
|
||||
if (dibp->uba_ctl == idev->uba_ctl &&
|
||||
dibp->uba_irq_pend != 0) {
|
||||
lvl = 0;
|
||||
for (j = 0200; j != 0; j>>=1) {
|
||||
/* At least one, no need to continue */
|
||||
if ((dibp->uba_irq_pend & j) != 0) {
|
||||
set_interrupt(dibp->uba_ctl<<2, pi);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev, "clr uba irq %06o %03o %o\n",
|
||||
idev->uba_addr, vect, idev->uba_br);
|
||||
clr_interrupt(vect);
|
||||
uba_irq_ctlr[vect >> 2] = 0;
|
||||
}
|
||||
|
||||
void
|
||||
@ -406,70 +394,27 @@ uba_reset()
|
||||
uba_status[0] = 0;
|
||||
uba_status[1] = 0;
|
||||
|
||||
for(i = 0; (dptr = sim_devices[i]) != NULL; i++) {
|
||||
DIB *dibp = (DIB *) dptr->ctxt;
|
||||
if (dibp == NULL)
|
||||
continue;
|
||||
/* Clear any pending interrupt */
|
||||
dibp->uba_irq_pend = 0;
|
||||
}
|
||||
for (i = 0; i < 128; i++)
|
||||
uba_irq_ctlr[i] = 0;
|
||||
}
|
||||
|
||||
t_addr
|
||||
uba_get_vect(t_addr addr, int lvl, int *dev, int *new_lvl)
|
||||
uba_get_vect(t_addr addr, int lvl, int dev)
|
||||
{
|
||||
DEVICE *dptr;
|
||||
DIB *idev = NULL;
|
||||
uint64 buffer;
|
||||
uint16 ivect;
|
||||
int i;
|
||||
int ctl = 17;
|
||||
int pi;
|
||||
int ubm;
|
||||
|
||||
*dev = 0; /* Adaptor 0 is special */
|
||||
/* Look for device */
|
||||
for(i = 0; (dptr = sim_devices[i]) != NULL; i++) {
|
||||
DIB *dibp = (DIB *) dptr->ctxt;
|
||||
if (dibp == NULL)
|
||||
continue;
|
||||
/* If device is pending on this level save */
|
||||
if ((dibp->uba_irq_pend & lvl) != 0) {
|
||||
/* But only if it is highest UBA */
|
||||
if (dibp->uba_ctl < ctl) {
|
||||
ctl = dibp->uba_ctl;
|
||||
idev = dibp;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Should have a device */
|
||||
if (idev != NULL) {
|
||||
*new_lvl = 0;
|
||||
*dev = idev->uba_ctl;
|
||||
/* Figure out what pi channel this will interrupt on */
|
||||
ubm = uba_device[idev->uba_ctl];
|
||||
/* Clear interrupts */
|
||||
idev->uba_irq_pend = 0;
|
||||
/* Fetch vector */
|
||||
if (Mem_read_word(0100 | idev->uba_ctl, &buffer, 1))
|
||||
ubm = uba_irq_ctlr[dev];
|
||||
if (ubm != 0) {
|
||||
/* Fetch vector base */
|
||||
ubm &= VECT_CTR;
|
||||
if (Mem_read_word(0100 | ubm, &buffer, 1))
|
||||
return addr;
|
||||
idev->uba_irq_pend = 0;
|
||||
ivect = idev->uba_vect;
|
||||
if (idev->irqv != NULL)
|
||||
ivect = (idev->irqv)(idev);
|
||||
addr = (buffer + (ivect >> 2)) & RMASK;
|
||||
/* Any other devices waiting on this PI channel? */
|
||||
for(pi = i = 0; (dptr = sim_devices[i]) != NULL; i++) {
|
||||
DIB *dibp = (DIB *) dptr->ctxt;
|
||||
if (dibp == NULL)
|
||||
continue;
|
||||
/* If device is pending on this level save */
|
||||
if (dibp->uba_ctl == idev->uba_ctl &&
|
||||
dibp->uba_irq_pend != 0) {
|
||||
/* At least one, no need to continue */
|
||||
*new_lvl |= dibp->uba_irq_pend;
|
||||
}
|
||||
}
|
||||
/* Compute unibus vector */
|
||||
addr = (buffer + dev) & RMASK;
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev, "get_vect d=%03o l=%03o ir=%02o v=%012llo\n",
|
||||
dev << 2, lvl, uba_irq_ctlr[dev], buffer);
|
||||
uba_irq_ctlr[dev] = 0;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
@ -184,6 +184,7 @@ int t20_page; /* Tops 20 paging selected */
|
||||
int ptr_flg; /* Access to pointer value */
|
||||
int extend = 0; /* Process extended instruction */
|
||||
int fe_xct = 0; /* Execute instruction at address */
|
||||
int pi_vect; /* Last pi location used for IRQ */
|
||||
#elif KL
|
||||
int pi_vect; /* Last pi location used for IRQ */
|
||||
int ext_ac; /* Extended instruction AC */
|
||||
@ -725,11 +726,7 @@ DEVICE cpu_dev = {
|
||||
#else
|
||||
#define QSLAVE 0
|
||||
#endif
|
||||
#if KS
|
||||
#define MAX_DEV 16
|
||||
#else
|
||||
#define MAX_DEV 128
|
||||
#endif
|
||||
|
||||
#if KL
|
||||
struct _byte {
|
||||
@ -825,11 +822,7 @@ get_quantum()
|
||||
void set_interrupt(int dev, int lvl) {
|
||||
lvl &= 07;
|
||||
if (lvl) {
|
||||
#if KS
|
||||
dev_irq[dev>>2] |= 0200 >> lvl;
|
||||
#else
|
||||
dev_irq[dev>>2] = 0200 >> lvl;
|
||||
#endif
|
||||
pi_pending = 1;
|
||||
#if DEBUG
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev, "set irq %o %o %03o %03o %03o\n",
|
||||
@ -4641,18 +4634,18 @@ st_pi:
|
||||
AB |= eb_ptr;
|
||||
extend = 0;
|
||||
if ((dev_irq[0] & pi_mask) == 0) {
|
||||
int new_lvl;
|
||||
int dev;
|
||||
AB = uba_get_vect(AB, pi_mask, &dev, &new_lvl);
|
||||
if (dev != 0) {
|
||||
dev_irq[dev] = new_lvl;
|
||||
if (new_lvl != 0)
|
||||
pi_pending = 1;
|
||||
}
|
||||
for (f = 1; f < MAX_DEV; f++) {
|
||||
if (dev_irq[f] & pi_mask) {
|
||||
AB = uba_get_vect(AB, pi_mask, f);
|
||||
dev_irq[f] = 0;
|
||||
break;
|
||||
}
|
||||
#if DEBUG
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev, "vect irq %o %06o\n", pi_enc, AB);
|
||||
sim_debug(DEBUG_IRQ, &cpu_dev, "vect irq %o %06o\n", pi_enc, AB);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
pi_vect = AB;
|
||||
goto fetch;
|
||||
#endif
|
||||
#if KI | KL
|
||||
@ -12038,7 +12031,7 @@ fprintf(stderr, "PIH = %03o\n\r", PIH);
|
||||
if ((!pi_hold) & f_inst_fetch) {
|
||||
pi_cycle = 0;
|
||||
} else {
|
||||
#if KL
|
||||
#if KL | KS
|
||||
AB = pi_vect | pi_ov;
|
||||
#else
|
||||
AB = 040 | (pi_enc << 1) | maoff | pi_ov;
|
||||
@ -12056,7 +12049,7 @@ fprintf(stderr, "PIH = %03o\n\r", PIH);
|
||||
if ((IR & 0700) == 0700) {
|
||||
(void)check_irq_level();
|
||||
}
|
||||
#if KL
|
||||
#if KL | KS
|
||||
AB = pi_vect | pi_ov;
|
||||
#else
|
||||
AB = 040 | (pi_enc << 1) | maoff | pi_ov;
|
||||
|
||||
@ -580,9 +580,9 @@ int uba_read_npr_byte(t_addr addr, uint16 ctl, uint8 *data);
|
||||
int uba_write_npr_byte(t_addr addr, uint16 ctl, uint8 data);
|
||||
int uba_read_npr_word(t_addr addr, uint16 ctl, uint16 *data);
|
||||
int uba_write_npr_word(t_addr addr, uint16 ctl, uint16 data);
|
||||
void uba_set_irq(DIB *dibp);
|
||||
void uba_clr_irq(DIB *dibp);
|
||||
t_addr uba_get_vect(t_addr addr, int lvl, int *dev, int *new_lvl);
|
||||
void uba_set_irq(DIB *dibp, int vect);
|
||||
void uba_clr_irq(DIB *dibp, int vect);
|
||||
t_addr uba_get_vect(t_addr addr, int lvl, int dev);
|
||||
void uba_set_parity(uint16 ctl);
|
||||
uint16 uba_rh_vect(struct pdp_dib *dibp);
|
||||
int uba_rh_read(DEVICE *dptr, t_addr addr, uint16 *data, int32 access);
|
||||
|
||||
@ -84,10 +84,8 @@
|
||||
|
||||
/* Bits in STATUS */
|
||||
#define IMPID 010 /* Input done. */
|
||||
#define IMPI32 020 /* Input in 32 bit mode. */
|
||||
#define IMPIB 040 /* Input busy. */
|
||||
#define IMPOD 0100 /* Output done. */
|
||||
#define IMPO32 0200 /* Output in 32-bit mode. */
|
||||
#define IMPOB 0400 /* Output busy. */
|
||||
#define IMPERR 01000 /* IMP error. */
|
||||
#define IMPR 02000 /* IMP ready. */
|
||||
@ -564,7 +562,7 @@ UNIT imp_unit[] = {
|
||||
};
|
||||
|
||||
#if KS
|
||||
DIB imp_dib = {0767600, 017, 0250, 6, 3, &imp_rd, &imp_wr, &imp_vect, 0, 0};
|
||||
DIB imp_dib = {0767600, 017, 0250, 6, 3, &imp_rd, &imp_wr, 0, 0, 0};
|
||||
#else
|
||||
DIB imp_dib = {IMP_DEVNUM, 1, &imp_devio,
|
||||
#if KL
|
||||
@ -668,22 +666,12 @@ DEVICE imp_dev = {
|
||||
#if KS
|
||||
static void check_interrupts (UNIT *uptr)
|
||||
{
|
||||
DEVICE *dptr = find_dev_from_unit (uptr);
|
||||
struct pdp_dib *dibp = (DIB *)dptr->ctxt;
|
||||
int irq = 0;
|
||||
DEVICE *dptr = &imp_dev;
|
||||
struct pdp_dib *dibp = (DIB *)dptr->ctxt;
|
||||
|
||||
if (imp_icsr & CSR_IE) {
|
||||
if (imp_icsr & CSR_RDY)
|
||||
irq = 1;
|
||||
if ((uptr->STATUS & IMPID) != 0 && imp_icsr & CSR_IE) {
|
||||
uba_set_irq(dibp, dibp->uba_vect);
|
||||
}
|
||||
if (imp_ocsr & CSR_IE) {
|
||||
if (imp_ocsr & CSR_RDY)
|
||||
irq = 1;
|
||||
}
|
||||
if (irq)
|
||||
uba_set_irq(dibp);
|
||||
else
|
||||
uba_clr_irq(dibp);
|
||||
}
|
||||
|
||||
int
|
||||
@ -708,7 +696,7 @@ imp_wr(DEVICE *dptr, t_addr addr, uint16 data, int32 access)
|
||||
imp_icsr = CSR_INR|CSR_RDY;
|
||||
imp_iba = 0;
|
||||
imp_iwcnt = 0;
|
||||
uba_clr_irq(dibp);
|
||||
uba_clr_irq(dibp, dibp->uba_vect);
|
||||
}
|
||||
data &= (CSR_GO|CSR_RST|CSR_UBA|CSR_IE|CSR_HRC|CSR_SE);
|
||||
imp_icsr &= ~(CSR_GO|CSR_RST|CSR_UBA|CSR_IE|CSR_HRC|CSR_SE|CSR_ERR
|
||||
@ -722,7 +710,8 @@ imp_wr(DEVICE *dptr, t_addr addr, uint16 data, int32 access)
|
||||
}
|
||||
if (data & CSR_GO) {
|
||||
imp_icsr &= ~CSR_RDY;
|
||||
uptr->STATUS &= ~IMPID;
|
||||
uptr->STATUS &= ~(IMPID|IMPLW);
|
||||
uba_clr_irq(dibp, dibp->uba_vect);
|
||||
}
|
||||
sim_debug(DEBUG_DETAIL, dptr, "IMP11 icsr %06o\n", imp_icsr);
|
||||
break;
|
||||
@ -739,6 +728,7 @@ imp_wr(DEVICE *dptr, t_addr addr, uint16 data, int32 access)
|
||||
|
||||
case 004: /* Input Bus Address */
|
||||
imp_iba = (data & 0177777);
|
||||
imp_icsr &= ~(CSR_ERR);
|
||||
break;
|
||||
|
||||
case 006: /* Input Word Count */
|
||||
@ -756,7 +746,7 @@ imp_wr(DEVICE *dptr, t_addr addr, uint16 data, int32 access)
|
||||
imp_ocsr |= CSR_RDY;
|
||||
imp_oba = 0;
|
||||
imp_owcnt = 0;
|
||||
uba_clr_irq(dibp);
|
||||
uba_clr_irq(dibp, dibp->uba_vect + 4);
|
||||
}
|
||||
data &= (CSR_GO|CSR_RST|CSR_UBA|CSR_IE|CSR_BB|CSR_ELB);
|
||||
imp_ocsr &= ~(CSR_GO|CSR_RST|CSR_UBA|CSR_IE|CSR_BB|CSR_ELB|CSR_ERR
|
||||
@ -764,7 +754,8 @@ imp_wr(DEVICE *dptr, t_addr addr, uint16 data, int32 access)
|
||||
imp_ocsr |= data;
|
||||
if (data & CSR_GO) {
|
||||
imp_ocsr &= ~CSR_RDY;
|
||||
uptr->STATUS &= ~IMPOD;
|
||||
uptr->STATUS &= ~(IMPOD);
|
||||
uba_clr_irq(dibp, dibp->uba_vect + 4);
|
||||
}
|
||||
sim_debug(DEBUG_DETAIL, dptr, "IMP11 ocsr %06o\n", imp_ocsr);
|
||||
break;
|
||||
@ -781,13 +772,13 @@ imp_wr(DEVICE *dptr, t_addr addr, uint16 data, int32 access)
|
||||
|
||||
case 014: /* Output Bus Address */
|
||||
imp_oba = (data & 0177777);
|
||||
imp_ocsr &= ~(CSR_ERR);
|
||||
break;
|
||||
|
||||
case 016: /* Output Word Count */
|
||||
imp_owcnt = (data & 0177777);
|
||||
break;
|
||||
}
|
||||
check_interrupts (uptr);
|
||||
if (imp_ocsr & CSR_GO || imp_icsr & CSR_GO)
|
||||
sim_activate(uptr, 100);
|
||||
return 0;
|
||||
@ -806,6 +797,8 @@ imp_rd(DEVICE *dptr, t_addr addr, uint16 *data, int32 access)
|
||||
*data = imp_icsr;
|
||||
if ((uptr->STATUS & (IMPID)) != 0)
|
||||
*data |= CSR_IBF;
|
||||
if ((uptr->STATUS & (IMPLW)) != 0)
|
||||
*data |= CSR_EOM;
|
||||
break;
|
||||
case 002: /* Input Data Buffer */
|
||||
*data = imp_idb;
|
||||
@ -843,19 +836,6 @@ imp_rd(DEVICE *dptr, t_addr addr, uint16 *data, int32 access)
|
||||
|
||||
}
|
||||
|
||||
|
||||
uint16
|
||||
imp_vect(struct pdp_dib *dibp)
|
||||
{
|
||||
uint16 vect = dibp->uba_vect;
|
||||
|
||||
if (imp_unit[0].STATUS & IMPID && (imp_unit[0].STATUS & IMPLW) == 0)
|
||||
return vect;
|
||||
if (imp_unit[0].STATUS & IMPOD)
|
||||
return vect+4;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
static void check_interrupts (UNIT *uptr)
|
||||
{
|
||||
@ -1046,7 +1026,9 @@ t_stat imp_srv(UNIT * uptr)
|
||||
imp_ocsr |= CSR_NXM;
|
||||
imp_ocsr &= ~CSR_GO;
|
||||
uptr->STATUS |= IMPOD;
|
||||
check_interrupts (uptr);
|
||||
if (imp_ocsr & CSR_IE) {
|
||||
uba_set_irq(dibp, dibp->uba_vect + 4);
|
||||
}
|
||||
sim_debug(DEBUG_DETAIL, &imp_dev, "IMP out npr failed\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
@ -1062,7 +1044,9 @@ t_stat imp_srv(UNIT * uptr)
|
||||
imp_ocsr |= CSR_NXM;
|
||||
imp_ocsr &= ~CSR_GO;
|
||||
uptr->STATUS |= IMPOD;
|
||||
check_interrupts (uptr);
|
||||
if (imp_ocsr & CSR_IE) {
|
||||
uba_set_irq(dibp, dibp->uba_vect + 4);
|
||||
}
|
||||
sim_debug(DEBUG_DETAIL, &imp_dev, "IMP out npr failed\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
@ -1086,7 +1070,9 @@ t_stat imp_srv(UNIT * uptr)
|
||||
imp_ocsr |= CSR_ERR;
|
||||
imp_ocsr &= ~CSR_GO;
|
||||
uptr->STATUS |= IMPOD;
|
||||
check_interrupts (uptr);
|
||||
if (imp_ocsr & CSR_IE) {
|
||||
uba_set_irq(dibp, dibp->uba_vect + 4);
|
||||
}
|
||||
sim_debug(DEBUG_DETAIL, &imp_dev, "IMP oba overflow\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
@ -1094,6 +1080,9 @@ t_stat imp_srv(UNIT * uptr)
|
||||
imp_ocsr |= CSR_RDY;
|
||||
imp_ocsr &= ~CSR_GO;
|
||||
uptr->STATUS |= IMPOD;
|
||||
if (imp_ocsr & CSR_IE) {
|
||||
uba_set_irq(dibp, dibp->uba_vect + 4);
|
||||
}
|
||||
if (imp_ocsr & CSR_ELB) {
|
||||
sim_debug(DEBUG_DETAIL, &imp_dev, "IMP send\n");
|
||||
|
||||
@ -1102,7 +1091,6 @@ t_stat imp_srv(UNIT * uptr)
|
||||
memset(imp_data.sbuffer, 0, ETH_FRAME_SIZE);
|
||||
uptr->OPOS = 0;
|
||||
}
|
||||
check_interrupts (uptr);
|
||||
}
|
||||
}
|
||||
if (uptr->STATUS & IMPIB && imp_icsr & CSR_GO) {
|
||||
@ -1111,7 +1099,9 @@ t_stat imp_srv(UNIT * uptr)
|
||||
imp_icsr |= CSR_ERR;
|
||||
imp_icsr &= ~CSR_GO;
|
||||
uptr->STATUS |= IMPID;
|
||||
check_interrupts (uptr);
|
||||
if (imp_icsr & CSR_IE) {
|
||||
uba_set_irq(dibp, dibp->uba_vect);
|
||||
}
|
||||
sim_debug(DEBUG_DETAIL, &imp_dev, "IMP oba overflow\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
@ -1125,7 +1115,9 @@ t_stat imp_srv(UNIT * uptr)
|
||||
imp_icsr |= CSR_NXM;
|
||||
imp_icsr &= ~CSR_GO;
|
||||
uptr->STATUS |= IMPID;
|
||||
check_interrupts (uptr);
|
||||
if (imp_icsr & CSR_IE) {
|
||||
uba_set_irq(dibp, dibp->uba_vect);
|
||||
}
|
||||
sim_debug(DEBUG_DETAIL, &imp_dev, "IMP in npr failed\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
@ -1144,8 +1136,10 @@ t_stat imp_srv(UNIT * uptr)
|
||||
if (uba_write_npr(pa, dibp->uba_ctl, wd64) == 0) {
|
||||
imp_ocsr |= CSR_NXM;
|
||||
imp_ocsr &= ~CSR_GO;
|
||||
uptr->STATUS |= IMPOD;
|
||||
check_interrupts (uptr);
|
||||
uptr->STATUS |= IMPID;
|
||||
if (imp_icsr & CSR_IE) {
|
||||
uba_set_irq(dibp, dibp->uba_vect);
|
||||
}
|
||||
sim_debug(DEBUG_DETAIL, &imp_dev, "IMP out npr failed\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
@ -1158,18 +1152,23 @@ t_stat imp_srv(UNIT * uptr)
|
||||
imp_iba += 2;
|
||||
imp_iwcnt++;
|
||||
if (uptr->IPOS > uptr->ILEN) {
|
||||
imp_icsr |= CSR_EOM|CSR_RDY;
|
||||
imp_icsr &= ~CSR_GO;
|
||||
uptr->STATUS |= IMPID;
|
||||
uptr->STATUS &= ~IMPIB;
|
||||
uptr->ILEN = 0;
|
||||
imp_icsr |= CSR_EOM|CSR_RDY;
|
||||
imp_icsr &= ~CSR_GO;
|
||||
uptr->STATUS |= IMPID|IMPLW;
|
||||
uptr->STATUS &= ~IMPIB;
|
||||
if (imp_icsr & CSR_IE) {
|
||||
uba_set_irq(dibp, dibp->uba_vect);
|
||||
}
|
||||
uptr->ILEN = 0;
|
||||
}
|
||||
if (imp_iwcnt == 0) {
|
||||
imp_icsr |= CSR_RDY;
|
||||
imp_icsr &= ~CSR_GO;
|
||||
uptr->STATUS |= IMPID;
|
||||
}
|
||||
check_interrupts (uptr);
|
||||
if (imp_icsr & CSR_IE) {
|
||||
uba_set_irq(dibp, dibp->uba_vect);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (imp_ocsr & CSR_GO || imp_icsr & CSR_GO)
|
||||
sim_activate(uptr, 100);
|
||||
|
||||
@ -230,7 +230,7 @@ uba_rh_write(DEVICE *dptr, t_addr addr, uint16 data, int32 access) {
|
||||
if ((rhc->status & BUSY) == 0)
|
||||
rhc->cda = ((data << 8) & 0600000) | (rhc->cda & 0177777);
|
||||
if ((data & CS1_GO) != 0 || (rhc->cs1 & CS1_IE) == 0)
|
||||
uba_clr_irq(rhc->dib);
|
||||
uba_clr_irq(rhc->dib, rhc->dib->uba_vect);
|
||||
if ((data & CS1_GO) != 0 && (rhc->status & BUSY) != 0 && GET_FNC(data) >= FNC_XFER) {
|
||||
rhc->cs2 |= CS2_PGE;
|
||||
break;
|
||||
@ -829,7 +829,7 @@ void rh_setattn(struct rh_if *rhc, int unit)
|
||||
rhc->attn |= 1<<unit;
|
||||
#if KS
|
||||
if ((rhc->status & BUSY) == 0 && (rhc->cs1 & CS1_IE) != 0)
|
||||
uba_set_irq(rhc->dib);
|
||||
uba_set_irq(rhc->dib, rhc->dib->uba_vect);
|
||||
#else
|
||||
if ((rhc->status & BUSY) == 0 && (rhc->status & IADR_ATTN) != 0)
|
||||
set_interrupt(rhc->devnum, rhc->status);
|
||||
@ -864,7 +864,7 @@ void rh_setirq(struct rh_if *rhc) {
|
||||
rhc->status |= PI_ENABLE;
|
||||
#if KS
|
||||
if ((rhc->status & BUSY) == 0 && (rhc->cs1 & CS1_IE) != 0)
|
||||
uba_set_irq(rhc->dib);
|
||||
uba_set_irq(rhc->dib, rhc->dib->uba_vect);
|
||||
#else
|
||||
set_interrupt(rhc->devnum, rhc->status);
|
||||
#endif
|
||||
|
||||
@ -329,7 +329,7 @@ struct rh_if rp_rh[NUM_DEVS_RP] = {
|
||||
};
|
||||
|
||||
DIB rp_dib[] = {
|
||||
{0776700, 077, 0254, 6, 1, &uba_rh_read, &uba_rh_write, &uba_rh_vect, 0, &rp_rh[0]},
|
||||
{0776700, 077, 0254, 6, 1, &uba_rh_read, &uba_rh_write, 0, 0, &rp_rh[0]},
|
||||
};
|
||||
#else
|
||||
struct rh_if rp_rh[NUM_DEVS_RP] = {
|
||||
|
||||
@ -198,7 +198,7 @@ struct rh_if tu_rh[NUM_DEVS_TU] = {
|
||||
};
|
||||
|
||||
DIB tu_dib[NUM_DEVS_TU] = {
|
||||
{0772440, 037, 0224, 6, 3, &uba_rh_read, &uba_rh_write, &uba_rh_vect, 0, &tu_rh[0]},
|
||||
{0772440, 037, 0224, 6, 3, &uba_rh_read, &uba_rh_write, 0, 0, &tu_rh[0]},
|
||||
};
|
||||
#else
|
||||
struct rh_if tu_rh[NUM_DEVS_TU] = {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user