diff --git a/PDP10/pdp10_defs.h b/PDP10/pdp10_defs.h index b6c551b5..fac99a78 100644 --- a/PDP10/pdp10_defs.h +++ b/PDP10/pdp10_defs.h @@ -619,6 +619,7 @@ typedef struct pdp_dib DIB; #define DZ_MUXES 4 /* max # of muxes */ #define DZ_LINES 8 /* lines per mux */ +#define DUP_LINES 4 /* max # of DUP11's */ #define DIB_MAX 100 /* max DIBs */ #define DEV_V_UBUS (DEV_V_UF + 0) /* Unibus */ @@ -706,6 +707,9 @@ typedef struct pdp_dib DIB; #define INT_V_PTP 25 #define INT_V_LP20 26 /* LPT20 */ #define INT_V_CR 27 /* CD20 (CD11) */ +#define INT_V_CR 27 /* CD20 (CD11) */ +#define INT_V_DUPRX 28 /* DUP11 */ +#define INT_V_DUPTX 29 #define INT_RP (1u << INT_V_RP) #define INT_TU (1u << INT_V_TU) @@ -719,6 +723,8 @@ typedef struct pdp_dib DIB; #define INT_PTP (1u << INT_V_PTP) #define INT_LP20 (1u << INT_V_LP20) #define INT_CR (1u << INT_V_CR) +#define INT_DUPRX (1u << INT_V_DUPRX) +#define INT_DUPTX (1u << INT_V_DUPTX) #define IPL_RP 6 /* int levels */ #define IPL_TU 6 @@ -728,6 +734,8 @@ typedef struct pdp_dib DIB; #define IPL_DZRX 5 #define IPL_DZTX 5 #define IPL_RY 5 +#define IPL_DUPRX 5 +#define IPL_DUPTX 5 #define IPL_PTR 4 #define IPL_PTP 4 #define IPL_LP20 4 diff --git a/PDP10/pdp10_ksio.c b/PDP10/pdp10_ksio.c index b3503c07..c8d14de4 100644 --- a/PDP10/pdp10_ksio.c +++ b/PDP10/pdp10_ksio.c @@ -961,6 +961,8 @@ AUTO_CON auto_tab[] = {/*c #v am vm fxa fxv */ {0017550}, {0070} }, /* PC11 reader - fx CSR, fx VEC */ { { "PTP" }, 1, 1, 0, 0, {0017554}, {0074} }, /* PC11 punch - fx CSR, fx VEC */ + { { "DUP" }, 1, 2, 0, 0, + {0000100}, {0300} }, /* DUP11 sync lines - fx CSR, fx VEC */ #else { { "QBA" }, 1, 0, 0, 0, {017500} }, /* doorbell - fx CSR, no VEC */ diff --git a/PDP10/pdp10_sys.c b/PDP10/pdp10_sys.c index 39c43a40..cefcd8c9 100644 --- a/PDP10/pdp10_sys.c +++ b/PDP10/pdp10_sys.c @@ -55,6 +55,7 @@ extern DEVICE dz_dev; extern DEVICE ry_dev; extern DEVICE cr_dev; extern DEVICE lp20_dev; +extern DEVICE dup_dev; extern UNIT cpu_unit; extern REG cpu_reg[]; extern d10 *M; @@ -90,6 +91,7 @@ DEVICE *sim_devices[] = { &rp_dev, &tu_dev, &dz_dev, + &dup_dev, NULL }; diff --git a/PDP11/pdp11_defs.h b/PDP11/pdp11_defs.h index 75b77bb5..e77dc2e5 100644 --- a/PDP11/pdp11_defs.h +++ b/PDP11/pdp11_defs.h @@ -482,6 +482,7 @@ typedef struct { #define VH_MUXES 4 /* max # of VH muxes */ #define DLX_LINES 16 /* max # of KL11/DL11's */ #define DCX_LINES 16 /* max # of DC11's */ +#define DUP_LINES 8 /* max # of DUP11/DPV11's */ #define MT_MAXFR (1 << 16) /* magtape max rec */ #define AUTO_LNT 34 /* autoconfig ranks */ #define DIB_MAX 100 /* max DIBs */ @@ -599,6 +600,8 @@ typedef struct pdp_dib DIB; #define INT_V_RC 17 #define INT_V_DMCRX 18 #define INT_V_DMCTX 19 +#define INT_V_DUPRX 20 +#define INT_V_DUPTX 21 #define INT_V_PIR4 0 /* BR4 */ #define INT_V_TTI 1 @@ -644,6 +647,8 @@ typedef struct pdp_dib DIB; #define INT_RC (1u << INT_V_RC) #define INT_DMCRX (1u << INT_V_DMCRX) #define INT_DMCTX (1u << INT_V_DMCTX) +#define INT_DUPRX (1u << INT_V_DUPRX) +#define INT_DUPTX (1u << INT_V_DUPTX) #define INT_PIR4 (1u << INT_V_PIR4) #define INT_TTI (1u << INT_V_TTI) #define INT_TTO (1u << INT_V_TTO) @@ -692,6 +697,8 @@ typedef struct pdp_dib DIB; #define IPL_RC 5 #define IPL_DMCRX 5 #define IPL_DMCTX 5 +#define IPL_DUPRX 5 +#define IPL_DUPTX 5 #define IPL_PTR 4 #define IPL_PTP 4 #define IPL_TTI 4 diff --git a/PDP11/pdp11_dup.c b/PDP11/pdp11_dup.c new file mode 100644 index 00000000..5e0e6b10 --- /dev/null +++ b/PDP11/pdp11_dup.c @@ -0,0 +1,1129 @@ +/* pdp11_dup.c: PDP-11 DUP11/DPV11 bit synchronous interface + + Copyright (c) 2013, Mark Pizzolato + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + Except as contained in this notice, the name of Robert M Supnik shall not be + used in advertising or otherwise to promote the sale, use or other dealings + in this Software without prior written authorization from Robert M Supnik. + + 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 interface are explicitly not supported. + + 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 + characters both initially and between DDCMP packets. + + 15-May-13 MP Initial implementation +*/ + +#if defined (VM_PDP10) /* PDP10 version */ +#include "pdp10_defs.h" + +#elif defined (VM_VAX) /* VAX version */ +#include "vax_defs.h" + +#else /* PDP-11 version */ +#include "pdp11_defs.h" +#endif + +#include "sim_tmxr.h" + +#if !defined(DUP_LINES) +#define DUP_LINES 8 +#endif +#define INITIAL_DUP_LINES 1 + +#define DUP_RX_WAIT 100 +#define DUP_TX_WAIT 100 +#define DUP_CONNECT_POLL 2 /* Seconds */ + +extern int32 IREQ (HLVL); +extern int32 tmxr_poll; /* calibrated delay */ + +uint16 dup_rxcsr[DUP_LINES]; +uint16 dup_rxdbuf[DUP_LINES]; +uint16 dup_parcsr[DUP_LINES]; +uint16 dup_txcsr[DUP_LINES]; +uint16 dup_txdbuf[DUP_LINES]; +uint32 dup_rxi = 0; /* rcv interrupts */ +uint32 dup_txi = 0; /* xmt interrupts */ +uint32 dup_rx_wait = DUP_RX_WAIT; /* rcv character delay */ +uint32 dup_tx_wait = DUP_TX_WAIT; /* xmt character delay */ +uint8 *dup_rcvpacket[DUP_LINES]; /* rcv buffer */ +uint16 dup_rcvpksize[DUP_LINES]; /* rcv buffer size */ +uint16 dup_rcvpkoffset[DUP_LINES]; /* rcv buffer offset */ +uint16 dup_rcvpkinoff[DUP_LINES]; /* rcv packet in offset */ +uint8 *dup_xmtpacket[DUP_LINES]; /* xmt buffer */ +uint16 dup_xmtpksize[DUP_LINES]; /* xmt buffer size */ +uint16 dup_xmtpkoffset[DUP_LINES]; /* xmt buffer offset */ +uint16 dup_xmtpkoutoff[DUP_LINES]; /* xmt packet out offset */ +t_bool dup_xmtpkrdy[DUP_LINES]; /* xmt packet ready */ + + +t_stat dup_rd (int32 *data, int32 PA, int32 access); +t_stat dup_wr (int32 data, int32 PA, int32 access); +t_stat dup_set_modem (int32 dup, int32 rxcsr_bits); +t_stat dup_get_modem (int32 dup); +t_stat dup_svc (UNIT *uptr); +t_stat dup_poll_svc (UNIT *uptr); +t_stat dup_reset (DEVICE *dptr); +t_stat dup_attach (UNIT *uptr, char *ptr); +t_stat dup_detach (UNIT *uptr); +t_stat dup_clear (int32 dup, t_bool flag); +void ddcmp_packet_trace (DEVICE *dptr, const char *txt, const uint8 *msg, int32 len, t_bool detail); +int32 dup_rxinta (void); +int32 dup_txinta (void); +void dup_update_rcvi (void); +void dup_update_xmti (void); +void dup_clr_rxint (int32 dup); +void dup_set_rxint (int32 dup); +void dup_clr_txint (int32 dup); +void dup_set_txint (int32 dup); +t_stat dup_setnl (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat dup_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr); +t_stat dup_help_attach (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr); +char *dup_description (DEVICE *dptr); +static uint16 dup_crc16(uint16 crc, const void* vbuf, size_t len); + +/* DDCMP packet types */ + +#define DDCMP_SOH 0201u /* Numbered Data Message Identifier */ +#define DDCMP_ENQ 0005u /* Control Message Identifier */ +#define DDCMP_DLE 0220u /* Maintenance Message Identifier */ + +/* RXCSR - 16XXX0 - receiver control/status register */ + +BITFIELD dup_rxcsr_bits[] = { + BIT(BDATSET), /* Data Set Change B */ +#define RXCSR_V_BDATSET 0 +#define RXCSR_M_BDATSET (1<> TXCSR_V_MAISEL) + BIT(MAISSCLK), /* Maintenance Single Step Clock */ +#define TXCSR_V_MAISSCLK 13 +#define TXCSR_M_MAISSCLK (1<> 3); /* get line num */ +TMLN *lp = &dup_desc.ldsc[dup]; +int32 orig_val; + +if (dup >= dup_desc.lines) /* validate line number */ + return SCPE_IERR; + +orig_val = regs[(PA >> 1) & 03][dup]; +switch ((PA >> 1) & 03) { /* case on PA<2:1> */ + + case 00: /* RXCSR */ + dup_get_modem (dup); + *data = dup_rxcsr[dup]; + break; + + case 01: /* RXDBUF */ + *data = dup_rxdbuf[dup]; + dup_rxcsr[dup] &= ~RXCSR_M_RXDONE; + if (dup_rxcsr[dup] & RXCSR_M_RXACT) + sim_activate (dup_units+dup, dup_rx_wait); + break; + + case 02: /* TXCSR */ + *data = dup_txcsr[dup]; + break; + + case 03: /* TXDBUF */ + *data = dup_txdbuf[dup]; + break; + } + +sim_debug(DBG_REG, DUPDPTR, "dup_rd(PA=0x%08X [%s], data=0x%X) ", PA, dup_rd_regs[(PA >> 1) & 03], *data); +sim_debug_bits(DBG_REG, DUPDPTR, bitdefs[(PA >> 1) & 03], (uint32)(orig_val), (uint32)(regs[(PA >> 1) & 03][dup]), TRUE); + +return SCPE_OK; +} + +t_stat dup_wr (int32 data, int32 PA, int32 access) +{ +static BITFIELD* bitdefs[] = {dup_rxcsr_bits, dup_parcsr_bits, dup_txcsr_bits, dup_txdbuf_bits}; +static uint16 *regs[] = {dup_rxcsr, dup_parcsr, dup_txcsr, dup_txdbuf}; +int32 dup = ((PA - dup_dib.ba) >> 3); /* get line num */ +int32 orig_val; + +if (dup >= dup_desc.lines) /* validate line number */ + return SCPE_IERR; + +orig_val = regs[(PA >> 1) & 03][dup]; + +switch ((PA >> 1) & 03) { /* case on PA<2:1> */ + + case 00: /* RXCSR */ + dup_set_modem (dup, data); + dup_rxcsr[dup] &= ~RXCSR_WRITEABLE; + dup_rxcsr[dup] |= (data & RXCSR_WRITEABLE); + if ((dup_rxcsr[dup] & RXCSR_M_RTS) && /* Upward transition of RTS */ + (!(orig_val & RXCSR_M_RTS))) /* Enables Receive on the line */ + dup_desc.ldsc[dup].rcve = TRUE; + if ((dup_rxcsr[dup] & RXCSR_M_RTS) && /* Upward transition of RTS */ + (!(orig_val & RXCSR_M_RTS)) && /* while receiver is enabled and */ + (dup_rxcsr[dup] & RXCSR_M_RCVEN) && /* not stripping sync characters */ + (!(dup_rxcsr[dup] & RXCSR_M_STRSYN)) ) { /* Receive a SYNC character */ + dup_rxcsr[dup] |= RXCSR_M_RXDONE; + dup_rxdbuf[dup] &= ~RXDBUF_M_RXDBUF; + dup_rxdbuf[dup] |= (dup_parcsr[dup] & PARCSR_M_ADSYNC); + if (dup_rxcsr[dup] & RXCSR_M_RXIE) + dup_set_rxint (dup); + } + break; + + case 01: /* PARCSR */ + dup_parcsr[dup] &= ~PARCSR_WRITEABLE; + dup_parcsr[dup] |= (data & PARCSR_WRITEABLE); + break; + + case 02: /* TXCSR */ + dup_txcsr[dup] &= ~TXCSR_WRITEABLE; + dup_txcsr[dup] |= (data & TXCSR_WRITEABLE); + if ((!(dup_txcsr[dup] & TXCSR_M_SEND)) && (orig_val & TXCSR_M_SEND)) + dup_txcsr[dup] &= ~TXCSR_M_TXACT; + if (dup_txcsr[dup] & TXCSR_M_DRESET) { + dup_clear(dup, FALSE); + break; + } + break; + + case 03: /* TXDBUF */ + dup_txdbuf[dup] &= ~TXDBUF_WRITEABLE; + dup_txdbuf[dup] |= (data & TXDBUF_WRITEABLE); + dup_txcsr[dup] &= ~TXCSR_M_TXDONE; + if (dup_txcsr[dup] & TXCSR_M_SEND) { + dup_txcsr[dup] |= TXCSR_M_TXACT; + sim_activate (dup_units+dup, dup_tx_wait); + } + break; + } + +sim_debug(DBG_REG, DUPDPTR, "dup_wr(PA=0x%08X [%s], data=0x%X) ", PA, dup_wr_regs[(PA >> 1) & 03], data); +sim_debug_bits(DBG_REG, DUPDPTR, bitdefs[(PA >> 1) & 03], (uint32)orig_val, (uint32)regs[(PA >> 1) & 03][dup], TRUE); +return SCPE_OK; +} + +t_stat dup_set_modem (int32 dup, int32 rxcsr_bits) +{ +int32 bits_to_set, bits_to_clear; + +if ((rxcsr_bits & (RXCSR_M_DTR | RXCSR_M_RTS)) == (dup_rxcsr[dup] & (RXCSR_M_DTR | RXCSR_M_RTS))) + return SCPE_OK; +bits_to_set = ((rxcsr_bits & RXCSR_M_DTR) ? TMXR_MDM_DTR : 0) | ((rxcsr_bits & RXCSR_M_RTS) ? TMXR_MDM_RTS : 0); +bits_to_clear = (~bits_to_set) & (TMXR_MDM_DTR | TMXR_MDM_RTS); +tmxr_set_get_modem_bits (dup_desc.ldsc+dup, bits_to_set, bits_to_clear, NULL); +return SCPE_OK; +} + +t_stat dup_get_modem (int32 dup) +{ +int32 modem_bits; +int32 old_rxcsr_a_modem_bits, new_rxcsr_a_modem_bits, old_rxcsr_b_modem_bits, new_rxcsr_b_modem_bits; +TMLN *lp = &dup_desc.ldsc[dup]; + +old_rxcsr_a_modem_bits = dup_rxcsr[dup] & RXCSR_A_MODEM_BITS; +old_rxcsr_b_modem_bits = dup_rxcsr[dup] & RXCSR_B_MODEM_BITS; +tmxr_set_get_modem_bits (lp, 0, 0, &modem_bits); +new_rxcsr_a_modem_bits = (((modem_bits & TMXR_MDM_RNG) ? RXCSR_M_RING : 0) | + ((modem_bits & TMXR_MDM_DCD) ? RXCSR_M_DCD : 0) | + ((modem_bits & TMXR_MDM_CTS) ? RXCSR_M_CTS : 0)); +new_rxcsr_b_modem_bits = ((modem_bits & TMXR_MDM_DSR) ? RXCSR_M_DSR : 0); +dup_rxcsr[dup] &= ~(RXCSR_A_MODEM_BITS | RXCSR_B_MODEM_BITS); +dup_rxcsr[dup] |= new_rxcsr_a_modem_bits | new_rxcsr_b_modem_bits; +if (old_rxcsr_a_modem_bits != new_rxcsr_a_modem_bits) + dup_rxcsr[dup] |= RXCSR_M_DSCHNG; +else + dup_rxcsr[dup] &= ~RXCSR_M_DSCHNG; +if (old_rxcsr_b_modem_bits != new_rxcsr_b_modem_bits) + dup_rxcsr[dup] |= RXCSR_M_BDATSET; +else + dup_rxcsr[dup] &= ~RXCSR_M_BDATSET; +if ((dup_rxcsr[dup] & RXCSR_M_DSCHNG) && + (dup_rxcsr[dup] & RXCSR_M_DSCIE)) + dup_set_rxint (dup); +return SCPE_OK; +} + +t_stat dup_rcv_byte (int32 dup) +{ +sim_debug (DBG_TRC, DUPDPTR, ""); +dup_rxcsr[dup] |= RXCSR_M_RXACT; +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] >= dup_rcvpkoffset[dup]) { + dup_rcvpkoffset[dup] = 0; + dup_rxcsr[dup] &= ~RXCSR_M_RXACT; + if (0 == dup_crc16 (0, dup_rcvpacket[dup], dup_rcvpkoffset[dup])) + dup_rxdbuf[dup] |= RXDBUF_M_RCRCER; + } +if (dup_rxcsr[dup] & RXCSR_M_RXIE) + dup_set_rxint (dup); +return SCPE_OK; +} + + +/* service routine to delay device activity */ +t_stat dup_svc (UNIT *uptr) +{ +DEVICE *dptr = DUPDPTR; +int32 dup = (int32)(uptr-dptr->units); +TMLN *lp = &dup_desc.ldsc[dup]; + +sim_debug(DBG_TRC, DUPDPTR, "dup_svc(dup=%d)\n", dup); +if (!(dup_txcsr[dup] & TXCSR_M_TXDONE)) { + if (dup_txdbuf[dup] & TXDBUF_M_TSOM) { + dup_xmtpkoffset[dup] = 0; + } + else { + if ((dup_xmtpkoffset[dup] != 0) || + ((dup_txdbuf[dup] & TXDBUF_M_TXDBUF) != (dup_parcsr[dup] & PARCSR_M_ADSYNC))) { + if (!(dup_txdbuf[dup] & TXDBUF_M_TEOM)) { + if (dup_xmtpkoffset[dup] + 1 > dup_xmtpksize[dup]) { + dup_xmtpksize[dup] += 512; + dup_xmtpacket[dup] = realloc (dup_xmtpacket[dup], dup_xmtpksize[dup]); + } + dup_xmtpacket[dup][dup_xmtpkoffset[dup]] = dup_txdbuf[dup] & TXDBUF_M_TXDBUF; + dup_xmtpkoffset[dup] += 1; + } + } + } + dup_txcsr[dup] |= TXCSR_M_TXDONE; + if (dup_txcsr[dup] & TXCSR_M_TXIE) + dup_set_txint (dup); + if (dup_txdbuf[dup] & TXDBUF_M_TEOM) { /* Packet ready to send? */ + uint16 crc16 = dup_crc16 (0, dup_xmtpacket[dup], dup_xmtpkoffset[dup]); + + if (dup_xmtpkoffset[dup] + 2 > dup_xmtpksize[dup]) { + dup_xmtpksize[dup] += 512; + dup_xmtpacket[dup] = realloc (dup_xmtpacket[dup], dup_xmtpksize[dup]); + } + dup_xmtpacket[dup][dup_xmtpkoffset[dup]++] = crc16 & 0xFF; + dup_xmtpacket[dup][dup_xmtpkoffset[dup]++] = crc16 >> 8; + sim_debug(DBG_TRC, DUPDPTR, "dup_svc(dup=%d) - Packet Done %d bytes\n", dup, dup_xmtpkoffset[dup]); + ddcmp_packet_trace (DUPDPTR, "XMT Packet", dup_xmtpacket[dup], dup_xmtpkoffset[dup], TRUE); + dup_xmtpkoutoff[dup] = 0; + dup_xmtpkrdy[dup] = TRUE; + } + } +if (dup_xmtpkrdy[dup]) { + t_stat st = SCPE_OK; + + while ((st == SCPE_OK) && (dup_xmtpkoutoff[dup] < dup_xmtpkoffset[dup])) { + st = tmxr_putc_ln (lp, dup_xmtpacket[dup][dup_xmtpkoutoff[dup]]); + if (st == SCPE_OK) + ++dup_xmtpkoutoff[dup]; + } + tmxr_send_buffered_data (lp); /* send any buffered data */ + if (st == SCPE_LOST) { /* line state transition? */ + dup_get_modem (dup); + dup_xmtpkrdy[dup] = FALSE; + } + else + if (st == SCPE_OK) + dup_xmtpkrdy[dup] = FALSE; + if (!dup_xmtpkrdy[dup]) + dup_txcsr[dup] &= ~TXCSR_M_TXACT; + } +if (dup_rxcsr[dup] & RXCSR_M_RXACT) + dup_rcv_byte (dup); +return SCPE_OK; +} + +t_stat dup_poll_svc (UNIT *uptr) +{ +int32 dup, active, attached, c; + +sim_debug(DBG_TRC, DUPDPTR, "dup_poll_svc()\n"); + +dup = tmxr_poll_conn(&dup_desc); +if (dup >= 0) { /* new connection? */ + dup_rxcsr[dup] |= RXCSR_M_RING | ((dup_rxcsr[dup] & RXCSR_M_DTR) ? (RXCSR_M_DCD | RXCSR_M_CTS | RXCSR_M_DSR) : 0); + dup_rxcsr[dup] |= RXCSR_M_DSCHNG; + if (dup_rxcsr[dup] & RXCSR_M_DSCIE) + dup_set_rxint (dup); /* Interrupt */ + } +tmxr_poll_rx (&dup_desc); +tmxr_poll_tx (&dup_desc); +for (dup=active=attached=0; dup < dup_desc.lines; dup++) { + TMLN *lp = &dup_desc.ldsc[dup]; + + if (dup_units[dup].flags & UNIT_ATT) + ++attached; + if (dup_ldsc[dup].conn) + ++active; + dup_get_modem (dup); + if (lp->xmte && dup_xmtpkrdy[dup]) + dup_svc (&dup_units[dup]); /* Flush pending output */ + if (!(dup_rxcsr[dup] & RXCSR_M_RXACT)) { + while (TMXR_VALID & (c = tmxr_getc_ln (lp))) { + if (dup_rcvpkoffset[dup] + 1 > dup_rcvpksize[dup]) { + dup_rcvpksize[dup] += 512; + dup_rcvpacket[dup] = realloc (dup_rcvpacket[dup], dup_rcvpksize[dup]); + } + dup_rcvpacket[dup][dup_rcvpkoffset[dup]] = c; + dup_rcvpkoffset[dup] += 1; + if (dup_rcvpkoffset[dup] == 1) { /* Validate first byte in packet */ + if ((dup_rxcsr[dup] & RXCSR_M_STRSYN) && + (dup_rcvpacket[dup][0] == (dup_parcsr[dup] & PARCSR_M_ADSYNC))) { + dup_rcvpkoffset[dup] = 0; + continue; + } + if (dup_parcsr[dup] & PARCSR_M_DECMODE) { + switch (dup_rcvpacket[dup][0]) { + default: + sim_debug (DBG_PKT, DUPDPTR, "Ignoring unexpected byte 0%o in DDCMP mode\n", dup_rcvpacket[dup][0]); + dup_rcvpkoffset[dup] = 0; + case DDCMP_SOH: + case DDCMP_ENQ: + case DDCMP_DLE: + continue; + } + } + } + if (dup_rcvpkoffset[dup] >= 8) { + if (dup_rcvpacket[dup][0] == DDCMP_ENQ) { /* Control Message? */ + ddcmp_packet_trace (DUPDPTR, "RCV Packet", dup_rcvpacket[dup], dup_rcvpkoffset[dup], TRUE); + dup_rcvpkinoff[dup] = 0; + dup_rcv_byte (dup); + break; + } + else { + int32 count = ((dup_rcvpacket[dup][2] & 0x3F) << 8)| dup_rcvpacket[dup][3]; + + if (dup_rcvpkoffset[dup] >= 10 + count) { + ddcmp_packet_trace (DUPDPTR, "RCV Packet", dup_rcvpacket[dup], dup_rcvpkoffset[dup], TRUE); + dup_rcvpkinoff[dup] = 0; + dup_rcv_byte (dup); + break; + } + } + } + } + } + } +if (active) + sim_clock_coschedule (uptr, tmxr_poll); /* reactivate */ +else + if (attached) + sim_activate_after (uptr, DUP_CONNECT_POLL*1000000);/* periodic check for connections */ +return SCPE_OK; +} + +/* Debug routines */ + +void ddcmp_packet_trace (DEVICE *dptr, const char *txt, const uint8 *msg, int32 len, t_bool detail) +{ +if (sim_deb && dptr && (DBG_PKT & dptr->dctrl)) { + sim_debug(DBG_PKT, dptr, "%s len: %d\n", txt, len); + if (detail) { + int i, same, group, sidx, oidx; + char outbuf[80], strbuf[18]; + static char hex[] = "0123456789ABCDEF"; + + switch (msg[0]) { + case DDCMP_SOH: /* Data Message */ + sim_debug (DBG_PKT, dptr, "Data Message, Link: %d, Count: %d, Resp: %d, Num: %d, HDRCRC: %s, DATACRC: %s\n", msg[1], msg[2]>>6, ((msg[2] & 0x3F) << 8)| msg[3], msg[4], msg[5], + (0 == dup_crc16 (0, msg, 8)) ? "OK" : "BAD", (0 == dup_crc16 (0, msg+8, 2+(((msg[2] & 0x3F) << 8)| msg[3]))) ? "OK" : "BAD"); + break; + case DDCMP_ENQ: /* Control Message */ + sim_debug (DBG_PKT, dptr, "Control: Type: %d ", msg[1]); + switch (msg[1]) { + case 1: /* ACK */ + sim_debug (DBG_PKT, dptr, "(ACK) Link: %d, Resp: %d\n", msg[2]>>6, msg[3]); + break; + case 2: /* NAK */ + sim_debug (DBG_PKT, dptr, "(NAK) Reason: %d, Link: %d, Resp: %d\n", msg[2] & 0x3F, msg[2]>>6, msg[3]); + break; + case 3: /* REP */ + sim_debug (DBG_PKT, dptr, "(REP) Link: %d, Num: %d\n", msg[2]>>6, msg[4]); + break; + case 6: /* STRT */ + sim_debug (DBG_PKT, dptr, "(STRT) Link: %d\n", msg[2]>>6); + break; + case 7: /* STACK */ + sim_debug (DBG_PKT, dptr, "(STACK) Link: %d\n", msg[2]>>6); + break; + default: /* Unknown */ + sim_debug (DBG_PKT, dptr, "(Unknown=0%o)\n", msg[1]); + break; + } + if (len != 8) + sim_debug (DBG_PKT, dptr, "Unexpected Control Message Length: %d expected 8\n", len); + if (0 != dup_crc16 (0, msg, len)) + sim_debug (DBG_PKT, dptr, "Unexpected Message CRC\n"); + break; + case DDCMP_DLE: /* Maintenance Message */ + sim_debug (DBG_PKT, dptr, "Maintenance Message, Link: %d, Count: %d, HDRCRC: %s, DATACRC: %s\n", msg[1], msg[2]>>6, ((msg[2] & 0x3F) << 8)| msg[3], + (0 == dup_crc16 (0, msg, 8)) ? "OK" : "BAD", (0 == dup_crc16 (0, msg+8, 2+(((msg[2] & 0x3F) << 8)| msg[3]))) ? "OK" : "BAD"); + break; + } + for (i=same=0; i 0) && (0 == memcmp(&msg[i], &msg[i-16], 16))) { + ++same; + continue; + } + if (same > 0) { + sim_debug(DBG_PKT, dptr, "%04X thru %04X same as above\n", i-(16*same), i-1); + same = 0; + } + group = (((len - i) > 16) ? 16 : (len - i)); + for (sidx=oidx=0; sidx>4)&0xf]; + outbuf[oidx++] = hex[msg[i+sidx]&0xf]; + if (isprint(msg[i+sidx])) + strbuf[sidx] = msg[i+sidx]; + else + strbuf[sidx] = '.'; + } + outbuf[oidx] = '\0'; + strbuf[sidx] = '\0'; + sim_debug(DBG_PKT, dptr, "%04X%-48s %s\n", i, outbuf, strbuf); + } + if (same > 0) { + sim_debug(DBG_PKT, dptr, "%04X thru %04X same as above\n", i-(16*same), len-1); + } + } + } +} + +/* Interrupt routines */ + +void dup_clr_rxint (int32 dup) +{ +dup_rxi = dup_rxi & ~(1 << dup); /* clr mux rcv int */ +if (dup_rxi == 0) /* all clr? */ + CLR_INT (DUPRX); +else SET_INT (DUPRX); /* no, set intr */ +return; +} + +void dup_set_rxint (int32 dup) +{ +dup_rxi = dup_rxi | (1 << dup); /* set mux rcv int */ +SET_INT (DUPRX); /* set master intr */ +sim_debug(DBG_INT, DUPDPTR, "dup_set_rxint(dup=%d)\n", dup); +return; +} + +int32 dup_rxinta (void) +{ +int32 dup; + +for (dup = 0; dup < dup_desc.lines; dup++) { /* find 1st mux */ + if (dup_rxi & (1 << dup)) { + sim_debug(DBG_INT, DUPDPTR, "dup_rxinta(dup=%d)\n", dup); + dup_clr_rxint (dup); /* clear intr */ + return (dup_dib.vec + (dup * 010)); /* return vector */ + } + } +return 0; +} + +void dup_clr_txint (int32 dup) +{ +dup_txi = dup_txi & ~(1 << dup); /* clr mux xmt int */ +if (dup_txi == 0) /* all clr? */ + CLR_INT (DUPTX); +else SET_INT (DUPTX); /* no, set intr */ +return; +} + +void dup_set_txint (int32 dup) +{ +dup_txi = dup_txi | (1 << dup); /* set mux xmt int */ +SET_INT (DUPTX); /* set master intr */ +sim_debug(DBG_INT, DUPDPTR, "dup_set_txint(dup=%d)\n", dup); +return; +} + +int32 dup_txinta (void) +{ +int32 dup; + +for (dup = 0; dup < dup_desc.lines; dup++) { /* find 1st mux */ + if (dup_txi & (1 << dup)) { + sim_debug(DBG_INT, DUPDPTR, "dup_txinta(dup=%d)\n", dup); + dup_clr_txint (dup); /* clear intr */ + return (dup_dib.vec + 4 + (dup * 010)); /* return vector */ + } + } +return 0; +} + +/* Device reset */ + +t_stat dup_clear (int32 dup, t_bool flag) +{ +sim_debug(DBG_TRC, DUPDPTR, "dup_clear(dup=%d,flag=%d)\n", dup, flag); + +dup_rxdbuf[dup] = 0; /* silo empty */ +dup_txdbuf[dup] = 0; +dup_parcsr[dup] = 0; /* no params */ +dup_txcsr[dup] = TXCSR_M_TXDONE; /* clear CSR */ +if (flag) /* INIT? clr all */ + dup_rxcsr[dup] = 0; +else + dup_rxcsr[dup] &= ~(RXCSR_M_DTR|RXCSR_M_RTS); /* else save dtr */ +dup_clr_rxint (dup); /* clear int */ +dup_clr_txint (dup); +if (!dup_ldsc[dup].conn) /* set xmt enb */ + dup_ldsc[dup].xmte = 1; +dup_ldsc[dup].rcve = 0; /* clr rcv enb */ +return SCPE_OK; +} + +t_stat dup_reset (DEVICE *dptr) +{ +int32 i, ndev; + +sim_debug(DBG_TRC, dptr, "dup_reset()\n"); + +if ((UNIBUS) && (dptr == &dpv_dev)) { + if (!(dptr->flags & DEV_DIS)) { + printf ("Can't enable Qbus device on Unibus system\n"); + dptr->flags |= DEV_DIS; + return SCPE_ARG; + } + return SCPE_OK; + } + +if ((!UNIBUS) && (dptr == &dup_dev)) { + if (!(dptr->flags & DEV_DIS)) { + printf ("Can't enable Unibus device on Qbus system\n"); + dptr->flags |= DEV_DIS; + return SCPE_ARG; + } + return SCPE_OK; + } + +if (dup_ldsc == NULL) { /* First time startup */ + dup_desc.ldsc = dup_ldsc = calloc (dup_desc.lines, sizeof(*dup_ldsc)); + for (i = 0; i < dup_desc.lines; i++) /* init each line */ + dup_units[i] = dup_unit_template; + dup_units[dup_desc.lines] = dup_poll_unit_template; + } +for (i = 0; i < dup_desc.lines; i++) /* init each line */ + dup_clear (i, TRUE); +dup_rxi = dup_txi = 0; /* clr master int */ +CLR_INT (DUPRX); +CLR_INT (DUPTX); +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 */ +dup_desc.uptr = dup_units+dup_desc.lines; /* Identify polling unit */ +sim_cancel (dup_units+dup_desc.lines); /* stop poll */ +ndev = ((dptr->flags & DEV_DIS)? 0: dup_desc.lines ); +if (ndev) + sim_activate_after (dup_units+dup_desc.lines, DUP_CONNECT_POLL*1000000); +return auto_config (dptr->name, ndev); /* auto config */ +} + +t_stat dup_attach (UNIT *uptr, char *cptr) +{ +t_stat r; +DEVICE *dptr = DUPDPTR; +int32 dup = (int32)(uptr-dptr->units); +char attach_string[512]; + +if (!cptr || !*cptr) + return SCPE_ARG; +sprintf (attach_string, "Line=%d,Buffered=16384,%s", dup, cptr); +r = tmxr_open_master (&dup_desc, attach_string); /* open master socket */ +free (uptr->filename); +uptr->filename = tmxr_line_attach_string(&dup_desc.ldsc[dup]); +if (r != SCPE_OK) /* error? */ + return r; +uptr->flags |= UNIT_ATT; +sim_activate_after (dup_units+dup_desc.lines, 2000000); /* start poll */ +return r; +} + +t_stat dup_detach (UNIT *uptr) +{ +DEVICE *dptr = DUPDPTR; +int32 dup = (int32)(uptr-dptr->units); +TMLN *lp = &dup_ldsc[dup]; + +if (!(uptr->flags & UNIT_ATT)) /* attached? */ + return SCPE_OK; +uptr->flags &= ~UNIT_ATT; +free (uptr->filename); +uptr->filename = NULL; +free (dup_rcvpacket[dup]); +dup_rcvpacket[dup] = NULL; +dup_rcvpksize[dup] = 0; +dup_rcvpkoffset[dup] = 0; +free (dup_xmtpacket[dup]); +dup_xmtpacket[dup] = NULL; +dup_xmtpksize[dup] = 0; +dup_xmtpkoffset[dup] = 0; +dup_xmtpkrdy[dup] = FALSE; +dup_xmtpkoutoff[dup] = 0; +return tmxr_detach_ln (lp); +} + +/* SET LINES processor */ + +t_stat dup_setnl (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +int32 newln, l; +uint32 i; +t_stat r; +DEVICE *dptr = DUPDPTR; + +for (i=0; inumunits; i++) + if (dptr->units[i].flags&UNIT_ATT) + return SCPE_ALATT; +if (cptr == NULL) + return SCPE_ARG; +newln = (int32) get_uint (cptr, 10, DUP_LINES, &r); +if ((r != SCPE_OK) || (newln == dup_desc.lines)) + return r; +if (newln == 0) + return SCPE_ARG; +sim_cancel (dup_units + dup_desc.lines); +dup_dib.lnt = newln * IOLN_DUP; /* set length */ +dup_desc.ldsc = dup_ldsc = realloc(dup_ldsc, newln*sizeof(*dup_ldsc)); +for (l=dup_desc.lines; l < newln; l++) { + memset (&dup_ldsc[l], 0, sizeof(*dup_ldsc)); + dup_units[l] = dup_unit_template; + } +dup_units[newln] = dup_poll_unit_template; +dup_desc.lines = newln; +dptr->numunits = newln + 1; +return dup_reset (dptr); /* setup lines and auto config */ +} + +t_stat dup_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr) +{ +fprintf (st, "Bit Serial Synchronous interface (%s)\n\n", dptr->name); +fprintf (st, "The %s connects two systems to provide a network connection.\n", dptr->name); +fprintf (st, "A maximum of %d %s devices/lines can be configured in the system.\n", DUP_LINES, dptr->name); +fprintf (st, "The number of configured devices can be changed with:\n\n"); +fprintf (st, " sim> SET %s LINES=n\n\n", dptr->name); +fprint_set_help (st, dptr); +fprint_show_help (st, dptr); +fprint_reg_help (st, dptr); +return SCPE_OK; +} + +t_stat dup_help_attach (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr) +{ + tmxr_attach_help (st, dptr, uptr, flag, cptr); + fprintf (st, "The communication line performs input and output through a TCP session\n"); + fprintf (st, "connected to a user-specified port. The ATTACH command specifies the"); + fprintf (st, "port to be used as well as the peer address:\n\n"); + fprintf (st, " sim> ATTACH %sn {interface:}port,Connect=peerhost:port\n\n", dptr->name); + fprintf (st, "where port is a decimal number between 1 and 65535 that is not being used for\n"); + fprintf (st, "other TCP/IP activities.\n\n"); + fprintf (st, "Specifying symmetric attach configuration (with both a listen port and\n"); + fprintf (st, "a connection destination) will cause the side receiving an incoming\n"); + fprintf (st, "connection to validate that the connection actually comes from the\n"); + fprintf (st, "connecction destination system.\n\n"); + return SCPE_OK; +} + +char *dup_description (DEVICE *dptr) +{ +return (UNIBUS) ? "DUP11 bit synchronous interface" : + "DPV11 bit synchronous interface"; +} + +/* crc16 polynomial x^16 + x^15 + x^2 + 1 (0xA001) CCITT LSB */ +static const uint16 crc16Table[256] = { + 0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011, + 0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022, + 0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072, + 0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041, + 0x80c3, 0x00c6, 0x00cc, 0x80c9, 0x00d8, 0x80dd, 0x80d7, 0x00d2, + 0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1, + 0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1, + 0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, 0x0082, + 0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192, + 0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1, + 0x01e0, 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1, + 0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2, + 0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151, + 0x8173, 0x0176, 0x017c, 0x8179, 0x0168, 0x816d, 0x8167, 0x0162, + 0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132, + 0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101, + 0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, 0x0312, + 0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321, + 0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371, + 0x8353, 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342, + 0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1, + 0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2, + 0x83a3, 0x03a6, 0x03ac, 0x83a9, 0x03b8, 0x83bd, 0x83b7, 0x03b2, + 0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381, + 0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291, + 0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, 0x02a2, + 0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2, + 0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1, + 0x8243, 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252, + 0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261, + 0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231, + 0x8213, 0x0216, 0x021c, 0x8219, 0x0208, 0x820d, 0x8207, 0x0202 +}; + +static uint16 dup_crc16 (uint16 crc, const void* vbuf, size_t len) +{ +const unsigned char* buf = (const unsigned char*)vbuf; + +while (len > 8) { + crc = (crc >> 8) ^ crc16Table[ (crc ^ (*buf++)) & 0xFF ]; + crc = (crc >> 8) ^ crc16Table[ (crc ^ (*buf++)) & 0xFF ]; + crc = (crc >> 8) ^ crc16Table[ (crc ^ (*buf++)) & 0xFF ]; + crc = (crc >> 8) ^ crc16Table[ (crc ^ (*buf++)) & 0xFF ]; + crc = (crc >> 8) ^ crc16Table[ (crc ^ (*buf++)) & 0xFF ]; + crc = (crc >> 8) ^ crc16Table[ (crc ^ (*buf++)) & 0xFF ]; + crc = (crc >> 8) ^ crc16Table[ (crc ^ (*buf++)) & 0xFF ]; + crc = (crc >> 8) ^ crc16Table[ (crc ^ (*buf++)) & 0xFF ]; + len -= 8; + } +while (0 != len--) + crc = (crc >> 8) ^ crc16Table[ (crc ^ (*buf++)) & 0xFF ]; +return(crc); +} + diff --git a/PDP11/pdp11_io_lib.c b/PDP11/pdp11_io_lib.c index 2e4dd412..0c69b1d6 100644 --- a/PDP11/pdp11_io_lib.c +++ b/PDP11/pdp11_io_lib.c @@ -440,14 +440,14 @@ AUTO_CON auto_tab[] = {/*c #v am vm fxa fxv */ { { NULL }, 1, 2, 0, 8, {012400} }, /* KW11W */ { { NULL }, 1, 2, 8, 8 }, /* DU11 */ - { { NULL }, 1, 2, 8, 8 }, /* DUP11 */ + { { "DUP" }, 1, 2, 8, 8 }, /* DUP11 */ { { NULL }, 1, 3, 0, 8, {015000, 015040, 015100, 015140, }}, /* DV11 */ { { NULL }, 1, 2, 8, 8 }, /* LK11A */ { { "DMC0", "DMC1", "DMC2", "DMC3" }, 1, 2, 8, 8 }, /* DMC11 */ { { "DZ" }, 1, 2, 8, 8 }, /* DZ11 */ - { { NULL }, 1, 2, 8, 8 }, /* KMC11 */ + { { "KMC" }, 1, 2, 8, 8 }, /* KMC11 */ { { NULL }, 1, 2, 8, 8 }, /* LPP11 */ { { NULL }, 1, 2, 8, 8 }, /* VMV21 */ { { NULL }, 1, 2, 16, 8 }, /* VMV31 */ @@ -468,7 +468,7 @@ AUTO_CON auto_tab[] = {/*c #v am vm fxa fxv */ { { NULL }, 1, 1, 8, 4, {012410, 012410}, {0124} }, /* DR11B - fx CSRs,vec */ { { "DMP" }, 1, 2, 8, 8 }, /* DMP11 */ - { { NULL }, 1, 2, 8, 8 }, /* DPV11 */ + { { "DPV" }, 1, 2, 8, 8 }, /* DPV11 */ { { NULL }, 1, 2, 8, 8 }, /* ISB11 */ { { NULL }, 1, 2, 16, 8 }, /* DMV11 */ { { "XU", "XUB" }, 1, 1, 8, 4, diff --git a/PDP11/pdp11_sys.c b/PDP11/pdp11_sys.c index 6743d117..7a2c787a 100644 --- a/PDP11/pdp11_sys.c +++ b/PDP11/pdp11_sys.c @@ -103,6 +103,8 @@ extern DEVICE xu_dev, xub_dev; extern DEVICE ke_dev; extern DEVICE kg_dev; extern DEVICE dmc_dev[]; +extern DEVICE dup_dev; +extern DEVICE dpv_dev; extern UNIT cpu_unit; extern REG cpu_reg[]; extern uint16 *M; @@ -171,6 +173,8 @@ DEVICE *sim_devices[] = { &dmc_dev[1], &dmc_dev[2], &dmc_dev[3], + &dup_dev, + &dpv_dev, NULL }; diff --git a/VAX/vax730_defs.h b/VAX/vax730_defs.h index 39ed5618..9db8abff 100644 --- a/VAX/vax730_defs.h +++ b/VAX/vax730_defs.h @@ -205,6 +205,7 @@ extern t_stat cpu_show_memory (FILE* st, UNIT* uptr, int32 val, void* desc); #define VH_MUXES 4 /* max # of DHQ muxes */ #define DLX_LINES 16 /* max # of KL11/DL11's */ #define DCX_LINES 16 /* max # of DC11's */ +#define DUP_LINES 8 /* max # of DUP11's */ #define MT_MAXFR (1 << 16) /* magtape max rec */ #define DEV_V_UBUS (DEV_V_UF + 0) /* Unibus */ @@ -256,6 +257,8 @@ typedef struct { #define INT_V_XU 9 #define INT_V_DMCRX 10 #define INT_V_DMCTX 11 +#define INT_V_DUPRX 12 +#define INT_V_DUPTX 13 #define INT_V_LPT 0 /* BR4 */ #define INT_V_PTR 1 @@ -282,6 +285,8 @@ typedef struct { #define INT_CR (1u << INT_V_CR) #define INT_DMCRX (1u << INT_V_DMCRX) #define INT_DMCTX (1u << INT_V_DMCTX) +#define INT_DUPRX (1u << INT_V_DUPRX) +#define INT_DUPTX (1u << INT_V_DUPTX) #define IPL_DZRX (0x15 - IPL_HMIN) #define IPL_DZTX (0x15 - IPL_HMIN) @@ -301,6 +306,8 @@ typedef struct { #define IPL_VHTX (0x14 - IPL_HMIN) #define IPL_DMCRX (0x15 - IPL_HMIN) #define IPL_DMCTX (0x15 - IPL_HMIN) +#define IPL_DUPRX (0x15 - IPL_HMIN) +#define IPL_DUPTX (0x15 - IPL_HMIN) /* Device vectors */ diff --git a/VAX/vax730_syslist.c b/VAX/vax730_syslist.c index 41e4e97c..23b0ea54 100644 --- a/VAX/vax730_syslist.c +++ b/VAX/vax730_syslist.c @@ -53,6 +53,7 @@ extern DEVICE dz_dev; extern DEVICE vh_dev; extern DEVICE xu_dev, xub_dev; extern DEVICE dmc_dev[]; +extern DEVICE dup_dev; extern UNIT cpu_unit; extern void WriteB (uint32 pa, int32 val); @@ -88,6 +89,7 @@ DEVICE *sim_devices[] = { &dmc_dev[1], &dmc_dev[2], &dmc_dev[3], + &dup_dev, NULL }; diff --git a/VAX/vax750_defs.h b/VAX/vax750_defs.h index ab536f22..7342482d 100644 --- a/VAX/vax750_defs.h +++ b/VAX/vax750_defs.h @@ -295,6 +295,8 @@ typedef struct { #define INT_V_XU 8 #define INT_V_DMCRX 9 #define INT_V_DMCTX 10 +#define INT_V_DUPRX 11 +#define INT_V_DUPTX 12 #define INT_V_LPT 0 /* BR4 */ #define INT_V_PTR 1 @@ -320,6 +322,8 @@ typedef struct { #define INT_CR (1u << INT_V_CR) #define INT_DMCRX (1u << INT_V_DMCRX) #define INT_DMCTX (1u << INT_V_DMCTX) +#define INT_DUPRX (1u << INT_V_DUPRX) +#define INT_DUPTX (1u << INT_V_DUPTX) #define IPL_DZRX (0x15 - IPL_HMIN) #define IPL_DZTX (0x15 - IPL_HMIN) @@ -338,6 +342,8 @@ typedef struct { #define IPL_VHTX (0x14 - IPL_HMIN) #define IPL_DMCRX (0x15 - IPL_HMIN) #define IPL_DMCTX (0x15 - IPL_HMIN) +#define IPL_DUPRX (0x15 - IPL_HMIN) +#define IPL_DUPTX (0x15 - IPL_HMIN) /* Device vectors */ diff --git a/VAX/vax750_syslist.c b/VAX/vax750_syslist.c index 44ebd5d8..ae815b99 100644 --- a/VAX/vax750_syslist.c +++ b/VAX/vax750_syslist.c @@ -55,6 +55,7 @@ extern DEVICE dz_dev; extern DEVICE vh_dev; extern DEVICE xu_dev, xub_dev; extern DEVICE dmc_dev[]; +extern DEVICE dup_dev; extern UNIT cpu_unit; extern void WriteB (uint32 pa, int32 val); @@ -93,6 +94,7 @@ DEVICE *sim_devices[] = { &dmc_dev[1], &dmc_dev[2], &dmc_dev[3], + &dup_dev, NULL }; diff --git a/VAX/vax780_defs.h b/VAX/vax780_defs.h index 8da9cc7b..a9a6153a 100644 --- a/VAX/vax780_defs.h +++ b/VAX/vax780_defs.h @@ -247,6 +247,7 @@ extern t_stat cpu_show_memory (FILE* st, UNIT* uptr, int32 val, void* desc); #define VH_MUXES 4 /* max # of DHU muxes */ #define DLX_LINES 16 /* max # of KL11/DL11's */ #define DCX_LINES 16 /* max # of DC11's */ +#define DUP_LINES 8 /* max # of DUP11's */ #define MT_MAXFR (1 << 16) /* magtape max rec */ #define DEV_V_UBUS (DEV_V_UF + 0) /* Unibus */ @@ -306,6 +307,8 @@ typedef struct { #define INT_V_XU 8 #define INT_V_DMCRX 9 #define INT_V_DMCTX 10 +#define INT_V_DUPRX 11 +#define INT_V_DUPTX 12 #define INT_V_LPT 0 /* BR4 */ #define INT_V_PTR 1 @@ -331,6 +334,8 @@ typedef struct { #define INT_CR (1u << INT_V_CR) #define INT_DMCRX (1u << INT_V_DMCRX) #define INT_DMCTX (1u << INT_V_DMCTX) +#define INT_DUPRX (1u << INT_V_DUPRX) +#define INT_DUPTX (1u << INT_V_DUPTX) #define IPL_DZRX (0x15 - IPL_HMIN) #define IPL_DZTX (0x15 - IPL_HMIN) @@ -349,6 +354,8 @@ typedef struct { #define IPL_VHTX (0x14 - IPL_HMIN) #define IPL_DMCRX (0x15 - IPL_HMIN) #define IPL_DMCTX (0x15 - IPL_HMIN) +#define IPL_DUPRX (0x15 - IPL_HMIN) +#define IPL_DUPTX (0x15 - IPL_HMIN) /* Device vectors */ diff --git a/VAX/vax780_syslist.c b/VAX/vax780_syslist.c index 0b088d80..767a4144 100644 --- a/VAX/vax780_syslist.c +++ b/VAX/vax780_syslist.c @@ -55,6 +55,7 @@ extern DEVICE dz_dev; extern DEVICE vh_dev; extern DEVICE xu_dev, xub_dev; extern DEVICE dmc_dev[]; +extern DEVICE dup_dev; extern UNIT cpu_unit; extern void WriteB (uint32 pa, int32 val); @@ -95,6 +96,7 @@ DEVICE *sim_devices[] = { &dmc_dev[1], &dmc_dev[2], &dmc_dev[3], + &dup_dev, NULL }; diff --git a/VAX/vax860_defs.h b/VAX/vax860_defs.h index a1d0b7f2..2d8b9fbb 100644 --- a/VAX/vax860_defs.h +++ b/VAX/vax860_defs.h @@ -342,6 +342,9 @@ typedef struct { #define INT_V_XU 8 #define INT_V_DMCRX 9 #define INT_V_DMCTX 10 +#define INT_V_DUPRX 11 +#define INT_V_DUPTX 12 + #define INT_V_LPT 0 /* BR4 */ #define INT_V_PTR 1 #define INT_V_PTP 2 @@ -366,6 +369,9 @@ typedef struct { #define INT_CR (1u << INT_V_CR) #define INT_DMCRX (1u << INT_V_DMCRX) #define INT_DMCTX (1u << INT_V_DMCTX) +#define INT_DUPRX (1u << INT_V_DUPRX) +#define INT_DUPTX (1u << INT_V_DUPTX) + #define IPL_DZRX (0x15 - IPL_HMIN) #define IPL_DZTX (0x15 - IPL_HMIN) #define IPL_HK (0x15 - IPL_HMIN) @@ -383,6 +389,8 @@ typedef struct { #define IPL_VHTX (0x14 - IPL_HMIN) #define IPL_DMCRX (0x15 - IPL_HMIN) #define IPL_DMCTX (0x15 - IPL_HMIN) +#define IPL_DUPRX (0x15 - IPL_HMIN) +#define IPL_DUPTX (0x15 - IPL_HMIN) /* Device vectors */ diff --git a/VAX/vax860_syslist.c b/VAX/vax860_syslist.c index 795e091f..2038f046 100644 --- a/VAX/vax860_syslist.c +++ b/VAX/vax860_syslist.c @@ -55,6 +55,7 @@ extern DEVICE dz_dev; extern DEVICE vh_dev; extern DEVICE xu_dev, xub_dev; extern DEVICE dmc_dev[]; +extern DEVICE dup_dev; extern UNIT cpu_unit; extern void WriteB (uint32 pa, int32 val); @@ -93,6 +94,7 @@ DEVICE *sim_devices[] = { &dmc_dev[1], &dmc_dev[2], &dmc_dev[3], + &dup_dev, NULL }; diff --git a/Visual Studio Projects/PDP10.vcproj b/Visual Studio Projects/PDP10.vcproj index 27db5bec..d00bff38 100644 --- a/Visual Studio Projects/PDP10.vcproj +++ b/Visual Studio Projects/PDP10.vcproj @@ -239,6 +239,10 @@ RelativePath="..\PDP11\pdp11_cr.c" > + + diff --git a/Visual Studio Projects/PDP11.vcproj b/Visual Studio Projects/PDP11.vcproj index 82269ec9..de099266 100644 --- a/Visual Studio Projects/PDP11.vcproj +++ b/Visual Studio Projects/PDP11.vcproj @@ -219,6 +219,10 @@ RelativePath="..\PDP11\pdp11_dmc.c" > + + diff --git a/Visual Studio Projects/VAX730.vcproj b/Visual Studio Projects/VAX730.vcproj index deff6aca..3f076350 100644 --- a/Visual Studio Projects/VAX730.vcproj +++ b/Visual Studio Projects/VAX730.vcproj @@ -206,6 +206,10 @@ RelativePath="..\PDP11\pdp11_dmc.c" > + + diff --git a/Visual Studio Projects/VAX750.vcproj b/Visual Studio Projects/VAX750.vcproj index 7868d9fa..6a4bd62e 100644 --- a/Visual Studio Projects/VAX750.vcproj +++ b/Visual Studio Projects/VAX750.vcproj @@ -206,6 +206,10 @@ RelativePath="..\PDP11\pdp11_dmc.c" > + + diff --git a/Visual Studio Projects/VAX780.vcproj b/Visual Studio Projects/VAX780.vcproj index d52b7466..04137a58 100644 --- a/Visual Studio Projects/VAX780.vcproj +++ b/Visual Studio Projects/VAX780.vcproj @@ -209,6 +209,10 @@ RelativePath="..\PDP11\pdp11_dmc.c" > + + diff --git a/Visual Studio Projects/VAX8600.vcproj b/Visual Studio Projects/VAX8600.vcproj index 3a228b42..23fe4f99 100644 --- a/Visual Studio Projects/VAX8600.vcproj +++ b/Visual Studio Projects/VAX8600.vcproj @@ -209,6 +209,10 @@ RelativePath="..\PDP11\pdp11_dmc.c" > + +