simh v2.7

This commit is contained in:
Bob Supnik 2001-11-06 21:02:00 -08:00 committed by Mark Pizzolato
parent 89bcd020e1
commit 654937fc88
67 changed files with 4214 additions and 1693 deletions

View file

@ -30,7 +30,6 @@ extern unsigned int32 get_uint (char *cptr, int32 radix, unsigned int32 max,
sim_PC pointer to saved PC register descriptor
sim_emax number of words needed for examine
sim_devices array of pointers to simulated devices
sim_consoles array of pointers to consoles (if more than one)
sim_stop_messages array of pointers to stop messages
sim_load binary loader
*/
@ -44,8 +43,6 @@ int32 sim_emax = 4;
DEVICE *sim_devices[] = { &cpu_dev, &sio_dev, &ptr_dev,
&ptp_dev, &dsk_dev, NULL };
UNIT *sim_consoles = NULL;
const char *sim_stop_messages[] = {
"Unknown error",
"Unknown I/O Instruction",

438
dec_dz.h Normal file
View file

@ -0,0 +1,438 @@
/* dec_dz.c: DZ11 terminal multiplexor simulator
Copyright (c) 2001, 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.
Based on the original DZ11 simulator by Thord Nilson, as updated by
Arthur Krewat.
dz DZ11 terminal multiplexor
20-Oct-01 RMS Moved getchar from sim_tmxr, changed interrupt
logic to use tmxr_rqln
06-Oct-01 RMS Fixed bug in carrier detect logic
03-Oct-01 RMS Added support for BSD-style "ringless" modems
27-Sep-01 RMS Fixed bug in xmte initialization
17-Sep-01 RMS Added separate autodisconnect switch
16-Sep-01 RMS Fixed modem control bit offsets
This file is intended to be included in a shell routine that invokes
a simulator definition file:
pdp11_dz.c = pdp11_defs.h + dec_dz.h
pdp10_dz.c = pdp10_defs.h + dec_dz.h
vax_dz.c = vax_defs.h + dec_dz.h
*/
#include "sim_sock.h"
#include "sim_tmxr.h"
#define DZ_LNOMASK (DZ_LINES - 1) /* mask for lineno */
#define DZ_LMASK ((1 << DZ_LINES) - 1) /* mask of lines */
#define DZ_SILO_ALM 16 /* silo alarm level */
/* DZCSR - 160100 - control/status register */
#define CSR_MAINT 0000010 /* maint - NI */
#define CSR_CLR 0000020 /* clear */
#define CSR_MSE 0000040 /* master scan enb */
#define CSR_RIE 0000100 /* rcv int enb */
#define CSR_RDONE 0000200 /* rcv done - RO */
#define CSR_V_TLINE 8 /* xmit line - RO */
#define CSR_TLINE (DZ_LNOMASK << CSR_V_TLINE)
#define CSR_SAE 0010000 /* silo alm enb */
#define CSR_SA 0020000 /* silo alm - RO */
#define CSR_TIE 0040000 /* xmit int enb */
#define CSR_TRDY 0100000 /* xmit rdy - RO */
#define CSR_RW (CSR_MSE | CSR_RIE | CSR_SAE | CSR_TIE)
#define CSR_MBZ (0004003 | CSR_CLR | CSR_MAINT)
#define CSR_GETTL(x) (((x) >> CSR_V_TLINE) & DZ_LNOMASK)
#define CSR_PUTTL(x,y) x = ((x) & ~CSR_TLINE) | (((y) & DZ_LNOMASK) << CSR_V_TLINE)
/* DZRBUF - 160102 - receive buffer, read only */
#define RBUF_CHAR 0000377 /* rcv char */
#define RBUF_V_RLINE 8 /* rcv line */
#define RBUF_PARE 0010000 /* parity err - NI */
#define RBUF_FRME 0020000 /* frame err - NI */
#define RBUF_OVRE 0040000 /* overrun err - NI */
#define RBUF_VALID 0100000 /* rcv valid */
#define RBUF_MBZ 0004000
/* DZLPR - 160102 - line parameter register, write only, word access only */
#define LPR_V_LINE 0 /* line */
#define LPR_LPAR 0007770 /* line pars - NI */
#define LPR_RCVE 0010000 /* receive enb */
#define LPR_GETLN(x) (((x) >> LPR_V_LINE) & DZ_LNOMASK)
/* DZTCR - 160104 - transmission control register */
#define TCR_V_XMTE 0 /* xmit enables */
#define TCR_V_DTR 8 /* DTRs */
/* DZMSR - 160106 - modem status register, read only */
#define MSR_V_RI 0 /* ring indicators */
#define MSR_V_CD 8 /* carrier detect */
/* DZTDR - 160106 - transmit data, write only */
#define TDR_CHAR 0000377 /* xmit char */
#define TDR_V_TBR 8 /* xmit break - NI */
extern int32 IREQ (HLVL);
extern int32 sim_switches;
extern FILE *sim_log;
extern int32 tmxr_poll; /* calibrated delay */
int32 dz_csr = 0; /* csr */
int32 dz_rbuf = 0; /* rcv buffer */
int32 dz_lpr = 0; /* line param */
int32 dz_tcr = 0; /* xmit control */
int32 dz_msr = 0; /* modem status */
int32 dz_tdr = 0; /* xmit data */
int32 dz_mctl = 0; /* modem ctrl enabled */
int32 dz_auto = 0; /* autodiscon enabled */
int32 dz_sa_enb = 1; /* silo alarm enabled */
int32 dz_enb = 1; /* device enable */
TMLN dz_ldsc[DZ_LINES] = { /* line descriptors */
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 } };
TMXR dz_desc = { /* mux descriptor */
DZ_LINES, 0,
&dz_ldsc[0], &dz_ldsc[1], &dz_ldsc[2], &dz_ldsc[3],
&dz_ldsc[4], &dz_ldsc[5], &dz_ldsc[6], &dz_ldsc[7] };
t_stat dz_svc (UNIT *uptr);
t_stat dz_reset (DEVICE *dptr);
t_stat dz_attach (UNIT *uptr, char *cptr);
t_stat dz_detach (UNIT *uptr);
t_stat dz_clear (t_bool flag);
int32 dz_getchar (TMXR *mp);
void dz_update_rcvi (void);
void dz_update_xmti (void);
t_stat dz_status (UNIT *uptr, FILE *st);
/* DZ data structures
dz_dev DZ device descriptor
dz_unit DZ unit list
dz_reg DZ register list
*/
UNIT dz_unit = { UDATA (&dz_svc, UNIT_ATTABLE, 0) };
REG dz_reg[] = {
{ ORDATA (CSR, dz_csr, 16) },
{ ORDATA (RBUF, dz_rbuf, 16) },
{ ORDATA (LPR, dz_lpr, 16) },
{ ORDATA (TCR, dz_tcr, 16) },
{ ORDATA (MSR, dz_msr, 16) },
{ ORDATA (TDR, dz_tdr, 16) },
{ FLDATA (SAENB, dz_sa_enb, 0) },
{ FLDATA (MDMCTL, dz_mctl, 0) },
{ FLDATA (AUTODS, dz_auto, 0) },
{ DRDATA (RPOS0, dz_ldsc[0].rxcnt, 32), PV_LEFT+REG_RO },
{ DRDATA (TPOS0, dz_ldsc[0].txcnt, 32), PV_LEFT+REG_RO },
{ DRDATA (RPOS1, dz_ldsc[1].rxcnt, 32), PV_LEFT+REG_RO },
{ DRDATA (TPOS1, dz_ldsc[1].txcnt, 32), PV_LEFT+REG_RO },
{ DRDATA (RPOS2, dz_ldsc[2].rxcnt, 32), PV_LEFT+REG_RO },
{ DRDATA (TPOS2, dz_ldsc[2].txcnt, 32), PV_LEFT+REG_RO },
{ DRDATA (RPOS3, dz_ldsc[3].rxcnt, 32), PV_LEFT+REG_RO },
{ DRDATA (TPOS3, dz_ldsc[3].txcnt, 32), PV_LEFT+REG_RO },
{ DRDATA (RPOS4, dz_ldsc[4].rxcnt, 32), PV_LEFT+REG_RO },
{ DRDATA (TPOS4, dz_ldsc[4].txcnt, 32), PV_LEFT+REG_RO },
{ DRDATA (RPOS5, dz_ldsc[5].rxcnt, 32), PV_LEFT+REG_RO },
{ DRDATA (TPOS5, dz_ldsc[5].txcnt, 32), PV_LEFT+REG_RO },
{ DRDATA (RPOS6, dz_ldsc[6].rxcnt, 32), PV_LEFT+REG_RO },
{ DRDATA (TPOS6, dz_ldsc[6].txcnt, 32), PV_LEFT+REG_RO },
{ DRDATA (RPOS7, dz_ldsc[7].rxcnt, 32), PV_LEFT+REG_RO },
{ DRDATA (TPOS7, dz_ldsc[7].txcnt, 32), PV_LEFT+REG_RO },
{ FLDATA (*DEVENB, dz_enb, 0) },
{ NULL } };
MTAB dz_mod[] = {
{ UNIT_ATT, UNIT_ATT, "line status:", NULL, &dz_status },
{ 0 } };
DEVICE dz_dev = {
"DZ", &dz_unit, dz_reg, dz_mod,
1, 8, 13, 1, 8, 8,
&tmxr_ex, &tmxr_dep, &dz_reset,
NULL, &dz_attach, &dz_detach };
/* IO dispatch routines, I/O addresses 17760100 - 17760107 */
t_stat dz_rd (int32 *data, int32 PA, int32 access)
{
switch ((PA >> 1) & 03) { /* case on PA<2:1> */
case 00: /* CSR */
*data = dz_csr = dz_csr & ~CSR_MBZ;
break;
case 01: /* RBUF */
dz_csr = dz_csr & ~CSR_SA; /* clr silo alarm */
if (dz_csr & CSR_MSE) { /* scanner on? */
dz_rbuf = dz_getchar (&dz_desc); /* get top of silo */
if (!dz_rbuf) dz_sa_enb = 1; /* empty? re-enable */
tmxr_poll_rx (&dz_desc); /* poll input */
dz_update_rcvi (); } /* update rx intr */
else { dz_rbuf = 0; /* no data */
dz_update_rcvi (); } /* no rx intr */
*data = dz_rbuf;
break;
case 02: /* TCR */
*data = dz_tcr;
break;
case 03: /* MSR */
*data = dz_msr;
break; }
return SCPE_OK;
}
t_stat dz_wr (int32 data, int32 PA, int32 access)
{
int32 i, line;
TMLN *lp;
switch ((PA >> 1) & 03) { /* case on PA<2:1> */
case 00: /* CSR */
if (access == WRITEB) data = (PA & 1)?
(dz_csr & 0377) | (data << 8): (dz_csr & ~0377) | data;
if (data & CSR_CLR) dz_clear (FALSE);
if (data & CSR_MSE) sim_activate (&dz_unit, tmxr_poll);
else { sim_cancel (&dz_unit);
dz_csr = dz_csr & ~(CSR_SA | CSR_RDONE | CSR_TRDY); }
if ((data & CSR_RIE) == 0) CLR_INT (DZRX);
else if (((dz_csr & CSR_IE) == 0) && /* RIE 0->1? */
((dz_csr & CSR_SAE)? (dz_csr & CSR_SA): (dz_csr & CSR_RDONE)))
SET_INT (DZRX);
if ((data & CSR_TIE) == 0) CLR_INT (DZTX);
else if (((dz_csr & CSR_TIE) == 0) && (dz_csr & CSR_TRDY))
SET_INT (DZTX);
dz_csr = (dz_csr & ~CSR_RW) | (data & CSR_RW);
break;
case 01: /* LPR */
dz_lpr = data;
line = LPR_GETLN (dz_lpr); /* get line */
lp = dz_desc.ldsc[line]; /* get line desc */
if (dz_lpr & LPR_RCVE) lp -> rcve = 1; /* rcv enb? on */
else lp -> rcve = 0; /* else line off */
tmxr_poll_rx (&dz_desc); /* poll input */
dz_update_rcvi (); /* update rx intr */
break;
case 02: /* TCR */
if (access == WRITEB) data = (PA & 1)?
(dz_tcr & 0377) | (data << 8): (dz_tcr & ~0377) | data;
if (dz_mctl) { /* modem ctl? */
dz_msr = dz_msr | ((data & 0177400) & /* dcd |= dtr & ring */
((dz_msr & DZ_LMASK) << MSR_V_CD));
dz_msr = dz_msr & ~(data >> TCR_V_DTR); /* ring = ring & ~dtr */
if (dz_auto) { /* auto disconnect? */
int32 drop;
drop = (dz_tcr & ~data) >> TCR_V_DTR; /* drop = dtr & ~data */
for (i = 0; i < DZ_LINES; i++) { /* drop hangups */
lp = dz_desc.ldsc[i]; /* get line desc */
if (lp -> conn && (drop & (1 << i))) {
tmxr_msg (lp -> conn, "\r\nLine hangup\r\n");
tmxr_reset_ln (lp); /* reset line, cdet */
dz_msr = dz_msr & ~(1 << (i + MSR_V_CD));
} /* end if drop */
} /* end for */
} /* end if auto */
} /* end if modem */
dz_tcr = data;
tmxr_poll_tx (&dz_desc); /* poll output */
dz_update_xmti (); /* update int */
break;
case 03: /* TDR */
if (PA & 1) { /* odd byte? */
dz_tdr = (dz_tdr & 0377) | (data << 8); /* just save */
break; }
dz_tdr = data;
if (dz_csr & CSR_MSE) { /* enabled? */
line = CSR_GETTL (dz_csr); /* get xmit line */
lp = dz_desc.ldsc[line]; /* get line desc */
tmxr_putc_ln (lp, dz_tdr & 0177); /* store char */
tmxr_poll_tx (&dz_desc); /* poll output */
dz_update_xmti (); } /* update int */
break; }
return SCPE_OK;
}
/* Unit service routine
The DZ11 polls to see if asynchronous activity has occurred and now
needs to be processed. The polling interval is controlled by the clock
simulator, so for most environments, it is calibrated to real time.
Typical polling intervals are 50-60 times per second.
*/
t_stat dz_svc (UNIT *uptr)
{
int32 newln;
if (dz_csr & CSR_MSE) { /* enabled? */
newln = tmxr_poll_conn (&dz_desc, uptr); /* poll connect */
if ((newln >= 0) && dz_mctl) { /* got a live one? */
if (dz_tcr & (1 << (newln + TCR_V_DTR))) /* DTR set? */
dz_msr = dz_msr | (1 << (newln + MSR_V_CD));
else dz_msr = dz_msr | (1 << newln); } /* set ring */
tmxr_poll_rx (&dz_desc); /* poll input */
dz_update_rcvi (); /* upd rcv intr */
tmxr_poll_tx (&dz_desc); /* poll output */
dz_update_xmti (); /* upd xmt intr */
sim_activate (uptr, tmxr_poll); } /* reactivate */
return SCPE_OK;
}
/* Get first available character, if any */
int32 dz_getchar (TMXR *mp)
{
int32 i, val;
for (i = val = 0; (i < mp -> lines) && (val == 0); i++) { /* loop thru lines */
val = tmxr_getc_ln (mp -> ldsc[i]); /* test for input */
if (val) val = val | (i << RBUF_V_RLINE); /* or in line # */
} /* end for */
return val;
}
/* Update receive interrupts */
void dz_update_rcvi (void)
{
int32 i, scnt;
TMLN *lp;
for (i = scnt = 0; i < DZ_LINES; i++) { /* poll lines */
lp = dz_desc.ldsc[i]; /* get line desc */
scnt = scnt + tmxr_rqln (lp); /* sum buffers */
if (dz_mctl && !lp -> conn) /* if disconn */
dz_msr = dz_msr & ~(1 << (i + MSR_V_CD)); /* reset car det */
}
if (scnt && (dz_csr & CSR_MSE)) { /* input & enabled? */
dz_csr = dz_csr | CSR_RDONE; /* set done */
if (dz_sa_enb && (scnt >= DZ_SILO_ALM)) { /* alm enb & cnt hi? */
dz_csr = dz_csr | CSR_SA; /* set status */
dz_sa_enb = 0; } } /* disable alarm */
else dz_csr = dz_csr & ~CSR_RDONE; /* no, clear done */
if ((dz_csr & CSR_RIE) && /* int enable */
((dz_csr & CSR_SAE)? (dz_csr & CSR_SA): (dz_csr & CSR_RDONE)))
SET_INT (DZRX); /* and alm/done? */
else CLR_INT (DZRX); /* no, clear int */
return;
}
/* Update transmit interrupts */
void dz_update_xmti (void)
{
int32 linemask, i, j;
linemask = dz_tcr & DZ_LMASK; /* enabled lines */
dz_csr = dz_csr & ~CSR_TRDY; /* assume not rdy */
for (i = 0, j = CSR_GETTL (dz_csr); i < DZ_LINES; i++) {
j = (j + 1) & DZ_LNOMASK;
if ((linemask & (1 << j)) && dz_desc.ldsc[j] -> xmte) {
CSR_PUTTL (dz_csr, j); /* update CSR */
dz_csr = dz_csr | CSR_TRDY; /* set xmt rdy */
break; } }
if ((dz_csr & CSR_TIE) && (dz_csr & CSR_TRDY)) /* ready plus int? */
SET_INT (DZTX);
else CLR_INT (DZTX); /* no int req */
return;
}
/* Device reset */
t_stat dz_clear (t_bool flag)
{
int32 i;
dz_csr = 0; /* clear CSR */
dz_rbuf = 0; /* silo empty */
dz_lpr = 0; /* no params */
if (flag) dz_tcr = 0; /* INIT? clr all */
else dz_tcr = dz_tcr & ~0377; /* else save dtr */
dz_tdr = 0;
dz_sa_enb = 1;
CLR_INT (DZRX);
CLR_INT (DZTX);
sim_cancel (&dz_unit); /* no polling */
for (i = 0; i < DZ_LINES; i++) {
if (!dz_desc.ldsc[i] -> conn) dz_desc.ldsc[i] -> xmte = 1;
dz_desc.ldsc[i] -> rcve = 0; } /* clr rcv enb */
return SCPE_OK;
}
t_stat dz_reset (DEVICE *dptr)
{
return dz_clear (TRUE);
}
/* Attach */
t_stat dz_attach (UNIT *uptr, char *cptr)
{
t_stat r;
extern int32 sim_switches;
dz_mctl = dz_auto = 0; /* modem ctl off */
r = tmxr_attach (&dz_desc, uptr, cptr); /* attach mux */
if (r != SCPE_OK) return r; /* error? */
if (sim_switches & SWMASK ('M')) { /* modem control? */
dz_mctl = 1;
printf ("Modem control activated\n");
if (sim_log) fprintf (sim_log, "Modem control activated\n");
if (sim_switches & SWMASK ('A')) { /* autodisconnect? */
dz_auto = 1;
printf ("Auto disconnect activated\n");
if (sim_log) fprintf (sim_log, "Auto disconnect activated\n");
}
}
return SCPE_OK;
}
/* Detach */
t_stat dz_detach (UNIT *uptr)
{
return tmxr_detach (&dz_desc, uptr);
}
/* Status */
t_stat dz_status (UNIT *uptr, FILE *st)
{
int32 i;
for (i = 0; (i < DZ_LINES) && (dz_desc.ldsc[i] -> conn == 0); i++) ;
if (i < DZ_LINES) {
for (i = 0; i < DZ_LINES; i++) {
if (dz_desc.ldsc[i] -> conn)
tmxr_fstatus (st, dz_desc.ldsc[i], i); } }
else fprintf (st, " all disconnected");
return SCPE_OK;
}

View file

@ -27,6 +27,8 @@
ptp 316/516-52 paper tape punch
tty 316/516-33 teleprinter
clk/options 316/516-12 real time clocks/internal options
07-Sep-01 RMS Moved function prototypes
*/
#include "h316_defs.h"
@ -54,9 +56,6 @@ t_stat tto_svc (UNIT *uptr);
t_stat tty_reset (DEVICE *dptr);
t_stat clk_svc (UNIT *uptr);
t_stat clk_reset (DEVICE *dptr);
extern t_stat sim_poll_kbd (void);
extern t_stat sim_putchar (int32 out);
extern t_bool hp_setdev (UNIT *uptr, int32 val);
/* PTR data structures

View file

@ -22,6 +22,8 @@
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.
17-Sep-01 RMS Removed multiconsole support
*/
#include "h316_defs.h"
@ -42,7 +44,6 @@ extern int32 sim_switches;
sim_PC pointer to saved PC register descriptor
sim_emax maximum number of words for examine/deposit
sim_devices array of pointers to simulated devices
sim_consoles array of pointers to consoles (if more than one)
sim_stop_messages array of pointers to stop messages
sim_load binary loader
*/
@ -59,8 +60,6 @@ DEVICE *sim_devices[] = { &cpu_dev,
&clk_dev,
NULL };
UNIT *sim_consoles = NULL;
const char *sim_stop_messages[] = {
"Unknown error",
"Unimplemented instruction",

View file

@ -175,3 +175,8 @@ struct hpdev {
#define IOT_V_REASON 16
#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */
/* Function prototypes */
t_bool hp_setdev (UNIT *uptr, int32 val);
t_bool hp_setdev2 (UNIT *uptr, int32 val);

View file

@ -25,6 +25,7 @@
dp 12557A cartridge disk system
07-Sep-01 RMS Moved function prototypes
29-Nov-00 RMS Made variable names unique
21-Nov-00 RMS Fixed flag, buffer power up state
*/
@ -125,7 +126,6 @@ t_stat dpc_detach (UNIT *uptr);
t_stat dpd_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
t_stat dpd_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
void dp_go (int32 fnc, int32 drv, int32 time, int32 attdev);
extern t_bool hp_setdev2 (UNIT *uptr, int32 val);
/* DPD data structures

View file

@ -25,6 +25,7 @@
lpt 12653A line printer
07-Sep-01 RMS Moved function prototypes
21-Nov-00 RMS Fixed flag, fbf power up state
Added command flop
15-Oct-00 RMS Added variable device number support
@ -42,7 +43,6 @@ int32 lpt_stopioe = 0; /* stop on error */
t_stat lpt_svc (UNIT *uptr);
t_stat lpt_reset (DEVICE *dptr);
extern struct hpdev infotab[];
extern t_bool hp_setdev (UNIT *uptr, int32 val);
/* LPT data structures

View file

@ -25,6 +25,7 @@
mt 12559A nine track magnetic tape
07-Sep-01 RMS Moved function prototypes
30-Nov-00 RMS Made variable names unique
04-Oct-98 RMS V2.4 magtape format
@ -101,7 +102,6 @@ t_stat mtc_attach (UNIT *uptr, char *cptr);
t_stat mtc_detach (UNIT *uptr);
t_stat mtd_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
t_stat mtd_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
extern t_bool hp_setdev2 (UNIT *uptr, int32 val);
/* MTD data structures

View file

@ -28,6 +28,7 @@
tty 12531C buffered teleprinter interface
clk 12539A/B/C time base generator
07-Sep-01 RMS Moved function prototypes
21-Nov-00 RMS Fixed flag, buffer power up state
Added status input for ptp, tty
15-Oct-00 RMS Added dynamic device number support
@ -71,9 +72,6 @@ t_stat tto_svc (UNIT *uptr);
t_stat tty_reset (DEVICE *dptr);
t_stat clk_svc (UNIT *uptr);
t_stat clk_reset (DEVICE *dptr);
extern t_stat sim_poll_kbd (void);
extern t_stat sim_putchar (int32 out);
extern t_bool hp_setdev (UNIT *uptr, int32 val);
/* PTR data structures

View file

@ -23,6 +23,7 @@
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.
17-Sep-01 RMS Removed multiconsole support
27-May-01 RMS Added multiconsole support
14-Mar-01 RMS Revised load/dump interface (again)
30-Oct-00 RMS Added examine to file support
@ -49,7 +50,6 @@ extern uint16 M[];
sim_PC pointer to saved PC register descriptor
sim_emax maximum number of words for examine/deposit
sim_devices array of pointers to simulated devices
sim_consoles array of pointers to consoles (if more than one)
sim_stop_messages array of pointers to stop messages
sim_load binary loader
*/
@ -69,8 +69,6 @@ DEVICE *sim_devices[] = { &cpu_dev,
&dpd_dev, &dpc_dev,
NULL };
UNIT *sim_consoles = NULL;
const char *sim_stop_messages[] = {
"Unknown error",
"Unimplemented instruction",

View file

@ -23,6 +23,7 @@
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.
07-Sep-01 RMS Moved function prototypes
14-Apr-99 RMS Changed t_addr to unsigned
*/
@ -38,8 +39,6 @@ int32 inq_char = 033; /* request inq */
t_stat inq_svc (UNIT *uptr);
t_stat inq_reset (DEVICE *dptr);
void puts_tty (char *cptr);
extern t_stat sim_poll_kbd (void);
extern t_stat sim_putchar (int32 out);
/* INQ data structures

View file

@ -23,6 +23,7 @@
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.
17-Sep-01 RMS Removed multiconsole support
13-Jul-01 RMS Fixed bug in symbolic output (found by Peter Schorn)
27-May-01 RMS Added multiconsole support
14-Mar-01 RMS Revised load/dump interface (again)
@ -52,7 +53,6 @@ extern int32 store_addr_u (int32 addr);
sim_PC pointer to saved PC register descriptor
sim_emax maximum number of words for examine/deposit
sim_devices array of pointers to simulated devices
sim_consoles array of pointers to consoles (if more than one)
sim_stop_messages array of pointers to stop messages
sim_load binary loader
*/
@ -67,8 +67,6 @@ DEVICE *sim_devices[] = { &cpu_dev, &inq_dev,
&cdr_dev, &cdp_dev, &stack_dev, &lpt_dev,
&mt_dev, NULL };
UNIT *sim_consoles = NULL;
const char *sim_stop_messages[] = {
"Unknown error",
"Unimplemented instruction",

View file

@ -23,6 +23,7 @@
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.
17-Sep-01 RMS Removed multiconsole support
17-Jul-01 RMS Fixed warning from VC++ 6.0
27-May-01 RMS Added multiconsole support
14-Mar-01 RMS Revised load/dump interface (again)
@ -46,7 +47,6 @@ extern int32 saved_PC;
sim_PC pointer to saved PC register descriptor
sim_emax number of words for examine
sim_devices array of pointers to simulated devices
sim_consoles array of pointers to consoles (if more than one)
sim_stop_messages array of pointers to stop messages
sim_load binary loader
*/
@ -61,8 +61,6 @@ DEVICE *sim_devices[] = { &cpu_dev,
&pt_dev, &tt_dev,
NULL };
UNIT *sim_consoles = NULL;
const char *sim_stop_messages[] = {
"Unknown error",
"Reserved instruction",

View file

@ -25,6 +25,7 @@
clk real-time clock
17-Sep-01 RMS Added terminal multiplexor support
17-Mar-01 RMS Moved function prototype
05-Mar-01 RMS Added clock calibration
24-Sep-97 RMS Fixed bug in unit service (found by Charles Owen)
@ -36,6 +37,8 @@ extern int32 int_req, dev_busy, dev_done, dev_disable;
int32 clk_sel = 0; /* selected freq */
int32 clk_time[4] = { 16000, 100000, 10000, 1000 }; /* freq table */
int32 clk_tps[4] = { 60, 10, 100, 1000 }; /* ticks per sec */
int32 clk_adj[4] = { 1, -5, 2, 20 }; /* tmxr adjust */
int32 tmxr_poll = 16000; /* tmxr poll */
t_stat clk_svc (UNIT *uptr);
t_stat clk_reset (DEVICE *dptr);
@ -95,11 +98,16 @@ return 0;
t_stat clk_svc (UNIT *uptr)
{
int32 t;
dev_done = dev_done | INT_CLK; /* set done */
dev_busy = dev_busy & ~INT_CLK; /* clear busy */
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
sim_activate (&clk_unit, /* reactivate unit */
sim_rtc_calb (clk_tps[clk_sel])); /* calibrate delay */
t = sim_rtc_calb (clk_tps[clk_sel]); /* calibrate delay */
sim_activate (&clk_unit, t); /* reactivate unit */
if (clk_adj[clk_sel] > 0) /* clk >= 60Hz? */
tmxr_poll = t * clk_adj[clk_sel]; /* poll is longer */
else tmxr_poll = t / (-clk_adj[clk_sel]); /* poll is shorter */
return SCPE_OK;
}
@ -112,5 +120,6 @@ dev_busy = dev_busy & ~INT_CLK; /* clear busy */
dev_done = dev_done & ~INT_CLK; /* clear done, int */
int_req = int_req & ~INT_CLK;
sim_cancel (&clk_unit); /* deactivate unit */
tmxr_poll = clk_time[0]; /* poll is default */
return SCPE_OK;
}

View file

@ -23,6 +23,7 @@
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.
17-Sep-01 RMS Removed multiconsole support
31-May-01 RMS Added multiconsole support
14-Mar-01 RMS Revised load/dump interface (again)
22-Dec-00 RMS Added second terminal support
@ -62,7 +63,6 @@ extern int32 saved_PC;
sim_PC pointer to saved PC register descriptor
sim_emax number of words needed for examine
sim_devices array of pointers to simulated devices
sim_consoles array of pointers to consoles (if more than one)
sim_stop_messages array of pointers to stop messages
sim_load binary loader
*/
@ -90,11 +90,6 @@ DEVICE *sim_devices[] = {
&dkp_dev, &mta_dev,
NULL };
UNIT *sim_consoles[] = {
&tti_unit, &tto_unit,
&tti1_unit, &tto1_unit,
NULL };
const char *sim_stop_messages[] = {
"Unknown error",
"Unknown I/O instruction",

View file

@ -26,6 +26,8 @@
tti terminal input
tto terminal output
17-Sep-01 RMS Removed multiconsole support
07-Sep-01 RMS Moved function prototypes
31-May-01 RMS Added multiconsole support
*/
@ -39,9 +41,6 @@ t_stat tto_svc (UNIT *uptr);
t_stat tti_reset (DEVICE *dptr);
t_stat tto_reset (DEVICE *dptr);
t_stat ttx_setmod (UNIT *uptr, int32 value);
extern t_stat sim_poll_kbd (void);
extern t_stat sim_putchar (int32 out);
static uint8 tto_consout[CONS_SIZE];
/* TTI data structures
@ -51,7 +50,7 @@ static uint8 tto_consout[CONS_SIZE];
ttx_mod TTI/TTO modifiers list
*/
UNIT tti_unit = { UDATA (&tti_svc, UNIT_CONS, 0), KBD_POLL_WAIT };
UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT };
REG tti_reg[] = {
{ ORDATA (BUF, tti_unit.buf, 8) },
@ -62,12 +61,9 @@ REG tti_reg[] = {
{ DRDATA (POS, tti_unit.pos, 31), PV_LEFT },
{ DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT },
{ FLDATA (MODE, tti_unit.flags, UNIT_V_DASHER), REG_HRO },
{ FLDATA (CFLAG, tti_unit.flags, UNIT_V_CONS), REG_HRO },
{ NULL } };
MTAB ttx_mod[] = {
{ UNIT_CONS, 0, "inactive", NULL, NULL },
{ UNIT_CONS, UNIT_CONS, "active console", "CONSOLE", &set_console },
{ UNIT_DASHER, 0, "ANSI", "ANSI", &ttx_setmod },
{ UNIT_DASHER, UNIT_DASHER, "Dasher", "DASHER", &ttx_setmod },
{ 0 } };
@ -85,7 +81,7 @@ DEVICE tti_dev = {
tto_reg TTO register list
*/
UNIT tto_unit = { UDATA (&tto_svc, UNIT_CONS, 0), SERIAL_OUT_WAIT };
UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT };
REG tto_reg[] = {
{ ORDATA (BUF, tto_unit.buf, 8) },
@ -96,8 +92,6 @@ REG tto_reg[] = {
{ DRDATA (POS, tto_unit.pos, 31), PV_LEFT },
{ DRDATA (TIME, tto_unit.wait, 24), PV_LEFT },
{ FLDATA (MODE, tto_unit.flags, UNIT_V_DASHER), REG_HRO },
{ BRDATA (CONSOUT, tto_consout, 8, 8, CONS_SIZE), REG_HIDDEN },
{ FLDATA (CFLAG, tto_unit.flags, UNIT_V_CONS), REG_HRO },
{ NULL } };
DEVICE tto_dev = {
@ -153,8 +147,7 @@ tti_unit.buf = 0;
dev_busy = dev_busy & ~INT_TTI; /* clear busy */
dev_done = dev_done & ~INT_TTI; /* clear done, int */
int_req = int_req & ~INT_TTI;
if (tti_unit.flags & UNIT_CONS) /* if active console, */
sim_activate (&tti_unit, tti_unit.wait); /* activate unit */
sim_activate (&tti_unit, tti_unit.wait); /* activate unit */
return SCPE_OK;
}
@ -190,7 +183,7 @@ dev_done = dev_done | INT_TTO; /* set done */
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
c = tto_unit.buf & 0177;
if ((tto_unit.flags & UNIT_DASHER) && (c == 031)) c = '\b';
if ((temp = sim_putcons (c, uptr)) != SCPE_OK) return temp;
if ((temp = sim_putchar (c)) != SCPE_OK) return temp;
tto_unit.pos = tto_unit.pos + 1;
return SCPE_OK;
}
@ -204,7 +197,6 @@ dev_busy = dev_busy & ~INT_TTO; /* clear busy */
dev_done = dev_done & ~INT_TTO; /* clear done, int */
int_req = int_req & ~INT_TTO;
sim_cancel (&tto_unit); /* deactivate unit */
tto_unit.filebuf = tto_consout; /* set buf pointer */
return SCPE_OK;
}

View file

@ -27,23 +27,32 @@
tti1 second terminal input
tto1 second terminal output
17-Sep-01 RMS Changed to use terminal multiplexor library
07-Sep-01 RMS Moved function prototypes
31-May-01 RMS Added multiconsole support
26-Apr-01 RMS Added device enable/disable support
*/
#include "nova_defs.h"
#include "sim_sock.h"
#include "sim_tmxr.h"
#define UNIT_V_DASHER (UNIT_V_UF + 0) /* Dasher mode */
#define UNIT_DASHER (1 << UNIT_V_DASHER)
extern int32 int_req, dev_busy, dev_done, dev_disable, iot_enb;
extern int32 tmxr_poll; /* calibrated poll */
TMLN tt1_ldsc = { 0 }; /* line descriptors */
TMXR tt_desc = { 1, 0, &tt1_ldsc }; /* mux descriptor */
t_stat tti1_svc (UNIT *uptr);
t_stat tto1_svc (UNIT *uptr);
t_stat tti1_reset (DEVICE *dptr);
t_stat tto1_reset (DEVICE *dptr);
t_stat ttx1_setmod (UNIT *uptr, int32 value);
extern t_stat sim_poll_kbd (void);
static uint8 tto1_consout[CONS_SIZE];
t_stat tti1_attach (UNIT *uptr, char *cptr);
t_stat tti1_detach (UNIT *uptr);
t_stat tti1_status (UNIT *uptr, FILE *st);
/* TTI1 data structures
@ -53,7 +62,7 @@ static uint8 tto1_consout[CONS_SIZE];
ttx1_mod TTI1/TTO1 modifiers list
*/
UNIT tti1_unit = { UDATA (&tti1_svc, 0, 0), KBD_POLL_WAIT };
UNIT tti1_unit = { UDATA (&tti1_svc, UNIT_ATTABLE, 0), KBD_POLL_WAIT };
REG tti1_reg[] = {
{ ORDATA (BUF, tti1_unit.buf, 8) },
@ -61,16 +70,14 @@ REG tti1_reg[] = {
{ FLDATA (DONE, dev_done, INT_V_TTI1) },
{ FLDATA (DISABLE, dev_disable, INT_V_TTI1) },
{ FLDATA (INT, int_req, INT_V_TTI1) },
{ DRDATA (POS, tti1_unit.pos, 31), PV_LEFT },
{ DRDATA (POS, tt1_ldsc.rxcnt, 31), PV_LEFT },
{ DRDATA (TIME, tti1_unit.wait, 24), REG_NZ + PV_LEFT },
{ FLDATA (MODE, tti1_unit.flags, UNIT_V_DASHER), REG_HRO },
{ FLDATA (CFLAG, tti1_unit.flags, UNIT_V_CONS), REG_HRO },
{ FLDATA (*DEVENB, iot_enb, INT_V_TTI1), REG_HRO },
{ NULL } };
MTAB ttx1_mod[] = {
{ UNIT_CONS, 0, "inactive", NULL, NULL },
{ UNIT_CONS, UNIT_CONS, "active console", "CONSOLE", &set_console },
{ UNIT_ATT, UNIT_ATT, "line status:", NULL, &tti1_status },
{ UNIT_DASHER, 0, "ANSI", "ANSI", &ttx1_setmod },
{ UNIT_DASHER, UNIT_DASHER, "Dasher", "DASHER", &ttx1_setmod },
{ 0 } };
@ -78,8 +85,8 @@ MTAB ttx1_mod[] = {
DEVICE tti1_dev = {
"TTI1", &tti1_unit, tti1_reg, ttx1_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &tti1_reset,
NULL, NULL, NULL };
&tmxr_ex, &tmxr_dep, &tti1_reset,
NULL, &tti1_attach, &tti1_detach };
/* TTO1 data structures
@ -96,11 +103,9 @@ REG tto1_reg[] = {
{ FLDATA (DONE, dev_done, INT_V_TTO1) },
{ FLDATA (DISABLE, dev_disable, INT_V_TTO1) },
{ FLDATA (INT, int_req, INT_V_TTO1) },
{ DRDATA (POS, tto1_unit.pos, 31), PV_LEFT },
{ DRDATA (POS, tt1_ldsc.txcnt, 31), PV_LEFT },
{ DRDATA (TIME, tto1_unit.wait, 24), PV_LEFT },
{ FLDATA (MODE, tto1_unit.flags, UNIT_V_DASHER), REG_HRO },
{ BRDATA (CONSOUT, tto1_consout, 8, 8, CONS_SIZE), REG_HIDDEN },
{ FLDATA (CFLAG, tto1_unit.flags, UNIT_V_CONS), REG_HRO },
{ FLDATA (*DEVENB, iot_enb, INT_V_TTI1), REG_HRO },
{ NULL } };
@ -135,17 +140,25 @@ return iodata;
t_stat tti1_svc (UNIT *uptr)
{
int32 temp;
int32 temp, newln;
sim_activate (&tti1_unit, tti1_unit.wait); /* continue poll */
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */
tti1_unit.buf = temp & 0177;
if ((tti1_unit.flags & UNIT_DASHER) && (tti1_unit.buf == '\r'))
tti1_unit.buf = '\n'; /* Dasher: cr -> nl */
dev_busy = dev_busy & ~INT_TTI1; /* clear busy */
dev_done = dev_done | INT_TTI1; /* set done */
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
tti1_unit.pos = tti1_unit.pos + 1;
if (tt1_ldsc.conn) { /* connected? */
tmxr_poll_rx (&tt_desc); /* poll for input */
if (temp = tmxr_getc_ln (&tt1_ldsc)) { /* get char */
uptr -> buf = temp & 0177;
if ((uptr -> flags & UNIT_DASHER) &&
(uptr -> buf == '\r'))
uptr -> buf = '\n'; /* Dasher: cr -> nl */
dev_busy = dev_busy & ~INT_TTI1; /* clear busy */
dev_done = dev_done | INT_TTI1; /* set done */
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); }
sim_activate (uptr, uptr -> wait); } /* continue poll */
if (uptr -> flags & UNIT_ATT) { /* attached? */
newln = tmxr_poll_conn (&tt_desc, uptr); /* poll connect */
if (newln >= 0) { /* got one? */
sim_activate (&tti1_unit, tti1_unit.wait);
tt1_ldsc.rcve = 1; } /* rcv enabled */
sim_activate (uptr, tmxr_poll); } /* sched poll */
return SCPE_OK;
}
@ -157,8 +170,12 @@ tti1_unit.buf = 0;
dev_busy = dev_busy & ~INT_TTI1; /* clear busy */
dev_done = dev_done & ~INT_TTI1; /* clear done, int */
int_req = int_req & ~INT_TTI1;
if (tti1_unit.flags & UNIT_CONS) /* active console? */
sim_activate (&tti1_unit, tti1_unit.wait);
if (tt1_ldsc.conn) { /* if conn, */
sim_activate (&tti1_unit, tti1_unit.wait); /* activate, */
tt1_ldsc.rcve = 1; } /* enable */
else if (tti1_unit.flags & UNIT_ATT) /* if attached, */
sim_activate (&tti1_unit, tmxr_poll); /* activate */
else sim_cancel (&tti1_unit); /* else stop */
return SCPE_OK;
}
@ -187,15 +204,20 @@ return 0;
t_stat tto1_svc (UNIT *uptr)
{
int32 c, temp;
int32 c;
dev_busy = dev_busy & ~INT_TTO1; /* clear busy */
dev_done = dev_done | INT_TTO1; /* set done */
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
c = tto1_unit.buf & 0177;
if ((tto1_unit.flags & UNIT_DASHER) && (c == 031)) c = '\b';
if ((temp = sim_putcons (c, uptr)) != SCPE_OK) return temp;
tto1_unit.pos = tto1_unit.pos + 1;
if (tt1_ldsc.conn) { /* connected? */
if (tt1_ldsc.xmte) { /* tx enabled? */
tmxr_putc_ln (&tt1_ldsc, c); /* output char */
tmxr_poll_tx (&tt_desc); } /* poll xmt */
else { tmxr_poll_tx (&tt_desc); /* poll xmt */
sim_activate (&tto1_unit, tmxr_poll); /* wait */
return SCPE_OK; } }
return SCPE_OK;
}
@ -208,7 +230,6 @@ dev_busy = dev_busy & ~INT_TTO1; /* clear busy */
dev_done = dev_done & ~INT_TTO1; /* clear done, int */
int_req = int_req & ~INT_TTO1;
sim_cancel (&tto1_unit); /* deactivate unit */
tto1_unit.filebuf = tto1_consout; /* set buf pointer */
return SCPE_OK;
}
@ -218,3 +239,35 @@ tti1_unit.flags = (tti1_unit.flags & ~UNIT_DASHER) | value;
tto1_unit.flags = (tto1_unit.flags & ~UNIT_DASHER) | value;
return SCPE_OK;
}
/* Attach routine */
t_stat tti1_attach (UNIT *uptr, char *cptr)
{
t_stat r;
r = tmxr_attach (&tt_desc, uptr, cptr); /* attach */
if (r != SCPE_OK) return r; /* error */
sim_activate (uptr, tmxr_poll); /* start poll */
return SCPE_OK;
}
/* Detach routine */
t_stat tti1_detach (UNIT *uptr)
{
t_stat r;
r = tmxr_detach (&tt_desc, uptr); /* detach */
tt1_ldsc.rcve = 0; /* disable rcv */
sim_cancel (uptr); /* stop poll */
return r;
}
/* Status routine */
t_stat tti1_status (UNIT *uptr, FILE *st)
{
tmxr_fstatus (st, &tt1_ldsc, -1);
return SCPE_OK;
}

View file

@ -25,6 +25,7 @@
cpu KS10 central processor
31-Aug-01 RMS Changed int64 to t_int64 for Windoze
10-Aug-01 RMS Removed register in declarations
17-Jul-01 RMS Moved function prototype
19-May-01 RMS Added workaround for TOPS-20 V4.1 boot bug
@ -531,7 +532,7 @@ void ashc (int32 ac, a10 ea);
void circ (int32 ac, a10 ea);
void blt (int32 ac, a10 ea, int32 pflgs);
void bltu (int32 ac, a10 ea, int32 pflgs, int dir);
a10 calc_ea (int64 inst, int32 prv);
a10 calc_ea (d10 inst, int32 prv);
a10 calc_ioea (d10 inst, int32 prv);
d10 calc_jrstfea (d10 inst, int32 pflgs);
void pi_dismiss (void);

View file

@ -23,6 +23,11 @@
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.
23-Oct-01 RMS New IO page address constants
19-Oct-01 RMS Added DZ definitions
07-Sep-01 RMS Revised for PDP-11 multi-level interrupts
31-Aug-01 RMS Changed int64 to t_int64 for Windoze
29-Aug-01 RMS Corrected models and dates (found by Lars Brinkhoff)
01-Jun-01 RMS Updated DZ11 vector definitions
19-May-01 RMS Added workaround for TOPS-20 V4.1 boot bug
*/
@ -35,9 +40,9 @@
PDP-6 0.25 Original 36b implementation, 1964
KA10 0.38 First PDP-10, flip chips, 1967
KI10 0.72 First paging system, flip chip + MSI, 1969
KL10 1.8 First ECL system, ECL 10K, 1972
KL10X 1.8 Expanded addressing, ECL 10K, 1975
KI10 0.72 First paging system, flip chip + MSI, 1972
KL10 1.8 First ECL system, ECL 10K, 1975
KL10B 1.8 Expanded addressing, ECL 10K, 1978
KS10 0.3 Last 36b system, 2901 based, 1979
In addition, it ran four major (incompatible) operating systems:
@ -69,8 +74,8 @@
/* Data types */
typedef int32 a10; /* PDP-10 addr (30b) */
typedef int64 d10; /* PDP-10 data (36b) */
typedef int32 a10; /* PDP-10 addr (30b) */
typedef t_int64 d10; /* PDP-10 data (36b) */
/* Abort codes, used to sort out longjmp's back to the main loop
Codes > 0 are simulator stop codes
@ -162,7 +167,7 @@ typedef int64 d10; /* PDP-10 data (36b) */
#define BP_S 0007700000000
#define GET_P(x) ((int32) (((x) >> BP_V_P) & BP_M_P))
#define GET_S(x) ((int32) (((x) >> BP_V_S) & BP_M_S))
#define PUT_P(b,x) (((b) & ~BP_P) | ((((int64) (x)) & BP_M_P) << BP_V_P))
#define PUT_P(b,x) (((b) & ~BP_P) | ((((t_int64) (x)) & BP_M_P) << BP_V_P))
/* Flags (stored in their own halfword) */
@ -567,17 +572,31 @@ typedef int64 d10; /* PDP-10 data (36b) */
#define IO_UBA3 (3 << IO_V_UBA)
#define GET_IOUBA(x) (((x) >> IO_V_UBA) & IO_M_UBA)
/* DZ11 parameters */
#define DZ_MUXES 1 /* # of muxes */
#define DZ_LINES 8 /* lines per mux */
/* I/O page layout */
#define IO_DZBASE 0760010 /* DZ11 base */
#define IO_TCUBASE 0760770 /* TCU150 base */
#define IO_UBMAP 0763000 /* Unibus map base */
#define IO_UBCS 0763100 /* Unibus c/s reg */
#define IO_UBMNT 0763101 /* Unibus maint reg */
#define IO_TMBASE 0772440 /* RH11/tape base */
#define IO_RHBASE 0776700 /* RH11/disk base */
#define IO_LPBASE 0775400 /* LP20 base */
#define IO_PTBASE 0777550 /* PC11 base */
#define IOBA_DZ 0760010 /* DZ11 */
#define IOLN_DZ (010 * DZ_MUXES)
#define IOBA_TCU 0760770 /* TCU150 */
#define IOLN_TCU 006
#define IOBA_UBMAP 0763000 /* Unibus map */
#define IOLN_UBMAP 0100
#define IOBA_UBCS 0763100 /* Unibus c/s reg */
#define IOLN_UBCS 001
#define IOBA_UBMNT 0763101 /* Unibus maint reg */
#define IOLN_UBMNT 001
#define IOBA_TU 0772440 /* RH11/tape */
#define IOLN_TU 034
#define IOBA_RP 0776700 /* RH11/disk */
#define IOLN_RP 050
#define IOBA_LP20 0775400 /* LP20 */
#define IOLN_LP20 020
#define IOBA_PT 0777550 /* PC11 */
#define IOLN_PT 010
/* Common Unibus CSR flags */
@ -603,20 +622,28 @@ typedef int64 d10; /* PDP-10 data (36b) */
#define INT_V_RP 6 /* RH11/RP,RM drives */
#define INT_V_TU 7 /* RH11/TM03/TU45 */
#define INT_V_DZ0RX 16 /* DZ11 */
#define INT_V_DZ0TX 17
#define INT_V_DZRX 16 /* DZ11 */
#define INT_V_DZTX 17
#define INT_V_PTR 24 /* PC11 */
#define INT_V_PTP 25
#define INT_V_LP20 26 /* LPT20 */
#define INT_RP (1u << INT_V_RP)
#define INT_TU (1u << INT_V_TU)
#define INT_DZ0RX (1u << INT_V_DZ0RX)
#define INT_DZ0TX (1u << INT_V_DZ0TX)
#define INT_DZRX (1u << INT_V_DZRX)
#define INT_DZTX (1u << INT_V_DZTX)
#define INT_PTR (1u << INT_V_PTR)
#define INT_PTP (1u << INT_V_PTP)
#define INT_LP20 (1u << INT_V_LP20)
#define IPL_RP 6 /* int levels */
#define IPL_TU 6
#define IPL_DZRX 5
#define IPL_DZTX 5
#define IPL_PTR 4
#define IPL_PTP 4
#define IPL_LP20 4
#define INT_UB1 INT_RP /* on Unibus 1 */
#define INT_UB3 (0xFFFFFFFFu & ~INT_UB1) /* on Unibus 3 */
@ -629,6 +656,10 @@ typedef int64 d10; /* PDP-10 data (36b) */
#define VEC_PTP 0074
#define VEC_TU 0224
#define VEC_RP 0254
#define VEC_DZ0RX 0340
#define VEC_DZ0TX 0344
#define VEC_DZRX 0340
#define VEC_DZTX 0344
#define VEC_LP20 0754
#define IREQ(dv) int_req
#define SET_INT(dv) IREQ(dv) = IREQ(dv) | (INT_##dv)
#define CLR_INT(dv) IREQ(dv) = IREQ(dv) & ~(INT_##dv)

View file

@ -1,6 +1,6 @@
/* pdp10_dz_stub.c: DZ11 terminal multiplexor simulator stub
/* pdp10_dz.c: DZ11 terminal multiplexor simulator
Copyright (c) 2001, Robert M Supnik
Copyright (c) 1993-2001, 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,168 +23,8 @@
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.
dz DZ11 terminal multiplexor (stub)
This version of the DZ11 is a stub to allow operating systems to play
with the device registers. It is required for ITS, and not harmful to
TOPS-10 or TOPS-20.
dz DZ11 terminal multiplexor
*/
#include "pdp10_defs.h"
#define DZ_LINES 8 /* lines per DZ11 */
#define DZ_LMASK (DZ_LINES - 1)
#define DZ_SILO_ALM 16 /* silo alarm level */
#define MAXBUF 128 /* buffer size */
/* DZCSR - 160100 - control/status register */
#define CSR_MAINT 0000010 /* maint - NI */
#define CSR_CLR 0000020 /* clear */
#define CSR_MSE 0000040 /* master scan enb */
#define CSR_RIE 0000100 /* rcv int enb */
#define CSR_RDONE 0000200 /* rcv done - RO */
#define CSR_V_TLINE 8 /* xmit line - RO */
#define CSR_TLINE (DZ_LMASK << CSR_V_TLINE)
#define CSR_SAE 0010000 /* silo alm enb */
#define CSR_SA 0020000 /* silo alm - RO */
#define CSR_TIE 0040000 /* xmit int enb */
#define CSR_TRDY 0100000 /* xmit rdy - RO */
#define CSR_RW (CSR_MSE | CSR_RIE | CSR_SAE | CSR_TIE)
#define CSR_MBZ (0004003 | CSR_CLR | CSR_MAINT)
#define CSR_GETTL(x) (((x) >> CSR_V_TLINE) & DZ_LMASK)
#define CSR_PUTTL(x,y) x = ((x) & ~CSR_TLINE) | (((y) & DZ_LMASK) << CSR_V_TLINE)
/* DZRBUF - 160102 - receive buffer, read only */
#define RBUF_CHAR 0000377 /* rcv char */
#define RBUF_V_RLINE 8 /* rcv line */
#define RBUF_PARE 0010000 /* parity err - NI */
#define RBUF_FRME 0020000 /* frame err - NI */
#define RBUF_OVRE 0040000 /* overrun err - NI */
#define RBUF_VALID 0100000 /* rcv valid */
#define RBUF_MBZ 0004000
/* DZLPR - 160102 - line parameter register, write only, word access only */
#define LPR_V_LINE 0 /* line */
#define LPR_LPAR 0007770 /* line pars - NI */
#define LPR_RCVE 0010000 /* receive enb */
#define LPR_GETLN(x) (((x) >> LPR_V_LINE) & DZ_LMASK)
/* DZTCR - 160104 - transmission control register */
#define TCR_V_XMTE 0 /* xmit enables */
#define TCR_V_DTR 7 /* DTRs */
/* DZMSR - 160106 - modem status register, read only */
#define MSR_V_RI 0 /* ring indicators */
#define MSR_V_CD 7 /* carrier detect */
/* DZTDR - 160106 - transmit data, write only */
#define TDR_CHAR 0000377 /* xmit char */
#define TDR_V_TBR 7 /* xmit break - NI */
extern int32 int_req, dev_enb;
int32 dz_csr = 0; /* csr */
int32 dz_rbuf = 0; /* rcv buffer */
int32 dz_lpr = 0; /* line param */
int32 dz_tcr = 0; /* xmit control */
int32 dz_msr = 0; /* modem status */
int32 dz_tdr = 0; /* xmit data */
int32 dz_mctl = 0; /* modem ctrl enab */
int32 dz_sa_enb = 1; /* silo alarm enabled */
t_stat dz_reset (DEVICE *dptr);
t_stat dz_clear (t_bool flag);
/* DZ data structures
dz_dev DZ device descriptor
dz_unit DZ unit list
dz_reg DZ register list
*/
UNIT dz_unit = { UDATA (NULL, 0, 0) };
REG dz_reg[] = {
{ ORDATA (CSR, dz_csr, 16) },
{ ORDATA (RBUF, dz_rbuf, 16) },
{ ORDATA (LPR, dz_lpr, 16) },
{ ORDATA (TCR, dz_tcr, 16) },
{ ORDATA (MSR, dz_msr, 16) },
{ ORDATA (TDR, dz_tdr, 16) },
{ FLDATA (MDMCTL, dz_mctl, 0) },
{ FLDATA (SAENB, dz_sa_enb, 0) },
{ FLDATA (*DEVENB, dev_enb, INT_V_DZ0RX), REG_HRO },
{ NULL } };
DEVICE dz_dev = {
"DZ", &dz_unit, dz_reg, NULL,
1, 8, 13, 1, 8, 8,
NULL, NULL, &dz_reset,
NULL, NULL, NULL };
/* IO dispatch routines, I/O addresses 17760100 - 17760107 */
t_stat dz0_rd (int32 *data, int32 PA, int32 access)
{
switch ((PA >> 1) & 03) { /* case on PA<2:1> */
case 00: /* CSR */
*data = dz_csr = dz_csr & ~CSR_MBZ;
break;
case 01: /* RBUF */
dz_csr = dz_csr & ~CSR_SA; /* clr silo alarm */
*data = dz_rbuf;
break;
case 02: /* TCR */
*data = dz_tcr;
break;
case 03: /* MSR */
*data = dz_msr;
break; }
return SCPE_OK;
}
t_stat dz0_wr (int32 data, int32 PA, int32 access)
{
switch ((PA >> 1) & 03) { /* case on PA<2:1> */
case 00: /* CSR */
if (access == WRITEB) data = (PA & 1)?
(dz_csr & 0377) | (data << 8): (dz_csr & ~0377) | data;
dz_csr = (dz_csr & ~CSR_RW) | (data & CSR_RW);
break;
case 01: /* LPR */
dz_lpr = data;
break;
case 02: /* TCR */
if (access == WRITEB) data = (PA & 1)?
(dz_tcr & 0377) | (data << 8): (dz_tcr & ~0377) | data;
dz_tcr = data;
break;
case 03: /* TDR */
if (PA & 1) { /* odd byte? */
dz_tdr = (dz_tdr & 0377) | (data << 8); /* just save */
break; }
dz_tdr = data;
break; }
return SCPE_OK;
}
/* Device reset */
t_stat dz_reset (DEVICE *dptr)
{
dz_csr = 0; /* clear CSR */
dz_rbuf = 0; /* silo empty */
dz_lpr = 0; /* no params */
dz_tcr = 0; /* clr all */
dz_tdr = 0;
dz_sa_enb = 1;
int_req = int_req & ~(INT_DZ0RX | INT_DZ0TX); /* clear int */
sim_cancel (&dz_unit); /* no polling */
return SCPE_OK;
}
#include "dec_dz.h"

View file

@ -24,6 +24,9 @@
in this Software without prior written authorization from Robert M Supnik.
fe KS10 console front end
23-Oct-01 RMS New IO page address constants
07-Sep-01 RMS Moved function prototypes
*/
#include "pdp10_defs.h"
@ -36,8 +39,6 @@ t_stat feo_svc (UNIT *uptr);
t_stat fe_reset (DEVICE *dptr);
t_stat fe_stop_os (UNIT *uptr, int32 val);
t_stat fe_ctrl_c (UNIT *uptr, int32 val);
extern t_stat sim_poll_kbd (void);
extern t_stat sim_putchar (int32 out);
/* FE data structures
@ -147,7 +148,7 @@ return SCPE_OK;
t_stat fe_stop_os (UNIT *uptr, int32 val)
{
M[FE_SWITCH] = IO_RHBASE; /* tell OS to stop */
M[FE_SWITCH] = IOBA_RP; /* tell OS to stop */
return SCPE_OK;
}
@ -159,4 +160,4 @@ fei_unit.buf = 003; /* control-C */
M[FE_CTYIN] = fei_unit.buf | FE_CVALID; /* put char in mem */
apr_flg = apr_flg | APRF_CON; /* interrupt KS10 */
return SCPE_OK;
}
}

View file

@ -25,6 +25,8 @@
uba Unibus adapters
23-Sep-01 RMS New IO page address constants
07-Sep-01 RMS Revised device disable mechanism
25-Aug-01 RMS Enabled DZ11
21-Aug-01 RMS Updated DZ11 disable
01-Jun-01 RMS Updated DZ11 vectors
@ -77,7 +79,6 @@
int32 ubcs[UBANUM] = { 0 }; /* status registers */
int32 ubmap[UBANUM][UMAP_MEMSIZE] = { 0 }; /* Unibus maps */
int32 int_req = 0; /* interrupt requests */
int32 dev_enb = -1 & ~(INT_PTR | INT_PTP | INT_DZ0RX); /* device enables */
/* Map IO controller numbers to Unibus adapters: -1 = non-existent */
@ -97,10 +98,12 @@ extern jmp_buf save_env;
extern d10 Read (a10 ea);
extern void pi_eval ();
extern t_stat dz0_rd (int32 *data, int32 addr, int32 access);
extern t_stat dz0_wr (int32 data, int32 addr, int32 access);
extern t_stat dz_rd (int32 *data, int32 addr, int32 access);
extern t_stat dz_wr (int32 data, int32 addr, int32 access);
extern int32 dz_enb;
extern t_stat pt_rd (int32 *data, int32 addr, int32 access);
extern t_stat pt_wr (int32 data, int32 addr, int32 access);
extern int32 pt_enb;
extern t_stat lp20_rd (int32 *data, int32 addr, int32 access);
extern t_stat lp20_wr (int32 data, int32 addr, int32 access);
extern int32 lp20_inta (void);
@ -138,7 +141,6 @@ REG uba_reg[] = {
{ ORDATA (INTREQ, int_req, 32), REG_RO },
{ ORDATA (UB1CS, ubcs[0], 18) },
{ ORDATA (UB3CS, ubcs[1], 18) },
{ ORDATA (DEVENB, dev_enb, 32), REG_HRO },
{ NULL } };
DEVICE uba_dev = {
@ -152,7 +154,7 @@ DEVICE uba_dev = {
struct iolink { /* I/O page linkage */
int32 low; /* low I/O addr */
int32 high; /* high I/O addr */
int32 enb; /* enable mask */
int32 *enb; /* enable flag */
t_stat (*read)(); /* read routine */
t_stat (*write)(); }; /* write routine */
@ -160,31 +162,31 @@ struct iolink { /* I/O page linkage */
The expected Unibus adapter number is included as the high 2 bits */
struct iolink iotable[] = {
{ IO_UBA1+IO_RHBASE, IO_UBA1+IO_RHBASE+047, 0,
&rp_rd, &rp_wr }, /* disk */
{ IO_UBA3+IO_TMBASE, IO_UBA3+IO_TMBASE+033, 0,
&tu_rd, &tu_wr }, /* mag tape */
{ IO_UBA3+IO_DZBASE, IO_UBA3+IO_DZBASE+07, INT_DZ0RX,
&dz0_rd, &dz0_wr }, /* terminal mux */
{ IO_UBA3+IO_LPBASE, IO_UBA3+IO_LPBASE+017, 0,
&lp20_rd, &lp20_wr }, /* line printer */
{ IO_UBA3+IO_PTBASE, IO_UBA3+IO_PTBASE+07, INT_PTR,
&pt_rd, &pt_wr }, /* paper tape */
{ IO_UBA1+IO_UBMAP, IO_UBA1+IO_UBMAP+077, 0,
&ubmap_rd, &ubmap_wr }, /* Unibus 1 map */
{ IO_UBA3+IO_UBMAP, IO_UBA3+IO_UBMAP+077, 0,
&ubmap_rd, &ubmap_wr }, /* Unibus 3 map */
{ IO_UBA1+IO_UBCS, IO_UBA1+IO_UBCS, 0,
&ubs_rd, &ubs_wr }, /* Unibus 1 c/s */
{ IO_UBA3+IO_UBCS, IO_UBA3+IO_UBCS, 0,
&ubs_rd, &ubs_wr }, /* Unibus 3 c/s */
{ IO_UBA1+IO_UBMNT, IO_UBA1+IO_UBMNT, 0,
&rd_zro, &wr_nop }, /* Unibus 1 maint */
{ IO_UBA3+IO_UBMNT, IO_UBA3+IO_UBMNT, 0,
&rd_zro, &wr_nop }, /* Unibus 3 maint */
{ IO_UBA3+IO_TCUBASE, IO_UBA3+IO_TCUBASE+05, 0,
&tcu_rd, &wr_nop }, /* TCU150 */
{ 00100000, 00100000, 0, &rd_zro, &wr_nop }, /* Mem sys stat */
{ IO_UBA1+IOBA_RP, IO_UBA1+IOBA_RP+IOLN_RP,
NULL, &rp_rd, &rp_wr }, /* disk */
{ IO_UBA3+IOBA_TU, IO_UBA3+IOBA_TU+IOLN_TU,
NULL, &tu_rd, &tu_wr }, /* mag tape */
{ IO_UBA3+IOBA_DZ, IO_UBA3+IOBA_DZ+IOLN_DZ,
&dz_enb, &dz_rd, &dz_wr }, /* terminal mux */
{ IO_UBA3+IOBA_LP20, IO_UBA3+IOBA_LP20+IOLN_LP20,
NULL, &lp20_rd, &lp20_wr }, /* line printer */
{ IO_UBA3+IOBA_PT, IO_UBA3+IOBA_PT+IOLN_PT,
&pt_enb, &pt_rd, &pt_wr }, /* paper tape */
{ IO_UBA1+IOBA_UBMAP, IO_UBA1+IOBA_UBMAP+IOLN_UBMAP,
NULL, &ubmap_rd, &ubmap_wr }, /* Unibus 1 map */
{ IO_UBA3+IOBA_UBMAP, IO_UBA3+IOBA_UBMAP+IOLN_UBMAP,
NULL, &ubmap_rd, &ubmap_wr }, /* Unibus 3 map */
{ IO_UBA1+IOBA_UBCS, IO_UBA1+IOBA_UBCS+IOLN_UBCS,
NULL, &ubs_rd, &ubs_wr }, /* Unibus 1 c/s */
{ IO_UBA3+IOBA_UBCS, IO_UBA3+IOBA_UBCS+IOLN_UBCS,
NULL, &ubs_rd, &ubs_wr }, /* Unibus 3 c/s */
{ IO_UBA1+IOBA_UBMNT, IO_UBA1+IOBA_UBMNT+IOLN_UBMNT,
NULL, &rd_zro, &wr_nop }, /* Unibus 1 maint */
{ IO_UBA3+IOBA_UBMNT, IO_UBA3+IOBA_UBMNT+IOLN_UBMNT,
NULL, &rd_zro, &wr_nop }, /* Unibus 3 maint */
{ IO_UBA3+IOBA_TCU, IO_UBA3+IOBA_TCU+IOLN_TCU,
NULL, &tcu_rd, &wr_nop }, /* TCU150 */
{ 00100000, 00100000, NULL, &rd_zro, &wr_nop }, /* Mem sys stat */
{ 0, 0, 0, NULL, NULL } };
/* Interrupt request to interrupt action map */
@ -200,7 +202,7 @@ int32 (*int_ack[32])() = { /* int ack routines */
int32 int_vec[32] = { /* int req to vector */
0, 0, 0, 0, 0, 0, VEC_RP, VEC_TU,
0, 0, 0, 0, 0, 0, 0, 0,
VEC_DZ0RX, VEC_DZ0TX, 0, 0, 0, 0, 0, 0,
VEC_DZRX, VEC_DZTX, 0, 0, 0, 0, 0, 0,
VEC_PTR, VEC_PTP, VEC_LP20, 0, 0, 0, 0, 0 };
/* IO 710 (DEC) TIOE - test I/O word, skip if zero
@ -396,8 +398,8 @@ struct iolink *p;
pa = (int32) ea; /* cvt addr to 32b */
for (p = &iotable[0]; p -> low != 0; p++ ) {
if ((pa >= p -> low) && (pa <= p -> high) &&
((p -> enb == 0) || (dev_enb & p -> enb))) {
if ((pa >= p -> low) && (pa < p -> high) &&
((p -> enb == NULL) || *p -> enb)) {
p -> read (&val, pa, READ);
pi_eval ();
return ((d10) val); } }
@ -411,8 +413,8 @@ struct iolink *p;
pa = (int32) ea; /* cvt addr to 32b */
for (p = &iotable[0]; p -> low != 0; p++ ) {
if ((pa >= p -> low) && (pa <= p -> high) &&
((p -> enb == 0) || (dev_enb & p -> enb))) {
if ((pa >= p -> low) && (pa < p -> high) &&
((p -> enb == NULL) || *p -> enb)) {
p -> write ((int32) val, pa, mode);
pi_eval ();
return; } }

View file

@ -91,6 +91,7 @@
format (so-called G floating). These instructions were not
implemented in the KS10 and are treated as MUUO's.
31-Aug-01 RMS Changed int64 to t_int64 for Windoze
10-Aug-01 RMS Removed register in declarations
*/
@ -98,10 +99,10 @@
#include <setjmp.h>
struct ufp { /* unpacked fp number */
int32 sign; /* sign */
int32 exp; /* exponent */
uint64 fhi; /* fraction high */
uint64 flo; }; /* for double prec */
int32 sign; /* sign */
int32 exp; /* exponent */
t_uint64 fhi; /* fraction high */
t_uint64 flo; }; /* for double prec */
typedef struct ufp UFP;
@ -154,7 +155,7 @@ extern d10 *ac_cur; /* current AC block */
extern int32 flags; /* flags */
void mul (d10 a, d10 b, d10 *rs);
void funpack (d10 h, d10 l, UFP *r, t_bool sgn);
void fnorm (UFP *r, int64 rnd);
void fnorm (UFP *r, t_int64 rnd);
d10 fpack (UFP *r, d10 *lo, t_bool fdvneg);
/* Integer multiply - checked against KS-10 ucode */
@ -197,9 +198,9 @@ return TRUE;
void mul (d10 s1, d10 s2, d10 *rs)
{
uint64 a = ABS (s1);
uint64 b = ABS (s2);
uint64 t, u, r;
t_uint64 a = ABS (s1);
t_uint64 b = ABS (s2);
t_uint64 t, u, r;
if ((a == 0) || (b == 0)) { /* operand = 0? */
rs[0] = rs[1] = 0; /* result 0 */
@ -232,7 +233,7 @@ t_bool divi (int32 ac, d10 b, d10 *rs)
{
int32 p1 = ADDAC (ac, 1);
d10 dvr = ABS (b); /* make divr positive */
int64 t;
t_int64 t;
int32 i;
d10 dvd[2];
@ -373,7 +374,7 @@ else { funpack (op1, 0, &a, SFRC); /* unpack operands */
b = t;
ediff = -ediff; }
if (ediff > 63) ediff = 63; /* cap diff at 63 */
if (ediff) b.fhi = (int64) b.fhi >> ediff; /* shift b (signed) */
if (ediff) b.fhi = (t_int64) b.fhi >> ediff; /* shift b (signed) */
a.fhi = a.fhi + b.fhi; /* add fractions */
if (a.sign ^ b.sign) { /* add or subtract? */
if (a.fhi & FP_UCRY) { /* subtract, frac -? */
@ -420,7 +421,7 @@ return fpack (&a, NULL, FALSE);
t_bool fdv (d10 op1, d10 op2, d10 *rs, t_bool rnd)
{
UFP a, b;
uint64 savhi;
t_uint64 savhi;
t_bool rem = FALSE;
funpack (op1, 0, &a, AFRC); /* unpack operands */
@ -479,7 +480,7 @@ return fpack (&a, NULL, FALSE); /* pack result */
void fix (int32 ac, d10 mb, t_bool rnd)
{
int32 sc;
uint64 so;
t_uint64 so;
UFP a;
funpack (mb, 0, &a, AFRC); /* unpack operand */
@ -521,11 +522,11 @@ else {
ediff = -ediff; }
if (ediff > 127) ediff = 127; /* cap diff at 127 */
if (ediff > 63) { /* diff > 63? */
a.flo = (int64) b.fhi >> (ediff - 64); /* b hi to a lo */
a.flo = (t_int64) b.fhi >> (ediff - 64); /* b hi to a lo */
b.fhi = b.sign? FP_ONES: 0; } /* hi = all sign */
else if (ediff) { /* diff <= 63 */
a.flo = (b.flo >> ediff) | (b.fhi << (64 - ediff));
b.fhi = (int64) b.fhi >> ediff; } /* shift b (signed) */
b.fhi = (t_int64) b.fhi >> ediff; } /* shift b (signed) */
a.fhi = a.fhi + b.fhi; /* do add */
if (a.sign ^ b.sign) { /* add or subtract? */
if (a.fhi & FP_UCRY) { /* subtract, frac -? */
@ -552,7 +553,7 @@ return;
void dfmp (int32 ac, d10 *rs)
{
int32 p1 = ADDAC (ac, 1);
uint64 xh, xl, yh, yl, mid;
t_uint64 xh, xl, yh, yl, mid;
UFP a, b;
funpack (AC(ac), AC(p1), &a, AFRC); /* unpack operands */
@ -587,7 +588,7 @@ void dfdv (int32 ac, d10 *rs)
{
int32 p1 = ADDAC (ac, 1);
int32 i;
uint64 qu = 0;
t_uint64 qu = 0;
UFP a, b;
funpack (AC(ac), AC(p1), &a, AFRC); /* unpack operands */
@ -636,10 +637,10 @@ return;
/* Normalize and optionally round floating point operand */
void fnorm (UFP *a, int64 rnd)
void fnorm (UFP *a, t_int64 rnd)
{
int32 i;
static uint64 normmask[6] = {
static t_uint64 normmask[6] = {
0x6000000000000000, 0x7800000000000000, 0x7F80000000000000,
0x7FFF800000000000, 0x7FFFFFFF80000000, 0x7FFFFFFFFFFFFFFF };
static int32 normtab[7] = { 1, 2, 4, 8, 16, 32, 63 };

View file

@ -25,6 +25,8 @@
ptr paper tape reader
ptp paper tape punch
07-Sep-01 RMS Revised disable mechanism
*/
#include "pdp10_defs.h"
@ -34,11 +36,12 @@
#define PTPCSR_IMP (CSR_ERR + CSR_DONE + CSR_IE) /* paper tape punch */
#define PTPCSR_RW (CSR_IE)
extern int32 int_req, dev_enb;
extern int32 int_req;
int32 ptr_csr = 0; /* control/status */
int32 ptr_stopioe = 0; /* stop on error */
int32 ptp_csr = 0; /* control/status */
int32 ptp_stopioe = 0; /* stop on error */
int32 pt_enb = 0; /* device enable */
t_stat ptr_svc (UNIT *uptr);
t_stat ptp_svc (UNIT *uptr);
t_stat ptr_reset (DEVICE *dptr);
@ -69,7 +72,7 @@ REG ptr_reg[] = {
{ DRDATA (POS, ptr_unit.pos, 31), PV_LEFT },
{ DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT },
{ FLDATA (STOP_IOE, ptr_stopioe, 0) },
{ FLDATA (*DEVENB, dev_enb, INT_V_PTR), REG_HRO },
{ FLDATA (*DEVENB, pt_enb, 0), REG_HRO },
{ NULL } };
DEVICE ptr_dev = {
@ -98,7 +101,7 @@ REG ptp_reg[] = {
{ DRDATA (POS, ptp_unit.pos, 31), PV_LEFT },
{ DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT },
{ FLDATA (STOP_IOE, ptp_stopioe, 0) },
{ FLDATA (*DEVENB, dev_enb, INT_V_PTR), REG_HRO },
{ FLDATA (*DEVENB, pt_enb, 0), REG_HRO },
{ NULL } };
DEVICE ptp_dev = {

View file

@ -25,8 +25,14 @@
rp RH/RP/RM moving head disks
23-Oct-01 RMS Fixed bug in error interrupts
New IO page address constants
05-Oct-01 RMS Rewrote interrupt handling from schematics
02-Oct-01 RMS Revised CS1 write code
30-Sep-01 RMS Moved CS1<5:0> into drives
28-Sep-01 RMS Fixed interrupt handling for SC/ATA
23-Aug-01 RMS Added read/write header stubs for ITS
(found by Mirian Crzig Lennox)
(found by Mirian Crzig Lennox)
13-Jul-01 RMS Changed fread call to fxread (found by Peter Schorn)
14-May-01 RMS Added check for unattached drive
@ -35,13 +41,19 @@
100% compatible) family of interfaces into the KS10 Unibus via
the RH11 disk controller.
WARNING: This controller is somewhat abstract. It is intended to run
the operating system drivers for the PDP-10 operating systems and
nothing more. Most error and all diagnostic functions have been
omitted. In addition, the controller conflates the RP04/05/06 series
controllers with the RM02/03/05/80 series controllers and with the
RP07 controller. There are actually significant differences, which
have been highlighted where noticed.
WARNING: The interupt logic of the RH11/RH70 is unusual and must be
simulated with great precision. The RH11 has an internal interrupt
request flop, CSTB INTR, which is controlled as follows:
- Writing IE and DONE simultaneously sets CSTB INTR
- Controller clear, INIT, and interrupt acknowledge clear CSTB INTR
(and also clear IE)
- A transition of DONE from 0 to 1 sets CSTB from INTR
The output of INTR is OR'd with the AND of RPCS1<SC,DONE,IE> to
create the interrupt request signal. Thus,
- The DONE interrupt is edge sensitive, but the SC interrupt is
level sensitive.
- The DONE interrupt, once set, is not disabled if IE is cleared,
but the SC interrupt is.
*/
#include "pdp10_defs.h"
@ -89,6 +101,7 @@
#define FNC_PRESET 010 /* read-in preset */
#define FNC_PACK 011 /* pack acknowledge */
#define FNC_SEARCH 014 /* search */
#define FNC_XFER 024 /* >=? data xfr */
#define FNC_WCHK 024 /* write check */
#define FNC_WRITE 030 /* write */
#define FNC_WRITEH 031 /* write w/ headers */
@ -104,7 +117,7 @@
#define CS1_TRE 0040000 /* transfer err */
#define CS1_SC 0100000 /* special cond */
#define CS1_MBZ 0012000
#define CS1_RW (CS1_FNC | CS1_IE | CS1_UAE)
#define CS1_DRV (CS1_FNC | CS1_GO)
#define GET_FNC(x) (((x) >> CS1_V_FNC) & CS1_M_FNC)
#define GET_UAE(x) (((x) & CS1_UAE) << (16 - CS1_V_UAE))
@ -211,7 +224,7 @@
#define GET_DA(c,fs,d) ((((GET_CY (c) * drv_tab[d].surf) + \
GET_SF (fs)) * drv_tab[d].sect) + GET_SC (fs))
/* RPCC - 176736 - current cylinder - unimplemented */
/* RPCC - 176736 - current cylinder */
/* RPER2 - 176740 - error status 2 - drive unsafe conditions - unimplemented */
/* RPER3 - 176742 - error status 3 - more unsafe conditions - unimplemented */
/* RPEC1 - 176744 - ECC status 1 - unimplemented */
@ -315,6 +328,7 @@ int32 rper2 = 0; /* error status 2 */
int32 rper3 = 0; /* error status 3 */
int32 rpec1 = 0; /* ECC correction 1 */
int32 rpec2 = 0; /* ECC correction 2 */
int32 rpiff = 0; /* INTR flip/flop */
int32 rp_stopioe = 1; /* stop on error */
int32 rp_swait = 10; /* seek time */
int32 rp_rwait = 10; /* rotate time */
@ -323,7 +337,7 @@ int reg_in_drive[32] = {
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
void update_rpcs (int32 flags, int32 drv);
void rp_go (int32 drv);
void rp_go (int32 drv, int32 fnc);
t_stat rp_set_size (UNIT *uptr, int32 value);
t_stat rp_svc (UNIT *uptr);
t_stat rp_reset (DEVICE *dptr);
@ -371,6 +385,7 @@ REG rp_reg[] = {
{ ORDATA (RPEC2, rpec2, 16) },
{ ORDATA (RPMR, rpmr, 16) },
{ ORDATA (RPDB, rpdb, 16) },
{ FLDATA (IFF, rpiff, 0) },
{ FLDATA (INT, int_req, INT_V_RP) },
{ FLDATA (SC, rpcs1, CSR_V_ERR) },
{ FLDATA (DONE, rpcs1, CSR_V_DONE) },
@ -393,6 +408,14 @@ REG rp_reg[] = {
{ ORDATA (RPDE5, rper1[5], 16) },
{ ORDATA (RPDE6, rper1[6], 16) },
{ ORDATA (RPDE7, rper1[7], 16) },
{ ORDATA (RPFN0, rp_unit[0].FUNC, 5), REG_HRO },
{ ORDATA (RPFN1, rp_unit[1].FUNC, 5), REG_HRO },
{ ORDATA (RPFN2, rp_unit[2].FUNC, 5), REG_HRO },
{ ORDATA (RPFN3, rp_unit[3].FUNC, 5), REG_HRO },
{ ORDATA (RPFN4, rp_unit[4].FUNC, 5), REG_HRO },
{ ORDATA (RPFN5, rp_unit[5].FUNC, 5), REG_HRO },
{ ORDATA (RPFN6, rp_unit[6].FUNC, 5), REG_HRO },
{ ORDATA (RPFN7, rp_unit[7].FUNC, 5), REG_HRO },
{ GRDATA (FLG0, rp_unit[0].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
REG_HRO },
{ GRDATA (FLG1, rp_unit[1].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
@ -550,9 +573,11 @@ return SCPE_OK;
t_stat rp_wr (int32 data, int32 PA, int32 access)
{
int32 cs1f, drv, i, j;
UNIT *uptr;
cs1f = 0; /* no int on cs1 upd */
drv = GET_UNIT (rpcs2); /* get current unit */
uptr = rp_dev.units + drv; /* get unit */
j = (PA >> 1) & 037; /* get reg offset */
if (reg_in_drive[j] && (rp_unit[drv].flags & UNIT_DIS)) { /* nx disk */
rpcs2 = rpcs2 | CS2_NED; /* set error flag */
@ -566,17 +591,27 @@ if (reg_in_drive[j] && sim_is_active (&rp_unit[drv])) { /* unit busy? */
switch (j) { /* decode PA<5:1> */
case 000: /* RPCS1 */
if ((access == WRITEB) && (PA & 1)) data = data << 8;
else { if ((data & CS1_IE) == 0) int_req = int_req & ~INT_RP;
else if (data & CS1_DONE) int_req = int_req | INT_RP; }
if (data & CS1_TRE) { /* error clear? */
rpcs1 = rpcs1 & ~CS1_TRE; /* clr CS1<TRE> */
rpcs2 = rpcs2 & ~CS2_ERR; } /* clr CS2<15:8> */
if (access == WRITEB) data = (rpcs1 & /* merge data */
((PA & 1)? 0377: 0177400)) | data;
rpcs1 = (rpcs1 & ~CS1_RW) | (data & CS1_RW);
if (data & CS1_GO) { /* new command? */
if (rpcs1 & CS1_DONE) rp_go (drv); /* start if not busy */
else rpcs2 = rpcs2 | CS2_PGE; } /* else prog error */
if ((access == WRITE) || (PA & 1)) { /* hi byte write? */
if (rpcs1 & CS1_DONE) /* done set? */
rpcs1 = (rpcs1 & ~CS1_UAE) | (data & CS1_UAE); }
if ((access == WRITE) || !(PA & 1)) { /* lo byte write? */
if ((data & CS1_DONE) && (data & CS1_IE)) /* to DONE+IE? */
rpiff = 1; /* set CSTB INTR */
rpcs1 = (rpcs1 & ~CS1_IE) | (data & CS1_IE);
if (uptr -> flags & UNIT_DIS) { /* nx disk? */
rpcs2 = rpcs2 | CS2_NED; /* set error flag */
cs1f = CS1_SC; } /* req interrupt */
else if (sim_is_active (uptr))
rper1[drv] = rper1[drv] | ER1_RMR; /* won't write */
else if (data & CS1_GO) { /* start op */
uptr -> FUNC = GET_FNC (data); /* set func */
if ((uptr -> FUNC >= FNC_XFER) && /* data xfer and */
((rpcs1 & CS1_DONE) == 0)) /* ~rdy? PGE */
rpcs2 = rpcs2 | CS2_PGE;
else rp_go (drv, uptr -> FUNC); } }
break;
case 001: /* RPWC */
if (access == WRITEB) data = (PA & 1)?
@ -650,29 +685,23 @@ update_rpcs (cs1f, drv); /* update status */
return SCPE_OK;
}
/* Initiate operation */
/* Initiate operation - unit not busy, function set */
void rp_go (int32 drv)
void rp_go (int32 drv, int32 fnc)
{
int32 dc, dtype, fnc;
int32 dc, dtype, t;
UNIT *uptr;
fnc = GET_FNC (rpcs1); /* get function */
uptr = rp_dev.units + drv; /* get unit */
if (uptr -> flags & UNIT_DIS) { /* nx unit? */
rpcs2 = rpcs2 | CS2_NED; /* set error flag */
update_rpcs (CS1_SC, drv); /* request intr */
return; }
if (fnc != FNC_DCLR) { /* not clear? */
if ((rpds[drv] & DS_ERR) || /* error or */
((rpds[drv] & DS_RDY) == 0)) { /* not ready? */
rpcs2 = rpcs2 | CS2_PGE; /* set error flag */
update_rpcs (CS1_SC, drv); /* request intr */
return; }
if ((uptr -> flags & UNIT_ATT) == 0) { /* not attached? */
rper1[drv] = rper1[drv] | ER1_UNS; /* unsafe */
update_rpcs (CS1_SC, drv); /* request intr */
return; } }
if ((fnc != FNC_DCLR) && (rpds[drv] & DS_ERR)) { /* err & ~clear? */
rper1[drv] = rper1[drv] | ER1_ILF; /* not allowed */
rpds[drv] = rpds[drv] | DS_ATA; /* set attention */
update_rpcs (CS1_SC, drv); /* request intr */
return; }
dtype = GET_DTYPE (uptr -> flags); /* get drive type */
rpds[drv] = rpds[drv] & ~DS_ATA; /* clear attention */
dc = rpdc; /* assume seek, sch */
@ -695,7 +724,9 @@ case FNC_PACK: /* pack acknowledge */
case FNC_OFFSET: /* offset mode */
case FNC_RETURN:
uptr -> FUNC = fnc; /* save function */
if ((uptr -> flags & UNIT_ATT) == 0) { /* not attached? */
rper1[drv] = rper1[drv] | ER1_UNS; /* unsafe */
break; }
rpds[drv] = (rpds[drv] & ~DS_RDY) | DS_PIP; /* set positioning */
sim_activate (uptr, rp_swait); /* time operation */
return;
@ -705,40 +736,46 @@ case FNC_RECAL: /* recalibrate */
dc = 0; /* seek to 0 */
case FNC_SEEK: /* seek */
case FNC_SEARCH: /* search */
if ((uptr -> flags & UNIT_ATT) == 0) { /* not attached? */
rper1[drv] = rper1[drv] | ER1_UNS; /* unsafe */
break; }
if ((GET_CY (dc) >= drv_tab[dtype].cyl) || /* bad cylinder */
(GET_SF (rpda) >= drv_tab[dtype].surf) || /* bad surface */
(GET_SC (rpda) >= drv_tab[dtype].sect)) { /* or bad sector? */
rper1[drv] = rper1[drv] | ER1_IAE;
break; }
rpds[drv] = (rpds[drv] & ~DS_RDY) | DS_PIP; /* set positioning */
sim_activate (uptr, rp_swait * abs (dc - uptr -> CYL));
uptr -> FUNC = fnc; /* save function */
t = abs (dc - uptr -> CYL); /* cyl diff */
if (t == 0) t = 1; /* min time */
sim_activate (uptr, rp_swait * t); /* schedule */
uptr -> CYL = dc; /* save cylinder */
return;
case FNC_WRITEH: /* write headers */
case FNC_WRITEH: /* write headers */
case FNC_WRITE: /* write */
case FNC_WCHK: /* write check */
case FNC_READ: /* read */
case FNC_READH: /* read headers */
if ((uptr -> flags & UNIT_ATT) == 0) { /* not attached? */
rper1[drv] = rper1[drv] | ER1_UNS; /* unsafe */
break; }
rpcs2 = rpcs2 & ~CS2_ERR; /* clear errors */
rpcs1 = rpcs1 & ~(CS1_TRE | CS1_MCPE | CS1_DONE);
if ((GET_CY (dc) >= drv_tab[dtype].cyl) || /* bad cylinder */
(GET_SF (rpda) >= drv_tab[dtype].surf) || /* bad surface */
(GET_SC (rpda) >= drv_tab[dtype].sect)) { /* or bad sector? */
rper1[drv] = rper1[drv] | ER1_IAE;
update_rpcs (CS1_DONE | CS1_TRE, drv); /* set done, err */
return; }
break; }
rpds[drv] = rpds[drv] & ~DS_RDY; /* clear drive rdy */
sim_activate (uptr, rp_rwait + (rp_swait * abs (dc - uptr -> CYL)));
uptr -> FUNC = fnc; /* save function */
uptr -> CYL = dc; /* save cylinder */
return;
default: /* all others */
rper1[drv] = rper1[drv] | ER1_ILF; /* not supported */
break; }
update_rpcs (CS1_SC, drv); /* error, interrupt */
rpds[drv] = rpds[drv] | DS_ATA; /* error, set attn */
update_rpcs (CS1_SC, drv); /* req intr */
return;
}
@ -870,21 +907,28 @@ case FNC_READH: /* read headers */
perror ("RP I/O error");
clearerr (uptr -> fileref);
return SCPE_IOERR; }
case FNC_WRITEH: /* write headers stub */
case FNC_WRITEH: /* write headers stub */
update_rpcs (CS1_DONE, drv); /* set done */
break; } /* end case func */
return SCPE_OK;
}
/* Controller status update
First update drive status, then update RPCS1
If optional argument, request interrupt
/* Controller status update
Check for done transition
Update drive status
Update RPCS1
Update interrupt request
*/
void update_rpcs (int32 flag, int32 drv)
{
int32 i;
UNIT *uptr;
if ((flag & ~rpcs1) & CS1_DONE) /* DONE 0 to 1? */
rpiff = (rpcs1 & CS1_IE)? 1: 0; /* CSTB INTR <- IE */
uptr = rp_dev.units + drv; /* get unit */
if (rp_unit[drv].flags & UNIT_DIS) rpds[drv] = rper1[drv] = 0;
else rpds[drv] = (rpds[drv] | DS_DPR) & ~DS_PGM;
if (rp_unit[drv].flags & UNIT_ATT) rpds[drv] = rpds[drv] | DS_MOL;
@ -892,13 +936,16 @@ else rpds[drv] = rpds[drv] & ~(DS_MOL | DS_VV | DS_RDY);
if (rper1[drv] | rper2 | rper3) rpds[drv] = rpds[drv] | DS_ERR | DS_ATA;
else rpds[drv] = rpds[drv] & ~DS_ERR;
rpcs1 = (rpcs1 & ~(CS1_SC | CS1_MCPE | CS1_MBZ)) | CS1_DVA | flag;
rpcs1 = (rpcs1 & ~(CS1_SC | CS1_MCPE | CS1_MBZ | CS1_DRV)) | CS1_DVA | flag;
rpcs1 = rpcs1 | (uptr -> FUNC << CS1_V_FNC);
if (sim_is_active (uptr)) rpcs1 = rpcs1 | CS1_GO;
if (rpcs2 & CS2_ERR) rpcs1 = rpcs1 | CS1_TRE | CS1_SC;
else if (rpcs1 & CS1_TRE) rpcs1 = rpcs1 | CS1_SC;
for (i = 0; i < RP_NUMDR; i++)
if (rpds[i] & DS_ATA) rpcs1 = rpcs1 | CS1_SC;
if (((rpcs1 & CS1_IE) == 0) || ((rpcs1 & CS1_DONE) == 0))
int_req = int_req & ~INT_RP;
else if (flag) int_req = int_req | INT_RP;
if (rpiff || ((rpcs1 & CS1_SC) && (rpcs1 & CS1_DONE) && (rpcs1 & CS1_IE)))
int_req = int_req | INT_RP;
else int_req = int_req & ~INT_RP;
return;
}
@ -907,6 +954,7 @@ return;
int32 rp_inta (void)
{
rpcs1 = rpcs1 & ~CS1_IE; /* clear int enable */
rpiff = 0; /* clear CSTB INTR */
return VEC_RP; /* acknowledge */
}
@ -923,7 +971,8 @@ rpba = rpda = 0;
rpof = rpdc = 0;
rper2 = rper3 = 0;
rpec1 = rpec2 = 0;
int_req = int_req & ~INT_RP;
rpiff = 0; /* clear CSTB INTR */
int_req = int_req & ~INT_RP; /* clear intr req */
for (i = 0; i < RP_NUMDR; i++) {
uptr = rp_dev.units + i;
sim_cancel (uptr);
@ -998,8 +1047,8 @@ return SCPE_OK;
static const d10 boot_rom_dec[] = {
0515040000001, /* boot:hrlzi 1,1 ; uba # */
0201000140001, /* movei 0,140001 ; vld,fst,pg 1 */
0713001000000+IO_UBMAP+1, /* wrio 0,763001(1); set ubmap */
0435040000000+IO_RHBASE, /* iori 1,776700 ; rh addr */
0713001000000+IOBA_UBMAP+1, /* wrio 0,763001(1); set ubmap */
0435040000000+IOBA_RP, /* iori 1,776700 ; rh addr */
0202040000000+FE_RHBASE, /* movem 1,FE_RHBASE */
0201000000040, /* movei 0,40 ; ctrl reset */
0713001000010, /* wrio 0,10(1) ; ->RPCS2 */
@ -1045,8 +1094,8 @@ static const d10 boot_rom_dec[] = {
static const d10 boot_rom_its[] = {
0515040000001, /* boot:hrlzi 1,1 ; uba # */
0201000140001, /* movei 0,140001 ; vld,fst,pg 1 */
0715000000000+IO_UBMAP+1, /* iowrq 0,763001 ; set ubmap */
0435040000000+IO_RHBASE, /* iori 1,776700 ; rh addr */
0715000000000+IOBA_UBMAP+1, /* iowrq 0,763001 ; set ubmap */
0435040000000+IOBA_RP, /* iori 1,776700 ; rh addr */
0202040000000+FE_RHBASE, /* movem 1,FE_RHBASE */
0201000000040, /* movei 0,40 ; ctrl reset */
0715001000010, /* iowrq 0,10(1) ; ->RPCS2 */

View file

@ -23,6 +23,7 @@
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.
17-Sep-01 RMS Removed multiconsole support
25-Aug-01 RMS Enabled DZ11
27-May-01 RMS Added multiconsole support
29-Apr-01 RMS Fixed format for RDPCST, WRPCST
@ -52,7 +53,6 @@ extern a10 saved_PC;
sim_PC pointer to saved PC register descriptor
sim_emax number of words for examine
sim_devices array of pointers to simulated devices
sim_consoles array of pointers to consoles (if more than one)
sim_stop_messages array of pointers to stop messages
sim_load binary loader
*/
@ -77,8 +77,6 @@ DEVICE *sim_devices[] = {
&tu_dev,
NULL };
UNIT *sim_consoles = NULL;
const char *sim_stop_messages[] = {
"Unknown error",
"HALT instruction",

View file

@ -25,6 +25,7 @@
tim timer subsystem
31-Aug-01 RMS Changed int64 to t_int64 for Windoze
17-Jul-01 RMS Moved function prototype
04-Jul-01 RMS Added DZ11 support
*/
@ -45,12 +46,12 @@ extern int32 apr_flg, pi_act;
extern UNIT cpu_unit;
extern d10 pcst;
extern a10 pager_PC;
int64 timebase = 0; /* 71b timebase */
t_int64 timebase = 0; /* 71b timebase */
d10 ttg = 0; /* time to go */
d10 period = 0; /* period */
d10 quant = 0; /* ITS quantum */
int32 diagflg = 0; /* diagnostics? */
int32 dz_poll = TIM_DELAY * DZ_MULT; /* DZ11 poll */
int32 tmxr_poll = TIM_DELAY * DZ_MULT; /* term mux poll */
t_stat tim_svc (UNIT *uptr);
t_stat tim_reset (DEVICE *dptr);
@ -132,7 +133,7 @@ int32 t;
t = diagflg? tim_unit.wait: sim_rtc_calb (TIM_TPS); /* calibrate clock */
sim_activate (&tim_unit, t); /* reactivate unit */
dz_poll = t * DZ_MULT; /* set DZ poll */
tmxr_poll = t * DZ_MULT; /* set mux poll */
timebase = (timebase + 1) & TB_MASK; /* increment timebase */
ttg = ttg - TIM_HWRE; /* decrement timer */
if (ttg <= 0) { /* timeout? */
@ -152,7 +153,7 @@ t_stat tim_reset (DEVICE *dptr)
period = ttg = 0; /* clear timer */
apr_flg = apr_flg & ~APRF_TIM; /* clear interrupt */
sim_activate (&tim_unit, tim_unit.wait); /* activate unit */
dz_poll = tim_unit.wait * DZ_MULT; /* set DZ poll */
tmxr_poll = tim_unit.wait * DZ_MULT; /* set mux poll */
return SCPE_OK;
}

View file

@ -25,6 +25,11 @@
tu RH11/TM03/TU45 magtape
23-Oct-01 RMS Fixed bug in error interrupts
New IO page address constants
05-Oct-01 RMS Rewrote interrupt handling from schematics
30-Sep-01 RMS Fixed handling of non-existent formatters
28-Sep-01 RMS Fixed interrupt handling for SC/ATA
4-May-01 RMS Fixed bug in odd address test
3-May-01 RMS Fixed drive reset to clear SSC
@ -42,6 +47,20 @@
If the byte count is odd, the record is padded with an extra byte
of junk. File marks are represented by a single record length of 0.
End of tape is two consecutive end of file marks.
WARNING: The interupt logic of the RH11/RH70 is unusual and must be
simulated with great precision. The RH11 has an internal interrupt
request flop, CSTB INTR, which is controlled as follows:
- Writing IE and DONE simultaneously sets CSTB INTR
- Controller clear, INIT, and interrupt acknowledge clear CSTB INTR
(and also clear IE)
- A transition of DONE from 0 to 1 sets CSTB from INTR
The output of INTR is OR'd with the AND of RPCS1<SC,DONE,IE> to
create the interrupt request signal. Thus,
- The DONE interrupt is edge sensitive, but the SC interrupt is
level sensitive.
- The DONE interrupt, once set, is not disabled if IE is cleared,
but the SC interrupt is.
*/
#include "pdp10_defs.h"
@ -71,6 +90,7 @@
#define FNC_WREOF 013 /* write tape mark */
#define FNC_SPACEF 014 /* space forward */
#define FNC_SPACER 015 /* space reverse */
#define FNC_XFER 024 /* >=? data xfr */
#define FNC_WCHKF 024 /* write check */
#define FNC_WCHKR 027 /* write check rev */
#define FNC_WRITE 030 /* write */
@ -86,7 +106,7 @@
#define CS1_TRE 0040000 /* transfer err */
#define CS1_SC 0100000 /* special cond */
#define CS1_MBZ 0012000
#define CS1_RW (CS1_FNC | CS1_IE | CS1_UAE | CS1_GO)
#define CS1_DRV (CS1_FNC | CS1_GO)
#define GET_FNC(x) (((x) >> CS1_V_FNC) & CS1_M_FNC)
#define GET_UAE(x) (((x) & CS1_UAE) << (16 - CS1_V_UAE))
@ -224,6 +244,7 @@
(((b) & XBA_ODD) != ((od) << 1))) { \
tucs2 = tucs2 | CS2_NEM; \
ubcs[1] = ubcs[1] | UBCS_TMO; \
tucs1 = tucs1 & ~CS1_GO; \
update_tucs (CS1_DONE, drv); \
return SCPE_OK; }
#define NEWPAGE(v,m) (((v) & PAG_M_OFF) == (m))
@ -257,6 +278,7 @@ int32 tucc = 0; /* check character */
int32 tudb = 0; /* data buffer */
int32 tumr = 0; /* maint register */
int32 tutc = 0; /* tape control */
int32 tuiff = 0; /* INTR flip/flop */
int32 tu_time = 10; /* record latency */
int32 tu_stopioe = 1; /* stop on error */
int32 tu_log = 0; /* debug */
@ -310,6 +332,7 @@ REG tu_reg[] = {
{ ORDATA (MTDB, tudb, 16) },
{ ORDATA (MTMR, tumr, 16) },
{ ORDATA (MTTC, tutc, 16) },
{ FLDATA (IFF, tuiff, 0) },
{ FLDATA (INT, int_req, INT_V_TU) },
{ FLDATA (DONE, tucs1, CSR_V_DONE) },
{ FLDATA (IE, tucs1, CSR_V_IE) },
@ -379,7 +402,8 @@ if (reg_in_fmtr[j] && (fmtr != 0)) { /* nx formatter */
update_tucs (0, drv); /* update status */
switch (j) { /* decode PA<4:1> */
case 000: /* MTCS1 */
*data = tucs1;
if (fmtr != 0) *data = tucs1 & ~CS1_DRV;
else *data = tucs1;
break;
case 001: /* MTWC */
*data = tuwc;
@ -448,21 +472,24 @@ if (reg_in_fmtr1[j] && ((tucs1 & CS1_DONE) == 0)) { /* formatter busy? */
switch (j) { /* decode PA<4:1> */
case 000: /* MTCS1 */
if ((access == WRITEB) && (PA & 1)) data = data << 8;
else { if ((data & CS1_IE) == 0) int_req = int_req & ~INT_TU;
else if (data & CS1_DONE) int_req = int_req | INT_TU; }
if (data & CS1_TRE) { /* error clear? */
tucs1 = tucs1 & ~CS1_TRE; /* clr CS1<TRE> */
tucs2 = tucs2 & ~CS2_ERR; } /* clr CS2<15:8> */
if (access == WRITEB) data = (tucs1 & /* merge data */
((PA & 1)? 0377: 0177400)) | data;
tucs1 = (tucs1 & ~CS1_RW) | (data & CS1_RW);
if (data & CS1_GO) { /* new command? */
if ((access == WRITE) || (PA & 1)) { /* hi byte write? */
if (tucs1 & CS1_DONE) /* done set? */
tucs1 = (tucs1 & ~CS1_UAE) | (data & CS1_UAE); }
if ((access == WRITE) || !(PA & 1)) { /* lo byte write? */
if ((data & CS1_DONE) && (data & CS1_IE)) /* to DONE+IE? */
tuiff = 1; /* set CSTB INTR */
tucs1 = (tucs1 & ~CS1_IE) | (data & CS1_IE);
if (fmtr != 0) { /* nx formatter? */
tucs2 = tucs2 | CS2_NEF; /* set error flag */
update_tucs (CS1_SC, drv); /* request intr */
return SCPE_OK; }
if (tucs1 & CS1_DONE) tu_go (drv); /* start if not busy */
else tucs2 = tucs2 | CS2_PGE; } /* else prog error */
cs1f = CS1_SC; } /* req interrupt */
else if (tucs1 & CS1_GO) { /* busy? */
if (tucs1 & CS1_DONE) tuer = tuer | ER_RMR;
else tucs2 = tucs2 | CS2_PGE; }
else { tucs1 = (tucs1 & ~CS1_DRV) | (data & CS1_DRV);
if (tucs1 & CS1_GO) tu_go (drv); } }
break;
case 001: /* MTWC */
if (access == WRITEB) data = (PA & 1)?
@ -533,8 +560,10 @@ fnc = GET_FNC (tucs1); /* get function */
den = GET_DEN (tutc); /* get density */
uptr = tu_dev.units + drv; /* get unit */
if ((fnc != FNC_FCLR) && /* not clear & err */
((tufs & FS_ERR) || sim_is_active (uptr))) { /* or in motion? */
tucs2 = tucs2 | CS2_PGE; /* set error flag */
((tufs & FS_ERR) || sim_is_active (uptr))) { /* or in motion? */
tuer = tuer | ER_ILF; /* set error flag */
tufs = tufs | FS_ATA; /* exception */
tucs1 = tucs1 & ~CS1_GO; /* clear go */
update_tucs (CS1_SC, drv); /* request intr */
return; }
tufs = tufs & ~FS_ATA; /* clear attention */
@ -621,9 +650,10 @@ DATA_XFER:
/* tuer = tuer | ER_NXF;
/* break; } */
uptr -> USTAT = 0;
tucs1 = tucs1 & ~CS1_DONE; /* clear done */
GO_XFER:
tucs2 = tucs2 & ~CS2_ERR; /* clear errors */
tucs1 = tucs1 & ~(CS1_TRE | CS1_MCPE | CS1_DONE);
tucs1 = tucs1 & ~(CS1_TRE | CS1_MCPE);
tufs = tufs & ~(FS_TMK | FS_ID); /* clear eof, id */
sim_activate (uptr, tu_time);
return;
@ -631,7 +661,9 @@ GO_XFER:
default: /* all others */
tuer = tuer | ER_ILF; /* not supported */
break; } /* end case function */
update_tucs (CS1_SC, drv); /* error, set intr */
tucs1 = tucs1 & ~CS1_GO; /* clear go */
tufs = tufs | FS_ATA; /* set attn */
update_tucs (CS1_SC, drv); /* set intr */
return;
}
@ -851,15 +883,20 @@ update_tucs (CS1_DONE, drv);
return SCPE_OK;
}
/* Controller status update
First update formatter status, then update MTCS1
If optional argument, request interrupt
/* Controller status update
Check for done transition
Update drive status
Update MTCS1
Update interrupt request
*/
void update_tucs (int32 flag, int32 drv)
{
int32 act = sim_is_active (&tu_unit[drv]);
if ((flag & ~tucs1) & CS1_DONE) /* DONE 0 to 1? */
tuiff = (tucs1 & CS1_IE)? 1: 0; /* CSTB INTR <- IE */
if (GET_FMTR (tucs2) == 0) { /* formatter present? */
tufs = (tufs & ~FS_DYN) | FS_FPR;
if (tu_unit[drv].flags & UNIT_ATT) {
@ -871,10 +908,11 @@ if (GET_FMTR (tucs2) == 0) { /* formatter present? */
else tufs = 0;
tucs1 = (tucs1 & ~(CS1_SC | CS1_MCPE | CS1_MBZ)) | CS1_DVA | flag;
if (tucs2 & CS2_ERR) tucs1 = tucs1 | CS1_TRE | CS1_SC;
else if (tucs1 & CS1_TRE) tucs1 = tucs1 | CS1_SC;
if (tufs & FS_ATA) tucs1 = tucs1 | CS1_SC;
if (((tucs1 & CS1_IE) == 0) || ((tucs1 & CS1_DONE) == 0))
int_req = int_req & ~INT_TU;
else if (flag) int_req = int_req | INT_TU;
if (tuiff || ((tucs1 & CS1_SC) && (tucs1 & CS1_DONE) && (tucs1 & CS1_IE)))
int_req = int_req | INT_TU;
else int_req = int_req & ~INT_TU;
if ((tucs1 & CS1_DONE) && tufs && !act) tufs = tufs | FS_RDY;
return;
}
@ -884,6 +922,7 @@ return;
int32 tu_inta (void)
{
tucs1 = tucs1 & ~CS1_IE; /* clear int enable */
tuiff = 0; /* clear CSTB INTR */
return VEC_TU; /* acknowledge */
}
@ -899,6 +938,7 @@ tucs2 = CS2_IR | CS2_OR;
tuba = tufc = 0;
tutc = tuer = 0;
tufs = FS_FPR | FS_RDY;
tuiff = 0; /* clear CSTB INTR */
int_req = int_req & ~INT_TU; /* clear interrupt */
for (u = 0; u < TU_NUMDR; u++) { /* loop thru units */
uptr = tu_dev.units + u;
@ -958,8 +998,8 @@ return SCPE_OK;
static const d10 boot_rom_dec[] = {
0515040000003, /* boot:hrlzi 1,3 ; uba # */
0201000040001, /* movei 0,40001 ; vld,pg 1 */
0713001000000+IO_UBMAP+1, /* wrio 0,763001(1); set ubmap */
0435040000000+IO_TMBASE, /* iori 1,772440 ; rh addr */
0713001000000+IOBA_UBMAP+1, /* wrio 0,763001(1); set ubmap */
0435040000000+IOBA_TU, /* iori 1,772440 ; rh addr */
0202040000000+FE_RHBASE, /* movem 1,FE_RHBASE */
0201000000040, /* movei 0,40 ; ctrl reset */
0713001000010, /* wrio 0,10(1) ; ->MTFS */
@ -996,8 +1036,8 @@ static const d10 boot_rom_dec[] = {
static const d10 boot_rom_its[] = {
0515040000003, /* boot:hrlzi 1,3 ; uba # - not used */
0201000040001, /* movei 0,40001 ; vld,pg 1 */
0714000000000+IO_UBMAP+1, /* iowri 0,763001 ; set ubmap */
0435040000000+IO_TMBASE, /* iori 1,772440 ; rh addr */
0714000000000+IOBA_UBMAP+1, /* iowri 0,763001 ; set ubmap */
0435040000000+IOBA_TU, /* iori 1,772440 ; rh addr */
0202040000000+FE_RHBASE, /* movem 1,FE_RHBASE */
0201000000040, /* movei 0,40 ; ctrl reset */
0714001000010, /* iowri 0,10(1) ; ->MTFS */

View file

@ -25,9 +25,13 @@
cpu PDP-11 CPU (J-11 microprocessor)
15-Oct-01 RMS Added debug logging
08-Oct-01 RMS Fixed bug in revised interrupt logic
07-Sep-01 RMS Revised device disable and interrupt mechanisms
26-Aug-01 RMS Added DZ11 support
10-Aug-01 RMS Removed register from declarations
17-Jul-01 RMS Fixed warning from VC++ 6.0
01-Jun-01 RMS Added DZ11 support
01-Jun-01 RMS Added DZ11 interrupts
23-Apr-01 RMS Added RK611 support
05-Apr-01 RMS Added TS11/TSV05 support
05-Mar-01 RMS Added clock calibration support
@ -151,8 +155,8 @@
lowest priority trap. Traps are processed by trap_vec and trap_clear,
which provide the vector and subordinate traps to clear, respectively.
Variable int_req bit encodes all possible interrupts. It is masked
under the interrupt masks, int_mask[ipl]. If any interrupt request
Array int_req[0:7] bit encodes all possible interrupts. It is masked
under the interrupt priority level, ipl. If any interrupt request
is not masked, the interrupt bit is set in trap_req. While most
interrupts are handled centrally, a device can supply an interrupt
acknowledge routine.
@ -176,8 +180,6 @@
#define calc_is(md) ((md) << VA_V_MODE)
#define calc_ds(md) (calc_is((md)) | ((MMR3 & dsmask[(md)])? VA_DS: 0))
#define calc_MMR1(val) (MMR1 = MMR1? ((val) << 8) | MMR1: (val))
#define calc_ints(lv,rq,tr) (((rq) & int_mask[(lv)])? \
((tr) | TRAP_INT) : ((tr) & ~TRAP_INT))
#define GET_SIGN_W(v) ((v) >> 15)
#define GET_SIGN_B(v) ((v) >> 7)
#define GET_Z(v) ((v) == 0)
@ -196,6 +198,8 @@
/* Global state */
extern FILE *sim_log;
uint16 *M = NULL; /* address of memory */
int32 REGFILE[6][2] = { 0 }; /* R0-R5, two sets */
int32 STACKFILE[4] = { 0 }; /* SP, four modes */
@ -210,7 +214,7 @@ int32 PSW = 0; /* PSW */
int32 N = 0, Z = 0, V = 0, C = 0; /* condition codes */
int32 wait_state = 0; /* wait state */
int32 trap_req = 0; /* trap requests */
int32 int_req = 0; /* interrupt requests */
int32 int_req[IPL_HLVL] = { 0 }; /* interrupt requests */
int32 PIRQ = 0; /* programmed int req */
int32 SR = 0; /* switch register */
int32 DR = 0; /* display register */
@ -235,13 +239,13 @@ int32 stop_trap = 1; /* stop on trap */
int32 stop_vecabort = 1; /* stop on vec abort */
int32 stop_spabort = 1; /* stop on SP abort */
int32 wait_enable = 0; /* wait state enable */
int32 pdp11_log = 0; /* logging */
int32 ibkpt_addr = ILL_ADR_FLAG | VAMASK; /* breakpoint addr */
int32 old_PC = 0; /* previous PC */
int32 dev_enb = (-1) & ~INT_TS; /* dev enables */
jmp_buf save_env; /* abort handler */
int32 dsmask[4] = { MMR3_KDS, MMR3_SDS, 0, MMR3_UDS }; /* dspace enables */
uint32 int_mask[8] = { INT_IPL0, INT_IPL1, INT_IPL2, /* interrupt masks */
INT_IPL3, INT_IPL4, INT_IPL5, INT_IPL6, INT_IPL7 };
extern int32 sim_int_char;
/* Function declarations */
@ -265,6 +269,7 @@ void PWriteW (int32 data, int32 addr);
void PWriteB (int32 data, int32 addr);
t_stat iopageR (int32 *data, int32 addr, int32 access);
t_stat iopageW (int32 data, int32 addr, int32 access);
int32 calc_ints (int32 nipl, int32 trq);
t_stat CPU_rd (int32 *data, int32 addr, int32 access);
t_stat CPU_wr (int32 data, int32 addr, int32 access);
@ -278,64 +283,87 @@ extern t_stat std_rd (int32 *data, int32 addr, int32 access);
extern t_stat std_wr (int32 data, int32 addr, int32 access);
extern t_stat lpt_rd (int32 *data, int32 addr, int32 access);
extern t_stat lpt_wr (int32 data, int32 addr, int32 access);
extern t_stat dz_rd (int32 *data, int32 addr, int32 access);
extern t_stat dz_wr (int32 data, int32 addr, int32 access);
extern t_stat rk_rd (int32 *data, int32 addr, int32 access);
extern t_stat rk_wr (int32 data, int32 addr, int32 access);
extern int32 rk_inta (void);
extern int32 rk_enb;
/* extern t_stat hk_rd (int32 *data, int32 addr, int32 access);
extern t_stat hk_wr (int32 data, int32 addr, int32 access);
extern int32 hk_inta (void); */
extern int32 hk_inta (void);
extern int32 hk_enb; */
extern t_stat rl_rd (int32 *data, int32 addr, int32 access);
extern t_stat rl_wr (int32 data, int32 addr, int32 access);
extern int32 rl_enb;
extern t_stat rp_rd (int32 *data, int32 addr, int32 access);
extern t_stat rp_wr (int32 data, int32 addr, int32 access);
extern int32 rp_inta (void);
extern int32 rp_enb;
extern t_stat rx_rd (int32 *data, int32 addr, int32 access);
extern t_stat rx_wr (int32 data, int32 addr, int32 access);
extern int32 rx_enb;
extern t_stat dt_rd (int32 *data, int32 addr, int32 access);
extern t_stat dt_wr (int32 data, int32 addr, int32 access);
extern int32 dt_enb;
extern t_stat tm_rd (int32 *data, int32 addr, int32 access);
extern t_stat tm_wr (int32 data, int32 addr, int32 access);
extern int32 tm_enb;
extern t_stat ts_rd (int32 *data, int32 addr, int32 access);
extern t_stat ts_wr (int32 data, int32 addr, int32 access);
extern int32 ts_enb;
/* Auxiliary data structures */
struct iolink { /* I/O page linkage */
int32 low; /* low I/O addr */
int32 high; /* high I/O addr */
int32 enb; /* enable mask */
int32 *enb; /* enable flag */
t_stat (*read)(); /* read routine */
t_stat (*write)(); }; /* write routine */
struct iolink iotable[] = {
{ 017777740, 017777777, 0, &CPU_rd, &CPU_wr },
{ 017777546, 017777567, 0, &std_rd, &std_wr },
{ 017777514, 017777517, 0, &lpt_rd, &lpt_wr },
{ 017777400, 017777417, INT_RK, &rk_rd, &rk_wr },
/* { 017777440, 017777477, INT_HK, &hk_rd, &hk_wr }, */
{ 017774400, 017774411, INT_RL, &rl_rd, &rl_wr },
{ 017776700, 017776753, INT_RP, &rp_rd, &rp_wr },
{ 017777170, 017777173, INT_RX, &rx_rd, &rx_wr },
{ 017777340, 017777351, INT_DTA, &dt_rd, &dt_wr },
{ 017772520, 017772533, INT_TM, &tm_rd, &tm_wr },
{ 017772520, 017772523, INT_TS, &ts_rd, &ts_wr },
{ 017777600, 017777677, 0, &APR_rd, &APR_wr },
{ 017772200, 017772377, 0, &APR_rd, &APR_wr },
{ 017777570, 017777577, 0, &SR_MMR012_rd, &SR_MMR012_wr },
{ 017772516, 017772517, 0, &MMR3_rd, &MMR3_wr },
{ 0, 0, 0, NULL, NULL } };
{ 017777740, 017777777, NULL, &CPU_rd, &CPU_wr },
{ 017777546, 017777567, NULL, &std_rd, &std_wr },
{ 017777514, 017777517, NULL, &lpt_rd, &lpt_wr },
{ 017760100, 017760107, NULL, &dz_rd, &dz_wr },
{ 017777400, 017777417, &rk_enb, &rk_rd, &rk_wr },
/* { 017777440, 017777477, &hk_enb, &hk_rd, &hk_wr }, */
{ 017774400, 017774411, &rl_enb, &rl_rd, &rl_wr },
{ 017776700, 017776753, &rp_enb, &rp_rd, &rp_wr },
{ 017777170, 017777173, &rx_enb, &rx_rd, &rx_wr },
{ 017777340, 017777351, &dt_enb, &dt_rd, &dt_wr },
{ 017772520, 017772533, &tm_enb, &tm_rd, &tm_wr },
{ 017772520, 017772523, &ts_enb, &ts_rd, &ts_wr },
{ 017777600, 017777677, NULL, &APR_rd, &APR_wr },
{ 017772200, 017772377, NULL, &APR_rd, &APR_wr },
{ 017777570, 017777577, NULL, &SR_MMR012_rd, &SR_MMR012_wr },
{ 017772516, 017772517, NULL, &MMR3_rd, &MMR3_wr },
{ 0, 0, NULL, NULL, NULL } };
int32 int_vec[32] = { /* int req to vector */
0, 0, 0, VEC_PIRQ, VEC_CLK, VEC_DTA, 0, VEC_PIRQ,
VEC_RK, VEC_RL, VEC_RX, VEC_TM, VEC_RP, VEC_TS, VEC_HK, 0,
VEC_DZ0RX, VEC_DZ0TX, 0, VEC_PIRQ, VEC_TTI, VEC_TTO, VEC_PTR, VEC_PTP,
VEC_LPT, 0, 0, 0, VEC_PIRQ, VEC_PIRQ, VEC_PIRQ, VEC_PIRQ };
int32 int_vec[IPL_HLVL][32] = { /* int req to vector */
{ 0 }, /* IPL 0 */
{ VEC_PIRQ }, /* IPL 1 */
{ VEC_PIRQ }, /* IPL 2 */
{ VEC_PIRQ }, /* IPL 3 */
{ VEC_TTI, VEC_TTO, VEC_PTR, VEC_PTP, /* IPL 4 */
VEC_LPT, VEC_PIRQ },
{ VEC_RK, VEC_RL, VEC_RX, VEC_TM, /* IPL 5 */
VEC_RP, VEC_TS, VEC_HK, VEC_DZRX,
VEC_DZTX, VEC_PIRQ },
{ VEC_CLK, VEC_DTA, VEC_PIRQ }, /* IPL 6 */
{ VEC_PIRQ } }; /* IPL 7 */
int32 (*int_ack[32])() = { /* int ack routines */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
&rk_inta, NULL, NULL, NULL, &rp_inta, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
int32 (*int_ack[IPL_HLVL][32])() = { /* int ack routines */
{ NULL }, /* IPL 0 */
{ NULL }, /* IPL 1 */
{ NULL }, /* IPL 2 */
{ NULL }, /* IPL 3 */
{ NULL }, /* IPL 4 */
{ &rk_inta, NULL, NULL, NULL, /* IPL 5 */
&rp_inta, NULL, NULL, NULL },
{ NULL }, /* IPL 6 */
{ NULL } }; /* IPL 7 */
int32 trap_vec[TRAP_V_MAX] = { /* trap req to vector */
VEC_RED, VEC_ODD, VEC_MME, VEC_NXM,
@ -398,7 +426,7 @@ REG cpu_reg[] = {
{ ORDATA (MAINT, MAINT, 16) },
{ ORDATA (HITMISS, HITMISS, 16) },
{ ORDATA (CPUERR, CPUERR, 16) },
{ ORDATA (INT, int_req, 32), REG_RO },
{ BRDATA (IREQ, int_req, 8, 32, IPL_HLVL), REG_RO },
{ ORDATA (TRAPS, trap_req, TRAP_V_MAX) },
{ ORDATA (PIRQ, PIRQ, 16) },
{ FLDATA (WAIT, wait_state, 0) },
@ -406,6 +434,7 @@ REG cpu_reg[] = {
{ ORDATA (STOP_TRAPS, stop_trap, TRAP_V_MAX) },
{ FLDATA (STOP_VECA, stop_vecabort, 0) },
{ FLDATA (STOP_SPA, stop_spabort, 0) },
{ ORDATA (DBGLOG, pdp11_log, 16), REG_HIDDEN },
{ ORDATA (FAC0H, FR[0].h, 32) },
{ ORDATA (FAC0L, FR[0].l, 32) },
{ ORDATA (FAC1H, FR[1].h, 32) },
@ -568,7 +597,7 @@ extern UNIT *sim_clock_queue;
extern UNIT clk_unit;
int32 IR, srcspec, srcreg, dstspec, dstreg;
int32 src, src2, dst;
int32 i, t, sign, oldrs, trapnum;
int32 i, j, t, sign, oldrs, trapnum;
int32 abortval;
volatile int32 trapea;
t_stat reason;
@ -602,7 +631,7 @@ isenable = calc_is (cm);
dsenable = calc_ds (cm);
CPU_wr (PIRQ, 017777772, WRITE); /* rewrite PIRQ */
trap_req = calc_ints (ipl, int_req, trap_req);
trap_req = calc_ints (ipl, trap_req);
trapea = 0;
reason = 0;
sim_rtc_init (clk_unit.wait); /* init clock */
@ -641,28 +670,38 @@ if (abortval != 0) {
while (reason == 0) {
if (sim_interval <= 0) { /* check clock queue */
reason = sim_process_event ();
trap_req = calc_ints (ipl, int_req, trap_req);
trap_req = calc_ints (ipl, trap_req);
continue; }
if (trap_req) { /* check traps, ints */
trapea = 0; /* assume srch fails */
if (t = trap_req & TRAP_ALL) { /* if a trap */
for (trapnum = 0; trapnum < TRAP_V_MAX; trapnum++) {
if ((t >> trapnum) & 1) {
trapea = trap_vec[trapnum];
trap_req = trap_req & ~trap_clear[trapnum];
if ((stop_trap >> trapnum) & 1)
reason = trapnum + 1;
break; } } }
else if (t = int_req & int_mask[ipl]) { /* if an interrupt */
for (i = 0; i < 32; i++) {
if ((t >> i) & 1) {
int_req = int_req & ~(1u << i);
if (int_ack[i]) trapea = int_ack[i]();
else trapea = int_vec[i];
trapnum = TRAP_V_MAX;
break; } } }
for (trapnum = 0; trapnum < TRAP_V_MAX; trapnum++) {
if ((t >> trapnum) & 1) {
trapea = trap_vec[trapnum];
trap_req = trap_req & ~trap_clear[trapnum];
if ((stop_trap >> trapnum) & 1)
reason = trapnum + 1;
break; } /* end if t & 1 */
} /* end for */
} /* end if */
else {
for (i = IPL_HLVL - 1; (trapea == 0) && (i > ipl); i--) {
t = int_req[i]; /* get level */
for (j = 0; t && (j < 32); j++) { /* srch level */
if ((t >> j) & 1) { /* irq found? */
int_req[i] = int_req[i] & ~(1u << j);
if (int_ack[i][j]) trapea = int_ack[i][j]();
else trapea = int_vec[i][j];
trapnum = TRAP_V_MAX;
if (DBG_LOG (LOG_CPU_I)) fprintf (sim_log,
">>CPU, lvl=%d, flag=%d, vec=%o\n",
i, j, trapea);
break; } /* end if t & 1 */
} /* end for j */
} /* end for i */
} /* end else */
if (trapea == 0) { /* nothing to do? */
trap_req = calc_ints (ipl, int_req, 0); /* recalculate */
trap_req = calc_ints (ipl, 0); /* recalculate */
continue; } /* back to fetch */
/* Process a trap or interrupt
@ -707,7 +746,7 @@ if (trap_req) { /* check traps, ints */
JMP_PC (src);
isenable = calc_is (cm);
dsenable = calc_ds (cm);
trap_req = calc_ints (ipl, int_req, trap_req);
trap_req = calc_ints (ipl, trap_req);
if ((SP < STKLIM) && (cm == KERNEL) &&
(trapnum != TRAP_V_RED) && (trapnum != TRAP_V_YEL)) {
setTRAP (TRAP_YEL);
@ -768,7 +807,8 @@ case 000:
if (cm == KERNEL) {
reset_all (1);
PIRQ = 0;
int_req = 0;
for (i = 0; i < IPL_HLVL; i++)
int_req[i] = 0;
MMR0 = MMR0 & ~(MMR0_MME | MMR0_FREEZE);
MMR3 = 0;
trap_req = trap_req & ~TRAP_INT;
@ -796,7 +836,7 @@ case 000:
Z = (src2 >> PSW_V_Z) & 01;
V = (src2 >> PSW_V_V) & 01;
C = (src2 >> PSW_V_C) & 01;
trap_req = calc_ints (ipl, int_req, trap_req);
trap_req = calc_ints (ipl, trap_req);
isenable = calc_is (cm);
dsenable = calc_ds (cm);
if (rs != oldrs) {
@ -830,7 +870,7 @@ case 000:
break; }
if (IR < 000240) { /* SPL */
if (cm == KERNEL) ipl = IR & 07;
trap_req = calc_ints (ipl, int_req, trap_req);
trap_req = calc_ints (ipl, trap_req);
break; } /* end if SPL */
if (IR < 000260) { /* clear CC */
if (IR & 010) N = 0;
@ -1503,7 +1543,7 @@ case 010:
dst = dstreg? R[dstspec]: ReadB (GeteaB (dstspec));
if (cm == KERNEL) {
ipl = (dst >> PSW_V_IPL) & 07;
trap_req = calc_ints (ipl, int_req, trap_req); }
trap_req = calc_ints (ipl, trap_req); }
N = (dst >> PSW_V_N) & 01;
Z = (dst >> PSW_V_Z) & 01;
V = (dst >> PSW_V_V) & 01;
@ -2068,9 +2108,9 @@ struct iolink *p;
for (p = &iotable[0]; p -> low != 0; p++ ) {
if ((pa >= p -> low) && (pa <= p -> high) &&
((p -> enb == 0) || (dev_enb & p -> enb))) {
((p -> enb == NULL) || *p -> enb)) {
stat = p -> read (data, pa, access);
trap_req = calc_ints (ipl, int_req, trap_req);
trap_req = calc_ints (ipl, trap_req);
return stat; } }
return SCPE_NXM;
}
@ -2082,12 +2122,23 @@ struct iolink *p;
for (p = &iotable[0]; p -> low != 0; p++ ) {
if ((pa >= p -> low) && (pa <= p -> high) &&
((p -> enb == 0) || (dev_enb & p -> enb))) {
((p -> enb == NULL) || *p -> enb)) {
stat = p -> write (data, pa, access);
trap_req = calc_ints (ipl, int_req, trap_req);
trap_req = calc_ints (ipl, trap_req);
return stat; } }
return SCPE_NXM;
}
/* Calculate interrupt outstanding */
int32 calc_ints (int32 nipl, int32 trq)
{
int32 i;
for (i = IPL_HLVL - 1; i > nipl; i--) {
if (int_req[i]) return (trq | TRAP_INT); }
return (trq & ~TRAP_INT);
}
/* I/O page routines for CPU registers
@ -2133,13 +2184,13 @@ default: /* MMR1, MMR2 */
return SCPE_OK; } /* end switch pa */
}
t_stat MMR3_rd (int32 *data, int32 pa, int32 access) /* MMR3 */
t_stat MMR3_rd (int32 *data, int32 pa, int32 access) /* MMR3 */
{
*data = MMR3 & MMR3_IMP;
return SCPE_OK;
}
t_stat MMR3_wr (int32 data, int32 pa, int32 access) /* MMR3 */
t_stat MMR3_wr (int32 data, int32 pa, int32 access) /* MMR3 */
{
if (pa & 1) return SCPE_OK;
MMR3 = data & MMR3_RW;
@ -2267,17 +2318,22 @@ case 015: /* PIRQ */
if (access == WRITEB) {
if (pa & 1) data = data << 8;
else return SCPE_OK; }
int_req = int_req & ~(INT_PIR7 + INT_PIR6 + INT_PIR5 + INT_PIR4 +
INT_PIR3 + INT_PIR2 + INT_PIR1);
PIRQ = data & PIRQ_RW;
pl = 0;
if (PIRQ & PIRQ_PIR1) { int_req = int_req | INT_PIR1; pl = 0042; }
if (PIRQ & PIRQ_PIR2) { int_req = int_req | INT_PIR2; pl = 0104; }
if (PIRQ & PIRQ_PIR3) { int_req = int_req | INT_PIR3; pl = 0146; }
if (PIRQ & PIRQ_PIR4) { int_req = int_req | INT_PIR4; pl = 0210; }
if (PIRQ & PIRQ_PIR5) { int_req = int_req | INT_PIR5; pl = 0252; }
if (PIRQ & PIRQ_PIR6) { int_req = int_req | INT_PIR6; pl = 0314; }
if (PIRQ & PIRQ_PIR7) { int_req = int_req | INT_PIR7; pl = 0356; }
if (PIRQ & PIRQ_PIR1) { SET_INT (PIR1); pl = 0042; }
else CLR_INT (PIR1);
if (PIRQ & PIRQ_PIR2) { SET_INT (PIR2); pl = 0104; }
else CLR_INT (PIR2);
if (PIRQ & PIRQ_PIR3) { SET_INT (PIR3); pl = 0146; }
else CLR_INT (PIR3);
if (PIRQ & PIRQ_PIR4) { SET_INT (PIR4); pl = 0210; }
else CLR_INT (PIR4);
if (PIRQ & PIRQ_PIR5) { SET_INT (PIR5); pl = 0252; }
else CLR_INT (PIR5);
if (PIRQ & PIRQ_PIR6) { SET_INT (PIR6); pl = 0314; }
else CLR_INT (PIR6);
if (PIRQ & PIRQ_PIR7) { SET_INT (PIR7); pl = 0356; }
else CLR_INT (PIR7);
PIRQ = PIRQ | pl;
return SCPE_OK;

View file

@ -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
19-Oct-01 RMS Added DZ definitions
15-Oct-01 RMS Added logging capabilities
07-Sep-01 RMS Revised for multilevel interrupts
01-Jun-01 RMS Added DZ11 support
23-Apr-01 RMS Added RK611 support
05-Apr-01 RMS Added TS11/TSV05 support
@ -237,40 +240,42 @@ typedef struct fpac fpac_t;
#define STOP_SPABORT TRAP_V_MAX + 5 /* abort trap push */
#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* cond error return */
/* Interrupt assignments, priority is right to left
/* DZ11 parameters */
<3:0> = BR7, <3> = PIR7
<7:4> = BR6, <7> = PIR6
<19:8> = BR5, <19> = PIR5
<28:20> = BR4, <28> = PIR4
<29> = PIR3
<30> = PIR2
<31> = PIR1
*/
#define DZ_MUXES 1 /* # of muxes */
#define DZ_LINES 8 /* lines per mux */
#define INT_V_PIR7 3
#define INT_V_CLK 4
#define INT_V_DTA 5
#define INT_V_PIR6 7
#define INT_V_RK 8
#define INT_V_RL 9
#define INT_V_RX 10
#define INT_V_TM 11
#define INT_V_RP 12
#define INT_V_TS 13
#define INT_V_HK 14
#define INT_V_DZ0RX 16
#define INT_V_DZ0TX 17
#define INT_V_PIR5 19
#define INT_V_TTI 20
#define INT_V_TTO 21
#define INT_V_PTR 22
#define INT_V_PTP 23
#define INT_V_LPT 24
#define INT_V_PIR4 28
#define INT_V_PIR3 29
#define INT_V_PIR2 30
#define INT_V_PIR1 31
/* Interrupt assignments; within each level, priority is right to left */
#define IPL_HLVL 8 /* # int levels */
#define INT_V_PIR7 0 /* BR7 */
#define INT_V_CLK 0 /* BR6 */
#define INT_V_DTA 1
#define INT_V_PIR6 2
#define INT_V_RK 0 /* BR5 */
#define INT_V_RL 1
#define INT_V_RX 2
#define INT_V_TM 3
#define INT_V_RP 4
#define INT_V_TS 5
#define INT_V_HK 6
#define INT_V_DZRX 7
#define INT_V_DZTX 8
#define INT_V_PIR5 9
#define INT_V_TTI 0 /* BR4 */
#define INT_V_TTO 1
#define INT_V_PTR 2
#define INT_V_PTP 3
#define INT_V_LPT 4
#define INT_V_PIR4 5
#define INT_V_PIR3 0 /* BR3 */
#define INT_V_PIR2 0 /* BR2 */
#define INT_V_PIR1 0 /* BR1 */
#define INT_PIR7 (1u << INT_V_PIR7)
#define INT_CLK (1u << INT_V_CLK)
@ -283,8 +288,8 @@ typedef struct fpac fpac_t;
#define INT_RP (1u << INT_V_RP)
#define INT_TS (1u << INT_V_TS)
#define INT_HK (1u << INT_V_HK)
#define INT_DZ0RX (1u << INT_V_DZ0RX)
#define INT_DZ0TX (1u << INT_V_DZ0TX)
#define INT_DZRX (1u << INT_V_DZRX)
#define INT_DZTX (1u << INT_V_DZTX)
#define INT_PIR5 (1u << INT_V_PIR5)
#define INT_PTR (1u << INT_V_PTR)
#define INT_PTP (1u << INT_V_PTP)
@ -296,14 +301,30 @@ typedef struct fpac fpac_t;
#define INT_PIR2 (1u << INT_V_PIR2)
#define INT_PIR1 (1u << INT_V_PIR1)
#define INT_IPL7 0x00000000 /* int level masks */
#define INT_IPL6 0x0000000F
#define INT_IPL5 0x000000FF
#define INT_IPL4 0x000FFFFF
#define INT_IPL3 0x1FFFFFFF
#define INT_IPL2 0x3FFFFFFF
#define INT_IPL1 0x7FFFFFFF
#define INT_IPL0 0xFFFFFFFF
#define IPL_CLK 6 /* int pri levels */
#define IPL_DTA 6
#define IPL_RK 5
#define IPL_RL 5
#define IPL_RX 5
#define IPL_TM 5
#define IPL_RP 5
#define IPL_TS 5
#define IPL_HK 5
#define IPL_DZRX 5
#define IPL_DZTX 5
#define IPL_PTR 4
#define IPL_PTP 4
#define IPL_TTI 4
#define IPL_TTO 4
#define IPL_LPT 4
#define IPL_PIR7 7
#define IPL_PIR6 6
#define IPL_PIR5 5
#define IPL_PIR4 4
#define IPL_PIR3 3
#define IPL_PIR2 2
#define IPL_PIR1 1
#define VEC_PIRQ 0240 /* interrupt vectors */
#define VEC_TTI 0060
@ -320,8 +341,14 @@ typedef struct fpac fpac_t;
#define VEC_TS 0224
#define VEC_RP 0254
#define VEC_RX 0264
#define VEC_DZ0RX 0310
#define VEC_DZ0TX 0314
#define VEC_DZRX 0310
#define VEC_DZTX 0314
/* Interrupt macros */
#define IREQ(dv) int_req[IPL_##dv]
#define SET_INT(dv) IREQ(dv) = IREQ(dv) | (INT_##dv)
#define CLR_INT(dv) IREQ(dv) = IREQ(dv) & ~(INT_##dv)
/* CPU and FPU macros */
@ -331,3 +358,15 @@ typedef struct fpac fpac_t;
#define ABORT(val) longjmp (save_env, (val))
#define SP R[6]
#define PC R[7]
/* Logging */
#define LOG_CPU_I 00000001
#define LOG_RP 00000010
#define LOG_TS 00000020
#define LOG_TC_MS 00000100
#define LOG_TC_RW 00000200
#define LOG_TC_RA 00000400
#define LOG_TC_BL 00001000
#define DBG_LOG(x) (sim_log && (pdp11_log & (x)))

30
pdp11_dz.c Normal file
View file

@ -0,0 +1,30 @@
/* pdp11_dz.c: DZ11 terminal multiplexor simulator
Copyright (c) 1993-2001, 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.
dz DZ11 terminal multiplexor
*/
#include "pdp11_defs.h"
#include "dec_dz.h"

View file

@ -25,6 +25,7 @@
lpt LP11 line printer
07-Sep-01 RMS Revised interrupt mechanism
30-Oct-00 RMS Standardized register naming
*/
@ -33,7 +34,7 @@
#define LPTCSR_IMP (CSR_ERR + CSR_DONE + CSR_IE) /* implemented */
#define LPTCSR_RW (CSR_IE) /* read/write */
extern int32 int_req;
extern int32 int_req[IPL_HLVL];
int32 lpt_csr = 0; /* control/status */
int32 lpt_stopioe = 0; /* stop on error */
t_stat lpt_svc (UNIT *uptr);
@ -54,7 +55,7 @@ UNIT lpt_unit = {
REG lpt_reg[] = {
{ ORDATA (BUF, lpt_unit.buf, 8) },
{ ORDATA (CSR, lpt_csr, 16) },
{ FLDATA (INT, int_req, INT_V_LPT) },
{ FLDATA (INT, IREQ (LPT), INT_V_LPT) },
{ FLDATA (ERR, lpt_csr, CSR_V_ERR) },
{ FLDATA (DONE, lpt_csr, CSR_V_DONE) },
{ FLDATA (IE, lpt_csr, CSR_V_IE) },
@ -90,13 +91,13 @@ t_stat lpt_wr (int32 data, int32 PA, int32 access)
{
if ((PA & 02) == 0) { /* csr */
if (PA & 1) return SCPE_OK;
if ((data & CSR_IE) == 0) int_req = int_req & ~INT_LPT;
if ((data & CSR_IE) == 0) CLR_INT (LPT);
else if ((lpt_csr & (CSR_DONE + CSR_IE)) == CSR_DONE)
int_req = int_req | INT_LPT;
SET_INT (LPT);
lpt_csr = (lpt_csr & ~LPTCSR_RW) | (data & LPTCSR_RW); }
else { if ((PA & 1) == 0) lpt_unit.buf = data & 0177; /* buffer */
lpt_csr = lpt_csr & ~CSR_DONE;
int_req = int_req & ~INT_LPT;
CLR_INT (LPT);
if ((lpt_unit.buf == 015) || (lpt_unit.buf == 014) ||
(lpt_unit.buf == 012)) sim_activate (&lpt_unit, lpt_unit.wait);
else sim_activate (&lpt_unit, 0); }
@ -106,7 +107,7 @@ return SCPE_OK;
t_stat lpt_svc (UNIT *uptr)
{
lpt_csr = lpt_csr | CSR_ERR | CSR_DONE;
if (lpt_csr & CSR_IE) int_req = int_req | INT_LPT;
if (lpt_csr & CSR_IE) SET_INT (LPT);
if ((lpt_unit.flags & UNIT_ATT) == 0)
return IORETURN (lpt_stopioe, SCPE_UNATT);
if (putc (lpt_unit.buf & 0177, lpt_unit.fileref) == EOF) {
@ -123,7 +124,7 @@ t_stat lpt_reset (DEVICE *dptr)
lpt_unit.buf = 0;
lpt_csr = CSR_DONE;
if ((lpt_unit.flags & UNIT_ATT) == 0) lpt_csr = lpt_csr | CSR_ERR;
int_req = int_req & ~INT_LPT;
CLR_INT (LPT);
sim_cancel (&lpt_unit); /* deactivate unit */
return SCPE_OK;
}

View file

@ -25,6 +25,7 @@
rk RK11/RK05 cartridge disk
07-Sep-01 RMS Revised device disable and interrupt mechanisms
26-Apr-01 RMS Added device enable/disable support
25-Mar-01 RMS Fixed block fill calculation
15-Feb-01 RMS Corrected bootstrap string
@ -161,7 +162,7 @@
#define MAX(x,y) (((x) > (y))? (x): (y))
extern uint16 *M; /* memory */
extern int32 int_req, dev_enb;
extern int32 int_req[IPL_HLVL];
extern UNIT cpu_unit;
int32 rkcs = 0; /* control/status */
int32 rkds = 0; /* drive status */
@ -174,6 +175,7 @@ int32 last_drv = 0; /* last r/w drive */
int32 rk_stopioe = 1; /* stop on error */
int32 rk_swait = 10; /* seek time */
int32 rk_rwait = 10; /* rotate time */
int32 rk_enb = 1; /* device enable */
t_stat rk_svc (UNIT *uptr);
t_stat rk_reset (DEVICE *dptr);
void rk_go (void);
@ -208,7 +210,7 @@ REG rk_reg[] = {
{ ORDATA (RKER, rker, 16) },
{ ORDATA (INTQ, rkintq, 9) },
{ ORDATA (DRVN, last_drv, 3) },
{ FLDATA (INT, int_req, INT_V_RK) },
{ FLDATA (INT, IREQ (RK), INT_V_RK) },
{ FLDATA (ERR, rkcs, CSR_V_ERR) },
{ FLDATA (DONE, rkcs, CSR_V_DONE) },
{ FLDATA (IE, rkcs, CSR_V_IE) },
@ -231,7 +233,7 @@ REG rk_reg[] = {
{ GRDATA (FLG7, rk_unit[7].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
REG_HRO },
{ FLDATA (STOP_IOE, rk_stopioe, 0) },
{ FLDATA (*DEVENB, dev_enb, INT_V_RK), REG_HRO },
{ FLDATA (*DEVENB, rk_enb, 0), REG_HRO },
{ NULL } };
MTAB rk_mod[] = {
@ -313,10 +315,10 @@ case 2: /* RKCS */
(rkcs & 0377) | (data << 8): (rkcs & ~0377) | data;
if ((data & CSR_IE) == 0) { /* int disable? */
rkintq = 0; /* clr int queue */
int_req = int_req & ~INT_RK; } /* clr int request */
CLR_INT (RK); } /* clr int request */
else if ((rkcs & (CSR_DONE + CSR_IE)) == CSR_DONE) {
rkintq = rkintq | RK_CTLI; /* queue ctrl int */
int_req = int_req | INT_RK; } /* set int request */
SET_INT (RK); } /* set int request */
rkcs = (rkcs & ~RKCS_RW) | (data & RKCS_RW);
if ((rkcs & CSR_DONE) && (data & CSR_GO)) rk_go (); /* new function? */
return SCPE_OK;
@ -354,7 +356,7 @@ if (func == RKCS_CTLRESET) { /* control reset? */
rkba = 0;
rkcs = CSR_DONE;
rkintq = 0; /* clr int queue */
int_req = int_req & ~INT_RK; /* clr int request */
CLR_INT (RK); /* clr int request */
return; }
rker = rker & ~RKER_SOFT; /* clear soft errors */
if (rker == 0) rkcs = rkcs & ~RKCS_ERR; /* redo summary */
@ -420,9 +422,9 @@ if (uptr -> FUNC == RKCS_SEEK) { /* seek */
rkcs = rkcs | RKCS_SCP; /* set seek done */
if (rkcs & CSR_IE) { /* ints enabled? */
rkintq = rkintq | RK_SCPI (drv); /* queue request */
if (rkcs & CSR_DONE) int_req = int_req | INT_RK; }
if (rkcs & CSR_DONE) SET_INT (RK); }
else { rkintq = 0; /* clear queue */
int_req = int_req & ~INT_RK; } /* clear interrupt */
CLR_INT (RK); } /* clear interrupt */
return SCPE_OK; }
if ((uptr -> flags & UNIT_ATT) == 0) { /* attached? */
@ -499,9 +501,9 @@ void rk_set_done (int32 error)
if (rker & RKER_HARD) rkcs = rkcs | RKCS_HERR; }
if (rkcs & CSR_IE) { /* int enable? */
rkintq = rkintq | RK_CTLI; /* set ctrl int */
int_req = int_req | INT_RK; } /* request int */
SET_INT (RK); } /* request int */
else { rkintq = 0; /* clear queue */
int_req = int_req & ~INT_RK; }
CLR_INT (RK); }
return;
}
@ -509,7 +511,7 @@ void rk_clr_done (void)
{
rkcs = rkcs & ~CSR_DONE; /* clear done */
rkintq = rkintq & ~RK_CTLI; /* clear ctl int */
int_req = int_req & ~INT_RK; /* clear int req */
CLR_INT (RK); /* clear int req */
return;
}
@ -520,7 +522,7 @@ int32 i;
for (i = 0; i <= RK_NUMDR; i++) { /* loop thru intq */
if (rkintq & (1u << i)) { /* bit i set? */
rkintq = rkintq & ~(1u << i); /* clear bit i */
if (rkintq) int_req = int_req | INT_RK; /* queue next */
if (rkintq) SET_INT (RK); /* queue next */
rkds = (rkds & ~RKDS_ID) | /* id drive */
(((i == 0)? last_drv: i - 1) << RKDS_V_ID);
return VEC_RK; } } /* return vector */
@ -538,7 +540,7 @@ UNIT *uptr;
rkcs = CSR_DONE;
rkda = rkba = rker = rkds = 0;
rkintq = last_drv = 0;
int_req = int_req & ~INT_RK;
CLR_INT (RK);
for (i = 0; i < RK_NUMDR; i++) {
uptr = rk_dev.units + i;
sim_cancel (uptr);
@ -549,8 +551,8 @@ return SCPE_OK;
/* Device bootstrap */
#define BOOT_START 02000 /* start */
#define BOOT_UNIT 02006 /* where to store unit number */
#define BOOT_START 02000 /* start */
#define BOOT_UNIT 02006 /* unit number */
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int32))
static const int32 boot_rom[] = {

View file

@ -25,6 +25,7 @@
rl RL11(RLV12)/RL01/RL02 cartridge disk
07-Sep-01 RMS Revised device disable and interrupt mechanisms
20-Aug-01 RMS Added bad block option in attach
17-Jul-01 RMS Fixed warning from VC++ 6.0
26-Apr-01 RMS Added device enable/disable support
@ -156,7 +157,7 @@
#define RLBAE_IMP 0000077 /* implemented */
extern uint16 *M; /* memory */
extern int32 int_req, dev_enb;
extern int32 int_req[IPL_HLVL];
extern UNIT cpu_unit;
int32 rlcs = 0; /* control/status */
int32 rlba = 0; /* memory address */
@ -166,6 +167,7 @@ int32 rlmp = 0, rlmp1 = 0, rlmp2 = 0; /* mp register queue */
int32 rl_swait = 10; /* seek wait */
int32 rl_rwait = 10; /* rotate wait */
int32 rl_stopioe = 1; /* stop on error */
int32 rl_enb = 1; /* device enable */
t_stat rl_svc (UNIT *uptr);
t_stat rl_reset (DEVICE *dptr);
void rl_set_done (int32 error);
@ -201,7 +203,7 @@ REG rl_reg[] = {
{ ORDATA (RLMP, rlmp, 16) },
{ ORDATA (RLMP1, rlmp1, 16) },
{ ORDATA (RLMP2, rlmp2, 16) },
{ FLDATA (INT, int_req, INT_V_RL) },
{ FLDATA (INT, IREQ (RL), INT_V_RL) },
{ FLDATA (ERR, rlcs, CSR_V_ERR) },
{ FLDATA (DONE, rlcs, CSR_V_DONE) },
{ FLDATA (IE, rlcs, CSR_V_IE) },
@ -220,7 +222,7 @@ REG rl_reg[] = {
{ DRDATA (CAPAC2, rl_unit[2].capac, 32), PV_LEFT + REG_HRO },
{ DRDATA (CAPAC3, rl_unit[3].capac, 32), PV_LEFT + REG_HRO },
{ FLDATA (STOP_IOE, rl_stopioe, 0) },
{ FLDATA (*DEVENB, dev_enb, INT_V_RL), REG_HRO },
{ FLDATA (*DEVENB, rl_enb, 0), REG_HRO },
{ NULL } };
MTAB rl_mod[] = {
@ -300,12 +302,12 @@ case 0: /* RLCS */
rlcs = (rlcs & ~RLCS_RW) | (data & RLCS_RW);
rlbae = (rlbae & ~RLCS_M_MEX) | ((rlcs >> RLCS_V_MEX) & RLCS_M_MEX);
if (data & CSR_DONE) { /* ready set? */
if ((data & CSR_IE) == 0) int_req = int_req & ~INT_RL;
if ((data & CSR_IE) == 0) CLR_INT (RL);
else if ((rlcs & (CSR_DONE + CSR_IE)) == CSR_DONE)
int_req = int_req | INT_RL;
SET_INT (RL);
return SCPE_OK; }
int_req = int_req & ~INT_RL; /* clear interrupt */
CLR_INT (RL); /* clear interrupt */
rlcs = rlcs & ~RLCS_ALLERR; /* clear errors */
switch (GET_FUNC (rlcs)) { /* case on RLCS<3:1> */
case RLCS_NOP: /* nop */
@ -459,8 +461,8 @@ return SCPE_OK;
void rl_set_done (int32 status)
{
rlcs = rlcs | status | CSR_DONE; /* set done */
if (rlcs & CSR_IE) int_req = int_req | INT_RL;
else int_req = int_req & ~INT_RL;
if (rlcs & CSR_IE) SET_INT (RL);
else CLR_INT (RL);
return;
}
@ -476,7 +478,7 @@ UNIT *uptr;
rlcs = CSR_DONE;
rlda = rlba = rlbae = rlmp = rlmp1 = rlmp2 = 0;
int_req = int_req & ~INT_RL;
CLR_INT (RL);
for (i = 0; i < RL_NUMDR; i++) {
uptr = rl_dev.units + i;
sim_cancel (uptr);
@ -523,8 +525,8 @@ return pdp11_bad_block (uptr, RL_NUMSC, RL_NUMWD);
/* Device bootstrap */
#define BOOT_START 02000 /* start */
#define BOOT_UNIT 02006 /* where to store unit number */
#define BOOT_START 02000 /* start */
#define BOOT_UNIT 02006 /* unit number */
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int32))
static const int32 boot_rom[] = {

View file

@ -25,6 +25,13 @@
rp RH/RP/RM moving head disks
23-Oct-01 RMS Fixed bug in error interrupts
15-Oct-01 RMS Added debug logging
05-Oct-01 RMS Rewrote interrupt handling from schematics
02-Oct-01 RMS Revised CS1 write code
30-Sep-01 RMS Moved CS1<5:0> into drives
28-Sep-01 RMS Fixed interrupt handling for SC/ATA
07-Sep-01 RMS Revised device disable and interrupt mechanisms
20-Aug-01 RMS Added bad block option in attach
13-Jul-01 RMS Changed fread call to fxread (found by Peter Schorn)
14-May-01 RMS Added check for unattached drive
@ -46,13 +53,19 @@
systems, this was through many different third party controllers
which emulated the Massbus interface.
WARNING: This controller is somewhat abstract. It is intended to run
the operating system drivers for the PDP-11 operating systems and
nothing more. Most error and all diagnostic functions have been
omitted. In addition, the controller conflates the RP04/05/06 series
controllers with the RM02/03/05/80 series controllers and with the
RP07 controller. There are actually significant differences, which
have been highlighted where noticed.
WARNING: The interupt logic of the RH11/RH70 is unusual and must be
simulated with great precision. The RH11 has an internal interrupt
request flop, CSTB INTR, which is controlled as follows:
- Writing IE and DONE simultaneously sets CSTB INTR
- Controller clear, INIT, and interrupt acknowledge clear CSTB INTR
(and also clear IE)
- A transition of DONE from 0 to 1 sets CSTB from INTR
The output of INTR is OR'd with the AND of RPCS1<SC,DONE,IE> to
create the interrupt request signal. Thus,
- The DONE interrupt is edge sensitive, but the SC interrupt is
level sensitive.
- The DONE interrupt, once set, is not disabled if IE is cleared,
but the SC interrupt is.
*/
#include "pdp11_defs.h"
@ -100,9 +113,12 @@
#define FNC_PRESET 010 /* read-in preset */
#define FNC_PACK 011 /* pack acknowledge */
#define FNC_SEARCH 014 /* search */
#define FNC_XFER 024 /* >=? data xfr */
#define FNC_WCHK 024 /* write check */
#define FNC_WRITE 030 /* write */
#define FNC_WRITEH 031 /* write w/ headers */
#define FNC_READ 034 /* read */
#define FNC_READH 035 /* read w/ headers */
#define CS1_IE CSR_IE /* int enable */
#define CS1_DONE CSR_DONE /* ready */
#define CS1_V_UAE 8 /* Unibus addr ext */
@ -113,7 +129,7 @@
#define CS1_TRE 0040000 /* transfer err */
#define CS1_SC 0100000 /* special cond */
#define CS1_MBZ 0012000
#define CS1_RW (CS1_FNC | CS1_IE | CS1_UAE)
#define CS1_DRV (CS1_FNC | CS1_GO)
#define GET_FNC(x) (((x) >> CS1_V_FNC) & CS1_M_FNC)
/* RPWC - 176702 - word count */
@ -219,7 +235,7 @@
#define GET_DA(c,fs,d) ((((GET_CY (c) * drv_tab[d].surf) + \
GET_SF (fs)) * drv_tab[d].sect) + GET_SC (fs))
/* RPCC - 176736 - current cylinder - unimplemented */
/* RPCC - 176736 - current cylinder */
/* RPER2 - 176740 - error status 2 - drive unsafe conditions - unimplemented */
/* RPER3 - 176742 - error status 3 - more unsafe conditions - unimplemented */
/* RPEC1 - 176744 - ECC status 1 - unimplemented */
@ -312,8 +328,10 @@ struct drvtyp drv_tab[] = {
{ 0 } };
extern uint16 *M; /* memory */
extern int32 int_req, dev_enb;
extern int32 int_req[IPL_HLVL];
extern UNIT cpu_unit;
extern int32 pdp11_log;
extern FILE *sim_log;
int32 rpcs1 = 0; /* control/status 1 */
int32 rpwc = 0; /* word count */
int32 rpba = 0; /* bus address */
@ -331,15 +349,17 @@ int32 rpec1 = 0; /* ECC correction 1 */
int32 rpec2 = 0; /* ECC correction 2 */
int32 rpbae = 0; /* bus address ext */
int32 rpcs3 = 0; /* control/status 3 */
int32 rpiff = 0; /* INTR flip/flop */
int32 rp_stopioe = 1; /* stop on error */
int32 rp_swait = 10; /* seek time */
int32 rp_rwait = 10; /* rotate time */
int32 rp_enb = 1; /* device enable */
int reg_in_drive[32] = {
0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1,
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
void update_rpcs (int32 flags, int32 drv);
void rp_go (int32 drv);
void rp_go (int32 drv, int32 fnc);
t_stat rp_set_size (UNIT *uptr, int32 value);
t_stat rp_set_bad (UNIT *uptr, int32 value);
t_stat rp_svc (UNIT *uptr);
@ -391,7 +411,8 @@ REG rp_reg[] = {
{ ORDATA (RPDB, rpdb, 16) },
{ ORDATA (RPBAE, rpbae, 6) },
{ ORDATA (RPCS3, rpcs3, 16) },
{ FLDATA (INT, int_req, INT_V_RP) },
{ FLDATA (IFF, rpiff, 0) },
{ FLDATA (INT, IREQ (RP), INT_V_RP) },
{ FLDATA (SC, rpcs1, CSR_V_ERR) },
{ FLDATA (DONE, rpcs1, CSR_V_DONE) },
{ FLDATA (IE, rpcs1, CSR_V_IE) },
@ -413,6 +434,14 @@ REG rp_reg[] = {
{ ORDATA (RPDE5, rper1[5], 16) },
{ ORDATA (RPDE6, rper1[6], 16) },
{ ORDATA (RPDE7, rper1[7], 16) },
{ ORDATA (RPFN0, rp_unit[0].FUNC, 5), REG_HRO },
{ ORDATA (RPFN1, rp_unit[1].FUNC, 5), REG_HRO },
{ ORDATA (RPFN2, rp_unit[2].FUNC, 5), REG_HRO },
{ ORDATA (RPFN3, rp_unit[3].FUNC, 5), REG_HRO },
{ ORDATA (RPFN4, rp_unit[4].FUNC, 5), REG_HRO },
{ ORDATA (RPFN5, rp_unit[5].FUNC, 5), REG_HRO },
{ ORDATA (RPFN6, rp_unit[6].FUNC, 5), REG_HRO },
{ ORDATA (RPFN7, rp_unit[7].FUNC, 5), REG_HRO },
{ GRDATA (FLG0, rp_unit[0].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
REG_HRO },
{ GRDATA (FLG1, rp_unit[1].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
@ -430,7 +459,7 @@ REG rp_reg[] = {
{ GRDATA (FLG7, rp_unit[7].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
REG_HRO },
{ FLDATA (STOP_IOE, rp_stopioe, 0) },
{ FLDATA (*DEVENB, dev_enb, INT_V_RP), REG_HRO },
{ FLDATA (*DEVENB, rp_enb, 0), REG_HRO },
{ NULL } };
MTAB rp_mod[] = {
@ -578,9 +607,11 @@ return SCPE_OK;
t_stat rp_wr (int32 data, int32 PA, int32 access)
{
int32 cs1f, drv, i, j;
UNIT *uptr;
cs1f = 0; /* no int on cs1 upd */
drv = GET_UNIT (rpcs2); /* get current unit */
uptr = rp_dev.units + drv; /* get unit */
j = (PA >> 1) & 037; /* get reg offset */
if (reg_in_drive[j] && (rp_unit[drv].flags & UNIT_DIS)) { /* nx disk */
rpcs2 = rpcs2 | CS2_NED; /* set error flag */
@ -594,19 +625,29 @@ if (reg_in_drive[j] && sim_is_active (&rp_unit[drv])) { /* unit busy? */
switch (j) { /* decode PA<5:1> */
case 000: /* RPCS1 */
if ((access == WRITEB) && (PA & 1)) data = data << 8;
else { if ((data & CS1_IE) == 0) int_req = int_req & ~INT_RP;
else if (data & CS1_DONE) int_req = int_req | INT_RP; }
if (data & CS1_TRE) { /* error clear? */
rpcs1 = rpcs1 & ~CS1_TRE; /* clr CS1<TRE> */
rpcs2 = rpcs2 & ~CS2_ERR; } /* clr CS2<15:8> */
if (access == WRITEB) data = (rpcs1 & /* merge data */
((PA & 1)? 0377: 0177400)) | data;
rpcs1 = (rpcs1 & ~CS1_RW) | (data & CS1_RW);
rpbae = (rpbae & ~CS1_M_UAE) | ((rpcs1 >> CS1_V_UAE) & CS1_M_UAE);
if ((access == WRITE) || (PA & 1)) { /* hi byte write? */
if (rpcs1 & CS1_DONE) /* done set? */
rpcs1 = (rpcs1 & ~CS1_UAE) | (data & CS1_UAE); }
if ((access == WRITE) || !(PA & 1)) { /* lo byte write? */
if ((data & CS1_DONE) && (data & CS1_IE)) /* to DONE+IE? */
rpiff = 1; /* set CSTB INTR */
rpcs1 = (rpcs1 & ~CS1_IE) | (data & CS1_IE);
if (uptr -> flags & UNIT_DIS) { /* nx disk? */
rpcs2 = rpcs2 | CS2_NED; /* set error flag */
cs1f = CS1_SC; } /* req interrupt */
else if (sim_is_active (uptr))
rper1[drv] = rper1[drv] | ER1_RMR; /* won't write */
else if (data & CS1_GO) { /* start op */
uptr -> FUNC = GET_FNC (data); /* set func */
if ((uptr -> FUNC >= FNC_XFER) && /* data xfer and */
((rpcs1 & CS1_DONE) == 0)) /* ~rdy? PGE */
rpcs2 = rpcs2 | CS2_PGE;
else rp_go (drv, uptr -> FUNC); } }
rpcs3 = (rpcs3 & ~CS1_IE) | (rpcs1 & CS1_IE);
if (data & CS1_GO) { /* new command? */
if (rpcs1 & CS1_DONE) rp_go (drv); /* start if not busy */
else rpcs2 = rpcs2 | CS2_PGE; } /* else prog error */
rpbae = (rpbae & ~CS1_M_UAE) | ((rpcs1 >> CS1_V_UAE) & CS1_M_UAE);
break;
case 001: /* RPWC */
if (access == WRITEB) data = (PA & 1)?
@ -670,9 +711,6 @@ case 024: /* RPBAE */
case 025: /* RPCS3 */
if ((access == WRITEB) && (PA & 1)) break;
rpcs3 = data & ~CS3_MBZ;
if ((data & CS1_IE) == 0) int_req = int_req & ~INT_RP;
else if (((rpcs1 & CS1_IE) == 0) && (rpcs1 & CS1_DONE))
int_req = int_req | INT_RP;
rpcs1 = (rpcs1 & ~CS1_IE) | (rpcs3 & CS1_IE);
break;
case 005: /* RPDS */
@ -692,30 +730,27 @@ update_rpcs (cs1f, drv); /* update status */
return SCPE_OK;
}
/* Initiate operation */
/* Initiate operation - unit not busy, function set */
void rp_go (int32 drv)
void rp_go (int32 drv, int32 fnc)
{
int32 dc, dtype, fnc;
int32 dc, dtype, t;
UNIT *uptr;
fnc = GET_FNC (rpcs1); /* get function */
if (DBG_LOG (LOG_RP)) fprintf (sim_log,
">>RP%d: fnc=%o, ds=%o, cyl=%o, da=%o, ba=%o, wc=%o\n",
drv, fnc, rpds[drv], rpdc, rpda, (rpbae << 16) | rpba, rpwc);
uptr = rp_dev.units + drv; /* get unit */
if (uptr -> flags & UNIT_DIS) { /* nx unit? */
rpcs2 = rpcs2 | CS2_NED; /* set error flag */
update_rpcs (CS1_SC, drv); /* request intr */
return; }
if (fnc != FNC_DCLR) { /* not clear? */
if ((rpds[drv] & DS_ERR) || /* error or */
((rpds[drv] & DS_RDY) == 0)) { /* not ready? */
rpcs2 = rpcs2 | CS2_PGE; /* set error flag */
update_rpcs (CS1_SC, drv); /* request intr */
return; }
if ((uptr -> flags & UNIT_ATT) == 0) { /* not attached? */
rper1[drv] = rper1[drv] | ER1_UNS; /* unsafe */
update_rpcs (CS1_SC, drv); /* request intr */
return; } }
if ((fnc != FNC_DCLR) && (rpds[drv] & DS_ERR)) { /* err & ~clear? */
rper1[drv] = rper1[drv] | ER1_ILF; /* not allowed */
rpds[drv] = rpds[drv] | DS_ATA; /* set attention */
update_rpcs (CS1_SC, drv); /* request intr */
return; }
dtype = GET_DTYPE (uptr -> flags); /* get drive type */
rpds[drv] = rpds[drv] & ~DS_ATA; /* clear attention */
dc = rpdc; /* assume seek, sch */
@ -738,7 +773,9 @@ case FNC_PACK: /* pack acknowledge */
case FNC_OFFSET: /* offset mode */
case FNC_RETURN:
uptr -> FUNC = fnc; /* save function */
if ((uptr -> flags & UNIT_ATT) == 0) { /* not attached? */
rper1[drv] = rper1[drv] | ER1_UNS; /* unsafe */
break; }
rpds[drv] = (rpds[drv] & ~DS_RDY) | DS_PIP; /* set positioning */
sim_activate (uptr, rp_swait); /* time operation */
return;
@ -748,38 +785,47 @@ case FNC_RECAL: /* recalibrate */
dc = 0; /* seek to 0 */
case FNC_SEEK: /* seek */
case FNC_SEARCH: /* search */
if ((uptr -> flags & UNIT_ATT) == 0) { /* not attached? */
rper1[drv] = rper1[drv] | ER1_UNS; /* unsafe */
break; }
if ((GET_CY (dc) >= drv_tab[dtype].cyl) || /* bad cylinder */
(GET_SF (rpda) >= drv_tab[dtype].surf) || /* bad surface */
(GET_SC (rpda) >= drv_tab[dtype].sect)) { /* or bad sector? */
rper1[drv] = rper1[drv] | ER1_IAE;
break; }
rpds[drv] = (rpds[drv] & ~DS_RDY) | DS_PIP; /* set positioning */
sim_activate (uptr, rp_swait * abs (dc - uptr -> CYL));
uptr -> FUNC = fnc; /* save function */
t = abs (dc - uptr -> CYL); /* cyl diff */
if (t == 0) t = 1; /* min time */
sim_activate (uptr, rp_swait * t); /* schedule */
uptr -> CYL = dc; /* save cylinder */
return;
case FNC_WRITEH: /* write headers */
case FNC_WRITE: /* write */
case FNC_WCHK: /* write check */
case FNC_READ: /* read */
case FNC_READH: /* read headers */
if ((uptr -> flags & UNIT_ATT) == 0) { /* not attached? */
rper1[drv] = rper1[drv] | ER1_UNS; /* unsafe */
break; }
rpcs2 = rpcs2 & ~CS2_ERR; /* clear errors */
rpcs1 = rpcs1 & ~(CS1_TRE | CS1_MCPE | CS1_DONE);
if ((GET_CY (dc) >= drv_tab[dtype].cyl) || /* bad cylinder */
(GET_SF (rpda) >= drv_tab[dtype].surf) || /* bad surface */
(GET_SC (rpda) >= drv_tab[dtype].sect)) { /* or bad sector? */
rper1[drv] = rper1[drv] | ER1_IAE;
update_rpcs (CS1_DONE | CS1_TRE, drv); /* set done, err */
return; }
break; }
rpds[drv] = rpds[drv] & ~DS_RDY; /* clear drive rdy */
sim_activate (uptr, rp_rwait + (rp_swait * abs (dc - uptr -> CYL)));
uptr -> FUNC = fnc; /* save function */
uptr -> CYL = dc; /* save cylinder */
return;
default: /* all others */
rper1[drv] = rper1[drv] | ER1_ILF; /* not supported */
rpds[drv] = rpds[drv] | DS_ATA; /* set attention */
break; }
update_rpcs (CS1_SC, drv); /* error, req intr */
rpds[drv] = rpds[drv] | DS_ATA; /* error, set attn */
update_rpcs (CS1_SC, drv); /* req intr */
return;
}
@ -826,6 +872,7 @@ case FNC_WRITE: /* write */
break; }
case FNC_WCHK: /* write check */
case FNC_READ: /* read */
case FNC_READH: /* read headers */
ba = (rpbae << 16) | rpba; /* get byte addr */
da = GET_DA (rpdc, rpda, dtype) * RP_NUMWD; /* get disk addr */
wc = 0200000 - rpwc; /* get true wc */
@ -882,20 +929,28 @@ case FNC_READ: /* read */
perror ("RP I/O error");
clearerr (uptr -> fileref);
return SCPE_IOERR; }
case FNC_WRITEH: /* write headers stub */
update_rpcs (CS1_DONE, drv); /* set done */
break; } /* end case function */
break; } /* end case func */
return SCPE_OK;
}
/* Controller status update
First update drive status, then update RPCS1
If optional argument, request interrupt
/* Controller status update
Check for done transition
Update drive status
Update RPCS1
Update interrupt request
*/
void update_rpcs (int32 flag, int32 drv)
{
int32 i;
UNIT *uptr;
if ((flag & ~rpcs1) & CS1_DONE) /* DONE 0 to 1? */
rpiff = (rpcs1 & CS1_IE)? 1: 0; /* CSTB INTR <- IE */
uptr = rp_dev.units + drv; /* get unit */
if (rp_unit[drv].flags & UNIT_DIS) rpds[drv] = rper1[drv] = 0;
else rpds[drv] = (rpds[drv] | DS_DPR) & ~DS_PGM;
if (rp_unit[drv].flags & UNIT_ATT) rpds[drv] = rpds[drv] | DS_MOL;
@ -903,13 +958,16 @@ else rpds[drv] = rpds[drv] & ~(DS_MOL | DS_VV | DS_RDY);
if (rper1[drv] | rper2 | rper3) rpds[drv] = rpds[drv] | DS_ERR | DS_ATA;
else rpds[drv] = rpds[drv] & ~DS_ERR;
rpcs1 = (rpcs1 & ~(CS1_SC | CS1_MCPE | CS1_MBZ)) | CS1_DVA | flag;
rpcs1 = (rpcs1 & ~(CS1_SC | CS1_MCPE | CS1_MBZ | CS1_DRV)) | CS1_DVA | flag;
rpcs1 = rpcs1 | (uptr -> FUNC << CS1_V_FNC);
if (sim_is_active (uptr)) rpcs1 = rpcs1 | CS1_GO;
if (rpcs2 & CS2_ERR) rpcs1 = rpcs1 | CS1_TRE | CS1_SC;
else if (rpcs1 & CS1_TRE) rpcs1 = rpcs1 | CS1_SC;
for (i = 0; i < RP_NUMDR; i++)
if (rpds[i] & DS_ATA) rpcs1 = rpcs1 | CS1_SC;
if (((rpcs1 & CS1_IE) == 0) || ((rpcs1 & CS1_DONE) == 0))
int_req = int_req & ~INT_RP;
else if (flag) int_req = int_req | INT_RP;
if (rpiff || ((rpcs1 & CS1_SC) && (rpcs1 & CS1_DONE) && (rpcs1 & CS1_IE)))
SET_INT (RP);
else CLR_INT (RP);
return;
}
@ -917,8 +975,9 @@ return;
int32 rp_inta (void)
{
/* rpcs1 = rpcs1 & ~CS1_IE; /* clear int enable */
/* rpcs3 = rpcs3 & ~CS1_IE; /* in both registers */
rpcs1 = rpcs1 & ~CS1_IE; /* clear int enable */
rpcs3 = rpcs3 & ~CS1_IE; /* in both registers */
rpiff = 0; /* clear CSTB INTR */
return VEC_RP; /* acknowledge */
}
@ -936,7 +995,8 @@ rpof = rpdc = 0;
rper2 = rper3 = 0;
rpec1 = rpec2 = 0;
rpbae = rpcs3 = 0;
int_req = int_req & ~INT_RP;
rpiff = 0; /* clear CSTB INTR */
CLR_INT (RP); /* clear intr req */
for (i = 0; i < RP_NUMDR; i++) {
uptr = rp_dev.units + i;
sim_cancel (uptr);
@ -1013,8 +1073,8 @@ return pdp11_bad_block (uptr, drv_tab[GET_DTYPE (uptr -> flags)].sect, RP_NUMWD)
/* Device bootstrap */
#define BOOT_START 02000 /* start */
#define BOOT_UNIT 02006 /* where to store unit number */
#define BOOT_START 02000 /* start */
#define BOOT_UNIT 02006 /* unit number */
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int32))
static const int32 boot_rom[] = {

View file

@ -25,6 +25,7 @@
rx RX11/RX01 floppy disk
07-Sep-01 RMS Revised device disable and interrupt mechanisms
17-Jul-01 RMS Fixed warning from VC++ 6.0
26-Apr-01 RMS Added device enable/disable support
13-Apr-01 RMS Revised for register arrays
@ -88,7 +89,7 @@
#define TRACK u3 /* current track */
#define CALC_DA(t,s) (((t) * RX_NUMSC) + ((s) - 1)) * RX_NUMBY
extern int32 int_req, dev_enb;
extern int32 int_req[IPL_HLVL];
int32 rx_csr = 0; /* control/status */
int32 rx_dbr = 0; /* data buffer */
int32 rx_esr = 0; /* error status */
@ -102,6 +103,7 @@ int32 rx_swait = 10; /* seek, per track */
int32 rx_xwait = 1; /* tr set time */
unsigned int8 rx_buf[RX_NUMBY] = { 0 }; /* sector buffer */
int32 bptr = 0; /* buffer pointer */
int32 rx_enb = 1; /* device enable */
t_stat rx_svc (UNIT *uptr);
t_stat rx_reset (DEVICE *dptr);
t_stat rx_boot (int32 unitno);
@ -129,7 +131,7 @@ REG rx_reg[] = {
{ ORDATA (RXSA, rx_sector, 8) },
{ ORDATA (STAPTR, rx_state, 3), REG_RO },
{ ORDATA (BUFPTR, bptr, 7) },
{ FLDATA (INT, int_req, INT_V_RX) },
{ FLDATA (INT, IREQ (RX), INT_V_RX) },
{ FLDATA (ERR, rx_csr, CSR_V_ERR) },
{ FLDATA (TR, rx_csr, RXCS_V_TR) },
{ FLDATA (IE, rx_csr, CSR_V_IE) },
@ -141,7 +143,7 @@ REG rx_reg[] = {
{ FLDATA (FLG1, rx_unit[1].flags, UNIT_V_WLK), REG_HRO },
{ FLDATA (STOP_IOE, rx_stopioe, 0) },
{ BRDATA (SBUF, rx_buf, 8, 8, RX_NUMBY) },
{ FLDATA (*DEVENB, dev_enb, INT_V_RX), REG_HRO },
{ FLDATA (*DEVENB, rx_enb, 0), REG_HRO },
{ NULL } };
MTAB rx_mod[] = {
@ -222,9 +224,9 @@ case 0: /* RXCS */
sim_activate (&rx_unit[drv], rx_cwait);
break; } /* end switch func */
return SCPE_OK; } /* end if GO */
if ((data & CSR_IE) == 0) int_req = int_req & ~INT_RX;
if ((data & CSR_IE) == 0) CLR_INT (RX);
else if ((rx_csr & (RXCS_DONE + CSR_IE)) == RXCS_DONE)
int_req = int_req | INT_RX;
SET_INT (RX);
rx_csr = (rx_csr & ~RXCS_RW) | (data & RXCS_RW);
break; /* end case RXCS */
@ -351,7 +353,7 @@ return IORETURN (rx_stopioe, rval);
void rx_done (int32 new_dbr, int32 new_ecode)
{
rx_csr = rx_csr | RXCS_DONE; /* set done */
if (rx_csr & CSR_IE) int_req = int_req | INT_RX; /* if ie, intr */
if (rx_csr & CSR_IE) SET_INT (RX); /* if ie, intr */
rx_dbr = new_dbr; /* update RXDB */
if (new_ecode != 0) { /* test for error */
rx_ecode = new_ecode;
@ -368,7 +370,7 @@ t_stat rx_reset (DEVICE *dptr)
{
rx_csr = rx_dbr = 0; /* clear regs */
rx_esr = rx_ecode = 0; /* clear error */
int_req = int_req & ~INT_RX; /* clear int req */
CLR_INT (RX); /* clear int req */
sim_cancel (&rx_unit[1]); /* cancel drive 1 */
if (rx_unit[0].flags & UNIT_BUF) { /* attached? */
rx_state = INIT_COMPLETE; /* yes, sched init */

View file

@ -27,6 +27,8 @@
tti,tto DL11 terminal input/output
clk KW11L line frequency clock
07-Oct-01 RMS Upgraded clock to full KW11L for RSTS/E autoconfigure
07-Sep-01 RMS Moved function prototypes, revised interrupt mechanism
17-Jul-01 RMS Moved function prototype
04-Jul-01 RMS Added DZ11 support
05-Mar-01 RMS Added clock calibration support
@ -44,11 +46,11 @@
#define TTICSR_RW (CSR_IE)
#define TTOCSR_IMP (CSR_DONE + CSR_IE) /* terminal output */
#define TTOCSR_RW (CSR_IE)
#define CLKCSR_IMP (CSR_IE) /* real-time clock */
#define CLKCSR_RW (CSR_IE)
#define CLKCSR_IMP (CSR_DONE + CSR_IE) /* real-time clock */
#define CLKCSR_RW (CSR_DONE + CSR_IE)
#define CLK_DELAY 8000
extern int32 int_req;
extern int32 int_req[IPL_HLVL];
int32 ptr_csr = 0; /* control/status */
int32 ptr_stopioe = 0; /* stop on error */
int32 ptp_csr = 0; /* control/status */
@ -57,7 +59,7 @@ int32 tti_csr = 0; /* control/status */
int32 tto_csr = 0; /* control/status */
int32 clk_csr = 0; /* control/status */
int32 clk_tps = 60; /* ticks/second */
int32 dz_poll = CLK_DELAY; /* DZ poll inteval */
int32 tmxr_poll = CLK_DELAY; /* term mux poll */
t_stat ptr_svc (UNIT *uptr);
t_stat ptp_svc (UNIT *uptr);
@ -73,8 +75,6 @@ t_stat ptr_attach (UNIT *uptr, char *ptr);
t_stat ptr_detach (UNIT *uptr);
t_stat ptp_attach (UNIT *uptr, char *ptr);
t_stat ptp_detach (UNIT *uptr);
extern t_stat sim_poll_kbd (void);
extern t_stat sim_putchar (int32 out);
/* PTR data structures
@ -89,7 +89,7 @@ UNIT ptr_unit = {
REG ptr_reg[] = {
{ ORDATA (BUF, ptr_unit.buf, 8) },
{ ORDATA (CSR, ptr_csr, 16) },
{ FLDATA (INT, int_req, INT_V_PTR) },
{ FLDATA (INT, IREQ (PTR), INT_V_PTR) },
{ FLDATA (ERR, ptr_csr, CSR_V_ERR) },
{ FLDATA (BUSY, ptr_csr, CSR_V_BUSY) },
{ FLDATA (DONE, ptr_csr, CSR_V_DONE) },
@ -118,7 +118,7 @@ UNIT ptp_unit = {
REG ptp_reg[] = {
{ ORDATA (BUF, ptp_unit.buf, 8) },
{ ORDATA (CSR, ptp_csr, 16) },
{ FLDATA (INT, int_req, INT_V_PTP) },
{ FLDATA (INT, IREQ (PTP), INT_V_PTP) },
{ FLDATA (ERR, ptp_csr, CSR_V_ERR) },
{ FLDATA (DONE, ptp_csr, CSR_V_DONE) },
{ FLDATA (IE, ptp_csr, CSR_V_IE) },
@ -145,7 +145,7 @@ UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT };
REG tti_reg[] = {
{ ORDATA (BUF, tti_unit.buf, 8) },
{ ORDATA (CSR, tti_csr, 16) },
{ FLDATA (INT, int_req, INT_V_TTI) },
{ FLDATA (INT, IREQ (TTI), INT_V_TTI) },
{ FLDATA (ERR, tti_csr, CSR_V_ERR) },
{ FLDATA (DONE, tti_csr, CSR_V_DONE) },
{ FLDATA (IE, tti_csr, CSR_V_IE) },
@ -171,7 +171,7 @@ UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT };
REG tto_reg[] = {
{ ORDATA (BUF, tto_unit.buf, 8) },
{ ORDATA (CSR, tto_csr, 16) },
{ FLDATA (INT, int_req, INT_V_TTO) },
{ FLDATA (INT, IREQ (TTO), INT_V_TTO) },
{ FLDATA (ERR, tto_csr, CSR_V_ERR) },
{ FLDATA (DONE, tto_csr, CSR_V_DONE) },
{ FLDATA (IE, tto_csr, CSR_V_IE) },
@ -196,7 +196,7 @@ UNIT clk_unit = { UDATA (&clk_svc, 0, 0), 8000 };
REG clk_reg[] = {
{ ORDATA (CSR, clk_csr, 16) },
{ FLDATA (INT, int_req, INT_V_CLK) },
{ FLDATA (INT, IREQ (CLK), INT_V_CLK) },
{ FLDATA (DONE, clk_csr, CSR_V_DONE) },
{ FLDATA (IE, clk_csr, CSR_V_IE) },
{ DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT },
@ -236,7 +236,7 @@ case 04: /* ptr csr */
return SCPE_OK;
case 05: /* ptr buf */
ptr_csr = ptr_csr & ~CSR_DONE;
int_req = int_req & ~INT_PTR;
CLR_INT (PTR);
*data = ptr_unit.buf & 0377;
return SCPE_OK;
case 06: /* ptp csr */
@ -250,7 +250,7 @@ case 010: /* tti csr */
return SCPE_OK;
case 011: /* tti buf */
tti_csr = tti_csr & ~CSR_DONE;
int_req = int_req & ~INT_TTI;
CLR_INT (TTI);
*data = tti_unit.buf & 0377;
return SCPE_OK;
case 012: /* tto csr */
@ -267,17 +267,20 @@ t_stat std_wr (int32 data, int32 PA, int32 access)
switch ((PA >> 1) & 017) { /* decode PA<4:1> */
case 03: /* clk csr */
if (PA & 1) return SCPE_OK;
if ((data & CSR_IE) == 0) int_req = int_req & ~INT_CLK;
if (((data & CSR_IE) == 0) || /* clr IE, DONE? */
((data & CSR_DONE) == 0)) CLR_INT (CLK); /* clr intr */
else if (((clk_csr & CSR_IE) == 0) || /* setting both */
((clk_csr & CSR_DONE) == 0)) SET_INT (CLK); /* if prv clr, intr */
clk_csr = (clk_csr & ~CLKCSR_RW) | (data & CLKCSR_RW);
return SCPE_OK;
case 04: /* ptr csr */
if (PA & 1) return SCPE_OK;
if ((data & CSR_IE) == 0) int_req = int_req & ~INT_PTR;
if ((data & CSR_IE) == 0) CLR_INT (PTR);
else if (((ptr_csr & CSR_IE) == 0) && (ptr_csr & (CSR_ERR | CSR_DONE)))
int_req = int_req | INT_PTR;
SET_INT (PTR);
if (data & CSR_GO) {
ptr_csr = (ptr_csr & ~CSR_DONE) | CSR_BUSY;
int_req = int_req & ~INT_PTR;
CLR_INT (PTR);
if (ptr_unit.flags & UNIT_ATT) /* data to read? */
sim_activate (&ptr_unit, ptr_unit.wait);
else sim_activate (&ptr_unit, 0); } /* error if not */
@ -287,39 +290,39 @@ case 05: /* ptr buf */
return SCPE_OK;
case 06: /* ptp csr */
if (PA & 1) return SCPE_OK;
if ((data & CSR_IE) == 0) int_req = int_req & ~INT_PTP;
if ((data & CSR_IE) == 0) CLR_INT (PTP);
else if (((ptp_csr & CSR_IE) == 0) && (ptp_csr & (CSR_ERR | CSR_DONE)))
int_req = int_req | INT_PTP;
SET_INT (PTP);
ptp_csr = (ptp_csr & ~PTPCSR_RW) | (data & PTPCSR_RW);
return SCPE_OK;
case 07: /* ptp buf */
if ((PA & 1) == 0) ptp_unit.buf = data & 0377;
ptp_csr = ptp_csr & ~CSR_DONE;
int_req = int_req & ~INT_PTP;
CLR_INT (PTP);
if (ptp_unit.flags & UNIT_ATT) /* file to write? */
sim_activate (&ptp_unit, ptp_unit.wait);
else sim_activate (&ptp_unit, 0); /* error if not */
return SCPE_OK;
case 010: /* tti csr */
if (PA & 1) return SCPE_OK;
if ((data & CSR_IE) == 0) int_req = int_req & ~INT_TTI;
if ((data & CSR_IE) == 0) CLR_INT (TTI);
else if ((tti_csr & (CSR_DONE + CSR_IE)) == CSR_DONE)
int_req = int_req | INT_TTI;
SET_INT (TTI);
tti_csr = (tti_csr & ~TTICSR_RW) | (data & TTICSR_RW);
return SCPE_OK;
case 011: /* tti buf */
return SCPE_OK;
case 012: /* tto csr */
if (PA & 1) return SCPE_OK;
if ((data & CSR_IE) == 0) int_req = int_req & ~INT_TTO;
if ((data & CSR_IE) == 0) CLR_INT (TTO);
else if ((tto_csr & (CSR_DONE + CSR_IE)) == CSR_DONE)
int_req = int_req | INT_TTO;
SET_INT (TTO);
tto_csr = (tto_csr & ~TTOCSR_RW) | (data & TTOCSR_RW);
return SCPE_OK;
case 013: /* tto buf */
if ((PA & 1) == 0) tto_unit.buf = data & 0377;
tto_csr = tto_csr & ~CSR_DONE;
int_req = int_req & ~INT_TTO;
CLR_INT (TTO);
sim_activate (&tto_unit, tto_unit.wait);
return SCPE_OK; } /* end switch PA */
return SCPE_NXM;
@ -338,7 +341,7 @@ t_stat ptr_svc (UNIT *uptr)
int32 temp;
ptr_csr = (ptr_csr | CSR_ERR) & ~CSR_BUSY;
if (ptr_csr & CSR_IE) int_req = int_req | INT_PTR;
if (ptr_csr & CSR_IE) SET_INT (PTR);
if ((ptr_unit.flags & UNIT_ATT) == 0)
return IORETURN (ptr_stopioe, SCPE_UNATT);
if ((temp = getc (ptr_unit.fileref)) == EOF) {
@ -359,7 +362,7 @@ t_stat ptr_reset (DEVICE *dptr)
ptr_unit.buf = 0;
ptr_csr = 0;
if ((ptr_unit.flags & UNIT_ATT) == 0) ptr_csr = ptr_csr | CSR_ERR;
int_req = int_req & ~INT_PTR;
CLR_INT (PTR);
sim_cancel (&ptr_unit);
return SCPE_OK;
}
@ -391,7 +394,7 @@ return detach_unit (uptr);
t_stat ptp_svc (UNIT *uptr)
{
ptp_csr = ptp_csr | CSR_ERR | CSR_DONE;
if (ptp_csr & CSR_IE) int_req = int_req | INT_PTP;
if (ptp_csr & CSR_IE) SET_INT (PTP);
if ((ptp_unit.flags & UNIT_ATT) == 0)
return IORETURN (ptp_stopioe, SCPE_UNATT);
if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) {
@ -408,7 +411,7 @@ t_stat ptp_reset (DEVICE *dptr)
ptp_unit.buf = 0;
ptp_csr = CSR_DONE;
if ((ptp_unit.flags & UNIT_ATT) == 0) ptp_csr = ptp_csr | CSR_ERR;
int_req = int_req & ~INT_PTP;
CLR_INT (PTP);
sim_cancel (&ptp_unit); /* deactivate unit */
return SCPE_OK;
}
@ -444,7 +447,7 @@ if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */
tti_unit.buf = temp & 0377;
tti_unit.pos = tti_unit.pos + 1;
tti_csr = tti_csr | CSR_DONE;
if (tti_csr & CSR_IE) int_req = int_req | INT_TTI;
if (tti_csr & CSR_IE) SET_INT (TTI);
return SCPE_OK;
}
@ -452,7 +455,7 @@ t_stat tti_reset (DEVICE *dptr)
{
tti_unit.buf = 0;
tti_csr = 0;
int_req = int_req & ~INT_TTI;
CLR_INT (TTI);
sim_activate (&tti_unit, tti_unit.wait); /* activate unit */
return SCPE_OK;
}
@ -468,7 +471,7 @@ t_stat tto_svc (UNIT *uptr)
int32 temp;
tto_csr = tto_csr | CSR_DONE;
if (tto_csr & CSR_IE) int_req = int_req | INT_TTO;
if (tto_csr & CSR_IE) SET_INT (TTO);
if ((temp = sim_putchar (tto_unit.buf & 0177)) != SCPE_OK) return temp;
tto_unit.pos = tto_unit.pos + 1;
return SCPE_OK;
@ -478,7 +481,7 @@ t_stat tto_reset (DEVICE *dptr)
{
tto_unit.buf = 0;
tto_csr = CSR_DONE;
int_req = int_req & ~INT_TTO;
CLR_INT (TTO);
sim_cancel (&tto_unit); /* deactivate unit */
return SCPE_OK;
}
@ -493,18 +496,19 @@ t_stat clk_svc (UNIT *uptr)
{
int32 t;
if (clk_csr & CSR_IE) int_req = int_req | INT_CLK;
clk_csr = clk_csr | CSR_DONE; /* set done */
if (clk_csr & CSR_IE) SET_INT (CLK);
t = sim_rtc_calb (clk_tps); /* calibrate clock */
sim_activate (&clk_unit, t); /* reactivate unit */
dz_poll = t; /* set DZ poll */
tmxr_poll = t; /* set mux poll */
return SCPE_OK;
}
t_stat clk_reset (DEVICE *dptr)
{
clk_csr = 0;
int_req = int_req & ~INT_CLK;
CLR_INT (CLK);
sim_activate (&clk_unit, clk_unit.wait); /* activate unit */
dz_poll = clk_unit.wait; /* set DZ poll */
tmxr_poll = clk_unit.wait; /* set mux poll */
return SCPE_OK;
}

View file

@ -23,6 +23,8 @@
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.
17-Sep-01 RMS Removed multiconsole support
26-Aug-01 RMS Added DZ11
20-Aug-01 RMS Updated bad block inquiry
17-Jul-01 RMS Fixed warning from VC++ 6.0
27-May-01 RMS Added multiconsole support
@ -45,6 +47,7 @@ extern DEVICE cpu_dev;
extern DEVICE ptr_dev, ptp_dev;
extern DEVICE tti_dev, tto_dev;
extern DEVICE lpt_dev, clk_dev;
extern DEVICE dz_dev;
extern DEVICE rk_dev, rx_dev;
extern DEVICE rl_dev, rp_dev;
extern DEVICE dt_dev, tm_dev;
@ -61,7 +64,6 @@ extern int32 saved_PC;
sim_PC pointer to saved PC register descriptor
sim_emax number of words for examine
sim_devices array of pointers to simulated devices
sim_consoles array of pointers to consoles (if more than one)
sim_stop_messages array of pointers to stop messages
sim_load binary loader
*/
@ -77,14 +79,13 @@ DEVICE *sim_devices[] = {
&ptr_dev, &ptp_dev,
&tti_dev, &tto_dev,
&lpt_dev, &clk_dev,
&dz_dev,
&rk_dev, /* &hk_dev, */
&rl_dev, &rp_dev,
&rx_dev, &dt_dev,
&tm_dev, &ts_dev,
NULL };
UNIT *sim_consoles = NULL;
const char *sim_stop_messages[] = {
"Unknown error",
"Red stack trap",
@ -317,7 +318,7 @@ static const char *opcode[] = {
"SOB",
"BPL","BMI","BHI","BLOS",
"BVC","BVS","BCC","BCS",
"BHIS","BLO", /* encode only */
"BHIS","BLO", /* encode only */
"EMT","TRAP",
"CLRB","COMB","INCB","DECB",
"NEGB","ADCB","SBCB","TSTB",

View file

@ -25,6 +25,10 @@
tc TC11/TU56 DECtape
15-Sep-01 RMS Integrated debug logging
27-Sep-01 RMS Fixed interrupt after stop for RSTS/E
07-Sep-01 RMS Revised device disable and interrupt mechanisms
29-Aug-01 RMS Added casts to PDP-8 unpack routine
17-Jul-01 RMS Moved function prototype
11-May-01 RMS Fixed bug in reset
26-Apr-01 RMS Added device enable/disable support
@ -228,27 +232,30 @@
#define LOG_BL 010 /* block # lblk */
#define DT_SETDONE tccm = tccm | CSR_DONE; \
if (tccm & CSR_IE) int_req = int_req | INT_DTA
if (tccm & CSR_IE) SET_INT (DTA)
#define DT_CLRDONE tccm = tccm & ~CSR_DONE; \
int_req = int_req & ~INT_DTA
CLR_INT (DTA)
#define ABS(x) (((x) < 0)? (-(x)): (x))
extern uint16 *M; /* memory */
extern int32 int_req, dev_enb;
extern int32 int_req[IPL_HLVL];
extern UNIT cpu_unit;
extern int32 sim_switches;
extern int32 pdp11_log;
extern FILE *sim_log;
int32 tcst = 0; /* status */
int32 tccm = 0; /* command */
int32 tcwc = 0; /* word count */
int32 tcba = 0; /* bus address */
int32 tcdt = 0; /* data */
int32 dt_ctime = 4; /* fast cmd time */
int32 dt_ctime = 100; /* fast cmd time */
int32 dt_ltime = 12; /* interline time */
int32 dt_actime = 54000; /* accel time */
int32 dt_dctime = 72000; /* decel time */
int32 dt_substate = 0;
int32 dt_log = 0;
int32 dt_logblk = 0;
int32 dt_enb = 1; /* device enable */
t_stat dt_svc (UNIT *uptr);
t_stat dt_svcdone (UNIT *uptr);
t_stat dt_reset (DEVICE *dptr);
@ -294,7 +301,7 @@ REG dt_reg[] = {
{ ORDATA (TCWC, tcwc, 16) },
{ ORDATA (TCBA, tcba, 16) },
{ ORDATA (TCDT, tcdt, 16) },
{ FLDATA (INT, int_req, INT_V_DTA) },
{ FLDATA (INT, IREQ (DTA), INT_V_DTA) },
{ FLDATA (ERR, tccm, CSR_V_ERR) },
{ FLDATA (DONE, tccm, CSR_V_DONE) },
{ FLDATA (IE, tccm, CSR_V_DONE) },
@ -303,7 +310,6 @@ REG dt_reg[] = {
{ DRDATA (ACTIME, dt_actime, 31), REG_NZ },
{ DRDATA (DCTIME, dt_dctime, 31), REG_NZ },
{ ORDATA (SUBSTATE, dt_substate, 1) },
{ ORDATA (LOG, dt_log, 4), REG_HIDDEN },
{ DRDATA (LBLK, dt_logblk, 12), REG_HIDDEN },
{ DRDATA (POS0, dt_unit[0].pos, 31), PV_LEFT + REG_RO },
{ DRDATA (POS1, dt_unit[1].pos, 31), PV_LEFT + REG_RO },
@ -345,7 +351,7 @@ REG dt_reg[] = {
REG_HRO },
{ GRDATA (FLG7, dt_unit[7].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
REG_HRO },
{ FLDATA (*DEVENB, dev_enb, INT_V_DTA), REG_HRO },
{ FLDATA (*DEVENB, dt_enb, 0), REG_HRO },
{ NULL } };
MTAB dt_mod[] = {
@ -411,14 +417,14 @@ case 001: /* TCCM */
old_tccm = tccm; /* save prior */
if (access == WRITEB) data = (PA & 1)?
(tccm & 0377) | (data << 8): (tccm & ~0377) | data;
if ((data & CSR_IE) == 0) int_req = int_req & ~INT_DTA;
if ((data & CSR_IE) == 0) CLR_INT (DTA);
else if ((((tccm & CSR_IE) == 0) && (tccm & CSR_DONE)) ||
(data & CSR_DONE)) int_req = int_req | INT_DTA;
(data & CSR_DONE)) SET_INT (DTA);
tccm = (tccm & ~CSR_RW) | (data & CSR_RW);
if ((data & CSR_GO) && (tccm & CSR_DONE)) { /* new cmd? */
tcst = tcst & ~STA_ALLERR; /* clear errors */
tccm = tccm & ~(CSR_ERR | CSR_DONE); /* clear done, err */
int_req = int_req & ~INT_DTA; /* clear int */
CLR_INT (DTA); /* clear int */
if ((old_tccm ^ tccm) & CSR_UNIT) dt_deselect (old_tccm);
unum = CSR_GETUNIT (tccm); /* get drive */
fnc = CSR_GETFNC (tccm); /* get function */
@ -581,8 +587,8 @@ case FNC_SRCH: /* search */
DTU_TSIZE (uptr): blk), uptr) - DT_BLKLN - DT_WSIZE;
else newpos = DT_BLK2LN ((DT_QREZ (uptr)?
0: blk + 1), uptr) + DT_BLKLN + (DT_WSIZE - 1);
if (dt_log & LOG_MS) printf ("[DT%d: searching %s]\n", unum,
(dir? "backward": "forward"));
if (DBG_LOG (LOG_TC_MS)) fprintf (sim_log, ">>DT%d: searching %s\n",
unum, (dir? "backward": "forward"));
break;
case FNC_WRIT: /* write */
case FNC_READ: /* read */
@ -599,8 +605,8 @@ case FNC_READ: /* read */
blk + 1: blk), uptr) - DT_HTLIN - DT_WSIZE;
else newpos = DT_BLK2LN (((relpos < DT_HTLIN)?
blk: blk + 1), uptr) + DT_HTLIN + (DT_WSIZE - 1);
if ((dt_log & LOG_RW) || ((dt_log & LOG_BL) && (blk == dt_logblk)))
printf ("[DT%d: %s block %d %s]\n",
if (DBG_LOG (LOG_TC_RW) || (DBG_LOG (LOG_TC_BL) && (blk == dt_logblk)))
fprintf (sim_log, ">>DT%d: %s block %d %s\n",
unum, ((fnc == FNC_READ)? "read": "write"),
blk, (dir? "backward": "forward"));
break;
@ -618,8 +624,8 @@ case FNC_WALL: /* write all */
else newpos = DT_BLK2LN (blk, uptr) + DT_CSMLN + (DT_WSIZE - 1); }
if (fnc == FNC_WALL) sim_activate /* write all? */
(&dt_dev.units[DT_TIMER], dt_ctime); /* sched done */
if ((dt_log & LOG_RA) || ((dt_log & LOG_BL) && (blk == dt_logblk)))
printf ("[DT%d: read all block %d %s]\n",
if (DBG_LOG (LOG_TC_RW) || (DBG_LOG (LOG_TC_BL) && (blk == dt_logblk)))
fprintf (sim_log, ">>DT%d: read all block %d %s\n",
unum, blk, (dir? "backward": "forward"));
break;
default:
@ -685,11 +691,11 @@ if ((uptr -> pos < 0) ||
return FALSE;
}
/* Command timer service after stop - set done but not interrupt */
/* Command timer service after stop - set done */
t_stat dt_svcdone (UNIT *uptr)
{
tccm = tccm | CSR_DONE;
DT_SETDONE;
return SCPE_OK;
}
@ -932,7 +938,7 @@ int32 ba = blk * DTU_BSIZE (uptr);
int32 i, csum, wrd;
csum = 077; /* init csum */
for (i = 0; i < DTU_BSIZE (uptr); i++) { /* loop thru buf */
for (i = 0; i < DTU_BSIZE (uptr); i++) { /* loop thru buf */
wrd = bptr[ba + i] ^ 0777777; /* get ~word */
csum = csum ^ (wrd >> 12) ^ (wrd >> 6) ^ wrd; }
return (csum & 077);
@ -974,14 +980,14 @@ for (i = 0; i < DT_NUMDR; i++) { /* stop all activity */
uptr -> LASTT = sim_grtime (); } }
tcst = tcwc = tcba = tcdt = 0; /* clear reg */
tccm = CSR_DONE;
int_req = int_req & ~INT_DTA; /* clear int req */
CLR_INT (DTA); /* clear int req */
return SCPE_OK;
}
/* Device bootstrap */
#define BOOT_START 02000 /* start */
#define BOOT_UNIT 02006 /* where to store unit number */
#define BOOT_START 02000 /* start */
#define BOOT_UNIT 02006 /* unit number */
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int32))
static const int32 boot_rom[] = {
@ -1064,7 +1070,7 @@ uptr -> filebuf = calloc (uptr -> capac, sizeof (int32));
if (uptr -> filebuf == NULL) { /* can't alloc? */
detach_unit (uptr);
return SCPE_MEM; }
printf ("%TC: buffering file in memory\n");
printf ("TC: buffering file in memory\n");
rewind (uptr -> fileref); /* start of file */
if (uptr -> flags & UNIT_8FMT) { /* PDP-8? */
bptr = uptr -> filebuf; /* file buffer */
@ -1073,10 +1079,10 @@ if (uptr -> flags & UNIT_8FMT) { /* PDP-8? */
if (k == 0) break;
for ( ; k < D8_NBSIZE; k++) pdp8b[k] = 0;
for (k = 0; k < D8_NBSIZE; k = k + 3) { /* loop thru blk */
bptr[ba] = ((pdp8b[k] & 07777) << 6) |
((pdp8b[k + 1] >> 6) & 077);
bptr[ba] = ((uint32) (pdp8b[k] & 07777) << 6) |
((uint32) (pdp8b[k + 1] >> 6) & 077);
bptr[ba + 1] = ((pdp8b[k + 1] & 077) << 12) |
(pdp8b[k + 2] & 07777);
((uint32) (pdp8b[k + 2] & 07777));
ba = ba + 2; } /* end blk loop */
} /* end file loop */
uptr -> hwmark = ba; } /* end if */
@ -1109,7 +1115,7 @@ if (sim_is_active (uptr)) { /* active? cancel op */
if ((unum == CSR_GETUNIT (tccm)) && ((tccm & CSR_DONE) == 0)) {
tcst = tcst | STA_SEL;
tccm = tccm | CSR_ERR | CSR_DONE;
if (tccm & CSR_IE) int_req = int_req | INT_DTA; }
if (tccm & CSR_IE) SET_INT (DTA); }
uptr -> STATE = uptr -> pos = 0; }
if (uptr -> hwmark) { /* any data? */
printf ("TC: writing buffer to file\n");

View file

@ -25,6 +25,8 @@
tm TM11/TU10 magtape
18-Oct-01 RMS Added stub diagnostic register (found by Thord Nilson)
07-Sep-01 RMS Revised device disable and interrupt mechanisms
26-Apr-01 RMS Added device enable/disable support
18-Apr-01 RMS Changed to rewind tape before boot
14-Apr-99 RMS Changed t_addr to unsigned
@ -124,17 +126,24 @@
#define STA_EFLGS (STA_ILL | STA_EOF | STA_CRC | STA_PAR | \
STA_DLT | STA_EOT | STA_RLE | STA_BAD | STA_NXM)
/* set error */
/* Read lines - tm_rdl */
#define RDL_CLK 0100000 /* 10 Khz clock */
extern uint16 *M; /* memory */
extern int32 int_req, dev_enb;
extern int32 int_req[IPL_HLVL];
extern UNIT cpu_unit;
int32 tm_sta = 0; /* status register */
int32 tm_cmd = 0; /* command register */
int32 tm_ca = 0; /* current address */
int32 tm_bc = 0; /* byte count */
int32 tm_db = 0; /* data buffer */
int32 tm_rdl = 0; /* read lines */
int32 tm_time = 10; /* record latency */
int32 tm_stopioe = 1; /* stop on error */
int32 tm_enb = 1; /* device enable */
t_stat tm_svc (UNIT *uptr);
t_stat tm_reset (DEVICE *dptr);
t_stat tm_attach (UNIT *uptr, char *cptr);
@ -169,7 +178,8 @@ REG tm_reg[] = {
{ ORDATA (MTBRC, tm_bc, 16) },
{ ORDATA (MTCMA, tm_ca, 16) },
{ ORDATA (MTD, tm_db, 8) },
{ FLDATA (INT, int_req, INT_V_TM) },
{ ORDATA (MTRD, tm_rdl, 16) },
{ FLDATA (INT, IREQ (TM), INT_V_TM) },
{ FLDATA (ERR, tm_cmd, CSR_V_ERR) },
{ FLDATA (DONE, tm_cmd, CSR_V_DONE) },
{ FLDATA (IE, tm_cmd, CSR_V_IE) },
@ -207,7 +217,7 @@ REG tm_reg[] = {
REG_HRO },
{ GRDATA (FLG7, tm_unit[7].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
REG_HRO },
{ FLDATA (*DEVENB, dev_enb, INT_V_TM), REG_HRO },
{ FLDATA (*DEVENB, tm_enb, 0), REG_HRO },
{ NULL } };
MTAB tm_mod[] = {
@ -229,7 +239,7 @@ DEVICE tm_dev = {
17772524 MTBRC read/write
17772526 MTCMA read/write
17772530 MTD read/write
17772532 MTRD unimplemented
17772532 MTRD read only
*/
t_stat tm_rd (int32 *data, int32 PA, int32 access)
@ -240,23 +250,28 @@ uptr = tm_dev.units + GET_UNIT (tm_cmd); /* get unit */
switch ((PA >> 1) & 07) { /* decode PA<3:1> */
case 0: /* MTS */
*data = tm_updcsta (uptr); /* update status */
return SCPE_OK;
break;
case 1: /* MTC */
tm_updcsta (uptr); /* update status */
*data = tm_cmd; /* return command */
return SCPE_OK;
break;
case 2: /* MTBRC */
*data = tm_bc; /* return byte count */
return SCPE_OK;
break;
case 3: /* MTCMA */
*data = tm_ca; /* return mem addr */
return SCPE_OK;
break;
case 4: /* MTD */
*data = tm_db; /* return data buffer */
return SCPE_OK;
break;
case 5: /* MTRD */
tm_rdl = tm_rdl ^ RDL_CLK; /* "clock" ticks */
*data = tm_rdl;
break;
default: /* unimplemented */
*data = 0;
return SCPE_OK; }
break; }
return SCPE_OK;
}
t_stat tm_wr (int32 data, int32 PA, int32 access)
@ -265,7 +280,7 @@ UNIT *uptr;
switch ((PA >> 1) & 07) { /* decode PA<3:1> */
case 0: /* MTS: read only */
return SCPE_OK;
break;
case 1: /* MTC */
uptr = tm_dev.units + GET_UNIT (tm_cmd); /* select unit */
if ((tm_cmd & MTC_DONE) == 0) tm_sta = tm_sta | STA_ILL;
@ -276,30 +291,29 @@ case 1: /* MTC */
tm_reset (&tm_dev); /* reset device */
return SCPE_OK; }
if ((data & MTC_IE) == 0) /* int disable? */
int_req = int_req & ~INT_TM; /* clr int request */
CLR_INT (TM); /* clr int request */
else if ((tm_cmd & (MTC_ERR + MTC_DONE)) && !(tm_cmd & MTC_IE))
int_req = int_req | INT_TM; /* set int request */
SET_INT (TM); /* set int request */
tm_cmd = (tm_cmd & ~MTC_RW) | (data & MTC_RW);
uptr = tm_dev.units + GET_UNIT (tm_cmd); /* new unit */
if (data & MTC_GO) tm_go (uptr); } /* new function? */
tm_updcsta (uptr); /* update status */
return SCPE_OK;
break;
case 2: /* MTBRC */
if (access == WRITEB) data = (PA & 1)?
(tm_bc & 0377) | (data << 8): (tm_bc & ~0377) | data;
tm_bc = data;
return SCPE_OK;
break;
case 3: /* MTCMA */
if (access == WRITEB) data = (PA & 1)?
(tm_ca & 0377) | (data << 8): (tm_ca & ~0377) | data;
tm_ca = data;
return SCPE_OK;
break;
case 4: /* MTD */
if ((access == WRITEB) && (PA & 1)) return SCPE_OK;
tm_db = data & 0377;
return SCPE_OK;
default:
return SCPE_OK; } /* end switch */
break; } /* end switch */
return SCPE_OK;
}
/* New magtape command */
@ -325,7 +339,7 @@ else if (f == MTC_REWIND) /* rewind */
uptr -> USTAT = uptr -> USTAT | STA_REW; /* rewinding */
/* else /* uncomment this else if rewind/unload don't set done */
tm_cmd = tm_cmd & ~MTC_DONE; /* clear done */
int_req = int_req & ~INT_TM; /* clear int */
CLR_INT (TM); /* clear int */
sim_activate (uptr, tm_time); /* start io */
return;
}
@ -501,7 +515,7 @@ if (sim_is_active (uptr)) tm_sta = tm_sta & ~STA_TUR;
else tm_sta = tm_sta | STA_TUR;
if (tm_sta & STA_EFLGS) tm_cmd = tm_cmd | MTC_ERR;
else tm_cmd = tm_cmd & ~MTC_ERR;
if ((tm_cmd & MTC_IE) == 0) int_req = int_req & ~INT_TM;
if ((tm_cmd & MTC_IE) == 0) CLR_INT (TM);
return tm_sta;
}
@ -510,7 +524,7 @@ return tm_sta;
void tm_set_done (void)
{
tm_cmd = tm_cmd | MTC_DONE;
if (tm_cmd & MTC_IE) int_req = int_req | INT_TM;
if (tm_cmd & MTC_IE) SET_INT (TM);
return;
}
@ -520,11 +534,12 @@ t_stat tm_reset (DEVICE *dptr)
{
int32 u;
UNIT *uptr;
extern int32 ts_enb;
if (dev_enb & INT_TM) dev_enb = dev_enb & ~INT_TS; /* TM or TS */
if (tm_enb) ts_enb = 0; /* TM or TS */
tm_cmd = MTC_DONE; /* set done */
tm_bc = tm_ca = tm_db = tm_sta = 0;
int_req = int_req & ~INT_TM; /* clear interrupt */
tm_bc = tm_ca = tm_db = tm_sta = tm_rdl = 0;
CLR_INT (TM); /* clear interrupt */
for (u = 0; u < TM_NUMDR; u++) { /* loop thru units */
uptr = tm_dev.units + u;
uptr -> UNUM = u; /* init drive number */

View file

@ -25,6 +25,12 @@
ts TS11/TSV05 magtape
15-Oct-01 RMS Integrated debug logging across simulator
27-Sep-01 RMS Implemented extended characteristics and status
Fixed bug in write characteristics status return
19-Sep-01 RMS Fixed bug in bootstrap
15-Sep-01 RMS Fixed bug in NXM test
07-Sep-01 RMS Revised device disable and interrupt mechanism
13-Jul-01 RMS Fixed bug in space reverse (found by Peter Schorn)
Magnetic tapes are represented as a series of variable 8b records
@ -171,24 +177,28 @@
/* Extended status register 1 - none of these errors are ever set */
/* Extended status register 2 - none of these errors are ever set */
/* Extended status register 2 */
#define XS2_XTF 0000200 /* ext features */
/* Extended status register 3 */
#define XS3_XTF 0000200 /* ext features */
#define XS3_OPI 0000100 /* op incomplete */
#define XS3_REV 0000040 /* reverse */
#define XS3_RIB 0000001 /* reverse to BOT */
/* Extended status register 4 - none of these errors are ever set */
/* Extended status register 4 */
#define XS4_HDS 0100000 /* high density */
/* Write characteristics packet offsets */
#define WCH_PLNT 4 /* packet length */
#define WCH_PLNT 5 /* packet length */
#define wchadl tswchp[0] /* address low */
#define wchadh tswchp[1] /* address high */
#define wchlnt tswchp[2] /* length */
#define wchopt tswchp[3] /* options */
#define wchxopt tswchp[4] /* ext options */
/* Write characteristics options */
@ -197,6 +207,10 @@
#define WCH_EAI 0000040 /* enb attn int */
#define WCH_ERI 0000020 /* enb mrls int */
/* Write characteristics extended options */
#define WCHX_HDS 0000040 /* high density */
#define MAX(a,b) (((a) >= (b))? (a): (b))
#define READ_BYTE(p) ((M[(p) >> 1] >> (((p) & 1)? 8: 0)) & 0377)
#define WRITE_BYTE(d,p) M[(p) >> 1] = (p & 1)? \
@ -204,8 +218,10 @@
((M[(p) >> 1] & ~0377) | (d))
extern uint16 *M; /* memory */
extern int32 int_req, dev_enb;
extern int32 int_req[IPL_HLVL];
extern UNIT cpu_unit;
extern FILE *sim_log;
extern int32 pdp11_log;
int32 tssr = 0; /* status register */
int32 tsba = 0; /* mem addr */
int32 tsdbx = 0; /* data buf ext */
@ -217,7 +233,7 @@ int32 ts_ownm = 0; /* tape owns msg */
int32 ts_qatn = 0; /* queued attn */
int32 ts_bcmd = 0; /* boot cmd */
int32 ts_time = 10; /* record latency */
int32 ts_log = 0;
int32 ts_enb = 0; /* device enable */
static uint8 dbuf[DBSIZE];
t_stat ts_svc (UNIT *uptr);
@ -259,6 +275,8 @@ REG ts_reg[] = {
{ ORDATA (WADH, wchadh, 16) },
{ ORDATA (WLNT, wchlnt, 16) },
{ ORDATA (WOPT, wchopt, 16) },
{ ORDATA (WXOPT, wchxopt, 16) },
{ FLDATA (INT, IREQ (TS), INT_V_TS) },
{ FLDATA (ATTN, ts_qatn, 0) },
{ FLDATA (BOOT, ts_bcmd, 0) },
{ FLDATA (OWNC, ts_ownc, 0) },
@ -266,8 +284,7 @@ REG ts_reg[] = {
{ DRDATA (TIME, ts_time, 24), PV_LEFT + REG_NZ },
{ DRDATA (POS, ts_unit.pos, 31), PV_LEFT + REG_RO },
{ FLDATA (WLK, ts_unit.flags, UNIT_V_WLK), REG_HRO },
{ FLDATA (LOG, ts_log, 0), REG_HIDDEN },
{ FLDATA (*DEVENB, dev_enb, INT_V_TS), REG_HRO },
{ FLDATA (*DEVENB, ts_enb, 0), REG_HRO },
{ NULL } };
MTAB ts_mod[] = {
@ -314,10 +331,10 @@ case 0: /* TSDB */
tssr = ts_updtssr (tssr & TSSR_NBA); /* clr ssr, err */
msgxs0 = ts_updxs0 (msgxs0 & ~XS0_ALLERR); /* clr err, upd xs0 */
msgrfc = msgxs1 = msgxs2 = msgxs3 = msgxs4 = 0; /* clr status */
int_req = int_req & ~INT_TS; /* clr int req */
CLR_INT (TS); /* clr int req */
for (i = 0; i < CMD_PLNT; i++) { /* get cmd pkt */
if (ADDR_IS_MEM (tsba)) tscmdp[i] = M[(tsba >> 1)];
else { ts_endcmd (TSSR_NXM + TC3, 0, MSG_ACK|MSG_MNEF|MSG_CFAIL);
else { ts_endcmd (TSSR_NXM + TC5, 0, MSG_ACK|MSG_MNEF|MSG_CFAIL);
return SCPE_OK; }
tsba = tsba + 2; } /* incr tsba */
ts_ownc = ts_ownm = 1; /* tape owns all */
@ -574,12 +591,12 @@ if (ts_bcmd) { /* boot? */
ts_readf (uptr, 512); /* read blk */
tssr = ts_updtssr (tssr | TSSR_SSR); }
else tssr = ts_updtssr (tssr | TSSR_SSR | TC3);
if (cmdhdr & CMD_IE) int_req = int_req | INT_TS;
if (cmdhdr & CMD_IE) SET_INT (TS);
return SCPE_OK; }
if (!(cmdhdr & CMD_ACK)) { /* no acknowledge? */
tssr = ts_updtssr (tssr | TSSR_SSR); /* set rdy, int */
if (cmdhdr & CMD_IE) int_req = int_req | INT_TS;
if (cmdhdr & CMD_IE) SET_INT (TS);
ts_ownc = ts_ownm = 0; /* CPU owns all */
return SCPE_OK; }
fnc = GET_FNC (cmdhdr); /* get fnc+mode */
@ -589,7 +606,7 @@ if ((fnc != FNC_WCHR) && (tssr & TSSR_NBA)) { /* ~wr chr & nba? */
return SCPE_OK; }
if (ts_qatn && (wchopt & WCH_EAI)) { /* attn pending? */
ts_endcmd (TC1, 0, MSG_MATN | MSG_CATN); /* send attn msg */
int_req = int_req | INT_TS; /* set interrupt */
SET_INT (TS); /* set interrupt */
ts_qatn = 0; /* not pending */
return SCPE_OK; }
if (cmdhdr & CMD_CVC) /* cvc? clr vck */
@ -628,13 +645,13 @@ case FNC_WCHR: /* write char */
break; }
tsba = (cmdadh << 16) | cmdadl;
for (i = 0; (i < WCH_PLNT) && (i < (cmdlnt / 2)); i++) {
if (ADDR_IS_MEM (cmdadl)) tswchp[i] = M[tsba >> 1];
else { ts_endcmd (TSSR_NBA | TSSR_NXM | TC3, 0, 0);
if (ADDR_IS_MEM (tsba)) tswchp[i] = M[tsba >> 1];
else { ts_endcmd (TSSR_NBA | TSSR_NXM | TC5, 0, 0);
return SCPE_OK; }
tsba = tsba + 2; }
if ((wchlnt < ((MSG_PLNT - 1) * 2)) || (wchadh & 0177700) ||
(wchadl & 1)) ts_endcmd (TSSR_NBA | TC3, 0, 0);
else { msgxs3 = msgxs3 | XS3_XTF | 1;
else { msgxs2 = msgxs2 | XS2_XTF | 1;
tssr = ts_updtssr (tssr & ~TSSR_NBA);
ts_endcmd (TC0, 0, MSG_ACK | MSG_CEND); }
return SCPE_OK;
@ -642,7 +659,7 @@ case FNC_CTL: /* control */
switch (mod) { /* case mode */
case 00: /* msg buf rls */
tssr = ts_updtssr (tssr | TSSR_SSR); /* set SSR */
if (wchopt & WCH_ERI) int_req = int_req | INT_TS;
if (wchopt & WCH_ERI) SET_INT (TS);
ts_ownc = 0; ts_ownm = 1; /* keep msg */
break;
case 01: /* clean */
@ -728,7 +745,8 @@ case FNC_POS:
break; }
ts_cmpendcmd (st0, 0);
break; }
if (ts_log) printf ("Cmd=%o, mod=%o, buf=%o, lnt=%o, sta = %o, tc=%o, pos=%d\n",
if (DBG_LOG (LOG_TS))
fprintf (sim_log, ">>TS: cmd=%o, mod=%o, buf=%o, lnt=%o, sta = %o, tc=%o, pos=%d\n",
fnc, mod, cmdadl, cmdlnt, msgxs0, (tssr & TSSR_TC) >> 1, ts_unit.pos);
return SCPE_OK;
}
@ -776,6 +794,7 @@ void ts_endcmd (int32 tc, int32 xs0, int32 msg)
int32 i;
msgxs0 = ts_updxs0 (msgxs0 | xs0); /* update XS0 */
if (wchxopt & WCHX_HDS) msgxs4 = msgxs4 | XS4_HDS; /* update XS4 */
if (msg && !(tssr & TSSR_NBA)) { /* send end pkt */
msghdr = msg;
msglnt = wchlnt - 4; /* exclude hdr, bc */
@ -787,7 +806,7 @@ if (msg && !(tssr & TSSR_NBA)) { /* send end pkt */
break; }
tsba = tsba + 2; } }
tssr = ts_updtssr (tssr | tc | TSSR_SSR | (tc? TSSR_SC: 0));
if (cmdhdr & CMD_IE) int_req = int_req | INT_TS;
if (cmdhdr & CMD_IE) SET_INT (TS);
ts_ownm = 0; ts_ownc = 0;
return;
}
@ -797,8 +816,9 @@ return;
t_stat ts_reset (DEVICE *dptr)
{
int32 i;
extern int32 tm_enb;
if (dev_enb & INT_TS) dev_enb = dev_enb & ~INT_TM; /* TM or TS */
if (ts_enb) tm_enb = 0; /* TM or TS */
ts_unit.pos = 0;
tsba = tsdbx = 0;
ts_ownc = ts_ownm = 0;
@ -809,7 +829,7 @@ for (i = 0; i < CMD_PLNT; i++) tscmdp[i] = 0;
for (i = 0; i < WCH_PLNT; i++) tswchp[i] = 0;
for (i = 0; i < MSG_PLNT; i++) tsmsgp[i] = 0;
msgxs0 = ts_updxs0 (XS0_VCK);
int_req = int_req & ~INT_TS;
CLR_INT (TS);
return SCPE_OK;
}
@ -825,7 +845,7 @@ tssr = tssr & ~TSSR_OFL; /* clr offline */
if ((tssr & TSSR_NBA) || !(wchopt & WCH_EAI)) return r; /* attn msg? */
if (ts_ownm) { /* own msg buf? */
ts_endcmd (TC1, 0, MSG_MATN | MSG_CATN); /* send attn */
int_req = int_req | INT_TS; /* set interrupt */
SET_INT (TS); /* set interrupt */
ts_qatn = 0; } /* don't queue */
else ts_qatn = 1; /* else queue */
return r;
@ -843,7 +863,7 @@ tssr = tssr | TSSR_OFL; /* set offline */
if ((tssr & TSSR_NBA) || !(wchopt & WCH_EAI)) return r; /* attn msg? */
if (ts_ownm) { /* own msg buf? */
ts_endcmd (TC1, 0, MSG_MATN | MSG_CATN); /* send attn */
int_req = int_req | INT_TS; /* set interrupt */
SET_INT (TS); /* set interrupt */
ts_qatn = 0; } /* don't queue */
else ts_qatn = 1; /* else queue */
return r;
@ -861,13 +881,13 @@ static const int32 boot_rom[] = {
0005011, /* clr (r1) ; init, rew */
0105711, /* tstb (r1) ; wait */
0100376, /* bpl .-2 */
0012710, 0001064, /* mov #pkt1, (r0) ; set char */
0012710, 0001070, /* mov #pkt1, (r0) ; set char */
0105711, /* tstb (r1) ; wait */
0100376, /* bpl .-2 */
0012710, 0001104, /* mov #pkt2, (r0) ; read, skip */
0012710, 0001110, /* mov #pkt2, (r0) ; read, skip */
0105711, /* tstb (r1) ; wait */
0100376, /* bpl .-2 */
0012710, 0001104, /* mov #pkt2, (r0) ; read */
0012710, 0001110, /* mov #pkt2, (r0) ; read */
0105711, /* tstb (r1) ; wait */
0100376, /* bpl .-2 */
0005711, /* tst (r1) ; err? */
@ -877,10 +897,10 @@ static const int32 boot_rom[] = {
0005007, /* clr r7 */
0046523, /* pad */
0140004, /* pkt1: 140004, wcpk, 0, 8. */
0001074,
0001100,
0000000,
0000010,
0001116, /* wcpk: msg, 0, 14., 0 */
0001122, /* wcpk: msg, 0, 14., 0 */
0000000,
0000016,
0000000,
@ -889,6 +909,7 @@ static const int32 boot_rom[] = {
0000000,
0001000,
0000000 /* hlt: halt */
/* msg: .blk 4 */
};
t_stat ts_boot (int32 unitno)

View file

@ -25,6 +25,8 @@
cpu PDP-4/7/9/15 central processor
19-Sep-01 RMS Fixed bug in EAE (found by Dave Conroy)
17-Sep-01 RMS Fixed typo in conditional
10-Aug-01 RMS Removed register from declarations
17-Jul-01 RMS Moved function prototype
27-May-01 RMS Added second Teletype support, fixed bug in API
@ -256,7 +258,7 @@
#else
#define EAE_DFLT 0
#endif
#if defined (PDP4) || (PDP7)
#if defined (PDP4) || defined (PDP7)
#define API_DFLT UNIT_NOAPI
#else
#define API_DFLT UNIT_NOAPI /* for now */
@ -612,7 +614,7 @@ api_cycle = 0; /* not API cycle */
/* Main instruction fetch/decode loop: check trap and interrupt */
while (reason == 0) { /* loop until halted */
int32 IR, MA, t, xct_count;
int32 IR, MA, esc, t, xct_count;
int32 link_init, fill;
if (sim_interval <= 0) { /* check clock queue */
@ -1086,6 +1088,7 @@ case 033: case 032: /* EAE */
if (IR & 0001000) LAC = LAC & 01000000; /* IR<8>? clear AC */
link_init = LAC & 01000000; /* link temporary */
fill = link_init? 0777777: 0; /* fill = link */
esc = (IR & 077)? IR & 077: 0100; /* get eff SC */
switch ((IR >> 6) & 07) { /* case on IR<9:11> */
case 0: /* setup */
@ -1100,7 +1103,7 @@ case 033: case 032: /* EAE */
PC = INCR_ADDR (PC); /* increment PC */
if (eae_ac_sign) MQ = MQ ^ 0777777; /* EAE AC sign? ~MQ */
LAC = LAC & 0777777; /* clear link */
for (SC = IR & 077; SC != 0; SC--) { /* loop per step cnt */
for (SC = esc; SC != 0; SC--) { /* loop per step cnt */
if (MQ & 1) LAC = LAC + MA; /* MQ<17>? add */
MQ = (MQ >> 1) | ((LAC & 1) << 17);
LAC = LAC >> 1; } /* shift AC'MQ right */
@ -1130,7 +1133,7 @@ case 033: case 032: /* EAE */
break; }
LAC = LAC & 0777777; /* clear link */
t = 0; /* init loop */
for (SC = IR & 077; SC != 0; SC--) {
for (SC = esc; SC != 0; SC--) { /* loop per step cnt */
if (t) LAC = (LAC + MA) & 01777777;
else LAC = (LAC - MA) & 01777777;
t = (LAC >> 18) & 1; /* quotient bit */
@ -1153,40 +1156,38 @@ case 033: case 032: /* EAE */
#if defined (PDP15)
if (!usmd) ion_defer = 2; /* free cycles */
#endif
for (SC = IR & 077; ((LAC & 0400000) ==
((LAC << 1) & 0400000)) && (SC != 0); SC--) {
for (SC = esc; (SC != 0) && ((LAC & 0400000) ==
((LAC << 1) & 0400000)); SC--) {
LAC = (LAC << 1) | ((MQ >> 17) & 1);
MQ = (MQ << 1) | (link_init >> 18); }
LAC = link_init | (LAC & 0777777); /* trim AC, restore L */
MQ = MQ & 0777777; /* trim MQ */
SC = SC & 077; /* trim SC */
break;
case 5: /* long right shift */
t = IR & 077; /* get shift count */
if (t < 18) {
MQ = ((LAC << (18 - t)) | (MQ >> t)) & 0777777;
LAC = ((fill << (18 - t)) | (LAC >> t)) & 01777777; }
else { if (t < 36) MQ =
((fill << (36 - t)) | (LAC >> (t - 18))) & 0777777;
if (esc < 18) {
MQ = ((LAC << (18 - esc)) | (MQ >> esc)) & 0777777;
LAC = ((fill << (18 - esc)) | (LAC >> esc)) & 01777777; }
else { if (esc < 36) MQ =
((fill << (36 - esc)) | (LAC >> (esc - 18))) & 0777777;
else MQ = fill;
LAC = link_init | fill; }
SC = 0; /* clear step count */
break;
case 6: /* long left shift */
t = IR & 077; /* get shift count */
if (t < 18) {
if (esc < 18) {
LAC = link_init |
(((LAC << t) | (MQ >> (18 - t))) & 0777777);
MQ = ((MQ << t) | (fill >> (18 - t))) & 0777777; }
else { if (t < 36) LAC = link_init |
(((MQ << (t - 18)) | (fill >> (36 - t))) & 0777777);
(((LAC << esc) | (MQ >> (18 - esc))) & 0777777);
MQ = ((MQ << esc) | (fill >> (18 - esc))) & 0777777; }
else { if (esc < 36) LAC = link_init |
(((MQ << (esc - 18)) | (fill >> (36 - esc))) & 0777777);
else LAC = link_init | fill;
MQ = fill; }
SC = 0; /* clear step count */
break;
case 7: /* AC left shift */
t = IR & 077; /* get shift count */
if (t < 18) LAC = link_init |
(((LAC << t) | (fill >> (18 - t))) & 0777777);
if (esc < 18) LAC = link_init |
(((LAC << esc) | (fill >> (18 - esc))) & 0777777);
else LAC = link_init | fill;
SC = 0; /* clear step count */
break; } /* end switch IR */

View file

@ -26,6 +26,7 @@
dt (PDP-9) TC02/TU55 DECtape
(PDP-15) TC15/TU56 DECtape
29-Aug-01 RMS Added casts to PDP-8 unpack routine
17-Jul-01 RMS Moved function prototype
11-May-01 RMS Fixed bug in reset
26-Apr-01 RMS Added device enable/disable support
@ -1008,10 +1009,10 @@ if (uptr -> flags & UNIT_8FMT) { /* PDP-8? */
if (k == 0) break;
for ( ; k < D8_NBSIZE; k++) pdp8b[k] = 0;
for (k = 0; k < D8_NBSIZE; k = k + 3) { /* loop thru blk */
bptr[ba] = ((pdp8b[k] & 07777) << 6) |
((pdp8b[k + 1] >> 6) & 077);
bptr[ba] = ((uint32) (pdp8b[k] & 07777) << 6) |
((uint32) (pdp8b[k + 1] >> 6) & 077);
bptr[ba + 1] = ((pdp8b[k + 1] & 077) << 12) |
(pdp8b[k + 2] & 07777);
((uint32) (pdp8b[k + 2] & 07777));
ba = ba + 2; } /* end blk loop */
} /* end file loop */
uptr -> hwmark = ba; } /* end if */

View file

@ -27,6 +27,7 @@
(PDP-7,9) Type 647 line printer
(PDP-15) LP15 line printer
19-Sep-01 RMS Fixed bug in 647
13-Feb-01 RMS Revised for register arrays
15-Feb-01 RMS Fixed 3 cycle data break sequence
30-Oct-00 RMS Standardized register naming
@ -234,7 +235,7 @@ int32 lpt65 (int32 pulse, int32 AC)
{
int32 i;
if (pulse == 001) return (int_req & INT_LPT)? IOT_SKP + AC: AC; /* LPSF */
if (pulse == 001) return (lpt_done? IOT_SKP + AC: AC); /* LPSF */
if (pulse & 002) { /* pulse 02 */
lpt_done = 0; /* clear done */
int_req = int_req & ~INT_LPT; } /* clear int req */
@ -265,7 +266,7 @@ return AC;
int32 lpt66 (int32 pulse, int32 AC)
{
if (pulse == 001) return lpt_err? IOT_SKP + AC: AC; /* LPSE */
if (pulse == 001) return (lpt_err? IOT_SKP + AC: AC); /* LPSE */
if (pulse & 002) { /* LPCF */
lpt_done = 0; /* clear done, int */
int_req = int_req & ~INT_LPT; }

View file

@ -29,6 +29,8 @@
tto teleprinter
clk clock
17-Sep-01 RMS Removed multiconsole support
07-Sep-01 RMS Added terminal multiplexor support
17-Jul-01 RMS Moved function prototype
10-Jun-01 RMS Cleaned up IOT decoding to reflect hardware
27-May-01 RMS Added multiconsole support
@ -52,10 +54,8 @@ int32 ptr_err = 0, ptr_stopioe = 0, ptr_state = 0;
int32 ptp_err = 0, ptp_stopioe = 0;
int32 tti_state = 0;
int32 tto_state = 0;
int32 clk_tps = 60;
#if defined (TTY1)
static uint8 tto_consout[CONS_SIZE];
#endif
int32 clk_tps = 60; /* ticks/second */
int32 tmxr_poll = 16000; /* term mux poll */
t_stat clk_svc (UNIT *uptr);
t_stat ptr_svc (UNIT *uptr);
@ -72,8 +72,6 @@ t_stat ptp_attach (UNIT *uptr, char *cptr);
t_stat ptr_detach (UNIT *uptr);
t_stat ptp_detach (UNIT *uptr);
t_stat ptr_boot (int32 unitno);
extern t_stat sim_poll_kbd (void);
extern t_stat sim_putchar (int32 out);
/* CLK data structures
@ -200,9 +198,9 @@ static const int32 tti_trans[128] = {
#define UNIT_HDX (1 << UNIT_V_HDX)
#if defined (PDP4) || defined (PDP7)
UNIT tti_unit = { UDATA (&tti_svc, UNIT_UC+UNIT_CONS, 0), KBD_POLL_WAIT };
UNIT tti_unit = { UDATA (&tti_svc, UNIT_UC, 0), KBD_POLL_WAIT };
#else
UNIT tti_unit = { UDATA (&tti_svc, UNIT_UC+UNIT_HDX+UNIT_CONS, 0), KBD_POLL_WAIT };
UNIT tti_unit = { UDATA (&tti_svc, UNIT_UC+UNIT_HDX, 0), KBD_POLL_WAIT };
#endif
REG tti_reg[] = {
@ -217,16 +215,9 @@ REG tti_reg[] = {
#endif
{ DRDATA (POS, tti_unit.pos, 31), PV_LEFT },
{ DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT },
#if defined (TTY1)
{ FLDATA (CFLAG, tti_unit.flags, UNIT_V_CONS), REG_HRO },
#endif
{ NULL } };
MTAB tti_mod[] = {
#if defined (TTY1)
{ UNIT_CONS, 0, "inactive", NULL, NULL },
{ UNIT_CONS, UNIT_CONS, "active console", "CONSOLE", &set_console },
#endif
#if !defined (KSR28)
{ UNIT_UC, 0, "lower case", "LC", NULL },
{ UNIT_UC, UNIT_UC, "upper case", "UC", NULL },
@ -269,7 +260,7 @@ static const char tto_trans[64] = {
#define TTO_MASK ((1 << TTO_WIDTH) - 1)
UNIT tto_unit = { UDATA (&tto_svc, UNIT_UC+UNIT_CONS, 0), SERIAL_OUT_WAIT };
UNIT tto_unit = { UDATA (&tto_svc, UNIT_UC, 0), SERIAL_OUT_WAIT };
REG tto_reg[] = {
{ ORDATA (BUF, tto_unit.buf, TTO_WIDTH) },
@ -280,17 +271,9 @@ REG tto_reg[] = {
#endif
{ DRDATA (POS, tto_unit.pos, 31), PV_LEFT },
{ DRDATA (TIME, tto_unit.wait, 24), PV_LEFT },
#if defined (TTY1)
{ BRDATA (CONSOUT, tto_consout, 8, 8, CONS_SIZE), REG_HIDDEN },
{ FLDATA (CFLAG, tto_unit.flags, UNIT_V_CONS), REG_HRO },
#endif
{ NULL } };
MTAB tto_mod[] = {
#if defined (TTY1)
{ UNIT_CONS, 0, "inactive", NULL, NULL },
{ UNIT_CONS, UNIT_CONS, "active console", "CONSOLE", &set_console },
#endif
#if !defined (KSR28)
{ UNIT_UC, 0, "lower case", "LC", NULL },
{ UNIT_UC, UNIT_UC, "upper case", "UC", NULL },
@ -324,11 +307,14 @@ return AC;
t_stat clk_svc (UNIT *uptr)
{
int32 t;
if (clk_state) { /* clock on? */
M[7] = (M[7] + 1) & 0777777; /* incr counter */
if (M[7] == 0) int_req = int_req | INT_CLK; /* ovrflo? set flag */
sim_activate (&clk_unit, /* reactivate unit */
sim_rtc_calb (clk_tps)); } /* calibr delay */
t = sim_rtc_calb (clk_tps); /* calibrate clock */
sim_activate (&clk_unit, t); /* reactivate unit */
tmxr_poll = t; } /* set mux poll */
return SCPE_OK;
}
@ -339,6 +325,7 @@ t_stat clk_reset (DEVICE *dptr)
int_req = int_req & ~INT_CLK; /* clear flag */
clk_state = 0; /* clock off */
sim_cancel (&clk_unit); /* stop clock */
tmxr_poll = clk_unit.wait; /* set mux poll */
return SCPE_OK;
}
@ -346,7 +333,7 @@ return SCPE_OK;
int32 std_iors (void)
{
return ((int_req & INT_CLK)? IOS_CLK: 0) |
return ((int_req & INT_CLK)? IOS_CLK: 0) |
((int_req & INT_PTR)? IOS_PTR: 0) |
((int_req & INT_PTP)? IOS_PTP: 0) |
((int_req & INT_TTI)? IOS_TTI: 0) |
@ -714,7 +701,7 @@ if ((tti_unit.flags & UNIT_UC) && islower (temp)) temp = toupper (temp);
if ((tti_unit.flags & UNIT_HDX) &&
(!(tto_unit.flags & UNIT_UC) ||
((temp >= 007) && (temp <= 0137)))) {
sim_putcons (temp, uptr);
sim_putchar (temp);
tto_unit.pos = tto_unit.pos + 1; }
tti_unit.buf = temp | 0200; /* got char */
#endif
@ -730,9 +717,6 @@ t_stat tti_reset (DEVICE *dptr)
tti_unit.buf = 0; /* clear buffer */
tti_state = 0; /* clear state */
int_req = int_req & ~INT_TTI; /* clear flag */
#if defined (TTY1)
if (tti_unit.flags & UNIT_CONS) /* if active cons */
#endif
sim_activate (&tti_unit, tti_unit.wait); /* activate unit */
return SCPE_OK;
}
@ -770,7 +754,7 @@ out = tto_unit.buf & 0177; /* ASCII... */
#endif
if (!(tto_unit.flags & UNIT_UC) ||
((out >= 007) && (out <= 0137))) {
temp = sim_putcons (out, uptr);
temp = sim_putchar (out);
if (temp != SCPE_OK) return temp;
tto_unit.pos = tto_unit.pos + 1; }
return SCPE_OK;
@ -784,8 +768,5 @@ tto_unit.buf = 0; /* clear buffer */
tto_state = 0; /* clear state */
int_req = int_req & ~INT_TTO; /* clear flag */
sim_cancel (&tto_unit); /* deactivate unit */
#if defined (TTY1)
tto_unit.filebuf = tto_consout;
#endif
return SCPE_OK;
}

View file

@ -23,6 +23,7 @@
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.
17-Sep-01 RMS Removed multiconsole support
27-May-01 RMS Added second Teletype support
18-May-01 RMS Added PDP-9,-15 API IOT's
12-May-01 RMS Fixed bug in RIM loaders
@ -117,15 +118,6 @@ DEVICE *sim_devices[] = { &cpu_dev,
#endif
NULL };
#if defined (TTY1)
UNIT *sim_consoles[] = {
&tti_unit, &tto_unit,
&tti1_unit, &tto1_unit,
NULL };
#else
UNIT *sim_consoles = NULL;
#endif
const char *sim_stop_messages[] = {
"Unknown error",
"Undefined instruction",

View file

@ -26,23 +26,32 @@
tti1 keyboard
tto1 teleprinter
19-Sep-01 RMS Fixed typo
17-Sep-01 RMS Changed to use terminal multiplexor library
07-Sep-01 RMS Moved function prototypes
10-Jun-01 RMS Cleaned up IOT decoding to reflect hardware
*/
#include "pdp18b_defs.h"
#include "sim_sock.h"
#include "sim_tmxr.h"
#include <ctype.h>
#define UNIT_V_UC (UNIT_V_UF + 0) /* UC only */
#define UNIT_UC (1 << UNIT_V_UC)
extern int32 int_req, saved_PC;
extern int32 tmxr_poll; /* calibrated poll */
TMLN tt1_ldsc = { 0 }; /* line descriptors */
TMXR tt_desc = { 1, 0, &tt1_ldsc }; /* mux descriptor */
t_stat tti1_svc (UNIT *uptr);
t_stat tto1_svc (UNIT *uptr);
t_stat tti1_reset (DEVICE *dptr);
t_stat tto1_reset (DEVICE *dptr);
extern t_stat sim_poll_kbd (void);
extern t_stat sim_putchar (int32 out);
static uint8 tto1_consout[CONS_SIZE];
t_stat tti1_attach (UNIT *uptr, char *cptr);
t_stat tti1_detach (UNIT *uptr);
t_stat tti1_status (UNIT *uptr, FILE *st);
/* TTI1 data structures
@ -52,30 +61,28 @@ static uint8 tto1_consout[CONS_SIZE];
tti1_reg TTI1 register list
*/
UNIT tti1_unit = { UDATA (&tti1_svc, UNIT_UC, 0), KBD_POLL_WAIT };
UNIT tti1_unit = { UDATA (&tti1_svc, UNIT_ATTABLE+UNIT_UC, 0), KBD_POLL_WAIT };
REG tti1_reg[] = {
{ ORDATA (BUF, tti1_unit.buf, 8) },
{ FLDATA (INT, int_req, INT_V_TTI1) },
{ FLDATA (DONE, int_req, INT_V_TTI1) },
{ FLDATA (UC, tti1_unit.flags, UNIT_V_UC), REG_HRO },
{ DRDATA (POS, tti1_unit.pos, 31), PV_LEFT },
{ DRDATA (POS, tt1_ldsc.rxcnt, 31), PV_LEFT },
{ DRDATA (TIME, tti1_unit.wait, 24), REG_NZ + PV_LEFT },
{ FLDATA (CFLAG, tti1_unit.flags, UNIT_V_CONS), REG_HRO },
{ NULL } };
MTAB tti1_mod[] = {
{ UNIT_CONS, 0, "inactive", NULL, NULL },
{ UNIT_CONS, UNIT_CONS, "active console", "CONSOLE", &set_console },
MTAB ttx1_mod[] = {
{ UNIT_ATT, UNIT_ATT, "line status:", NULL, &tti1_status },
{ UNIT_UC, 0, "lower case", "LC", NULL },
{ UNIT_UC, UNIT_UC, "upper case", "UC", NULL },
{ 0 } };
DEVICE tti1_dev = {
"TTI1", &tti1_unit, tti1_reg, tti1_mod,
"TTI1", &tti1_unit, tti1_reg, ttx1_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &tti1_reset,
NULL, NULL, NULL };
&tmxr_ex, &tmxr_dep, &tti1_reset,
NULL, &tti1_attach, &tti1_detach };
/* TTO1 data structures
@ -91,21 +98,12 @@ REG tto1_reg[] = {
{ ORDATA (BUF, tto1_unit.buf, 8) },
{ FLDATA (INT, int_req, INT_V_TTO1) },
{ FLDATA (DONE, int_req, INT_V_TTO1) },
{ DRDATA (POS, tto1_unit.pos, 31), PV_LEFT },
{ DRDATA (POS, tt1_ldsc.txcnt, 31), PV_LEFT },
{ DRDATA (TIME, tto1_unit.wait, 24), PV_LEFT },
{ BRDATA (CONSOUT, tto1_consout, 8, 8, CONS_SIZE), REG_HIDDEN },
{ FLDATA (CFLAG, tto1_unit.flags, UNIT_V_CONS), REG_HRO },
{ NULL } };
MTAB tto1_mod[] = {
{ UNIT_CONS, 0, "inactive", NULL, NULL },
{ UNIT_CONS, UNIT_CONS, "active console", "CONSOLE", &set_console },
{ UNIT_UC, 0, "lower case", "LC", NULL },
{ UNIT_UC, UNIT_UC, "upper case", "UC", NULL },
{ 0 } };
DEVICE tto1_dev = {
"TTO1", &tto1_unit, tto1_reg, tto1_mod,
"TTO1", &tto1_unit, tto1_reg, ttx1_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &tto1_reset,
NULL, NULL, NULL };
@ -126,15 +124,23 @@ return AC;
t_stat tti1_svc (UNIT *uptr)
{
int32 temp;
int32 temp, newln;
sim_activate (&tti1_unit, tti1_unit.wait); /* continue poll */
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */
temp = temp & 0177;
if ((tti1_unit.flags & UNIT_UC) && islower (temp)) temp = toupper (temp);
tti1_unit.buf = temp | 0200; /* got char */
int_req = int_req | INT_TTI1; /* set flag */
tti1_unit.pos = tti1_unit.pos + 1;
if (tt1_ldsc.conn) { /* connected? */
tmxr_poll_rx (&tt_desc); /* poll for input */
if (temp = tmxr_getc_ln (&tt1_ldsc)) { /* get char */
temp = temp & 0177;
if ((uptr -> flags & UNIT_UC) &&
islower (temp)) temp = toupper (temp);
uptr -> buf = temp | 0200; /* got char */
int_req = int_req | INT_TTI1; } /* set flag */
sim_activate (uptr, uptr -> wait); } /* continue poll */
if (uptr -> flags & UNIT_ATT) { /* attached? */
newln = tmxr_poll_conn (&tt_desc, uptr); /* poll connect */
if (newln >= 0) { /* got one? */
sim_activate (&tti1_unit, tti1_unit.wait);
tt1_ldsc.rcve = 1; } /* rcv enabled */
sim_activate (uptr, tmxr_poll); } /* sched poll */
return SCPE_OK;
}
@ -143,9 +149,13 @@ return SCPE_OK;
t_stat tti1_reset (DEVICE *dptr)
{
tti1_unit.buf = 0; /* clear buffer */
int_req = int_req & ~INT_TTI; /* clear flag */
if (tti1_unit.flags & UNIT_CONS) /* if active console */
sim_activate (&tti1_unit, tti1_unit.wait); /* activate unit */
int_req = int_req & ~INT_TTI1; /* clear flag */
if (tt1_ldsc.conn) { /* if conn, */
sim_activate (&tti1_unit, tti1_unit.wait); /* activate, */
tt1_ldsc.rcve = 1; } /* enable */
else if (tti1_unit.flags & UNIT_ATT) /* if attached, */
sim_activate (&tti1_unit, tmxr_poll); /* activate */
else sim_cancel (&tti1_unit); /* else stop */
return SCPE_OK;
}
@ -166,15 +176,19 @@ return AC;
t_stat tto1_svc (UNIT *uptr)
{
int32 out, temp;
int32 out;
int_req = int_req | INT_TTO1; /* set flag */
out = tto1_unit.buf & 0177;
if (!(tto1_unit.flags & UNIT_UC) ||
((out >= 007) && (out <= 0137))) {
temp = sim_putcons (out, uptr);
if (temp != SCPE_OK) return temp;
tto1_unit.pos = tto1_unit.pos + 1; }
if (tt1_ldsc.conn) { /* connected? */
if (tt1_ldsc.xmte) { /* tx enabled? */
if (!(tto1_unit.flags & UNIT_UC) ||
((out >= 007) && (out <= 0137)))
tmxr_putc_ln (&tt1_ldsc, out); /* output char */
tmxr_poll_tx (&tt_desc); } /* poll xmt */
else { tmxr_poll_tx (&tt_desc); /* poll xmt */
sim_activate (&tto1_unit, tmxr_poll); /* wait */
return SCPE_OK; } }
return SCPE_OK;
}
@ -185,6 +199,37 @@ t_stat tto1_reset (DEVICE *dptr)
tto1_unit.buf = 0; /* clear buffer */
int_req = int_req & ~INT_TTO1; /* clear flag */
sim_cancel (&tto1_unit); /* deactivate unit */
tto1_unit.filebuf = tto1_consout; /* set buf pointer */
return SCPE_OK;
}
/* Attach routine */
t_stat tti1_attach (UNIT *uptr, char *cptr)
{
t_stat r;
r = tmxr_attach (&tt_desc, uptr, cptr); /* attach */
if (r != SCPE_OK) return r; /* error */
sim_activate (uptr, tmxr_poll); /* start poll */
return SCPE_OK;
}
/* Detach routine */
t_stat tti1_detach (UNIT *uptr)
{
t_stat r;
r = tmxr_detach (&tt_desc, uptr); /* detach */
tt1_ldsc.rcve = 0; /* disable rcv */
sim_cancel (uptr); /* stop poll */
return r;
}
/* Status routine */
t_stat tti1_status (UNIT *uptr, FILE *st)
{
tmxr_fstatus (st, &tt1_ldsc, -1);
return SCPE_OK;
}

View file

@ -28,6 +28,7 @@
tti keyboard
tto teleprinter
07-Sep-01 RMS Moved function prototypes
10-Jun-01 RMS Fixed comment
30-Oct-00 RMS Standardized device naming
*/
@ -55,8 +56,6 @@ t_stat ptp_reset (DEVICE *dptr);
t_stat tti_reset (DEVICE *dptr);
t_stat tto_reset (DEVICE *dptr);
t_stat ptr_boot (int32 unitno);
extern t_stat sim_poll_kbd (void);
extern t_stat sim_putchar (int32 out);
/* Character translation tables */

View file

@ -23,6 +23,7 @@
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.
17-Sep-01 RMS Removed multiconsole support
13-Jul-01 RMS Fixed RIM loader format
27-May-01 RMS Added multiconsole support
14-Mar-01 RMS Revised load/dump interface (again)
@ -52,7 +53,6 @@ extern int32 sc_map[];
sim_PC pointer to saved PC register descriptor
sim_emax number of words for examine
sim_devices array of pointers to simulated devices
sim_consoles array of pointers to consoles (if more than one)
sim_stop_messages array of pointers to stop messages
sim_load binary loader
*/
@ -67,8 +67,6 @@ DEVICE *sim_devices[] = { &cpu_dev,
&ptr_dev, &ptp_dev, &tti_dev, &tto_dev,
&lpt_dev, NULL };
UNIT *sim_consoles = NULL;
const char *sim_stop_messages[] = {
"Unknown error",
"Undefined instruction",

View file

@ -25,6 +25,7 @@
clk real time clock
05-Sep-01 RMS Added terminal multiplexor support
17-Jul-01 RMS Moved function prototype
05-Mar-01 RMS Added clock calibration support
@ -36,7 +37,8 @@
extern int32 int_req, int_enable, dev_done, stop_inst;
t_stat clk_svc (UNIT *uptr);
t_stat clk_reset (DEVICE *dptr);
int32 clk_tps = 60;
int32 clk_tps = 60; /* ticks/second */
int32 tmxr_poll = 16000; /* term mux poll */
/* CLK data structures
@ -103,9 +105,13 @@ default:
t_stat clk_svc (UNIT *uptr)
{
int32 t;
dev_done = dev_done | INT_CLK; /* set done */
int_req = INT_UPDATE; /* update interrupts */
sim_activate (&clk_unit, sim_rtc_calb (clk_tps)); /* reactivate unit */
t = sim_rtc_calb (clk_tps); /* calibrate clock */
sim_activate (&clk_unit, t); /* reactivate unit */
tmxr_poll = t; /* set mux poll */
return SCPE_OK;
}
@ -117,5 +123,6 @@ dev_done = dev_done & ~INT_CLK; /* clear done, int */
int_req = int_req & ~INT_CLK;
int_enable = int_enable & ~INT_CLK; /* clear enable */
sim_activate (&clk_unit, clk_unit.wait); /* activate unit */
tmxr_poll = clk_unit.wait; /* set mux poll */
return SCPE_OK;
}

View file

@ -25,6 +25,7 @@
cpu central processor
16-Sep-01 RMS Fixed bug in reset routine, added KL8A support
10-Aug-01 RMS Removed register from declarations
17-Jul-01 RMS Moved function prototype
07-Jun-01 RMS Fixed bug in JMS to non-existent memory
@ -284,6 +285,8 @@ extern int32 ptr (int32 pulse, int32 AC);
extern int32 ptp (int32 pulse, int32 AC);
extern int32 clk (int32 pulse, int32 AC);
extern int32 lpt (int32 pulse, int32 AC);
extern int32 ttix (int32 inst, int32 AC);
extern int32 ttox (int32 inst, int32 AC);
extern int32 rk (int32 pulse, int32 AC);
extern int32 rx (int32 pulse, int32 AC);
extern int32 df60 (int32 pulse, int32 AC);
@ -1018,6 +1021,12 @@ case 030:case 031:case 032:case 033: /* IOT */
case 013: /* CLK */
iot_data = clk (pulse, iot_data);
break;
case 040: case 042: case 044: case 046: /* KL8A in */
iot_data = ttix (IR, iot_data);
break;
case 041: case 043: case 045: case 047: /* KL8A out */
iot_data = ttox (IR, iot_data);
break;
case 060: /* DF32/RF08 */
if (dev_enb & INT_DF) iot_data = df60 (pulse, iot_data);
else if (dev_enb & INT_RF) iot_data = rf60 (pulse, iot_data);
@ -1087,7 +1096,7 @@ return reason;
t_stat cpu_reset (DEVICE *dptr)
{
int_req = (int_req & ~INT_ION) | INT_NO_CIF_PENDING;
saved_DF = IB = (saved_PC >> 12) & 03;
saved_DF = IB = saved_PC & 070000;
UF = UB = gtf = emode = 0;
return cpu_svc (&cpu_unit);
}

View file

@ -23,6 +23,7 @@
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.
16-Sep-01 RMS Added multiple KL support
18-Mar-01 RMS Added DF32 support
15-Feb-01 RMS Added DECtape support
14-Apr-99 RMS Changed t_addr to unsigned
@ -73,6 +74,9 @@
Because the PDP-8 does not have priority interrupts, the order
of devices within groups does not matter.
Note: all extra KL input and output interrupts must be assigned
to contiguous bits.
*/
#define INT_V_START 0 /* enable start */
@ -82,7 +86,15 @@
#define INT_V_TTO (INT_V_START+3) /* terminal */
#define INT_V_TTI (INT_V_START+4) /* keyboard */
#define INT_V_CLK (INT_V_START+5) /* clock */
#define INT_V_DIRECT (INT_V_START+6) /* direct start */
#define INT_V_TTO1 (INT_V_START+6) /* tto1 */
#define INT_V_TTO2 (INT_V_START+7) /* tto2 */
#define INT_V_TTO3 (INT_V_START+8) /* tto3 */
#define INT_V_TTO4 (INT_V_START+9) /* tto4 */
#define INT_V_TTI1 (INT_V_START+10) /* tti1 */
#define INT_V_TTI2 (INT_V_START+11) /* tti2 */
#define INT_V_TTI3 (INT_V_START+12) /* tti3 */
#define INT_V_TTI4 (INT_V_START+13) /* tti4 */
#define INT_V_DIRECT (INT_V_START+14) /* direct start */
#define INT_V_RX (INT_V_DIRECT+0) /* RX8E */
#define INT_V_RK (INT_V_DIRECT+1) /* RK8E */
#define INT_V_RF (INT_V_DIRECT+2) /* RF08 */
@ -102,6 +114,14 @@
#define INT_TTO (1 << INT_V_TTO)
#define INT_TTI (1 << INT_V_TTI)
#define INT_CLK (1 << INT_V_CLK)
#define INT_TTO1 (1 << INT_V_TTO1)
#define INT_TTO2 (1 << INT_V_TTO2)
#define INT_TTO3 (1 << INT_V_TTO3)
#define INT_TTO4 (1 << INT_V_TTO4)
#define INT_TTI1 (1 << INT_V_TTI1)
#define INT_TTI2 (1 << INT_V_TTI2)
#define INT_TTI3 (1 << INT_V_TTI3)
#define INT_TTI4 (1 << INT_V_TTI4)
#define INT_RX (1 << INT_V_RX)
#define INT_RK (1 << INT_V_RK)
#define INT_RF (1 << INT_V_RF)

View file

@ -25,6 +25,7 @@
dt TC08/TU56 DECtape
29-Aug-01 RMS Added casts to PDP-18b packup routine
17-Jul-01 RMS Moved function prototype
11-May-01 RMS Fixed bug in reset
25-Apr-01 RMS Added device enable/disable support
@ -1130,10 +1131,10 @@ if (uptr -> hwmark) { /* any data? */
else { /* PDP9/11/15 */
for (ba = 0; ba < uptr -> hwmark; ) { /* loop thru buf */
for (k = 0; k < D18_NBSIZE; k = k + 2) {
pdp18b[k] = ((bptr[ba] & 07777) << 6) |
((bptr[ba + 1] >> 6) & 077);
pdp18b[k + 1] = ((bptr[ba + 1] & 077) << 12) |
(bptr[ba + 2] & 07777);
pdp18b[k] = ((uint32) (bptr[ba] & 07777) << 6) |
((uint32) (bptr[ba + 1] >> 6) & 077);
pdp18b[k + 1] = ((uint32) (bptr[ba + 1] & 077) << 12) |
((uint32) (bptr[ba + 2] & 07777));
ba = ba + 3; } /* end loop blk */
fxwrite (pdp18b, sizeof (int32),
D18_NBSIZE, uptr -> fileref);

View file

@ -23,6 +23,8 @@
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.
17-Sep-01 RMS Removed multiconsole support
16-Sep-01 RMS Added TSS/8 packed char support, added KL8A support
27-May-01 RMS Added multiconsole support
18-Mar-01 RMS Added DF32 support
14-Mar-01 RMS Added extension detection of RIM binary tapes
@ -44,6 +46,10 @@ extern DEVICE clk_dev, lpt_dev;
extern DEVICE rk_dev, rx_dev;
extern DEVICE df_dev, rf_dev;
extern DEVICE dt_dev, mt_dev;
extern DEVICE tti1_dev, tto1_dev;
extern DEVICE tti2_dev, tto2_dev;
extern DEVICE tti3_dev, tto3_dev;
extern DEVICE tti4_dev, tto4_dev;
extern REG cpu_reg[];
extern uint16 M[];
extern int32 sim_switches;
@ -69,14 +75,16 @@ DEVICE *sim_devices[] = {
&cpu_dev,
&ptr_dev, &ptp_dev,
&tti_dev, &tto_dev,
&tti1_dev, &tto1_dev,
&tti2_dev, &tto2_dev,
&tti3_dev, &tto3_dev,
&tti4_dev, &tto4_dev,
&clk_dev, &lpt_dev,
&rk_dev, &rx_dev,
&df_dev, &rf_dev,
&dt_dev, &mt_dev,
NULL };
UNIT *sim_consoles = NULL;
const char *sim_stop_messages[] = {
"Unknown error",
"Unimplemented instruction",
@ -333,6 +341,7 @@ return sp;
#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x)
#define SIXTOASC(x) (((x) >= 040)? (x): (x) + 0100)
#define TSSTOASC(x) ((x) + 040)
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
UNIT *uptr, int32 sw)
@ -350,6 +359,10 @@ if (sw & SWMASK ('C')) { /* characters? */
fprintf (of, "%c", SIXTOASC ((inst >> 6) & 077));
fprintf (of, "%c", SIXTOASC (inst & 077));
return SCPE_OK; }
if (sw & SWMASK ('T')) { /* TSS8 packed? */
fprintf (of, "%c", TSSTOASC ((inst >> 6) & 077));
fprintf (of, "%c", TSSTOASC (inst & 077));
return SCPE_OK; }
if (!(sw & SWMASK ('M'))) return SCPE_ARG;
/* Instruction decode */
@ -423,6 +436,11 @@ if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* sixbit string? */
val[0] = (((t_value) cptr[0] & 077) << 6) |
((t_value) cptr[1] & 077);
return SCPE_OK; }
if ((sw & SWMASK ('T')) || ((*cptr == '"') && cptr++)) { /* TSS8 string? */
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
val[0] = (((t_value) (cptr[0] - 040) & 077) << 6) |
((t_value) (cptr[1] - 040) & 077);
return SCPE_OK; }
/* Instruction parse */

View file

@ -24,6 +24,8 @@
in this Software without prior written authorization from Robert M Supnik.
tti,tto KL8E terminal input/output
07-Sep-01 RMS Moved function prototypes
*/
#include "pdp8_defs.h"
@ -36,8 +38,6 @@ t_stat tti_svc (UNIT *uptr);
t_stat tto_svc (UNIT *uptr);
t_stat tti_reset (DEVICE *dptr);
t_stat tto_reset (DEVICE *dptr);
extern t_stat sim_poll_kbd (void);
extern t_stat sim_putchar (int32 out);
/* TTI data structures

423
pdp8_ttx.c Normal file
View file

@ -0,0 +1,423 @@
/* pdp8_ttx.c: PDP-8 additional terminals simulator
Copyright (c) 1993-2001, 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.
ttix,ttox PT08/KL8JA terminal input/output
This module implements four individual serial interfaces similar in function
to the console. These interfaces are mapped to Telnet based connections as
though they were the four lines of a terminal multiplexor. The connection
polling mechanism is superimposed onto the keyboard of the first interface.
*/
#include "pdp8_defs.h"
#include "sim_sock.h"
#include "sim_tmxr.h"
#include <ctype.h>
#define TTX_LINES 4
#define TTX_MASK (TTX_LINES - 1)
#define UNIT_V_UC (UNIT_V_UF + 0) /* UC only */
#define UNIT_UC (1 << UNIT_V_UC)
#define TTX_GETLN(x) (((x) >> 4) & TTX_MASK)
extern int32 int_req, int_enable, dev_done, stop_inst;
extern int32 tmxr_poll; /* calibrated poll */
TMLN tt1_ldsc = { 0 }; /* line descriptors */
TMLN tt2_ldsc = { 0 }; /* line descriptors */
TMLN tt3_ldsc = { 0 }; /* line descriptors */
TMLN tt4_ldsc = { 0 }; /* line descriptors */
TMXR ttx_desc = { /* mux descriptor */
TTX_LINES, 0, &tt1_ldsc, &tt2_ldsc, &tt3_ldsc, &tt4_ldsc };
t_stat ttix_svc (UNIT *uptr);
t_stat ttix_reset (DEVICE *dptr);
t_stat ttox_svc (UNIT *uptr);
t_stat ttox_reset (DEVICE *dptr);
t_stat ttx_attach (UNIT *uptr, char *cptr);
t_stat ttx_detach (UNIT *uptr);
t_stat ttx_status (UNIT *uptr, FILE *st);
/* TTIx data structures
ttix_dev TTIx device descriptor
ttix_unit TTIx unit descriptor
ttix_reg TTIx register list
ttix_mod TTIx modifiers list
*/
MTAB ttix_mod[] = {
{ UNIT_UC, 0, "lower case", "LC", NULL },
{ UNIT_UC, UNIT_UC, "upper case", "UC", NULL },
{ UNIT_ATT, UNIT_ATT, "line status:", NULL, &ttx_status },
{ 0 } };
UNIT ttix_unit[] = {
{ UDATA (&ttix_svc, UNIT_ATTABLE+UNIT_UC, 0), KBD_POLL_WAIT },
{ UDATA (&ttix_svc, UNIT_UC, 0), KBD_POLL_WAIT },
{ UDATA (&ttix_svc, UNIT_UC, 0), KBD_POLL_WAIT },
{ UDATA (&ttix_svc, UNIT_UC, 0), KBD_POLL_WAIT } };
#define tti1_unit ttix_unit[0]
#define tti2_unit ttix_unit[1]
#define tti3_unit ttix_unit[2]
#define tti4_unit ttix_unit[3]
REG tti1_reg[] = {
{ ORDATA (BUF, tti1_unit.buf, 8) },
{ FLDATA (DONE, dev_done, INT_V_TTI1) },
{ FLDATA (ENABLE, int_enable, INT_V_TTI1) },
{ FLDATA (INT, int_req, INT_V_TTI1) },
{ DRDATA (POS, tt1_ldsc.rxcnt, 32), PV_LEFT },
{ DRDATA (TIME, tti1_unit.wait, 24), REG_NZ + PV_LEFT },
{ FLDATA (UC, tti1_unit.flags, UNIT_V_UC), REG_HRO },
{ NULL } };
DEVICE tti1_dev = {
"TTI1", &tti1_unit, tti1_reg, ttix_mod,
1, 10, 31, 1, 8, 8,
&tmxr_ex, &tmxr_dep, &ttix_reset,
NULL, &ttx_attach, &ttx_detach };
REG tti2_reg[] = {
{ ORDATA (BUF, tti2_unit.buf, 8) },
{ FLDATA (DONE, dev_done, INT_V_TTI2) },
{ FLDATA (ENABLE, int_enable, INT_V_TTI2) },
{ FLDATA (INT, int_req, INT_V_TTI2) },
{ DRDATA (POS, tt2_ldsc.rxcnt, 32), PV_LEFT },
{ DRDATA (TIME, tti2_unit.wait, 24), REG_NZ + PV_LEFT },
{ FLDATA (UC, tti2_unit.flags, UNIT_V_UC), REG_HRO },
{ NULL } };
DEVICE tti2_dev = {
"TTI2", &tti2_unit, tti2_reg, ttix_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &ttix_reset,
NULL, NULL, NULL };
REG tti3_reg[] = {
{ ORDATA (BUF, tti3_unit.buf, 8) },
{ FLDATA (DONE, dev_done, INT_V_TTI3) },
{ FLDATA (ENABLE, int_enable, INT_V_TTI3) },
{ FLDATA (INT, int_req, INT_V_TTI3) },
{ DRDATA (POS, tt3_ldsc.rxcnt, 32), PV_LEFT },
{ DRDATA (TIME, tti3_unit.wait, 24), REG_NZ + PV_LEFT },
{ FLDATA (UC, tti3_unit.flags, UNIT_V_UC), REG_HRO },
{ NULL } };
DEVICE tti3_dev = {
"TTI3", &tti3_unit, tti3_reg, ttix_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &ttix_reset,
NULL, NULL, NULL };
REG tti4_reg[] = {
{ ORDATA (BUF, tti4_unit.buf, 8) },
{ FLDATA (DONE, dev_done, INT_V_TTI4) },
{ FLDATA (ENABLE, int_enable, INT_V_TTI4) },
{ FLDATA (INT, int_req, INT_V_TTI4) },
{ DRDATA (POS, tt4_ldsc.rxcnt, 32), PV_LEFT },
{ DRDATA (TIME, tti4_unit.wait, 24), REG_NZ + PV_LEFT },
{ FLDATA (UC, tti4_unit.flags, UNIT_V_UC), REG_HRO },
{ NULL } };
DEVICE tti4_dev = {
"TTI4", &tti4_unit, tti4_reg, ttix_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &ttix_reset,
NULL, NULL, NULL };
/* TTOx data structures
ttox_dev TTOx device descriptor
ttox_unit TTOx unit descriptor
ttox_reg TTOx register list
*/
UNIT ttox_unit[] = {
{ UDATA (&ttox_svc, 0, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, 0, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, 0, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, 0, 0), SERIAL_OUT_WAIT } };
#define tto1_unit ttox_unit[0]
#define tto2_unit ttox_unit[0]
#define tto3_unit ttox_unit[0]
#define tto4_unit ttox_unit[0]
REG tto1_reg[] = {
{ ORDATA (BUF, tto1_unit.buf, 8) },
{ FLDATA (DONE, dev_done, INT_V_TTO1) },
{ FLDATA (ENABLE, int_enable, INT_V_TTO1) },
{ FLDATA (INT, int_req, INT_V_TTO1) },
{ DRDATA (POS, tt1_ldsc.txcnt, 32), PV_LEFT },
{ DRDATA (TIME, tto1_unit.wait, 24), PV_LEFT },
{ NULL } };
DEVICE tto1_dev = {
"TTO1", &tto1_unit, tto1_reg, NULL,
1, 10, 31, 1, 8, 8,
NULL, NULL, &ttox_reset,
NULL, NULL, NULL };
REG tto2_reg[] = {
{ ORDATA (BUF, tto2_unit.buf, 8) },
{ FLDATA (DONE, dev_done, INT_V_TTO2) },
{ FLDATA (ENABLE, int_enable, INT_V_TTO2) },
{ FLDATA (INT, int_req, INT_V_TTO2) },
{ DRDATA (POS, tt2_ldsc.txcnt, 32), PV_LEFT },
{ DRDATA (TIME, tto2_unit.wait, 24), PV_LEFT },
{ NULL } };
DEVICE tto2_dev = {
"TTO2", &tto2_unit, tto2_reg, NULL,
1, 10, 31, 1, 8, 8,
NULL, NULL, &ttox_reset,
NULL, NULL, NULL };
REG tto3_reg[] = {
{ ORDATA (BUF, tto3_unit.buf, 8) },
{ FLDATA (DONE, dev_done, INT_V_TTO3) },
{ FLDATA (ENABLE, int_enable, INT_V_TTO3) },
{ FLDATA (INT, int_req, INT_V_TTO3) },
{ DRDATA (POS, tt3_ldsc.txcnt, 32), PV_LEFT },
{ DRDATA (TIME, tto3_unit.wait, 24), PV_LEFT },
{ NULL } };
DEVICE tto3_dev = {
"TTO3", &tto3_unit, tto3_reg, NULL,
1, 10, 31, 1, 8, 8,
NULL, NULL, &ttox_reset,
NULL, NULL, NULL };
REG tto4_reg[] = {
{ ORDATA (BUF, tto4_unit.buf, 8) },
{ FLDATA (DONE, dev_done, INT_V_TTO4) },
{ FLDATA (ENABLE, int_enable, INT_V_TTO4) },
{ FLDATA (INT, int_req, INT_V_TTO4) },
{ DRDATA (POS, tt4_ldsc.txcnt, 32), PV_LEFT },
{ DRDATA (TIME, tto4_unit.wait, 24), PV_LEFT },
{ NULL } };
DEVICE tto4_dev = {
"TTO4", &tto4_unit, tto4_reg, NULL,
1, 10, 31, 1, 8, 8,
NULL, NULL, &ttox_reset,
NULL, NULL, NULL };
/* Terminal input: IOT routine */
int32 ttix (int32 inst, int32 AC)
{
int32 pulse = inst & 07; /* IOT pulse */
int32 ln = TTX_GETLN (inst); /* line # */
int32 itti = (INT_TTI1 << ln); /* rx intr */
int32 itto = (INT_TTO1 << ln); /* tx intr */
switch (pulse) { /* case IR<9:11> */
case 0: /* KCF */
dev_done = dev_done & ~itti; /* clear flag */
int_req = int_req & ~itti;
break;
case 1: /* KSF */
return (dev_done & itti)? IOT_SKP + AC: AC;
case 2: /* KCC */
dev_done = dev_done & ~itti; /* clear flag */
int_req = int_req & ~itti;
return 0; /* clear AC */
case 4: /* KRS */
return (AC | ttix_unit[ln].buf); /* return buf */
case 5: /* KIE */
if (AC & 1) int_enable = int_enable | (itti + itto);
else int_enable = int_enable & ~(itti + itto);
int_req = INT_UPDATE; /* update intr */
break;
case 6: /* KRB */
dev_done = dev_done & ~itti; /* clear flag */
int_req = int_req & ~itti;
return ttix_unit[ln].buf; /* return buf */
default:
return (stop_inst << IOT_V_REASON) + AC; } /* end switch */
return AC;
}
/* Unit service */
t_stat ttix_svc (UNIT *uptr)
{
int32 temp, newln;
int32 ln = uptr - ttix_unit; /* line # */
int32 itti = (INT_TTI1 << ln); /* rx intr */
if (ttx_desc.ldsc[ln] -> conn) { /* connected? */
tmxr_poll_rx (&ttx_desc); /* poll for input */
if (temp = tmxr_getc_ln (ttx_desc.ldsc[ln])) { /* get char */
temp = temp & 0177; /* mask to 7b */
if ((uptr -> flags & UNIT_UC) && islower (temp))
temp = toupper (temp);
uptr -> buf = temp | 0200; /* Teletype code */
dev_done = dev_done | itti; /* set done */
int_req = INT_UPDATE; } /* update intr */
sim_activate (uptr, uptr -> wait); } /* continue poll */
if (uptr -> flags & UNIT_ATT) { /* attached? */
newln = tmxr_poll_conn (&ttx_desc, uptr); /* poll connect */
if (newln >= 0) { /* got one? */
sim_activate (&ttix_unit[newln], ttix_unit[newln].wait);
ttx_desc.ldsc[newln] -> rcve = 1; } /* rcv enabled */
sim_activate (uptr, tmxr_poll); } /* sched poll */
return SCPE_OK;
}
/* Reset routine */
t_stat ttix_reset (DEVICE *dptr)
{
UNIT *uptr = dptr -> units; /* unit */
int32 ln = uptr - ttix_unit; /* line # */
int32 itti = (INT_TTI1 << ln); /* rx intr */
uptr -> buf = 0; /* clr buf */
dev_done = dev_done & ~itti; /* clr done, int */
int_req = int_req & ~itti;
int_enable = int_enable | itti; /* set enable */
if (ttx_desc.ldsc[ln] -> conn) { /* if conn, */
sim_activate (uptr, uptr -> wait); /* activate, */
ttx_desc.ldsc[ln] -> rcve = 1; } /* enable */
else if (uptr -> flags & UNIT_ATT) /* if attached, */
sim_activate (uptr, tmxr_poll); /* activate */
else sim_cancel (uptr); /* else stop */
return SCPE_OK;
}
/* Terminal output: IOT routine */
int32 ttox (int32 inst, int32 AC)
{
int32 pulse = inst & 07; /* pulse */
int32 ln = TTX_GETLN (inst); /* line # */
int32 itti = (INT_TTI1 << ln); /* rx intr */
int32 itto = (INT_TTO1 << ln); /* tx intr */
switch (pulse) { /* case IR<9:11> */
case 0: /* TLF */
dev_done = dev_done | itto; /* set flag */
int_req = INT_UPDATE; /* update intr */
break;
case 1: /* TSF */
return (dev_done & itto)? IOT_SKP + AC: AC;
case 2: /* TCF */
dev_done = dev_done & ~itto; /* clear flag */
int_req = int_req & ~itto; /* clear intr */
break;
case 5: /* SPI */
return (int_req & (itti | itto))? IOT_SKP + AC: AC;
case 6: /* TLS */
dev_done = dev_done & ~itto; /* clear flag */
int_req = int_req & ~itto; /* clear int req */
case 4: /* TPC */
sim_activate (&ttox_unit[ln], ttox_unit[ln].wait); /* activate */
ttox_unit[ln].buf = AC & 0377; /* load buffer */
break;
default:
return (stop_inst << IOT_V_REASON) + AC; } /* end switch */
return AC;
}
/* Unit service */
t_stat ttox_svc (UNIT *uptr)
{
int32 ln = uptr - ttox_unit; /* line # */
int32 itto = (INT_TTO1 << ln); /* tx intr */
if (ttx_desc.ldsc[ln] -> conn) { /* connected? */
if (ttx_desc.ldsc[ln] -> xmte) { /* tx enabled? */
TMLN *lp = ttx_desc.ldsc[ln]; /* get line */
tmxr_putc_ln (lp, uptr -> buf & 0177); /* output char */
tmxr_poll_tx (&ttx_desc); } /* poll xmt */
else { tmxr_poll_tx (&ttx_desc); /* poll xmt */
sim_activate (uptr, tmxr_poll); /* wait */
return SCPE_OK; } }
dev_done = dev_done | itto; /* set done */
int_req = INT_UPDATE; /* update intr */
return SCPE_OK;
}
/* Reset routine */
t_stat ttox_reset (DEVICE *dptr)
{
UNIT *uptr = dptr -> units; /* unit */
int32 ln = uptr - ttox_unit; /* line # */
int32 itto = (INT_TTO1 << ln); /* tx intr */
uptr -> buf = 0; /* clr buf */
dev_done = dev_done & ~itto; /* clr done, int */
int_req = int_req & ~itto;
int_enable = int_enable | itto; /* set enable */
sim_cancel (uptr); /* deactivate */
return SCPE_OK;
}
/* Attach master unit */
t_stat ttx_attach (UNIT *uptr, char *cptr)
{
t_stat r;
r = tmxr_attach (&ttx_desc, uptr, cptr); /* attach */
if (r != SCPE_OK) return r; /* error */
sim_activate (uptr, tmxr_poll); /* start poll */
return SCPE_OK;
}
/* Detach master unit */
t_stat ttx_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_desc.ldsc[i] -> rcve = 0; /* disable rcv */
sim_cancel (&ttix_unit[i]); } /* stop poll */
return SCPE_OK;
}
/* Status */
t_stat ttx_status (UNIT *uptr, FILE *st)
{
int32 i;
for (i = 0; (i < TTX_LINES) && (ttx_desc.ldsc[i] -> conn == 0); i++) ;
if (i < TTX_LINES) {
for (i = 0; i < TTX_LINES; i++) {
if (ttx_desc.ldsc[i] -> conn)
tmxr_fstatus (st, ttx_desc.ldsc[i], i); } }
else fprintf (st, " all disconnected");
return SCPE_OK;
}

193
scp.c
View file

@ -23,6 +23,13 @@
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.
08-Oct-01 RMS Added SHOW VERSION
30-Sep-01 RMS Relaxed attach test in BOOT
27-Sep-01 RMS Added queue count routine, fixed typo in ex/mod
17-Sep-01 RMS Removed multiple console support
07-Sep-01 RMS Removed conditional externs on function prototypes
Added special modifier print
31-Aug-01 RMS Changed int64 to t_int64 for Windoze (V2.7)
18-Jul-01 RMS Minor changes for Macintosh port
12-Jun-01 RMS Fixed bug in big-endian I/O (found by Dave Conroy)
27-May-01 RMS Added multiple console support
@ -56,8 +63,8 @@
13-Apr-95 RMS Added symbolic printouts
*/
#define SCP 1 /* defining module */
#include "sim_defs.h"
#include "sim_rev.h"
#include <signal.h>
#include <ctype.h>
#define EX_D 0 /* deposit */
@ -87,7 +94,6 @@
extern char sim_name[];
extern DEVICE *sim_devices[];
extern UNIT *sim_consoles[];
extern REG *sim_PC;
extern char *sim_stop_messages[];
extern t_stat sim_instr (void);
@ -120,17 +126,17 @@ unsigned char sim_flip[FLIP_SIZE];
#define SZ_D(dp) (size_map[((dp) -> dwidth + CHAR_BIT - 1) / CHAR_BIT])
#define SZ_R(rp) \
(size_map[((rp) -> width + (rp) -> offset + CHAR_BIT - 1) / CHAR_BIT])
#if defined (int64)
#if defined (t_int64)
#define SZ_LOAD(sz,v,mb,j) \
if (sz == sizeof (uint8)) v = *(((uint8 *) mb) + j); \
else if (sz == sizeof (uint16)) v = *(((uint16 *) mb) + j); \
else if (sz == sizeof (uint32)) v = *(((uint32 *) mb) + j); \
else v = *(((uint64 *) mb) + j);
else v = *(((t_uint64 *) mb) + j);
#define SZ_STORE(sz,v,mb,j) \
if (sz == sizeof (uint8)) *(((uint8 *) mb) + j) = (uint8) v; \
else if (sz == sizeof (uint16)) *(((uint16 *) mb) + j) = (uint16) v; \
else if (sz == sizeof (uint32)) *(((uint32 *) mb) + j) = (uint32) v; \
else *(((uint64 *) mb) + j) = v;
else *(((t_uint64 *) mb) + j) = v;
#else
#define SZ_LOAD(sz,v,mb,j) \
if (sz == sizeof (uint8)) v = *(((uint8 *) mb) + j); \
@ -161,14 +167,13 @@ t_stat get_aval (t_addr addr, DEVICE *dptr, UNIT *uptr);
t_value strtotv (char *inptr, char **endptr, int radix);
t_stat fprint_val (FILE *stream, t_value val, int rdx, int wid, int fmt);
void fprint_stopped (FILE *stream, t_stat r);
void sim_chkcons (void);
char *read_line (char *ptr, int size, FILE *stream);
DEVICE *find_dev (char *ptr);
DEVICE *find_unit (char *ptr, int32 *iptr);
DEVICE *find_dev_from_unit (UNIT *uptr);
REG *find_reg (char *ptr, char **optr, DEVICE *dptr);
t_bool qdisable (DEVICE *dptr);
t_stat detach_all (int start_device);
t_stat detach_all (int32 start_device, t_bool shutdown);
t_stat ex_reg (FILE *ofile, t_value val, int flag, REG *rptr, t_addr idx);
t_stat dep_reg (int flag, char *cptr, REG *rptr, t_addr idx);
t_stat ex_addr (FILE *ofile, int flag, t_addr addr, DEVICE *dptr, UNIT *uptr);
@ -179,6 +184,7 @@ char *get_range (char *cptr, t_addr *lo, t_addr *hi, int rdx,
SCHTAB *get_search (char *cptr, DEVICE *dptr, SCHTAB *schptr);
int test_search (t_value val, SCHTAB *schptr);
t_stat step_svc (UNIT *ptr);
t_stat show_version (FILE *st, int flag);
UNIT step_unit = { UDATA (&step_svc, 0, 0) };
const char save_vercur[] = "V2.6";
@ -217,8 +223,8 @@ const char *scp_error_messages[] = {
const size_t size_map[] = { sizeof (int8),
sizeof (int8), sizeof (int16), sizeof (int32), sizeof (int32)
#if defined (int64)
, sizeof (int64), sizeof (int64), sizeof (int64), sizeof (int64)
#if defined (t_int64)
, sizeof (t_int64), sizeof (t_int64), sizeof (t_int64), sizeof (t_int64)
#endif
};
@ -231,7 +237,7 @@ const t_value width_mask[] = { 0,
0x1FFFFF, 0x3FFFFF, 0x7FFFFF, 0xFFFFFF,
0x1FFFFFF, 0x3FFFFFF, 0x7FFFFFF, 0xFFFFFFF,
0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF
#if defined (int64)
#if defined (t_int64)
, 0x1FFFFFFFF, 0x3FFFFFFFF, 0x7FFFFFFFF, 0xFFFFFFFFF,
0x1FFFFFFFFF, 0x3FFFFFFFFF, 0x7FFFFFFFFF, 0xFFFFFFFFFF,
0x1FFFFFFFFFF, 0x3FFFFFFFFFF, 0x7FFFFFFFFFF, 0xFFFFFFFFFFF,
@ -312,7 +318,8 @@ if ((stat = ttinit ()) != SCPE_OK) {
printf ("Fatal terminal initialization error\n%s\n",
scp_error_messages[stat - SCPE_BASE]);
return 0; }
printf ("\n%s simulator V2.6b\n", sim_name);
printf ("\n");
show_version (stdout, 0);
end_test.i = 1; /* test endian-ness */
sim_end = end_test.c[0];
stop_cpu = 0;
@ -363,7 +370,7 @@ do { printf ("sim> "); /* prompt */
scp_error_messages[stat - SCPE_BASE]); }
} while (stat != SCPE_EXIT);
detach_all (0); /* close files */
detach_all (0, TRUE); /* close files */
nolog_cmd (0, NULL); /* close log */
ttclose (); /* close console */
return 0;
@ -400,9 +407,11 @@ fprintf (st, "exi{t}|q{uit}|by{e} exit from simulation\n");
fprintf (st, "set <unit> <val> set unit parameter\n");
fprintf (st, "show <device> show device parameters\n");
fprintf (st, "sh{ow} c{onfiguration} show configuration\n");
fprintf (st, "sh{ow} d{evices} show devices\n");
fprintf (st, "sh{ow} m{odifiers} show modifiers\n");
fprintf (st, "sh{ow} q{ueue} show event queue\n");
fprintf (st, "sh{ow} t{ime} show simulated time\n");
fprintf (st, "sh{ow} v{ersion} show simulator version\n");
fprintf (st, "en{able} <device> enable device\n");
fprintf (st, "di{sable} <device> disable device\n");
fprintf (st, "ad{d} <unit> add unit to configuration\n");
@ -441,23 +450,24 @@ GET_SWITCHES (cptr, gbuf); /* test for switches */
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
dptr = find_unit (gbuf, &unitno); /* find dev+unit */
if ((dptr == NULL) || (dptr -> units == NULL) ||
(*cptr == 0)) return SCPE_ARG; /* argument? */
(*cptr == 0)) return SCPE_ARG; /* argument? */
cptr = get_glyph (cptr, gbuf, 0); /* get glyph */
if (*cptr != 0) return SCPE_ARG; /* now eol? */
uptr = dptr -> units + unitno;
if (uptr -> flags & UNIT_DIS) return SCPE_UDIS; /* disabled? */
for (i = 0; set_table[i].name != NULL; i++) { /* check globals */
if (MATCH_CMD (gbuf, set_table[i].name) == 0)
return set_table[i].action (dptr, set_table[i].arg); }
if (MATCH_CMD (gbuf, set_table[i].name) == 0) {
if (*cptr != 0) return SCPE_ARG; /* now eol? */
return set_table[i].action (dptr, set_table[i].arg); } }
if (dptr -> modifiers == NULL) return SCPE_NOPARAM; /* any modifiers? */
for (mptr = dptr -> modifiers; mptr -> mask != 0; mptr++) {
if ((mptr -> mstring != NULL) &&
(MATCH_CMD (gbuf, mptr -> mstring) == 0)) {
if (*cptr != 0) return SCPE_ARG; /* now eol? */
if ((mptr -> valid != NULL) &&
((r = mptr -> valid (uptr, mptr -> match)) != SCPE_OK))
return r; /* invalid? */
uptr -> flags = (uptr -> flags & ~(mptr -> mask)) |
(mptr -> match & mptr -> mask); /* set new value */
(mptr -> match & mptr -> mask); /* set new value */
return SCPE_OK; } }
return SCPE_ARG; /* no match */
}
@ -491,6 +501,7 @@ static CTAB show_table[] = {
{ "QUEUE", &show_queue, 0 },
{ "TIME", &show_time, 0 },
{ "MODIFIERS", &show_modifiers, 0 },
{ "VERSION", &show_version, 0 },
{ NULL, NULL, 0 } };
GET_SWITCHES (cptr, gbuf); /* test for switches */
@ -536,24 +547,34 @@ for (j = 0; j < dptr -> numunits; j++) {
if (uptr -> flags & UNIT_DIS) continue;
if (ucnt > 1) fprintf (st, " unit %d", j);
if (uptr -> flags & UNIT_FIX) {
if (uptr -> capac < kval)
fprintf (st, ", %d%s", uptr -> capac,
((dptr -> dwidth / dptr -> aincr) > 8)? "W": "B");
else fprintf (st, ", %dK%s", uptr -> capac / kval,
((dptr -> dwidth / dptr -> aincr) > 8)? "W": "B"); }
if (uptr -> capac < kval)
fprintf (st, ", %d%s", uptr -> capac,
((dptr -> dwidth / dptr -> aincr) > 8)? "W": "B");
else fprintf (st, ", %dK%s", uptr -> capac / kval,
((dptr -> dwidth / dptr -> aincr) > 8)? "W": "B"); }
if (uptr -> flags & UNIT_ATT)
fprintf (st, ", attached to %s", uptr -> filename);
fprintf (st, ", attached to %s", uptr -> filename);
else if (uptr -> flags & UNIT_ATTABLE)
fprintf (st, ", not attached");
fprintf (st, ", not attached");
if (dptr -> modifiers != NULL) {
for (mptr = dptr -> modifiers; mptr -> mask != 0; mptr++) {
if ((mptr -> pstring != NULL) &&
((uptr -> flags & mptr -> mask) == mptr -> match))
fprintf (st, ", %s", mptr -> pstring); } }
if ((mptr -> pstring != NULL) &&
((uptr -> flags & mptr -> mask) == mptr -> match)) {
fprintf (st, ", %s", mptr -> pstring);
if ((mptr -> mstring == NULL) && mptr -> valid)
mptr -> valid (uptr, st); } } }
fprintf (st, "\n"); }
return SCPE_OK;
}
t_stat show_version (FILE *st, int flag)
{
int32 vmaj = SIM_MAJOR, vmin = SIM_MINOR, vpat = SIM_PATCH;
fprintf (st, "%s simulator V%d.%d-%d\n", sim_name, vmaj, vmin, vpat);
return SCPE_OK;
}
t_stat show_config (FILE *st, int flag)
{
int32 i;
@ -890,7 +911,7 @@ GET_SWITCHES (cptr, gbuf); /* test for switches */
if (*cptr == 0) return SCPE_ARG;
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
if (*cptr != 0) return SCPE_ARG;
if (strcmp (gbuf, "ALL") == 0) return (detach_all (0));
if (strcmp (gbuf, "ALL") == 0) return (detach_all (0, FALSE));
dptr = find_unit (gbuf, &unitno); /* locate dev+unit# */
if ((dptr == NULL) || (dptr -> units == NULL)) return SCPE_ARG;
uptr = (dptr -> units) + unitno;
@ -903,11 +924,12 @@ return detach_unit (uptr);
Inputs:
start = number of starting device
shutdown = TRUE if simulator shutting down
Outputs:
status = error status
*/
t_stat detach_all (int start)
t_stat detach_all (int32 start, t_bool shutdown)
{
int32 i, j;
t_stat reason;
@ -918,9 +940,10 @@ if ((start < 0) || (start > 1)) return SCPE_ARG;
for (i = start; (dptr = sim_devices[i]) != NULL; i++) {
for (j = 0; j < dptr -> numunits; j++) {
uptr = (dptr -> units) + j;
if (dptr -> detach != NULL) reason = dptr -> detach (uptr);
else reason = detach_unit (uptr);
if (reason != SCPE_OK) return reason; } }
if ((uptr -> flags & UNIT_ATTABLE) || shutdown) {
if (dptr -> detach != NULL) reason = dptr -> detach (uptr);
else reason = detach_unit (uptr);
if (reason != SCPE_OK) return reason; } } }
return SCPE_OK;
}
@ -1201,8 +1224,8 @@ if (flag == RU_BOOT) { /* boot */
(dptr -> boot == NULL)) return SCPE_ARG;
uptr = dptr -> units + unitno;
if (uptr -> flags & UNIT_DIS) return SCPE_ARG; /* disabled? */
if (!(uptr -> flags & UNIT_ATTABLE)) return SCPE_NOATT;
if (!(uptr -> flags & UNIT_ATT)) return SCPE_UNATT;
if ((uptr -> flags & UNIT_ATTABLE) &&
!(uptr -> flags & UNIT_ATT)) return SCPE_UNATT;
if ((r = dptr -> boot (unitno)) != SCPE_OK) return r; }
if (*cptr != 0) return SCPE_ARG;
@ -1227,7 +1250,6 @@ if (ttrunstate () != SCPE_OK) { /* set console */
return SCPE_TTYERR; }
if (step) sim_activate (&step_unit, step); /* set step timer */
sim_is_running = 1; /* flag running */
sim_chkcons (); /* check console buffer */
r = sim_instr();
sim_is_running = 0; /* flag idle */
@ -1400,7 +1422,7 @@ for (gptr = gbuf, reason = SCPE_OK;
continue; }
tptr = get_range (gptr, &low, &high, dptr -> aradix,
(((uptr -> capac == 0) | (flag == EX_E))? 0:
(((uptr -> capac == 0) || (flag == EX_E))? 0:
uptr -> capac - dptr -> aincr), 0);
if (tptr == NULL) return SCPE_ARG;
if (*tptr && (*tptr++ != ',')) return SCPE_ARG;
@ -1517,12 +1539,12 @@ if ((rptr -> depth > 1) && (sz == sizeof (uint8)))
val = *(((uint8 *) rptr -> loc) + idx);
else if ((rptr -> depth > 1) && (sz == sizeof (uint16)))
val = *(((uint16 *) rptr -> loc) + idx);
#if !defined (int64)
#if !defined (t_int64)
else val = *(((uint32 *) rptr -> loc) + idx);
#else
else if (sz <= sizeof (uint32))
val = *(((uint32 *) rptr -> loc) + idx);
else val = *(((uint64 *) rptr -> loc) + idx);
else val = *(((t_uint64 *) rptr -> loc) + idx);
#endif
val = (val >> rptr -> offset) & width_mask[rptr -> width];
return val;
@ -1589,12 +1611,12 @@ if ((rptr -> depth > 1) && (sz == sizeof (uint8)))
PUT_RVAL (uint8, rptr, idx, (uint32) val, (uint32) mask);
else if ((rptr -> depth > 1) && (sz == sizeof (uint16)))
PUT_RVAL (uint16, rptr, idx, (uint32) val, (uint32) mask);
#if !defined (int64)
#if !defined (t_int64)
else PUT_RVAL (uint32, rptr, idx, val, mask);
#else
else if (sz <= sizeof (uint32))
PUT_RVAL (uint32, rptr, idx, (int32) val, (uint32) mask);
else PUT_RVAL (uint64, rptr, idx, val, mask);
else PUT_RVAL (t_uint64, rptr, idx, val, mask);
#endif
return;
}
@ -2182,6 +2204,7 @@ return SCPE_OK;
sim_is_active see if entry is on event queue
sim_atime return absolute time for an entry
sim_gtime return global time
sim_qcount return event queue entry count
Asynchronous events are set up by queueing a unit data structure
to the event queue with a timeout (in simulator units, relative
@ -2335,6 +2358,23 @@ if (sim_clock_queue == NULL) { UPDATE_SIM_TIME (noqueue_time); }
else { UPDATE_SIM_TIME (sim_clock_queue -> time); }
return sim_rtime;
}
/* sim_qcount - return queue entry count
Inputs: none
Outputs:
count = number of entries on the queue
*/
int32 sim_qcount (void)
{
int32 cnt;
UNIT *uptr;
cnt = 0;
for (uptr = sim_clock_queue; uptr != NULL; uptr = uptr -> next) cnt++;
return cnt;
}
/* Endian independent binary I/O package
@ -2456,77 +2496,4 @@ rtc_currdelay = (int32) (((double) rtc_basedelay * (double) rtc_nextintv) /
1000.0); /* next delay */
return rtc_currdelay;
}
/* OS independent multiconsole package
set_console make unit the active console
sim_putcons output character in a multiconsole simulator
sim_chkcons check for buffered output in a multiconsole simulator
*/
t_stat set_console (UNIT *uptr, int32 flag)
{
int32 i;
DEVICE *idptr, *odptr;
UNIT *wuptr, *iuptr = NULL, *ouptr = NULL;
if (sim_consoles == NULL) return SCPE_NOFNC;
for (i = 0; sim_consoles[i] != NULL; i++) {
if (uptr == sim_consoles[i]) {
iuptr = sim_consoles[i & ~1];
ouptr = sim_consoles[i | 1]; } }
if ((iuptr == NULL) || (ouptr == NULL)) return SCPE_ARG;
idptr = find_dev_from_unit (iuptr);
odptr = find_dev_from_unit (ouptr);
if ((idptr == NULL) || (odptr == NULL)) return SCPE_ARG;
for (i = 0; sim_consoles[i] != NULL; i++) {
wuptr = sim_consoles[i];
wuptr -> flags = wuptr -> flags & ~UNIT_CONS;
if (!(i & 1)) sim_cancel (wuptr); }
iuptr -> flags = iuptr -> flags | UNIT_CONS;
ouptr -> flags = ouptr -> flags | UNIT_CONS;
sim_activate (iuptr, iuptr -> wait);
if (idptr == odptr) {
printf ("Active console is %s\n", idptr -> name);
if (sim_log) fprintf (sim_log, "Active console is %s\n", idptr -> name); }
else { printf ("Active console is %s/%s\n", idptr -> name, odptr -> name);
if (sim_log) fprintf (sim_log,
"Active console is %s/%s\n", idptr -> name, odptr -> name); }
return SCPE_OK;
}
t_stat sim_putcons (int32 out, UNIT *uptr)
{
uint8 *consbuf;
if ((uptr -> flags & UNIT_CONS) || (uptr -> filebuf == NULL))
return sim_putchar (out);
if (uptr -> u4 < CONS_SIZE) {
consbuf = (uint8 *) uptr -> filebuf;
consbuf[uptr -> u4] = out; }
uptr -> u4 = uptr -> u4 + 1;
return SCPE_OK;
}
void sim_chkcons (void)
{
int32 i, j, limit;
uint8 *consbuf;
UNIT *uptr;
if (sim_consoles == NULL) return;
for (i = 0; sim_consoles[i] != NULL; i++) {
uptr = sim_consoles[i];
if ((i & 1) && (uptr -> flags & UNIT_CONS) &&
(uptr -> filebuf) && (uptr -> u4)) {
consbuf = (uint8 *) uptr -> filebuf;
limit = (uptr -> u4 < CONS_SIZE)? uptr -> u4: CONS_SIZE;
for (j = 0; j < limit; j++) sim_putchar (consbuf[j]);
if (uptr -> u4 >= CONS_SIZE) {
printf ("\n[Buffered output lost]\n");
if (sim_log) fprintf (sim_log, "\n[Buffered output lost]\n"); }
uptr -> u4 = 0;
return; } }
return;
}

View file

@ -23,6 +23,8 @@
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.
19-Sep-01 RMS More Mac changes
31-Aug-01 RMS Changed int64 to t_int64 for Windoze
20-Jul-01 RMS Added Macintosh support (from Louis Chretien, Peter Schorn,
and Ben Supnik)
15-May-01 RMS Added logging support
@ -50,7 +52,6 @@
The POSIX UNIX version works with LINUX.
*/
#undef USE_INT64 /* hack for Windows */
#include "sim_defs.h"
int32 sim_int_char = 005; /* interrupt character */
extern FILE *sim_log;
@ -190,7 +191,7 @@ return quo;
/* Win32 routines */
#if defined (WIN32)
#if defined (_WIN32)
#define __TTYROUTINES 0
#include <conio.h>
#include <windows.h>
@ -326,6 +327,7 @@ return 0;
#include <sioux.h>
#include <siouxglobals.h>
#include <Traps.h>
#include <LowMem.h>
extern char sim_name[];
extern pSIOUXWin SIOUXTextWindow;
@ -339,7 +341,11 @@ static void updateCursor(void) {
Point localMouse;
GetPort(&savePort);
SetPort(window);
#if !TARGET_API_MAC_CARBON
localMouse = LMGetMouseLocation();
#else
GetGlobalMouse(&localMouse);
#endif
GlobalToLocal(&localMouse);
if (PtInRect(localMouse, &(*SIOUXTextWindow->edit)->viewRect) && iBeamCursorH) {
SetCursor(*iBeamCursorH);

View file

@ -23,6 +23,10 @@
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.
27-Sep-01 RMS Added queue count prototype
17-Sep-01 RMS Removed multiple console support
07-Sep-01 RMS Removed conditional externs on function prototypes
31-Aug-01 RMS Changed int64 to t_int64 for Windoze
17-Jul-01 RMS Added additional function prototypes
27-May-01 RMS Added multiple console support
15-May-01 RMS Increased string buffer size
@ -73,16 +77,18 @@ typedef int t_bool; /* boolean */
typedef unsigned int8 uint8;
typedef unsigned int16 uint16;
typedef unsigned int32 uint32, t_addr; /* address */
#if defined (USE_INT64) && defined (WIN32)
#define int64 __int64 /* for Windows */
#elif defined (USE_INT64) && defined (__digital__) && defined (__unix__)
#define int64 long /* for DUNIX */
#if defined (USE_INT64) && defined (_WIN32)
#define t_int64 __int64 /* for Windows */
#elif defined (USE_INT64) && defined (VMS) && defined (__ALPHA)
#define t_int64 __int64 /* for AVMS */
#elif defined (USE_INT64) && defined (__ALPHA) && defined (__unix__)
#define t_int64 long /* for DUNIX */
#elif defined (USE_INT64)
#define int64 long long /* for GCC */
#define t_int64 long long /* for GCC */
#endif
#if defined (int64)
typedef unsigned int64 uint64, t_value; /* value */
typedef int64 t_svalue; /* signed value */
#if defined (t_int64)
typedef unsigned t_int64 t_uint64, t_value; /* value */
typedef t_int64 t_svalue; /* signed value */
#else
typedef unsigned int32 t_value;
typedef int32 t_svalue;
@ -221,8 +227,6 @@ struct unit {
#define UNIT_BUF 000400 /* buffered */
#define UNIT_DISABLE 001000 /* disable-able */
#define UNIT_DIS 002000 /* disabled */
#define UNIT_CONS 004000 /* active console */
#define UNIT_V_CONS 11
#define UNIT_V_UF 12 /* device specific */
/* Register data structure */
@ -254,8 +258,8 @@ struct ctab {
/* Modifier table */
struct mtab {
int32 mask; /* mask */
int32 match; /* match */
int32 mask; /* mask or radix */
int32 match; /* match or max */
char *pstring; /* print string */
char *mstring; /* match string */
t_stat (*valid)(); /* validation routine */
@ -301,30 +305,24 @@ typedef struct schtab SCHTAB;
/* Function prototypes */
#if defined (SCP) /* defining routine? */
#define EXTERN
#else /* referencing routine */
#define EXTERN extern
#endif
EXTERN t_stat sim_process_event (void);
EXTERN t_stat sim_activate (UNIT *uptr, int32 interval);
EXTERN t_stat sim_cancel (UNIT *uptr);
EXTERN int32 sim_is_active (UNIT *uptr);
EXTERN double sim_gtime (void);
EXTERN uint32 sim_grtime (void);
EXTERN t_stat attach_unit (UNIT *uptr, char *cptr);
EXTERN t_stat detach_unit (UNIT *uptr);
EXTERN t_stat reset_all (int start_device);
EXTERN size_t fxread (void *bptr, size_t size, size_t count, FILE *fptr);
EXTERN size_t fxwrite (void *bptr, size_t size, size_t count, FILE *fptr);
EXTERN t_stat get_yn (char *ques, t_stat deflt);
EXTERN char *get_glyph (char *iptr, char *optr, char mchar);
EXTERN char *get_glyph_nc (char *iptr, char *optr, char mchar);
EXTERN t_value get_uint (char *cptr, int radix, t_value max, t_stat *status);
EXTERN t_value strtotv (char *cptr, char **endptr, int radix);
EXTERN int32 sim_rtc_init (int32 time);
EXTERN int32 sim_rtc_calb (int32 ticksper);
EXTERN t_stat set_console (UNIT *uptr, int32 flag);
EXTERN t_stat sim_putcons (int32 out, UNIT *uptr);
t_stat sim_process_event (void);
t_stat sim_activate (UNIT *uptr, int32 interval);
t_stat sim_cancel (UNIT *uptr);
int32 sim_is_active (UNIT *uptr);
double sim_gtime (void);
uint32 sim_grtime (void);
int32 sim_qcount (void);
t_stat attach_unit (UNIT *uptr, char *cptr);
t_stat detach_unit (UNIT *uptr);
t_stat reset_all (int start_device);
size_t fxread (void *bptr, size_t size, size_t count, FILE *fptr);
size_t fxwrite (void *bptr, size_t size, size_t count, FILE *fptr);
t_stat get_yn (char *ques, t_stat deflt);
char *get_glyph (char *iptr, char *optr, char mchar);
char *get_glyph_nc (char *iptr, char *optr, char mchar);
t_value get_uint (char *cptr, int radix, t_value max, t_stat *status);
t_value strtotv (char *cptr, char **endptr, int radix);
int32 sim_rtc_init (int32 time);
int32 sim_rtc_calb (int32 ticksper);
t_stat sim_poll_kbd (void);
t_stat sim_putchar (int32 out);

123
sim_rev.h Normal file
View file

@ -0,0 +1,123 @@
/* sim_rev.h: simulator revisions and current rev level
Copyright (c) 1993-2001, 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.
*/
#define SIM_MAJOR 2
#define SIM_MINOR 7
#define SIM_PATCH 15
/* SIMH detailed revision list, starting with V2.7
patch date module(s) and fix(es)
15 23-Oct-01 pdp11_rp.c, pdp10_rp.c, pdp10_tu.c: fixed bugs
error interrupt handling
pdp10_defs.h, pdp10_ksio.c, pdp10_fe.c, pdp10_fe.c,
pdp10_rp.c, pdp10_tu.c: reworked I/O page interface
to use symbolic base addresses and lengths
14 20-Oct-01 dec_dz.h, sim_tmxr_h, sim_tmxr.c: fixed bug in Telnet
state handling (found by Thord Nilson), removed
tmxr_getchar, added tmxr_rqln and tmxr_tqln
13 18-Oct-01 pdp11_tm.c: added stub diagnostic register clock
for RSTS/E (found by Thord Nilson)
12 15-Oct-01 pdp11_defs.h, pdp11_cpu.c, pdp11_tc.c, pdp11_ts.c,
pdp11_rp.c: added operations logging
11 8-Oct-01 scp.c: added sim_rev.h include and version print
pdp11_cpu.c: fixed bug in interrupt acknowledge,
multiple outstanding interrupts caused the lowest
rather than the highest to be acknowledged
10 7-Oct-01 pdp11_stddev.c: added monitor bits (CSR<7>) for full
KW11L compatibility, needed for RSTS/E autoconfiguration
9 6-Oct-01 pdp11_rp.c, pdp10_rp.c, pdp10_tu.c: rewrote interrupt
logic from RH11/RH70 schematics, to mimic hardware quirks
dec_dz.c: fixed bug in carrier detect logic, carrier
detect was being cleared on next modem poll
8 4-Oct-01 pdp11_rp.c, pdp10_rp.c, pdp10_tu.c: undid edit of
28-Sep-01; real problem was level-sensitive nature of
CS1_SC, but CS1_SC can only trigger an interrupt if
DONE is set
7 2-Oct-01 pdp11_rp.c, pdp10_rp.c: CS1_SC is evaluated as a level-
sensitive, rather than an edge-sensitive, input to
interrupt request
6 30-Sep-01 pdp11_rp.c, pdp10_rp.c: separated out CS1<5:0> to per-
drive registers
pdp10_tu.c: based on above, cleaned up handling of
non-existent formatters, fixed non-data transfer commands
clearing DONE
5 28-Sep-01 pdp11_rp.c, pdp10_rp.c, pdp10_tu.c: controller should
interrupt if ATA or SC sets when IE is set, was
interrupting only if DON = 1 as well
4 27-Sep-01 pdp11_ts.c:
-- NXM errors should return TC4 or TC5; were returning TC3
-- extended features is part of XS2; was returned in XS3
-- extended characteristics (fifth) word needed for RSTS/E
pdp11_tc.c: stop, stop all do cause an interrupt
dec_dz.h: scanner should find a ready output line, even
if there are no connections; needed for RSTS/E autoconfigure
scp.c:
-- added routine sim_qcount for 1130
-- added "simulator exit" detach routine for 1130
sim_defs.h: added header for sim_qcount
3 20-Sep-01 pdp11_ts.c: boot code binary was incorrect
2 19-Sep-01 pdp18b_cpu.c: EAE should interpret initial count of 00
as 100
scp.c: modified Macintosh support
1 17-Sep-01 pdp8_ttx.c: new module for PDP-8 multi-terminal support
pdp18b_tt1.c: modified to use sim_tmxr library
nova_tt1.c: modified to use sim_tmxr library
dec_dz.h: added autodisconnect support
scp.c: removed old multiconsole support
sim_tmxr.c: modified calling sequence for sim_putchar_ln
sim_sock.c: added Macintosh sockets support
*/

210
sim_sock.c Normal file
View file

@ -0,0 +1,210 @@
/* scp_sock.c: OS-dependent socket routines
Copyright (c) 2001, 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.
16-Sep-01 RMS Added Macintosh support from Peter Schorn
02-Sep-01 RMS Fixed UNIX bugs found by Mirian Lennox and Tom Markson
*/
#include "sim_defs.h"
#include "sim_sock.h"
#include <signal.h>
/* OS dependent routines
sim_master_sock create master socket
sim_accept_conn accept connection
sim_read_sock read from socket
sim_write_sock write from socket
sim_close_sock close socket
sim_setnonblock set socket non-blocking
sim_msg_sock send message to socket
*/
/* First, all the non-implemented versions */
#if defined (VMS) || defined (__OS2__)
SOCKET sim_master_sock (int32 port)
{
return INVALID_SOCKET;
}
SOCKET sim_accept_conn (SOCKET master, UNIT *uptr)
{
return INVALID_SOCKET;
}
int32 sim_read_sock (SOCKET sock, char *buf, int32 nbytes)
{
return -1;
}
int32 sim_write_sock (SOCKET sock, char *msg, int32 nbytes)
{
return 0;
}
void sim_close_sock (SOCKET sock)
{
return;
}
SOCKET sim_setnonblock (SOCKET sock)
{
return SOCKET_ERROR;
}
#else /* endif unimpl */
/* UNIX, Win32, Macintosh (Berkeley socket) routines */
SOCKET sim_master_sock (int32 port)
{
SOCKET newsock;
struct sockaddr_in name;
int32 sta;
#if defined (_WIN32)
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(1, 1);
sta = WSAStartup(wVersionRequested, &wsaData); /* start Winsock */
if (sta != 0) {
printf ("Winsock: startup error %d\n", sta);
return sta; }
#endif /* endif Win32 */
newsock = socket (AF_INET, SOCK_STREAM, 0); /* create socket */
if (newsock == INVALID_SOCKET) { /* socket error? */
perror ("Sockets: socket error");
return INVALID_SOCKET; }
name.sin_family = AF_INET; /* name socket */
name.sin_port = htons ((unsigned short) port); /* insert port */
name.sin_addr.s_addr = htonl (INADDR_ANY);
sta = bind (newsock, (struct sockaddr *) &name, sizeof (name));
if (sta == SOCKET_ERROR) { /* bind error? */
perror ("Sockets: bind error");
sim_close_sock (newsock, 1);
return INVALID_SOCKET; }
sta = sim_setnonblock (newsock); /* set nonblocking */
if (sta == SOCKET_ERROR) { /* fcntl error? */
perror ("Sockets: fcntl error");
sim_close_sock (newsock, 1);
return INVALID_SOCKET; }
sta = listen (newsock, 1); /* listen on socket */
if (sta == SOCKET_ERROR) { /* listen error? */
perror ("Sockets: listen error");
sim_close_sock (newsock, 1);
return INVALID_SOCKET; }
return newsock; /* got it! */
}
SOCKET sim_accept_conn (SOCKET master, UNIT *uptr, uint32 *ipaddr)
{
int32 sta;
#if defined (macintosh)
socklen_t size;
#else
size_t size;
#endif
SOCKET newsock;
struct sockaddr_in clientname;
if ((uptr -> flags & UNIT_ATT) == 0) /* not attached? */
return INVALID_SOCKET;
size = sizeof (clientname);
newsock = accept (master, (struct sockaddr *) &clientname, &size);
if (newsock == INVALID_SOCKET) { /* error? */
if (WSAGetLastError () != WSAEWOULDBLOCK)
perror ("Sockets: accept error");
return INVALID_SOCKET; }
if (ipaddr != NULL) *ipaddr = ntohl (clientname.sin_addr.s_addr);
sta = sim_setnonblock (newsock); /* set nonblocking */
if (sta == SOCKET_ERROR) { /* fcntl error? */
perror ("Sockets: fcntl error");
sim_close_sock (newsock, 0);
return INVALID_SOCKET; }
return newsock;
}
int32 sim_read_sock (SOCKET sock, char *buf, int32 nbytes)
{
int32 rbytes;
rbytes = recv (sock, buf, nbytes, 0);
if (rbytes == 0) return -1; /* disconnect */
if (rbytes == SOCKET_ERROR) {
if (WSAGetLastError () == WSAEWOULDBLOCK) return 0; /* no data */
perror("Sockets: read error");
return -1; }
return rbytes;
}
int32 sim_write_sock (SOCKET sock, char *msg, int32 nbytes)
{
return send (sock, msg, nbytes, 0);
}
void sim_close_sock (SOCKET sock, t_bool master)
{
#if defined (_WIN32)
closesocket (sock);
if (master) WSACleanup ();
#else
close (sock);
#endif
return;
}
#if defined (_WIN32)
SOCKET sim_setnonblock (SOCKET sock)
{
unsigned long non_block = 1;
return ioctlsocket (sock, FIONBIO, &non_block); /* set nonblocking */
}
#else
int32 sim_setnonblock (SOCKET sock)
{
int32 fl, sta;
fl = fcntl (sock, F_GETFL,0); /* get flags */
if (fl == -1) return SOCKET_ERROR;
sta = fcntl (sock, F_SETFL, fl | O_NONBLOCK); /* set nonblock */
if (sta == -1) return SOCKET_ERROR;
#if !defined (macintosh)
sta = fcntl (sock, F_SETOWN, getpid()); /* set ownership */
if (sta == -1) return SOCKET_ERROR;
#endif
return 0;
}
#endif /* endif Win32 */
#endif /* endif Win32/UNIX/Mac */

64
sim_sock.h Normal file
View file

@ -0,0 +1,64 @@
/* scp_sock.h: OS-dependent socket routines header file
Copyright (c) 2001, 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.
16-Sep-01 RMS Added Macintosh support from Peter Schorn
*/
#if defined (WIN32)
#undef INT_PTR /* hack, hack */
#include <winsock.h>
#else
#define WSAGetLastError() errno
#if !defined (VMS) && !defined (__OS2__)
#include <sys/types.h> /* for fcntl, getpid */
#include <sys/socket.h> /* for sockets */
#include <fcntl.h>
#include <unistd.h>
#include <netinet/in.h> /* for sockaddr_in */
#include <netdb.h>
#endif
#endif
/* Code uses Windows-specific defs that are undefined for most systems */
#if !defined (SOCKET)
#define SOCKET int32
#endif
#if !defined (WSAEWOULDBLOCK)
#define WSAEWOULDBLOCK EWOULDBLOCK
#endif
#if !defined (INVALID_SOCKET)
#define INVALID_SOCKET -1
#endif
#if !defined (SOCKET_ERROR)
#define SOCKET_ERROR -1
#endif
SOCKET sim_master_sock (int32 port);
SOCKET sim_accept_conn (SOCKET master, UNIT *uptr, uint32 *ipaddr);
int32 sim_read_sock (SOCKET sock, char *buf, int32 nbytes);
int32 sim_write_sock (SOCKET sock, char *msg, int32 nbytes);
void sim_close_sock (SOCKET sock, t_bool master);
SOCKET sim_setnonblock (SOCKET sock);

403
sim_tmxr.c Normal file
View file

@ -0,0 +1,403 @@
/* sim_tmxr.c: Telnet terminal multiplexor library
Copyright (c) 2001, 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.
Based on the original DZ11 simulator by Thord Nilson, as updated by
Arthur Krewat.
20-Oct-01 RMS Fixed bugs in read logic (found by Thord Nilson).
added tmxr_rqln, tmxr_tqln
*/
#include "sim_defs.h"
#include "sim_sock.h"
#include "sim_tmxr.h"
/* Telnet protocol constants - negatives are for init'ing signed char data */
#define TN_IAC -1 /* protocol delim */
#define TN_DONT -2 /* dont */
#define TN_DO -3 /* do */
#define TN_WONT -4 /* wont */
#define TN_WILL -5 /* will */
#define TN_BIN 0 /* bin */
#define TN_ECHO 1 /* echo */
#define TN_SGA 3 /* sga */
#define TN_LINE 34 /* line mode */
#define TN_CR 015 /* carriage return */
/* Telnet line states */
#define TNS_NORM 000 /* normal */
#define TNS_IAC 001 /* IAC seen */
#define TNS_WILL 002 /* WILL seen */
#define TNS_WONT 003 /* WONT seen */
#define TNS_SKIP 004 /* skip next */
void tmxr_rmvrc (TMLN *lp, int32 p);
extern int32 sim_switches;
extern char sim_name[];
extern FILE *sim_log;
extern uint32 sim_os_msec (void);
/* Poll for new connection
Called from unit service routine to test for new connection
Inputs:
*mp = pointer to terminal multiplexor descriptor
Outputs:
line number activated, -1 if none
*/
int32 tmxr_poll_conn (TMXR *mp, UNIT *uptr)
{
SOCKET newsock;
TMLN *lp;
int32 i;
uint32 ipaddr;
static char mantra[] = {
TN_IAC, TN_WILL, TN_LINE,
TN_IAC, TN_WILL, TN_SGA,
TN_IAC, TN_WILL, TN_ECHO,
TN_IAC, TN_WILL, TN_BIN,
TN_IAC, TN_DO, TN_BIN };
newsock = sim_accept_conn (mp -> master, uptr, &ipaddr);/* poll connect */
if (newsock != INVALID_SOCKET) { /* got a live one? */
for (i = 0; i < mp -> lines; i++) { /* find avail line */
lp = mp -> ldsc[i]; /* ptr to ln desc */
if (lp -> conn == 0) break; } /* available? */
if (i >= mp -> lines) { /* all busy? */
tmxr_msg (newsock, "All connections busy... please try later\r\n");
sim_close_sock (newsock, 0); }
else { lp = mp -> ldsc[i]; /* get line desc */
lp -> conn = newsock; /* record connection */
lp -> ipad = ipaddr; /* ip address */
lp -> cnms = sim_os_msec (); /* time of conn */
lp -> rxbpr = lp -> rxbpi = 0; /* init buf pointers */
lp -> txbpr = lp -> txbpi = 0;
lp -> rxcnt = lp -> txcnt = 0; /* init counters */
lp -> tsta = 0; /* init telnet state */
lp -> xmte = 1; /* enable transmit */
lp -> dstb = 0; /* default bin mode */
sim_write_sock (newsock, mantra, 15);
tmxr_msg (newsock, "\n\r\nWelcome to the ");
tmxr_msg (newsock, sim_name);
tmxr_msg (newsock, " simulator\r\n\n");
return i; }
} /* end if newsock */
return -1;
}
/* Reset line */
void tmxr_reset_ln (TMLN *lp)
{
sim_close_sock (lp -> conn, 0); /* reset conn */
lp -> conn = lp -> tsta = 0; /* reset state */
lp -> rxbpr = lp -> rxbpi = 0;
lp -> txbpr = lp -> txbpi = 0;
lp -> xmte = 1;
lp -> dstb = 0;
return;
}
/* Get character from specific line
Inputs:
*lp = pointer to terminal line descriptor
Output:
valid + char, 0 if line
*/
int32 tmxr_getc_ln (TMLN *lp)
{
int32 j, val = 0;
uint32 tmp;
if (lp -> conn && lp -> rcve) { /* conn & enb? */
j = lp -> rxbpi - lp -> rxbpr; /* # input chrs */
if (j) { /* any? */
tmp = lp -> rxb[lp -> rxbpr]; /* get char */
lp -> rxbpr = lp -> rxbpr + 1; /* adv pointer */
val = TMXR_VALID | (tmp & 0377); } /* valid + chr */
} /* end if conn */
if (lp -> rxbpi == lp -> rxbpr) /* empty? zero ptrs */
lp -> rxbpi = lp -> rxbpr = 0;
return val;
}
/* Poll for input
Inputs:
*mp = pointer to terminal multiplexor descriptor
Outputs: none
*/
void tmxr_poll_rx (TMXR *mp)
{
int32 i, nbytes, j;
TMLN *lp;
for (i = 0; i < mp -> lines; i++) { /* loop thru lines */
lp = mp -> ldsc[i]; /* get line desc */
if (!lp -> conn || !lp -> rcve) continue; /* skip if !conn */
nbytes = 0;
if (lp -> rxbpi == 0) /* need input? */
nbytes = sim_read_sock (lp -> conn, /* yes, read */
&(lp -> rxb[lp -> rxbpi]), /* leave spc for */
TMXR_MAXBUF - TMXR_GUARD); /* Telnet cruft */
else if (lp -> tsta) /* in Telnet seq? */
nbytes = sim_read_sock (lp -> conn, /* yes, read to end */
&(lp -> rxb[lp -> rxbpi]),
TMXR_MAXBUF - lp -> rxbpi);
if (nbytes < 0) tmxr_reset_ln (lp); /* closed? reset ln */
else if (nbytes > 0) { /* if data rcvd */
j = lp -> rxbpi; /* start of data */
lp -> rxbpi = lp -> rxbpi + nbytes; /* adv pointers */
lp -> rxcnt = lp -> rxcnt + nbytes;
/* Examine new data, remove TELNET cruft before making input available */
for (; j < lp -> rxbpi; ) { /* loop thru char */
char tmp = lp -> rxb[j]; /* get char */
switch (lp -> tsta) { /* case tlnt state */
case TNS_NORM: /* normal */
if (tmp == TN_IAC) { /* IAC? */
lp -> tsta = TNS_IAC; /* change state */
tmxr_rmvrc (lp, j); /* remove char */
break; }
if ((tmp == TN_CR) && lp -> dstb) /* CR, no bin */
lp -> tsta = TNS_SKIP; /* skip next */
j = j + 1; /* advance j */
break;
case TNS_IAC: /* IAC prev */
if (tmp == TN_WILL) /* IAC + WILL? */
lp -> tsta = TNS_WILL;
else if (tmp == TN_WONT) /* IAC + WONT? */
lp -> tsta = TNS_WONT;
else lp -> tsta = TNS_SKIP; /* IAC + other */
tmxr_rmvrc (lp, j); /* remove char */
break;
case TNS_WILL: case TNS_WONT: /* IAC+WILL/WONT prev */
if (tmp == TN_BIN) { /* BIN? */
if (lp -> tsta == TNS_WILL) lp -> dstb = 0;
else lp -> dstb = 1; }
case TNS_SKIP: default: /* skip char */
lp -> tsta = TNS_NORM; /* next normal */
tmxr_rmvrc (lp, j); /* remove char */
break; } /* end case state */
} /* end for char */
} /* end else nbytes */
} /* end for lines */
for (i = 0; i < mp -> lines; i++) { /* loop thru lines */
lp = mp -> ldsc[i]; /* get line desc */
if (lp -> rxbpi == lp -> rxbpr) /* if buf empty, */
lp -> rxbpi = lp -> rxbpr = 0; /* reset pointers */
} /* end for */
return;
}
/* Return count of available characters for line */
int32 tmxr_rqln (TMLN *lp)
{
return (lp -> rxbpi - lp -> rxbpr);
}
/* Remove character p from line l input buffer */
void tmxr_rmvrc (TMLN *lp, int32 p)
{
for ( ; p < lp -> rxbpi; p++) lp -> rxb[p] = lp -> rxb[p + 1];
lp -> rxbpi = lp -> rxbpi - 1;
return;
}
/* Store character in line buffer
Inputs:
*lp = pointer to line descriptor
chr = characters
Outputs:
none
*/
void tmxr_putc_ln (TMLN *lp, int32 chr)
{
if (lp -> conn == 0) return; /* no conn? done */
if (lp -> txbpi < TMXR_MAXBUF) { /* room for char? */
lp -> txb[lp -> txbpi] = (char) chr; /* buffer char */
lp -> txbpi = lp -> txbpi + 1; /* adv pointer */
if (lp -> txbpi > (TMXR_MAXBUF - TMXR_GUARD)) /* near full? */
lp -> xmte = 0; } /* disable line */
else lp -> xmte = 0; /* disable line */
return;
}
/* Poll for output
Inputs:
*mp = pointer to terminal multiplexor descriptor
Outputs:
none
*/
void tmxr_poll_tx (TMXR *mp)
{
int32 i, nbytes, sbytes;
TMLN *lp;
for (i = 0; i < mp -> lines; i++) { /* loop thru lines */
lp = mp -> ldsc[i]; /* get line desc */
if (lp -> conn == 0) continue; /* skip if !conn */
nbytes = lp -> txbpi - lp -> txbpr; /* avail bytes */
if (nbytes) { /* >0? write */
sbytes = sim_write_sock (lp -> conn,
&(lp -> txb[lp -> txbpr]), nbytes);
if (sbytes != SOCKET_ERROR) { /* update ptrs */
lp -> txbpr = lp -> txbpr + sbytes;
lp -> txcnt = lp -> txcnt + sbytes;
nbytes = nbytes - sbytes; }
}
if (nbytes == 0) { /* buf empty? */
lp -> xmte = 1; /* enable this line */
lp -> txbpr = lp -> txbpi = 0; }
} /* end for */
return;
}
/* Return count of buffered characters for line */
int32 tmxr_tqln (TMLN *lp)
{
return (lp -> txbpi - lp -> txbpr);
}
/* Attach */
t_stat tmxr_attach (TMXR *mp, UNIT *uptr, char *cptr)
{
char* tptr;
int32 i, port;
SOCKET sock;
TMLN *lp;
t_stat r;
extern int32 sim_switches;
port = (int32) get_uint (cptr, 10, 65535, &r); /* get port */
if ((r != SCPE_OK) || (port == 0)) return SCPE_ARG;
tptr = malloc (strlen (cptr) + 1); /* get string buf */
if (tptr == NULL) return SCPE_MEM; /* no more mem? */
sock = sim_master_sock (port); /* make master socket */
if (sock == INVALID_SOCKET) { /* open error */
free (tptr); /* release buf */
return SCPE_OPENERR; }
printf ("Listening on socket %d\n", sock);
if (sim_log) fprintf (sim_log, "Listening on socket %d\n", sock);
mp -> master = sock; /* save master socket */
strcpy (tptr, cptr); /* copy port */
uptr -> filename = tptr; /* save */
uptr -> flags = uptr -> flags | UNIT_ATT; /* no more errors */
for (i = 0; i < mp -> lines; i++) { /* initialize lines */
lp = mp -> ldsc[i];
lp -> conn = lp -> tsta = 0;
lp -> rxbpi = lp -> rxbpr = 0;
lp -> txbpi = lp -> txbpr = 0;
lp -> rxcnt = lp -> txcnt = 0;
lp -> xmte = 1;
lp -> dstb = 0; }
return SCPE_OK;
}
/* Detach */
t_stat tmxr_detach (TMXR *mp, UNIT *uptr)
{
int32 i;
TMLN *lp;
if ((uptr -> flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */
for (i = 0; i < mp -> lines; i++) { /* loop thru conn */
lp = mp -> ldsc[i];
if (lp -> conn) {
tmxr_msg (lp -> conn, "\r\n");
tmxr_msg (lp -> conn, sim_name);
tmxr_msg (lp -> conn, " simulator shutting down... please come back later\r\n\n");
tmxr_reset_ln (lp); } /* end if conn */
} /* end for */
sim_close_sock (mp -> master, 1); /* close master socket */
mp -> master = 0;
free (uptr -> filename); /* free port string */
uptr -> filename = NULL;
uptr -> flags = uptr -> flags & ~UNIT_ATT; /* not attached */
return SCPE_OK;
}
/* Stub examine and deposit */
t_stat tmxr_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)
{
return SCPE_NOFNC;
}
t_stat tmxr_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw)
{
return SCPE_NOFNC;
}
/* Output message */
void tmxr_msg (SOCKET sock, char *msg)
{
if (sock) sim_write_sock (sock, msg, strlen (msg));
return;
}
/* Print line status */
void tmxr_fstatus (FILE *st, TMLN *lp, int32 ln)
{
if (ln >= 0) fprintf (st, "\n line %d", ln);
if (lp -> conn) {
int32 o1, o2, o3, o4, hr, mn, sc;
uint32 ctime;
o1 = (lp -> ipad >> 24) & 0xFF;
o2 = (lp -> ipad >> 16) & 0xFF;
o3 = (lp -> ipad >> 8) & 0xFF;
o4 = (lp -> ipad) & 0xFF;
ctime = (sim_os_msec () - lp -> cnms) / 1000;
hr = ctime / 3600;
mn = (ctime / 60) % 60;
sc = ctime % 3600;
fprintf (st, ": IP address %d.%d.%d.%d", o1, o2, o3, o4);
if (ctime) fprintf (st, ", connected %02d:%02d:%02d", hr, mn, sc); }
else fprintf (st, ": disconnected");
return;
}

81
sim_tmxr.h Normal file
View file

@ -0,0 +1,81 @@
/* sim_tmxr.h: terminal multiplexor definitions
Copyright (c) 2001, 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.
Based on the original DZ11 simulator by Thord Nilson, as updated by
Arthur Krewat.
20-Oct-01 RMS Removed tmxr_getchar, formalized buffer guard,
added tmxr_rqln, tmxr_tqln
*/
#define TMXR_V_VALID 15
#define TMXR_VALID (1 << TMXR_V_VALID)
#define TMXR_MAXBUF 128 /* buffer size */
#define TMXR_GUARD 8 /* buffer guard */
#define TMXR_MAXLIN 64 /* max lines */
struct tmln {
SOCKET conn; /* line conn */
uint32 ipad; /* IP address */
uint32 cnms; /* conn time */
int32 tsta; /* Telnet state */
int32 rcve; /* rcv enable */
int32 xmte; /* xmt enable */
int32 dstb; /* disable Tlnt bin */
int32 rxbpr; /* rcv buf remove */
int32 rxbpi; /* rcv buf insert */
int32 rxcnt; /* rcv count */
int32 txbpr; /* xmt buf remove */
int32 txbpi; /* xmt buf insert */
int32 txcnt; /* xmt count */
char rxb[TMXR_MAXBUF]; /* rcv buffer */
char txb[TMXR_MAXBUF]; /* xmt buffer */
};
typedef struct tmln TMLN;
struct tmxr {
int32 lines; /* # lines */
SOCKET master; /* master socket */
TMLN *ldsc[TMXR_MAXLIN]; /* line descriptors */
};
typedef struct tmxr TMXR;
int32 tmxr_poll_conn (TMXR *mp, UNIT *uptr);
void tmxr_reset_ln (TMLN *lp);
int32 tmxr_getc_ln (TMLN *lp);
void tmxr_poll_rx (TMXR *mp);
void tmxr_putc_ln (TMLN *lp, int32 chr);
void tmxr_poll_tx (TMXR *mp);
t_stat tmxr_attach (TMXR *mp, UNIT *uptr, char *cptr);
t_stat tmxr_detach (TMXR *mp, UNIT *uptr);
t_stat tmxr_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
t_stat tmxr_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
void tmxr_msg (SOCKET sock, char *msg);
void tmxr_fstatus (FILE *st, TMLN *lp, int32 ln);
int32 tmxr_rqln (TMLN *lp);
int32 tmxr_tqln (TMLN *lp);

1097
simh.doc

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
To: Users
From: Bob Supnik
Subj: Simulator Usage, V2.6b
Date: 15-Sep-01
Subj: Simulator Usage, V2.7
Date: 30-Sep-01
COPYRIGHT NOTICE
@ -54,30 +54,33 @@ in scp_tty.c and scp_sock.c.
To compile the simulators on VMS, use these commands (note that separate
compilations are required for each of the 18b PDP's):
$ cc pdp8_*.c,scp.c,scp_tty.c ! PDP-8
$ link/exec=pdp8 pdp8_*.obj,scp.obj,scp_tty.obj
$ cc pdp8_*.c,scp.c,scp_tty.c,sim_*.c ! PDP-8
$ link/exec=pdp8 pdp8_*.obj,scp.obj,scp_tty.obj,sim_*.obj
$ cc pdp11_*.c,scp.c,scp_tty.c ! PDP-11
$ link/exec=pdp11 pdp11_*.obj,scp.obj,scp_tty.obj
$ cc pdp11_*.c,scp.c,scp_tty.c,sim_*.c ! PDP-11
$ link/exec=pdp11 pdp11_*.obj,scp.obj,scp_tty.obj,sim_*.obj
$ cc nova_*.c,scp.c,scp_tty.c ! Nova
$ link/exec=nova nova_*.obj,scp.obj,scp_tty.obj
$ cc nova_*.c,scp.c,scp_tty.c,sim_*.c ! Nova
$ link/exec=nova nova_*.obj,scp.obj,scp_tty.obj,sim_*.obj
$ cc pdp1_*.c,scp.c,scp_tty.c ! PDP-1
$ cc pdp1_*.c,scp.c,scp_tty.c ! PDP-1
$ link/exec=pdp1 pdp1_*.obj,scp.obj,scp_tty.obj
$ cc/define=PDP{4,7,9,15} pdp18b_*.c,scp.c,scp_tty.c
$ link/exec=pdp{4,7,9,15} pdp18b_*.obj,scp.obj,scp_tty.obj
$ cc/define=PDP{4,7,9,15} pdp18b_*.c,scp.c,scp_tty.c,sim_*.c
$ link/exec=pdp{4,7,9,15} pdp18b_*.obj,scp.obj,scp_tty.obj,sim_*.obj
$ cc i1401_*.c,scp.c,scp_tty.c ! IBM 1401
$ cc i1401_*.c,scp.c,scp_tty.c ! IBM 1401
$ link/exec=i1401 i1401_*.obj,scp.obj,scp_tty.obj
$ cc hp2100_*.c,scp.c,scp_tty.c ! HP 2100
$ cc hp2100_*.c,scp.c,scp_tty.c ! HP 2100
$ link/exec=hp2100 hp2100_*.obj,scp.obj,scp_tty.obj
$ cc id4_*.c,scp.c,scp_tty.c ! Interdata 4
$ cc id4_*.c,scp.c,scp_tty.c ! Interdata 4
$ link/exec=id4 id4_*.obj,scp.obj,scp_tty.obj
$ cc h316_*.c,scp.c,scp_tty.c ! Honeywell 316
$ link/exec=h316 h316_*.obj,scp.obj,scp_tty.obj
On version of VMS prior to 6.2, the simulators must then be defined as
foreign commands so that they can be started by name.
@ -86,14 +89,15 @@ the POSIX compliant TERMIOS interface (including Linux and Mac OS X), use
the following commands (note that separate compilations are required for
each of the 18b PDP's):
% cc pdp8_*.c scp*.c -lm -o pdp8
% cc pdp11_*.c scp*.c -lm -o pdp11
% cc nova_*.c scp*.c -lm -o nova
% cc pdp8_*.c scp*.c sim_*.c -lm -o pdp8
% cc pdp11_*.c scp*.c sim_*.c -lm -o pdp11
% cc nova_*.c scp*.c sim_*.c -lm -o nova
% cc pdp1_*.c scp*.c -o pdp1
% cc -DPDP{4,7,9,15} pdp18b_*.c scp*.c -lm -o pdp{4,7,9,15}
% cc -DPDP{4,7,9,15} pdp18b_*.c scp*.c sim_*.c -lm -o pdp{4,7,9,15}
% cc i1401_*.c scp*.c -o i1401
% cc hp2100_*.c scp*.c -o hp2100
% cc id4_*.c scp*.c -o id4
% cc h316_*.c scp*.c -o h316
These commands should work with most UNIX variants. If your UNIX only
supports the old BSD terminal interface, add -DBSDTTY to each command.
@ -104,7 +108,7 @@ The PDP-10 simulator requires 64b support in the simulator and in the
simulator control package (SCP). To turn on 64b support, add the symbol
USE_INT64 to the command line:
% cc -DUSE_INT64 pdp10_*.c,scp*.c -lm -o pdp10
% cc -DUSE_INT64 pdp10_*.c scp*.c sim_*.c -lm -o pdp10
Since 64b integer declarations vary, sim_defs.h has conditional
declarations for Windows (_int64) and Digital UNIX (long). The default
@ -115,12 +119,20 @@ To compile the simulators on Windows 9x/ME/NT/2000 and Visual C++,
each simulator must be set up as a separate project. Under the VC++
file menu, select New, select Project Workspace, select Console
Application, and type in the name of the simulator. In the project
files view, select Add Files To Project and add in all the files for
that simulator (e.g., all files beginning nova_ for the Nova), plus
sim_defs.h, scp.c, and scp_tty.c. If the project requires the DZ11,
also add in scp_sock.h and scp_sock.c. If the project requires a
command line switch, add the switches to the C/C++ tab of the
Configuration dialog. The simulator should then build properly.
files view, select Add Files To Project and add in the required files:
- all simulators: sim_defs.h, sim_rev.h, scp.c, scp_tty
- all simulators: simulator specific files (e.g., all
files beginning with nova_* for the Nova)
- PDP-10, PDP-11: dec_dz.h
- PDP-8, PDP-10, PDP-11, PDP-18b, Nova: sim_sock.h,
sim_sock.c, sim_txmr.h, sim_txmr.c
If the project requires 64b support, add the switch -DUSE_INT64 to
the C/C++ tab of the Configuration dialog. If the project includes
Telnet-based terminals, add the appropriate Winsock library to the
library search list (Wsock32.dll for VC++ V4.) The simulator should
then build properly.
To start the simulator, simply type its name. The simulator takes
one optional argument, a startup command file. If specified, this
@ -136,6 +148,7 @@ for example, disk sizes.
% i1401 <startup file>(cr) or
% hp2100 <startup file>(cr) or
% id4 <startup file>(cr) or
% h316 <startup file>(cr) or
% pdp10 <startup file>(cr)
The simulator types out its name and version, executes the commands
@ -234,8 +247,16 @@ unit. The ATTACH (abbreviation AT) command associates a unit and a file:
If the file does not exist, it is created, and an appropriate message
is printed.
For Telnet-based terminal emulators, the ATTACH command associates the
master unit with a TCP/IP port:
sim> ATTACH <device><unit number> <port>(cr)
The port is a decimal number between 1 and 65535 and should not used
by standard TCP/IP protocols.
The DETACH (abbreviation DET) command breaks the association between a
unit and a file and closes the file:
unit and a file, or between a unit and a port:
sim> DETACH ALL(cr) -- detach all units
sim> DETACH <device><unit number>(cr) -- detach specified unit
@ -463,6 +484,7 @@ CPU PDP-8/E CPU with 32KW of memory
- KM8E memory management and timeshare control
PTR,PTP PC8E paper tape reader/punch
TTI,TTO KL8E console terminal
TTI1-4,TTO1-4 KL8JA additional terminals
LPT LE8E line printer
CLK DK8E line frequency clock (also PDP-8/A compatible)
RK RK8E/RK05 cartridge disk controller with four drives
@ -605,7 +627,7 @@ Error handling is as follows:
4.2.3 KL8E Terminal Input (TTI)
The terminal input (TTI) reads from the controling console port. The
The terminal input (TTI) polls the console keyboard for input. The
input side has one option, UC; when set, it automatically converts lower
case input to upper case. This is required by OS/8 and is on by default.
@ -622,7 +644,7 @@ The terminal input implements these registers:
4.2.4 KL8E Terminal Output (TTO)
The terminal output (TTO) writes to the controling console port. It
The terminal output (TTO) writes to the simulator console window. It
implements these registers:
name size comments
@ -676,6 +698,52 @@ The real-time clock (CLK) implements these registers:
The real-time clock autocalibrates; the clock interval is adjusted up or
down so that the clock tracks actual elapsed time.
4.2.7 KL8JA Additional Terminals (TTI1-4, TTO1-4)
Each additional terminal consists of two independent devices, TTIn and
TTOn. The entire set is modelled as a terminal multiplexor, with TTI1
as the master unit. The additional terminals perform input and output
through Telnet sessions connected to a user-specified port. The ATTACH
command specifies the port to be used:
ATTACH TTI1 <port>(cr) -- set up listening port
where port is a decimal number between 1 and 65535 that is not being used
for other TCP/IP activities.
Once TTI1 is attached and the simulator is running, the terminals listen
for connections on the specified port. They assume that the incoming
connections are Telnet connections. The connections remain open until
disconnected either by the Telnet client, or by a DETACH TTI1 command.
The SHOW TTI1 command displays the current connections to the additional
terminals.
The input devices (TTI1-4) implement these registers:
name size comments
BUF 8 last data item processed
DONE 1 device done flag
ENABLE 1 interrupt enable flag
INT 1 interrupt pending flag
POS 31 number of characters input
TIME 24 keyboard polling interval
The output devices (TTO1-4) implement these registers:
name size comments
BUF 8 last data item processed
DONE 1 device done flag
ENABLE 1 interrupt enable flag
INT 1 interrupt pending flag
POS 31 number of characters output
TIME 24 time from I/O initiation to interrupt
The additional terminals do not support save and restore. All open
connections are lost when the simulator shuts down or TTI1 is detached.
4.3 RK8E Cartridge Disk (RK)
RK8E options include the ability to make units write enabled or write locked:
@ -923,6 +991,7 @@ controlled by command line switches:
-a display as ASCII character
-c display as (sixbit) character string
-t display as (TSS/8 sixbit) character string
-m display instruction mnemonics
Input parsing is controlled by the first character typed in or by command
@ -930,6 +999,7 @@ line switches:
' or -a ASCII character
" or -c two character sixbit string
# or -t two character TSS/8 sixbit string
alphabetic instruction mnemonic
numeric octal number
@ -985,6 +1055,7 @@ PTR,PTP PC11 paper tape reader/punch
TTI,TTO DL11 console terminal
LPT LP11 line printer
CLK line frequency clock
DZ DZ11 8-line terminal multiplexor
RK RK11/RK05 cartridge disk controller with eight drives
RL RLV12/RL01(2) cartridge disk controller with four drives
RP RM02/03/05/80, RP04/05/06/07 Massbus style controller
@ -994,9 +1065,9 @@ TC TC11/TU56 DECtape controller with eight drives
TM TM11/TU10 magnetic tape controller with eight drives
TS TS11/TSV05 magnetic tape controller with one drive
The RK, RL, RP, RX, TC, TM, and TS devices can be DISABLEd. The PDP-11 can
support either a TM11 or a TS11, but not both, since they use the same I/O
addresses. The simulator defaults to the TM11. To change the magtape,
The DZ, RK, RL, RP, RX, TC, TM, and TS devices can be DISABLEd. The PDP-11
can support either a TM11 or a TS11, but not both, since they use the same
I/O addresses. The simulator defaults to the TM11. To change the magtape,
ENABLE TM11 enable TM11 and disable TS11
ENABLE TS11 enable TS11 and disable TM11
@ -1164,7 +1235,7 @@ Error handling is as follows:
5.2.3 KL11 Terminal Input (TTI)
The terminal input (TTI) reads from the controling console port. It
The terminal input (TTI) polls the console keyboard for input. It
implements these registers:
name size comments
@ -1180,7 +1251,7 @@ implements these registers:
5.2.4 KL11 Terminal Output (TTO)
The terminal output (TTO) writes to the controling console port. It
The terminal output (TTO) writes to the simulator console window. It
implements these registers:
name size comments
@ -1239,6 +1310,45 @@ The clock (CLK) implements these registers:
The real-time clock autocalibrates; the clock interval is adjusted up or
down so that the clock tracks actual elapsed time.
5.2.7 DZ11 Terminal Multiplexor (DZ)
The DZ11 is an 8-line terminal multiplexor. The terminal lines perform
input and output through Telnet sessions connected to a user-specified
port. The ATTACH command specifies the port to be used:
ATTACH {-am} DZ <port>(cr) -- set up listening port
where port is a decimal number between 1 and 65535 that is not being used
for other TCP/IP activities. The optional switch -m turns on the DZ11's
modem controls; the optional switch -a turns on active disconnects
(disconnect session if computer clears Data Terminal Ready).
Once the DZ is attached and the simulator is running, the DZ will listen
for connections on the specified port. It assumes that the incoming
connections are Telnet connections. The connection remains open until
disconnected either by the simulated program or by the Telnet client.
The SHOW DZ command displays the current connections to the DZ.
The DZ11 implements these registers:
name size comments
CSR 16 control/status register
RBUF 16 receive buffer
LPR 16 line parameter register
TCR 16 transmission control register
MSR 16 modem status register
TDR 16 transmit data register
SAENB 1 silo alarm enabled
MDMTCL 1 modem control enabled
AUTODS 1 autodisconnect enabled
RPOS0..7 32 count of characters received
TPOS0..7 32 count of characters transmitted
The DZ11 does not support save and restore. All open connections are
lost when the simulator shuts down or the DZ is detached.
5.3 RK11/RK05 Cartridge Disk (RK)
RK11 options include the ability to make units write enabled or write locked:
@ -1390,7 +1500,7 @@ a DEC standard 044 compliant bad block table on the last track:
SET RPn RP06 set size to RP06
SET RPn RP07 set size to RP07
SET RPn AUTOSIZE set size based on file size at attach
SET RLn BADBLOCK write bad block table on last track
SET RPn BADBLOCK write bad block table on last track
The size options can be used only when a unit is not attached to a file. The
bad block option can be used only when a unit is attached to a file. Units
@ -1402,26 +1512,29 @@ The RP controller implements these registers:
name size comments
RPCS1 16 control/status 1
RPCS2 16 control/status 2
RPCS3 16 control/status 3
RPWC 16 word count
RPBA 16 bus address
RPBAE 6 bus address extension
RPDA 16 desired surface, sector
RPDC 8 desired cylinder
RPCS2 16 control/status 2
RPOF 16 offset
RPDS0..7 16 drive status, drives 0-7
RPDE0..7 16 drive error, drives 0-7
RPDC 8 desired cylinder
RPER2 16 error status 2
RPER3 16 error status 3
RPDB 16 data buffer
RPEC1 16 ECC syndrome 1
RPEC2 16 ECC syndrome 2
RPMR 16 maintenance register
RPDB 16 data buffer
RPBAE 6 bus address extension
RPCS3 16 control/status 3
RPIFF 1 transfer complete interrupt request flop
INT 1 interrupt pending flag
SC 1 special condition (CSR1<15>)
DONE 1 device done flag (CSR1<7>)
IE 1 interrupt enable flag (CSR1<6>)
STIME 24 seek time, per cylinder
RTIME 24 rotational delay
RPDS0..7 16 drive status, drives 0-7
RPDE0..7 16 drive error, drives 0-7
STOP_IOE 1 stop on I/O error
Error handling is as follows:
@ -1568,6 +1681,7 @@ The magnetic tape controller implements these registers:
WADH 16 write char packet high address
WLNT 16 write char packet length
WOPT 16 write char packet options
WXOPT 16 write char packet extended options
ATTN 1 attention message pending
BOOT 1 boot request pending
OWNC 1 if set, tape owns command buffer
@ -1732,22 +1846,6 @@ control registers for the interrupt system.
6.2 Programmed I/O Devices
The Nova can have two terminals (TTI/TTO, TTI1/TTO1). At any moment
only one terminal is active. It can receive input from the keyboard;
it can output to the simulator window. The inactive console cannot
receive input from the keyboard and outputs to an internal buffer
(maximum 4K characters).
Control is switched among terminals with a SET TTI{n} CONSOLE or SET
TTO{n} CONSOLE command:
At startup, active console is TTI/TTO
SET TTI1 CONSOLE Active console is now TTI1/TTO1
SET TTO CONSOLE Active console is now TTI/TTO
When control is switched to an inactive terminal, any buffered output
is printed when simulation resumes.
6.2.1 Paper Tape Reader (PTR)
The paper tape reader (PTR) reads data from a disk file. The POS
@ -1807,23 +1905,19 @@ Error handling is as follows:
OS I/O error x report error and stop
6.2.3 Terminal Input (TTI, TTI1)
6.2.3 Terminal Input (TTI)
The active terminal input polls the console keyboard for input. The
inactive terminal input cannot receive characters. Terminal input
options include the ability to set limited Dasher compatibility mode
or ANSI standard mode:
The terminal input polls the console keyboard for input. Terminal
input options include the ability to set ANSI mode or limited Dasher
compatibility mode:
SET TTI ANSI normal mode
SET TTI DASHER Dasher mode
SET TTO ANSI normal mode
SET TTO DASHER Dasher mode
Setting either TTI (TTI1) or TTO (TTO1) changes both devices. In Dasher
mode, carriage return is changed to newline on input, and ^X is changed
to backspace.
Setting either TTI or TTO changes both devices. In Dasher mode, carriage
return is changed to newline on input, and ^X is changed to backspace.
The terminal inputs implement these registers:
The terminal input implements these registers:
name size comments
@ -1835,22 +1929,19 @@ The terminal inputs implement these registers:
POS 31 number of characters input
TIME 24 keyboard polling interval
6.2.4 Terminal Output (TTO, TTO1)
6.2.4 Terminal Output (TTO)
The active terminal output writes to the simulator window. The inactive
terminal output buffers characters. Terminal output options include the
the ability to set limited Dasher compatibility mode or ANSI mode:
The terminal output writes to the simulator console window. Terminal
output options include the the ability to set ANSI mode or limited
Dasher compatibility mode:
SET TTI ANSI normal mode
SET TTI DASHER Dasher mode
SET TTO ANSI normal mode
SET TTO DASHER Dasher mode
Setting either TTI (TTI1) or TTO (TTO1) changes both devices. In Dasher
mode, carriage return is changed to newline on input, and ^X is changed
to backspace.
Setting either TTI or TTO changes both devices. In Dasher mode, carriage
return is changed to newline on input, and ^X is changed to backspace.
The terminal outputs implement these registers:
The terminal output implements these registers:
name size comments
@ -1937,6 +2028,61 @@ Error handling is as follows:
OS I/O error x report error and stop
6.2.8 Second Terminal (TTI1, TTO1)
The second terminal consists of two independent devices, TTI1 and TTO1.
The additional terminal performs input and output through a Telnet session
connecting into a user-specified port. The ATTACH command specifies the
port to be used:
ATTACH TTI1 <port>(cr) -- set up listening port
where port is a decimal number between 1 and 65535 that is not being used
for other TCP/IP activities.
Once TTI1 is attached and the simulator is running, the terminal listens
for a connection on the specified port. It assumes that the incoming
connection is a Telnet connection. The connection remain opens until
disconnected by the Telnet client, or by a DETACH TTI1 command.
The second terminal has two options, recognized on both devices, for
setting limited Dasher-compatibility mode or ANSI mode:
SET TTI1 ANSI normal mode
SET TTI1 DASHER Dasher mode
SET TTO1 ANSI normal mode
SET TTO1 DASHER Dasher mode
Setting either TTI1 or TTO1 changes both devices. In Dasher mode, carriage
return is changed to newline on input, and ^X is changed to backspace.
The SHOW TTI1 command displays the current connection to the second
terminal.
The second terminal input implements these registers:
name size comments
BUF 8 last data item processed
BUSY 1 device busy flag
DONE 1 device done flag
DISABLE 1 interrupt disable flag
INT 1 interrupt pending flag
POS 31 number of characters input
TIME 24 keyboard polling interval
The second terminal output implements these registers:
name size comments
BUF 8 last data item processed
BUSY 1 device busy flag
DONE 1 device done flag
DISABLE 1 interrupt disable flag
INT 1 interrupt pending flag
POS 31 number of characters output
TIME 24 time from I/O initiation to interrupt
6.3 Fixed Head Disk (DK)
The fixed head disk controller implements these registers:
@ -2261,8 +2407,8 @@ Error handling is as follows:
7.2.3 Terminal Input (TTI)
The terminal input (TTO) reads from the controling console port.
It implements these registers:
The terminal input (TTI) polls the console keyboard for input. It
implements these registers:
name size comments
@ -2273,7 +2419,7 @@ It implements these registers:
7.2.4 Terminal Output (TTO)
The terminal output (TTO) writes to the controling console port.
The terminal output (TTO) writes to the simulator console window.
It implements these registers:
name size comments
@ -2629,22 +2775,6 @@ the PDP-7 and PDP-9, 17b for the PDP-15).
8.2 Programmed I/O Devices
The PDP-9 and PDP-15 have two terminals (TTI/TTO, TTI1/TTO1). At any
moment, only one terminal is active. It can receive input from the
keyboard; it can output to the simulator window. The inactive console
cannot receive input from the keyboard and outputs to an internal buffer
(maximum 4K characters).
Control is switched among terminals with a SET TTI{n} CONSOLE or SET
TTO{n} CONSOLE command:
At startup, active console is TTI/TTO
SET TTI1 CONSOLE Active console is now TTI1/TTO1
SET TTO CONSOLE Active console is now TTI/TTO
When control is switched to an inactive terminal, any buffered output
is printed when simulation resumes.
8.2.1 Paper Tape Reader (PTR)
The paper tape reader (PTR) reads data from a disk file. The POS
@ -2707,20 +2837,19 @@ Error handling is as follows:
OS I/O error x report error and stop
8.2.3 Terminal Input (TTI, TTI1)
8.2.3 Terminal Input (TTI)
The active terminal input polls the console keyboard for input. The
inactive terminal input cannot receive characters. The terminal inputs
have one option, UC; when set, it automatically converts lower case input
to upper case.
The terminal input (TTI) polls the console keyboard for input. The
input side has one option, UC; when set, it automatically converts lower
case input to upper case.
The PDP-9 and PDP-15 operated the primary terminal (TTI/TTO), by default,
as half-duplex. For backward compatibility, on the PDP-9 and PDP-15
The PDP-9 and PDP-15 operate the console terminal (TTI/TTO), by default,
as half duplex. For backward compatibility, on the PDP-9 and PDP-15
the first terminal input has a second option, FDX; when set, it operates
the terminal input in full-duplex mode. The second terminal is always
full duplex.
The terminal inputs implement these registers:
The terminal input implements these registers:
name size comments
@ -2730,14 +2859,13 @@ The terminal inputs implement these registers:
POS 31 number of characters input
TIME 24 keyboard polling interval
8.2.4 Terminal Output (TTO, TTO1)
8.2.4 Terminal Output (TTO)
The active terminal output writes to the simulator window. The inactive
terminal output buffers characters. The terminal outputs have one option,
UC; when set, it suppresses lower case output (so that ALTMODE is not
echoed as }).
The terminal output (TTO) writes to the simulator console window. The
terminal output has one option, UC; when set, it suppresses lower case
output (so that ALTMODE is not echoed as }).
The terminal outputs implement these registers:
The terminal output implements these registers:
name size comments
@ -2822,6 +2950,51 @@ The real-time clock (CLK) implements these registers:
The real-time clock autocalibrates; the clock interval is adjusted up or
down so that the clock tracks actual elapsed time.
8.2.7 Second Terminal (TTI1, TTO1)
The second terminal consists of two independent devices, TTI1 and TTO1.
The second terminal performs input and output through a Telnet session
connected to a user-specified port. The ATTACH command specifies the
port to be used:
ATTACH TTI1 <port>(cr) -- set up listening port
where port is a decimal number between 1 and 65535 that is not being used
for other TCP/IP activities.
Once TTI1 is attached and the simulator is running, the terminal listens
for a connection on the specified port. It assumes that the incoming
connection is a Telnet connection. The connection remain opens until
disconnected by the Telnet client, or by a DETACH TTI1 command.
The second terminal input has one option, UC; when set, it automatically
converts lower case input to upper case. The second terminal output also
has one option, UC; when set, it suppresses lower case output (so that
ALTMODE is not echoed as }).
The SHOW TTI1 command displays the current connection to the second
terminal.
The second terminal input implements these registers:
name size comments
BUF 8 last data item processed
INT 1 interrupt pending flag
DONE 1 device done flag
POS 31 number of characters input
TIME 24 keyboard polling interval
The second terminal output implements these registers:
name size comments
BUF 8 last data item processed
INT 1 interrupt pending flag
DONE 1 device done flag
POS 31 number of chararacters output
TIME 24 time from I/O initiation to interrupt
8.3 RP15/RP02 Disk Pack (RP)
RP15 options include the ability to make units write enabled or write locked:
@ -3384,8 +3557,8 @@ Error handling is as follows:
9.4 1407 Inquiry Terminal (INQ)
The IBM 1407 inquiry terminal (INQ) is a half-duplex console. It polls
the controling keyboard of the simulator periodically for inquiry requests.
The inquiry terminal registers are:
the console keyboard periodically for inquiry requests. The inquiry
terminal registers are:
name size comments
@ -3725,11 +3898,11 @@ Error handling is as follows:
10.4.3 12631C Buffered Teleprinter (TTY)
The console teleprinter has three units: keyboard (unit 0), printer
(unit 1), and punch (unit 2). The keyboard reads from, and the
printer writes to, the controlling console port. The punch writes
to a disk file. The keyboard has one option, UC; when set, it
automatically converts lower case input to upper case. This is on
by default.
(unit 1), and punch (unit 2). The keyboard reads from the console
keyboard; the printer writes to the simulator console window. The
punch writes to a disk file. The keyboard has one option, UC; when
set, it automatically converts lower case input to upper case. This
is on by default.
The terminal implements these registers:
@ -4076,9 +4249,10 @@ Error handling is as follows:
11.3 Teletype (TT)
The teletype reads and writes to the controlling console port. The
keyboard has one option, UC; when set, it automatically converts lower
case input to upper case. This is on by default.
The teletype keyboard reads from the console keyboard; the teletype
printer writes to the simulator console window. The keyboard has
one option, UC; when set, it automatically converts lower case
input to upper case. This is on by default.
name size comments
@ -4158,12 +4332,13 @@ UBA Unibus adapters (translation maps)
FE console
TIM timer
PTR,PTP PC11 paper tape reader/punch
DZ DZ11 8-line terminal multiplexor
LP20 LP20 line printer
RP RH11/RP04/RP05/RP06/RP07/RM03/RM05/RM80 controller with
eight drives
TU RH11/TM02/TU45 controller with eight drives
The PTR/PTP are initially DISABLEd. No other device can be DISABLEd.
The PTR/PTP are initially DISABLEd. The DZ11 can also be DISABLEd.
The PDP-10 simulator implements several unique stop condition:
@ -4371,7 +4546,54 @@ Error handling is as follows:
OS I/O error x report error and stop
12.8 RH11 Adapter, RM02/03/05/80, RP04/05/06/07 drives (RP)
12.8 DZ11 Terminal Multiplexor (DZ)
The DZ11 is an 8-line terminal multiplexor. The terminal lines perform
input and output through Telnet sessions connected to a user-specified
port. The ATTACH command specifies the port to be used:
ATTACH {-am} DZ <port>(cr) -- set up listening port
where port is a decimal number between 1 and 65535 that is not being used
for other TCP/IP activities. The optional switch -m turns on the DZ11's
modem controls; the optional switch -a turns on active disconnects
(disconnect session if computer clears Data Terminal Ready).
ATTACH {-m} DZ <port>(cr) -- set up listening port
where port is a decimal number between 1 and 65535 that is not being used
for other TCP/IP activities. The optional switch -m turns on the DZ11's
modem controls; the optional switch -a turns on active disconnects
(disconnect session if computer clears Data Terminal Ready).
Once the DZ is attached and the simulator is running, the DZ will listen
for connections on the specified port. It assumes that the incoming
connections are Telnet connections. The connection remains open until
disconnected either by the simulated program or by the Telnet client.
The SHOW DZ command displays the current connections to the DZ.
The DZ11 implements these registers:
name size comments
CSR 16 control/status register
RBUF 16 receive buffer
LPR 16 line parameter register
TCR 16 transmission control register
MSR 16 modem status register
TDR 16 transmit data register
SAENB 1 silo alarm enabled
MDMTCL 1 modem control enabled
AUTODS 1 autodisconnect enabled
RPOS0..7 32 count of characters received
TPOS0..7 32 count of characters transmitted
The DZ11 does not support save and restore. All open connections are
lost when the simulator shuts down or the DZ is detached.
12.9 RH11 Adapter, RM02/03/05/80, RP04/05/06/07 drives (RP)
The RP controller implements the Massbus 18b (RH11) direct interface for
large disk drives. It is more abstract than other device simulators, with
@ -4401,26 +4623,27 @@ The RP controller implements these registers:
name size comments
RPCS1 16 control/status 1
RPCS2 16 control/status 2
RPCS3 16 control/status 3
RPWC 16 word count
RPBA 16 bus address
RPBAE 6 bus address extension
RPDA 16 desired surface, sector
RPDC 8 desired cylinder
RPCS2 16 control/status 2
RPOF 16 offset
RPDS0..7 16 drive status, drives 0-7
RPDE0..7 16 drive error, drives 0-7
RPDC 8 desired cylinder
RPER2 16 error status 2
RPER3 16 error status 3
RPDB 16 data buffer
RPEC1 16 ECC syndrome 1
RPEC2 16 ECC syndrome 2
RPMR 16 maintenance register
RPDB 16 data buffer
RPIFF 1 transfer complete interrupt request flop
INT 1 interrupt pending flag
SC 1 special condition (CSR1<15>)
DONE 1 device done flag (CSR1<7>)
IE 1 interrupt enable flag (CSR1<6>)
STIME 24 seek time, per cylinder
RTIME 24 rotational delay
RPDS0..7 16 drive status, drives 0-7
RPDE0..7 16 drive error, drives 0-7
STOP_IOE 1 stop on I/O error
Error handling is as follows:
@ -4434,11 +4657,11 @@ Error handling is as follows:
OS I/O error x report error and stop
12.9 RH11/TM02/TU45 Magnetic Tape (TU)
12.10 RH11 Adapter, TM02 Formatter, TU45 Magnetic Tape (TU)
The magnetic tape simulator simulates an RH11 Massbus adapter with one
TM02 formatter and up to eight TU45. Magnetic tape options include the
ability to make units write enabled or locked.
TM02 formatter and up to eight TU45 drives. Magnetic tape options include
the ability to make units write enabled or locked.
SET TUn LOCKED set unit n write locked
SET TUn ENABLED set unit n write enabled
@ -4479,7 +4702,7 @@ Error handling is as follows:
OS I/O error report error and stop
12.10 LP20 DMA Line Printer (LP20)
12.11 LP20 DMA Line Printer (LP20)
The LP20 is a DMA-based line printer controller. There is one
line printer option to clear the vertical forms unit (VFU).
@ -4521,7 +4744,7 @@ Error handling is as follows:
OS I/O error x report error and stop
12.11 Symbolic Display and Input
12.12 Symbolic Display and Input
The PDP-10 simulator implements symbolic display and input. Display is
controlled by command line switches:
@ -4701,9 +4924,10 @@ Error handling is as follows:
13.2.3 316/516-33 Console Teletype (TTY)
The terminal reads and writes to the controlling console port. It has
one option, UC; when set, it automatically converts lower case input
to upper case. This is on by default.
The terminal reads from the console keyboard and writes to the
simulator console window. The terminal has one option, UC; when
set, the terminal automatically converts lower case input to upper
case. This is on by default.
The terminal these registers:
@ -4865,7 +5089,7 @@ use 578 blocks of 256 32b words. Each 32b word contains 18b (6 lines)
of data. PDP-8 DECtapes use 1474 blocks of 129 16b words. Each 16b
word contains 12b (4 lines) of data. Note that PDP-8 OS/8 does not use
the 129th word of each block, and OS/8 DECtape dumps contain only 128
words per block. A utility, DSOS8CVT.C, is provided to convert OS/8
words per block. A utility, DTOS8CVT.C, is provided to convert OS/8
DECtape dumps to simulator format.
A known problem in DECtape format is that when a block is recorded in
@ -4932,28 +5156,47 @@ legend: y = runs operating system or sample program
Revision History (since Rev 1.1)
Rev 2.6b, Jul, 01
Rev 2.7, Sep, 01
Added DZ11 (from Thord Nilson and Art Krewat)
to PDP-11, PDP-10
Added additional terminals to PDP-8
Added TSS/8 packed character format to PDP-8
Added sim_sock and sim_tmxr libraries
Added sim_qcount and simulator exit detach all facilities
Added Macintosh sim_sock support (from Peter Schorn)
Added simulator revision level, SHOW version
Changed int64/uint64 to t_int64/t_uint64 for Windoze
Fixed bug in PDP-11 interrupt acknowledge
Fixed bugs in PDP-11 TS NXM check, boot code, error status;
added extended characteristics and status
Fixed bug in PDP-11 TC stop, stop all functions
Fixed receive interrupt while disconnected bug in DZ11
Fixed multi-unit operation bugs, interrupt bugs in
PDP-11 RP, PDP-10 RP, PDP-10 TU
Fixed carrier detect bug in PDP-11, PDP-10 DZ
Fixed bug in PDP-8 reset routine
Fixed conditional in PDP-18b CPU
Fixed SC = 0 bug in PDP-18b EAE
Fixed bug in PDP-7 LPT
Upgraded Nova second terminal to use sim_tmxr
Upgraded PDP-18b second terminal to use sim_tmxr
Upgraded PDP-11 LTC to full KW11-L
Removed hack multiple console support
Rev 2.6b, Aug, 01
Added H316/516 simulator
Added Macintosh support from Louis Chrétien, Peter Schorn,
and Ben Supnik
Added bad block table option to PDP-11 RL, RP
Removed register in declarations
Fixed bugs found by Peter Schorn
Endian error in PDP-10, PDP-11 RP
Space reverse error in PDP-11 TS
Symbolic input in 1401
-- endian error in PDP-10, PDP-11 RP
-- space reverse error in PDP-11 TS
-- symbolic input in 1401
Fixed bug in PDP-1 RIM loader found by Derek Peschel
Fixed bug in Nova fixed head disk
Removed register in declarations
Rev 2.6a, Jun, 01
Fixed bug (found by Dave Conroy) in big-endian I/O
Fixed DECtape reset in PDP-8, PDP-11, PDP-9/15
Fixed RIM loader PC handling in PDP-9/15
Fixed indirect pointers in PDP-10 paging
Fixed SSC handling in PDP-10 TM02/TU45
Fixed JMS to non-existent memory in PDP-8
Fixed error handling on command file
Increased size of string buffers for long path names
Added PDP-9, PDP-15 API option
Added PDP-9, PDP-15 second terminal
Added PDP-10 option for TOPS-20 V4.1 bug fix
@ -4961,6 +5204,14 @@ Rev 2.6a, Jun, 01
Added console logging
Added multiple console support
Added comment recognition
Increased size of string buffers for long path names
Fixed bug in big-endian I/O found by Dave Conroy
Fixed DECtape reset in PDP-8, PDP-11, PDP-9/15
Fixed RIM loader PC handling in PDP-9/15
Fixed indirect pointers in PDP-10 paging
Fixed SSC handling in PDP-10 TM02/TU45
Fixed JMS to non-existent memory in PDP-8
Fixed error handling on command file
Rev 2.6, May, 01
Added ENABLE/DISABLE devices
@ -4989,31 +5240,31 @@ Rev 2.6, May, 01
Updated copyright notices, fixed comments
Rev 2.5a, Dec, 00
Fixed SCP handling of devices without units
Fixed FLG, FBF initialization in many HP peripherals
Added CMD flop to HP paper tape and line printer
Added status input for HP paper tape punch and TTY
Added Dutch Owens' 1401 mag tape boot routine
Added Bruce Ray's Nova plotter and second terminal modules
Added Charles Owen's Eclipse CPU support
Added PDP-9/PDP-15 RIM/BIN loader support
Added PDP-9/PDP-15 extend/bank initial state registers
Added PDP-9/PDP-15 half/full duplex support
Moved software documentation to a separate file
Fixed SCP handling of devices without units
Fixed FLG, FBF initialization in many HP peripherals
Fixed 1401 bugs found by Dutch Owens
-- 4, 7 char NOPs are legal
-- 1 char B is chained BCE
-- MCE moves whole character, not digit, after first
Added Dutch Owens' 1401 mag tape boot routine
Fixed Nova bugs found by Bruce Ray
-- traps implemented on Nova 3 as well as Nova 4
-- DIV and DIVS 0/0 set carry
-- RETN sets SP from FP at outset
-- IORST does not clear carry
-- Nova 4 implements two undocumented instructions
Added Bruce Ray's Nova plotter and second terminal modules
Added Charles Owen's Eclipse CPU support
Fixed bugs in 18b PDP's
-- XCT indirect address calculation
-- missing index instructions in PDP-15
-- bank mode handling in PDP-15
Added PDP-9/PDP-15 RIM/BIN loader support
Added PDP-9/PDP-15 extend/bank initial state registers
Added PDP-9/PDP-15 half/full duplex support
Moved software documentation to a separate file
Rev 2.5, Nov, 00
Removed Digital and Compaq from copyrights, as
@ -5072,6 +5323,8 @@ Rev 2.3a, Nov, 97
Fixed endian dependence in 18b PDP RIM loader
Rev 2.3, Mar, 97
Added PDP-11 RP
Added PDP-1
Changed UNIX terminal I/O to TERMIOS
Changed magtape format to double ended
Changed PDP-8 current page mnemonic from T to C
@ -5085,8 +5338,6 @@ Rev 2.3, Mar, 97
Fixed bug in 18b PDP paper tape reader
Fixed bug in PDP-4 console
Fixed bug in PDP-4,7 line printer
Added PDP-11 RP
Added PDP-1
Rev 2.2d, Dec, 96
Added ADD/REMOVE commands
@ -5171,9 +5422,11 @@ Jay Jaeger IBM 1401 information
Doug Jones PDP-8 information, simulator, and software
Al Kossow HP 21xx, Varian 620, TI 990, DEC documentation and software
Arthur Krewat DZ11 update for the PDP-10
Mirian Crzig Lennox ITS and DZ11 debugging
Don Lewine Nova documentation and legal permissions
Tim Litt PDP-10 hardware documentation and schematics,
tape images, and software sources
Tim Markson DZ11 debugging
Scott McGregor PDP-11 UNIX legal permissions
Jeff Moffatt HP 2100 information, documentation, and software
Alec Muffett Solaris port testing
@ -5209,6 +5462,7 @@ David Waks PDP-8 ESI-X and PDP-7 SIM8 software
Tom West Nova documentation
Adrian Wise H316 simulator, documentation, and software
John Wilson PDP-11 simulator and software
Joe Young RP debugging on Ultrix-11 and BSD
In addition, the following companies have graciously licensed their
software at no cost for hobbyist use:

View file

@ -1,7 +1,7 @@
To: Users
From: Bob Supnik
Subj: Sample Software Packages
Date: 31-May-01
Date: 30-Sep-01
This memorandum documents the sample software packages available to run
with the SIMH simulators. Many of these packages are available under
@ -88,6 +88,75 @@ Note that OS/8 only recognizes upper case characters. The first disk
(drive 0) is the system disk; it also includes BASIC. The second disk
(drive 1) includes FORTRAN.
1.4 PDP-8 TSS/8
TSS/8 is the PDP-8's timesharing system. It provides a program development
and execution environment for assembler, BASIC, and FORTRAN programs. TSS/8
is provided as is, without fee, by Digital Equipment Corporation, for non-
commercial use only. My thanks to John Wilson of Dbit Inc, who provided
the disk image and the initialization tape source.
Loading TSS/8
-------------
Note: your environment must have a functioning second Teletype; that is, you cannot
at present run Foreground/Background if your host system is VMS or OS/2.
- Load the paper-tape bootstrap:
sim> load tss8_init.bin
- Mount the TSS/8 disk image of the RF08:
sim> attach rf tss8_rf.dsk
- Assign a TCP/IP port to the Telnet listener for the extra terminals:
sim> attach tti1 <port #> -- 4000 typically works
- Run the bootstrap:
sim> run 24200
- TSS/8 will boot and go through its startup dialog
LOAD, DUMP, START, ETC? START
MONTH-DAY-YEAR: mm:dd:yy -- numeric, yy in range [74:85]
HR:MIN - hh:mm -- numeric, 24 hour format
(type cr to get attention)
.
and is now ready for login. The list of accounts and passwords:
PPN Password
[0,1] VH3M
[0,2] LXHE
[0,3] SHUG
[77,77]
[1,10] WBCN
[20,1] DT
[20,2] PT
[20,3] TSS8
[20,4] EDIT
[20,5] 4TH
[1,50] JERK
- Login using one of the existing accounts. The login command won't echo:
.LOGIN 2 LXHE -- privileged library account
TSS/8.24 JOB 01 [00,02] K00 23:23:06
SYSTEM IS DOWN, INC.
- The system is now ready for commands. To get a directory listing:
.R CAT
- Other users can log in by connecting, from a Telnet client, to localhost
on the port specified in the attach tti1 command.
2. PDP-11
2.1 UNIX V5, V6, V7
@ -301,6 +370,69 @@ execution capabilities. To load and run ADSS/KM-15:
4.0000
*
6.3 Advanced Software System/Foreground Background
Foreground/Background System
----------------------------
Note: your environment must have a functioning second Teletype; that is, you cannot
at present run Foreground/Background if your host system is VMS or OS/2.
- Load the paper-tape bootstrap into upper memory:
sim> load dec-15u.rim 77637
You <must> specify the load address.
- Verify that the bootstrap loaded correctly:
sim> ex pc
PC: 077646
- Mount the Advanced Software System DECtape image on DECtape unit 0:
sim> attach dt fb15_32k.dtp
- Turn on the API option:
sim> set cpu api
- Assign a TCP/IP port to the Telnet listener for the second terminal:
sim> assign tti1 <port #> -- 4000 typically works
- Start a Telnet client to act as the second terminal and connect to
localhost on the specified port.
- Run the bootstrap:
sim> run
- The DECtape will boot and print out
F9/15 V4A
$
and is now ready for commands. Recognized commands include:
D 0 list system device directory
R list device assignments
- To activate the background, load IDLE into the foreground:
$A DTA0 -4
$GLOAD
FGLOAD V2A
>_IDLE<altmode = control-[>
Background terminal responds with
B9/15 V4A
$
and is now ready for commands.
7. IBM 1401
7.1 Single Card "Koans"