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_PC pointer to saved PC register descriptor
sim_emax number of words needed for examine sim_emax number of words needed for examine
sim_devices array of pointers to simulated devices 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_stop_messages array of pointers to stop messages
sim_load binary loader sim_load binary loader
*/ */
@ -44,8 +43,6 @@ int32 sim_emax = 4;
DEVICE *sim_devices[] = { &cpu_dev, &sio_dev, &ptr_dev, DEVICE *sim_devices[] = { &cpu_dev, &sio_dev, &ptr_dev,
&ptp_dev, &dsk_dev, NULL }; &ptp_dev, &dsk_dev, NULL };
UNIT *sim_consoles = NULL;
const char *sim_stop_messages[] = { const char *sim_stop_messages[] = {
"Unknown error", "Unknown error",
"Unknown I/O Instruction", "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 ptp 316/516-52 paper tape punch
tty 316/516-33 teleprinter tty 316/516-33 teleprinter
clk/options 316/516-12 real time clocks/internal options clk/options 316/516-12 real time clocks/internal options
07-Sep-01 RMS Moved function prototypes
*/ */
#include "h316_defs.h" #include "h316_defs.h"
@ -54,9 +56,6 @@ t_stat tto_svc (UNIT *uptr);
t_stat tty_reset (DEVICE *dptr); t_stat tty_reset (DEVICE *dptr);
t_stat clk_svc (UNIT *uptr); t_stat clk_svc (UNIT *uptr);
t_stat clk_reset (DEVICE *dptr); 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 /* PTR data structures

View file

@ -22,6 +22,8 @@
Except as contained in this notice, the name of Robert M Supnik shall not 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 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. in this Software without prior written authorization from Robert M Supnik.
17-Sep-01 RMS Removed multiconsole support
*/ */
#include "h316_defs.h" #include "h316_defs.h"
@ -42,7 +44,6 @@ extern int32 sim_switches;
sim_PC pointer to saved PC register descriptor sim_PC pointer to saved PC register descriptor
sim_emax maximum number of words for examine/deposit sim_emax maximum number of words for examine/deposit
sim_devices array of pointers to simulated devices 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_stop_messages array of pointers to stop messages
sim_load binary loader sim_load binary loader
*/ */
@ -59,8 +60,6 @@ DEVICE *sim_devices[] = { &cpu_dev,
&clk_dev, &clk_dev,
NULL }; NULL };
UNIT *sim_consoles = NULL;
const char *sim_stop_messages[] = { const char *sim_stop_messages[] = {
"Unknown error", "Unknown error",
"Unimplemented instruction", "Unimplemented instruction",

View file

@ -175,3 +175,8 @@ struct hpdev {
#define IOT_V_REASON 16 #define IOT_V_REASON 16
#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */ #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 dp 12557A cartridge disk system
07-Sep-01 RMS Moved function prototypes
29-Nov-00 RMS Made variable names unique 29-Nov-00 RMS Made variable names unique
21-Nov-00 RMS Fixed flag, buffer power up state 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_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); 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); void dp_go (int32 fnc, int32 drv, int32 time, int32 attdev);
extern t_bool hp_setdev2 (UNIT *uptr, int32 val);
/* DPD data structures /* DPD data structures

View file

@ -25,6 +25,7 @@
lpt 12653A line printer lpt 12653A line printer
07-Sep-01 RMS Moved function prototypes
21-Nov-00 RMS Fixed flag, fbf power up state 21-Nov-00 RMS Fixed flag, fbf power up state
Added command flop Added command flop
15-Oct-00 RMS Added variable device number support 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_svc (UNIT *uptr);
t_stat lpt_reset (DEVICE *dptr); t_stat lpt_reset (DEVICE *dptr);
extern struct hpdev infotab[]; extern struct hpdev infotab[];
extern t_bool hp_setdev (UNIT *uptr, int32 val);
/* LPT data structures /* LPT data structures

View file

@ -25,6 +25,7 @@
mt 12559A nine track magnetic tape mt 12559A nine track magnetic tape
07-Sep-01 RMS Moved function prototypes
30-Nov-00 RMS Made variable names unique 30-Nov-00 RMS Made variable names unique
04-Oct-98 RMS V2.4 magtape format 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 mtc_detach (UNIT *uptr);
t_stat mtd_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw); 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); 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 /* MTD data structures

View file

@ -28,6 +28,7 @@
tty 12531C buffered teleprinter interface tty 12531C buffered teleprinter interface
clk 12539A/B/C time base generator clk 12539A/B/C time base generator
07-Sep-01 RMS Moved function prototypes
21-Nov-00 RMS Fixed flag, buffer power up state 21-Nov-00 RMS Fixed flag, buffer power up state
Added status input for ptp, tty Added status input for ptp, tty
15-Oct-00 RMS Added dynamic device number support 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 tty_reset (DEVICE *dptr);
t_stat clk_svc (UNIT *uptr); t_stat clk_svc (UNIT *uptr);
t_stat clk_reset (DEVICE *dptr); 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 /* PTR data structures

View file

@ -23,6 +23,7 @@
be used in advertising or otherwise to promote the sale, use or other dealings 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. 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 27-May-01 RMS Added multiconsole support
14-Mar-01 RMS Revised load/dump interface (again) 14-Mar-01 RMS Revised load/dump interface (again)
30-Oct-00 RMS Added examine to file support 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_PC pointer to saved PC register descriptor
sim_emax maximum number of words for examine/deposit sim_emax maximum number of words for examine/deposit
sim_devices array of pointers to simulated devices 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_stop_messages array of pointers to stop messages
sim_load binary loader sim_load binary loader
*/ */
@ -69,8 +69,6 @@ DEVICE *sim_devices[] = { &cpu_dev,
&dpd_dev, &dpc_dev, &dpd_dev, &dpc_dev,
NULL }; NULL };
UNIT *sim_consoles = NULL;
const char *sim_stop_messages[] = { const char *sim_stop_messages[] = {
"Unknown error", "Unknown error",
"Unimplemented instruction", "Unimplemented instruction",

View file

@ -23,6 +23,7 @@
be used in advertising or otherwise to promote the sale, use or other dealings 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. 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 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_svc (UNIT *uptr);
t_stat inq_reset (DEVICE *dptr); t_stat inq_reset (DEVICE *dptr);
void puts_tty (char *cptr); void puts_tty (char *cptr);
extern t_stat sim_poll_kbd (void);
extern t_stat sim_putchar (int32 out);
/* INQ data structures /* INQ data structures

View file

@ -23,6 +23,7 @@
be used in advertising or otherwise to promote the sale, use or other dealings 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. 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) 13-Jul-01 RMS Fixed bug in symbolic output (found by Peter Schorn)
27-May-01 RMS Added multiconsole support 27-May-01 RMS Added multiconsole support
14-Mar-01 RMS Revised load/dump interface (again) 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_PC pointer to saved PC register descriptor
sim_emax maximum number of words for examine/deposit sim_emax maximum number of words for examine/deposit
sim_devices array of pointers to simulated devices 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_stop_messages array of pointers to stop messages
sim_load binary loader sim_load binary loader
*/ */
@ -67,8 +67,6 @@ DEVICE *sim_devices[] = { &cpu_dev, &inq_dev,
&cdr_dev, &cdp_dev, &stack_dev, &lpt_dev, &cdr_dev, &cdp_dev, &stack_dev, &lpt_dev,
&mt_dev, NULL }; &mt_dev, NULL };
UNIT *sim_consoles = NULL;
const char *sim_stop_messages[] = { const char *sim_stop_messages[] = {
"Unknown error", "Unknown error",
"Unimplemented instruction", "Unimplemented instruction",

View file

@ -23,6 +23,7 @@
be used in advertising or otherwise to promote the sale, use or other dealings 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. 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 17-Jul-01 RMS Fixed warning from VC++ 6.0
27-May-01 RMS Added multiconsole support 27-May-01 RMS Added multiconsole support
14-Mar-01 RMS Revised load/dump interface (again) 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_PC pointer to saved PC register descriptor
sim_emax number of words for examine sim_emax number of words for examine
sim_devices array of pointers to simulated devices 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_stop_messages array of pointers to stop messages
sim_load binary loader sim_load binary loader
*/ */
@ -61,8 +61,6 @@ DEVICE *sim_devices[] = { &cpu_dev,
&pt_dev, &tt_dev, &pt_dev, &tt_dev,
NULL }; NULL };
UNIT *sim_consoles = NULL;
const char *sim_stop_messages[] = { const char *sim_stop_messages[] = {
"Unknown error", "Unknown error",
"Reserved instruction", "Reserved instruction",

View file

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

View file

@ -23,6 +23,7 @@
be used in advertising or otherwise to promote the sale, use or other dealings 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. 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 31-May-01 RMS Added multiconsole support
14-Mar-01 RMS Revised load/dump interface (again) 14-Mar-01 RMS Revised load/dump interface (again)
22-Dec-00 RMS Added second terminal support 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_PC pointer to saved PC register descriptor
sim_emax number of words needed for examine sim_emax number of words needed for examine
sim_devices array of pointers to simulated devices 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_stop_messages array of pointers to stop messages
sim_load binary loader sim_load binary loader
*/ */
@ -90,11 +90,6 @@ DEVICE *sim_devices[] = {
&dkp_dev, &mta_dev, &dkp_dev, &mta_dev,
NULL }; NULL };
UNIT *sim_consoles[] = {
&tti_unit, &tto_unit,
&tti1_unit, &tto1_unit,
NULL };
const char *sim_stop_messages[] = { const char *sim_stop_messages[] = {
"Unknown error", "Unknown error",
"Unknown I/O instruction", "Unknown I/O instruction",

View file

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

View file

@ -27,23 +27,32 @@
tti1 second terminal input tti1 second terminal input
tto1 second terminal output 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 31-May-01 RMS Added multiconsole support
26-Apr-01 RMS Added device enable/disable support 26-Apr-01 RMS Added device enable/disable support
*/ */
#include "nova_defs.h" #include "nova_defs.h"
#include "sim_sock.h"
#include "sim_tmxr.h"
#define UNIT_V_DASHER (UNIT_V_UF + 0) /* Dasher mode */ #define UNIT_V_DASHER (UNIT_V_UF + 0) /* Dasher mode */
#define UNIT_DASHER (1 << UNIT_V_DASHER) #define UNIT_DASHER (1 << UNIT_V_DASHER)
extern int32 int_req, dev_busy, dev_done, dev_disable, iot_enb; 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 tti1_svc (UNIT *uptr);
t_stat tto1_svc (UNIT *uptr); t_stat tto1_svc (UNIT *uptr);
t_stat tti1_reset (DEVICE *dptr); t_stat tti1_reset (DEVICE *dptr);
t_stat tto1_reset (DEVICE *dptr); t_stat tto1_reset (DEVICE *dptr);
t_stat ttx1_setmod (UNIT *uptr, int32 value); t_stat ttx1_setmod (UNIT *uptr, int32 value);
extern t_stat sim_poll_kbd (void); t_stat tti1_attach (UNIT *uptr, char *cptr);
static uint8 tto1_consout[CONS_SIZE]; t_stat tti1_detach (UNIT *uptr);
t_stat tti1_status (UNIT *uptr, FILE *st);
/* TTI1 data structures /* TTI1 data structures
@ -53,7 +62,7 @@ static uint8 tto1_consout[CONS_SIZE];
ttx1_mod TTI1/TTO1 modifiers list 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[] = { REG tti1_reg[] = {
{ ORDATA (BUF, tti1_unit.buf, 8) }, { ORDATA (BUF, tti1_unit.buf, 8) },
@ -61,16 +70,14 @@ REG tti1_reg[] = {
{ FLDATA (DONE, dev_done, INT_V_TTI1) }, { FLDATA (DONE, dev_done, INT_V_TTI1) },
{ FLDATA (DISABLE, dev_disable, INT_V_TTI1) }, { FLDATA (DISABLE, dev_disable, INT_V_TTI1) },
{ FLDATA (INT, int_req, 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 }, { DRDATA (TIME, tti1_unit.wait, 24), REG_NZ + PV_LEFT },
{ FLDATA (MODE, tti1_unit.flags, UNIT_V_DASHER), REG_HRO }, { 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 }, { FLDATA (*DEVENB, iot_enb, INT_V_TTI1), REG_HRO },
{ NULL } }; { NULL } };
MTAB ttx1_mod[] = { MTAB ttx1_mod[] = {
{ UNIT_CONS, 0, "inactive", NULL, NULL }, { UNIT_ATT, UNIT_ATT, "line status:", NULL, &tti1_status },
{ UNIT_CONS, UNIT_CONS, "active console", "CONSOLE", &set_console },
{ UNIT_DASHER, 0, "ANSI", "ANSI", &ttx1_setmod }, { UNIT_DASHER, 0, "ANSI", "ANSI", &ttx1_setmod },
{ UNIT_DASHER, UNIT_DASHER, "Dasher", "DASHER", &ttx1_setmod }, { UNIT_DASHER, UNIT_DASHER, "Dasher", "DASHER", &ttx1_setmod },
{ 0 } }; { 0 } };
@ -78,8 +85,8 @@ MTAB ttx1_mod[] = {
DEVICE tti1_dev = { DEVICE tti1_dev = {
"TTI1", &tti1_unit, tti1_reg, ttx1_mod, "TTI1", &tti1_unit, tti1_reg, ttx1_mod,
1, 10, 31, 1, 8, 8, 1, 10, 31, 1, 8, 8,
NULL, NULL, &tti1_reset, &tmxr_ex, &tmxr_dep, &tti1_reset,
NULL, NULL, NULL }; NULL, &tti1_attach, &tti1_detach };
/* TTO1 data structures /* TTO1 data structures
@ -96,11 +103,9 @@ REG tto1_reg[] = {
{ FLDATA (DONE, dev_done, INT_V_TTO1) }, { FLDATA (DONE, dev_done, INT_V_TTO1) },
{ FLDATA (DISABLE, dev_disable, INT_V_TTO1) }, { FLDATA (DISABLE, dev_disable, INT_V_TTO1) },
{ FLDATA (INT, int_req, 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 }, { DRDATA (TIME, tto1_unit.wait, 24), PV_LEFT },
{ FLDATA (MODE, tto1_unit.flags, UNIT_V_DASHER), REG_HRO }, { 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 }, { FLDATA (*DEVENB, iot_enb, INT_V_TTI1), REG_HRO },
{ NULL } }; { NULL } };
@ -135,17 +140,25 @@ return iodata;
t_stat tti1_svc (UNIT *uptr) t_stat tti1_svc (UNIT *uptr)
{ {
int32 temp; int32 temp, newln;
sim_activate (&tti1_unit, tti1_unit.wait); /* continue poll */ if (tt1_ldsc.conn) { /* connected? */
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */ tmxr_poll_rx (&tt_desc); /* poll for input */
tti1_unit.buf = temp & 0177; if (temp = tmxr_getc_ln (&tt1_ldsc)) { /* get char */
if ((tti1_unit.flags & UNIT_DASHER) && (tti1_unit.buf == '\r')) uptr -> buf = temp & 0177;
tti1_unit.buf = '\n'; /* Dasher: cr -> nl */ if ((uptr -> flags & UNIT_DASHER) &&
dev_busy = dev_busy & ~INT_TTI1; /* clear busy */ (uptr -> buf == '\r'))
dev_done = dev_done | INT_TTI1; /* set done */ uptr -> buf = '\n'; /* Dasher: cr -> nl */
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); dev_busy = dev_busy & ~INT_TTI1; /* clear busy */
tti1_unit.pos = tti1_unit.pos + 1; 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; return SCPE_OK;
} }
@ -157,8 +170,12 @@ tti1_unit.buf = 0;
dev_busy = dev_busy & ~INT_TTI1; /* clear busy */ dev_busy = dev_busy & ~INT_TTI1; /* clear busy */
dev_done = dev_done & ~INT_TTI1; /* clear done, int */ dev_done = dev_done & ~INT_TTI1; /* clear done, int */
int_req = int_req & ~INT_TTI1; int_req = int_req & ~INT_TTI1;
if (tti1_unit.flags & UNIT_CONS) /* active console? */ if (tt1_ldsc.conn) { /* if conn, */
sim_activate (&tti1_unit, tti1_unit.wait); 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; return SCPE_OK;
} }
@ -187,15 +204,20 @@ return 0;
t_stat tto1_svc (UNIT *uptr) t_stat tto1_svc (UNIT *uptr)
{ {
int32 c, temp; int32 c;
dev_busy = dev_busy & ~INT_TTO1; /* clear busy */ dev_busy = dev_busy & ~INT_TTO1; /* clear busy */
dev_done = dev_done | INT_TTO1; /* set done */ dev_done = dev_done | INT_TTO1; /* set done */
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable); int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
c = tto1_unit.buf & 0177; c = tto1_unit.buf & 0177;
if ((tto1_unit.flags & UNIT_DASHER) && (c == 031)) c = '\b'; if ((tto1_unit.flags & UNIT_DASHER) && (c == 031)) c = '\b';
if ((temp = sim_putcons (c, uptr)) != SCPE_OK) return temp; if (tt1_ldsc.conn) { /* connected? */
tto1_unit.pos = tto1_unit.pos + 1; 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; return SCPE_OK;
} }
@ -208,7 +230,6 @@ dev_busy = dev_busy & ~INT_TTO1; /* clear busy */
dev_done = dev_done & ~INT_TTO1; /* clear done, int */ dev_done = dev_done & ~INT_TTO1; /* clear done, int */
int_req = int_req & ~INT_TTO1; int_req = int_req & ~INT_TTO1;
sim_cancel (&tto1_unit); /* deactivate unit */ sim_cancel (&tto1_unit); /* deactivate unit */
tto1_unit.filebuf = tto1_consout; /* set buf pointer */
return SCPE_OK; 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; tto1_unit.flags = (tto1_unit.flags & ~UNIT_DASHER) | value;
return SCPE_OK; 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 cpu KS10 central processor
31-Aug-01 RMS Changed int64 to t_int64 for Windoze
10-Aug-01 RMS Removed register in declarations 10-Aug-01 RMS Removed register in declarations
17-Jul-01 RMS Moved function prototype 17-Jul-01 RMS Moved function prototype
19-May-01 RMS Added workaround for TOPS-20 V4.1 boot bug 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 circ (int32 ac, a10 ea);
void blt (int32 ac, a10 ea, int32 pflgs); void blt (int32 ac, a10 ea, int32 pflgs);
void bltu (int32 ac, a10 ea, int32 pflgs, int dir); 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); a10 calc_ioea (d10 inst, int32 prv);
d10 calc_jrstfea (d10 inst, int32 pflgs); d10 calc_jrstfea (d10 inst, int32 pflgs);
void pi_dismiss (void); void pi_dismiss (void);

View file

@ -23,6 +23,11 @@
be used in advertising or otherwise to promote the sale, use or other dealings 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. 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 01-Jun-01 RMS Updated DZ11 vector definitions
19-May-01 RMS Added workaround for TOPS-20 V4.1 boot bug 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 PDP-6 0.25 Original 36b implementation, 1964
KA10 0.38 First PDP-10, flip chips, 1967 KA10 0.38 First PDP-10, flip chips, 1967
KI10 0.72 First paging system, flip chip + MSI, 1969 KI10 0.72 First paging system, flip chip + MSI, 1972
KL10 1.8 First ECL system, ECL 10K, 1972 KL10 1.8 First ECL system, ECL 10K, 1975
KL10X 1.8 Expanded addressing, ECL 10K, 1975 KL10B 1.8 Expanded addressing, ECL 10K, 1978
KS10 0.3 Last 36b system, 2901 based, 1979 KS10 0.3 Last 36b system, 2901 based, 1979
In addition, it ran four major (incompatible) operating systems: In addition, it ran four major (incompatible) operating systems:
@ -69,8 +74,8 @@
/* Data types */ /* Data types */
typedef int32 a10; /* PDP-10 addr (30b) */ typedef int32 a10; /* PDP-10 addr (30b) */
typedef int64 d10; /* PDP-10 data (36b) */ typedef t_int64 d10; /* PDP-10 data (36b) */
/* Abort codes, used to sort out longjmp's back to the main loop /* Abort codes, used to sort out longjmp's back to the main loop
Codes > 0 are simulator stop codes Codes > 0 are simulator stop codes
@ -162,7 +167,7 @@ typedef int64 d10; /* PDP-10 data (36b) */
#define BP_S 0007700000000 #define BP_S 0007700000000
#define GET_P(x) ((int32) (((x) >> BP_V_P) & BP_M_P)) #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 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) */ /* 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 IO_UBA3 (3 << IO_V_UBA)
#define GET_IOUBA(x) (((x) >> IO_V_UBA) & IO_M_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 */ /* I/O page layout */
#define IO_DZBASE 0760010 /* DZ11 base */ #define IOBA_DZ 0760010 /* DZ11 */
#define IO_TCUBASE 0760770 /* TCU150 base */ #define IOLN_DZ (010 * DZ_MUXES)
#define IO_UBMAP 0763000 /* Unibus map base */ #define IOBA_TCU 0760770 /* TCU150 */
#define IO_UBCS 0763100 /* Unibus c/s reg */ #define IOLN_TCU 006
#define IO_UBMNT 0763101 /* Unibus maint reg */ #define IOBA_UBMAP 0763000 /* Unibus map */
#define IO_TMBASE 0772440 /* RH11/tape base */ #define IOLN_UBMAP 0100
#define IO_RHBASE 0776700 /* RH11/disk base */ #define IOBA_UBCS 0763100 /* Unibus c/s reg */
#define IO_LPBASE 0775400 /* LP20 base */ #define IOLN_UBCS 001
#define IO_PTBASE 0777550 /* PC11 base */ #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 */ /* 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_RP 6 /* RH11/RP,RM drives */
#define INT_V_TU 7 /* RH11/TM03/TU45 */ #define INT_V_TU 7 /* RH11/TM03/TU45 */
#define INT_V_DZ0RX 16 /* DZ11 */ #define INT_V_DZRX 16 /* DZ11 */
#define INT_V_DZ0TX 17 #define INT_V_DZTX 17
#define INT_V_PTR 24 /* PC11 */ #define INT_V_PTR 24 /* PC11 */
#define INT_V_PTP 25 #define INT_V_PTP 25
#define INT_V_LP20 26 /* LPT20 */ #define INT_V_LP20 26 /* LPT20 */
#define INT_RP (1u << INT_V_RP) #define INT_RP (1u << INT_V_RP)
#define INT_TU (1u << INT_V_TU) #define INT_TU (1u << INT_V_TU)
#define INT_DZ0RX (1u << INT_V_DZ0RX) #define INT_DZRX (1u << INT_V_DZRX)
#define INT_DZ0TX (1u << INT_V_DZ0TX) #define INT_DZTX (1u << INT_V_DZTX)
#define INT_PTR (1u << INT_V_PTR) #define INT_PTR (1u << INT_V_PTR)
#define INT_PTP (1u << INT_V_PTP) #define INT_PTP (1u << INT_V_PTP)
#define INT_LP20 (1u << INT_V_LP20) #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_UB1 INT_RP /* on Unibus 1 */
#define INT_UB3 (0xFFFFFFFFu & ~INT_UB1) /* on Unibus 3 */ #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_PTP 0074
#define VEC_TU 0224 #define VEC_TU 0224
#define VEC_RP 0254 #define VEC_RP 0254
#define VEC_DZ0RX 0340 #define VEC_DZRX 0340
#define VEC_DZ0TX 0344 #define VEC_DZTX 0344
#define VEC_LP20 0754 #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 Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), 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 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. in this Software without prior written authorization from Robert M Supnik.
dz DZ11 terminal multiplexor (stub) dz DZ11 terminal multiplexor
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.
*/ */
#include "pdp10_defs.h" #include "pdp10_defs.h"
#include "dec_dz.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;
}

View file

@ -24,6 +24,9 @@
in this Software without prior written authorization from Robert M Supnik. in this Software without prior written authorization from Robert M Supnik.
fe KS10 console front end 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" #include "pdp10_defs.h"
@ -36,8 +39,6 @@ t_stat feo_svc (UNIT *uptr);
t_stat fe_reset (DEVICE *dptr); t_stat fe_reset (DEVICE *dptr);
t_stat fe_stop_os (UNIT *uptr, int32 val); t_stat fe_stop_os (UNIT *uptr, int32 val);
t_stat fe_ctrl_c (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 /* FE data structures
@ -147,7 +148,7 @@ return SCPE_OK;
t_stat fe_stop_os (UNIT *uptr, int32 val) 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; 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 */ M[FE_CTYIN] = fei_unit.buf | FE_CVALID; /* put char in mem */
apr_flg = apr_flg | APRF_CON; /* interrupt KS10 */ apr_flg = apr_flg | APRF_CON; /* interrupt KS10 */
return SCPE_OK; return SCPE_OK;
} }

View file

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

View file

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

View file

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

View file

@ -25,8 +25,14 @@
rp RH/RP/RM moving head disks 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 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) 13-Jul-01 RMS Changed fread call to fxread (found by Peter Schorn)
14-May-01 RMS Added check for unattached drive 14-May-01 RMS Added check for unattached drive
@ -35,13 +41,19 @@
100% compatible) family of interfaces into the KS10 Unibus via 100% compatible) family of interfaces into the KS10 Unibus via
the RH11 disk controller. the RH11 disk controller.
WARNING: This controller is somewhat abstract. It is intended to run WARNING: The interupt logic of the RH11/RH70 is unusual and must be
the operating system drivers for the PDP-10 operating systems and simulated with great precision. The RH11 has an internal interrupt
nothing more. Most error and all diagnostic functions have been request flop, CSTB INTR, which is controlled as follows:
omitted. In addition, the controller conflates the RP04/05/06 series - Writing IE and DONE simultaneously sets CSTB INTR
controllers with the RM02/03/05/80 series controllers and with the - Controller clear, INIT, and interrupt acknowledge clear CSTB INTR
RP07 controller. There are actually significant differences, which (and also clear IE)
have been highlighted where noticed. - 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" #include "pdp10_defs.h"
@ -89,6 +101,7 @@
#define FNC_PRESET 010 /* read-in preset */ #define FNC_PRESET 010 /* read-in preset */
#define FNC_PACK 011 /* pack acknowledge */ #define FNC_PACK 011 /* pack acknowledge */
#define FNC_SEARCH 014 /* search */ #define FNC_SEARCH 014 /* search */
#define FNC_XFER 024 /* >=? data xfr */
#define FNC_WCHK 024 /* write check */ #define FNC_WCHK 024 /* write check */
#define FNC_WRITE 030 /* write */ #define FNC_WRITE 030 /* write */
#define FNC_WRITEH 031 /* write w/ headers */ #define FNC_WRITEH 031 /* write w/ headers */
@ -104,7 +117,7 @@
#define CS1_TRE 0040000 /* transfer err */ #define CS1_TRE 0040000 /* transfer err */
#define CS1_SC 0100000 /* special cond */ #define CS1_SC 0100000 /* special cond */
#define CS1_MBZ 0012000 #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_FNC(x) (((x) >> CS1_V_FNC) & CS1_M_FNC)
#define GET_UAE(x) (((x) & CS1_UAE) << (16 - CS1_V_UAE)) #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) + \ #define GET_DA(c,fs,d) ((((GET_CY (c) * drv_tab[d].surf) + \
GET_SF (fs)) * drv_tab[d].sect) + GET_SC (fs)) 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 */ /* RPER2 - 176740 - error status 2 - drive unsafe conditions - unimplemented */
/* RPER3 - 176742 - error status 3 - more unsafe conditions - unimplemented */ /* RPER3 - 176742 - error status 3 - more unsafe conditions - unimplemented */
/* RPEC1 - 176744 - ECC status 1 - unimplemented */ /* RPEC1 - 176744 - ECC status 1 - unimplemented */
@ -315,6 +328,7 @@ int32 rper2 = 0; /* error status 2 */
int32 rper3 = 0; /* error status 3 */ int32 rper3 = 0; /* error status 3 */
int32 rpec1 = 0; /* ECC correction 1 */ int32 rpec1 = 0; /* ECC correction 1 */
int32 rpec2 = 0; /* ECC correction 2 */ int32 rpec2 = 0; /* ECC correction 2 */
int32 rpiff = 0; /* INTR flip/flop */
int32 rp_stopioe = 1; /* stop on error */ int32 rp_stopioe = 1; /* stop on error */
int32 rp_swait = 10; /* seek time */ int32 rp_swait = 10; /* seek time */
int32 rp_rwait = 10; /* rotate 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 }; 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
void update_rpcs (int32 flags, int32 drv); 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_size (UNIT *uptr, int32 value);
t_stat rp_svc (UNIT *uptr); t_stat rp_svc (UNIT *uptr);
t_stat rp_reset (DEVICE *dptr); t_stat rp_reset (DEVICE *dptr);
@ -371,6 +385,7 @@ REG rp_reg[] = {
{ ORDATA (RPEC2, rpec2, 16) }, { ORDATA (RPEC2, rpec2, 16) },
{ ORDATA (RPMR, rpmr, 16) }, { ORDATA (RPMR, rpmr, 16) },
{ ORDATA (RPDB, rpdb, 16) }, { ORDATA (RPDB, rpdb, 16) },
{ FLDATA (IFF, rpiff, 0) },
{ FLDATA (INT, int_req, INT_V_RP) }, { FLDATA (INT, int_req, INT_V_RP) },
{ FLDATA (SC, rpcs1, CSR_V_ERR) }, { FLDATA (SC, rpcs1, CSR_V_ERR) },
{ FLDATA (DONE, rpcs1, CSR_V_DONE) }, { FLDATA (DONE, rpcs1, CSR_V_DONE) },
@ -393,6 +408,14 @@ REG rp_reg[] = {
{ ORDATA (RPDE5, rper1[5], 16) }, { ORDATA (RPDE5, rper1[5], 16) },
{ ORDATA (RPDE6, rper1[6], 16) }, { ORDATA (RPDE6, rper1[6], 16) },
{ ORDATA (RPDE7, rper1[7], 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), { GRDATA (FLG0, rp_unit[0].flags, 8, UNIT_W_UF, UNIT_V_UF - 1),
REG_HRO }, REG_HRO },
{ GRDATA (FLG1, rp_unit[1].flags, 8, UNIT_W_UF, UNIT_V_UF - 1), { 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) t_stat rp_wr (int32 data, int32 PA, int32 access)
{ {
int32 cs1f, drv, i, j; int32 cs1f, drv, i, j;
UNIT *uptr;
cs1f = 0; /* no int on cs1 upd */ cs1f = 0; /* no int on cs1 upd */
drv = GET_UNIT (rpcs2); /* get current unit */ drv = GET_UNIT (rpcs2); /* get current unit */
uptr = rp_dev.units + drv; /* get unit */
j = (PA >> 1) & 037; /* get reg offset */ j = (PA >> 1) & 037; /* get reg offset */
if (reg_in_drive[j] && (rp_unit[drv].flags & UNIT_DIS)) { /* nx disk */ if (reg_in_drive[j] && (rp_unit[drv].flags & UNIT_DIS)) { /* nx disk */
rpcs2 = rpcs2 | CS2_NED; /* set error flag */ 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> */ switch (j) { /* decode PA<5:1> */
case 000: /* RPCS1 */ case 000: /* RPCS1 */
if ((access == WRITEB) && (PA & 1)) data = data << 8; 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? */ if (data & CS1_TRE) { /* error clear? */
rpcs1 = rpcs1 & ~CS1_TRE; /* clr CS1<TRE> */ rpcs1 = rpcs1 & ~CS1_TRE; /* clr CS1<TRE> */
rpcs2 = rpcs2 & ~CS2_ERR; } /* clr CS2<15:8> */ rpcs2 = rpcs2 & ~CS2_ERR; } /* clr CS2<15:8> */
if (access == WRITEB) data = (rpcs1 & /* merge data */ if ((access == WRITE) || (PA & 1)) { /* hi byte write? */
((PA & 1)? 0377: 0177400)) | data; if (rpcs1 & CS1_DONE) /* done set? */
rpcs1 = (rpcs1 & ~CS1_RW) | (data & CS1_RW); rpcs1 = (rpcs1 & ~CS1_UAE) | (data & CS1_UAE); }
if (data & CS1_GO) { /* new command? */ if ((access == WRITE) || !(PA & 1)) { /* lo byte write? */
if (rpcs1 & CS1_DONE) rp_go (drv); /* start if not busy */ if ((data & CS1_DONE) && (data & CS1_IE)) /* to DONE+IE? */
else rpcs2 = rpcs2 | CS2_PGE; } /* else prog error */ 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; break;
case 001: /* RPWC */ case 001: /* RPWC */
if (access == WRITEB) data = (PA & 1)? if (access == WRITEB) data = (PA & 1)?
@ -650,29 +685,23 @@ update_rpcs (cs1f, drv); /* update status */
return SCPE_OK; 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; UNIT *uptr;
fnc = GET_FNC (rpcs1); /* get function */
uptr = rp_dev.units + drv; /* get unit */ uptr = rp_dev.units + drv; /* get unit */
if (uptr -> flags & UNIT_DIS) { /* nx unit? */ if (uptr -> flags & UNIT_DIS) { /* nx unit? */
rpcs2 = rpcs2 | CS2_NED; /* set error flag */ rpcs2 = rpcs2 | CS2_NED; /* set error flag */
update_rpcs (CS1_SC, drv); /* request intr */ update_rpcs (CS1_SC, drv); /* request intr */
return; } return; }
if (fnc != FNC_DCLR) { /* not clear? */ if ((fnc != FNC_DCLR) && (rpds[drv] & DS_ERR)) { /* err & ~clear? */
if ((rpds[drv] & DS_ERR) || /* error or */ rper1[drv] = rper1[drv] | ER1_ILF; /* not allowed */
((rpds[drv] & DS_RDY) == 0)) { /* not ready? */ rpds[drv] = rpds[drv] | DS_ATA; /* set attention */
rpcs2 = rpcs2 | CS2_PGE; /* set error flag */ update_rpcs (CS1_SC, drv); /* request intr */
update_rpcs (CS1_SC, drv); /* request intr */ return; }
return; }
if ((uptr -> flags & UNIT_ATT) == 0) { /* not attached? */
rper1[drv] = rper1[drv] | ER1_UNS; /* unsafe */
update_rpcs (CS1_SC, drv); /* request intr */
return; } }
dtype = GET_DTYPE (uptr -> flags); /* get drive type */ dtype = GET_DTYPE (uptr -> flags); /* get drive type */
rpds[drv] = rpds[drv] & ~DS_ATA; /* clear attention */ rpds[drv] = rpds[drv] & ~DS_ATA; /* clear attention */
dc = rpdc; /* assume seek, sch */ dc = rpdc; /* assume seek, sch */
@ -695,7 +724,9 @@ case FNC_PACK: /* pack acknowledge */
case FNC_OFFSET: /* offset mode */ case FNC_OFFSET: /* offset mode */
case FNC_RETURN: 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 */ rpds[drv] = (rpds[drv] & ~DS_RDY) | DS_PIP; /* set positioning */
sim_activate (uptr, rp_swait); /* time operation */ sim_activate (uptr, rp_swait); /* time operation */
return; return;
@ -705,40 +736,46 @@ case FNC_RECAL: /* recalibrate */
dc = 0; /* seek to 0 */ dc = 0; /* seek to 0 */
case FNC_SEEK: /* seek */ case FNC_SEEK: /* seek */
case FNC_SEARCH: /* search */ 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 */ if ((GET_CY (dc) >= drv_tab[dtype].cyl) || /* bad cylinder */
(GET_SF (rpda) >= drv_tab[dtype].surf) || /* bad surface */ (GET_SF (rpda) >= drv_tab[dtype].surf) || /* bad surface */
(GET_SC (rpda) >= drv_tab[dtype].sect)) { /* or bad sector? */ (GET_SC (rpda) >= drv_tab[dtype].sect)) { /* or bad sector? */
rper1[drv] = rper1[drv] | ER1_IAE; rper1[drv] = rper1[drv] | ER1_IAE;
break; } break; }
rpds[drv] = (rpds[drv] & ~DS_RDY) | DS_PIP; /* set positioning */ rpds[drv] = (rpds[drv] & ~DS_RDY) | DS_PIP; /* set positioning */
sim_activate (uptr, rp_swait * abs (dc - uptr -> CYL)); t = abs (dc - uptr -> CYL); /* cyl diff */
uptr -> FUNC = fnc; /* save function */ if (t == 0) t = 1; /* min time */
sim_activate (uptr, rp_swait * t); /* schedule */
uptr -> CYL = dc; /* save cylinder */ uptr -> CYL = dc; /* save cylinder */
return; return;
case FNC_WRITEH: /* write headers */ case FNC_WRITEH: /* write headers */
case FNC_WRITE: /* write */ case FNC_WRITE: /* write */
case FNC_WCHK: /* write check */ case FNC_WCHK: /* write check */
case FNC_READ: /* read */ case FNC_READ: /* read */
case FNC_READH: /* read headers */ 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 */ rpcs2 = rpcs2 & ~CS2_ERR; /* clear errors */
rpcs1 = rpcs1 & ~(CS1_TRE | CS1_MCPE | CS1_DONE); rpcs1 = rpcs1 & ~(CS1_TRE | CS1_MCPE | CS1_DONE);
if ((GET_CY (dc) >= drv_tab[dtype].cyl) || /* bad cylinder */ if ((GET_CY (dc) >= drv_tab[dtype].cyl) || /* bad cylinder */
(GET_SF (rpda) >= drv_tab[dtype].surf) || /* bad surface */ (GET_SF (rpda) >= drv_tab[dtype].surf) || /* bad surface */
(GET_SC (rpda) >= drv_tab[dtype].sect)) { /* or bad sector? */ (GET_SC (rpda) >= drv_tab[dtype].sect)) { /* or bad sector? */
rper1[drv] = rper1[drv] | ER1_IAE; rper1[drv] = rper1[drv] | ER1_IAE;
update_rpcs (CS1_DONE | CS1_TRE, drv); /* set done, err */ break; }
return; }
rpds[drv] = rpds[drv] & ~DS_RDY; /* clear drive rdy */ rpds[drv] = rpds[drv] & ~DS_RDY; /* clear drive rdy */
sim_activate (uptr, rp_rwait + (rp_swait * abs (dc - uptr -> CYL))); sim_activate (uptr, rp_rwait + (rp_swait * abs (dc - uptr -> CYL)));
uptr -> FUNC = fnc; /* save function */
uptr -> CYL = dc; /* save cylinder */ uptr -> CYL = dc; /* save cylinder */
return; return;
default: /* all others */ default: /* all others */
rper1[drv] = rper1[drv] | ER1_ILF; /* not supported */ rper1[drv] = rper1[drv] | ER1_ILF; /* not supported */
break; } 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; return;
} }
@ -870,21 +907,28 @@ case FNC_READH: /* read headers */
perror ("RP I/O error"); perror ("RP I/O error");
clearerr (uptr -> fileref); clearerr (uptr -> fileref);
return SCPE_IOERR; } return SCPE_IOERR; }
case FNC_WRITEH: /* write headers stub */ case FNC_WRITEH: /* write headers stub */
update_rpcs (CS1_DONE, drv); /* set done */ update_rpcs (CS1_DONE, drv); /* set done */
break; } /* end case func */ break; } /* end case func */
return SCPE_OK; return SCPE_OK;
} }
/* Controller status update /* Controller status update
First update drive status, then update RPCS1
If optional argument, request interrupt Check for done transition
Update drive status
Update RPCS1
Update interrupt request
*/ */
void update_rpcs (int32 flag, int32 drv) void update_rpcs (int32 flag, int32 drv)
{ {
int32 i; 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; if (rp_unit[drv].flags & UNIT_DIS) rpds[drv] = rper1[drv] = 0;
else rpds[drv] = (rpds[drv] | DS_DPR) & ~DS_PGM; else rpds[drv] = (rpds[drv] | DS_DPR) & ~DS_PGM;
if (rp_unit[drv].flags & UNIT_ATT) rpds[drv] = rpds[drv] | DS_MOL; 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; if (rper1[drv] | rper2 | rper3) rpds[drv] = rpds[drv] | DS_ERR | DS_ATA;
else rpds[drv] = rpds[drv] & ~DS_ERR; 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; 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++) for (i = 0; i < RP_NUMDR; i++)
if (rpds[i] & DS_ATA) rpcs1 = rpcs1 | CS1_SC; if (rpds[i] & DS_ATA) rpcs1 = rpcs1 | CS1_SC;
if (((rpcs1 & CS1_IE) == 0) || ((rpcs1 & CS1_DONE) == 0)) if (rpiff || ((rpcs1 & CS1_SC) && (rpcs1 & CS1_DONE) && (rpcs1 & CS1_IE)))
int_req = int_req & ~INT_RP; int_req = int_req | INT_RP;
else if (flag) int_req = int_req | INT_RP; else int_req = int_req & ~INT_RP;
return; return;
} }
@ -907,6 +954,7 @@ return;
int32 rp_inta (void) int32 rp_inta (void)
{ {
rpcs1 = rpcs1 & ~CS1_IE; /* clear int enable */ rpcs1 = rpcs1 & ~CS1_IE; /* clear int enable */
rpiff = 0; /* clear CSTB INTR */
return VEC_RP; /* acknowledge */ return VEC_RP; /* acknowledge */
} }
@ -923,7 +971,8 @@ rpba = rpda = 0;
rpof = rpdc = 0; rpof = rpdc = 0;
rper2 = rper3 = 0; rper2 = rper3 = 0;
rpec1 = rpec2 = 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++) { for (i = 0; i < RP_NUMDR; i++) {
uptr = rp_dev.units + i; uptr = rp_dev.units + i;
sim_cancel (uptr); sim_cancel (uptr);
@ -998,8 +1047,8 @@ return SCPE_OK;
static const d10 boot_rom_dec[] = { static const d10 boot_rom_dec[] = {
0515040000001, /* boot:hrlzi 1,1 ; uba # */ 0515040000001, /* boot:hrlzi 1,1 ; uba # */
0201000140001, /* movei 0,140001 ; vld,fst,pg 1 */ 0201000140001, /* movei 0,140001 ; vld,fst,pg 1 */
0713001000000+IO_UBMAP+1, /* wrio 0,763001(1); set ubmap */ 0713001000000+IOBA_UBMAP+1, /* wrio 0,763001(1); set ubmap */
0435040000000+IO_RHBASE, /* iori 1,776700 ; rh addr */ 0435040000000+IOBA_RP, /* iori 1,776700 ; rh addr */
0202040000000+FE_RHBASE, /* movem 1,FE_RHBASE */ 0202040000000+FE_RHBASE, /* movem 1,FE_RHBASE */
0201000000040, /* movei 0,40 ; ctrl reset */ 0201000000040, /* movei 0,40 ; ctrl reset */
0713001000010, /* wrio 0,10(1) ; ->RPCS2 */ 0713001000010, /* wrio 0,10(1) ; ->RPCS2 */
@ -1045,8 +1094,8 @@ static const d10 boot_rom_dec[] = {
static const d10 boot_rom_its[] = { static const d10 boot_rom_its[] = {
0515040000001, /* boot:hrlzi 1,1 ; uba # */ 0515040000001, /* boot:hrlzi 1,1 ; uba # */
0201000140001, /* movei 0,140001 ; vld,fst,pg 1 */ 0201000140001, /* movei 0,140001 ; vld,fst,pg 1 */
0715000000000+IO_UBMAP+1, /* iowrq 0,763001 ; set ubmap */ 0715000000000+IOBA_UBMAP+1, /* iowrq 0,763001 ; set ubmap */
0435040000000+IO_RHBASE, /* iori 1,776700 ; rh addr */ 0435040000000+IOBA_RP, /* iori 1,776700 ; rh addr */
0202040000000+FE_RHBASE, /* movem 1,FE_RHBASE */ 0202040000000+FE_RHBASE, /* movem 1,FE_RHBASE */
0201000000040, /* movei 0,40 ; ctrl reset */ 0201000000040, /* movei 0,40 ; ctrl reset */
0715001000010, /* iowrq 0,10(1) ; ->RPCS2 */ 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 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. in this Software without prior written authorization from Robert M Supnik.
17-Sep-01 RMS Removed multiconsole support
25-Aug-01 RMS Enabled DZ11 25-Aug-01 RMS Enabled DZ11
27-May-01 RMS Added multiconsole support 27-May-01 RMS Added multiconsole support
29-Apr-01 RMS Fixed format for RDPCST, WRPCST 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_PC pointer to saved PC register descriptor
sim_emax number of words for examine sim_emax number of words for examine
sim_devices array of pointers to simulated devices 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_stop_messages array of pointers to stop messages
sim_load binary loader sim_load binary loader
*/ */
@ -77,8 +77,6 @@ DEVICE *sim_devices[] = {
&tu_dev, &tu_dev,
NULL }; NULL };
UNIT *sim_consoles = NULL;
const char *sim_stop_messages[] = { const char *sim_stop_messages[] = {
"Unknown error", "Unknown error",
"HALT instruction", "HALT instruction",

View file

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

View file

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

View file

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

View file

@ -26,6 +26,9 @@
The author gratefully acknowledges the help of Max Burnet, Megan Gentry, The author gratefully acknowledges the help of Max Burnet, Megan Gentry,
and John Wilson in resolving questions about the PDP-11 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 01-Jun-01 RMS Added DZ11 support
23-Apr-01 RMS Added RK611 support 23-Apr-01 RMS Added RK611 support
05-Apr-01 RMS Added TS11/TSV05 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 STOP_SPABORT TRAP_V_MAX + 5 /* abort trap push */
#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* cond error return */ #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 #define DZ_MUXES 1 /* # of muxes */
<7:4> = BR6, <7> = PIR6 #define DZ_LINES 8 /* lines per mux */
<19:8> = BR5, <19> = PIR5
<28:20> = BR4, <28> = PIR4
<29> = PIR3
<30> = PIR2
<31> = PIR1
*/
#define INT_V_PIR7 3 /* Interrupt assignments; within each level, priority is right to left */
#define INT_V_CLK 4
#define INT_V_DTA 5 #define IPL_HLVL 8 /* # int levels */
#define INT_V_PIR6 7
#define INT_V_RK 8 #define INT_V_PIR7 0 /* BR7 */
#define INT_V_RL 9
#define INT_V_RX 10 #define INT_V_CLK 0 /* BR6 */
#define INT_V_TM 11 #define INT_V_DTA 1
#define INT_V_RP 12 #define INT_V_PIR6 2
#define INT_V_TS 13
#define INT_V_HK 14 #define INT_V_RK 0 /* BR5 */
#define INT_V_DZ0RX 16 #define INT_V_RL 1
#define INT_V_DZ0TX 17 #define INT_V_RX 2
#define INT_V_PIR5 19 #define INT_V_TM 3
#define INT_V_TTI 20 #define INT_V_RP 4
#define INT_V_TTO 21 #define INT_V_TS 5
#define INT_V_PTR 22 #define INT_V_HK 6
#define INT_V_PTP 23 #define INT_V_DZRX 7
#define INT_V_LPT 24 #define INT_V_DZTX 8
#define INT_V_PIR4 28 #define INT_V_PIR5 9
#define INT_V_PIR3 29
#define INT_V_PIR2 30 #define INT_V_TTI 0 /* BR4 */
#define INT_V_PIR1 31 #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_PIR7 (1u << INT_V_PIR7)
#define INT_CLK (1u << INT_V_CLK) #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_RP (1u << INT_V_RP)
#define INT_TS (1u << INT_V_TS) #define INT_TS (1u << INT_V_TS)
#define INT_HK (1u << INT_V_HK) #define INT_HK (1u << INT_V_HK)
#define INT_DZ0RX (1u << INT_V_DZ0RX) #define INT_DZRX (1u << INT_V_DZRX)
#define INT_DZ0TX (1u << INT_V_DZ0TX) #define INT_DZTX (1u << INT_V_DZTX)
#define INT_PIR5 (1u << INT_V_PIR5) #define INT_PIR5 (1u << INT_V_PIR5)
#define INT_PTR (1u << INT_V_PTR) #define INT_PTR (1u << INT_V_PTR)
#define INT_PTP (1u << INT_V_PTP) #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_PIR2 (1u << INT_V_PIR2)
#define INT_PIR1 (1u << INT_V_PIR1) #define INT_PIR1 (1u << INT_V_PIR1)
#define INT_IPL7 0x00000000 /* int level masks */ #define IPL_CLK 6 /* int pri levels */
#define INT_IPL6 0x0000000F #define IPL_DTA 6
#define INT_IPL5 0x000000FF #define IPL_RK 5
#define INT_IPL4 0x000FFFFF #define IPL_RL 5
#define INT_IPL3 0x1FFFFFFF #define IPL_RX 5
#define INT_IPL2 0x3FFFFFFF #define IPL_TM 5
#define INT_IPL1 0x7FFFFFFF #define IPL_RP 5
#define INT_IPL0 0xFFFFFFFF #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_PIRQ 0240 /* interrupt vectors */
#define VEC_TTI 0060 #define VEC_TTI 0060
@ -320,8 +341,14 @@ typedef struct fpac fpac_t;
#define VEC_TS 0224 #define VEC_TS 0224
#define VEC_RP 0254 #define VEC_RP 0254
#define VEC_RX 0264 #define VEC_RX 0264
#define VEC_DZ0RX 0310 #define VEC_DZRX 0310
#define VEC_DZ0TX 0314 #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 */ /* CPU and FPU macros */
@ -331,3 +358,15 @@ typedef struct fpac fpac_t;
#define ABORT(val) longjmp (save_env, (val)) #define ABORT(val) longjmp (save_env, (val))
#define SP R[6] #define SP R[6]
#define PC R[7] #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 lpt LP11 line printer
07-Sep-01 RMS Revised interrupt mechanism
30-Oct-00 RMS Standardized register naming 30-Oct-00 RMS Standardized register naming
*/ */
@ -33,7 +34,7 @@
#define LPTCSR_IMP (CSR_ERR + CSR_DONE + CSR_IE) /* implemented */ #define LPTCSR_IMP (CSR_ERR + CSR_DONE + CSR_IE) /* implemented */
#define LPTCSR_RW (CSR_IE) /* read/write */ #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_csr = 0; /* control/status */
int32 lpt_stopioe = 0; /* stop on error */ int32 lpt_stopioe = 0; /* stop on error */
t_stat lpt_svc (UNIT *uptr); t_stat lpt_svc (UNIT *uptr);
@ -54,7 +55,7 @@ UNIT lpt_unit = {
REG lpt_reg[] = { REG lpt_reg[] = {
{ ORDATA (BUF, lpt_unit.buf, 8) }, { ORDATA (BUF, lpt_unit.buf, 8) },
{ ORDATA (CSR, lpt_csr, 16) }, { 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 (ERR, lpt_csr, CSR_V_ERR) },
{ FLDATA (DONE, lpt_csr, CSR_V_DONE) }, { FLDATA (DONE, lpt_csr, CSR_V_DONE) },
{ FLDATA (IE, lpt_csr, CSR_V_IE) }, { 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 & 02) == 0) { /* csr */
if (PA & 1) return SCPE_OK; 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) 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); } lpt_csr = (lpt_csr & ~LPTCSR_RW) | (data & LPTCSR_RW); }
else { if ((PA & 1) == 0) lpt_unit.buf = data & 0177; /* buffer */ else { if ((PA & 1) == 0) lpt_unit.buf = data & 0177; /* buffer */
lpt_csr = lpt_csr & ~CSR_DONE; lpt_csr = lpt_csr & ~CSR_DONE;
int_req = int_req & ~INT_LPT; CLR_INT (LPT);
if ((lpt_unit.buf == 015) || (lpt_unit.buf == 014) || if ((lpt_unit.buf == 015) || (lpt_unit.buf == 014) ||
(lpt_unit.buf == 012)) sim_activate (&lpt_unit, lpt_unit.wait); (lpt_unit.buf == 012)) sim_activate (&lpt_unit, lpt_unit.wait);
else sim_activate (&lpt_unit, 0); } else sim_activate (&lpt_unit, 0); }
@ -106,7 +107,7 @@ return SCPE_OK;
t_stat lpt_svc (UNIT *uptr) t_stat lpt_svc (UNIT *uptr)
{ {
lpt_csr = lpt_csr | CSR_ERR | CSR_DONE; 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) if ((lpt_unit.flags & UNIT_ATT) == 0)
return IORETURN (lpt_stopioe, SCPE_UNATT); return IORETURN (lpt_stopioe, SCPE_UNATT);
if (putc (lpt_unit.buf & 0177, lpt_unit.fileref) == EOF) { 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_unit.buf = 0;
lpt_csr = CSR_DONE; lpt_csr = CSR_DONE;
if ((lpt_unit.flags & UNIT_ATT) == 0) lpt_csr = lpt_csr | CSR_ERR; 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 */ sim_cancel (&lpt_unit); /* deactivate unit */
return SCPE_OK; return SCPE_OK;
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -23,6 +23,7 @@
be used in advertising or otherwise to promote the sale, use or other dealings 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. 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 27-May-01 RMS Added second Teletype support
18-May-01 RMS Added PDP-9,-15 API IOT's 18-May-01 RMS Added PDP-9,-15 API IOT's
12-May-01 RMS Fixed bug in RIM loaders 12-May-01 RMS Fixed bug in RIM loaders
@ -117,15 +118,6 @@ DEVICE *sim_devices[] = { &cpu_dev,
#endif #endif
NULL }; 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[] = { const char *sim_stop_messages[] = {
"Unknown error", "Unknown error",
"Undefined instruction", "Undefined instruction",

View file

@ -26,23 +26,32 @@
tti1 keyboard tti1 keyboard
tto1 teleprinter 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 10-Jun-01 RMS Cleaned up IOT decoding to reflect hardware
*/ */
#include "pdp18b_defs.h" #include "pdp18b_defs.h"
#include "sim_sock.h"
#include "sim_tmxr.h"
#include <ctype.h> #include <ctype.h>
#define UNIT_V_UC (UNIT_V_UF + 0) /* UC only */ #define UNIT_V_UC (UNIT_V_UF + 0) /* UC only */
#define UNIT_UC (1 << UNIT_V_UC) #define UNIT_UC (1 << UNIT_V_UC)
extern int32 int_req, saved_PC; 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 tti1_svc (UNIT *uptr);
t_stat tto1_svc (UNIT *uptr); t_stat tto1_svc (UNIT *uptr);
t_stat tti1_reset (DEVICE *dptr); t_stat tti1_reset (DEVICE *dptr);
t_stat tto1_reset (DEVICE *dptr); t_stat tto1_reset (DEVICE *dptr);
extern t_stat sim_poll_kbd (void); t_stat tti1_attach (UNIT *uptr, char *cptr);
extern t_stat sim_putchar (int32 out); t_stat tti1_detach (UNIT *uptr);
static uint8 tto1_consout[CONS_SIZE]; t_stat tti1_status (UNIT *uptr, FILE *st);
/* TTI1 data structures /* TTI1 data structures
@ -52,30 +61,28 @@ static uint8 tto1_consout[CONS_SIZE];
tti1_reg TTI1 register list 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[] = { REG tti1_reg[] = {
{ ORDATA (BUF, tti1_unit.buf, 8) }, { ORDATA (BUF, tti1_unit.buf, 8) },
{ FLDATA (INT, int_req, INT_V_TTI1) }, { FLDATA (INT, int_req, INT_V_TTI1) },
{ FLDATA (DONE, int_req, INT_V_TTI1) }, { FLDATA (DONE, int_req, INT_V_TTI1) },
{ FLDATA (UC, tti1_unit.flags, UNIT_V_UC), REG_HRO }, { 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 }, { DRDATA (TIME, tti1_unit.wait, 24), REG_NZ + PV_LEFT },
{ FLDATA (CFLAG, tti1_unit.flags, UNIT_V_CONS), REG_HRO },
{ NULL } }; { NULL } };
MTAB tti1_mod[] = { MTAB ttx1_mod[] = {
{ UNIT_CONS, 0, "inactive", NULL, NULL }, { UNIT_ATT, UNIT_ATT, "line status:", NULL, &tti1_status },
{ UNIT_CONS, UNIT_CONS, "active console", "CONSOLE", &set_console },
{ UNIT_UC, 0, "lower case", "LC", NULL }, { UNIT_UC, 0, "lower case", "LC", NULL },
{ UNIT_UC, UNIT_UC, "upper case", "UC", NULL }, { UNIT_UC, UNIT_UC, "upper case", "UC", NULL },
{ 0 } }; { 0 } };
DEVICE tti1_dev = { DEVICE tti1_dev = {
"TTI1", &tti1_unit, tti1_reg, tti1_mod, "TTI1", &tti1_unit, tti1_reg, ttx1_mod,
1, 10, 31, 1, 8, 8, 1, 10, 31, 1, 8, 8,
NULL, NULL, &tti1_reset, &tmxr_ex, &tmxr_dep, &tti1_reset,
NULL, NULL, NULL }; NULL, &tti1_attach, &tti1_detach };
/* TTO1 data structures /* TTO1 data structures
@ -91,21 +98,12 @@ REG tto1_reg[] = {
{ ORDATA (BUF, tto1_unit.buf, 8) }, { ORDATA (BUF, tto1_unit.buf, 8) },
{ FLDATA (INT, int_req, INT_V_TTO1) }, { FLDATA (INT, int_req, INT_V_TTO1) },
{ FLDATA (DONE, 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 }, { 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 } }; { 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 = { DEVICE tto1_dev = {
"TTO1", &tto1_unit, tto1_reg, tto1_mod, "TTO1", &tto1_unit, tto1_reg, ttx1_mod,
1, 10, 31, 1, 8, 8, 1, 10, 31, 1, 8, 8,
NULL, NULL, &tto1_reset, NULL, NULL, &tto1_reset,
NULL, NULL, NULL }; NULL, NULL, NULL };
@ -126,15 +124,23 @@ return AC;
t_stat tti1_svc (UNIT *uptr) t_stat tti1_svc (UNIT *uptr)
{ {
int32 temp; int32 temp, newln;
sim_activate (&tti1_unit, tti1_unit.wait); /* continue poll */ if (tt1_ldsc.conn) { /* connected? */
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */ tmxr_poll_rx (&tt_desc); /* poll for input */
temp = temp & 0177; if (temp = tmxr_getc_ln (&tt1_ldsc)) { /* get char */
if ((tti1_unit.flags & UNIT_UC) && islower (temp)) temp = toupper (temp); temp = temp & 0177;
tti1_unit.buf = temp | 0200; /* got char */ if ((uptr -> flags & UNIT_UC) &&
int_req = int_req | INT_TTI1; /* set flag */ islower (temp)) temp = toupper (temp);
tti1_unit.pos = tti1_unit.pos + 1; 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; return SCPE_OK;
} }
@ -143,9 +149,13 @@ return SCPE_OK;
t_stat tti1_reset (DEVICE *dptr) t_stat tti1_reset (DEVICE *dptr)
{ {
tti1_unit.buf = 0; /* clear buffer */ tti1_unit.buf = 0; /* clear buffer */
int_req = int_req & ~INT_TTI; /* clear flag */ int_req = int_req & ~INT_TTI1; /* clear flag */
if (tti1_unit.flags & UNIT_CONS) /* if active console */ if (tt1_ldsc.conn) { /* if conn, */
sim_activate (&tti1_unit, tti1_unit.wait); /* activate unit */ 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; return SCPE_OK;
} }
@ -166,15 +176,19 @@ return AC;
t_stat tto1_svc (UNIT *uptr) t_stat tto1_svc (UNIT *uptr)
{ {
int32 out, temp; int32 out;
int_req = int_req | INT_TTO1; /* set flag */ int_req = int_req | INT_TTO1; /* set flag */
out = tto1_unit.buf & 0177; out = tto1_unit.buf & 0177;
if (!(tto1_unit.flags & UNIT_UC) || if (tt1_ldsc.conn) { /* connected? */
((out >= 007) && (out <= 0137))) { if (tt1_ldsc.xmte) { /* tx enabled? */
temp = sim_putcons (out, uptr); if (!(tto1_unit.flags & UNIT_UC) ||
if (temp != SCPE_OK) return temp; ((out >= 007) && (out <= 0137)))
tto1_unit.pos = tto1_unit.pos + 1; } 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; return SCPE_OK;
} }
@ -185,6 +199,37 @@ t_stat tto1_reset (DEVICE *dptr)
tto1_unit.buf = 0; /* clear buffer */ tto1_unit.buf = 0; /* clear buffer */
int_req = int_req & ~INT_TTO1; /* clear flag */ int_req = int_req & ~INT_TTO1; /* clear flag */
sim_cancel (&tto1_unit); /* deactivate unit */ 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; return SCPE_OK;
} }

View file

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

View file

@ -23,6 +23,7 @@
be used in advertising or otherwise to promote the sale, use or other dealings 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. 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 13-Jul-01 RMS Fixed RIM loader format
27-May-01 RMS Added multiconsole support 27-May-01 RMS Added multiconsole support
14-Mar-01 RMS Revised load/dump interface (again) 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_PC pointer to saved PC register descriptor
sim_emax number of words for examine sim_emax number of words for examine
sim_devices array of pointers to simulated devices 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_stop_messages array of pointers to stop messages
sim_load binary loader sim_load binary loader
*/ */
@ -67,8 +67,6 @@ DEVICE *sim_devices[] = { &cpu_dev,
&ptr_dev, &ptp_dev, &tti_dev, &tto_dev, &ptr_dev, &ptp_dev, &tti_dev, &tto_dev,
&lpt_dev, NULL }; &lpt_dev, NULL };
UNIT *sim_consoles = NULL;
const char *sim_stop_messages[] = { const char *sim_stop_messages[] = {
"Unknown error", "Unknown error",
"Undefined instruction", "Undefined instruction",

View file

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

View file

@ -25,6 +25,7 @@
cpu central processor cpu central processor
16-Sep-01 RMS Fixed bug in reset routine, added KL8A support
10-Aug-01 RMS Removed register from declarations 10-Aug-01 RMS Removed register from declarations
17-Jul-01 RMS Moved function prototype 17-Jul-01 RMS Moved function prototype
07-Jun-01 RMS Fixed bug in JMS to non-existent memory 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 ptp (int32 pulse, int32 AC);
extern int32 clk (int32 pulse, int32 AC); extern int32 clk (int32 pulse, int32 AC);
extern int32 lpt (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 rk (int32 pulse, int32 AC);
extern int32 rx (int32 pulse, int32 AC); extern int32 rx (int32 pulse, int32 AC);
extern int32 df60 (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 */ case 013: /* CLK */
iot_data = clk (pulse, iot_data); iot_data = clk (pulse, iot_data);
break; 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 */ case 060: /* DF32/RF08 */
if (dev_enb & INT_DF) iot_data = df60 (pulse, iot_data); if (dev_enb & INT_DF) iot_data = df60 (pulse, iot_data);
else if (dev_enb & INT_RF) iot_data = rf60 (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) t_stat cpu_reset (DEVICE *dptr)
{ {
int_req = (int_req & ~INT_ION) | INT_NO_CIF_PENDING; 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; UF = UB = gtf = emode = 0;
return cpu_svc (&cpu_unit); 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 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. 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 18-Mar-01 RMS Added DF32 support
15-Feb-01 RMS Added DECtape support 15-Feb-01 RMS Added DECtape support
14-Apr-99 RMS Changed t_addr to unsigned 14-Apr-99 RMS Changed t_addr to unsigned
@ -73,6 +74,9 @@
Because the PDP-8 does not have priority interrupts, the order Because the PDP-8 does not have priority interrupts, the order
of devices within groups does not matter. 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 */ #define INT_V_START 0 /* enable start */
@ -82,7 +86,15 @@
#define INT_V_TTO (INT_V_START+3) /* terminal */ #define INT_V_TTO (INT_V_START+3) /* terminal */
#define INT_V_TTI (INT_V_START+4) /* keyboard */ #define INT_V_TTI (INT_V_START+4) /* keyboard */
#define INT_V_CLK (INT_V_START+5) /* clock */ #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_RX (INT_V_DIRECT+0) /* RX8E */
#define INT_V_RK (INT_V_DIRECT+1) /* RK8E */ #define INT_V_RK (INT_V_DIRECT+1) /* RK8E */
#define INT_V_RF (INT_V_DIRECT+2) /* RF08 */ #define INT_V_RF (INT_V_DIRECT+2) /* RF08 */
@ -102,6 +114,14 @@
#define INT_TTO (1 << INT_V_TTO) #define INT_TTO (1 << INT_V_TTO)
#define INT_TTI (1 << INT_V_TTI) #define INT_TTI (1 << INT_V_TTI)
#define INT_CLK (1 << INT_V_CLK) #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_RX (1 << INT_V_RX)
#define INT_RK (1 << INT_V_RK) #define INT_RK (1 << INT_V_RK)
#define INT_RF (1 << INT_V_RF) #define INT_RF (1 << INT_V_RF)

View file

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

View file

@ -23,6 +23,8 @@
be used in advertising or otherwise to promote the sale, use or other dealings 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. 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 27-May-01 RMS Added multiconsole support
18-Mar-01 RMS Added DF32 support 18-Mar-01 RMS Added DF32 support
14-Mar-01 RMS Added extension detection of RIM binary tapes 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 rk_dev, rx_dev;
extern DEVICE df_dev, rf_dev; extern DEVICE df_dev, rf_dev;
extern DEVICE dt_dev, mt_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 REG cpu_reg[];
extern uint16 M[]; extern uint16 M[];
extern int32 sim_switches; extern int32 sim_switches;
@ -69,14 +75,16 @@ DEVICE *sim_devices[] = {
&cpu_dev, &cpu_dev,
&ptr_dev, &ptp_dev, &ptr_dev, &ptp_dev,
&tti_dev, &tto_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, &clk_dev, &lpt_dev,
&rk_dev, &rx_dev, &rk_dev, &rx_dev,
&df_dev, &rf_dev, &df_dev, &rf_dev,
&dt_dev, &mt_dev, &dt_dev, &mt_dev,
NULL }; NULL };
UNIT *sim_consoles = NULL;
const char *sim_stop_messages[] = { const char *sim_stop_messages[] = {
"Unknown error", "Unknown error",
"Unimplemented instruction", "Unimplemented instruction",
@ -333,6 +341,7 @@ return sp;
#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x) #define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x)
#define SIXTOASC(x) (((x) >= 040)? (x): (x) + 0100) #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, t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
UNIT *uptr, int32 sw) 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 >> 6) & 077));
fprintf (of, "%c", SIXTOASC (inst & 077)); fprintf (of, "%c", SIXTOASC (inst & 077));
return SCPE_OK; } 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; if (!(sw & SWMASK ('M'))) return SCPE_ARG;
/* Instruction decode */ /* Instruction decode */
@ -423,6 +436,11 @@ if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* sixbit string? */
val[0] = (((t_value) cptr[0] & 077) << 6) | val[0] = (((t_value) cptr[0] & 077) << 6) |
((t_value) cptr[1] & 077); ((t_value) cptr[1] & 077);
return SCPE_OK; } 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 */ /* Instruction parse */

View file

@ -24,6 +24,8 @@
in this Software without prior written authorization from Robert M Supnik. in this Software without prior written authorization from Robert M Supnik.
tti,tto KL8E terminal input/output tti,tto KL8E terminal input/output
07-Sep-01 RMS Moved function prototypes
*/ */
#include "pdp8_defs.h" #include "pdp8_defs.h"
@ -36,8 +38,6 @@ t_stat tti_svc (UNIT *uptr);
t_stat tto_svc (UNIT *uptr); t_stat tto_svc (UNIT *uptr);
t_stat tti_reset (DEVICE *dptr); t_stat tti_reset (DEVICE *dptr);
t_stat tto_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 /* 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 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. 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 18-Jul-01 RMS Minor changes for Macintosh port
12-Jun-01 RMS Fixed bug in big-endian I/O (found by Dave Conroy) 12-Jun-01 RMS Fixed bug in big-endian I/O (found by Dave Conroy)
27-May-01 RMS Added multiple console support 27-May-01 RMS Added multiple console support
@ -56,8 +63,8 @@
13-Apr-95 RMS Added symbolic printouts 13-Apr-95 RMS Added symbolic printouts
*/ */
#define SCP 1 /* defining module */
#include "sim_defs.h" #include "sim_defs.h"
#include "sim_rev.h"
#include <signal.h> #include <signal.h>
#include <ctype.h> #include <ctype.h>
#define EX_D 0 /* deposit */ #define EX_D 0 /* deposit */
@ -87,7 +94,6 @@
extern char sim_name[]; extern char sim_name[];
extern DEVICE *sim_devices[]; extern DEVICE *sim_devices[];
extern UNIT *sim_consoles[];
extern REG *sim_PC; extern REG *sim_PC;
extern char *sim_stop_messages[]; extern char *sim_stop_messages[];
extern t_stat sim_instr (void); 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_D(dp) (size_map[((dp) -> dwidth + CHAR_BIT - 1) / CHAR_BIT])
#define SZ_R(rp) \ #define SZ_R(rp) \
(size_map[((rp) -> width + (rp) -> offset + CHAR_BIT - 1) / CHAR_BIT]) (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) \ #define SZ_LOAD(sz,v,mb,j) \
if (sz == sizeof (uint8)) v = *(((uint8 *) mb) + j); \ if (sz == sizeof (uint8)) v = *(((uint8 *) mb) + j); \
else if (sz == sizeof (uint16)) v = *(((uint16 *) mb) + j); \ else if (sz == sizeof (uint16)) v = *(((uint16 *) mb) + j); \
else if (sz == sizeof (uint32)) v = *(((uint32 *) 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) \ #define SZ_STORE(sz,v,mb,j) \
if (sz == sizeof (uint8)) *(((uint8 *) mb) + j) = (uint8) v; \ if (sz == sizeof (uint8)) *(((uint8 *) mb) + j) = (uint8) v; \
else if (sz == sizeof (uint16)) *(((uint16 *) mb) + j) = (uint16) v; \ else if (sz == sizeof (uint16)) *(((uint16 *) mb) + j) = (uint16) v; \
else if (sz == sizeof (uint32)) *(((uint32 *) mb) + j) = (uint32) v; \ else if (sz == sizeof (uint32)) *(((uint32 *) mb) + j) = (uint32) v; \
else *(((uint64 *) mb) + j) = v; else *(((t_uint64 *) mb) + j) = v;
#else #else
#define SZ_LOAD(sz,v,mb,j) \ #define SZ_LOAD(sz,v,mb,j) \
if (sz == sizeof (uint8)) v = *(((uint8 *) 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_value strtotv (char *inptr, char **endptr, int radix);
t_stat fprint_val (FILE *stream, t_value val, int rdx, int wid, int fmt); t_stat fprint_val (FILE *stream, t_value val, int rdx, int wid, int fmt);
void fprint_stopped (FILE *stream, t_stat r); void fprint_stopped (FILE *stream, t_stat r);
void sim_chkcons (void);
char *read_line (char *ptr, int size, FILE *stream); char *read_line (char *ptr, int size, FILE *stream);
DEVICE *find_dev (char *ptr); DEVICE *find_dev (char *ptr);
DEVICE *find_unit (char *ptr, int32 *iptr); DEVICE *find_unit (char *ptr, int32 *iptr);
DEVICE *find_dev_from_unit (UNIT *uptr); DEVICE *find_dev_from_unit (UNIT *uptr);
REG *find_reg (char *ptr, char **optr, DEVICE *dptr); REG *find_reg (char *ptr, char **optr, DEVICE *dptr);
t_bool qdisable (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 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 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); 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); SCHTAB *get_search (char *cptr, DEVICE *dptr, SCHTAB *schptr);
int test_search (t_value val, SCHTAB *schptr); int test_search (t_value val, SCHTAB *schptr);
t_stat step_svc (UNIT *ptr); t_stat step_svc (UNIT *ptr);
t_stat show_version (FILE *st, int flag);
UNIT step_unit = { UDATA (&step_svc, 0, 0) }; UNIT step_unit = { UDATA (&step_svc, 0, 0) };
const char save_vercur[] = "V2.6"; const char save_vercur[] = "V2.6";
@ -217,8 +223,8 @@ const char *scp_error_messages[] = {
const size_t size_map[] = { sizeof (int8), const size_t size_map[] = { sizeof (int8),
sizeof (int8), sizeof (int16), sizeof (int32), sizeof (int32) sizeof (int8), sizeof (int16), sizeof (int32), sizeof (int32)
#if defined (int64) #if defined (t_int64)
, sizeof (int64), sizeof (int64), sizeof (int64), sizeof (int64) , sizeof (t_int64), sizeof (t_int64), sizeof (t_int64), sizeof (t_int64)
#endif #endif
}; };
@ -231,7 +237,7 @@ const t_value width_mask[] = { 0,
0x1FFFFF, 0x3FFFFF, 0x7FFFFF, 0xFFFFFF, 0x1FFFFF, 0x3FFFFF, 0x7FFFFF, 0xFFFFFF,
0x1FFFFFF, 0x3FFFFFF, 0x7FFFFFF, 0xFFFFFFF, 0x1FFFFFF, 0x3FFFFFF, 0x7FFFFFF, 0xFFFFFFF,
0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF
#if defined (int64) #if defined (t_int64)
, 0x1FFFFFFFF, 0x3FFFFFFFF, 0x7FFFFFFFF, 0xFFFFFFFFF, , 0x1FFFFFFFF, 0x3FFFFFFFF, 0x7FFFFFFFF, 0xFFFFFFFFF,
0x1FFFFFFFFF, 0x3FFFFFFFFF, 0x7FFFFFFFFF, 0xFFFFFFFFFF, 0x1FFFFFFFFF, 0x3FFFFFFFFF, 0x7FFFFFFFFF, 0xFFFFFFFFFF,
0x1FFFFFFFFFF, 0x3FFFFFFFFFF, 0x7FFFFFFFFFF, 0xFFFFFFFFFFF, 0x1FFFFFFFFFF, 0x3FFFFFFFFFF, 0x7FFFFFFFFFF, 0xFFFFFFFFFFF,
@ -312,7 +318,8 @@ if ((stat = ttinit ()) != SCPE_OK) {
printf ("Fatal terminal initialization error\n%s\n", printf ("Fatal terminal initialization error\n%s\n",
scp_error_messages[stat - SCPE_BASE]); scp_error_messages[stat - SCPE_BASE]);
return 0; } return 0; }
printf ("\n%s simulator V2.6b\n", sim_name); printf ("\n");
show_version (stdout, 0);
end_test.i = 1; /* test endian-ness */ end_test.i = 1; /* test endian-ness */
sim_end = end_test.c[0]; sim_end = end_test.c[0];
stop_cpu = 0; stop_cpu = 0;
@ -363,7 +370,7 @@ do { printf ("sim> "); /* prompt */
scp_error_messages[stat - SCPE_BASE]); } scp_error_messages[stat - SCPE_BASE]); }
} while (stat != SCPE_EXIT); } while (stat != SCPE_EXIT);
detach_all (0); /* close files */ detach_all (0, TRUE); /* close files */
nolog_cmd (0, NULL); /* close log */ nolog_cmd (0, NULL); /* close log */
ttclose (); /* close console */ ttclose (); /* close console */
return 0; 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, "set <unit> <val> set unit parameter\n");
fprintf (st, "show <device> show device parameters\n"); fprintf (st, "show <device> show device parameters\n");
fprintf (st, "sh{ow} c{onfiguration} show configuration\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} m{odifiers} show modifiers\n");
fprintf (st, "sh{ow} q{ueue} show event queue\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} 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, "en{able} <device> enable device\n");
fprintf (st, "di{sable} <device> disable device\n"); fprintf (st, "di{sable} <device> disable device\n");
fprintf (st, "ad{d} <unit> add unit to configuration\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 */ cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
dptr = find_unit (gbuf, &unitno); /* find dev+unit */ dptr = find_unit (gbuf, &unitno); /* find dev+unit */
if ((dptr == NULL) || (dptr -> units == NULL) || 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 */ cptr = get_glyph (cptr, gbuf, 0); /* get glyph */
if (*cptr != 0) return SCPE_ARG; /* now eol? */
uptr = dptr -> units + unitno; uptr = dptr -> units + unitno;
if (uptr -> flags & UNIT_DIS) return SCPE_UDIS; /* disabled? */ if (uptr -> flags & UNIT_DIS) return SCPE_UDIS; /* disabled? */
for (i = 0; set_table[i].name != NULL; i++) { /* check globals */ for (i = 0; set_table[i].name != NULL; i++) { /* check globals */
if (MATCH_CMD (gbuf, set_table[i].name) == 0) if (MATCH_CMD (gbuf, set_table[i].name) == 0) {
return set_table[i].action (dptr, set_table[i].arg); } 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? */ if (dptr -> modifiers == NULL) return SCPE_NOPARAM; /* any modifiers? */
for (mptr = dptr -> modifiers; mptr -> mask != 0; mptr++) { for (mptr = dptr -> modifiers; mptr -> mask != 0; mptr++) {
if ((mptr -> mstring != NULL) && if ((mptr -> mstring != NULL) &&
(MATCH_CMD (gbuf, mptr -> mstring) == 0)) { (MATCH_CMD (gbuf, mptr -> mstring) == 0)) {
if (*cptr != 0) return SCPE_ARG; /* now eol? */
if ((mptr -> valid != NULL) && if ((mptr -> valid != NULL) &&
((r = mptr -> valid (uptr, mptr -> match)) != SCPE_OK)) ((r = mptr -> valid (uptr, mptr -> match)) != SCPE_OK))
return r; /* invalid? */ return r; /* invalid? */
uptr -> flags = (uptr -> flags & ~(mptr -> mask)) | 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_OK; } }
return SCPE_ARG; /* no match */ return SCPE_ARG; /* no match */
} }
@ -491,6 +501,7 @@ static CTAB show_table[] = {
{ "QUEUE", &show_queue, 0 }, { "QUEUE", &show_queue, 0 },
{ "TIME", &show_time, 0 }, { "TIME", &show_time, 0 },
{ "MODIFIERS", &show_modifiers, 0 }, { "MODIFIERS", &show_modifiers, 0 },
{ "VERSION", &show_version, 0 },
{ NULL, NULL, 0 } }; { NULL, NULL, 0 } };
GET_SWITCHES (cptr, gbuf); /* test for switches */ 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 (uptr -> flags & UNIT_DIS) continue;
if (ucnt > 1) fprintf (st, " unit %d", j); if (ucnt > 1) fprintf (st, " unit %d", j);
if (uptr -> flags & UNIT_FIX) { if (uptr -> flags & UNIT_FIX) {
if (uptr -> capac < kval) if (uptr -> capac < kval)
fprintf (st, ", %d%s", uptr -> capac, fprintf (st, ", %d%s", uptr -> capac,
((dptr -> dwidth / dptr -> aincr) > 8)? "W": "B"); ((dptr -> dwidth / dptr -> aincr) > 8)? "W": "B");
else fprintf (st, ", %dK%s", uptr -> capac / kval, else fprintf (st, ", %dK%s", uptr -> capac / kval,
((dptr -> dwidth / dptr -> aincr) > 8)? "W": "B"); } ((dptr -> dwidth / dptr -> aincr) > 8)? "W": "B"); }
if (uptr -> flags & UNIT_ATT) 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) else if (uptr -> flags & UNIT_ATTABLE)
fprintf (st, ", not attached"); fprintf (st, ", not attached");
if (dptr -> modifiers != NULL) { if (dptr -> modifiers != NULL) {
for (mptr = dptr -> modifiers; mptr -> mask != 0; mptr++) { for (mptr = dptr -> modifiers; mptr -> mask != 0; mptr++) {
if ((mptr -> pstring != NULL) && if ((mptr -> pstring != NULL) &&
((uptr -> flags & mptr -> mask) == mptr -> match)) ((uptr -> flags & mptr -> mask) == mptr -> match)) {
fprintf (st, ", %s", mptr -> pstring); } } fprintf (st, ", %s", mptr -> pstring);
if ((mptr -> mstring == NULL) && mptr -> valid)
mptr -> valid (uptr, st); } } }
fprintf (st, "\n"); } fprintf (st, "\n"); }
return SCPE_OK; 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) t_stat show_config (FILE *st, int flag)
{ {
int32 i; int32 i;
@ -890,7 +911,7 @@ GET_SWITCHES (cptr, gbuf); /* test for switches */
if (*cptr == 0) return SCPE_ARG; if (*cptr == 0) return SCPE_ARG;
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */ cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
if (*cptr != 0) return SCPE_ARG; 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# */ dptr = find_unit (gbuf, &unitno); /* locate dev+unit# */
if ((dptr == NULL) || (dptr -> units == NULL)) return SCPE_ARG; if ((dptr == NULL) || (dptr -> units == NULL)) return SCPE_ARG;
uptr = (dptr -> units) + unitno; uptr = (dptr -> units) + unitno;
@ -903,11 +924,12 @@ return detach_unit (uptr);
Inputs: Inputs:
start = number of starting device start = number of starting device
shutdown = TRUE if simulator shutting down
Outputs: Outputs:
status = error status status = error status
*/ */
t_stat detach_all (int start) t_stat detach_all (int32 start, t_bool shutdown)
{ {
int32 i, j; int32 i, j;
t_stat reason; 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 (i = start; (dptr = sim_devices[i]) != NULL; i++) {
for (j = 0; j < dptr -> numunits; j++) { for (j = 0; j < dptr -> numunits; j++) {
uptr = (dptr -> units) + j; uptr = (dptr -> units) + j;
if (dptr -> detach != NULL) reason = dptr -> detach (uptr); if ((uptr -> flags & UNIT_ATTABLE) || shutdown) {
else reason = detach_unit (uptr); if (dptr -> detach != NULL) reason = dptr -> detach (uptr);
if (reason != SCPE_OK) return reason; } } else reason = detach_unit (uptr);
if (reason != SCPE_OK) return reason; } } }
return SCPE_OK; return SCPE_OK;
} }
@ -1201,8 +1224,8 @@ if (flag == RU_BOOT) { /* boot */
(dptr -> boot == NULL)) return SCPE_ARG; (dptr -> boot == NULL)) return SCPE_ARG;
uptr = dptr -> units + unitno; uptr = dptr -> units + unitno;
if (uptr -> flags & UNIT_DIS) return SCPE_ARG; /* disabled? */ if (uptr -> flags & UNIT_DIS) return SCPE_ARG; /* disabled? */
if (!(uptr -> flags & UNIT_ATTABLE)) return SCPE_NOATT; if ((uptr -> flags & UNIT_ATTABLE) &&
if (!(uptr -> flags & UNIT_ATT)) return SCPE_UNATT; !(uptr -> flags & UNIT_ATT)) return SCPE_UNATT;
if ((r = dptr -> boot (unitno)) != SCPE_OK) return r; } if ((r = dptr -> boot (unitno)) != SCPE_OK) return r; }
if (*cptr != 0) return SCPE_ARG; if (*cptr != 0) return SCPE_ARG;
@ -1227,7 +1250,6 @@ if (ttrunstate () != SCPE_OK) { /* set console */
return SCPE_TTYERR; } return SCPE_TTYERR; }
if (step) sim_activate (&step_unit, step); /* set step timer */ if (step) sim_activate (&step_unit, step); /* set step timer */
sim_is_running = 1; /* flag running */ sim_is_running = 1; /* flag running */
sim_chkcons (); /* check console buffer */
r = sim_instr(); r = sim_instr();
sim_is_running = 0; /* flag idle */ sim_is_running = 0; /* flag idle */
@ -1400,7 +1422,7 @@ for (gptr = gbuf, reason = SCPE_OK;
continue; } continue; }
tptr = get_range (gptr, &low, &high, dptr -> aradix, 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); uptr -> capac - dptr -> aincr), 0);
if (tptr == NULL) return SCPE_ARG; if (tptr == NULL) return SCPE_ARG;
if (*tptr && (*tptr++ != ',')) 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); val = *(((uint8 *) rptr -> loc) + idx);
else if ((rptr -> depth > 1) && (sz == sizeof (uint16))) else if ((rptr -> depth > 1) && (sz == sizeof (uint16)))
val = *(((uint16 *) rptr -> loc) + idx); val = *(((uint16 *) rptr -> loc) + idx);
#if !defined (int64) #if !defined (t_int64)
else val = *(((uint32 *) rptr -> loc) + idx); else val = *(((uint32 *) rptr -> loc) + idx);
#else #else
else if (sz <= sizeof (uint32)) else if (sz <= sizeof (uint32))
val = *(((uint32 *) rptr -> loc) + idx); val = *(((uint32 *) rptr -> loc) + idx);
else val = *(((uint64 *) rptr -> loc) + idx); else val = *(((t_uint64 *) rptr -> loc) + idx);
#endif #endif
val = (val >> rptr -> offset) & width_mask[rptr -> width]; val = (val >> rptr -> offset) & width_mask[rptr -> width];
return val; return val;
@ -1589,12 +1611,12 @@ if ((rptr -> depth > 1) && (sz == sizeof (uint8)))
PUT_RVAL (uint8, rptr, idx, (uint32) val, (uint32) mask); PUT_RVAL (uint8, rptr, idx, (uint32) val, (uint32) mask);
else if ((rptr -> depth > 1) && (sz == sizeof (uint16))) else if ((rptr -> depth > 1) && (sz == sizeof (uint16)))
PUT_RVAL (uint16, rptr, idx, (uint32) val, (uint32) mask); 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 PUT_RVAL (uint32, rptr, idx, val, mask);
#else #else
else if (sz <= sizeof (uint32)) else if (sz <= sizeof (uint32))
PUT_RVAL (uint32, rptr, idx, (int32) val, (uint32) mask); 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 #endif
return; return;
} }
@ -2182,6 +2204,7 @@ return SCPE_OK;
sim_is_active see if entry is on event queue sim_is_active see if entry is on event queue
sim_atime return absolute time for an entry sim_atime return absolute time for an entry
sim_gtime return global time sim_gtime return global time
sim_qcount return event queue entry count
Asynchronous events are set up by queueing a unit data structure Asynchronous events are set up by queueing a unit data structure
to the event queue with a timeout (in simulator units, relative 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); } else { UPDATE_SIM_TIME (sim_clock_queue -> time); }
return sim_rtime; 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 /* Endian independent binary I/O package
@ -2456,77 +2496,4 @@ rtc_currdelay = (int32) (((double) rtc_basedelay * (double) rtc_nextintv) /
1000.0); /* next delay */ 1000.0); /* next delay */
return rtc_currdelay; 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 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. 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, 20-Jul-01 RMS Added Macintosh support (from Louis Chretien, Peter Schorn,
and Ben Supnik) and Ben Supnik)
15-May-01 RMS Added logging support 15-May-01 RMS Added logging support
@ -50,7 +52,6 @@
The POSIX UNIX version works with LINUX. The POSIX UNIX version works with LINUX.
*/ */
#undef USE_INT64 /* hack for Windows */
#include "sim_defs.h" #include "sim_defs.h"
int32 sim_int_char = 005; /* interrupt character */ int32 sim_int_char = 005; /* interrupt character */
extern FILE *sim_log; extern FILE *sim_log;
@ -190,7 +191,7 @@ return quo;
/* Win32 routines */ /* Win32 routines */
#if defined (WIN32) #if defined (_WIN32)
#define __TTYROUTINES 0 #define __TTYROUTINES 0
#include <conio.h> #include <conio.h>
#include <windows.h> #include <windows.h>
@ -326,6 +327,7 @@ return 0;
#include <sioux.h> #include <sioux.h>
#include <siouxglobals.h> #include <siouxglobals.h>
#include <Traps.h> #include <Traps.h>
#include <LowMem.h>
extern char sim_name[]; extern char sim_name[];
extern pSIOUXWin SIOUXTextWindow; extern pSIOUXWin SIOUXTextWindow;
@ -339,7 +341,11 @@ static void updateCursor(void) {
Point localMouse; Point localMouse;
GetPort(&savePort); GetPort(&savePort);
SetPort(window); SetPort(window);
#if !TARGET_API_MAC_CARBON
localMouse = LMGetMouseLocation();
#else
GetGlobalMouse(&localMouse); GetGlobalMouse(&localMouse);
#endif
GlobalToLocal(&localMouse); GlobalToLocal(&localMouse);
if (PtInRect(localMouse, &(*SIOUXTextWindow->edit)->viewRect) && iBeamCursorH) { if (PtInRect(localMouse, &(*SIOUXTextWindow->edit)->viewRect) && iBeamCursorH) {
SetCursor(*iBeamCursorH); SetCursor(*iBeamCursorH);

View file

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

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 To: Users
From: Bob Supnik From: Bob Supnik
Subj: Simulator Usage, V2.6b Subj: Simulator Usage, V2.7
Date: 15-Sep-01 Date: 30-Sep-01
COPYRIGHT NOTICE 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 To compile the simulators on VMS, use these commands (note that separate
compilations are required for each of the 18b PDP's): compilations are required for each of the 18b PDP's):
$ cc pdp8_*.c,scp.c,scp_tty.c ! PDP-8 $ cc pdp8_*.c,scp.c,scp_tty.c,sim_*.c ! PDP-8
$ link/exec=pdp8 pdp8_*.obj,scp.obj,scp_tty.obj $ link/exec=pdp8 pdp8_*.obj,scp.obj,scp_tty.obj,sim_*.obj
$ cc pdp11_*.c,scp.c,scp_tty.c ! PDP-11 $ cc pdp11_*.c,scp.c,scp_tty.c,sim_*.c ! PDP-11
$ link/exec=pdp11 pdp11_*.obj,scp.obj,scp_tty.obj $ link/exec=pdp11 pdp11_*.obj,scp.obj,scp_tty.obj,sim_*.obj
$ cc nova_*.c,scp.c,scp_tty.c ! Nova $ cc nova_*.c,scp.c,scp_tty.c,sim_*.c ! Nova
$ link/exec=nova nova_*.obj,scp.obj,scp_tty.obj $ 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 $ link/exec=pdp1 pdp1_*.obj,scp.obj,scp_tty.obj
$ cc/define=PDP{4,7,9,15} pdp18b_*.c,scp.c,scp_tty.c $ 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 $ 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 $ 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 $ 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 $ 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 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. 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 the following commands (note that separate compilations are required for
each of the 18b PDP's): each of the 18b PDP's):
% cc pdp8_*.c scp*.c -lm -o pdp8 % cc pdp8_*.c scp*.c sim_*.c -lm -o pdp8
% cc pdp11_*.c scp*.c -lm -o pdp11 % cc pdp11_*.c scp*.c sim_*.c -lm -o pdp11
% cc nova_*.c scp*.c -lm -o nova % cc nova_*.c scp*.c sim_*.c -lm -o nova
% cc pdp1_*.c scp*.c -o pdp1 % 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 i1401_*.c scp*.c -o i1401
% cc hp2100_*.c scp*.c -o hp2100 % cc hp2100_*.c scp*.c -o hp2100
% cc id4_*.c scp*.c -o id4 % 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 These commands should work with most UNIX variants. If your UNIX only
supports the old BSD terminal interface, add -DBSDTTY to each command. 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 simulator control package (SCP). To turn on 64b support, add the symbol
USE_INT64 to the command line: 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 Since 64b integer declarations vary, sim_defs.h has conditional
declarations for Windows (_int64) and Digital UNIX (long). The default 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++ each simulator must be set up as a separate project. Under the VC++
file menu, select New, select Project Workspace, select Console file menu, select New, select Project Workspace, select Console
Application, and type in the name of the simulator. In the project 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 files view, select Add Files To Project and add in the required files:
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, - all simulators: sim_defs.h, sim_rev.h, scp.c, scp_tty
also add in scp_sock.h and scp_sock.c. If the project requires a - all simulators: simulator specific files (e.g., all
command line switch, add the switches to the C/C++ tab of the files beginning with nova_* for the Nova)
Configuration dialog. The simulator should then build properly. - 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 To start the simulator, simply type its name. The simulator takes
one optional argument, a startup command file. If specified, this one optional argument, a startup command file. If specified, this
@ -136,6 +148,7 @@ for example, disk sizes.
% i1401 <startup file>(cr) or % i1401 <startup file>(cr) or
% hp2100 <startup file>(cr) or % hp2100 <startup file>(cr) or
% id4 <startup file>(cr) or % id4 <startup file>(cr) or
% h316 <startup file>(cr) or
% pdp10 <startup file>(cr) % pdp10 <startup file>(cr)
The simulator types out its name and version, executes the commands 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 If the file does not exist, it is created, and an appropriate message
is printed. 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 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 ALL(cr) -- detach all units
sim> DETACH <device><unit number>(cr) -- detach specified unit 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 - KM8E memory management and timeshare control
PTR,PTP PC8E paper tape reader/punch PTR,PTP PC8E paper tape reader/punch
TTI,TTO KL8E console terminal TTI,TTO KL8E console terminal
TTI1-4,TTO1-4 KL8JA additional terminals
LPT LE8E line printer LPT LE8E line printer
CLK DK8E line frequency clock (also PDP-8/A compatible) CLK DK8E line frequency clock (also PDP-8/A compatible)
RK RK8E/RK05 cartridge disk controller with four drives 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) 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 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. 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) 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: implements these registers:
name size comments 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 The real-time clock autocalibrates; the clock interval is adjusted up or
down so that the clock tracks actual elapsed time. 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) 4.3 RK8E Cartridge Disk (RK)
RK8E options include the ability to make units write enabled or write locked: 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 -a display as ASCII character
-c display as (sixbit) character string -c display as (sixbit) character string
-t display as (TSS/8 sixbit) character string
-m display instruction mnemonics -m display instruction mnemonics
Input parsing is controlled by the first character typed in or by command Input parsing is controlled by the first character typed in or by command
@ -930,6 +999,7 @@ line switches:
' or -a ASCII character ' or -a ASCII character
" or -c two character sixbit string " or -c two character sixbit string
# or -t two character TSS/8 sixbit string
alphabetic instruction mnemonic alphabetic instruction mnemonic
numeric octal number numeric octal number
@ -985,6 +1055,7 @@ PTR,PTP PC11 paper tape reader/punch
TTI,TTO DL11 console terminal TTI,TTO DL11 console terminal
LPT LP11 line printer LPT LP11 line printer
CLK line frequency clock CLK line frequency clock
DZ DZ11 8-line terminal multiplexor
RK RK11/RK05 cartridge disk controller with eight drives RK RK11/RK05 cartridge disk controller with eight drives
RL RLV12/RL01(2) cartridge disk controller with four drives RL RLV12/RL01(2) cartridge disk controller with four drives
RP RM02/03/05/80, RP04/05/06/07 Massbus style controller 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 TM TM11/TU10 magnetic tape controller with eight drives
TS TS11/TSV05 magnetic tape controller with one drive 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 The DZ, RK, RL, RP, RX, TC, TM, and TS devices can be DISABLEd. The PDP-11
support either a TM11 or a TS11, but not both, since they use the same I/O can support either a TM11 or a TS11, but not both, since they use the same
addresses. The simulator defaults to the TM11. To change the magtape, I/O addresses. The simulator defaults to the TM11. To change the magtape,
ENABLE TM11 enable TM11 and disable TS11 ENABLE TM11 enable TM11 and disable TS11
ENABLE TS11 enable TS11 and disable TM11 ENABLE TS11 enable TS11 and disable TM11
@ -1164,7 +1235,7 @@ Error handling is as follows:
5.2.3 KL11 Terminal Input (TTI) 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: implements these registers:
name size comments name size comments
@ -1180,7 +1251,7 @@ implements these registers:
5.2.4 KL11 Terminal Output (TTO) 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: implements these registers:
name size comments 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 The real-time clock autocalibrates; the clock interval is adjusted up or
down so that the clock tracks actual elapsed time. 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) 5.3 RK11/RK05 Cartridge Disk (RK)
RK11 options include the ability to make units write enabled or write locked: 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 RP06 set size to RP06
SET RPn RP07 set size to RP07 SET RPn RP07 set size to RP07
SET RPn AUTOSIZE set size based on file size at attach 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 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 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 name size comments
RPCS1 16 control/status 1 RPCS1 16 control/status 1
RPCS2 16 control/status 2
RPCS3 16 control/status 3
RPWC 16 word count RPWC 16 word count
RPBA 16 bus address RPBA 16 bus address
RPBAE 6 bus address extension
RPDA 16 desired surface, sector RPDA 16 desired surface, sector
RPDC 8 desired cylinder RPCS2 16 control/status 2
RPOF 16 offset RPOF 16 offset
RPDS0..7 16 drive status, drives 0-7 RPDC 8 desired cylinder
RPDE0..7 16 drive error, drives 0-7
RPER2 16 error status 2 RPER2 16 error status 2
RPER3 16 error status 3 RPER3 16 error status 3
RPDB 16 data buffer RPEC1 16 ECC syndrome 1
RPEC2 16 ECC syndrome 2
RPMR 16 maintenance register 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 INT 1 interrupt pending flag
SC 1 special condition (CSR1<15>) SC 1 special condition (CSR1<15>)
DONE 1 device done flag (CSR1<7>) DONE 1 device done flag (CSR1<7>)
IE 1 interrupt enable flag (CSR1<6>) IE 1 interrupt enable flag (CSR1<6>)
STIME 24 seek time, per cylinder STIME 24 seek time, per cylinder
RTIME 24 rotational delay 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 STOP_IOE 1 stop on I/O error
Error handling is as follows: Error handling is as follows:
@ -1568,6 +1681,7 @@ The magnetic tape controller implements these registers:
WADH 16 write char packet high address WADH 16 write char packet high address
WLNT 16 write char packet length WLNT 16 write char packet length
WOPT 16 write char packet options WOPT 16 write char packet options
WXOPT 16 write char packet extended options
ATTN 1 attention message pending ATTN 1 attention message pending
BOOT 1 boot request pending BOOT 1 boot request pending
OWNC 1 if set, tape owns command buffer OWNC 1 if set, tape owns command buffer
@ -1732,22 +1846,6 @@ control registers for the interrupt system.
6.2 Programmed I/O Devices 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) 6.2.1 Paper Tape Reader (PTR)
The paper tape reader (PTR) reads data from a disk file. The POS 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 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 The terminal input polls the console keyboard for input. Terminal
inactive terminal input cannot receive characters. Terminal input input options include the ability to set ANSI mode or limited Dasher
options include the ability to set limited Dasher compatibility mode compatibility mode:
or ANSI standard mode:
SET TTI ANSI normal mode SET TTI ANSI normal mode
SET TTI DASHER Dasher 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 Setting either TTI or TTO changes both devices. In Dasher mode, carriage
mode, carriage return is changed to newline on input, and ^X is changed return is changed to newline on input, and ^X is changed to backspace.
to backspace.
The terminal inputs implement these registers: The terminal input implements these registers:
name size comments name size comments
@ -1835,22 +1929,19 @@ The terminal inputs implement these registers:
POS 31 number of characters input POS 31 number of characters input
TIME 24 keyboard polling interval 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 The terminal output writes to the simulator console window. Terminal
terminal output buffers characters. Terminal output options include the output options include the the ability to set ANSI mode or limited
the ability to set limited Dasher compatibility mode or ANSI mode: Dasher compatibility mode:
SET TTI ANSI normal mode
SET TTI DASHER Dasher mode
SET TTO ANSI normal mode SET TTO ANSI normal mode
SET TTO DASHER Dasher mode SET TTO DASHER Dasher mode
Setting either TTI (TTI1) or TTO (TTO1) changes both devices. In Dasher Setting either TTI or TTO changes both devices. In Dasher mode, carriage
mode, carriage return is changed to newline on input, and ^X is changed return is changed to newline on input, and ^X is changed to backspace.
to backspace.
The terminal outputs implement these registers: The terminal output implements these registers:
name size comments name size comments
@ -1937,6 +2028,61 @@ Error handling is as follows:
OS I/O error x report error and stop 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) 6.3 Fixed Head Disk (DK)
The fixed head disk controller implements these registers: The fixed head disk controller implements these registers:
@ -2261,8 +2407,8 @@ Error handling is as follows:
7.2.3 Terminal Input (TTI) 7.2.3 Terminal Input (TTI)
The terminal input (TTO) reads from the controling console port. The terminal input (TTI) polls the console keyboard for input. It
It implements these registers: implements these registers:
name size comments name size comments
@ -2273,7 +2419,7 @@ It implements these registers:
7.2.4 Terminal Output (TTO) 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: It implements these registers:
name size comments name size comments
@ -2629,22 +2775,6 @@ the PDP-7 and PDP-9, 17b for the PDP-15).
8.2 Programmed I/O Devices 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) 8.2.1 Paper Tape Reader (PTR)
The paper tape reader (PTR) reads data from a disk file. The POS 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 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 The terminal input (TTI) polls the console keyboard for input. The
inactive terminal input cannot receive characters. The terminal inputs input side has one option, UC; when set, it automatically converts lower
have one option, UC; when set, it automatically converts lower case input case input to upper case.
to upper case.
The PDP-9 and PDP-15 operated the primary terminal (TTI/TTO), by default, 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 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 first terminal input has a second option, FDX; when set, it operates
the terminal input in full-duplex mode. The second terminal is always the terminal input in full-duplex mode. The second terminal is always
full duplex. full duplex.
The terminal inputs implement these registers: The terminal input implements these registers:
name size comments name size comments
@ -2730,14 +2859,13 @@ The terminal inputs implement these registers:
POS 31 number of characters input POS 31 number of characters input
TIME 24 keyboard polling interval 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 The terminal output (TTO) writes to the simulator console window. The
terminal output buffers characters. The terminal outputs have one option, terminal output has one option, UC; when set, it suppresses lower case
UC; when set, it suppresses lower case output (so that ALTMODE is not output (so that ALTMODE is not echoed as }).
echoed as }).
The terminal outputs implement these registers: The terminal output implements these registers:
name size comments 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 The real-time clock autocalibrates; the clock interval is adjusted up or
down so that the clock tracks actual elapsed time. 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) 8.3 RP15/RP02 Disk Pack (RP)
RP15 options include the ability to make units write enabled or write locked: 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) 9.4 1407 Inquiry Terminal (INQ)
The IBM 1407 inquiry terminal (INQ) is a half-duplex console. It polls The IBM 1407 inquiry terminal (INQ) is a half-duplex console. It polls
the controling keyboard of the simulator periodically for inquiry requests. the console keyboard periodically for inquiry requests. The inquiry
The inquiry terminal registers are: terminal registers are:
name size comments name size comments
@ -3725,11 +3898,11 @@ Error handling is as follows:
10.4.3 12631C Buffered Teleprinter (TTY) 10.4.3 12631C Buffered Teleprinter (TTY)
The console teleprinter has three units: keyboard (unit 0), printer The console teleprinter has three units: keyboard (unit 0), printer
(unit 1), and punch (unit 2). The keyboard reads from, and the (unit 1), and punch (unit 2). The keyboard reads from the console
printer writes to, the controlling console port. The punch writes keyboard; the printer writes to the simulator console window. The
to a disk file. The keyboard has one option, UC; when set, it punch writes to a disk file. The keyboard has one option, UC; when
automatically converts lower case input to upper case. This is on set, it automatically converts lower case input to upper case. This
by default. is on by default.
The terminal implements these registers: The terminal implements these registers:
@ -4076,9 +4249,10 @@ Error handling is as follows:
11.3 Teletype (TT) 11.3 Teletype (TT)
The teletype reads and writes to the controlling console port. The The teletype keyboard reads from the console keyboard; the teletype
keyboard has one option, UC; when set, it automatically converts lower printer writes to the simulator console window. The keyboard has
case input to upper case. This is on by default. one option, UC; when set, it automatically converts lower case
input to upper case. This is on by default.
name size comments name size comments
@ -4158,12 +4332,13 @@ UBA Unibus adapters (translation maps)
FE console FE console
TIM timer TIM timer
PTR,PTP PC11 paper tape reader/punch PTR,PTP PC11 paper tape reader/punch
DZ DZ11 8-line terminal multiplexor
LP20 LP20 line printer LP20 LP20 line printer
RP RH11/RP04/RP05/RP06/RP07/RM03/RM05/RM80 controller with RP RH11/RP04/RP05/RP06/RP07/RM03/RM05/RM80 controller with
eight drives eight drives
TU RH11/TM02/TU45 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: 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 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 The RP controller implements the Massbus 18b (RH11) direct interface for
large disk drives. It is more abstract than other device simulators, with 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 name size comments
RPCS1 16 control/status 1 RPCS1 16 control/status 1
RPCS2 16 control/status 2
RPCS3 16 control/status 3
RPWC 16 word count RPWC 16 word count
RPBA 16 bus address RPBA 16 bus address
RPBAE 6 bus address extension
RPDA 16 desired surface, sector RPDA 16 desired surface, sector
RPDC 8 desired cylinder RPCS2 16 control/status 2
RPOF 16 offset RPOF 16 offset
RPDS0..7 16 drive status, drives 0-7 RPDC 8 desired cylinder
RPDE0..7 16 drive error, drives 0-7
RPER2 16 error status 2 RPER2 16 error status 2
RPER3 16 error status 3 RPER3 16 error status 3
RPDB 16 data buffer RPEC1 16 ECC syndrome 1
RPEC2 16 ECC syndrome 2
RPMR 16 maintenance register RPMR 16 maintenance register
RPDB 16 data buffer
RPIFF 1 transfer complete interrupt request flop
INT 1 interrupt pending flag INT 1 interrupt pending flag
SC 1 special condition (CSR1<15>) SC 1 special condition (CSR1<15>)
DONE 1 device done flag (CSR1<7>) DONE 1 device done flag (CSR1<7>)
IE 1 interrupt enable flag (CSR1<6>) IE 1 interrupt enable flag (CSR1<6>)
STIME 24 seek time, per cylinder STIME 24 seek time, per cylinder
RTIME 24 rotational delay 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 STOP_IOE 1 stop on I/O error
Error handling is as follows: Error handling is as follows:
@ -4434,11 +4657,11 @@ Error handling is as follows:
OS I/O error x report error and stop 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 The magnetic tape simulator simulates an RH11 Massbus adapter with one
TM02 formatter and up to eight TU45. Magnetic tape options include the TM02 formatter and up to eight TU45 drives. Magnetic tape options include
ability to make units write enabled or locked. the ability to make units write enabled or locked.
SET TUn LOCKED set unit n write locked SET TUn LOCKED set unit n write locked
SET TUn ENABLED set unit n write enabled 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 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 The LP20 is a DMA-based line printer controller. There is one
line printer option to clear the vertical forms unit (VFU). 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 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 The PDP-10 simulator implements symbolic display and input. Display is
controlled by command line switches: controlled by command line switches:
@ -4701,9 +4924,10 @@ Error handling is as follows:
13.2.3 316/516-33 Console Teletype (TTY) 13.2.3 316/516-33 Console Teletype (TTY)
The terminal reads and writes to the controlling console port. It has The terminal reads from the console keyboard and writes to the
one option, UC; when set, it automatically converts lower case input simulator console window. The terminal has one option, UC; when
to upper case. This is on by default. set, the terminal automatically converts lower case input to upper
case. This is on by default.
The terminal these registers: 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 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 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 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. DECtape dumps to simulator format.
A known problem in DECtape format is that when a block is recorded in 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) 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 H316/516 simulator
Added Macintosh support from Louis Chrétien, Peter Schorn, Added Macintosh support from Louis Chrétien, Peter Schorn,
and Ben Supnik and Ben Supnik
Added bad block table option to PDP-11 RL, RP Added bad block table option to PDP-11 RL, RP
Removed register in declarations
Fixed bugs found by Peter Schorn Fixed bugs found by Peter Schorn
Endian error in PDP-10, PDP-11 RP -- endian error in PDP-10, PDP-11 RP
Space reverse error in PDP-11 TS -- space reverse error in PDP-11 TS
Symbolic input in 1401 -- symbolic input in 1401
Fixed bug in PDP-1 RIM loader found by Derek Peschel Fixed bug in PDP-1 RIM loader found by Derek Peschel
Fixed bug in Nova fixed head disk Fixed bug in Nova fixed head disk
Removed register in declarations
Rev 2.6a, Jun, 01 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 API option
Added PDP-9, PDP-15 second terminal Added PDP-9, PDP-15 second terminal
Added PDP-10 option for TOPS-20 V4.1 bug fix Added PDP-10 option for TOPS-20 V4.1 bug fix
@ -4961,6 +5204,14 @@ Rev 2.6a, Jun, 01
Added console logging Added console logging
Added multiple console support Added multiple console support
Added comment recognition 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 Rev 2.6, May, 01
Added ENABLE/DISABLE devices Added ENABLE/DISABLE devices
@ -4989,31 +5240,31 @@ Rev 2.6, May, 01
Updated copyright notices, fixed comments Updated copyright notices, fixed comments
Rev 2.5a, Dec, 00 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 CMD flop to HP paper tape and line printer
Added status input for HP paper tape punch and TTY 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 Fixed 1401 bugs found by Dutch Owens
-- 4, 7 char NOPs are legal -- 4, 7 char NOPs are legal
-- 1 char B is chained BCE -- 1 char B is chained BCE
-- MCE moves whole character, not digit, after first -- MCE moves whole character, not digit, after first
Added Dutch Owens' 1401 mag tape boot routine
Fixed Nova bugs found by Bruce Ray Fixed Nova bugs found by Bruce Ray
-- traps implemented on Nova 3 as well as Nova 4 -- traps implemented on Nova 3 as well as Nova 4
-- DIV and DIVS 0/0 set carry -- DIV and DIVS 0/0 set carry
-- RETN sets SP from FP at outset -- RETN sets SP from FP at outset
-- IORST does not clear carry -- IORST does not clear carry
-- Nova 4 implements two undocumented instructions -- 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 Fixed bugs in 18b PDP's
-- XCT indirect address calculation -- XCT indirect address calculation
-- missing index instructions in PDP-15 -- missing index instructions in PDP-15
-- bank mode handling 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 Rev 2.5, Nov, 00
Removed Digital and Compaq from copyrights, as Removed Digital and Compaq from copyrights, as
@ -5072,6 +5323,8 @@ Rev 2.3a, Nov, 97
Fixed endian dependence in 18b PDP RIM loader Fixed endian dependence in 18b PDP RIM loader
Rev 2.3, Mar, 97 Rev 2.3, Mar, 97
Added PDP-11 RP
Added PDP-1
Changed UNIX terminal I/O to TERMIOS Changed UNIX terminal I/O to TERMIOS
Changed magtape format to double ended Changed magtape format to double ended
Changed PDP-8 current page mnemonic from T to C 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 18b PDP paper tape reader
Fixed bug in PDP-4 console Fixed bug in PDP-4 console
Fixed bug in PDP-4,7 line printer Fixed bug in PDP-4,7 line printer
Added PDP-11 RP
Added PDP-1
Rev 2.2d, Dec, 96 Rev 2.2d, Dec, 96
Added ADD/REMOVE commands Added ADD/REMOVE commands
@ -5171,9 +5422,11 @@ Jay Jaeger IBM 1401 information
Doug Jones PDP-8 information, simulator, and software Doug Jones PDP-8 information, simulator, and software
Al Kossow HP 21xx, Varian 620, TI 990, DEC documentation and software Al Kossow HP 21xx, Varian 620, TI 990, DEC documentation and software
Arthur Krewat DZ11 update for the PDP-10 Arthur Krewat DZ11 update for the PDP-10
Mirian Crzig Lennox ITS and DZ11 debugging
Don Lewine Nova documentation and legal permissions Don Lewine Nova documentation and legal permissions
Tim Litt PDP-10 hardware documentation and schematics, Tim Litt PDP-10 hardware documentation and schematics,
tape images, and software sources tape images, and software sources
Tim Markson DZ11 debugging
Scott McGregor PDP-11 UNIX legal permissions Scott McGregor PDP-11 UNIX legal permissions
Jeff Moffatt HP 2100 information, documentation, and software Jeff Moffatt HP 2100 information, documentation, and software
Alec Muffett Solaris port testing Alec Muffett Solaris port testing
@ -5209,6 +5462,7 @@ David Waks PDP-8 ESI-X and PDP-7 SIM8 software
Tom West Nova documentation Tom West Nova documentation
Adrian Wise H316 simulator, documentation, and software Adrian Wise H316 simulator, documentation, and software
John Wilson PDP-11 simulator 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 In addition, the following companies have graciously licensed their
software at no cost for hobbyist use: software at no cost for hobbyist use:

View file

@ -1,7 +1,7 @@
To: Users To: Users
From: Bob Supnik From: Bob Supnik
Subj: Sample Software Packages Subj: Sample Software Packages
Date: 31-May-01 Date: 30-Sep-01
This memorandum documents the sample software packages available to run This memorandum documents the sample software packages available to run
with the SIMH simulators. Many of these packages are available under 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 0) is the system disk; it also includes BASIC. The second disk
(drive 1) includes FORTRAN. (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. PDP-11
2.1 UNIX V5, V6, V7 2.1 UNIX V5, V6, V7
@ -301,6 +370,69 @@ execution capabilities. To load and run ADSS/KM-15:
4.0000 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. IBM 1401
7.1 Single Card "Koans" 7.1 Single Card "Koans"