diff --git a/PDP11/pdp11_dz.c b/PDP11/pdp11_dz.c index a8a20535..c0610364 100644 --- a/PDP11/pdp11_dz.c +++ b/PDP11/pdp11_dz.c @@ -160,6 +160,20 @@ int32 dz_auto = 0; /* autodiscon enabled */ TMLN dz_ldsc[DZ_MUXES * DZ_LINES] = { 0 }; /* line descriptors */ TMXR dz_desc = { DZ_MUXES * DZ_LINES, 0, 0, dz_ldsc }; /* mux descriptor */ +/* debugging bitmaps */ +#define DBG_REG 0x0001 /* trace read/write registers */ +#define DBG_INT 0x0002 /* display transfer requests */ +#define DBG_XMT TMXR_DBG_XMT /* display Transmitted Data */ +#define DBG_RCV TMXR_DBG_RCV /* display Received Data */ + +DEBTAB dz_debug[] = { + {"REG", DBG_REG}, + {"INT", DBG_INT}, + {"XMT", DBG_XMT}, + {"RCV", DBG_RCV}, + {0} +}; + DEVICE dz_dev; t_stat dz_rd (int32 *data, int32 PA, int32 access); t_stat dz_wr (int32 data, int32 PA, int32 access); @@ -249,9 +263,16 @@ DEVICE dz_dev = { 1, DEV_RDX, 8, 1, DEV_RDX, 8, &tmxr_ex, &tmxr_dep, &dz_reset, NULL, &dz_attach, &dz_detach, - &dz_dib, DEV_FLTA | DEV_DISABLE | DEV_NET | DEV_UBUS | DEV_QBUS + &dz_dib, DEV_FLTA | DEV_DISABLE | DEV_NET | DEV_UBUS | DEV_QBUS | DEV_DEBUG, + 0, dz_debug }; +/* Register names for Debug tracing */ +static char *dz_rd_regs[] = + {"CSR ", "RBUF", "TCR ", "MSR " }; +static char *dz_wr_regs[] = + {"CSR ", "LPR ", "TCR ", "TDR "}; + /* IO dispatch routines, I/O addresses 177601x0 - 177601x7 */ t_stat dz_rd (int32 *data, int32 PA, int32 access) @@ -289,6 +310,8 @@ switch ((PA >> 1) & 03) { /* case on PA<2:1> */ break; } +sim_debug(DBG_REG, &dz_dev, "dz_rd(PA=0x%08X [%s], access=%d, data=0x%X)\n", PA, dz_rd_regs[(PA >> 1) & 03], access, *data); + return SCPE_OK; } @@ -298,6 +321,8 @@ int32 dz = ((PA - dz_dib.ba) >> 3) & DZ_MNOMASK; /* get mux num */ int32 i, c, line; TMLN *lp; +sim_debug(DBG_REG, &dz_dev, "dz_wr(PA=0x%08X [%s], access=%d, data=0x%X)\n", PA, dz_wr_regs[(PA >> 1) & 03], access, data); + switch ((PA >> 1) & 03) { /* case on PA<2:1> */ case 00: /* CSR */ @@ -517,6 +542,7 @@ int32 dz; for (dz = 0; dz < DZ_MUXES; dz++) { /* find 1st mux */ if (dz_rxi & (1 << dz)) { + sim_debug(DBG_INT, &dz_dev, "dz_rzinta(dz=%d)\n", dz); dz_clr_rxint (dz); /* clear intr */ return (dz_dib.vec + (dz * 010)); /* return vector */ } @@ -546,6 +572,7 @@ int32 dz; for (dz = 0; dz < DZ_MUXES; dz++) { /* find 1st mux */ if (dz_txi & (1 << dz)) { + sim_debug(DBG_INT, &dz_dev, "dz_txinta(dz=%d)\n", dz); dz_clr_txint (dz); /* clear intr */ return (dz_dib.vec + 4 + (dz * 010)); /* return vector */ } diff --git a/PDP11/pdp11_vh.c b/PDP11/pdp11_vh.c index 72f09280..da8e472a 100644 --- a/PDP11/pdp11_vh.c +++ b/PDP11/pdp11_vh.c @@ -24,266 +24,286 @@ used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the Author. - vh DHQ11 asynch multiplexor for SIMH + vh DHQ11 asynch multiplexor for SIMH + 02-Jun-11 MP Added debugging support to trace register, interrupt + and data traffic (SET VH DEBUG[=REG;INT;XMT;RCV]) + Added SET LOG and SET NOLOG support for logging mux + traffic + Fixed SET VH LINES=n to correctly adjust the number + of lines available to be 8, 16, 24, or 32. + Fixed performance issue avoiding redundant polling 03-Jan-10 JAD Eliminate gcc warnings 19-Nov-08 RMS Revised for common TMXR show routines 18-Jun-07 RMS Added UNIT_IDLE flag 29-Oct-06 RMS Synced poll and clock - 07-Jul-05 RMS Removed extraneous externs - 15-Jun-05 RMS Revised for new autoconfigure interface - Fixed bug in vector display routine - 12-Jun-04 RMS Repair MS2SIMH macro to avoid divide by 0 bug - 08-Jun-04 JAD Repair vh_dev initialization; remove unused - variables, cast to avoid conversion confusion - 07-Jun-04 JAD Complete function prototypes of forward declarations. - Repair broken prototypes of vh_rd() and vh_wr() - Explicitly size integer declarations - 4-Jun-04 JAD Preliminary code: If operating in a PDP-11 Unibus - environment, force DHU mode - 29-May-04 JAD Make certain RX.TIMER is within allowable range - 25-May-04 JAD All time-based operations are scaled by tmxr_poll units - 23-May-04 JAD Change to fifo_get() and dq_tx_report() to avoid - gratuitous stack manipulation - 20-May-04 JAD Made modem control and auto-hangup unit flags - 19-May-04 JAD Fix problem with modem status where the line number - was not being included - 12-May-04 JAD Revised for updated tmxr interfaces - 28-Jan-04 JAD Original creation and testing + 07-Jul-05 RMS Removed extraneous externs + 15-Jun-05 RMS Revised for new autoconfigure interface + Fixed bug in vector display routine + 12-Jun-04 RMS Repair MS2SIMH macro to avoid divide by 0 bug + 08-Jun-04 JAD Repair vh_dev initialization; remove unused + variables, cast to avoid conversion confusion + 07-Jun-04 JAD Complete function prototypes of forward declarations. + Repair broken prototypes of vh_rd() and vh_wr() + Explicitly size integer declarations + 4-Jun-04 JAD Preliminary code: If operating in a PDP-11 Unibus + environment, force DHU mode + 29-May-04 JAD Make certain RX.TIMER is within allowable range + 25-May-04 JAD All time-based operations are scaled by tmxr_poll units + 23-May-04 JAD Change to fifo_get() and dq_tx_report() to avoid + gratuitous stack manipulation + 20-May-04 JAD Made modem control and auto-hangup unit flags + 19-May-04 JAD Fix problem with modem status where the line number + was not being included + 12-May-04 JAD Revised for updated tmxr interfaces + 28-Jan-04 JAD Original creation and testing I/O Page Registers -CSR 17 760 440 (float) +CSR 17 760 440 (float) -Vector: 300 (float) +Vector: 300 (float) -Priority: BR4 +Priority: BR4 -Rank: 32 +Rank: 32 */ /* MANY constants needed! */ -#if defined (VM_VAX) +#if defined (VM_VAX) #include "vax_defs.h" -extern int32 int_req[IPL_HLVL]; +extern int32 int_req[IPL_HLVL]; #endif -#if defined (VM_PDP11) +#if defined (VM_PDP11) #include "pdp11_defs.h" -extern int32 int_req[IPL_HLVL]; -extern int32 cpu_opt; +extern int32 int_req[IPL_HLVL]; +extern int32 cpu_opt; #endif #include "sim_sock.h" #include "sim_tmxr.h" /* imports from pdp11_stddev.c: */ -extern int32 tmxr_poll, clk_tps; +extern int32 tmxr_poll, clk_tps; /* convert ms to SIMH time units based on tmxr_poll polls per second */ -#define MS2SIMH(ms) (((ms) * clk_tps) / 1000) -extern FILE *sim_log; +#define MS2SIMH(ms) (((ms) * clk_tps) / 1000) -#ifndef VH_MUXES -#define VH_MUXES (4) +#ifndef VH_MUXES +#define VH_MUXES (4) #endif -#define VH_MNOMASK (VH_MUXES - 1) +#define VH_MNOMASK (VH_MUXES - 1) -#define VH_LINES (8) +#define VH_LINES (8) -#define UNIT_V_MODEDHU (UNIT_V_UF + 0) -#define UNIT_V_FASTDMA (UNIT_V_UF + 1) -#define UNIT_V_MODEM (UNIT_V_UF + 2) -#define UNIT_V_HANGUP (UNIT_V_UF + 3) -#define UNIT_MODEDHU (1 << UNIT_V_MODEDHU) -#define UNIT_FASTDMA (1 << UNIT_V_FASTDMA) -#define UNIT_MODEM (1 << UNIT_V_MODEM) -#define UNIT_HANGUP (1 << UNIT_V_HANGUP) +#define UNIT_V_MODEDHU (UNIT_V_UF + 0) +#define UNIT_V_FASTDMA (UNIT_V_UF + 1) +#define UNIT_V_MODEM (UNIT_V_UF + 2) +#define UNIT_V_HANGUP (UNIT_V_UF + 3) +#define UNIT_MODEDHU (1 << UNIT_V_MODEDHU) +#define UNIT_FASTDMA (1 << UNIT_V_FASTDMA) +#define UNIT_MODEM (1 << UNIT_V_MODEM) +#define UNIT_HANGUP (1 << UNIT_V_HANGUP) /* VHCSR - 160440 - Control and Status Register */ -#define CSR_M_IND_ADDR (017) -#define CSR_SKIP (1 << 4) -#define CSR_MASTER_RESET (1 << 5) -#define CSR_RXIE (1 << 6) -#define CSR_RX_DATA_AVAIL (1 << 7) -#define CSR_M_TX_LINE (017) -#define CSR_V_TX_LINE (8) -#define CSR_TX_DMA_ERR (1 << 12) -#define CSR_DIAG_FAIL (1 << 13) -#define CSR_TXIE (1 << 14) -#define CSR_TX_ACTION (1 << 15) -#define CSR_GETCHAN(x) ((x) & CSR_M_IND_ADDR) -#define CSR_RW \ - (CSR_TXIE|CSR_RXIE|CSR_SKIP|CSR_M_IND_ADDR|CSR_MASTER_RESET) -#define RESET_ABORT (052525) +#define CSR_M_IND_ADDR (017) +#define CSR_SKIP (1 << 4) +#define CSR_MASTER_RESET (1 << 5) +#define CSR_RXIE (1 << 6) +#define CSR_RX_DATA_AVAIL (1 << 7) +#define CSR_M_TX_LINE (017) +#define CSR_V_TX_LINE (8) +#define CSR_TX_DMA_ERR (1 << 12) +#define CSR_DIAG_FAIL (1 << 13) +#define CSR_TXIE (1 << 14) +#define CSR_TX_ACTION (1 << 15) +#define CSR_GETCHAN(x) ((x) & CSR_M_IND_ADDR) +#define CSR_RW \ + (CSR_TXIE|CSR_RXIE|CSR_SKIP|CSR_M_IND_ADDR|CSR_MASTER_RESET) +#define RESET_ABORT (052525) /* Receive Buffer (RBUF) */ -#define FIFO_SIZE (256) -#define FIFO_ALARM (191) -#define FIFO_HALF (FIFO_SIZE / 2) -#define RBUF_M_RX_CHAR (0377) -#define RBUF_M_RX_LINE (07) -#define RBUF_V_RX_LINE (8) -#define RBUF_PARITY_ERR (1 << 12) -#define RBUF_FRAME_ERR (1 << 13) -#define RBUF_OVERRUN_ERR (1 << 14) -#define RBUF_DATA_VALID (1 << 15) -#define RBUF_GETLINE(x) (((x) >> RBUF_V_RX_LINE) & RBUF_M_RX_LINE) -#define RBUF_PUTLINE(x) ((x) << RBUF_V_RX_LINE) -#define RBUF_DIAG \ - (RBUF_PARITY_ERR|RBUF_FRAME_ERR|RBUF_OVERRUN_ERR) -#define XON (021) -#define XOFF (023) +#define FIFO_SIZE (256) +#define FIFO_ALARM (191) +#define FIFO_HALF (FIFO_SIZE / 2) +#define RBUF_M_RX_CHAR (0377) +#define RBUF_M_RX_LINE (07) +#define RBUF_V_RX_LINE (8) +#define RBUF_PARITY_ERR (1 << 12) +#define RBUF_FRAME_ERR (1 << 13) +#define RBUF_OVERRUN_ERR (1 << 14) +#define RBUF_DATA_VALID (1 << 15) +#define RBUF_GETLINE(x) (((x) >> RBUF_V_RX_LINE) & RBUF_M_RX_LINE) +#define RBUF_PUTLINE(x) ((x) << RBUF_V_RX_LINE) +#define RBUF_DIAG \ + (RBUF_PARITY_ERR|RBUF_FRAME_ERR|RBUF_OVERRUN_ERR) +#define XON (021) +#define XOFF (023) /* Transmit Character Register (TXCHAR) */ -#define TXCHAR_M_CHAR (0377) -#define TXCHAR_TX_DATA_VALID (1 << 15) +#define TXCHAR_M_CHAR (0377) +#define TXCHAR_TX_DATA_VALID (1 << 15) /* Receive Timer Register (RXTIMER) */ -#define RXTIMER_M_RX_TIMER (0377) +#define RXTIMER_M_RX_TIMER (0377) /* Line-Parameter Register (LPR) */ -#define LPR_DISAB_XRPT (1 << 0) /* not impl. in real DHU */ -#define LPR_V_DIAG (1) -#define LPR_M_DIAG (03) -#define LPR_V_CHAR_LGTH (3) -#define LPR_M_CHAR_LGTH (03) -#define LPR_PARITY_ENAB (1 << 5) -#define LPR_EVEN_PARITY (1 << 6) -#define LPR_STOP_CODE (1 << 7) -#define LPR_V_RX_SPEED (8) -#define LPR_M_RX_SPEED (017) -#define LPR_V_TX_SPEED (12) -#define LPR_M_TX_SPEED (017) +#define LPR_DISAB_XRPT (1 << 0) /* not impl. in real DHU */ +#define LPR_V_DIAG (1) +#define LPR_M_DIAG (03) +#define LPR_V_CHAR_LGTH (3) +#define LPR_M_CHAR_LGTH (03) +#define LPR_PARITY_ENAB (1 << 5) +#define LPR_EVEN_PARITY (1 << 6) +#define LPR_STOP_CODE (1 << 7) +#define LPR_V_RX_SPEED (8) +#define LPR_M_RX_SPEED (017) +#define LPR_V_TX_SPEED (12) +#define LPR_M_TX_SPEED (017) -#define RATE_50 (0) -#define RATE_75 (1) -#define RATE_110 (2) -#define RATE_134 (3) -#define RATE_150 (4) -#define RATE_300 (5) -#define RATE_600 (6) -#define RATE_1200 (7) -#define RATE_1800 (8) -#define RATE_2000 (9) -#define RATE_2400 (10) -#define RATE_4800 (11) -#define RATE_7200 (12) -#define RATE_9600 (13) -#define RATE_19200 (14) -#define RATE_38400 (15) +#define RATE_50 (0) +#define RATE_75 (1) +#define RATE_110 (2) +#define RATE_134 (3) +#define RATE_150 (4) +#define RATE_300 (5) +#define RATE_600 (6) +#define RATE_1200 (7) +#define RATE_1800 (8) +#define RATE_2000 (9) +#define RATE_2400 (10) +#define RATE_4800 (11) +#define RATE_7200 (12) +#define RATE_9600 (13) +#define RATE_19200 (14) +#define RATE_38400 (15) /* Line-Status Register (STAT) */ -#define STAT_DHUID (1 << 8) /* mode: 0=DHV, 1=DHU */ -#define STAT_MDL (1 << 9) /* always 0, has modem support */ -#define STAT_CTS (1 << 11) /* CTS from modem */ -#define STAT_DCD (1 << 12) /* DCD from modem */ -#define STAT_RI (1 << 13) /* RI from modem */ -#define STAT_DSR (1 << 15) /* DSR from modem */ +#define STAT_DHUID (1 << 8) /* mode: 0=DHV, 1=DHU */ +#define STAT_MDL (1 << 9) /* always 0, has modem support */ +#define STAT_CTS (1 << 11) /* CTS from modem */ +#define STAT_DCD (1 << 12) /* DCD from modem */ +#define STAT_RI (1 << 13) /* RI from modem */ +#define STAT_DSR (1 << 15) /* DSR from modem */ /* FIFO Size Register (FIFOSIZE) */ -#define FIFOSIZE_M_SIZE (0377) +#define FIFOSIZE_M_SIZE (0377) /* FIFO Data Register (FIFODATA) */ -#define FIFODATA_W0 (0377) -#define FIFODATA_V_W1 (8) -#define FIFODATA_M_W1 (0377) +#define FIFODATA_W0 (0377) +#define FIFODATA_V_W1 (8) +#define FIFODATA_M_W1 (0377) /* Line-Control Register (LNCTRL) */ -#define LNCTRL_TX_ABORT (1 << 0) -#define LNCTRL_IAUTO (1 << 1) -#define LNCTRL_RX_ENA (1 << 2) -#define LNCTRL_BREAK (1 << 3) -#define LNCTRL_OAUTO (1 << 4) -#define LNCTRL_FORCE_XOFF (1 << 5) -#define LNCTRL_V_MAINT (6) -#define LNCTRL_M_MAINT (03) -#define LNCTRL_LINK_TYPE (1 << 8) /* 0=data leads only, 1=modem */ -#define LNCTRL_DTR (1 << 9) /* DTR to modem */ -#define LNCTRL_RTS (1 << 12) /* RTS to modem */ +#define LNCTRL_TX_ABORT (1 << 0) +#define LNCTRL_IAUTO (1 << 1) +#define LNCTRL_RX_ENA (1 << 2) +#define LNCTRL_BREAK (1 << 3) +#define LNCTRL_OAUTO (1 << 4) +#define LNCTRL_FORCE_XOFF (1 << 5) +#define LNCTRL_V_MAINT (6) +#define LNCTRL_M_MAINT (03) +#define LNCTRL_LINK_TYPE (1 << 8) /* 0=data leads only, 1=modem */ +#define LNCTRL_DTR (1 << 9) /* DTR to modem */ +#define LNCTRL_RTS (1 << 12) /* RTS to modem */ /* Transmit Buffer Address Register Number 1 (TBUFFAD1) */ /* Transmit Buffer Address Register Number 2 (TBUFFAD2) */ -#define TB2_M_TBUFFAD (077) -#define TB2_TX_DMA_START (1 << 7) -#define TB2_TX_ENA (1 << 15) +#define TB2_M_TBUFFAD (077) +#define TB2_TX_DMA_START (1 << 7) +#define TB2_TX_ENA (1 << 15) /* Transmit DMA Buffer Counter (TBUFFCT) */ /* Self-Test Error Codes */ -#define SELF_NULL (0201) -#define SELF_SKIP (0203) -#define SELF_OCT (0211) -#define SELF_RAM (0225) -#define SELF_RCD (0231) -#define SELF_DRD (0235) +#define SELF_NULL (0201) +#define SELF_SKIP (0203) +#define SELF_OCT (0211) +#define SELF_RAM (0225) +#define SELF_RCD (0231) +#define SELF_DRD (0235) -#define BMP_OK (0305) -#define BMP_BAD (0307) +#define BMP_OK (0305) +#define BMP_BAD (0307) /* Loopback types */ -#define LOOP_NONE (0) -#define LOOP_H325 (1) -#define LOOP_H3101 (2) /* p.2-13 DHQ manual */ +#define LOOP_NONE (0) +#define LOOP_H325 (1) +#define LOOP_H3101 (2) /* p.2-13 DHQ manual */ /* Local storage */ -static uint16 vh_csr[VH_MUXES] = { 0 }; /* CSRs */ -static uint16 vh_timer[VH_MUXES] = { 1 }; /* controller timeout */ -static uint16 vh_mcount[VH_MUXES] = { 0 }; -static uint32 vh_timeo[VH_MUXES] = { 0 }; -static uint32 vh_ovrrun[VH_MUXES] = { 0 }; /* line overrun bits */ +static uint16 vh_csr[VH_MUXES] = { 0 }; /* CSRs */ +static uint16 vh_timer[VH_MUXES] = { 1 }; /* controller timeout */ +static uint16 vh_mcount[VH_MUXES] = { 0 }; +static uint32 vh_timeo[VH_MUXES] = { 0 }; +static uint32 vh_ovrrun[VH_MUXES] = { 0 }; /* line overrun bits */ /* XOFF'd channels, one bit/channel */ -static uint32 vh_stall[VH_MUXES] = { 0 }; -static uint16 vh_loop[VH_MUXES] = { 0 }; /* loopback status */ +static uint32 vh_stall[VH_MUXES] = { 0 }; +static uint16 vh_loop[VH_MUXES] = { 0 }; /* loopback status */ /* One bit per controller: */ -static uint32 vh_rxi = 0; /* rcv interrupts */ -static uint32 vh_txi = 0; /* xmt interrupts */ -static uint32 vh_crit = 0; /* FIFO.CRIT */ +static uint32 vh_rxi = 0; /* rcv interrupts */ +static uint32 vh_txi = 0; /* xmt interrupts */ +static uint32 vh_crit = 0; /* FIFO.CRIT */ static const int32 bitmask[4] = { 037, 077, 0177, 0377 }; /* RX FIFO state */ -static int32 rbuf_idx[VH_MUXES] = { 0 };/* index into vh_rbuf */ +static int32 rbuf_idx[VH_MUXES] = { 0 };/* index into vh_rbuf */ static uint32 vh_rbuf[VH_MUXES][FIFO_SIZE] = { { 0 } }; /* TXQ state */ -#define TXQ_SIZE (16) -static int32 txq_idx[VH_MUXES] = { 0 }; -static uint32 vh_txq[VH_MUXES][TXQ_SIZE] = { { 0 } }; +#define TXQ_SIZE (16) +static int32 txq_idx[VH_MUXES] = { 0 }; +static uint32 vh_txq[VH_MUXES][TXQ_SIZE] = { { 0 } }; /* Need to extend the TMLN structure */ typedef struct { - TMLN *tmln; - uint16 lpr; /* line parameters */ - uint16 lnctrl; /* line control */ - uint16 lstat; /* line modem status */ - uint16 tbuffct; /* remaining character count */ - uint16 tbuf1; - uint16 tbuf2; - uint16 txchar; /* single character I/O */ + TMLN *tmln; + uint16 lpr; /* line parameters */ + uint16 lnctrl; /* line control */ + uint16 lstat; /* line modem status */ + uint16 tbuffct; /* remaining character count */ + uint16 tbuf1; + uint16 tbuf2; + uint16 txchar; /* single character I/O */ } TMLX; static TMLN vh_ldsc[VH_MUXES * VH_LINES] = { { 0 } }; static TMXR vh_desc = { VH_MUXES * VH_LINES, 0, 0, vh_ldsc }; static TMLX vh_parm[VH_MUXES * VH_LINES] = { { 0 } }; +/* debugging bitmaps */ +#define DBG_REG 0x0001 /* trace read/write registers */ +#define DBG_INT 0x0002 /* display transfer requests */ +#define DBG_XMT TMXR_DBG_XMT /* display Transmitted Data */ +#define DBG_RCV TMXR_DBG_RCV /* display Received Data */ + +DEBTAB vh_debug[] = { + {"REG", DBG_REG}, + {"INT", DBG_INT}, + {"XMT", DBG_XMT}, + {"RCV", DBG_RCV}, + {0} +}; + /* Forward references */ static t_stat vh_rd (int32 *data, int32 PA, int32 access); static t_stat vh_wr (int32 data, int32 PA, int32 access); @@ -294,842 +314,869 @@ static t_stat vh_clear (int32 vh, t_bool flag); static t_stat vh_reset (DEVICE *dptr); static t_stat vh_attach (UNIT *uptr, char *cptr); static t_stat vh_detach (UNIT *uptr); -static t_stat vh_show_debug (FILE *st, UNIT *uptr, int32 val, void *desc); +static t_stat vh_show_detail (FILE *st, UNIT *uptr, int32 val, void *desc); static t_stat vh_show_rbuf (FILE *st, UNIT *uptr, int32 val, void *desc); static t_stat vh_show_txq (FILE *st, UNIT *uptr, int32 val, void *desc); static t_stat vh_putc (int32 vh, TMLX *lp, int32 chan, int32 data); static void doDMA (int32 vh, int32 chan); +static t_stat vh_setnl (UNIT *uptr, int32 val, char *cptr, void *desc); +static t_stat vh_set_log (UNIT *uptr, int32 val, char *cptr, void *desc); +static t_stat vh_set_nolog (UNIT *uptr, int32 val, char *cptr, void *desc); +static t_stat vh_show_log (FILE *st, UNIT *uptr, int32 val, void *desc); int32 tmxr_send_buffered_data (TMLN *lp); /* SIMH I/O Structures */ static DIB vh_dib = { - IOBA_VH, - IOLN_VH * VH_MUXES, - &vh_rd, /* read */ - &vh_wr, /* write */ - 2, /* # of vectors */ - IVCL (VHRX), - VEC_VHRX, - { &vh_rxinta, &vh_txinta } /* int. ack. routines */ + IOBA_VH, + IOLN_VH * VH_MUXES, + &vh_rd, /* read */ + &vh_wr, /* write */ + 2, /* # of vectors */ + IVCL (VHRX), + VEC_VHRX, + { &vh_rxinta, &vh_txinta } /* int. ack. routines */ }; static UNIT vh_unit[VH_MUXES] = { - { UDATA (&vh_svc, UNIT_IDLE|UNIT_ATTABLE, 0) }, - { UDATA (&vh_svc, UNIT_IDLE|UNIT_ATTABLE, 0) }, - { UDATA (&vh_svc, UNIT_IDLE|UNIT_ATTABLE, 0) }, - { UDATA (&vh_svc, UNIT_IDLE|UNIT_ATTABLE, 0) }, + { UDATA (&vh_svc, UNIT_IDLE|UNIT_ATTABLE, 0) }, }; static const REG vh_reg[] = { - { BRDATA (CSR, vh_csr, DEV_RDX, 16, VH_MUXES) }, - { GRDATA (DEVADDR, vh_dib.ba, DEV_RDX, 32, 0), REG_HRO }, - { GRDATA (DEVVEC, vh_dib.vec, DEV_RDX, 16, 0), REG_HRO }, - { NULL } + { BRDATA (CSR, vh_csr, DEV_RDX, 16, VH_MUXES) }, + { GRDATA (DEVADDR, vh_dib.ba, DEV_RDX, 32, 0), REG_HRO }, + { GRDATA (DEVVEC, vh_dib.vec, DEV_RDX, 16, 0), REG_HRO }, + { NULL } }; static const MTAB vh_mod[] = { - { UNIT_MODEDHU, 0, "DHV mode", "DHV", NULL }, - { UNIT_MODEDHU, UNIT_MODEDHU, "DHU mode", "DHU", NULL }, - { UNIT_FASTDMA, 0, NULL, "NORMAL", NULL }, - { UNIT_FASTDMA, UNIT_FASTDMA, "fast DMA", "FASTDMA", NULL }, - { UNIT_MODEM, 0, NULL, "NOMODEM", NULL }, - { UNIT_MODEM, UNIT_MODEM, "modem", "MODEM", NULL }, - { UNIT_HANGUP, 0, NULL, "NOHANGUP", NULL }, - { UNIT_HANGUP, UNIT_HANGUP, "hangup", "HANGUP", NULL }, - { MTAB_XTD|MTAB_VDV, 020, "ADDRESS", "ADDRESS", - &set_addr, &show_addr, NULL }, - { MTAB_XTD|MTAB_VDV, VH_LINES, "VECTOR", "VECTOR", - &set_vec, &show_vec_mux, (void *) &vh_desc }, - { MTAB_XTD|MTAB_VDV, 0, NULL, "AUTOCONFIGURE", - &set_addr_flt, NULL, NULL }, - /* this one is dangerous, don't use yet */ - { MTAB_XTD|MTAB_VDV, 0, "LINES", "LINES", - NULL, &tmxr_show_lines, (void *) &vh_desc }, - { UNIT_ATT, UNIT_ATT, "summary", NULL, + { UNIT_MODEDHU, 0, "DHV mode", "DHV", NULL }, + { UNIT_MODEDHU, UNIT_MODEDHU, "DHU mode", "DHU", NULL }, + { UNIT_FASTDMA, 0, NULL, "NORMAL", NULL }, + { UNIT_FASTDMA, UNIT_FASTDMA, "fast DMA", "FASTDMA", NULL }, + { UNIT_MODEM, 0, NULL, "NOMODEM", NULL }, + { UNIT_MODEM, UNIT_MODEM, "modem", "MODEM", NULL }, + { UNIT_HANGUP, 0, NULL, "NOHANGUP", NULL }, + { UNIT_HANGUP, UNIT_HANGUP, "hangup", "HANGUP", NULL }, + { MTAB_XTD|MTAB_VDV, 020, "ADDRESS", "ADDRESS", + &set_addr, &show_addr, NULL }, + { MTAB_XTD|MTAB_VDV, VH_LINES, "VECTOR", "VECTOR", + &set_vec, &show_vec_mux, (void *) &vh_desc }, + { MTAB_XTD|MTAB_VDV, 0, NULL, "AUTOCONFIGURE", + &set_addr_flt, NULL, NULL }, + { MTAB_XTD|MTAB_VDV, 0, "LINES", "LINES", + &vh_setnl, &tmxr_show_lines, (void *) &vh_desc }, + { UNIT_ATT, UNIT_ATT, "summary", NULL, NULL, &tmxr_show_summ, (void *) &vh_desc }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, - NULL, &tmxr_show_cstat, (void *) &vh_desc }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, - NULL, &tmxr_show_cstat, (void *) &vh_desc }, - { MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT", - &tmxr_dscln, NULL, &vh_desc }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "DEBUG", NULL, - NULL, &vh_show_debug, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "RBUF", NULL, - NULL, &vh_show_rbuf, NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "TXQ", NULL, - NULL, &vh_show_txq, NULL }, - { 0 } + { MTAB_XTD|MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL, + NULL, &tmxr_show_cstat, (void *) &vh_desc }, + { MTAB_XTD|MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, + NULL, &tmxr_show_cstat, (void *) &vh_desc }, + { MTAB_XTD|MTAB_VDV, 1, NULL, "DISCONNECT", + &tmxr_dscln, NULL, &vh_desc }, + { MTAB_XTD|MTAB_VDV | MTAB_NMO, 0, "DETAIL", NULL, + NULL, &vh_show_detail, NULL }, + { MTAB_XTD|MTAB_VDV | MTAB_NMO, 0, "RBUF", NULL, + NULL, &vh_show_rbuf, NULL }, + { MTAB_XTD|MTAB_VDV | MTAB_NMO, 0, "TXQ", NULL, + NULL, &vh_show_txq, NULL }, + { MTAB_XTD|MTAB_VDV | MTAB_NC, 0, NULL, "LOG", + &vh_set_log, NULL, &vh_desc }, + { MTAB_XTD|MTAB_VDV | MTAB_NC, 0, NULL, "NOLOG", + &vh_set_nolog, NULL, &vh_desc }, + { MTAB_XTD|MTAB_VDV | MTAB_NMO, 0, "LOG", NULL, + NULL, &vh_show_log, &vh_desc }, + { 0 } }; DEVICE vh_dev = { - "VH", /* name */ - vh_unit, /* units */ - (REG *)vh_reg, /* registers */ - (MTAB *)vh_mod, /* modifiers */ - VH_MUXES, /* # units */ - DEV_RDX, /* address radix */ - 8, /* address width */ - 1, /* address increment */ - DEV_RDX, /* data radix */ - 8, /* data width */ - NULL, /* examine routine */ - NULL, /* deposit routine */ - &vh_reset, /* reset routine */ - NULL, /* boot routine */ - &vh_attach, /* attach routine */ - &vh_detach, /* detach routine */ - (void *)&vh_dib, /* context */ - DEV_FLTA | DEV_DISABLE | DEV_DIS |DEV_NET | DEV_QBUS | DEV_UBUS, /* flags */ + "VH", /* name */ + vh_unit, /* units */ + (REG *)vh_reg, /* registers */ + (MTAB *)vh_mod, /* modifiers */ + VH_MUXES, /* # units */ + DEV_RDX, /* address radix */ + 8, /* address width */ + 1, /* address increment */ + DEV_RDX, /* data radix */ + 8, /* data width */ + NULL, /* examine routine */ + NULL, /* deposit routine */ + &vh_reset, /* reset routine */ + NULL, /* boot routine */ + &vh_attach, /* attach routine */ + &vh_detach, /* detach routine */ + (void *)&vh_dib,/* context */ + DEV_FLTA | DEV_DISABLE | DEV_DIS |DEV_NET | DEV_QBUS | DEV_UBUS | DEV_DEBUG, /* flags */ + 0, vh_debug }; +/* Register names for Debug tracing */ +static char *vh_rd_dhv_regs[] = + {"CSR ", "RBUF ", "LPR ", "STAT ", "LNCTRL", "TBFAD1", "TBFAD2", "TBFCNT" }; +static char *vh_wr_dhv_regs[] = + {"CSR ", "TXCHAR", "LPR ", "STAT ", "LNCTRL", "TBFAD1", "TBFAD2", "TBFCNT" }; +static char *vh_rd_dhu_regs[] = + {"CSR ", "RBUF ", "LPR ", "FIFOSZ", "LNCTRL", "TBFAD1", "TBFAD2", "TBFCNT" }; +static char *vh_wr_dhu_regs[] = + {"CSR ", "RXTIMR", "LPR ", "FIFODT", "LNCTRL", "TBFAD1", "TBFAD2", "TBFCNT" }; + /* Interrupt routines */ -static void vh_clr_rxint ( int32 vh ) +static void vh_clr_rxint ( int32 vh ) { - vh_rxi &= ~(1 << vh); - if (vh_rxi == 0) - CLR_INT (VHRX); - else - SET_INT (VHRX); + vh_rxi &= ~(1 << vh); + if (vh_rxi == 0) + CLR_INT (VHRX); + else + SET_INT (VHRX); } -static void vh_set_rxint ( int32 vh ) +static void vh_set_rxint ( int32 vh ) { - vh_rxi |= (1 << vh); - SET_INT (VHRX); + vh_rxi |= (1 << vh); + SET_INT (VHRX); } /* RX interrupt ack. (bus cycle) */ static int32 vh_rxinta (void) { - int32 vh; + int32 vh; - for (vh = 0; vh < VH_MUXES; vh++) { - if (vh_rxi & (1 << vh)) { - vh_clr_rxint (vh); - return (vh_dib.vec + (vh * 010)); - } - } - return (0); + for (vh = 0; vh < vh_desc.lines/VH_LINES; vh++) { + if (vh_rxi & (1 << vh)) { + sim_debug(DBG_INT, &vh_dev, "vh_rzinta(vh=%d)\n", vh); + vh_clr_rxint (vh); + return (vh_dib.vec + (vh * 010)); + } + } + return (0); } -static void vh_clr_txint ( int32 vh ) +static void vh_clr_txint ( int32 vh ) { - vh_txi &= ~(1 << vh); - if (vh_txi == 0) - CLR_INT (VHTX); - else - SET_INT (VHTX); + vh_txi &= ~(1 << vh); + if (vh_txi == 0) + CLR_INT (VHTX); + else + SET_INT (VHTX); } -static void vh_set_txint ( int32 vh ) +static void vh_set_txint ( int32 vh ) { - vh_txi |= (1 << vh); - SET_INT (VHTX); + vh_txi |= (1 << vh); + SET_INT (VHTX); } /* TX interrupt ack. (bus cycle) */ static int32 vh_txinta (void) { - int32 vh; + int32 vh; - for (vh = 0; vh < VH_MUXES; vh++) { - if (vh_txi & (1 << vh)) { - vh_clr_txint (vh); - return (vh_dib.vec + 4 + (vh * 010)); - } - } - return (0); + for (vh = 0; vh < vh_desc.lines/VH_LINES; vh++) { + if (vh_txi & (1 << vh)) { + sim_debug(DBG_INT, &vh_dev, "vh_txinta(vh=%d)\n", vh); + vh_clr_txint (vh); + return (vh_dib.vec + 4 + (vh * 010)); + } + } + return (0); } /* RX FIFO get/put routines */ /* return 0 on success, -1 on FIFO overflow */ -static int32 fifo_put ( int32 vh, - TMLX *lp, - int32 data ) +static int32 fifo_put ( int32 vh, + TMLX *lp, + int32 data ) { - int32 status = 0; + int32 status = 0; - if (lp == NULL) - goto override; - /* this might have to move to vh_getc() */ - if ((lp->lnctrl & LNCTRL_OAUTO) && ((data & RBUF_DIAG) == 0)) { - TMLX *l0p; - /* implement transmitted data flow control */ - switch (data & 0377) { - case XON: - lp->tbuf2 |= TB2_TX_ENA; - goto common; - case XOFF: - lp->tbuf2 &= ~TB2_TX_ENA; - common: - /* find line 0 for this controller */ - l0p = &vh_parm[vh * VH_LINES]; - if (l0p->lpr & LPR_DISAB_XRPT) - return (0); - break; - default: - break; - } - } + if (lp == NULL) + goto override; + /* this might have to move to vh_getc() */ + if ((lp->lnctrl & LNCTRL_OAUTO) && ((data & RBUF_DIAG) == 0)) { + TMLX *l0p; + /* implement transmitted data flow control */ + switch (data & 0377) { + case XON: + lp->tbuf2 |= TB2_TX_ENA; + goto common; + case XOFF: + lp->tbuf2 &= ~TB2_TX_ENA; + common: + /* find line 0 for this controller */ + l0p = &vh_parm[vh * VH_LINES]; + if (l0p->lpr & LPR_DISAB_XRPT) + return (0); + break; + default: + break; + } + } /* BUG: which of the following 2 is correct? */ - /* if ((data & RBUF_DIAG) == RBUF_DIAG) */ - if (data & RBUF_DIAG) - goto override; - if (((lp->lnctrl >> LNCTRL_V_MAINT) & LNCTRL_M_MAINT) == 2) - goto override; - if (!(lp->lnctrl & LNCTRL_RX_ENA)) - return (0); + /* if ((data & RBUF_DIAG) == RBUF_DIAG) */ + if (data & RBUF_DIAG) + goto override; + if (((lp->lnctrl >> LNCTRL_V_MAINT) & LNCTRL_M_MAINT) == 2) + goto override; + if (!(lp->lnctrl & LNCTRL_RX_ENA)) + return (0); override: - vh_csr[vh] |= CSR_RX_DATA_AVAIL; - if (rbuf_idx[vh] < FIFO_SIZE) { - vh_rbuf[vh][rbuf_idx[vh]] = data; - rbuf_idx[vh] += 1; - } else { - vh_ovrrun[vh] |= (1 << RBUF_GETLINE (data)); - status = -1; - } - if (vh_csr[vh] & CSR_RXIE) { - if (vh_unit[vh].flags & UNIT_MODEDHU) { - /* was it a modem status change? */ - if ((data & RBUF_DIAG) == RBUF_DIAG) - vh_set_rxint (vh); - /* look for FIFO alarm @ 3/4 full */ - else if (rbuf_idx[vh] == FIFO_ALARM) - vh_set_rxint (vh); - else if (vh_timer[vh] == 0) - ; /* nothing, infinite timeout */ - else if (vh_timer[vh] == 1) - vh_set_rxint (vh); - else if (vh_timeo[vh] == 0) - vh_timeo[vh] = MS2SIMH (vh_timer[vh]) + 1; - } else { - /* Interrupt on transition _from_ an empty FIFO */ - if (rbuf_idx[vh] == 1) - vh_set_rxint (vh); - } - } - if (rbuf_idx[vh] > FIFO_ALARM) - vh_crit |= (1 << vh); - /* Implement RX FIFO-level flow control */ - if (lp != NULL) { - if ((lp->lnctrl & LNCTRL_FORCE_XOFF) || - ((vh_crit & (1 << vh)) && (lp->lnctrl & LNCTRL_IAUTO))) { - int32 chan = RBUF_GETLINE(data); - vh_stall[vh] ^= (1 << chan); - /* send XOFF every other character received */ - if (vh_stall[vh] & (1 << chan)) - vh_putc (vh, lp, chan, XOFF); - } - } - return (status); + vh_csr[vh] |= CSR_RX_DATA_AVAIL; + if (rbuf_idx[vh] < FIFO_SIZE) { + vh_rbuf[vh][rbuf_idx[vh]] = data; + rbuf_idx[vh] += 1; + } else { + vh_ovrrun[vh] |= (1 << RBUF_GETLINE (data)); + status = -1; + } + if (vh_csr[vh] & CSR_RXIE) { + if (vh_unit[vh].flags & UNIT_MODEDHU) { + /* was it a modem status change? */ + if ((data & RBUF_DIAG) == RBUF_DIAG) + vh_set_rxint (vh); + /* look for FIFO alarm @ 3/4 full */ + else if (rbuf_idx[vh] == FIFO_ALARM) + vh_set_rxint (vh); + else if (vh_timer[vh] == 0) + ; /* nothing, infinite timeout */ + else if (vh_timer[vh] == 1) + vh_set_rxint (vh); + else if (vh_timeo[vh] == 0) + vh_timeo[vh] = MS2SIMH (vh_timer[vh]) + 1; + } else { + /* Interrupt on transition _from_ an empty FIFO */ + if (rbuf_idx[vh] == 1) + vh_set_rxint (vh); + } + } + if (rbuf_idx[vh] > FIFO_ALARM) + vh_crit |= (1 << vh); + /* Implement RX FIFO-level flow control */ + if (lp != NULL) { + if ((lp->lnctrl & LNCTRL_FORCE_XOFF) || + ((vh_crit & (1 << vh)) && (lp->lnctrl & LNCTRL_IAUTO))) { + int32 chan = RBUF_GETLINE(data); + vh_stall[vh] ^= (1 << chan); + /* send XOFF every other character received */ + if (vh_stall[vh] & (1 << chan)) + vh_putc (vh, lp, chan, XOFF); + } + } + return (status); } -static int32 fifo_get ( int32 vh ) +static int32 fifo_get ( int32 vh ) { - int32 data, i; + int32 data, i; - if (rbuf_idx[vh] == 0) { - vh_csr[vh] &= ~CSR_RX_DATA_AVAIL; - return (0); - } - /* pick off the first character, mark valid */ - data = vh_rbuf[vh][0] | RBUF_DATA_VALID; - /* move the remainder up */ - rbuf_idx[vh] -= 1; - for (i = 0; i < rbuf_idx[vh]; i++) - vh_rbuf[vh][i] = vh_rbuf[vh][i + 1]; - /* rbuf_idx[vh] -= 1; */ - /* look for any previous overruns */ - if (vh_ovrrun[vh]) { - for (i = 0; i < VH_LINES; i++) { - if (vh_ovrrun[vh] & (1 << i)) { - fifo_put (vh, NULL, RBUF_OVERRUN_ERR | - RBUF_PUTLINE (i)); - vh_ovrrun[vh] &= ~(1 << i); - break; - } - } - } - /* recompute FIFO alarm condition */ - if ((rbuf_idx[vh] < FIFO_HALF) && (vh_crit & (1 << vh))) { - vh_crit &= ~(1 << vh); - /* send XON to all XOFF'd channels on this controller */ - for (i = 0; i < VH_LINES; i++) { - TMLX *lp = &vh_parm[(vh * VH_LINES) + i]; - if (lp->lnctrl & LNCTRL_FORCE_XOFF) - continue; - if (vh_stall[vh] & (1 << i)) { - vh_putc (vh, NULL, i, XON); - vh_stall[vh] &= ~(1 << i); - } - } - } - return (data & 0177777); + if (rbuf_idx[vh] == 0) { + vh_csr[vh] &= ~CSR_RX_DATA_AVAIL; + return (0); + } + /* pick off the first character, mark valid */ + data = vh_rbuf[vh][0] | RBUF_DATA_VALID; + /* move the remainder up */ + rbuf_idx[vh] -= 1; + for (i = 0; i < rbuf_idx[vh]; i++) + vh_rbuf[vh][i] = vh_rbuf[vh][i + 1]; + /* rbuf_idx[vh] -= 1; */ + /* look for any previous overruns */ + if (vh_ovrrun[vh]) { + for (i = 0; i < VH_LINES; i++) { + if (vh_ovrrun[vh] & (1 << i)) { + fifo_put (vh, NULL, RBUF_OVERRUN_ERR | + RBUF_PUTLINE (i)); + vh_ovrrun[vh] &= ~(1 << i); + break; + } + } + } + /* recompute FIFO alarm condition */ + if ((rbuf_idx[vh] < FIFO_HALF) && (vh_crit & (1 << vh))) { + vh_crit &= ~(1 << vh); + /* send XON to all XOFF'd channels on this controller */ + for (i = 0; i < VH_LINES; i++) { + TMLX *lp = &vh_parm[(vh * VH_LINES) + i]; + if (lp->lnctrl & LNCTRL_FORCE_XOFF) + continue; + if (vh_stall[vh] & (1 << i)) { + vh_putc (vh, NULL, i, XON); + vh_stall[vh] &= ~(1 << i); + } + } + } + return (data & 0177777); } /* TX Q manipulation */ -static int32 dq_tx_report ( int32 vh ) +static int32 dq_tx_report ( int32 vh ) { - int32 data, i; + int32 data, i; - if (txq_idx[vh] == 0) - return (0); - data = vh_txq[vh][0]; - txq_idx[vh] -= 1; - for (i = 0; i < txq_idx[vh]; i++) - vh_txq[vh][i] = vh_txq[vh][i + 1]; - /* txq_idx[vh] -= 1; */ - return (data & 0177777); + if (txq_idx[vh] == 0) + return (0); + data = vh_txq[vh][0]; + txq_idx[vh] -= 1; + for (i = 0; i < txq_idx[vh]; i++) + vh_txq[vh][i] = vh_txq[vh][i + 1]; + /* txq_idx[vh] -= 1; */ + return (data & 0177777); } -static void q_tx_report ( int32 vh, - int32 data ) +static void q_tx_report ( int32 vh, + int32 data ) { - if (vh_csr[vh] & CSR_TXIE) - vh_set_txint (vh); - if (txq_idx[vh] >= TXQ_SIZE) { + if (vh_csr[vh] & CSR_TXIE) + vh_set_txint (vh); + if (txq_idx[vh] >= TXQ_SIZE) { /* BUG: which of the following 2 is correct? */ - dq_tx_report (vh); - /* return; */ - } - vh_txq[vh][txq_idx[vh]] = CSR_TX_ACTION | data; - txq_idx[vh] += 1; + dq_tx_report (vh); + /* return; */ + } + vh_txq[vh][txq_idx[vh]] = CSR_TX_ACTION | data; + txq_idx[vh] += 1; } /* Channel get/put routines */ -static void HangupModem ( int32 vh, - TMLX *lp, - int32 chan ) +static void HangupModem ( int32 vh, + TMLX *lp, + int32 chan ) { - if (vh_unit[vh].flags & UNIT_MODEM) - lp->lstat &= ~(STAT_DCD|STAT_DSR|STAT_CTS|STAT_RI); - if (lp->lnctrl & LNCTRL_LINK_TYPE) - /* RBUF<0> = 0 for modem status */ - fifo_put (vh, lp, RBUF_DIAG | - RBUF_PUTLINE (chan) | - ((lp->lstat >> 8) & 0376)); - /* BUG: check for overflow above */ + if (vh_unit[vh].flags & UNIT_MODEM) + lp->lstat &= ~(STAT_DCD|STAT_DSR|STAT_CTS|STAT_RI); + if (lp->lnctrl & LNCTRL_LINK_TYPE) + /* RBUF<0> = 0 for modem status */ + fifo_put (vh, lp, RBUF_DIAG | + RBUF_PUTLINE (chan) | + ((lp->lstat >> 8) & 0376)); + /* BUG: check for overflow above */ } /* TX a character on a line, regardless of the TX enable state */ -static t_stat vh_putc ( int32 vh, - TMLX *lp, - int32 chan, - int32 data ) +static t_stat vh_putc ( int32 vh, + TMLX *lp, + int32 chan, + int32 data ) { - int32 val; - t_stat status = SCPE_OK; + int32 val; + t_stat status = SCPE_OK; - /* truncate to desired character length */ - data &= bitmask[(lp->lpr >> LPR_V_CHAR_LGTH) & LPR_M_CHAR_LGTH]; - switch ((lp->lnctrl >> LNCTRL_V_MAINT) & LNCTRL_M_MAINT) { - case 0: /* normal */ -#if 0 - /* check for (external) loopback setting */ - switch (vh_loop[vh]) { - default: - case LOOP_NONE: - break; - } + /* truncate to desired character length */ + data &= bitmask[(lp->lpr >> LPR_V_CHAR_LGTH) & LPR_M_CHAR_LGTH]; + switch ((lp->lnctrl >> LNCTRL_V_MAINT) & LNCTRL_M_MAINT) { + case 0: /* normal */ +#if 0 + /* check for (external) loopback setting */ + switch (vh_loop[vh]) { + default: + case LOOP_NONE: + break; + } #endif - status = tmxr_putc_ln (lp->tmln, data); - if (status == SCPE_LOST) { - tmxr_reset_ln (lp->tmln); - HangupModem (vh, lp, chan); - } else if (status == SCPE_STALL) { - /* let's flush and try again */ - tmxr_send_buffered_data (lp->tmln); - status = tmxr_putc_ln (lp->tmln, data); - } - break; - case 1: /* auto echo */ - break; - case 2: /* local loopback */ - if (lp->lnctrl & LNCTRL_BREAK) - val = fifo_put (vh, lp, - RBUF_FRAME_ERR | RBUF_PUTLINE (chan)); - else - val = fifo_put (vh, lp, - RBUF_PUTLINE (chan) | data); - status = (val < 0) ? SCPE_TTMO : SCPE_OK; - break; - default: /* remote loopback */ - break; - } - return (status); + status = tmxr_putc_ln (lp->tmln, data); + if (status == SCPE_LOST) { + tmxr_reset_ln (lp->tmln); + HangupModem (vh, lp, chan); + } else if (status == SCPE_STALL) { + /* let's flush and try again */ + tmxr_send_buffered_data (lp->tmln); + status = tmxr_putc_ln (lp->tmln, data); + } + break; + case 1: /* auto echo */ + break; + case 2: /* local loopback */ + if (lp->lnctrl & LNCTRL_BREAK) + val = fifo_put (vh, lp, + RBUF_FRAME_ERR | RBUF_PUTLINE (chan)); + else + val = fifo_put (vh, lp, + RBUF_PUTLINE (chan) | data); + status = (val < 0) ? SCPE_TTMO : SCPE_OK; + break; + default: /* remote loopback */ + break; + } + return (status); } /* Retrieve all stored input from TMXR and place in RX FIFO */ -static void vh_getc ( int32 vh ) +static void vh_getc ( int32 vh ) { - uint32 i, c; - TMLX *lp; + uint32 i, c; + TMLX *lp; - for (i = 0; i < VH_LINES; i++) { - lp = &vh_parm[(vh * VH_LINES) + i]; - while ((c = tmxr_getc_ln (lp->tmln)) != 0) { - if (c & SCPE_BREAK) { - fifo_put (vh, lp, - RBUF_FRAME_ERR | RBUF_PUTLINE (i)); - /* BUG: check for overflow above */ - } else { - c &= bitmask[(lp->lpr >> LPR_V_CHAR_LGTH) & - LPR_M_CHAR_LGTH]; - fifo_put (vh, lp, RBUF_PUTLINE (i) | c); - /* BUG: check for overflow above */ - } - } - } + for (i = 0; i < VH_LINES; i++) { + lp = &vh_parm[(vh * VH_LINES) + i]; + while ((c = tmxr_getc_ln (lp->tmln)) != 0) { + if (c & SCPE_BREAK) { + fifo_put (vh, lp, + RBUF_FRAME_ERR | RBUF_PUTLINE (i)); + /* BUG: check for overflow above */ + } else { + c &= bitmask[(lp->lpr >> LPR_V_CHAR_LGTH) & + LPR_M_CHAR_LGTH]; + fifo_put (vh, lp, RBUF_PUTLINE (i) | c); + /* BUG: check for overflow above */ + } + } + } } /* I/O dispatch routines */ -static t_stat vh_rd ( int32 *data, - int32 PA, - int32 access ) +static t_stat vh_rd ( int32 *data, + int32 PA, + int32 access ) { - int32 vh = ((PA - vh_dib.ba) >> 4) & VH_MNOMASK, line; - TMLX *lp; + int32 vh = ((PA - vh_dib.ba) >> 4) & VH_MNOMASK, line; + TMLX *lp; - switch ((PA >> 1) & 7) { - case 0: /* CSR */ - *data = vh_csr[vh] | dq_tx_report (vh); - vh_csr[vh] &= ~0117400; /* clear the read-once bits */ - break; - case 1: /* RBUF */ - *data = fifo_get (vh); - break; - case 2: /* LPR */ - if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) { - *data = 0; - break; - } - line = (vh * VH_LINES) + CSR_GETCHAN (vh_csr[vh]); - lp = &vh_parm[line]; - *data = lp->lpr; - break; - case 3: /* STAT/FIFOSIZE */ - if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) { - *data = 0; - break; - } - line = (vh * VH_LINES) + CSR_GETCHAN (vh_csr[vh]); - lp = &vh_parm[line]; - *data = (lp->lstat & ~0377) | /* modem status */ -#if 0 - (64 - tmxr_tqln (lp->tmln)); + switch ((PA >> 1) & 7) { + case 0: /* CSR */ + *data = vh_csr[vh] | dq_tx_report (vh); + vh_csr[vh] &= ~0117400; /* clear the read-once bits */ + break; + case 1: /* RBUF */ + *data = fifo_get (vh); + break; + case 2: /* LPR */ + if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) { + *data = 0; + break; + } + line = (vh * VH_LINES) + CSR_GETCHAN (vh_csr[vh]); + lp = &vh_parm[line]; + *data = lp->lpr; + break; + case 3: /* STAT/FIFOSIZE */ + if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) { + *data = 0; + break; + } + line = (vh * VH_LINES) + CSR_GETCHAN (vh_csr[vh]); + lp = &vh_parm[line]; + *data = (lp->lstat & ~0377) | /* modem status */ +#if 0 + (64 - tmxr_tqln (lp->tmln)); fprintf (stderr, "\rtqln %d\n", 64 - tmxr_tqln (lp->tmln)); #else - 64; + 64; #endif - break; - case 4: /* LNCTRL */ - if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) { - *data = 0; - break; - } - line = (vh * VH_LINES) + CSR_GETCHAN (vh_csr[vh]); - lp = &vh_parm[line]; - *data = lp->lnctrl; - break; - case 5: /* TBUFFAD1 */ - if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) { - *data = 0; - break; - } - line = (vh * VH_LINES) + CSR_GETCHAN (vh_csr[vh]); - lp = &vh_parm[line]; - *data = lp->tbuf1; - break; - case 6: /* TBUFFAD2 */ - if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) { - *data = 0; - break; - } - line = (vh * VH_LINES) + CSR_GETCHAN (vh_csr[vh]); - lp = &vh_parm[line]; - *data = lp->tbuf2; - break; - case 7: /* TBUFFCT */ - if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) { - *data = 0; - break; - } - line = (vh * VH_LINES) + CSR_GETCHAN (vh_csr[vh]); - lp = &vh_parm[line]; - *data = lp->tbuffct; - break; - default: - /* can't happen */ - break; - } - return (SCPE_OK); + break; + case 4: /* LNCTRL */ + if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) { + *data = 0; + break; + } + line = (vh * VH_LINES) + CSR_GETCHAN (vh_csr[vh]); + lp = &vh_parm[line]; + *data = lp->lnctrl; + break; + case 5: /* TBUFFAD1 */ + if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) { + *data = 0; + break; + } + line = (vh * VH_LINES) + CSR_GETCHAN (vh_csr[vh]); + lp = &vh_parm[line]; + *data = lp->tbuf1; + break; + case 6: /* TBUFFAD2 */ + if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) { + *data = 0; + break; + } + line = (vh * VH_LINES) + CSR_GETCHAN (vh_csr[vh]); + lp = &vh_parm[line]; + *data = lp->tbuf2; + break; + case 7: /* TBUFFCT */ + if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) { + *data = 0; + break; + } + line = (vh * VH_LINES) + CSR_GETCHAN (vh_csr[vh]); + lp = &vh_parm[line]; + *data = lp->tbuffct; + break; + default: + /* can't happen */ + break; + } + + sim_debug(DBG_REG, &vh_dev, "vh_rd(PA=0x%08X [%s], access=%d, data=0x%X)\n", PA, + ((vh_unit[vh].flags & UNIT_MODEDHU) ? vh_rd_dhu_regs : vh_rd_dhv_regs)[(PA >> 1) & 07], access, data); + + return (SCPE_OK); } -static t_stat vh_wr ( int32 data, - int32 PA, - int32 access ) +static t_stat vh_wr ( int32 data, + int32 PA, + int32 access ) { - int32 vh = ((PA - vh_dib.ba) >> 4) & VH_MNOMASK, line; - TMLX *lp; + int32 vh = ((PA - vh_dib.ba) >> 4) & VH_MNOMASK, line; + TMLX *lp; - switch ((PA >> 1) & 7) { - case 0: /* CSR, but no read-modify-write */ - if (access == WRITEB) - data = (PA & 1) ? - (vh_csr[vh] & 0377) | (data << 8) : - (vh_csr[vh] & ~0377) | (data & 0377); - if (data & CSR_MASTER_RESET) { - if ((vh_unit[vh].flags & UNIT_MODEDHU) && (data & CSR_SKIP)) - data &= ~CSR_MASTER_RESET; - sim_activate (&vh_unit[vh], clk_cosched (tmxr_poll)); - /* vh_mcount[vh] = 72; */ /* 1.2 seconds */ - vh_mcount[vh] = MS2SIMH (1200); /* 1.2 seconds */ - } - if ((data & CSR_RXIE) == 0) - vh_clr_rxint (vh); - /* catch the RXIE transition if the FIFO is not empty */ - else if (((vh_csr[vh] & CSR_RXIE) == 0) && - (rbuf_idx[vh] != 0)) { - if (vh_unit[vh].flags & UNIT_MODEDHU) { - if (rbuf_idx[vh] > FIFO_ALARM) - vh_set_rxint (vh); - else if (vh_timer[vh] == 0) - ; - else if (vh_timer[vh] == 1) - vh_set_rxint (vh); - else if (vh_timeo[vh] == 0) - vh_timeo[vh] = MS2SIMH (vh_timer[vh]) + 1; - } else { - vh_set_rxint (vh); - } - } - if ((data & CSR_TXIE) == 0) - vh_clr_txint (vh); - else if (((vh_csr[vh] & CSR_TXIE) == 0) && - (txq_idx[vh] != 0)) - vh_set_txint (vh); - vh_csr[vh] = (vh_csr[vh] & ~((uint16) CSR_RW)) | (data & (uint16) CSR_RW); - break; - case 1: /* TXCHAR/RXTIMER */ - if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) - break; - if ((data == RESET_ABORT) && (vh_csr[vh] & CSR_MASTER_RESET)) { - vh_mcount[vh] = 1; - break; - } - if (vh_unit[vh].flags & UNIT_MODEDHU) { - if (CSR_GETCHAN (vh_csr[vh]) != 0) - break; - if (access == WRITEB) - data = (PA & 1) ? - (vh_timer[vh] & 0377) | (data << 8) : - (vh_timer[vh] & ~0377) | (data & 0377); - vh_timer[vh] = data & 0377; -#if 0 - if (vh_csr[vh] & CSR_RXIE) { - if (rbuf_idx[vh] > FIFO_ALARM) - vh_set_rxint (vh); - else if (vh_timer[vh] == 0) - ; - else if (vh_timer[vh] == 1) - vh_set_rxint (vh); - else if (vh_timeo[vh] == 0) - vh_timeo[vh] = MS2SIMH (vh_timer[vh]) + 1; - } + sim_debug(DBG_REG, &vh_dev, "vh_wr(PA=0x%08X [%s], access=%d, data=0x%X)\n", PA, + ((vh_unit[vh].flags & UNIT_MODEDHU) ? vh_wr_dhu_regs : vh_wr_dhv_regs)[(PA >> 1) & 07], access, data); + + switch ((PA >> 1) & 7) { + case 0: /* CSR, but no read-modify-write */ + if (access == WRITEB) + data = (PA & 1) ? + (vh_csr[vh] & 0377) | (data << 8) : + (vh_csr[vh] & ~0377) | (data & 0377); + if (data & CSR_MASTER_RESET) { + if ((vh_unit[vh].flags & UNIT_MODEDHU) && (data & CSR_SKIP)) + data &= ~CSR_MASTER_RESET; + if (vh == 0) /* Only start unit service on the first unit. Units are polled there */ + sim_activate (&vh_unit[vh], clk_cosched (tmxr_poll)); + /* vh_mcount[vh] = 72; */ /* 1.2 seconds */ + vh_mcount[vh] = MS2SIMH (1200); /* 1.2 seconds */ + } + if ((data & CSR_RXIE) == 0) + vh_clr_rxint (vh); + /* catch the RXIE transition if the FIFO is not empty */ + else if (((vh_csr[vh] & CSR_RXIE) == 0) && + (rbuf_idx[vh] != 0)) { + if (vh_unit[vh].flags & UNIT_MODEDHU) { + if (rbuf_idx[vh] > FIFO_ALARM) + vh_set_rxint (vh); + else if (vh_timer[vh] == 0) + ; + else if (vh_timer[vh] == 1) + vh_set_rxint (vh); + else if (vh_timeo[vh] == 0) + vh_timeo[vh] = MS2SIMH (vh_timer[vh]) + 1; + } else { + vh_set_rxint (vh); + } + } + if ((data & CSR_TXIE) == 0) + vh_clr_txint (vh); + else if (((vh_csr[vh] & CSR_TXIE) == 0) && + (txq_idx[vh] != 0)) + vh_set_txint (vh); + vh_csr[vh] = (vh_csr[vh] & ~((uint16) CSR_RW)) | (data & (uint16) CSR_RW); + break; + case 1: /* TXCHAR/RXTIMER */ + if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) + break; + if ((data == RESET_ABORT) && (vh_csr[vh] & CSR_MASTER_RESET)) { + vh_mcount[vh] = 1; + break; + } + if (vh_unit[vh].flags & UNIT_MODEDHU) { + if (CSR_GETCHAN (vh_csr[vh]) != 0) + break; + if (access == WRITEB) + data = (PA & 1) ? + (vh_timer[vh] & 0377) | (data << 8) : + (vh_timer[vh] & ~0377) | (data & 0377); + vh_timer[vh] = data & 0377; +#if 0 + if (vh_csr[vh] & CSR_RXIE) { + if (rbuf_idx[vh] > FIFO_ALARM) + vh_set_rxint (vh); + else if (vh_timer[vh] == 0) + ; + else if (vh_timer[vh] == 1) + vh_set_rxint (vh); + else if (vh_timeo[vh] == 0) + vh_timeo[vh] = MS2SIMH (vh_timer[vh]) + 1; + } #endif - } else { - line = (vh * VH_LINES) + CSR_GETCHAN (vh_csr[vh]); - lp = &vh_parm[line]; - if (access == WRITEB) - data = (PA & 1) ? - (lp->txchar & 0377) | (data << 8) : - (lp->txchar & ~0377) | (data & 0377); - lp->txchar = data; /* TXCHAR */ - if (lp->txchar & TXCHAR_TX_DATA_VALID) { - if (lp->tbuf2 & TB2_TX_ENA) - vh_putc (vh, lp, - CSR_GETCHAN (vh_csr[vh]), - lp->txchar); - q_tx_report (vh, - CSR_GETCHAN (vh_csr[vh]) << CSR_V_TX_LINE); - lp->txchar &= ~TXCHAR_TX_DATA_VALID; - } - } - break; - case 2: /* LPR */ - if ((data == RESET_ABORT) && (vh_csr[vh] & CSR_MASTER_RESET)) { - vh_mcount[vh] = 1; - break; - } - if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) - break; - line = (vh * VH_LINES) + CSR_GETCHAN (vh_csr[vh]); - lp = &vh_parm[line]; - if (access == WRITEB) - data = (PA & 1) ? - (lp->lpr & 0377) | (data << 8) : - (lp->lpr & ~0377) | (data & 0377); - /* Modify only if CSR<3:0> == 0 */ - if (CSR_GETCHAN (vh_csr[vh]) != 0) - data &= ~LPR_DISAB_XRPT; - lp->lpr = data; - if (((lp->lpr >> LPR_V_DIAG) & LPR_M_DIAG) == 1) { - fifo_put (vh, lp, - RBUF_DIAG | - RBUF_PUTLINE (CSR_GETCHAN (vh_csr[vh])) | - BMP_OK); - /* BUG: check for overflow above */ - lp->lpr &= ~(LPR_M_DIAG << LPR_V_DIAG); - } - break; - case 3: /* STAT/FIFODATA */ - if ((data == RESET_ABORT) && (vh_csr[vh] & CSR_MASTER_RESET)) { - vh_mcount[vh] = 1; - break; - } - if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) - break; - line = (vh * VH_LINES) + CSR_GETCHAN (vh_csr[vh]); - lp = &vh_parm[line]; - if (vh_unit[vh].flags & UNIT_MODEDHU) { - /* high byte writes not allowed */ - if (PA & 1) - break; - /* transmit 1 or 2 characters */ - if (!(lp->tbuf2 & TB2_TX_ENA)) - break; - vh_putc (vh, lp, CSR_GETCHAN (vh_csr[vh]), data); - q_tx_report (vh, CSR_GETCHAN (vh_csr[vh]) << CSR_V_TX_LINE); - if (access != WRITEB) - vh_putc (vh, lp, CSR_GETCHAN (vh_csr[vh]), - data >> 8); - } - break; - case 4: /* LNCTRL */ - if ((data == RESET_ABORT) && (vh_csr[vh] & CSR_MASTER_RESET)) { - vh_mcount[vh] = 1; - break; - } - if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) - break; - line = (vh * VH_LINES) + CSR_GETCHAN (vh_csr[vh]); - lp = &vh_parm[line]; - if (access == WRITEB) - data = (PA & 1) ? - (lp->lnctrl & 0377) | (data << 8) : - (lp->lnctrl & ~0377) | (data & 0377); - /* catch the abort TX transition */ - if (!(lp->lnctrl & LNCTRL_TX_ABORT) && - (data & LNCTRL_TX_ABORT)) { - if ((lp->tbuf2 & TB2_TX_ENA) && - (lp->tbuf2 & TB2_TX_DMA_START)) { - lp->tbuf2 &= ~TB2_TX_DMA_START; - q_tx_report (vh, CSR_GETCHAN (vh_csr[vh]) << CSR_V_TX_LINE); - } - } - /* Implement program-initiated flow control */ - if ( (data & LNCTRL_FORCE_XOFF) && - !(lp->lnctrl & LNCTRL_FORCE_XOFF) ) { - if (!(lp->lnctrl & LNCTRL_IAUTO)) - vh_putc (vh, lp, CSR_GETCHAN (vh_csr[vh]), XOFF); - } else if ( !(data & LNCTRL_FORCE_XOFF) && - (lp->lnctrl & LNCTRL_FORCE_XOFF) ) { - if (!(lp->lnctrl & LNCTRL_IAUTO)) - vh_putc (vh, lp, CSR_GETCHAN (vh_csr[vh]), XON); - else if (!(vh_crit & (1 << vh)) && - (vh_stall[vh] & (1 << CSR_GETCHAN (vh_csr[vh])))) - vh_putc (vh, lp, CSR_GETCHAN (vh_csr[vh]), XON); - } - if ( (data & LNCTRL_IAUTO) && /* IAUTO 0->1 */ - !(lp->lnctrl & LNCTRL_IAUTO) ) { - if (!(lp->lnctrl & LNCTRL_FORCE_XOFF)) { - if (vh_crit & (1 << vh)) { - vh_putc (vh, lp, - CSR_GETCHAN (vh_csr[vh]), XOFF); - vh_stall[vh] |= (1 << CSR_GETCHAN (vh_csr[vh])); - } - } else { - /* vh_stall[vh] |= (1 << CSR_GETCHAN (vh_csr[vh])) */; - } - } else if ( !(data & LNCTRL_IAUTO) && - (lp->lnctrl & LNCTRL_IAUTO) ) { - if (!(lp->lnctrl & LNCTRL_FORCE_XOFF)) - vh_putc (vh, lp, CSR_GETCHAN (vh_csr[vh]), XON); - } - /* check modem control bits */ - if ( !(data & LNCTRL_DTR) && /* DTR 1->0 */ - (lp->lnctrl & LNCTRL_DTR)) { - if ((lp->tmln->conn) && (vh_unit[vh].flags & UNIT_HANGUP)) { - tmxr_linemsg (lp->tmln, "\r\nLine hangup\r\n"); - tmxr_reset_ln (lp->tmln); - } - HangupModem (vh, lp, CSR_GETCHAN (vh_csr[vh])); - } - lp->lnctrl = data; - lp->tmln->rcve = (data & LNCTRL_RX_ENA) ? 1 : 0; - tmxr_poll_rx (&vh_desc); - vh_getc (vh); - if (lp->lnctrl & LNCTRL_BREAK) - vh_putc (vh, lp, CSR_GETCHAN (vh_csr[vh]), 0); - break; - case 5: /* TBUFFAD1 */ - if ((data == RESET_ABORT) && (vh_csr[vh] & CSR_MASTER_RESET)) { - vh_mcount[vh] = 1; - break; - } - if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) - break; - line = (vh * VH_LINES) + CSR_GETCHAN (vh_csr[vh]); - lp = &vh_parm[line]; - if (access == WRITEB) - data = (PA & 1) ? - (lp->tbuf1 & 0377) | (data << 8) : - (lp->tbuf1 & ~0377) | (data & 0377); - lp->tbuf1 = data; - break; - case 6: /* TBUFFAD2 */ - if ((data == RESET_ABORT) && (vh_csr[vh] & CSR_MASTER_RESET)) { - vh_mcount[vh] = 1; - break; - } - if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) - break; - line = (vh * VH_LINES) + CSR_GETCHAN (vh_csr[vh]); - lp = &vh_parm[line]; - if (access == WRITEB) - data = (PA & 1) ? - (lp->tbuf2 & 0377) | (data << 8) : - (lp->tbuf2 & ~0377) | (data & 0377); - lp->tbuf2 = data; - /* if starting a DMA, clear DMA_ERR */ - if (vh_unit[vh].flags & UNIT_FASTDMA) { - doDMA (vh, CSR_GETCHAN (vh_csr[vh])); - tmxr_send_buffered_data (lp->tmln); - } - break; - case 7: /* TBUFFCT */ - if ((data == RESET_ABORT) && (vh_csr[vh] & CSR_MASTER_RESET)) { - vh_mcount[vh] = 1; - break; - } - if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) - break; - line = (vh * VH_LINES) + CSR_GETCHAN (vh_csr[vh]); - lp = &vh_parm[line]; - if (access == WRITEB) - data = (PA & 1) ? - (lp->tbuffct & 0377) | (data << 8) : - (lp->tbuffct & ~0377) | (data & 0377); - lp->tbuffct = data; - break; - default: - /* can't happen */ - break; - } - return (SCPE_OK); + } else { + line = (vh * VH_LINES) + CSR_GETCHAN (vh_csr[vh]); + lp = &vh_parm[line]; + if (access == WRITEB) + data = (PA & 1) ? + (lp->txchar & 0377) | (data << 8) : + (lp->txchar & ~0377) | (data & 0377); + lp->txchar = data; /* TXCHAR */ + if (lp->txchar & TXCHAR_TX_DATA_VALID) { + if (lp->tbuf2 & TB2_TX_ENA) + vh_putc (vh, lp, + CSR_GETCHAN (vh_csr[vh]), + lp->txchar); + q_tx_report (vh, + CSR_GETCHAN (vh_csr[vh]) << CSR_V_TX_LINE); + lp->txchar &= ~TXCHAR_TX_DATA_VALID; + } + } + break; + case 2: /* LPR */ + if ((data == RESET_ABORT) && (vh_csr[vh] & CSR_MASTER_RESET)) { + vh_mcount[vh] = 1; + break; + } + if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) + break; + line = (vh * VH_LINES) + CSR_GETCHAN (vh_csr[vh]); + lp = &vh_parm[line]; + if (access == WRITEB) + data = (PA & 1) ? + (lp->lpr & 0377) | (data << 8) : + (lp->lpr & ~0377) | (data & 0377); + /* Modify only if CSR<3:0> == 0 */ + if (CSR_GETCHAN (vh_csr[vh]) != 0) + data &= ~LPR_DISAB_XRPT; + lp->lpr = data; + if (((lp->lpr >> LPR_V_DIAG) & LPR_M_DIAG) == 1) { + fifo_put (vh, lp, + RBUF_DIAG | + RBUF_PUTLINE (CSR_GETCHAN (vh_csr[vh])) | + BMP_OK); + /* BUG: check for overflow above */ + lp->lpr &= ~(LPR_M_DIAG << LPR_V_DIAG); + } + break; + case 3: /* STAT/FIFODATA */ + if ((data == RESET_ABORT) && (vh_csr[vh] & CSR_MASTER_RESET)) { + vh_mcount[vh] = 1; + break; + } + if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) + break; + line = (vh * VH_LINES) + CSR_GETCHAN (vh_csr[vh]); + lp = &vh_parm[line]; + if (vh_unit[vh].flags & UNIT_MODEDHU) { + /* high byte writes not allowed */ + if (PA & 1) + break; + /* transmit 1 or 2 characters */ + if (!(lp->tbuf2 & TB2_TX_ENA)) + break; + vh_putc (vh, lp, CSR_GETCHAN (vh_csr[vh]), data); + q_tx_report (vh, CSR_GETCHAN (vh_csr[vh]) << CSR_V_TX_LINE); + if (access != WRITEB) + vh_putc (vh, lp, CSR_GETCHAN (vh_csr[vh]), + data >> 8); + } + break; + case 4: /* LNCTRL */ + if ((data == RESET_ABORT) && (vh_csr[vh] & CSR_MASTER_RESET)) { + vh_mcount[vh] = 1; + break; + } + if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) + break; + line = (vh * VH_LINES) + CSR_GETCHAN (vh_csr[vh]); + lp = &vh_parm[line]; + if (access == WRITEB) + data = (PA & 1) ? + (lp->lnctrl & 0377) | (data << 8) : + (lp->lnctrl & ~0377) | (data & 0377); + /* catch the abort TX transition */ + if (!(lp->lnctrl & LNCTRL_TX_ABORT) && + (data & LNCTRL_TX_ABORT)) { + if ((lp->tbuf2 & TB2_TX_ENA) && + (lp->tbuf2 & TB2_TX_DMA_START)) { + lp->tbuf2 &= ~TB2_TX_DMA_START; + q_tx_report (vh, CSR_GETCHAN (vh_csr[vh]) << CSR_V_TX_LINE); + } + } + /* Implement program-initiated flow control */ + if ( (data & LNCTRL_FORCE_XOFF) && + !(lp->lnctrl & LNCTRL_FORCE_XOFF) ) { + if (!(lp->lnctrl & LNCTRL_IAUTO)) + vh_putc (vh, lp, CSR_GETCHAN (vh_csr[vh]), XOFF); + } else if ( !(data & LNCTRL_FORCE_XOFF) && + (lp->lnctrl & LNCTRL_FORCE_XOFF) ) { + if (!(lp->lnctrl & LNCTRL_IAUTO)) + vh_putc (vh, lp, CSR_GETCHAN (vh_csr[vh]), XON); + else if (!(vh_crit & (1 << vh)) && + (vh_stall[vh] & (1 << CSR_GETCHAN (vh_csr[vh])))) + vh_putc (vh, lp, CSR_GETCHAN (vh_csr[vh]), XON); + } + if ( (data & LNCTRL_IAUTO) && /* IAUTO 0->1 */ + !(lp->lnctrl & LNCTRL_IAUTO) ) { + if (!(lp->lnctrl & LNCTRL_FORCE_XOFF)) { + if (vh_crit & (1 << vh)) { + vh_putc (vh, lp, + CSR_GETCHAN (vh_csr[vh]), XOFF); + vh_stall[vh] |= (1 << CSR_GETCHAN (vh_csr[vh])); + } + } else { + /* vh_stall[vh] |= (1 << CSR_GETCHAN (vh_csr[vh])) */; + } + } else if ( !(data & LNCTRL_IAUTO) && + (lp->lnctrl & LNCTRL_IAUTO) ) { + if (!(lp->lnctrl & LNCTRL_FORCE_XOFF)) + vh_putc (vh, lp, CSR_GETCHAN (vh_csr[vh]), XON); + } + /* check modem control bits */ + if ( !(data & LNCTRL_DTR) && /* DTR 1->0 */ + (lp->lnctrl & LNCTRL_DTR)) { + if ((lp->tmln->conn) && (vh_unit[vh].flags & UNIT_HANGUP)) { + tmxr_linemsg (lp->tmln, "\r\nLine hangup\r\n"); + tmxr_reset_ln (lp->tmln); + } + HangupModem (vh, lp, CSR_GETCHAN (vh_csr[vh])); + } + lp->lnctrl = data; + lp->tmln->rcve = (data & LNCTRL_RX_ENA) ? 1 : 0; + tmxr_poll_rx (&vh_desc); + vh_getc (vh); + if (lp->lnctrl & LNCTRL_BREAK) + vh_putc (vh, lp, CSR_GETCHAN (vh_csr[vh]), 0); + break; + case 5: /* TBUFFAD1 */ + if ((data == RESET_ABORT) && (vh_csr[vh] & CSR_MASTER_RESET)) { + vh_mcount[vh] = 1; + break; + } + if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) + break; + line = (vh * VH_LINES) + CSR_GETCHAN (vh_csr[vh]); + lp = &vh_parm[line]; + if (access == WRITEB) + data = (PA & 1) ? + (lp->tbuf1 & 0377) | (data << 8) : + (lp->tbuf1 & ~0377) | (data & 0377); + lp->tbuf1 = data; + break; + case 6: /* TBUFFAD2 */ + if ((data == RESET_ABORT) && (vh_csr[vh] & CSR_MASTER_RESET)) { + vh_mcount[vh] = 1; + break; + } + if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) + break; + line = (vh * VH_LINES) + CSR_GETCHAN (vh_csr[vh]); + lp = &vh_parm[line]; + if (access == WRITEB) + data = (PA & 1) ? + (lp->tbuf2 & 0377) | (data << 8) : + (lp->tbuf2 & ~0377) | (data & 0377); + lp->tbuf2 = data; + /* if starting a DMA, clear DMA_ERR */ + if (vh_unit[vh].flags & UNIT_FASTDMA) { + doDMA (vh, CSR_GETCHAN (vh_csr[vh])); + tmxr_send_buffered_data (lp->tmln); + } + break; + case 7: /* TBUFFCT */ + if ((data == RESET_ABORT) && (vh_csr[vh] & CSR_MASTER_RESET)) { + vh_mcount[vh] = 1; + break; + } + if (CSR_GETCHAN (vh_csr[vh]) >= VH_LINES) + break; + line = (vh * VH_LINES) + CSR_GETCHAN (vh_csr[vh]); + lp = &vh_parm[line]; + if (access == WRITEB) + data = (PA & 1) ? + (lp->tbuffct & 0377) | (data << 8) : + (lp->tbuffct & ~0377) | (data & 0377); + lp->tbuffct = data; + break; + default: + /* can't happen */ + break; + } + return (SCPE_OK); } -static void doDMA ( int32 vh, - int32 chan ) +static void doDMA ( int32 vh, + int32 chan ) { - int32 line, status; - uint32 pa; - TMLX *lp; + int32 line, status; + uint32 pa; + TMLX *lp; - line = (vh * VH_LINES) + chan; - lp = &vh_parm[line]; - if ((lp->tbuf2 & TB2_TX_ENA) && (lp->tbuf2 & TB2_TX_DMA_START)) { + line = (vh * VH_LINES) + chan; + lp = &vh_parm[line]; + if ((lp->tbuf2 & TB2_TX_ENA) && (lp->tbuf2 & TB2_TX_DMA_START)) { /* BUG: should compare against available xmit buffer space */ - pa = lp->tbuf1; - pa |= (lp->tbuf2 & TB2_M_TBUFFAD) << 16; - status = chan << CSR_V_TX_LINE; - while (lp->tbuffct) { - uint8 buf; - if (Map_ReadB (pa, 1, &buf)) { - status |= CSR_TX_DMA_ERR; - lp->tbuffct = 0; - break; - } - if (vh_putc (vh, lp, chan, buf) != SCPE_OK) - break; - /* pa = (pa + 1) & PAMASK; */ - pa = (pa + 1) & ((1 << 22) - 1); - lp->tbuffct--; - } - lp->tbuf1 = pa & 0177777; - lp->tbuf2 = (lp->tbuf2 & ~TB2_M_TBUFFAD) | - ((pa >> 16) & TB2_M_TBUFFAD); - if (lp->tbuffct == 0) { - lp->tbuf2 &= ~TB2_TX_DMA_START; - q_tx_report (vh, status); - } - } + pa = lp->tbuf1; + pa |= (lp->tbuf2 & TB2_M_TBUFFAD) << 16; + status = chan << CSR_V_TX_LINE; + while (lp->tbuffct) { + uint8 buf; + if (Map_ReadB (pa, 1, &buf)) { + status |= CSR_TX_DMA_ERR; + lp->tbuffct = 0; + break; + } + if (vh_putc (vh, lp, chan, buf) != SCPE_OK) + break; + /* pa = (pa + 1) & PAMASK; */ + pa = (pa + 1) & ((1 << 22) - 1); + lp->tbuffct--; + } + lp->tbuf1 = pa & 0177777; + lp->tbuf2 = (lp->tbuf2 & ~TB2_M_TBUFFAD) | + ((pa >> 16) & TB2_M_TBUFFAD); + if (lp->tbuffct == 0) { + lp->tbuf2 &= ~TB2_TX_DMA_START; + q_tx_report (vh, status); + } + } } /* Perform many of the functions of PROC2 */ -static t_stat vh_svc ( UNIT *uptr ) +static t_stat vh_svc ( UNIT *uptr ) { - int32 vh, newln, i; + int32 vh, newln, i; - /* scan all muxes for countdown reset */ - for (vh = 0; vh < VH_MUXES; vh++) { - if (vh_csr[vh] & CSR_MASTER_RESET) { - if (vh_mcount[vh] != 0) - vh_mcount[vh] -= 1; - else - vh_clear (vh, FALSE); - } - } - /* sample every 10ms for modem changes (new connections) */ - newln = tmxr_poll_conn (&vh_desc); - if (newln >= 0) { - TMLX *lp; - int32 line; - vh = newln / VH_LINES; /* determine which mux */ - line = newln - (vh * VH_LINES); - lp = &vh_parm[newln]; - lp->lstat |= STAT_DSR | STAT_DCD | STAT_CTS; - if (!(lp->lnctrl & LNCTRL_DTR)) - lp->lstat |= STAT_RI; - if (lp->lnctrl & LNCTRL_LINK_TYPE) - fifo_put (vh, lp, RBUF_DIAG | - RBUF_PUTLINE (line) | - ((lp->lstat >> 8) & 0376)); - /* BUG: should check for overflow above */ - } - /* scan all muxes, lines for DMA to complete; start every 3.12ms */ - for (vh = 0; vh < VH_MUXES; vh++) { - for (i = 0; i < VH_LINES; i++) - doDMA (vh, i); - } - /* interrupt driven in a real DHQ */ - tmxr_poll_rx (&vh_desc); - for (vh = 0; vh < VH_MUXES; vh++) - vh_getc (vh); - tmxr_poll_tx (&vh_desc); - /* scan all DHU-mode muxes for RX FIFO timeout */ - for (vh = 0; vh < VH_MUXES; vh++) { - if (vh_unit[vh].flags & UNIT_MODEDHU) { - if (vh_timeo[vh] && (vh_csr[vh] & CSR_RXIE)) { - vh_timeo[vh] -= 1; - if ((vh_timeo[vh] == 0) && rbuf_idx[vh]) - vh_set_rxint (vh); - } - } - } - sim_activate (uptr, tmxr_poll); /* requeue ourselves */ - return (SCPE_OK); + /* scan all muxes for countdown reset */ + for (vh = 0; vh < vh_desc.lines/VH_LINES; vh++) { + if (vh_csr[vh] & CSR_MASTER_RESET) { + if (vh_mcount[vh] != 0) + vh_mcount[vh] -= 1; + else + vh_clear (vh, FALSE); + } + } + /* sample every 10ms for modem changes (new connections) */ + newln = tmxr_poll_conn (&vh_desc); + if (newln >= 0) { + TMLX *lp; + int32 line; + vh = newln / VH_LINES; /* determine which mux */ + line = newln - (vh * VH_LINES); + lp = &vh_parm[newln]; + lp->lstat |= STAT_DSR | STAT_DCD | STAT_CTS; + if (!(lp->lnctrl & LNCTRL_DTR)) + lp->lstat |= STAT_RI; + if (lp->lnctrl & LNCTRL_LINK_TYPE) + fifo_put (vh, lp, RBUF_DIAG | + RBUF_PUTLINE (line) | + ((lp->lstat >> 8) & 0376)); + /* BUG: should check for overflow above */ + } + /* scan all muxes, lines for DMA to complete; start every 3.12ms */ + for (vh = 0; vh < vh_desc.lines/VH_LINES; vh++) { + for (i = 0; i < VH_LINES; i++) + doDMA (vh, i); + } + /* interrupt driven in a real DHQ */ + tmxr_poll_rx (&vh_desc); + for (vh = 0; vh < vh_desc.lines/VH_LINES; vh++) + vh_getc (vh); + tmxr_poll_tx (&vh_desc); + /* scan all DHU-mode muxes for RX FIFO timeout */ + for (vh = 0; vh < vh_desc.lines/VH_LINES; vh++) { + if (vh_unit[vh].flags & UNIT_MODEDHU) { + if (vh_timeo[vh] && (vh_csr[vh] & CSR_RXIE)) { + vh_timeo[vh] -= 1; + if ((vh_timeo[vh] == 0) && rbuf_idx[vh]) + vh_set_rxint (vh); + } + } + } + sim_activate (uptr, tmxr_poll); /* requeue ourselves */ + return (SCPE_OK); } /* init a channel on a controller */ @@ -1155,175 +1202,257 @@ auto-flow reports enabled FIFO size set to 64 */ -static void vh_init_chan ( int32 vh, - int32 chan ) +static void vh_init_chan ( int32 vh, + int32 chan ) { - int32 line; - TMLX *lp; + int32 line; + TMLX *lp; - line = (vh * VH_LINES) + chan; - lp = &vh_parm[line]; - lp->lpr = (RATE_9600 << LPR_V_TX_SPEED) | - (RATE_9600 << LPR_V_RX_SPEED) | - (03 << LPR_V_CHAR_LGTH); - lp->lnctrl = 0; - lp->lstat &= ~(STAT_MDL | STAT_DHUID | STAT_RI); - if (vh_unit[vh].flags & UNIT_MODEDHU) - lp->lstat |= STAT_DHUID | 64; - if (!(vh_unit[vh].flags & UNIT_MODEM)) - lp->lstat |= STAT_DSR | STAT_DCD | STAT_CTS; - lp->tmln->xmte = 1; - lp->tmln->rcve = 0; - lp->tbuffct = 0; - lp->tbuf1 = 0; - lp->tbuf2 = TB2_TX_ENA; - lp->txchar = 0; + line = (vh * VH_LINES) + chan; + lp = &vh_parm[line]; + lp->lpr = (RATE_9600 << LPR_V_TX_SPEED) | + (RATE_9600 << LPR_V_RX_SPEED) | + (03 << LPR_V_CHAR_LGTH); + lp->lnctrl = 0; + lp->lstat &= ~(STAT_MDL | STAT_DHUID | STAT_RI); + if (vh_unit[vh].flags & UNIT_MODEDHU) + lp->lstat |= STAT_DHUID | 64; + if (!(vh_unit[vh].flags & UNIT_MODEM)) + lp->lstat |= STAT_DSR | STAT_DCD | STAT_CTS; + lp->tmln->xmte = 1; + lp->tmln->rcve = 0; + lp->tbuffct = 0; + lp->tbuf1 = 0; + lp->tbuf2 = TB2_TX_ENA; + lp->txchar = 0; } /* init a controller; flag true if BINIT, false if master.reset */ -static t_stat vh_clear ( int32 vh, - t_bool flag ) +static t_stat vh_clear ( int32 vh, + t_bool flag ) { - int32 i; + int32 i; - txq_idx[vh] = 0; - rbuf_idx[vh] = 0; - /* put 8 diag bytes in FIFO: 6 SELF_x, 2 circuit revision codes */ - if (vh_csr[vh] & CSR_SKIP) { - fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(0) | SELF_SKIP); - fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(1) | SELF_SKIP); - fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(2) | SELF_SKIP); - fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(3) | SELF_SKIP); - fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(4) | SELF_SKIP); - fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(5) | SELF_SKIP); - fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(6) | 0107); - fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(7) | 0105); - } else { - fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(0) | SELF_NULL); - fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(1) | SELF_NULL); - fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(2) | SELF_NULL); - fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(3) | SELF_NULL); - fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(4) | SELF_NULL); - fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(5) | SELF_NULL); - /* PROC2 ver. 1 */ - fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(6) | 0107); - /* PROC1 ver. 1 */ - fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(7) | 0105); - } - vh_csr[vh] &= ~(CSR_TX_ACTION|CSR_DIAG_FAIL|CSR_MASTER_RESET); - if (flag) - vh_csr[vh] &= ~(CSR_TXIE|CSR_RXIE|CSR_SKIP); - vh_csr[vh] |= CSR_TX_DMA_ERR | (CSR_M_TX_LINE << CSR_V_TX_LINE); - vh_clr_rxint (vh); - vh_clr_txint (vh); - vh_timer[vh] = 1; - vh_timeo[vh] = 0; - vh_ovrrun[vh] = 0; - for (i = 0; i < VH_LINES; i++) - vh_init_chan (vh, i); - vh_crit &= ~(1 << vh); - vh_stall[vh] = 0; - vh_loop[vh] = LOOP_NONE; - return (SCPE_OK); + txq_idx[vh] = 0; + rbuf_idx[vh] = 0; + /* put 8 diag bytes in FIFO: 6 SELF_x, 2 circuit revision codes */ + if (vh_csr[vh] & CSR_SKIP) { + fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(0) | SELF_SKIP); + fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(1) | SELF_SKIP); + fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(2) | SELF_SKIP); + fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(3) | SELF_SKIP); + fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(4) | SELF_SKIP); + fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(5) | SELF_SKIP); + fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(6) | 0107); + fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(7) | 0105); + } else { + fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(0) | SELF_NULL); + fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(1) | SELF_NULL); + fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(2) | SELF_NULL); + fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(3) | SELF_NULL); + fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(4) | SELF_NULL); + fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(5) | SELF_NULL); + /* PROC2 ver. 1 */ + fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(6) | 0107); + /* PROC1 ver. 1 */ + fifo_put (vh, NULL, RBUF_DIAG | RBUF_PUTLINE(7) | 0105); + } + vh_csr[vh] &= ~(CSR_TX_ACTION|CSR_DIAG_FAIL|CSR_MASTER_RESET); + if (flag) + vh_csr[vh] &= ~(CSR_TXIE|CSR_RXIE|CSR_SKIP); + vh_csr[vh] |= CSR_TX_DMA_ERR | (CSR_M_TX_LINE << CSR_V_TX_LINE); + vh_clr_rxint (vh); + vh_clr_txint (vh); + vh_timer[vh] = 1; + vh_timeo[vh] = 0; + vh_ovrrun[vh] = 0; + for (i = 0; i < VH_LINES; i++) + vh_init_chan (vh, i); + vh_crit &= ~(1 << vh); + vh_stall[vh] = 0; + vh_loop[vh] = LOOP_NONE; + return (SCPE_OK); } /* Reset all controllers. Used by BINIT and RESET. */ -static t_stat vh_reset ( DEVICE *dptr ) +static t_stat vh_reset ( DEVICE *dptr ) { - int32 i; + int32 i; - for (i = 0; i < (VH_MUXES * VH_LINES); i++) - vh_parm[i].tmln = &vh_ldsc[i]; - for (i = 0; i < VH_MUXES; i++) { + for (i = 0; i < vh_desc.lines; i++) + vh_parm[i].tmln = &vh_ldsc[i]; + for (i = 0; i < vh_desc.lines/VH_LINES; i++) { #if defined (VM_PDP11) - /* if Unibus, force DHU mode */ - if (UNIBUS) - vh_unit[i].flags |= UNIT_MODEDHU; + /* if Unibus, force DHU mode */ + if (UNIBUS) + vh_unit[i].flags |= UNIT_MODEDHU; #endif - vh_clear (i, TRUE); - } - vh_rxi = vh_txi = 0; - CLR_INT (VHRX); - CLR_INT (VHTX); - for (i = 0; i < VH_MUXES; i++) - sim_cancel (&vh_unit[i]); - return (auto_config (dptr->name, (dptr->flags & DEV_DIS) ? 0 : VH_MUXES)); + vh_clear (i, TRUE); + } + vh_rxi = vh_txi = 0; + CLR_INT (VHRX); + CLR_INT (VHTX); + sim_cancel (&vh_unit[0]); + return (auto_config (dptr->name, (dptr->flags & DEV_DIS) ? 0 : vh_desc.lines/VH_LINES)); } -static t_stat vh_attach ( UNIT *uptr, - char *cptr ) +static t_stat vh_attach ( UNIT *uptr, + char *cptr ) { - if (uptr == &vh_unit[0]) - return (tmxr_attach (&vh_desc, uptr, cptr)); - return (SCPE_NOATT); + if (uptr == &vh_unit[0]) + return (tmxr_attach (&vh_desc, uptr, cptr)); + return (SCPE_NOATT); } -static t_stat vh_detach ( UNIT *uptr ) +static t_stat vh_detach ( UNIT *uptr ) { - return (tmxr_detach (&vh_desc, uptr)); + return (tmxr_detach (&vh_desc, uptr)); } -static void debug_line ( FILE *st, - int32 vh, - int32 chan ) +static void vh_detail_line ( FILE *st, + int32 vh, + int32 chan ) { - int32 line; - TMLX *lp; + int32 line; + TMLX *lp; - line = (vh * VH_LINES) + chan; - lp = &vh_parm[line]; - fprintf (st, "\tline %d\tlpr %06o, lnctrl %06o, lstat %06o\n", - chan, lp->lpr, lp->lnctrl, lp->lstat); - fprintf (st, "\t\ttbuffct %06o, tbuf1 %06o, tbuf2 %06o, txchar %06o\n", - lp->tbuffct, lp->tbuf1, lp->tbuf2, lp->txchar); - fprintf (st, "\t\ttmln rcve %d xmte %d\n", - lp->tmln->rcve, lp->tmln->xmte); + line = (vh * VH_LINES) + chan; + lp = &vh_parm[line]; + fprintf (st, "\tline %d\tlpr %06o, lnctrl %06o, lstat %06o\n", + chan, lp->lpr, lp->lnctrl, lp->lstat); + fprintf (st, "\t\ttbuffct %06o, tbuf1 %06o, tbuf2 %06o, txchar %06o\n", + lp->tbuffct, lp->tbuf1, lp->tbuf2, lp->txchar); + fprintf (st, "\t\ttmln rcve %d xmte %d\n", + lp->tmln->rcve, lp->tmln->xmte); } -static t_stat vh_show_debug ( FILE *st, - UNIT *uptr, - int32 val, - void *desc ) +static t_stat vh_show_detail ( FILE *st, + UNIT *uptr, + int32 val, + void *desc ) { - int32 i, j; + int32 i, j; - fprintf (st, "VH:\trxi %d, txi %d\n", vh_rxi, vh_txi); - for (i = 0; i < VH_MUXES; i++) { - fprintf (st, "VH%d:\tmode %s, crit %d\n", i, - vh_unit[i].flags & UNIT_MODEDHU ? "DHU" : "DHV", - vh_crit & (1 << i)); - fprintf (st, "\tCSR %06o, mcount %d, rbuf_idx %d, txq_idx %d\n", - vh_csr[i], vh_mcount[i], rbuf_idx[i], txq_idx[i]); - for (j = 0; j < VH_LINES; j++) - debug_line (st, i, j); - } - return (SCPE_OK); + fprintf (st, "VH:\trxi %d, txi %d\n", vh_rxi, vh_txi); + for (i = 0; i < vh_desc.lines/VH_LINES; i++) { + fprintf (st, "VH%d:\tmode %s, crit %d\n", i, + vh_unit[i].flags & UNIT_MODEDHU ? "DHU" : "DHV", + vh_crit & (1 << i)); + fprintf (st, "\tCSR %06o, mcount %d, rbuf_idx %d, txq_idx %d\n", + vh_csr[i], vh_mcount[i], rbuf_idx[i], txq_idx[i]); + for (j = 0; j < VH_LINES; j++) + vh_detail_line (st, i, j); + } + return (SCPE_OK); } -static t_stat vh_show_rbuf ( FILE *st, - UNIT *uptr, - int32 val, - void *desc ) +static t_stat vh_show_rbuf ( FILE *st, + UNIT *uptr, + int32 val, + void *desc ) { - int32 i; + int32 i; - for (i = 0; i < rbuf_idx[0]; i++) - fprintf (st, "%03d: %06o\n", i, vh_rbuf[0][i]); - return (SCPE_OK); + for (i = 0; i < rbuf_idx[0]; i++) + fprintf (st, "%03d: %06o\n", i, vh_rbuf[0][i]); + return (SCPE_OK); } -static t_stat vh_show_txq ( FILE *st, - UNIT *uptr, - int32 val, - void *desc ) +static t_stat vh_show_txq ( FILE *st, + UNIT *uptr, + int32 val, + void *desc ) { - int32 i; + int32 i; - for (i = 0; i < txq_idx[0]; i++) - fprintf (st, "%02d: %06o\n\r", i, vh_txq[0][i]); - return (SCPE_OK); + for (i = 0; i < txq_idx[0]; i++) + fprintf (st, "%02d: %06o\n\r", i, vh_txq[0][i]); + return (SCPE_OK); } +/* SET LINES processor */ + +static t_stat vh_setnl (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +int32 newln, i, t, ndev; +t_stat r; + +if (cptr == NULL) + return SCPE_ARG; +newln = (int32) get_uint (cptr, 10, (VH_MUXES * VH_LINES), &r); +if ((r != SCPE_OK) || (newln == vh_desc.lines)) + return r; +if ((newln == 0) || (newln % VH_LINES)) + return SCPE_ARG; +if (newln < vh_desc.lines) { + for (i = newln, t = 0; i < vh_desc.lines; i++) + t = t | vh_ldsc[i].conn; + if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE)) + return SCPE_OK; + for (i = newln; i < vh_desc.lines; i++) { + if (vh_ldsc[i].conn) { + tmxr_linemsg (&vh_ldsc[i], "\r\nOperator disconnected line\r\n"); + tmxr_reset_ln (&vh_ldsc[i]); /* reset line */ + } + if ((i % VH_LINES) == (VH_LINES - 1)) + vh_clear (i / VH_LINES, TRUE); /* reset mux */ + } + } +vh_dib.lnt = (newln / VH_LINES) * IOLN_VH; /* set length */ +vh_desc.lines = newln; +ndev = ((vh_dev.flags & DEV_DIS)? 0: (vh_desc.lines / VH_LINES)); +vh_dev.numunits = (newln / VH_LINES); +return auto_config (vh_dev.name, ndev); /* auto config */ +} + +/* SET LOG processor */ + +static t_stat vh_set_log (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +char *tptr; +t_stat r; +int32 ln; + +if (cptr == NULL) + return SCPE_ARG; +tptr = strchr (cptr, '='); +if ((tptr == NULL) || (*tptr == 0)) + return SCPE_ARG; +*tptr++ = 0; +ln = (int32) get_uint (cptr, 10, (VH_MUXES * VH_LINES), &r); +if ((r != SCPE_OK) || (ln >= vh_desc.lines)) + return SCPE_ARG; +return tmxr_set_log (NULL, ln, tptr, desc); +} + +/* SET NOLOG processor */ + +static t_stat vh_set_nolog (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +t_stat r; +int32 ln; + +if (cptr == NULL) + return SCPE_ARG; +ln = (int32) get_uint (cptr, 10, (VH_MUXES * VH_LINES), &r); +if ((r != SCPE_OK) || (ln >= vh_desc.lines)) + return SCPE_ARG; +return tmxr_set_nolog (NULL, ln, NULL, desc); +} + +/* SHOW LOG processor */ + +static t_stat vh_show_log (FILE *st, UNIT *uptr, int32 val, void *desc) +{ +int32 i; + +for (i = 0; i < vh_desc.lines; i++) { + fprintf (st, "line %d: ", i); + tmxr_show_log (st, NULL, i, desc); + fprintf (st, "\n"); + } +return SCPE_OK; +}