From f30d43209e7b7436fbe0ae753a47bfc70b05bad5 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Mon, 27 May 2013 15:14:54 -0700 Subject: [PATCH 01/22] Fixes to: 1) retain the buffered/unbuffered line specific details across save/restore 2) retain modem control outgoing bits (CTS and DTR) accross line resets which may occur due to carrier/connection loss. 3) change the behavior which sends the prior contents of the transmit buffer on a line reconnect to only happen for buffered telnet lines. 4) avoid crash in SHOW MULTIPLEXER output when only specific lines have been attached instead of --- sim_tmxr.c | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/sim_tmxr.c b/sim_tmxr.c index 38802e55..5ce9f491 100644 --- a/sim_tmxr.c +++ b/sim_tmxr.c @@ -436,12 +436,14 @@ lp->tsta = 0; /* init telnet state */ lp->xmte = 1; /* enable transmit */ lp->dstb = 0; /* default bin mode */ lp->rxbpr = lp->rxbpi = lp->rxcnt = 0; /* init receive indexes */ -if (!lp->txbfd) /* if not buffered */ +if (!lp->txbfd || lp->notelnet) /* if not buffered telnet */ lp->txbpr = lp->txbpi = lp->txcnt = 0; /* init transmit indexes */ memset (lp->rbr, 0, sizeof(lp->rbr)); /* clear break status array */ lp->txdrp = 0; -if (lp->modem_control) - lp->modembits = TMXR_MDM_CTS | TMXR_MDM_DSR; +if (lp->modem_control) { + lp->modembits &= ~TMXR_MDM_INCOMING; + lp->modembits |= TMXR_MDM_CTS | TMXR_MDM_DSR; + } if (!lp->mp->buffered) { lp->txbfd = 0; lp->txbsz = TMXR_MAXBUF; @@ -695,7 +697,7 @@ static char *growstring(char **string, size_t growth) return *string + strlen(*string); } -static char *_mux_attach_string(char *old, TMXR *mp) +static char *tmxr_mux_attach_string(char *old, TMXR *mp) { char* tptr = NULL; int32 i; @@ -767,6 +769,10 @@ if (lp->destination || lp->port || lp->txlogname) { sprintf (growstring(&tptr, 32), "Line=%d", (int)(lp-lp->mp->ldsc)); if (lp->modem_control != lp->mp->modem_control) sprintf (growstring(&tptr, 32), ",%s", lp->modem_control ? "Modem" : "NoModem"); + if (lp->txbfd && (lp->txbsz != lp->mp->buffered)) + sprintf (growstring(&tptr, 32), ",Buffered=%d", lp->txbsz); + if (!lp->txbfd && (lp->mp->buffered > 0)) + sprintf (growstring(&tptr, 32), ",UnBuffered"); if (lp->destination) { if (lp->serport) { char portname[CBUFSIZE]; @@ -1091,7 +1097,7 @@ if ((lp->destination) && (!lp->serport)) { tmxr_init_line (lp); /* initialize line state */ if (lp->mp->uptr) { /* Revise the unit's connect string to reflect the current attachments */ - lp->mp->uptr->filename = _mux_attach_string (lp->mp->uptr->filename, lp->mp); + lp->mp->uptr->filename = tmxr_mux_attach_string (lp->mp->uptr->filename, lp->mp); /* No connections or listeners exist, then we're equivalent to being fully detached. We should reflect that */ if (lp->mp->uptr->filename == NULL) tmxr_detach (lp->mp, lp->mp->uptr); @@ -1272,7 +1278,7 @@ else { r = SCPE_OK; } if (r == SCPE_OK) /* Record port state for proper restore */ - lp->mp->uptr->filename = _mux_attach_string (lp->mp->uptr->filename, lp->mp); + lp->mp->uptr->filename = tmxr_mux_attach_string (lp->mp->uptr->filename, lp->mp); return r; } @@ -1342,7 +1348,7 @@ for (i = 0; i < mp->lines; i++) { /* loop thru lines */ TMXR_MAXBUF - lp->rxbpi); if (nbytes < 0) { /* line error? */ - if (!lp->txbfd) + if (!lp->txbfd || lp->notelnet) lp->txbpi = lp->txbpr = 0; /* Drop the data we already know we can't send */ tmxr_close_ln (lp); /* disconnect line */ } @@ -1493,8 +1499,8 @@ return (lp->rxbpi - lp->rxbpr + ((lp->rxbpi < lp->rxbpr)? TMXR_MAXBUF: 0)); t_stat tmxr_putc_ln (TMLN *lp, int32 chr) { -if ((lp->conn == FALSE) && /* no conn & not buffered? */ - (!lp->txbfd)) { +if ((lp->conn == FALSE) && /* no conn & not buffered telnet? */ + (!lp->txbfd || lp->notelnet)) { ++lp->txdrp; /* lost */ return SCPE_LOST; } @@ -1507,7 +1513,7 @@ tmxr_debug_trace_line (lp, "tmxr_putc_ln()"); lp->txbpr = (1+lp->txbpr)%lp->txbsz, ++lp->txdrp; \ } if ((lp->txbfd) || (TXBUF_AVAIL(lp) > 1)) { /* room for char (+ IAC)? */ - if ((TN_IAC == (u_char) chr) && (!lp->notelnet)) /* char == IAC in telnet session? */ + if ((TN_IAC == (u_char) chr) && (!lp->notelnet)) /* char == IAC in telnet session? */ TXBUF_CHAR (lp, TN_IAC); /* stuff extra IAC char */ TXBUF_CHAR (lp, chr); /* buffer char & adv pointer */ if ((!lp->txbfd) && (TXBUF_AVAIL (lp) <= TMXR_GUARD))/* near full? */ @@ -2783,7 +2789,7 @@ r = tmxr_open_master (mp, cptr); /* open master socket */ if (r != SCPE_OK) /* error? */ return r; mp->uptr = uptr; /* save unit for polling */ -uptr->filename = _mux_attach_string (uptr->filename, mp);/* save */ +uptr->filename = tmxr_mux_attach_string (uptr->filename, mp);/* save */ uptr->flags = uptr->flags | UNIT_ATT; /* no more errors */ if ((mp->lines > 1) || ((mp->master == 0) && @@ -2828,9 +2834,12 @@ else { for (i=0; idptr->name); - fprintf(st, ", attached to %s, ", mp->uptr->filename); + fprintf(st, "Multiplexer device: %s, ", mp->dptr->name); + attach = tmxr_mux_attach_string (NULL, mp); + fprintf(st, "attached to %s, ", attach); + free (attach); if (mp->lines > 1) { tmxr_show_lines(st, NULL, 0, mp); fprintf(st, ", "); @@ -3427,7 +3436,7 @@ if (lp->txlog == NULL) { /* error? */ free (lp->txlogname); /* free buffer */ return SCPE_OPENERR; } -lp->mp->uptr->filename = _mux_attach_string (lp->mp->uptr->filename, lp->mp); +lp->mp->uptr->filename = tmxr_mux_attach_string (lp->mp->uptr->filename, lp->mp); return SCPE_OK; } @@ -3450,7 +3459,7 @@ if (lp->txlog) { /* logging? */ lp->txlog = NULL; lp->txlogname = NULL; } -lp->mp->uptr->filename = _mux_attach_string (lp->mp->uptr->filename, lp->mp); +lp->mp->uptr->filename = tmxr_mux_attach_string (lp->mp->uptr->filename, lp->mp); return SCPE_OK; } From 89bd58a6fac83f94f4678181385432ce28ebd1e2 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Mon, 27 May 2013 16:24:18 -0700 Subject: [PATCH 02/22] Addition of DUP11 simulation to all Unibus simulators (PDP11, PDP10, and all Unibus VAXen) --- PDP10/pdp10_defs.h | 8 + PDP10/pdp10_ksio.c | 2 + PDP10/pdp10_sys.c | 2 + PDP11/pdp11_defs.h | 7 + PDP11/pdp11_dup.c | 1129 +++++++++++++++++++++++++ PDP11/pdp11_io_lib.c | 6 +- PDP11/pdp11_sys.c | 4 + VAX/vax730_defs.h | 7 + VAX/vax730_syslist.c | 2 + VAX/vax750_defs.h | 6 + VAX/vax750_syslist.c | 2 + VAX/vax780_defs.h | 7 + VAX/vax780_syslist.c | 2 + VAX/vax860_defs.h | 8 + VAX/vax860_syslist.c | 2 + Visual Studio Projects/PDP10.vcproj | 4 + Visual Studio Projects/PDP11.vcproj | 4 + Visual Studio Projects/VAX730.vcproj | 4 + Visual Studio Projects/VAX750.vcproj | 4 + Visual Studio Projects/VAX780.vcproj | 4 + Visual Studio Projects/VAX8600.vcproj | 4 + 21 files changed, 1215 insertions(+), 3 deletions(-) create mode 100644 PDP11/pdp11_dup.c 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" > + + From 3b8784b2c331333426a7ff5cf05ac23158e1b197 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Mon, 27 May 2013 16:55:12 -0700 Subject: [PATCH 03/22] Added makefile support for the DUP11 device --- descrip.mms | 13 +++++++------ makefile | 16 ++++++++++------ 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/descrip.mms b/descrip.mms index 9756beb6..c727c74f 100644 --- a/descrip.mms +++ b/descrip.mms @@ -534,7 +534,7 @@ PDP11_SOURCE1 = $(PDP11_DIR)PDP11_FP.C,$(PDP11_DIR)PDP11_CPU.C,\ $(PDP11_DIR)PDP11_SYS.C,$(PDP11_DIR)PDP11_TC.C, \ $(PDP11_DIR)PDP11_CPUMOD.C,$(PDP11_DIR)PDP11_CR.C,\ $(PDP11_DIR)PDP11_TA.C,$(PDP11_DIR)PDP11_DMC.C,\ - $(PDP11_DIR)PDP11_IO_LIB.C + $(PDP11_DIR)PDP11_DUP.C,$(PDP11_DIR)PDP11_IO_LIB.C PDP11_LIB2 = $(LIB_DIR)PDP11L2-$(ARCH).OLB PDP11_SOURCE2 = $(PDP11_DIR)PDP11_TM.C,$(PDP11_DIR)PDP11_TS.C,\ $(PDP11_DIR)PDP11_IO.C,$(PDP11_DIR)PDP11_RQ.C,\ @@ -561,7 +561,8 @@ PDP10_SOURCE = $(PDP10_DIR)PDP10_FE.C,\ $(PDP10_DIR)PDP10_RP.C,$(PDP10_DIR)PDP10_SYS.C,\ $(PDP10_DIR)PDP10_TIM.C,$(PDP10_DIR)PDP10_TU.C,\ $(PDP11_DIR)PDP11_PT.C,$(PDP11_DIR)PDP11_DZ.C,\ - $(PDP11_DIR)PDP11_RY.C,$(PDP11_DIR)PDP11_CR.C + $(PDP11_DIR)PDP11_RY.C,$(PDP11_DIR)PDP11_CR.C,\ + $(PDP11_DIR)PDP11_DUP.C PDP10_OPTIONS = /INCL=($(SIMH_DIR),$(PDP10_DIR),$(PDP11_DIR))\ /DEF=($(CC_DEFS),"USE_INT64=1","VM_PDP10=1"$(PCAP_DEFS)) @@ -749,7 +750,7 @@ VAX730_SOURCE2 = $(PDP11_DIR)PDP11_RL.C,$(PDP11_DIR)PDP11_RQ.C,\ $(PDP11_DIR)PDP11_XU.C,$(PDP11_DIR)PDP11_RY.C,\ $(PDP11_DIR)PDP11_CR.C,$(PDP11_DIR)PDP11_HK.C,\ $(PDP11_DIR)PDP11_VH.C,$(PDP11_DIR)PDP11_DMC.C,\ - $(PDP11_DIR)PDP11_IO_LIB.C + $(PDP11_DIR)PDP11_DUP.C,$(PDP11_DIR)PDP11_IO_LIB.C .IFDEF ALPHA_OR_IA64 VAX730_OPTIONS = /INCL=($(SIMH_DIR),$(VAX730_DIR),$(PDP11_DIR)$(PCAP_INC))\ /DEF=($(CC_DEFS),"VM_VAX=1","USE_ADDR64=1","USE_INT64=1"$(PCAP_DEFS),"VAX_730=1") @@ -780,7 +781,7 @@ VAX750_SOURCE2 = $(PDP11_DIR)PDP11_RL.C,$(PDP11_DIR)PDP11_RQ.C,\ $(PDP11_DIR)PDP11_CR.C,$(PDP11_DIR)PDP11_HK.C,\ $(PDP11_DIR)PDP11_RP.C,$(PDP11_DIR)PDP11_TU.C,\ $(PDP11_DIR)PDP11_VH.C,$(PDP11_DIR)PDP11_DMC.C,\ - $(PDP11_DIR)PDP11_IO_LIB.C + $(PDP11_DIR)PDP11_DUP.C,$(PDP11_DIR)PDP11_IO_LIB.C .IFDEF ALPHA_OR_IA64 VAX750_OPTIONS = /INCL=($(SIMH_DIR),$(VAX750_DIR),$(PDP11_DIR)$(PCAP_INC))\ /DEF=($(CC_DEFS),"VM_VAX=1","USE_ADDR64=1","USE_INT64=1"$(PCAP_DEFS),"VAX_750=1") @@ -811,7 +812,7 @@ VAX780_SOURCE2 = $(PDP11_DIR)PDP11_RL.C,$(PDP11_DIR)PDP11_RQ.C,\ $(PDP11_DIR)PDP11_CR.C,$(PDP11_DIR)PDP11_RP.C,\ $(PDP11_DIR)PDP11_TU.C,$(PDP11_DIR)PDP11_HK.C,\ $(PDP11_DIR)PDP11_VH.C,$(PDP11_DIR)PDP11_DMC.C,\ - $(PDP11_DIR)PDP11_IO_LIB.C + $(PDP11_DIR)PDP11_DUP.C,$(PDP11_DIR)PDP11_IO_LIB.C .IFDEF ALPHA_OR_IA64 VAX780_OPTIONS = /INCL=($(SIMH_DIR),$(VAX780_DIR),$(PDP11_DIR)$(PCAP_INC))\ /DEF=($(CC_DEFS),"VM_VAX=1","USE_ADDR64=1","USE_INT64=1"$(PCAP_DEFS),"VAX_780=1") @@ -842,7 +843,7 @@ VAX8600_SOURCE2 = $(PDP11_DIR)PDP11_RL.C,$(PDP11_DIR)PDP11_RQ.C,\ $(PDP11_DIR)PDP11_CR.C,$(PDP11_DIR)PDP11_RP.C,\ $(PDP11_DIR)PDP11_TU.C,$(PDP11_DIR)PDP11_HK.C,\ $(PDP11_DIR)PDP11_VH.C,$(PDP11_DIR)PDP11_DMC.C,\ - $(PDP11_DIR)PDP11_IO_LIB.C + $(PDP11_DIR)PDP11_DUP.C,$(PDP11_DIR)PDP11_IO_LIB.C .IFDEF ALPHA_OR_IA64 VAX8600_OPTIONS = /INCL=($(SIMH_DIR),$(VAX8600_DIR),$(PDP11_DIR)$(PCAP_INC))\ /DEF=($(CC_DEFS),"VM_VAX=1","USE_ADDR64=1","USE_INT64=1"$(PCAP_DEFS),"VAX_860=1") diff --git a/makefile b/makefile index 33f08919..0557002b 100644 --- a/makefile +++ b/makefile @@ -661,7 +661,7 @@ PDP11 = ${PDP11D}/pdp11_fp.c ${PDP11D}/pdp11_cpu.c ${PDP11D}/pdp11_dz.c \ ${PDP11D}/pdp11_cr.c ${PDP11D}/pdp11_rf.c ${PDP11D}/pdp11_dl.c \ ${PDP11D}/pdp11_ta.c ${PDP11D}/pdp11_rc.c ${PDP11D}/pdp11_kg.c \ ${PDP11D}/pdp11_ke.c ${PDP11D}/pdp11_dc.c ${PDP11D}/pdp11_dmc.c \ - ${PDP11D}/pdp11_io_lib.c + ${PDP11D}/pdp11_dup.c ${PDP11D}/pdp11_io_lib.c PDP11_OPT = -DVM_PDP11 -I ${PDP11D} ${NETWORK_OPT} @@ -711,7 +711,7 @@ VAX730 = ${VAXD}/vax_cpu.c ${VAXD}/vax_cpu1.c ${VAXD}/vax_fpa.c \ ${PDP11D}/pdp11_dz.c ${PDP11D}/pdp11_lp.c ${PDP11D}/pdp11_tq.c \ ${PDP11D}/pdp11_xu.c ${PDP11D}/pdp11_ry.c ${PDP11D}/pdp11_cr.c \ ${PDP11D}/pdp11_hk.c ${PDP11D}/pdp11_vh.c ${PDP11D}/pdp11_dmc.c \ - ${PDP11D}/pdp11_io_lib.c + ${PDP11D}/pdp11_dup.c ${PDP11D}/pdp11_io_lib.c VAX730_OPT = -DVM_VAX -DVAX_730 -DUSE_INT64 -DUSE_ADDR64 -I VAX -I ${PDP11D} ${NETWORK_OPT} @@ -725,7 +725,8 @@ VAX750 = ${VAXD}/vax_cpu.c ${VAXD}/vax_cpu1.c ${VAXD}/vax_fpa.c \ ${PDP11D}/pdp11_dz.c ${PDP11D}/pdp11_lp.c ${PDP11D}/pdp11_tq.c \ ${PDP11D}/pdp11_xu.c ${PDP11D}/pdp11_ry.c ${PDP11D}/pdp11_cr.c \ ${PDP11D}/pdp11_hk.c ${PDP11D}/pdp11_rp.c ${PDP11D}/pdp11_tu.c \ - ${PDP11D}/pdp11_vh.c ${PDP11D}/pdp11_dmc.c ${PDP11D}/pdp11_io_lib.c + ${PDP11D}/pdp11_vh.c ${PDP11D}/pdp11_dmc.c ${PDP11D}/pdp11_dup.c \ + ${PDP11D}/pdp11_io_lib.c VAX750_OPT = -DVM_VAX -DVAX_750 -DUSE_INT64 -DUSE_ADDR64 -I VAX -I ${PDP11D} ${NETWORK_OPT} @@ -739,7 +740,8 @@ VAX780 = ${VAXD}/vax_cpu.c ${VAXD}/vax_cpu1.c ${VAXD}/vax_fpa.c \ ${PDP11D}/pdp11_dz.c ${PDP11D}/pdp11_lp.c ${PDP11D}/pdp11_tq.c \ ${PDP11D}/pdp11_xu.c ${PDP11D}/pdp11_ry.c ${PDP11D}/pdp11_cr.c \ ${PDP11D}/pdp11_rp.c ${PDP11D}/pdp11_tu.c ${PDP11D}/pdp11_hk.c \ - ${PDP11D}/pdp11_vh.c ${PDP11D}/pdp11_dmc.c ${PDP11D}/pdp11_io_lib.c + ${PDP11D}/pdp11_vh.c ${PDP11D}/pdp11_dmc.c ${PDP11D}/pdp11_dup.c \ + ${PDP11D}/pdp11_io_lib.c VAX780_OPT = -DVM_VAX -DVAX_780 -DUSE_INT64 -DUSE_ADDR64 -I VAX -I ${PDP11D} ${NETWORK_OPT} @@ -753,7 +755,8 @@ VAX8600 = ${VAXD}/vax_cpu.c ${VAXD}/vax_cpu1.c ${VAXD}/vax_fpa.c \ ${PDP11D}/pdp11_dz.c ${PDP11D}/pdp11_lp.c ${PDP11D}/pdp11_tq.c \ ${PDP11D}/pdp11_xu.c ${PDP11D}/pdp11_ry.c ${PDP11D}/pdp11_cr.c \ ${PDP11D}/pdp11_rp.c ${PDP11D}/pdp11_tu.c ${PDP11D}/pdp11_hk.c \ - ${PDP11D}/pdp11_vh.c ${PDP11D}/pdp11_dmc.c ${PDP11D}/pdp11_io_lib.c + ${PDP11D}/pdp11_vh.c ${PDP11D}/pdp11_dmc.c ${PDP11D}/pdp11_dup.c \ + ${PDP11D}/pdp11_io_lib.c VAX8600_OPT = -DVM_VAX -DVAX_860 -DUSE_INT64 -DUSE_ADDR64 -I VAX -I ${PDP11D} ${NETWORK_OPT} @@ -762,7 +765,8 @@ PDP10 = ${PDP10D}/pdp10_fe.c ${PDP11D}/pdp11_dz.c ${PDP10D}/pdp10_cpu.c \ ${PDP10D}/pdp10_ksio.c ${PDP10D}/pdp10_lp20.c ${PDP10D}/pdp10_mdfp.c \ ${PDP10D}/pdp10_pag.c ${PDP10D}/pdp10_rp.c ${PDP10D}/pdp10_sys.c \ ${PDP10D}/pdp10_tim.c ${PDP10D}/pdp10_tu.c ${PDP10D}/pdp10_xtnd.c \ - ${PDP11D}/pdp11_pt.c ${PDP11D}/pdp11_ry.c ${PDP11D}/pdp11_cr.c + ${PDP11D}/pdp11_pt.c ${PDP11D}/pdp11_ry.c ${PDP11D}/pdp11_cr.c \ + ${PDP11D}/pdp11_dup.c PDP10_OPT = -DVM_PDP10 -DUSE_INT64 -I ${PDP10D} -I ${PDP11D} From c3750e64440ca2336e949401f8cb920796f6c1ee Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Tue, 28 May 2013 01:03:58 -0700 Subject: [PATCH 04/22] Added logic to act on the state and transitions of the RCVEN bit of the receiver CSR. --- PDP11/pdp11_dup.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/PDP11/pdp11_dup.c b/PDP11/pdp11_dup.c index 5e0e6b10..96c0a7cc 100644 --- a/PDP11/pdp11_dup.c +++ b/PDP11/pdp11_dup.c @@ -49,6 +49,7 @@ #endif #include "sim_tmxr.h" +#include #if !defined(DUP_LINES) #define DUP_LINES 8 @@ -88,6 +89,7 @@ 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_rcv_byte (int32 dup); t_stat dup_reset (DEVICE *dptr); t_stat dup_attach (UNIT *uptr, char *ptr); t_stat dup_detach (UNIT *uptr); @@ -508,6 +510,15 @@ 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) && + (!(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)) && + (orig_val & RXCSR_M_RCVEN)) { /* Downward transition of receiver enable */ + dup_rxcsr[dup] &= ~RXCSR_M_RXDONE; + dup_rcvpkinoff[dup] = dup_rcvpkoffset[dup] = 0; + } break; case 01: /* PARCSR */ @@ -585,7 +596,11 @@ return SCPE_OK; t_stat dup_rcv_byte (int32 dup) { -sim_debug (DBG_TRC, DUPDPTR, ""); +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_rcvpkoffset[dup]); +if (!(dup_rxcsr[dup] & RXCSR_M_RCVEN) || (dup_rcvpkoffset[dup] == 0)) + return SCPE_OK; dup_rxcsr[dup] |= RXCSR_M_RXACT; dup_rxdbuf[dup] &= ~RXDBUF_M_RCRCER; dup_rxdbuf[dup] &= ~RXDBUF_M_RXDBUF; @@ -729,7 +744,7 @@ for (dup=active=attached=0; dup < dup_desc.lines; dup++) { break; } else { - int32 count = ((dup_rcvpacket[dup][2] & 0x3F) << 8)| dup_rcvpacket[dup][3]; + int32 count = ((dup_rcvpacket[dup][2] & 0x3F) << 8)| dup_rcvpacket[dup][1]; if (dup_rcvpkoffset[dup] >= 10 + count) { ddcmp_packet_trace (DUPDPTR, "RCV Packet", dup_rcvpacket[dup], dup_rcvpkoffset[dup], TRUE); @@ -763,8 +778,8 @@ if (sim_deb && dptr && (DBG_PKT & dptr->dctrl)) { 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"); + sim_debug (DBG_PKT, dptr, "Data Message, Link: %d, Count: %d, Resp: %d, Num: %d, HDRCRC: %s, DATACRC: %s\n", msg[2]>>6, ((msg[2] & 0x3F) << 8)|msg[1], msg[3], msg[4], + (0 == dup_crc16 (0, msg, 8)) ? "OK" : "BAD", (0 == dup_crc16 (0, msg+8, 2+(((msg[2] & 0x3F) << 8)|msg[1]))) ? "OK" : "BAD"); break; case DDCMP_ENQ: /* Control Message */ sim_debug (DBG_PKT, dptr, "Control: Type: %d ", msg[1]); From 4019e670e07e092c7b7f1220b6639cfbb246db2f Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Tue, 28 May 2013 12:18:32 -0700 Subject: [PATCH 05/22] Fixed CRC implementation, CRC state bit presentation and added register declarations --- PDP11/pdp11_dup.c | 80 +++++++++++++++++------------------------------ 1 file changed, 29 insertions(+), 51 deletions(-) diff --git a/PDP11/pdp11_dup.c b/PDP11/pdp11_dup.c index 96c0a7cc..a0590753 100644 --- a/PDP11/pdp11_dup.c +++ b/PDP11/pdp11_dup.c @@ -336,6 +336,20 @@ UNIT dup_poll_unit_template = { UNIT dup_units[DUP_LINES+1]; /* One unit per line and a polling unit */ REG dup_reg[] = { + { BRDATADF (RXCSR, dup_rxcsr, DEV_RDX, 16, DUP_LINES, "receive control/status register", dup_rxcsr_bits) }, + { BRDATADF (RXDBUF, dup_rxdbuf, DEV_RDX, 16, DUP_LINES, "receive data buffer", dup_rxdbuf_bits) }, + { BRDATADF (PARCSR, dup_parcsr, DEV_RDX, 16, DUP_LINES, "receive control/status register", dup_parcsr_bits) }, + { BRDATADF (TXCSR, dup_txcsr, DEV_RDX, 16, DUP_LINES, "transmit control/status register", dup_txcsr_bits) }, + { BRDATADF (TXDBUF, dup_txdbuf, DEV_RDX, 16, DUP_LINES, "transmit data buffer", dup_txdbuf_bits) }, + { GRDATAD (RXINT, dup_rxi, DEV_RDX, DUP_LINES, 0, "receive interrupts") }, + { GRDATAD (TXINT, dup_txi, DEV_RDX, DUP_LINES, 0, "transmit interrupts") }, + { DRDATAD (RXWAIT, dup_rx_wait, 24, "delay time for receive bytes") }, + { DRDATAD (TXWAIT, dup_tx_wait, 24, "delay time for transmit bytes") }, + { BRDATAD (RPOFFSET, dup_rcvpkoffset, DEV_RDX, 16, DUP_LINES, "receive assembly packet offset") }, + { BRDATAD (TPOFFSET, dup_xmtpkoffset, DEV_RDX, 16, DUP_LINES, "transmit assembly packet offset") }, + { BRDATAD (RPINOFF, dup_rcvpkinoff, DEV_RDX, 16, DUP_LINES, "receive digest packet offset") }, + { BRDATAD (TPOUTOFF, dup_xmtpkoutoff, DEV_RDX, 16, DUP_LINES, "transmit digest packet offset") }, + { BRDATAD (TPREADY, dup_xmtpkrdy, DEV_RDX, 16, DUP_LINES, "transmit packet ready") }, { NULL } }; @@ -606,11 +620,15 @@ 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) || + (dup_rcvpkinoff[dup] >= dup_rcvpkoffset[dup])) && + (0 == dup_crc16 (0, dup_rcvpacket[dup], dup_rcvpkinoff[dup]))) + dup_rxdbuf[dup] |= RXDBUF_M_RCRCER; +else + dup_rxdbuf[dup] &= ~RXDBUF_M_RCRCER; 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); @@ -1087,58 +1105,18 @@ return (UNIBUS) ? "DUP11 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 crc16_nibble[16] = { + 0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401, + 0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400, + }; -static uint16 dup_crc16 (uint16 crc, const void* vbuf, size_t len) +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 ]; +while(0 != len--) { + crc = (crc>>4) ^ crc16_nibble[(*buf ^ crc) & 0xF]; + crc = (crc>>4) ^ crc16_nibble[((*buf++)>>4 ^ crc) & 0xF]; + }; return(crc); } - From 4ba152db79fec8e9eb232c1c0856e0b5e8aea551 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Tue, 28 May 2013 17:35:49 -0700 Subject: [PATCH 06/22] Fix packet transmit overrun behaviors which caused DECnet circuit failures. --- PDP11/pdp11_dup.c | 39 ++++++++++++++++++++++++--------------- sim_tmxr.c | 2 +- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/PDP11/pdp11_dup.c b/PDP11/pdp11_dup.c index a0590753..aebb87a4 100644 --- a/PDP11/pdp11_dup.c +++ b/PDP11/pdp11_dup.c @@ -531,7 +531,9 @@ switch ((PA >> 1) & 03) { /* case on PA<2:1> */ if ((!(dup_rxcsr[dup] & RXCSR_M_RCVEN)) && (orig_val & RXCSR_M_RCVEN)) { /* Downward transition of receiver enable */ dup_rxcsr[dup] &= ~RXCSR_M_RXDONE; - dup_rcvpkinoff[dup] = dup_rcvpkoffset[dup] = 0; + if ((dup_rcvpkinoff[dup] != 0) || + (dup_rcvpkoffset[dup] != 0)) + dup_rcvpkinoff[dup] = dup_rcvpkoffset[dup] = 0; } break; @@ -627,7 +629,7 @@ if (((dup_rcvpkinoff[dup] == 8) || else dup_rxdbuf[dup] &= ~RXDBUF_M_RCRCER; if (dup_rcvpkinoff[dup] >= dup_rcvpkoffset[dup]) { - dup_rcvpkoffset[dup] = 0; + dup_rcvpkinoff[dup] = dup_rcvpkoffset[dup] = 0; dup_rxcsr[dup] &= ~RXCSR_M_RXACT; } if (dup_rxcsr[dup] & RXCSR_M_RXIE) @@ -644,7 +646,7 @@ 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_txcsr[dup] & TXCSR_M_TXDONE) && (!dup_xmtpkrdy[dup])) { if (dup_txdbuf[dup] & TXDBUF_M_TSOM) { dup_xmtpkoffset[dup] = 0; } @@ -674,12 +676,12 @@ if (!(dup_txcsr[dup] & TXCSR_M_TXDONE)) { 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); + 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]) { +if (dup_xmtpkrdy[dup] && lp->xmte) { t_stat st = SCPE_OK; while ((st == SCPE_OK) && (dup_xmtpkoutoff[dup] < dup_xmtpkoffset[dup])) { @@ -693,8 +695,13 @@ if (dup_xmtpkrdy[dup]) { dup_xmtpkrdy[dup] = FALSE; } else - if (st == SCPE_OK) + if (st == SCPE_OK) { + sim_debug(DBG_PKT, DUPDPTR, "dup_svc(dup=%d) - %d byte packet transmission complete\n", dup, dup_xmtpkoutoff[dup]); dup_xmtpkrdy[dup] = FALSE; + } + else { + sim_debug(DBG_PKT, DUPDPTR, "dup_svc(dup=%d) - Packet Transmission Stalled with %d bytes remaining\n", dup, (int)(dup_xmtpkoffset[dup]-dup_xmtpkoutoff[dup])); + } if (!dup_xmtpkrdy[dup]) dup_txcsr[dup] &= ~TXCSR_M_TXACT; } @@ -726,8 +733,10 @@ for (dup=active=attached=0; dup < dup_desc.lines; dup++) { if (dup_ldsc[dup].conn) ++active; dup_get_modem (dup); - if (lp->xmte && dup_xmtpkrdy[dup]) + if (lp->xmte && dup_xmtpkrdy[dup]) { + sim_debug(DBG_PKT, DUPDPTR, "dup_poll_svc(dup=%d) - Packet Transmission of remaining %d bytes restarting...\n", dup, (int)(dup_xmtpkoffset[dup]-dup_xmtpkoutoff[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]) { @@ -756,7 +765,7 @@ for (dup=active=attached=0; dup < dup_desc.lines; dup++) { } 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); + ddcmp_packet_trace (DUPDPTR, "<<< RCV Packet", dup_rcvpacket[dup], dup_rcvpkoffset[dup], TRUE); dup_rcvpkinoff[dup] = 0; dup_rcv_byte (dup); break; @@ -765,7 +774,7 @@ for (dup=active=attached=0; dup < dup_desc.lines; dup++) { int32 count = ((dup_rcvpacket[dup][2] & 0x3F) << 8)| dup_rcvpacket[dup][1]; if (dup_rcvpkoffset[dup] >= 10 + count) { - ddcmp_packet_trace (DUPDPTR, "RCV Packet", dup_rcvpacket[dup], dup_rcvpkoffset[dup], TRUE); + ddcmp_packet_trace (DUPDPTR, "<<< RCV Packet", dup_rcvpacket[dup], dup_rcvpkoffset[dup], TRUE); dup_rcvpkinoff[dup] = 0; dup_rcv_byte (dup); break; @@ -803,19 +812,19 @@ if (sim_deb && dptr && (DBG_PKT & dptr->dctrl)) { 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]); + sim_debug (DBG_PKT, dptr, "(ACK) ACKSUB: %d, Link: %d, Resp: %d\n", msg[2] & 0x3F, 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]); + sim_debug (DBG_PKT, dptr, "(REP) REPSUB: %d, Link: %d, Num: %d\n", msg[2] & 0x3F, msg[2]>>6, msg[4]); break; case 6: /* STRT */ - sim_debug (DBG_PKT, dptr, "(STRT) Link: %d\n", msg[2]>>6); + sim_debug (DBG_PKT, dptr, "(STRT) STRTSUB: %d, Link: %d\n", msg[2] & 0x3F, msg[2]>>6); break; case 7: /* STACK */ - sim_debug (DBG_PKT, dptr, "(STACK) Link: %d\n", msg[2]>>6); + sim_debug (DBG_PKT, dptr, "(STACK) STCKSUB: %d, Link: %d\n", msg[2] & 0x3F, msg[2]>>6); break; default: /* Unknown */ sim_debug (DBG_PKT, dptr, "(Unknown=0%o)\n", msg[1]); @@ -827,8 +836,8 @@ if (sim_deb && dptr && (DBG_PKT & dptr->dctrl)) { 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"); + sim_debug (DBG_PKT, dptr, "Maintenance Message, Link: %d, Count: %d, HDRCRC: %s, DATACRC: %s\n", msg[2]>>6, ((msg[2] & 0x3F) << 8)| msg[1], + (0 == dup_crc16 (0, msg, 8)) ? "OK" : "BAD", (0 == dup_crc16 (0, msg+8, 2+(((msg[2] & 0x3F) << 8)| msg[1]))) ? "OK" : "BAD"); break; } for (i=same=0; itxbpi == lp->txbpr) \ lp->txbpr = (1+lp->txbpr)%lp->txbsz, ++lp->txdrp; \ } -if ((lp->txbfd) || (TXBUF_AVAIL(lp) > 1)) { /* room for char (+ IAC)? */ +if ((lp->txbfd && !lp->notelnet) || (TXBUF_AVAIL(lp) > 1)) {/* room for char (+ IAC)? */ if ((TN_IAC == (u_char) chr) && (!lp->notelnet)) /* char == IAC in telnet session? */ TXBUF_CHAR (lp, TN_IAC); /* stuff extra IAC char */ TXBUF_CHAR (lp, chr); /* buffer char & adv pointer */ From 27dac1ade26e196f5ad62d7159c37f5955faef3d Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Wed, 29 May 2013 05:33:51 -0700 Subject: [PATCH 07/22] Added rate limit support (SET DUPn SPEED=bps). --- PDP11/pdp11_dup.c | 95 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 73 insertions(+), 22 deletions(-) diff --git a/PDP11/pdp11_dup.c b/PDP11/pdp11_dup.c index aebb87a4..7271bdb5 100644 --- a/PDP11/pdp11_dup.c +++ b/PDP11/pdp11_dup.c @@ -56,12 +56,13 @@ #endif #define INITIAL_DUP_LINES 1 -#define DUP_RX_WAIT 100 -#define DUP_TX_WAIT 100 -#define DUP_CONNECT_POLL 2 /* Seconds */ +#define DUP_WAIT 50 /* Minimum character time */ +#define DUP_CONNECT_POLL 2 /* Seconds */ extern int32 IREQ (HLVL); extern int32 tmxr_poll; /* calibrated delay */ +extern int32 clk_tps; /* clock ticks per second */ +extern int32 tmr_poll; /* instructions per tick */ uint16 dup_rxcsr[DUP_LINES]; uint16 dup_rxdbuf[DUP_LINES]; @@ -70,8 +71,8 @@ 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 */ +uint32 dup_wait[DUP_LINES]; /* rcv/xmt byte delay */ +uint32 dup_speed[DUP_LINES]; /* line speed (bits/sec) */ uint8 *dup_rcvpacket[DUP_LINES]; /* rcv buffer */ uint16 dup_rcvpksize[DUP_LINES]; /* rcv buffer size */ uint16 dup_rcvpkoffset[DUP_LINES]; /* rcv buffer offset */ @@ -104,6 +105,8 @@ 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_setspeed (UNIT* uptr, int32 val, char* cptr, void* desc); +t_stat dup_showspeed (FILE* st, UNIT* uptr, int32 val, 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); @@ -343,8 +346,7 @@ REG dup_reg[] = { { BRDATADF (TXDBUF, dup_txdbuf, DEV_RDX, 16, DUP_LINES, "transmit data buffer", dup_txdbuf_bits) }, { GRDATAD (RXINT, dup_rxi, DEV_RDX, DUP_LINES, 0, "receive interrupts") }, { GRDATAD (TXINT, dup_txi, DEV_RDX, DUP_LINES, 0, "transmit interrupts") }, - { DRDATAD (RXWAIT, dup_rx_wait, 24, "delay time for receive bytes") }, - { DRDATAD (TXWAIT, dup_tx_wait, 24, "delay time for transmit bytes") }, + { BRDATAD (RXWAIT, dup_wait, 10, 24, DUP_LINES, "delay time for transmit/receive bytes") }, { BRDATAD (RPOFFSET, dup_rcvpkoffset, DEV_RDX, 16, DUP_LINES, "receive assembly packet offset") }, { BRDATAD (TPOFFSET, dup_xmtpkoffset, DEV_RDX, 16, DUP_LINES, "transmit assembly packet offset") }, { BRDATAD (RPINOFF, dup_rcvpkinoff, DEV_RDX, 16, DUP_LINES, "receive digest packet offset") }, @@ -357,6 +359,8 @@ TMLN *dup_ldsc = NULL; /* line descriptors */ TMXR dup_desc = { INITIAL_DUP_LINES, 0, 0, NULL }; /* mux descriptor */ MTAB dup_mod[] = { + { MTAB_XTD|MTAB_VUN, 0, "SPEED", "SPEED=bits/sec (0=unrestricted)" , + &dup_setspeed, &dup_showspeed, NULL, "Display rate limit" }, { MTAB_XTD|MTAB_VDV|MTAB_VALR, 020, "ADDRESS", "ADDRESS", &set_addr, &show_addr, NULL, "Bus address" }, { MTAB_XTD|MTAB_VDV|MTAB_VALR, 1, "VECTOR", "VECTOR", @@ -475,7 +479,7 @@ switch ((PA >> 1) & 03) { /* case on PA<2:1> */ *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); + sim_activate (dup_units+dup, dup_wait[dup]); break; case 02: /* TXCSR */ @@ -559,7 +563,7 @@ switch ((PA >> 1) & 03) { /* case on PA<2:1> */ 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); + sim_activate (dup_units+dup, dup_wait[dup]); } break; } @@ -786,9 +790,19 @@ for (dup=active=attached=0; dup < dup_desc.lines; dup++) { } if (active) sim_clock_coschedule (uptr, tmxr_poll); /* reactivate */ -else +else { + for (dup=0; dup < dup_desc.lines; dup++) { + if (dup_speed[dup]/8) { + dup_wait[dup] = (tmr_poll*clk_tps)/(dup_speed[dup]/8); + if (dup_wait[dup] < DUP_WAIT) + dup_wait[dup] = DUP_WAIT; + } + else + dup_wait[dup] = DUP_WAIT; /* set minimum byte delay */ + } if (attached) sim_activate_after (uptr, DUP_CONNECT_POLL*1000000);/* periodic check for connections */ + } return SCPE_OK; } @@ -944,6 +958,7 @@ dup_rxdbuf[dup] = 0; /* silo empty */ dup_txdbuf[dup] = 0; dup_parcsr[dup] = 0; /* no params */ dup_txcsr[dup] = TXCSR_M_TXDONE; /* clear CSR */ +dup_wait[dup] = DUP_WAIT; /* initial/default byte delay */ if (flag) /* INIT? clr all */ dup_rxcsr[dup] = 0; else @@ -1046,6 +1061,36 @@ dup_xmtpkoutoff[dup] = 0; return tmxr_detach_ln (lp); } +/* SET/SHOW SPEED processor */ + +t_stat dup_showspeed (FILE* st, UNIT* uptr, int32 val, void* desc) +{ +DEVICE *dptr = DUPDPTR; +int32 dup = (int32)(uptr-dptr->units); + +if (dup_speed[dup]) + fprintf(st, "speed=%d bits/sec", dup_speed[dup]); +else + fprintf(st, "speed=0 (unrestricted)"); +return SCPE_OK; +} + +t_stat dup_setspeed (UNIT* uptr, int32 val, char* cptr, void* desc) +{ +DEVICE *dptr = DUPDPTR; +int32 dup = (int32)(uptr-dptr->units); +t_stat r; +int32 newspeed; + +if (cptr == NULL) + return SCPE_ARG; +newspeed = (int32) get_uint (cptr, 10, 100000000, &r); +if (r != SCPE_OK) + return r; +dup_speed[dup] = newspeed; +return SCPE_OK; +} + /* SET LINES processor */ t_stat dup_setnl (UNIT *uptr, int32 val, char *cptr, void *desc) @@ -1085,6 +1130,13 @@ fprintf (st, "The %s connects two systems to provide a network connection.\n", d 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); +fprintf (st, "If you want to experience the actual data rates of the physical hardware you\n"); +fprintf (st, "can set the bit rate of the simulated line can be set using the following\n"); +fprintf (st, "command:\n\n"); +fprintf (st, " sim> SET %sn SPEED=bps\n\n", dptr->name); +fprintf (st, "Where bps is the number of data bits per second that the simulated line runs\n"); +fprintf (st, "at. Use a value of zero to run at full speed with no artificial\n"); +fprintf (st, "throttling.\n\n"); fprint_set_help (st, dptr); fprint_show_help (st, dptr); fprint_reg_help (st, dptr); @@ -1093,18 +1145,17 @@ 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; +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\n"); +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 peer address) 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) From f5de2f4d22469d7eed791a14cdc44b862f551c13 Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Wed, 29 May 2013 13:43:12 -0400 Subject: [PATCH 08/22] LP20 emulation was overwriting existing files When an LP20 is attached to an existing file, the file is opened in update mode. Since the initial file position is zero, any existing output is over-written. This is not intuitive. This edit makes the LP20 seek to EOF on attach. N.B. Other devices may have cousin issues. --- PDP10/pdp10_lp20.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/PDP10/pdp10_lp20.c b/PDP10/pdp10_lp20.c index fec1cda6..20858e10 100644 --- a/PDP10/pdp10_lp20.c +++ b/PDP10/pdp10_lp20.c @@ -25,6 +25,8 @@ lp20 line printer + 29-May-13 TL Force append when an existing file is attached. Previously + over-wrote file from the top. 19-Jan-07 RMS Added UNIT_TEXT flag 04-Sep-05 RMS Fixed missing return (found by Peter Schorn) 07-Jul-05 RMS Removed extraneous externs @@ -657,6 +659,10 @@ t_stat lp20_attach (UNIT *uptr, char *cptr) t_stat reason; reason = attach_unit (uptr, cptr); /* attach file */ +if (reason == SCPE_OK) { + sim_fseek (uptr->fileref, 0, SEEK_END); + uptr->pos = ftell (uptr->fileref); +} if (lpcsa & CSA_ONL) /* just file chg? */ return reason; if (sim_is_active (&lp20_unit)) /* busy? no int */ From 611b7632c993006c5e4bd1d0fe3516cd3f6f4de4 Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Wed, 29 May 2013 13:50:56 -0400 Subject: [PATCH 09/22] Add set serial to KS cpu With multiple instances, error logging gets confusing when every CPU has the same serial number. This makes the CPU serial number settable. If not set, the old defaults apply. --- PDP10/pdp10_cpu.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-- PDP10/pdp10_defs.h | 34 ++++++++++++++++++++++++---------- 2 files changed, 68 insertions(+), 12 deletions(-) diff --git a/PDP10/pdp10_cpu.c b/PDP10/pdp10_cpu.c index 8a24bfed..21098b5e 100644 --- a/PDP10/pdp10_cpu.c +++ b/PDP10/pdp10_cpu.c @@ -197,6 +197,7 @@ jmp_buf save_env; int32 hst_p = 0; /* history pointer */ int32 hst_lnt = 0; /* history length */ InstHistory *hst = NULL; /* instruction history */ +int32 apr_serial = -1; /* CPU Serial number */ /* Forward and external declarations */ @@ -205,6 +206,9 @@ t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); t_stat cpu_reset (DEVICE *dptr); t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc); t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc); +t_stat cpu_set_serial (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat cpu_show_serial (FILE *st, UNIT *uptr, int32 val, void *desc); + d10 adjsp (d10 val, a10 ea); void ibp (a10 ea, int32 pflgs); d10 ldb (a10 ea, int32 pflgs); @@ -400,6 +404,7 @@ MTAB cpu_mod[] = { NULL, &show_iospace }, { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY", &cpu_set_hist, &cpu_show_hist }, + { MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "SERIAL", "SERIAL", &cpu_set_serial, &cpu_show_serial }, { 0 } }; @@ -2104,8 +2109,14 @@ return; t_bool aprid (a10 ea, int32 prv) { -Write (ea, (Q_ITS)? UC_AIDITS: UC_AIDDEC, prv); -return FALSE; + d10 value = (Q_ITS)? UC_AIDITS: UC_AIDDEC; + if( (apr_serial == -1) || (!Q_ITS && apr_serial < 4096) ) + value |= (Q_ITS)? UC_SERITS: UC_SERDEC; + else + value |= apr_serial; + + Write (ea, value, prv); + return FALSE; } /* Checked against KS10 ucode */ @@ -2419,3 +2430,34 @@ for (k = 0; k < lnt; k++) { /* print specified */ } /* end for */ return SCPE_OK; } + +/* Set serial */ + +t_stat cpu_set_serial (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +int32 lnt; +t_stat r; + +if (cptr == NULL) { + apr_serial = -1; + return SCPE_OK; + } +lnt = (int32) get_uint (cptr, 10, 077777, &r); +if ((r != SCPE_OK) || (lnt <= 0) || (!Q_ITS && lnt < 4096)) + return SCPE_ARG; +apr_serial = lnt & 077777; +return SCPE_OK; +} + +/* Show serial */ + +t_stat cpu_show_serial (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +fprintf (st, "Serial: " ); +if( (apr_serial == -1) || (!Q_ITS && apr_serial < 4096) ) { + fprintf (st, "%d (default)", (Q_ITS)? UC_SERITS: UC_SERDEC); + return SCPE_OK; +} +fprintf (st, "%d", apr_serial); +return SCPE_OK; +} diff --git a/PDP10/pdp10_defs.h b/PDP10/pdp10_defs.h index fac99a78..0a161f33 100644 --- a/PDP10/pdp10_defs.h +++ b/PDP10/pdp10_defs.h @@ -476,8 +476,8 @@ typedef t_int64 d10; /* PDP-10 data (36b) */ #define UC_SERDEC 4097 /* serial number */ #define UC_SERITS 1729 #define UC_AIDDEC (UC_INHCST | UC_UBABLT | UC_KIPAGE | UC_KLPAGE | \ - UC_VERDEC | UC_SERDEC) -#define UC_AIDITS (UC_KIPAGE | UC_VERITS | UC_SERITS) + UC_VERDEC) +#define UC_AIDITS (UC_KIPAGE | UC_VERITS) #define UC_HSBDEC 0376000 /* DEC initial HSB */ #define UC_HSBITS 0000500 /* ITS initial HSB */ @@ -619,7 +619,6 @@ 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 */ @@ -659,6 +658,12 @@ typedef struct pdp_dib DIB; #define IOLN_UBMNT3 001 #define IOBA_XU (IO_UBA3 + 0774510) /* DEUNA/DELUA */ #define IOLN_XU 010 +#define IOBA_DMR (IO_UBA3 + 0764000) /* DMR11 */ +#define IOLN_DMR 010 +#define IOBA_DUP (IO_UBA3 + 0760300) /* DUP11 */ +#define IOLN_DUP 010 +#define IOBA_KMC (IO_UBA3 + 0760540) /* KMC11 */ +#define IOLN_KMC 010 #define IOBA_CR (IO_UBA3 + 0777160) /* CD/CR/CM */ #define IOLN_CR 010 #define IOBA_RY (IO_UBA3 + 0777170) /* RX211 */ @@ -697,6 +702,10 @@ typedef struct pdp_dib DIB; #define INT_V_RP 6 /* RH11/RP,RM drives */ #define INT_V_TU 7 /* RH11/TM03/TU45 */ +#define INT_V_KMCA 8 /* KMC11 */ +#define INT_V_KMCB 9 +#define INT_V_DMRA 10 /* DMR11 */ +#define INT_V_DMRB 11 #define INT_V_DMCRX 13 #define INT_V_DMCTX 14 #define INT_V_XU 15 /* DEUNA/DELUA */ @@ -707,12 +716,13 @@ 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) +#define INT_KMCA (1u << INT_V_KMCA) +#define INT_KMCB (1u << INT_V_KMCB) +#define INT_DMRA (1u << INT_V_DMRA) +#define INT_DMRB (1u << INT_V_DMRB) #define INT_DMCRX (1u << INT_V_DMCRX) #define INT_DMCTX (1u << INT_V_DMCTX) #define INT_XU (1u << INT_V_XU) @@ -723,19 +733,19 @@ 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 +#define IPL_KMCA 5 +#define IPL_KMCB 5 +#define IPL_DMRA 5 +#define IPL_DMRB 5 #define IPL_DMCRX 5 #define IPL_DMCTX 5 #define IPL_XU 5 #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 @@ -759,6 +769,10 @@ typedef struct pdp_dib DIB; #define VEC_RY 0264 #define VEC_DZRX 0340 #define VEC_DZTX 0344 +#define VEC_KMCA 0540 +#define VEC_KMCB 0544 +#define VEC_DMRA 0610 +#define VEC_DMRB 0614 #define VEC_LP20 0754 #define VEC_AUTO 0 /* Set by Auto Configure */ From b80fa0ae50cb38efba5e8c8ec030e6681a8f4013 Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Wed, 29 May 2013 13:52:29 -0400 Subject: [PATCH 10/22] Revert "Add set serial to KS cpu" This reverts commit 611b7632c993006c5e4bd1d0fe3516cd3f6f4de4. --- PDP10/pdp10_cpu.c | 46 ++-------------------------------------------- PDP10/pdp10_defs.h | 34 ++++++++++------------------------ 2 files changed, 12 insertions(+), 68 deletions(-) diff --git a/PDP10/pdp10_cpu.c b/PDP10/pdp10_cpu.c index 21098b5e..8a24bfed 100644 --- a/PDP10/pdp10_cpu.c +++ b/PDP10/pdp10_cpu.c @@ -197,7 +197,6 @@ jmp_buf save_env; int32 hst_p = 0; /* history pointer */ int32 hst_lnt = 0; /* history length */ InstHistory *hst = NULL; /* instruction history */ -int32 apr_serial = -1; /* CPU Serial number */ /* Forward and external declarations */ @@ -206,9 +205,6 @@ t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); t_stat cpu_reset (DEVICE *dptr); t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc); t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc); -t_stat cpu_set_serial (UNIT *uptr, int32 val, char *cptr, void *desc); -t_stat cpu_show_serial (FILE *st, UNIT *uptr, int32 val, void *desc); - d10 adjsp (d10 val, a10 ea); void ibp (a10 ea, int32 pflgs); d10 ldb (a10 ea, int32 pflgs); @@ -404,7 +400,6 @@ MTAB cpu_mod[] = { NULL, &show_iospace }, { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY", &cpu_set_hist, &cpu_show_hist }, - { MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "SERIAL", "SERIAL", &cpu_set_serial, &cpu_show_serial }, { 0 } }; @@ -2109,14 +2104,8 @@ return; t_bool aprid (a10 ea, int32 prv) { - d10 value = (Q_ITS)? UC_AIDITS: UC_AIDDEC; - if( (apr_serial == -1) || (!Q_ITS && apr_serial < 4096) ) - value |= (Q_ITS)? UC_SERITS: UC_SERDEC; - else - value |= apr_serial; - - Write (ea, value, prv); - return FALSE; +Write (ea, (Q_ITS)? UC_AIDITS: UC_AIDDEC, prv); +return FALSE; } /* Checked against KS10 ucode */ @@ -2430,34 +2419,3 @@ for (k = 0; k < lnt; k++) { /* print specified */ } /* end for */ return SCPE_OK; } - -/* Set serial */ - -t_stat cpu_set_serial (UNIT *uptr, int32 val, char *cptr, void *desc) -{ -int32 lnt; -t_stat r; - -if (cptr == NULL) { - apr_serial = -1; - return SCPE_OK; - } -lnt = (int32) get_uint (cptr, 10, 077777, &r); -if ((r != SCPE_OK) || (lnt <= 0) || (!Q_ITS && lnt < 4096)) - return SCPE_ARG; -apr_serial = lnt & 077777; -return SCPE_OK; -} - -/* Show serial */ - -t_stat cpu_show_serial (FILE *st, UNIT *uptr, int32 val, void *desc) -{ -fprintf (st, "Serial: " ); -if( (apr_serial == -1) || (!Q_ITS && apr_serial < 4096) ) { - fprintf (st, "%d (default)", (Q_ITS)? UC_SERITS: UC_SERDEC); - return SCPE_OK; -} -fprintf (st, "%d", apr_serial); -return SCPE_OK; -} diff --git a/PDP10/pdp10_defs.h b/PDP10/pdp10_defs.h index 0a161f33..fac99a78 100644 --- a/PDP10/pdp10_defs.h +++ b/PDP10/pdp10_defs.h @@ -476,8 +476,8 @@ typedef t_int64 d10; /* PDP-10 data (36b) */ #define UC_SERDEC 4097 /* serial number */ #define UC_SERITS 1729 #define UC_AIDDEC (UC_INHCST | UC_UBABLT | UC_KIPAGE | UC_KLPAGE | \ - UC_VERDEC) -#define UC_AIDITS (UC_KIPAGE | UC_VERITS) + UC_VERDEC | UC_SERDEC) +#define UC_AIDITS (UC_KIPAGE | UC_VERITS | UC_SERITS) #define UC_HSBDEC 0376000 /* DEC initial HSB */ #define UC_HSBITS 0000500 /* ITS initial HSB */ @@ -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 */ @@ -658,12 +659,6 @@ typedef struct pdp_dib DIB; #define IOLN_UBMNT3 001 #define IOBA_XU (IO_UBA3 + 0774510) /* DEUNA/DELUA */ #define IOLN_XU 010 -#define IOBA_DMR (IO_UBA3 + 0764000) /* DMR11 */ -#define IOLN_DMR 010 -#define IOBA_DUP (IO_UBA3 + 0760300) /* DUP11 */ -#define IOLN_DUP 010 -#define IOBA_KMC (IO_UBA3 + 0760540) /* KMC11 */ -#define IOLN_KMC 010 #define IOBA_CR (IO_UBA3 + 0777160) /* CD/CR/CM */ #define IOLN_CR 010 #define IOBA_RY (IO_UBA3 + 0777170) /* RX211 */ @@ -702,10 +697,6 @@ typedef struct pdp_dib DIB; #define INT_V_RP 6 /* RH11/RP,RM drives */ #define INT_V_TU 7 /* RH11/TM03/TU45 */ -#define INT_V_KMCA 8 /* KMC11 */ -#define INT_V_KMCB 9 -#define INT_V_DMRA 10 /* DMR11 */ -#define INT_V_DMRB 11 #define INT_V_DMCRX 13 #define INT_V_DMCTX 14 #define INT_V_XU 15 /* DEUNA/DELUA */ @@ -716,13 +707,12 @@ 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) -#define INT_KMCA (1u << INT_V_KMCA) -#define INT_KMCB (1u << INT_V_KMCB) -#define INT_DMRA (1u << INT_V_DMRA) -#define INT_DMRB (1u << INT_V_DMRB) #define INT_DMCRX (1u << INT_V_DMCRX) #define INT_DMCTX (1u << INT_V_DMCTX) #define INT_XU (1u << INT_V_XU) @@ -733,19 +723,19 @@ 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 -#define IPL_KMCA 5 -#define IPL_KMCB 5 -#define IPL_DMRA 5 -#define IPL_DMRB 5 #define IPL_DMCRX 5 #define IPL_DMCTX 5 #define IPL_XU 5 #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 @@ -769,10 +759,6 @@ typedef struct pdp_dib DIB; #define VEC_RY 0264 #define VEC_DZRX 0340 #define VEC_DZTX 0344 -#define VEC_KMCA 0540 -#define VEC_KMCB 0544 -#define VEC_DMRA 0610 -#define VEC_DMRB 0614 #define VEC_LP20 0754 #define VEC_AUTO 0 /* Set by Auto Configure */ From 5f26e6011a73bc9ab0d6b36fbb6427cfc3c1bec1 Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Wed, 29 May 2013 13:59:42 -0400 Subject: [PATCH 11/22] Add set cpu serial for KS Allow CPU serial number to be set for KS cpus. With multiple instances running about, this prevents a lot of confusion, especially in the error logs. --- PDP10/pdp10_cpu.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-- PDP10/pdp10_defs.h | 5 +++-- 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/PDP10/pdp10_cpu.c b/PDP10/pdp10_cpu.c index 8a24bfed..21098b5e 100644 --- a/PDP10/pdp10_cpu.c +++ b/PDP10/pdp10_cpu.c @@ -197,6 +197,7 @@ jmp_buf save_env; int32 hst_p = 0; /* history pointer */ int32 hst_lnt = 0; /* history length */ InstHistory *hst = NULL; /* instruction history */ +int32 apr_serial = -1; /* CPU Serial number */ /* Forward and external declarations */ @@ -205,6 +206,9 @@ t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw); t_stat cpu_reset (DEVICE *dptr); t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc); t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc); +t_stat cpu_set_serial (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat cpu_show_serial (FILE *st, UNIT *uptr, int32 val, void *desc); + d10 adjsp (d10 val, a10 ea); void ibp (a10 ea, int32 pflgs); d10 ldb (a10 ea, int32 pflgs); @@ -400,6 +404,7 @@ MTAB cpu_mod[] = { NULL, &show_iospace }, { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY", &cpu_set_hist, &cpu_show_hist }, + { MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "SERIAL", "SERIAL", &cpu_set_serial, &cpu_show_serial }, { 0 } }; @@ -2104,8 +2109,14 @@ return; t_bool aprid (a10 ea, int32 prv) { -Write (ea, (Q_ITS)? UC_AIDITS: UC_AIDDEC, prv); -return FALSE; + d10 value = (Q_ITS)? UC_AIDITS: UC_AIDDEC; + if( (apr_serial == -1) || (!Q_ITS && apr_serial < 4096) ) + value |= (Q_ITS)? UC_SERITS: UC_SERDEC; + else + value |= apr_serial; + + Write (ea, value, prv); + return FALSE; } /* Checked against KS10 ucode */ @@ -2419,3 +2430,34 @@ for (k = 0; k < lnt; k++) { /* print specified */ } /* end for */ return SCPE_OK; } + +/* Set serial */ + +t_stat cpu_set_serial (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +int32 lnt; +t_stat r; + +if (cptr == NULL) { + apr_serial = -1; + return SCPE_OK; + } +lnt = (int32) get_uint (cptr, 10, 077777, &r); +if ((r != SCPE_OK) || (lnt <= 0) || (!Q_ITS && lnt < 4096)) + return SCPE_ARG; +apr_serial = lnt & 077777; +return SCPE_OK; +} + +/* Show serial */ + +t_stat cpu_show_serial (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +fprintf (st, "Serial: " ); +if( (apr_serial == -1) || (!Q_ITS && apr_serial < 4096) ) { + fprintf (st, "%d (default)", (Q_ITS)? UC_SERITS: UC_SERDEC); + return SCPE_OK; +} +fprintf (st, "%d", apr_serial); +return SCPE_OK; +} diff --git a/PDP10/pdp10_defs.h b/PDP10/pdp10_defs.h index fac99a78..a88c92f8 100644 --- a/PDP10/pdp10_defs.h +++ b/PDP10/pdp10_defs.h @@ -476,8 +476,9 @@ typedef t_int64 d10; /* PDP-10 data (36b) */ #define UC_SERDEC 4097 /* serial number */ #define UC_SERITS 1729 #define UC_AIDDEC (UC_INHCST | UC_UBABLT | UC_KIPAGE | UC_KLPAGE | \ - UC_VERDEC | UC_SERDEC) -#define UC_AIDITS (UC_KIPAGE | UC_VERITS | UC_SERITS) + UC_VERDEC) +#define UC_AIDITS (UC_KIPAGE | UC_VERITS) + #define UC_HSBDEC 0376000 /* DEC initial HSB */ #define UC_HSBITS 0000500 /* ITS initial HSB */ From 3e250420176444fa2a52a907081de1c40c10763a Mon Sep 17 00:00:00 2001 From: Timothe Litt Date: Wed, 29 May 2013 14:48:43 -0400 Subject: [PATCH 12/22] Change some tabs to spaces --- PDP10/pdp10_cpu.c | 50 +++++++++++++++++++++++----------------------- PDP10/pdp10_lp20.c | 14 ++++++------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/PDP10/pdp10_cpu.c b/PDP10/pdp10_cpu.c index 21098b5e..03af6947 100644 --- a/PDP10/pdp10_cpu.c +++ b/PDP10/pdp10_cpu.c @@ -197,7 +197,7 @@ jmp_buf save_env; int32 hst_p = 0; /* history pointer */ int32 hst_lnt = 0; /* history length */ InstHistory *hst = NULL; /* instruction history */ -int32 apr_serial = -1; /* CPU Serial number */ +int32 apr_serial = -1; /* CPU Serial number */ /* Forward and external declarations */ @@ -404,7 +404,7 @@ MTAB cpu_mod[] = { NULL, &show_iospace }, { MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY", &cpu_set_hist, &cpu_show_hist }, - { MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "SERIAL", "SERIAL", &cpu_set_serial, &cpu_show_serial }, + { MTAB_XTD|MTAB_VDV|MTAB_VALR, 0, "SERIAL", "SERIAL", &cpu_set_serial, &cpu_show_serial }, { 0 } }; @@ -2109,14 +2109,14 @@ return; t_bool aprid (a10 ea, int32 prv) { - d10 value = (Q_ITS)? UC_AIDITS: UC_AIDDEC; - if( (apr_serial == -1) || (!Q_ITS && apr_serial < 4096) ) - value |= (Q_ITS)? UC_SERITS: UC_SERDEC; - else - value |= apr_serial; + d10 value = (Q_ITS)? UC_AIDITS: UC_AIDDEC; + if( (apr_serial == -1) || (!Q_ITS && apr_serial < 4096) ) + value |= (Q_ITS)? UC_SERITS: UC_SERDEC; + else + value |= apr_serial; - Write (ea, value, prv); - return FALSE; + Write (ea, value, prv); + return FALSE; } /* Checked against KS10 ucode */ @@ -2435,29 +2435,29 @@ return SCPE_OK; t_stat cpu_set_serial (UNIT *uptr, int32 val, char *cptr, void *desc) { -int32 lnt; -t_stat r; + int32 lnt; + t_stat r; -if (cptr == NULL) { + if (cptr == NULL) { apr_serial = -1; - return SCPE_OK; - } -lnt = (int32) get_uint (cptr, 10, 077777, &r); -if ((r != SCPE_OK) || (lnt <= 0) || (!Q_ITS && lnt < 4096)) + return SCPE_OK; + } + lnt = (int32) get_uint (cptr, 10, 077777, &r); + if ((r != SCPE_OK) || (lnt <= 0) || (!Q_ITS && lnt < 4096)) return SCPE_ARG; -apr_serial = lnt & 077777; -return SCPE_OK; + apr_serial = lnt & 077777; + return SCPE_OK; } /* Show serial */ t_stat cpu_show_serial (FILE *st, UNIT *uptr, int32 val, void *desc) { -fprintf (st, "Serial: " ); -if( (apr_serial == -1) || (!Q_ITS && apr_serial < 4096) ) { - fprintf (st, "%d (default)", (Q_ITS)? UC_SERITS: UC_SERDEC); - return SCPE_OK; -} -fprintf (st, "%d", apr_serial); -return SCPE_OK; + fprintf (st, "Serial: " ); + if( (apr_serial == -1) || (!Q_ITS && apr_serial < 4096) ) { + fprintf (st, "%d (default)", (Q_ITS)? UC_SERITS: UC_SERDEC); + return SCPE_OK; + } + fprintf (st, "%d", apr_serial); + return SCPE_OK; } diff --git a/PDP10/pdp10_lp20.c b/PDP10/pdp10_lp20.c index 20858e10..f27296ca 100644 --- a/PDP10/pdp10_lp20.c +++ b/PDP10/pdp10_lp20.c @@ -25,8 +25,8 @@ lp20 line printer - 29-May-13 TL Force append when an existing file is attached. Previously - over-wrote file from the top. + 29-May-13 TL Force append when an existing file is attached. + Previously over-wrote file from the top. 19-Jan-07 RMS Added UNIT_TEXT flag 04-Sep-05 RMS Fixed missing return (found by Peter Schorn) 07-Jul-05 RMS Removed extraneous externs @@ -376,17 +376,17 @@ return SCPE_OK; else if (paper) davfu_action; else print_xlate; - } + } else if (paper) { if (xlate || delim || delim_hold) davfu_action; else print_input; - } + } else { if (xlate || delim || delim_hold) print_xlate; else print_input; - } + } */ t_stat lp20_svc (UNIT *uptr) @@ -660,8 +660,8 @@ t_stat reason; reason = attach_unit (uptr, cptr); /* attach file */ if (reason == SCPE_OK) { - sim_fseek (uptr->fileref, 0, SEEK_END); - uptr->pos = ftell (uptr->fileref); + sim_fseek (uptr->fileref, 0, SEEK_END); + uptr->pos = ftell (uptr->fileref); } if (lpcsa & CSA_ONL) /* just file chg? */ return reason; From a61dec654484714264c00cc31222facd7147060f Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Wed, 29 May 2013 12:37:51 -0700 Subject: [PATCH 13/22] Add initial sharable DDCMP support --- PDP11/pdp11_ddcmp.h | 45 +++++++++++++++++++ PDP11/pdp11_dup.c | 63 ++++++++++++--------------- Visual Studio Projects/PDP10.vcproj | 4 ++ Visual Studio Projects/PDP11.vcproj | 4 ++ Visual Studio Projects/VAX730.vcproj | 4 ++ Visual Studio Projects/VAX750.vcproj | 4 ++ Visual Studio Projects/VAX780.vcproj | 4 ++ Visual Studio Projects/VAX8600.vcproj | 4 ++ 8 files changed, 98 insertions(+), 34 deletions(-) create mode 100644 PDP11/pdp11_ddcmp.h diff --git a/PDP11/pdp11_ddcmp.h b/PDP11/pdp11_ddcmp.h new file mode 100644 index 00000000..331d4f45 --- /dev/null +++ b/PDP11/pdp11_ddcmp.h @@ -0,0 +1,45 @@ +/* pdp11_ddcmp.h: Digital Data Communications Message Protocol support + + 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. + + Digital Data Communications Message Protocol - DDCMP support routines + + 29-May-13 MP Initial implementation +*/ + +#ifndef PDP11_DDCMP_H_ +#define PDP11_DDCMP_H_ 0 + +/* 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 */ + +/* Support routines */ + +void ddcmp_packet_trace (uint32 reason, DEVICE *dptr, const char *txt, const uint8 *msg, int32 len, t_bool detail); +uint16 ddcmp_crc16(uint16 crc, const void* vbuf, size_t len); + +#endif /* PDP11_DDCMP_H_ */ diff --git a/PDP11/pdp11_dup.c b/PDP11/pdp11_dup.c index 7271bdb5..c6704170 100644 --- a/PDP11/pdp11_dup.c +++ b/PDP11/pdp11_dup.c @@ -49,6 +49,7 @@ #endif #include "sim_tmxr.h" +#include "pdp11_ddcmp.h" #include #if !defined(DUP_LINES) @@ -95,7 +96,8 @@ 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); +void ddcmp_packet_trace (uint32 reason, DEVICE *dptr, const char *txt, const uint8 *msg, int32 len, t_bool detail); +uint16 ddcmp_crc16(uint16 crc, const void* vbuf, size_t len); int32 dup_rxinta (void); int32 dup_txinta (void); void dup_update_rcvi (void); @@ -110,13 +112,6 @@ t_stat dup_showspeed (FILE* st, UNIT* uptr, int32 val, 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 */ @@ -628,7 +623,7 @@ dup_rxdbuf[dup] |= dup_rcvpacket[dup][dup_rcvpkinoff[dup]++]; dup_rxcsr[dup] |= RXCSR_M_RXDONE; if (((dup_rcvpkinoff[dup] == 8) || (dup_rcvpkinoff[dup] >= dup_rcvpkoffset[dup])) && - (0 == dup_crc16 (0, dup_rcvpacket[dup], dup_rcvpkinoff[dup]))) + (0 == ddcmp_crc16 (0, dup_rcvpacket[dup], dup_rcvpkinoff[dup]))) dup_rxdbuf[dup] |= RXDBUF_M_RCRCER; else dup_rxdbuf[dup] &= ~RXDBUF_M_RCRCER; @@ -671,7 +666,7 @@ if (!(dup_txcsr[dup] & TXCSR_M_TXDONE) && (!dup_xmtpkrdy[dup])) { 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]); + uint16 crc16 = ddcmp_crc16 (0, dup_xmtpacket[dup], dup_xmtpkoffset[dup]); if (dup_xmtpkoffset[dup] + 2 > dup_xmtpksize[dup]) { dup_xmtpksize[dup] += 512; @@ -680,7 +675,7 @@ if (!(dup_txcsr[dup] & TXCSR_M_TXDONE) && (!dup_xmtpkrdy[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); + ddcmp_packet_trace (DBG_PKT, DUPDPTR, ">>> XMT Packet", dup_xmtpacket[dup], dup_xmtpkoffset[dup], TRUE); dup_xmtpkoutoff[dup] = 0; dup_xmtpkrdy[dup] = TRUE; } @@ -769,7 +764,7 @@ for (dup=active=attached=0; dup < dup_desc.lines; dup++) { } 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); + ddcmp_packet_trace (DBG_PKT, DUPDPTR, "<<< RCV Packet", dup_rcvpacket[dup], dup_rcvpkoffset[dup], TRUE); dup_rcvpkinoff[dup] = 0; dup_rcv_byte (dup); break; @@ -778,7 +773,7 @@ for (dup=active=attached=0; dup < dup_desc.lines; dup++) { int32 count = ((dup_rcvpacket[dup][2] & 0x3F) << 8)| dup_rcvpacket[dup][1]; if (dup_rcvpkoffset[dup] >= 10 + count) { - ddcmp_packet_trace (DUPDPTR, "<<< RCV Packet", dup_rcvpacket[dup], dup_rcvpkoffset[dup], TRUE); + ddcmp_packet_trace (DBG_PKT, DUPDPTR, "<<< RCV Packet", dup_rcvpacket[dup], dup_rcvpkoffset[dup], TRUE); dup_rcvpkinoff[dup] = 0; dup_rcv_byte (dup); break; @@ -808,10 +803,10 @@ return SCPE_OK; /* Debug routines */ -void ddcmp_packet_trace (DEVICE *dptr, const char *txt, const uint8 *msg, int32 len, t_bool detail) +void ddcmp_packet_trace (uint32 reason, 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 (sim_deb && dptr && (reason & dptr->dctrl)) { + sim_debug(reason, dptr, "%s len: %d\n", txt, len); if (detail) { int i, same, group, sidx, oidx; char outbuf[80], strbuf[18]; @@ -819,39 +814,39 @@ if (sim_deb && dptr && (DBG_PKT & dptr->dctrl)) { 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[2]>>6, ((msg[2] & 0x3F) << 8)|msg[1], msg[3], msg[4], - (0 == dup_crc16 (0, msg, 8)) ? "OK" : "BAD", (0 == dup_crc16 (0, msg+8, 2+(((msg[2] & 0x3F) << 8)|msg[1]))) ? "OK" : "BAD"); + sim_debug (reason, dptr, "Data Message, Link: %d, Count: %d, Resp: %d, Num: %d, HDRCRC: %s, DATACRC: %s\n", msg[2]>>6, ((msg[2] & 0x3F) << 8)|msg[1], msg[3], msg[4], + (0 == ddcmp_crc16 (0, msg, 8)) ? "OK" : "BAD", (0 == ddcmp_crc16 (0, msg+8, 2+(((msg[2] & 0x3F) << 8)|msg[1]))) ? "OK" : "BAD"); break; case DDCMP_ENQ: /* Control Message */ - sim_debug (DBG_PKT, dptr, "Control: Type: %d ", msg[1]); + sim_debug (reason, dptr, "Control: Type: %d ", msg[1]); switch (msg[1]) { case 1: /* ACK */ - sim_debug (DBG_PKT, dptr, "(ACK) ACKSUB: %d, Link: %d, Resp: %d\n", msg[2] & 0x3F, msg[2]>>6, msg[3]); + sim_debug (reason, dptr, "(ACK) ACKSUB: %d, Link: %d, Resp: %d\n", msg[2] & 0x3F, 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]); + sim_debug (reason, 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) REPSUB: %d, Link: %d, Num: %d\n", msg[2] & 0x3F, msg[2]>>6, msg[4]); + sim_debug (reason, dptr, "(REP) REPSUB: %d, Link: %d, Num: %d\n", msg[2] & 0x3F, msg[2]>>6, msg[4]); break; case 6: /* STRT */ - sim_debug (DBG_PKT, dptr, "(STRT) STRTSUB: %d, Link: %d\n", msg[2] & 0x3F, msg[2]>>6); + sim_debug (reason, dptr, "(STRT) STRTSUB: %d, Link: %d\n", msg[2] & 0x3F, msg[2]>>6); break; case 7: /* STACK */ - sim_debug (DBG_PKT, dptr, "(STACK) STCKSUB: %d, Link: %d\n", msg[2] & 0x3F, msg[2]>>6); + sim_debug (reason, dptr, "(STACK) STCKSUB: %d, Link: %d\n", msg[2] & 0x3F, msg[2]>>6); break; default: /* Unknown */ - sim_debug (DBG_PKT, dptr, "(Unknown=0%o)\n", msg[1]); + sim_debug (reason, 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"); + sim_debug (reason, dptr, "Unexpected Control Message Length: %d expected 8\n", len); + if (0 != ddcmp_crc16 (0, msg, len)) + sim_debug (reason, 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[2]>>6, ((msg[2] & 0x3F) << 8)| msg[1], - (0 == dup_crc16 (0, msg, 8)) ? "OK" : "BAD", (0 == dup_crc16 (0, msg+8, 2+(((msg[2] & 0x3F) << 8)| msg[1]))) ? "OK" : "BAD"); + sim_debug (reason, dptr, "Maintenance Message, Link: %d, Count: %d, HDRCRC: %s, DATACRC: %s\n", msg[2]>>6, ((msg[2] & 0x3F) << 8)| msg[1], + (0 == ddcmp_crc16 (0, msg, 8)) ? "OK" : "BAD", (0 == ddcmp_crc16 (0, msg+8, 2+(((msg[2] & 0x3F) << 8)| msg[1]))) ? "OK" : "BAD"); break; } for (i=same=0; idctrl)) { continue; } if (same > 0) { - sim_debug(DBG_PKT, dptr, "%04X thru %04X same as above\n", i-(16*same), i-1); + sim_debug(reason, dptr, "%04X thru %04X same as above\n", i-(16*same), i-1); same = 0; } group = (((len - i) > 16) ? 16 : (len - i)); @@ -875,10 +870,10 @@ if (sim_deb && dptr && (DBG_PKT & dptr->dctrl)) { } outbuf[oidx] = '\0'; strbuf[sidx] = '\0'; - sim_debug(DBG_PKT, dptr, "%04X%-48s %s\n", i, outbuf, strbuf); + sim_debug(reason, 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); + sim_debug(reason, dptr, "%04X thru %04X same as above\n", i-(16*same), len-1); } } } @@ -1170,7 +1165,7 @@ static uint16 crc16_nibble[16] = { 0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400, }; -static uint16 dup_crc16(uint16 crc, const void* vbuf, size_t len) +uint16 ddcmp_crc16(uint16 crc, const void* vbuf, size_t len) { const unsigned char* buf = (const unsigned char*)vbuf; diff --git a/Visual Studio Projects/PDP10.vcproj b/Visual Studio Projects/PDP10.vcproj index d00bff38..00c05465 100644 --- a/Visual Studio Projects/PDP10.vcproj +++ b/Visual Studio Projects/PDP10.vcproj @@ -304,6 +304,10 @@ RelativePath="..\PDP10\pdp10_defs.h" > + + diff --git a/Visual Studio Projects/PDP11.vcproj b/Visual Studio Projects/PDP11.vcproj index de099266..fc04e0f1 100644 --- a/Visual Studio Projects/PDP11.vcproj +++ b/Visual Studio Projects/PDP11.vcproj @@ -416,6 +416,10 @@ RelativePath="..\PDP11\pdp11_cr_dat.h" > + + diff --git a/Visual Studio Projects/VAX730.vcproj b/Visual Studio Projects/VAX730.vcproj index 3f076350..b876604d 100644 --- a/Visual Studio Projects/VAX730.vcproj +++ b/Visual Studio Projects/VAX730.vcproj @@ -383,6 +383,10 @@ RelativePath="..\dec_dz.h" > + + diff --git a/Visual Studio Projects/VAX750.vcproj b/Visual Studio Projects/VAX750.vcproj index 6a4bd62e..491836cf 100644 --- a/Visual Studio Projects/VAX750.vcproj +++ b/Visual Studio Projects/VAX750.vcproj @@ -391,6 +391,10 @@ RelativePath="..\dec_dz.h" > + + diff --git a/Visual Studio Projects/VAX780.vcproj b/Visual Studio Projects/VAX780.vcproj index 04137a58..7d38ef3f 100644 --- a/Visual Studio Projects/VAX780.vcproj +++ b/Visual Studio Projects/VAX780.vcproj @@ -403,6 +403,10 @@ RelativePath="..\PDP11\pdp11_cr_dat.h" > + + diff --git a/Visual Studio Projects/VAX8600.vcproj b/Visual Studio Projects/VAX8600.vcproj index 23fe4f99..73afff04 100644 --- a/Visual Studio Projects/VAX8600.vcproj +++ b/Visual Studio Projects/VAX8600.vcproj @@ -395,6 +395,10 @@ Name="Header Files" Filter="h;hpp;hxx;hm;inl;inc" > + + From 1c7bf986106b764533df61274e576d6397ba721d Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Wed, 29 May 2013 12:39:20 -0700 Subject: [PATCH 14/22] Cleaned up readme documentation to avoid potential confusion when initially setting up a windows build environment. --- README.md | 6 +++--- Visual Studio Projects/0ReadMe_Projects.txt | 19 +++++++++++++++---- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index ba743650..d0b6c1e0 100644 --- a/README.md +++ b/README.md @@ -276,15 +276,15 @@ See the 0readme_ethernet.txt file for details about the required network compone Compiling on windows is supported with recent versions of Microsoft Visual Studio (Standard or Express) and using GCC via the MinGW environment. Things may also work under Cygwin, but that is not the preferred windows environment. Not all features will be available as well as with either Visual Studio or MinGW. -##### Required related files. The file https://github.com/simh/simh/master/Visual%20Studio%20Projects/0ReadMe_Projects.txt +##### Required related files. The file https://github.com/simh/simh/blob/master/Visual%20Studio%20Projects/0ReadMe_Projects.txt ##### Visual Studio (Standard or Express) 2008, 2010 or 2012 -The file https://github.com/simh/simh/master/Visual%20Studio%20Projects/0ReadMe_Projects.txt describes the required steps to use the setup your environment to build using Visual Studio. +The file https://github.com/simh/simh/blob/master/Visual%20Studio%20Projects/0ReadMe_Projects.txt describes the required steps to use the setup your environment to build using Visual Studio. ##### MinGW -The file https://github.com/simh/simh/master/Visual%20Studio%20Projects/0ReadMe_Projects.txt describes the required steps to use the setup your environment to build using MinGW. +The file https://github.com/simh/simh/blob/master/Visual%20Studio%20Projects/0ReadMe_Projects.txt describes the required steps to use the setup your environment to build using MinGW. #### VMS diff --git a/Visual Studio Projects/0ReadMe_Projects.txt b/Visual Studio Projects/0ReadMe_Projects.txt index 9961d138..24445549 100644 --- a/Visual Studio Projects/0ReadMe_Projects.txt +++ b/Visual Studio Projects/0ReadMe_Projects.txt @@ -23,18 +23,29 @@ The contents of the windows-build directory can be downloaded from: https://github.com/simh/windows-build/archive/windows-build.zip +Download and extract the contents of this zip file into the appropriate +place in your directory structure. You do not need to do anything else +but have this directory properly located. Network devices are capable of using pthreads to enhance their performance. To realize these benefits, you must build the desire simulator with USE_READER_THREAD defined. The relevant simulators which have network -support are VAX, VAX780 and PDP11. +support are all of the VAX simulators and the PDP11 simulator. Additionally, simulators which contain devices which use the asynchronous APIs in sim_disk.c and sim_tape.c can also achieve greater performance by leveraging pthreads to perform blocking I/O in separate threads. Currently -the simulators which have such devices are VAX, VAX780 and PDP11. To -achieve these benefits the simulators must be built with SIM_ASYNCH_IO -defined. +the simulators which have such devices are all of the VAX simulators and +the PDP11. To achieve these benefits the simulators must be built with +SIM_ASYNCH_IO defined. The project files in this directory build these simulators with support for both network and asynchronous I/O. + +To build any of the supported simulators you should open the simh.sln file +in this directory. + +If you are using a version of Visual Studio beyond Visual Studio 2008, then +your later version of Visual Studio will automatically convert the Visual +Studio 2008 project fils. You should ignore any warnings produced by the +conversion process. From 39c794292d8c03dbd6bdcf923bb74600b07b02ea Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Wed, 29 May 2013 12:48:19 -0700 Subject: [PATCH 15/22] Changed some spaces and indentations --- PDP10/pdp10_cpu.c | 37 +++++++++++++++++++------------------ PDP10/pdp10_lp20.c | 12 ++++++------ 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/PDP10/pdp10_cpu.c b/PDP10/pdp10_cpu.c index 03af6947..4a66f701 100644 --- a/PDP10/pdp10_cpu.c +++ b/PDP10/pdp10_cpu.c @@ -2109,14 +2109,15 @@ return; t_bool aprid (a10 ea, int32 prv) { - d10 value = (Q_ITS)? UC_AIDITS: UC_AIDDEC; - if( (apr_serial == -1) || (!Q_ITS && apr_serial < 4096) ) +d10 value = (Q_ITS)? UC_AIDITS: UC_AIDDEC; + +if( (apr_serial == -1) || (!Q_ITS && apr_serial < 4096) ) value |= (Q_ITS)? UC_SERITS: UC_SERDEC; - else +else value |= apr_serial; - Write (ea, value, prv); - return FALSE; +Write (ea, value, prv); +return FALSE; } /* Checked against KS10 ucode */ @@ -2435,29 +2436,29 @@ return SCPE_OK; t_stat cpu_set_serial (UNIT *uptr, int32 val, char *cptr, void *desc) { - int32 lnt; - t_stat r; +int32 lnt; +t_stat r; - if (cptr == NULL) { +if (cptr == NULL) { apr_serial = -1; return SCPE_OK; - } - lnt = (int32) get_uint (cptr, 10, 077777, &r); - if ((r != SCPE_OK) || (lnt <= 0) || (!Q_ITS && lnt < 4096)) + } +lnt = (int32) get_uint (cptr, 10, 077777, &r); +if ((r != SCPE_OK) || (lnt <= 0) || (!Q_ITS && lnt < 4096)) return SCPE_ARG; - apr_serial = lnt & 077777; - return SCPE_OK; +apr_serial = lnt & 077777; +return SCPE_OK; } /* Show serial */ t_stat cpu_show_serial (FILE *st, UNIT *uptr, int32 val, void *desc) { - fprintf (st, "Serial: " ); - if( (apr_serial == -1) || (!Q_ITS && apr_serial < 4096) ) { +fprintf (st, "Serial: " ); +if( (apr_serial == -1) || (!Q_ITS && apr_serial < 4096) ) { fprintf (st, "%d (default)", (Q_ITS)? UC_SERITS: UC_SERDEC); return SCPE_OK; - } - fprintf (st, "%d", apr_serial); - return SCPE_OK; + } +fprintf (st, "%d", apr_serial); +return SCPE_OK; } diff --git a/PDP10/pdp10_lp20.c b/PDP10/pdp10_lp20.c index f27296ca..d8122f01 100644 --- a/PDP10/pdp10_lp20.c +++ b/PDP10/pdp10_lp20.c @@ -376,17 +376,17 @@ return SCPE_OK; else if (paper) davfu_action; else print_xlate; - } + } else if (paper) { if (xlate || delim || delim_hold) davfu_action; else print_input; - } + } else { if (xlate || delim || delim_hold) print_xlate; else print_input; - } + } */ t_stat lp20_svc (UNIT *uptr) @@ -660,9 +660,9 @@ t_stat reason; reason = attach_unit (uptr, cptr); /* attach file */ if (reason == SCPE_OK) { - sim_fseek (uptr->fileref, 0, SEEK_END); - uptr->pos = ftell (uptr->fileref); -} + sim_fseek (uptr->fileref, 0, SEEK_END); + uptr->pos = sim_ftell (uptr->fileref); + } if (lpcsa & CSA_ONL) /* just file chg? */ return reason; if (sim_is_active (&lp20_unit)) /* busy? no int */ From bc49f6b78ac8fc51be5268c3340c076b572e3c68 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Fri, 31 May 2013 04:16:42 -0700 Subject: [PATCH 16/22] Fix for Unibus word DMA from Rob Jarratt --- PDP10/pdp10_ksio.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/PDP10/pdp10_ksio.c b/PDP10/pdp10_ksio.c index c8d14de4..4d7478ec 100644 --- a/PDP10/pdp10_ksio.c +++ b/PDP10/pdp10_ksio.c @@ -512,7 +512,7 @@ d10 val; ba = ba & ~01; /* align start */ lim = ba + (bc & ~01); -for ( ; ba < lim; ba++) { /* by bytes */ +for ( ; ba < lim; ba += 2) { /* by bytes */ pa10 = Map_Addr10 (ba, 1); /* map addr */ if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */ ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA times out */ @@ -520,8 +520,8 @@ for ( ; ba < lim; ba++) { /* by bytes */ } val = *buf++; /* get data */ if (ba & 2) - M[pa10] = (M[pa10] & INT64_C(0777777600000)) | val; - else M[pa10] = (M[pa10] & INT64_C(0600000777777)) | (val << 18); + M[pa10] = (M[pa10] & INT64_C(0777777000000)) | val; + else M[pa10] = (M[pa10] & INT64_C(0000000777777)) | (val << 18); } return 0; } @@ -961,8 +961,6 @@ 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 */ From 881f53e4577e6824c10722fd64e2f69c1b943956 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Fri, 31 May 2013 09:33:05 -0700 Subject: [PATCH 17/22] Added support to the Remote Console facility to close a remote console session on EOF --- README.md | 2 ++ doc/simh_doc.doc | Bin 196608 -> 177664 bytes sim_console.c | 44 +++++++++++++++++++++++++++++++++++++------- 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index d0b6c1e0..9047c52d 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,8 @@ A subset of normal simh commands are available for use in remote console session The Single Command Mode commands are: ATTACH, DETACH, PWD, SHOW, DIR, LS, ECHO, HELP The Multiple Command Mode commands are: EXAMINE, IEXAMINE, DEPOSIT, EVALUATE, ATTACH, DETACH, ASSIGN, DEASSIGN, STEP, CONTINUE, PWD, SAVE, SET, SHOW, DIR, LS, ECHO, HELP +A remote console session will close when an EOF character is entered (i.e. ^D or ^Z). + #### VAX/PDP11 Enhancements RQ has new disk types: RC25, RCF25, RA80 RQ device has a settable controller type (RQDX3, UDA50, KLESI, RUX50) diff --git a/doc/simh_doc.doc b/doc/simh_doc.doc index 02cec35ba569e91ce2d84d30f9d6b38c1e6ca14c..ad8c08104ae20a51b0358bdd18327aa8ab1133ac 100644 GIT binary patch delta 28481 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

1RNFdt8z{FN;E3$3LS`a+X)1n(1;2W*r+K;t0n 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

#&TnOG})(Z;L}(EFEjIi6vse=w%k#8NA*Tpg3 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 A=Kufz diff --git a/sim_console.c b/sim_console.c index 6f072a3d..2fe37942 100644 --- a/sim_console.c +++ b/sim_console.c @@ -518,6 +518,7 @@ t_bool stepping = FALSE; int32 steps = 1; t_bool was_stepping = (sim_rem_step_line != -1); t_bool got_command; +t_bool close_session = FALSE; TMLN *lp; char cbuf[4*CBUFSIZE], gbuf[CBUFSIZE], *cptr, *argv[1] = {NULL}; CTAB *cmdp; @@ -535,15 +536,15 @@ for (i=(was_stepping ? sim_rem_step_line : 0); sim_rem_step_line = -1; /* Done with step */ stat = SCPE_STEP; cmdp = find_cmd ("STEP"); - stat_nomessage = stat & SCPE_NOMESSAGE; /* extract possible message supression flag */ - stat = SCPE_BARE_STATUS(stat); /* remove possible flag */ - if (!stat_nomessage) { /* displaying message status? */ + stat_nomessage = stat & SCPE_NOMESSAGE; /* extract possible message supression flag */ + stat = SCPE_BARE_STATUS(stat); /* remove possible flag */ + if (!stat_nomessage) { /* displaying message status? */ fflush (sim_log); cmd_log_start = sim_ftell (sim_log); - if (cmdp && (cmdp->message)) /* special message handler? */ - cmdp->message (NULL, stat); /* let it deal with display */ + if (cmdp && (cmdp->message)) /* special message handler? */ + cmdp->message (NULL, stat); /* let it deal with display */ else - if (stat >= SCPE_BASE) { /* error? */ + if (stat >= SCPE_BASE) { /* error? */ printf ("%s\r\n", sim_error_text (stat)); if (sim_log) fprintf (sim_log, "%s\n", sim_error_text (stat)); @@ -579,6 +580,12 @@ for (i=(was_stepping ? sim_rem_step_line : 0); tmxr_linemsgf (lp, "Simulation will resume automatically if input is not received in %d seconds\n", sim_rem_read_timeout); } else { + if ((c == '\004') || (c == '\032')) { /* EOF character (^D or ^Z) ? */ + tmxr_linemsgf (lp, "\r\nGoodbye\r\n"); + tmxr_send_buffered_data (lp); /* flush any buffered data */ + tmxr_reset_ln (lp); + continue; + } sim_rem_single_mode[i] = TRUE; tmxr_linemsgf (lp, "\r\n%s", sim_prompt); tmxr_send_buffered_data (lp); /* flush any buffered data */ @@ -648,6 +655,23 @@ for (i=(was_stepping ? sim_rem_step_line : 0); sim_rem_buf[i][sim_rem_buf_ptr[i]++] = '\0'; got_command = TRUE; break; + case '\004': /* EOF (^D) */ + case '\032': /* EOF (^Z) */ + while (sim_rem_buf_ptr[i] > 0) { /* Erase current input line */ + tmxr_linemsg (lp, "\b \b"); + --sim_rem_buf_ptr[i]; + } + if (!sim_rem_single_mode[i]) { + if (sim_rem_buf_ptr[i]+80 >= sim_rem_buf_size[i]) { + sim_rem_buf_size[i] += 1024; + sim_rem_buf[i] = realloc (sim_rem_buf[i], sim_rem_buf_size[i]); + } + strcpy (sim_rem_buf[i], "CONTINUE ! Automatic continue before close"); + tmxr_linemsgf (lp, "%s\n", sim_rem_buf[i]); + got_command = TRUE; + } + close_session = TRUE; + break; default: tmxr_putc_ln (lp, c); if (sim_rem_buf_ptr[i]+2 >= sim_rem_buf_size[i]) { @@ -662,8 +686,9 @@ for (i=(was_stepping ? sim_rem_step_line : 0); } } while ((!got_command) && (!sim_rem_single_mode[i])); tmxr_send_buffered_data (lp); /* flush any buffered data */ - if ((sim_rem_single_mode[i]) && !got_command) + if ((sim_rem_single_mode[i]) && !got_command) { break; + } printf ("Remote Console Command from %s> %s\r\n", lp->ipad, sim_rem_buf[i]); if (sim_log) fprintf (sim_log, "Remote Console Command from %s> %s\n", lp->ipad, sim_rem_buf[i]); @@ -790,6 +815,11 @@ for (i=(was_stepping ? sim_rem_step_line : 0); break; } } + if (close_session) { + tmxr_linemsgf (lp, "\r\nGoodbye\r\n"); + tmxr_send_buffered_data (lp); /* flush any buffered data */ + tmxr_reset_ln (lp); + } } if (stepping) sim_activate(uptr, steps); /* check again after 'steps' instructions */ From 4d34547b053aead7e90e541b9c8b4cb83732d746 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Fri, 31 May 2013 11:58:09 -0700 Subject: [PATCH 18/22] Cleanup DUP11 implementation and refactor for shared use by another device (KMC11). --- PDP11/pdp11_ddcmp.h | 8 +-- PDP11/pdp11_dup.c | 129 ++++++++++++++++++++++++++++++++------------ PDP11/pdp11_dup.h | 47 ++++++++++++++++ sim_tmxr.c | 2 +- 4 files changed, 148 insertions(+), 38 deletions(-) create mode 100644 PDP11/pdp11_dup.h diff --git a/PDP11/pdp11_ddcmp.h b/PDP11/pdp11_ddcmp.h index 331d4f45..8d6e8d44 100644 --- a/PDP11/pdp11_ddcmp.h +++ b/PDP11/pdp11_ddcmp.h @@ -33,9 +33,11 @@ /* 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 */ +#define DDCMP_SYN 0226u /* Sync character on synchronous links */ +#define DDCMP_DEL 0377u /* Sync character on asynchronous links */ +#define DDCMP_SOH 0201u /* Numbered Data Message Identifier */ +#define DDCMP_ENQ 0005u /* Control Message Identifier */ +#define DDCMP_DLE 0220u /* Maintenance Message Identifier */ /* Support routines */ diff --git a/PDP11/pdp11_dup.c b/PDP11/pdp11_dup.c index c6704170..9fe3b644 100644 --- a/PDP11/pdp11_dup.c +++ b/PDP11/pdp11_dup.c @@ -50,6 +50,7 @@ #include "sim_tmxr.h" #include "pdp11_ddcmp.h" +#include "pdp11_dup.h" #include #if !defined(DUP_LINES) @@ -84,6 +85,8 @@ 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 */ +PACKET_RECEIVE_CALLBACK dup_rcv_packet_callback[DUP_LINES]; +PACKET_TRANSMIT_COMPLETE_CALLBACK dup_xmt_complete_callback[DUP_LINES]; t_stat dup_rd (int32 *data, int32 PA, int32 access); t_stat dup_wr (int32 data, int32 PA, int32 access); @@ -341,7 +344,8 @@ REG dup_reg[] = { { BRDATADF (TXDBUF, dup_txdbuf, DEV_RDX, 16, DUP_LINES, "transmit data buffer", dup_txdbuf_bits) }, { GRDATAD (RXINT, dup_rxi, DEV_RDX, DUP_LINES, 0, "receive interrupts") }, { GRDATAD (TXINT, dup_txi, DEV_RDX, DUP_LINES, 0, "transmit interrupts") }, - { BRDATAD (RXWAIT, dup_wait, 10, 24, DUP_LINES, "delay time for transmit/receive bytes") }, + { BRDATAD (WAIT, dup_wait, 10, 32, DUP_LINES, "delay time for transmit/receive bytes"), PV_RSPC }, + { BRDATAD (SPEED, dup_speed, 10, 32, DUP_LINES, "line bit rate"), PV_RCOMMA }, { BRDATAD (RPOFFSET, dup_rcvpkoffset, DEV_RDX, 16, DUP_LINES, "receive assembly packet offset") }, { BRDATAD (TPOFFSET, dup_xmtpkoffset, DEV_RDX, 16, DUP_LINES, "transmit assembly packet offset") }, { BRDATAD (RPINOFF, dup_rcvpkinoff, DEV_RDX, 16, DUP_LINES, "receive digest packet offset") }, @@ -503,6 +507,11 @@ if (dup >= dup_desc.lines) /* validate line number return SCPE_IERR; orig_val = regs[(PA >> 1) & 03][dup]; +if (PA & 1) /* unaligned byte access? */ + data = ((data << 8) & (orig_val & 0xFF)) & 0xFFFF; /* Merge with original word */ +else + if (access == WRITEB) /* byte access? */ + data = (orig_val & 0xFF00) | (data & 0xFF); /* Merge with original high word */ switch ((PA >> 1) & 03) { /* case on PA<2:1> */ @@ -529,11 +538,16 @@ switch ((PA >> 1) & 03) { /* case on PA<2:1> */ } if ((!(dup_rxcsr[dup] & RXCSR_M_RCVEN)) && (orig_val & RXCSR_M_RCVEN)) { /* Downward transition of receiver enable */ - dup_rxcsr[dup] &= ~RXCSR_M_RXDONE; + dup_rxcsr[dup] &= ~(RXCSR_M_RXDONE|RXCSR_M_RXACT); if ((dup_rcvpkinoff[dup] != 0) || (dup_rcvpkoffset[dup] != 0)) dup_rcvpkinoff[dup] = dup_rcvpkoffset[dup] = 0; } + 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)) + dup_set_rxint (dup); break; case 01: /* PARCSR */ @@ -609,13 +623,40 @@ if ((dup_rxcsr[dup] & RXCSR_M_DSCHNG) && return SCPE_OK; } +int32 dup_csr_to_linenum (int32 CSRPA) +{ +DEVICE *dptr = DUPDPTR; +DIB *dib = (DIB *)dptr->ctxt; + +if ((dib->ba > (uint32)CSRPA) || ((uint32)CSRPA > (dib->ba + dib->lnt))) + return -1; + +return ((uint32)CSRPA - dib->ba)/dib->lnt; +} + +void dup_set_callback_mode (int32 dup, PACKET_RECEIVE_CALLBACK receive, PACKET_TRANSMIT_COMPLETE_CALLBACK transmit) +{ +dup_rcv_packet_callback[dup] = receive; +dup_xmt_complete_callback[dup] = transmit; +} + +int32 dup_get_line_speed (int32 dup) +{ +return dup_speed[dup]; +} + + t_stat dup_rcv_byte (int32 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_rcvpkoffset[dup]); -if (!(dup_rxcsr[dup] & RXCSR_M_RCVEN) || (dup_rcvpkoffset[dup] == 0)) +if (!(dup_rxcsr[dup] & RXCSR_M_RCVEN) || (dup_rcvpkoffset[dup] == 0) || (dup_rxcsr[dup] & RXCSR_M_RXDONE)) return SCPE_OK; +if (dup_rcv_packet_callback[dup]) { + dup_rcv_packet_callback[dup](dup, dup_rcvpacket[dup], dup_rcvpkoffset[dup]); + return SCPE_OK; + } dup_rxcsr[dup] |= RXCSR_M_RXACT; dup_rxdbuf[dup] &= ~RXDBUF_M_RCRCER; dup_rxdbuf[dup] &= ~RXDBUF_M_RXDBUF; @@ -636,6 +677,45 @@ if (dup_rxcsr[dup] & RXCSR_M_RXIE) return SCPE_OK; } +t_bool dup_put_msg_bytes (int32 dup, uint8 *bytes, size_t len, t_bool start, t_bool end) +{ +t_bool breturn = FALSE; + +if (!dup_xmtpkrdy[dup]) { /* Not Busy sending? */ + if (start) + dup_xmtpkoffset[dup] = 0; + if (dup_xmtpkoffset[dup] + 2 + len > dup_xmtpksize[dup]) { + dup_xmtpksize[dup] += 2 + len; + dup_xmtpacket[dup] = realloc (dup_xmtpacket[dup], dup_xmtpksize[dup]); + } + /* Strip sync bytes at the beginning of a message */ + while (len && (dup_xmtpkoffset[dup] == 0) && (bytes[0] == DDCMP_SYN)) { + --len; + ++bytes; + } + /* Insert remaining bytes into transmit buffer */ + if (len) { + memcpy (&dup_xmtpacket[dup][dup_xmtpkoffset[dup]], bytes, len); + dup_xmtpkoffset[dup] += len; + } + dup_txcsr[dup] |= TXCSR_M_TXDONE; + if (dup_txcsr[dup] & TXCSR_M_TXIE) + dup_set_txint (dup); + /* On End of Message, insert CRC and flag delivery start */ + if (end) { + uint16 crc16 = ddcmp_crc16 (0, dup_xmtpacket[dup], dup_xmtpkoffset[dup]); + + dup_xmtpacket[dup][dup_xmtpkoffset[dup]++] = crc16 & 0xFF; + dup_xmtpacket[dup][dup_xmtpkoffset[dup]++] = crc16 >> 8; + dup_xmtpkoutoff[dup] = 0; + dup_xmtpkrdy[dup] = TRUE; + } + breturn = TRUE; + } +sim_debug (DBG_TRC, DUPDPTR, "dup_put_msg_bytes(dup=%d, len=%d, start=%s, end=%s) %s\n", + dup, len, start ? "TRUE" : "FALSE", end ? "TRUE" : "FALSE", breturn ? "Good" : "Busy"); +return breturn; +} /* service routine to delay device activity */ t_stat dup_svc (UNIT *uptr) @@ -646,38 +726,12 @@ TMLN *lp = &dup_desc.ldsc[dup]; sim_debug(DBG_TRC, DUPDPTR, "dup_svc(dup=%d)\n", dup); if (!(dup_txcsr[dup] & TXCSR_M_TXDONE) && (!dup_xmtpkrdy[dup])) { - 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 = ddcmp_crc16 (0, dup_xmtpacket[dup], dup_xmtpkoffset[dup]); + uint8 data = dup_txdbuf[dup] & TXDBUF_M_TXDBUF; - 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; + dup_put_msg_bytes (dup, &data, (dup_txdbuf[dup] & TXDBUF_M_TEOM) ? 0 : 1, dup_txdbuf[dup] & TXDBUF_M_TSOM, (dup_txdbuf[dup] & TXDBUF_M_TEOM)); + if (dup_xmtpkrdy[dup]) { /* Packet ready to send? */ sim_debug(DBG_TRC, DUPDPTR, "dup_svc(dup=%d) - Packet Done %d bytes\n", dup, dup_xmtpkoffset[dup]); ddcmp_packet_trace (DBG_PKT, DUPDPTR, ">>> XMT Packet", dup_xmtpacket[dup], dup_xmtpkoffset[dup], TRUE); - dup_xmtpkoutoff[dup] = 0; - dup_xmtpkrdy[dup] = TRUE; } } if (dup_xmtpkrdy[dup] && lp->xmte) { @@ -692,17 +746,22 @@ if (dup_xmtpkrdy[dup] && lp->xmte) { if (st == SCPE_LOST) { /* line state transition? */ dup_get_modem (dup); dup_xmtpkrdy[dup] = FALSE; + dup_xmtpkoffset[dup] = 0; } else if (st == SCPE_OK) { sim_debug(DBG_PKT, DUPDPTR, "dup_svc(dup=%d) - %d byte packet transmission complete\n", dup, dup_xmtpkoutoff[dup]); dup_xmtpkrdy[dup] = FALSE; + dup_xmtpkoffset[dup] = 0; } else { sim_debug(DBG_PKT, DUPDPTR, "dup_svc(dup=%d) - Packet Transmission Stalled with %d bytes remaining\n", dup, (int)(dup_xmtpkoffset[dup]-dup_xmtpkoutoff[dup])); } - if (!dup_xmtpkrdy[dup]) - dup_txcsr[dup] &= ~TXCSR_M_TXACT; + if (!dup_xmtpkrdy[dup]) { /* Done transmitting? */ + dup_txcsr[dup] &= ~TXCSR_M_TXACT; /* Set idle */ + if (dup_xmt_complete_callback[dup]) + dup_xmt_complete_callback[dup](dup, (dup_rxcsr[dup] & RXCSR_M_DCD) ? 0 : 1); + } } if (dup_rxcsr[dup] & RXCSR_M_RXACT) dup_rcv_byte (dup); @@ -766,6 +825,7 @@ for (dup=active=attached=0; dup < dup_desc.lines; dup++) { if (dup_rcvpacket[dup][0] == DDCMP_ENQ) { /* Control Message? */ ddcmp_packet_trace (DBG_PKT, DUPDPTR, "<<< RCV Packet", dup_rcvpacket[dup], dup_rcvpkoffset[dup], TRUE); dup_rcvpkinoff[dup] = 0; + dup_rxcsr[dup] |= RXCSR_M_RXACT; dup_rcv_byte (dup); break; } @@ -775,6 +835,7 @@ for (dup=active=attached=0; dup < dup_desc.lines; dup++) { if (dup_rcvpkoffset[dup] >= 10 + count) { ddcmp_packet_trace (DBG_PKT, DUPDPTR, "<<< RCV Packet", dup_rcvpacket[dup], dup_rcvpkoffset[dup], TRUE); dup_rcvpkinoff[dup] = 0; + dup_rxcsr[dup] |= RXCSR_M_RXACT; dup_rcv_byte (dup); break; } diff --git a/PDP11/pdp11_dup.h b/PDP11/pdp11_dup.h new file mode 100644 index 00000000..1d7e4f66 --- /dev/null +++ b/PDP11/pdp11_dup.h @@ -0,0 +1,47 @@ +/* pdp11_dup.h: PDP-11 DUP11 bit synchronous shared device packet interface 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 describes the interfaces exposed by the dup device for use by + a packet delivery devices (i.e. KMC11). + + 31-May-13 MP Initial implementation +*/ + +#ifndef PDP11_DUP_H_ +#define PDP11_DUP_H_ 0 + +typedef void (*PACKET_RECEIVE_CALLBACK)(int32 dup, uint8 *buf, size_t len); +typedef void (*PACKET_TRANSMIT_COMPLETE_CALLBACK)(int32 dup, int status); + +int32 dup_get_line_speed (int32 dup); +int32 dup_csr_to_linenum (int32 CSRPA); + +void dup_set_callback_mode (int32 dup, PACKET_RECEIVE_CALLBACK receive, PACKET_TRANSMIT_COMPLETE_CALLBACK transmit); + +t_bool dup_put_msg_bytes (int32 dup, uint8 *bytes, size_t len, t_bool start, t_bool end); + +#endif /* PDP11_DUP_H_ */ \ No newline at end of file diff --git a/sim_tmxr.c b/sim_tmxr.c index ae618ab8..c0a06ac7 100644 --- a/sim_tmxr.c +++ b/sim_tmxr.c @@ -444,7 +444,7 @@ if (lp->modem_control) { lp->modembits &= ~TMXR_MDM_INCOMING; lp->modembits |= TMXR_MDM_CTS | TMXR_MDM_DSR; } -if (!lp->mp->buffered) { +if ((!lp->mp->buffered) && (!lp->txbfd)) { lp->txbfd = 0; lp->txbsz = TMXR_MAXBUF; lp->txb = (char *)realloc (lp->txb, lp->txbsz); From e5ee32d4116680421ccc5c5810e28dada32e8359 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Fri, 31 May 2013 17:18:46 -0700 Subject: [PATCH 19/22] Fix network build on OSX when libvdeplug is available. --- makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/makefile b/makefile index 0557002b..b7d0e7a9 100644 --- a/makefile +++ b/makefile @@ -399,7 +399,11 @@ ifeq ($(WIN32),) #*nix Environments (&& cygwin) ifneq (,$(call find_include,libvdeplug)) # Provide support for vde networking NETWORK_CCDEFS += -DUSE_VDE_NETWORK - NETWORK_LDFLAGS += -lvdeplug -Wl,-R,$(dir $(call find_lib,vdeplug)) -L$(dir $(call find_lib,vdeplug)) + ifeq (Darwin,$(OSTYPE)) + NETWORK_LDFLAGS += -lvdeplug -L$(dir $(call find_lib,vdeplug)) + else + NETWORK_LDFLAGS += -lvdeplug -Wl,-R,$(dir $(call find_lib,vdeplug)) -L$(dir $(call find_lib,vdeplug)) + endif $(info using libvdeplug: $(call find_lib,vdeplug) $(call find_include,libvdeplug)) endif endif From 486ef585951f37944ade8c44f74274cdc550165d Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Sat, 1 Jun 2013 23:04:45 -0700 Subject: [PATCH 20/22] Compiler warning cleanup --- PDP11/pdp11_dup.c | 8 +++++--- scp.c | 3 ++- sim_console.c | 3 ++- sim_tmxr.c | 3 ++- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/PDP11/pdp11_dup.c b/PDP11/pdp11_dup.c index 9fe3b644..cf961ee6 100644 --- a/PDP11/pdp11_dup.c +++ b/PDP11/pdp11_dup.c @@ -728,7 +728,7 @@ sim_debug(DBG_TRC, DUPDPTR, "dup_svc(dup=%d)\n", dup); if (!(dup_txcsr[dup] & TXCSR_M_TXDONE) && (!dup_xmtpkrdy[dup])) { uint8 data = dup_txdbuf[dup] & TXDBUF_M_TXDBUF; - dup_put_msg_bytes (dup, &data, (dup_txdbuf[dup] & TXDBUF_M_TEOM) ? 0 : 1, dup_txdbuf[dup] & TXDBUF_M_TSOM, (dup_txdbuf[dup] & TXDBUF_M_TEOM)); + dup_put_msg_bytes (dup, &data, (dup_txdbuf[dup] & TXDBUF_M_TEOM) && (dptr == &dup_dev) ? 0 : 1, dup_txdbuf[dup] & TXDBUF_M_TSOM, (dup_txdbuf[dup] & TXDBUF_M_TEOM)); if (dup_xmtpkrdy[dup]) { /* Packet ready to send? */ sim_debug(DBG_TRC, DUPDPTR, "dup_svc(dup=%d) - Packet Done %d bytes\n", dup, dup_xmtpkoffset[dup]); ddcmp_packet_trace (DBG_PKT, DUPDPTR, ">>> XMT Packet", dup_xmtpacket[dup], dup_xmtpkoffset[dup], TRUE); @@ -900,10 +900,12 @@ if (sim_deb && dptr && (reason & dptr->dctrl)) { sim_debug (reason, dptr, "(Unknown=0%o)\n", msg[1]); break; } - if (len != 8) + if (len != 8) { sim_debug (reason, dptr, "Unexpected Control Message Length: %d expected 8\n", len); - if (0 != ddcmp_crc16 (0, msg, len)) + } + if (0 != ddcmp_crc16 (0, msg, len)) { sim_debug (reason, dptr, "Unexpected Message CRC\n"); + } break; case DDCMP_DLE: /* Maintenance Message */ sim_debug (reason, dptr, "Maintenance Message, Link: %d, Count: %d, HDRCRC: %s, DATACRC: %s\n", msg[2]>>6, ((msg[2] & 0x3F) << 8)| msg[1], diff --git a/scp.c b/scp.c index 8f5a3bf0..57252fbc 100644 --- a/scp.c +++ b/scp.c @@ -6431,8 +6431,9 @@ return 0; double sim_gtime (void) { -if (AIO_MAIN_THREAD) +if (AIO_MAIN_THREAD) { UPDATE_SIM_TIME; + } return sim_time; } diff --git a/sim_console.c b/sim_console.c index 2fe37942..544e45b8 100644 --- a/sim_console.c +++ b/sim_console.c @@ -704,13 +704,14 @@ for (i=(was_stepping ? sim_rem_step_line : 0); strcpy (cbuf, sim_rem_buf[i]); sim_rem_buf_ptr[i] = 0; sim_rem_buf[i][sim_rem_buf_ptr[i]] = '\0'; - if (cbuf[0] == '\0') + if (cbuf[0] == '\0') { if (sim_rem_single_mode[i]) { sim_rem_single_mode[i] = FALSE; break; } else continue; + } sim_sub_args (cbuf, sizeof(cbuf), argv); cptr = cbuf; cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */ diff --git a/sim_tmxr.c b/sim_tmxr.c index c0a06ac7..d9062879 100644 --- a/sim_tmxr.c +++ b/sim_tmxr.c @@ -1817,7 +1817,7 @@ while (*tptr) { sim_close_sock (sock, 1); strcpy(listen, port); cptr = get_glyph (cptr, option, ';'); - if (option[0]) + if (option[0]) { if (0 == MATCH_CMD (option, "NOTELNET")) listennotelnet = TRUE; else @@ -1825,6 +1825,7 @@ while (*tptr) { listennotelnet = FALSE; else return SCPE_ARG; + } } if (line == -1) { if (modem_control != mp->modem_control) From 4064cc079a596d7d0283b3a1fab2833abfbf061f Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Sun, 2 Jun 2013 06:52:32 -0700 Subject: [PATCH 21/22] This fixes the problem that MMR1 is recording changes to R7 (PC), which it should not. (issue #44) It does not fix the problem that MMR1 is not used for floating point instructions. I don't know if I will fix the FP MMR1 problem. It does not seem to impact running software. It is consistent with the architecture spec - just not with the actual J11 implementation. The J11 microcode has a variety of exception exits for FP conditions, and I have to trace which ones invoke fix-up, and which do not. --- PDP11/pdp11_cpu.c | 36 +++++++++++++++++++++--------------- PDP11/pdp11_fp.c | 11 ++++++----- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/PDP11/pdp11_cpu.c b/PDP11/pdp11_cpu.c index 63e032c2..e4e853df 100644 --- a/PDP11/pdp11_cpu.c +++ b/PDP11/pdp11_cpu.c @@ -1,6 +1,6 @@ /* pdp11_cpu.c: PDP-11 CPU simulator - Copyright (c) 1993-2012, Robert M Supnik + Copyright (c) 1993-2013, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,7 @@ cpu PDP-11 CPU + 10-Apr-13 RMS MMR1 does not track PC changes (Johnny Billquist) 29-Apr-12 RMS Fixed compiler warning (Mark Pizzolato) 19-Mar-12 RMS Fixed declaration of sim_switches (Mark Pizzolato) 29-Dec-08 RMS Fixed failure to clear cpu_bme on RESET (Walter Mueller) @@ -689,7 +690,8 @@ if (abortval != 0) { if ((trapea > 0) && stop_vecabort) reason = STOP_VECABORT; if ((trapea < 0) && /* stack push abort? */ - (CPUT (STOP_STKA) || stop_spabort)) reason = STOP_SPABORT; + (CPUT (STOP_STKA) || stop_spabort)) + reason = STOP_SPABORT; if (trapea == ~MD_KER) { /* kernel stk abort? */ setTRAP (TRAP_RED); setCPUERR (CPUE_RED); @@ -715,7 +717,7 @@ while (reason == 0) { cpu_astop = 0; reason = SCPE_STOP; break; - } + } AIO_CHECK_EVENT; if (sim_interval <= 0) { /* intv cnt expired? */ @@ -809,7 +811,7 @@ while (reason == 0) { if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */ reason = STOP_IBKPT; /* stop simulation */ continue; - } + } if (update_MM) { /* if mm not frozen */ MMR1 = 0; @@ -907,7 +909,8 @@ while (reason == 0) { trap_req = calc_ints (ipl, trap_req); JMP_PC (src); if (CPUT (HAS_RTT) && tbit && /* RTT impl? */ - (IR == 000002)) setTRAP (TRAP_TRC); /* RTI immed trap */ + (IR == 000002)) + setTRAP (TRAP_TRC); /* RTI immed trap */ break; case 7: /* MFPT */ if (CPUT (HAS_MFPT)) /* implemented? */ @@ -1352,7 +1355,8 @@ while (reason == 0) { } else { dst = srcreg? R[srcspec]: ReadW (GeteaW (srcspec)); - if (!dstreg) ea = GeteaW (dstspec); + if (!dstreg) + ea = GeteaW (dstspec); } N = GET_SIGN_W (dst); Z = GET_Z (dst); @@ -1888,6 +1892,7 @@ while (reason == 0) { R[dstspec] = (R[dstspec] & 0177400) | dst; else PWriteB (dst, last_pa); break; + /* Notes: - MTPS cannot alter the T bit - MxPD must mask GeteaW returned address, dspace is from cm not pm @@ -1981,7 +1986,8 @@ while (reason == 0) { } else { dst = srcreg? R[srcspec] & 0377: ReadB (GeteaB (srcspec)); - if (!dstreg) ea = GeteaB (dstspec); + if (!dstreg) + ea = GeteaB (dstspec); } N = GET_SIGN_B (dst); Z = GET_Z (dst); @@ -2161,20 +2167,20 @@ switch (spec >> 3) { /* decode spec<5:3> */ case 2: /* (R)+ */ R[reg] = ((adr = R[reg]) + 2) & 0177777; - if (update_MM) + if (update_MM && (reg != 7)) MMR1 = calc_MMR1 (020 | reg); return (adr | ds); case 3: /* @(R)+ */ R[reg] = ((adr = R[reg]) + 2) & 0177777; - if (update_MM) + if (update_MM && (reg != 7)) MMR1 = calc_MMR1 (020 | reg); adr = ReadW (adr | ds); return (adr | dsenable); case 4: /* -(R) */ adr = R[reg] = (R[reg] - 2) & 0177777; - if (update_MM) + if (update_MM && (reg != 7)) MMR1 = calc_MMR1 (0360 | reg); if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y))) set_stack_trap (adr); @@ -2182,7 +2188,7 @@ switch (spec >> 3) { /* decode spec<5:3> */ case 5: /* @-(R) */ adr = R[reg] = (R[reg] - 2) & 0177777; - if (update_MM) + if (update_MM && (reg != 7)) MMR1 = calc_MMR1 (0360 | reg); if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y))) set_stack_trap (adr); @@ -2219,13 +2225,13 @@ switch (spec >> 3) { /* decode spec<5:3> */ case 2: /* (R)+ */ delta = 1 + (reg >= 6); /* 2 if R6, PC */ R[reg] = ((adr = R[reg]) + delta) & 0177777; - if (update_MM) + if (update_MM && (reg != 7)) MMR1 = calc_MMR1 ((delta << 3) | reg); return (adr | ds); case 3: /* @(R)+ */ R[reg] = ((adr = R[reg]) + 2) & 0177777; - if (update_MM) + if (update_MM && (reg != 7)) MMR1 = calc_MMR1 (020 | reg); adr = ReadW (adr | ds); return (adr | dsenable); @@ -2233,7 +2239,7 @@ switch (spec >> 3) { /* decode spec<5:3> */ case 4: /* -(R) */ delta = 1 + (reg >= 6); /* 2 if R6, PC */ adr = R[reg] = (R[reg] - delta) & 0177777; - if (update_MM) + if (update_MM && (reg != 7)) MMR1 = calc_MMR1 ((((-delta) & 037) << 3) | reg); if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y))) set_stack_trap (adr); @@ -2241,7 +2247,7 @@ switch (spec >> 3) { /* decode spec<5:3> */ case 5: /* @-(R) */ adr = R[reg] = (R[reg] - 2) & 0177777; - if (update_MM) + if (update_MM && (reg != 7)) MMR1 = calc_MMR1 (0360 | reg); if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y))) set_stack_trap (adr); diff --git a/PDP11/pdp11_fp.c b/PDP11/pdp11_fp.c index fe7c9660..4b8a9993 100644 --- a/PDP11/pdp11_fp.c +++ b/PDP11/pdp11_fp.c @@ -1,6 +1,6 @@ /* pdp11_fp.c: PDP-11 floating point simulator (32b version) - Copyright (c) 1993-2008, Robert M Supnik + Copyright (c) 1993-2013, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -23,6 +23,7 @@ used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 20-Apr-13 RMS MMR1 does not track PC changes (Johnny Billquist) 22-Sep-05 RMS Fixed declarations (Sterling Garwood) 04-Oct-04 RMS Added FIS instructions 19-Jan-03 RMS Changed mode definitions for Apple Dev Kit conflict @@ -584,20 +585,20 @@ switch (spec >> 3) { /* case on spec */ if (reg == 7) len = 2; R[reg] = ((adr = R[reg]) + len) & 0177777; - if (update_MM) + if (update_MM && (reg != 7)) MMR1 = (len << 3) | reg; return (adr | ds); case 3: /* @(R)+ */ R[reg] = ((adr = R[reg]) + 2) & 0177777; - if (update_MM) + if (update_MM && (reg != 7)) MMR1 = 020 | reg; adr = ReadW (adr | ds); return (adr | dsenable); case 4: /* -(R) */ adr = R[reg] = (R[reg] - len) & 0177777; - if (update_MM) + if (update_MM && (reg != 7)) MMR1 = (((-len) & 037) << 3) | reg; if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y))) set_stack_trap (adr); @@ -605,7 +606,7 @@ switch (spec >> 3) { /* case on spec */ case 5: /* @-(R) */ adr = R[reg] = (R[reg] - 2) & 0177777; - if (update_MM) + if (update_MM && (reg != 7)) MMR1 = 0360 | reg; if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y))) set_stack_trap (adr); From 596cb3f5801cd6899fd61fc7f5d745adfc3d71a7 Mon Sep 17 00:00:00 2001 From: Mark Pizzolato Date: Sun, 2 Jun 2013 13:19:23 -0700 Subject: [PATCH 22/22] Added needed DUP interfaces to allow use by KMC11/KDP. --- PDP11/pdp11_ddcmp.h | 100 ++++++++++++++++++++++++++++++++- PDP11/pdp11_dup.c | 134 +++++++++++--------------------------------- PDP11/pdp11_dup.h | 3 + 3 files changed, 136 insertions(+), 101 deletions(-) diff --git a/PDP11/pdp11_ddcmp.h b/PDP11/pdp11_ddcmp.h index 8d6e8d44..6ac3f1a9 100644 --- a/PDP11/pdp11_ddcmp.h +++ b/PDP11/pdp11_ddcmp.h @@ -41,7 +41,105 @@ /* Support routines */ -void ddcmp_packet_trace (uint32 reason, DEVICE *dptr, const char *txt, const uint8 *msg, int32 len, t_bool detail); +/* crc16 polynomial x^16 + x^15 + x^2 + 1 (0xA001) CCITT LSB */ +static uint16 crc16_nibble[16] = { + 0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401, + 0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400, + }; + +static uint16 ddcmp_crc16(uint16 crc, const void* vbuf, size_t len) +{ +const unsigned char* buf = (const unsigned char*)vbuf; + +while(0 != len--) { + crc = (crc>>4) ^ crc16_nibble[(*buf ^ crc) & 0xF]; + crc = (crc>>4) ^ crc16_nibble[((*buf++)>>4 ^ crc) & 0xF]; + }; +return(crc); +} + +/* Debug routines */ + +#include + +static void ddcmp_packet_trace (uint32 reason, DEVICE *dptr, const char *txt, const uint8 *msg, int32 len, t_bool detail) +{ +if (sim_deb && dptr && (reason & dptr->dctrl)) { + sim_debug(reason, 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 (reason, dptr, "Data Message, Link: %d, Count: %d, Resp: %d, Num: %d, HDRCRC: %s, DATACRC: %s\n", msg[2]>>6, ((msg[2] & 0x3F) << 8)|msg[1], msg[3], msg[4], + (0 == ddcmp_crc16 (0, msg, 8)) ? "OK" : "BAD", (0 == ddcmp_crc16 (0, msg+8, 2+(((msg[2] & 0x3F) << 8)|msg[1]))) ? "OK" : "BAD"); + break; + case DDCMP_ENQ: /* Control Message */ + sim_debug (reason, dptr, "Control: Type: %d ", msg[1]); + switch (msg[1]) { + case 1: /* ACK */ + sim_debug (reason, dptr, "(ACK) ACKSUB: %d, Link: %d, Resp: %d\n", msg[2] & 0x3F, msg[2]>>6, msg[3]); + break; + case 2: /* NAK */ + sim_debug (reason, dptr, "(NAK) Reason: %d, Link: %d, Resp: %d\n", msg[2] & 0x3F, msg[2]>>6, msg[3]); + break; + case 3: /* REP */ + sim_debug (reason, dptr, "(REP) REPSUB: %d, Link: %d, Num: %d\n", msg[2] & 0x3F, msg[2]>>6, msg[4]); + break; + case 6: /* STRT */ + sim_debug (reason, dptr, "(STRT) STRTSUB: %d, Link: %d\n", msg[2] & 0x3F, msg[2]>>6); + break; + case 7: /* STACK */ + sim_debug (reason, dptr, "(STACK) STCKSUB: %d, Link: %d\n", msg[2] & 0x3F, msg[2]>>6); + break; + default: /* Unknown */ + sim_debug (reason, dptr, "(Unknown=0%o)\n", msg[1]); + break; + } + if (len != 8) { + sim_debug (reason, dptr, "Unexpected Control Message Length: %d expected 8\n", len); + } + if (0 != ddcmp_crc16 (0, msg, len)) { + sim_debug (reason, dptr, "Unexpected Message CRC\n"); + } + break; + case DDCMP_DLE: /* Maintenance Message */ + sim_debug (reason, dptr, "Maintenance Message, Link: %d, Count: %d, HDRCRC: %s, DATACRC: %s\n", msg[2]>>6, ((msg[2] & 0x3F) << 8)| msg[1], + (0 == ddcmp_crc16 (0, msg, 8)) ? "OK" : "BAD", (0 == ddcmp_crc16 (0, msg+8, 2+(((msg[2] & 0x3F) << 8)| msg[1]))) ? "OK" : "BAD"); + break; + } + for (i=same=0; i 0) && (0 == memcmp(&msg[i], &msg[i-16], 16))) { + ++same; + continue; + } + if (same > 0) { + sim_debug(reason, 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(reason, dptr, "%04X%-48s %s\n", i, outbuf, strbuf); + } + if (same > 0) { + sim_debug(reason, dptr, "%04X thru %04X same as above\n", i-(16*same), len-1); + } + } + } +} + uint16 ddcmp_crc16(uint16 crc, const void* vbuf, size_t len); #endif /* PDP11_DDCMP_H_ */ diff --git a/PDP11/pdp11_dup.c b/PDP11/pdp11_dup.c index cf961ee6..7f99d8c5 100644 --- a/PDP11/pdp11_dup.c +++ b/PDP11/pdp11_dup.c @@ -51,7 +51,6 @@ #include "sim_tmxr.h" #include "pdp11_ddcmp.h" #include "pdp11_dup.h" -#include #if !defined(DUP_LINES) #define DUP_LINES 8 @@ -99,8 +98,6 @@ 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 (uint32 reason, DEVICE *dptr, const char *txt, const uint8 *msg, int32 len, t_bool detail); -uint16 ddcmp_crc16(uint16 crc, const void* vbuf, size_t len); int32 dup_rxinta (void); int32 dup_txinta (void); void dup_update_rcvi (void); @@ -623,11 +620,16 @@ if ((dup_rxcsr[dup] & RXCSR_M_DSCHNG) && return SCPE_OK; } +/* + * Public routines for use by other devices (i.e. KDP11) + */ + int32 dup_csr_to_linenum (int32 CSRPA) { DEVICE *dptr = DUPDPTR; DIB *dib = (DIB *)dptr->ctxt; +CSRPA += IOPAGEBASE; if ((dib->ba > (uint32)CSRPA) || ((uint32)CSRPA > (dib->ba + dib->lnt))) return -1; @@ -636,15 +638,44 @@ return ((uint32)CSRPA - dib->ba)/dib->lnt; void dup_set_callback_mode (int32 dup, PACKET_RECEIVE_CALLBACK receive, PACKET_TRANSMIT_COMPLETE_CALLBACK transmit) { +if ((dup < 0) || (dup >= dup_desc.lines)) + return; dup_rcv_packet_callback[dup] = receive; dup_xmt_complete_callback[dup] = transmit; } int32 dup_get_line_speed (int32 dup) { +if ((dup < 0) || (dup >= dup_desc.lines)) + return -1; return dup_speed[dup]; } +int32 dup_get_DCD (int32 dup) +{ +if ((dup < 0) || (dup >= dup_desc.lines)) + return -1; +return (dup_rxcsr[dup] & RXCSR_M_DCD) ? 1 : 0; +} + +t_stat dup_set_DTR (int32 dup, t_bool state) +{ +if ((dup < 0) || (dup >= dup_desc.lines)) + return SCPE_IERR; +dup_set_modem (dup, state ? (RXCSR_M_DTR | RXCSR_M_RTS) : 0); +return SCPE_OK; +} + +t_stat dup_set_DDCMP (int32 dup, t_bool state) +{ +if ((dup < 0) || (dup >= dup_desc.lines)) + return SCPE_IERR; +dup_parcsr[dup] &= ~PARCSR_M_NOCRC; +dup_parcsr[dup] |= (state ? 0: PARCSR_M_NOCRC); +dup_parcsr[dup] &= ~PARCSR_M_DECMODE; +dup_parcsr[dup] |= (state ? PARCSR_M_DECMODE : 0); +return SCPE_OK; +} t_stat dup_rcv_byte (int32 dup) { @@ -862,86 +893,6 @@ else { return SCPE_OK; } -/* Debug routines */ - -void ddcmp_packet_trace (uint32 reason, DEVICE *dptr, const char *txt, const uint8 *msg, int32 len, t_bool detail) -{ -if (sim_deb && dptr && (reason & dptr->dctrl)) { - sim_debug(reason, 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 (reason, dptr, "Data Message, Link: %d, Count: %d, Resp: %d, Num: %d, HDRCRC: %s, DATACRC: %s\n", msg[2]>>6, ((msg[2] & 0x3F) << 8)|msg[1], msg[3], msg[4], - (0 == ddcmp_crc16 (0, msg, 8)) ? "OK" : "BAD", (0 == ddcmp_crc16 (0, msg+8, 2+(((msg[2] & 0x3F) << 8)|msg[1]))) ? "OK" : "BAD"); - break; - case DDCMP_ENQ: /* Control Message */ - sim_debug (reason, dptr, "Control: Type: %d ", msg[1]); - switch (msg[1]) { - case 1: /* ACK */ - sim_debug (reason, dptr, "(ACK) ACKSUB: %d, Link: %d, Resp: %d\n", msg[2] & 0x3F, msg[2]>>6, msg[3]); - break; - case 2: /* NAK */ - sim_debug (reason, dptr, "(NAK) Reason: %d, Link: %d, Resp: %d\n", msg[2] & 0x3F, msg[2]>>6, msg[3]); - break; - case 3: /* REP */ - sim_debug (reason, dptr, "(REP) REPSUB: %d, Link: %d, Num: %d\n", msg[2] & 0x3F, msg[2]>>6, msg[4]); - break; - case 6: /* STRT */ - sim_debug (reason, dptr, "(STRT) STRTSUB: %d, Link: %d\n", msg[2] & 0x3F, msg[2]>>6); - break; - case 7: /* STACK */ - sim_debug (reason, dptr, "(STACK) STCKSUB: %d, Link: %d\n", msg[2] & 0x3F, msg[2]>>6); - break; - default: /* Unknown */ - sim_debug (reason, dptr, "(Unknown=0%o)\n", msg[1]); - break; - } - if (len != 8) { - sim_debug (reason, dptr, "Unexpected Control Message Length: %d expected 8\n", len); - } - if (0 != ddcmp_crc16 (0, msg, len)) { - sim_debug (reason, dptr, "Unexpected Message CRC\n"); - } - break; - case DDCMP_DLE: /* Maintenance Message */ - sim_debug (reason, dptr, "Maintenance Message, Link: %d, Count: %d, HDRCRC: %s, DATACRC: %s\n", msg[2]>>6, ((msg[2] & 0x3F) << 8)| msg[1], - (0 == ddcmp_crc16 (0, msg, 8)) ? "OK" : "BAD", (0 == ddcmp_crc16 (0, msg+8, 2+(((msg[2] & 0x3F) << 8)| msg[1]))) ? "OK" : "BAD"); - break; - } - for (i=same=0; i 0) && (0 == memcmp(&msg[i], &msg[i-16], 16))) { - ++same; - continue; - } - if (same > 0) { - sim_debug(reason, 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(reason, dptr, "%04X%-48s %s\n", i, outbuf, strbuf); - } - if (same > 0) { - sim_debug(reason, dptr, "%04X thru %04X same as above\n", i-(16*same), len-1); - } - } - } -} - /* Interrupt routines */ void dup_clr_rxint (int32 dup) @@ -1221,20 +1172,3 @@ 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 uint16 crc16_nibble[16] = { - 0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401, - 0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400, - }; - -uint16 ddcmp_crc16(uint16 crc, const void* vbuf, size_t len) -{ -const unsigned char* buf = (const unsigned char*)vbuf; - -while(0 != len--) { - crc = (crc>>4) ^ crc16_nibble[(*buf ^ crc) & 0xF]; - crc = (crc>>4) ^ crc16_nibble[((*buf++)>>4 ^ crc) & 0xF]; - }; -return(crc); -} diff --git a/PDP11/pdp11_dup.h b/PDP11/pdp11_dup.h index 1d7e4f66..4e49d603 100644 --- a/PDP11/pdp11_dup.h +++ b/PDP11/pdp11_dup.h @@ -38,6 +38,9 @@ typedef void (*PACKET_RECEIVE_CALLBACK)(int32 dup, uint8 *buf, size_t len); typedef void (*PACKET_TRANSMIT_COMPLETE_CALLBACK)(int32 dup, int status); int32 dup_get_line_speed (int32 dup); +int32 dup_get_DCD (int32 dup); +t_stat dup_set_DTR (int32 dup, t_bool state); +t_stat dup_set_DDCMP (int32 dup, t_bool state); int32 dup_csr_to_linenum (int32 CSRPA); void dup_set_callback_mode (int32 dup, PACKET_RECEIVE_CALLBACK receive, PACKET_TRANSMIT_COMPLETE_CALLBACK transmit);