mirror of
https://github.com/simh/simh.git
synced 2026-01-25 19:56:25 +00:00
Notes For V3.8
The makefile now works for Linux and most Unix's. Howevr, for Solaris and MacOS, you must first export the OSTYPE environment variable: > export OSTYPE > make Otherwise, you will get build errors. 1. New Features 1.1 3.8-0 1.1.1 SCP and Libraries - BREAK, NOBREAK, and SHOW BREAK with no argument will set, clear, and show (respectively) a breakpoint at the current PC. 1.2 GRI - Added support for the GRI-99 processor. 1.3 HP2100 - Added support for the BACI terminal interface. - Added support for RTE OS/VMA/EMA, SIGNAL, VIS firmware extensions. 1.4 Nova - Added support for 64KW memory (implemented in third-party CPU's). 1.5 PDP-11 - Added support for DC11, RC11, KE11A, KG11A. - Added modem control support for DL11. - Added ASCII character support for all 8b devices. 2. Bugs Fixed Please see the revision history on http://simh.trailing-edge.com or in the source module sim_rev.h.
This commit is contained in:
committed by
Mark Pizzolato
parent
3cb7c60d5d
commit
59aa4a73b1
@@ -1,6 +1,6 @@
|
||||
/* pdp11_cpu.c: PDP-11 CPU simulator
|
||||
|
||||
Copyright (c) 1993-2007, Robert M Supnik
|
||||
Copyright (c) 1993-2008, 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,8 @@
|
||||
|
||||
cpu PDP-11 CPU
|
||||
|
||||
22-Apr-08 RMS Fixed MMR0 treatment in RESET (found by Walter Mueller)
|
||||
02-Feb-08 RMS Fixed DMA memory address limit test (found by John Dundas)
|
||||
28-Apr-07 RMS Removed clock initialization
|
||||
27-Oct-06 RMS Added idle support
|
||||
18-Oct-06 RMS Fixed bug in ASH -32 C value
|
||||
@@ -296,6 +298,7 @@ int32 hst_p = 0; /* history pointer */
|
||||
int32 hst_lnt = 0; /* history length */
|
||||
InstHistory *hst = NULL; /* instruction history */
|
||||
int32 dsmask[4] = { MMR3_KDS, MMR3_SDS, 0, MMR3_UDS }; /* dspace enables */
|
||||
t_addr cpu_memsize = INIMEMSIZE; /* last mem addr */
|
||||
|
||||
extern int32 CPUERR, MAINT;
|
||||
extern int32 sim_interval;
|
||||
@@ -646,6 +649,9 @@ t_stat reason;
|
||||
|
||||
reason = build_dib_tab (); /* build, chk dib_tab */
|
||||
if (reason != SCPE_OK) return reason;
|
||||
if (MEMSIZE < cpu_tab[cpu_model].maxm) /* mem size < max? */
|
||||
cpu_memsize = MEMSIZE; /* then okay */
|
||||
else cpu_memsize = cpu_tab[cpu_model].maxm - IOPAGESIZE;/* max - io page */
|
||||
cpu_type = 1u << cpu_model; /* reset type mask */
|
||||
cpu_bme = (MMR3 & MMR3_BME) && (cpu_opt & OPT_UBM); /* map enabled? */
|
||||
PC = saved_PC;
|
||||
@@ -863,11 +869,11 @@ while (reason == 0) {
|
||||
case 5: /* RESET */
|
||||
if (cm == MD_KER) {
|
||||
reset_all (2); /* skip CPU, sys reg */
|
||||
PIRQ = 0; /* clear PIRQ, STKLIM, */
|
||||
STKLIM = 0; /* MMR0<15:12,0>, */
|
||||
PIRQ = 0; /* clear PIRQ */
|
||||
STKLIM = 0; /* clear STKLIM */
|
||||
MMR0 = 0; /* clear MMR0 */
|
||||
MMR3 = 0; /* clear MMR3 */
|
||||
for (i = 0; i < IPL_HLVL; i++) int_req[i] = 0;
|
||||
MMR0 = MMR0 & ~(MMR0_MME | MMR0_FREEZE);
|
||||
MMR3 = 0; /* MMR3 */
|
||||
trap_req = trap_req & ~TRAP_INT;
|
||||
dsenable = calc_ds (cm);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* pdp11_cpumod.c: PDP-11 CPU model-specific features
|
||||
|
||||
Copyright (c) 2004-2007, Robert M Supnik
|
||||
Copyright (c) 2004-2008, 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,9 @@
|
||||
|
||||
system PDP-11 model-specific registers
|
||||
|
||||
20-May-08 RMS Added JCSR default for KDJ11B, KDJ11E
|
||||
22-Apr-08 RMS Fixed write behavior of 11/70 MBRK, LOSIZE, HISIZE
|
||||
(found by Walter Mueller)
|
||||
29-Apr-07 RMS Don't run bus setup routine during RESTORE
|
||||
30-Aug-05 RMS Added additional 11/60 registers
|
||||
16-Aug-05 RMS Fixed C++ declaration and cast problems
|
||||
@@ -65,6 +68,7 @@ int32 CCR = 0; /* cache control reg */
|
||||
int32 HITMISS = 0; /* hit/miss reg */
|
||||
int32 MAINT = 0; /* maint reg */
|
||||
int32 JCSR = 0; /* J11 control */
|
||||
int32 JCSR_dflt = 0; /* J11 boot ctl def */
|
||||
int32 JPCR = 0; /* J11 page ctrl */
|
||||
int32 JASR = 0; /* J11 addtl status */
|
||||
int32 UDCR = 0; /* UBA diag ctrl */
|
||||
@@ -118,6 +122,8 @@ t_stat sys_reset (DEVICE *dptr);
|
||||
int32 toy_read (void);
|
||||
void toy_write (int32 bit);
|
||||
uint8 toy_set (int32 val);
|
||||
t_stat sys_set_jclk_dflt (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat sys_show_jclk_dflt (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
|
||||
extern t_stat PSW_rd (int32 *data, int32 addr, int32 access);
|
||||
extern t_stat PSW_wr (int32 data, int32 addr, int32 access);
|
||||
@@ -243,6 +249,10 @@ static const char *opt_name[] = {
|
||||
"RH11", "RH70", "PARITY", "NOPARITY", "Unibus map", "No map", NULL
|
||||
};
|
||||
|
||||
static const char *jcsr_val[4] = {
|
||||
"LINE", "50HZ", "60HZ", "800HZ"
|
||||
};
|
||||
|
||||
/* SYSTEM data structures
|
||||
|
||||
sys_dev SYSTEM device descriptor
|
||||
@@ -264,6 +274,7 @@ REG sys_reg[] = {
|
||||
{ ORDATA (WCS, WCS, 16) },
|
||||
{ ORDATA (SYSID, SYSID, 16) },
|
||||
{ ORDATA (JCSR, JCSR, 16) },
|
||||
{ ORDATA (JCSR_DFLT, JCSR_dflt, 16), REG_HRO },
|
||||
{ ORDATA (JPCR, JPCR, 16) },
|
||||
{ ORDATA (JASR, JASR, 16) },
|
||||
{ ORDATA (UDCR, UDCR, 16) },
|
||||
@@ -276,8 +287,14 @@ REG sys_reg[] = {
|
||||
{ NULL}
|
||||
};
|
||||
|
||||
MTAB sys_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "JCLK_DFLT", "JCLK_DFLT",
|
||||
&sys_set_jclk_dflt, &sys_show_jclk_dflt },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE sys_dev = {
|
||||
"SYSTEM", &sys_unit, sys_reg, NULL,
|
||||
"SYSTEM", &sys_unit, sys_reg, sys_mod,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
NULL, NULL, &sys_reset,
|
||||
NULL, NULL, NULL,
|
||||
@@ -541,7 +558,11 @@ t_stat CPU70_rd (int32 *data, int32 pa, int32 access)
|
||||
{
|
||||
switch ((pa >> 1) & 017) { /* decode pa<4:1> */
|
||||
|
||||
case 000: case 001: case 011: /* LO,HI ERR, HI SIZE */
|
||||
case 000: /* low error */
|
||||
*data = 0;
|
||||
return SCPE_OK;
|
||||
|
||||
case 001: /* high error */
|
||||
*data = 0;
|
||||
return SCPE_OK;
|
||||
|
||||
@@ -561,10 +582,14 @@ switch ((pa >> 1) & 017) { /* decode pa<4:1> */
|
||||
*data = HITMISS;
|
||||
return SCPE_OK;
|
||||
|
||||
case 010: /* lower size */
|
||||
case 010: /* low size */
|
||||
*data = (MEMSIZE >> 6) - 1;
|
||||
return SCPE_OK;
|
||||
|
||||
case 011: /* high size */
|
||||
*data = 0;
|
||||
return SCPE_OK;
|
||||
|
||||
case 012: /* system ID */
|
||||
*data = SYSID;
|
||||
return SCPE_OK;
|
||||
@@ -610,12 +635,19 @@ switch ((pa >> 1) & 017) { /* decode pa<4:1> */
|
||||
case 005: /* Hit/miss */
|
||||
return SCPE_OK;
|
||||
|
||||
case 010: /* low size */
|
||||
return SCPE_OK;
|
||||
|
||||
case 011: /* high size */
|
||||
return SCPE_OK;
|
||||
|
||||
case 013: /* CPUERR */
|
||||
CPUERR = 0;
|
||||
return SCPE_OK;
|
||||
|
||||
case 014: /* MBRK */
|
||||
MBRK = data;
|
||||
ODD_IGN (data);
|
||||
MBRK = data & MBRK70_WR;
|
||||
return SCPE_OK;
|
||||
|
||||
case 015: /* PIRQ */
|
||||
@@ -1143,7 +1175,9 @@ MEMERR = 0;
|
||||
if (!CPUT (CPUT_J)) MAINT = 0;
|
||||
MBRK = 0;
|
||||
WCS = 0;
|
||||
JCSR = 0;
|
||||
if (CPUT (CPUT_JB|CPUT_JE))
|
||||
JCSR = JCSR_dflt;
|
||||
else JCSR = 0;
|
||||
JPCR = 0;
|
||||
JASR = 0;
|
||||
UDCR = 0;
|
||||
@@ -1156,3 +1190,28 @@ for (i = 0; i < UBM_LNT_LW; i++) ub_map[i] = 0;
|
||||
for (i = 0; i < TOY_LNT; i++) toy_data[i] = 0;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Set/show JCLK default values */
|
||||
|
||||
t_stat sys_set_jclk_dflt (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
uint32 i;
|
||||
|
||||
if ((CPUT (CPUT_JB|CPUT_JE)) && cptr) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (strncmp (cptr, jcsr_val[i], strlen (cptr)) == 0) {
|
||||
JCSR_dflt = i << CSRJ_V_LTCSEL;
|
||||
return SCPE_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
return SCPE_ARG;
|
||||
}
|
||||
|
||||
t_stat sys_show_jclk_dflt (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
if (CPUT (CPUT_JB|CPUT_JE))
|
||||
fprintf (st, "JCLK default=%s\n", jcsr_val[CSRJ_LTCSEL (JCSR_dflt)]);
|
||||
else fprintf (st, "Not implemented\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* pdp11_cpumod.h: PDP-11 CPU model definitions
|
||||
|
||||
Copyright (c) 2004-2005, Robert M Supnik
|
||||
Copyright (c) 2004-2008, 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.
|
||||
|
||||
22-Apr-08 RMS Added 11/70 MBRK register
|
||||
30-Aug-05 RMS Added additional 11/60 registers
|
||||
*/
|
||||
|
||||
@@ -177,6 +178,10 @@
|
||||
|
||||
#define CPUE60_RD (CPUE_ODD|CPUE_TMO|CPUE_RED)
|
||||
|
||||
/* 11/70 specific registers */
|
||||
|
||||
#define MBRK70_WR 0000377 /* microbreak */
|
||||
|
||||
/* J11 specific registers */
|
||||
|
||||
/* Maintenance register */
|
||||
|
||||
651
PDP11/pdp11_dc.c
Normal file
651
PDP11/pdp11_dc.c
Normal file
@@ -0,0 +1,651 @@
|
||||
/* pdp11_dc.c: PDP-11 DC11 multiple terminal interface simulator
|
||||
|
||||
Copyright (c) 1993-2008, 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"),
|
||||
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.
|
||||
|
||||
dci,dco DC11 terminal input/output
|
||||
|
||||
The simulator supports both hardwired and modem-like behavior. If modem
|
||||
control is not enabled, carrier detect, ring, and carrier change are
|
||||
never set.
|
||||
*/
|
||||
|
||||
#if defined (VM_PDP10) /* PDP10 version */
|
||||
#error "DC11 is not supported on the PDP-10!"
|
||||
|
||||
#elif defined (VM_VAX) /* VAX version */
|
||||
#error "DC11 is not supported on the VAX!"
|
||||
|
||||
#else /* PDP-11 version */
|
||||
#include "pdp11_defs.h"
|
||||
#endif
|
||||
#include "sim_sock.h"
|
||||
#include "sim_tmxr.h"
|
||||
|
||||
#define DCX_MASK (DCX_LINES - 1)
|
||||
|
||||
/* Parity and modem control */
|
||||
|
||||
#define DCX_V_OPAR (TTUF_V_UF + 0)
|
||||
#define DCX_V_EPAR (TTUF_V_UF + 1)
|
||||
#define DCX_V_MDM (TTUF_V_UF + 2)
|
||||
#define DCX_OPAR (1u << DCX_V_OPAR)
|
||||
#define DCX_EPAR (1u << DCX_V_EPAR)
|
||||
#define DCX_MDM (1u << DCX_V_MDM)
|
||||
|
||||
/* registers */
|
||||
|
||||
#define DCICSR_RD 0173777
|
||||
#define DCICSR_WR 0003533
|
||||
#define DCICSR_DTR 0000001 /* DTR (RW) */
|
||||
#define DCICSR_XBR 0000002 /* xmit brk (RWNI) */
|
||||
#define DCICSR_CDT 0000004 /* car det (RO) */
|
||||
#define DCICSR_PAR 0000040 /* odd par (RO) */
|
||||
#define DCICSR_OVR 0010000 /* overrun (RO) */
|
||||
#define DCICSR_RNG 0020000 /* ring (RO) */
|
||||
#define DCICSR_CCH 0040000 /* car change (RO) */
|
||||
#define DCICSR_ALLERR (DCICSR_OVR|DCICSR_RNG|DCICSR_CCH)
|
||||
#define DCICSR_ERR 0100000 /* error */
|
||||
#define DCOCSR_RD 0100737
|
||||
#define DCOCSR_WR 0000535
|
||||
#define DCOCSR_RTS 0000001 /* req to send (RW) */
|
||||
#define DCOCSR_CTS 0000002 /* clr to send (RO) */
|
||||
#define DCOCSR_MNT 0000004 /* maint (RWNI) */
|
||||
|
||||
extern int32 int_req[IPL_HLVL];
|
||||
extern int32 tmxr_poll;
|
||||
|
||||
uint16 dci_csr[DCX_LINES] = { 0 }; /* control/status */
|
||||
uint8 dci_buf[DCX_LINES] = { 0 };
|
||||
uint32 dci_ireq = 0;
|
||||
uint16 dco_csr[DCX_LINES] = { 0 }; /* control/status */
|
||||
uint8 dco_buf[DCX_LINES] = { 0 };
|
||||
uint32 dco_ireq = 0;
|
||||
TMLN dcx_ldsc[DCX_LINES] = { 0 }; /* line descriptors */
|
||||
TMXR dcx_desc = { DCX_LINES, 0, 0, dcx_ldsc }; /* mux descriptor */
|
||||
|
||||
static const uint8 odd_par[] = {
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 00 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 10 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 20 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 30 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 40 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 50 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 60 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 70 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 80 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 90 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* A0 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* B0 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* C0 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* D0 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* E0 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* F0 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80
|
||||
};
|
||||
|
||||
t_stat dcx_rd (int32 *data, int32 PA, int32 access);
|
||||
t_stat dcx_wr (int32 data, int32 PA, int32 access);
|
||||
t_stat dcx_reset (DEVICE *dptr);
|
||||
t_stat dci_svc (UNIT *uptr);
|
||||
t_stat dco_svc (UNIT *uptr);
|
||||
t_stat dcx_attach (UNIT *uptr, char *cptr);
|
||||
t_stat dcx_detach (UNIT *uptr);
|
||||
t_stat dcx_summ (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
t_stat dcx_show (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
t_stat dcx_show_vec (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
t_stat dcx_set_lines (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat dcx_show_lines (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
void dcx_enbdis (int32 dis);
|
||||
void dci_clr_int (int32 ln);
|
||||
void dci_set_int (int32 ln);
|
||||
int32 dci_iack (void);
|
||||
void dco_clr_int (int32 ln);
|
||||
void dco_set_int (int32 ln);
|
||||
int32 dco_iack (void);
|
||||
void dcx_reset_ln (int32 ln);
|
||||
|
||||
/* DCI data structures
|
||||
|
||||
dci_dev DCI device descriptor
|
||||
dci_unit DCI unit descriptor
|
||||
dci_reg DCI register list
|
||||
*/
|
||||
|
||||
DIB dci_dib = {
|
||||
IOBA_DC, IOLN_DC, &dcx_rd, &dcx_wr,
|
||||
2, IVCL (DCI), VEC_DCI, { &dci_iack, &dco_iack }
|
||||
};
|
||||
|
||||
UNIT dci_unit = { UDATA (&dci_svc, 0, 0), KBD_POLL_WAIT };
|
||||
|
||||
REG dci_reg[] = {
|
||||
{ BRDATA (BUF, dci_buf, DEV_RDX, 8, DCX_LINES) },
|
||||
{ BRDATA (CSR, dci_csr, DEV_RDX, 16, DCX_LINES) },
|
||||
{ GRDATA (IREQ, dci_ireq, DEV_RDX, DCX_LINES, 0) },
|
||||
{ DRDATA (LINES, dcx_desc.lines, 6), REG_HRO },
|
||||
{ GRDATA (DEVADDR, dci_dib.ba, DEV_RDX, 32, 0), REG_HRO },
|
||||
{ GRDATA (DEVIOLN, dci_dib.lnt, DEV_RDX, 32, 0), REG_HRO },
|
||||
{ GRDATA (DEVVEC, dci_dib.vec, DEV_RDX, 16, 0), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB dci_mod[] = {
|
||||
{ UNIT_ATT, UNIT_ATT, "summary", NULL, NULL, &dcx_summ },
|
||||
{ MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT",
|
||||
&tmxr_dscln, NULL, &dcx_desc },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL,
|
||||
NULL, &dcx_show, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL,
|
||||
NULL, &dcx_show, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL,
|
||||
&set_addr, &show_addr, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL,
|
||||
&set_vec, &dcx_show_vec, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 0, "lines", "LINES",
|
||||
&dcx_set_lines, &dcx_show_lines },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE dci_dev = {
|
||||
"DCI", &dci_unit, dci_reg, dci_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &dcx_reset,
|
||||
NULL, &dcx_attach, &dcx_detach,
|
||||
&dci_dib, DEV_UBUS | DEV_QBUS | DEV_DISABLE | DEV_DIS
|
||||
};
|
||||
|
||||
/* DCO data structures
|
||||
|
||||
dco_dev DCO device descriptor
|
||||
dco_unit DCO unit descriptor
|
||||
dco_reg DCO register list
|
||||
*/
|
||||
|
||||
UNIT dco_unit[] = {
|
||||
{ UDATA (&dco_svc, TT_MODE_7P+DCX_EPAR+DCX_MDM, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&dco_svc, TT_MODE_7P+DCX_EPAR+DCX_MDM, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&dco_svc, TT_MODE_7P+DCX_EPAR+DCX_MDM, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&dco_svc, TT_MODE_7P+DCX_EPAR+DCX_MDM, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&dco_svc, TT_MODE_7P+DCX_EPAR+DCX_MDM, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&dco_svc, TT_MODE_7P+DCX_EPAR+DCX_MDM, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&dco_svc, TT_MODE_7P+DCX_EPAR+DCX_MDM, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&dco_svc, TT_MODE_7P+DCX_EPAR+DCX_MDM, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&dco_svc, TT_MODE_7P+DCX_EPAR+DCX_MDM, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&dco_svc, TT_MODE_7P+DCX_EPAR+DCX_MDM, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&dco_svc, TT_MODE_7P+DCX_EPAR+DCX_MDM, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&dco_svc, TT_MODE_7P+DCX_EPAR+DCX_MDM, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&dco_svc, TT_MODE_7P+DCX_EPAR+DCX_MDM, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&dco_svc, TT_MODE_7P+DCX_EPAR+DCX_MDM, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&dco_svc, TT_MODE_7P+DCX_EPAR+DCX_MDM, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&dco_svc, TT_MODE_7P+DCX_EPAR+DCX_MDM, 0), SERIAL_OUT_WAIT }
|
||||
};
|
||||
|
||||
REG dco_reg[] = {
|
||||
{ BRDATA (BUF, dco_buf, DEV_RDX, 8, DCX_LINES) },
|
||||
{ BRDATA (CSR, dco_csr, DEV_RDX, 16, DCX_LINES) },
|
||||
{ GRDATA (IREQ, dco_ireq, DEV_RDX, DCX_LINES, 0) },
|
||||
{ URDATA (TIME, dco_unit[0].wait, 10, 31, 0,
|
||||
DCX_LINES, PV_LEFT) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB dco_mod[] = {
|
||||
{ TT_MODE, TT_MODE_UC, "UC", "UC", NULL },
|
||||
{ TT_MODE, TT_MODE_7B, "7b", "7B", NULL },
|
||||
{ TT_MODE, TT_MODE_8B, "8b", "8B", NULL },
|
||||
{ TT_MODE, TT_MODE_7P, "7p", "7P", NULL },
|
||||
{ DCX_OPAR+DCX_EPAR, 0, "no parity", "NOPARITY", NULL },
|
||||
{ DCX_OPAR+DCX_EPAR, DCX_OPAR, "odd parity", "ODDPARITY", NULL },
|
||||
{ DCX_OPAR+DCX_EPAR, DCX_EPAR, "even parity", "EVENPARITY", NULL },
|
||||
{ DCX_MDM, 0, "no dataset", "NODATASET", NULL },
|
||||
{ DCX_MDM, DCX_MDM, "dataset", "DATASET", NULL },
|
||||
{ MTAB_XTD|MTAB_VUN, 0, NULL, "DISCONNECT",
|
||||
&tmxr_dscln, NULL, &dcx_desc },
|
||||
{ MTAB_XTD|MTAB_VUN|MTAB_NC, 0, "LOG", "LOG",
|
||||
&tmxr_set_log, &tmxr_show_log, &dcx_desc },
|
||||
{ MTAB_XTD|MTAB_VUN|MTAB_NC, 0, NULL, "NOLOG",
|
||||
&tmxr_set_nolog, NULL, &dcx_desc },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE dco_dev = {
|
||||
"DCO", dco_unit, dco_reg, dco_mod,
|
||||
DCX_LINES, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &dcx_reset,
|
||||
NULL, NULL, NULL,
|
||||
NULL, DEV_UBUS | DEV_DISABLE | DEV_DIS
|
||||
};
|
||||
|
||||
/* Terminal input routines */
|
||||
|
||||
t_stat dcx_rd (int32 *data, int32 PA, int32 access)
|
||||
{
|
||||
int32 ln = ((PA - dci_dib.ba) >> 3) & DCX_MASK;
|
||||
|
||||
switch ((PA >> 1) & 03) { /* decode PA<2:1> */
|
||||
|
||||
case 00: /* dci csr */
|
||||
if (dci_csr[ln] & DCICSR_ALLERR)
|
||||
dci_csr[ln] |= DCICSR_ERR;
|
||||
else dci_csr[ln] &= ~DCICSR_ERR;
|
||||
*data = dci_csr[ln] & DCICSR_RD;
|
||||
dci_csr[ln] &= ~(CSR_DONE|DCICSR_ALLERR|DCICSR_ERR);
|
||||
return SCPE_OK;
|
||||
|
||||
case 01: /* dci buf */
|
||||
dci_clr_int (ln);
|
||||
*data = dci_buf[ln];
|
||||
return SCPE_OK;
|
||||
|
||||
case 02: /* dco csr */
|
||||
*data = dco_csr[ln] & DCOCSR_RD;
|
||||
return SCPE_OK;
|
||||
|
||||
case 03: /* dco buf */
|
||||
*data = dco_buf[ln];
|
||||
return SCPE_OK;
|
||||
} /* end switch PA */
|
||||
|
||||
return SCPE_NXM;
|
||||
}
|
||||
|
||||
t_stat dcx_wr (int32 data, int32 PA, int32 access)
|
||||
{
|
||||
int32 ln = ((PA - dci_dib.ba) >> 3) & DCX_MASK;
|
||||
TMLN *lp = &dcx_ldsc[ln];
|
||||
|
||||
switch ((PA >> 1) & 03) { /* decode PA<2:1> */
|
||||
|
||||
case 00: /* dci csr */
|
||||
if (access == WRITEB) /* byte write? */
|
||||
data = (PA & 1)?
|
||||
(dci_csr[ln] & 0377) | (data << 8):
|
||||
(dci_csr[ln] & ~0377) | data;
|
||||
if ((data & CSR_IE) == 0) /* clr ie? */
|
||||
dci_clr_int (ln); /* clr int req */
|
||||
else if ((dci_csr[ln] & (CSR_DONE + CSR_IE)) == CSR_DONE)
|
||||
dci_set_int (ln);
|
||||
if (((data ^ dci_csr[ln]) & DCICSR_DTR) && /* DTR change? */
|
||||
(dco_unit[ln].flags & DCX_MDM)) { /* modem ctl? */
|
||||
if (data & DCICSR_DTR) { /* setting DTR? */
|
||||
if (lp->conn) { /* ringing? */
|
||||
dci_csr[ln] = (dci_csr[ln] & ~DCICSR_RNG) |
|
||||
(DCICSR_CDT|DCICSR_CCH|DCICSR_ERR);
|
||||
dco_csr[ln] |= DCOCSR_CTS; /* set CDT,CCH,CTS */
|
||||
if (data & CSR_IE) /* if ie, req int */
|
||||
dci_set_int (ln);
|
||||
}
|
||||
} /* end DTR 0->1 */
|
||||
else { /* clearing DTR */
|
||||
if (lp->conn) { /* connected? */
|
||||
tmxr_linemsg (lp, "\r\nLine hangup\r\n");
|
||||
tmxr_reset_ln (lp); /* reset line */
|
||||
if (dci_csr[ln] & DCICSR_CDT) { /* carrier det? */
|
||||
dci_csr[ln] |= (DCICSR_CCH|DCICSR_ERR);
|
||||
if (data & CSR_IE) /* if ie, req int */
|
||||
dci_set_int (ln);
|
||||
}
|
||||
}
|
||||
dci_csr[ln] &= ~(DCICSR_CDT|DCICSR_RNG);
|
||||
dco_csr[ln] &= ~DCOCSR_CTS; /* clr CDT,RNG,CTS */
|
||||
} /* end DTR 1->0 */
|
||||
} /* end DTR chg+modem */
|
||||
dci_csr[ln] = (uint16) ((dci_csr[ln] & ~DCICSR_WR) | (data & DCICSR_WR));
|
||||
return SCPE_OK;
|
||||
|
||||
case 01: /* dci buf */
|
||||
return SCPE_OK;
|
||||
|
||||
case 02: /* dco csr */
|
||||
if (access == WRITEB) /* byte write? */
|
||||
data = (PA & 1)?
|
||||
(dco_csr[ln] & 0377) | (data << 8):
|
||||
(dco_csr[ln] & ~0377) | data;
|
||||
if ((data & CSR_IE) == 0) /* clr ie? */
|
||||
dco_clr_int (ln); /* clr int req */
|
||||
else if ((dco_csr[ln] & (CSR_DONE + CSR_IE)) == CSR_DONE)
|
||||
dco_set_int (ln);
|
||||
dco_csr[ln] = (uint16) ((dco_csr[ln] & ~DCOCSR_WR) | (data & DCOCSR_WR));
|
||||
return SCPE_OK;
|
||||
|
||||
case 03: /* dco buf */
|
||||
if ((PA & 1) == 0)
|
||||
dco_buf[ln] = data & 0377;
|
||||
dco_csr[ln] &= ~CSR_DONE; /* clr done */
|
||||
dco_clr_int (ln); /* clr int req */
|
||||
sim_activate (&dco_unit[ln], dco_unit[ln].wait);
|
||||
return SCPE_OK;
|
||||
} /* end switch PA */
|
||||
|
||||
return SCPE_NXM;
|
||||
}
|
||||
|
||||
/* Terminal input service */
|
||||
|
||||
t_stat dci_svc (UNIT *uptr)
|
||||
{
|
||||
int32 ln, c, temp;
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
|
||||
return SCPE_OK;
|
||||
sim_activate (uptr, tmxr_poll); /* continue poll */
|
||||
ln = tmxr_poll_conn (&dcx_desc); /* look for connect */
|
||||
if (ln >= 0) { /* got one? */
|
||||
dcx_ldsc[ln].rcve = 1; /* set rcv enb */
|
||||
if (dco_unit[ln].flags & DCX_MDM) { /* modem control? */
|
||||
if (dci_csr[ln] & DCICSR_DTR) /* DTR already set? */
|
||||
dci_csr[ln] |= (DCICSR_CDT|DCICSR_CCH|DCICSR_ERR);
|
||||
else dci_csr[ln] |= (DCICSR_RNG|DCICSR_ERR); /* no, ring */
|
||||
if (dci_csr[ln] & CSR_IE) /* if ie, */
|
||||
dci_set_int (ln); /* req int */
|
||||
}
|
||||
else dco_csr[ln] |= DCOCSR_CTS; /* just connect */
|
||||
}
|
||||
tmxr_poll_rx (&dcx_desc); /* poll for input */
|
||||
for (ln = 0; ln < DCX_LINES; ln++) { /* loop thru lines */
|
||||
if (dcx_ldsc[ln].conn) { /* connected? */
|
||||
if ((temp = tmxr_getc_ln (&dcx_ldsc[ln])) && /* get char */
|
||||
!(temp & SCPE_BREAK)) { /* not break? */
|
||||
c = sim_tt_inpcvt (temp, TT_GET_MODE (dco_unit[ln].flags));
|
||||
if (dci_csr[ln] & CSR_DONE) /* overrun? */
|
||||
dci_csr[ln] |= DCICSR_OVR;
|
||||
else dci_csr[ln] |= CSR_DONE; /* set done */
|
||||
if (dci_csr[ln] & CSR_IE) /* if ie, */
|
||||
dci_set_int (ln); /* req int */
|
||||
if (dco_unit[ln].flags & DCX_OPAR) /* odd parity */
|
||||
c = (c & 0177) | odd_par[c & 0177];
|
||||
else if (dco_unit[ln].flags & DCX_EPAR) /* even parity */
|
||||
c = (c & 0177) | (odd_par[c & 0177] ^ 0200);
|
||||
dci_buf[ln] = c;
|
||||
if ((c & 0200) == odd_par[c & 0177]) /* odd par? */
|
||||
dci_csr[ln] |= DCICSR_PAR;
|
||||
else dci_csr[ln] &= ~DCICSR_PAR;
|
||||
}
|
||||
}
|
||||
else { /* disconnected */
|
||||
if ((dco_unit[ln].flags & DCX_MDM) && /* modem control? */
|
||||
(dci_csr[ln] & DCICSR_CDT)) { /* carrier detect? */
|
||||
dci_csr[ln] |= (DCICSR_CCH|DCICSR_ERR); /* carrier change */
|
||||
if (dci_csr[ln] & CSR_IE) /* if ie, */
|
||||
dci_set_int (ln); /* req int */
|
||||
}
|
||||
dci_csr[ln] &= ~(DCICSR_CDT|DCICSR_RNG); /* clr CDT,RNG,CTS */
|
||||
dco_csr[ln] &= ~DCOCSR_CTS;
|
||||
}
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Terminal output service */
|
||||
|
||||
t_stat dco_svc (UNIT *uptr)
|
||||
{
|
||||
int32 c;
|
||||
int32 ln = uptr - dco_unit; /* line # */
|
||||
|
||||
if (dcx_ldsc[ln].conn) { /* connected? */
|
||||
if (dcx_ldsc[ln].xmte) { /* tx enabled? */
|
||||
TMLN *lp = &dcx_ldsc[ln]; /* get line */
|
||||
c = sim_tt_outcvt (dco_buf[ln], TT_GET_MODE (dco_unit[ln].flags));
|
||||
if (c >= 0) tmxr_putc_ln (lp, c); /* output char */
|
||||
tmxr_poll_tx (&dcx_desc); /* poll xmt */
|
||||
}
|
||||
else {
|
||||
tmxr_poll_tx (&dcx_desc); /* poll xmt */
|
||||
sim_activate (uptr, dco_unit[ln].wait); /* wait */
|
||||
return SCPE_OK;
|
||||
}
|
||||
}
|
||||
dco_csr[ln] |= CSR_DONE; /* set done */
|
||||
if (dco_csr[ln] & CSR_IE) /* ie set? */
|
||||
dco_set_int (ln); /* req int */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Interrupt routines */
|
||||
|
||||
void dci_clr_int (int32 ln)
|
||||
{
|
||||
dci_ireq &= ~(1 << ln); /* clr mux rcv int */
|
||||
if (dci_ireq == 0) /* all clr? */
|
||||
CLR_INT (DCI);
|
||||
else SET_INT (DCI); /* no, set intr */
|
||||
return;
|
||||
}
|
||||
|
||||
void dci_set_int (int32 ln)
|
||||
{
|
||||
dci_ireq |= (1 << ln); /* clr mux rcv int */
|
||||
SET_INT (DCI); /* set master intr */
|
||||
return;
|
||||
}
|
||||
|
||||
int32 dci_iack (void)
|
||||
{
|
||||
int32 ln;
|
||||
|
||||
for (ln = 0; ln < DCX_LINES; ln++) { /* find 1st line */
|
||||
if (dci_ireq & (1 << ln)) {
|
||||
dci_clr_int (ln); /* clear intr */
|
||||
return (dci_dib.vec + (ln * 010)); /* return vector */
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dco_clr_int (int32 ln)
|
||||
{
|
||||
dco_ireq &= ~(1 << ln); /* clr mux rcv int */
|
||||
if (dco_ireq == 0) /* all clr? */
|
||||
CLR_INT (DCO);
|
||||
else SET_INT (DCO); /* no, set intr */
|
||||
return;
|
||||
}
|
||||
|
||||
void dco_set_int (int32 ln)
|
||||
{
|
||||
dco_ireq |= (1 << ln); /* clr mux rcv int */
|
||||
SET_INT (DCO); /* set master intr */
|
||||
return;
|
||||
}
|
||||
|
||||
int32 dco_iack (void)
|
||||
{
|
||||
int32 ln;
|
||||
|
||||
for (ln = 0; ln < DCX_LINES; ln++) { /* find 1st line */
|
||||
if (dco_ireq & (1 << ln)) {
|
||||
dco_clr_int (ln); /* clear intr */
|
||||
return (dci_dib.vec + (ln * 010) + 4); /* return vector */
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Reset */
|
||||
|
||||
t_stat dcx_reset (DEVICE *dptr)
|
||||
{
|
||||
int32 ln;
|
||||
|
||||
dcx_enbdis (dptr->flags & DEV_DIS); /* sync enables */
|
||||
sim_cancel (&dci_unit); /* assume stop */
|
||||
if (dci_unit.flags & UNIT_ATT) /* if attached, */
|
||||
sim_activate (&dci_unit, tmxr_poll); /* activate */
|
||||
for (ln = 0; ln < DCX_LINES; ln++) /* for all lines */
|
||||
dcx_reset_ln (ln);
|
||||
return auto_config (dci_dev.name, dcx_desc.lines); /* auto config */
|
||||
}
|
||||
|
||||
/* Reset individual line */
|
||||
|
||||
void dcx_reset_ln (int32 ln)
|
||||
{
|
||||
dci_buf[ln] = 0; /* clear buf */
|
||||
dci_csr[ln] = 0;
|
||||
dco_buf[ln] = 0; /* clear buf */
|
||||
dco_csr[ln] = CSR_DONE;
|
||||
sim_cancel (&dco_unit[ln]); /* deactivate */
|
||||
dci_clr_int (ln);
|
||||
dco_clr_int (ln);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Attach master unit */
|
||||
|
||||
t_stat dcx_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
t_stat r;
|
||||
|
||||
r = tmxr_attach (&dcx_desc, uptr, cptr); /* attach */
|
||||
if (r != SCPE_OK) /* error? */
|
||||
return r;
|
||||
sim_activate (uptr, tmxr_poll); /* start poll */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Detach master unit */
|
||||
|
||||
t_stat dcx_detach (UNIT *uptr)
|
||||
{
|
||||
int32 i;
|
||||
t_stat r;
|
||||
|
||||
r = tmxr_detach (&dcx_desc, uptr); /* detach */
|
||||
for (i = 0; i < DCX_LINES; i++) /* all lines, */
|
||||
dcx_ldsc[i].rcve = 0; /* disable rcv */
|
||||
sim_cancel (uptr); /* stop poll */
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Show summary processor */
|
||||
|
||||
t_stat dcx_summ (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
int32 i, t;
|
||||
|
||||
for (i = t = 0; i < DCX_LINES; i++) t = t + (dcx_ldsc[i].conn != 0);
|
||||
if (t == 1) fprintf (st, "1 connection");
|
||||
else fprintf (st, "%d connections", t);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* SHOW CONN/STAT processor */
|
||||
|
||||
t_stat dcx_show (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
int32 i, t;
|
||||
|
||||
for (i = t = 0; i < DCX_LINES; i++) t = t + (dcx_ldsc[i].conn != 0);
|
||||
if (t) {
|
||||
for (i = 0; i < DCX_LINES; i++) {
|
||||
if (dcx_ldsc[i].conn) {
|
||||
if (val) tmxr_fconns (st, &dcx_ldsc[i], i);
|
||||
else tmxr_fstats (st, &dcx_ldsc[i], i);
|
||||
}
|
||||
}
|
||||
}
|
||||
else fprintf (st, "all disconnected\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Enable/disable device */
|
||||
|
||||
void dcx_enbdis (int32 dis)
|
||||
{
|
||||
if (dis) {
|
||||
dci_dev.flags = dco_dev.flags | DEV_DIS;
|
||||
dco_dev.flags = dco_dev.flags | DEV_DIS;
|
||||
}
|
||||
else {
|
||||
dci_dev.flags = dci_dev.flags & ~DEV_DIS;
|
||||
dco_dev.flags = dco_dev.flags & ~DEV_DIS;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* SHOW VECTOR processor */
|
||||
|
||||
t_stat dcx_show_vec (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
return show_vec (st, uptr, dcx_desc.lines * 2, desc);
|
||||
}
|
||||
|
||||
/* Change number of lines */
|
||||
|
||||
t_stat dcx_set_lines (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
int32 newln, i, t;
|
||||
t_stat r;
|
||||
|
||||
if (cptr == NULL) return SCPE_ARG;
|
||||
newln = get_uint (cptr, 10, DCX_LINES, &r);
|
||||
if ((r != SCPE_OK) || (newln == dcx_desc.lines)) return r;
|
||||
if (newln == 0) return SCPE_ARG;
|
||||
if (newln < dcx_desc.lines) {
|
||||
for (i = newln, t = 0; i < dcx_desc.lines; i++) t = t | dcx_ldsc[i].conn;
|
||||
if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE))
|
||||
return SCPE_OK;
|
||||
for (i = newln; i < dcx_desc.lines; i++) {
|
||||
if (dcx_ldsc[i].conn) {
|
||||
tmxr_linemsg (&dcx_ldsc[i], "\r\nOperator disconnected line\r\n");
|
||||
tmxr_reset_ln (&dcx_ldsc[i]); /* reset line */
|
||||
}
|
||||
dco_unit[i].flags |= UNIT_DIS;
|
||||
dcx_reset_ln (i);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i = dcx_desc.lines; i < newln; i++) {
|
||||
dco_unit[i].flags &= ~UNIT_DIS;
|
||||
dcx_reset_ln (i);
|
||||
}
|
||||
}
|
||||
dcx_desc.lines = newln;
|
||||
dci_dib.lnt = newln * 010; /* upd IO page lnt */
|
||||
return auto_config (dci_dev.name, newln); /* auto config */
|
||||
}
|
||||
|
||||
/* Show number of lines */
|
||||
|
||||
t_stat dcx_show_lines (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
fprintf (st, "lines=%d", dcx_desc.lines);
|
||||
return SCPE_OK;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/* pdp11_defs.h: PDP-11 simulator definitions
|
||||
|
||||
Copyright (c) 1993-2006, Robert M Supnik
|
||||
Copyright (c) 1993-2008, 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"),
|
||||
@@ -26,6 +26,9 @@
|
||||
The author gratefully acknowledges the help of Max Burnet, Megan Gentry,
|
||||
and John Wilson in resolving questions about the PDP-11
|
||||
|
||||
16-May-08 RMS Added KE11A, DC11 support
|
||||
02-Feb-08 RMS Fixed DMA memory address limit test (found by John Dundas)
|
||||
25-Jan-08 RMS Added RC11, KG11A support (from John Dundas)
|
||||
16-Dec-06 RMS Added TA11 support
|
||||
29-Oct-06 RMS Added clock coscheduling
|
||||
06-Jul-06 RMS Added multiple KL11/DL11 support
|
||||
@@ -92,7 +95,7 @@
|
||||
#define MAXMEMSIZE 020000000 /* 2**22 */
|
||||
#define PAMASK (MAXMEMSIZE - 1) /* 2**22 - 1 */
|
||||
#define MEMSIZE (cpu_unit.capac)
|
||||
#define ADDR_IS_MEM(x) (((t_addr) (x)) < MEMSIZE)
|
||||
#define ADDR_IS_MEM(x) (((t_addr) (x)) < cpu_memsize) /* use only in sim! */
|
||||
#define DMASK 0177777
|
||||
|
||||
/* CPU models */
|
||||
@@ -469,7 +472,8 @@ typedef struct {
|
||||
#define DZ_MUXES 4 /* max # of DZ muxes */
|
||||
#define DZ_LINES 8 /* lines per DZ mux */
|
||||
#define VH_MUXES 4 /* max # of VH muxes */
|
||||
#define TTX_LINES 16 /* max # of KL11/DL11's */
|
||||
#define DLX_LINES 16 /* max # of KL11/DL11's */
|
||||
#define DCX_LINES 16 /* max # of DC11's */
|
||||
#define MT_MAXFR (1 << 16) /* magtape max rec */
|
||||
#define AUTO_LNT 34 /* autoconfig ranks */
|
||||
#define DIB_MAX 100 /* max DIBs */
|
||||
@@ -521,6 +525,8 @@ typedef struct pdp_dib DIB;
|
||||
#define IOLN_VH 020
|
||||
#define IOBA_UBM (IOPAGEBASE + 010200) /* Unibus map */
|
||||
#define IOLN_UBM (UBM_LNT_LW * sizeof (int32))
|
||||
#define IOBA_KG (IOPAGEBASE + 010700) /* KG11-A */
|
||||
#define IOLN_KG 006
|
||||
#define IOBA_RQ (IOPAGEBASE + 012150) /* RQDX3 */
|
||||
#define IOLN_RQ 004
|
||||
#define IOBA_SUP (IOPAGEBASE + 012200) /* supervisor APR's */
|
||||
@@ -543,6 +549,8 @@ typedef struct pdp_dib DIB;
|
||||
#define IOLN_TS 004
|
||||
#define IOBA_PCLK (IOPAGEBASE + 012540) /* KW11P */
|
||||
#define IOLN_PCLK 006
|
||||
#define IOBA_DC (IOPAGEBASE + 014000) /* DC11 */
|
||||
#define IOLN_DC (DCX_LINES * 010)
|
||||
#define IOBA_RL (IOPAGEBASE + 014400) /* RL11 */
|
||||
#define IOLN_RL 012
|
||||
#define IOBA_XQ (IOPAGEBASE + 014440) /* DEQNA/DELQA */
|
||||
@@ -553,8 +561,8 @@ typedef struct pdp_dib DIB;
|
||||
#define IOLN_TQ 004
|
||||
#define IOBA_XU (IOPAGEBASE + 014510) /* DEUNA/DELUA */
|
||||
#define IOLN_XU 010
|
||||
#define IOBA_TTIX (IOPAGEBASE + 016500) /* extra KL11/DL11 */
|
||||
#define IOLN_TTIX (TTX_LINES * 010)
|
||||
#define IOBA_DL (IOPAGEBASE + 016500) /* extra KL11/DL11 */
|
||||
#define IOLN_DL (DLX_LINES * 010)
|
||||
#define IOBA_RP (IOPAGEBASE + 016700) /* RP/RM */
|
||||
#define IOLN_RP 054
|
||||
#define IOBA_CR (IOPAGEBASE + 017160) /* CD/CR/CM */
|
||||
@@ -563,10 +571,14 @@ typedef struct pdp_dib DIB;
|
||||
#define IOLN_RX 004
|
||||
#define IOBA_RY (IOPAGEBASE + 017170) /* RY11 */
|
||||
#define IOLN_RY 004
|
||||
#define IOBA_KE (IOPAGEBASE + 017300) /* KE11-A */
|
||||
#define IOLN_KE 020
|
||||
#define IOBA_TC (IOPAGEBASE + 017340) /* TC11 */
|
||||
#define IOLN_TC 012
|
||||
#define IOBA_RK (IOPAGEBASE + 017400) /* RK11 */
|
||||
#define IOLN_RK 020
|
||||
#define IOBA_RC (IOPAGEBASE + 017440) /* RC11/RS64 */
|
||||
#define IOLN_RC 020
|
||||
#define IOBA_HK (IOPAGEBASE + 017440) /* RK611 */
|
||||
#define IOLN_HK 040
|
||||
#define IOBA_RF (IOPAGEBASE + 017460) /* RF11 */
|
||||
@@ -636,7 +648,8 @@ typedef struct pdp_dib DIB;
|
||||
#define INT_V_XU 13
|
||||
#define INT_V_TU 14
|
||||
#define INT_V_RF 15
|
||||
#define INT_V_PIR5 16
|
||||
#define INT_V_RC 16
|
||||
#define INT_V_PIR5 17
|
||||
|
||||
#define INT_V_TTI 0 /* BR4 */
|
||||
#define INT_V_TTO 1
|
||||
@@ -646,9 +659,11 @@ typedef struct pdp_dib DIB;
|
||||
#define INT_V_VHRX 5
|
||||
#define INT_V_VHTX 6
|
||||
#define INT_V_CR 7
|
||||
#define INT_V_TTIX 8
|
||||
#define INT_V_TTOX 9
|
||||
#define INT_V_PIR4 10
|
||||
#define INT_V_DLI 8
|
||||
#define INT_V_DLO 9
|
||||
#define INT_V_DCI 10
|
||||
#define INT_V_DCO 11
|
||||
#define INT_V_PIR4 12
|
||||
|
||||
#define INT_V_PIR3 0 /* BR3 */
|
||||
#define INT_V_PIR2 0 /* BR2 */
|
||||
@@ -676,6 +691,7 @@ typedef struct pdp_dib DIB;
|
||||
#define INT_XU (1u << INT_V_XU)
|
||||
#define INT_TU (1u << INT_V_TU)
|
||||
#define INT_RF (1u << INT_V_RF)
|
||||
#define INT_RC (1u << INT_V_RC)
|
||||
#define INT_PIR5 (1u << INT_V_PIR5)
|
||||
#define INT_PTR (1u << INT_V_PTR)
|
||||
#define INT_PTP (1u << INT_V_PTP)
|
||||
@@ -685,8 +701,10 @@ typedef struct pdp_dib DIB;
|
||||
#define INT_VHRX (1u << INT_V_VHRX)
|
||||
#define INT_VHTX (1u << INT_V_VHTX)
|
||||
#define INT_CR (1u << INT_V_CR)
|
||||
#define INT_TTIX (1u << INT_V_TTIX)
|
||||
#define INT_TTOX (1u << INT_V_TTOX)
|
||||
#define INT_DLI (1u << INT_V_DLI)
|
||||
#define INT_DLO (1u << INT_V_DLO)
|
||||
#define INT_DCI (1u << INT_V_DCI)
|
||||
#define INT_DCO (1u << INT_V_DCO)
|
||||
#define INT_PIR4 (1u << INT_V_PIR4)
|
||||
#define INT_PIR3 (1u << INT_V_PIR3)
|
||||
#define INT_PIR2 (1u << INT_V_PIR2)
|
||||
@@ -712,6 +730,7 @@ typedef struct pdp_dib DIB;
|
||||
#define IPL_XU 5
|
||||
#define IPL_TU 5
|
||||
#define IPL_RF 5
|
||||
#define IPL_RC 5
|
||||
#define IPL_PTR 4
|
||||
#define IPL_PTP 4
|
||||
#define IPL_TTI 4
|
||||
@@ -720,8 +739,10 @@ typedef struct pdp_dib DIB;
|
||||
#define IPL_VHRX 4
|
||||
#define IPL_VHTX 4
|
||||
#define IPL_CR 4
|
||||
#define IPL_TTIX 4
|
||||
#define IPL_TTOX 4
|
||||
#define IPL_DLI 4
|
||||
#define IPL_DLO 4
|
||||
#define IPL_DCI 4
|
||||
#define IPL_DCO 4
|
||||
|
||||
#define IPL_PIR7 7
|
||||
#define IPL_PIR6 6
|
||||
@@ -748,6 +769,7 @@ typedef struct pdp_dib DIB;
|
||||
#define VEC_LPT 0200
|
||||
#define VEC_RF 0204
|
||||
#define VEC_HK 0210
|
||||
#define VEC_RC 0210
|
||||
#define VEC_RK 0220
|
||||
#define VEC_DTA 0214
|
||||
#define VEC_TM 0224
|
||||
@@ -759,8 +781,10 @@ typedef struct pdp_dib DIB;
|
||||
#define VEC_TA 0260
|
||||
#define VEC_RX 0264
|
||||
#define VEC_RY 0264
|
||||
#define VEC_TTIX 0300
|
||||
#define VEC_TTOX 0304
|
||||
#define VEC_DLI 0300
|
||||
#define VEC_DLO 0304
|
||||
#define VEC_DCI 0300
|
||||
#define VEC_DCO 0304
|
||||
#define VEC_DZRX 0300
|
||||
#define VEC_DZTX 0304
|
||||
#define VEC_VHRX 0310
|
||||
|
||||
543
PDP11/pdp11_dl.c
543
PDP11/pdp11_dl.c
@@ -23,9 +23,10 @@
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
ttix,ttox DL11 terminal input/output
|
||||
*/
|
||||
dli,dlo DL11 terminal input/output
|
||||
|
||||
20-May-2008 RMS Added modem control support
|
||||
*/
|
||||
|
||||
#if defined (VM_PDP10) /* PDP10 version */
|
||||
#error "DL11 is not supported on the PDP-10!"
|
||||
@@ -39,198 +40,258 @@
|
||||
#include "sim_sock.h"
|
||||
#include "sim_tmxr.h"
|
||||
|
||||
#define TTX_MASK (TTX_LINES - 1)
|
||||
#define DLX_MASK (DLX_LINES - 1)
|
||||
#define DLI_RCI 0 /* rcv ints */
|
||||
#define DLI_DSI 1 /* dset ints */
|
||||
|
||||
#define TTIXCSR_IMP (CSR_DONE + CSR_IE) /* terminal input */
|
||||
#define TTIXCSR_RW (CSR_IE)
|
||||
#define TTIXBUF_ERR 0100000
|
||||
#define TTIXBUF_OVR 0040000
|
||||
#define TTIXBUF_RBRK 0020000
|
||||
#define TTOXCSR_IMP (CSR_DONE + CSR_IE) /* terminal output */
|
||||
#define TTOXCSR_RW (CSR_IE)
|
||||
/* Modem control */
|
||||
|
||||
#define DLX_V_MDM (TTUF_V_UF + 0)
|
||||
#define DLX_MDM (1u << DLX_V_MDM)
|
||||
|
||||
/* registers */
|
||||
|
||||
#define DLICSR_DSI 0100000 /* dataset int, RO */
|
||||
#define DLICSR_RNG 0040000 /* ring, RO */
|
||||
#define DLICSR_CTS 0020000 /* CTS, RO */
|
||||
#define DLICSR_CDT 0010000 /* CDT, RO */
|
||||
#define DLICSR_SEC 0002000 /* sec rcv, RONI */
|
||||
#define DLICSR_DSIE 0000040 /* DSI ie, RW */
|
||||
#define DLICSR_SECX 0000010 /* sec xmt, RWNI */
|
||||
#define DLICSR_RTS 0000004 /* RTS, RW */
|
||||
#define DLICSR_DTR 0000002 /* DTR, RW */
|
||||
#define DLICSR_RD (CSR_DONE|CSR_IE) /* DL11C */
|
||||
#define DLICSR_WR (CSR_IE)
|
||||
#define DLICSR_RD_M (DLICSR_DSI|DLICSR_RNG|DLICSR_CTS|DLICSR_CDT|DLICSR_SEC| \
|
||||
CSR_DONE|CSR_IE|DLICSR_DSIE|DLICSR_SECX|DLICSR_RTS|DLICSR_DTR)
|
||||
#define DLICSR_WR_M (CSR_IE|DLICSR_DSIE|DLICSR_SECX|DLICSR_RTS|DLICSR_DTR)
|
||||
#define DLIBUF_ERR 0100000
|
||||
#define DLIBUF_OVR 0040000
|
||||
#define DLIBUF_RBRK 0020000
|
||||
#define DLIBUF_RD (DLIBUF_ERR|DLIBUF_OVR|DLIBUF_RBRK|0377)
|
||||
#define DLOCSR_MNT 0000004 /* maint, RWNI */
|
||||
#define DLOCSR_XBR 0000001 /* xmit brk, RWNI */
|
||||
#define DLOCSR_RD (CSR_DONE|CSR_IE|DLOCSR_MNT|DLOCSR_XBR)
|
||||
#define DLOCSR_WR (CSR_IE|DLOCSR_MNT|DLOCSR_XBR)
|
||||
|
||||
extern int32 int_req[IPL_HLVL];
|
||||
extern int32 tmxr_poll;
|
||||
|
||||
uint16 ttix_csr[TTX_LINES] = { 0 }; /* control/status */
|
||||
uint16 ttix_buf[TTX_LINES] = { 0 };
|
||||
uint32 ttix_ireq = 0;
|
||||
uint16 ttox_csr[TTX_LINES] = { 0 }; /* control/status */
|
||||
uint8 ttox_buf[TTX_LINES] = { 0 };
|
||||
uint32 ttox_ireq = 0;
|
||||
TMLN ttx_ldsc[TTX_LINES] = { 0 }; /* line descriptors */
|
||||
TMXR ttx_desc = { TTX_LINES, 0, 0, ttx_ldsc }; /* mux descriptor */
|
||||
uint16 dli_csr[DLX_LINES] = { 0 }; /* control/status */
|
||||
uint16 dli_buf[DLX_LINES] = { 0 };
|
||||
uint32 dli_ireq[2] = { 0, 0};
|
||||
uint16 dlo_csr[DLX_LINES] = { 0 }; /* control/status */
|
||||
uint8 dlo_buf[DLX_LINES] = { 0 };
|
||||
uint32 dlo_ireq = 0;
|
||||
TMLN dlx_ldsc[DLX_LINES] = { 0 }; /* line descriptors */
|
||||
TMXR dlx_desc = { DLX_LINES, 0, 0, dlx_ldsc }; /* mux descriptor */
|
||||
|
||||
t_stat ttx_rd (int32 *data, int32 PA, int32 access);
|
||||
t_stat ttx_wr (int32 data, int32 PA, int32 access);
|
||||
t_stat ttx_reset (DEVICE *dptr);
|
||||
t_stat ttix_svc (UNIT *uptr);
|
||||
t_stat ttox_svc (UNIT *uptr);
|
||||
t_stat ttx_attach (UNIT *uptr, char *cptr);
|
||||
t_stat ttx_detach (UNIT *uptr);
|
||||
t_stat ttx_summ (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
t_stat ttx_show (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
t_stat ttx_show_vec (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
t_stat ttx_set_lines (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat ttx_show_lines (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
void ttx_enbdis (int32 dis);
|
||||
void ttix_clr_int (uint32 ln);
|
||||
void ttix_set_int (int32 ln);
|
||||
int32 ttix_iack (void);
|
||||
void ttox_clr_int (int32 ln);
|
||||
void ttox_set_int (int32 ln);
|
||||
int32 ttox_iack (void);
|
||||
void ttx_reset_ln (uint32 ln);
|
||||
t_stat dlx_rd (int32 *data, int32 PA, int32 access);
|
||||
t_stat dlx_wr (int32 data, int32 PA, int32 access);
|
||||
t_stat dlx_reset (DEVICE *dptr);
|
||||
t_stat dli_svc (UNIT *uptr);
|
||||
t_stat dlo_svc (UNIT *uptr);
|
||||
t_stat dlx_attach (UNIT *uptr, char *cptr);
|
||||
t_stat dlx_detach (UNIT *uptr);
|
||||
t_stat dlx_summ (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
t_stat dlx_show (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
t_stat dlx_show_vec (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
t_stat dlx_set_lines (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat dlx_show_lines (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
void dlx_enbdis (int32 dis);
|
||||
void dli_clr_int (int32 ln, uint32 wd);
|
||||
void dli_set_int (int32 ln, uint32 wd);
|
||||
int32 dli_iack (void);
|
||||
void dlo_clr_int (int32 ln);
|
||||
void dlo_set_int (int32 ln);
|
||||
int32 dlo_iack (void);
|
||||
void dlx_reset_ln (int32 ln);
|
||||
|
||||
/* TTIX data structures
|
||||
/* DLI data structures
|
||||
|
||||
ttix_dev TTIX device descriptor
|
||||
ttix_unit TTIX unit descriptor
|
||||
ttix_reg TTIX register list
|
||||
dli_dev DLI device descriptor
|
||||
dli_unit DLI unit descriptor
|
||||
dli_reg DLI register list
|
||||
*/
|
||||
|
||||
DIB ttix_dib = {
|
||||
IOBA_TTIX, IOLN_TTIX, &ttx_rd, &ttx_wr,
|
||||
2, IVCL (TTIX), VEC_TTIX, { &ttix_iack, &ttox_iack }
|
||||
DIB dli_dib = {
|
||||
IOBA_DL, IOLN_DL, &dlx_rd, &dlx_wr,
|
||||
2, IVCL (DLI), VEC_DLI, { &dli_iack, &dlo_iack }
|
||||
};
|
||||
|
||||
UNIT ttix_unit = { UDATA (&ttix_svc, 0, 0), KBD_POLL_WAIT };
|
||||
UNIT dli_unit = { UDATA (&dli_svc, 0, 0), KBD_POLL_WAIT };
|
||||
|
||||
REG ttix_reg[] = {
|
||||
{ BRDATA (BUF, ttix_buf, DEV_RDX, 16, TTX_LINES) },
|
||||
{ BRDATA (CSR, ttix_csr, DEV_RDX, 16, TTX_LINES) },
|
||||
{ GRDATA (IREQ, ttix_ireq, DEV_RDX, TTX_LINES, 0) },
|
||||
{ DRDATA (LINES, ttx_desc.lines, 6), REG_HRO },
|
||||
{ GRDATA (DEVADDR, ttix_dib.ba, DEV_RDX, 32, 0), REG_HRO },
|
||||
{ GRDATA (DEVVEC, ttix_dib.vec, DEV_RDX, 16, 0), REG_HRO },
|
||||
REG dli_reg[] = {
|
||||
{ BRDATA (BUF, dli_buf, DEV_RDX, 16, DLX_LINES) },
|
||||
{ BRDATA (CSR, dli_csr, DEV_RDX, 16, DLX_LINES) },
|
||||
{ GRDATA (IREQ, dli_ireq[DLI_RCI], DEV_RDX, DLX_LINES, 0) },
|
||||
{ GRDATA (DSI, dli_ireq[DLI_DSI], DEV_RDX, DLX_LINES, 0) },
|
||||
{ DRDATA (LINES, dlx_desc.lines, 6), REG_HRO },
|
||||
{ GRDATA (DEVADDR, dli_dib.ba, DEV_RDX, 32, 0), REG_HRO },
|
||||
{ GRDATA (DEVIOLN, dli_dib.lnt, DEV_RDX, 32, 0), REG_HRO },
|
||||
{ GRDATA (DEVVEC, dli_dib.vec, DEV_RDX, 16, 0), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB ttix_mod[] = {
|
||||
{ UNIT_ATT, UNIT_ATT, "summary", NULL, NULL, &ttx_summ },
|
||||
MTAB dli_mod[] = {
|
||||
{ UNIT_ATT, UNIT_ATT, "summary", NULL, NULL, &dlx_summ },
|
||||
{ MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT",
|
||||
&tmxr_dscln, NULL, &ttx_desc },
|
||||
&tmxr_dscln, NULL, &dlx_desc },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL,
|
||||
NULL, &ttx_show, NULL },
|
||||
NULL, &dlx_show, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL,
|
||||
NULL, &ttx_show, NULL },
|
||||
NULL, &dlx_show, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL,
|
||||
&set_addr, &show_addr, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL,
|
||||
&set_vec, &ttx_show_vec, NULL },
|
||||
&set_vec, &dlx_show_vec, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 0, "lines", "LINES",
|
||||
&ttx_set_lines, &ttx_show_lines },
|
||||
&dlx_set_lines, &dlx_show_lines },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE ttix_dev = {
|
||||
"TTIX", &ttix_unit, ttix_reg, ttix_mod,
|
||||
DEVICE dli_dev = {
|
||||
"DLI", &dli_unit, dli_reg, dli_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &ttx_reset,
|
||||
NULL, &ttx_attach, &ttx_detach,
|
||||
&ttix_dib, DEV_UBUS | DEV_QBUS | DEV_DISABLE | DEV_DIS
|
||||
NULL, NULL, &dlx_reset,
|
||||
NULL, &dlx_attach, &dlx_detach,
|
||||
&dli_dib, DEV_UBUS | DEV_QBUS | DEV_DISABLE | DEV_DIS
|
||||
};
|
||||
|
||||
/* TTOX data structures
|
||||
/* DLO data structures
|
||||
|
||||
ttox_dev TTOX device descriptor
|
||||
ttox_unit TTOX unit descriptor
|
||||
ttox_reg TTOX register list
|
||||
dlo_dev DLO device descriptor
|
||||
dlo_unit DLO unit descriptor
|
||||
dlo_reg DLO register list
|
||||
*/
|
||||
|
||||
UNIT ttox_unit[] = {
|
||||
{ UDATA (&ttox_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&ttox_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&ttox_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&ttox_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&ttox_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&ttox_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&ttox_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&ttox_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&ttox_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&ttox_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&ttox_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&ttox_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&ttox_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&ttox_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&ttox_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&ttox_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT }
|
||||
UNIT dlo_unit[] = {
|
||||
{ UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT },
|
||||
{ UDATA (&dlo_svc, TT_MODE_UC, 0), SERIAL_OUT_WAIT }
|
||||
};
|
||||
|
||||
REG ttox_reg[] = {
|
||||
{ BRDATA (BUF, ttox_buf, DEV_RDX, 8, TTX_LINES) },
|
||||
{ BRDATA (CSR, ttox_csr, DEV_RDX, 16, TTX_LINES) },
|
||||
{ GRDATA (IREQ, ttox_ireq, DEV_RDX, TTX_LINES, 0) },
|
||||
{ URDATA (TIME, ttox_unit[0].wait, 10, 31, 0,
|
||||
TTX_LINES, PV_LEFT) },
|
||||
REG dlo_reg[] = {
|
||||
{ BRDATA (BUF, dlo_buf, DEV_RDX, 8, DLX_LINES) },
|
||||
{ BRDATA (CSR, dlo_csr, DEV_RDX, 16, DLX_LINES) },
|
||||
{ GRDATA (IREQ, dlo_ireq, DEV_RDX, DLX_LINES, 0) },
|
||||
{ URDATA (TIME, dlo_unit[0].wait, 10, 31, 0,
|
||||
DLX_LINES, PV_LEFT) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB ttox_mod[] = {
|
||||
MTAB dlo_mod[] = {
|
||||
{ TT_MODE, TT_MODE_UC, "UC", "UC", NULL },
|
||||
{ TT_MODE, TT_MODE_7B, "7b", "7B", NULL },
|
||||
{ TT_MODE, TT_MODE_8B, "8b", "8B", NULL },
|
||||
{ TT_MODE, TT_MODE_7P, "7p", "7P", NULL },
|
||||
{ DLX_MDM, 0, "no dataset", "NODATASET", NULL },
|
||||
{ DLX_MDM, DLX_MDM, "dataset", "DATASET", NULL },
|
||||
{ MTAB_XTD|MTAB_VUN, 0, NULL, "DISCONNECT",
|
||||
&tmxr_dscln, NULL, &ttx_desc },
|
||||
&tmxr_dscln, NULL, &dlx_desc },
|
||||
{ MTAB_XTD|MTAB_VUN|MTAB_NC, 0, "LOG", "LOG",
|
||||
&tmxr_set_log, &tmxr_show_log, &ttx_desc },
|
||||
&tmxr_set_log, &tmxr_show_log, &dlx_desc },
|
||||
{ MTAB_XTD|MTAB_VUN|MTAB_NC, 0, NULL, "NOLOG",
|
||||
&tmxr_set_nolog, NULL, &ttx_desc },
|
||||
&tmxr_set_nolog, NULL, &dlx_desc },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE ttox_dev = {
|
||||
"TTOX", ttox_unit, ttox_reg, ttox_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &ttx_reset,
|
||||
DEVICE dlo_dev = {
|
||||
"DLO", dlo_unit, dlo_reg, dlo_mod,
|
||||
DLX_LINES, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &dlx_reset,
|
||||
NULL, NULL, NULL,
|
||||
NULL, DEV_UBUS | DEV_QBUS | DEV_DISABLE | DEV_DIS
|
||||
};
|
||||
|
||||
/* Terminal input routines */
|
||||
|
||||
t_stat ttx_rd (int32 *data, int32 PA, int32 access)
|
||||
t_stat dlx_rd (int32 *data, int32 PA, int32 access)
|
||||
{
|
||||
uint32 ln = ((PA - ttix_dib.ba) >> 3) & TTX_MASK;
|
||||
int32 ln = ((PA - dli_dib.ba) >> 3) & DLX_MASK;
|
||||
|
||||
switch ((PA >> 1) & 03) { /* decode PA<2:1> */
|
||||
|
||||
case 00: /* tti csr */
|
||||
*data = ttix_csr[ln] & TTIXCSR_IMP;
|
||||
*data = dli_csr[ln] &
|
||||
((dlo_unit[ln].flags & DLX_MDM)? DLICSR_RD_M: DLICSR_RD);
|
||||
dli_csr[ln] &= ~DLICSR_DSI; /* clr DSI flag */
|
||||
dli_clr_int (ln, DLI_DSI); /* clr dset int req */
|
||||
return SCPE_OK;
|
||||
|
||||
case 01: /* tti buf */
|
||||
ttix_csr[ln] &= ~CSR_DONE;
|
||||
ttix_clr_int (ln);
|
||||
*data = ttix_buf[ln];
|
||||
*data = dli_buf[ln] & DLIBUF_RD;
|
||||
dli_csr[ln] &= ~CSR_DONE; /* clr rcv done */
|
||||
dli_clr_int (ln, DLI_RCI); /* clr rcv int req */
|
||||
return SCPE_OK;
|
||||
|
||||
case 02: /* tto csr */
|
||||
*data = ttox_csr[ln] & TTOXCSR_IMP;
|
||||
*data = dlo_csr[ln] & DLOCSR_RD;
|
||||
return SCPE_OK;
|
||||
|
||||
case 03: /* tto buf */
|
||||
*data = ttox_buf[ln];
|
||||
*data = dlo_buf[ln];
|
||||
return SCPE_OK;
|
||||
} /* end switch PA */
|
||||
|
||||
return SCPE_NXM;
|
||||
}
|
||||
|
||||
t_stat ttx_wr (int32 data, int32 PA, int32 access)
|
||||
t_stat dlx_wr (int32 data, int32 PA, int32 access)
|
||||
{
|
||||
uint32 ln = ((PA - ttix_dib.ba) >> 3) & TTX_MASK;
|
||||
int32 ln = ((PA - dli_dib.ba) >> 3) & DLX_MASK;
|
||||
TMLN *lp = &dlx_ldsc[ln];
|
||||
|
||||
switch ((PA >> 1) & 03) { /* decode PA<2:1> */
|
||||
|
||||
case 00: /* tti csr */
|
||||
if (PA & 1) return SCPE_OK;
|
||||
if (PA & 1) return SCPE_OK; /* odd byte RO */
|
||||
if ((data & CSR_IE) == 0)
|
||||
ttix_clr_int (ln);
|
||||
else if ((ttix_csr[ln] & (CSR_DONE + CSR_IE)) == CSR_DONE)
|
||||
ttix_set_int (ln);
|
||||
ttix_csr[ln] = (uint16) ((ttix_csr[ln] & ~TTIXCSR_RW) | (data & TTIXCSR_RW));
|
||||
dli_clr_int (ln, DLI_RCI);
|
||||
else if ((dli_csr[ln] & (CSR_DONE + CSR_IE)) == CSR_DONE)
|
||||
dli_set_int (ln, DLI_RCI);
|
||||
if (dlo_unit[ln].flags & DLX_MDM) { /* modem control */
|
||||
if ((data & DLICSR_DSIE) == 0)
|
||||
dli_clr_int (ln, DLI_DSI);
|
||||
else if ((dli_csr[ln] & (DLICSR_DSI|DLICSR_DSIE)) == DLICSR_DSI)
|
||||
dli_set_int (ln, DLI_DSI);
|
||||
if ((data ^ dli_csr[ln]) & DLICSR_DTR) { /* DTR change? */
|
||||
if ((data & DLICSR_DTR) && lp->conn) { /* setting DTR? */
|
||||
dli_csr[ln] = (dli_csr[ln] & ~DLICSR_RNG) |
|
||||
(DLICSR_CDT|DLICSR_CTS|DLICSR_DSI);
|
||||
if (data & DLICSR_DSIE) /* if ie, req int */
|
||||
dli_set_int (ln, DLI_DSI);
|
||||
} /* end DTR 0->1 + ring */
|
||||
else { /* clearing DTR */
|
||||
if (lp->conn) { /* connected? */
|
||||
tmxr_linemsg (lp, "\r\nLine hangup\r\n");
|
||||
tmxr_reset_ln (lp); /* reset line */
|
||||
if (dli_csr[ln] & DLICSR_CDT) { /* carrier det? */
|
||||
dli_csr[ln] |= DLICSR_DSI;
|
||||
if (data & DLICSR_DSIE) /* if ie, req int */
|
||||
dli_set_int (ln, DLI_DSI);
|
||||
}
|
||||
}
|
||||
dli_csr[ln] &= ~(DLICSR_CDT|DLICSR_RNG|DLICSR_CTS);
|
||||
/* clr CDT,RNG,CTS */
|
||||
} /* end DTR 1->0 */
|
||||
} /* end DTR chg */
|
||||
dli_csr[ln] = (uint16) ((dli_csr[ln] & ~DLICSR_WR_M) | (data & DLICSR_WR_M));
|
||||
} /* end modem */
|
||||
dli_csr[ln] = (uint16) ((dli_csr[ln] & ~DLICSR_WR) | (data & DLICSR_WR));
|
||||
return SCPE_OK;
|
||||
|
||||
case 01: /* tti buf */
|
||||
@@ -239,18 +300,18 @@ switch ((PA >> 1) & 03) { /* decode PA<2:1> */
|
||||
case 02: /* tto csr */
|
||||
if (PA & 1) return SCPE_OK;
|
||||
if ((data & CSR_IE) == 0)
|
||||
ttox_clr_int (ln);
|
||||
else if ((ttox_csr[ln] & (CSR_DONE + CSR_IE)) == CSR_DONE)
|
||||
ttox_set_int (ln);
|
||||
ttox_csr[ln] = (uint16) ((ttox_csr[ln] & ~TTOXCSR_RW) | (data & TTOXCSR_RW));
|
||||
dlo_clr_int (ln);
|
||||
else if ((dlo_csr[ln] & (CSR_DONE + CSR_IE)) == CSR_DONE)
|
||||
dlo_set_int (ln);
|
||||
dlo_csr[ln] = (uint16) ((dlo_csr[ln] & ~DLOCSR_WR) | (data & DLOCSR_WR));
|
||||
return SCPE_OK;
|
||||
|
||||
case 03: /* tto buf */
|
||||
if ((PA & 1) == 0)
|
||||
ttox_buf[ln] = data & 0377;
|
||||
ttox_csr[ln] &= ~CSR_DONE;
|
||||
ttox_clr_int (ln);
|
||||
sim_activate (&ttox_unit[ln], ttox_unit[ln].wait);
|
||||
dlo_buf[ln] = data & 0377;
|
||||
dlo_csr[ln] &= ~CSR_DONE;
|
||||
dlo_clr_int (ln);
|
||||
sim_activate (&dlo_unit[ln], dlo_unit[ln].wait);
|
||||
return SCPE_OK;
|
||||
} /* end switch PA */
|
||||
|
||||
@@ -259,112 +320,132 @@ return SCPE_NXM;
|
||||
|
||||
/* Terminal input service */
|
||||
|
||||
t_stat ttix_svc (UNIT *uptr)
|
||||
t_stat dli_svc (UNIT *uptr)
|
||||
{
|
||||
int32 ln, c, temp;
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */
|
||||
sim_activate (uptr, tmxr_poll); /* continue poll */
|
||||
ln = tmxr_poll_conn (&ttx_desc); /* look for connect */
|
||||
if (ln >= 0) ttx_ldsc[ln].rcve = 1; /* got one? rcv enb */
|
||||
tmxr_poll_rx (&ttx_desc); /* poll for input */
|
||||
for (ln = 0; ln < TTX_LINES; ln++) { /* loop thru lines */
|
||||
if (ttx_ldsc[ln].conn) { /* connected? */
|
||||
if (temp = tmxr_getc_ln (&ttx_ldsc[ln])) { /* get char */
|
||||
ln = tmxr_poll_conn (&dlx_desc); /* look for connect */
|
||||
if (ln >= 0) { /* got one? rcv enb */
|
||||
dlx_ldsc[ln].rcve = 1;
|
||||
if (dlo_unit[ln].flags & DLX_MDM) { /* modem control? */
|
||||
if (dli_csr[ln] & DLICSR_DTR) /* DTR already set? */
|
||||
dli_csr[ln] |= (DLICSR_CDT|DLICSR_CTS|DLICSR_DSI);
|
||||
else dli_csr[ln] |= (DLICSR_RNG|DLICSR_DSI); /* no, ring */
|
||||
if (dli_csr[ln] & DLICSR_DSIE) /* if ie, */
|
||||
dli_set_int (ln, DLI_DSI); /* req int */
|
||||
} /* end modem */
|
||||
} /* end new conn */
|
||||
tmxr_poll_rx (&dlx_desc); /* poll for input */
|
||||
for (ln = 0; ln < DLX_LINES; ln++) { /* loop thru lines */
|
||||
if (dlx_ldsc[ln].conn) { /* connected? */
|
||||
if (temp = tmxr_getc_ln (&dlx_ldsc[ln])) { /* get char */
|
||||
if (temp & SCPE_BREAK) /* break? */
|
||||
c = TTIXBUF_ERR|TTIXBUF_RBRK;
|
||||
else c = sim_tt_inpcvt (temp, TT_GET_MODE (ttox_unit[ln].flags));
|
||||
if (ttix_csr[ln] & CSR_DONE)
|
||||
c |= TTIXBUF_ERR|TTIXBUF_OVR;
|
||||
else {
|
||||
ttix_csr[ln] |= CSR_DONE;
|
||||
if (ttix_csr[ln] & CSR_IE) ttix_set_int (ln);
|
||||
}
|
||||
ttix_buf[ln] = c;
|
||||
c = DLIBUF_ERR|DLIBUF_RBRK;
|
||||
else c = sim_tt_inpcvt (temp, TT_GET_MODE (dlo_unit[ln].flags));
|
||||
if (dli_csr[ln] & CSR_DONE)
|
||||
c |= DLIBUF_ERR|DLIBUF_OVR;
|
||||
else dli_csr[ln] |= CSR_DONE;
|
||||
if (dli_csr[ln] & CSR_IE)
|
||||
dli_set_int (ln, DLI_RCI);
|
||||
dli_buf[ln] = c;
|
||||
}
|
||||
}
|
||||
else if (dlo_unit[ln].flags & DLX_MDM) { /* discpnn & modem? */
|
||||
if (dli_csr[ln] & DLICSR_CDT) { /* carrier detect? */
|
||||
dli_csr[ln] |= DLICSR_DSI; /* dataset change */
|
||||
if (dli_csr[ln] & DLICSR_DSIE) /* if ie, */
|
||||
dli_set_int (ln, DLI_DSI); /* req int */
|
||||
}
|
||||
dli_csr[ln] &= ~(DLICSR_CDT|DLICSR_RNG|DLICSR_CTS);
|
||||
/* clr CDT,RNG,CTS */
|
||||
}
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Terminal output service */
|
||||
|
||||
t_stat ttox_svc (UNIT *uptr)
|
||||
t_stat dlo_svc (UNIT *uptr)
|
||||
{
|
||||
int32 c;
|
||||
uint32 ln = uptr - ttox_unit; /* line # */
|
||||
int32 ln = uptr - dlo_unit; /* line # */
|
||||
|
||||
if (ttx_ldsc[ln].conn) { /* connected? */
|
||||
if (ttx_ldsc[ln].xmte) { /* tx enabled? */
|
||||
TMLN *lp = &ttx_ldsc[ln]; /* get line */
|
||||
c = sim_tt_outcvt (ttox_buf[ln], TT_GET_MODE (ttox_unit[ln].flags));
|
||||
if (dlx_ldsc[ln].conn) { /* connected? */
|
||||
if (dlx_ldsc[ln].xmte) { /* tx enabled? */
|
||||
TMLN *lp = &dlx_ldsc[ln]; /* get line */
|
||||
c = sim_tt_outcvt (dlo_buf[ln], TT_GET_MODE (dlo_unit[ln].flags));
|
||||
if (c >= 0) tmxr_putc_ln (lp, c); /* output char */
|
||||
tmxr_poll_tx (&ttx_desc); /* poll xmt */
|
||||
tmxr_poll_tx (&dlx_desc); /* poll xmt */
|
||||
}
|
||||
else {
|
||||
tmxr_poll_tx (&ttx_desc); /* poll xmt */
|
||||
sim_activate (uptr, ttox_unit[ln].wait); /* wait */
|
||||
tmxr_poll_tx (&dlx_desc); /* poll xmt */
|
||||
sim_activate (uptr, dlo_unit[ln].wait); /* wait */
|
||||
return SCPE_OK;
|
||||
}
|
||||
}
|
||||
ttox_csr[ln] |= CSR_DONE; /* set done */
|
||||
if (ttox_csr[ln] & CSR_IE) ttox_set_int (ln);
|
||||
dlo_csr[ln] |= CSR_DONE; /* set done */
|
||||
if (dlo_csr[ln] & CSR_IE)
|
||||
dlo_set_int (ln);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Interrupt routines */
|
||||
|
||||
void ttix_clr_int (uint32 ln)
|
||||
void dli_clr_int (int32 ln, uint32 wd)
|
||||
{
|
||||
ttix_ireq &= ~(1 << ln); /* clr mux rcv int */
|
||||
if (ttix_ireq == 0) CLR_INT (TTIX); /* all clr? */
|
||||
else SET_INT (TTIX); /* no, set intr */
|
||||
dli_ireq[wd] &= ~(1 << ln); /* clr rcv/dset int */
|
||||
if ((dli_ireq[DLI_RCI] | dli_ireq[DLI_DSI]) == 0) /* all clr? */
|
||||
CLR_INT (DLI); /* all clr? */
|
||||
else SET_INT (DLI); /* no, set intr */
|
||||
return;
|
||||
}
|
||||
|
||||
void ttix_set_int (int32 ln)
|
||||
void dli_set_int (int32 ln, uint32 wd)
|
||||
{
|
||||
ttix_ireq |= (1 << ln); /* clr mux rcv int */
|
||||
SET_INT (TTIX); /* set master intr */
|
||||
dli_ireq[wd] |= (1 << ln); /* set rcv/dset int */
|
||||
SET_INT (DLI); /* set master intr */
|
||||
return;
|
||||
}
|
||||
|
||||
int32 ttix_iack (void)
|
||||
int32 dli_iack (void)
|
||||
{
|
||||
int32 ln;
|
||||
|
||||
for (ln = 0; ln < TTX_LINES; ln++) { /* find 1st line */
|
||||
if (ttix_ireq & (1 << ln)) {
|
||||
ttix_clr_int (ln); /* clear intr */
|
||||
return (ttix_dib.vec + (ln * 010)); /* return vector */
|
||||
for (ln = 0; ln < DLX_LINES; ln++) { /* find 1st line */
|
||||
if ((dli_ireq[DLI_RCI] | dli_ireq[DLI_DSI]) & (1 << ln)) {
|
||||
dli_clr_int (ln, DLI_RCI); /* clr both req */
|
||||
dli_clr_int (ln, DLI_DSI);
|
||||
return (dli_dib.vec + (ln * 010)); /* return vector */
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ttox_clr_int (int32 ln)
|
||||
void dlo_clr_int (int32 ln)
|
||||
{
|
||||
ttox_ireq &= ~(1 << ln); /* clr mux rcv int */
|
||||
if (ttox_ireq == 0) CLR_INT (TTOX); /* all clr? */
|
||||
else SET_INT (TTOX); /* no, set intr */
|
||||
dlo_ireq &= ~(1 << ln); /* clr xmit int */
|
||||
if (dlo_ireq == 0) CLR_INT (DLO); /* all clr? */
|
||||
else SET_INT (DLO); /* no, set intr */
|
||||
return;
|
||||
}
|
||||
|
||||
void ttox_set_int (int32 ln)
|
||||
void dlo_set_int (int32 ln)
|
||||
{
|
||||
ttox_ireq |= (1 << ln); /* clr mux rcv int */
|
||||
SET_INT (TTOX); /* set master intr */
|
||||
dlo_ireq |= (1 << ln); /* set xmit int */
|
||||
SET_INT (DLO); /* set master intr */
|
||||
return;
|
||||
}
|
||||
|
||||
int32 ttox_iack (void)
|
||||
int32 dlo_iack (void)
|
||||
{
|
||||
int32 ln;
|
||||
|
||||
for (ln = 0; ln < TTX_LINES; ln++) { /* find 1st line */
|
||||
if (ttox_ireq & (1 << ln)) {
|
||||
ttox_clr_int (ln); /* clear intr */
|
||||
return (ttix_dib.vec + (ln * 010) + 4); /* return vector */
|
||||
for (ln = 0; ln < DLX_LINES; ln++) { /* find 1st line */
|
||||
if (dlo_ireq & (1 << ln)) {
|
||||
dlo_clr_int (ln); /* clear intr */
|
||||
return (dli_dib.vec + (ln * 010) + 4); /* return vector */
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -372,40 +453,43 @@ return 0;
|
||||
|
||||
/* Reset */
|
||||
|
||||
t_stat ttx_reset (DEVICE *dptr)
|
||||
t_stat dlx_reset (DEVICE *dptr)
|
||||
{
|
||||
int32 ln;
|
||||
|
||||
ttx_enbdis (dptr->flags & DEV_DIS); /* sync enables */
|
||||
sim_cancel (&ttix_unit); /* assume stop */
|
||||
if (ttix_unit.flags & UNIT_ATT) /* if attached, */
|
||||
sim_activate (&ttix_unit, tmxr_poll); /* activate */
|
||||
for (ln = 0; ln < TTX_LINES; ln++) /* for all lines */
|
||||
ttx_reset_ln (ln);
|
||||
return auto_config (ttix_dev.name, ttx_desc.lines); /* auto config */
|
||||
dlx_enbdis (dptr->flags & DEV_DIS); /* sync enables */
|
||||
sim_cancel (&dli_unit); /* assume stop */
|
||||
if (dli_unit.flags & UNIT_ATT) /* if attached, */
|
||||
sim_activate (&dli_unit, tmxr_poll); /* activate */
|
||||
for (ln = 0; ln < DLX_LINES; ln++) /* for all lines */
|
||||
dlx_reset_ln (ln);
|
||||
return auto_config (dli_dev.name, dlx_desc.lines); /* auto config */
|
||||
}
|
||||
|
||||
/* Reset individual line */
|
||||
|
||||
void ttx_reset_ln (uint32 ln)
|
||||
void dlx_reset_ln (int32 ln)
|
||||
{
|
||||
ttix_buf[ln] = 0; /* clear buf, */
|
||||
ttix_csr[ln] = CSR_DONE;
|
||||
ttox_buf[ln] = 0; /* clear buf */
|
||||
ttox_csr[ln] = CSR_DONE;
|
||||
sim_cancel (&ttox_unit[ln]); /* deactivate */
|
||||
ttix_clr_int (ln);
|
||||
ttox_clr_int (ln);
|
||||
dli_buf[ln] = 0; /* clear buf */
|
||||
if (dlo_unit[ln].flags & DLX_MDM) /* modem */
|
||||
dli_csr[ln] &= DLICSR_DTR; /* dont clr DTR */
|
||||
else dli_csr[ln] = 0;
|
||||
dlo_buf[ln] = 0; /* clear buf */
|
||||
dlo_csr[ln] = CSR_DONE;
|
||||
sim_cancel (&dlo_unit[ln]); /* deactivate */
|
||||
dli_clr_int (ln, DLI_RCI);
|
||||
dli_clr_int (ln, DLI_DSI);
|
||||
dlo_clr_int (ln);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Attach master unit */
|
||||
|
||||
t_stat ttx_attach (UNIT *uptr, char *cptr)
|
||||
t_stat dlx_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
t_stat r;
|
||||
|
||||
r = tmxr_attach (&ttx_desc, uptr, cptr); /* attach */
|
||||
r = tmxr_attach (&dlx_desc, uptr, cptr); /* attach */
|
||||
if (r != SCPE_OK) return r; /* error */
|
||||
sim_activate (uptr, tmxr_poll); /* start poll */
|
||||
return SCPE_OK;
|
||||
@@ -413,25 +497,25 @@ return SCPE_OK;
|
||||
|
||||
/* Detach master unit */
|
||||
|
||||
t_stat ttx_detach (UNIT *uptr)
|
||||
t_stat dlx_detach (UNIT *uptr)
|
||||
{
|
||||
int32 i;
|
||||
t_stat r;
|
||||
|
||||
r = tmxr_detach (&ttx_desc, uptr); /* detach */
|
||||
for (i = 0; i < TTX_LINES; i++) /* all lines, */
|
||||
ttx_ldsc[i].rcve = 0; /* disable rcv */
|
||||
r = tmxr_detach (&dlx_desc, uptr); /* detach */
|
||||
for (i = 0; i < DLX_LINES; i++) /* all lines, */
|
||||
dlx_ldsc[i].rcve = 0; /* disable rcv */
|
||||
sim_cancel (uptr); /* stop poll */
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Show summary processor */
|
||||
|
||||
t_stat ttx_summ (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
t_stat dlx_summ (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
int32 i, t;
|
||||
|
||||
for (i = t = 0; i < TTX_LINES; i++) t = t + (ttx_ldsc[i].conn != 0);
|
||||
for (i = t = 0; i < DLX_LINES; i++) t = t + (dlx_ldsc[i].conn != 0);
|
||||
if (t == 1) fprintf (st, "1 connection");
|
||||
else fprintf (st, "%d connections", t);
|
||||
return SCPE_OK;
|
||||
@@ -439,16 +523,16 @@ return SCPE_OK;
|
||||
|
||||
/* SHOW CONN/STAT processor */
|
||||
|
||||
t_stat ttx_show (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
t_stat dlx_show (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
int32 i, t;
|
||||
|
||||
for (i = t = 0; i < TTX_LINES; i++) t = t + (ttx_ldsc[i].conn != 0);
|
||||
for (i = t = 0; i < DLX_LINES; i++) t = t + (dlx_ldsc[i].conn != 0);
|
||||
if (t) {
|
||||
for (i = 0; i < TTX_LINES; i++) {
|
||||
if (ttx_ldsc[i].conn) {
|
||||
if (val) tmxr_fconns (st, &ttx_ldsc[i], i);
|
||||
else tmxr_fstats (st, &ttx_ldsc[i], i);
|
||||
for (i = 0; i < DLX_LINES; i++) {
|
||||
if (dlx_ldsc[i].conn) {
|
||||
if (val) tmxr_fconns (st, &dlx_ldsc[i], i);
|
||||
else tmxr_fstats (st, &dlx_ldsc[i], i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -458,64 +542,65 @@ return SCPE_OK;
|
||||
|
||||
/* Enable/disable device */
|
||||
|
||||
void ttx_enbdis (int32 dis)
|
||||
void dlx_enbdis (int32 dis)
|
||||
{
|
||||
if (dis) {
|
||||
ttix_dev.flags = ttox_dev.flags | DEV_DIS;
|
||||
ttox_dev.flags = ttox_dev.flags | DEV_DIS;
|
||||
dli_dev.flags = dlo_dev.flags | DEV_DIS;
|
||||
dlo_dev.flags = dlo_dev.flags | DEV_DIS;
|
||||
}
|
||||
else {
|
||||
ttix_dev.flags = ttix_dev.flags & ~DEV_DIS;
|
||||
ttox_dev.flags = ttox_dev.flags & ~DEV_DIS;
|
||||
dli_dev.flags = dli_dev.flags & ~DEV_DIS;
|
||||
dlo_dev.flags = dlo_dev.flags & ~DEV_DIS;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* SHOW VECTOR processor */
|
||||
|
||||
t_stat ttx_show_vec (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
t_stat dlx_show_vec (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
return show_vec (st, uptr, ttx_desc.lines * 2, desc);
|
||||
return show_vec (st, uptr, dlx_desc.lines * 2, desc);
|
||||
}
|
||||
|
||||
/* Change number of lines */
|
||||
|
||||
t_stat ttx_set_lines (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
t_stat dlx_set_lines (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
int32 newln, i, t;
|
||||
t_stat r;
|
||||
|
||||
if (cptr == NULL) return SCPE_ARG;
|
||||
newln = get_uint (cptr, 10, TTX_LINES, &r);
|
||||
if ((r != SCPE_OK) || (newln == ttx_desc.lines)) return r;
|
||||
newln = get_uint (cptr, 10, DLX_LINES, &r);
|
||||
if ((r != SCPE_OK) || (newln == dlx_desc.lines)) return r;
|
||||
if (newln == 0) return SCPE_ARG;
|
||||
if (newln < ttx_desc.lines) {
|
||||
for (i = newln, t = 0; i < ttx_desc.lines; i++) t = t | ttx_ldsc[i].conn;
|
||||
if (newln < dlx_desc.lines) {
|
||||
for (i = newln, t = 0; i < dlx_desc.lines; i++) t = t | dlx_ldsc[i].conn;
|
||||
if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE))
|
||||
return SCPE_OK;
|
||||
for (i = newln; i < ttx_desc.lines; i++) {
|
||||
if (ttx_ldsc[i].conn) {
|
||||
tmxr_linemsg (&ttx_ldsc[i], "\r\nOperator disconnected line\r\n");
|
||||
tmxr_reset_ln (&ttx_ldsc[i]); /* reset line */
|
||||
for (i = newln; i < dlx_desc.lines; i++) {
|
||||
if (dlx_ldsc[i].conn) {
|
||||
tmxr_linemsg (&dlx_ldsc[i], "\r\nOperator disconnected line\r\n");
|
||||
tmxr_reset_ln (&dlx_ldsc[i]); /* reset line */
|
||||
}
|
||||
ttox_unit[i].flags |= UNIT_DIS;
|
||||
ttx_reset_ln (i);
|
||||
dlo_unit[i].flags |= UNIT_DIS;
|
||||
dlx_reset_ln (i);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i = ttx_desc.lines; i < newln; i++) {
|
||||
ttox_unit[i].flags &= ~UNIT_DIS;
|
||||
ttx_reset_ln (i);
|
||||
for (i = dlx_desc.lines; i < newln; i++) {
|
||||
dlo_unit[i].flags &= ~UNIT_DIS;
|
||||
dlx_reset_ln (i);
|
||||
}
|
||||
}
|
||||
ttx_desc.lines = newln;
|
||||
return auto_config (ttix_dev.name, newln); /* auto config */
|
||||
dlx_desc.lines = newln;
|
||||
dli_dib.lnt = newln * 010; /* upd IO page lnt */
|
||||
return auto_config (dli_dev.name, newln); /* auto config */
|
||||
}
|
||||
|
||||
/* Show number of lines */
|
||||
|
||||
t_stat ttx_show_lines (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
t_stat dlx_show_lines (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
fprintf (st, "lines=%d", ttx_desc.lines);
|
||||
fprintf (st, "lines=%d", dlx_desc.lines);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* pdp11_io.c: PDP-11 I/O simulator
|
||||
|
||||
Copyright (c) 1993-2006, Robert M Supnik
|
||||
Copyright (c) 1993-2008, 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,9 @@
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
16-May-08 RMS Added multiple DC11 support
|
||||
Renamed DL11 in autoconfigure
|
||||
02-Feb-08 RMS Fixed DMA memory address limit test (found by John Dundas)
|
||||
06-Jul-06 RMS Added multiple KL11/DL11 support
|
||||
15-Oct-05 RMS Fixed bug in autoconfiguration (missing XU)
|
||||
25-Jul-05 RMS Revised autoconfiguration algorithm and interface
|
||||
@@ -54,7 +57,7 @@ extern int32 autcon_enb;
|
||||
extern int32 uba_last;
|
||||
extern FILE *sim_log;
|
||||
extern DEVICE *sim_devices[], cpu_dev;
|
||||
extern UNIT cpu_unit;
|
||||
extern t_addr cpu_memsize;
|
||||
|
||||
int32 calc_ints (int32 nipl, int32 trq);
|
||||
|
||||
@@ -239,7 +242,7 @@ if (cpu_bme) { /* map enabled? */
|
||||
}
|
||||
else { /* physical */
|
||||
if (ADDR_IS_MEM (lim)) alim = lim; /* end ok? */
|
||||
else if (ADDR_IS_MEM (ba)) alim = MEMSIZE; /* no, strt ok? */
|
||||
else if (ADDR_IS_MEM (ba)) alim = cpu_memsize; /* no, strt ok? */
|
||||
else return bc; /* no, err */
|
||||
for ( ; ba < alim; ba++) { /* by bytes */
|
||||
if (ba & 1) *buf++ = (M[ba >> 1] >> 8) & 0377; /* get byte */
|
||||
@@ -265,7 +268,7 @@ if (cpu_bme) { /* map enabled? */
|
||||
}
|
||||
else { /* physical */
|
||||
if (ADDR_IS_MEM (lim)) alim = lim; /* end ok? */
|
||||
else if (ADDR_IS_MEM (ba)) alim = MEMSIZE; /* no, strt ok? */
|
||||
else if (ADDR_IS_MEM (ba)) alim = cpu_memsize; /* no, strt ok? */
|
||||
else return bc; /* no, err */
|
||||
for ( ; ba < alim; ba = ba + 2) { /* by words */
|
||||
*buf++ = M[ba >> 1];
|
||||
@@ -292,7 +295,7 @@ if (cpu_bme) { /* map enabled? */
|
||||
}
|
||||
else { /* physical */
|
||||
if (ADDR_IS_MEM (lim)) alim = lim; /* end ok? */
|
||||
else if (ADDR_IS_MEM (ba)) alim = MEMSIZE; /* no, strt ok? */
|
||||
else if (ADDR_IS_MEM (ba)) alim = cpu_memsize; /* no, strt ok? */
|
||||
else return bc; /* no, err */
|
||||
for ( ; ba < alim; ba++) { /* by bytes */
|
||||
if (ba & 1) M[ba >> 1] = (M[ba >> 1] & 0377) |
|
||||
@@ -319,7 +322,7 @@ if (cpu_bme) { /* map enabled? */
|
||||
}
|
||||
else { /* physical */
|
||||
if (ADDR_IS_MEM (lim)) alim = lim; /* end ok? */
|
||||
else if (ADDR_IS_MEM (ba)) alim = MEMSIZE; /* no, strt ok? */
|
||||
else if (ADDR_IS_MEM (ba)) alim = cpu_memsize; /* no, strt ok? */
|
||||
else return bc; /* no, err */
|
||||
for ( ; ba < alim; ba = ba + 2) { /* by words */
|
||||
M[ba >> 1] = *buf++;
|
||||
@@ -600,7 +603,8 @@ typedef struct {
|
||||
} AUTO_CON;
|
||||
|
||||
AUTO_CON auto_tab[] = {
|
||||
{ { "TTIX" }, TTX_LINES, 2, 0, 8, { 0 } }, /* KL11/DL11/DLV11 - fx CSRs */
|
||||
{ { "DCI" }, DCX_LINES, 2, 0, 8, { 0 } }, /* DC11 - fx CSRs */
|
||||
{ { "DLI" }, DLX_LINES, 2, 0, 8, { 0 } }, /* KL11/DL11/DLV11 - fx CSRs */
|
||||
{ { NULL }, 1, 2, 8, 8 }, /* DJ11 */
|
||||
{ { NULL }, 1, 2, 16, 8 }, /* DH11 */
|
||||
{ { NULL }, 1, 2, 8, 8 }, /* DQ11 */
|
||||
|
||||
348
PDP11/pdp11_ke.c
Normal file
348
PDP11/pdp11_ke.c
Normal file
@@ -0,0 +1,348 @@
|
||||
/* pdp11_ke.c: PDP-11/20 extended arithmetic element
|
||||
|
||||
Copyright (c) 1993-2008, 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"),
|
||||
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 ke_ACTION OF CONTRke_ACT, 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.
|
||||
|
||||
This code draws on prior work by Tim Shoppa and Brad Parker. My thanks for
|
||||
to them for letting me use their work.
|
||||
|
||||
EAE PDP-11/20 extended arithmetic element
|
||||
*/
|
||||
|
||||
#include "pdp11_defs.h"
|
||||
|
||||
#define GET_SIGN_L(v) (((v) >> 31) & 1)
|
||||
#define GET_SIGN_W(v) (((v) >> 15) & 1)
|
||||
#define GET_SIGN_B(v) (((v) >> 7) & 1)
|
||||
|
||||
/* KE11A I/O address offsets 0177300 - 0177316 */
|
||||
|
||||
#define KE_DIV 000 /* divide */
|
||||
#define KE_AC 002 /* accumulator */
|
||||
#define KE_MQ 004 /* MQ */
|
||||
#define KE_MUL 006 /* multiply */
|
||||
#define KE_SC 010 /* step counter */
|
||||
#define KE_NOR 012 /* normalize */
|
||||
#define KE_LSH 014 /* logical shift */
|
||||
#define KE_ASH 016 /* arithmetic shift */
|
||||
|
||||
/* Status register */
|
||||
|
||||
#define KE_SR_C 0001 /* carry */
|
||||
#define KE_SR_SXT 0002 /* AC<15:0> = MQ<15> */
|
||||
#define KE_SR_Z 0004 /* AC = MQ = 0 */
|
||||
#define KE_SR_MQZ 0010 /* MQ = 0 */
|
||||
#define KE_SR_ACZ 0020 /* AC = 0 */
|
||||
#define KE_SR_ACM1 0040 /* AC = 177777 */
|
||||
#define KE_SR_N 0100 /* last op negative */
|
||||
#define KE_SR_NXV 0200 /* last op ovf XOR N */
|
||||
#define KE_SR_DYN (KE_SR_SXT|KE_SR_Z|KE_SR_MQZ|KE_SR_ACZ|KE_SR_ACM1)
|
||||
|
||||
/* Visible state */
|
||||
|
||||
uint32 ke_AC = 0;
|
||||
uint32 ke_MQ = 0;
|
||||
uint32 ke_SC = 0;
|
||||
uint32 ke_SR = 0;
|
||||
|
||||
DEVICE ke_dev;
|
||||
t_stat ke_rd (int32 *data, int32 PA, int32 access);
|
||||
t_stat ke_wr (int32 data, int32 PA, int32 access);
|
||||
t_stat ke_reset (DEVICE *dptr);
|
||||
uint32 ke_set_SR (void);
|
||||
|
||||
DIB ke_dib = { IOBA_KE, IOLN_KE, &ke_rd, &ke_wr, 0 };
|
||||
|
||||
UNIT ke_unit = {
|
||||
UDATA (NULL, UNIT_DISABLE, 0)
|
||||
};
|
||||
|
||||
REG ke_reg[] = {
|
||||
{ ORDATA (AC, ke_AC, 16) },
|
||||
{ ORDATA (MQ, ke_MQ, 16) },
|
||||
{ ORDATA (SC, ke_SC, 6) },
|
||||
{ ORDATA (SR, ke_SR, 8) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB ke_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL,
|
||||
NULL, &show_addr, NULL },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE ke_dev = {
|
||||
"KE", &ke_unit, ke_reg, ke_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &ke_reset,
|
||||
NULL, NULL, NULL,
|
||||
&ke_dib, DEV_DISABLE | DEV_DIS | DEV_UBUS
|
||||
};
|
||||
|
||||
/* KE read - reads are always 16b, to even addresses */
|
||||
|
||||
t_stat ke_rd (int32 *data, int32 PA, int32 access)
|
||||
{
|
||||
switch (PA & 016) { /* decode PA<3:1> */
|
||||
|
||||
case KE_AC: /* AC */
|
||||
*data = ke_AC;
|
||||
break;
|
||||
|
||||
case KE_MQ: /* MQ */
|
||||
*data = ke_MQ;
|
||||
break;
|
||||
|
||||
case KE_NOR: /* norm (SC) */
|
||||
*data = ke_SC;
|
||||
break;
|
||||
|
||||
case KE_SC: /* SR/SC */
|
||||
*data = (ke_set_SR () << 8) | ke_SC;
|
||||
break;
|
||||
|
||||
default:
|
||||
*data = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* KE write - writes trigger actual arithmetic */
|
||||
|
||||
t_stat ke_wr (int32 data, int32 PA, int32 access)
|
||||
{
|
||||
int32 quo, t32, sout, sign;
|
||||
uint32 absd, absr;
|
||||
|
||||
switch (PA & 017) { /* decode PA<3:0> */
|
||||
|
||||
case KE_DIV: /* divide */
|
||||
if ((access == WRITEB) && GET_SIGN_B (data)) /* byte write? */
|
||||
data |= 0177400; /* sext data to 16b */
|
||||
ke_SR = 0; /* N = V = C = 0 */
|
||||
t32 = (ke_AC << 16) | ke_MQ; /* 32b divd */
|
||||
if (GET_SIGN_W (ke_AC)) /* sext (divd) */
|
||||
t32 = t32 | ~017777777777;
|
||||
if (GET_SIGN_W (data)) /* sext (divr) */
|
||||
data = data | ~077777;
|
||||
absd = abs (t32);
|
||||
absr = abs (data);
|
||||
if ((absd >> 16) >= absr) { /* divide fails? */
|
||||
|
||||
/* Based on the documentation, here's what has happened:
|
||||
|
||||
SC = 16.
|
||||
SR<c> = (AC<15> == data<15>)
|
||||
AC'MQ = (AC'MQ << 1) | SR<c>
|
||||
AC = SR<c>? AC - data: AC + data
|
||||
SR<c> = (AC<15> == data<15>)
|
||||
SC = SC - 1
|
||||
stop
|
||||
*/
|
||||
|
||||
sign = GET_SIGN_W (ke_AC ^ data) ^ 1; /* 1 if signs match */
|
||||
ke_AC = (ke_AC << 1) | (ke_MQ >> 15);
|
||||
ke_AC = (sign? ke_AC - data: ke_AC + data) & DMASK;
|
||||
ke_MQ = ((ke_MQ << 1) | sign) & DMASK;
|
||||
if (GET_SIGN_W (ke_AC ^ data) == 0) /* 0 if signs match */
|
||||
ke_SR |= KE_SR_C;
|
||||
ke_SC = 15; /* SC clocked once */
|
||||
ke_SR |= KE_SR_NXV; /* set overflow */
|
||||
}
|
||||
else {
|
||||
ke_SC = 0;
|
||||
quo = t32 / data;
|
||||
ke_MQ = quo & DMASK; /* MQ has quo */
|
||||
ke_AC = (t32 % data) & DMASK; /* AC has rem */
|
||||
if ((quo > 32767) || (quo < -32768)) /* quo overflow? */
|
||||
ke_SR |= KE_SR_NXV; /* set overflow */
|
||||
}
|
||||
if (GET_SIGN_W (ke_MQ)) /* result negative? */
|
||||
ke_SR ^= (KE_SR_N | KE_SR_NXV); /* N = 1, compl NXV */
|
||||
break;
|
||||
|
||||
case KE_AC: /* AC */
|
||||
if ((access == WRITEB) && GET_SIGN_B (data)) /* byte write? */
|
||||
data |= 0177400; /* sext data to 16b */
|
||||
ke_AC = data;
|
||||
break;
|
||||
|
||||
case KE_AC + 1: /* AC odd byte */
|
||||
ke_AC = (ke_AC & 0377) | (data << 8);
|
||||
break;
|
||||
|
||||
case KE_MQ: /* MQ */
|
||||
if ((access == WRITEB) && GET_SIGN_B (data)) /* byte write? */
|
||||
data |= 0177400; /* sext data to 16b */
|
||||
ke_MQ = data;
|
||||
if (GET_SIGN_W (ke_MQ)) /* sext MQ to AC */
|
||||
ke_AC = 0177777;
|
||||
else ke_AC = 0;
|
||||
break;
|
||||
|
||||
case KE_MQ + 1: /* MQ odd byte */
|
||||
ke_MQ = (ke_MQ & 0377) | (data << 8);
|
||||
if (GET_SIGN_W (ke_MQ)) /* sext MQ to AC */
|
||||
ke_AC = 0177777;
|
||||
else ke_AC = 0;
|
||||
break;
|
||||
|
||||
case KE_MUL: /* multiply */
|
||||
if ((access == WRITEB) && GET_SIGN_B (data)) /* byte write? */
|
||||
data |= 0177400; /* sext data to 16b */
|
||||
ke_SC = 0;
|
||||
if (GET_SIGN_W (data)) /* sext operands */
|
||||
data |= ~077777;
|
||||
t32 = ke_MQ;
|
||||
if (GET_SIGN_W (t32))
|
||||
t32 |= ~077777;
|
||||
t32 = t32 * data;
|
||||
ke_AC = (t32 >> 16) & DMASK;
|
||||
ke_MQ = t32 & DMASK;
|
||||
if (GET_SIGN_W (ke_AC)) /* result negative? */
|
||||
ke_SR = KE_SR_N | KE_SR_NXV; /* N = 1, V = C = 0 */
|
||||
else ke_SR = 0; /* N = 0, V = C = 0 */
|
||||
break;
|
||||
|
||||
case KE_SC: /* SC */
|
||||
if (access == WRITEB) /* ignore byte writes */
|
||||
return SCPE_OK;
|
||||
ke_SR = (data >> 8) & (KE_SR_NXV|KE_SR_N|KE_SR_C);
|
||||
ke_SC = data & 077;
|
||||
break;
|
||||
|
||||
case KE_NOR: /* normalize */
|
||||
for (ke_SC = 0; ke_SC < 31; ke_SC++) { /* max 31 shifts */
|
||||
if (((ke_AC == 0140000) && (ke_MQ == 0)) || /* special case? */
|
||||
(GET_SIGN_W (ke_AC ^ (ke_AC << 1)))) /* AC<15> != AC<14>? */
|
||||
break;
|
||||
ke_AC = ((ke_AC << 1) | (ke_MQ >> 15)) & DMASK;
|
||||
ke_MQ = (ke_MQ << 1) & DMASK;
|
||||
}
|
||||
if (GET_SIGN_W (ke_AC)) /* result negative? */
|
||||
ke_SR = KE_SR_N | KE_SR_NXV; /* N = 1, V = C = 0 */
|
||||
else ke_SR = 0; /* N = 0, V = C = 0 */
|
||||
break;
|
||||
|
||||
case KE_LSH: /* logical shift */
|
||||
ke_SC = 0;
|
||||
ke_SR = 0; /* N = V = C = 0 */
|
||||
data = data & 077; /* 6b shift count */
|
||||
if (data != 0) {
|
||||
t32 = (ke_AC << 16) | ke_MQ; /* 32b operand */
|
||||
if (sign = GET_SIGN_W (ke_AC)) /* sext operand */
|
||||
t32 = t32 | ~017777777777;
|
||||
if (data < 32) { /* [1,31] - left */
|
||||
sout = (t32 >> (32 - data)) | (-sign << data);
|
||||
t32 = ((uint32) t32) << data; /* do shift (zext) */
|
||||
if (sout != (GET_SIGN_L (t32)? -1: 0)) /* bits lost = sext? */
|
||||
ke_SR |= KE_SR_NXV; /* no, V = 1 */
|
||||
if (sout & 1) /* last bit lost = 1? */
|
||||
ke_SR |= KE_SR_C; /* yes, C = 1 */
|
||||
}
|
||||
else { /* [32,63] = -32,-1 */
|
||||
if ((t32 >> (63 - data)) & 1) /* last bit lost = 1? */
|
||||
ke_SR |= KE_SR_C; /* yes, C = 1*/
|
||||
t32 = (data != 32)? ((uint32) t32) >> (64 - data): 0;
|
||||
}
|
||||
ke_AC = (t32 >> 16) & DMASK;
|
||||
ke_MQ = t32 & DMASK;
|
||||
}
|
||||
if (GET_SIGN_W (ke_AC)) /* result negative? */
|
||||
ke_SR ^= (KE_SR_N | KE_SR_NXV); /* N = 1, compl NXV */
|
||||
break;
|
||||
|
||||
/* EAE ASH differs from EIS ASH and cannot use the same overflow test */
|
||||
|
||||
case KE_ASH: /* arithmetic shift */
|
||||
ke_SC = 0;
|
||||
ke_SR = 0; /* N = V = C = 0 */
|
||||
data = data & 077; /* 6b shift count */
|
||||
if (data != 0) {
|
||||
t32 = (ke_AC << 16) | ke_MQ; /* 32b operand */
|
||||
if (sign = GET_SIGN_W (ke_AC)) /* sext operand */
|
||||
t32 = t32 | ~017777777777;
|
||||
if (data < 32) { /* [1,31] - left */
|
||||
sout = (t32 >> (31 - data)) | (-sign << data);
|
||||
t32 = (t32 & 020000000000) | ((t32 << data) & 017777777777);
|
||||
if (sout != (GET_SIGN_L (t32)? -1: 0)) /* bits lost = sext? */
|
||||
ke_SR |= KE_SR_NXV; /* no, V = 1 */
|
||||
if (sout & 1) /* last bit lost = 1? */
|
||||
ke_SR |= KE_SR_C; /* yes, C = 1 */
|
||||
}
|
||||
else { /* [32,63] = -32,-1 */
|
||||
if ((t32 >> (63 - data)) & 1) /* last bit lost = 1? */
|
||||
ke_SR |= KE_SR_C; /* yes, C = 1 */
|
||||
t32 = (data != 32)? /* special case 32 */
|
||||
(((uint32) t32) >> (64 - data)) | (-sign << (data - 32)):
|
||||
-sign;
|
||||
}
|
||||
ke_AC = (t32 >> 16) & DMASK;
|
||||
ke_MQ = t32 & DMASK;
|
||||
}
|
||||
if (GET_SIGN_W (ke_AC)) /* result negative? */
|
||||
ke_SR ^= (KE_SR_N | KE_SR_NXV); /* N = 1, compl NXV */
|
||||
break;
|
||||
|
||||
default: /* all others ignored */
|
||||
return SCPE_OK;
|
||||
} /* end switch PA */
|
||||
|
||||
ke_set_SR ();
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Update status register based on current AC, MQ */
|
||||
|
||||
uint32 ke_set_SR (void)
|
||||
{
|
||||
ke_SR &= ~KE_SR_DYN; /* clr dynamic bits */
|
||||
if (ke_MQ == 0) /* MQ == 0? */
|
||||
ke_SR |= KE_SR_MQZ;
|
||||
if (ke_AC == 0) { /* AC == 0? */
|
||||
ke_SR |= KE_SR_ACZ;
|
||||
if (GET_SIGN_W (ke_MQ) == 0) /* MQ positive? */
|
||||
ke_SR |= KE_SR_SXT;
|
||||
if (ke_MQ == 0) /* MQ zero? */
|
||||
ke_SR |= KE_SR_Z;
|
||||
}
|
||||
if (ke_AC == 0177777) { /* AC == 177777? */
|
||||
ke_SR |= KE_SR_ACM1;
|
||||
if (GET_SIGN_W (ke_MQ) == 1) /* MQ negative? */
|
||||
ke_SR |= KE_SR_SXT;
|
||||
}
|
||||
return ke_SR;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat ke_reset (DEVICE *dptr)
|
||||
{
|
||||
ke_SR = 0;
|
||||
ke_SC = 0;
|
||||
ke_AC = 0;
|
||||
ke_MQ = 0;
|
||||
return SCPE_OK;
|
||||
}
|
||||
477
PDP11/pdp11_kg.c
Normal file
477
PDP11/pdp11_kg.c
Normal file
@@ -0,0 +1,477 @@
|
||||
/* pdp11_kg.c - Communications Arithmetic Option KG11-A
|
||||
|
||||
Copyright (c) 2007-2008, John A. Dundas III
|
||||
|
||||
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 the author shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from the author.
|
||||
|
||||
kg KG11-A Communications Arithmetic Option (M7251)
|
||||
|
||||
08-Jan-08 JAD First public release integrated with SIMH V3.7-3.
|
||||
09-Dec-07 JAD SIMH-style debugging.
|
||||
Finished validating against real hardware.
|
||||
Support for up to 8 units, the maximum.
|
||||
Keep all module data in the UNIT structure.
|
||||
Clean up bit and mask definitions.
|
||||
01-Dec-07 JAD Now work on the corner cases that the
|
||||
diagnostic does not check.
|
||||
CLR does not clear the QUO bit.
|
||||
Correct SR write logic.
|
||||
29-Nov-07 JAD Original implementation and testing based on
|
||||
an idea from 07-Jul-03. Passes the ZKGAB0
|
||||
diagnostic.
|
||||
|
||||
Information necessary to create this simulation was gathered from
|
||||
a number of sources including:
|
||||
|
||||
KG11-A Exclusive-OR and CRC block check manual, DEC-11-HKGAA-B-D
|
||||
<http://www.computer.museum.uq.edu.au/pdf/DEC-11-HKGAA-B-D%20KG11-A%20Exclusive-OR%20and%20CRC%20Block%20Check%20Manual.pdf>
|
||||
Maintenance print set
|
||||
<http://bitsavers.org/pdf/dec/unibus/KG11A_EngrDrws.pdf>
|
||||
A Painless Guide to CRC Error Detection Algorithms, Ross N. Williams
|
||||
<http://www.ross.net/crc/download/crc_v3.txt">
|
||||
|
||||
The original PDP-11 instruction set, as implemented in the /20,
|
||||
/15, /10, and /5, did not include XOR. [One of the differences
|
||||
tables incorrectly indicates the /04 does not implement this
|
||||
instruction.] This device implements XOR, XORB, and a variety of
|
||||
CRCs.
|
||||
|
||||
The maintenance prints indicate that the device was probably available
|
||||
starting in late 1971. May need to check further. The first edition
|
||||
of the manual was May 1972.
|
||||
|
||||
The device was still sold at least as late as mid-1982 according
|
||||
to the PDP-11 Systems and Options Summary. RSTS/E included support
|
||||
for up to 8 units in support of the 2780 emulation or for use with
|
||||
DP11, DU11, or DUP11. The device appears to have been retired by
|
||||
1983-03, and possibly earlier.
|
||||
|
||||
I/O Page Registers
|
||||
|
||||
SR 7707x0 (read-write) status
|
||||
BCC 7707x2 (read-only) BCC (block check character)
|
||||
DR 7707x4 (write-only) data
|
||||
|
||||
Vector: none
|
||||
|
||||
Priority: none
|
||||
|
||||
The KG11-A is a programmed-I/O, non-interrupting device. Therefore
|
||||
no vector or bus request level are necessary. It is a Unibus device
|
||||
but since it does not address memory itself (it only presents
|
||||
registers in the I/O page) it is compatible with extended Unibus
|
||||
machines (22-bit) as well as traditional Unibus.
|
||||
|
||||
Implements 5 error detection codes:
|
||||
LRC-8
|
||||
LRC-16
|
||||
CRC-12
|
||||
CRC-16
|
||||
CRC-CCITT
|
||||
*/
|
||||
|
||||
#if !defined (VM_PDP11)
|
||||
#error "KG11 is not supported!"
|
||||
#endif
|
||||
#include "pdp11_defs.h"
|
||||
|
||||
extern FILE *sim_deb;
|
||||
extern REG cpu_reg[];
|
||||
extern int32 R[];
|
||||
|
||||
#ifndef KG_UNITS
|
||||
#define KG_UNITS (8)
|
||||
#endif
|
||||
|
||||
/* Control and Status Register */
|
||||
|
||||
#define KGSR_V_QUO (8) /* RO */
|
||||
#define KGSR_V_DONE (7) /* RO */
|
||||
#define KGSR_V_SEN (6) /* R/W shift enable */
|
||||
#define KGSR_V_STEP (5) /* W */
|
||||
#define KGSR_V_CLR (4) /* W */
|
||||
#define KGSR_V_DDB (3) /* R/W double data byte */
|
||||
#define KGSR_V_CRCIC (2) /* R/W */
|
||||
#define KGSR_V_LRC (1) /* R/W */
|
||||
#define KGSR_V_16 (0) /* R/W */
|
||||
|
||||
#define KGSR_M_QUO (1u << KGSR_V_QUO)
|
||||
#define KGSR_M_DONE (1u << KGSR_V_DONE)
|
||||
#define KGSR_M_SEN (1u << KGSR_V_SEN)
|
||||
#define KGSR_M_STEP (1u << KGSR_V_STEP)
|
||||
#define KGSR_M_CLR (1u << KGSR_V_CLR)
|
||||
#define KGSR_M_DDB (1u << KGSR_V_DDB)
|
||||
#define KGSR_M_CRCIC (1u << KGSR_V_CRCIC)
|
||||
#define KGSR_M_LRC (1u << KGSR_V_LRC)
|
||||
#define KGSR_M_16 (1u << KGSR_V_16)
|
||||
|
||||
#define KG_SR_RDMASK (KGSR_M_QUO | KGSR_M_DONE | KGSR_M_SEN | KGSR_M_DDB | \
|
||||
KGSR_M_CRCIC | KGSR_M_LRC | KGSR_M_16)
|
||||
#define KG_SR_WRMASK (KGSR_M_SEN | KGSR_M_DDB | KGSR_M_CRCIC | \
|
||||
KGSR_M_LRC | KGSR_M_16)
|
||||
|
||||
#define KG_SR_POLYMASK (KGSR_M_CRCIC|KGSR_M_LRC|KGSR_M_16)
|
||||
|
||||
/* Unit structure redefinitions */
|
||||
#define SR u3
|
||||
#define BCC u4
|
||||
#define DR u5
|
||||
#define PULSCNT u6
|
||||
|
||||
#define POLY_LRC8 (0x0008)
|
||||
#define POLY_LRC16 (0x0080)
|
||||
#define POLY_CRC12 (0x0f01)
|
||||
#define POLY_CRC16 (0xa001)
|
||||
#define POLY_CCITT (0x8408)
|
||||
|
||||
static const struct {
|
||||
uint16 poly;
|
||||
uint16 pulses;
|
||||
const char * const name;
|
||||
} config[] = {
|
||||
/* DDB=0 */
|
||||
{ POLY_CRC12, 6, "CRC-12" },
|
||||
{ POLY_CRC16, 8, "CRC-16" },
|
||||
{ POLY_LRC8, 8, "LRC-8" },
|
||||
{ POLY_LRC16, 8, "LRC-16" },
|
||||
{ 0, 0, "undefined" },
|
||||
{ POLY_CCITT, 8, "CRC-CCITT" },
|
||||
{ 0, 0, "undefined" },
|
||||
{ 0, 0, "undefined" },
|
||||
/* DDB=1 */
|
||||
{ POLY_CRC12, 12, "CRC-12" },
|
||||
{ POLY_CRC16, 16, "CRC-16" },
|
||||
{ POLY_LRC8, 16, "LRC-8" },
|
||||
{ POLY_LRC16, 16, "LRC-16" },
|
||||
{ 0, 0, "undefined" },
|
||||
{ POLY_CCITT, 16, "CRC-CCITT" },
|
||||
{ 0, 0, "undefined" },
|
||||
{ 0, 0, "undefined" }
|
||||
};
|
||||
|
||||
/* Forward declarations */
|
||||
|
||||
static t_stat kg_rd (int32 *, int32, int32);
|
||||
static t_stat kg_wr (int32, int32, int32);
|
||||
static t_stat kg_reset (DEVICE *);
|
||||
static void do_poly (int, t_bool);
|
||||
static t_stat set_units (UNIT *, int32, char *, void *);
|
||||
|
||||
/* 16-bit rotate right */
|
||||
|
||||
#define ROR(n,v) (((v >> n) & DMASK) | (v << (16 - n)) & DMASK)
|
||||
|
||||
/* 8-bit rotate right */
|
||||
|
||||
#define RORB(n,v) (((v & 0377) >> n) | ((v << (8 - n)) & 0377))
|
||||
|
||||
/* KG data structures
|
||||
|
||||
kg_dib KG PDP-11 device information block
|
||||
kg_unit KG unit descriptor
|
||||
kg_reg KG register list
|
||||
kg_mod KG modifiers table
|
||||
kg_debug KG debug names table
|
||||
kg_dev KG device descriptor
|
||||
*/
|
||||
|
||||
static DIB kg_dib = {
|
||||
IOBA_KG,
|
||||
(IOLN_KG + 2) * KG_UNITS,
|
||||
&kg_rd,
|
||||
&kg_wr,
|
||||
0, 0, 0, { NULL }
|
||||
};
|
||||
|
||||
static UNIT kg_unit[] = {
|
||||
{ UDATA (NULL, 0, 0) },
|
||||
{ UDATA (NULL, UNIT_DISABLE + UNIT_DIS, 0) },
|
||||
{ UDATA (NULL, UNIT_DISABLE + UNIT_DIS, 0) },
|
||||
{ UDATA (NULL, UNIT_DISABLE + UNIT_DIS, 0) },
|
||||
{ UDATA (NULL, UNIT_DISABLE + UNIT_DIS, 0) },
|
||||
{ UDATA (NULL, UNIT_DISABLE + UNIT_DIS, 0) },
|
||||
{ UDATA (NULL, UNIT_DISABLE + UNIT_DIS, 0) },
|
||||
{ UDATA (NULL, UNIT_DISABLE + UNIT_DIS, 0) },
|
||||
};
|
||||
|
||||
static const REG kg_reg[] = {
|
||||
{ ORDATA (SR0, kg_unit[0].SR, 16) },
|
||||
{ ORDATA (SR1, kg_unit[1].SR, 16) },
|
||||
{ ORDATA (SR2, kg_unit[2].SR, 16) },
|
||||
{ ORDATA (SR3, kg_unit[3].SR, 16) },
|
||||
{ ORDATA (SR4, kg_unit[4].SR, 16) },
|
||||
{ ORDATA (SR5, kg_unit[5].SR, 16) },
|
||||
{ ORDATA (SR6, kg_unit[6].SR, 16) },
|
||||
{ ORDATA (SR7, kg_unit[7].SR, 16) },
|
||||
{ ORDATA (BCC0, kg_unit[0].BCC, 16) },
|
||||
{ ORDATA (BCC1, kg_unit[1].BCC, 16) },
|
||||
{ ORDATA (BCC2, kg_unit[2].BCC, 16) },
|
||||
{ ORDATA (BCC3, kg_unit[3].BCC, 16) },
|
||||
{ ORDATA (BCC4, kg_unit[4].BCC, 16) },
|
||||
{ ORDATA (BCC5, kg_unit[5].BCC, 16) },
|
||||
{ ORDATA (BCC6, kg_unit[6].BCC, 16) },
|
||||
{ ORDATA (BCC7, kg_unit[7].BCC, 16) },
|
||||
{ ORDATA (DR0, kg_unit[0].DR, 16) },
|
||||
{ ORDATA (DR1, kg_unit[1].DR, 16) },
|
||||
{ ORDATA (DR2, kg_unit[2].DR, 16) },
|
||||
{ ORDATA (DR3, kg_unit[3].DR, 16) },
|
||||
{ ORDATA (DR4, kg_unit[4].DR, 16) },
|
||||
{ ORDATA (DR5, kg_unit[5].DR, 16) },
|
||||
{ ORDATA (DR6, kg_unit[6].DR, 16) },
|
||||
{ ORDATA (DR7, kg_unit[7].DR, 16) },
|
||||
{ ORDATA (PULSCNT0, kg_unit[0].PULSCNT, 16) },
|
||||
{ ORDATA (PULSCNT1, kg_unit[1].PULSCNT, 16) },
|
||||
{ ORDATA (PULSCNT2, kg_unit[2].PULSCNT, 16) },
|
||||
{ ORDATA (PULSCNT3, kg_unit[3].PULSCNT, 16) },
|
||||
{ ORDATA (PULSCNT4, kg_unit[4].PULSCNT, 16) },
|
||||
{ ORDATA (PULSCNT5, kg_unit[5].PULSCNT, 16) },
|
||||
{ ORDATA (PULSCNT6, kg_unit[6].PULSCNT, 16) },
|
||||
{ ORDATA (PULSCNT7, kg_unit[7].PULSCNT, 16) },
|
||||
{ ORDATA (DEVADDR, kg_dib.ba, 32), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static const MTAB kg_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL, NULL, &show_addr, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, NULL, "UNITS=0..8", &set_units, NULL, NULL },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
#define DBG_REG (01)
|
||||
#define DBG_POLY (02)
|
||||
#define DBG_CYCLE (04)
|
||||
|
||||
static const DEBTAB kg_debug[] = {
|
||||
{"REG", DBG_REG},
|
||||
{"POLY", DBG_POLY},
|
||||
{"CYCLE", DBG_CYCLE},
|
||||
{0},
|
||||
};
|
||||
|
||||
DEVICE kg_dev = {
|
||||
"KG", (UNIT *) &kg_unit, (REG *) kg_reg, (MTAB *) kg_mod,
|
||||
KG_UNITS, 8, 16, 2, 8, 16,
|
||||
NULL, /* examine */
|
||||
NULL, /* deposit */
|
||||
&kg_reset, /* reset */
|
||||
NULL, /* boot */
|
||||
NULL, /* attach */
|
||||
NULL, /* detach */
|
||||
&kg_dib,
|
||||
DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_DEBUG,
|
||||
0, /* debug control */
|
||||
(DEBTAB *) &kg_debug, /* debug flags */
|
||||
NULL, /* memory size chage */
|
||||
NULL /* logical name */
|
||||
};
|
||||
/* KG I/O address routines */
|
||||
|
||||
static t_stat kg_rd (int32 *data, int32 PA, int32 access)
|
||||
{
|
||||
int unit = (PA >> 3) & 07;
|
||||
|
||||
if ((unit >= KG_UNITS) || (kg_unit[unit].flags & UNIT_DIS))
|
||||
return (SCPE_NXM);
|
||||
switch ((PA >> 1) & 03) {
|
||||
|
||||
case 00: /* SR */
|
||||
if (DEBUG_PRI(kg_dev, DBG_REG))
|
||||
fprintf (sim_deb, ">>KG%d: rd SR %06o, PC %06o\n",
|
||||
unit, kg_unit[unit].SR, PC);
|
||||
*data = kg_unit[unit].SR & KG_SR_RDMASK;
|
||||
break;
|
||||
|
||||
case 01: /* BCC */
|
||||
if (DEBUG_PRI(kg_dev, DBG_REG))
|
||||
fprintf (sim_deb, ">>KG%d rd BCC %06o, PC %06o\n",
|
||||
unit, kg_unit[unit].BCC, PC);
|
||||
*data = kg_unit[unit].BCC & DMASK;
|
||||
break;
|
||||
|
||||
case 02: /* DR */
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (SCPE_OK);
|
||||
}
|
||||
|
||||
static t_stat kg_wr (int32 data, int32 PA, int32 access)
|
||||
{
|
||||
int setup;
|
||||
int unit = (PA >> 3) & 07;
|
||||
|
||||
if ((unit >= KG_UNITS) || (kg_unit[unit].flags & UNIT_DIS))
|
||||
return (SCPE_NXM);
|
||||
switch ((PA >> 1) & 03) {
|
||||
|
||||
case 00: /* SR */
|
||||
if (access == WRITEB)
|
||||
data = (PA & 1) ?
|
||||
(kg_unit[unit].SR & 0377) | (data << 8) :
|
||||
(kg_unit[unit].SR & ~0377) | data;
|
||||
if (DEBUG_PRI(kg_dev, DBG_REG))
|
||||
fprintf (sim_deb, ">>KG%d: wr SR %06o, PC %06o\n",
|
||||
unit, data, PC);
|
||||
if (data & KGSR_M_CLR) {
|
||||
kg_unit[unit].PULSCNT = 0; /* not sure about this */
|
||||
kg_unit[unit].BCC = 0;
|
||||
kg_unit[unit].SR |= KGSR_M_DONE;
|
||||
}
|
||||
setup = (kg_unit[unit].SR & 017) ^ (data & 017);
|
||||
kg_unit[unit].SR = (kg_unit[unit].SR & ~KG_SR_WRMASK) |
|
||||
(data & KG_SR_WRMASK);
|
||||
/* if low 4b changed, reset C1 & C2 */
|
||||
if (setup) {
|
||||
kg_unit[unit].PULSCNT = 0;
|
||||
if (DEBUG_PRI(kg_dev, DBG_POLY))
|
||||
fprintf (sim_deb, ">>KG%d poly %s %d\n",
|
||||
unit, config[data & 017].name, config[data & 017].pulses);
|
||||
}
|
||||
if (data & KGSR_M_SEN)
|
||||
break;
|
||||
if (data & KGSR_M_STEP) {
|
||||
do_poly (unit, TRUE);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 01: /* BCC */
|
||||
break; /* ignored */
|
||||
|
||||
case 02: /* DR */
|
||||
if (access == WRITEB)
|
||||
data = (PA & 1) ?
|
||||
(kg_unit[unit].DR & 0377) | (data << 8) :
|
||||
(kg_unit[unit].DR & ~0377) | data;
|
||||
kg_unit[unit].DR = data & DMASK;
|
||||
if (DEBUG_PRI(kg_dev, DBG_REG))
|
||||
fprintf (sim_deb, ">>KG%d: wr DR %06o, data %06o, PC %06o\n",
|
||||
unit, kg_unit[unit].DR, data, PC);
|
||||
kg_unit[unit].SR &= ~KGSR_M_DONE;
|
||||
|
||||
/* In a typical device, this is normally where we would use sim_activate()
|
||||
to initiate an I/O to be completed later. The KG is a little
|
||||
different. When it was first introduced, it's computation operation
|
||||
completed before another instruction could execute (on early PDP-11s),
|
||||
and software often took "advantage" of this fact by not bothering
|
||||
to check the status of the DONE bit. In reality, the execution
|
||||
time of the polynomial is dependent upon the width of the poly; if
|
||||
8 bits 1us, if 16 bits, 2us. Since known existing software will
|
||||
break if we actually defer the computation, it is performed immediately
|
||||
instead. However this could easily be made into a run-time option,
|
||||
if there were software to validate correct operation. */
|
||||
|
||||
if (kg_unit[unit].SR & KGSR_M_SEN)
|
||||
do_poly (unit, FALSE);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (SCPE_OK);
|
||||
}
|
||||
|
||||
/* KG reset */
|
||||
|
||||
static t_stat kg_reset (DEVICE *dptr)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (DEBUG_PRI(kg_dev, DBG_REG))
|
||||
fprintf (sim_deb, ">>KG: reset PC %06o\n", PC);
|
||||
for (i = 0; i < KG_UNITS; i++) {
|
||||
kg_unit[i].SR = KGSR_M_DONE;
|
||||
kg_unit[i].BCC = 0;
|
||||
kg_unit[i].PULSCNT = 0;
|
||||
}
|
||||
return (SCPE_OK);
|
||||
}
|
||||
|
||||
static void cycleOneBit (int unit)
|
||||
{
|
||||
int quo;
|
||||
|
||||
if (DEBUG_PRI(kg_dev, DBG_CYCLE))
|
||||
fprintf (sim_deb, ">>KG%d: cycle s BCC %06o DR %06o\n",
|
||||
unit, kg_unit[unit].BCC, kg_unit[unit].DR);
|
||||
if (kg_unit[unit].SR & KGSR_M_DONE)
|
||||
return;
|
||||
if ((kg_unit[unit].SR & KG_SR_POLYMASK) == 0)
|
||||
kg_unit[unit].BCC = (kg_unit[unit].BCC & 077) |
|
||||
((kg_unit[unit].BCC >> 2) & 07700);
|
||||
kg_unit[unit].SR &= ~KGSR_M_QUO;
|
||||
quo = (kg_unit[unit].BCC & 01) ^ (kg_unit[unit].DR & 01);
|
||||
kg_unit[unit].BCC = (kg_unit[unit].BCC & ~01) | quo;
|
||||
if (kg_unit[unit].SR & KGSR_M_LRC)
|
||||
kg_unit[unit].BCC = (kg_unit[unit].SR & KGSR_M_16) ?
|
||||
ROR(1, kg_unit[unit].BCC) :
|
||||
RORB(1, kg_unit[unit].BCC);
|
||||
else
|
||||
kg_unit[unit].BCC = (kg_unit[unit].BCC & 01) ?
|
||||
(kg_unit[unit].BCC >> 1) ^ config[kg_unit[unit].SR & 07].poly :
|
||||
kg_unit[unit].BCC >> 1;
|
||||
kg_unit[unit].DR >>= 1;
|
||||
kg_unit[unit].SR |= quo << KGSR_V_QUO;
|
||||
if ((kg_unit[unit].SR & KG_SR_POLYMASK) == 0)
|
||||
kg_unit[unit].BCC = (kg_unit[unit].BCC & 077) |
|
||||
((kg_unit[unit].BCC & 07700) << 2);
|
||||
kg_unit[unit].PULSCNT++;
|
||||
if (kg_unit[unit].PULSCNT >= config[kg_unit[unit].SR & 017].pulses)
|
||||
kg_unit[unit].SR |= KGSR_M_DONE;
|
||||
if (DEBUG_PRI(kg_dev, DBG_CYCLE))
|
||||
fprintf (sim_deb, ">>KG%d: cycle e BCC %06o DR %06o\n",
|
||||
unit, kg_unit[unit].BCC, kg_unit[unit].DR);
|
||||
}
|
||||
|
||||
static void do_poly (int unit, t_bool step)
|
||||
{
|
||||
if (kg_unit[unit].SR & KGSR_M_DONE)
|
||||
return;
|
||||
if (step)
|
||||
cycleOneBit (unit);
|
||||
else {
|
||||
while (!(kg_unit[unit].SR & KGSR_M_DONE))
|
||||
cycleOneBit (unit);
|
||||
}
|
||||
}
|
||||
|
||||
static t_stat set_units (UNIT *u, int32 val, char *s, void *desc)
|
||||
{
|
||||
int32 i, units;
|
||||
t_stat stat;
|
||||
|
||||
if (s == NULL)
|
||||
return (SCPE_ARG);
|
||||
units = get_uint (s, 10, KG_UNITS, &stat);
|
||||
if (stat != SCPE_OK)
|
||||
return (stat);
|
||||
for (i = 0; i < KG_UNITS; i++) {
|
||||
if (i < units)
|
||||
kg_unit[i].flags &= ~UNIT_DIS;
|
||||
else
|
||||
kg_unit[i].flags |= UNIT_DIS;
|
||||
}
|
||||
kg_dev.numunits = units;
|
||||
return (SCPE_OK);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/* pdp11_pclk.c: KW11P programmable clock simulator
|
||||
|
||||
Copyright (c) 1993-2007, Robert M Supnik
|
||||
Copyright (c) 1993-2008, Robert M Supnik
|
||||
Written by John Dundas, used with his gracious permission
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
pclk KW11P line frequency clock
|
||||
|
||||
20-May-08 RMS Standardized clock delay at 1mips
|
||||
18-Jun-07 RMS Added UNIT_IDLE flag
|
||||
07-Jul-05 RMS Removed extraneous externs
|
||||
|
||||
@@ -133,7 +134,7 @@ uint32 pclk_csr = 0; /* control/status */
|
||||
uint32 pclk_csb = 0; /* count set buffer */
|
||||
uint32 pclk_ctr = 0; /* counter */
|
||||
static uint32 rate[4] = { 100000, 10000, 60, 10 }; /* ticks per second */
|
||||
static uint32 xtim[4] = { 10, 100, 16000, 100000 }; /* nominal time delay */
|
||||
static uint32 xtim[4] = { 10, 100, 16667, 100000 }; /* nominal time delay */
|
||||
|
||||
DEVICE pclk_dev;
|
||||
t_stat pclk_rd (int32 *data, int32 PA, int32 access);
|
||||
|
||||
583
PDP11/pdp11_rc.c
Normal file
583
PDP11/pdp11_rc.c
Normal file
@@ -0,0 +1,583 @@
|
||||
/* pdp11_rc.c: RC11/RS64 fixed head disk simulator
|
||||
|
||||
Copyright (c) 2007-2008, John A. Dundas III
|
||||
|
||||
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 the author shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from the author.
|
||||
|
||||
rc RC11/RS64 fixed head disk
|
||||
|
||||
28-Dec-07 JAD Correct extraction of unit number from da in rc_svc.
|
||||
Clear _all_ error bits when a new operation starts.
|
||||
Passes all diagnostics in all configurations.
|
||||
25-Dec-07 JAD Compute the CRC-16 of the last sector read via
|
||||
a READ or WCHK.
|
||||
20-Dec-07 JAD Correctly simulate rotation over the selected
|
||||
track for RCLA. Also update the register
|
||||
correctly during I/O operations.
|
||||
Insure function activation time is non-zero.
|
||||
Handle unit number wrap correctly.
|
||||
19-Dec-07 JAD Iterate over a full sector regardless of the
|
||||
actual word count so that RCDA ends correctly.
|
||||
Honor the read-only vs. read-write status of the
|
||||
attached file.
|
||||
16-Dec-07 JAD The RCDA must be checked for validity when it is
|
||||
written to, not just when GO is received.
|
||||
15-Dec-07 JAD Better handling of disk address errors and the RCLA
|
||||
register.
|
||||
Add more registers to the visible device state.
|
||||
07-Jan-07 JAD Initial creation and testing. Adapted from pdp11_rf.c.
|
||||
|
||||
The RS64 is a head-per-track disk. To minimize overhead, the entire RC11
|
||||
is buffered in memory. Up to 4 RS64 "platters" may be controlled by one
|
||||
RC11 for a total of 262,144 words (65536kW/platter). [Later in time the
|
||||
RK611 was assigned the same CSR address.]
|
||||
|
||||
Diagnostic routines:
|
||||
ZRCAB0.BIC - passes w/1-4 platters
|
||||
ZRCBB0.BIC - passes w/1-4 platters
|
||||
ZRCCB0.BIC - passes w/1-4 platters
|
||||
Note that the diagnostics require R/W disks (i.e., will destroy any
|
||||
existing data).
|
||||
|
||||
For regression, must pass all three diagnostics configured for 1-4
|
||||
platters for a total of 12 tests.
|
||||
|
||||
Information necessary to create this simulation was gathered from the
|
||||
PDP11 Peripherals Handbook, 1973-74 edition.
|
||||
|
||||
One timing parameter is provided:
|
||||
|
||||
rc_time Minimum I/O operation time, must be non-zero
|
||||
*/
|
||||
|
||||
#if !defined (VM_PDP11)
|
||||
#error "RC11 is not supported!"
|
||||
#endif
|
||||
#include "pdp11_defs.h"
|
||||
#include <math.h>
|
||||
|
||||
#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */
|
||||
#define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */
|
||||
#define UNIT_M_PLAT 03
|
||||
#define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1)
|
||||
#define UNIT_AUTO (1 << UNIT_V_AUTO)
|
||||
#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT)
|
||||
|
||||
/* Constants */
|
||||
|
||||
#define RC_NUMWD (32*64) /* words/track */
|
||||
#define RC_NUMTR 32 /* tracks/disk */
|
||||
#define RC_DKSIZE (RC_NUMTR * RC_NUMWD) /* words/disk */
|
||||
#define RC_NUMDK 4 /* disks/controller */
|
||||
#define RC_WMASK (RC_NUMWD - 1) /* word mask */
|
||||
|
||||
/* Parameters in the unit descriptor */
|
||||
|
||||
#define FUNC u4 /* function */
|
||||
|
||||
/* Control and status register (RCCS) */
|
||||
|
||||
#define RCCS_ERR (CSR_ERR) /* error */
|
||||
#define RCCS_DATA 0040000 /* data error */
|
||||
#define RCCS_ADDR 0020000 /* address error */
|
||||
#define RCCS_WLK 0010000 /* write lock */
|
||||
#define RCCS_NED 0004000 /* nx disk */
|
||||
#define RCCS_WCHK 0002000 /* write check */
|
||||
#define RCCS_INH 0001000 /* inhibit CA incr */
|
||||
#define RCCS_ABO 0000400 /* abort */
|
||||
#define RCCS_DONE (CSR_DONE)
|
||||
#define RCCS_IE (CSR_IE)
|
||||
#define RCCS_M_MEX 0000003 /* memory extension */
|
||||
#define RCCS_V_MEX 4
|
||||
#define RCCS_MEX (RCCS_M_MEX << RCCS_V_MEX)
|
||||
#define RCCS_MAINT 0000010 /* maint */
|
||||
#define RCCS_M_FUNC 0000003 /* function */
|
||||
#define RFNC_LAH 0
|
||||
#define RFNC_WRITE 1
|
||||
#define RFNC_READ 2
|
||||
#define RFNC_WCHK 3
|
||||
#define RCCS_V_FUNC 1
|
||||
#define RCCS_FUNC (RCCS_M_FUNC << RCCS_V_FUNC)
|
||||
#define RCCS_GO 0000001
|
||||
|
||||
#define RCCS_ALLERR (RCCS_DATA|RCCS_ADDR|RCCS_WLK|RCCS_NED|RCCS_WCHK)
|
||||
#define RCCS_W (RCCS_INH | RCCS_ABO |RCCS_IE | RCCS_MEX | RCCS_MAINT | \
|
||||
RCCS_FUNC | RCCS_GO)
|
||||
|
||||
/* Disk error status register (RCER) */
|
||||
|
||||
#define RCER_DLT 0100000 /* data late */
|
||||
#define RCER_CHK 0040000 /* block check */
|
||||
#define RCER_SYNC 0020000 /* data sync */
|
||||
#define RCER_NXM 0010000 /* nonexistant memory */
|
||||
#define RCER_TRK 0001000 /* track error */
|
||||
#define RCER_APAR 0000200 /* address parity */
|
||||
#define RCER_SADDR 0000100 /* sync address */
|
||||
#define RCER_OVFL 0000040 /* disk overflow */
|
||||
#define RCER_MIS 0000020 /* missed transfer */
|
||||
|
||||
/* Lood Ahead Register (RCLA) */
|
||||
|
||||
#define RCLA_BADD 0100000 /* bad address */
|
||||
|
||||
/* extract device operation code */
|
||||
#define GET_FUNC(x) (((x) >> RCCS_V_FUNC) & RCCS_M_FUNC)
|
||||
/* extract memory extension address (bits 17,18) */
|
||||
#define GET_MEX(x) (((x) & RCCS_MEX) << (16 - RCCS_V_MEX))
|
||||
#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \
|
||||
((double) RC_NUMWD)))
|
||||
|
||||
extern int32 int_req[IPL_HLVL];
|
||||
extern FILE *sim_deb;
|
||||
extern int32 R[];
|
||||
|
||||
static uint32 rc_la = 0; /* look-ahead */
|
||||
static uint32 rc_da = 0; /* disk address */
|
||||
static uint32 rc_er = 0; /* error status */
|
||||
static uint32 rc_cs = 0; /* command and status */
|
||||
static uint32 rc_wc = 0; /* word count */
|
||||
static uint32 rc_ca = 0; /* current address */
|
||||
static uint32 rc_maint = 0; /* maintenance */
|
||||
static uint32 rc_db = 0; /* data buffer */
|
||||
static uint32 rc_wlk = 0; /* write lock */
|
||||
static uint32 rc_time = 16; /* inter-word time: 16us */
|
||||
static uint32 rc_stopioe = 1; /* stop on error */
|
||||
|
||||
/* forward references */
|
||||
|
||||
DEVICE rc_dev;
|
||||
static t_stat rc_rd (int32 *, int32, int32);
|
||||
static t_stat rc_wr (int32, int32, int32);
|
||||
static t_stat rc_svc (UNIT *);
|
||||
static t_stat rc_reset (DEVICE *);
|
||||
static t_stat rc_attach (UNIT *, char *);
|
||||
static t_stat rc_set_size (UNIT *, int32, char *, void *);
|
||||
static uint32 update_rccs (uint32, uint32);
|
||||
|
||||
/* RC11 data structures
|
||||
|
||||
rc_dev RC device descriptor
|
||||
rc_unit RC unit descriptor
|
||||
rc_reg RC register list
|
||||
*/
|
||||
|
||||
static DIB rc_dib = {
|
||||
IOBA_RC,
|
||||
IOLN_RC,
|
||||
&rc_rd,
|
||||
&rc_wr,
|
||||
1, IVCL (RC), VEC_RC, { NULL }
|
||||
};
|
||||
|
||||
static UNIT rc_unit = {
|
||||
UDATA (&rc_svc, UNIT_FIX + UNIT_ATTABLE + UNIT_BUFABLE +
|
||||
UNIT_MUSTBUF + UNIT_ROABLE + UNIT_BINK, RC_DKSIZE)
|
||||
};
|
||||
|
||||
static const REG rc_reg[] = {
|
||||
{ ORDATA (RCLA, rc_la, 16) },
|
||||
{ ORDATA (RCDA, rc_da, 16) },
|
||||
{ ORDATA (RCER, rc_er, 16) },
|
||||
{ ORDATA (RCCS, rc_cs, 16) },
|
||||
{ ORDATA (RCWC, rc_wc, 16) },
|
||||
{ ORDATA (RCCA, rc_ca, 16) },
|
||||
{ ORDATA (RCMN, rc_maint, 16) },
|
||||
{ ORDATA (RCDB, rc_db, 16) },
|
||||
{ ORDATA (RCWLK, rc_wlk, 32) },
|
||||
{ FLDATA (INT, IREQ (RC), INT_V_RC) },
|
||||
{ FLDATA (ERR, rc_cs, CSR_V_ERR) },
|
||||
{ FLDATA (DONE, rc_cs, CSR_V_DONE) },
|
||||
{ FLDATA (IE, rc_cs, CSR_V_IE) },
|
||||
{ DRDATA (TIME, rc_time, 24), REG_NZ + PV_LEFT },
|
||||
{ FLDATA (STOP_IOE, rc_stopioe, 0) },
|
||||
{ ORDATA (DEVADDR, rc_dib.ba, 32), REG_HRO },
|
||||
{ ORDATA (DEVVEC, rc_dib.vec, 16), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static const MTAB rc_mod[] = {
|
||||
{ UNIT_PLAT, (0 << UNIT_V_PLAT), NULL, "1P", &rc_set_size },
|
||||
{ UNIT_PLAT, (1 << UNIT_V_PLAT), NULL, "2P", &rc_set_size },
|
||||
{ UNIT_PLAT, (2 << UNIT_V_PLAT), NULL, "3P", &rc_set_size },
|
||||
{ UNIT_PLAT, (3 << UNIT_V_PLAT), NULL, "4P", &rc_set_size },
|
||||
{ UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 020, "ADDRESS", "ADDRESS",
|
||||
&set_addr, &show_addr, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR",
|
||||
&set_vec, &show_vec, NULL },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE rc_dev = {
|
||||
"RC", &rc_unit, (REG *) rc_reg, (MTAB *) rc_mod,
|
||||
1, 8, 21, 1, 8, 16,
|
||||
NULL, /* examine */
|
||||
NULL, /* deposit */
|
||||
&rc_reset, /* reset */
|
||||
NULL, /* boot */
|
||||
&rc_attach, /* attach */
|
||||
NULL, /* detach */
|
||||
&rc_dib,
|
||||
DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_DEBUG
|
||||
};
|
||||
|
||||
/* I/O dispatch routine, I/O addresses 17777440 - 17777456 */
|
||||
|
||||
static t_stat rc_rd (int32 *data, int32 PA, int32 access)
|
||||
{
|
||||
uint32 t;
|
||||
|
||||
switch ((PA >> 1) & 07) { /* decode PA<3:1> */
|
||||
|
||||
case 0: /* RCLA */
|
||||
t = rc_la & 017777;
|
||||
if ((rc_cs & RCCS_NED) || (rc_er & RCER_OVFL))
|
||||
t |= RCLA_BADD;
|
||||
*data = t;
|
||||
/* simulate sequential rotation about the current track */
|
||||
rc_la = (rc_la & ~077) | ((rc_la + 1) & 077);
|
||||
if (DEBUG_PRS (rc_dev))
|
||||
fprintf (sim_deb, ">>RC rd: RCLA %06o\n", rc_la);
|
||||
break;
|
||||
|
||||
case 1: /* RCDA */
|
||||
*data = rc_da;
|
||||
if (DEBUG_PRS (rc_dev))
|
||||
fprintf (sim_deb, ">>RC rd: RCDA %06o, PC %06o\n",
|
||||
rc_da, PC);
|
||||
break;
|
||||
|
||||
case 2: /* RCER */
|
||||
*data = rc_er;
|
||||
if (DEBUG_PRS (rc_dev))
|
||||
fprintf (sim_deb, ">>RC rd: RCER %06o\n", rc_er);
|
||||
break;
|
||||
|
||||
case 3: /* RCCS */
|
||||
*data = update_rccs (0, 0) & ~(RCCS_ABO | RCCS_GO);
|
||||
if (DEBUG_PRS (rc_dev))
|
||||
fprintf (sim_deb, ">>RC rd: RCCS %06o\n", *data);
|
||||
break;
|
||||
|
||||
case 4: /* RCWC */
|
||||
*data = rc_wc;
|
||||
if (DEBUG_PRS (rc_dev))
|
||||
fprintf (sim_deb, ">>RC rd: RCWC %06o\n", rc_wc);
|
||||
break;
|
||||
|
||||
case 5: /* RCCA */
|
||||
*data = rc_ca;
|
||||
if (DEBUG_PRS (rc_dev))
|
||||
fprintf (sim_deb, ">>RC rd: RCCA %06o\n", rc_ca);
|
||||
break;
|
||||
|
||||
case 6: /* RCMN */
|
||||
*data = rc_maint;
|
||||
if (DEBUG_PRS (rc_dev))
|
||||
fprintf (sim_deb, ">>RC rd: RCMN %06o\n", rc_maint);
|
||||
break;
|
||||
|
||||
case 7: /* RCDB */
|
||||
*data = rc_db;
|
||||
if (DEBUG_PRS (rc_dev))
|
||||
fprintf (sim_deb, ">>RC rd: RCDB %06o\n", rc_db);
|
||||
break;
|
||||
|
||||
default:
|
||||
return (SCPE_NXM); /* can't happen */
|
||||
} /* end switch */
|
||||
return (SCPE_OK);
|
||||
}
|
||||
|
||||
static t_stat rc_wr (int32 data, int32 PA, int32 access)
|
||||
{
|
||||
int32 t;
|
||||
|
||||
switch ((PA >> 1) & 07) { /* decode PA<3:1> */
|
||||
|
||||
case 0: /* RCLA */
|
||||
if (DEBUG_PRS (rc_dev))
|
||||
fprintf (sim_deb, ">>RC wr: RCLA\n");
|
||||
break; /* read only */
|
||||
|
||||
case 1: /* RCDA */
|
||||
if (access == WRITEB)
|
||||
data = (PA & 1) ?
|
||||
(rc_da & 0377) | (data << 8) :
|
||||
(rc_da & ~0377) | data;
|
||||
rc_da = data & 017777;
|
||||
rc_cs &= ~RCCS_NED;
|
||||
update_rccs (0, 0);
|
||||
/* perform unit select */
|
||||
if (((rc_da >> 11) & 03) >= UNIT_GETP(rc_unit.flags))
|
||||
update_rccs (RCCS_NED, 0);
|
||||
else
|
||||
rc_la = rc_da;
|
||||
if (DEBUG_PRS (rc_dev))
|
||||
fprintf (sim_deb, ">>RC wr: RCDA %06o, PC %06o\n",
|
||||
rc_da, PC);
|
||||
break;
|
||||
|
||||
case 2: /* RCER */
|
||||
if (DEBUG_PRS (rc_dev))
|
||||
fprintf (sim_deb, ">>RC wr: RCER\n");
|
||||
break; /* read only */
|
||||
|
||||
case 3: /* RCCS */
|
||||
if (access == WRITEB)
|
||||
data = (PA & 1) ?
|
||||
(rc_cs & 0377) | (data << 8) :
|
||||
(rc_cs & ~0377) | data;
|
||||
if (data & RCCS_ABO) {
|
||||
update_rccs (RCCS_DONE, 0);
|
||||
sim_cancel (&rc_unit);
|
||||
}
|
||||
if ((data & RCCS_IE) == 0) /* int disable? */
|
||||
CLR_INT (RC); /* clr int request */
|
||||
else if ((rc_cs & (RCCS_DONE | RCCS_IE)) == RCCS_DONE)
|
||||
SET_INT (RC); /* set int request */
|
||||
rc_cs = (rc_cs & ~RCCS_W) | (data & RCCS_W); /* merge */
|
||||
if ((rc_cs & RCCS_DONE) && (data & RCCS_GO)) { /* new function? */
|
||||
rc_unit.FUNC = GET_FUNC (data); /* save function */
|
||||
t = (rc_da & RC_WMASK) - GET_POS (rc_time); /* delta to new loc */
|
||||
if (t <= 0) /* wrap around? */
|
||||
t = t + RC_NUMWD;
|
||||
sim_activate (&rc_unit, t * rc_time); /* schedule op */
|
||||
/* clear error indicators for new operation */
|
||||
rc_cs &= ~(RCCS_ALLERR | RCCS_ERR | RCCS_DONE);
|
||||
rc_er = 0;
|
||||
CLR_INT (RC);
|
||||
if (DEBUG_PRS (rc_dev))
|
||||
fprintf (sim_deb, ">>RC start: cs = %o, da = %o, ma = %o, wc = %o\n",
|
||||
update_rccs (0, 0), rc_da,
|
||||
GET_MEX (rc_cs) | rc_ca, rc_wc);
|
||||
}
|
||||
break;
|
||||
|
||||
case 4: /* RCWC */
|
||||
if (access == WRITEB)
|
||||
data = (PA & 1) ?
|
||||
(rc_wc & 0377) | (data << 8) :
|
||||
(rc_wc & ~0377) | data;
|
||||
rc_wc = data & DMASK;
|
||||
if (DEBUG_PRS (rc_dev))
|
||||
fprintf (sim_deb, ">>RC wr: RCWC %06o, PC %06o\n",
|
||||
rc_wc, PC);
|
||||
break;
|
||||
|
||||
case 5: /* RCCA */
|
||||
/* TBD: write byte fixup? */
|
||||
rc_ca = data & 0177776;
|
||||
if (DEBUG_PRS (rc_dev))
|
||||
fprintf (sim_deb, ">>RC wr: RCCA %06o\n", rc_ca);
|
||||
break;
|
||||
|
||||
case 6: /* RCMN */
|
||||
/* TBD: write byte fixup? */
|
||||
rc_maint = data & 0177700;
|
||||
if (DEBUG_PRS (rc_dev))
|
||||
fprintf (sim_deb, ">>RC wr: RCMN %06o\n", rc_maint);
|
||||
break;
|
||||
|
||||
case 7: /* RCDB */
|
||||
if (DEBUG_PRS (rc_dev))
|
||||
fprintf (sim_deb, ">>RC wr: RCDB\n");
|
||||
break; /* read only */
|
||||
|
||||
default: /* can't happen */
|
||||
return (SCPE_NXM);
|
||||
} /* end switch */
|
||||
update_rccs (0, 0);
|
||||
return (SCPE_OK);
|
||||
}
|
||||
|
||||
/* sector (32W) CRC-16 */
|
||||
|
||||
static uint32 sectorCRC (const uint16 *data)
|
||||
{
|
||||
uint32 crc, i, j, d;
|
||||
|
||||
crc = 0;
|
||||
for (i = 0; i < 32; i++) {
|
||||
d = *data++;
|
||||
/* cribbed from KG11-A */
|
||||
for (j = 0; j < 16; j++) {
|
||||
crc = (crc & ~01) | ((crc & 01) ^ (d & 01));
|
||||
crc = (crc & 01) ? (crc >> 1) ^ 0120001 : crc >> 1;
|
||||
d >>= 1;
|
||||
}
|
||||
}
|
||||
return (crc);
|
||||
}
|
||||
|
||||
/* Unit service
|
||||
|
||||
Note that for reads and writes, memory addresses wrap around in the
|
||||
current field. This code assumes the entire disk is buffered.
|
||||
*/
|
||||
|
||||
static t_stat rc_svc (UNIT *uptr)
|
||||
{
|
||||
uint32 ma, da, t, u_old, u_new, last_da;
|
||||
uint16 dat;
|
||||
uint16 *fbuf = uptr->filebuf;
|
||||
|
||||
if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
|
||||
update_rccs (RCCS_NED | RCCS_DONE, 0); /* nx disk */
|
||||
return (IORETURN (rc_stopioe, SCPE_UNATT));
|
||||
}
|
||||
|
||||
ma = GET_MEX (rc_cs) | rc_ca; /* 18b mem addr */
|
||||
da = rc_da * RC_NUMTR; /* sector->word offset */
|
||||
u_old = (da >> 16) & 03; /* save starting unit# */
|
||||
do {
|
||||
u_new = (da >> 16) & 03;
|
||||
if (u_new < u_old) { /* unit # overflow? */
|
||||
update_rccs (RCCS_NED, RCER_OVFL);
|
||||
break;
|
||||
}
|
||||
if (u_new >= UNIT_GETP(uptr->flags)) { /* disk overflow? */
|
||||
update_rccs (RCCS_NED, 0);
|
||||
break;
|
||||
}
|
||||
if (uptr->FUNC == RFNC_READ) { /* read? */
|
||||
last_da = da & ~037;
|
||||
dat = fbuf[da]; /* get disk data */
|
||||
rc_db = dat;
|
||||
if (Map_WriteW (ma, 2, &dat)) { /* store mem, nxm? */
|
||||
update_rccs (0, RCER_NXM);
|
||||
break;
|
||||
}
|
||||
} else if (uptr->FUNC == RFNC_WCHK) { /* write check? */
|
||||
last_da = da & ~037;
|
||||
rc_db = fbuf[da]; /* get disk data */
|
||||
if (Map_ReadW (ma, 2, &dat)) { /* read mem, nxm? */
|
||||
update_rccs (0, RCER_NXM);
|
||||
break;
|
||||
}
|
||||
if (rc_db != dat) { /* miscompare? */
|
||||
update_rccs (RCCS_WCHK, 0);
|
||||
break;
|
||||
}
|
||||
} else if (uptr->FUNC == RFNC_WRITE) { /* write */
|
||||
t = (da >> 15) & 037;
|
||||
if (((rc_wlk >> t) & 1) ||
|
||||
(uptr->flags & UNIT_RO)) { /* write locked? */
|
||||
update_rccs (RCCS_WLK, 0);
|
||||
break;
|
||||
}
|
||||
/* not locked */
|
||||
if (Map_ReadW (ma, 2, &dat)) { /* read mem, nxm? */
|
||||
update_rccs (0, RCER_NXM);
|
||||
break;
|
||||
}
|
||||
fbuf[da] = dat; /* write word */
|
||||
rc_db = dat;
|
||||
if (da >= uptr->hwmark)
|
||||
uptr->hwmark = da + 1;
|
||||
} else { /* look ahead */
|
||||
break; /* no op for now */
|
||||
}
|
||||
rc_wc = (rc_wc + 1) & DMASK; /* incr word count */
|
||||
da = (da + 1) & 0777777; /* incr disk addr */
|
||||
if ((rc_cs & RCCS_INH) == 0) /* inhibit clear? */
|
||||
ma = (ma + 2) & UNIMASK; /* incr mem addr */
|
||||
} while (rc_wc != 0); /* brk if wc */
|
||||
rc_ca = ma & DMASK; /* split ma */
|
||||
rc_cs = (rc_cs & ~RCCS_MEX) | ((ma >> (16 - RCCS_V_MEX)) & RCCS_MEX);
|
||||
da += 31;
|
||||
rc_da = (da >> 5) & 017777;
|
||||
/* CRC of last 32W, if necessary */
|
||||
if ((uptr->FUNC == RFNC_READ) || (uptr->FUNC == RFNC_WCHK))
|
||||
rc_db = sectorCRC (&fbuf[last_da]);
|
||||
if (uptr->FUNC != RFNC_LAH)
|
||||
rc_la = rc_da;
|
||||
update_rccs (RCCS_DONE, 0);
|
||||
if (DEBUG_PRS (rc_dev))
|
||||
fprintf (sim_deb, ">>RC done: cs = %o, da = %o, ma = %o, wc = %o\n",
|
||||
rc_cs, rc_da, rc_ca, rc_wc);
|
||||
return (SCPE_OK);
|
||||
}
|
||||
|
||||
/* Update CS register */
|
||||
|
||||
static uint32 update_rccs (uint32 newcs, uint32 newer)
|
||||
{
|
||||
uint32 oldcs = rc_cs;
|
||||
|
||||
rc_er |= newer; /* update RCER */
|
||||
rc_cs |= newcs; /* update CS */
|
||||
if ((rc_cs & RCCS_ALLERR) || (rc_er != 0)) /* update CS<err> */
|
||||
rc_cs |= RCCS_ERR;
|
||||
else
|
||||
rc_cs &= ~RCCS_ERR;
|
||||
if ((rc_cs & RCCS_IE) && /* IE and */
|
||||
(rc_cs & RCCS_DONE) && !(oldcs & RCCS_DONE)) /* done 0->1? */
|
||||
SET_INT (RC);
|
||||
return (rc_cs);
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
static t_stat rc_reset (DEVICE *dptr)
|
||||
{
|
||||
rc_cs = RCCS_DONE;
|
||||
rc_la = rc_da = 0;
|
||||
rc_er = 0;
|
||||
rc_wc = 0;
|
||||
rc_ca = 0;
|
||||
rc_maint = 0;
|
||||
rc_db = 0;
|
||||
CLR_INT (RC);
|
||||
sim_cancel (&rc_unit);
|
||||
return (SCPE_OK);
|
||||
}
|
||||
|
||||
/* Attach routine */
|
||||
|
||||
static t_stat rc_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
uint32 sz, p;
|
||||
static const uint32 ds_bytes = RC_DKSIZE * sizeof (int16);
|
||||
|
||||
if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize_name (cptr))) {
|
||||
p = (sz + ds_bytes - 1) / ds_bytes;
|
||||
if (p >= RC_NUMDK)
|
||||
p = RC_NUMDK - 1;
|
||||
uptr->flags = (uptr->flags & ~UNIT_PLAT) | (p << UNIT_V_PLAT);
|
||||
}
|
||||
uptr->capac = UNIT_GETP (uptr->flags) * RC_DKSIZE;
|
||||
return (attach_unit (uptr, cptr));
|
||||
}
|
||||
|
||||
/* Change disk size */
|
||||
|
||||
static t_stat rc_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if (val < 0)
|
||||
return (SCPE_IERR);
|
||||
if (uptr->flags & UNIT_ATT)
|
||||
return (SCPE_ALATT);
|
||||
uptr->capac = UNIT_GETP (val) * RC_DKSIZE;
|
||||
uptr->flags = uptr->flags & ~UNIT_AUTO;
|
||||
return (SCPE_OK);
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/* pdp11_rh.c: PDP-11 Massbus adapter simulator
|
||||
|
||||
Copyright (c) 2005-2007, Robert M Supnik
|
||||
Copyright (c) 2005-2008, 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 @@
|
||||
|
||||
rha, rhb RH11/RH70 Massbus adapter
|
||||
|
||||
02-Feb-08 RMS Fixed DMA memory address limit test (found by John Dundas)
|
||||
17-May-07 RMS Moved CS1 drive enable to devices
|
||||
21-Nov-05 RMS Added enable/disable routine
|
||||
07-Jul-05 RMS Removed extraneous externs
|
||||
@@ -160,7 +161,7 @@ MBACTX massbus[MBA_NUM];
|
||||
extern int32 cpu_opt, cpu_bme;
|
||||
extern uint16 *M;
|
||||
extern int32 int_req[IPL_HLVL];
|
||||
extern UNIT cpu_unit;
|
||||
extern t_addr cpu_memsize;
|
||||
extern FILE *sim_deb;
|
||||
extern FILE *sim_log;
|
||||
extern int32 sim_switches;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* pdp11_stddev.c: PDP-11 standard I/O devices simulator
|
||||
|
||||
Copyright (c) 1993-2007, Robert M Supnik
|
||||
Copyright (c) 1993-2008, 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"),
|
||||
@@ -26,6 +26,7 @@
|
||||
tti,tto DL11 terminal input/output
|
||||
clk KW11L (and other) line frequency clock
|
||||
|
||||
20-May-08 RMS Standardized clock delay at 1mips
|
||||
18-Jun-07 RMS Added UNIT_IDLE flag to console input, clock
|
||||
29-Oct-06 RMS Synced keyboard and clock
|
||||
Added clock coscheduling support
|
||||
@@ -66,7 +67,7 @@
|
||||
#define TTOCSR_RW (CSR_IE)
|
||||
#define CLKCSR_IMP (CSR_DONE + CSR_IE) /* real-time clock */
|
||||
#define CLKCSR_RW (CSR_IE)
|
||||
#define CLK_DELAY 8000
|
||||
#define CLK_DELAY 16667
|
||||
|
||||
extern int32 int_req[IPL_HLVL];
|
||||
extern uint32 cpu_type;
|
||||
@@ -202,7 +203,7 @@ DIB clk_dib = {
|
||||
1, IVCL (CLK), VEC_CLK, { &clk_inta }
|
||||
};
|
||||
|
||||
UNIT clk_unit = { UDATA (&clk_svc, UNIT_IDLE, 0), 8000 };
|
||||
UNIT clk_unit = { UDATA (&clk_svc, UNIT_IDLE, 0), CLK_DELAY };
|
||||
|
||||
REG clk_reg[] = {
|
||||
{ ORDATA (CSR, clk_csr, 16) },
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* pdp11_sys.c: PDP-11 simulator interface
|
||||
|
||||
Copyright (c) 1993-2006, Robert M Supnik
|
||||
Copyright (c) 1993-2008, 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,11 @@
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
15-May-08 RMS Added KE11-A, DC11 support
|
||||
Renamed DL11
|
||||
04-Feb-08 RMS Modified to allow -A, -B use with 8b devices
|
||||
25-Jan-08 RMS Added RC11, KG11A support from John Dundas
|
||||
10-Sep-07 RMS Cleaned up binary loader
|
||||
20-Dec-06 RMS Added TA11 support
|
||||
12-Nov-06 RMS Fixed operand order in EIS instructions (found by W.F.J. Mueller)
|
||||
14-Jul-06 RMS Reordered device list
|
||||
@@ -69,11 +74,14 @@ extern DEVICE lpt_dev;
|
||||
extern DEVICE cr_dev;
|
||||
extern DEVICE clk_dev;
|
||||
extern DEVICE pclk_dev;
|
||||
extern DEVICE ttix_dev;
|
||||
extern DEVICE ttox_dev;
|
||||
extern DEVICE dli_dev;
|
||||
extern DEVICE dlo_dev;
|
||||
extern DEVICE dci_dev;
|
||||
extern DEVICE dco_dev;
|
||||
extern DEVICE dz_dev;
|
||||
extern DEVICE vh_dev;
|
||||
extern DEVICE dt_dev;
|
||||
extern DEVICE rc_dev;
|
||||
extern DEVICE rf_dev;
|
||||
extern DEVICE rk_dev;
|
||||
extern DEVICE rl_dev;
|
||||
@@ -90,6 +98,8 @@ extern DEVICE tu_dev;
|
||||
extern DEVICE ta_dev;
|
||||
extern DEVICE xq_dev, xqb_dev;
|
||||
extern DEVICE xu_dev, xub_dev;
|
||||
extern DEVICE ke_dev;
|
||||
extern DEVICE kg_dev;
|
||||
extern UNIT cpu_unit;
|
||||
extern REG cpu_reg[];
|
||||
extern uint16 *M;
|
||||
@@ -124,10 +134,13 @@ DEVICE *sim_devices[] = {
|
||||
&tto_dev,
|
||||
&cr_dev,
|
||||
&lpt_dev,
|
||||
&ttix_dev,
|
||||
&ttox_dev,
|
||||
&dli_dev,
|
||||
&dlo_dev,
|
||||
&dci_dev,
|
||||
&dco_dev,
|
||||
&dz_dev,
|
||||
&vh_dev,
|
||||
&rc_dev,
|
||||
&rf_dev,
|
||||
&rk_dev,
|
||||
&rl_dev,
|
||||
@@ -149,6 +162,8 @@ DEVICE *sim_devices[] = {
|
||||
&xqb_dev,
|
||||
&xu_dev,
|
||||
&xub_dev,
|
||||
&ke_dev,
|
||||
&kg_dev,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -202,66 +217,44 @@ const char *sim_stop_messages[] = {
|
||||
|
||||
t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
|
||||
{
|
||||
int32 csum, count, state, i;
|
||||
uint32 origin;
|
||||
int32 c[6], d, i, cnt, csum;
|
||||
uint32 org;
|
||||
|
||||
if ((*cptr != 0) || (flag != 0)) return SCPE_ARG;
|
||||
state = csum = 0;
|
||||
while ((i = getc (fileref)) != EOF) {
|
||||
csum = csum + i; /* add into chksum */
|
||||
switch (state) {
|
||||
|
||||
case 0: /* leader */
|
||||
if (i == 1) state = 1;
|
||||
else csum = 0;
|
||||
break;
|
||||
|
||||
case 1: /* ignore after 001 */
|
||||
state = 2;
|
||||
break;
|
||||
|
||||
case 2: /* low count */
|
||||
count = i;
|
||||
state = 3;
|
||||
break;
|
||||
|
||||
case 3: /* high count */
|
||||
count = (i << 8) | count;
|
||||
state = 4;
|
||||
break;
|
||||
|
||||
case 4: /* low origin */
|
||||
origin = i;
|
||||
state = 5;
|
||||
break;
|
||||
|
||||
case 5: /* high origin */
|
||||
origin = (i << 8) | origin;
|
||||
if (count == 6) {
|
||||
if (origin != 1) saved_PC = origin & 0177776;
|
||||
return SCPE_OK;
|
||||
}
|
||||
count = count - 6;
|
||||
state = 6;
|
||||
break;
|
||||
|
||||
case 6: /* data */
|
||||
if (origin >= MEMSIZE) return SCPE_NXM;
|
||||
M[origin >> 1] = (origin & 1)?
|
||||
(M[origin >> 1] & 0377) | (i << 8):
|
||||
(M[origin >> 1] & 0177400) | i;
|
||||
origin = origin + 1;
|
||||
count = count - 1;
|
||||
state = state + (count == 0);
|
||||
break;
|
||||
|
||||
case 7: /* checksum */
|
||||
if (csum & 0377) return SCPE_CSUM;
|
||||
csum = state = 0;
|
||||
break;
|
||||
} /* end switch */
|
||||
} /* end while */
|
||||
return SCPE_FMT; /* unexpected eof */
|
||||
if ((*cptr != 0) || (flag != 0))
|
||||
return SCPE_ARG;
|
||||
do { /* block loop */
|
||||
csum = 0; /* init checksum */
|
||||
for (i = 0; i < 6; ) { /* 6 char header */
|
||||
if ((c[i] = getc (fileref)) == EOF)
|
||||
return SCPE_FMT;
|
||||
if ((i != 0) || (c[i] == 1)) /* 1st must be 1 */
|
||||
csum = csum + c[i++]; /* add into csum */
|
||||
}
|
||||
cnt = (c[3] << 8) | c[2]; /* count */
|
||||
org = (c[5] << 8) | c[4]; /* origin */
|
||||
if (cnt < 6) /* invalid? */
|
||||
return SCPE_FMT;
|
||||
if (cnt == 6) { /* end block? */
|
||||
if (org != 1) /* set PC? */
|
||||
saved_PC = org & 0177776;
|
||||
return SCPE_OK;
|
||||
}
|
||||
for (i = 6; i < cnt; i++) { /* exclude hdr */
|
||||
if ((d = getc (fileref)) == EOF) /* data char */
|
||||
return SCPE_FMT;
|
||||
csum = csum + d; /* add into csum */
|
||||
if (org >= MEMSIZE) /* invalid addr? */
|
||||
return SCPE_NXM;
|
||||
M[org >> 1] = (org & 1)? /* store data */
|
||||
(M[org >> 1] & 0377) | (d << 8):
|
||||
(M[org >> 1] & 0177400) | d;
|
||||
org = (org + 1) & 0177777; /* inc origin */
|
||||
}
|
||||
if ((d = getc (fileref)) == EOF) /* get csum */
|
||||
return SCPE_FMT;
|
||||
csum = csum + d; /* add in */
|
||||
} while ((csum & 0377) == 0); /* result mbz */
|
||||
return SCPE_CSUM;
|
||||
}
|
||||
|
||||
/* Factory bad block table creation routine
|
||||
@@ -288,20 +281,27 @@ t_stat pdp11_bad_block (UNIT *uptr, int32 sec, int32 wds)
|
||||
int32 i, da;
|
||||
uint16 *buf;
|
||||
|
||||
if ((sec < 2) || (wds < 16)) return SCPE_ARG;
|
||||
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT;
|
||||
if (uptr->flags & UNIT_RO) return SCPE_RO;
|
||||
if (!get_yn ("Create bad block table on last track? [N]", FALSE)) return SCPE_OK;
|
||||
da = (uptr->capac - (sec * wds)) * sizeof (int16);
|
||||
if (fseek (uptr->fileref, da, SEEK_SET)) return SCPE_IOERR;
|
||||
if ((buf = (uint16 *) malloc (wds * sizeof (uint16))) == NULL) return SCPE_MEM;
|
||||
if ((sec < 2) || (wds < 16))
|
||||
return SCPE_ARG;
|
||||
if ((uptr->flags & UNIT_ATT) == 0)
|
||||
return SCPE_UNATT;
|
||||
if (uptr->flags & UNIT_RO)
|
||||
return SCPE_RO;
|
||||
if (!get_yn ("Create bad block table on last track? [N]", FALSE))
|
||||
return SCPE_OK;
|
||||
da = (uptr->capac - (sec * wds)) * sizeof (uint16);
|
||||
if (fseek (uptr->fileref, da, SEEK_SET))
|
||||
return SCPE_IOERR;
|
||||
if ((buf = (uint16 *) malloc (wds * sizeof (uint16))) == NULL)
|
||||
return SCPE_MEM;
|
||||
buf[0] = buf[1] = 012345u;
|
||||
buf[2] = buf[3] = 0;
|
||||
for (i = 4; i < wds; i++) buf[i] = 0177777u;
|
||||
for (i = 0; (i < sec) && (i < 10); i++)
|
||||
fxwrite (buf, sizeof (uint16), wds, uptr->fileref);
|
||||
free (buf);
|
||||
if (ferror (uptr->fileref)) return SCPE_IOERR;
|
||||
if (ferror (uptr->fileref))
|
||||
return SCPE_IOERR;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -532,7 +532,8 @@ mode = ((spec >> 3) & 07);
|
||||
switch (mode) {
|
||||
|
||||
case 0:
|
||||
if (iflag) fprintf (of, "%s", rname[reg]);
|
||||
if (iflag)
|
||||
fprintf (of, "%s", rname[reg]);
|
||||
else fprintf (of, "%s", fname[reg]);
|
||||
break;
|
||||
|
||||
@@ -541,12 +542,14 @@ switch (mode) {
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (reg != 7) fprintf (of, "(%s)+", rname[reg]);
|
||||
if (reg != 7)
|
||||
fprintf (of, "(%s)+", rname[reg]);
|
||||
else fprintf (of, "#%-o", nval);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (reg != 7) fprintf (of, "@(%s)+", rname[reg]);
|
||||
if (reg != 7)
|
||||
fprintf (of, "@(%s)+", rname[reg]);
|
||||
else fprintf (of, "@#%-o", nval);
|
||||
break;
|
||||
|
||||
@@ -559,12 +562,14 @@ switch (mode) {
|
||||
break;
|
||||
|
||||
case 6:
|
||||
if ((reg != 7) || !flag) fprintf (of, "%-o(%s)", nval, rname[reg]);
|
||||
if ((reg != 7) || !flag)
|
||||
fprintf (of, "%-o(%s)", nval, rname[reg]);
|
||||
else fprintf (of, "%-o", (nval + addr + 4) & 0177777);
|
||||
break;
|
||||
|
||||
case 7:
|
||||
if ((reg != 7) || !flag) fprintf (of, "@%-o(%s)", nval, rname[reg]);
|
||||
if ((reg != 7) || !flag)
|
||||
fprintf (of, "@%-o(%s)", nval, rname[reg]);
|
||||
else fprintf (of, "@%-o", (nval + addr + 4) & 0177777);
|
||||
break;
|
||||
} /* end case */
|
||||
@@ -589,20 +594,35 @@ t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
|
||||
UNIT *uptr, int32 sw)
|
||||
{
|
||||
int32 cflag, i, j, c1, c2, c3, inst, fac, srcm, srcr, dstm, dstr;
|
||||
int32 l8b, brdisp, wd1, wd2;
|
||||
int32 bflag, l8b, brdisp, wd1, wd2;
|
||||
extern int32 FPS;
|
||||
|
||||
cflag = (uptr == NULL) || (uptr == &cpu_unit);
|
||||
bflag = 0; /* assume 16b */
|
||||
cflag = (uptr == NULL) || (uptr == &cpu_unit); /* cpu? */
|
||||
if (!cflag) { /* not cpu? */
|
||||
DEVICE *dptr = find_dev_from_unit (uptr);
|
||||
if (dptr == NULL)
|
||||
return SCPE_IERR;
|
||||
if (dptr->dwidth < 16)
|
||||
bflag = 1;
|
||||
}
|
||||
|
||||
if (sw & SWMASK ('A')) { /* ASCII? */
|
||||
c1 = (val[0] >> ((addr & 1)? 8: 0)) & 0177;
|
||||
if (bflag)
|
||||
c1 = val[0] & 0177;
|
||||
else c1 = (val[0] >> ((addr & 1)? 8: 0)) & 0177;
|
||||
fprintf (of, (c1 < 040)? "<%03o>": "%c", c1);
|
||||
return 0;
|
||||
}
|
||||
if (sw & SWMASK ('B')) { /* byte? */
|
||||
c1 = (val[0] >> ((addr & 1)? 8: 0)) & 0377;
|
||||
if (bflag)
|
||||
c1 = val[0] & 0177;
|
||||
else c1 = (val[0] >> ((addr & 1)? 8: 0)) & 0377;
|
||||
fprintf (of, "%o", c1);
|
||||
return 0;
|
||||
}
|
||||
if (bflag) return SCPE_ARG; /* 16b only */
|
||||
|
||||
if (sw & SWMASK ('C')) { /* character? */
|
||||
c1 = val[0] & 0177;
|
||||
c2 = (val[0] >> 8) & 0177;
|
||||
@@ -669,8 +689,10 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
|
||||
case I_V_BR: /* cond branch */
|
||||
fprintf (of, "%s ", opcode[i]);
|
||||
brdisp = (l8b + l8b + ((l8b & 0200)? 0177002: 2)) & 0177777;
|
||||
if (cflag) fprintf (of, "%-o", (addr + brdisp) & 0177777);
|
||||
else if (brdisp < 01000) fprintf (of, ".+%-o", brdisp);
|
||||
if (cflag)
|
||||
fprintf (of, "%-o", (addr + brdisp) & 0177777);
|
||||
else if (brdisp < 01000)
|
||||
fprintf (of, ".+%-o", brdisp);
|
||||
else fprintf (of, ".-%-o", 0200000 - brdisp);
|
||||
break;
|
||||
|
||||
@@ -681,8 +703,10 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
|
||||
case I_V_SOB: /* sob */
|
||||
fprintf (of, "%s %s,", opcode[i], rname[srcr]);
|
||||
brdisp = (dstm * 2) - 2;
|
||||
if (cflag) fprintf (of, "%-o", (addr - brdisp) & 0177777);
|
||||
else if (brdisp <= 0) fprintf (of, ".+%-o", -brdisp);
|
||||
if (cflag)
|
||||
fprintf (of, "%-o", (addr - brdisp) & 0177777);
|
||||
else if (brdisp <= 0)
|
||||
fprintf (of, ".+%-o", -brdisp);
|
||||
else fprintf (of, ".-%-o", brdisp);
|
||||
break;
|
||||
|
||||
@@ -741,7 +765,8 @@ int32 i;
|
||||
|
||||
if (*(cptr + 2) != mchar) return -1;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (strncmp (cptr, strings[i], 2) == 0) return i;
|
||||
if (strncmp (cptr, strings[i], 2) == 0)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -782,11 +807,13 @@ if (*cptr == '-') { /* -? */
|
||||
errno = 0;
|
||||
val = strtoul (cptr, &tptr, 8);
|
||||
if (cptr == tptr) { /* no number? */
|
||||
if (*pflag == (A_REL + A_NUM)) return NULL; /* .+, .-? */
|
||||
if (*pflag == (A_REL + A_NUM)) /* .+, .-? */
|
||||
return NULL;
|
||||
*dptr = 0;
|
||||
return cptr;
|
||||
}
|
||||
if (errno || (*pflag == A_REL)) return NULL; /* .n? */
|
||||
if (errno || (*pflag == A_REL)) /* .n? */
|
||||
return NULL;
|
||||
*dptr = (minus? -val: val) & 0177777;
|
||||
*pflag = *pflag | A_NUM;
|
||||
return tptr;
|
||||
@@ -832,7 +859,8 @@ if (strncmp (cptr, "-(", 2) == 0) { /* autodecrement? */
|
||||
else if ((cptr = get_addr (cptr, &disp, &pflag)) == NULL) return 1;
|
||||
if (*cptr == '(') { /* register index? */
|
||||
pflag = pflag | A_PAR;
|
||||
if ((reg = get_reg (cptr + 1, rname, ')')) < 0) return 1;
|
||||
if ((reg = get_reg (cptr + 1, rname, ')')) < 0)
|
||||
return 1;
|
||||
cptr = cptr + 4;
|
||||
if (*cptr == '+') { /* autoincrement? */
|
||||
pflag = pflag | A_PLS;
|
||||
@@ -843,7 +871,8 @@ else if ((reg = get_reg (cptr, iflag? rname: fname, 0)) >= 0) {
|
||||
pflag = pflag | A_REG;
|
||||
cptr = cptr + 2;
|
||||
}
|
||||
if (*cptr != 0) return 1; /* all done? */
|
||||
if (*cptr != 0) /* all done? */
|
||||
return 1;
|
||||
switch (pflag) { /* case on syntax */
|
||||
|
||||
case A_REG: /* Rn, @Rn */
|
||||
@@ -873,7 +902,8 @@ switch (pflag) { /* case on syntax */
|
||||
return -1;
|
||||
|
||||
case A_PND+A_REL: case A_PND+A_REL+A_NUM: /* #.+n, @#.+n */
|
||||
if (!cflag) return 1;
|
||||
if (!cflag)
|
||||
return 1;
|
||||
disp = (disp + addr) & 0177777; /* fall through */
|
||||
case A_PND+A_NUM: /* #n, @#n */
|
||||
*sptr = 027 + indir;
|
||||
@@ -917,37 +947,59 @@ switch (pflag) { /* case on syntax */
|
||||
|
||||
t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
|
||||
{
|
||||
int32 cflag, d, i, j, reg, spec, n1, n2, disp, pflag;
|
||||
int32 bflag, cflag, d, i, j, reg, spec, n1, n2, disp, pflag;
|
||||
t_value by;
|
||||
t_stat r;
|
||||
char *tptr, gbuf[CBUFSIZE];
|
||||
|
||||
cflag = (uptr == NULL) || (uptr == &cpu_unit);
|
||||
bflag = 0; /* assume 16b */
|
||||
cflag = (uptr == NULL) || (uptr == &cpu_unit); /* cpu? */
|
||||
if (!cflag) { /* not cpu? */
|
||||
DEVICE *dptr = find_dev_from_unit (uptr);
|
||||
if (dptr == NULL)
|
||||
return SCPE_IERR;
|
||||
if (dptr->dwidth < 16)
|
||||
bflag = 1;
|
||||
}
|
||||
|
||||
while (isspace (*cptr)) cptr++; /* absorb spaces */
|
||||
if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */
|
||||
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
|
||||
if (addr & 1) val[0] = (val[0] & 0377) | (((t_value) cptr[0]) << 8);
|
||||
else val[0] = (val[0] & ~0377) | ((t_value) cptr[0]);
|
||||
if (cptr[0] == 0) /* must have 1 char */
|
||||
return SCPE_ARG;
|
||||
if (bflag)
|
||||
val[0] = (t_value) cptr[0];
|
||||
else val[0] = (addr & 1)?
|
||||
(val[0] & 0377) | (((t_value) cptr[0]) << 8):
|
||||
(val[0] & ~0377) | ((t_value) cptr[0]);
|
||||
return 0;
|
||||
}
|
||||
if (sw & SWMASK ('B')) { /* byte? */
|
||||
by = get_uint (cptr, 8, 0377, &r); /* get byte */
|
||||
if (r != SCPE_OK) return SCPE_ARG;
|
||||
if (addr & 1) val[0] = (val[0] & 0377) | (by << 8);
|
||||
else val[0] = (val[0] & ~0377) | by;
|
||||
if (r != SCPE_OK)
|
||||
return SCPE_ARG;
|
||||
if (bflag)
|
||||
val[0] = by;
|
||||
else val[0] = (addr & 1)?
|
||||
(val[0] & 0377) | (by << 8):
|
||||
(val[0] & ~0377) | by;
|
||||
return 0;
|
||||
}
|
||||
if (bflag) return SCPE_ARG;
|
||||
|
||||
if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII string? */
|
||||
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
|
||||
if (cptr[0] == 0) /* must have 1 char */
|
||||
return SCPE_ARG;
|
||||
val[0] = ((t_value) cptr[1] << 8) | (t_value) cptr[0];
|
||||
return -1;
|
||||
}
|
||||
if (sw & SWMASK ('R')) return SCPE_ARG; /* radix 50 */
|
||||
if (sw & SWMASK ('R')) /* radix 50 */
|
||||
return SCPE_ARG;
|
||||
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get opcode */
|
||||
n1 = n2 = pflag = 0;
|
||||
for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;
|
||||
if (opcode[i] == NULL) return SCPE_ARG;
|
||||
if (opcode[i] == NULL)
|
||||
return SCPE_ARG;
|
||||
val[0] = opc_val[i] & 0177777; /* get value */
|
||||
j = (opc_val[i] >> I_V_CL) & I_M_CL; /* get class */
|
||||
|
||||
@@ -958,26 +1010,30 @@ switch (j) { /* case on class */
|
||||
|
||||
case I_V_REG: /* register */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get glyph */
|
||||
if ((reg = get_reg (gbuf, rname, 0)) < 0) return SCPE_ARG;
|
||||
if ((reg = get_reg (gbuf, rname, 0)) < 0)
|
||||
return SCPE_ARG;
|
||||
val[0] = val[0] | reg;
|
||||
break;
|
||||
|
||||
case I_V_3B: case I_V_6B: case I_V_8B: /* xb literal */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get literal */
|
||||
d = get_uint (gbuf, 8, (1 << j) - 1, &r);
|
||||
if (r != SCPE_OK) return SCPE_ARG;
|
||||
if (r != SCPE_OK)
|
||||
return SCPE_ARG;
|
||||
val[0] = val[0] | d; /* put in place */
|
||||
break;
|
||||
|
||||
case I_V_BR: /* cond br */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get address */
|
||||
tptr = get_addr (gbuf, &disp, &pflag); /* parse */
|
||||
if ((tptr == NULL) || (*tptr != 0)) return SCPE_ARG;
|
||||
if ((tptr == NULL) || (*tptr != 0))
|
||||
return SCPE_ARG;
|
||||
if ((pflag & A_REL) == 0) {
|
||||
if (cflag) disp = (disp - addr) & 0177777;
|
||||
else return SCPE_ARG;
|
||||
}
|
||||
if ((disp & 1) || (disp > 0400) && (disp < 0177402)) return SCPE_ARG;
|
||||
if ((disp & 1) || (disp > 0400) && (disp < 0177402))
|
||||
return SCPE_ARG;
|
||||
val[0] = val[0] | (((disp - 2) >> 1) & 0377);
|
||||
break;
|
||||
|
||||
@@ -987,18 +1043,21 @@ switch (j) { /* case on class */
|
||||
val[0] = val[0] | (reg << 6);
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get address */
|
||||
tptr = get_addr (gbuf, &disp, &pflag); /* parse */
|
||||
if ((tptr == NULL) || (*tptr != 0)) return SCPE_ARG;
|
||||
if ((tptr == NULL) || (*tptr != 0))
|
||||
return SCPE_ARG;
|
||||
if ((pflag & A_REL) == 0) {
|
||||
if (cflag) disp = (disp - addr) & 0177777;
|
||||
else return SCPE_ARG;
|
||||
}
|
||||
if ((disp & 1) || ((disp > 2) && (disp < 0177604))) return SCPE_ARG;
|
||||
if ((disp & 1) || ((disp > 2) && (disp < 0177604)))
|
||||
return SCPE_ARG;
|
||||
val[0] = val[0] | (((2 - disp) >> 1) & 077);
|
||||
break;
|
||||
|
||||
case I_V_RSOP: /* reg, sop */
|
||||
cptr = get_glyph (cptr, gbuf, ','); /* get glyph */
|
||||
if ((reg = get_reg (gbuf, rname, 0)) < 0) return SCPE_ARG;
|
||||
if ((reg = get_reg (gbuf, rname, 0)) < 0)
|
||||
return SCPE_ARG;
|
||||
val[0] = val[0] | (reg << 6); /* fall through */
|
||||
case I_V_SOP: /* sop */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get glyph */
|
||||
@@ -1013,19 +1072,23 @@ switch (j) { /* case on class */
|
||||
return SCPE_ARG;
|
||||
val[0] = val[0] | spec;
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get glyph */
|
||||
if ((reg = get_reg (gbuf, rname, 0)) < 0) return SCPE_ARG;
|
||||
if ((reg = get_reg (gbuf, rname, 0)) < 0)
|
||||
return SCPE_ARG;
|
||||
val[0] = val[0] | (reg << 6);
|
||||
break;
|
||||
|
||||
case I_V_AFOP: case I_V_ASOP: case I_V_ASMD: /* fac, (s)fop */
|
||||
cptr = get_glyph (cptr, gbuf, ','); /* get glyph */
|
||||
if ((reg = get_reg (gbuf, fname, 0)) < 0) return SCPE_ARG;
|
||||
if (reg > 3) return SCPE_ARG;
|
||||
if ((reg = get_reg (gbuf, fname, 0)) < 0)
|
||||
return SCPE_ARG;
|
||||
if (reg > 3)
|
||||
return SCPE_ARG;
|
||||
val[0] = val[0] | (reg << 6); /* fall through */
|
||||
case I_V_FOP: /* fop */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get glyph */
|
||||
if ((n1 = get_spec (gbuf, addr, 0, &spec, &val[1], cflag,
|
||||
(j == I_V_ASOP) || (j == I_V_ASMD))) > 0) return SCPE_ARG;
|
||||
(j == I_V_ASOP) || (j == I_V_ASMD))) > 0)
|
||||
return SCPE_ARG;
|
||||
val[0] = val[0] | spec;
|
||||
break;
|
||||
|
||||
@@ -1036,7 +1099,8 @@ switch (j) { /* case on class */
|
||||
val[0] = val[0] | (spec << 6);
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get glyph */
|
||||
if ((n2 = get_spec (gbuf, addr, n1, &spec, &val[1 - n1],
|
||||
cflag, TRUE)) > 0) return SCPE_ARG;
|
||||
cflag, TRUE)) > 0)
|
||||
return SCPE_ARG;
|
||||
val[0] = val[0] | spec;
|
||||
break;
|
||||
|
||||
@@ -1046,7 +1110,8 @@ switch (j) { /* case on class */
|
||||
for (i = 0; (opcode[i] != NULL) &&
|
||||
(strcmp (opcode[i], gbuf) != 0) ; i++) ;
|
||||
if ((((opc_val[i] >> I_V_CL) & I_M_CL) != j) ||
|
||||
(opcode[i] == NULL)) return SCPE_ARG;
|
||||
(opcode[i] == NULL))
|
||||
return SCPE_ARG;
|
||||
val[0] = val[0] | (opc_val[i] & 0177777);
|
||||
}
|
||||
break;
|
||||
@@ -1055,6 +1120,7 @@ switch (j) { /* case on class */
|
||||
return SCPE_ARG;
|
||||
}
|
||||
|
||||
if (*cptr != 0) return SCPE_ARG; /* junk at end? */
|
||||
if (*cptr != 0) /* junk at end? */
|
||||
return SCPE_ARG;
|
||||
return ((n1 + n2) * 2) - 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user