mirror of
https://github.com/simh/simh.git
synced 2026-03-04 18:44:11 +00:00
HP2100: Release 28
See HP2100/hp2100_release.txt for details of the release.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/* hp2100_baci.c: HP 12966A buffered asynchronous communications interface simulator
|
||||
/* hp2100_baci.c: HP 12966A Buffered Asynchronous Communications Interface simulator
|
||||
|
||||
Copyright (c) 2007-2016, J. David Bryan
|
||||
Copyright (c) 2007-2017, J. David Bryan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -23,8 +23,13 @@
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from the author.
|
||||
|
||||
BACI 12966A BACI card
|
||||
BACI 12966A Buffered Asynchronous Communications Interface
|
||||
|
||||
01-Nov-17 JDB Fixed serial output buffer overflow handling
|
||||
15-Mar-17 JDB Trace flags are now global
|
||||
Changed DEBUG_PRI calls to tprintfs
|
||||
10-Mar-17 JDB Added IOBUS to the debug table
|
||||
17-Jan-17 JDB Changed "hp_---sc" and "hp_---dev" to "hp_---_dib"
|
||||
02-Aug-16 JDB "baci_poll_svc" now calls "tmxr_poll_conn" unilaterally
|
||||
13-May-16 JDB Modified for revised SCP API function parameter types
|
||||
24-Dec-14 JDB Added casts for explicit downward conversions
|
||||
@@ -83,13 +88,13 @@
|
||||
an "external rate" that is equivalent to 9600 baud, as most terminals were
|
||||
set to their maximum speeds.
|
||||
|
||||
We support the 12966A connected to an HP terminal emulator via Telnet.
|
||||
Internally, we model the BACI as a terminal multiplexer with one line. The
|
||||
simulation is complicated by the half-duplex nature of the card (there is
|
||||
only one FIFO, used selectively either for transmission or reception) and the
|
||||
double-buffered UART (a Western Digital TR1863A), which has holding registers
|
||||
as well as a shift registers for transmission and reception. We model both
|
||||
sets of device registers.
|
||||
We support the 12966A connected to an HP terminal emulator via Telnet or a
|
||||
serial port. Internally, we model the BACI as a terminal multiplexer with
|
||||
one line. The simulation is complicated by the half-duplex nature of the
|
||||
card (there is only one FIFO, used selectively either for transmission or
|
||||
reception) and the double-buffered UART (a Western Digital TR1863A), which
|
||||
has holding registers as well as a shift registers for transmission and
|
||||
reception. We model both sets of device registers.
|
||||
|
||||
During an output operation, the first character output to the card passes
|
||||
through the FIFO and into the transmitter holding register. Subsequent
|
||||
@@ -118,12 +123,12 @@
|
||||
as an "optimized (fast) timing" option. Optimization makes three
|
||||
improvements:
|
||||
|
||||
1. On output, characters in the FIFO are emptied into the Telnet buffer as a
|
||||
1. On output, characters in the FIFO are emptied into the line buffer as a
|
||||
block, rather than one character per service call, and on input, all of
|
||||
the characters available in the Telnet buffer are loaded into the FIFO as
|
||||
a block.
|
||||
the characters available in the line buffer are loaded into the FIFO as a
|
||||
block.
|
||||
|
||||
2. The ENQ/ACK handshake is done locally, without involving the Telnet
|
||||
2. The ENQ/ACK handshake is done locally, without involving the terminal
|
||||
client.
|
||||
|
||||
3. Input occurring during an output operation is delayed until the second or
|
||||
@@ -184,14 +189,6 @@
|
||||
#define UNIT_CAPSLOCK (1 << UNIT_V_CAPSLOCK)
|
||||
|
||||
|
||||
/* Debug flags */
|
||||
|
||||
#define DEB_CMDS (1 << 0) /* commands and status */
|
||||
#define DEB_CPU (1 << 1) /* CPU I/O */
|
||||
#define DEB_BUF (1 << 2) /* buffer gets and puts */
|
||||
#define DEB_XFER (1 << 3) /* character reads and writes */
|
||||
|
||||
|
||||
/* Bit flags */
|
||||
|
||||
#define OUT_MR 0100000 /* common master reset */
|
||||
@@ -322,7 +319,7 @@
|
||||
/* Unit references */
|
||||
|
||||
#define baci_term baci_unit[0] /* terminal I/O unit */
|
||||
#define baci_poll baci_unit[1] /* Telnet polling unit */
|
||||
#define baci_poll baci_unit[1] /* line polling unit */
|
||||
|
||||
|
||||
/* BACI state variables */
|
||||
@@ -395,11 +392,11 @@ t_stat baci_detach (UNIT *uptr);
|
||||
baci_deb BACI debug list
|
||||
baci_dev BACI device descriptor
|
||||
|
||||
Two units are used: one to handle character I/O via the Telnet library, and
|
||||
another to poll for connections and input. The character I/O service routine
|
||||
runs only when there are characters to read or write. It operates at the
|
||||
approximate baud rate of the terminal (in CPU instructions per second) in
|
||||
order to be compatible with the OS drivers. The Telnet poll must run
|
||||
Two units are used: one to handle character I/O via the multiplexer library,
|
||||
and another to poll for connections and input. The character I/O service
|
||||
routine runs only when there are characters to read or write. It operates at
|
||||
the approximate baud rate of the terminal (in CPU instructions per second) in
|
||||
order to be compatible with the OS drivers. The line poll must run
|
||||
continuously, but it can operate much more slowly, as the only requirement is
|
||||
that it must not present a perceptible lag to human input. To be compatible
|
||||
with CPU idling, it is co-scheduled with the master poll timer, which uses a
|
||||
@@ -408,59 +405,61 @@ t_stat baci_detach (UNIT *uptr);
|
||||
|
||||
DEVICE baci_dev;
|
||||
|
||||
TMLN baci_ldsc = { 0 }; /* line descriptor */
|
||||
TMXR baci_desc = { 1, 0, 0, &baci_ldsc }; /* device descriptor */
|
||||
TMLN baci_ldsc = { 0 }; /* line descriptor */
|
||||
TMXR baci_desc = { 1, 0, 0, &baci_ldsc, NULL, &baci_dev }; /* device descriptor */
|
||||
|
||||
DIB baci_dib = { &baci_io, BACI, 0 };
|
||||
|
||||
UNIT baci_unit[] = {
|
||||
{ UDATA (&baci_term_svc, UNIT_ATTABLE | UNIT_FASTTIME, 0) }, /* terminal I/O unit */
|
||||
{ UDATA (&baci_poll_svc, UNIT_DIS, POLL_FIRST) } /* Telnet poll unit */
|
||||
{ UDATA (&baci_poll_svc, UNIT_DIS, POLL_FIRST) } /* line poll unit */
|
||||
};
|
||||
|
||||
REG baci_reg[] = {
|
||||
{ ORDATA (IBUF, baci_ibuf, 16), REG_FIT },
|
||||
{ ORDATA (OBUF, baci_obuf, 16), REG_FIT },
|
||||
{ ORDATA (STATUS, baci_status, 16), REG_FIT },
|
||||
REG baci_reg [] = {
|
||||
/* Macro Name Location Radix Width Offset Depth Flags */
|
||||
/* ------ -------- -------------------- ----- ----- ------ ---------- --------------- */
|
||||
{ ORDATA (IBUF, baci_ibuf, 16), REG_FIT | REG_X },
|
||||
{ ORDATA (OBUF, baci_obuf, 16), REG_FIT | REG_X },
|
||||
{ GRDATA (STATUS, baci_status, 2, 16, 0), REG_FIT },
|
||||
|
||||
{ ORDATA (EDSIW, baci_edsiw, 16), REG_FIT },
|
||||
{ ORDATA (DSRW, baci_dsrw, 16), REG_FIT },
|
||||
{ ORDATA (CFCW, baci_cfcw, 16), REG_FIT },
|
||||
{ ORDATA (ICW, baci_icw, 16), REG_FIT },
|
||||
{ ORDATA (ISRW, baci_isrw, 16), REG_FIT },
|
||||
{ ORDATA (EDSIW, baci_edsiw, 16), REG_FIT },
|
||||
{ ORDATA (DSRW, baci_dsrw, 16), REG_FIT },
|
||||
{ ORDATA (CFCW, baci_cfcw, 16), REG_FIT },
|
||||
{ ORDATA (ICW, baci_icw, 16), REG_FIT },
|
||||
{ ORDATA (ISRW, baci_isrw, 16), REG_FIT },
|
||||
|
||||
{ DRDATA (FIFOPUT, baci_fput, 8) },
|
||||
{ DRDATA (FIFOGET, baci_fget, 8) },
|
||||
{ DRDATA (FIFOCNTR, baci_fcount, 8) },
|
||||
{ DRDATA (BRKCNTR, baci_bcount, 16) },
|
||||
{ DRDATA (FIFOPUT, baci_fput, 8) },
|
||||
{ DRDATA (FIFOGET, baci_fget, 8) },
|
||||
{ DRDATA (FIFOCNTR, baci_fcount, 8) },
|
||||
{ DRDATA (BRKCNTR, baci_bcount, 16) },
|
||||
|
||||
{ BRDATA (FIFO, baci_fifo, 8, 8, FIFO_SIZE) },
|
||||
{ BRDATA (SPCHAR, baci_spchar, 8, 1, 256) },
|
||||
{ BRDATA (FIFO, baci_fifo, 8, 8, FIFO_SIZE), REG_A },
|
||||
{ BRDATA (SPCHAR, baci_spchar, 8, 1, 256) },
|
||||
|
||||
{ ORDATA (UARTTHR, baci_uart_thr, 16), REG_FIT },
|
||||
{ ORDATA (UARTTR, baci_uart_tr, 16), REG_NZ },
|
||||
{ ORDATA (UARTRHR, baci_uart_rhr, 16), REG_FIT },
|
||||
{ ORDATA (UARTRR, baci_uart_rr, 16), REG_NZ },
|
||||
{ DRDATA (UARTCLK, baci_uart_clk, 16) },
|
||||
{ ORDATA (UARTTHR, baci_uart_thr, 16), REG_FIT | REG_X },
|
||||
{ ORDATA (UARTTR, baci_uart_tr, 16), REG_NZ | REG_X },
|
||||
{ ORDATA (UARTRHR, baci_uart_rhr, 16), REG_FIT | REG_X },
|
||||
{ ORDATA (UARTRR, baci_uart_rr, 16), REG_NZ | REG_X },
|
||||
{ DRDATA (UARTCLK, baci_uart_clk, 16) },
|
||||
|
||||
{ DRDATA (CTIME, baci_term.wait, 19), REG_RO },
|
||||
{ DRDATA (CTIME, baci_term.wait, 19) },
|
||||
|
||||
{ FLDATA (ENQFLAG, baci_enq_seen, 0), REG_HRO },
|
||||
{ DRDATA (ENQCNTR, baci_enq_cntr, 16), REG_HRO },
|
||||
{ FLDATA (ENQFLAG, baci_enq_seen, 0), REG_HRO },
|
||||
{ DRDATA (ENQCNTR, baci_enq_cntr, 16), REG_HRO },
|
||||
|
||||
{ FLDATA (LKO, baci.lockout, 0) },
|
||||
{ FLDATA (CTL, baci.control, 0) },
|
||||
{ FLDATA (FLG, baci.flag, 0) },
|
||||
{ FLDATA (FBF, baci.flagbuf, 0) },
|
||||
{ FLDATA (SRQ, baci.srq, 0) },
|
||||
{ ORDATA (SC, baci_dib.select_code, 6), REG_HRO },
|
||||
{ ORDATA (DEVNO, baci_dib.select_code, 6), REG_HRO },
|
||||
{ FLDATA (LKO, baci.lockout, 0) },
|
||||
{ FLDATA (CTL, baci.control, 0) },
|
||||
{ FLDATA (FLG, baci.flag, 0) },
|
||||
{ FLDATA (FBF, baci.flagbuf, 0) },
|
||||
{ FLDATA (SRQ, baci.srq, 0) },
|
||||
{ ORDATA (SC, baci_dib.select_code, 6), REG_HRO },
|
||||
{ ORDATA (DEVNO, baci_dib.select_code, 6), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB baci_mod[] = {
|
||||
{ UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", NULL, NULL, NULL },
|
||||
{ UNIT_DIAG, 0, "terminal mode", "TERMINAL", NULL, NULL, NULL },
|
||||
{ UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAGNOSTIC", NULL, NULL, NULL },
|
||||
{ UNIT_DIAG, 0, "terminal mode", "TERMINAL", NULL, NULL, NULL },
|
||||
|
||||
{ UNIT_FASTTIME, UNIT_FASTTIME, "fast timing", "FASTTIME", NULL, NULL, NULL },
|
||||
{ UNIT_FASTTIME, 0, "realistic timing", "REALTIME", NULL, NULL, NULL },
|
||||
@@ -468,24 +467,25 @@ MTAB baci_mod[] = {
|
||||
{ UNIT_CAPSLOCK, UNIT_CAPSLOCK, "CAPS LOCK down", "CAPSLOCK", NULL, NULL, NULL },
|
||||
{ UNIT_CAPSLOCK, 0, "CAPS LOCK up", "NOCAPSLOCK", NULL, NULL, NULL },
|
||||
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NC, 0, "LOG", "LOG", &tmxr_set_log, &tmxr_show_log, &baci_desc },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NC, 0, NULL, "NOLOG", &tmxr_set_nolog, NULL, &baci_desc },
|
||||
{ MTAB_XDV | MTAB_NC, 0, "LOG", "LOG", &tmxr_set_log, &tmxr_show_log, &baci_desc },
|
||||
{ MTAB_XDV | MTAB_NC, 0, NULL, "NOLOG", &tmxr_set_nolog, NULL, &baci_desc },
|
||||
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTION", NULL, NULL, &tmxr_show_cstat, &baci_desc },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL, NULL, &tmxr_show_cstat, &baci_desc },
|
||||
{ MTAB_XTD | MTAB_VDV, 0, NULL, "DISCONNECT", &tmxr_dscln, NULL, &baci_desc },
|
||||
{ MTAB_XDV | MTAB_NMO, 1, "CONNECTION", NULL, NULL, &tmxr_show_cstat, &baci_desc },
|
||||
{ MTAB_XDV | MTAB_NMO, 0, "STATISTICS", NULL, NULL, &tmxr_show_cstat, &baci_desc },
|
||||
{ MTAB_XDV, 0, NULL, "DISCONNECT", &tmxr_dscln, NULL, &baci_desc },
|
||||
|
||||
{ MTAB_XTD | MTAB_VDV, 0, "SC", "SC", &hp_setsc, &hp_showsc, &baci_dev },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &baci_dev },
|
||||
{ MTAB_XDV, 1u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &baci_dib },
|
||||
{ MTAB_XDV | MTAB_NMO, ~1u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &baci_dib },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEBTAB baci_deb[] = {
|
||||
{ "CMDS", DEB_CMDS },
|
||||
{ "CPU", DEB_CPU },
|
||||
{ "BUF", DEB_BUF },
|
||||
{ "XFER", DEB_XFER },
|
||||
{ NULL, 0 }
|
||||
DEBTAB baci_deb [] = {
|
||||
{ "CMDS", DEB_CMDS },
|
||||
{ "CPU", DEB_CPU },
|
||||
{ "BUF", DEB_BUF },
|
||||
{ "XFER", DEB_XFER },
|
||||
{ "IOBUS", TRACE_IOBUS }, /* interface I/O bus signals and data words */
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
DEVICE baci_dev = {
|
||||
@@ -560,8 +560,7 @@ while (working_set) {
|
||||
baci.flag = baci.flagbuf = CLEAR; /* clear flag and flag buffer */
|
||||
baci.srq = CLEAR; /* clear SRQ */
|
||||
|
||||
if (DEBUG_PRI (baci_dev, DEB_CMDS))
|
||||
fputs (">>BACI cmds: [CLF] Flag and SRQ cleared\n", sim_deb);
|
||||
tprintf (baci_dev, DEB_CMDS, "[CLF] Flag and SRQ cleared\n");
|
||||
|
||||
update_status (); /* FLG might set when SRQ clears */
|
||||
break;
|
||||
@@ -572,8 +571,7 @@ while (working_set) {
|
||||
baci.lockout = SET; /* set lockout */
|
||||
baci.srq = SET; /* set SRQ */
|
||||
|
||||
if (DEBUG_PRI (baci_dev, DEB_CMDS))
|
||||
fputs (">>BACI cmds: [STF] Flag, SRQ, and lockout set\n", sim_deb);
|
||||
tprintf (baci_dev, DEB_CMDS, "[STF] Flag, SRQ, and lockout set\n");
|
||||
break;
|
||||
|
||||
|
||||
@@ -602,15 +600,15 @@ while (working_set) {
|
||||
|
||||
data = baci_ibuf; /* return received data */
|
||||
|
||||
if (DEBUG_PRI (baci_dev, DEB_CPU))
|
||||
fprintf (sim_deb, ">>BACI cpu: [LIx%s] Received data = %06o\n", hold_or_clear, baci_ibuf);
|
||||
tprintf (baci_dev, DEB_CPU, "[LIx%s] Received data = %06o\n",
|
||||
hold_or_clear, baci_ibuf);
|
||||
}
|
||||
|
||||
else { /* control clear? */
|
||||
data = baci_status; /* return status */
|
||||
|
||||
if (DEBUG_PRI (baci_dev, DEB_CPU))
|
||||
fprintf (sim_deb, ">>BACI cpu: [LIx%s] Status = %06o\n", hold_or_clear, baci_status);
|
||||
tprintf (baci_dev, DEB_CPU, "[LIx%s] Status = %06o\n",
|
||||
hold_or_clear, baci_status);
|
||||
}
|
||||
|
||||
stat_data = IORETURN (SCPE_OK, data); /* merge in return status */
|
||||
@@ -620,15 +618,14 @@ while (working_set) {
|
||||
case ioIOO: /* I/O data output */
|
||||
baci_obuf = IODATA (stat_data); /* get data value */
|
||||
|
||||
if (DEBUG_PRI (baci_dev, DEB_CPU))
|
||||
fprintf (sim_deb, ">>BACI cpu: [OTx%s] Command = %06o\n", hold_or_clear, baci_obuf);
|
||||
tprintf (baci_dev, DEB_CPU, "[OTx%s] Command = %06o\n",
|
||||
hold_or_clear, baci_obuf);
|
||||
|
||||
if (baci_obuf & OUT_MR) { /* master reset? */
|
||||
master_reset (); /* do before processing */
|
||||
baci_io (&baci_dib, ioSIR, 0); /* set interrupt request */
|
||||
|
||||
if (DEBUG_PRI (baci_dev, DEB_CMDS))
|
||||
fprintf (sim_deb, ">>BACI cmds: [OTx%s] Master reset\n", hold_or_clear);
|
||||
tprintf (baci_dev, DEB_CMDS, "[OTx%s] Master reset\n", hold_or_clear);
|
||||
}
|
||||
|
||||
switch (GET_ID (baci_obuf)) { /* isolate ID code */
|
||||
@@ -639,10 +636,10 @@ while (working_set) {
|
||||
fifo_put (ch); /* queue character */
|
||||
|
||||
if (baci_term.flags & UNIT_ATT) { /* attached to network? */
|
||||
if (DEBUG_PRI (baci_dev, DEB_CMDS) && /* debugging? */
|
||||
if (TRACING (baci_dev, DEB_CMDS) && /* debugging? */
|
||||
(sim_is_active (&baci_term) == 0)) /* service stopped? */
|
||||
fprintf (sim_deb, ">>BACI cmds: [OTx%s] Terminal service scheduled, "
|
||||
"time = %d\n", hold_or_clear, baci_term.wait);
|
||||
hp_trace (&baci_dev, DEB_CMDS, "[OTx%s] Terminal service scheduled, "
|
||||
"time = %d\n", hold_or_clear, baci_term.wait);
|
||||
|
||||
if (baci_fcount == 1) /* first char to xmit? */
|
||||
sim_activate_abs (&baci_term, /* start service with full char time */
|
||||
@@ -683,17 +680,15 @@ while (working_set) {
|
||||
sim_activate (&baci_term, /* activate I/O service */
|
||||
baci_term.wait);
|
||||
|
||||
if (DEBUG_PRI (baci_dev, DEB_CMDS))
|
||||
fprintf (sim_deb, ">>BACI cmds: [OTx%s] Terminal service scheduled, "
|
||||
"time = %d\n", hold_or_clear, baci_term.wait);
|
||||
tprintf (baci_dev, DEB_CMDS, "[OTx%s] Terminal service scheduled, "
|
||||
"time = %d\n", hold_or_clear, baci_term.wait);
|
||||
}
|
||||
|
||||
else { /* external rate */
|
||||
sim_cancel (&baci_term); /* stop I/O service */
|
||||
|
||||
if (DEBUG_PRI (baci_dev, DEB_CMDS))
|
||||
fprintf (sim_deb, ">>BACI cmds: [OTx%s] Terminal service stopped\n",
|
||||
hold_or_clear);
|
||||
tprintf (baci_dev, DEB_CMDS, "[OTx%s] Terminal service stopped\n",
|
||||
hold_or_clear);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -724,16 +719,14 @@ while (working_set) {
|
||||
case ioCRS: /* control reset */
|
||||
master_reset (); /* issue master reset */
|
||||
|
||||
if (DEBUG_PRI (baci_dev, DEB_CMDS))
|
||||
fputs (">>BACI cmds: [CRS] Master reset\n", sim_deb);
|
||||
tprintf (baci_dev, DEB_CMDS, "[CRS] Master reset\n");
|
||||
break;
|
||||
|
||||
|
||||
case ioCLC: /* clear control flip-flop */
|
||||
baci.control = CLEAR; /* clear control */
|
||||
|
||||
if (DEBUG_PRI (baci_dev, DEB_CMDS))
|
||||
fprintf (sim_deb, ">>BACI cmds: [CLC%s] Control cleared\n", hold_or_clear);
|
||||
tprintf (baci_dev, DEB_CMDS, "[CLC%s] Control cleared\n", hold_or_clear);
|
||||
break;
|
||||
|
||||
|
||||
@@ -741,8 +734,7 @@ while (working_set) {
|
||||
baci.control = SET; /* set control */
|
||||
baci.lockout = CLEAR; /* clear lockout */
|
||||
|
||||
if (DEBUG_PRI (baci_dev, DEB_CMDS))
|
||||
fprintf (sim_deb, ">>BACI cmds: [STC%s] Control set and lockout cleared\n", hold_or_clear);
|
||||
tprintf (baci_dev, DEB_CMDS, "[STC%s] Control set and lockout cleared\n", hold_or_clear);
|
||||
|
||||
if (!(signal_set & ioCLF)) /* STC without ,C ? */
|
||||
update_status (); /* clearing lockout might interrupt */
|
||||
@@ -777,7 +769,7 @@ return stat_data;
|
||||
The terminal service routine is used to transmit and receive characters.
|
||||
|
||||
In terminal mode, it is started when a character is ready for output or when
|
||||
the Telnet poll routine determines that there are characters ready for input
|
||||
the line poll routine determines that there are characters ready for input
|
||||
and stopped when there are no more characters to output or input. When the
|
||||
terminal is quiescent, this routine does not run.
|
||||
|
||||
@@ -817,11 +809,11 @@ return stat_data;
|
||||
first character after an ENQ is not an ACK.
|
||||
|
||||
Finally, fast timing enables buffer combining. For output, all characters
|
||||
present in the FIFO are unloaded into the Telnet buffer before initiating a
|
||||
packet send. For input, all characters present in the Telnet buffer are
|
||||
loaded into the FIFO. This reduces network traffic and decreases simulator
|
||||
overhead (there is only one service routine entry per block, rather than one
|
||||
per character).
|
||||
present in the FIFO are unloaded into the line buffer before initiating a
|
||||
packet send. For input, all characters present in the line buffer are loaded
|
||||
into the FIFO. This reduces network traffic and decreases simulator overhead
|
||||
(there is only one service routine entry per block, rather than one per
|
||||
character).
|
||||
|
||||
In fast output mode, it is imperative that not less than 1500 instructions
|
||||
elapse between the first character load to the FIFO and the initiation of
|
||||
@@ -835,6 +827,46 @@ return stat_data;
|
||||
|
||||
To avoid this, the OTx output character handler does an absolute schedule for
|
||||
the first character to ensure that a full character time is used.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. The terminal multiplexer library "tmxr_putc_ln" routine returns
|
||||
SCPE_STALL if it is called when the transmit buffer is full. When the
|
||||
last character is added to the buffer, the routine returns SCPE_OK but
|
||||
also changes the "xmte" field of the terminal multiplexer line (TMLN)
|
||||
structure from 1 to 0 to indicate that further calls will be rejected.
|
||||
The "xmte" value is set back to 1 when the tranmit buffer empties.
|
||||
|
||||
This presents two approaches to handling buffer overflows: either call
|
||||
"tmxr_putc_ln" unconditionally and test for SCPE_STALL on return, or call
|
||||
"tmxr_putc_ln" only if "xmte" is 1. The former approach adds a new
|
||||
character to the transmit buffer as soon as space is available, while the
|
||||
latter adds a new character only when the buffer has completely emptied.
|
||||
With either approach, transmission must be rescheduled after a delay to
|
||||
allow the buffer to drain.
|
||||
|
||||
It would seem that the former approach is more attractive, as it would
|
||||
allow the simulated I/O operation to complete more quickly. However,
|
||||
there are two mitigating factors. First, the library attempts to write
|
||||
the entire transmit buffer in one host system call, so there is usually
|
||||
no time difference between freeing one buffer character and freeing the
|
||||
entire buffer (barring host system buffer congestion). Second, the
|
||||
routine increments a "character dropped" counter when returning
|
||||
SCPE_STALL status. However, the characters actually would not be lost,
|
||||
as the SCPE_STALL return would schedule retransmission when buffer space
|
||||
is available, . This would lead to erroneous reporting in the SHOW
|
||||
<unit> STATISTICS command.
|
||||
|
||||
Therefore, we adopt the latter approach and reschedule transmission if
|
||||
the "xmte" field is 0. Note that the "tmxr_poll_tx" routine still must
|
||||
be called in this case, as it is responsible for transmitting the buffer
|
||||
contents and therefore freeing space in the buffer.
|
||||
|
||||
2. The "tmxr_putc_ln" library routine returns SCPE_LOST if the line is not
|
||||
connected. We ignore this error so that an OS may output an
|
||||
initialization "welcome" message even when the terminal is not connected.
|
||||
This permits the simulation to continue while ignoring the output.
|
||||
*/
|
||||
|
||||
t_stat baci_term_svc (UNIT *uptr)
|
||||
@@ -843,12 +875,16 @@ uint32 data_bits, data_mask;
|
||||
const t_bool fast_timing = (baci_term.flags & UNIT_FASTTIME) != 0;
|
||||
const t_bool is_attached = (baci_term.flags & UNIT_ATT) != 0;
|
||||
t_stat status = SCPE_OK;
|
||||
t_bool xmit_loop = TRUE;
|
||||
t_bool recv_loop = TRUE;
|
||||
t_bool xmit_loop = (baci_ldsc.xmte != 0); /* TRUE if the transmit buffer is not full */
|
||||
|
||||
|
||||
/* Transmission */
|
||||
|
||||
if (baci_ldsc.xmte == 0) /* if the transmit buffer is full */
|
||||
tprintf (baci_dev, DEB_XFER, "Transmission stalled for full buffer\n");
|
||||
|
||||
|
||||
while (xmit_loop && (baci_uart_thr & IN_VALID)) { /* valid character in UART? */
|
||||
data_bits = 5 + (baci_cfcw & OUT_CHARSIZE); /* calculate number of data bits */
|
||||
data_mask = (1 << data_bits) - 1; /* generate mask for data bits */
|
||||
@@ -859,9 +895,8 @@ while (xmit_loop && (baci_uart_thr & IN_VALID)) { /* valid character in UA
|
||||
baci_enq_cntr = baci_enq_cntr + 1; /* bump ENQ counter */
|
||||
recv_loop = FALSE; /* skip recv to allow time before ACK */
|
||||
|
||||
if (DEBUG_PRI (baci_dev, DEB_XFER))
|
||||
fprintf (sim_deb, ">>BACI xfer: Character ENQ absorbed internally, "
|
||||
"ENQ count = %d\n", baci_enq_cntr);
|
||||
tprintf (baci_dev, DEB_XFER, "Character ENQ absorbed internally, "
|
||||
"ENQ count = %d\n", baci_enq_cntr);
|
||||
}
|
||||
|
||||
else { /* character is not ENQ or not fast timing */
|
||||
@@ -871,11 +906,17 @@ while (xmit_loop && (baci_uart_thr & IN_VALID)) { /* valid character in UA
|
||||
status = tmxr_putc_ln (&baci_ldsc, /* transmit the character */
|
||||
baci_uart_tr);
|
||||
|
||||
if ((status == SCPE_OK) && /* transmitted OK? */
|
||||
DEBUG_PRI (baci_dev, DEB_XFER))
|
||||
fprintf (sim_deb, ">>BACI xfer: Character %s "
|
||||
"transmitted from UART\n",
|
||||
fmt_char ((uint8) baci_uart_tr));
|
||||
if (status == SCPE_OK) /* transmitted OK? */
|
||||
tprintf (baci_dev, DEB_XFER, "Character %s transmitted from the UART\n",
|
||||
fmt_char ((uint8) baci_uart_tr));
|
||||
|
||||
else {
|
||||
tprintf (baci_dev, DEB_XFER, "Character %s transmission failed with status %d\n",
|
||||
fmt_char ((uint8) baci_uart_tr), status);
|
||||
|
||||
if (status == SCPE_LOST) /* if the line is not connected */
|
||||
status = SCPE_OK; /* then ignore the output */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -891,11 +932,12 @@ while (xmit_loop && (baci_uart_thr & IN_VALID)) { /* valid character in UA
|
||||
else /* receive mode */
|
||||
baci_uart_thr = CLEAR_HR; /* clear holding register */
|
||||
|
||||
xmit_loop = fast_timing && !baci_enq_seen; /* loop if fast mode and char not ENQ */
|
||||
xmit_loop = (fast_timing && ! baci_enq_seen /* loop if fast mode and char not ENQ */
|
||||
&& baci_ldsc.xmte != 0); /* and buffer space is available */
|
||||
}
|
||||
|
||||
else
|
||||
xmit_loop = FALSE;
|
||||
else /* otherwise transmission failed */
|
||||
xmit_loop = FALSE; /* so drop out of the loop */
|
||||
}
|
||||
|
||||
|
||||
@@ -907,9 +949,8 @@ if (recv_loop && /* ok to process? */
|
||||
|
||||
baci_uart_rhr = baci_uart_rhr & ~IN_VALID; /* clear valid bit */
|
||||
|
||||
if (DEBUG_PRI (baci_dev, DEB_XFER))
|
||||
fprintf (sim_deb, ">>BACI xfer: Deferred character %s processed\n",
|
||||
fmt_char ((uint8) baci_uart_rhr));
|
||||
tprintf (baci_dev, DEB_XFER, "Deferred character %s processed\n",
|
||||
fmt_char ((uint8) baci_uart_rhr));
|
||||
|
||||
fifo_put ((uint8) baci_uart_rhr); /* move deferred character to FIFO */
|
||||
baci_uart_rhr = CLEAR_HR; /* clear RHR */
|
||||
@@ -928,8 +969,7 @@ while (recv_loop) { /* OK to process? */
|
||||
if (baci_uart_rr & SCPE_BREAK) { /* break detected? */
|
||||
baci_status = baci_status | IN_BREAK; /* set break status */
|
||||
|
||||
if (DEBUG_PRI (baci_dev, DEB_XFER))
|
||||
fputs (">>BACI xfer: Break detected\n", sim_deb);
|
||||
tprintf (baci_dev, DEB_XFER, "Break detected\n");
|
||||
}
|
||||
|
||||
data_bits = 5 + (baci_cfcw & OUT_CHARSIZE); /* calculate number of data bits */
|
||||
@@ -937,9 +977,8 @@ while (recv_loop) { /* OK to process? */
|
||||
baci_uart_rhr = (uint16) (baci_uart_rr & data_mask); /* mask data into holding register */
|
||||
baci_uart_rr = CLEAR_R; /* clear receiver register */
|
||||
|
||||
if (DEBUG_PRI (baci_dev, DEB_XFER))
|
||||
fprintf (sim_deb, ">>BACI xfer: Character %s received by UART\n",
|
||||
fmt_char ((uint8) baci_uart_rhr));
|
||||
tprintf (baci_dev, DEB_XFER, "Character %s received by the UART\n",
|
||||
fmt_char ((uint8) baci_uart_rhr));
|
||||
|
||||
if (baci_term.flags & UNIT_CAPSLOCK) /* caps lock mode? */
|
||||
baci_uart_rhr = (uint16) toupper (baci_uart_rhr); /* convert to upper case if lower */
|
||||
@@ -967,8 +1006,7 @@ while (recv_loop) { /* OK to process? */
|
||||
if (recv_loop && baci_enq_seen) { /* OK to process and ENQ seen? */
|
||||
baci_enq_seen = FALSE; /* reset flag */
|
||||
|
||||
if (DEBUG_PRI (baci_dev, DEB_XFER))
|
||||
fputs (">>BACI xfer: Character ACK generated internally\n", sim_deb);
|
||||
tprintf (baci_dev, DEB_XFER, "Character ACK generated internally\n");
|
||||
|
||||
fifo_put (ACK); /* fake ACK from terminal */
|
||||
update_status (); /* update FIFO status */
|
||||
@@ -981,19 +1019,17 @@ if ((baci_uart_thr & IN_VALID) || baci_enq_seen || /* more to transmit? */
|
||||
tmxr_rqln (&baci_ldsc)) /* or more to receive? */
|
||||
sim_activate (uptr, uptr->wait); /* reschedule service */
|
||||
else
|
||||
if (DEBUG_PRI (baci_dev, DEB_CMDS))
|
||||
fputs (">>BACI cmds: Terminal service stopped\n", sim_deb);
|
||||
tprintf (baci_dev, DEB_CMDS, "Terminal service stopped\n");
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* BACI Telnet poll service.
|
||||
/* BACI line poll service.
|
||||
|
||||
This service routine is used to poll for Telnet connections and incoming
|
||||
characters. If characters are available, the terminal I/O service routine is
|
||||
scheduled. It starts when the socket is attached and stops when the socket
|
||||
is detached.
|
||||
This service routine is used to poll for connections and incoming characters.
|
||||
If characters are available, the terminal I/O service routine is scheduled.
|
||||
It starts when the line is attached and stops when the line is detached.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
@@ -1042,16 +1078,16 @@ baci_term.wait = service_time (baci_icw); /* set terminal I/O time
|
||||
|
||||
if (baci_term.flags & UNIT_ATT) { /* device attached? */
|
||||
baci_poll.wait = POLL_FIRST; /* set up poll */
|
||||
sim_activate (&baci_poll, baci_poll.wait); /* start Telnet poll immediately */
|
||||
sim_activate (&baci_poll, baci_poll.wait); /* start line poll immediately */
|
||||
}
|
||||
else
|
||||
sim_cancel (&baci_poll); /* else stop Telnet poll */
|
||||
sim_cancel (&baci_poll); /* else stop line poll */
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Attach controller */
|
||||
/* Attach line */
|
||||
|
||||
t_stat baci_attach (UNIT *uptr, CONST char *cptr)
|
||||
{
|
||||
@@ -1061,20 +1097,20 @@ status = tmxr_attach (&baci_desc, uptr, cptr); /* attach to socket */
|
||||
|
||||
if (status == SCPE_OK) {
|
||||
baci_poll.wait = POLL_FIRST; /* set up poll */
|
||||
sim_activate (&baci_poll, baci_poll.wait); /* start Telnet poll immediately */
|
||||
sim_activate (&baci_poll, baci_poll.wait); /* start line poll immediately */
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* Detach controller */
|
||||
/* Detach line */
|
||||
|
||||
t_stat baci_detach (UNIT *uptr)
|
||||
{
|
||||
t_stat status;
|
||||
|
||||
baci_ldsc.rcve = 0; /* disable line reception */
|
||||
sim_cancel (&baci_poll); /* stop Telnet poll */
|
||||
sim_cancel (&baci_poll); /* stop line poll */
|
||||
status = tmxr_detach (&baci_desc, uptr); /* detach socket */
|
||||
return status;
|
||||
}
|
||||
@@ -1122,8 +1158,10 @@ baci_dsrw = 0; /* clear status referenc
|
||||
baci_cfcw = baci_cfcw & ~OUT_ECHO; /* clear echo flag */
|
||||
baci_icw = baci_icw & OUT_BAUDRATE; /* clear interface control */
|
||||
|
||||
if (baci_term.flags & UNIT_DIAG) /* diagnostic mode? */
|
||||
if (baci_term.flags & UNIT_DIAG) { /* diagnostic mode? */
|
||||
baci_status = baci_status & ~IN_MODEM | IN_SPARE; /* clear loopback status, set BA */
|
||||
baci_ldsc.xmte = 1; /* enable transmitter */
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1179,48 +1217,37 @@ if ((baci_status & IN_STDIRQ) || /* standard interrupt? *
|
||||
(baci_edsiw & OUT_ENCM) && /* and char mode */
|
||||
(baci_fget != baci_fput)) { /* and FIFO not empty? */
|
||||
|
||||
if (baci.lockout) { /* interrupt lockout? */
|
||||
if (DEBUG_PRI (baci_dev, DEB_CMDS))
|
||||
fputs (">>BACI cmds: Lockout prevents flag set", sim_deb);
|
||||
}
|
||||
if (baci.lockout) /* interrupt lockout? */
|
||||
tprintf (baci_dev, DEB_CMDS, "Lockout prevents flag set, status = %06o\n",
|
||||
baci_status);
|
||||
|
||||
else if (baci.srq) { /* SRQ set? */
|
||||
if (DEBUG_PRI (baci_dev, DEB_CMDS))
|
||||
fputs (">>BACI cmds: SRQ prevents flag set", sim_deb);
|
||||
}
|
||||
else if (baci.srq) /* SRQ set? */
|
||||
tprintf (baci_dev, DEB_CMDS, "SRQ prevents flag set, status = %06o\n",
|
||||
baci_status);
|
||||
|
||||
else {
|
||||
baci_io (&baci_dib, ioENF, 0); /* set flag */
|
||||
|
||||
if (DEBUG_PRI (baci_dev, DEB_CMDS))
|
||||
fputs (">>BACI cmds: Flag and lockout set", sim_deb);
|
||||
tprintf (baci_dev, DEB_CMDS, "Flag and lockout set, status = %06o\n",
|
||||
baci_status);
|
||||
}
|
||||
|
||||
if (DEBUG_PRI (baci_dev, DEB_CMDS))
|
||||
fprintf (sim_deb, ", status = %06o\n", baci_status);
|
||||
}
|
||||
|
||||
if ((baci_icw & OUT_DCPC) && /* DCPC enabled? */
|
||||
((IO_MODE == XMIT) && (baci_fcount < 128) || /* and xmit and room in FIFO */
|
||||
(IO_MODE == RECV) && (baci_fcount > 0))) { /* or recv and data in FIFO? */
|
||||
|
||||
if (baci.lockout) { /* interrupt lockout? */
|
||||
if (DEBUG_PRI (baci_dev, DEB_CMDS))
|
||||
fputs (">>BACI cmds: Lockout prevents SRQ set", sim_deb);
|
||||
}
|
||||
(IO_MODE == RECV) && (baci_fcount > 0))) /* or recv and data in FIFO? */
|
||||
if (baci.lockout) /* interrupt lockout? */
|
||||
tprintf (baci_dev, DEB_CMDS, "Lockout prevents SRQ set, status = %06o\n",
|
||||
baci_status);
|
||||
|
||||
else {
|
||||
baci.srq = SET; /* set SRQ */
|
||||
baci_io (&baci_dib, ioSIR, 0); /* set interrupt request */
|
||||
|
||||
if (DEBUG_PRI (baci_dev, DEB_CMDS))
|
||||
fputs (">>BACI cmds: SRQ set", sim_deb);
|
||||
tprintf (baci_dev, DEB_CMDS, "SRQ set, status = %06o\n",
|
||||
baci_status);
|
||||
}
|
||||
|
||||
if (DEBUG_PRI (baci_dev, DEB_CMDS))
|
||||
fprintf (sim_deb, ", status = %06o\n", baci_status);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1340,10 +1367,9 @@ if ((baci_fget != baci_fput) || (baci_fcount >= 128)) { /* FIFO occupied? */
|
||||
if (IO_MODE == RECV) /* receive mode? */
|
||||
baci_fcount = baci_fcount - 1; /* decrement occupancy counter */
|
||||
|
||||
if (DEBUG_PRI (baci_dev, DEB_BUF))
|
||||
fprintf (sim_deb, ">>BACI buf: Character %s get from FIFO [%d], "
|
||||
"character counter = %d\n",
|
||||
fmt_char ((uint8) data), baci_fget, baci_fcount);
|
||||
tprintf (baci_dev, DEB_BUF, "Character %s get from FIFO [%d], "
|
||||
"character counter = %d\n",
|
||||
fmt_char ((uint8) data), baci_fget, baci_fcount);
|
||||
|
||||
baci_fget = (baci_fget + 1) % FIFO_SIZE; /* bump index modulo array size */
|
||||
|
||||
@@ -1354,9 +1380,8 @@ if ((baci_fget != baci_fput) || (baci_fcount >= 128)) { /* FIFO occupied? */
|
||||
}
|
||||
|
||||
else /* FIFO empty */
|
||||
if (DEBUG_PRI (baci_dev, DEB_BUF))
|
||||
fprintf (sim_deb, ">>BACI buf: Attempted get on empty FIFO, "
|
||||
"character count = %d\n", baci_fcount);
|
||||
tprintf (baci_dev, DEB_BUF, "Attempted get on empty FIFO, "
|
||||
"character count = %d\n", baci_fcount);
|
||||
|
||||
if (baci_fcount == 0) /* count now zero? */
|
||||
baci_status = baci_status | IN_BUFEMPTY; /* set buffer empty flag */
|
||||
@@ -1398,13 +1423,12 @@ else { /* RECV or THR occupied
|
||||
|
||||
baci_fcount = baci_fcount + 1; /* increment occupancy counter */
|
||||
|
||||
if (DEBUG_PRI (baci_dev, DEB_BUF))
|
||||
if (pass_thru)
|
||||
fprintf (sim_deb, ">>BACI buf: Character %s put to UART transmitter holding register, "
|
||||
"character counter = 1\n", fmt_char (ch));
|
||||
else
|
||||
fprintf (sim_deb, ">>BACI buf: Character %s put to FIFO [%d], "
|
||||
"character counter = %d\n", fmt_char (ch), index, baci_fcount);
|
||||
if (pass_thru)
|
||||
tprintf (baci_dev, DEB_BUF, "Character %s put to UART transmitter holding register, "
|
||||
"character counter = 1\n", fmt_char (ch));
|
||||
else
|
||||
tprintf (baci_dev, DEB_BUF, "Character %s put to FIFO [%d], "
|
||||
"character counter = %d\n", fmt_char (ch), index, baci_fcount);
|
||||
|
||||
if ((IO_MODE == RECV) && (baci_spchar [ch])) /* receive mode and special character? */
|
||||
baci_status = baci_status | IN_SPCHAR; /* set special char seen flag */
|
||||
@@ -1477,8 +1501,7 @@ if (baci_uart_clk > 0) { /* transfer in progress?
|
||||
if (baci_bcount == 160) { /* break held long enough? */
|
||||
baci_status = baci_status | IN_BREAK; /* set break flag */
|
||||
|
||||
if (DEBUG_PRI (baci_dev, DEB_XFER))
|
||||
fputs (">>BACI xfer: Break detected\n", sim_deb);
|
||||
tprintf (baci_dev, DEB_XFER, "Break detected\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1499,9 +1522,8 @@ if (baci_uart_clk > 0) { /* transfer in progress?
|
||||
baci_uart_thr = fifo_get (); /* get next char into THR */
|
||||
update_status (); /* update FIFO status */
|
||||
|
||||
if (DEBUG_PRI (baci_dev, DEB_XFER))
|
||||
fprintf (sim_deb, ">>BACI xfer: UART transmitter empty, "
|
||||
"holding register = %06o\n", baci_uart_thr);
|
||||
tprintf (baci_dev, DEB_XFER, "UART transmitter empty, "
|
||||
"holding register = %06o\n", baci_uart_thr);
|
||||
}
|
||||
|
||||
else if ((IO_MODE == RECV) && /* receive mode? */
|
||||
@@ -1517,10 +1539,8 @@ if (baci_uart_clk > 0) { /* transfer in progress?
|
||||
baci_uart_rhr = (uint16) (baci_uart_rr >> (16 - uart_bits)); /* position data to right align */
|
||||
baci_uart_rr = CLEAR_R; /* clear receiver register */
|
||||
|
||||
if (DEBUG_PRI (baci_dev, DEB_XFER))
|
||||
fprintf (sim_deb, ">>BACI xfer: UART receiver = %06o (%s)\n",
|
||||
baci_uart_rhr,
|
||||
fmt_char ((uint8) (baci_uart_rhr & data_mask)));
|
||||
tprintf (baci_dev, DEB_XFER, "UART receiver = %06o (%s)\n",
|
||||
baci_uart_rhr, fmt_char ((uint8) (baci_uart_rhr & data_mask)));
|
||||
|
||||
fifo_put ((uint8) (baci_uart_rhr & data_mask)); /* put data in FIFO */
|
||||
update_status (); /* update FIFO status */
|
||||
@@ -1539,8 +1559,7 @@ if (baci_uart_clk > 0) { /* transfer in progress?
|
||||
if (parity & 1) { /* parity error? */
|
||||
baci_status = baci_status | IN_OVRUNPE; /* report it */
|
||||
|
||||
if (DEBUG_PRI (baci_dev, DEB_XFER))
|
||||
fputs (">>BACI xfer: Parity error detected\n", sim_deb);
|
||||
tprintf (baci_dev, DEB_XFER, "Parity error detected\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1578,19 +1597,17 @@ if ((baci_uart_clk == 0) && /* start of transfer? */
|
||||
|
||||
baci_uart_tr = (~data_mask | baci_uart_tr) << 2 | 1; /* form serial data stream */
|
||||
|
||||
if (DEBUG_PRI (baci_dev, DEB_XFER))
|
||||
fprintf (sim_deb, ">>BACI xfer: UART transmitter = %06o (%s), "
|
||||
"clock count = %d\n", baci_uart_tr & DMASK,
|
||||
fmt_char ((uint8) (baci_uart_thr & data_mask)),
|
||||
baci_uart_clk);
|
||||
tprintf (baci_dev, DEB_XFER, "UART transmitter = %06o (%s), "
|
||||
"clock count = %d\n", baci_uart_tr & DMASK,
|
||||
fmt_char ((uint8) (baci_uart_thr & data_mask)),
|
||||
baci_uart_clk);
|
||||
}
|
||||
|
||||
else {
|
||||
baci_uart_rr = CLEAR_R; /* clear receiver register */
|
||||
|
||||
if (DEBUG_PRI (baci_dev, DEB_XFER))
|
||||
fprintf (sim_deb, ">>BACI xfer: UART receiver empty, "
|
||||
"clock count = %d\n", baci_uart_clk);
|
||||
tprintf (baci_dev, DEB_XFER, "UART receiver empty, "
|
||||
"clock count = %d\n", baci_uart_clk);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
8098
HP2100/hp2100_cpu.c
8098
HP2100/hp2100_cpu.c
File diff suppressed because it is too large
Load Diff
@@ -1,28 +1,41 @@
|
||||
/* hp2100_cpu.h: HP 2100 CPU definitions
|
||||
/* hp2100_cpu.h: HP 2100 CPU declarations
|
||||
|
||||
Copyright (c) 2005-2016, Robert M. Supnik
|
||||
Copyright (c) 2017-2018, J. David Bryan
|
||||
|
||||
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:
|
||||
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.
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS 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.
|
||||
Except as contained in this notice, the names of the authors shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from the authors.
|
||||
|
||||
22-Feb-18 JDB Reworked "cpu_ibl" into "cpu_copy_loader"
|
||||
Cleaned up IBL definitions, added loader structure
|
||||
22-Jul-17 JDB Renamed "intaddr" to CIR; added IR
|
||||
14-Jul-17 JDB Removed calc_defer() prototype
|
||||
11-Jul-17 JDB Moved "ibl_copy" and renamed to "cpu_ibl"
|
||||
10-Jul-17 JDB Renamed the global routine "iogrp" to "cpu_iog"
|
||||
07-Jul-17 JDB Changed "iotrap" from uint32 to t_bool
|
||||
07-Jun-17 JDB Added maximum instruction length for sim_emax definition
|
||||
06-Jun-17 JDB Added instruction group decoding macros
|
||||
04-Apr-17 JDB Added "cpu_configuration" for symbolic ex/dep validation
|
||||
08-Mar-17 JDB Added "cpu_speed" for TBG service access
|
||||
15-Feb-17 JDB Deleted unneeded guard macro definition
|
||||
05-Aug-16 JDB Renamed the P register from "PC" to "PR"
|
||||
24-Dec-14 JDB Added casts for explicit downward conversions
|
||||
18-Mar-13 JDB Added declarations for the MP abort handler and CPU registers
|
||||
@@ -50,73 +63,213 @@
|
||||
encode the series within the type.
|
||||
*/
|
||||
|
||||
#ifndef HP2100_CPU_H_
|
||||
#define HP2100_CPU_H_ 0
|
||||
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
|
||||
/* CPU model definition flags */
|
||||
|
||||
#define CPU_V_SERIES 0
|
||||
#define CPU_V_TYPE 2
|
||||
#define CPU_V_FAMILY 3
|
||||
/* Memory access macros.
|
||||
|
||||
#define FAMILY_21XX (0 << CPU_V_FAMILY)
|
||||
#define FAMILY_1000 (1 << CPU_V_FAMILY)
|
||||
These macros provide simplified function call sequences for memory reads and
|
||||
writes by the CPU. They supply the correct access classification. The
|
||||
following macro routines are provided:
|
||||
|
||||
#define TYPE_211X (0 << CPU_V_TYPE) /* 2114, 2115, 2116 */
|
||||
#define TYPE_2100 (1 << CPU_V_TYPE) /* 2100A, 2100S */
|
||||
#define TYPE_1000MEF (0 << CPU_V_TYPE) /* 1000-M, 1000-E, 1000-F */
|
||||
#define TYPE_1000AL (1 << CPU_V_TYPE) /* 1000-L, A600, A700, A900, A990 */
|
||||
Name Action
|
||||
------- ------------------------------------------------------------
|
||||
ReadF Read an instruction word using the current map
|
||||
ReadW Read a data word using the current map
|
||||
ReadWA Read a data word using the alternate map
|
||||
ReadS Read a data word using the system map
|
||||
ReadU Read a data word using the user map
|
||||
|
||||
ReadB Read a data byte using the current map
|
||||
ReadBA Read a data byte using the alternate map
|
||||
|
||||
WriteW Write a data word using the current map
|
||||
WriteWA Write a data word using the alternate map
|
||||
WriteS Write a data word using the system map
|
||||
WriteU Write a data word using the user map
|
||||
|
||||
WriteB Write a data byte using the current map
|
||||
WriteBA Write a data byte using the alternate map
|
||||
|
||||
The MP_ABORT macro performs a "longjmp" to the memory protect handler in the
|
||||
instruction execution loop. The parameter is the address of the violation.
|
||||
The conditions that initiate a MP abort must be tested explicitly before
|
||||
calling MP_ABORT.
|
||||
*/
|
||||
|
||||
#define ReadF(a) mem_read (&cpu_dev, Fetch, a)
|
||||
#define ReadW(a) mem_read (&cpu_dev, Data, a)
|
||||
#define ReadWA(a) mem_read (&cpu_dev, Data_Alternate, a)
|
||||
#define ReadS(a) mem_read (&cpu_dev, Data_System, a)
|
||||
#define ReadU(a) mem_read (&cpu_dev, Data_User, a)
|
||||
|
||||
#define ReadB(a) mem_read_byte (&cpu_dev, Data, a)
|
||||
#define ReadBA(a) mem_read_byte (&cpu_dev, Data_Alternate, a)
|
||||
|
||||
#define WriteW(a,v) mem_write (&cpu_dev, Data, a, v)
|
||||
#define WriteWA(a,v) mem_write (&cpu_dev, Data_Alternate, a, v)
|
||||
#define WriteS(a,v) mem_write (&cpu_dev, Data_System, a, v)
|
||||
#define WriteU(a,v) mem_write (&cpu_dev, Data_User, a, v)
|
||||
|
||||
#define WriteB(a,v) mem_write_byte (&cpu_dev, Data, a, v)
|
||||
#define WriteBA(a,v) mem_write_byte (&cpu_dev, Data_Alternate, a, v)
|
||||
|
||||
#define MP_ABORT(va) longjmp (save_env, (va))
|
||||
|
||||
|
||||
/* CPU tracing flags */
|
||||
|
||||
#define DEBUG_NOOS (1u << 0) /* configure RTE-6/VM not to use OS firmware */
|
||||
|
||||
#define TRACE_INSTR (1u << 1) /* trace instruction executions */
|
||||
#define TRACE_DATA (1u << 2) /* trace memory data accesses */
|
||||
#define TRACE_FETCH (1u << 3) /* trace memory instruction fetches */
|
||||
#define TRACE_REG (1u << 4) /* trace register values */
|
||||
#define TRACE_OPND (1u << 5) /* trace instruction operands */
|
||||
#define TRACE_EXEC (1u << 6) /* trace matching instruction execution states */
|
||||
#define TRACE_SR (1u << 7) /* trace service requests received */
|
||||
|
||||
#define TRACE_ALL ~DEBUG_NOOS /* trace everything */
|
||||
|
||||
#define DMS_FORMAT "%c %04o %05o %06o " /* map | physical page | logical address | value format */
|
||||
#define REGA_FORMAT "%c **** %05o %06o " /* protection | fence | S register format for working registers */
|
||||
#define REGB_FORMAT "%c **** ***** ****** " /* protection format for MP/MEM registers */
|
||||
#define OPND_FORMAT "* **** %05o %06o " /* address | data format for operands */
|
||||
#define EXEC_FORMAT "******************** " /* null format for EXEC separation */
|
||||
|
||||
|
||||
/* CPU stop flags */
|
||||
|
||||
#define SS_INHIBIT (t_stat) (~0u) /* inhibit stops for the first instruction executed */
|
||||
|
||||
#define STOP(s) ((s) & ~cpu_ss_inhibit) /* stop if the condition is enabled and not inhibited */
|
||||
|
||||
|
||||
/* Supported breakpoint switches */
|
||||
|
||||
#define BP_EXEC (SWMASK ('E')) /* an execution breakpoint */
|
||||
#define BP_ENONE (SWMASK ('N')) /* an execution breakpoint when mapping is off */
|
||||
#define BP_ESYS (SWMASK ('S')) /* an execution breakpoint in the system map */
|
||||
#define BP_EUSER (SWMASK ('U')) /* an execution breakpoint in the user map */
|
||||
|
||||
#define BP_SUPPORTED (BP_EXEC | BP_ENONE | BP_ESYS | BP_EUSER)
|
||||
|
||||
|
||||
/* CPU unit flags.
|
||||
|
||||
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| R | - | G | V | O | E | D | F | M | I | P | U | CPU model |
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| f | t | series|
|
||||
+---+---+---+---+
|
||||
|
||||
Where:
|
||||
|
||||
R = reserved
|
||||
G = SIGNAL/1000 firmware is present
|
||||
V = Vector Instruction Set firmware is present
|
||||
O = RTE-6/VM VMA and OS firmware is present
|
||||
E = RTE-IV EMA firmware is present
|
||||
D = Double Integer firmware is present
|
||||
F = Fast FORTRAN Processor firmware is present
|
||||
M = Dynamic Mapping System firmware is present
|
||||
I = 2000 I/O Processor firmware is present
|
||||
P = Floating Point hardware or firmware is present
|
||||
U = Extended Arithmetic Unit is present
|
||||
f = CPU family
|
||||
t = CPU type
|
||||
|
||||
CPU Models:
|
||||
|
||||
0 0 00 = HP 2116
|
||||
0 0 01 = HP 2115
|
||||
0 0 10 = HP 2114
|
||||
0 0 11 = unused
|
||||
|
||||
0 1 00 = HP 2100
|
||||
0 1 01 = unused
|
||||
0 1 10 = unused
|
||||
0 1 11 = unused
|
||||
|
||||
1 0 00 = HP 1000 M-Series
|
||||
1 0 01 = HP 1000 E-Series
|
||||
1 0 10 = HP 1000 F-Series
|
||||
1 0 11 = unused
|
||||
|
||||
1 1 00 = unused (1000 A-Series)
|
||||
1 1 01 = unused (1000 A-Series)
|
||||
1 1 10 = unused (1000 A-Series)
|
||||
1 1 11 = unused (1000 A-Series)
|
||||
|
||||
*/
|
||||
|
||||
#define CPU_V_SERIES 0
|
||||
#define CPU_V_TYPE 2
|
||||
#define CPU_V_FAMILY 3
|
||||
|
||||
#define FAMILY_21XX (0 << CPU_V_FAMILY)
|
||||
#define FAMILY_1000 (1 << CPU_V_FAMILY)
|
||||
|
||||
#define TYPE_211X (0 << CPU_V_TYPE) /* 2114, 2115, 2116 */
|
||||
#define TYPE_2100 (1 << CPU_V_TYPE) /* 2100A, 2100S */
|
||||
#define TYPE_1000MEF (0 << CPU_V_TYPE) /* 1000-M, 1000-E, 1000-F */
|
||||
#define TYPE_1000AL (1 << CPU_V_TYPE) /* 1000-L, A600, A700, A900, A990 */
|
||||
|
||||
#define SERIES_16 (0 << CPU_V_SERIES) /* 211X */
|
||||
#define SERIES_15 (1 << CPU_V_SERIES) /* 211X */
|
||||
#define SERIES_14 (2 << CPU_V_SERIES) /* 211X */
|
||||
#define SERIES_00 (0 << CPU_V_SERIES) /* 2100 */
|
||||
#define SERIES_M (0 << CPU_V_SERIES) /* 1000 */
|
||||
#define SERIES_E (1 << CPU_V_SERIES) /* 1000 */
|
||||
#define SERIES_F (2 << CPU_V_SERIES) /* 1000 */
|
||||
|
||||
#define SERIES_16 (0 << CPU_V_SERIES) /* 211X */
|
||||
#define SERIES_15 (1 << CPU_V_SERIES) /* 211X */
|
||||
#define SERIES_14 (2 << CPU_V_SERIES) /* 211X */
|
||||
#define SERIES_00 (0 << CPU_V_SERIES) /* 2100 */
|
||||
#define SERIES_M (0 << CPU_V_SERIES) /* 1000 */
|
||||
#define SERIES_E (1 << CPU_V_SERIES) /* 1000 */
|
||||
#define SERIES_F (2 << CPU_V_SERIES) /* 1000 */
|
||||
|
||||
/* CPU unit flags */
|
||||
|
||||
#define UNIT_M_CPU 017 /* CPU model mask [3:0] */
|
||||
#define UNIT_M_TYPE 014 /* CPU type mask [3:2] */
|
||||
#define UNIT_M_FAMILY 010 /* CPU family mask [3:3] */
|
||||
#define UNIT_M_CPU 017 /* CPU model mask [3:0] */
|
||||
#define UNIT_M_TYPE 014 /* CPU type mask [3:2] */
|
||||
#define UNIT_M_FAMILY 010 /* CPU family mask [3:3] */
|
||||
|
||||
#define UNIT_V_CPU (UNIT_V_UF + 0) /* CPU model bits 0-3 */
|
||||
#define UNIT_V_EAU (UNIT_V_UF + 4) /* EAU installed */
|
||||
#define UNIT_V_FP (UNIT_V_UF + 5) /* FP installed */
|
||||
#define UNIT_V_IOP (UNIT_V_UF + 6) /* IOP installed */
|
||||
#define UNIT_V_DMS (UNIT_V_UF + 7) /* DMS installed */
|
||||
#define UNIT_V_FFP (UNIT_V_UF + 8) /* FFP installed */
|
||||
#define UNIT_V_DBI (UNIT_V_UF + 9) /* DBI installed */
|
||||
#define UNIT_V_EMA (UNIT_V_UF + 10) /* RTE-4 EMA installed */
|
||||
#define UNIT_V_VMAOS (UNIT_V_UF + 11) /* RTE-6 VMA/OS installed */
|
||||
#define UNIT_V_VIS (UNIT_V_UF + 12) /* VIS installed */
|
||||
#define UNIT_V_SIGNAL (UNIT_V_UF + 13) /* SIGNAL/1000 installed */
|
||||
#define UNIT_V_CPU (UNIT_V_UF + 0) /* CPU model bits 0-3 */
|
||||
#define UNIT_V_EAU (UNIT_V_UF + 4) /* EAU installed */
|
||||
#define UNIT_V_FP (UNIT_V_UF + 5) /* FP installed */
|
||||
#define UNIT_V_IOP (UNIT_V_UF + 6) /* IOP installed */
|
||||
#define UNIT_V_DMS (UNIT_V_UF + 7) /* DMS installed */
|
||||
#define UNIT_V_FFP (UNIT_V_UF + 8) /* FFP installed */
|
||||
#define UNIT_V_DBI (UNIT_V_UF + 9) /* DBI installed */
|
||||
#define UNIT_V_EMA (UNIT_V_UF + 10) /* RTE-4 EMA installed */
|
||||
#define UNIT_V_VMAOS (UNIT_V_UF + 11) /* RTE-6 VMA/OS installed */
|
||||
#define UNIT_V_VIS (UNIT_V_UF + 12) /* VIS installed */
|
||||
#define UNIT_V_SIGNAL (UNIT_V_UF + 13) /* SIGNAL/1000 installed */
|
||||
/* Future microcode expansion; reuse flags bottom-up if needed */
|
||||
#define UNIT_V_DS (UNIT_V_UF + 14) /* DS installed */
|
||||
#define UNIT_V_DS (UNIT_V_UF + 14) /* DS installed */
|
||||
|
||||
|
||||
/* Unit models */
|
||||
|
||||
#define UNIT_MODEL_MASK (UNIT_M_CPU << UNIT_V_CPU)
|
||||
#define UNIT_MODEL_MASK (UNIT_M_CPU << UNIT_V_CPU)
|
||||
|
||||
#define UNIT_2116 ((FAMILY_21XX | TYPE_211X | SERIES_16) << UNIT_V_CPU)
|
||||
#define UNIT_2115 ((FAMILY_21XX | TYPE_211X | SERIES_15) << UNIT_V_CPU)
|
||||
#define UNIT_2114 ((FAMILY_21XX | TYPE_211X | SERIES_14) << UNIT_V_CPU)
|
||||
#define UNIT_2100 ((FAMILY_21XX | TYPE_2100 | SERIES_00) << UNIT_V_CPU)
|
||||
#define UNIT_1000_M ((FAMILY_1000 | TYPE_1000MEF | SERIES_M) << UNIT_V_CPU)
|
||||
#define UNIT_1000_E ((FAMILY_1000 | TYPE_1000MEF | SERIES_E) << UNIT_V_CPU)
|
||||
#define UNIT_1000_F ((FAMILY_1000 | TYPE_1000MEF | SERIES_F) << UNIT_V_CPU)
|
||||
|
||||
#define UNIT_2116 ((FAMILY_21XX | TYPE_211X | SERIES_16) << UNIT_V_CPU)
|
||||
#define UNIT_2115 ((FAMILY_21XX | TYPE_211X | SERIES_15) << UNIT_V_CPU)
|
||||
#define UNIT_2114 ((FAMILY_21XX | TYPE_211X | SERIES_14) << UNIT_V_CPU)
|
||||
#define UNIT_2100 ((FAMILY_21XX | TYPE_2100 | SERIES_00) << UNIT_V_CPU)
|
||||
#define UNIT_1000_M ((FAMILY_1000 | TYPE_1000MEF | SERIES_M) << UNIT_V_CPU)
|
||||
#define UNIT_1000_E ((FAMILY_1000 | TYPE_1000MEF | SERIES_E) << UNIT_V_CPU)
|
||||
#define UNIT_1000_F ((FAMILY_1000 | TYPE_1000MEF | SERIES_F) << UNIT_V_CPU)
|
||||
|
||||
/* Unit types */
|
||||
|
||||
#define UNIT_TYPE_MASK (UNIT_M_TYPE << UNIT_V_CPU)
|
||||
#define UNIT_TYPE_MASK (UNIT_M_TYPE << UNIT_V_CPU)
|
||||
|
||||
#define UNIT_TYPE_211X ((FAMILY_21XX | TYPE_211X) << UNIT_V_CPU)
|
||||
#define UNIT_TYPE_2100 ((FAMILY_21XX | TYPE_2100) << UNIT_V_CPU)
|
||||
#define UNIT_TYPE_1000 ((FAMILY_1000 | TYPE_1000MEF) << UNIT_V_CPU)
|
||||
|
||||
#define UNIT_TYPE_211X ((FAMILY_21XX | TYPE_211X) << UNIT_V_CPU)
|
||||
#define UNIT_TYPE_2100 ((FAMILY_21XX | TYPE_2100) << UNIT_V_CPU)
|
||||
#define UNIT_TYPE_1000 ((FAMILY_1000 | TYPE_1000MEF) << UNIT_V_CPU)
|
||||
|
||||
/* Unit families */
|
||||
|
||||
@@ -125,92 +278,282 @@
|
||||
#define UNIT_FAMILY_21XX (FAMILY_21XX << UNIT_V_CPU)
|
||||
#define UNIT_FAMILY_1000 (FAMILY_1000 << UNIT_V_CPU)
|
||||
|
||||
|
||||
/* Unit accessors */
|
||||
|
||||
#define UNIT_CPU_MODEL (cpu_unit.flags & UNIT_MODEL_MASK)
|
||||
#define UNIT_CPU_TYPE (cpu_unit.flags & UNIT_TYPE_MASK)
|
||||
#define UNIT_CPU_FAMILY (cpu_unit.flags & UNIT_FAMILY_MASK)
|
||||
#define UNIT_CPU_MODEL (cpu_unit.flags & UNIT_MODEL_MASK)
|
||||
#define UNIT_CPU_TYPE (cpu_unit.flags & UNIT_TYPE_MASK)
|
||||
#define UNIT_CPU_FAMILY (cpu_unit.flags & UNIT_FAMILY_MASK)
|
||||
|
||||
#define CPU_MODEL_INDEX (UNIT_CPU_MODEL >> UNIT_V_CPU)
|
||||
|
||||
#define CPU_MODEL_INDEX (UNIT_CPU_MODEL >> UNIT_V_CPU)
|
||||
|
||||
/* Unit features */
|
||||
|
||||
#define UNIT_EAU (1 << UNIT_V_EAU)
|
||||
#define UNIT_FP (1 << UNIT_V_FP)
|
||||
#define UNIT_IOP (1 << UNIT_V_IOP)
|
||||
#define UNIT_DMS (1 << UNIT_V_DMS)
|
||||
#define UNIT_FFP (1 << UNIT_V_FFP)
|
||||
#define UNIT_DBI (1 << UNIT_V_DBI)
|
||||
#define UNIT_EMA (1 << UNIT_V_EMA)
|
||||
#define UNIT_VMAOS (1 << UNIT_V_VMAOS)
|
||||
#define UNIT_VIS (1 << UNIT_V_VIS)
|
||||
#define UNIT_DS (1 << UNIT_V_DS)
|
||||
#define UNIT_SIGNAL (1 << UNIT_V_SIGNAL)
|
||||
#define UNIT_EAU (1u << UNIT_V_EAU)
|
||||
#define UNIT_FP (1u << UNIT_V_FP)
|
||||
#define UNIT_IOP (1u << UNIT_V_IOP)
|
||||
#define UNIT_DMS (1u << UNIT_V_DMS)
|
||||
#define UNIT_FFP (1u << UNIT_V_FFP)
|
||||
#define UNIT_DBI (1u << UNIT_V_DBI)
|
||||
#define UNIT_EMA (1u << UNIT_V_EMA)
|
||||
#define UNIT_VMAOS (1u << UNIT_V_VMAOS)
|
||||
#define UNIT_VIS (1u << UNIT_V_VIS)
|
||||
#define UNIT_DS (1u << UNIT_V_DS)
|
||||
#define UNIT_SIGNAL (1u << UNIT_V_SIGNAL)
|
||||
|
||||
#define UNIT_EMA_VMA (UNIT_EMA | UNIT_VMAOS)
|
||||
#define UNIT_EMA_VMA (UNIT_EMA | UNIT_VMAOS)
|
||||
|
||||
#define UNIT_OPTS (UNIT_EAU | UNIT_FP | UNIT_IOP | \
|
||||
UNIT_DMS | UNIT_FFP | UNIT_DBI | \
|
||||
UNIT_EMA | UNIT_VMAOS | \
|
||||
UNIT_VIS | UNIT_DS | UNIT_SIGNAL)
|
||||
#define UNIT_OPTS (UNIT_EAU | UNIT_FP | UNIT_IOP | \
|
||||
UNIT_DMS | UNIT_FFP | UNIT_DBI | \
|
||||
UNIT_EMA | UNIT_VMAOS | \
|
||||
UNIT_VIS | UNIT_DS | UNIT_SIGNAL)
|
||||
|
||||
/* "Pseudo-option" flags used only for option testing; never set into UNIT structure. */
|
||||
|
||||
#define UNIT_V_PFAIL (UNIT_V_UF - 1) /* Power fail installed */
|
||||
#define UNIT_V_DMA (UNIT_V_UF - 2) /* DMA installed */
|
||||
#define UNIT_V_MP (UNIT_V_UF - 3) /* Memory protect installed */
|
||||
#define UNIT_V_PFAIL (UNIT_V_UF - 1) /* Power fail installed */
|
||||
#define UNIT_V_DMA (UNIT_V_UF - 2) /* DMA installed */
|
||||
#define UNIT_V_MP (UNIT_V_UF - 3) /* Memory protect installed */
|
||||
|
||||
#define UNIT_PFAIL (1 << UNIT_V_PFAIL)
|
||||
#define UNIT_DMA (1 << UNIT_V_DMA)
|
||||
#define UNIT_MP (1 << UNIT_V_MP)
|
||||
#define UNIT_PFAIL (1 << UNIT_V_PFAIL)
|
||||
#define UNIT_DMA (1 << UNIT_V_DMA)
|
||||
#define UNIT_MP (1 << UNIT_V_MP)
|
||||
|
||||
#define UNIT_NONE 0 /* no options */
|
||||
#define UNIT_NONE 0 /* no options */
|
||||
|
||||
/* Debug flags */
|
||||
|
||||
#define DEB_OS (1 << 0) /* RTE-6/VM OS firmware non-TBG processing */
|
||||
#define DEB_OSTBG (1 << 1) /* RTE-6/VM OS firmware TBG processing */
|
||||
#define DEB_VMA (1 << 2) /* RTE-6/VM VMA firmware instructions */
|
||||
#define DEB_EMA (1 << 3) /* RTE-6/VM EMA firmware instructions */
|
||||
#define DEB_VIS (1 << 4) /* E/F-Series VIS firmware instructions */
|
||||
#define DEB_SIG (1 << 5) /* F-Series SIGNAL/1000 firmware instructions */
|
||||
/* CPU configuration model flags */
|
||||
|
||||
#define CPU_MASK D16_MASK
|
||||
|
||||
#define CPU_2116 (1u << (FAMILY_21XX | TYPE_211X | SERIES_16))
|
||||
#define CPU_2115 (1u << (FAMILY_21XX | TYPE_211X | SERIES_15))
|
||||
#define CPU_2114 (1u << (FAMILY_21XX | TYPE_211X | SERIES_14))
|
||||
#define CPU_2100 (1u << (FAMILY_21XX | TYPE_2100 | SERIES_00))
|
||||
#define CPU_1000_M (1u << (FAMILY_1000 | TYPE_1000MEF | SERIES_M))
|
||||
#define CPU_1000_E (1u << (FAMILY_1000 | TYPE_1000MEF | SERIES_E))
|
||||
#define CPU_1000_F (1u << (FAMILY_1000 | TYPE_1000MEF | SERIES_F))
|
||||
|
||||
#define CPU_1000 (CPU_1000_M | CPU_1000_E | CPU_1000_F)
|
||||
|
||||
#define CPU_ALL (CPU_2116 | CPU_2115 | CPU_2114 | \
|
||||
CPU_2100 | \
|
||||
CPU_1000_M | CPU_1000_E | CPU_1000_F)
|
||||
|
||||
/* PC queue. */
|
||||
|
||||
#define PCQ_SIZE 64 /* must be 2**n */
|
||||
#define PCQ_MASK (PCQ_SIZE - 1)
|
||||
#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = (uint16) err_PC
|
||||
#define PCQ_ENTRY pcq [pcq_p = (pcq_p - 1) & PCQ_MASK] = (uint16) err_PC
|
||||
|
||||
/* Memory reference instructions */
|
||||
|
||||
#define I_IA 0100000 /* indirect address */
|
||||
#define I_AB 0004000 /* A/B select */
|
||||
#define I_CP 0002000 /* current page */
|
||||
#define I_DISP 0001777 /* page displacement */
|
||||
#define I_PAGENO 0076000 /* page number */
|
||||
/* Maximum instruction length.
|
||||
|
||||
This value is the length in words of the longest machine instruction. It is
|
||||
used to set "sim_emax", which, in turn, is used to allocate the "sim_eval"
|
||||
array. This array holds the words of a machine instruction to be formatted
|
||||
and printed or to be parsed and stored.
|
||||
|
||||
The longest instruction in the 21xx/1000 family is the [D]VPIV (vector pivot)
|
||||
instruction in the Vector Instruction Set.
|
||||
*/
|
||||
|
||||
#define MAX_INSTR_LENGTH 10
|
||||
|
||||
|
||||
/* Instruction group decoding.
|
||||
|
||||
The HP 21xx/1000 instruction set consists of five groups: the Memory
|
||||
Reference Group (MRG), the Shift-Rotate Group (SRG), the Alter-Skip Group
|
||||
(ASG), the I/O Group (IOG), and the Macro Group (MAC). Group membership is
|
||||
determined by a multi-level decoding of bits 15-10, as follows:
|
||||
|
||||
Bits
|
||||
15-10 Group
|
||||
------ -----
|
||||
xnnnx MRG
|
||||
00000 SRG
|
||||
00001 ASG
|
||||
10001 IOG
|
||||
10000 MAC
|
||||
|
||||
Where:
|
||||
|
||||
x = 0 or 1
|
||||
n = any collective value other than 0
|
||||
|
||||
The MAC group is subdivided into the Extended Arithmetic Group (EAG), the
|
||||
first User Instruction Group (UIG-0), and the second User Instruction Group
|
||||
(UIG-1). Decoding is by bits 11-8, as follows (note that bit 10 = 0 for the
|
||||
MAC group):
|
||||
|
||||
Bits
|
||||
11-8 Group
|
||||
---- -----
|
||||
0000 EAG
|
||||
0001 EAG
|
||||
0010 EAG
|
||||
0011 UIG-1
|
||||
1000 EAG
|
||||
1001 EAG
|
||||
1010 UIG-0
|
||||
1011 UIG-1
|
||||
|
||||
Bits 7-4 further decode the UIG instruction feature group.
|
||||
*/
|
||||
|
||||
#define GROUP_MASK 0172000u /* instruction group mask */
|
||||
|
||||
#define MRG 0070000u /* Memory Reference Group indicator */
|
||||
#define SRG 0000000u /* Shift-Rotate Group indicator */
|
||||
#define ASG 0002000u /* Alter-Skip Group indicator */
|
||||
#define IOG 0102000u /* I/O Group indicator */
|
||||
|
||||
#define MRGOP(v) (((v) & MRG) != 0) /* MRG membership test */
|
||||
#define SRGOP(v) (((v) & GROUP_MASK) == SRG) /* SRG membership test */
|
||||
#define ASGOP(v) (((v) & GROUP_MASK) == ASG) /* ASG membership test */
|
||||
#define IOGOP(v) (((v) & GROUP_MASK) == IOG) /* IOG membership test */
|
||||
|
||||
#define SRG_CLE 0000040u /* SRG CLE opcode */
|
||||
#define SRG_SLx 0000010u /* SRG SLA/SLB opcode */
|
||||
#define SRG_NOP 0000000u /* SRG no-operation opcode */
|
||||
|
||||
#define SRG1_DE_MASK 0001000u /* SRG disable/enable first micro-op field bit */
|
||||
#define SRG1_MASK 0001700u
|
||||
#define SRG1_SHIFT 6
|
||||
|
||||
#define SRG2_DE_MASK 0000020u /* SRG disable/enable second micro-op field bit */
|
||||
#define SRG2_MASK 0000027u
|
||||
#define SRG2_SHIFT 0
|
||||
|
||||
#define SRG1(u) (((u) & SRG1_MASK) >> SRG1_SHIFT)
|
||||
#define SRG2(u) (((u) & SRG2_MASK) >> SRG2_SHIFT)
|
||||
|
||||
#define UIG_MASK 0000360u /* UIG feature group mask */
|
||||
#define UIG_SHIFT 4 /* UIG feature group alignment shift */
|
||||
|
||||
#define UIG(i) (((i) & UIG_MASK) >> UIG_SHIFT)
|
||||
|
||||
#define UIG_0_MASK 0177400u /* UIG-0 opcode mask */
|
||||
#define UIG_0_RANGE 0105000u /* UIG-0 opcode range */
|
||||
|
||||
#define UIG_1_MASK 0173400u /* UIG-1 opcode mask */
|
||||
#define UIG_1_RANGE 0101400u /* UIG-1 opcode range */
|
||||
|
||||
#define UIG_0_OP(i) (((i) & UIG_0_MASK) == UIG_0_RANGE) /* UIG-0 membership test */
|
||||
#define UIG_1_OP(i) (((i) & UIG_1_MASK) == UIG_1_RANGE) /* UIG-1 membership test */
|
||||
|
||||
#define RTE_IRQ_RANGE 0105354 /* RTE-6/VM interrupt request instructions range */
|
||||
|
||||
|
||||
/* Memory Reference Group instructions */
|
||||
|
||||
#define I_IA 0100000u /* indirect address */
|
||||
#define I_AB 0004000u /* A/B select */
|
||||
#define I_CP 0002000u /* current page */
|
||||
#define I_DISP 0001777u /* page displacement */
|
||||
#define I_PAGENO 0076000u /* page number */
|
||||
|
||||
/* Alter/Skip Group instructions */
|
||||
|
||||
#define I_CMx 0001000u /* CMA/B */
|
||||
#define I_CLx 0000400u /* CLA/B */
|
||||
#define I_CME 0000200u /* CME */
|
||||
#define I_CLE 0000100u /* CLE */
|
||||
#define I_SEZ 0000040u /* SEZ */
|
||||
#define I_SSx 0000020u /* SSA/B */
|
||||
#define I_SLx 0000010u /* SLA/B */
|
||||
#define I_INx 0000004u /* INA/B */
|
||||
#define I_SZx 0000002u /* SZA/B */
|
||||
#define I_RSS 0000001u /* RSS */
|
||||
|
||||
#define I_SSx_SLx_RSS (I_SSx | I_SLx | I_RSS) /* a special case */
|
||||
#define I_ALL_SKIPS (I_SEZ | I_SZx | I_SSx_SLx_RSS) /* another special case */
|
||||
|
||||
/* Shift/Rotate Group micro-ops */
|
||||
|
||||
#define I_xLS 0000000u /* ALS/BLS */
|
||||
#define I_xRS 0000001u /* ARS/BRS */
|
||||
#define I_RxL 0000002u /* RAL/RBL */
|
||||
#define I_RxR 0000003u /* RAR/RBR */
|
||||
#define I_xLR 0000004u /* ALR/BLR */
|
||||
#define I_ERx 0000005u /* ERA/ERB */
|
||||
#define I_ELx 0000006u /* ELA/ELB */
|
||||
#define I_xLF 0000007u /* ALF/BLF */
|
||||
|
||||
#define SRG_DIS 0000000u
|
||||
#define SRG1_EN 0000010u
|
||||
#define SRG2_EN 0000020u
|
||||
|
||||
/* Other instructions */
|
||||
|
||||
#define I_NMRMASK 0172000 /* non-mrf opcode */
|
||||
#define I_ASKP 0002000 /* alter/skip */
|
||||
#define I_IO 0102000 /* I/O */
|
||||
#define I_CTL 0004000 /* CTL on/off */
|
||||
#define I_HC 0001000 /* hold/clear */
|
||||
#define I_DEVMASK 0000077 /* device select code mask */
|
||||
#define I_GETIOOP(x) (((x) >> 6) & 07) /* I/O sub op */
|
||||
#define I_NOP 0000000u /* no operation */
|
||||
#define I_NMRMASK 0172000u /* non-mrf opcode */
|
||||
#define I_ASKP 0002000u /* alter/skip */
|
||||
#define I_IO 0102000u /* I/O */
|
||||
#define I_CTL 0004000u /* CTL on/off */
|
||||
#define I_HC 0001000u /* hold/clear */
|
||||
#define I_DEVMASK 0000077u /* device select code mask */
|
||||
#define I_GETIOOP(x) (((x) >> 6) & 07u) /* I/O sub op */
|
||||
|
||||
/* Instruction masks */
|
||||
|
||||
#define I_MRG 0074000 /* MRG instructions */
|
||||
#define I_MRG 0074000u /* MRG instructions */
|
||||
#define I_MRG_I (I_MRG | I_IA) /* MRG indirect instruction group */
|
||||
#define I_JSB 0014000 /* JSB instruction */
|
||||
#define I_JSB 0014000u /* JSB instruction */
|
||||
#define I_JSB_I (I_JSB | I_IA) /* JSB,I instruction */
|
||||
#define I_JMP 0024000 /* JMP instruction */
|
||||
#define I_ISZ 0034000 /* ISZ instruction */
|
||||
#define I_JMP 0024000u /* JMP instruction */
|
||||
#define I_ISZ 0034000u /* ISZ instruction */
|
||||
|
||||
#define I_IOG 0107700u /* I/O group instruction */
|
||||
#define I_SFS 0102300u /* SFS instruction */
|
||||
#define I_STF 0102100u /* STF instruction */
|
||||
|
||||
|
||||
/* Initial Binary Loader.
|
||||
|
||||
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| ROM # | - - | select code | - - - - - - |
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
*/
|
||||
|
||||
#define IBL_WIDTH 6 /* loader ROM address width */
|
||||
#define IBL_MASK ((1u << IBL_WIDTH) - 1) /* loader ROM address mask (2 ** 6 - 1) */
|
||||
#define IBL_MAX ((1u << IBL_WIDTH) - 1) /* loader ROM address maximum (2 ** 6 - 1) */
|
||||
#define IBL_SIZE (IBL_MAX + 1) /* loader ROM size in words */
|
||||
|
||||
#define IBL_START 0 /* ROM array index of the program start */
|
||||
#define IBL_DMA (IBL_MAX - 1) /* ROM array index of the DMA configuration word */
|
||||
#define IBL_FWA (IBL_MAX - 0) /* ROM array index of the negative starting address */
|
||||
#define IBL_NA (IBL_MAX + 1) /* "not-applicable" ROM array index */
|
||||
|
||||
#define IBL_S_CLEAR 0000000u /* cpu_copy_loader mask to clear the S register */
|
||||
#define IBL_S_NOCLEAR 0177777u /* cpu_copy_loader mask to preserve the S register */
|
||||
#define IBL_S_NOSET 0000000u /* cpu_copy_loader mask to preserve the S register */
|
||||
|
||||
#define IBL_ROM_MASK 0140000u /* ROM socket selector mask */
|
||||
#define IBL_SC_MASK 0007700u /* device select code mask */
|
||||
#define IBL_USER_MASK ~(IBL_ROM_MASK | IBL_SC_MASK)
|
||||
|
||||
#define IBL_ROM_SHIFT 14
|
||||
#define IBL_SC_SHIFT 6
|
||||
|
||||
#define IBL_ROM(s) (((s) & IBL_ROM_MASK) >> IBL_ROM_SHIFT)
|
||||
#define IBL_SC(s) (((s) & IBL_SC_MASK) >> IBL_SC_SHIFT)
|
||||
|
||||
#define IBL_TO_SC(c) ((c) << IBL_SC_SHIFT & IBL_SC_MASK)
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32 start_index; /* the array index of the start of the program */
|
||||
uint32 dma_index; /* the array index of the DMA configuration word */
|
||||
uint32 fwa_index; /* the array index of the negative starting address */
|
||||
MEMORY_WORD loader [IBL_SIZE]; /* the 64-word bootstrap loader program */
|
||||
} BOOT_LOADER;
|
||||
|
||||
typedef BOOT_LOADER LOADER_ARRAY [2]; /* array (21xx, 1000) of bootstrap loaders */
|
||||
|
||||
#define I_IOG 0107700 /* I/O group instruction */
|
||||
#define I_SFS 0102300 /* SFS instruction */
|
||||
#define I_STF 0102100 /* STF instruction */
|
||||
|
||||
/* Memory management */
|
||||
|
||||
@@ -243,17 +586,19 @@
|
||||
#define MAP_N_PAG (PA_N_SIZE - VA_N_OFF) /* page width */
|
||||
#define MAP_V_PAG (VA_N_OFF)
|
||||
#define MAP_M_PAG ((1 << MAP_N_PAG) - 1)
|
||||
#define MAP_GETPAG(x) (((x) & MAP_M_PAG) << MAP_V_PAG)
|
||||
|
||||
#define MAP_PAGE(r) ((r) & MAP_M_PAG) /* extract the page number from a map register */
|
||||
#define TO_PAGE(n) ((n) << MAP_V_PAG) /* position the page number in a physical address */
|
||||
|
||||
/* MEM status register */
|
||||
|
||||
#define MST_ENBI 0100000 /* MEM enabled at interrupt */
|
||||
#define MST_UMPI 0040000 /* User map selected at inerrupt */
|
||||
#define MST_ENB 0020000 /* MEM enabled currently */
|
||||
#define MST_UMP 0010000 /* User map selected currently */
|
||||
#define MST_PRO 0004000 /* Protected mode enabled currently */
|
||||
#define MST_FLT 0002000 /* Base page portion mapped */
|
||||
#define MST_FENCE 0001777 /* Base page fence */
|
||||
#define MST_ENBI 0100000u /* MEM enabled at interrupt */
|
||||
#define MST_UMPI 0040000u /* User map selected at interrupt */
|
||||
#define MST_ENB 0020000u /* MEM enabled currently */
|
||||
#define MST_UMP 0010000u /* User map selected currently */
|
||||
#define MST_PRO 0004000u /* Protected mode enabled currently */
|
||||
#define MST_FLT 0002000u /* Base page portion mapped */
|
||||
#define MST_FENCE 0001777u /* Base page fence */
|
||||
|
||||
/* MEM violation register */
|
||||
|
||||
@@ -261,76 +606,104 @@
|
||||
#define MVI_V_WPR 14 /* MAP_V_xPR */
|
||||
#define MVI_RPR (1 << MVI_V_RPR) /* rd viol */
|
||||
#define MVI_WPR (1 << MVI_V_WPR) /* wr viol */
|
||||
#define MVI_BPG 0020000 /* base page viol */
|
||||
#define MVI_PRV 0010000 /* priv viol */
|
||||
#define MVI_MEB 0000200 /* me bus enb @ viol */
|
||||
#define MVI_MEM 0000100 /* mem enb @ viol */
|
||||
#define MVI_UMP 0000040 /* usr map @ viol */
|
||||
#define MVI_PAG 0000037 /* pag sel */
|
||||
#define MVI_BPG 0020000u /* base page viol */
|
||||
#define MVI_PRV 0010000u /* priv viol */
|
||||
#define MVI_MEB 0000200u /* me bus enb @ viol */
|
||||
#define MVI_MEM 0000100u /* mem enb @ viol */
|
||||
#define MVI_UMP 0000040u /* usr map @ viol */
|
||||
#define MVI_PAG 0000037u /* pag sel */
|
||||
|
||||
/* CPU registers */
|
||||
|
||||
#define AR ABREG[0] /* A = reg 0 */
|
||||
#define BR ABREG[1] /* B = reg 1 */
|
||||
#define AR ABREG [0] /* A = reg 0 */
|
||||
#define BR ABREG [1] /* B = reg 1 */
|
||||
|
||||
extern HP_WORD ABREG [2]; /* A/B regs (use AR/BR) */
|
||||
extern HP_WORD PR; /* P register */
|
||||
extern HP_WORD SR; /* S register */
|
||||
extern HP_WORD MR; /* M register */
|
||||
extern HP_WORD TR; /* T register */
|
||||
extern HP_WORD XR; /* X register */
|
||||
extern HP_WORD YR; /* Y register */
|
||||
extern uint32 E; /* E register */
|
||||
extern uint32 O; /* O register */
|
||||
|
||||
extern HP_WORD IR; /* Instruction Register */
|
||||
extern HP_WORD CIR; /* Central Interrupt Register */
|
||||
|
||||
extern uint16 ABREG[2]; /* A/B regs (use AR/BR) */
|
||||
extern uint32 PR; /* P register */
|
||||
extern uint32 SR; /* S register */
|
||||
extern uint32 MR; /* M register */
|
||||
extern uint32 TR; /* T register */
|
||||
extern uint32 XR; /* X register */
|
||||
extern uint32 YR; /* Y register */
|
||||
extern uint32 E; /* E register */
|
||||
extern uint32 O; /* O register */
|
||||
|
||||
/* CPU state */
|
||||
|
||||
extern uint32 err_PC;
|
||||
extern HP_WORD err_PC;
|
||||
extern uint32 dms_enb;
|
||||
extern uint32 dms_ump;
|
||||
extern uint32 dms_sr;
|
||||
extern uint32 dms_vr;
|
||||
extern HP_WORD dms_sr;
|
||||
extern FLIP_FLOP mp_control;
|
||||
extern uint32 mp_fence;
|
||||
extern uint32 mp_viol;
|
||||
extern HP_WORD mp_fence;
|
||||
extern HP_WORD mp_viol;
|
||||
extern FLIP_FLOP mp_mevff;
|
||||
extern uint32 iop_sp;
|
||||
extern HP_WORD iop_sp;
|
||||
extern t_bool ion_defer;
|
||||
extern uint32 intaddr;
|
||||
extern uint16 pcq [PCQ_SIZE];
|
||||
extern uint32 pcq_p;
|
||||
extern uint32 stop_inst;
|
||||
extern UNIT cpu_unit;
|
||||
extern DEVICE cpu_dev;
|
||||
extern REG cpu_reg [];
|
||||
extern jmp_buf save_env;
|
||||
extern t_bool mp_mem_changed;
|
||||
|
||||
extern t_stat cpu_ss_unimpl; /* status return for unimplemented instruction execution */
|
||||
extern t_stat cpu_ss_undef; /* status return for undefined instruction execution */
|
||||
extern t_stat cpu_ss_unsc; /* status return for I/O to an unassigned select code */
|
||||
extern t_stat cpu_ss_ioerr; /* status return for an unreported I/O error */
|
||||
extern t_stat cpu_ss_indir; /* status return for indirect loop execution */
|
||||
extern t_stat cpu_ss_inhibit; /* simulation stop inhibition mask */
|
||||
extern UNIT *cpu_ioerr_uptr; /* pointer to a unit with an unreported I/O error */
|
||||
|
||||
extern uint32 cpu_configuration; /* the current CPU option set and model */
|
||||
extern uint32 cpu_speed; /* the CPU speed, expressed as a multiplier of a real machine */
|
||||
extern t_bool is_1000; /* TRUE if the CPU is a 1000 M/E/F-Series */
|
||||
|
||||
|
||||
/* CPU functions */
|
||||
/* CPU global SCP support routines declared in scp.h
|
||||
|
||||
#define MP_ABORT(va) longjmp (save_env, (va))
|
||||
extern t_stat sim_instr (void);
|
||||
*/
|
||||
|
||||
extern t_stat resolve (uint32 MA, uint32 *addr, uint32 irq);
|
||||
extern uint16 ReadPW (uint32 pa);
|
||||
extern uint8 ReadB (uint32 va);
|
||||
extern uint8 ReadBA (uint32 va);
|
||||
extern uint16 ReadW (uint32 va);
|
||||
extern uint16 ReadWA (uint32 va);
|
||||
extern uint16 ReadIO (uint32 va, uint32 map);
|
||||
extern void WritePW (uint32 pa, uint32 dat);
|
||||
extern void WriteB (uint32 va, uint32 dat);
|
||||
extern void WriteBA (uint32 va, uint32 dat);
|
||||
extern void WriteW (uint32 va, uint32 dat);
|
||||
extern void WriteWA (uint32 va, uint32 dat);
|
||||
extern void WriteIO (uint32 va, uint32 dat, uint32 map);
|
||||
extern t_stat iogrp (uint32 ir, uint32 iotrap);
|
||||
extern uint32 calc_int (void);
|
||||
extern t_bool calc_defer (void);
|
||||
extern void mp_dms_jmp (uint32 va, uint32 plb);
|
||||
extern uint16 dms_rmap (uint32 mapi);
|
||||
extern void dms_wmap (uint32 mapi, uint32 dat);
|
||||
extern void dms_viol (uint32 va, uint32 st);
|
||||
extern uint32 dms_upd_vr (uint32 va);
|
||||
extern uint32 dms_upd_sr (void);
|
||||
|
||||
#endif
|
||||
/* CPU global SCP support routines */
|
||||
|
||||
extern void cpu_post_cmd (t_bool from_scp);
|
||||
|
||||
|
||||
/* CPU global utility routines */
|
||||
|
||||
extern t_stat cpu_copy_loader (const LOADER_ARRAY boot, uint32 sc, HP_WORD sr_clear, HP_WORD sr_set);
|
||||
extern t_stat cpu_iog (HP_WORD IR, t_bool iotrap);
|
||||
extern uint32 calc_int (void);
|
||||
extern t_stat resolve (HP_WORD MA, HP_WORD *address, uint32 irq);
|
||||
|
||||
|
||||
/* Memory global utility routines */
|
||||
|
||||
extern HP_WORD mem_read (DEVICE *dptr, ACCESS_CLASS classification, HP_WORD address);
|
||||
extern void mem_write (DEVICE *dptr, ACCESS_CLASS classification, HP_WORD address, HP_WORD value);
|
||||
extern uint8 mem_read_byte (DEVICE *dptr, ACCESS_CLASS classification, HP_WORD byte_address);
|
||||
extern void mem_write_byte (DEVICE *dptr, ACCESS_CLASS classification, HP_WORD byte_address, uint8 value);
|
||||
|
||||
extern HP_WORD mem_fast_read (HP_WORD address, uint32 map);
|
||||
extern HP_WORD mem_examine (uint32 address);
|
||||
extern void mem_deposit (uint32 address, HP_WORD value);
|
||||
|
||||
|
||||
/* Memory Expansion Unit global utility routines */
|
||||
|
||||
extern uint16 dms_rmap (uint32 mapi);
|
||||
extern void dms_wmap (uint32 mapi, uint32 dat);
|
||||
extern void dms_viol (uint32 va, HP_WORD st);
|
||||
extern HP_WORD dms_upd_vr (uint32 va);
|
||||
extern HP_WORD dms_upd_sr (void);
|
||||
|
||||
|
||||
/* Memory Protect global utility routines */
|
||||
|
||||
extern void mp_dms_jmp (uint32 va, uint32 plb);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* hp2100_cpu0.c: HP 1000 user microcode and unimplemented instruction set stubs
|
||||
|
||||
Copyright (c) 2006-2012, J. David Bryan
|
||||
Copyright (c) 2006-2017, J. David Bryan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
CPU0 User microcode and unimplemented firmware options
|
||||
|
||||
01-Aug-17 JDB Changed .FLUN and self-tests to test for unimplemented stops
|
||||
09-May-12 JDB Separated assignments from conditional expressions
|
||||
04-Nov-10 JDB Removed DS note regarding PIF card (is now implemented)
|
||||
18-Sep-08 JDB .FLUN and self-tests for VIS and SIGNAL are NOP if not present
|
||||
@@ -138,8 +139,8 @@ if (op_ds [entry] != OP_N) {
|
||||
|
||||
switch (entry) { /* decode IR<3:0> */
|
||||
|
||||
default: /* others undefined */
|
||||
reason = stop_inst;
|
||||
default: /* others unimplemented */
|
||||
reason = STOP (cpu_ss_unimpl);
|
||||
}
|
||||
|
||||
return reason;
|
||||
@@ -151,7 +152,7 @@ return reason;
|
||||
All UIG instructions unclaimed by installed firmware options are directed
|
||||
here. User- or site-specific firmware may be simulated by dispatching to the
|
||||
appropriate simulator routine. Unimplemented instructions should return
|
||||
"stop_inst" to cause a simulator stop if enabled.
|
||||
"STOP (cpu_ss_unimpl)" to cause a simulator stop if enabled.
|
||||
|
||||
Implementation notes:
|
||||
|
||||
@@ -182,15 +183,7 @@ t_stat cpu_user (uint32 IR, uint32 intrq)
|
||||
t_stat reason = SCPE_OK;
|
||||
|
||||
if (UNIT_CPU_TYPE == UNIT_TYPE_211X) /* 2116/15/14 CPU? */
|
||||
return stop_inst; /* user microprograms not supported */
|
||||
|
||||
switch (IR) {
|
||||
case 0105226: /* firmware detection: FFP .FLUN */
|
||||
case 0105355: /* firmware detection: RTE-6/VM OS self-test */
|
||||
case 0105477: /* firmware detection: VIS self-test */
|
||||
case 0105617: /* firmware detection: SIGNAL/1000 self-test */
|
||||
return SCPE_OK; /* execute as NOP */
|
||||
}
|
||||
return STOP (cpu_ss_unimpl); /* user microprograms not supported */
|
||||
|
||||
switch ((IR >> 4) & 037) { /* decode IR<8:4> */
|
||||
|
||||
@@ -212,8 +205,8 @@ switch ((IR >> 4) & 037) { /* decode IR<8:4> */
|
||||
/* case 0nn: ** other cases as needed */
|
||||
/* return cpu_user_nn (IR, intrq); ** uncomment to handle instruction */
|
||||
|
||||
default: /* others undefined */
|
||||
reason = stop_inst;
|
||||
default: /* others unimplemented */
|
||||
reason = STOP (cpu_ss_unimpl);
|
||||
}
|
||||
|
||||
return reason;
|
||||
@@ -223,8 +216,8 @@ return reason;
|
||||
/* Example user microprogram simulator.
|
||||
|
||||
User- or site-specific firmware may be simulated by writing the appropriate
|
||||
code below. Unimplemented instructions should return "stop_inst" to cause a
|
||||
simulator stop if enabled.
|
||||
code below. Unimplemented instructions should return "STOP (cpu_ss_unimpl)"
|
||||
to cause a simulator stop if enabled.
|
||||
|
||||
For information on the operand patterns used in the "op_user" array, see the
|
||||
comments preceding the "cpu_ops" routine in "hp2100_cpu1.c" and the "operand
|
||||
@@ -263,8 +256,8 @@ switch (entry) { /* decode IR<4:0> */
|
||||
/* case 0nn: ** other cases as needed */
|
||||
/* break; ** uncomment to handle instruction */
|
||||
|
||||
default: /* others undefined */
|
||||
reason = stop_inst;
|
||||
default: /* others unimplemented */
|
||||
reason = STOP (cpu_ss_unimpl);
|
||||
}
|
||||
|
||||
return reason;
|
||||
|
||||
@@ -26,8 +26,14 @@
|
||||
|
||||
CPU1 Extended arithmetic and optional microcode dispatchers
|
||||
|
||||
07-Sep-17 JDB Removed unnecessary "uint16" casts
|
||||
01-Aug-17 JDB Changed TIMER and RRR 16 to test for undefined stops
|
||||
07-Jul-17 JDB Changed "iotrap" from uint32 to t_bool
|
||||
26-Jun-17 JDB Replaced SEXT with SEXT16
|
||||
22-Apr-17 JDB Improved the EAU shift/rotate instructions
|
||||
21-Mar-17 JDB Fixed UIG 1 comment regarding 2000 IOP and F-Series
|
||||
31-Jan-17 JDB Added fmt_ab to print A/B-register error codes
|
||||
30-Jan-17 JDB Removed fprint_ops, fprint_regs (now redundant)
|
||||
05-Aug-16 JDB Renamed the P register from "PC" to "PR"
|
||||
24-Dec-14 JDB Added casts for explicit downward conversions
|
||||
05-Apr-14 JDB Corrected typo in comments for cpu_ops
|
||||
@@ -121,16 +127,18 @@
|
||||
The design of the 1000 microinstruction set was such that executing an
|
||||
instruction for which no microcode was present (e.g., executing a FFP
|
||||
instruction when the FFP firmware was not installed) resulted in a NOP.
|
||||
Under simulation, such execution causes an undefined instruction stop if
|
||||
"stop_inst" is non-zero and a NOP otherwise.
|
||||
Under simulation, such execution causes an unimplemented instruction stop if
|
||||
"STOP (cpu_ss_unimpl)" is non-zero and a no-operation otherwise.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "hp2100_defs.h"
|
||||
#include "hp2100_cpu.h"
|
||||
#include "hp2100_cpu1.h"
|
||||
|
||||
|
||||
|
||||
/* EAU
|
||||
|
||||
The Extended Arithmetic Unit (EAU) adds ten instructions with double-word
|
||||
@@ -175,13 +183,15 @@
|
||||
EXECUTE (100120), is also described but was never implemented, and the
|
||||
E/F-series microcode execute a NOP for this instruction code.
|
||||
|
||||
If the EAU is not installed in a 2115 or 2116, EAU instructions execute as
|
||||
NOPs or cause unimplemented instruction stops if enabled.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. Under simulation, TIMER, DIAG, and EXECUTE cause undefined instruction
|
||||
stops if the CPU is set to 21xx. DIAG and EXECUTE also cause stops on
|
||||
the 1000-M. TIMER does not, because it is used by several HP programs
|
||||
to differentiate between M- and E/F-series machines.
|
||||
1. Under simulation, TIMER and DIAG cause undefined instruction stops if the
|
||||
CPU is not an E/F-Series. Note that TIMER is intentionally executed by
|
||||
several HP programs to differentiate between M- and E/F-series machines.
|
||||
|
||||
2. DIAG is not implemented under simulation. On the E/F, it performs a
|
||||
destructive test of all installed memory. Because of this, it is only
|
||||
@@ -189,9 +199,9 @@
|
||||
executed with the INSTR STEP button. If it is executed in a program,
|
||||
the result is NOP.
|
||||
|
||||
3. RRR is permitted and executed as NOP if the CPU is a 2114, as the
|
||||
presence of the EAU is tested by the diagnostic configurator to
|
||||
differentiate between 2114 and 2100/1000 CPUs.
|
||||
3. The RRR 16 instruction is intentionally executed by the diagnostic
|
||||
configurator on the 2114, which does not have an EAU, to differentiate
|
||||
between 2114 and 2100/1000 CPUs.
|
||||
|
||||
4. The shift count is calculated unconditionally, as six of the ten
|
||||
instructions will be using the value.
|
||||
@@ -215,11 +225,8 @@ OPS op;
|
||||
uint32 rs, qs, v1, v2, operand, fill, mask, shift;
|
||||
int32 sop1, sop2;
|
||||
|
||||
if ((cpu_unit.flags & UNIT_EAU) == 0) /* option installed? */
|
||||
if (UNIT_CPU_MODEL == UNIT_2114 && IR == 0101100) /* 2114 and RRR 16? */
|
||||
return SCPE_OK; /* allowed as NOP */
|
||||
else
|
||||
return stop_inst; /* fail */
|
||||
if ((cpu_unit.flags & UNIT_EAU) == 0) /* if the EAU is not installed */
|
||||
return STOP (cpu_ss_unimpl); /* then the instructions execute as NOPs */
|
||||
|
||||
if (IR & 017) /* if the shift count is 1-15 */
|
||||
shift = IR & 017; /* then use it verbatim */
|
||||
@@ -232,10 +239,10 @@ switch ((IR >> 8) & 0377) { /* decode IR<15:8> */
|
||||
switch ((IR >> 4) & 017) { /* decode IR<7:4> */
|
||||
|
||||
case 000: /* DIAG 100000 */
|
||||
if ((UNIT_CPU_MODEL != UNIT_1000_E) && /* must be 1000 E-series */
|
||||
(UNIT_CPU_MODEL != UNIT_1000_F)) /* or 1000 F-series */
|
||||
return stop_inst; /* trap if not */
|
||||
break; /* DIAG is NOP unless halted */
|
||||
if (UNIT_CPU_MODEL != UNIT_1000_E /* if the CPU is not an E-series */
|
||||
&& UNIT_CPU_MODEL != UNIT_1000_F) /* or an F-series */
|
||||
return STOP (cpu_ss_undef); /* then the instruction is undefined */
|
||||
break; /* and executes as NOP */
|
||||
|
||||
|
||||
case 001: /* ASL 100020-100037 */
|
||||
@@ -277,25 +284,31 @@ switch ((IR >> 8) & 0377) { /* decode IR<15:8> */
|
||||
|
||||
|
||||
case 003: /* TIMER 100060 */
|
||||
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* must be 1000 */
|
||||
return stop_inst; /* trap if not */
|
||||
if (UNIT_CPU_MODEL == UNIT_1000_E /* if the CPU is an E-series */
|
||||
|| UNIT_CPU_MODEL == UNIT_1000_F) { /* or an F-series */
|
||||
BR = BR + 1 & R_MASK; /* then increment B */
|
||||
|
||||
if (UNIT_CPU_MODEL != UNIT_1000_M) { /* 1000 E/F-series? */
|
||||
BR = (BR + 1) & DMASK; /* increment B */
|
||||
|
||||
if (BR) /* if !=0, repeat */
|
||||
PR = err_PC;
|
||||
if (BR != 0) /* if B did not roll over */
|
||||
PR = err_PC; /* then repeat the instruction */
|
||||
break;
|
||||
}
|
||||
|
||||
else { /* otherwise it's a 21xx or 1000 M-Series */
|
||||
reason = STOP (cpu_ss_undef); /* and the instruction is undefined */
|
||||
|
||||
if (reason != SCPE_OK /* if a stop is indicated */
|
||||
|| UNIT_CPU_MODEL != UNIT_1000_M) /* or the CPU is a 21xx */
|
||||
break; /* then the instruction executes as NOP */
|
||||
}
|
||||
|
||||
/* fall into the MPY case if 1000 M-Series */
|
||||
|
||||
case 010: /* MPY 100200 (OP_K) */
|
||||
reason = cpu_ops (OP_K, op, intrq); /* get operand */
|
||||
|
||||
if (reason == SCPE_OK) { /* successful eval? */
|
||||
sop1 = SEXT (AR); /* sext AR */
|
||||
sop2 = SEXT (op[0].word); /* sext mem */
|
||||
sop1 = SEXT16 (AR); /* sext AR */
|
||||
sop2 = SEXT16 (op[0].word); /* sext mem */
|
||||
sop1 = sop1 * sop2; /* signed mpy */
|
||||
BR = UPPER_WORD (sop1); /* to BR'AR */
|
||||
AR = LOWER_WORD (sop1);
|
||||
@@ -305,7 +318,7 @@ switch ((IR >> 8) & 0377) { /* decode IR<15:8> */
|
||||
|
||||
|
||||
default: /* others undefined */
|
||||
return stop_inst;
|
||||
return STOP (cpu_ss_unimpl);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -392,7 +405,7 @@ switch ((IR >> 8) & 0377) { /* decode IR<15:8> */
|
||||
|
||||
|
||||
default: /* others undefined */
|
||||
return stop_inst;
|
||||
return STOP (cpu_ss_undef);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -480,7 +493,7 @@ return reason;
|
||||
user microcode dispatcher.
|
||||
*/
|
||||
|
||||
t_stat cpu_uig_0 (uint32 IR, uint32 intrq, uint32 iotrap)
|
||||
t_stat cpu_uig_0 (uint32 IR, uint32 intrq, t_bool iotrap)
|
||||
{
|
||||
if ((cpu_unit.flags & UNIT_IOP) && /* I/O Processor? */
|
||||
(UNIT_CPU_TYPE == UNIT_TYPE_2100)) /* and 2100 CPU? */
|
||||
@@ -621,10 +634,10 @@ return cpu_user (IR, intrq); /* try user microcode */
|
||||
user microcode dispatcher.
|
||||
*/
|
||||
|
||||
t_stat cpu_uig_1 (uint32 IR, uint32 intrq, uint32 iotrap)
|
||||
t_stat cpu_uig_1 (uint32 IR, uint32 intrq, t_bool iotrap)
|
||||
{
|
||||
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* 1000 execution? */
|
||||
return stop_inst; /* no, so trap */
|
||||
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* if the CPU is not a 1000 */
|
||||
return STOP (cpu_ss_unimpl); /* the the instruction is unimplemented */
|
||||
|
||||
switch ((IR >> 4) & 017) { /* decode IR<7:4> */
|
||||
|
||||
@@ -680,7 +693,7 @@ return cpu_user (IR, intrq); /* try user microcode */
|
||||
|
||||
/* Read a multiple-precision operand value. */
|
||||
|
||||
OP ReadOp (uint32 va, OPSIZE precision)
|
||||
OP ReadOp (HP_WORD va, OPSIZE precision)
|
||||
{
|
||||
OP operand;
|
||||
uint32 i;
|
||||
@@ -702,7 +715,7 @@ return operand;
|
||||
|
||||
/* Write a multiple-precision operand value. */
|
||||
|
||||
void WriteOp (uint32 va, OP operand, OPSIZE precision)
|
||||
void WriteOp (HP_WORD va, OP operand, OPSIZE precision)
|
||||
{
|
||||
uint32 i;
|
||||
|
||||
@@ -810,19 +823,29 @@ return;
|
||||
An operand pattern consists of one or more operand encodings, corresponding
|
||||
to the operands required by a given instruction. Values are returned in
|
||||
sequence to the operand array.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. The reads of address operand words that follow an instruction (e.g., the
|
||||
DEFs above) are classified as instruction fetches. The reads of the
|
||||
operands themselves are classified as data accesses.
|
||||
*/
|
||||
|
||||
t_stat cpu_ops (OP_PAT pattern, OPS op, uint32 irq)
|
||||
{
|
||||
t_stat reason = SCPE_OK;
|
||||
OP_PAT flags;
|
||||
uint32 i, MA;
|
||||
OP_PAT flags;
|
||||
uint32 i;
|
||||
HP_WORD MA, address;
|
||||
t_stat reason = SCPE_OK;
|
||||
|
||||
for (i = 0; i < OP_N_F; i++) {
|
||||
flags = pattern & OP_M_FLAGS; /* get operand pattern */
|
||||
|
||||
if (flags >= OP_ADR) { /* address operand? */
|
||||
reason = resolve (ReadW (PR), &MA, irq); /* resolve indirects */
|
||||
address = ReadF (PR); /* get the pointer */
|
||||
|
||||
reason = resolve (address, &MA, irq); /* resolve indirects */
|
||||
if (reason != SCPE_OK) /* resolution failed? */
|
||||
return reason;
|
||||
}
|
||||
@@ -849,11 +872,11 @@ for (i = 0; i < OP_N_F; i++) {
|
||||
break;
|
||||
|
||||
case OP_VAR: /* inline variable operand */
|
||||
(*op++).word = (uint16) PR; /* get pointer to variable */
|
||||
(*op++).word = PR; /* get pointer to variable */
|
||||
break;
|
||||
|
||||
case OP_ADR: /* inline address operand */
|
||||
(*op++).word = (uint16) MA; /* get address (set by "resolve" above) */
|
||||
(*op++).word = MA; /* get address (set by "resolve" above) */
|
||||
break;
|
||||
|
||||
case OP_ADK: /* address of int constant */
|
||||
@@ -892,117 +915,33 @@ return reason;
|
||||
}
|
||||
|
||||
|
||||
/* Print operands to the debug device.
|
||||
/* Format an error code in the A and B registers.
|
||||
|
||||
The values of an operand array are printed to the debug device. The types of
|
||||
the operands are specified by an operand pattern. Typically, the operand
|
||||
pattern is the same one that was used to fill the array originally.
|
||||
This routine conditionally formats the contents of the A and B registers into
|
||||
an error message. If the supplied "success" flag is 0, the A and B registers
|
||||
contain a four-character error code (e.g., "EM82"), with the leading
|
||||
characters in the B register. The characters are moved into the error
|
||||
message, and a pointer to the message is returned. If "success" is non-zero,
|
||||
then a pointer to the message reporting normal execution is returned.
|
||||
|
||||
The routine is typically called from an instructio executor during operand
|
||||
tracing.
|
||||
*/
|
||||
|
||||
void fprint_ops (OP_PAT pattern, OPS op)
|
||||
const char *fmt_ab (t_bool success)
|
||||
{
|
||||
OP_PAT flags;
|
||||
uint32 i;
|
||||
static const char good [] = "normal";
|
||||
static char error [] = "error ....";
|
||||
|
||||
for (i = 0; i < OP_N_F; i++) {
|
||||
flags = pattern & OP_M_FLAGS; /* get operand pattern */
|
||||
if (success) /* if the instruction succeeded */
|
||||
return good; /* then report a normal completion */
|
||||
|
||||
switch (flags) {
|
||||
case OP_NUL: /* null operand */
|
||||
return; /* no more, so quit */
|
||||
else { /* otherwise */
|
||||
error [6] = UPPER_BYTE (BR); /* format the */
|
||||
error [7] = LOWER_BYTE (BR); /* error code */
|
||||
error [8] = UPPER_BYTE (AR); /* into the */
|
||||
error [9] = LOWER_BYTE (AR); /* error message */
|
||||
|
||||
case OP_IAR: /* int in A */
|
||||
case OP_CON: /* inline constant operand */
|
||||
case OP_VAR: /* inline variable operand */
|
||||
case OP_ADR: /* inline address operand */
|
||||
case OP_ADK: /* address of int constant */
|
||||
fprintf (sim_deb,
|
||||
", op[%d] = %06o",
|
||||
i, op[i].word);
|
||||
break;
|
||||
|
||||
case OP_JAB: /* dbl-int in A/B */
|
||||
case OP_ADD: /* address of dbl-int constant */
|
||||
fprintf (sim_deb,
|
||||
", op[%d] = %011o",
|
||||
i, op[i].dword);
|
||||
break;
|
||||
|
||||
case OP_FAB: /* 2-word FP in A/B */
|
||||
case OP_ADF: /* address of 2-word FP const */
|
||||
fprintf (sim_deb,
|
||||
", op[%d] = (%06o, %06o)",
|
||||
i, op[i].fpk[0], op[i].fpk[1]);
|
||||
break;
|
||||
|
||||
case OP_ADX: /* address of 3-word FP const */
|
||||
fprintf (sim_deb,
|
||||
", op[%d] = (%06o, %06o, %06o)",
|
||||
i, op[i].fpk[0], op[i].fpk[1],
|
||||
op[i].fpk[2]);
|
||||
break;
|
||||
|
||||
case OP_ADT: /* address of 4-word FP const */
|
||||
fprintf (sim_deb,
|
||||
", op[%d] = (%06o, %06o, %06o, %06o)",
|
||||
i, op[i].fpk[0], op[i].fpk[1],
|
||||
op[i].fpk[2], op[i].fpk[3]);
|
||||
break;
|
||||
|
||||
case OP_ADE: /* address of 5-word FP const */
|
||||
fprintf (sim_deb,
|
||||
", op[%d] = (%06o, %06o, %06o, %06o, %06o)",
|
||||
i, op[i].fpk[0], op[i].fpk[1],
|
||||
op[i].fpk[2], op[i].fpk[3], op[i].fpk[4]);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf (sim_deb, "UNKNOWN OPERAND TYPE"); /* not implemented */
|
||||
}
|
||||
|
||||
pattern = pattern >> OP_N_FLAGS; /* move next pattern into place */
|
||||
return error; /* report an abnormal completion */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Print CPU registers to the debug device.
|
||||
|
||||
One or more CPU registers may be printed to the debug output device, which
|
||||
must be valid before calling.
|
||||
*/
|
||||
|
||||
void fprint_regs (char *caption, uint32 regs, uint32 base)
|
||||
{
|
||||
static uint32 ARX, BRX, PRL; /* static so addresses are constant */
|
||||
|
||||
static const char *reg_names[] = { "CIR", "A", "B", "E", "X", "Y", "O", "P", "return" };
|
||||
static const uint32 *reg_ptrs[] = { &intaddr, &ARX, &BRX, &E, &XR, &YR, &O, &PR, &PRL };
|
||||
static const char *formats[] = { "%02o", "%06o", "%06o", "%01o", "%06o", "%06o", "%01o", "%06o", "P+%d" };
|
||||
|
||||
static char format[20] = " %s = "; /* base format string */
|
||||
static const int eos = 6; /* length of base format string */
|
||||
|
||||
uint32 i;
|
||||
t_bool first = TRUE; /* first-time through flag */
|
||||
|
||||
ARX = AR; /* copy 16-bit value to static variable */
|
||||
BRX = BR; /* copy 16-bit value to static variable */
|
||||
PRL = PR - base; /* compute value in static variable */
|
||||
|
||||
for (i = 0; i < REG_COUNT; i++) {
|
||||
if (regs & 1) { /* register requested? */
|
||||
if (first) /* first time? */
|
||||
fputs (caption, sim_deb); /* print caption */
|
||||
else
|
||||
fputc (',', sim_deb); /* print separator */
|
||||
|
||||
strcpy (&format[eos], formats[i]); /* copy format specifier */
|
||||
fprintf (sim_deb, format, reg_names[i], *reg_ptrs[i]);
|
||||
|
||||
first = FALSE;
|
||||
}
|
||||
|
||||
regs = regs >> 1; /* align next register flag */
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* hp2100_cpu1.h: HP 2100/1000 firmware dispatcher definitions
|
||||
/* hp2100_cpu1.h: HP 2100/1000 firmware dispatcher declarations
|
||||
|
||||
Copyright (c) 2006-2013, J. David Bryan
|
||||
Copyright (c) 2006-2017, J. David Bryan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -23,6 +23,10 @@
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from the author.
|
||||
|
||||
07-Jul-17 JDB Changed "iotrap" from uint32 to t_bool
|
||||
15-Feb-17 JDB Deleted unneeded guard macro definition
|
||||
26-Jan-17 JDB Removed debug parameters from cpu_ema_* routines
|
||||
17-Jan-17 JDB Removed register print encoding constants (now redundant)
|
||||
18-Mar-13 JDB Added externs for microcode helper functions
|
||||
14-Mar-13 MP Changed guard macro name to avoid reserved namespace
|
||||
11-Sep-08 JDB Moved microcode function prototypes here
|
||||
@@ -35,23 +39,6 @@
|
||||
26-Sep-06 JDB Split from hp2100_cpu1.c
|
||||
*/
|
||||
|
||||
#ifndef HP2100_CPU1_H_
|
||||
#define HP2100_CPU1_H_
|
||||
|
||||
|
||||
/* Register print encoding */
|
||||
|
||||
#define REG_COUNT 9 /* count of print flags */
|
||||
|
||||
#define REG_CIR (1 << 0) /* print central interrupt register */
|
||||
#define REG_A (1 << 1) /* print A register */
|
||||
#define REG_B (1 << 2) /* print B register */
|
||||
#define REG_E (1 << 3) /* print E register */
|
||||
#define REG_X (1 << 4) /* print X register */
|
||||
#define REG_Y (1 << 5) /* print Y register */
|
||||
#define REG_O (1 << 6) /* print O register */
|
||||
#define REG_P (1 << 7) /* print P register */
|
||||
#define REG_P_REL (1 << 8) /* print P register as relative */
|
||||
|
||||
|
||||
/* Operand processing encoding */
|
||||
@@ -246,7 +233,7 @@ typedef enum { in_s, in_d, fp_f, fp_x, fp_t, fp_e, fp_a } OPSIZE;
|
||||
Actual value will use two, three, four, or five words, as needed.
|
||||
*/
|
||||
|
||||
typedef uint16 FPK[5];
|
||||
typedef HP_WORD FPK [5];
|
||||
|
||||
|
||||
/* Operand processing types.
|
||||
@@ -259,9 +246,9 @@ typedef uint16 FPK[5];
|
||||
*/
|
||||
|
||||
typedef union { /* general operand */
|
||||
FPK fpk; /* floating-point value */
|
||||
uint16 word; /* 16-bit integer */
|
||||
uint32 dword; /* 32-bit integer */
|
||||
FPK fpk; /* floating-point value */
|
||||
HP_WORD word; /* 16-bit integer */
|
||||
uint32 dword; /* 32-bit integer */
|
||||
} OP;
|
||||
|
||||
typedef OP OPS[OP_N_F]; /* operand array */
|
||||
@@ -276,8 +263,8 @@ extern t_stat cpu_user (uint32 IR, uint32 intrq); /* [0] User
|
||||
extern t_stat cpu_user_20 (uint32 IR, uint32 intrq); /* [0] Module 20 user microprograms stub */
|
||||
|
||||
extern t_stat cpu_eau (uint32 IR, uint32 intrq); /* [1] EAU group simulator */
|
||||
extern t_stat cpu_uig_0 (uint32 IR, uint32 intrq, uint32 iotrap); /* [1] UIG group 0 dispatcher */
|
||||
extern t_stat cpu_uig_1 (uint32 IR, uint32 intrq, uint32 iotrap); /* [1] UIG group 1 dispatcher */
|
||||
extern t_stat cpu_uig_0 (uint32 IR, uint32 intrq, t_bool iotrap); /* [1] UIG group 0 dispatcher */
|
||||
extern t_stat cpu_uig_1 (uint32 IR, uint32 intrq, t_bool iotrap); /* [1] UIG group 1 dispatcher */
|
||||
|
||||
#if !defined (HAVE_INT64) /* int64 support unavailable */
|
||||
extern t_stat cpu_fp (uint32 IR, uint32 intrq); /* [2] Firmware Floating Point */
|
||||
@@ -297,7 +284,7 @@ extern t_stat cpu_sis (uint32 IR, uint32 intrq); /* [4] Scien
|
||||
extern t_stat cpu_rte_vma (uint32 IR, uint32 intrq); /* [5] RTE-6 VMA */
|
||||
extern t_stat cpu_rte_ema (uint32 IR, uint32 intrq); /* [5] RTE-IV EMA */
|
||||
|
||||
extern t_stat cpu_rte_os (uint32 IR, uint32 intrq, uint32 iotrap); /* [6] RTE-6 OS */
|
||||
extern t_stat cpu_rte_os (uint32 IR, uint32 intrq, t_bool iotrap); /* [6] RTE-6 OS */
|
||||
|
||||
#if defined (HAVE_INT64) /* int64 support available */
|
||||
extern t_stat cpu_vis (uint32 IR, uint32 intrq); /* [7] Vector Instruction Set */
|
||||
@@ -307,17 +294,14 @@ extern t_stat cpu_signal (uint32 IR, uint32 intrq); /* [7] SIGNA
|
||||
|
||||
/* Microcode helper functions */
|
||||
|
||||
extern OP ReadOp (uint32 va, OPSIZE precision); /* generalized operand read */
|
||||
extern void WriteOp (uint32 va, OP operand, OPSIZE precision); /* generalized operand write */
|
||||
extern t_stat cpu_ops (OP_PAT pattern, OPS op, uint32 irq); /* operand processor */
|
||||
extern OP ReadOp (HP_WORD va, OPSIZE precision); /* generalized operand read */
|
||||
extern void WriteOp (HP_WORD va, OP operand, OPSIZE precision); /* generalized operand write */
|
||||
extern t_stat cpu_ops (OP_PAT pattern, OPS op, uint32 irq); /* operand processor */
|
||||
|
||||
extern void fprint_ops (OP_PAT pattern, OPS op); /* debug print operands */
|
||||
extern void fprint_regs (char *caption, uint32 regs, uint32 base); /* debug print CPU registers */
|
||||
extern const char *fmt_ab (t_bool success); /* format an error code in the A/B registers */
|
||||
|
||||
/* implemented in hp2100_cpu5.c (RTE-IV EMA functions) */
|
||||
|
||||
extern t_stat cpu_ema_eres (uint32 *rtn, uint32 dtbl, uint32 atbl, t_bool debug);
|
||||
extern t_stat cpu_ema_eseg (uint32 *rtn, uint32 ir, uint32 tbl, t_bool debug);
|
||||
extern t_stat cpu_ema_vset (uint32 *rtn, OPS op, t_bool debug);
|
||||
|
||||
#endif
|
||||
extern t_stat cpu_ema_eres (HP_WORD *rtn, uint32 dtbl, uint32 atbl);
|
||||
extern t_stat cpu_ema_eseg (HP_WORD *rtn, uint32 ir, uint32 tbl);
|
||||
extern t_stat cpu_ema_vset (HP_WORD *rtn, OPS op);
|
||||
|
||||
@@ -1,31 +1,37 @@
|
||||
/* hp2100_cpu2.c: HP 2100/1000 FP/DMS/EIG/IOP instructions
|
||||
|
||||
Copyright (c) 2005-2016, Robert M. Supnik
|
||||
Copyright (c) 2017 J. David Bryan
|
||||
|
||||
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:
|
||||
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.
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHOR 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
|
||||
Except as contained in this notice, the names of the authors 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.
|
||||
in this Software without prior written authorization from the authors.
|
||||
|
||||
CPU2 Floating-point, dynamic mapping, extended, and I/O processor
|
||||
instructions
|
||||
|
||||
07-Sep-17 JDB Removed unnecessary "uint16" casts
|
||||
10-Jul-17 JDB Renamed the global routine "iogrp" to "cpu_iog"
|
||||
26-Jun-17 JDB Replaced SEXT with SEXT16
|
||||
22-Mar-17 JDB Corrected comments regarding IR bit 11 selecting A/B
|
||||
25-Jan-17 JDB Set mp_mem_changed whenever MEM registers are changed
|
||||
05-Aug-16 JDB Renamed the P register from "PC" to "PR"
|
||||
24-Dec-14 JDB Added casts for explicit downward conversions
|
||||
09-May-12 JDB Separated assignments from conditional expressions
|
||||
@@ -202,12 +208,13 @@ return reason;
|
||||
10x716 [nop] [nop] 10x736 UJP UJP
|
||||
10x717 [nop] [nop] 10x737 UJS UJS
|
||||
|
||||
Instructions that use IR bit 9 to select the A or B register are designated
|
||||
Instructions that use IR bit 11 to select the A or B register are designated
|
||||
with a * above (e.g., 101710 is SYA, and 105710 is SYB). For those that do
|
||||
not use this feature, either the 101xxx or 105xxx code will execute the
|
||||
corresponding instruction, although the 105xxx form is the documented
|
||||
instruction code.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. Instruction code 10x700 will execute the XMM instruction, although 10x720
|
||||
@@ -221,8 +228,8 @@ return reason;
|
||||
- load map and CTL5 set (XMM, XMS, XM*, SY*, US*, PA*, PB*)
|
||||
- load state or fence and UMAP set (JRS, DJP, DJS, SJP, SJS, UJP, UJS, LF*)
|
||||
|
||||
4. The 1000 manual is incorrect in stating that M*I, M*W, XS* are
|
||||
privileged.
|
||||
4. DM (write) violations for the use of the MBI, MWI, MBW, MWW, XSA, and XSB
|
||||
instructions in protected mode are generated by the mem_write routine.
|
||||
|
||||
5. The protected memory lower bound for the DJP, SJP, UJP, and JRS
|
||||
instructions is 2.
|
||||
@@ -243,8 +250,9 @@ t_stat cpu_dms (uint32 IR, uint32 intrq)
|
||||
{
|
||||
t_stat reason = SCPE_OK;
|
||||
OPS op;
|
||||
uint32 entry, absel;
|
||||
uint32 i, t, mapi, mapj;
|
||||
uint8 byte;
|
||||
uint32 entry, absel, i, mapi, mapj;
|
||||
HP_WORD t;
|
||||
|
||||
absel = (IR & I_AB)? 1: 0; /* get A/B select */
|
||||
entry = IR & 037; /* mask to entry point */
|
||||
@@ -272,8 +280,8 @@ switch (entry) { /* decode IR<3:0> */
|
||||
AR = AR & ~1; /* force A, B even */
|
||||
BR = BR & ~1;
|
||||
while (XR != 0) { /* loop */
|
||||
t = ReadB (AR); /* read curr */
|
||||
WriteBA (BR, t); /* write alt */
|
||||
byte = ReadB (AR); /* read curr */
|
||||
WriteBA (BR, byte); /* write alt */
|
||||
AR = (AR + 1) & DMASK; /* incr ptrs */
|
||||
BR = (BR + 1) & DMASK;
|
||||
XR = (XR - 1) & DMASK;
|
||||
@@ -288,8 +296,8 @@ switch (entry) { /* decode IR<3:0> */
|
||||
AR = AR & ~1; /* force A, B even */
|
||||
BR = BR & ~1;
|
||||
while (XR != 0) { /* loop */
|
||||
t = ReadBA (AR); /* read alt */
|
||||
WriteB (BR, t); /* write curr */
|
||||
byte = ReadBA (AR); /* read alt */
|
||||
WriteB (BR, byte); /* write curr */
|
||||
AR = (AR + 1) & DMASK; /* incr ptrs */
|
||||
BR = (BR + 1) & DMASK;
|
||||
XR = (XR - 1) & DMASK;
|
||||
@@ -304,8 +312,8 @@ switch (entry) { /* decode IR<3:0> */
|
||||
AR = AR & ~1; /* force A, B even */
|
||||
BR = BR & ~1;
|
||||
while (XR != 0) { /* loop */
|
||||
t = ReadBA (AR); /* read alt */
|
||||
WriteBA (BR, t); /* write alt */
|
||||
byte = ReadBA (AR); /* read alt */
|
||||
WriteBA (BR, byte); /* write alt */
|
||||
AR = (AR + 1) & DMASK; /* incr ptrs */
|
||||
BR = (BR + 1) & DMASK;
|
||||
XR = (XR - 1) & DMASK;
|
||||
@@ -391,10 +399,11 @@ switch (entry) { /* decode IR<3:0> */
|
||||
dms_enb = 1;
|
||||
if (op[0].word & 0040000) dms_ump = UMAP; /* set/clr usr */
|
||||
}
|
||||
mp_mem_changed = TRUE; /* set the MP/MEM registers changed flag */
|
||||
mp_dms_jmp (op[1].word, 2); /* mpck jmp target */
|
||||
PCQ_ENTRY; /* save old P */
|
||||
PR = op[1].word; /* jump */
|
||||
ion_defer = 1; /* defer intr */
|
||||
ion_defer = TRUE; /* defer intr */
|
||||
break;
|
||||
|
||||
/* DMS module 2 */
|
||||
@@ -467,14 +476,16 @@ switch (entry) { /* decode IR<3:0> */
|
||||
if (dms_ump) dms_viol (err_PC, MVI_PRV); /* priv viol if prot */
|
||||
dms_sr = (dms_sr & ~(MST_FLT | MST_FENCE)) |
|
||||
(ABREG[absel] & (MST_FLT | MST_FENCE));
|
||||
|
||||
mp_mem_changed = TRUE; /* set the MP/MEM registers changed flag */
|
||||
break;
|
||||
|
||||
case 030: /* RSA, RSB 10x730 (OP_N) */
|
||||
ABREG[absel] = (uint16) dms_upd_sr (); /* save stat */
|
||||
ABREG [absel] = dms_upd_sr (); /* save stat */
|
||||
break;
|
||||
|
||||
case 031: /* RVA, RVB 10x731 (OP_N) */
|
||||
ABREG[absel] = (uint16) dms_upd_vr (err_PC); /* return updated violation register */
|
||||
ABREG [absel] = dms_upd_vr (err_PC); /* return updated violation register */
|
||||
break;
|
||||
|
||||
case 032: /* DJP 105732 (OP_A) */
|
||||
@@ -484,7 +495,7 @@ switch (entry) { /* decode IR<3:0> */
|
||||
mp_dms_jmp (op[0].word, 2); /* validate jump addr */
|
||||
PCQ_ENTRY; /* save curr P */
|
||||
PR = op[0].word; /* new P */
|
||||
ion_defer = 1;
|
||||
ion_defer = TRUE; /* defer interrupts */
|
||||
break;
|
||||
|
||||
case 033: /* DJS 105733 (OP_A) */
|
||||
@@ -494,7 +505,7 @@ switch (entry) { /* decode IR<3:0> */
|
||||
PR = (op[0].word + 1) & VAMASK; /* new P */
|
||||
dms_enb = 0; /* disable map */
|
||||
dms_ump = SMAP;
|
||||
ion_defer = 1; /* defer intr */
|
||||
ion_defer = TRUE; /* defer intr */
|
||||
break;
|
||||
|
||||
case 034: /* SJP 105734 (OP_A) */
|
||||
@@ -504,7 +515,7 @@ switch (entry) { /* decode IR<3:0> */
|
||||
mp_dms_jmp (op[0].word, 2); /* validate jump addr */
|
||||
PCQ_ENTRY; /* save curr P */
|
||||
PR = op[0].word; /* jump */
|
||||
ion_defer = 1; /* defer intr */
|
||||
ion_defer = TRUE; /* defer intr */
|
||||
break;
|
||||
|
||||
case 035: /* SJS 105735 (OP_A) */
|
||||
@@ -515,7 +526,7 @@ switch (entry) { /* decode IR<3:0> */
|
||||
dms_enb = 1; /* enable system */
|
||||
dms_ump = SMAP;
|
||||
WriteW (op[0].word, t); /* store ret addr */
|
||||
ion_defer = 1; /* defer intr */
|
||||
ion_defer = TRUE; /* defer intr */
|
||||
break;
|
||||
|
||||
case 036: /* UJP 105736 (OP_A) */
|
||||
@@ -525,7 +536,7 @@ switch (entry) { /* decode IR<3:0> */
|
||||
mp_dms_jmp (op[0].word, 2); /* validate jump addr */
|
||||
PCQ_ENTRY; /* save curr P */
|
||||
PR = op[0].word; /* jump */
|
||||
ion_defer = 1; /* defer intr */
|
||||
ion_defer = TRUE; /* defer intr */
|
||||
break;
|
||||
|
||||
case 037: /* UJS 105737 (OP_A) */
|
||||
@@ -536,7 +547,7 @@ switch (entry) { /* decode IR<3:0> */
|
||||
dms_enb = 1; /* enable user */
|
||||
dms_ump = UMAP;
|
||||
WriteW (op[0].word, t); /* store ret addr */
|
||||
ion_defer = 1; /* defer intr */
|
||||
ion_defer = TRUE; /* defer intr */
|
||||
break;
|
||||
|
||||
default: /* others NOP */
|
||||
@@ -581,7 +592,7 @@ return reason;
|
||||
10x756 ADY 10x776 CMW
|
||||
10x757 X*Y 10x777 MVW
|
||||
|
||||
Instructions that use IR bit 9 to select the A or B register are designated
|
||||
Instructions that use IR bit 11 to select the A or B register are designated
|
||||
with a * above (e.g., 101740 is SAX, and 105740 is SBX). For those that do
|
||||
not use this feature, either the 101xxx or 105xxx code will execute the
|
||||
corresponding instruction, although the 105xxx form is the documented
|
||||
@@ -611,8 +622,9 @@ t_stat cpu_eig (uint32 IR, uint32 intrq)
|
||||
{
|
||||
t_stat reason = SCPE_OK;
|
||||
OPS op;
|
||||
uint32 entry, absel;
|
||||
uint32 t, v1, v2, wc;
|
||||
uint8 byte, b1, b2;
|
||||
uint32 entry, absel, sum;
|
||||
HP_WORD t, v1, v2, wc;
|
||||
int32 sop1, sop2;
|
||||
|
||||
absel = (IR & I_AB)? 1: 0; /* get A/B select */
|
||||
@@ -648,7 +660,7 @@ switch (entry) { /* decode IR<4:0> */
|
||||
break;
|
||||
|
||||
case 004: /* CXA, CXB 10x744 (OP_N) */
|
||||
ABREG[absel] = (uint16) XR; /* copy from XR */
|
||||
ABREG [absel] = XR; /* copy from XR */
|
||||
break;
|
||||
|
||||
case 005: /* LDX 105745 (OP_K)*/
|
||||
@@ -656,16 +668,16 @@ switch (entry) { /* decode IR<4:0> */
|
||||
break;
|
||||
|
||||
case 006: /* ADX 105746 (OP_K) */
|
||||
t = XR + op[0].word; /* add to XR */
|
||||
if (t > DMASK) E = 1; /* set E, O */
|
||||
if (((~XR ^ op[0].word) & (XR ^ t)) & SIGN) O = 1;
|
||||
XR = t & DMASK;
|
||||
sum = XR + op[0].word; /* add to XR */
|
||||
if (sum > DMASK) E = 1; /* set E, O */
|
||||
if (((~XR ^ op[0].word) & (XR ^ sum)) & SIGN) O = 1;
|
||||
XR = sum & DMASK;
|
||||
break;
|
||||
|
||||
case 007: /* XAX, XBX 10x747 (OP_N) */
|
||||
t = XR; /* exchange XR */
|
||||
XR = ABREG[absel];
|
||||
ABREG[absel] = (uint16) t;
|
||||
XR = ABREG [absel];
|
||||
ABREG [absel] = t;
|
||||
break;
|
||||
|
||||
case 010: /* SAY, SBY 10x750 (OP_A) */
|
||||
@@ -687,7 +699,7 @@ switch (entry) { /* decode IR<4:0> */
|
||||
break;
|
||||
|
||||
case 014: /* CYA, CYB 10x754 (OP_N) */
|
||||
ABREG[absel] = (uint16) YR; /* copy from YR */
|
||||
ABREG [absel] = YR; /* copy from YR */
|
||||
break;
|
||||
|
||||
case 015: /* LDY 105755 (OP_K) */
|
||||
@@ -695,16 +707,16 @@ switch (entry) { /* decode IR<4:0> */
|
||||
break;
|
||||
|
||||
case 016: /* ADY 105756 (OP_K) */
|
||||
t = YR + op[0].word; /* add to YR */
|
||||
if (t > DMASK) E = 1; /* set E, O */
|
||||
if (((~YR ^ op[0].word) & (YR ^ t)) & SIGN) O = 1;
|
||||
YR = t & DMASK;
|
||||
sum = YR + op[0].word; /* add to YR */
|
||||
if (sum > DMASK) E = 1; /* set E, O */
|
||||
if (((~YR ^ op[0].word) & (YR ^ sum)) & SIGN) O = 1;
|
||||
YR = sum & DMASK;
|
||||
break;
|
||||
|
||||
case 017: /* XAY, XBY 10x757 (OP_N) */
|
||||
t = YR; /* exchange YR */
|
||||
YR = ABREG[absel];
|
||||
ABREG[absel] = (uint16) t;
|
||||
YR = ABREG [absel];
|
||||
ABREG [absel] = t;
|
||||
break;
|
||||
|
||||
/* EIG module 2 */
|
||||
@@ -732,7 +744,7 @@ switch (entry) { /* decode IR<4:0> */
|
||||
break;
|
||||
|
||||
case 024: /* SBT 105764 (OP_N) */
|
||||
WriteB (BR, AR); /* store byte */
|
||||
WriteB (BR, LOWER_BYTE (AR)); /* store byte */
|
||||
BR = (BR + 1) & DMASK; /* incr ptr */
|
||||
break;
|
||||
|
||||
@@ -744,8 +756,8 @@ switch (entry) { /* decode IR<4:0> */
|
||||
break; /* < 0 is NOP for 2100 IOP */
|
||||
while (wc != 0) { /* while count */
|
||||
WriteW (op[1].word, wc); /* for MP abort */
|
||||
t = ReadB (AR); /* move byte */
|
||||
WriteB (BR, t);
|
||||
byte = ReadB (AR); /* move byte */
|
||||
WriteB (BR, byte);
|
||||
AR = (AR + 1) & DMASK; /* incr src */
|
||||
BR = (BR + 1) & DMASK; /* incr dst */
|
||||
wc = (wc - 1) & DMASK; /* decr cnt */
|
||||
@@ -762,10 +774,10 @@ switch (entry) { /* decode IR<4:0> */
|
||||
if (wc == 0) wc = op[0].word; /* none? get initiation count */
|
||||
while (wc != 0) { /* while count */
|
||||
WriteW (op[1].word, wc); /* for MP abort */
|
||||
v1 = ReadB (AR); /* get src1 */
|
||||
v2 = ReadB (BR); /* get src2 */
|
||||
if (v1 != v2) { /* compare */
|
||||
PR = (PR + 1 + (v1 > v2)) & VAMASK;
|
||||
b1 = ReadB (AR); /* get src1 */
|
||||
b2 = ReadB (BR); /* get src2 */
|
||||
if (b1 != b2) { /* compare */
|
||||
PR = (PR + 1 + (b1 > b2)) & VAMASK;
|
||||
BR = (BR + wc) & DMASK; /* update BR */
|
||||
wc = 0; /* clr interim */
|
||||
break;
|
||||
@@ -782,13 +794,13 @@ switch (entry) { /* decode IR<4:0> */
|
||||
break;
|
||||
|
||||
case 027: /* SFB 105767 (OP_N) */
|
||||
v1 = AR & 0377; /* test byte */
|
||||
v2 = (AR >> 8) & 0377; /* term byte */
|
||||
b1 = LOWER_BYTE (AR); /* test byte */
|
||||
b2 = UPPER_BYTE (AR); /* term byte */
|
||||
for (;;) { /* scan */
|
||||
t = ReadB (BR); /* read byte */
|
||||
if (t == v1) break; /* test match? */
|
||||
byte = ReadB (BR); /* read byte */
|
||||
if (byte == b1) break; /* test match? */
|
||||
BR = (BR + 1) & DMASK;
|
||||
if (t == v2) { /* term match? */
|
||||
if (byte == b2) { /* term match? */
|
||||
PR = (PR + 1) & VAMASK;
|
||||
break;
|
||||
}
|
||||
@@ -838,8 +850,8 @@ switch (entry) { /* decode IR<4:0> */
|
||||
WriteW (op[1].word, wc); /* for abort */
|
||||
v1 = ReadW (AR & VAMASK); /* first op */
|
||||
v2 = ReadW (BR & VAMASK); /* second op */
|
||||
sop1 = (int32) SEXT (v1); /* signed */
|
||||
sop2 = (int32) SEXT (v2);
|
||||
sop1 = SEXT16 (v1); /* signed */
|
||||
sop2 = SEXT16 (v2);
|
||||
if (sop1 != sop2) { /* compare */
|
||||
PR = (PR + 1 + (sop1 > sop2)) & VAMASK;
|
||||
BR = (BR + wc) & DMASK; /* update BR */
|
||||
@@ -954,8 +966,9 @@ t_stat cpu_iop (uint32 IR, uint32 intrq)
|
||||
{
|
||||
t_stat reason = SCPE_OK;
|
||||
OPS op;
|
||||
uint32 entry;
|
||||
uint32 hp, tp, i, t, wc, MA;
|
||||
uint8 byte;
|
||||
uint32 entry, i;
|
||||
HP_WORD hp, tp, t, wc, MA;
|
||||
|
||||
if (UNIT_CPU_TYPE == UNIT_TYPE_2100) { /* 2100 IOP? */
|
||||
if ((IR >= 0105020) && (IR <= 0105057)) /* remap LAI */
|
||||
@@ -982,7 +995,7 @@ if (UNIT_CPU_TYPE == UNIT_TYPE_2100) { /* 2100 IOP? */
|
||||
case 0105362: IR = 0105474; break; /* SAVE */
|
||||
|
||||
default: /* all others invalid */
|
||||
return stop_inst;
|
||||
return STOP (cpu_ss_unimpl);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -996,7 +1009,7 @@ if (entry <= 037) { /* LAI/SAI 10x400-437 */
|
||||
return reason;
|
||||
}
|
||||
else if (entry <= 057) /* IR = 10x440-457? */
|
||||
return stop_inst; /* not part of IOP */
|
||||
return STOP (cpu_ss_unimpl); /* not part of IOP */
|
||||
|
||||
entry = entry - 060; /* offset 10x460-477 */
|
||||
|
||||
@@ -1032,7 +1045,7 @@ switch (entry) { /* decode IR<5:0> */
|
||||
break;
|
||||
|
||||
case 002: /* READF 105462 (OP_N) */
|
||||
AR = (uint16) iop_sp; /* copy stk ptr */
|
||||
AR = iop_sp; /* copy stk ptr */
|
||||
break;
|
||||
|
||||
case 003: /* INS 105463 (OP_N) */
|
||||
@@ -1073,8 +1086,8 @@ switch (entry) { /* decode IR<5:0> */
|
||||
if (wc & SIGN) break; /* cnt < 0? */
|
||||
while (wc != 0) { /* loop */
|
||||
MA = (AR + AR + ReadB (BR)) & VAMASK;
|
||||
t = ReadB (MA); /* xlate */
|
||||
WriteB (BR, t); /* store char */
|
||||
byte = ReadB (MA); /* xlate */
|
||||
WriteB (BR, byte); /* store char */
|
||||
BR = (BR + 1) & DMASK; /* incr ptr */
|
||||
wc = (wc - 1) & DMASK; /* decr cnt */
|
||||
if (wc && intrq) { /* more and intr? */
|
||||
@@ -1097,7 +1110,7 @@ switch (entry) { /* decode IR<5:0> */
|
||||
|
||||
case 011: /* PRFEI 105471 (OP_CVA) */
|
||||
WriteW (op[1].word, 1); /* set flag */
|
||||
reason = iogrp (op[0].word, 0); /* execute I/O instr */
|
||||
reason = cpu_iog (op[0].word, 0); /* execute I/O instr */
|
||||
op[0].word = op[2].word; /* set rtn and fall through */
|
||||
|
||||
case 012: /* PRFEX 105472 (OP_A) */
|
||||
@@ -1108,7 +1121,7 @@ switch (entry) { /* decode IR<5:0> */
|
||||
|
||||
case 013: /* PRFIO 105473 (OP_CV) */
|
||||
WriteW (op[1].word, 1); /* set flag */
|
||||
reason = iogrp (op[0].word, 0); /* execute instr */
|
||||
reason = cpu_iog (op[0].word, 0); /* execute instr */
|
||||
break;
|
||||
|
||||
case 014: /* SAVE 105474 (OP_N) */
|
||||
@@ -1116,15 +1129,15 @@ switch (entry) { /* decode IR<5:0> */
|
||||
iop_sp = (iop_sp + 1) & VAMASK; /* incr stack ptr */
|
||||
WriteW (iop_sp, BR); /* save B */
|
||||
iop_sp = (iop_sp + 1) & VAMASK; /* incr stack ptr */
|
||||
t = ((O ^ 1) << 1) | E; /* merge E and O */
|
||||
t = (HP_WORD) ((O ^ 1) << 1 | E); /* merge E and O */
|
||||
WriteW (iop_sp, t); /* save E and O */
|
||||
iop_sp = (iop_sp + 1) & VAMASK; /* incr stack ptr */
|
||||
if (UNIT_CPU_TYPE == UNIT_TYPE_2100)
|
||||
mp_fence = iop_sp; /* 2100 keeps sp in MP FR */
|
||||
break;
|
||||
|
||||
default: /* instruction undefined */
|
||||
return stop_inst;
|
||||
default: /* instruction unimplemented */
|
||||
return STOP (cpu_ss_unimpl);
|
||||
}
|
||||
|
||||
return reason;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* hp2100_cpu3.c: HP 2100/1000 FFP/DBI instructions
|
||||
|
||||
Copyright (c) 2005-2016, J. David Bryan
|
||||
Copyright (c) 2005-2017, J. David Bryan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
CPU3 Fast FORTRAN and Double Integer instructions
|
||||
|
||||
24-Aug-17 JDB op_ffp_f definition is now conditional on HAVE_INT64
|
||||
27-Mar-17 JDB Improved the comments for the FFP instructions
|
||||
05-Aug-16 JDB Renamed the P register from "PC" to "PR"
|
||||
24-Dec-14 JDB Added casts for explicit downward conversions
|
||||
09-May-12 JDB Separated assignments from conditional expressions
|
||||
@@ -41,15 +43,23 @@
|
||||
18-Feb-05 JDB Add 2100/21MX Fast FORTRAN Processor instructions
|
||||
|
||||
Primary references:
|
||||
- HP 1000 M/E/F-Series Computers Technical Reference Handbook
|
||||
(5955-0282, Mar-1980)
|
||||
- HP 1000 M/E/F-Series Computers Engineering and Reference Documentation
|
||||
(92851-90001, Mar-1981)
|
||||
- Macro/1000 Reference Manual (92059-90001, Dec-1992)
|
||||
- HP 1000 M/E/F-Series Computers Technical Reference Handbook
|
||||
(5955-0282, March 1980)
|
||||
- HP 1000 M/E/F-Series Computers Engineering and Reference Documentation
|
||||
(92851-90001, March 1981)
|
||||
- Macro/1000 Reference Manual
|
||||
(92059-90001, December 1992)
|
||||
|
||||
Firmware-specific references:
|
||||
- DOS/RTE Relocatable Library Reference Manual
|
||||
(24998-90001, October 1981)
|
||||
- Implementing the HP 2100 Fast FORTRAN Processor
|
||||
(12907-90010, November 1974)
|
||||
- 93585A Microcode Source
|
||||
(93585-18002 Rev. 2005)
|
||||
- 93585A Double Integer Instructions Installation and Reference Manual
|
||||
(93585-90007, February 1984)
|
||||
|
||||
Additional references are listed with the associated firmware
|
||||
implementations, as are the HP option model numbers pertaining to the
|
||||
applicable CPUs.
|
||||
*/
|
||||
|
||||
#include "hp2100_defs.h"
|
||||
@@ -143,12 +153,14 @@
|
||||
|
||||
9. The protected memory lower bound for the .GOTO instruction is 2.
|
||||
|
||||
Additional references:
|
||||
- DOS/RTE Relocatable Library Reference Manual (24998-90001, Oct-1981)
|
||||
- Implementing the HP 2100 Fast FORTRAN Processor (12907-90010, Nov-1974)
|
||||
10. The OP_N (none) operand pattern is used here for all double-integer
|
||||
instructions. They are dispatched to the DBI handler for execution,
|
||||
where the correct operands will be retrieved
|
||||
*/
|
||||
|
||||
static const OP_PAT op_ffp_f[32] = { /* patterns for F-Series only */
|
||||
#if defined (HAVE_INT64) /* int64 support available */
|
||||
|
||||
static const OP_PAT op_ffp_f [32] = { /* patterns for F-Series only */
|
||||
OP_N, OP_AAF, OP_AX, OP_N, /* [tst] DBLE SNGL .DNG */
|
||||
OP_N, OP_AA, OP_A, OP_AAF, /* .DCO .DFER .XPAK .BLE */
|
||||
OP_N, OP_N, OP_N, OP_N, /* .DIN .DDE .DIS .DDS */
|
||||
@@ -159,7 +171,9 @@ static const OP_PAT op_ffp_f[32] = { /* patterns for F-Series
|
||||
OP_N, OP_N, OP_N, OP_N /* --- --- --- --- */
|
||||
};
|
||||
|
||||
static const OP_PAT op_ffp_e[32] = { /* patterns for 2100/M/E-Series */
|
||||
#endif /* end of int64 support */
|
||||
|
||||
static const OP_PAT op_ffp_e [32] = { /* patterns for 2100/M/E-Series */
|
||||
OP_N, OP_AAF, OP_AX, OP_AXX, /* [nop] DBLE SNGL .XMPY */
|
||||
OP_AXX, OP_AA, OP_A, OP_AAXX, /* .XDIV .DFER .XPAK XADD */
|
||||
OP_AAXX, OP_AAXX, OP_AAXX, OP_AXX, /* XSUB XMPY XDIV .XADD */
|
||||
@@ -175,7 +189,7 @@ t_stat cpu_ffp (uint32 IR, uint32 intrq)
|
||||
OP fpop;
|
||||
OPS op, op2;
|
||||
uint32 entry;
|
||||
uint32 j, sa, sb, sc, da, dc, ra, MA;
|
||||
HP_WORD j, sa, sb, sc, da, dc, ra, MA;
|
||||
int32 expon;
|
||||
t_stat reason = SCPE_OK;
|
||||
|
||||
@@ -267,7 +281,7 @@ switch (entry) { /* decode IR<4:0> */
|
||||
|
||||
case 000: /* [nop] 105200 (OP_N) */
|
||||
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* must be 1000 M/E-series */
|
||||
return stop_inst; /* trap if not */
|
||||
return STOP (cpu_ss_unimpl); /* trap if not */
|
||||
break;
|
||||
|
||||
#if defined (HAVE_INT64) /* int64 support available */
|
||||
@@ -302,7 +316,7 @@ switch (entry) { /* decode IR<4:0> */
|
||||
|
||||
case 006: /* .XPAK 105206 (OP_A) */
|
||||
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* must be 1000 */
|
||||
return stop_inst; /* trap if not */
|
||||
return STOP (cpu_ss_unimpl); /* trap if not */
|
||||
|
||||
if (intrq) { /* interrupt pending? */
|
||||
PR = err_PC; /* restart instruction */
|
||||
@@ -310,7 +324,7 @@ switch (entry) { /* decode IR<4:0> */
|
||||
}
|
||||
|
||||
fpop = ReadOp (op[0].word, fp_x); /* read unpacked */
|
||||
O = fp_nrpack (&fpop, fpop, (int16) AR, fp_x); /* nrm/rnd/pack mantissa, exponent */
|
||||
O = fp_nrpack (&fpop, fpop, SEXT16 (AR), fp_x); /* nrm/rnd/pack mantissa, exponent */
|
||||
WriteOp (op[0].word, fpop, fp_x); /* write result */
|
||||
break;
|
||||
|
||||
@@ -372,7 +386,7 @@ switch (entry) { /* decode IR<4:0> */
|
||||
|
||||
case 015: /* .XCOM 105215 (OP_A) */
|
||||
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* must be 1000 */
|
||||
return stop_inst; /* trap if not */
|
||||
return STOP (cpu_ss_unimpl); /* trap if not */
|
||||
|
||||
fpop = ReadOp (op[0].word, fp_x); /* read unpacked */
|
||||
AR = fp_ucom (&fpop, fp_x); /* complement and rtn exp adj */
|
||||
@@ -381,7 +395,7 @@ switch (entry) { /* decode IR<4:0> */
|
||||
|
||||
case 016: /* ..DCM 105216 (OP_A) */
|
||||
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* must be 1000 */
|
||||
return stop_inst; /* trap if not */
|
||||
return STOP (cpu_ss_unimpl); /* trap if not */
|
||||
|
||||
if (intrq) { /* interrupt pending? */
|
||||
PR = err_PC; /* restart instruction */
|
||||
@@ -395,7 +409,7 @@ switch (entry) { /* decode IR<4:0> */
|
||||
|
||||
case 017: /* DDINT 105217 (OP_AAX) */
|
||||
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* must be 1000 */
|
||||
return stop_inst; /* trap if not */
|
||||
return STOP (cpu_ss_unimpl); /* trap if not */
|
||||
|
||||
if (intrq) { /* interrupt pending? */
|
||||
PR = err_PC; /* restart instruction */
|
||||
@@ -418,7 +432,7 @@ switch (entry) { /* decode IR<4:0> */
|
||||
goto CFER; /* do transfer */
|
||||
|
||||
case 021: /* .GOTO 105221 (OP_AK) */
|
||||
if ((int16) op[1].word < 1) /* index < 1? */
|
||||
if (SEXT16 (op[1].word) < 1) /* index < 1? */
|
||||
op[1].word = 1; /* reset min */
|
||||
|
||||
sa = PR + op[1].word - 1; /* point to jump target */
|
||||
@@ -455,7 +469,7 @@ switch (entry) { /* decode IR<4:0> */
|
||||
op[2].word - 1) * op2[0].word;
|
||||
}
|
||||
|
||||
AR = (op[0].word + op[1].word * BR) & DMASK; /* return element address */
|
||||
AR = (op[0].word + op[1].word * BR) & R_MASK; /* return element address */
|
||||
break;
|
||||
|
||||
case 023: /* .ENTR 105223 (OP_A) */
|
||||
@@ -480,8 +494,8 @@ switch (entry) { /* decode IR<4:0> */
|
||||
WriteW (da++, MA); /* put addr into formal */
|
||||
}
|
||||
|
||||
AR = (uint16) ra; /* return address */
|
||||
BR = (uint16) da; /* addr of 1st unused formal */
|
||||
AR = (HP_WORD) ra; /* return address */
|
||||
BR = (HP_WORD) da; /* addr of 1st unused formal */
|
||||
break;
|
||||
|
||||
case 024: /* .ENTP 105224 (OP_A) */
|
||||
@@ -490,10 +504,10 @@ switch (entry) { /* decode IR<4:0> */
|
||||
|
||||
case 025: /* .PWR2 105225 (OP_RK) */
|
||||
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* must be 1000 */
|
||||
return stop_inst; /* trap if not */
|
||||
return STOP (cpu_ss_unimpl); /* trap if not */
|
||||
|
||||
fp_unpack (&fpop, &expon, op[0], fp_f); /* unpack value */
|
||||
expon = expon + (int16) (op[1].word); /* multiply by 2**n */
|
||||
expon = expon + SEXT16 (op[1].word); /* multiply by 2**n */
|
||||
fp_pack (&fpop, fpop, expon, fp_f); /* repack value */
|
||||
AR = fpop.fpk[0]; /* return result */
|
||||
BR = fpop.fpk[1]; /* to A/B registers */
|
||||
@@ -501,10 +515,10 @@ switch (entry) { /* decode IR<4:0> */
|
||||
|
||||
case 026: /* .FLUN 105226 (OP_R) */
|
||||
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* must be 1000 */
|
||||
return stop_inst; /* trap if not */
|
||||
return STOP (cpu_ss_unimpl); /* trap if not */
|
||||
|
||||
fp_unpack (&fpop, &expon, op[0], fp_f); /* unpack value */
|
||||
AR = (int16) expon; /* return expon to A */
|
||||
AR = expon & R_MASK; /* return expon to A */
|
||||
BR = fpop.fpk[1]; /* and low mant to B */
|
||||
break;
|
||||
|
||||
@@ -516,12 +530,12 @@ switch (entry) { /* decode IR<4:0> */
|
||||
|
||||
do {
|
||||
WriteW (BR, j); /* write value to address */
|
||||
j = (j + 1) & DMASK; /* incr value */
|
||||
j = (j + 1) & D16_MASK; /* incr value */
|
||||
BR = (BR + 1) & VAMASK; /* incr address */
|
||||
op[0].word = op[0].word - 1; /* decr count */
|
||||
if (op[0].word && intrq) { /* more and intr? */
|
||||
AR = (uint16) sa; /* restore A */
|
||||
BR = (uint16) sb; /* restore B */
|
||||
AR = sa; /* restore A */
|
||||
BR = sb; /* restore B */
|
||||
PR = err_PC; /* restart instruction */
|
||||
break;
|
||||
}
|
||||
@@ -531,10 +545,10 @@ switch (entry) { /* decode IR<4:0> */
|
||||
|
||||
case 030: /* .PACK 105230 (OP_RC) */
|
||||
if (UNIT_CPU_TYPE != UNIT_TYPE_1000) /* must be 1000 */
|
||||
return stop_inst; /* trap if not */
|
||||
return STOP (cpu_ss_unimpl); /* trap if not */
|
||||
|
||||
O = fp_nrpack (&fpop, op[0], /* nrm/rnd/pack value */
|
||||
(int16) (op[1].word), fp_f);
|
||||
SEXT16 (op[1].word), fp_f);
|
||||
AR = fpop.fpk[0]; /* return result */
|
||||
BR = fpop.fpk[1]; /* to A/B registers */
|
||||
break;
|
||||
@@ -542,7 +556,7 @@ switch (entry) { /* decode IR<4:0> */
|
||||
case 031: /* .CFER 105231 (OP_AA) */
|
||||
if ((UNIT_CPU_MODEL != UNIT_1000_E) && /* must be 1000 E-series */
|
||||
(UNIT_CPU_MODEL != UNIT_1000_F)) /* or 1000 F-series */
|
||||
return stop_inst; /* trap if not */
|
||||
return STOP (cpu_ss_unimpl); /* trap if not */
|
||||
|
||||
BR = op[0].word; /* get destination address */
|
||||
AR = op[1].word; /* get source address */
|
||||
@@ -562,8 +576,8 @@ switch (entry) { /* decode IR<4:0> */
|
||||
}
|
||||
break;
|
||||
|
||||
default: /* others undefined */
|
||||
reason = stop_inst;
|
||||
default: /* others unimplemented */
|
||||
reason = STOP (cpu_ss_unimpl);
|
||||
}
|
||||
|
||||
return reason;
|
||||
@@ -632,11 +646,6 @@ return reason;
|
||||
execute the extended-precision multiply/divide, and then fixing the
|
||||
product to a 32-bit double integer. We simulate these directly with 64-
|
||||
or 32-bit integer arithmetic.
|
||||
|
||||
Additional references:
|
||||
- 93585A Microcode Source (93585-18002 Rev. 2005)
|
||||
- 93585A Double Integer Instructions Installation and Reference Manual
|
||||
(93585-90007)
|
||||
*/
|
||||
|
||||
static const OP_PAT op_dbi[16] = {
|
||||
@@ -692,7 +701,7 @@ switch (entry) { /* decode IR<3:0> */
|
||||
if (O)
|
||||
t = ~SIGN32; /* if overflow, rtn max pos */
|
||||
else
|
||||
t = (uint32) (t64 & DMASK32); /* else lower 32 bits of result */
|
||||
t = (uint32) (t64 & D32_MASK); /* else lower 32 bits of result */
|
||||
|
||||
#else /* int64 support unavailable */
|
||||
|
||||
@@ -814,14 +823,14 @@ switch (entry) { /* decode IR<3:0> */
|
||||
op[1].dword = t;
|
||||
goto DSB; /* continue at .DSB */
|
||||
|
||||
default: /* others undefined */
|
||||
default: /* others unimplemented */
|
||||
t = (AR << 16) | BR; /* set t for NOP */
|
||||
reason = stop_inst;
|
||||
reason = STOP (cpu_ss_unimpl);
|
||||
}
|
||||
|
||||
if (reason == SCPE_OK) { /* if return OK */
|
||||
AR = (t >> 16) & DMASK; /* break result */
|
||||
BR = t & DMASK; /* into A and B */
|
||||
AR = UPPER_WORD (t); /* break result */
|
||||
BR = LOWER_WORD (t); /* into A and B */
|
||||
}
|
||||
|
||||
return reason;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* hp2100_cpu4.c: HP 1000 FPP/SIS
|
||||
|
||||
Copyright (c) 2006-2016, J. David Bryan
|
||||
Copyright (c) 2006-2017, J. David Bryan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
CPU4 Floating Point Processor and Scientific Instruction Set
|
||||
|
||||
07-Sep-17 JDB Replaced "uint16" cast with "HP_WORD" for FPK assignment
|
||||
05-Aug-16 JDB Renamed the P register from "PC" to "PR"
|
||||
24-Dec-14 JDB Added casts for explicit downward conversions
|
||||
09-May-12 JDB Separated assignments from conditional expressions
|
||||
@@ -252,7 +253,8 @@ t_stat cpu_fpp (uint32 IR, uint32 intrq)
|
||||
OP fpop;
|
||||
OPS op;
|
||||
OPSIZE op1_prec, op2_prec, rslt_prec, cvt_prec;
|
||||
uint16 opcode, rtn_addr, stk_ptr;
|
||||
HP_WORD rtn_addr, stk_ptr;
|
||||
uint16 opcode;
|
||||
uint32 entry;
|
||||
t_stat reason = SCPE_OK;
|
||||
|
||||
@@ -314,7 +316,7 @@ switch (entry) { /* decode IR<6:0> */
|
||||
|
||||
case 0007: /* [stk] 105007 (OP_A) */
|
||||
O = 0; /* clear overflow */
|
||||
stk_ptr = (uint16) PR; /* save ptr to next buf */
|
||||
stk_ptr = PR; /* save ptr to next buf */
|
||||
rtn_addr = op[0].word; /* save return address */
|
||||
|
||||
while (TRUE) {
|
||||
@@ -428,8 +430,8 @@ switch (entry) { /* decode IR<6:0> */
|
||||
case 0134: /* .DDIR 105134 (OP_N) */
|
||||
return cpu_dbi (0105326, intrq); /* remap to double int handler */
|
||||
|
||||
default: /* others undefined */
|
||||
reason = stop_inst;
|
||||
default: /* others unimplemented */
|
||||
reason = STOP (cpu_ss_unimpl);
|
||||
}
|
||||
|
||||
return reason;
|
||||
@@ -711,7 +713,7 @@ switch (entry) { /* decode IR<3:0> */
|
||||
op[1].fpk[1] = op[1].fpk[1] | 2; /* set "exponent" to 1 */
|
||||
}
|
||||
|
||||
op[2].fpk[0] = (uint16) exponent;
|
||||
op[2].fpk[0] = (HP_WORD) exponent;
|
||||
fp_exec (0120, &op[3], op[2], NOP); /* op3 = FLT(exponent) */
|
||||
|
||||
fp_exec (0020, &op[4], op[1], plus_1); /* op4 = op1 - 1.0 */
|
||||
@@ -1117,8 +1119,8 @@ switch (entry) { /* decode IR<3:0> */
|
||||
return reason;
|
||||
|
||||
|
||||
default: /* others undefined */
|
||||
return stop_inst;
|
||||
default: /* others unimplemented */
|
||||
return STOP (cpu_ss_unimpl);
|
||||
}
|
||||
|
||||
AR = op[0].fpk[0]; /* save result */
|
||||
|
||||
1714
HP2100/hp2100_cpu5.c
1714
HP2100/hp2100_cpu5.c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
/* hp2100_cpu7.c: HP 1000 VIS and SIGNAL/1000 microcode
|
||||
|
||||
Copyright (c) 2008, Holger Veit
|
||||
Copyright (c) 2006-2016, J. David Bryan
|
||||
Copyright (c) 2006-2017, J. David Bryan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
CPU7 Vector Instruction Set and SIGNAL firmware
|
||||
|
||||
31-Jan-17 JDB Revised to use tprintf and TRACE_OPND for debugging
|
||||
26-Jan-17 JDB Removed debug parameters from cpu_ema_* routines
|
||||
05-Aug-16 JDB Renamed the P register from "PC" to "PR"
|
||||
24-Dec-14 JDB Added casts for explicit downward conversions
|
||||
18-Mar-13 JDB Moved EMA helper declarations to hp2100_cpu1.h
|
||||
@@ -62,85 +64,6 @@
|
||||
static const OP zero = { { 0, 0, 0, 0, 0 } }; /* DEC 0.0D0 */
|
||||
|
||||
|
||||
/* Vector Instruction Set
|
||||
|
||||
The VIS provides instructions that operate on one-dimensional arrays of
|
||||
floating-point values. Both single- and double-precision operations are
|
||||
supported. VIS uses the F-Series floating-point processor to handle the
|
||||
floating-point math.
|
||||
|
||||
Option implementation by CPU was as follows:
|
||||
|
||||
2114 2115 2116 2100 1000-M 1000-E 1000-F
|
||||
------ ------ ------ ------ ------ ------ ------
|
||||
N/A N/A N/A N/A N/A N/A 12824A
|
||||
|
||||
The routines are mapped to instruction codes as follows:
|
||||
|
||||
Single-Precision Double-Precision
|
||||
Instr. Opcode Subcod Instr. Opcode Subcod Description
|
||||
------ ------ ------ ------ ------ ------ -----------------------------
|
||||
VADD 101460 000000 DVADD 105460 004002 Vector add
|
||||
VSUB 101460 000020 DVSUB 105460 004022 Vector subtract
|
||||
VMPY 101460 000040 DVMPY 105460 004042 Vector multiply
|
||||
VDIV 101460 000060 DVDIV 105460 004062 Vector divide
|
||||
VSAD 101460 000400 DVSAD 105460 004402 Scalar-vector add
|
||||
VSSB 101460 000420 DVSSB 105460 004422 Scalar-vector subtract
|
||||
VSMY 101460 000440 DVSMY 105460 004442 Scalar-vector multiply
|
||||
VSDV 101460 000460 DVSDV 105460 004462 Scalar-vector divide
|
||||
VPIV 101461 0xxxxx DVPIV 105461 0xxxxx Vector pivot
|
||||
VABS 101462 0xxxxx DVABS 105462 0xxxxx Vector absolute value
|
||||
VSUM 101463 0xxxxx DVSUM 105463 0xxxxx Vector sum
|
||||
VNRM 101464 0xxxxx DVNRM 105464 0xxxxx Vector norm
|
||||
VDOT 101465 0xxxxx DVDOT 105465 0xxxxx Vector dot product
|
||||
VMAX 101466 0xxxxx DVMAX 105466 0xxxxx Vector maximum value
|
||||
VMAB 101467 0xxxxx DVMAB 105467 0xxxxx Vector maximum absolute value
|
||||
VMIN 101470 0xxxxx DVMIN 105470 0xxxxx Vector minimum value
|
||||
VMIB 101471 0xxxxx DVMIB 105471 0xxxxx Vector minimum absolute value
|
||||
VMOV 101472 0xxxxx DVMOV 105472 0xxxxx Vector move
|
||||
VSWP 101473 0xxxxx DVSWP 105473 0xxxxx Vector swap
|
||||
.ERES 101474 -- -- -- -- Resolve array element address
|
||||
.ESEG 101475 -- -- -- -- Load MSEG maps
|
||||
.VSET 101476 -- -- -- -- Vector setup
|
||||
[test] -- -- -- 105477 -- [self test]
|
||||
|
||||
Instructions use IR bit 11 to select single- or double-precision format. The
|
||||
double-precision instruction names begin with "D" (e.g., DVADD vs. VADD).
|
||||
Most VIS instructions are two words in length, with a sub-opcode immediately
|
||||
following the primary opcode.
|
||||
|
||||
Notes:
|
||||
|
||||
1. The .VECT (101460) and .DVCT (105460) opcodes preface a single- or
|
||||
double-precision arithmetic operation that is determined by the
|
||||
sub-opcode value. The remainder of the dual-precision sub-opcode values
|
||||
are "don't care," except for requiring a zero in bit 15.
|
||||
|
||||
2. The VIS uses the hardware FPP of the F-Series. FPP malfunctions are
|
||||
detected by the VIS firmware and are indicated by a memory-protect
|
||||
violation and setting the overflow flag. Under simulation,
|
||||
malfunctions cannot occur.
|
||||
|
||||
Additional references:
|
||||
- 12824A Vector Instruction Set User's Manual (12824-90001, Jun-1979).
|
||||
- VIS Microcode Source (12824-18059, revision 3).
|
||||
*/
|
||||
|
||||
static const OP_PAT op_vis[16] = {
|
||||
OP_N, OP_AAKAKAKK,OP_AKAKK, OP_AAKK, /* .VECT VPIV VABS VSUM */
|
||||
OP_AAKK, OP_AAKAKK, OP_AAKK, OP_AAKK, /* VNRM VDOT VMAX VMAB */
|
||||
OP_AAKK, OP_AAKK, OP_AKAKK, OP_AKAKK, /* VMIN VMIB VMOV VSWP */
|
||||
OP_AA, OP_A, OP_AAACCC,OP_N /* .ERES .ESEG .VSET [test] */
|
||||
};
|
||||
|
||||
static const t_bool op_ftnret[16] = {
|
||||
FALSE, TRUE, TRUE, TRUE,
|
||||
TRUE, TRUE, TRUE, TRUE,
|
||||
TRUE, TRUE, TRUE, TRUE,
|
||||
FALSE, TRUE, TRUE, FALSE,
|
||||
};
|
||||
|
||||
|
||||
/* handle the scalar/vector base ops */
|
||||
static void vis_svop(uint32 subcode, OPS op, OPSIZE opsize)
|
||||
{
|
||||
@@ -361,115 +284,200 @@ for (i=0; i<n; i++) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Vector Instruction Set
|
||||
|
||||
The VIS provides instructions that operate on one-dimensional arrays of
|
||||
floating-point values. Both single- and double-precision operations are
|
||||
supported. VIS uses the F-Series floating-point processor to handle the
|
||||
floating-point math.
|
||||
|
||||
Option implementation by CPU was as follows:
|
||||
|
||||
2114 2115 2116 2100 1000-M 1000-E 1000-F
|
||||
------ ------ ------ ------ ------ ------ ------
|
||||
N/A N/A N/A N/A N/A N/A 12824A
|
||||
|
||||
The routines are mapped to instruction codes as follows:
|
||||
|
||||
Single-Precision Double-Precision
|
||||
Instr. Opcode Subcod Instr. Opcode Subcod Description
|
||||
------ ------ ------ ------ ------ ------ -----------------------------
|
||||
VADD 101460 000000 DVADD 105460 004002 Vector add
|
||||
VSUB 101460 000020 DVSUB 105460 004022 Vector subtract
|
||||
VMPY 101460 000040 DVMPY 105460 004042 Vector multiply
|
||||
VDIV 101460 000060 DVDIV 105460 004062 Vector divide
|
||||
VSAD 101460 000400 DVSAD 105460 004402 Scalar-vector add
|
||||
VSSB 101460 000420 DVSSB 105460 004422 Scalar-vector subtract
|
||||
VSMY 101460 000440 DVSMY 105460 004442 Scalar-vector multiply
|
||||
VSDV 101460 000460 DVSDV 105460 004462 Scalar-vector divide
|
||||
VPIV 101461 0xxxxx DVPIV 105461 0xxxxx Vector pivot
|
||||
VABS 101462 0xxxxx DVABS 105462 0xxxxx Vector absolute value
|
||||
VSUM 101463 0xxxxx DVSUM 105463 0xxxxx Vector sum
|
||||
VNRM 101464 0xxxxx DVNRM 105464 0xxxxx Vector norm
|
||||
VDOT 101465 0xxxxx DVDOT 105465 0xxxxx Vector dot product
|
||||
VMAX 101466 0xxxxx DVMAX 105466 0xxxxx Vector maximum value
|
||||
VMAB 101467 0xxxxx DVMAB 105467 0xxxxx Vector maximum absolute value
|
||||
VMIN 101470 0xxxxx DVMIN 105470 0xxxxx Vector minimum value
|
||||
VMIB 101471 0xxxxx DVMIB 105471 0xxxxx Vector minimum absolute value
|
||||
VMOV 101472 0xxxxx DVMOV 105472 0xxxxx Vector move
|
||||
VSWP 101473 0xxxxx DVSWP 105473 0xxxxx Vector swap
|
||||
.ERES 101474 -- -- -- -- Resolve array element address
|
||||
.ESEG 101475 -- -- -- -- Load MSEG maps
|
||||
.VSET 101476 -- -- -- -- Vector setup
|
||||
[test] -- -- -- 105477 -- [self test]
|
||||
|
||||
Instructions use IR bit 11 to select single- or double-precision format. The
|
||||
double-precision instruction names begin with "D" (e.g., DVADD vs. VADD).
|
||||
Most VIS instructions are two words in length, with a sub-opcode immediately
|
||||
following the primary opcode.
|
||||
|
||||
Notes:
|
||||
|
||||
1. The .VECT (101460) and .DVCT (105460) opcodes preface a single- or
|
||||
double-precision arithmetic operation that is determined by the
|
||||
sub-opcode value. The remainder of the dual-precision sub-opcode values
|
||||
are "don't care," except for requiring a zero in bit 15.
|
||||
|
||||
2. The VIS uses the hardware FPP of the F-Series. FPP malfunctions are
|
||||
detected by the VIS firmware and are indicated by a memory-protect
|
||||
violation and setting the overflow flag. Under simulation,
|
||||
malfunctions cannot occur.
|
||||
|
||||
Additional references:
|
||||
- 12824A Vector Instruction Set User's Manual (12824-90001, Jun-1979).
|
||||
- VIS Microcode Source (12824-18059, revision 3).
|
||||
*/
|
||||
|
||||
static const OP_PAT op_vis [16] = {
|
||||
OP_N, OP_AAKAKAKK, OP_AKAKK, OP_AAKK, /* .VECT VPIV VABS VSUM */
|
||||
OP_AAKK, OP_AAKAKK, OP_AAKK, OP_AAKK, /* VNRM VDOT VMAX VMAB */
|
||||
OP_AAKK, OP_AAKK, OP_AKAKK, OP_AKAKK, /* VMIN VMIB VMOV VSWP */
|
||||
OP_AA, OP_A, OP_AAACCC, OP_N /* .ERES .ESEG .VSET [test] */
|
||||
};
|
||||
|
||||
static const t_bool op_ftnret [16] = {
|
||||
FALSE, TRUE, TRUE, TRUE,
|
||||
TRUE, TRUE, TRUE, TRUE,
|
||||
TRUE, TRUE, TRUE, TRUE,
|
||||
FALSE, TRUE, TRUE, FALSE,
|
||||
};
|
||||
|
||||
t_stat cpu_vis (uint32 IR, uint32 intrq)
|
||||
{
|
||||
static const char *const difficulty [2] = { "hard", "easy" };
|
||||
|
||||
t_stat reason = SCPE_OK;
|
||||
OPS op;
|
||||
OP ret;
|
||||
uint32 entry, rtn, rtn1 = 0, subcode = 0;
|
||||
OP_PAT pattern;
|
||||
OPSIZE opsize;
|
||||
t_bool debug = DEBUG_PRI (cpu_dev, DEB_VIS);
|
||||
uint32 entry, subcode;
|
||||
HP_WORD rtn = 0;
|
||||
|
||||
opsize = (IR & 004000) ? fp_t : fp_f; /* double or single precision */
|
||||
entry = IR & 017; /* mask to entry point */
|
||||
pattern = op_vis[entry];
|
||||
pattern = op_vis [entry];
|
||||
|
||||
if (entry == 0) { /* retrieve sub opcode */
|
||||
subcode = ReadF (PR); /* get it */
|
||||
|
||||
if (entry==0) { /* retrieve sub opcode */
|
||||
ret = ReadOp (PR, in_s); /* get it */
|
||||
subcode = ret.word;
|
||||
if (subcode & 0100000) /* special property of ucode */
|
||||
subcode = AR; /* for reentry */
|
||||
|
||||
PR = (PR + 1) & VAMASK; /* bump to real argument list */
|
||||
pattern = (subcode & 0400) ? OP_AAKAKK : OP_AKAKAKK; /* scalar or vector operation */
|
||||
}
|
||||
|
||||
if (pattern != OP_N) {
|
||||
if (op_ftnret[entry]) { /* most VIS instrs ignore RTN addr */
|
||||
ret = ReadOp(PR, in_s);
|
||||
rtn = rtn1 = ret.word; /* but save it just in case */
|
||||
if (op_ftnret [entry]) { /* most VIS instrs ignore RTN addr */
|
||||
rtn = ReadF (PR); /* get it */
|
||||
PR = (PR + 1) & VAMASK; /* move to next argument */
|
||||
}
|
||||
|
||||
reason = cpu_ops (pattern, op, intrq); /* get instruction operands */
|
||||
|
||||
if (reason != SCPE_OK) /* evaluation failed? */
|
||||
return reason; /* return reason for failure */
|
||||
}
|
||||
|
||||
if (debug) { /* debugging? */
|
||||
fprintf (sim_deb, ">>CPU VIS: IR = %06o/%06o (", /* print preamble and IR */
|
||||
IR, subcode);
|
||||
fprint_sym (sim_deb, err_PC, (t_value *) &IR, /* print instruction mnemonic */
|
||||
NULL, SWMASK('M'));
|
||||
fprintf (sim_deb, "), P = %06o", err_PC); /* print location */
|
||||
fprint_ops (pattern, op); /* print operands */
|
||||
fputc ('\n', sim_deb); /* terminate line */
|
||||
}
|
||||
|
||||
switch (entry) { /* decode IR<3:0> */
|
||||
|
||||
case 000: /* .VECT (OP_special) */
|
||||
if (subcode & 0400)
|
||||
vis_svop(subcode,op,opsize); /* scalar/vector op */
|
||||
else
|
||||
vis_vvop(subcode,op,opsize); /* vector/vector op */
|
||||
break;
|
||||
|
||||
case 001: /* VPIV (OP_(A)AAKAKAKK) */
|
||||
vis_vpiv(op,opsize);
|
||||
break;
|
||||
|
||||
case 002: /* VABS (OP_(A)AKAKK) */
|
||||
vis_vabs(op,opsize);
|
||||
break;
|
||||
|
||||
case 003: /* VSUM (OP_(A)AAKK) */
|
||||
vis_vsmnm(op,opsize,FALSE);
|
||||
break;
|
||||
|
||||
case 004: /* VNRM (OP_(A)AAKK) */
|
||||
vis_vsmnm(op,opsize,TRUE);
|
||||
break;
|
||||
|
||||
case 005: /* VDOT (OP_(A)AAKAKK) */
|
||||
vis_vdot(op,opsize);
|
||||
break;
|
||||
|
||||
case 006: /* VMAX (OP_(A)AAKK) */
|
||||
vis_minmax(op,opsize,TRUE,FALSE);
|
||||
break;
|
||||
|
||||
case 007: /* VMAB (OP_(A)AAKK) */
|
||||
vis_minmax(op,opsize,TRUE,TRUE);
|
||||
break;
|
||||
|
||||
case 010: /* VMIN (OP_(A)AAKK) */
|
||||
vis_minmax(op,opsize,FALSE,FALSE);
|
||||
break;
|
||||
|
||||
case 011: /* VMIB (OP_(A)AAKK) */
|
||||
vis_minmax(op,opsize,FALSE,TRUE);
|
||||
break;
|
||||
|
||||
case 012: /* VMOV (OP_(A)AKAKK) */
|
||||
vis_movswp(op,opsize,FALSE);
|
||||
break;
|
||||
|
||||
case 013: /* VSWP (OP_(A)AKAKK) */
|
||||
vis_movswp(op,opsize,TRUE);
|
||||
break;
|
||||
|
||||
case 014: /* .ERES (OP_(A)AA) */
|
||||
reason = cpu_ema_eres(&rtn,op[2].word,PR,debug); /* handle the ERES instruction */
|
||||
PR = rtn;
|
||||
if (debug)
|
||||
fprintf (sim_deb,
|
||||
">>CPU VIS: return .ERES: AR = %06o, BR = %06o, rtn=%s\n",
|
||||
AR, BR, PR==op[0].word ? "error" : "good");
|
||||
reason = cpu_ema_eres(&PR,op[2].word,PR); /* handle the ERES instruction */
|
||||
|
||||
tprintf (cpu_dev, TRACE_OPND, OPND_FORMAT " return location is P+%u (%s)\n",
|
||||
PR, IR, PR - err_PC, fmt_ab (PR - rtn));
|
||||
break;
|
||||
|
||||
case 015: /* .ESEG (OP_(A)A) */
|
||||
reason = cpu_ema_eseg(&rtn,IR,op[0].word,debug); /* handle the ESEG instruction */
|
||||
PR = rtn;
|
||||
if (debug)
|
||||
fprintf (sim_deb,
|
||||
">>CPU VIS: return .ESEG: AR = %06o , BR = %06o, rtn=%s\n",
|
||||
AR, BR, rtn==rtn1 ? "error" : "good");
|
||||
reason = cpu_ema_eseg(&PR,IR,op[0].word); /* handle the ESEG instruction */
|
||||
|
||||
tprintf (cpu_dev, TRACE_OPND, OPND_FORMAT " return location is P+%u (%s)\n",
|
||||
PR, IR, PR - err_PC, fmt_ab (PR - rtn));
|
||||
break;
|
||||
|
||||
case 016: /* .VSET (OP_(A)AAACCC) */
|
||||
reason = cpu_ema_vset(&rtn,op,debug);
|
||||
PR = rtn;
|
||||
if (debug)
|
||||
fprintf (sim_deb, ">>CPU VIS: return .VSET: AR = %06o BR = %06o, rtn=%s\n",
|
||||
AR, BR,
|
||||
rtn==rtn1 ? "error" : (rtn==(rtn1+1) ? "hard" : "easy") );
|
||||
reason = cpu_ema_vset(&PR,op);
|
||||
|
||||
tprintf (cpu_dev, TRACE_OPND, OPND_FORMAT " return location is P+%u (%s)\n",
|
||||
PR, IR, PR - err_PC,
|
||||
(PR == rtn
|
||||
? fmt_ab (0)
|
||||
: difficulty [PR - rtn - 1]));
|
||||
break;
|
||||
|
||||
case 017: /* [test] (OP_N) */
|
||||
@@ -477,66 +485,20 @@ switch (entry) { /* decode IR<3:0> */
|
||||
SR = 0102077; /* test passed code */
|
||||
PR = (PR + 1) & VAMASK; /* P+2 return for firmware w/VIS */
|
||||
break;
|
||||
default: /* others undefined */
|
||||
reason = stop_inst;
|
||||
}
|
||||
|
||||
default: /* others unimplemented */
|
||||
reason = STOP (cpu_ss_unimpl);
|
||||
}
|
||||
|
||||
return reason;
|
||||
}
|
||||
|
||||
|
||||
/* SIGNAL/1000 Instructions
|
||||
|
||||
The SIGNAL/1000 instructions provide fast Fourier transforms and complex
|
||||
arithmetic. They utilize the F-Series floating-point processor and the
|
||||
Vector Instruction Set.
|
||||
|
||||
Option implementation by CPU was as follows:
|
||||
|
||||
2114 2115 2116 2100 1000-M 1000-E 1000-F
|
||||
------ ------ ------ ------ ------ ------ ------
|
||||
N/A N/A N/A N/A N/A N/A 92835A
|
||||
|
||||
The routines are mapped to instruction codes as follows:
|
||||
|
||||
Instr. 1000-F Description
|
||||
------ ------ ----------------------------------------------
|
||||
BITRV 105600 Bit reversal
|
||||
BTRFY 105601 Butterfly algorithm
|
||||
UNSCR 105602 Unscramble for phasor MPY
|
||||
PRSCR 105603 Unscramble for phasor MPY
|
||||
BITR1 105604 Swap two elements in array (alternate format)
|
||||
BTRF1 105605 Butterfly algorithm (alternate format)
|
||||
.CADD 105606 Complex number addition
|
||||
.CSUB 105607 Complex number subtraction
|
||||
.CMPY 105610 Complex number multiplication
|
||||
.CDIV 105611 Complex number division
|
||||
CONJG 105612 Complex conjugate
|
||||
..CCM 105613 Complex complement
|
||||
AIMAG 105614 Return imaginary part
|
||||
CMPLX 105615 Form complex number
|
||||
[nop] 105616 [no operation]
|
||||
[test] 105617 [self test]
|
||||
|
||||
Notes:
|
||||
|
||||
1. SIGNAL/1000 ROM data are available from Bitsavers.
|
||||
|
||||
Additional references (documents unavailable):
|
||||
- HP Signal/1000 User Reference and Installation Manual (92835-90002).
|
||||
- SIGNAL/1000 Microcode Source (92835-18075, revision 2).
|
||||
*/
|
||||
/* SIGNAL/1000 routines */
|
||||
|
||||
#define RE(x) (x+0)
|
||||
#define IM(x) (x+2)
|
||||
|
||||
static const OP_PAT op_signal[16] = {
|
||||
OP_AAKK, OP_AAFFKK, OP_AAFFKK,OP_AAFFKK, /* BITRV BTRFY UNSCR PRSCR */
|
||||
OP_AAAKK, OP_AAAFFKK,OP_AAA, OP_AAA, /* BITR1 BTRF1 .CADD .CSUB */
|
||||
OP_AAA, OP_AAA, OP_AAA, OP_A, /* .CMPY .CDIV CONJG ..CCM */
|
||||
OP_AA, OP_AAFF, OP_N, OP_N /* AIMAG CMPLX --- [test]*/
|
||||
};
|
||||
|
||||
/* complex addition helper */
|
||||
static void sig_caddsub(uint16 addsub,OPS op)
|
||||
{
|
||||
@@ -641,6 +603,56 @@ OP p;
|
||||
(void)fp_exec(004, i, p, NOP); /* imag := ad+bc */
|
||||
}
|
||||
|
||||
|
||||
/* SIGNAL/1000 Instructions
|
||||
|
||||
The SIGNAL/1000 instructions provide fast Fourier transforms and complex
|
||||
arithmetic. They utilize the F-Series floating-point processor and the
|
||||
Vector Instruction Set.
|
||||
|
||||
Option implementation by CPU was as follows:
|
||||
|
||||
2114 2115 2116 2100 1000-M 1000-E 1000-F
|
||||
------ ------ ------ ------ ------ ------ ------
|
||||
N/A N/A N/A N/A N/A N/A 92835A
|
||||
|
||||
The routines are mapped to instruction codes as follows:
|
||||
|
||||
Instr. 1000-F Description
|
||||
------ ------ ----------------------------------------------
|
||||
BITRV 105600 Bit reversal
|
||||
BTRFY 105601 Butterfly algorithm
|
||||
UNSCR 105602 Unscramble for phasor MPY
|
||||
PRSCR 105603 Unscramble for phasor MPY
|
||||
BITR1 105604 Swap two elements in array (alternate format)
|
||||
BTRF1 105605 Butterfly algorithm (alternate format)
|
||||
.CADD 105606 Complex number addition
|
||||
.CSUB 105607 Complex number subtraction
|
||||
.CMPY 105610 Complex number multiplication
|
||||
.CDIV 105611 Complex number division
|
||||
CONJG 105612 Complex conjugate
|
||||
..CCM 105613 Complex complement
|
||||
AIMAG 105614 Return imaginary part
|
||||
CMPLX 105615 Form complex number
|
||||
[nop] 105616 [no operation]
|
||||
[test] 105617 [self test]
|
||||
|
||||
Notes:
|
||||
|
||||
1. SIGNAL/1000 ROM data are available from Bitsavers.
|
||||
|
||||
Additional references (documents unavailable):
|
||||
- HP Signal/1000 User Reference and Installation Manual (92835-90002).
|
||||
- SIGNAL/1000 Microcode Source (92835-18075, revision 2).
|
||||
*/
|
||||
|
||||
static const OP_PAT op_signal [16] = {
|
||||
OP_AAKK, OP_AAFFKK, OP_AAFFKK, OP_AAFFKK, /* BITRV BTRFY UNSCR PRSCR */
|
||||
OP_AAAKK, OP_AAAFFKK, OP_AAA, OP_AAA, /* BITR1 BTRF1 .CADD .CSUB */
|
||||
OP_AAA, OP_AAA, OP_AAA, OP_A, /* .CMPY .CDIV CONJG ..CCM */
|
||||
OP_AA, OP_AAFF, OP_N, OP_N /* AIMAG CMPLX --- [test]*/
|
||||
};
|
||||
|
||||
t_stat cpu_signal (uint32 IR, uint32 intrq)
|
||||
{
|
||||
t_stat reason = SCPE_OK;
|
||||
@@ -649,8 +661,6 @@ OP a,b,c,d,p1,p2,p3,p4,m1,m2,wr,wi;
|
||||
uint32 entry, v, idx1, idx2;
|
||||
int32 exc, exd;
|
||||
|
||||
t_bool debug = DEBUG_PRI (cpu_dev, DEB_SIG);
|
||||
|
||||
entry = IR & 017; /* mask to entry point */
|
||||
|
||||
if (op_signal [entry] != OP_N) {
|
||||
@@ -659,15 +669,6 @@ if (op_signal [entry] != OP_N) {
|
||||
return reason; /* return reason for failure */
|
||||
}
|
||||
|
||||
if (debug) { /* debugging? */
|
||||
fprintf (sim_deb, ">>CPU SIG: IR = %06o (", IR); /* print preamble and IR */
|
||||
fprint_sym (sim_deb, err_PC, (t_value *) &IR, /* print instruction mnemonic */
|
||||
NULL, SWMASK('M'));
|
||||
fprintf (sim_deb, "), P = %06o", err_PC); /* print location */
|
||||
fprint_ops (op_signal[entry], op); /* print operands */
|
||||
fputc ('\n', sim_deb); /* terminate line */
|
||||
}
|
||||
|
||||
switch (entry) { /* decode IR<3:0> */
|
||||
case 000: /* BITRV (OP_AAKK) */
|
||||
/* BITRV
|
||||
@@ -933,8 +934,8 @@ switch (entry) { /* decode IR<3:0> */
|
||||
break;
|
||||
|
||||
case 016: /* invalid */
|
||||
default: /* others undefined */
|
||||
reason = stop_inst;
|
||||
default: /* others unimplemented */
|
||||
reason = STOP (cpu_ss_unimpl);
|
||||
}
|
||||
|
||||
return reason;
|
||||
|
||||
@@ -1,29 +1,43 @@
|
||||
/* hp2100_defs.h: HP 2100 System architectural declarations
|
||||
|
||||
Copyright (c) 1993-2016, Robert M. Supnik
|
||||
Copyright (c) 2017 J. David Bryan
|
||||
Copyright (c) 2017-2018 J. David Bryan
|
||||
|
||||
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:
|
||||
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.
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS 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.
|
||||
Except as contained in this notice, the names of the authors shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from the authors.
|
||||
|
||||
07-May-18 JDB Added NOTE_SKIP, simplified setSKF macro
|
||||
02-May-18 JDB Added "SIRDEV" for first device to receive the SIR signal
|
||||
16-Oct-17 JDB Suppressed logical-not-parentheses warning on clang
|
||||
30-Aug-17 JDB Replaced POLL_WAIT with POLL_PERIOD
|
||||
07-Aug-17 JDB Added "hp_attach"
|
||||
20-Jul-17 JDB Removed STOP_OFFLINE, STOP_PWROFF stop codes
|
||||
11-Jul-17 JDB Moved "ibl_copy" to hp2100_cpu.h
|
||||
26-Jun-17 JDB Moved I/O instruction subopcode constants to hp2100_cpu.c
|
||||
14-Jun-17 JDB Renamed STOP_RSRV to STOP_UNIMPL (unimplemented instruction)
|
||||
15-Mar-17 JDB Added global trace flags
|
||||
27-Feb-17 JDB ibl_copy no longer returns a status code
|
||||
15-Feb-17 JDB Deleted unneeded guard macro definition
|
||||
16-Jan-17 JDB Added tracing and console output macros
|
||||
13-Jan-17 JDB Added fprint_cpu
|
||||
10-Jan-17 JDB Added architectural constants
|
||||
05-Aug-16 JDB Removed PC_Global renaming; P register is now "PR"
|
||||
13-May-16 JDB Modified for revised SCP API function parameter types
|
||||
@@ -150,9 +164,6 @@
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HP2100_DEFS_H_
|
||||
#define HP2100_DEFS_H_ 0
|
||||
|
||||
|
||||
#include "sim_rev.h"
|
||||
#include "sim_defs.h"
|
||||
@@ -177,6 +188,7 @@
|
||||
*/
|
||||
|
||||
#if defined (__clang__)
|
||||
#pragma clang diagnostic ignored "-Wlogical-not-parentheses"
|
||||
#pragma clang diagnostic ignored "-Wlogical-op-parentheses"
|
||||
#pragma clang diagnostic ignored "-Wbitwise-op-parentheses"
|
||||
#pragma clang diagnostic ignored "-Wshift-op-parentheses"
|
||||
@@ -188,18 +200,143 @@
|
||||
#endif
|
||||
|
||||
|
||||
/* Simulator stop and notification codes */
|
||||
/* Device register display mode flags */
|
||||
|
||||
#define STOP_RSRV 1 /* must be 1 */
|
||||
#define STOP_IODV 2 /* must be 2 */
|
||||
#define STOP_HALT 3 /* HALT */
|
||||
#define STOP_IBKPT 4 /* breakpoint */
|
||||
#define STOP_IND 5 /* indirect loop */
|
||||
#define NOTE_INDINT 6 /* indirect intr */
|
||||
#define STOP_NOCONN 7 /* no connection */
|
||||
#define STOP_OFFLINE 8 /* device offline */
|
||||
#define STOP_PWROFF 9 /* device powered off */
|
||||
#define NOTE_IOG 10 /* I/O instr executed */
|
||||
#define REG_X REG_VMIO /* permit symbolic display overrides */
|
||||
|
||||
#define REG_A (1u << REG_V_UF + 0) /* default format is -A (one ASCII character) */
|
||||
#define REG_C (1u << REG_V_UF + 1) /* default format is -C (two ASCII characters) */
|
||||
#define REG_M (1u << REG_V_UF + 2) /* default format is -M (mnemonic) */
|
||||
|
||||
|
||||
/* Global tracing flags.
|
||||
|
||||
Global tracing flags are allocated in descending order, as they may be used
|
||||
by modules that allocate their own private flags in ascending order. No
|
||||
check is made for overlapping values.
|
||||
*/
|
||||
|
||||
#define TRACE_CMD (1u << 31) /* trace interface or controller commands */
|
||||
#define TRACE_INCO (1u << 30) /* trace interface or controller command initiations and completions */
|
||||
#define TRACE_CSRW (1u << 29) /* trace interface control, status, read, and write actions */
|
||||
#define TRACE_STATE (1u << 28) /* trace state changes */
|
||||
#define TRACE_SERV (1u << 27) /* trace unit service scheduling calls and entries */
|
||||
#define TRACE_PSERV (1u << 26) /* trace periodic unit service scheduling calls and entries */
|
||||
#define TRACE_XFER (1u << 25) /* trace data receptions and transmissions */
|
||||
#define TRACE_IOBUS (1u << 24) /* trace I/O bus signals and data words received and returned */
|
||||
|
||||
#define DEB_CMDS (1u << 23) /* (old) trace command initiations and completions */
|
||||
#define DEB_CPU (1u << 22) /* (old) trace words received from and sent to the CPU */
|
||||
#define DEB_BUF (1u << 21) /* (old) trace data read from and written to the FIFO */
|
||||
#define DEB_XFER (1u << 20) /* (old) trace data receptions and transmissions */
|
||||
#define DEB_RWS (1u << 19) /* (old) trace tape reads, writes, and status returns */
|
||||
#define DEB_RWSC (1u << 18) /* (old) trace disc read/write/status/control commands */
|
||||
#define DEB_SERV (1u << 17) /* (old) trace unit service scheduling calls and entries */
|
||||
|
||||
|
||||
/* Tracing and console output.
|
||||
|
||||
"tprintf" is used to write tracing messages. It does an "fprintf" to the
|
||||
debug output stream if the stream is open and the trace "flag" is currently
|
||||
enabled in device "dev". Otherwise, it's a NOP. "..." is the format string
|
||||
and associated values.
|
||||
|
||||
"tpprintf" is identical to "tprintf", except that a device pointer is passed
|
||||
instead of a device structure.
|
||||
|
||||
"TRACING" and "TRACINGP" implement the test conditions for device and device
|
||||
pointer tracing, respectively. They are used explicitly only when several
|
||||
trace statements employing the same flag are required, and it is desirable to
|
||||
avoid repeating the stream and flag test for each one.
|
||||
|
||||
"cprintf", "cputs", and "cputc" are used to write messages to the console
|
||||
and, if console logging is enabled, to the log output stream. They do
|
||||
"(f)printf", "fputs", or "(f)putc", respectively. "..." is the format string
|
||||
and associated values, "str" is the string to write, and "ch" is the
|
||||
character to write.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. The "cputs" macro uses "fputs" for both console and log file output
|
||||
because "puts" appends a newline, whereas "fputs" does not.
|
||||
*/
|
||||
|
||||
#define TRACING(d,f) (sim_deb != NULL && ((d).dctrl & (f)))
|
||||
|
||||
#define TRACINGP(d,f) (sim_deb != NULL && ((d)->dctrl & (f)))
|
||||
|
||||
#define tprintf(dev, flag, ...) \
|
||||
if (TRACING (dev, flag)) \
|
||||
hp_trace (&(dev), (flag), __VA_ARGS__); \
|
||||
else \
|
||||
(void) 0
|
||||
|
||||
#define tpprintf(dptr, flag, ...) \
|
||||
if (TRACINGP (dptr, flag)) \
|
||||
hp_trace ((dptr), (flag), __VA_ARGS__); \
|
||||
else \
|
||||
(void) 0
|
||||
|
||||
#define cprintf(...) \
|
||||
do { \
|
||||
printf (__VA_ARGS__); \
|
||||
if (sim_log) \
|
||||
fprintf (sim_log, __VA_ARGS__); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define cputs(str) \
|
||||
do { \
|
||||
fputs (str, stdout); \
|
||||
if (sim_log) \
|
||||
fputs (str, sim_log); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define cputc(ch) \
|
||||
do { \
|
||||
putc (ch); \
|
||||
if (sim_log) \
|
||||
fputc (ch, sim_log); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
|
||||
/* Simulation stop and notification codes.
|
||||
|
||||
The STOP_* status codes stop the simulator. The "sim_stop_messages" array in
|
||||
"hp2100_sys.c" contains the message strings that correspond one-for-one with
|
||||
the stop codes.
|
||||
|
||||
The NOTE_* status codes do not stop the simulator. Instead, they inform the
|
||||
instruction execution loop of special situations that occurred while
|
||||
processing the current machine instruction..
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. Codes before STOP_RERUN cause the instruction to be rerun, so P is backed
|
||||
up twice. For codes after, P points to the next instruction to be
|
||||
executed (which is the current instruction for an infinite loop stop).
|
||||
*/
|
||||
|
||||
#define STOP_UNIMPL 1 /* unimplemented instruction stop */
|
||||
#define STOP_UNSC 2 /* stop on I/O to an unassigned select code */
|
||||
#define STOP_UNDEF 3 /* undefined instruction stop */
|
||||
#define STOP_INDIR 4 /* stop on an indirect loop */
|
||||
|
||||
#define STOP_RERUN 4 /* stops above here cause the instruction to be re-run */
|
||||
|
||||
#define STOP_HALT 5 /* programmed halt */
|
||||
#define STOP_BRKPNT 6 /* breakpoint */
|
||||
#define STOP_NOCONN 7 /* no connection */
|
||||
#define STOP_NOTAPE 8 /* no tape */
|
||||
#define STOP_EOT 9 /* end of tape */
|
||||
|
||||
#define NOTE_IOG 10 /* an I/O instruction was executed */
|
||||
#define NOTE_INDINT 11 /* an interrupt occurred while resolving an indirect address */
|
||||
#define NOTE_SKIP 12 /* the SKF signal was asserted by an I/O interface */
|
||||
|
||||
|
||||
/* Modifier validation identifiers */
|
||||
@@ -208,6 +345,54 @@
|
||||
#define MTAB_XUN (MTAB_XTD | MTAB_VUN)
|
||||
|
||||
|
||||
/* I/O event timing.
|
||||
|
||||
I/O events are scheduled for future service by specifying the desired delay
|
||||
in units of event ticks. Typically, one event tick represents the execution
|
||||
of one CPU instruction, and this is the way event ticks are defined in the
|
||||
current simulator implementation. However, the various CPUs themselves not
|
||||
only vary in speed, but the actual instruction times vary greatly, due to the
|
||||
presence of block move, compare, and scan instructions. Variations of an
|
||||
order of magnitude are common, and two orders or more are possible for longer
|
||||
blocks.
|
||||
|
||||
The 24296-90001 Diagnostic Configurator provides a one millisecond timer for
|
||||
use by the diagnostic programs. The timer is a two-instruction software
|
||||
loop, plus four instructions of entry/exit overhead, based on the processor
|
||||
type. The values provided are:
|
||||
|
||||
Loop Instr
|
||||
CPU Count /msec
|
||||
------ ----- -----
|
||||
2114 246 496
|
||||
2115 246 496
|
||||
2116 309 622
|
||||
2100 252 508
|
||||
1000-M 203 410
|
||||
1000-E 1573 * 1577
|
||||
|
||||
* The E-Series TIMER instruction is used instead of a software loop. TIMER
|
||||
re-executes an internal decrement until the supplied value reaches zero.
|
||||
|
||||
To pass diagnostics that time peripheral operations, the simulator assumes
|
||||
the E-Series execution rate for all devices (0.634 microseconds per event
|
||||
tick), although this results in needlessly long delays for normal operation.
|
||||
A correct implementation would change the timing base depending on the
|
||||
currently selected CPU.
|
||||
|
||||
To accommodate possible future variable instruction timing, I/O service
|
||||
activation times must not assume a constant 0.634 microseconds per event
|
||||
tick. Delays should be defined in terms of the "uS" (microseconds), "mS"
|
||||
(milliseconds), and "S" (seconds) macros below.
|
||||
*/
|
||||
|
||||
#define USEC_PER_EVENT 0.634 /* average CPU instruction time in microseconds */
|
||||
|
||||
#define uS(t) (uint32) ((t) > USEC_PER_EVENT ? (t) / USEC_PER_EVENT + 0.5 : 1)
|
||||
#define mS(t) (uint32) (((t) * 1000.0) / USEC_PER_EVENT + 0.5)
|
||||
#define S(t) (uint32) (((t) * 1000000.0) / USEC_PER_EVENT + 0.5)
|
||||
|
||||
|
||||
/* Architectural constants.
|
||||
|
||||
These macros specify the width, sign location, value mask, and minimum and
|
||||
@@ -217,11 +402,52 @@
|
||||
|
||||
The HP_WORD type is used to declare variables that represent 16-bit registers
|
||||
or buses in hardware.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. The HP_WORD type is a 32-bit unsigned type, instead of the more logical
|
||||
16-bit unsigned type. There are two reasons for this. First, SCP
|
||||
requires that scalars referenced by REG (register) entries be 32 bits in
|
||||
size. Second, IA-32 processors execute instructions with 32-bit operands
|
||||
much faster than those with 16-bit operands.
|
||||
|
||||
Using 16-bit operands omits the masking required for 32-bit values. For
|
||||
example, the code generated for the following operations is as follows:
|
||||
|
||||
uint16 a, b, c;
|
||||
a = b + c & 0xFFFF;
|
||||
|
||||
movzwl _b, %eax
|
||||
addw _c, %ax
|
||||
movw %ax, _a
|
||||
|
||||
uint32 x, y, z;
|
||||
x = y + z & 0xFFFF;
|
||||
|
||||
movl _z, %eax
|
||||
addl _y, %eax
|
||||
andl $65535, %eax
|
||||
movl %eax, _x
|
||||
|
||||
However, the first case uses operand override prefixes, which require
|
||||
substantially more time to decode (6 clock cycles vs. 1 clock cycle).
|
||||
This time outweighs the additional 32-bit AND instruction, which executes
|
||||
in 1 clock cycle.
|
||||
|
||||
2. The MEMORY_WORD type is a 16-bit unsigned type, corresponding with the
|
||||
16-bit main memory in the HP 21xx/1000. Unlike the general data type,
|
||||
which is a 32-bit type for speed, main memory does not benefit from the
|
||||
faster 32-bit execution on IA-32 processors, as only one instruction in
|
||||
the mem_read and mem_write routines has an operand override that invokes
|
||||
the slower instruction fetch path. There is a negligible difference in
|
||||
the Memory Pattern Test diagnostic execution speeds for the uint32 vs.
|
||||
uint16 definition, whereas the VM requirements are doubled for the
|
||||
former.
|
||||
*/
|
||||
|
||||
typedef uint16 HP_WORD; /* HP 16-bit data word representation */
|
||||
|
||||
#define R_MASK 0177777u /* 16-bit register mask */
|
||||
typedef uint32 HP_WORD; /* HP 16-bit data word representation */
|
||||
typedef uint16 MEMORY_WORD; /* HP 16-bit memory word representation */
|
||||
|
||||
#define D4_WIDTH 4 /* 4-bit data bit width */
|
||||
#define D4_MASK 0017u /* 4-bit data mask */
|
||||
@@ -267,6 +493,11 @@ typedef uint16 HP_WORD; /* HP 16-bit data word r
|
||||
#define S32_OVFL_MASK ((t_uint64) D32_UMAX << D32_WIDTH | \
|
||||
D32_SIGN) /* 32-bit signed overflow mask */
|
||||
|
||||
#define LSB 1u /* least-significant bit */
|
||||
#define D16_SIGN_LSB (D16_SIGN | LSB) /* bit 15 and bit 0 */
|
||||
|
||||
#define R_MASK 0177777u /* 16-bit register mask */
|
||||
|
||||
|
||||
/* Memory constants */
|
||||
|
||||
@@ -293,6 +524,40 @@ typedef uint16 HP_WORD; /* HP 16-bit data word r
|
||||
#define DV_SMAX ((1u << (DV_WIDTH - 1)) - 1) /* data value signed maximum (2 ** 15 - 1) */
|
||||
|
||||
|
||||
/* Memory address macros.
|
||||
|
||||
These macros convert between logical and physical addresses. The functions
|
||||
provided are:
|
||||
|
||||
- PAGE -- extract the page number part of a physical address
|
||||
- OFFSET -- extract the offset part of a physical address
|
||||
- TO_PA -- merge a page number and offset into a physical address
|
||||
*/
|
||||
|
||||
#define PAGE(p) ((p) >> PG_WIDTH & PG_MASK)
|
||||
#define OFFSET(p) ((p) & OF_MASK)
|
||||
#define TO_PA(b,o) (((uint32) (b) & PG_MASK) << PG_WIDTH | (uint32) (o) & OF_MASK)
|
||||
|
||||
|
||||
/* Memory access classifications.
|
||||
|
||||
The access classification determines the DMS map set and protections to use
|
||||
when reading or writing memory words. The classification also is used to
|
||||
label each data access when tracing is enabled. When DMS is disabled, or
|
||||
when the CPU is one of the 21xx models, the classification is irrelevant.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
Fetch, /* instruction fetch, current map */
|
||||
Data, /* data access, current map */
|
||||
Data_Alternate, /* data access, alternate map */
|
||||
Data_System, /* data access, system map */
|
||||
Data_User, /* data access, user map */
|
||||
DMA_Channel_1, /* DMA channel 1, port A map */
|
||||
DMA_Channel_2 /* DMA channel 2, port B map */
|
||||
} ACCESS_CLASS;
|
||||
|
||||
|
||||
/* Portable conversions.
|
||||
|
||||
SIMH is written with the assumption that the defined-size types (e.g.,
|
||||
@@ -302,28 +567,28 @@ typedef uint16 HP_WORD; /* HP 16-bit data word r
|
||||
|
||||
negative_value_32 = (int32) negative_value_16;
|
||||
|
||||
...will not guarantee that bits 0-15 of "negative_value_32" are ones, whereas
|
||||
the supplied sign-extension macro will.
|
||||
...will not guarantee that the upper 16 bits of "negative_value_32" are all
|
||||
ones, whereas the supplied sign-extension macro will.
|
||||
|
||||
The conversions available are:
|
||||
|
||||
- SEXT8 -- int8 sign-extended to int32
|
||||
- SEXT16 -- int16 sign-extended to int32
|
||||
- NEG16 -- int8 negated
|
||||
- NEG16 -- int16 negated
|
||||
- NEG32 -- int32 negated
|
||||
- SEXT8 -- signed 8-bit value sign-extended to int32
|
||||
- SEXT16 -- signed 16-bit value sign-extended to int32
|
||||
- NEG8 -- signed 8-bit value negated
|
||||
- NEG16 -- signed 16-bit value negated
|
||||
- NEG32 -- signed 32-bit value negated
|
||||
- INT16 -- uint16 to int16
|
||||
- INT32 -- uint32 to int32
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. The routines assume that 16-bit values are masked to exactly 16 bits
|
||||
before invoking.
|
||||
1. The SEXTn and INTn routines assume that their values are masked to
|
||||
exactly n bits before invoking.
|
||||
*/
|
||||
|
||||
#define SEXT8(x) (int32) ((x) & D8_SIGN ? (x) | ~D8_MASK : (x))
|
||||
#define SEXT16(x) (int32) ((x) & D16_SIGN ? (x) | ~D16_MASK : (x))
|
||||
#define SEXT8(x) ((int32) ((x) & D8_SIGN ? (x) | ~D8_MASK : (x)))
|
||||
#define SEXT16(x) ((int32) ((x) & D16_SIGN ? (x) | ~D16_MASK : (x)))
|
||||
|
||||
#define NEG8(x) ((~(x) + 1) & D8_MASK)
|
||||
#define NEG16(x) ((~(x) + 1) & D16_MASK)
|
||||
@@ -371,12 +636,43 @@ typedef enum {
|
||||
#define TO_DWORD(u,l) ((uint32) (u) << D16_WIDTH | (l))
|
||||
|
||||
|
||||
/* Portable conversions (sign-extension, unsigned-to-signed) */
|
||||
/* CPU instruction symbolic source.
|
||||
|
||||
#define SEXT(x) ((int32) (((x) & SIGN)? ((x) | ~DMASK): ((x) & DMASK)))
|
||||
The memory-reference group (MRG) instructions do not specify full logical
|
||||
addresses of their targets. Instead, they specify offsets from either the
|
||||
base page or the current page. Instructions specifying base-page offsets are
|
||||
always displayed with target addresses between 0000-1777. The display and
|
||||
parsing of instructions specifying current-page offsets depends on the source
|
||||
of the instructions.
|
||||
|
||||
If the current-page CPU instruction is contained in main memory, the current
|
||||
page is taken from the address of the word containing the instruction, and
|
||||
the full target address between 00000-77777 is displayed or parsed. However,
|
||||
if the instruction is contained in a device buffer, e.g., a disc drive sector
|
||||
buffer, the destination memory address is unknown until the instruction is
|
||||
transferred to memory. In this case, the target address is displayed or
|
||||
parsed as the offset prefixed with the letter "C" (e.g., "LDA C 1200"). In
|
||||
order to present the proper symbolic behavior, the mnemonic formatter and
|
||||
parser must know the source of the request.
|
||||
|
||||
Additionally, display requests from the EXAMINE command have preloaded a
|
||||
value array with the maximum number of words required to encode the longest
|
||||
instruction. This is inefficient, as only a fraction of the instruction set
|
||||
requires more than one word. For EXAMINE commands entered by the user at the
|
||||
SCP prompt, this is unimportant. However, for calls from the CPU instruction
|
||||
trace routine, the overhead is significant. In the latter case, the array is
|
||||
loaded only with a single word, and the mnemonic formatter loads additional
|
||||
words if the specific instruction to be displayed requires them.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
Device_Symbol, /* called for an EXAMINE <device> or DEPOSIT <device> command */
|
||||
CPU_Symbol, /* called for an EXAMINE CPU or DEPOSIT CPU command */
|
||||
CPU_Trace /* called for a CPU trace command */
|
||||
} SYMBOL_SOURCE;
|
||||
|
||||
|
||||
/* Memory */
|
||||
/* Memory constants (deprecated) */
|
||||
|
||||
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
|
||||
#define VA_N_SIZE 15 /* virtual addr size */
|
||||
@@ -386,7 +682,7 @@ typedef enum {
|
||||
#define PASIZE (1 << PA_N_SIZE)
|
||||
#define PAMASK (PASIZE - 1) /* phys addr mask */
|
||||
|
||||
/* Architectural constants */
|
||||
/* Architectural constants (deprecated) */
|
||||
|
||||
#define SIGN32 020000000000 /* 32b sign */
|
||||
#define DMASK32 037777777777 /* 32b data mask/maximum value */
|
||||
@@ -403,20 +699,10 @@ typedef enum {
|
||||
|
||||
#define POLL_RATE 100 /* poll 100 times per second */
|
||||
#define POLL_FIRST 1 /* first poll is "immediate" */
|
||||
#define POLL_WAIT 15800 /* initial poll ~ 10 msec. */
|
||||
#define POLL_PERIOD mS (10) /* 10 millisecond poll period */
|
||||
|
||||
typedef enum { INITIAL, SERVICE } POLLMODE; /* poll synchronization modes */
|
||||
|
||||
/* I/O instruction sub-opcodes */
|
||||
|
||||
#define soHLT 0 /* halt */
|
||||
#define soFLG 1 /* set/clear flag */
|
||||
#define soSFC 2 /* skip on flag clear */
|
||||
#define soSFS 3 /* skip on flag set */
|
||||
#define soMIX 4 /* merge into A/B */
|
||||
#define soLIX 5 /* load into A/B */
|
||||
#define soOTX 6 /* output from A/B */
|
||||
#define soCTL 7 /* set/clear control */
|
||||
|
||||
/* I/O devices - fixed select code assignments */
|
||||
|
||||
@@ -460,37 +746,11 @@ typedef enum { INITIAL, SERVICE } POLLMODE; /* poll synchronization
|
||||
#define DI_DC 044 /* 12821A Disc Interface with CS/80 disc and tape devices */
|
||||
|
||||
#define OPTDEV 002 /* start of optional devices */
|
||||
#define SIRDEV 004 /* start of devices that receive SIR */
|
||||
#define CRSDEV 006 /* start of devices that receive CRS */
|
||||
#define VARDEV 010 /* start of variable assignments */
|
||||
#define MAXDEV 077 /* end of select code range */
|
||||
|
||||
/* IBL assignments */
|
||||
|
||||
#define IBL_V_SEL 14 /* ROM select <15:14> */
|
||||
#define IBL_M_SEL 03
|
||||
#define IBL_PTR 0000000 /* ROM 0: 12992K paper tape reader (PTR) */
|
||||
#define IBL_DP 0040000 /* ROM 1: 12992A 7900 disc (DP) */
|
||||
#define IBL_DQ 0060000 /* ROM 1: 12992A 2883 disc (DQ) */
|
||||
#define IBL_MS 0100000 /* ROM 2: 12992D 7970 tape (MS) */
|
||||
#define IBL_DS 0140000 /* ROM 3: 12992B 7905/06/20/25 disc (DS) */
|
||||
#define IBL_MAN 0010000 /* RPL/manual boot <13:12> */
|
||||
#define IBL_V_DEV 6 /* select code <11:6> */
|
||||
#define IBL_OPT 0000070 /* options in <5:3> */
|
||||
#define IBL_DP_REM 0000001 /* DP removable <0:0> */
|
||||
#define IBL_DS_HEAD 0000003 /* DS head number <1:0> */
|
||||
#define IBL_LNT 64 /* boot ROM length in words */
|
||||
#define IBL_MASK (IBL_LNT - 1) /* boot length mask */
|
||||
#define IBL_DPC (IBL_LNT - 2) /* DMA ctrl word */
|
||||
#define IBL_END (IBL_LNT - 1) /* last location */
|
||||
|
||||
#define IBL_S_CLR 0000000 /* ibl_copy mask to clear the S register */
|
||||
#define IBL_S_NOCLR 0177777 /* ibl_copy mask to preserve the S register */
|
||||
#define IBL_S_NOSET 0000000 /* ibl_copy mask to preserve the S register */
|
||||
|
||||
#define IBL_SET_SC(s) ((s) << IBL_V_DEV) /* position the select code in the S register */
|
||||
|
||||
typedef uint16 BOOT_ROM [IBL_LNT]; /* boot ROM data */
|
||||
|
||||
|
||||
/* I/O backplane signals.
|
||||
|
||||
@@ -526,9 +786,9 @@ typedef uint16 BOOT_ROM [IBL_LNT]; /* boot ROM data */
|
||||
|
||||
2. The ioSKF signal is never sent to an I/O handler. Rather, it is returned
|
||||
from the handler if the SFC or SFS condition is true. If the condition
|
||||
is false, ioNONE is returned instead. As these two values are returned
|
||||
in the 16-bit data portion of the returned value, their assigned values
|
||||
must be <= 100000 octal.
|
||||
is false, ioNONE is returned instead. As the ioSKF value is returned in
|
||||
the upper 16 bits of the returned value, its assigned value must be >=
|
||||
200000 octal.
|
||||
|
||||
3. An I/O handler will receive ioCRS as a result of a CLC 0 instruction,
|
||||
ioPOPIO and ioCRS as a result of a RESET command, and ioPON, ioPOPIO, and
|
||||
@@ -563,21 +823,22 @@ typedef enum { ioNONE = 0000000, /* -- -- -- -- -- no sig
|
||||
ioIOI = 0000004, /* -- -- T4 T5 -- I/O data input (CPU)
|
||||
T2 T3 -- -- -- I/O data input (DMA) */
|
||||
ioIOO = 0000010, /* -- T3 T4 -- -- I/O data output */
|
||||
ioSKF = 0000020, /* -- T3 T4 T5 -- skip on flag */
|
||||
ioSFS = 0000040, /* -- T3 T4 T5 -- skip if flag is set */
|
||||
ioSFC = 0000100, /* -- T3 T4 T5 -- skip if flag is clear */
|
||||
ioSTC = 0000200, /* -- -- T4 -- -- set control flip-flop (CPU)
|
||||
ioSFS = 0000020, /* -- T3 T4 T5 -- skip if flag is set */
|
||||
ioSFC = 0000040, /* -- T3 T4 T5 -- skip if flag is clear */
|
||||
ioSTC = 0000100, /* -- -- T4 -- -- set control flip-flop (CPU)
|
||||
-- T3 -- -- -- set control flip-flop (DMA) */
|
||||
ioCLC = 0000400, /* -- -- T4 -- -- clear control flip-flop (CPU)
|
||||
ioCLC = 0000200, /* -- -- T4 -- -- clear control flip-flop (CPU)
|
||||
-- T3 T4 -- -- clear control flip-flop (DMA) */
|
||||
ioSTF = 0001000, /* -- T3 -- -- -- set flag flip-flop */
|
||||
ioCLF = 0002000, /* -- -- T4 -- -- clear flag flip-flop (CPU)
|
||||
ioSTF = 0000400, /* -- T3 -- -- -- set flag flip-flop */
|
||||
ioCLF = 0001000, /* -- -- T4 -- -- clear flag flip-flop (CPU)
|
||||
-- T3 -- -- -- clear flag flip-flop (DMA) */
|
||||
ioEDT = 0004000, /* -- -- T4 -- -- end data transfer */
|
||||
ioCRS = 0010000, /* -- -- -- T5 -- control reset */
|
||||
ioPOPIO = 0020000, /* -- -- -- T5 -- power-on preset to I/O */
|
||||
ioIAK = 0040000, /* -- -- -- -- T6 interrupt acknowledge */
|
||||
ioSIR = 0100000 } IOSIGNAL; /* -- -- -- T5 -- set interrupt request */
|
||||
ioEDT = 0002000, /* -- -- T4 -- -- end data transfer */
|
||||
ioCRS = 0004000, /* -- -- -- T5 -- control reset */
|
||||
ioPOPIO = 0010000, /* -- -- -- T5 -- power-on preset to I/O */
|
||||
ioIAK = 0020000, /* -- -- -- -- T6 interrupt acknowledge */
|
||||
ioSIR = 0040000, /* -- -- -- T5 -- set interrupt request */
|
||||
|
||||
ioSKF = 0200000 } IOSIGNAL; /* -- T3 T4 T5 -- skip on flag */
|
||||
|
||||
|
||||
typedef uint32 IOCYCLE; /* a set of signals forming one I/O cycle */
|
||||
@@ -599,20 +860,50 @@ typedef enum {
|
||||
#define D_FF(b) (FLIP_FLOP) ((b) != 0) /* use a Boolean expression for a D flip-flop */
|
||||
|
||||
|
||||
/* I/O structures */
|
||||
/* I/O structures.
|
||||
|
||||
typedef struct dib DIB; /* incomplete definition */
|
||||
The Device Information Block (DIB) allows devices to be relocated in the
|
||||
machine's I/O space. Each DIB contains a pointer to the device interface
|
||||
routine, a value corresponding to the location of the interface card in the
|
||||
CPU's I/O card cage (which determines the card's select code), and a card
|
||||
index if the interface routine services multiple cards.
|
||||
|
||||
typedef uint32 IOHANDLER (DIB *dibptr, /* I/O signal handler prototype */
|
||||
IOCYCLE signal_set,
|
||||
uint32 stat_data);
|
||||
|
||||
struct dib { /* Device information block */
|
||||
IOHANDLER *io_handler; /* pointer to device's I/O signal handler */
|
||||
uint32 select_code; /* device's select code */
|
||||
uint32 card_index; /* device's card index for state variables */
|
||||
Implementation notes:
|
||||
|
||||
1. The select_code and card_index fields could be smaller than the defined
|
||||
32-bit sizes, but IA-32 processors execute instructions with 32-bit
|
||||
operands much faster than those with 16- or 8-bit operands.
|
||||
|
||||
2. The DIB_REGS macro provides hidden register entries needed to save and
|
||||
restore the state of a DIB. Only the potentially variable fields are
|
||||
referenced. In particular, the "io_interface" field must not be saved,
|
||||
as the address of the device's interface routine may change from version
|
||||
to version of the simulator.
|
||||
*/
|
||||
|
||||
#define SC_MAX 077 /* the maximum select code */
|
||||
#define SC_MASK 077u /* the mask for the select code */
|
||||
#define SC_BASE 8 /* the radix for the select code */
|
||||
|
||||
typedef struct dib DIB; /* an incomplete definition */
|
||||
|
||||
typedef uint32 IOHANDLER /* the I/O device interface function prototype */
|
||||
(DIB *dibptr, /* a pointer to the device information block */
|
||||
IOCYCLE signal_set, /* a set of inbound signals */
|
||||
uint32 stat_data); /* a 32-bit inbound value */
|
||||
|
||||
struct dib { /* the Device Information Block */
|
||||
IOHANDLER *io_handler; /* the device's I/O interface function pointer */
|
||||
uint32 select_code; /* the device's select code (02-77) */
|
||||
uint32 card_index; /* the card index if multiple interfaces are supported */
|
||||
};
|
||||
|
||||
#define DIB_REGS(dib) \
|
||||
/* Macro Name Location Width Flags */ \
|
||||
/* ------ ------- -------------------------- ----- ----------------- */ \
|
||||
{ ORDATA (DIBSC, dib.select_code, 32), PV_LEFT | REG_HRO }
|
||||
|
||||
|
||||
/* I/O signal and status macros.
|
||||
|
||||
@@ -654,12 +945,12 @@ struct dib { /* Device information bl
|
||||
if the Boolean test B is true.
|
||||
*/
|
||||
|
||||
#define IONEXT(I) (IOSIGNAL) ((I) & (IOCYCLE) (- (int32) (I))) /* extract next I/O signal to handle */
|
||||
#define IONEXT(I) (IOSIGNAL) ((I) & ~(I) + 1) /* extract next I/O signal to handle */
|
||||
#define IOADDSIR(I) ((I) & IOIRQSET ? (I) | ioSIR : (I)) /* add SIR if IRQ state might change */
|
||||
|
||||
#define IORETURN(E,D) ((uint32) ((E) << 16 | (D) & DMASK)) /* form I/O handler return value */
|
||||
#define IOSTATUS(C) ((t_stat) ((C) >> 16) & DMASK) /* extract I/O status from combined value */
|
||||
#define IODATA(C) ((uint16) ((C) & DMASK)) /* extract data from combined value */
|
||||
#define IORETURN(E,D) ((uint32) ((E) << D16_WIDTH | (D) & D16_MASK)) /* form I/O handler return value */
|
||||
#define IOSTATUS(C) ((t_stat) ((C) >> D16_WIDTH) & D16_MASK) /* extract I/O status from combined value */
|
||||
#define IODATA(C) ((uint16) ((C) & D16_MASK)) /* extract data from combined value */
|
||||
|
||||
#define IOPOWERON(P) (P)->io_handler ((P), ioPON | ioPOPIO | ioCRS, 0) /* send power-on signals to handler */
|
||||
#define IOPRESET(P) (P)->io_handler ((P), ioPOPIO | ioCRS, 0) /* send PRESET signals to handler */
|
||||
@@ -718,7 +1009,7 @@ struct dib { /* Device information bl
|
||||
#define BIT_V(S) ((S) & 037) /* convert select code to bit position */
|
||||
#define BIT_M(S) (1u << BIT_V (S)) /* convert select code to bit mask */
|
||||
|
||||
#define setSKF(B) stat_data = IORETURN (SCPE_OK, (uint16) ((B) ? ioSKF : ioNONE))
|
||||
#define setSKF(B) stat_data = ((B) ? ioSKF : ioNONE)
|
||||
|
||||
#define setPRL(S,B) dev_prl[(S)/32] = dev_prl[(S)/32] & ~BIT_M (S) | (((B) & 1) << BIT_V (S))
|
||||
#define setIRQ(S,B) dev_irq[(S)/32] = dev_irq[(S)/32] & ~BIT_M (S) | (((B) & 1) << BIT_V (S))
|
||||
@@ -736,26 +1027,81 @@ struct dib { /* Device information bl
|
||||
#define setstdSRQ(N) setSRQ (dibptr->select_code, N.flag);
|
||||
|
||||
|
||||
/* CPU state */
|
||||
/* Bitset formatting.
|
||||
|
||||
See the comments at the "fmt_bitset" function (hp2100_sys.c) for details of
|
||||
the specification of bitset names and format structures.
|
||||
*/
|
||||
|
||||
typedef enum { /* direction of interpretation */
|
||||
msb_first, /* left-to-right */
|
||||
lsb_first /* right-to-left */
|
||||
} BITSET_DIRECTION;
|
||||
|
||||
typedef enum { /* alternate names */
|
||||
no_alt, /* no alternates are present in the name array */
|
||||
has_alt /* the name array contains alternates */
|
||||
} BITSET_ALTERNATE;
|
||||
|
||||
typedef enum { /* trailing separator */
|
||||
no_bar, /* omit a trailing separator */
|
||||
append_bar /* append a trailing separator */
|
||||
} BITSET_BAR;
|
||||
|
||||
typedef const char *const BITSET_NAME; /* a bit name string pointer */
|
||||
|
||||
typedef struct { /* bit set format descriptor */
|
||||
uint32 name_count; /* count of bit names */
|
||||
BITSET_NAME *names; /* pointer to an array of bit names */
|
||||
uint32 offset; /* offset from LSB to first bit */
|
||||
BITSET_DIRECTION direction; /* direction of interpretation */
|
||||
BITSET_ALTERNATE alternate; /* alternate interpretations presence */
|
||||
BITSET_BAR bar; /* trailing separator choice */
|
||||
} BITSET_FORMAT;
|
||||
|
||||
/* Bitset format specifier initialization */
|
||||
|
||||
#define FMT_INIT(names,offset,dir,alt,bar) \
|
||||
sizeof (names) / sizeof (names) [0], \
|
||||
(names), (offset), (dir), (alt), (bar)
|
||||
|
||||
|
||||
/* System interface global data structures */
|
||||
|
||||
extern const HP_WORD odd_parity [256]; /* a table of parity bits for odd parity */
|
||||
|
||||
|
||||
/* System interface global SCP support routines declared in scp.h
|
||||
|
||||
extern t_stat sim_load (FILE *fptr, CONST char *cptr, CONST char *fnam, int flag);
|
||||
extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, UNIT *uptr, int32 sw);
|
||||
extern t_stat parse_sym (CONST char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw);
|
||||
*/
|
||||
|
||||
/* System interface global SCP support routines */
|
||||
|
||||
extern t_stat hp_attach (UNIT *uptr, CONST char *cptr);
|
||||
extern t_stat hp_set_dib (UNIT *uptr, int32 count, CONST char *cptr, void *desc);
|
||||
extern t_stat hp_show_dib (FILE *st, UNIT *uptr, int32 count, CONST void *desc);
|
||||
|
||||
|
||||
/* System interface global utility routines */
|
||||
|
||||
extern t_stat fprint_cpu (FILE *ofile, t_addr addr, t_value *val, uint32 radix, SYMBOL_SOURCE source);
|
||||
|
||||
extern const char *fmt_char (uint32 charval);
|
||||
extern const char *fmt_bitset (uint32 bitset, const BITSET_FORMAT bitfmt);
|
||||
|
||||
extern void hp_trace (DEVICE *dptr, uint32 flag, ...);
|
||||
extern t_bool hp_device_conflict (void);
|
||||
extern void hp_enbdis_pair (DEVICE *ccptr, DEVICE *dcptr);
|
||||
|
||||
|
||||
/* I/O state */
|
||||
|
||||
extern uint32 dev_prl [2], dev_irq [2], dev_srq [2]; /* I/O signal vectors */
|
||||
|
||||
/* CPU functions */
|
||||
|
||||
extern t_stat ibl_copy (const BOOT_ROM rom, int32 dev, uint32 sr_clear, uint32 sr_set);
|
||||
extern void hp_enbdis_pair (DEVICE *ccp, DEVICE *dcp);
|
||||
|
||||
/* System functions */
|
||||
|
||||
extern const char *fmt_char (uint8 ch);
|
||||
extern t_stat hp_setsc (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||||
extern t_stat hp_setdev (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||||
extern t_stat hp_showsc (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
||||
extern t_stat hp_showdev (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
||||
extern t_bool hp_fprint_stopped (FILE *st, t_stat reason);
|
||||
|
||||
/* Device-specific functions */
|
||||
|
||||
extern int32 sync_poll (POLLMODE poll_mode);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
DI 12821A Disc Interface
|
||||
|
||||
15-Mar-17 JDB Converted debug fprintfs to tpprintfs
|
||||
10-Mar-17 JDB Added IOBUS to the debug table
|
||||
17-Jan-17 JDB Changed to use new byte accessors in hp2100_defs.h
|
||||
13-May-16 JDB Modified for revised SCP API function parameter types
|
||||
24-Dec-14 JDB Added casts for explicit downward conversions
|
||||
@@ -177,6 +179,33 @@
|
||||
|
||||
#define TAG_MASK (TAG_ATN | TAG_EOI | TAG_EDT | TAG_LBR)
|
||||
|
||||
static const BITSET_NAME tag_names [] = { /* Bus signal names */
|
||||
"ATN", /* bit 16 */
|
||||
"EOI", /* bit 17 */
|
||||
"EDT", /* bit 18 */
|
||||
"LBR" /* bit 19 */
|
||||
};
|
||||
|
||||
static const BITSET_FORMAT tag_format = /* names, offset, direction, alternates, bar */
|
||||
{ FMT_INIT (tag_names, 16, lsb_first, no_alt, no_bar) };
|
||||
|
||||
|
||||
/* Bus signals */
|
||||
|
||||
static const BITSET_NAME bus_names [] = { /* Bus signal names */
|
||||
"ATN", /* bit 0 = attention */
|
||||
"EOI", /* bit 1 = end or identify */
|
||||
"DAV", /* bit 2 = data available */
|
||||
"NRFD", /* bit 3 = not ready for data */
|
||||
"NDAC", /* bit 4 = not data accepted */
|
||||
"REN", /* bit 5 = remote enable */
|
||||
"IFC", /* bit 6 = interface clear */
|
||||
"SRQ" /* bit 7 = service request */
|
||||
};
|
||||
|
||||
static const BITSET_FORMAT bus_format = /* names, offset, direction, alternates, bar */
|
||||
{ FMT_INIT (bus_names, 0, lsb_first, no_alt, no_bar) };
|
||||
|
||||
|
||||
/* FIFO access modes */
|
||||
|
||||
@@ -207,7 +236,6 @@ static void master_reset (CARD_ID card);
|
||||
static void update_state (CARD_ID card);
|
||||
static void fifo_load (CARD_ID card, uint16 data, FIFO_ACCESS access);
|
||||
static uint16 fifo_unload (CARD_ID card, FIFO_ACCESS access);
|
||||
static void fprint_bus (FILE *file, char *format, uint8 cntl);
|
||||
|
||||
|
||||
|
||||
@@ -251,7 +279,8 @@ DEVICE dc_dev = {
|
||||
0, /* debug control flags */
|
||||
di_deb, /* debug flag name table */
|
||||
NULL, /* memory size change routine */
|
||||
NULL }; /* logical device name */
|
||||
NULL /* logical device name */
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -280,13 +309,14 @@ static RESPONDER *bus_respond [card_count] = { &da_bus_respond, NULL, NULL };
|
||||
|
||||
|
||||
DEBTAB di_deb [] = {
|
||||
{ "CPU", DEB_CPU },
|
||||
{ "CMDS", DEB_CMDS },
|
||||
{ "BUF", DEB_BUF },
|
||||
{ "XFER", DEB_XFER },
|
||||
{ "RWSC", DEB_RWSC },
|
||||
{ "SERV", DEB_SERV },
|
||||
{ NULL, 0 }
|
||||
{ "RWSC", DEB_RWSC },
|
||||
{ "CMDS", DEB_CMDS },
|
||||
{ "CPU", DEB_CPU },
|
||||
{ "BUF", DEB_BUF },
|
||||
{ "XFER", DEB_XFER },
|
||||
{ "SERV", DEB_SERV },
|
||||
{ "IOBUS", TRACE_IOBUS },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
||||
@@ -408,7 +438,6 @@ DEBTAB di_deb [] = {
|
||||
optimization.
|
||||
*/
|
||||
|
||||
|
||||
uint32 di_io (DIB *dibptr, IOCYCLE signal_set, uint32 stat_data)
|
||||
{
|
||||
static const char * const output_state [] = { "Control", "Data" };
|
||||
@@ -434,9 +463,7 @@ while (working_set) {
|
||||
di_card->flag = CLEAR; /* clear the flag */
|
||||
di_card->flagbuf = CLEAR; /* and flag buffer */
|
||||
|
||||
if (DEBUG_PRJ (dptrs [card], DEB_CMDS))
|
||||
fprintf (sim_deb, ">>%s cmds: [CLF] Flag cleared\n",
|
||||
dptrs [card]->name);
|
||||
tpprintf (dptrs [card], DEB_CMDS, "[CLF] Flag cleared\n");
|
||||
|
||||
if (update_required) /* if the card state has changed */
|
||||
update_state (card); /* then update the state */
|
||||
@@ -444,9 +471,7 @@ while (working_set) {
|
||||
|
||||
|
||||
case ioSTF: /* set flag flip-flop */
|
||||
if (DEBUG_PRJ (dptrs [card], DEB_CMDS))
|
||||
fprintf (sim_deb, ">>%s cmds: [STF] Flag set\n",
|
||||
dptrs [card]->name);
|
||||
tpprintf (dptrs [card], DEB_CMDS, "[STF] Flag set\n");
|
||||
|
||||
/* fall into ENF handler */
|
||||
|
||||
@@ -472,9 +497,8 @@ while (working_set) {
|
||||
di_card->status_register &= ~STAT_IRL; /* clear the input register loaded status */
|
||||
|
||||
if (FIFO_EMPTY && di_card->eor == CLEAR) { /* is the FIFO empty and end of record not seen? */
|
||||
if (di_card->srq == SET && DEBUG_PRJ (dptrs [card], DEB_CMDS))
|
||||
fprintf (sim_deb, ">>%s cmds: SRQ cleared\n",
|
||||
dptrs [card]->name);
|
||||
if (di_card->srq == SET)
|
||||
tpprintf (dptrs [card], DEB_CMDS, "SRQ cleared\n");
|
||||
|
||||
di_card->srq = CLEAR; /* clear SRQ */
|
||||
update_required = FALSE; /* the card state does not change */
|
||||
@@ -505,10 +529,8 @@ while (working_set) {
|
||||
data = di_card->status_register; /* return the status word */
|
||||
}
|
||||
|
||||
if (DEBUG_PRJ (dptrs [card], DEB_CPU))
|
||||
fprintf (sim_deb, ">>%s cpu: [LIx%s] %s = %06o\n",
|
||||
dptrs [card]->name, hold_or_clear,
|
||||
input_state [di_card->control], data);
|
||||
tpprintf (dptrs [card], DEB_CPU, "[LIx%s] %s = %06o\n",
|
||||
hold_or_clear, input_state [di_card->control], data);
|
||||
|
||||
if (update_required && !(signal_set & ioCLF)) /* if an update is required and CLF is not present, */
|
||||
update_state (card); /* update the state, else ioCLF will update it */
|
||||
@@ -520,10 +542,8 @@ while (working_set) {
|
||||
case ioIOO: /* I/O data output */
|
||||
data = IODATA (stat_data); /* get the data value */
|
||||
|
||||
if (DEBUG_PRJ (dptrs [card], DEB_CPU))
|
||||
fprintf (sim_deb, ">>%s cpu: [OTx%s] %s = %06o\n",
|
||||
dptrs [card]->name, hold_or_clear,
|
||||
output_state [di_card->control], data);
|
||||
tpprintf (dptrs [card], DEB_CPU, "[OTx%s] %s = %06o\n",
|
||||
hold_or_clear, output_state [di_card->control], data);
|
||||
|
||||
if (di_card->control == SET) { /* is the card in data mode? */
|
||||
if (signal_set & ioEDT) /* if end of DCPC transfer */
|
||||
@@ -547,9 +567,8 @@ while (working_set) {
|
||||
fifo_load (card, data, cpu_access); /* load the data word into the FIFO */
|
||||
|
||||
if (FIFO_FULL && (di_card->bus_cntl & BUS_NRFD)) { /* FIFO full and listener not ready? */
|
||||
if (di_card->srq == SET && DEBUG_PRJ (dptrs [card], DEB_CMDS))
|
||||
fprintf (sim_deb, ">>%s cmds: SRQ cleared\n",
|
||||
dptrs [card]->name);
|
||||
if (di_card->srq == SET)
|
||||
tpprintf (dptrs [card], DEB_CMDS, "SRQ cleared\n");
|
||||
|
||||
di_card->srq = CLEAR; /* clear SRQ */
|
||||
update_required = FALSE; /* the card state does not change */
|
||||
@@ -638,16 +657,12 @@ while (working_set) {
|
||||
di_card->flag = SET; /* set the flag */
|
||||
di_card->flagbuf = SET; /* and flag buffer */
|
||||
|
||||
if (DEBUG_PRJ (dptrs [card], DEB_CMDS))
|
||||
fprintf (sim_deb, ">>%s cmds: [POPIO] Flag set\n",
|
||||
dptrs [card]->name);
|
||||
tpprintf (dptrs [card], DEB_CMDS, "[POPIO] Flag set\n");
|
||||
break;
|
||||
|
||||
|
||||
case ioCRS: /* control reset */
|
||||
if (DEBUG_PRJ (dptrs [card], DEB_CMDS))
|
||||
fprintf (sim_deb, ">>%s cmds: [CRS] Master reset\n",
|
||||
dptrs [card]->name);
|
||||
tpprintf (dptrs [card], DEB_CMDS, "[CRS] Master reset\n");
|
||||
|
||||
di_card->status_register &= /* clear listen and talk status */
|
||||
~(STAT_LSTN | STAT_TALK);
|
||||
@@ -671,15 +686,8 @@ while (working_set) {
|
||||
case ioCLC: /* clear control flip-flop */
|
||||
di_card->control = CLEAR; /* clear control */
|
||||
|
||||
if (DEBUG_PRJ (dptrs [card], DEB_CMDS)) {
|
||||
fprintf (sim_deb, ">>%s cmds: [CLC%s] Control cleared (configure mode)",
|
||||
dptrs [card]->name, hold_or_clear);
|
||||
|
||||
if (signal_set & ioCLF) /* if ioCLF is given, */
|
||||
fputs (", master reset\n", sim_deb); /* then report a master reset */
|
||||
else
|
||||
fputc ('\n', sim_deb);
|
||||
}
|
||||
tpprintf (dptrs [card], DEB_CMDS, "[CLC%s] Control cleared (configure mode)%s\n",
|
||||
hold_or_clear, (signal_set & ioCLF ? ", master reset" : ""));
|
||||
|
||||
if (signal_set & ioCLF) /* if ioCLF is given, */
|
||||
master_reset (card); /* then do a master reset */
|
||||
@@ -689,16 +697,13 @@ while (working_set) {
|
||||
case ioSTC: /* set control flip-flop */
|
||||
di_card->control = SET; /* set control */
|
||||
|
||||
if (DEBUG_PRJ (dptrs [card], DEB_CMDS))
|
||||
fprintf (sim_deb, ">>%s cmds: [STC%s] Control set (data mode)\n",
|
||||
dptrs [card]->name, hold_or_clear);
|
||||
tpprintf (dptrs [card], DEB_CMDS, "[STC%s] Control set (data mode)\n",
|
||||
hold_or_clear);
|
||||
break;
|
||||
|
||||
|
||||
case ioEDT: /* end data transfer */
|
||||
if (DEBUG_PRJ (dptrs [card], DEB_CPU))
|
||||
fprintf (sim_deb, ">>%s cpu: [EDT] DCPC transfer ended\n",
|
||||
dptrs [card]->name);
|
||||
tpprintf (dptrs [card], DEB_CPU, "[EDT] DCPC transfer ended\n");
|
||||
break;
|
||||
|
||||
|
||||
@@ -1017,10 +1022,8 @@ CARD_ID other;
|
||||
uint32 acceptors, unit;
|
||||
t_bool accepted = FALSE;
|
||||
|
||||
if (DEBUG_PRJ (dptrs [card], DEB_XFER)) {
|
||||
fprintf (sim_deb, ">>%s xfer: HP-IB DIO %03o available ", dptrs [card]->name, data);
|
||||
fprint_bus (sim_deb, "[%s]\n", di [card].bus_cntl);
|
||||
}
|
||||
tpprintf (dptrs [card], DEB_XFER, "HP-IB DIO %03o signals %s available\n",
|
||||
data, fmt_bitset (di [card].bus_cntl, bus_format));
|
||||
|
||||
if (dptrs [card]->flags & DEV_DIAG) /* is this a diagnostic run? */
|
||||
for (other = first_card; other <= last_card; other++) { /* look through the list of cards */
|
||||
@@ -1048,9 +1051,8 @@ else if ((di [card].bus_cntl & BUS_PPOLL) != BUS_PPOLL) { /* this is a normal
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG_PRJ (dptrs [card], DEB_XFER) && !accepted)
|
||||
fprintf (sim_deb, ">>%s xfer: HP-IB no acceptors\n",
|
||||
dptrs [card]->name);
|
||||
if (!accepted)
|
||||
tpprintf (dptrs [card], DEB_XFER, "HP-IB no acceptors\n");
|
||||
|
||||
return accepted;
|
||||
}
|
||||
@@ -1114,21 +1116,18 @@ new_denials = di [card].bus_cntl & deny; /* get the changing deni
|
||||
|
||||
di [card].bus_cntl = new_state; /* establish the new control state */
|
||||
|
||||
if (DEBUG_PRJ (dptrs [card], DEB_XFER)) {
|
||||
if (unit == CONTROLLER)
|
||||
fprintf (sim_deb, ">>%s xfer: HP-IB card %d", dptrs [card]->name, card);
|
||||
else
|
||||
fprintf (sim_deb, ">>%s xfer: HP-IB address %d",
|
||||
dptrs [card]->name, GET_BUSADR (dptrs [card]->units [unit].flags));
|
||||
|
||||
if (new_assertions)
|
||||
fprint_bus (sim_deb, " asserted [%s]", new_assertions);
|
||||
|
||||
if (new_denials)
|
||||
fprint_bus (sim_deb, " denied [%s]", new_denials);
|
||||
|
||||
fprint_bus (sim_deb, ", bus is [%s]\n", new_state);
|
||||
}
|
||||
if (unit == CONTROLLER)
|
||||
tpprintf (dptrs [card], DEB_XFER, "HP-IB card %d asserted %s denied %s bus is %s\n",
|
||||
card,
|
||||
fmt_bitset (new_assertions, bus_format),
|
||||
fmt_bitset (new_denials, bus_format),
|
||||
fmt_bitset (new_state, bus_format));
|
||||
else
|
||||
tpprintf (dptrs [card], DEB_XFER, "HP-IB address %d asserted %s denied %s bus is %s\n",
|
||||
GET_BUSADR (dptrs [card]->units [unit].flags),
|
||||
fmt_bitset (new_assertions, bus_format),
|
||||
fmt_bitset (new_denials, bus_format),
|
||||
fmt_bitset (new_state, bus_format));
|
||||
|
||||
if ((dptrs [card]->flags & DEV_DIAG) /* is the card in diagnostic mode? */
|
||||
|| (new_assertions & ASSERT_SET) /* or are changed signals in the */
|
||||
@@ -1158,9 +1157,8 @@ if ((dptrs [card]->flags & DEV_DIAG) /* is the card i
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG_PRJ (dptrs [card], DEB_XFER) & !responded)
|
||||
fprintf (sim_deb, ">>%s xfer: HP-IB no responders\n",
|
||||
dptrs [card]->name);
|
||||
if (!responded)
|
||||
tpprintf (dptrs [card], DEB_XFER, "HP-IB no responders\n");
|
||||
}
|
||||
|
||||
if ((new_state & BUS_PPOLL) == BUS_PPOLL) /* was a parallel poll requested? */
|
||||
@@ -1191,10 +1189,9 @@ if (response == SET) { /* enable the poll respo
|
||||
else /* disable the poll response */
|
||||
di [card].poll_response &= ~PPR (address); /* by clearing the response bit */
|
||||
|
||||
if (DEBUG_PRJ (dptrs [card], DEB_XFER)
|
||||
&& previous_response != di [card].poll_response)
|
||||
fprintf (sim_deb, ">>%s xfer: HP-IB address %d parallel poll response %s\n",
|
||||
dptrs [card]->name, address, (response == SET ? "enabled" : "disabled"));
|
||||
if (previous_response != di [card].poll_response)
|
||||
tpprintf (dptrs [card], DEB_XFER, "HP-IB address %d parallel poll response %s\n",
|
||||
address, (response == SET ? "enabled" : "disabled"));
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1249,9 +1246,8 @@ if (dptrs [card]->flags & DEV_DIAG) /* is this a diagnos
|
||||
PPR (GET_DIADR (dptrs [other]->flags));
|
||||
|
||||
if (response) { /* is a poll response indicated? */
|
||||
if (DEBUG_PRJ (dptrs [card], DEB_XFER))
|
||||
fprintf (sim_deb, ">>%s xfer: HP-IB parallel poll DIO %03o\n",
|
||||
dptrs [card]->name, response);
|
||||
tpprintf (dptrs [card], DEB_XFER, "HP-IB parallel poll DIO %03o\n",
|
||||
response);
|
||||
|
||||
while (di [card].fifo_count != FIFO_SIZE) /* fill the card FIFO with the responses */
|
||||
fifo_load (card, (uint16) response, diag_access); /* (hardware feature) */
|
||||
@@ -1274,9 +1270,8 @@ return;
|
||||
|
||||
static t_bool di_bus_accept (CARD_ID card, uint8 data)
|
||||
{
|
||||
if (DEBUG_PRJ (dptrs [card], DEB_XFER))
|
||||
fprintf (sim_deb, ">>%s xfer: HP-IB card %d accepted data %03o \n",
|
||||
dptrs [card]->name, card, data);
|
||||
tpprintf (dptrs [card], DEB_XFER, "HP-IB card %d accepted data %03o\n",
|
||||
card, data);
|
||||
|
||||
fifo_load (card, data, bus_access); /* load the data byte into the FIFO */
|
||||
update_state (card); /* and update the card state */
|
||||
@@ -1339,9 +1334,7 @@ di [card].status_register &= /* clear the status flip
|
||||
di [card].input_data_register = 0; /* clear the input data register */
|
||||
di [card].fifo_count = 0; /* clear the FIFO */
|
||||
|
||||
if (DEBUG_PRJ (dptrs [card], DEB_BUF))
|
||||
fprintf (sim_deb, ">>%s buf: FIFO cleared\n",
|
||||
dptrs [card]->name);
|
||||
tpprintf (dptrs [card], DEB_BUF, "FIFO cleared\n");
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1465,10 +1458,9 @@ else
|
||||
di_card->srq = CLEAR; /* otherwise, DCPC service is not needed */
|
||||
|
||||
|
||||
if (DEBUG_PRJ (dptrs [card], DEB_CMDS)
|
||||
&& di_card->srq != previous_state)
|
||||
fprintf (sim_deb, ">>%s cmds: SRQ %s\n",
|
||||
dptrs [card]->name, di_card->srq == SET ? "set" : "cleared");
|
||||
if (di_card->srq != previous_state)
|
||||
tpprintf (dptrs [card], DEB_CMDS, "SRQ %s\n",
|
||||
di_card->srq == SET ? "set" : "cleared");
|
||||
|
||||
|
||||
if (di_card->status_register & STAT_IRL /* is the input register loaded */
|
||||
@@ -1487,9 +1479,7 @@ if (di_card->status_register & STAT_IRL /* is the input register
|
||||
&& di_card->status_register & STAT_IFC /* and IFC is asserted on the bus */
|
||||
&& di_card->cntl_register & CNTL_IFC) { /* and notification is wanted? */
|
||||
|
||||
if (DEBUG_PRJ (dptrs [card], DEB_CMDS))
|
||||
fprintf (sim_deb, ">>%s cmds: Flag set\n",
|
||||
dptrs [card]->name);
|
||||
tpprintf (dptrs [card], DEB_CMDS, "Flag set\n");
|
||||
|
||||
di_io (dibptr, ioENF, 0); /* set the flag and recalculate interrupts */
|
||||
}
|
||||
@@ -1596,9 +1586,8 @@ t_bool add_word = TRUE;
|
||||
DI_STATE * const di_card = &di [card];
|
||||
|
||||
if (FIFO_FULL) { /* is the FIFO already full? */
|
||||
if (DEBUG_PRJ (dptrs [card], DEB_BUF))
|
||||
fprintf (sim_deb, ">>%s buf: Attempted load to full FIFO, data %0*o\n",
|
||||
dptrs [card]->name, (access == bus_access ? 3 : 6), data);
|
||||
tpprintf (dptrs [card], DEB_BUF, "Attempted load to full FIFO, data %0*o\n",
|
||||
(access == bus_access ? 3 : 6), data);
|
||||
|
||||
return; /* return with the load ignored */
|
||||
}
|
||||
@@ -1665,12 +1654,9 @@ else { /* must be diagnostic ac
|
||||
if (add_word) /* did we add a word to the FIFO? */
|
||||
di_card->fifo_count = di_card->fifo_count + 1; /* increment the count of words stored */
|
||||
|
||||
if (DEBUG_PRJ (dptrs [card], DEB_BUF)) {
|
||||
fprintf (sim_deb, ">>%s buf: Data %0*o tag ",
|
||||
dptrs [card]->name, (access == bus_access ? 3 : 6), data);
|
||||
fprint_val (sim_deb, tag >> BUS_SHIFT, 2, 4, PV_RZRO);
|
||||
fprintf (sim_deb, " loaded into FIFO (%d)\n", di_card->fifo_count);
|
||||
}
|
||||
tpprintf (dptrs [card], DEB_XFER, "Data %0*o tag %s loaded into FIFO (%d)\n",
|
||||
(access == bus_access ? 3 : 6), data,
|
||||
fmt_bitset (tag, tag_format), di_card->fifo_count);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1783,10 +1769,7 @@ t_bool remove_word = TRUE;
|
||||
DI_STATE * const di_card = &di [card];
|
||||
|
||||
if (FIFO_EMPTY) { /* is the FIFO already empty? */
|
||||
if (DEBUG_PRJ (dptrs [card], DEB_BUF))
|
||||
fprintf (sim_deb, ">>%s buf: Attempted unload from empty FIFO\n",
|
||||
dptrs [card]->name);
|
||||
|
||||
tpprintf (dptrs [card], DEB_BUF, "Attempted unload from empty FIFO\n");
|
||||
return 0; /* return with no data */
|
||||
}
|
||||
|
||||
@@ -1838,12 +1821,9 @@ if (remove_word) { /* remove the word from
|
||||
}
|
||||
|
||||
|
||||
if (DEBUG_PRJ (dptrs [card], DEB_BUF)) {
|
||||
fprintf (sim_deb, ">>%s buf: Data %0*o tag ",
|
||||
dptrs [card]->name, (access == cpu_access ? 6 : 3), data);
|
||||
fprint_val (sim_deb, tag >> BUS_SHIFT, 2, 4, PV_RZRO);
|
||||
fprintf (sim_deb, " unloaded from FIFO (%d)\n", di_card->fifo_count);
|
||||
}
|
||||
tpprintf (dptrs [card], DEB_BUF, "Data %0*o tag %s unloaded from FIFO (%d)\n",
|
||||
(access == cpu_access ? 6 : 3), data,
|
||||
fmt_bitset (tag, tag_format), di_card->fifo_count);
|
||||
|
||||
|
||||
if (di_card->cntl_register & CNTL_TALK) /* is the card talking? */
|
||||
@@ -1867,51 +1847,3 @@ if (di_card->cntl_register & CNTL_TALK) /* is the card talking?
|
||||
|
||||
return (uint16) data; /* return the data value */
|
||||
}
|
||||
|
||||
|
||||
/* Print the bus state for debugging.
|
||||
|
||||
The states of the supplied bus control lines are decoded and printed in
|
||||
mnemonic form to the specified file using the indicated format string. An
|
||||
asserted bus signal is indicated by its name; a denied signal is omitted.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. The strings in the cntl_names array must appear in BUS_xxx order. The
|
||||
first element corresponds to bus bit 0, etc.
|
||||
*/
|
||||
|
||||
static void fprint_bus (FILE *file, char *format, uint8 cntl)
|
||||
{
|
||||
static const char *cntl_names [] = {
|
||||
"ATN", /* bit 0: attention */
|
||||
"EOI", /* bit 1: end or identify */
|
||||
"DAV", /* bit 2: data available */
|
||||
"NRFD", /* bit 3: not ready for data */
|
||||
"NDAC", /* bit 4: not data accepted */
|
||||
"REN", /* bit 5: remote enable */
|
||||
"IFC", /* bit 6: interface clear */
|
||||
"SRQ" /* bit 7: service request */
|
||||
};
|
||||
|
||||
uint32 signal;
|
||||
char mnemonics [40];
|
||||
|
||||
if (cntl == 0) /* are any control signals asserted? */
|
||||
strcpy (mnemonics, "---"); /* no; use dashes in lieu of an empty string */
|
||||
|
||||
else { /* one or more signals are asserted */
|
||||
mnemonics [0] = '\0';
|
||||
|
||||
for (signal = 0; signal <= 7; signal++) /* loop though the set of signals */
|
||||
if (cntl & (1 << signal)) { /* is this signal asserted? */
|
||||
if (strlen (mnemonics) > 0) /* yes; is it the first one asserted? */
|
||||
strcat (mnemonics, " "); /* no, so append a space to separate */
|
||||
strcat (mnemonics, cntl_names [signal]); /* append the name of the asserted signal */
|
||||
}
|
||||
}
|
||||
|
||||
fprintf (file, format, mnemonics); /* print the bus state */
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
|
||||
DI 12821A Disc Interface
|
||||
|
||||
15-Mar-17 JDB Trace flags are now global
|
||||
09-Mar-17 JDB Changed the DIAG option to DIAGNOSTIC
|
||||
10-Jan-17 JDB Moved byte accessors to hp2100_defs.h
|
||||
13-May-16 JDB Modified for revised SCP API function parameter types
|
||||
14-Feb-12 JDB First release
|
||||
@@ -89,16 +91,6 @@ typedef enum {
|
||||
#define SET_BUSADR(f) (((f) & UNIT_M_BUSADR) << UNIT_V_BUSADR)
|
||||
|
||||
|
||||
/* Debug flags */
|
||||
|
||||
#define DEB_CPU (1 << 0) /* words received from and sent to the CPU */
|
||||
#define DEB_CMDS (1 << 1) /* interface commands received from the CPU */
|
||||
#define DEB_BUF (1 << 2) /* data read from and written to the card FIFO */
|
||||
#define DEB_XFER (1 << 3) /* data received and transmitted via HP-IB */
|
||||
#define DEB_RWSC (1 << 4) /* device read/write/status/control commands */
|
||||
#define DEB_SERV (1 << 5) /* unit service scheduling calls */
|
||||
|
||||
|
||||
/* HP-IB control line state bit flags.
|
||||
|
||||
NOTE that these flags align with the corresponding flags in the DI status
|
||||
@@ -140,31 +132,31 @@ typedef enum {
|
||||
/* Per-card state variables */
|
||||
|
||||
typedef struct {
|
||||
FLIP_FLOP control; /* control flip-flop */
|
||||
FLIP_FLOP flag; /* flag flip-flop */
|
||||
FLIP_FLOP flagbuf; /* flag buffer flip-flop */
|
||||
FLIP_FLOP srq; /* SRQ flip-flop */
|
||||
FLIP_FLOP edt; /* EDT flip-flop */
|
||||
FLIP_FLOP eor; /* EOR flip-flop */
|
||||
BYTE_SELECTOR ibp; /* input byte pointer selector */
|
||||
BYTE_SELECTOR obp; /* output byte pointer selector */
|
||||
FLIP_FLOP control; /* control flip-flop */
|
||||
FLIP_FLOP flag; /* flag flip-flop */
|
||||
FLIP_FLOP flagbuf; /* flag buffer flip-flop */
|
||||
FLIP_FLOP srq; /* SRQ flip-flop */
|
||||
FLIP_FLOP edt; /* EDT flip-flop */
|
||||
FLIP_FLOP eor; /* EOR flip-flop */
|
||||
BYTE_SELECTOR ibp; /* input byte pointer selector */
|
||||
BYTE_SELECTOR obp; /* output byte pointer selector */
|
||||
|
||||
uint16 cntl_register; /* control word register */
|
||||
uint16 status_register; /* status word register */
|
||||
uint16 input_data_register; /* input data register */
|
||||
uint16 cntl_register; /* control word register */
|
||||
uint16 status_register; /* status word register */
|
||||
uint16 input_data_register; /* input data register */
|
||||
|
||||
uint32 fifo [FIFO_SIZE]; /* FIFO buffer */
|
||||
uint32 fifo_count; /* FIFO occupancy counter */
|
||||
REG *fifo_reg; /* FIFO register pointer */
|
||||
uint32 fifo [FIFO_SIZE]; /* FIFO buffer */
|
||||
uint32 fifo_count; /* FIFO occupancy counter */
|
||||
REG *fifo_reg; /* FIFO register pointer */
|
||||
|
||||
uint32 acceptors; /* unit bitmap of the bus acceptors */
|
||||
uint32 listeners; /* unit bitmap of the bus listeners */
|
||||
uint32 talker; /* unit bitmap of the bus talker */
|
||||
uint32 acceptors; /* unit bitmap of the bus acceptors */
|
||||
uint32 listeners; /* unit bitmap of the bus listeners */
|
||||
uint32 talker; /* unit bitmap of the bus talker */
|
||||
|
||||
uint8 bus_cntl; /* HP-IB bus control state (ATN, EOI, etc.) */
|
||||
uint8 poll_response; /* address bitmap of parallel poll responses */
|
||||
uint8 bus_cntl; /* HP-IB bus control state (ATN, EOI, etc.) */
|
||||
uint8 poll_response; /* address bitmap of parallel poll responses */
|
||||
|
||||
double ifc_timer; /* 100 microsecond IFC timer */
|
||||
double ifc_timer; /* 100 microsecond IFC timer */
|
||||
} DI_STATE;
|
||||
|
||||
|
||||
@@ -212,17 +204,17 @@ typedef struct {
|
||||
These definitions should be included before any device-specific modifiers.
|
||||
*/
|
||||
|
||||
#define DI_MODS(dev) \
|
||||
{ MTAB_XTD | MTAB_VDV, 1, "ADDRESS", "ADDRESS", &di_set_address, &di_show_address, &dev }, \
|
||||
\
|
||||
{ MTAB_XTD | MTAB_VDV, 1, NULL, "DIAG", &di_set_cable, NULL, &dev }, \
|
||||
{ MTAB_XTD | MTAB_VDV, 0, NULL, "HPIB", &di_set_cable, NULL, &dev }, \
|
||||
{ MTAB_XTD | MTAB_VDV, 0, "CABLE", NULL, NULL, &di_show_cable, &dev }, \
|
||||
\
|
||||
{ MTAB_XTD | MTAB_VDV, 0, "SC", "SC", &hp_setsc, &hp_showsc, &dev }, \
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &dev }, \
|
||||
\
|
||||
{ MTAB_XTD | MTAB_VUN, 0, "BUS", "BUS", &di_set_address, &di_show_address, &dev }
|
||||
#define DI_MODS(dev,dib) \
|
||||
{ MTAB_XTD | MTAB_VDV, 1, "ADDRESS", "ADDRESS", &di_set_address, &di_show_address, &dev }, \
|
||||
\
|
||||
{ MTAB_XTD | MTAB_VDV, 1, NULL, "DIAGNOSTIC", &di_set_cable, NULL, &dev }, \
|
||||
{ MTAB_XTD | MTAB_VDV, 0, NULL, "HPIB", &di_set_cable, NULL, &dev }, \
|
||||
{ MTAB_XTD | MTAB_VDV, 0, "CABLE", NULL, NULL, &di_show_cable, &dev }, \
|
||||
\
|
||||
{ MTAB_XTD | MTAB_VDV, 1, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &dib }, \
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, ~1u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &dib }, \
|
||||
\
|
||||
{ MTAB_XTD | MTAB_VUN, 0, "BUS", "BUS", &di_set_address, &di_show_address, &dev }
|
||||
|
||||
|
||||
/* Disc interface global bus routine definitions */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* hp2100_di_da.c: HP 12821A HP-IB Disc Interface simulator for Amigo disc drives
|
||||
|
||||
Copyright (c) 2011-2017, J. David Bryan
|
||||
Copyright (c) 2011-2018, J. David Bryan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -25,6 +25,11 @@
|
||||
|
||||
DA 12821A Disc Interface with Amigo disc drives
|
||||
|
||||
21-Feb-18 JDB ATTACH -N now creates a full-size disc image
|
||||
11-Jul-17 JDB Renamed "ibl_copy" to "cpu_ibl"
|
||||
15-Mar-17 JDB Changed DEBUG_PRI calls to tprintfs
|
||||
09-Mar-17 JDB Deprecated LOCKED/WRITEENABLED for PROTECT/UNPROTECT
|
||||
27-Feb-17 JDB ibl_copy no longer returns a status code
|
||||
17-Jan-17 JDB Changed to use new byte accessors in hp2100_defs.h
|
||||
13-May-16 JDB Modified for revised SCP API function parameter types
|
||||
04-Mar-16 JDB Name changed to "hp2100_disclib" until HP 3000 integration
|
||||
@@ -345,6 +350,7 @@
|
||||
|
||||
|
||||
#include "hp2100_defs.h"
|
||||
#include "hp2100_cpu.h"
|
||||
#include "hp2100_di.h"
|
||||
#include "hp2100_disclib.h"
|
||||
|
||||
@@ -553,20 +559,25 @@ REG da_reg [] = {
|
||||
};
|
||||
|
||||
MTAB da_mod [] = {
|
||||
DI_MODS (da_dev),
|
||||
DI_MODS (da_dev, da_dib),
|
||||
|
||||
{ UNIT_UNLOAD, UNIT_UNLOAD, "heads unloaded", "UNLOADED", &da_load_unload, NULL, NULL },
|
||||
{ UNIT_UNLOAD, 0, "heads loaded", "LOADED", &da_load_unload, NULL, NULL },
|
||||
/* Mask Value Match Value Print String Match String Validation Display Descriptor */
|
||||
/* ------------ ------------ ----------------- --------------- ---------------- ------- ---------- */
|
||||
{ UNIT_UNLOAD, UNIT_UNLOAD, "heads unloaded", "UNLOADED", &da_load_unload, NULL, NULL },
|
||||
{ UNIT_UNLOAD, 0, "heads loaded", "LOADED", &da_load_unload, NULL, NULL },
|
||||
|
||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL, NULL, NULL },
|
||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL, NULL, NULL },
|
||||
{ UNIT_WLK, UNIT_WLK, "protected", "PROTECT", NULL, NULL, NULL },
|
||||
{ UNIT_WLK, 0, "unprotected", "UNPROTECT", NULL, NULL, NULL },
|
||||
|
||||
{ UNIT_FMT, UNIT_FMT, "format enabled", "FORMAT", NULL, NULL, NULL },
|
||||
{ UNIT_FMT, 0, "format disabled", "NOFORMAT", NULL, NULL, NULL },
|
||||
{ UNIT_WLK, UNIT_WLK, NULL, "LOCKED", NULL, NULL, NULL },
|
||||
{ UNIT_WLK, 0, NULL, "WRITEENABLED", NULL, NULL, NULL },
|
||||
|
||||
{ UNIT_MODEL, MODEL_7906, "7906H", "7906H", &dl_set_model, NULL, NULL },
|
||||
{ UNIT_MODEL, MODEL_7920, "7920H", "7920H", &dl_set_model, NULL, NULL },
|
||||
{ UNIT_MODEL, MODEL_7925, "7925H", "7925H", &dl_set_model, NULL, NULL },
|
||||
{ UNIT_FMT, UNIT_FMT, "format enabled", "FORMAT", NULL, NULL, NULL },
|
||||
{ UNIT_FMT, 0, "format disabled", "NOFORMAT", NULL, NULL, NULL },
|
||||
|
||||
{ UNIT_MODEL, MODEL_7906, "7906H", "7906H", &dl_set_model, NULL, NULL },
|
||||
{ UNIT_MODEL, MODEL_7920, "7920H", "7920H", &dl_set_model, NULL, NULL },
|
||||
{ UNIT_MODEL, MODEL_7925, "7925H", "7925H", &dl_set_model, NULL, NULL },
|
||||
|
||||
{ 0 }
|
||||
};
|
||||
@@ -807,9 +818,8 @@ switch (if_state [unit]) { /* dispatch the inte
|
||||
if_state [unit] = read_xfer; /* we are ready to transfer the data */
|
||||
uptr->wait = cvptr->cmd_time; /* schedule the transfer */
|
||||
|
||||
if (DEBUG_PRI (da_dev, DEB_RWSC))
|
||||
fprintf (sim_deb, ">>DA rwsc: Unit %d Amigo identify response %04XH\n",
|
||||
unit, buffer [0]);
|
||||
tprintf (da_dev, DEB_RWSC, "Unit %d Amigo identify response %04XH\n",
|
||||
unit, buffer [0]);
|
||||
break;
|
||||
|
||||
|
||||
@@ -967,36 +977,31 @@ switch (if_state [unit]) { /* dispatch the inte
|
||||
if (uptr->wait) /* is service requested? */
|
||||
activate_unit (uptr); /* schedule the next event */
|
||||
|
||||
if (result == SCPE_IERR && DEBUG_PRI (da_dev, DEB_RWSC)) { /* did an internal error occur? */
|
||||
fprintf (sim_deb, ">>DA rwsc: Unit %d ", unit); /* report it if debugging */
|
||||
|
||||
if (result == SCPE_IERR) /* did an internal error occur? */
|
||||
if (if_state [unit] == command_exec
|
||||
&& if_command [unit] == disc_command)
|
||||
fprintf (sim_deb, "%s command %s phase ",
|
||||
tprintf (da_dev, DEB_RWSC, "Unit %d %s command %s phase service not handled\n",
|
||||
unit,
|
||||
dl_opcode_name (ICD, (CNTLR_OPCODE) uptr->OP),
|
||||
dl_phase_name ((CNTLR_PHASE) uptr->PHASE));
|
||||
else
|
||||
fprintf (sim_deb, "%s state %s ",
|
||||
tprintf (da_dev, DEB_RWSC, "Unit %d %s state %s service not handled\n",
|
||||
unit,
|
||||
if_command_name [if_command [unit]],
|
||||
if_state_name [if_state [unit]]);
|
||||
|
||||
fputs ("service not handled\n", sim_deb);
|
||||
}
|
||||
|
||||
if (if_state [unit] == idle) { /* is the command now complete? */
|
||||
if (if_command [unit] == disc_command) { /* did a disc command complete? */
|
||||
if (cvptr->opcode != End) /* yes; if the command was not End, */
|
||||
di_poll_response (da, unit, SET); /* then enable PPR */
|
||||
|
||||
if (DEBUG_PRI (da_dev, DEB_RWSC))
|
||||
fprintf (sim_deb, ">>DA rwsc: Unit %d %s disc command completed\n",
|
||||
unit, dl_opcode_name (ICD, cvptr->opcode));
|
||||
tprintf (da_dev, DEB_RWSC, "Unit %d %s disc command completed\n",
|
||||
unit, dl_opcode_name (ICD, cvptr->opcode));
|
||||
}
|
||||
|
||||
else /* an interface command completed */
|
||||
if (DEBUG_PRI (da_dev, DEB_RWSC))
|
||||
fprintf (sim_deb, ">>DA rwsc: Unit %d %s command completed\n",
|
||||
unit, if_command_name [if_command [unit]]);
|
||||
tprintf (da_dev, DEB_RWSC, "Unit %d %s command completed\n",
|
||||
unit, if_command_name [if_command [unit]]);
|
||||
|
||||
if (release_interface) /* if the next command is already pending */
|
||||
di_bus_control (da, unit, 0, BUS_NRFD); /* deny NRFD to allow the card to resume */
|
||||
@@ -1076,6 +1081,9 @@ return status;
|
||||
The unspecified responses are illegal conditions; for example, the simulator
|
||||
does not allow an attached unit to be disabled.
|
||||
|
||||
If a new file is specified, the file is initialized to its capacity by
|
||||
writing a zero to the last byte in the file.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
@@ -1087,19 +1095,36 @@ return status;
|
||||
specifying a validation routine works for the DISABLED case but not the
|
||||
ENABLED case -- set_unit_enbdis returns SCPE_UDIS before calling the
|
||||
validation routine.
|
||||
|
||||
2. The C standard says, "A binary stream need not meaningfully support fseek
|
||||
calls with a whence value of SEEK_END," so instead we determine the
|
||||
offset from the start of the file to the last byte and seek there.
|
||||
*/
|
||||
|
||||
t_stat da_attach (UNIT *uptr, CONST char *cptr)
|
||||
{
|
||||
t_stat result;
|
||||
t_stat result;
|
||||
t_addr offset;
|
||||
const uint8 zero = 0;
|
||||
const int32 unit = uptr - da_unit; /* calculate the unit number */
|
||||
|
||||
result = dl_attach (&icd_cntlr [unit], uptr, cptr); /* attach the drive */
|
||||
|
||||
if (result == SCPE_OK) /* was the attach successful? */
|
||||
di [da].acceptors |= (1 << unit); /* set the unit's accepting bit */
|
||||
if (result == SCPE_OK) { /* if the attach was successful */
|
||||
di [da].acceptors |= (1 << unit); /* then set the unit's accepting bit */
|
||||
|
||||
return result;
|
||||
if (sim_switches & SWMASK ('N')) { /* if this is a new disc image */
|
||||
offset = (t_addr) /* then determine the offset of */
|
||||
(uptr->capac * sizeof (int16) - sizeof zero); /* the last byte in a full-sized file */
|
||||
|
||||
if (sim_fseek (uptr->fileref, offset, SEEK_SET) != 0 /* seek to the last byte */
|
||||
|| fwrite (&zero, sizeof zero, 1, uptr->fileref) == 0 /* and write a zero to fill */
|
||||
|| fflush (uptr->fileref) != 0) /* the file to its capacity */
|
||||
clearerr (uptr->fileref); /* clear and ignore any errors */
|
||||
}
|
||||
}
|
||||
|
||||
return result; /* return the result of the attach */
|
||||
}
|
||||
|
||||
|
||||
@@ -1126,17 +1151,131 @@ return result;
|
||||
}
|
||||
|
||||
|
||||
/* Boot an Amigo disc drive.
|
||||
/* 7906H/20H/25H disc bootstrap loader (12992H).
|
||||
|
||||
The ICD disc bootstrap program is loaded from the HP 12992H Boot Loader ROM
|
||||
into memory, the I/O instructions are configured for the interface card's
|
||||
select code, and the program is run to boot from the specified unit. The
|
||||
loader supports booting the disc at bus address 0 only. Before execution,
|
||||
the S register is automatically set as follows:
|
||||
The HP 1000 uses the 12992H boot loader ROM to bootstrap the ICD discs. Bit
|
||||
12 of the S register determines whether an RPL or manual boot is performed.
|
||||
Bits 1-0 specify the head number to use.
|
||||
|
||||
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
------ ------ ---------------------- ------------- -----
|
||||
ROM # 0 1 select code reserved head
|
||||
The loader reads 256 words from cylinder 0 sector 0 of the specified head
|
||||
into memory starting at location 2011 octal. Loader execution ends with one
|
||||
of the following instructions:
|
||||
|
||||
* HLT 11 - the drive aborted the transfer due to an unrecoverable error
|
||||
* JSB 2055,I - the disc read succeeded
|
||||
|
||||
The ICD drives are not supported on the 2100/14/15/16 CPUs, so no 21xx loader
|
||||
is provided.
|
||||
*/
|
||||
|
||||
static const LOADER_ARRAY da_loaders = {
|
||||
{ /* HP 21xx Loader does not exist */
|
||||
IBL_NA, /* loader starting index */
|
||||
IBL_NA, /* DMA index */
|
||||
IBL_NA, /* FWA index */
|
||||
{ 0 } },
|
||||
|
||||
{ /* HP 1000 Loader ROM (12992H) */
|
||||
IBL_START, /* loader starting index */
|
||||
IBL_DMA, /* DMA index */
|
||||
IBL_FWA, /* FWA index */
|
||||
{ 0102501, /* 77700: START LIA 1 GET SWITCH REGISTER SETTING */
|
||||
0100044, /* 77701: LSL 4 SHIFT A LEFT 4 */
|
||||
0006111, /* 77702: CLE,SLB,RSS SR BIT 12 SET FOR MANUAL BOOT? */
|
||||
0100041, /* 77703: LSL 1 NO. SHIFT HEAD # FOR RPL BOOT */
|
||||
0001424, /* 77704: ALR,ALR SHIFT HEAD 2, CLEAR SIGN */
|
||||
0033744, /* 77705: IOR HDSEC SET EOI BIT */
|
||||
0073744, /* 77706: STA HDSEC PLACE IN COMMAND BUFFER */
|
||||
0017756, /* 77707: JSB BTCTL SEND DUMMY,U-CLR,PP */
|
||||
0102510, /* 77710: LIA IBI READ INPUT REGISTER */
|
||||
0101027, /* 77711: ASR 7 SHIFT DRIVE 0 RESPONSE TO LSB */
|
||||
0002011, /* 77712: SLA,RSS DID DRIVE 0 RESPOND? */
|
||||
0027710, /* 77713: JMP *-3 NO, GO LOOK AGAIN */
|
||||
0107700, /* 77714: CLC 0,C */
|
||||
0017756, /* 77715: JSB BTCTL SEND TALK, CL-RD,BUS HOLDER */
|
||||
0002300, /* 77716: CCE */
|
||||
0017756, /* 77717: JSB BTCTL TELL CARD TO LISTEN */
|
||||
0063776, /* 77720: LDA DMACW LOAD DMA CONTROL WORD */
|
||||
0102606, /* 77721: OTA 6 OUTPUT TO DCPC */
|
||||
0106702, /* 77722: CLC 2 READY DCPC */
|
||||
0063735, /* 77723: LDA ADDR1 LOAD DMA BUFFER ADDRESS */
|
||||
0102602, /* 77724: OTA 2 OUTPUT TO DCPC */
|
||||
0063740, /* 77725: LDA DMAWC LOAD DMA WORD COUNT */
|
||||
0102702, /* 77726: STC 2 READY DCPC */
|
||||
0102602, /* 77727: OTA 2 OUTPUT TO DCPC */
|
||||
0103706, /* 77730: STC 6,C START DCPC */
|
||||
0102206, /* 77731: TEST SFC 6 SKIP IF DMA NOT DONE */
|
||||
0117750, /* 77732: JSB ADDR2,I SUCCESSFUL END OF TRANSFER */
|
||||
0102310, /* 77733: SFS IBI SKIP IF DISC ABORTED TRANSFER */
|
||||
0027731, /* 77734: JMP TEST RECHECK FOR TRANSFER END */
|
||||
0102011, /* 77735: ADDR1 HLT 11B ERROR HALT */
|
||||
0000677, /* 77736: UNCLR OCT 677 UNLISTEN */
|
||||
0000737, /* 77737: OCT 737 UNTALK */
|
||||
0176624, /* 77740: DMAWC OCT 176624 UNIVERSAL CLEAR,LBO */
|
||||
0000440, /* 77741: LIST OCT 440 LISTEN BUS ADDRESS 0 */
|
||||
0000550, /* 77742: CMSEC OCT 550 SECONDARY GET COMMAND */
|
||||
0000000, /* 77743: BOOT OCT 0 COLD LOAD READ COMMAND */
|
||||
0001000, /* 77744: HDSEC OCT 1000 HEAD,SECTOR PLUS EOI */
|
||||
0000677, /* 77745: UNLST OCT 677 ATN,PRIMARY UNLISTEN,PARITY */
|
||||
0000500, /* 77746: TALK OCT 500 SEND READ DATA */
|
||||
0100740, /* 77747: RDSEC OCT 100740 SECONDARY READ DATA */
|
||||
0102055, /* 77750: ADDR2 OCT 102055 BOOT EXTENSION STARTING ADDRESS */
|
||||
0004003, /* 77751: CTLP OCT 4003 INT=LBO,T,CIC */
|
||||
0000047, /* 77752: OCT 47 PPE,L,T,CIC */
|
||||
0004003, /* 77753: OCT 4003 INT=LBO,T,CIC */
|
||||
0000413, /* 77754: OCT 413 ATN,P,L,CIC */
|
||||
0001015, /* 77755: OCT 1015 INT=EOI,P,L,CIC */
|
||||
0000000, /* 77756: BTCTL NOP */
|
||||
0107710, /* 77757: CLC IBI,C RESET IBI */
|
||||
0063751, /* 77760: BM LDA CTLP LOAD CONTROL WORD */
|
||||
0102610, /* 77761: OTA IBI OUTPUT TO CONTROL REGISTER */
|
||||
0102710, /* 77762: STC IBI RETURN IBI TO DATA MODE */
|
||||
0037760, /* 77763: ISZ BM INCREMENT CONTROL WORD POINTER */
|
||||
0002240, /* 77764: SEZ,CME */
|
||||
0127756, /* 77765: JMP BTCTL,I RETURN */
|
||||
0063736, /* 77766: LABL LDA UNCLR LOAD DATA WORD */
|
||||
0037766, /* 77767: ISZ LABL INCREMENT WORD POINTER */
|
||||
0102610, /* 77770: OTA IBI OUTPUT TO HPIB */
|
||||
0002021, /* 77771: SSA,RSS SKIP IF LAST WORD */
|
||||
0027766, /* 77772: JMP LABL GO BACK FOR NEXT WORD */
|
||||
0102310, /* 77773: SFS IBI SKIP IF LAST WORD SENT TO BUS */
|
||||
0027773, /* 77774: JMP *-1 RECHECK ACCEPTANCE */
|
||||
0027757, /* 77775: JMP BTCTL+1 */
|
||||
0000010, /* 77776: DMACW ABS IBI */
|
||||
0170100 } } /* 77777: ABS -START */
|
||||
};
|
||||
|
||||
/* Device boot routine.
|
||||
|
||||
This routine is called directly by the BOOT DA and LOAD DA commands to copy
|
||||
the device bootstrap into the upper 64 words of the logical address space. It
|
||||
is also called indirectly by a BOOT CPU or LOAD CPU command when the
|
||||
specified HP 1000 loader ROM socket contains a 12992H ROM.
|
||||
|
||||
When called in response to a BOOT DA or LOAD DA command, the "unitno"
|
||||
parameter indicates the unit number specified in the BOOT command or is zero
|
||||
for the LOAD command, and "dptr" points at the DA device structure. The
|
||||
bootstrap supports loading only from the disc at bus address 0 only. The
|
||||
12992F loader ROM will be copied into memory and configured for the DA select
|
||||
code. The S register will be set as it would be by the front-panel
|
||||
microcode.
|
||||
|
||||
When called for a BOOT/LOAD CPU command, the "unitno" parameter indicates the
|
||||
select code to be used for configuration, and "dptr" will be NULL. As above,
|
||||
the 12992H loader ROM will be copied into memory and configured for the
|
||||
specified select code. The S register is assumed to be set correctly on entry
|
||||
and is not modified.
|
||||
|
||||
The loader expects the S register to be is set as follows:
|
||||
|
||||
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| ROM # | 0 1 | select code | reserved | head |
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
|
||||
Bit 12 must be 1 for a manual boot. Bits 5-2 are nominally zero but are
|
||||
reserved for the target operating system. For example, RTE uses bit 5 to
|
||||
indicate whether a standard (0) or reconfiguration (1) boot is desired.
|
||||
|
||||
The boot routine sets bits 15-6 of the S register to appropriate values.
|
||||
Bits 5-3 and 1-0 retain their original values, so S should be set before
|
||||
@@ -1145,84 +1284,21 @@ return result;
|
||||
than 0 is desired.
|
||||
*/
|
||||
|
||||
static const BOOT_ROM da_rom = {
|
||||
0102501, /* START LIA 1 GET SWITCH REGISTER SETTING */
|
||||
0100044, /* LSL 4 SHIFT A LEFT 4 */
|
||||
0006111, /* CLE,SLB,RSS SR BIT 12 SET FOR MANUAL BOOT? */
|
||||
0100041, /* LSL 1 NO. SHIFT HEAD # FOR RPL BOOT */
|
||||
0001424, /* ALR,ALR SHIFT HEAD 2, CLEAR SIGN */
|
||||
0033744, /* IOR HDSEC SET EOI BIT */
|
||||
0073744, /* STA HDSEC PLACE IN COMMAND BUFFER */
|
||||
0017756, /* JSB BTCTL SEND DUMMY,U-CLR,PP */
|
||||
0102510, /* LIA IBI READ INPUT REGISTER */
|
||||
0101027, /* ASR 7 SHIFT DRIVE 0 RESPONSE TO LSB */
|
||||
0002011, /* SLA,RSS DID DRIVE 0 RESPOND? */
|
||||
0027710, /* JMP *-3 NO, GO LOOK AGAIN */
|
||||
0107700, /* CLC 0,C */
|
||||
0017756, /* JSB BTCTL SEND TALK, CL-RD,BUS HOLDER */
|
||||
0002300, /* CCE */
|
||||
0017756, /* JSB BTCTL TELL CARD TO LISTEN */
|
||||
0063776, /* LDA DMACW LOAD DMA CONTROL WORD */
|
||||
0102606, /* OTA 6 OUTPUT TO DCPC */
|
||||
0106702, /* CLC 2 READY DCPC */
|
||||
0063735, /* LDA ADDR1 LOAD DMA BUFFER ADDRESS */
|
||||
0102602, /* OTA 2 OUTPUT TO DCPC */
|
||||
0063740, /* LDA DMAWC LOAD DMA WORD COUNT */
|
||||
0102702, /* STC 2 READY DCPC */
|
||||
0102602, /* OTA 2 OUTPUT TO DCPC */
|
||||
0103706, /* STC 6,C START DCPC */
|
||||
0102206, /* TEST SFC 6 SKIP IF DMA NOT DONE */
|
||||
0117750, /* JSB ADDR2,I SUCCESSFUL END OF TRANSFER */
|
||||
0102310, /* SFS IBI SKIP IF DISC ABORTED TRANSFER */
|
||||
0027731, /* JMP TEST RECHECK FOR TRANSFER END */
|
||||
0102011, /* ADDR1 HLT 11B ERROR HALT */
|
||||
0000677, /* UNCLR OCT 677 UNLISTEN */
|
||||
0000737, /* OCT 737 UNTALK */
|
||||
0176624, /* DMAWC OCT 176624 UNIVERSAL CLEAR,LBO */
|
||||
0000440, /* LIST OCT 440 LISTEN BUS ADDRESS 0 */
|
||||
0000550, /* CMSEC OCT 550 SECONDARY GET COMMAND */
|
||||
0000000, /* BOOT OCT 0 COLD LOAD READ COMMAND */
|
||||
0001000, /* HDSEC OCT 1000 HEAD,SECTOR PLUS EOI */
|
||||
0000677, /* UNLST OCT 677 ATN,PRIMARY UNLISTEN,PARITY */
|
||||
0000500, /* TALK OCT 500 SEND READ DATA */
|
||||
0100740, /* RDSEC OCT 100740 SECONDARY READ DATA */
|
||||
0102055, /* ADDR2 OCT 102055 BOOT EXTENSION STARTING ADDRESS */
|
||||
0004003, /* CTLP OCT 4003 INT=LBO,T,CIC */
|
||||
0000047, /* OCT 47 PPE,L,T,CIC */
|
||||
0004003, /* OCT 4003 INT=LBO,T,CIC */
|
||||
0000413, /* OCT 413 ATN,P,L,CIC */
|
||||
0001015, /* OCT 1015 INT=EOI,P,L,CIC */
|
||||
0000000, /* BTCTL NOP */
|
||||
0107710, /* CLC IBI,C RESET IBI */
|
||||
0063751, /* BM LDA CTLP LOAD CONTROL WORD */
|
||||
0102610, /* OTA IBI OUTPUT TO CONTROL REGISTER */
|
||||
0102710, /* STC IBI RETURN IBI TO DATA MODE */
|
||||
0037760, /* ISZ BM INCREMENT CONTROL WORD POINTER */
|
||||
0002240, /* SEZ,CME */
|
||||
0127756, /* JMP BTCTL,I RETURN */
|
||||
0063736, /* LABL LDA UNCLR LOAD DATA WORD */
|
||||
0037766, /* ISZ LABL INCREMENT WORD POINTER */
|
||||
0102610, /* OTA IBI OUTPUT TO HPIB */
|
||||
0002021, /* SSA,RSS SKIP IF LAST WORD */
|
||||
0027766, /* JMP LABL GO BACK FOR NEXT WORD */
|
||||
0102310, /* SFS IBI SKIP IF LAST WORD SENT TO BUS */
|
||||
0027773, /* JMP *-1 RECHECK ACCEPTANCE */
|
||||
0027757, /* JMP BTCTL+1 */
|
||||
0000010, /* DMACW ABS IBI */
|
||||
0170100 /* ABS -START */
|
||||
};
|
||||
|
||||
t_stat da_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
if (GET_BUSADR (da_unit [unitno].flags) != 0) /* booting is supported on bus address 0 only */
|
||||
return SCPE_NOFNC; /* report "Command not allowed" if attempted */
|
||||
static const HP_WORD da_preserved = 0000073u; /* S-register bits 5-3 and 1-0 are preserved */
|
||||
static const HP_WORD da_manual_boot = 0010000u; /* S-register bit 12 set for a manual boot */
|
||||
|
||||
if (ibl_copy (da_rom, da_dib.select_code, /* copy the boot ROM to memory and configure */
|
||||
IBL_OPT | IBL_DS_HEAD, /* the S register accordingly */
|
||||
IBL_DS | IBL_MAN | IBL_SET_SC (da_dib.select_code)))
|
||||
return SCPE_IERR; /* return an internal error if the copy failed */
|
||||
else
|
||||
return SCPE_OK;
|
||||
if (dptr == NULL) /* if we are being called for a BOOT/LOAD CPU */
|
||||
return cpu_copy_loader (da_loaders, unitno, /* then copy the boot loader to memory */
|
||||
IBL_S_NOCLEAR, IBL_S_NOSET); /* but do not alter the S register */
|
||||
|
||||
else if (GET_BUSADR (da_unit [unitno].flags) != 0) /* otherwise BOOT DA is supported on bus address 0 only */
|
||||
return SCPE_NOFNC; /* so reject other addresses as unsupported */
|
||||
|
||||
else /* otherwise this is a BOOT/LOAD DA */
|
||||
return cpu_copy_loader (da_loaders, da_dib.select_code, /* so copy the boot loader to memory */
|
||||
da_preserved, da_manual_boot); /* and configure the S register if 1000 CPU */
|
||||
}
|
||||
|
||||
|
||||
@@ -1451,8 +1527,7 @@ if (di [da].bus_cntl & BUS_ATN) { /* is it a bus comma
|
||||
case 0x04: /* selected device clear */
|
||||
case 0x05: /* SDC with parity freeze */
|
||||
case 0x14: /* universal clear */
|
||||
if (DEBUG_PRI (da_dev, DEB_RWSC))
|
||||
fprintf (sim_deb, ">>DA rwsc: Unit %d device cleared\n", unit);
|
||||
tprintf (da_dev, DEB_RWSC, "Unit %d device cleared\n", unit);
|
||||
|
||||
sim_cancel (&da_unit [unit]); /* cancel any in-progress command */
|
||||
dl_idle_controller (&icd_cntlr [unit]); /* idle the controller */
|
||||
@@ -1460,7 +1535,7 @@ if (di [da].bus_cntl & BUS_ATN) { /* is it a bus comma
|
||||
if_state [unit] = idle; /* idle the interface */
|
||||
di_poll_response (da, unit, SET); /* enable PPR */
|
||||
|
||||
if (DEBUG_PRI (da_dev, DEB_XFER))
|
||||
if (TRACING (da_dev, DEB_XFER))
|
||||
strcpy (action, "device clear");
|
||||
break;
|
||||
|
||||
@@ -1482,7 +1557,7 @@ if (di [da].bus_cntl & BUS_ATN) { /* is it a bus comma
|
||||
addressed = TRUE; /* unit is now addressed */
|
||||
stopped_talking = TRUE; /* MLA stops the unit from talking */
|
||||
|
||||
if (DEBUG_PRI (da_dev, DEB_XFER))
|
||||
if (TRACING (da_dev, DEB_XFER))
|
||||
sprintf (action, "listen %d", message_address);
|
||||
}
|
||||
|
||||
@@ -1491,7 +1566,7 @@ if (di [da].bus_cntl & BUS_ATN) { /* is it a bus comma
|
||||
|
||||
stopped_listening = TRUE; /* UNL stops the unit from listening */
|
||||
|
||||
if (DEBUG_PRI (da_dev, DEB_XFER))
|
||||
if (TRACING (da_dev, DEB_XFER))
|
||||
strcpy (action, "unlisten");
|
||||
}
|
||||
|
||||
@@ -1511,7 +1586,7 @@ if (di [da].bus_cntl & BUS_ATN) { /* is it a bus comma
|
||||
addressed = TRUE; /* the unit is now addressed */
|
||||
stopped_listening = TRUE; /* MTA stops the unit from listening */
|
||||
|
||||
if (DEBUG_PRI (da_dev, DEB_XFER))
|
||||
if (TRACING (da_dev, DEB_XFER))
|
||||
sprintf (action, "talk %d", message_address);
|
||||
}
|
||||
|
||||
@@ -1524,7 +1599,7 @@ if (di [da].bus_cntl & BUS_ATN) { /* is it a bus comma
|
||||
accepted = FALSE; /* are not accepted */
|
||||
|
||||
else /* it's an Untalk */
|
||||
if (DEBUG_PRI (da_dev, DEB_XFER))
|
||||
if (TRACING (da_dev, DEB_XFER))
|
||||
strcpy (action, "untalk");
|
||||
}
|
||||
|
||||
@@ -1670,7 +1745,7 @@ if (di [da].bus_cntl & BUS_ATN) { /* is it a bus comma
|
||||
|
||||
|
||||
if (accepted) { /* was the command accepted? */
|
||||
if (DEBUG_PRI (da_dev, DEB_XFER))
|
||||
if (TRACING (da_dev, DEB_XFER))
|
||||
sprintf (action, "secondary %02XH", message_address);
|
||||
|
||||
if (if_command [unit] != amigo_identify) /* disable PPR for all commands */
|
||||
@@ -1685,8 +1760,7 @@ if (di [da].bus_cntl & BUS_ATN) { /* is it a bus comma
|
||||
if_state [unit] = command_wait; /* change the interface state to wait */
|
||||
di_bus_control (da, unit, BUS_NRFD, 0); /* and assert NRFD to hold off the card */
|
||||
|
||||
if (DEBUG_PRI (da_dev, DEB_RWSC))
|
||||
fprintf (sim_deb, ">>DA rwsc: Unit %d addressed while controller is busy\n", unit);
|
||||
tprintf (da_dev, DEB_RWSC, "Unit %d addressed while controller is busy\n", unit);
|
||||
}
|
||||
|
||||
if (stopped_listening) { /* was the unit Unlistened? */
|
||||
@@ -1715,7 +1789,7 @@ else { /* it is bus data (A
|
||||
switch (if_state [unit]) { /* dispatch the interface state */
|
||||
|
||||
case opcode_wait: /* waiting for an opcode */
|
||||
if (DEBUG_PRI (da_dev, DEB_XFER))
|
||||
if (TRACING (da_dev, DEB_XFER))
|
||||
sprintf (action, "opcode %02XH", data & DL_OPCODE_MASK);
|
||||
|
||||
buffer [0] = TO_WORD (data, 0); /* set the opcode into the buffer */
|
||||
@@ -1737,7 +1811,7 @@ else { /* it is bus data (A
|
||||
|
||||
|
||||
case parameter_wait: /* waiting for a parameter */
|
||||
if (DEBUG_PRI (da_dev, DEB_XFER))
|
||||
if (TRACING (da_dev, DEB_XFER))
|
||||
sprintf (action, "parameter %02XH", data);
|
||||
|
||||
put_buffer_byte (&icd_cntlr [unit], data); /* add the byte to the buffer */
|
||||
@@ -1761,7 +1835,7 @@ else { /* it is bus data (A
|
||||
/* fall into error_sink handler */
|
||||
|
||||
case error_sink: /* sinking data after an error */
|
||||
if (DEBUG_PRI (da_dev, DEB_XFER))
|
||||
if (TRACING (da_dev, DEB_XFER))
|
||||
sprintf (action, "data %03o", data);
|
||||
|
||||
if (di [da].bus_cntl & BUS_EOI) /* is this the last byte from the bus? */
|
||||
@@ -1777,26 +1851,26 @@ else { /* it is bus data (A
|
||||
abort_command (unit, io_program_error, /* report the error */
|
||||
error_sink); /* and sink any data that follows */
|
||||
|
||||
if (DEBUG_PRI (da_dev, DEB_XFER))
|
||||
if (TRACING (da_dev, DEB_XFER))
|
||||
sprintf (action, "unhandled data %03o", data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (accepted && DEBUG_PRI (da_dev, DEB_XFER))
|
||||
fprintf (sim_deb, ">>DA xfer: HP-IB address %d accepted %s\n",
|
||||
if (accepted)
|
||||
tprintf (da_dev, DEB_XFER, "HP-IB address %d accepted %s\n",
|
||||
GET_BUSADR (da_unit [unit].flags), action);
|
||||
|
||||
if (da_unit [unit].wait > 0) /* was service requested? */
|
||||
activate_unit (&da_unit [unit]); /* schedule the unit */
|
||||
|
||||
if (initiated && DEBUG_PRI (da_dev, DEB_RWSC))
|
||||
if (initiated)
|
||||
if (if_command [unit] == disc_command)
|
||||
fprintf (sim_deb, ">>DA rwsc: Unit %d position %" T_ADDR_FMT "d %s disc command initiated\n",
|
||||
tprintf (da_dev, DEB_RWSC, "Unit %d position %" T_ADDR_FMT "d %s disc command initiated\n",
|
||||
unit, da_unit [unit].pos, dl_opcode_name (ICD, icd_cntlr [unit].opcode));
|
||||
else
|
||||
fprintf (sim_deb, ">>DA rwsc: Unit %d %s command initiated\n",
|
||||
tprintf (da_dev, DEB_RWSC, "Unit %d %s command initiated\n",
|
||||
unit, if_command_name [if_command [unit]]);
|
||||
|
||||
return accepted; /* indicate the acceptance condition */
|
||||
@@ -2123,15 +2197,10 @@ return;
|
||||
|
||||
static t_stat activate_unit (UNIT *uptr)
|
||||
{
|
||||
int32 unit;
|
||||
t_stat result;
|
||||
|
||||
if (DEBUG_PRI (da_dev, DEB_SERV)) {
|
||||
unit = uptr - da_unit;
|
||||
|
||||
fprintf (sim_deb, ">>DA serv: Unit %d state %s delay %d service scheduled\n",
|
||||
unit, if_state_name [if_state [unit]], uptr->wait);
|
||||
}
|
||||
tprintf (da_dev, DEB_SERV, "Unit %d state %s delay %d service scheduled\n",
|
||||
uptr - da_unit, if_state_name [if_state [uptr - da_unit]], uptr->wait);
|
||||
|
||||
result = sim_activate (uptr, uptr->wait); /* activate the unit */
|
||||
uptr->wait = 0; /* reset the activation time */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
SIMH/HP 21XX DIAGNOSTICS PERFORMANCE
|
||||
====================================
|
||||
Last update: 2016-12-18
|
||||
Last update: 2018-05-15
|
||||
|
||||
|
||||
The HP 24396 diagnostic suite has been run against the SIMH HP 21xx simulation.
|
||||
@@ -84,7 +84,7 @@ The results of the diagnostic runs are summarized below:
|
||||
105000 2610/14 Line Printer 1451 - No simulation
|
||||
105101 2767 Line Printer 1611 3.3-0 Passed
|
||||
105102 2607 Line Printer 1446 3.3-0 Passed
|
||||
145103 2613/17/18 Line Printer 1633 - No simulation
|
||||
145103 2613/17/18 Line Printer 1633 4.0-0 Passed
|
||||
105104 9866 Line Printer 1541 - No simulation
|
||||
105106 2631 Printer 1913 - No simulation
|
||||
105107 2635 Printing Terminal 1913 - No simulation
|
||||
@@ -488,13 +488,13 @@ TEST RESULT: Passed.
|
||||
|
||||
|
||||
|
||||
-------------------------------------
|
||||
DSN 143300 - General Purpose Register
|
||||
-------------------------------------
|
||||
-------------------------------------------
|
||||
DSN 143300 - General Purpose Register (LPS)
|
||||
-------------------------------------------
|
||||
|
||||
TESTED DEVICE: LPS (hp2100_lps.c)
|
||||
|
||||
CONFIGURATION: sim> set LPS diag
|
||||
CONFIGURATION: sim> set LPS DIAGNOSTIC
|
||||
sim> deposit S 000014
|
||||
sim> reset
|
||||
sim> go 100
|
||||
@@ -1064,7 +1064,7 @@ DSN 103115 - Privileged Interrupt
|
||||
TESTED DEVICE: PIF (hp2100_pif.c)
|
||||
|
||||
CONFIGURATION: sim> set PIF 12936A
|
||||
sim> set LPT DEV=44
|
||||
sim> set LPT SC=44
|
||||
|
||||
sim> deposit S 004414
|
||||
sim> reset
|
||||
@@ -1096,9 +1096,9 @@ TEST RESULT: Passed.
|
||||
|
||||
|
||||
|
||||
-------------------------------------
|
||||
DSN 143300 - General Purpose Register
|
||||
-------------------------------------
|
||||
-------------------------------------------
|
||||
DSN 143300 - General Purpose Register (PIF)
|
||||
-------------------------------------------
|
||||
|
||||
TESTED DEVICE: PIF (hp2100_pif.c)
|
||||
|
||||
@@ -1136,6 +1136,81 @@ TEST REPORT: GENERAL PURPOSE REGISTER DIAGNOSTIC, DSN 143300
|
||||
|
||||
TEST RESULT: Passed.
|
||||
|
||||
TEST NOTES: Only test 00 (Basic I/O Test) is executed. The other tests are
|
||||
not applicable, as the 12620A card has no data path circuitry.
|
||||
|
||||
|
||||
|
||||
--------------------------------------------
|
||||
DSN 143300 - General Purpose Register (IPLI)
|
||||
--------------------------------------------
|
||||
|
||||
TESTED DEVICE: IPLI (hp2100_ipl.c)
|
||||
|
||||
CONFIGURATION: sim> set IPLI DIAGNOSTIC
|
||||
|
||||
sim> deposit S 000032
|
||||
sim> reset
|
||||
sim> go 100
|
||||
|
||||
Programmed halt, T: 102074 (HLT 74)
|
||||
|
||||
sim> deposit S 000000
|
||||
sim> go
|
||||
|
||||
TEST REPORT: GENERAL PURPOSE REGISTER DIAGNOSTIC, DSN 143300
|
||||
|
||||
H024 PRESS PRESET (EXT&INT),RUN
|
||||
|
||||
Programmed halt, T: 102024 (HLT 24)
|
||||
|
||||
sim> reset
|
||||
sim> go
|
||||
|
||||
H025 BASIC I-O COMPLETED
|
||||
|
||||
PASS 000001
|
||||
|
||||
Programmed halt, T: 102077 (HLT 77)
|
||||
|
||||
TEST RESULT: Passed.
|
||||
|
||||
|
||||
|
||||
--------------------------------------------
|
||||
DSN 143300 - General Purpose Register (IPLO)
|
||||
--------------------------------------------
|
||||
|
||||
TESTED DEVICE: IPLO (hp2100_ipl.c)
|
||||
|
||||
CONFIGURATION: sim> set IPLI DIAGNOSTIC
|
||||
|
||||
sim> deposit S 000033
|
||||
sim> reset
|
||||
sim> go 100
|
||||
|
||||
Programmed halt, T: 102074 (HLT 74)
|
||||
|
||||
sim> deposit S 000000
|
||||
sim> go
|
||||
|
||||
TEST REPORT: GENERAL PURPOSE REGISTER DIAGNOSTIC, DSN 143300
|
||||
|
||||
H024 PRESS PRESET (EXT&INT),RUN
|
||||
|
||||
Programmed halt, T: 102024 (HLT 24)
|
||||
|
||||
sim> reset
|
||||
sim> go
|
||||
|
||||
H025 BASIC I-O COMPLETED
|
||||
|
||||
PASS 000001
|
||||
|
||||
Programmed halt, T: 102077 (HLT 77)
|
||||
|
||||
TEST RESULT: Passed.
|
||||
|
||||
|
||||
|
||||
---------------------------------------------------
|
||||
@@ -1596,12 +1671,12 @@ DSN 105102 - 2607 Line Printer
|
||||
|
||||
TESTED DEVICE: LPT (hp2100_lpt.c)
|
||||
|
||||
CONFIGURATION: sim> attach LPT scratch.2607.printer
|
||||
CONFIGURATION: sim> attach -n LPT scratch.2607.printer
|
||||
sim> deposit S 100015
|
||||
sim> reset
|
||||
sim> go 100
|
||||
|
||||
HALT instruction 102074
|
||||
Programmed halt, T: 102074 (HLT 74)
|
||||
|
||||
sim> deposit S 001000
|
||||
sim> reset
|
||||
@@ -1609,7 +1684,7 @@ CONFIGURATION: sim> attach LPT scratch.2607.printer
|
||||
|
||||
2607 LINE PRINTER DIAGNOSTIC
|
||||
|
||||
HALT instruction 102075
|
||||
Programmed halt, T: 102075 (HLT 75)
|
||||
|
||||
sim> deposit A 000377
|
||||
sim> deposit S 000000
|
||||
@@ -1618,7 +1693,7 @@ CONFIGURATION: sim> attach LPT scratch.2607.printer
|
||||
|
||||
TEST REPORT: H024 PRESS PRESET (EXT&INT),RUN
|
||||
|
||||
HALT instruction 102024
|
||||
Programmed halt, T: 102024 (HLT 24)
|
||||
|
||||
sim> reset
|
||||
sim> go
|
||||
@@ -1626,63 +1701,63 @@ TEST REPORT: H024 PRESS PRESET (EXT&INT),RUN
|
||||
H025 BI-O COMP
|
||||
H040 PWR OFF LP,PRESS RUN
|
||||
|
||||
HALT instruction 102040
|
||||
Programmed halt, T: 102040 (HLT 40)
|
||||
|
||||
sim> set LPT poweroff
|
||||
sim> set LPT POWEROFF
|
||||
sim> go
|
||||
|
||||
H041 PWR ON LP,READY LP,PRESS RUN
|
||||
|
||||
HALT instruction 102041
|
||||
Programmed halt, T: 102041 (HLT 41)
|
||||
|
||||
sim> set LPT poweron
|
||||
sim> set LPT POWERON
|
||||
sim> go
|
||||
|
||||
H042 PRINT SW OFF,PRESS RUN
|
||||
|
||||
HALT instruction 102042
|
||||
Programmed halt, T: 102042 (HLT 42)
|
||||
|
||||
sim> set LPT offline
|
||||
sim> set LPT OFFLINE
|
||||
sim> go
|
||||
|
||||
H043 PRINT SW ON,PRESS RUN
|
||||
|
||||
HALT instruction 102043
|
||||
Programmed halt, T: 102043 (HLT 43)
|
||||
|
||||
sim> set LPT online
|
||||
sim> set LPT ONLINE
|
||||
sim> go
|
||||
|
||||
H044 OPEN PLATEN,PRESS RUN
|
||||
|
||||
HALT instruction 102044
|
||||
Programmed halt, T: 102044 (HLT 44)
|
||||
|
||||
sim> set LPT offline
|
||||
sim> set LPT OFFLINE
|
||||
sim> go
|
||||
|
||||
H045 CLOSE PLATEN,PRESS RUN
|
||||
|
||||
HALT instruction 102045
|
||||
Programmed halt, T: 102045 (HLT 45)
|
||||
|
||||
sim> set LPT online
|
||||
sim> set LPT ONLINE
|
||||
sim> go
|
||||
|
||||
H046 REMOVE PAPER FROM LP,PRESS RUN
|
||||
|
||||
HALT instruction 102046
|
||||
Programmed halt, T: 102046 (HLT 46)
|
||||
|
||||
sim> detach LPT
|
||||
sim> go
|
||||
|
||||
H047 RESTORE PAPER IN LP, READY LP,PRESS RUN
|
||||
|
||||
HALT instruction 102047
|
||||
Programmed halt, T: 102047 (HLT 47)
|
||||
|
||||
sim> attach LPT scratch.2607.printer
|
||||
sim> go
|
||||
|
||||
PASS 000001
|
||||
|
||||
HALT instruction 102077
|
||||
Programmed halt, T: 102077 (HLT 77)
|
||||
|
||||
TEST RESULT: Passed.
|
||||
|
||||
@@ -1692,6 +1767,90 @@ TEST NOTES: The standard tests 00-07 are executed. Test 08 (operator
|
||||
|
||||
|
||||
|
||||
------------------------------------
|
||||
DSN 145103 - 2613/17/18 Line Printer
|
||||
------------------------------------
|
||||
|
||||
TESTED DEVICE: LPT (hp2100_lpt.c)
|
||||
|
||||
CONFIGURATION: sim> set LPT 2613,DIAGNOSTIC
|
||||
sim> attach -n LPT scratch.2613.printer
|
||||
sim> deposit S 000015
|
||||
sim> reset
|
||||
sim> go 100
|
||||
|
||||
Programmed halt, T: 102074 (HLT 74)
|
||||
|
||||
sim> deposit S 000000
|
||||
sim> reset
|
||||
sim> go
|
||||
|
||||
TEST REPORT: 2613-2618 LINE PRINTER DIAG
|
||||
H024 PRESS PRESET (EXT&INT),RUN
|
||||
|
||||
Programmed halt, T: 102024 (HLT 24)
|
||||
|
||||
sim> reset
|
||||
sim> go
|
||||
|
||||
H025 BI-O COMP
|
||||
H040 PWR OFF LP,PRESS RUN
|
||||
|
||||
Programmed halt, T: 102040 (HLT 40)
|
||||
|
||||
sim> set LPT POWEROFF
|
||||
sim> go
|
||||
|
||||
H041 PWR ON, ON LINE LP,PRESS RUN
|
||||
|
||||
Programmed halt, T: 102041 (HLT 41)
|
||||
|
||||
sim> set LPT POWERON
|
||||
sim> go
|
||||
|
||||
H042 LP TO OFF LINE,PRESS RUN
|
||||
|
||||
Programmed halt, T: 102042 (HLT 42)
|
||||
|
||||
sim> set LPT OFFLINE
|
||||
sim> go
|
||||
|
||||
H043 LP TO ON LINE,PRESS RUN
|
||||
|
||||
Programmed halt, T: 102043 (HLT 43)
|
||||
|
||||
sim> set LPT ONLINE
|
||||
sim> go
|
||||
|
||||
H044 OPEN DRUM GATE,PRESS RUN
|
||||
|
||||
Programmed halt, T: 102044 (HLT 44)
|
||||
|
||||
sim> detach LPT
|
||||
sim> go
|
||||
|
||||
H046 REMOVE PAPER,CLOSE DRUM GATE,PRESS RUN
|
||||
|
||||
Programmed halt, T: 102046 (HLT 46)
|
||||
|
||||
sim> go
|
||||
|
||||
H047 RESTORE PAPER, ON LINE LP, PRESS RUN
|
||||
|
||||
Programmed halt, T: 102047 (HLT 47)
|
||||
|
||||
sim> attach LPT scratch.2613.printer
|
||||
sim> set LPT ONLINE
|
||||
sim> go
|
||||
|
||||
PASS 000001
|
||||
|
||||
Programmed halt, T: 102077 (HLT 77)
|
||||
|
||||
TEST RESULT: Passed.
|
||||
|
||||
|
||||
|
||||
-----------------------------------------------------
|
||||
DSN 111001 - HP2100A Disc File (2883) (multiple unit)
|
||||
-----------------------------------------------------
|
||||
@@ -2044,7 +2203,7 @@ TEST REPORT: H0 7900/7901 CARTRIDGE DISC MEMORY DIAGNOSTIC
|
||||
|
||||
HALT instruction 102002
|
||||
|
||||
sim> set DPC0 unloaded
|
||||
sim> set DPC0 unload
|
||||
sim> go
|
||||
|
||||
H40 PROTECT U/D THEN READY UNIT 0
|
||||
@@ -2052,15 +2211,14 @@ TEST REPORT: H0 7900/7901 CARTRIDGE DISC MEMORY DIAGNOSTIC
|
||||
[CTRL+E]
|
||||
Simulation stopped
|
||||
|
||||
sim> set DPC0 locked
|
||||
sim> set DPC0 loaded
|
||||
sim> set DPC0 load,protect
|
||||
sim> go
|
||||
|
||||
H41 CLEAR U/D PROTECT,LOAD,PUSH RUN
|
||||
|
||||
HALT instruction 102002
|
||||
|
||||
sim> set DPC0 writeenabled
|
||||
sim> set DPC0 unprotect
|
||||
sim> go
|
||||
|
||||
H71 PRESS PRESET(S) THEN PRESS RUN
|
||||
@@ -3271,8 +3429,8 @@ TESTED DEVICE: IPLI, IPLO (hp2100_ipl.c)
|
||||
|
||||
BINARY TAPE: 24197-60001 Rev. B
|
||||
|
||||
CONFIGURATION: sim> set IPLI DIAG
|
||||
sim> set IPLO DIAG
|
||||
CONFIGURATION: sim> set IPLI DIAGNOSTIC
|
||||
sim> set IPLO DIAGNOSTIC
|
||||
sim> deposit S 003332
|
||||
sim> reset
|
||||
sim> go 2
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from the authors.
|
||||
|
||||
03-Aug-17 JDB Changed perror call for I/O errors to cprintf
|
||||
22-Apr-17 JDB A failed sim_fseek call now causes a drive fault
|
||||
09-Mar-17 JDB Added the simulator name to the "perror" message.
|
||||
17-Jan-17 JDB Moved "hp2100_defs.h" inclusion to "hp2100_disclib.c"
|
||||
@@ -2279,8 +2280,10 @@ static t_stat io_error (CVPTR cvptr, UNIT *uptr, CNTLR_STATUS status)
|
||||
{
|
||||
dl_end_command (cvptr, status); /* terminate the command with an error */
|
||||
|
||||
perror ("HP 2100 simulator disc library I/O error"); /* report the error to the console */
|
||||
clearerr (uptr->fileref); /* and clear the error in case we resume */
|
||||
cprintf ("%s simulator disc library I/O error: %s\n", /* report the error to the console */
|
||||
sim_name, strerror (errno));
|
||||
|
||||
clearerr (uptr->fileref); /* clear the error */
|
||||
|
||||
return SCPE_IOERR; /* return an I/O error to stop the simulator */
|
||||
}
|
||||
|
||||
@@ -1,33 +1,41 @@
|
||||
/* hp2100_dp.c: HP 2100 12557A/13210A disk simulator
|
||||
/* hp2100_dp.c: HP 2100 12557A/13210A disc simulator
|
||||
|
||||
Copyright (c) 1993-2016, Robert M. Supnik
|
||||
Copyright (c) 2017 J. David Bryan
|
||||
Copyright (c) 2017-2018 J. David Bryan
|
||||
|
||||
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:
|
||||
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.
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS 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
|
||||
Except as contained in this notice, the names of the authors 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.
|
||||
in this Software without prior written authorization from the authors.
|
||||
|
||||
DP 12557A 2870 disk subsystem
|
||||
13210A 7900 disk subsystem
|
||||
DP 12557A 2870 disc subsystem
|
||||
13210A 7900 disc subsystem
|
||||
|
||||
27-Feb-18 JDB Corrected the conditions that clear drive status
|
||||
Added the BMDL
|
||||
13-Feb-18 JDB First Status is now cleared on Read, etc.
|
||||
26-Jan-18 JDB ATTACH -N now creates a full-size disc image
|
||||
03-Aug-17 JDB Changed perror call for I/O errors to cprintf
|
||||
11-Jul-17 JDB Renamed "ibl_copy" to "cpu_ibl"
|
||||
22-Apr-17 JDB Added fall-through comment for FNC_STA case in dpcio
|
||||
09-Mar-17 JDB Deprecated LOCKED/WRITEENABLED for PROTECT/UNPROTECT
|
||||
27-Feb-17 JDB ibl_copy no longer returns a status code
|
||||
09-Nov-16 JDB Corrected disk subsystem model number from 2871 to 2870
|
||||
13-May-16 JDB Modified for revised SCP API function parameter types
|
||||
30-Dec-14 JDB Added S-register parameters to ibl_copy
|
||||
@@ -75,11 +83,12 @@
|
||||
21-Nov-00 RMS Fixed flag, buffer power up state
|
||||
|
||||
References:
|
||||
- 7900A Disc Drive Operating and Service Manual (07900-90002, Feb-1975)
|
||||
- 13210A Disc Drive Interface Kit Operating and Service Manual
|
||||
(13210-90003, Nov-1974)
|
||||
- 12557A Cartridge Disc Interface Kit Operating and Service Manual
|
||||
(12557-90001, Sep-1970)
|
||||
- 7900A Disc Drive Operating and Service Manual
|
||||
(07900-90002, February 1975)
|
||||
- 13210A Disc Drive Interface Kit Operating and Service Manual
|
||||
(13210-90003, May 1978)
|
||||
- 12557A Cartridge Disc Interface Kit Operating and Service Manual
|
||||
(12557-90001, Sepember 1970)
|
||||
|
||||
|
||||
The simulator uses a number of state variables:
|
||||
@@ -119,15 +128,111 @@
|
||||
drive's current position register during a read, i.e., the "on-disc" address
|
||||
field is assumed to match the current position.
|
||||
|
||||
The following implemented behaviors have been inferred from secondary sources
|
||||
(diagnostics, operating system drivers, etc.), due to absent or contradictory
|
||||
authoritative information; future correction may be needed:
|
||||
NOTE: 13210A manuals dated November 1974 and earlier contain errors in the
|
||||
schematics. See the comments preceding the "dpcio" routine for details.
|
||||
|
||||
1. Status bit 15 (ATTENTION) does not set bit 0 (ANY ERROR) on the 12557A.
|
||||
2. Omitting STC DC before Status Check does not set DC flag but does poll.
|
||||
|
||||
The 13210A interfaces respond to I/O instructions as follows:
|
||||
|
||||
Output Data Word format (OTA and OTB):
|
||||
|
||||
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| command | - - | P | D | - - - - - - | unit | command
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| write data | data
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| - - - - - - - - | cylinder address | data
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| - - - - - - | head | - - - | sector address | data
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| - - - - - - - - - - | sector count | data
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
|
||||
Where:
|
||||
|
||||
D = Defective Track
|
||||
P = Protected Track
|
||||
|
||||
Command:
|
||||
|
||||
0000 = Status Check
|
||||
0001 = Write Data
|
||||
0010 = Read Data
|
||||
0011 = Seek Record
|
||||
0101 = Refine Sector
|
||||
0110 = Check Data
|
||||
1001 = Initialize Data
|
||||
1011 = Address Record
|
||||
|
||||
The 12557A interface responds identically, except that the sector address and
|
||||
sector count fields use one fewer bit each, i.e., use bits 3-0 and 4-0,
|
||||
respectively.
|
||||
|
||||
|
||||
Input Data Word format (LIA and LIB):
|
||||
|
||||
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| - - - - - - - - - - - - | attention | command
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| read data | data
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| - | F | O | - | U | P | - | S | - | N | C | A | G | B | D | E | data
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
|
||||
Where:
|
||||
|
||||
F = First Status
|
||||
O = Overrun
|
||||
U = Drive Unsafe
|
||||
P = Data Protected
|
||||
S = Seek Check
|
||||
N = Not Ready
|
||||
C = End of Cylinder
|
||||
A = Address Error
|
||||
G = Flagged Cylinder
|
||||
B = Drive Busy
|
||||
D = Data Error
|
||||
E = Any Error
|
||||
|
||||
The 12557A interface responds identically, except that the status word is
|
||||
extended as follows:
|
||||
|
||||
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| T | F | O | R | U | H | I | S | - | N | C | A | G | B | D | E | data
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
|
||||
Where the differing bits are:
|
||||
|
||||
T = Attention
|
||||
R = Read/Write Unsafe
|
||||
H = Access Hunting
|
||||
I = Seek Incomplete
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. The following implemented behaviors have been inferred from secondary
|
||||
sources (diagnostics, operating system drivers, etc.), due to absent or
|
||||
contradictory authoritative information; future correction may be needed:
|
||||
|
||||
- 12557A status bit 15 (ATTENTION) does not set bit 0 (ANY ERROR).
|
||||
|
||||
- 12557A clears status after a Check Status command, but 13210A does
|
||||
not.
|
||||
|
||||
- Omitting STC DC before Status Check does not set DC flag but does
|
||||
poll.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "hp2100_defs.h"
|
||||
#include "hp2100_cpu.h"
|
||||
|
||||
|
||||
|
||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
||||
#define UNIT_V_UNLOAD (UNIT_V_UF + 1) /* heads unloaded */
|
||||
@@ -148,7 +253,13 @@
|
||||
#define DP_SIZE3 (DP_NUMSF * DP_NUMCY * DP_NUMSC3 * DP_NUMWD)
|
||||
#define DP_NUMDRV 4 /* # drives */
|
||||
|
||||
/* Command word */
|
||||
/* Command word.
|
||||
|
||||
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| command | - - | P | D | - - - - - - | unit |
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
*/
|
||||
|
||||
#define CW_V_FNC 12 /* function */
|
||||
#define CW_M_FNC 017
|
||||
@@ -187,35 +298,51 @@
|
||||
#define DA_CKMASK3 077
|
||||
#define DA_CKMASK (dp_ctype ? DA_CKMASK3 : DA_CKMASK2)
|
||||
|
||||
/* Status in dpc_sta[drv], (u) = unused in 13210, (d) = dynamic */
|
||||
/* Status in dpc_sta [drv].
|
||||
|
||||
#define STA_ATN 0100000 /* attention (u) */
|
||||
#define STA_1ST 0040000 /* first status */
|
||||
#define STA_OVR 0020000 /* overrun */
|
||||
#define STA_RWU 0010000 /* rw unsafe NI (u) */
|
||||
#define STA_ACU 0004000 /* access unsafe NI */
|
||||
#define STA_HUNT 0002000 /* hunting NI (12557) */
|
||||
#define STA_PROT 0002000 /* protected (13210) */
|
||||
#define STA_SKI 0001000 /* incomplete NI (u) */
|
||||
#define STA_SKE 0000400 /* seek error */
|
||||
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| - | F | O | - | U | P | - | S | - | N | C | A | G | B | D | E | 13210A
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| T | F | O | R | U | H | I | S | - | N | C | A | G | B | D | E | 12557A
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. The Data Protected, Not Ready, and Any Error bits are determined
|
||||
dynamically. The other status bits are stored in the drive status array.
|
||||
*/
|
||||
|
||||
#define STA_ATN 0100000 /* (T) Attention (12557) */
|
||||
#define STA_1ST 0040000 /* (F) First status */
|
||||
#define STA_OVR 0020000 /* (O) Overrun */
|
||||
#define STA_RWU 0010000 /* (R) Read/Write Unsafe (12557) */
|
||||
#define STA_ACU 0004000 /* (U) Drive Unsafe */
|
||||
#define STA_PROT 0002000 /* (P) Data Protected (13210) */
|
||||
#define STA_HUNT 0002000 /* (H) Access Hunting (12557) */
|
||||
#define STA_SKI 0001000 /* (I) Seek Incomplete (12557) */
|
||||
#define STA_SKE 0000400 /* (S) Seek Check */
|
||||
/* 0000200 (unused) */
|
||||
#define STA_NRDY 0000100 /* not ready (d) */
|
||||
#define STA_EOC 0000040 /* end of cylinder */
|
||||
#define STA_AER 0000020 /* addr error */
|
||||
#define STA_FLG 0000010 /* flagged */
|
||||
#define STA_BSY 0000004 /* seeking */
|
||||
#define STA_DTE 0000002 /* data error */
|
||||
#define STA_ERR 0000001 /* any error (d) */
|
||||
#define STA_NRDY 0000100 /* (N) Not Ready */
|
||||
#define STA_EOC 0000040 /* (C) End of Cylinder */
|
||||
#define STA_AER 0000020 /* (A) Address Error */
|
||||
#define STA_FLG 0000010 /* (G) Flagged Cylinder */
|
||||
#define STA_BSY 0000004 /* (B) Drive Busy */
|
||||
#define STA_DTE 0000002 /* (D) Data Error */
|
||||
#define STA_ERR 0000001 /* (E) Any Error */
|
||||
|
||||
#define STA_ERSET2 (STA_1ST | STA_OVR | STA_RWU | STA_ACU | \
|
||||
STA_SKI | STA_SKE | STA_NRDY | \
|
||||
STA_EOC | STA_AER | STA_DTE) /* 12557A error set */
|
||||
|
||||
#define STA_ERSET3 (STA_ATN | STA_1ST | STA_OVR | STA_RWU | STA_ACU | \
|
||||
STA_SKI | STA_SKE | STA_NRDY | STA_EOC | STA_AER | \
|
||||
STA_FLG | STA_BSY | STA_DTE) /* 13210A error set */
|
||||
#define STA_ANYERR (dp_ctype ? STA_ERSET3 : STA_ERSET2)
|
||||
|
||||
#define STA_ANYERR (dp_ctype ? STA_ERSET3 : STA_ERSET2)
|
||||
#define STA_UNLOADED (dp_ctype ? (STA_NRDY | STA_BSY) : STA_NRDY)
|
||||
|
||||
#define STA_MBZ13 (STA_ATN | STA_RWU | STA_SKI) /* zero in 13210 */
|
||||
|
||||
struct {
|
||||
@@ -311,18 +438,46 @@ REG dpd_reg[] = {
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB dpd_mod[] = {
|
||||
{ MTAB_XTD | MTAB_VDV, 1, "SC", "SC", &hp_setsc, &hp_showsc, &dpd_dev },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &dpd_dev },
|
||||
MTAB dpd_mod [] = {
|
||||
/* Entry Flags Value Print String Match String Validation Display Descriptor */
|
||||
/* ------------------- ----- ------------ ------------ ------------ ------------- ---------------- */
|
||||
{ MTAB_XDV, 2u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &dp_dib },
|
||||
{ MTAB_XDV | MTAB_NMO, ~2u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &dp_dib },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
/* Debugging trace list */
|
||||
|
||||
static DEBTAB dpd_deb [] = {
|
||||
{ "IOBUS", TRACE_IOBUS }, /* trace I/O bus signals and data words received and returned */
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
/* Device descriptor */
|
||||
|
||||
DEVICE dpd_dev = {
|
||||
"DPD", &dpd_unit, dpd_reg, dpd_mod,
|
||||
1, 10, DP_N_NUMWD, 1, 8, 16,
|
||||
NULL, NULL, &dpc_reset,
|
||||
NULL, NULL, NULL,
|
||||
&dpd_dib, DEV_DISABLE
|
||||
"DPD", /* device name */
|
||||
&dpd_unit, /* unit array */
|
||||
dpd_reg, /* register array */
|
||||
dpd_mod, /* modifier array */
|
||||
1, /* number of units */
|
||||
10, /* address radix */
|
||||
DP_N_NUMWD, /* address width = 4 GB */
|
||||
1, /* address increment */
|
||||
8, /* data radix */
|
||||
16, /* data width */
|
||||
NULL, /* examine routine */
|
||||
NULL, /* deposit routine */
|
||||
&dpc_reset, /* reset routine */
|
||||
NULL, /* boot routine */
|
||||
NULL, /* attach routine */
|
||||
NULL, /* detach routine */
|
||||
&dpd_dib, /* device information block pointer */
|
||||
DEV_DISABLE | DEV_DEBUG, /* device flags */
|
||||
0, /* debug control flags */
|
||||
dpd_deb, /* debug flag name array */
|
||||
NULL, /* memory size change routine */
|
||||
NULL /* logical device name */
|
||||
};
|
||||
|
||||
/* DPC data structures
|
||||
@@ -373,28 +528,58 @@ REG dpc_reg[] = {
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB dpc_mod[] = {
|
||||
{ UNIT_UNLOAD, UNIT_UNLOAD, "heads unloaded", "UNLOADED", dpc_load_unload },
|
||||
{ UNIT_UNLOAD, 0, "heads loaded", "LOADED", dpc_load_unload },
|
||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 1, NULL, "13210A",
|
||||
&dp_settype, NULL, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 0, NULL, "12557A",
|
||||
&dp_settype, NULL, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 0, "TYPE", NULL,
|
||||
NULL, &dp_showtype, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 1, "SC", "SC", &hp_setsc, &hp_showsc, &dpd_dev },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &dpd_dev },
|
||||
MTAB dpc_mod [] = {
|
||||
/* Mask Value Match Value Print String Match String Validation Display Descriptor */
|
||||
/* ------------ ------------ ----------------- --------------- ----------------- ------- ---------- */
|
||||
{ UNIT_UNLOAD, UNIT_UNLOAD, "heads unloaded", "UNLOADED", &dpc_load_unload, NULL, NULL },
|
||||
{ UNIT_UNLOAD, 0, "heads loaded", "LOADED", &dpc_load_unload, NULL, NULL },
|
||||
{ UNIT_WLK, UNIT_WLK, "protected", "PROTECT", NULL, NULL, NULL },
|
||||
{ UNIT_WLK, 0, "unprotected", "UNPROTECT", NULL, NULL, NULL },
|
||||
{ UNIT_WLK, UNIT_WLK, NULL, "LOCKED", NULL, NULL, NULL },
|
||||
{ UNIT_WLK, 0, NULL, "WRITEENABLED", NULL, NULL, NULL },
|
||||
|
||||
/* Entry Flags Value Print String Match String Validation Display Descriptor */
|
||||
/* ------------------- ----- ------------ ------------ ------------ ------------- ---------------- */
|
||||
{ MTAB_XDV, 1, NULL, "13210A", &dp_settype, NULL, NULL },
|
||||
{ MTAB_XDV, 0, NULL, "12557A", &dp_settype, NULL, NULL },
|
||||
{ MTAB_XDV, 0, "TYPE", NULL, NULL, &dp_showtype, NULL },
|
||||
{ MTAB_XDV, 2u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &dp_dib },
|
||||
{ MTAB_XDV | MTAB_NMO, ~2u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &dp_dib },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
/* Debugging trace list */
|
||||
|
||||
static DEBTAB dpc_deb [] = {
|
||||
{ "IOBUS", TRACE_IOBUS }, /* trace I/O bus signals and data words received and returned */
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
/* Device descriptor */
|
||||
|
||||
DEVICE dpc_dev = {
|
||||
"DPC", dpc_unit, dpc_reg, dpc_mod,
|
||||
DP_NUMDRV, 8, 24, 1, 8, 16,
|
||||
NULL, NULL, &dpc_reset,
|
||||
&dpc_boot, &dpc_attach, &dpc_detach,
|
||||
&dpc_dib, DEV_DISABLE
|
||||
"DPC", /* device name */
|
||||
dpc_unit, /* unit array */
|
||||
dpc_reg, /* register array */
|
||||
dpc_mod, /* modifier array */
|
||||
DP_NUMDRV, /* number of units */
|
||||
8, /* address radix */
|
||||
24, /* address width = 4 GB */
|
||||
1, /* address increment */
|
||||
8, /* data radix */
|
||||
16, /* data width */
|
||||
NULL, /* examine routine */
|
||||
NULL, /* deposit routine */
|
||||
&dpc_reset, /* reset routine */
|
||||
&dpc_boot, /* boot routine */
|
||||
&dpc_attach, /* attach routine */
|
||||
&dpc_detach, /* detach routine */
|
||||
&dpc_dib, /* device information block pointer */
|
||||
DEV_DISABLE | DEV_DEBUG, /* device flags */
|
||||
0, /* debug control flags */
|
||||
dpc_deb, /* debug flag name array */
|
||||
NULL, /* memory size change routine */
|
||||
NULL /* logical device name */
|
||||
};
|
||||
|
||||
|
||||
@@ -533,6 +718,7 @@ return stat_data;
|
||||
flip-flops. Only the 12557A has a command flip-flop. IRQ, PRL, and SRQ are
|
||||
standard.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. In hardware, the command channel card passes PRH to PRL. The data card
|
||||
@@ -542,6 +728,30 @@ return stat_data;
|
||||
the command card is interrupting. This works in hardware, but we must
|
||||
break PRL at the command card under simulation to allow the command card
|
||||
to interrupt.
|
||||
|
||||
2. The 13210 manual says that a Check Status command clears the status
|
||||
register, which consists of status word bits 14, 13, 11, 10, 8, 5, 4, 3,
|
||||
1, and 0, i.e., all except bit 6 "Not Ready" and bit 2 "Drive Busy",
|
||||
which are direct pass-throughs from the drive. However, the schematic
|
||||
shows that the register is cleared on STC assertion for any command
|
||||
OTHER than Check Status. In other words, every command except Check
|
||||
Status clears the old status in order to assert new status (so two
|
||||
successive Check Status commands will return the same status word,
|
||||
contrary to the manual). The simulator implements the schematic
|
||||
behavior.
|
||||
|
||||
3. The schematics contained in 13210A manuals dated November 1974 and
|
||||
earlier show that CRS does not clear the status register, but examining
|
||||
the hardware PCA shows that it does. The simulator implements the
|
||||
hardware behavior.
|
||||
|
||||
4. The schematics contained in 13210A manuals dated November 1974 and
|
||||
earlier show that CRS clears the attention register, but examining the
|
||||
hardware PCA shows that it does not. The signal marked CRS is actually
|
||||
the XFER CYL signal from the sequencer, so the register is actually
|
||||
cleared when a Check Status or Seek command is issued. However, later
|
||||
PCAs did add CRS to the other two clearing conditions. The simulator
|
||||
implements this later behavior.
|
||||
*/
|
||||
|
||||
uint32 dpcio (DIB *dibptr, IOCYCLE signal_set, uint32 stat_data)
|
||||
@@ -609,6 +819,11 @@ while (working_set) {
|
||||
|
||||
if (dp_ctype == A12557) /* 12557? */
|
||||
dpc.command = CLEAR; /* clear command */
|
||||
|
||||
for (drv = 0; drv < DP_NUMDRV; drv++) /* clear drive status */
|
||||
dpc_sta [drv] &= /* for each drive */
|
||||
~(STA_1ST | STA_OVR | STA_RWU | STA_ACU | STA_EOC
|
||||
| STA_AER | STA_FLG | STA_DTE);
|
||||
break;
|
||||
|
||||
|
||||
@@ -638,6 +853,11 @@ while (working_set) {
|
||||
drv = CW_GETDRV (dpc_obuf); /* get fnc, drv */
|
||||
fnc = CW_GETFNC (dpc_obuf); /* from cmd word */
|
||||
|
||||
if (fnc != FNC_STA) /* if this is not a status command */
|
||||
dpc_sta [drv] &= /* then clear the status register */
|
||||
~(STA_OVR | STA_RWU | STA_ACU | STA_EOC
|
||||
| STA_AER | STA_FLG | STA_DTE);
|
||||
|
||||
switch (fnc) { /* case on fnc */
|
||||
|
||||
case FNC_SEEK: /* seek */
|
||||
@@ -716,7 +936,7 @@ dpc_eoc = 0; /* clear end cyl */
|
||||
dpc_busy = drv + 1; /* set busy */
|
||||
dpd_xfer = 1; /* xfer in prog */
|
||||
dpc_unit[drv].FNC = fnc; /* save function */
|
||||
dpc_sta[drv] = dpc_sta[drv] & ~STA_ATN; /* clear ATN */
|
||||
dpc_sta[drv] &= ~(STA_ATN | STA_1ST); /* clear Attention and First Status */
|
||||
sim_activate (&dpc_unit[drv], time); /* activate unit */
|
||||
return;
|
||||
}
|
||||
@@ -739,6 +959,8 @@ return;
|
||||
Status check - transfer status, finish operation
|
||||
Check data
|
||||
chk - transfer sector count
|
||||
|
||||
The 12557A clears status after a Check Status command. The 13210A does not.
|
||||
*/
|
||||
|
||||
t_stat dpd_svc (UNIT *uptr)
|
||||
@@ -820,10 +1042,14 @@ switch (uptr->FNC) { /* case function */
|
||||
dpdio (&dpd_dib, ioENF, 0); /* set dch flg */
|
||||
}
|
||||
|
||||
dpc_sta[drv] = dpc_sta[drv] & /* clr sta flags */
|
||||
~(STA_ATN | STA_1ST | STA_OVR |
|
||||
STA_RWU | STA_ACU | STA_EOC |
|
||||
STA_AER | STA_FLG | STA_DTE);
|
||||
if (dp_ctype == A13210)
|
||||
dpc_sta [drv] &= ~STA_ATN; /* clear the current drive's attention bit */
|
||||
else
|
||||
dpc_sta[drv] &=
|
||||
~(STA_ATN | STA_1ST | STA_OVR |
|
||||
STA_RWU | STA_ACU | STA_EOC |
|
||||
STA_AER | STA_FLG | STA_DTE);
|
||||
|
||||
dpc_poll = 1; /* enable polling */
|
||||
for (i = 0; i < DP_NUMDRV; i++) { /* loop thru drives */
|
||||
if (dpc_sta[i] & STA_ATN) { /* any ATN set? */
|
||||
@@ -997,8 +1223,10 @@ dpc_busy = 0; /* ctlr is free */
|
||||
dpd_xfer = dpd_wval = 0;
|
||||
|
||||
if (err != 0) { /* error? */
|
||||
perror ("DP I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
cprintf ("%s simulator DP disc I/O error: %s\n", /* then report the error to the console */
|
||||
sim_name, strerror (errno));
|
||||
|
||||
clearerr (uptr->fileref); /* clear the error */
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
return SCPE_OK;
|
||||
@@ -1045,15 +1273,44 @@ return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Attach routine */
|
||||
/* Attach a drive unit.
|
||||
|
||||
The specified file is attached to the indicated drive unit, and the heads are
|
||||
loaded, which will will set the First Status and Attention bits in the drive
|
||||
status. If a new file is specified, the file is initialized to its capacity
|
||||
by writing a zero to the last byte in the file.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. The C standard says, "A binary stream need not meaningfully support fseek
|
||||
calls with a whence value of SEEK_END," so instead we determine the
|
||||
offset from the start of the file to the last byte and seek there.
|
||||
*/
|
||||
|
||||
t_stat dpc_attach (UNIT *uptr, CONST char *cptr)
|
||||
{
|
||||
t_stat r;
|
||||
t_stat result;
|
||||
t_addr offset;
|
||||
const uint8 zero = 0;
|
||||
|
||||
r = attach_unit (uptr, cptr); /* attach unit */
|
||||
if (r == SCPE_OK) dpc_load_unload (uptr, 0, NULL, NULL);/* if OK, load heads */
|
||||
return r;
|
||||
result = attach_unit (uptr, cptr); /* attach the drive */
|
||||
|
||||
if (result == SCPE_OK) { /* if the attach was successful */
|
||||
dpc_load_unload (uptr, 0, NULL, NULL); /* then load the heads */
|
||||
|
||||
if (sim_switches & SWMASK ('N')) { /* if this is a new disc image */
|
||||
offset = (t_addr) /* then determine the offset of */
|
||||
(uptr->capac * sizeof (int16) - sizeof zero); /* the last byte in a full-sized file */
|
||||
|
||||
if (sim_fseek (uptr->fileref, offset, SEEK_SET) != 0 /* seek to the last byte */
|
||||
|| fwrite (&zero, sizeof zero, 1, uptr->fileref) == 0 /* and write a zero to fill */
|
||||
|| fflush (uptr->fileref) != 0) /* the file to its capacity */
|
||||
clearerr (uptr->fileref); /* clear and ignore any errors */
|
||||
}
|
||||
}
|
||||
|
||||
return result; /* return the result of the attach */
|
||||
}
|
||||
|
||||
|
||||
@@ -1122,83 +1379,278 @@ return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* 7900/7901 bootstrap routine (HP 12992F ROM) */
|
||||
/* 7900/2870 disc bootstrap loaders (BMDL and 12992F).
|
||||
|
||||
const BOOT_ROM dp_rom = {
|
||||
0106710, /*ST CLC DC ; clr dch */
|
||||
0106711, /* CLC CC ; clr cch */
|
||||
0017757, /* JSB STAT ; get status */
|
||||
0067746, /*SK LDB SKCMD ; seek cmd */
|
||||
0106610, /* OTB DC ; cyl # */
|
||||
0103710, /* STC DC,C ; to dch */
|
||||
0106611, /* OTB CC ; seek cmd */
|
||||
0103711, /* STC CC,C ; to cch */
|
||||
0102310, /* SFS DC ; addr wd ok? */
|
||||
0027710, /* JMP *-1 ; no, wait */
|
||||
0006400, /* CLB */
|
||||
0102501, /* LIA 1 ; read switches */
|
||||
0002011, /* SLA,RSS ; <0> set? */
|
||||
0047747, /* ADB BIT9 ; head 2 = removable */
|
||||
0106610, /* OTB DC ; head/sector */
|
||||
0103710, /* STC DC,C ; to dch */
|
||||
0102311, /* SFS CC ; seek done? */
|
||||
0027720, /* JMP *-1 ; no, wait */
|
||||
0017757, /* JSB STAT ; get status */
|
||||
0067776, /* LDB DMACW ; DMA control */
|
||||
0106606, /* OTB 6 */
|
||||
0067750, /* LDB ADDR1 ; memory addr */
|
||||
0106602, /* OTB 2 */
|
||||
0102702, /* STC 2 ; flip DMA ctrl */
|
||||
0067752, /* LDB CNT ; word count */
|
||||
0106602, /* OTB 2 */
|
||||
0063745, /* LDB RDCMD ; read cmd */
|
||||
0102611, /* OTA CC ; to cch */
|
||||
0103710, /* STC DC,C ; start dch */
|
||||
0103706, /* STC 6,C ; start DMA */
|
||||
0103711, /* STC CC,C ; start cch */
|
||||
0102311, /* SFS CC ; done? */
|
||||
0027737, /* JMP *-1 ; no, wait */
|
||||
0017757, /* JSB STAT ; get status */
|
||||
0027775, /* JMP XT ; done */
|
||||
0037766, /*FSMSK 037766 ; status mask */
|
||||
0004000, /*STMSK 004000 ; unsafe mask */
|
||||
0020000, /*RDCMD 020000 ; read cmd */
|
||||
0030000, /*SKCMD 030000 ; seek cmd */
|
||||
0001000, /*BIT9 001000 ; head 2 select */
|
||||
0102011, /*ADDR1 102011 */
|
||||
0102055, /*ADDR2 102055 */
|
||||
0164000, /*CNT -6144. */
|
||||
0, 0, 0, 0, /* unused */
|
||||
0000000, /*STAT 0 */
|
||||
0002400, /* CLA ; status request */
|
||||
0102611, /* OTC CC ; to cch */
|
||||
0103711, /* STC CC,C ; start cch */
|
||||
0102310, /* SFS DC ; done? */
|
||||
0027763, /* JMP *-1 */
|
||||
0102510, /* LIA DC ; get status */
|
||||
0013743, /* AND FSMSK ; mask 15,14,3,0 */
|
||||
0002003, /* SZA,RSS ; drive ready? */
|
||||
0127757, /* JMP STAT,I ; yes */
|
||||
0013744, /* AND STMSK ; fault? */
|
||||
0002002, /* SZA */
|
||||
0102030, /* HLT 30 ; yes */
|
||||
0027700, /* JMP ST ; no, retry */
|
||||
0117751, /*XT JSB ADDR2,I ; start program */
|
||||
0120010, /*DMACW 120000+DC */
|
||||
0000000 /* -ST */
|
||||
The Basic Moving-Head Disc Loader (BMDL) consists of two programs. The
|
||||
program starting at address x7700 loads absolute paper tapes into memory.
|
||||
The program starting at address x7750 loads a disc-resident bootstrap from
|
||||
the 7900 or 2870 disc drive into memory. The S register setting does not
|
||||
affect loader operation.
|
||||
|
||||
For a 2100/14/15/16 CPU, entering a LOAD DPC or BOOT DPC command loads the
|
||||
BMDL into memory and executes the disc portion starting at x7750. The
|
||||
bootstrap reads 6144 (for a 7900) or 3072 (for a 2870) words from cylinder 0,
|
||||
head 0, sector 0 into memory starting at location 2011 octal. Loader
|
||||
execution ends with the following instruction:
|
||||
|
||||
* JSB 2055,I - the disc read completed.
|
||||
|
||||
The BMDL configures DMA for an oversize (~32000 word) transfer and expects
|
||||
the disc to terminate the operation with End of Cylinder (EOC) status.
|
||||
|
||||
The HP 1000 uses the 12992F boot loader ROM to bootstrap the 7900 disc. Bit
|
||||
0 of the S register determines whether the boot extension is read from
|
||||
subchannel 0 (the fixed platter) or subchannel 1 (the removable platter).
|
||||
The loader reads 6144 words from cylinder 0 sector 0 of the specified
|
||||
subchannel into memory starting at location 2011 octal. Loader execution
|
||||
ends with one of the following instructions:
|
||||
|
||||
* HLT 30 - a drive fault occurred.
|
||||
* JSB 2055,I - the disc read succeeded.
|
||||
|
||||
The loader automatically retries the operations for all disc errors other
|
||||
than a drive fault.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. After the BMDL has been loaded into memory, the paper tape portion may be
|
||||
executed manually by setting the P register to the starting address
|
||||
(x7700).
|
||||
|
||||
2. For compatibility with the "cpu_copy_loader" routine, the BMDL device I/O
|
||||
instructions address select codes 10 and 11.
|
||||
|
||||
3. As published, the BMDL is configured to read from head 0 (the removable
|
||||
platter, a.k.a. subchannel 1). To read from head 2 (the fixed platter,
|
||||
subchannel 0), the head/sector control word must be changed.
|
||||
*/
|
||||
|
||||
#define BMDL_SUBCHANNEL_0 031000 /* BMDL control word to address subchannel 0 instead of 1 */
|
||||
|
||||
static const LOADER_ARRAY dp_loaders = {
|
||||
{ /* HP 21xx Basic Moving-Head Disc Loader (BMDL-7900) */
|
||||
050, /* loader starting index */
|
||||
077, /* DMA index */
|
||||
034, /* FWA index */
|
||||
{ 0002401, /* 77700: PTAPE CLA,RSS Paper Tape start */
|
||||
0063721, /* 77701: LDA 77721 */
|
||||
0107700, /* 77702: CLC 0,C */
|
||||
0002307, /* 77703: CCE,INA,SZA,RSS */
|
||||
0102077, /* 77704: HLT 77 */
|
||||
0017735, /* 77705: JSB 77735 */
|
||||
0007307, /* 77706: CMB,CCE,INB,SZB,RSS */
|
||||
0027702, /* 77707: JMP 77702 */
|
||||
0077733, /* 77710: STB 77733 */
|
||||
0017735, /* 77711: JSB 77735 */
|
||||
0017735, /* 77712: JSB 77735 */
|
||||
0074000, /* 77713: STB 0 */
|
||||
0077747, /* 77714: STB 77747 */
|
||||
0047734, /* 77715: ADB 77734 */
|
||||
0002140, /* 77716: SEZ,CLE */
|
||||
0102055, /* 77717: HLT 55 */
|
||||
0017735, /* 77720: JSB 77735 */
|
||||
0177747, /* 77721: STB 77747,I */
|
||||
0040001, /* 77722: ADA 1 */
|
||||
0067747, /* 77723: LDB 77747 */
|
||||
0006104, /* 77724: CLE,INB */
|
||||
0037733, /* 77725: ISZ 77733 */
|
||||
0027714, /* 77726: JMP 77714 */
|
||||
0017735, /* 77727: JSB 77735 */
|
||||
0054000, /* 77730: CPB 0 */
|
||||
0027701, /* 77731: JMP 77701 */
|
||||
0102011, /* 77732: HLT 11 */
|
||||
0000000, /* 77733: OCT 000000 */
|
||||
0100100, /* 77734: OCT 1n0100 */
|
||||
0000000, /* 77735: NOP */
|
||||
0006400, /* 77736: CLB */
|
||||
0103710, /* 77737: STC 10,C */
|
||||
0102310, /* 77740: SFS 10 */
|
||||
0027740, /* 77741: JMP 77740 */
|
||||
0107410, /* 77742: MIB 10,C */
|
||||
0002240, /* 77743: SEZ,CME */
|
||||
0127735, /* 77744: JMP 77735,I */
|
||||
0005727, /* 77745: BLF,BLF */
|
||||
0027737, /* 77746: JMP 77737 */
|
||||
0000000, /* 77747: OCT 000000 */
|
||||
0030000, /* 77750: DISC IOR 0 Disc start */
|
||||
0067741, /* 77751: LDB 77741 */
|
||||
0106611, /* 77752: OTB 11 */
|
||||
0103711, /* 77753: STC 11,C */
|
||||
0063750, /* 77754: LDA 77750 */
|
||||
0102610, /* 77755: OTA 10 */
|
||||
0103710, /* 77756: STC 10,C */
|
||||
0102611, /* 77757: OTA 11 */
|
||||
0103711, /* 77760: STC 11,C */
|
||||
0063777, /* 77761: LDA 77777 */
|
||||
0102606, /* 77762: OTA 6 */
|
||||
0063732, /* 77763: LDA 77732 */
|
||||
0102602, /* 77764: OTA 2 */
|
||||
0103710, /* 77765: STC 10,C */
|
||||
0102702, /* 77766: STC 2 */
|
||||
0102602, /* 77767: OTA 2 */
|
||||
0106611, /* 77770: OTB 11 */
|
||||
0103710, /* 77771: STC 10,C */
|
||||
0103706, /* 77772: STC 6,C */
|
||||
0103711, /* 77773: STC 11,C */
|
||||
0102311, /* 77774: SFS 11 */
|
||||
0027774, /* 77775: JMP 77774 */
|
||||
0117717, /* 77776: JSB 77717,I */
|
||||
0120010 } }, /* 77777: OCT 120010 */
|
||||
|
||||
{ /* HP 1000 Loader ROM (12992F) */
|
||||
IBL_START, /* loader starting index */
|
||||
IBL_DMA, /* DMA index */
|
||||
IBL_FWA, /* FWA index */
|
||||
{ 0106710, /* 77700: ST CLC DC ; clr dch */
|
||||
0106711, /* 77701: CLC CC ; clr cch */
|
||||
0017757, /* 77702: JSB STAT ; get status */
|
||||
0067746, /* 77703: SK LDB SKCMD ; seek cmd */
|
||||
0106610, /* 77704: OTB DC ; cyl # */
|
||||
0103710, /* 77705: STC DC,C ; to dch */
|
||||
0106611, /* 77706: OTB CC ; seek cmd */
|
||||
0103711, /* 77707: STC CC,C ; to cch */
|
||||
0102310, /* 77710: SFS DC ; addr wd ok? */
|
||||
0027710, /* 77711: JMP *-1 ; no, wait */
|
||||
0006400, /* 77712: CLB */
|
||||
0102501, /* 77713: LIA 1 ; read switches */
|
||||
0002011, /* 77714: SLA,RSS ; <0> set? */
|
||||
0047747, /* 77715: ADB BIT9 ; head 2 = removable */
|
||||
0106610, /* 77716: OTB DC ; head/sector */
|
||||
0103710, /* 77717: STC DC,C ; to dch */
|
||||
0102311, /* 77720: SFS CC ; seek done? */
|
||||
0027720, /* 77721: JMP *-1 ; no, wait */
|
||||
0017757, /* 77722: JSB STAT ; get status */
|
||||
0067776, /* 77723: LDB DMACW ; DMA control */
|
||||
0106606, /* 77724: OTB 6 */
|
||||
0067750, /* 77725: LDB ADDR1 ; memory addr */
|
||||
0106602, /* 77726: OTB 2 */
|
||||
0102702, /* 77727: STC 2 ; flip DMA ctrl */
|
||||
0067752, /* 77730: LDB CNT ; word count */
|
||||
0106602, /* 77731: OTB 2 */
|
||||
0063745, /* 77732: LDB RDCMD ; read cmd */
|
||||
0102611, /* 77733: OTA CC ; to cch */
|
||||
0103710, /* 77734: STC DC,C ; start dch */
|
||||
0103706, /* 77735: STC 6,C ; start DMA */
|
||||
0103711, /* 77736: STC CC,C ; start cch */
|
||||
0102311, /* 77737: SFS CC ; done? */
|
||||
0027737, /* 77740: JMP *-1 ; no, wait */
|
||||
0017757, /* 77741: JSB STAT ; get status */
|
||||
0027775, /* 77742: JMP XT ; done */
|
||||
0037766, /* 77743: FSMSK OCT 037766 ; status mask */
|
||||
0004000, /* 77744: STMSK OCT 004000 ; unsafe mask */
|
||||
0020000, /* 77745: RDCMD OCT 020000 ; read cmd */
|
||||
0030000, /* 77746: SKCMD OCT 030000 ; seek cmd */
|
||||
0001000, /* 77747: BIT9 OCT 001000 ; head 2 select */
|
||||
0102011, /* 77750: ADDR1 OCT 102011 */
|
||||
0102055, /* 77751: ADDR2 OCT 102055 */
|
||||
0164000, /* 77752: CNT DEC -6144. */
|
||||
0000000, /* 77753: NOP */
|
||||
0000000, /* 77754: NOP */
|
||||
0000000, /* 77755: NOP */
|
||||
0000000, /* 77756: NOP */
|
||||
0000000, /* 77757: STAT NOP */
|
||||
0002400, /* 77760: CLA ; status request */
|
||||
0102611, /* 77761: OTC CC ; to cch */
|
||||
0103711, /* 77762: STC CC,C ; start cch */
|
||||
0102310, /* 77763: SFS DC ; done? */
|
||||
0027763, /* 77764: JMP *-1 */
|
||||
0102510, /* 77765: LIA DC ; get status */
|
||||
0013743, /* 77766: AND FSMSK ; mask 15,14,3,0 */
|
||||
0002003, /* 77767: SZA,RSS ; drive ready? */
|
||||
0127757, /* 77770: JMP STAT,I ; yes */
|
||||
0013744, /* 77771: AND STMSK ; fault? */
|
||||
0002002, /* 77772: SZA */
|
||||
0102030, /* 77773: HLT 30 ; yes */
|
||||
0027700, /* 77774: JMP ST ; no, retry */
|
||||
0117751, /* 77775: XT JSB ADDR2,I ; start program */
|
||||
0120010, /* 77776: DMACW ABS 120000+DC */
|
||||
0000000 } } /* 77777: ABS -ST */
|
||||
};
|
||||
|
||||
|
||||
/* Device boot routine.
|
||||
|
||||
This routine is called directly by the BOOT DPC and LOAD DPC commands to copy
|
||||
the device bootstrap into the upper 64 words of the logical address space.
|
||||
It is also called indirectly by a BOOT CPU or LOAD CPU command when the
|
||||
specified HP 1000 loader ROM socket contains a 12992F ROM.
|
||||
|
||||
When called in response to a BOOT DPC or LOAD DPC command, the "unitno"
|
||||
parameter indicates the unit number specified in the BOOT command or is zero
|
||||
for the LOAD command, and "dptr" points at the DPC device structure. The
|
||||
bootstrap supports loading only from unit 0, and the command will be rejected
|
||||
if another unit is specified (e.g., BOOT DPC1). Otherwise, depending on the
|
||||
current CPU model, the BMDL or 12992F loader ROM will be copied into memory
|
||||
and configured for the DPD/DPC select code pair. If the CPU is a 1000, the S
|
||||
register will be set as it would be by the front-panel microcode.
|
||||
|
||||
When called for a BOOT/LOAD CPU command, the "unitno" parameter indicates the
|
||||
select code to be used for configuration, and "dptr" will be NULL. As above,
|
||||
the BMDL or 12992F loader ROM will be copied into memory and configured for
|
||||
the specified select code. The S register is assumed to be set correctly on
|
||||
entry and is not modified.
|
||||
|
||||
In either case, if the CPU is a 21xx model, the paper tape portion of the
|
||||
BMDL will be automatically configured for the select code of the paper tape
|
||||
reader.
|
||||
|
||||
For the 12992F boot loader ROM for the HP 1000, the S register is set as
|
||||
follows:
|
||||
|
||||
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| ROM # | 0 0 | select code | reserved | 0 0 | S |
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
|
||||
Where:
|
||||
|
||||
S = the subchannel number
|
||||
|
||||
Bit 0 specifies the subchannel containing the operating system. For the
|
||||
7900, either the fixed (0) or removable (1) platter may be specified. For
|
||||
the 7901, bit 0 must be 1. If the -R switch is specified for the BOOT or
|
||||
LOAD command, the loader ROM will be configured to boot from the removable
|
||||
platter instead of the fixed platter.
|
||||
|
||||
Bits 5-3 are nominally zero but are reserved for the target operating system.
|
||||
For example, RTE uses bit 5 to indicate whether a standard (0) or
|
||||
reconfiguration (1) boot is desired.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. In hardware, the BMDL was hand-configured for the disc and paper tape
|
||||
reader select codes when it was installed on a given system. Under
|
||||
simulation, the LOAD and BOOT commands automatically configure the BMDL
|
||||
to the current select codes of the PTR and DP devices.
|
||||
|
||||
2. As installed, the BMDL is configured to read from the removable platter
|
||||
(a.k.a. subchannel 1). If the -R switch is specified to read from the
|
||||
fixed platter (subchannel 0), the head number in the head/sector control
|
||||
word in memory is changed from 0 to 2.
|
||||
*/
|
||||
|
||||
t_stat dpc_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
const int32 dev = dpd_dib.select_code; /* data chan select code */
|
||||
static const HP_WORD dp_preserved = 0000070u; /* S-register bits 5-3 are preserved */
|
||||
const uint32 subchannel = sim_switches & SWMASK ('R') ? 1 : 0; /* the selected boot subchannel */
|
||||
t_stat status;
|
||||
|
||||
if (unitno != 0) /* boot supported on drive unit 0 only */
|
||||
return SCPE_NOFNC; /* report "Command not allowed" if attempted */
|
||||
if (dptr == NULL) /* if we are being called for a BOOT/LOAD CPU */
|
||||
status = cpu_copy_loader (dp_loaders, unitno, /* then copy the boot loader to memory */
|
||||
IBL_S_NOCLEAR, IBL_S_NOSET); /* but do not alter the S register */
|
||||
|
||||
if (ibl_copy (dp_rom, dev, IBL_OPT, /* copy the boot ROM to memory and configure */
|
||||
IBL_DP | IBL_SET_SC (dev) /* the S register accordingly */
|
||||
| (sim_switches & SWMASK ('R') ? IBL_DP_REM : 0)))
|
||||
return SCPE_IERR; /* return an internal error if the copy failed */
|
||||
else
|
||||
return SCPE_OK;
|
||||
else if (unitno != 0) /* otherwise a BOOT DPC for a non-zero unit */
|
||||
return SCPE_NOFNC; /* is rejected as unsupported */
|
||||
|
||||
else /* otherwise this is a BOOT/LOAD DPC */
|
||||
status = cpu_copy_loader (dp_loaders, dpd_dib.select_code, /* so copy the boot loader to memory */
|
||||
dp_preserved, subchannel); /* and configure the S register if 1000 CPU */
|
||||
|
||||
if (status == SCPE_OK && subchannel == 0 /* if loader installed OK and boot is from subchan 0 */
|
||||
&& (PR & IBL_MASK) == dp_loaders [0].start_index) /* and the BMDL was installed */
|
||||
mem_deposit (PR, BMDL_SUBCHANNEL_0); /* then change the control word to use head 2 */
|
||||
|
||||
return status; /* return the status of the installation */
|
||||
}
|
||||
|
||||
@@ -1,31 +1,37 @@
|
||||
/* hp2100_dq.c: HP 2100 12565A disk simulator
|
||||
/* hp2100_dq.c: HP 2100 12565A Disc Interface and 2883 disc drive simulator
|
||||
|
||||
Copyright (c) 1993-2006, Bill McDermith
|
||||
Copyright (c) 2004-2016 J. David Bryan
|
||||
Copyright (c) 2004-2018, J. David Bryan
|
||||
|
||||
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:
|
||||
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.
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS 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 names of the authors shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from the authors.
|
||||
|
||||
DQ 12565A 2883 disk system
|
||||
DQ 12565A Disc Interface and 2883 disc drive
|
||||
|
||||
27-Feb-18 JDB Added the BMDL
|
||||
15-Feb-18 JDB ATTACH -N now creates a full-size disc image
|
||||
03-Aug-17 JDB Changed perror call for I/O errors to cprintf
|
||||
11-Jul-17 JDB Renamed "ibl_copy" to "cpu_ibl"
|
||||
09-Mar-17 JDB Deprecated LOCKED/WRITEENABLED for PROTECT/UNPROTECT
|
||||
27-Feb-17 JDB ibl_copy no longer returns a status code
|
||||
13-May-16 JDB Modified for revised SCP API function parameter types
|
||||
30-Dec-14 JDB Added S-register parameters to ibl_copy
|
||||
24-Dec-14 JDB Added casts for explicit downward conversions
|
||||
@@ -52,10 +58,11 @@
|
||||
09-Jan-02 WOM Copied dp driver and mods for 2883
|
||||
|
||||
Reference:
|
||||
- 12565A Disc Interface Kit Operating and Service Manual (12565-90003, Aug-1973)
|
||||
- 12565A Disc Interface Kit Operating and Service Manual
|
||||
(12565-90003, August 1973)
|
||||
|
||||
|
||||
Differences between 12559/13210 and 12565 controllers
|
||||
Differences between 12559/13210 and 12565 controllers:
|
||||
- 12565 stops transfers on address miscompares; 12559/13210 only stops writes
|
||||
- 12565 does not set error on positioner busy
|
||||
- 12565 does not set positioner busy if already on cylinder
|
||||
@@ -82,7 +89,12 @@
|
||||
1. Read Address command starts at the sector number in the RAR.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "hp2100_defs.h"
|
||||
#include "hp2100_cpu.h"
|
||||
|
||||
|
||||
|
||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
||||
#define UNIT_V_UNLOAD (UNIT_V_UF + 1) /* heads unloaded */
|
||||
@@ -234,9 +246,11 @@ REG dqd_reg[] = {
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB dqd_mod[] = {
|
||||
{ MTAB_XTD | MTAB_VDV, 1, "SC", "SC", &hp_setsc, &hp_showsc, &dqd_dev },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &dqd_dev },
|
||||
MTAB dqd_mod [] = {
|
||||
/* Entry Flags Value Print String Match String Validation Display Descriptor */
|
||||
/* ------------------- ----- ------------ ------------ ------------ ------------- ---------------- */
|
||||
{ MTAB_XDV, 2u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &dq_dib },
|
||||
{ MTAB_XDV | MTAB_NMO, ~2u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &dq_dib },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
@@ -288,13 +302,20 @@ REG dqc_reg[] = {
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB dqc_mod[] = {
|
||||
{ UNIT_UNLOAD, UNIT_UNLOAD, "heads unloaded", "UNLOADED", dqc_load_unload },
|
||||
{ UNIT_UNLOAD, 0, "heads loaded", "LOADED", dqc_load_unload },
|
||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 1, "SC", "SC", &hp_setsc, &hp_showsc, &dqd_dev },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &dqd_dev },
|
||||
MTAB dqc_mod [] = {
|
||||
/* Mask Value Match Value Print String Match String Validation Display Descriptor */
|
||||
/* ------------ ------------ ----------------- --------------- ----------------- ------- ---------- */
|
||||
{ UNIT_UNLOAD, UNIT_UNLOAD, "heads unloaded", "UNLOADED", &dqc_load_unload, NULL, NULL },
|
||||
{ UNIT_UNLOAD, 0, "heads loaded", "LOADED", &dqc_load_unload, NULL, NULL },
|
||||
{ UNIT_WLK, UNIT_WLK, "protected", "PROTECT", NULL, NULL, NULL },
|
||||
{ UNIT_WLK, 0, "unprotected", "UNPROTECT", NULL, NULL, NULL },
|
||||
{ UNIT_WLK, UNIT_WLK, NULL, "LOCKED", NULL, NULL, NULL },
|
||||
{ UNIT_WLK, 0, NULL, "WRITEENABLED", NULL, NULL, NULL },
|
||||
|
||||
/* Entry Flags Value Print String Match String Validation Display Descriptor */
|
||||
/* ------------------- ----- ------------ ------------ ------------ ------------- ---------------- */
|
||||
{ MTAB_XDV, 2u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &dq_dib },
|
||||
{ MTAB_XDV | MTAB_NMO, ~2u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &dq_dib },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
@@ -821,8 +842,10 @@ dqcio (&dqc_dib, ioENF, 0); /* set cch flg */
|
||||
dqc_busy = 0; /* ctlr is free */
|
||||
dqd_xfer = dqd_wval = 0;
|
||||
if (err != 0) { /* error? */
|
||||
perror ("DQ I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
cprintf ("%s simulator DQ disc I/O error: %s\n", /* then report the error to the console */
|
||||
sim_name, strerror (errno));
|
||||
|
||||
clearerr (uptr->fileref); /* clear the error */
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
return SCPE_OK;
|
||||
@@ -864,15 +887,43 @@ for (drv = 0; drv < DQ_NUMDRV; drv++) { /* loop thru drives */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Attach routine */
|
||||
/* Attach a drive unit.
|
||||
|
||||
The specified file is attached to the indicated drive unit, and the heads are
|
||||
loaded. If a new file is specified, the file is initialized to its capacity
|
||||
by writing a zero to the last byte in the file.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. The C standard says, "A binary stream need not meaningfully support fseek
|
||||
calls with a whence value of SEEK_END," so instead we determine the
|
||||
offset from the start of the file to the last byte and seek there.
|
||||
*/
|
||||
|
||||
t_stat dqc_attach (UNIT *uptr, CONST char *cptr)
|
||||
{
|
||||
t_stat r;
|
||||
t_stat result;
|
||||
t_addr offset;
|
||||
const uint8 zero = 0;
|
||||
|
||||
r = attach_unit (uptr, cptr); /* attach unit */
|
||||
if (r == SCPE_OK) dqc_load_unload (uptr, 0, NULL, NULL);/* if OK, load heads */
|
||||
return r;
|
||||
result = attach_unit (uptr, cptr); /* attach the drive */
|
||||
|
||||
if (result == SCPE_OK) { /* if the attach was successful */
|
||||
dqc_load_unload (uptr, 0, NULL, NULL); /* then load the heads */
|
||||
|
||||
if (sim_switches & SWMASK ('N')) { /* if this is a new disc image */
|
||||
offset = (t_addr) /* then determine the offset of */
|
||||
(uptr->capac * sizeof (int16) - sizeof zero); /* the last byte in a full-sized file */
|
||||
|
||||
if (sim_fseek (uptr->fileref, offset, SEEK_SET) != 0 /* seek to the last byte */
|
||||
|| fwrite (&zero, sizeof zero, 1, uptr->fileref) == 0 /* and write a zero to fill */
|
||||
|| fflush (uptr->fileref) != 0) /* the file to its capacity */
|
||||
clearerr (uptr->fileref); /* clear and ignore any errors */
|
||||
}
|
||||
}
|
||||
|
||||
return result; /* return the result of the attach */
|
||||
}
|
||||
|
||||
/* Detach routine */
|
||||
@@ -894,85 +945,227 @@ else uptr->flags = uptr->flags & ~UNIT_UNLOAD; /* indicate load */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* 7900/7901/2883/2884 bootstrap routine (HP 12992A ROM) */
|
||||
|
||||
const BOOT_ROM dq_rom = {
|
||||
0102501, /*ST LIA 1 ; get switches */
|
||||
0106501, /* LIB 1 */
|
||||
0013765, /* AND D7 ; isolate hd */
|
||||
0005750, /* BLF,CLE,SLB */
|
||||
0027741, /* JMP RD */
|
||||
0005335, /* RBR,SLB,ERB ; <13>->E, set = 2883 */
|
||||
0027717, /* JMP IS */
|
||||
0102611, /*LP OTA CC ; do 7900 status to */
|
||||
0103711, /* STC CC,C ; clear first seek */
|
||||
0102310, /* SFS DC */
|
||||
0027711, /* JMP *-1 */
|
||||
0002004, /* INA ; get next drive */
|
||||
0053765, /* CPA D7 ; all cleared? */
|
||||
0002001, /* RSS */
|
||||
0027707, /* JMP LP */
|
||||
0067761, /*IS LDB SEEKC ; get seek comnd */
|
||||
0106610, /* OTB DC ; issue cyl addr (0) */
|
||||
0103710, /* STC DC,C ; to dch */
|
||||
0106611, /* OTB CC ; seek cmd */
|
||||
0103711, /* STC CC,C ; to cch */
|
||||
0102310, /* SFS DC ; addr wd ok? */
|
||||
0027724, /* JMP *-1 ; no, wait */
|
||||
0006400, /* CLB */
|
||||
0102501, /* LIA 1 ; get switches */
|
||||
0002051, /* SEZ,SLA,RSS ; subchan = 1 or ISS */
|
||||
0047770, /* ADB BIT9 ; head 2 */
|
||||
0106610, /* OTB DC ; head/sector */
|
||||
0103710, /* STC DC,C ; to dch */
|
||||
0102311, /* SFS CC ; seek done? */
|
||||
0027734, /* JMP *-1 ; no, wait */
|
||||
0063731, /* LDA ISSRD ; get read read */
|
||||
0002341, /* SEZ,CCE,RSS ; iss disc? */
|
||||
0001100, /* ARS ; no, make 7900 read */
|
||||
0067776, /*RD LDB DMACW ; DMA control */
|
||||
0106606, /* OTB 6 */
|
||||
0067762, /* LDB ADDR1 ; memory addr */
|
||||
0077741, /* STB RD ; make non re-executable */
|
||||
0106602, /* OTB 2 */
|
||||
0102702, /* STC 2 ; flip DMA ctrl */
|
||||
0067764, /* LDB COUNT ; word count */
|
||||
0106602, /* OTB 2 */
|
||||
0002041, /* SEZ,RSS */
|
||||
0027766, /* JMP NW */
|
||||
0102611, /* OTA CC ; to cch */
|
||||
0103710, /* STC DC,C ; start dch */
|
||||
0103706, /* STC 6,C ; start DMA */
|
||||
0103711, /* STC CC,C ; start cch */
|
||||
0037773, /* ISZ SK */
|
||||
0027773, /* JMP SK */
|
||||
0030000, /*SEEKC 030000 */
|
||||
0102011, /*ADDR1 102011 */
|
||||
0102055, /*ADDR2 102055 */
|
||||
0164000, /*COUNT -6144. */
|
||||
0000007, /*D7 7 */
|
||||
0106710, /*NW CLC DC ; set 'next wd is cmd' flag */
|
||||
0001720, /* ALF,ALF ; move to head number loc */
|
||||
0001000, /*BIT9 ALS */
|
||||
0103610, /* OTA DC,C ; output cold load cmd */
|
||||
0103706, /* STC 6,C ; start DMA */
|
||||
0102310, /* SFS DC ; done? */
|
||||
0027773, /* JMP *-1 ; no, wait */
|
||||
0117763, /*XT JSB ADDR2,I ; start program */
|
||||
0120010, /*DMACW 120000+DC */
|
||||
0000000 /* -ST */
|
||||
/* 2883 disc bootstrap loaders (BMDL and 12992A).
|
||||
|
||||
The Basic Moving-Head Disc Loader (BMDL) consists of two programs. The
|
||||
program starting at address x7700 loads absolute paper tapes into memory.
|
||||
The program starting at address x7750 loads a disc-resident bootstrap from
|
||||
the 2883 disc drive into memory. The S register setting does not affect
|
||||
loader operation.
|
||||
|
||||
For a 2100/14/15/16 CPU, entering a LOAD DQC or BOOT DQC command loads the
|
||||
BMDL into memory and executes the disc portion starting at x7750. For a 1000
|
||||
CPU, the 12992A boot loader ROM is used. In either case, the bootstrap reads
|
||||
128 words from cylinder 0, head 0, sector 0 into memory starting at location
|
||||
2011 octal. Loader execution ends with the following instruction:
|
||||
|
||||
* JMP 2055,I - the disc read completed.
|
||||
|
||||
Note that the BMDL does a JMP 2055,I and the 12992A does a JSB 2055,I.
|
||||
*/
|
||||
|
||||
static const LOADER_ARRAY dq_loaders = {
|
||||
{ /* HP 21xx Basic Moving-Head Disc Loader (BMDL-2883) */
|
||||
050, /* loader starting index */
|
||||
076, /* DMA index */
|
||||
077, /* FWA index */
|
||||
{ 0002701, /* 77700: PTAPE CLA,CCE,RSS Paper Tape start */
|
||||
0063722, /* 77701: LDA 77722 */
|
||||
0002307, /* 77702: CCE,INA,SZA,RSS */
|
||||
0102077, /* 77703: HLT 77 */
|
||||
0017735, /* 77704: JSB 77735 */
|
||||
0007307, /* 77705: CMB,CCE,INB,SZB,RSS */
|
||||
0027702, /* 77706: JMP 77702 */
|
||||
0077733, /* 77707: STB 77733 */
|
||||
0017735, /* 77710: JSB 77735 */
|
||||
0017735, /* 77711: JSB 77735 */
|
||||
0074000, /* 77712: STB 0 */
|
||||
0077734, /* 77713: STB 77734 */
|
||||
0067734, /* 77714: LDB 77734 */
|
||||
0047777, /* 77715: ADB 77777 */
|
||||
0002040, /* 77716: SEZ */
|
||||
0102055, /* 77717: HLT 55 */
|
||||
0017735, /* 77720: JSB 77735 */
|
||||
0040001, /* 77721: ADA 1 */
|
||||
0177734, /* 77722: STB 77734,I */
|
||||
0037734, /* 77723: ISZ 77734 */
|
||||
0000040, /* 77724: CLE */
|
||||
0037733, /* 77725: ISZ 77733 */
|
||||
0027714, /* 77726: JMP 77714 */
|
||||
0017735, /* 77727: JSB 77735 */
|
||||
0054000, /* 77730: CPB 0 */
|
||||
0027701, /* 77731: JMP 77701 */
|
||||
0102011, /* 77732: HLT 11 */
|
||||
0000000, /* 77733: NOP */
|
||||
0000000, /* 77734: NOP */
|
||||
0000000, /* 77735: NOP */
|
||||
0006600, /* 77736: CLB,CME */
|
||||
0103710, /* 77737: STC 10,C */
|
||||
0102310, /* 77740: SFS 10 */
|
||||
0027740, /* 77741: JMP 77740 */
|
||||
0106410, /* 77742: MIB 10 */
|
||||
0002041, /* 77743: SEZ,RSS */
|
||||
0127735, /* 77744: JMP 77735,I */
|
||||
0005767, /* 77745: BLF,CLE,BLF */
|
||||
0027737, /* 77746: JMP 77737 */
|
||||
0177600, /* 77747: OCT 177600 */
|
||||
0063775, /* 77750: DISC LDA 77775 Disc start */
|
||||
0102611, /* 77751: OTA 11 */
|
||||
0103711, /* 77752: STC 11,C */
|
||||
0102311, /* 77753: SFS 11 */
|
||||
0027753, /* 77754: JMP 77753 */
|
||||
0067776, /* 77755: LDB 77776 */
|
||||
0106606, /* 77756: OTB 6 */
|
||||
0067732, /* 77757: LDB 77732 */
|
||||
0106602, /* 77760: OTB 2 */
|
||||
0102702, /* 77761: STC 2 */
|
||||
0067747, /* 77762: LDB 77747 */
|
||||
0106602, /* 77763: OTB 2 */
|
||||
0001000, /* 77764: ALS */
|
||||
0106711, /* 77765: CLC 11 */
|
||||
0102611, /* 77766: OTA 11 */
|
||||
0103710, /* 77767: STC 10,C */
|
||||
0103706, /* 77770: STC 6,C */
|
||||
0103711, /* 77771: STC 11,C */
|
||||
0102311, /* 77772: SFS 11 */
|
||||
0027772, /* 77773: JMP 77772 */
|
||||
0127717, /* 77774: JMP 77717,I */
|
||||
0020000, /* 77775: OCT 020000 */
|
||||
0120010, /* 77776: ABS 120000+DC */
|
||||
0100100 } }, /* 77777: ABS -PTAPE */
|
||||
|
||||
{ /* HP 1000 Loader ROM (12992A) */
|
||||
IBL_START, /* loader starting index */
|
||||
IBL_DMA, /* DMA index */
|
||||
IBL_FWA, /* FWA index */
|
||||
{ 0102501, /* 77700: ST LIA 1 ; get switches */
|
||||
0106501, /* 77701: LIB 1 */
|
||||
0013765, /* 77702: AND D7 ; isolate hd */
|
||||
0005750, /* 77703: BLF,CLE,SLB */
|
||||
0027741, /* 77704: JMP RD */
|
||||
0005335, /* 77705: RBR,SLB,ERB ; <13>->E, set = 2883 */
|
||||
0027717, /* 77706: JMP IS */
|
||||
0102611, /* 77707: LP OTA CC ; do 7900 status to */
|
||||
0103711, /* 77710: STC CC,C ; clear first seek */
|
||||
0102310, /* 77711: SFS DC */
|
||||
0027711, /* 77712: JMP *-1 */
|
||||
0002004, /* 77713: INA ; get next drive */
|
||||
0053765, /* 77714: CPA D7 ; all cleared? */
|
||||
0002001, /* 77715: RSS */
|
||||
0027707, /* 77716: JMP LP */
|
||||
0067761, /* 77717: IS LDB SEEKC ; get seek comnd */
|
||||
0106610, /* 77720: OTB DC ; issue cyl addr (0) */
|
||||
0103710, /* 77721: STC DC,C ; to dch */
|
||||
0106611, /* 77722: OTB CC ; seek cmd */
|
||||
0103711, /* 77723: STC CC,C ; to cch */
|
||||
0102310, /* 77724: SFS DC ; addr wd ok? */
|
||||
0027724, /* 77725: JMP *-1 ; no, wait */
|
||||
0006400, /* 77726: CLB */
|
||||
0102501, /* 77727: LIA 1 ; get switches */
|
||||
0002051, /* 77730: SEZ,SLA,RSS ; subchan = 1 or ISS */
|
||||
0047770, /* 77731: ADB BIT9 ; head 2 */
|
||||
0106610, /* 77732: OTB DC ; head/sector */
|
||||
0103710, /* 77733: STC DC,C ; to dch */
|
||||
0102311, /* 77734: SFS CC ; seek done? */
|
||||
0027734, /* 77735: JMP *-1 ; no, wait */
|
||||
0063731, /* 77736: LDA ISSRD ; get read read */
|
||||
0002341, /* 77737: SEZ,CCE,RSS ; iss disc? */
|
||||
0001100, /* 77740: ARS ; no, make 7900 read */
|
||||
0067776, /* 77741: RD LDB DMACW ; DMA control */
|
||||
0106606, /* 77742: OTB 6 */
|
||||
0067762, /* 77743: LDB ADDR1 ; memory addr */
|
||||
0077741, /* 77744: STB RD ; make non re-executable */
|
||||
0106602, /* 77745: OTB 2 */
|
||||
0102702, /* 77746: STC 2 ; flip DMA ctrl */
|
||||
0067764, /* 77747: LDB COUNT ; word count */
|
||||
0106602, /* 77750: OTB 2 */
|
||||
0002041, /* 77751: SEZ,RSS */
|
||||
0027766, /* 77752: JMP NW */
|
||||
0102611, /* 77753: OTA CC ; to cch */
|
||||
0103710, /* 77754: STC DC,C ; start dch */
|
||||
0103706, /* 77755: STC 6,C ; start DMA */
|
||||
0103711, /* 77756: STC CC,C ; start cch */
|
||||
0037773, /* 77757: ISZ SK */
|
||||
0027773, /* 77760: JMP SK */
|
||||
0030000, /* 77761: SEEKC OCT 030000 */
|
||||
0102011, /* 77762: ADDR1 OCT 102011 */
|
||||
0102055, /* 77763: ADDR2 OCT 102055 */
|
||||
0164000, /* 77764: COUNT DEC -6144. */
|
||||
0000007, /* 77765: D7 DEC 7 */
|
||||
0106710, /* 77766: NW CLC DC ; set 'next wd is cmd' flag */
|
||||
0001720, /* 77767: ALF,ALF ; move to head number loc */
|
||||
0001000, /* 77770: BIT9 ALS */
|
||||
0103610, /* 77771: OTA DC,C ; output cold load cmd */
|
||||
0103706, /* 77772: STC 6,C ; start DMA */
|
||||
0102310, /* 77773: SFS DC ; done? */
|
||||
0027773, /* 77774: JMP *-1 ; no, wait */
|
||||
0117763, /* 77775: XT JSB ADDR2,I ; start program */
|
||||
0120010, /* 77776: DMACW ABS 120000+DC */
|
||||
0170100 } } /* 77777: MAXAD ABS -ST ; max addr */
|
||||
};
|
||||
|
||||
|
||||
/* Device boot routine.
|
||||
|
||||
This routine is called directly by the BOOT DQC and LOAD DQC commands to copy
|
||||
the device bootstrap into the upper 64 words of the logical address space.
|
||||
It is also called indirectly by a BOOT CPU or LOAD CPU command when the
|
||||
specified HP 1000 loader ROM socket contains a 12992A ROM.
|
||||
|
||||
When called in response to a BOOT DQC or LOAD DQC command, the "unitno"
|
||||
parameter indicates the unit number specified in the BOOT command or is zero
|
||||
for the LOAD command, and "dptr" points at the DQC device structure. The
|
||||
bootstrap supports loading only from unit 0, and the command will be rejected
|
||||
if another unit is specified (e.g., BOOT DQC1). Otherwise, depending on the
|
||||
current CPU model, the BMDL or 12992A loader ROM will be copied into memory
|
||||
and configured for the DQD/DQC select code pair. If the CPU is a 1000, the S
|
||||
register will be set as it would be by the front-panel microcode.
|
||||
|
||||
When called for a BOOT/LOAD CPU command, the "unitno" parameter indicates the
|
||||
select code to be used for configuration, and "dptr" will be NULL. As above,
|
||||
the BMDL or 12992A loader ROM will be copied into memory and configured for
|
||||
the specified select code. The S register is assumed to be set correctly on
|
||||
entry and is not modified.
|
||||
|
||||
In either case, if the CPU is a 21xx model, the paper tape portion of the
|
||||
BMDL will be automatically configured for the select code of the paper tape
|
||||
reader.
|
||||
|
||||
For the 12992A boot loader ROM for the HP 1000, the S register is set as
|
||||
follows:
|
||||
|
||||
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| ROM # | 1 0 | select code | reserved | 0 0 0 |
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
|
||||
Bits 5-3 are nominally zero but are reserved for the target operating system.
|
||||
For example, RTE uses bit 5 to indicate whether a standard (0) or
|
||||
reconfiguration (1) boot is desired.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. In hardware, the BMDL was hand-configured for the disc and paper tape
|
||||
reader select codes when it was installed on a given system. Under
|
||||
simulation, the LOAD and BOOT commands automatically configure the BMDL
|
||||
to the current select codes of the PTR and DQ devices.
|
||||
*/
|
||||
|
||||
t_stat dqc_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
const int32 dev = dqd_dib.select_code; /* data chan select code */
|
||||
static const HP_WORD dq_preserved = 0000070u; /* S-register bits 5-3 are preserved */
|
||||
static const HP_WORD dq_standard = 0020000u; /* S-register bit 13 set for a standard boot */
|
||||
|
||||
if (unitno != 0) /* boot supported on drive unit 0 only */
|
||||
return SCPE_NOFNC; /* report "Command not allowed" if attempted */
|
||||
if (dptr == NULL) /* if we are being called for a BOOT/LOAD CPU */
|
||||
return cpu_copy_loader (dq_loaders, unitno, /* then copy the boot loader to memory */
|
||||
IBL_S_NOCLEAR, IBL_S_NOSET); /* but do not alter the S register */
|
||||
|
||||
if (ibl_copy (dq_rom, dev, IBL_OPT, /* copy the boot ROM to memory and configure */
|
||||
IBL_DQ | IBL_SET_SC (dev))) /* the S register accordingly */
|
||||
return SCPE_IERR; /* return an internal error if the copy failed */
|
||||
else
|
||||
return SCPE_OK;
|
||||
else if (unitno != 0) /* otherwise a BOOT DQC for a non-zero unit */
|
||||
return SCPE_NOFNC; /* is rejected as unsupported */
|
||||
|
||||
else /* otherwise this is a BOOT/LOAD DQC */
|
||||
return cpu_copy_loader (dq_loaders, dqd_dib.select_code, /* so copy the boot loader to memory */
|
||||
dq_preserved, dq_standard); /* and configure the S register if 1000 CPU */
|
||||
}
|
||||
|
||||
@@ -1,31 +1,37 @@
|
||||
/* hp2100_dr.c: HP 2100 12606B/12610B fixed head disk/drum simulator
|
||||
|
||||
Copyright (c) 1993-2016, Robert M. Supnik
|
||||
Copyright (c) 2017-2018, J. David Bryan
|
||||
|
||||
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:
|
||||
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.
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS 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
|
||||
Except as contained in this notice, the names of the authors 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.
|
||||
in this Software without prior written authorization from the authors.
|
||||
|
||||
DR 12606B 2770/2771 fixed head disk
|
||||
12610B 2773/2774/2775 drum
|
||||
|
||||
27-Feb-18 JDB Added the BBDL, reworked drc_boot to use cpu_copy_loader
|
||||
21-Feb-18 JDB ATTACH -N now creates a full-size disc image
|
||||
19-Jul-17 JDB Removed "dr_stopioe" variable and register
|
||||
11-Jul-17 JDB Renamed "ibl_copy" to "cpu_ibl"
|
||||
27-Feb-17 JDB ibl_copy no longer returns a status code
|
||||
10-Nov-16 JDB Modified the drc_boot routine to use the BBDL
|
||||
05-Aug-16 JDB Renamed the P register from "PC" to "PR"
|
||||
13-May-16 JDB Modified for revised SCP API function parameter types
|
||||
@@ -109,10 +115,14 @@
|
||||
- inst timing = 6 inst/word, 12288 inst/revolution
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "hp2100_defs.h"
|
||||
#include "hp2100_cpu.h"
|
||||
#include <math.h>
|
||||
|
||||
|
||||
|
||||
/* Constants */
|
||||
|
||||
#define DR_NUMWD 64 /* words/sector */
|
||||
@@ -195,7 +205,6 @@ int32 drd_ibuf = 0; /* input buffer */
|
||||
int32 drd_obuf = 0; /* output buffer */
|
||||
int32 drd_ptr = 0; /* sector pointer */
|
||||
int32 drc_pcount = 1; /* number of prot tracks */
|
||||
int32 dr_stopioe = 1; /* stop on error */
|
||||
int32 dr_time = DR_DTIME; /* time per word */
|
||||
|
||||
static int32 sz_tab[16] = {
|
||||
@@ -252,8 +261,8 @@ REG drd_reg[] = {
|
||||
};
|
||||
|
||||
MTAB drd_mod[] = {
|
||||
{ MTAB_XTD | MTAB_VDV, 1, "SC", "SC", &hp_setsc, &hp_showsc, &drd_dev },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &drd_dev },
|
||||
{ MTAB_XTD | MTAB_VDV, 2u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &dr_dib },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, ~2u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &dr_dib },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
@@ -284,7 +293,6 @@ REG drc_reg[] = {
|
||||
{ ORDATA (STA, drc_sta, 16) },
|
||||
{ FLDATA (RUN, drc_run, 0) },
|
||||
{ DRDATA (TIME, dr_time, 24), REG_NZ + PV_LEFT },
|
||||
{ FLDATA (STOP_IOE, dr_stopioe, 0) },
|
||||
{ ORDATA (SC, drc_dib.select_code, 6), REG_HRO },
|
||||
{ ORDATA (DEVNO, drc_dib.select_code, 6), REG_HRO },
|
||||
{ DRDATA (CAPAC, drc_unit.capac, 24), REG_HRO },
|
||||
@@ -308,8 +316,8 @@ MTAB drc_mod[] = {
|
||||
{ UNIT_PROT, 0, "unprotected", "UNPROTECTED", NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 0, "TRACKPROT", "TRACKPROT",
|
||||
&dr_set_prot, &dr_show_prot, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 1, "SC", "SC", &hp_setsc, &hp_showsc, &drd_dev },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &drd_dev },
|
||||
{ MTAB_XTD | MTAB_VDV, 2u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &dr_dib },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, ~2u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &dr_dib },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
@@ -522,7 +530,7 @@ uint16 *bptr = (uint16 *) uptr->filebuf;
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) {
|
||||
drc_sta = DRS_ABO;
|
||||
return IOERROR (dr_stopioe, SCPE_UNATT);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
trk = CW_GETTRK (drc_cw);
|
||||
@@ -631,15 +639,29 @@ sim_cancel (&drd_unit[TMR_INH]);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Attach routine */
|
||||
/* Attach a drive unit.
|
||||
|
||||
The specified file is attached to the indicated drive unit. If a new file is
|
||||
specified, the file is initialized to its capacity by setting the high-water
|
||||
mark to the last byte in the file.
|
||||
*/
|
||||
|
||||
t_stat drc_attach (UNIT *uptr, CONST char *cptr)
|
||||
{
|
||||
int32 sz = sz_tab[DR_GETSZ (uptr->flags)];
|
||||
t_stat result;
|
||||
const int32 sz = sz_tab [DR_GETSZ (uptr->flags)];
|
||||
|
||||
if (sz == 0) return SCPE_IERR;
|
||||
uptr->capac = sz;
|
||||
return attach_unit (uptr, cptr);
|
||||
if (sz == 0)
|
||||
return SCPE_IERR;
|
||||
else
|
||||
uptr->capac = sz;
|
||||
|
||||
result = attach_unit (uptr, cptr); /* attach the drive */
|
||||
|
||||
if (result == SCPE_OK && (sim_switches & SWMASK ('N'))) /* if the attach was successful and a new image was specified */
|
||||
uptr->hwmark = (uint32) uptr->capac; /* then set the high-water mark to the last byte */
|
||||
|
||||
return result; /* return the result of the attach */
|
||||
}
|
||||
|
||||
/* Set protected track count */
|
||||
@@ -706,126 +728,159 @@ return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Basic Binary Disc Loader.
|
||||
/* 277x fixed disc/drum bootstrap loaders (BBDL).
|
||||
|
||||
The Basic Binary Disc Loader (BBDL) contains two programs. The program
|
||||
The Basic Binary Disc Loader (BBDL) consists of two programs. The program
|
||||
starting at address x7700 loads absolute paper tapes into memory. The
|
||||
program starting at address x7760 loads a disc-resident bootstrap from the
|
||||
277x fixed-head disc/drum. Entering a BOOT DRC command loads the BBDL into
|
||||
memory and executes the disc portion starting at x7760. The bootstrap issues
|
||||
a CLC 0,C to clear the disc track and sector address registers and then sets
|
||||
up a 64-word read from track 0 sector 0 to memory locations 0-77 octal. It
|
||||
then stores a JMP * instruction in location 77, starts the read, and jumps to
|
||||
277x fixed-head disc/drum into memory. The S register setting does not
|
||||
affect loader operation.
|
||||
|
||||
Entering a LOAD DRC or BOOT DRC command loads the BBDL into memory and
|
||||
executes the disc portion starting at x7760. The bootstrap issues a CLC 0,C
|
||||
to clear the disc track and sector address registers and then sets up a
|
||||
64-word read from track 0 sector 0 to memory locations 0-77 octal. It then
|
||||
stores a JMP * instruction in location 77, starts the read, and jumps to
|
||||
location 77. The JMP * causes the CPU to loop until the last word read from
|
||||
the disc overlays location 77 which, typically, would be a JMP instruction to
|
||||
the start of the disc-resident bootstrap.
|
||||
the disc extension overlays location 77 which, typically, would be a JMP
|
||||
instruction to the start of the disc-resident bootstrap. The success or
|
||||
failure of the transfer is not checked.
|
||||
|
||||
In hardware, the BBDL was hand-configured for the disc and paper tape reader
|
||||
select codes when it was installed on a given system. Under simulation, we
|
||||
treat it as a standard HP 1000 loader, even though it is not structured that
|
||||
way, and so the ibl_copy mechanism used to load and configure it must be
|
||||
augmented to account for the differences.
|
||||
The HP 1000 does not support the 277x drives, so there is no 1000 boot loader
|
||||
ROM for these peripherals. Attempting to LOAD DRC or BOOT DRC while the CPU
|
||||
is configured as a 1000 will be rejected.
|
||||
|
||||
|
||||
Implementaion notes:
|
||||
Implementation notes:
|
||||
|
||||
1. The full BBDL is loaded into memory, even though only the disc portion
|
||||
will be used.
|
||||
1. After the BBDL is loaded into memory, the paper tape portion may be
|
||||
executed manually by setting the P register to the starting address
|
||||
(x7700).
|
||||
|
||||
2. For compatibility with the ibl_copy routine, the loader has been changed
|
||||
from the standard HP version. The device I/O instructions are modified
|
||||
to address locations 10 and 11.
|
||||
2. For compatibility with the cpu_copy_loader routine, the BBDL has been
|
||||
altered from the standard HP version. The device I/O instructions are
|
||||
modified to address select codes 10 and 11.
|
||||
|
||||
3. The "HP 20854A Timeshared BASIC/2000, Level F System Operator's Manual"
|
||||
(HP 02000-90074, November 1974) lists an IBL procedure for booting a 21MX
|
||||
(i.e., 1000 M-Series) CPU from the fixed-head disc. However, there is no
|
||||
evidence that a fixed-head disc boot loader ROM ever existed. Moreover,
|
||||
the procedure listed is suspicious, as it specifies the command channel
|
||||
select code instead of the data channel select code, so I/O instruction
|
||||
configuration would be incorrect. Also, the equivalent 2100 boot
|
||||
procedure printed adjacently gives the wrong BBDL starting address (it is
|
||||
listed correctly in the 1973 version of the manual). Actually, the 21MX
|
||||
and 2100 procedures appear to be verbatim copies of the moving-head disc
|
||||
boot procedures listed two pages earlier. Consequently, it would appear
|
||||
that 21MX-based 2000 F TSB systems with fixed-head drives must boot from
|
||||
paper tape.
|
||||
*/
|
||||
|
||||
static const BOOT_ROM dr_rom = {
|
||||
0107700, /* ST2 CLC 0,C START OF PAPER TAPE LOADER */
|
||||
0002401, /* CLA,RSS */
|
||||
0063726, /* CONT2 LDA CM21 */
|
||||
0006700, /* CLB,CCE */
|
||||
0017742, /* JSB READ2 */
|
||||
0007306, /* LEDR2 CMB,CCE,INB,SZB */
|
||||
0027713, /* JMP RECL2 */
|
||||
0002006, /* EOTC2 INA,SZA */
|
||||
0027703, /* JMP CONT2+1 */
|
||||
0102077, /* HLT 77B */
|
||||
0027700, /* JMP ST2 */
|
||||
0077754, /* RECL2 STB CNT2 */
|
||||
0017742, /* JSB READ2 */
|
||||
0017742, /* JSB READ2 */
|
||||
0074000, /* STB A */
|
||||
0077757, /* STB ADR11 */
|
||||
0067757, /* SUCID LDB ADR11 */
|
||||
0047755, /* ADB MAXAD */
|
||||
0002040, /* SEZ */
|
||||
0027740, /* JMP RESCU */
|
||||
0017742, /* LOAD2 JSB READ2 */
|
||||
0040001, /* ADA B */
|
||||
0177757, /* CM21 STB ADR11,I */
|
||||
0037757, /* ISZ ADR11 */
|
||||
0000040, /* CLE */
|
||||
0037754, /* ISZ CNT2 */
|
||||
0027720, /* JMP SUCID */
|
||||
0017742, /* JSB READ2 */
|
||||
0054000, /* CPB A */
|
||||
0027702, /* JMP CONT2 */
|
||||
0102011, /* HLT 11B */
|
||||
0027700, /* JMP ST2 */
|
||||
0102055, /* RESCU HLT 55B */
|
||||
0027700, /* JMP ST2 */
|
||||
0000000, /* READ2 NOP */
|
||||
0006600, /* CLB,CME */
|
||||
0103710, /* RED2 STC PR,C */
|
||||
0102310, /* SFS PR */
|
||||
0027745, /* JMP *-1 */
|
||||
0107410, /* MIB PR,C */
|
||||
0002041, /* SEZ,RSS */
|
||||
0127742, /* JMP READ2,I */
|
||||
0005767, /* BLF,CLE,BLF */
|
||||
0027744, /* JMP RED2 */
|
||||
0000000, /* CNT2 NOP */
|
||||
0000000, /* MAXAD NOP */
|
||||
0020000, /* CWORD ABS 20000B+DC */
|
||||
0000000, /* ADR11 NOP */
|
||||
static const LOADER_ARRAY dr_loaders = {
|
||||
{ /* HP 21xx Basic Binary Disc Loader (BBDL) */
|
||||
060, /* loader starting index */
|
||||
056, /* DMA index */
|
||||
055, /* FWA index */
|
||||
{ 0107700, /* 77700: ST2 CLC 0,C START OF PAPER TAPE LOADER */
|
||||
0002401, /* 77701: CLA,RSS */
|
||||
0063726, /* 77702: CONT2 LDA CM21 */
|
||||
0006700, /* 77703: CLB,CCE */
|
||||
0017742, /* 77704: JSB READ2 */
|
||||
0007306, /* 77705: LEDR2 CMB,CCE,INB,SZB */
|
||||
0027713, /* 77706: JMP RECL2 */
|
||||
0002006, /* 77707: EOTC2 INA,SZA */
|
||||
0027703, /* 77710: JMP CONT2+1 */
|
||||
0102077, /* 77711: HLT 77B */
|
||||
0027700, /* 77712: JMP ST2 */
|
||||
0077754, /* 77713: RECL2 STB CNT2 */
|
||||
0017742, /* 77714: JSB READ2 */
|
||||
0017742, /* 77715: JSB READ2 */
|
||||
0074000, /* 77716: STB A */
|
||||
0077757, /* 77717: STB ADR11 */
|
||||
0067757, /* 77720: SUCID LDB ADR11 */
|
||||
0047755, /* 77721: ADB MAXAD */
|
||||
0002040, /* 77722: SEZ */
|
||||
0027740, /* 77723: JMP RESCU */
|
||||
0017742, /* 77724: LOAD2 JSB READ2 */
|
||||
0040001, /* 77725: ADA B */
|
||||
0177757, /* 77726: CM21 STB ADR11,I */
|
||||
0037757, /* 77727: ISZ ADR11 */
|
||||
0000040, /* 77730: CLE */
|
||||
0037754, /* 77731: ISZ CNT2 */
|
||||
0027720, /* 77732: JMP SUCID */
|
||||
0017742, /* 77733: JSB READ2 */
|
||||
0054000, /* 77734: CPB A */
|
||||
0027702, /* 77735: JMP CONT2 */
|
||||
0102011, /* 77736: HLT 11B */
|
||||
0027700, /* 77737: JMP ST2 */
|
||||
0102055, /* 77740: RESCU HLT 55B */
|
||||
0027700, /* 77741: JMP ST2 */
|
||||
0000000, /* 77742: READ2 NOP */
|
||||
0006600, /* 77743: CLB,CME */
|
||||
0103710, /* 77744: RED2 STC PR,C */
|
||||
0102310, /* 77745: SFS PR */
|
||||
0027745, /* 77746: JMP *-1 */
|
||||
0107410, /* 77747: MIB PR,C */
|
||||
0002041, /* 77750: SEZ,RSS */
|
||||
0127742, /* 77751: JMP READ2,I */
|
||||
0005767, /* 77752: BLF,CLE,BLF */
|
||||
0027744, /* 77753: JMP RED2 */
|
||||
0000000, /* 77754: CNT2 NOP */
|
||||
0000000, /* 77755: MAXAD NOP */
|
||||
0020010, /* 77756: CWORD ABS 20000B+DC */
|
||||
0000000, /* 77757: ADR11 NOP */
|
||||
0107700, /* 77760: DLDR CLC 0,C START OF FIXED DISC LOADER */
|
||||
0063756, /* 77761: LDA CWORD */
|
||||
0102606, /* 77762: OTA 6 */
|
||||
0002700, /* 77763: CLA,CCE */
|
||||
0102611, /* 77764: OTA CC */
|
||||
0001500, /* 77765: ERA */
|
||||
0102602, /* 77766: OTA 2 */
|
||||
0063777, /* 77767: LDA WRDCT */
|
||||
0102702, /* 77770: STC 2 */
|
||||
0102602, /* 77771: OTA 2 */
|
||||
0103706, /* 77772: STC 6,C */
|
||||
0102710, /* 77773: STC DC */
|
||||
0067776, /* 77774: LDB JMP77 */
|
||||
0074077, /* 77775: STB 77B */
|
||||
0024077, /* 77776: JMP77 JMP 77B */
|
||||
0177700 } }, /* 77777: WRDCT OCT -100 */
|
||||
|
||||
0107700, /* DLDR CLC 0,C START OF FIXED DISC LOADER */
|
||||
0063756, /* LDA CWORD */
|
||||
0102606, /* OTA 6 */
|
||||
0002700, /* CLA,CCE */
|
||||
0102611, /* OTA CC */
|
||||
0001500, /* ERA */
|
||||
0102602, /* OTA 2 */
|
||||
0063777, /* LDA WRDCT */
|
||||
0102702, /* STC 2 */
|
||||
0102602, /* OTA 2 */
|
||||
0103706, /* STC 6,C */
|
||||
0102710, /* STC DC */
|
||||
0067776, /* LDB JMP77 */
|
||||
0074077, /* STB 77B */
|
||||
0024077, /* JMP77 JMP 77B */
|
||||
0177700 /* WRDCT OCT -100 */
|
||||
{ /* HP 1000 Loader ROM does not exist */
|
||||
IBL_NA, /* loader starting index */
|
||||
IBL_NA, /* DMA index */
|
||||
IBL_NA, /* FWA index */
|
||||
{ 0 } }
|
||||
};
|
||||
|
||||
#define BBDL_MAX_ADDR 0000055 /* ROM index of the maximum address word */
|
||||
#define BBDL_DMA_CNTL 0000056 /* ROM index of the DMA control word */
|
||||
#define BBDL_DISC_START 0000060 /* ROM index of the disc loader */
|
||||
|
||||
/* Device boot routine.
|
||||
|
||||
This routine is called by the LOAD DRC and BOOT DRC commands to copy the
|
||||
device bootstrap into the upper 64 words of the logical address space. On
|
||||
entry, the "unitno" parameter is checked to ensure that it is 0, as the
|
||||
bootstrap only loads from unit 0. Then the BBDL is loaded into memory, the
|
||||
disc portion is configured for the DRD/DRC select code pair, and the paper
|
||||
tape portion is configured for the select code of the paper tape reader.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. The fixed-head disc/drum device is not supported on the HP 1000, so this
|
||||
routine cannot be called by a BOOT CPU or LOAD CPU command.
|
||||
|
||||
2. In hardware, the BBDL was hand-configured for the disc and paper tape
|
||||
reader select codes when it was installed on a given system. Under
|
||||
simulation, the LOAD and BOOT commands automatically configure the BBDL
|
||||
to the current select codes of the PTR and DR devices.
|
||||
*/
|
||||
|
||||
t_stat drc_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
const int32 dev = drd_dib.select_code; /* data chan select code */
|
||||
if (unitno != 0) /* a BOOT DRC for a non-zero unit */
|
||||
return SCPE_NOFNC; /* is rejected as unsupported */
|
||||
|
||||
if (unitno != 0) /* boot supported on drive unit 0 only */
|
||||
return SCPE_NOFNC; /* report "Command not allowed" if attempted */
|
||||
|
||||
if (ibl_copy (dr_rom, dev, IBL_S_NOCLR, IBL_S_NOSET)) /* copy the boot ROM to memory and configure */
|
||||
return SCPE_IERR; /* return an internal error if the copy failed */
|
||||
|
||||
WritePW (PR + BBDL_MAX_ADDR, ReadPW (PR + IBL_END)); /* move the maximum address word */
|
||||
WritePW (PR + BBDL_DMA_CNTL, dr_rom [BBDL_DMA_CNTL] + dev); /* set up the DMA control word */
|
||||
|
||||
WritePW (PR + IBL_DPC, dr_rom [IBL_DPC]); /* restore the overwritten word */
|
||||
WritePW (PR + IBL_END, dr_rom [IBL_END]); /* restore the overwritten word */
|
||||
|
||||
PR = PR + BBDL_DISC_START; /* select the starting address */
|
||||
|
||||
return SCPE_OK;
|
||||
else /* otherwise this is a BOOT/LOAD DRC */
|
||||
return cpu_copy_loader (dr_loaders, drd_dib.select_code, /* so copy the boot loader to memory */
|
||||
IBL_S_NOCLEAR, IBL_S_NOSET); /* and preserve the S register */
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* hp2100_ds.c: HP 13037D/13175D disc controller/interface simulator
|
||||
|
||||
Copyright (c) 2004-2012, Robert M. Supnik
|
||||
Copyright (c) 2012-2016 J. David Bryan
|
||||
Copyright (c) 2012-2018 J. David Bryan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -26,6 +26,14 @@
|
||||
|
||||
DS 13037D/13175D disc controller/interface
|
||||
|
||||
07-May-18 JDB Removed "dl_clear_controller" status return
|
||||
27-Feb-18 JDB Added the BMDL
|
||||
21-Feb-18 JDB ATTACH -N now creates a full-size disc image
|
||||
11-Jul-17 JDB Renamed "ibl_copy" to "cpu_ibl"
|
||||
15-Mar-17 JDB Trace flags are now global
|
||||
Changed DEBUG_PRI calls to tprintfs
|
||||
10-Mar-17 JDB Added IOBUS to the debug table
|
||||
09-Mar-17 JDB Deprecated LOCKED/WRITEENABLED for PROTECT/UNPROTECT
|
||||
13-May-16 JDB Modified for revised SCP API function parameter types
|
||||
04-Mar-16 JDB Name changed to "hp2100_disclib" until HP 3000 integration
|
||||
30-Dec-14 JDB Added S-register parameters to ibl_copy
|
||||
@@ -122,6 +130,7 @@
|
||||
|
||||
|
||||
#include "hp2100_defs.h"
|
||||
#include "hp2100_cpu.h"
|
||||
#include "hp2100_disclib.h"
|
||||
|
||||
|
||||
@@ -142,16 +151,6 @@
|
||||
#define PRESET_ENABLE TRUE /* Preset Jumper (W4) is enabled */
|
||||
|
||||
|
||||
/* Debug flags */
|
||||
|
||||
#define DEB_CPU (1 << 0) /* words received from and sent to the CPU */
|
||||
#define DEB_CMDS (1 << 1) /* interface commands received from the CPU */
|
||||
#define DEB_BUF (1 << 2) /* data read from and written to the card FIFO */
|
||||
#define DEB_RWSC (1 << 3) /* device read/write/status/control commands */
|
||||
#define DEB_SERV (1 << 4) /* unit service scheduling calls */
|
||||
|
||||
|
||||
|
||||
/* Per-card state variables */
|
||||
|
||||
typedef struct {
|
||||
@@ -305,17 +304,23 @@ static REG ds_reg [] = {
|
||||
};
|
||||
|
||||
static MTAB ds_mod [] = {
|
||||
/* mask match pstring mstring valid disp desc */
|
||||
{ UNIT_UNLOAD, UNIT_UNLOAD, "heads unloaded", "UNLOADED", &ds_load_unload, NULL, NULL },
|
||||
{ UNIT_UNLOAD, 0, "heads loaded", "LOADED", &ds_load_unload, NULL, NULL },
|
||||
/* Mask Value Match Value Print String Match String Validation Display Descriptor */
|
||||
/* ------------ ------------ ----------------- --------------- ---------------- ------- ---------- */
|
||||
{ UNIT_UNLOAD, UNIT_UNLOAD, "heads unloaded", "UNLOADED", &ds_load_unload, NULL, NULL },
|
||||
{ UNIT_UNLOAD, 0, "heads loaded", "LOADED", &ds_load_unload, NULL, NULL },
|
||||
|
||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL, NULL, NULL },
|
||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL, NULL, NULL },
|
||||
{ UNIT_WLK, UNIT_WLK, "protected", "PROTECT", NULL, NULL, NULL },
|
||||
{ UNIT_WLK, 0, "unprotected", "UNPROTECT", NULL, NULL, NULL },
|
||||
|
||||
{ UNIT_FMT, UNIT_FMT, "format enabled", "FORMAT", NULL, NULL, NULL },
|
||||
{ UNIT_FMT, 0, "format disabled", "NOFORMAT", NULL, NULL, NULL },
|
||||
{ UNIT_WLK, UNIT_WLK, NULL, "LOCKED", NULL, NULL, NULL },
|
||||
{ UNIT_WLK, 0, NULL, "WRITEENABLED", NULL, NULL, NULL },
|
||||
|
||||
/* mask match pstring mstring valid disp desc */
|
||||
{ UNIT_FMT, UNIT_FMT, "format enabled", "FORMAT", NULL, NULL, NULL },
|
||||
{ UNIT_FMT, 0, "format disabled", "NOFORMAT", NULL, NULL, NULL },
|
||||
|
||||
/* Print Match */
|
||||
/* Mask Value Match Value String String Validation Disp Desc */
|
||||
/* --------------------------------- --------------------- ---------- ---------- ------------- ---- ---- */
|
||||
{ UNIT_AUTO | UNIT_ATT, UNIT_AUTO, "autosize", "AUTOSIZE", &dl_set_model, NULL, NULL },
|
||||
{ UNIT_AUTO | UNIT_ATT | UNIT_MODEL, MODEL_7905, "7905", "7905", &dl_set_model, NULL, NULL },
|
||||
{ UNIT_AUTO | UNIT_ATT | UNIT_MODEL, MODEL_7906, "7906", "7906", &dl_set_model, NULL, NULL },
|
||||
@@ -326,18 +331,21 @@ static MTAB ds_mod [] = {
|
||||
{ UNIT_ATT | UNIT_MODEL, UNIT_ATT | MODEL_7920, "7920", NULL, NULL, NULL, NULL },
|
||||
{ UNIT_ATT | UNIT_MODEL, UNIT_ATT | MODEL_7925, "7925", NULL, NULL, NULL, NULL },
|
||||
|
||||
{ MTAB_XTD | MTAB_VDV, 0, "SC", "SC", &hp_setsc, &hp_showsc, &ds_dev },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &ds_dev },
|
||||
/* Entry Flags Value Print String Match String Validation Display Descriptor */
|
||||
/* ------------------- ----- ------------ ------------ ------------ ------------- ---------------- */
|
||||
{ MTAB_XDV, 1u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &ds_dib },
|
||||
{ MTAB_XDV | MTAB_NMO, ~1u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &ds_dib },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static DEBTAB ds_deb [] = {
|
||||
{ "CPU", DEB_CPU },
|
||||
{ "CMDS", DEB_CMDS },
|
||||
{ "BUF", DEB_BUF },
|
||||
{ "RWSC", DEB_RWSC },
|
||||
{ "SERV", DEB_SERV },
|
||||
{ NULL, 0 }
|
||||
{ "RWSC", DEB_RWSC },
|
||||
{ "CMDS", DEB_CMDS },
|
||||
{ "CPU", DEB_CPU },
|
||||
{ "BUF", DEB_BUF },
|
||||
{ "SERV", DEB_SERV },
|
||||
{ "IOBUS", TRACE_IOBUS },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
DEVICE ds_dev = {
|
||||
@@ -431,7 +439,6 @@ static const char * const output_state [] = { "Data", "Command" };
|
||||
const char * const hold_or_clear = (signal_set & ioCLF ? ",C" : "");
|
||||
|
||||
uint16 data;
|
||||
t_stat status;
|
||||
IOSIGNAL signal;
|
||||
IOCYCLE working_set = IOADDSIR (signal_set); /* add ioSIR if needed */
|
||||
t_bool command_issued = FALSE;
|
||||
@@ -446,8 +453,7 @@ while (working_set) {
|
||||
ds.flag = CLEAR; /* clear the flag */
|
||||
ds.flagbuf = CLEAR; /* and flag buffer */
|
||||
|
||||
if (DEBUG_PRI (ds_dev, DEB_CMDS))
|
||||
fputs (">>DS cmds: [CLF] Flag cleared\n", sim_deb);
|
||||
tprintf (ds_dev, DEB_CMDS, "[CLF] Flag cleared\n");
|
||||
break;
|
||||
|
||||
|
||||
@@ -456,8 +462,7 @@ while (working_set) {
|
||||
ds.flag = SET; /* set the flag */
|
||||
ds.flagbuf = SET; /* and flag buffer */
|
||||
|
||||
if (DEBUG_PRI (ds_dev, DEB_CMDS))
|
||||
fputs (">>DS cmds: [STF] Flag set\n", sim_deb);
|
||||
tprintf (ds_dev, DEB_CMDS, "[STF] Flag set\n");
|
||||
break;
|
||||
|
||||
|
||||
@@ -475,12 +480,11 @@ while (working_set) {
|
||||
data = fifo_unload (); /* unload the next word from the FIFO */
|
||||
stat_data = IORETURN (SCPE_OK, data); /* merge in the return status */
|
||||
|
||||
if (DEBUG_PRI (ds_dev, DEB_CPU))
|
||||
fprintf (sim_deb, ">>DS cpu: [LIx%s] Data = %06o\n", hold_or_clear, data);
|
||||
tprintf (ds_dev, DEB_CPU, "[LIx%s] Data = %06o\n", hold_or_clear, data);
|
||||
|
||||
if (FIFO_EMPTY) { /* is the FIFO now empty? */
|
||||
if (ds.srq == SET && DEBUG_PRI (ds_dev, DEB_CMDS))
|
||||
fprintf (sim_deb, ">>DS cmds: [LIx%s] SRQ cleared\n", hold_or_clear);
|
||||
if (ds.srq == SET)
|
||||
tprintf (ds_dev, DEB_CMDS, "[LIx%s] SRQ cleared\n", hold_or_clear);
|
||||
|
||||
ds.srq = CLEAR; /* clear SRQ */
|
||||
|
||||
@@ -495,9 +499,8 @@ while (working_set) {
|
||||
case ioIOO: /* I/O data output */
|
||||
data = IODATA (stat_data); /* mask to just the data word */
|
||||
|
||||
if (DEBUG_PRI (ds_dev, DEB_CPU))
|
||||
fprintf (sim_deb, ">>DS cpu: [OTx%s] %s = %06o\n",
|
||||
hold_or_clear, output_state [ds.cmfol], data);
|
||||
tprintf (ds_dev, DEB_CPU, "[OTx%s] %s = %06o\n",
|
||||
hold_or_clear, output_state [ds.cmfol], data);
|
||||
|
||||
fifo_load (data); /* load the word into the FIFO */
|
||||
|
||||
@@ -514,8 +517,8 @@ while (working_set) {
|
||||
}
|
||||
|
||||
if (FIFO_STOP) { /* is the FIFO now full enough? */
|
||||
if (ds.srq == SET && DEBUG_PRI (ds_dev, DEB_CMDS))
|
||||
fprintf (sim_deb, ">>DS cmds: [OTx%s] SRQ cleared\n", hold_or_clear);
|
||||
if (ds.srq == SET)
|
||||
tprintf (ds_dev, DEB_CMDS, "[OTx%s] SRQ cleared\n", hold_or_clear);
|
||||
|
||||
ds.srq = CLEAR; /* clear SRQ to stop filling */
|
||||
}
|
||||
@@ -528,14 +531,12 @@ while (working_set) {
|
||||
ds.flagbuf = SET; /* and flag buffer */
|
||||
ds.cmrdy = CLEAR; /* clear the command ready flip-flop */
|
||||
|
||||
if (DEBUG_PRI (ds_dev, DEB_CMDS))
|
||||
fputs (">>DS cmds: [POPIO] Flag set\n", sim_deb);
|
||||
tprintf (ds_dev, DEB_CMDS, "[POPIO] Flag set\n");
|
||||
break;
|
||||
|
||||
|
||||
case ioCRS: /* control reset */
|
||||
if (DEBUG_PRI (ds_dev, DEB_CMDS))
|
||||
fputs (">>DS cmds: [CRS] Master reset\n", sim_deb);
|
||||
tprintf (ds_dev, DEB_CMDS, "[CRS] Master reset\n");
|
||||
|
||||
ds.control = CLEAR; /* clear the control */
|
||||
ds.cmfol = CLEAR; /* and command follows flip-flops */
|
||||
@@ -543,17 +544,14 @@ while (working_set) {
|
||||
if (PRESET_ENABLE) { /* is preset enabled for this interface? */
|
||||
fifo_clear (); /* clear the FIFO */
|
||||
|
||||
status = dl_clear_controller (&mac_cntlr, /* do a hard clear of the controller */
|
||||
ds_unit, hard_clear);
|
||||
|
||||
stat_data = IORETURN (status, 0); /* return the status from the controller */
|
||||
dl_clear_controller (&mac_cntlr, ds_unit, /* do a hard clear of the controller */
|
||||
hard_clear);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case ioCLC: /* clear control flip-flop */
|
||||
if (DEBUG_PRI (ds_dev, DEB_CMDS))
|
||||
fprintf (sim_deb, ">>DS cmds: [CLC%s] Control cleared\n", hold_or_clear);
|
||||
tprintf (ds_dev, DEB_CMDS, "[CLC%s] Control cleared\n", hold_or_clear);
|
||||
|
||||
ds.control = CLEAR; /* clear the control */
|
||||
ds.edt = CLEAR; /* and EDT flip-flops */
|
||||
@@ -569,16 +567,14 @@ while (working_set) {
|
||||
|
||||
interrupt_enabled = TRUE; /* check for drive attention */
|
||||
|
||||
if (DEBUG_PRI (ds_dev, DEB_CMDS))
|
||||
fprintf (sim_deb, ">>DS cmds: [STC%s] Control set\n", hold_or_clear);
|
||||
tprintf (ds_dev, DEB_CMDS, "[STC%s] Control set\n", hold_or_clear);
|
||||
break;
|
||||
|
||||
|
||||
case ioEDT: /* end data transfer */
|
||||
ds.edt = SET; /* set the EDT flip-flop */
|
||||
|
||||
if (DEBUG_PRI (ds_dev, DEB_CPU))
|
||||
fputs (">>DS cpu: [EDT] DCPC transfer ended\n", sim_deb);
|
||||
tprintf (ds_dev, DEB_CPU, "[EDT] DCPC transfer ended\n");
|
||||
break;
|
||||
|
||||
|
||||
@@ -698,10 +694,8 @@ return stat_data;
|
||||
|
||||
t_stat ds_service_drive (UNIT *uptr)
|
||||
{
|
||||
static const char completion_message [] = ">>DS rwsc: Unit %d %s command completed\n";
|
||||
t_stat result;
|
||||
t_bool seek_completion;
|
||||
int32 unit;
|
||||
FLIP_FLOP entry_srq = ds.srq; /* get the SRQ state on entry */
|
||||
CNTLR_PHASE entry_phase = (CNTLR_PHASE) uptr->PHASE; /* get the operation phase on entry */
|
||||
uint32 entry_status = uptr->STAT; /* get the drive status on entry */
|
||||
@@ -777,9 +771,8 @@ if ((CNTLR_PHASE) uptr->PHASE == data_phase) /* is the drive in the d
|
||||
} /* end of data phase operation dispatch */
|
||||
|
||||
|
||||
if (DEBUG_PRI (ds_dev, DEB_CMDS) && entry_srq != ds.srq)
|
||||
fprintf (sim_deb, ">>DS cmds: SRQ %s\n", ds.srq == SET ? "set" : "cleared");
|
||||
|
||||
if (entry_srq != ds.srq)
|
||||
tprintf (ds_dev, DEB_CMDS, "SRQ %s\n", ds.srq == SET ? "set" : "cleared");
|
||||
|
||||
if (uptr->wait) /* was service requested? */
|
||||
activate_unit (uptr); /* schedule the next event */
|
||||
@@ -795,22 +788,18 @@ if (mac_cntlr.state != cntlr_busy) { /* is the command co
|
||||
}
|
||||
|
||||
|
||||
if (DEBUG_PRI (ds_dev, DEB_RWSC)) {
|
||||
unit = uptr - ds_unit; /* get the unit number */
|
||||
if (result == SCPE_IERR) /* did an internal error occur? */
|
||||
tprintf (ds_dev, DEB_RWSC, "Unit %d %s command %s phase service not handled\n",
|
||||
uptr - ds_unit, dl_opcode_name (MAC, (CNTLR_OPCODE) uptr->OP),
|
||||
dl_phase_name ((CNTLR_PHASE) uptr->PHASE));
|
||||
|
||||
if (result == SCPE_IERR) /* did an internal error occur? */
|
||||
fprintf (sim_deb, ">>DS rwsc: Unit %d %s command %s phase service not handled\n",
|
||||
unit, dl_opcode_name (MAC, (CNTLR_OPCODE) uptr->OP),
|
||||
dl_phase_name ((CNTLR_PHASE) uptr->PHASE));
|
||||
else if (seek_completion) /* if a seek has completed */
|
||||
tprintf (ds_dev, DEB_RWSC, "Unit %d %s command completed\n", /* report the unit command */
|
||||
uptr - ds_unit, dl_opcode_name (MAC, (CNTLR_OPCODE) uptr->OP));
|
||||
|
||||
else if (seek_completion) /* if a seek has completed */
|
||||
fprintf (sim_deb, completion_message, /* report the unit command */
|
||||
unit, dl_opcode_name (MAC, (CNTLR_OPCODE) uptr->OP));
|
||||
|
||||
else if (mac_cntlr.state == cntlr_wait) /* if the controller has stopped */
|
||||
fprintf (sim_deb, completion_message, /* report the controller command */
|
||||
unit, dl_opcode_name (MAC, mac_cntlr.opcode));
|
||||
}
|
||||
else if (mac_cntlr.state == cntlr_wait) /* if the controller has stopped */
|
||||
tprintf (ds_dev, DEB_RWSC, "Unit %d %s command completed\n", /* report the controller command */
|
||||
uptr - ds_unit, dl_opcode_name (MAC, mac_cntlr.opcode));
|
||||
|
||||
return result; /* return the result of the service */
|
||||
}
|
||||
@@ -932,8 +921,8 @@ switch ((CNTLR_PHASE) uptr->PHASE) { /* dispatch the current
|
||||
} /* end of phase dispatch */
|
||||
|
||||
|
||||
if (result == SCPE_IERR && DEBUG_PRI (ds_dev, DEB_RWSC)) /* did an internal error occur? */
|
||||
fprintf (sim_deb, ">>DS rwsc: Controller %s command %s phase service not handled\n",
|
||||
if (result == SCPE_IERR) /* did an internal error occur? */
|
||||
tprintf (ds_dev, DEB_RWSC, "Controller %s command %s phase service not handled\n",
|
||||
dl_opcode_name (MAC, opcode), dl_phase_name ((CNTLR_PHASE) uptr->PHASE));
|
||||
|
||||
|
||||
@@ -941,9 +930,8 @@ if (mac_cntlr.state != cntlr_busy) { /* has the controller st
|
||||
poll_interface (); /* poll the interface for the next command */
|
||||
poll_drives (); /* poll the drives for Attention status */
|
||||
|
||||
if (DEBUG_PRI (ds_dev, DEB_RWSC))
|
||||
fprintf (sim_deb, ">>DS rwsc: Controller %s command completed\n",
|
||||
dl_opcode_name (MAC, opcode));
|
||||
tprintf (ds_dev, DEB_RWSC, "Controller %s command completed\n",
|
||||
dl_opcode_name (MAC, opcode));
|
||||
}
|
||||
|
||||
return result; /* return the result of the service */
|
||||
@@ -1027,23 +1015,43 @@ return SCPE_OK;
|
||||
Attention bits in the drive status, so we poll the drives to ensure that the
|
||||
CPU is notified that the drive is now online.
|
||||
|
||||
If a new file is specified, the file is initialized to its capacity by
|
||||
writing a zero to the last byte in the file.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. If we are called during a RESTORE command, the drive status will not be
|
||||
changed, so polling the drives will have no effect.
|
||||
|
||||
2. The C standard says, "A binary stream need not meaningfully support fseek
|
||||
calls with a whence value of SEEK_END," so instead we determine the
|
||||
offset from the start of the file to the last byte and seek there.
|
||||
*/
|
||||
|
||||
t_stat ds_attach (UNIT *uptr, CONST char *cptr)
|
||||
{
|
||||
t_stat result;
|
||||
t_stat result;
|
||||
t_addr offset;
|
||||
const uint8 zero = 0;
|
||||
|
||||
result = dl_attach (&mac_cntlr, uptr, cptr); /* attach the drive */
|
||||
|
||||
if (result == SCPE_OK) /* was the attach successful? */
|
||||
poll_drives (); /* poll the drives to notify the CPU */
|
||||
if (result == SCPE_OK) { /* if the attach was successful */
|
||||
poll_drives (); /* then poll the drives to notify the CPU */
|
||||
|
||||
return result;
|
||||
if (sim_switches & SWMASK ('N')) { /* if this is a new disc image */
|
||||
offset = (t_addr) /* then determine the offset of */
|
||||
(uptr->capac * sizeof (int16) - sizeof zero); /* the last byte in a full-sized file */
|
||||
|
||||
if (sim_fseek (uptr->fileref, offset, SEEK_SET) != 0 /* seek to the last byte */
|
||||
|| fwrite (&zero, sizeof zero, 1, uptr->fileref) == 0 /* and write a zero to fill */
|
||||
|| fflush (uptr->fileref) != 0) /* the file to its capacity */
|
||||
clearerr (uptr->fileref); /* clear and ignore any errors */
|
||||
}
|
||||
}
|
||||
|
||||
return result; /* return the result of the attach */
|
||||
}
|
||||
|
||||
|
||||
@@ -1068,116 +1076,259 @@ return result;
|
||||
}
|
||||
|
||||
|
||||
/* Boot a MAC disc drive.
|
||||
/* MAC disc bootstrap loaders (BMDL and 12992B).
|
||||
|
||||
The MAC disc bootstrap program is loaded from the HP 12992B Boot Loader ROM
|
||||
into memory, the I/O instructions are configured for the interface card's
|
||||
select code, and the program is run to boot from the specified unit. The
|
||||
loader supports booting from cylinder 0 of drive unit 0 only. Before
|
||||
execution, the S register is automatically set as follows:
|
||||
The Basic Moving-Head Disc Loader (BMDL) consists of two programs. The
|
||||
program starting at address x7700 loads absolute paper tapes into memory.
|
||||
The program starting at address x7750 loads a disc-resident bootstrap from
|
||||
the MAC disc drive into memory. The S register specifies the head to use.
|
||||
|
||||
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
------ ------ ---------------------- --------- ---------
|
||||
ROM # 0 1 select code reserved head
|
||||
For a 2100/14/15/16 CPU, entering a LOAD DS or BOOT DS command loads the BMDL
|
||||
into memory and executes the disc portion starting at x7750. The bootstrap
|
||||
reads 2047 words from cylinder 0 sector 0 of the specified head into memory
|
||||
starting at location 2011 octal. Loader execution ends with one of the
|
||||
following instructions:
|
||||
|
||||
The boot routine sets bits 15-6 of the S register to appropriate values.
|
||||
Bits 5-3 and 1-0 retain their original values, so S should be set before
|
||||
booting. These bits are typically set to 0, although bit 5 is set for an RTE
|
||||
reconfiguration boot, and bits 1-0 may be set if booting from a head other
|
||||
than 0 is desired.
|
||||
* HLT 11B - the disc read failed.
|
||||
* JSB 2055,I - the disc read completed.
|
||||
|
||||
The HP 1000 uses the 12992B boot loader ROM to bootstrap the disc. The head
|
||||
number is obtained from bits 2-0 of the existing S-register value when the
|
||||
loader is executed. Bits 5-3 of the existing S-register value are also
|
||||
retained and are available to the boot extension program. The loader reads
|
||||
6144 words from cylinder 0 sector 0 of the specified head into memory
|
||||
starting at location 2011 octal. Loader execution ends with one of the
|
||||
following instructions:
|
||||
|
||||
* HLT 30 - the drive is not ready..
|
||||
* JSB 2055,I - the disc read succeeded.
|
||||
|
||||
The loader automatically retries the operations for all disc errors other
|
||||
than a drive fault.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. The Loader ROMs manual indicates that bits 2-0 select the head to use,
|
||||
implying that heads 0-7 are valid. However, Table 5 has entries only for
|
||||
heads 0-3, and the boot loader code will malfunction if heads 4-7 are
|
||||
specified. The code masks the head number to three bits but forms the
|
||||
Cold Load Read command by shifting the head number six bits to the left.
|
||||
As the head field in the command is only two bits wide, specifying heads
|
||||
4-7 will result in bit 2 being shifted into the opcode field, resulting
|
||||
in a Recalibrate command.
|
||||
1. After the BMDL has been loaded into memory, the paper tape portion may be
|
||||
executed manually by setting the P register to the starting address
|
||||
(x7700).
|
||||
|
||||
2. For compatibility with the "cpu_copy_loader" routine, the BMDL device I/O
|
||||
instructions address select codes 10 and 11.
|
||||
*/
|
||||
|
||||
static const LOADER_ARRAY ds_loaders = {
|
||||
{ /* HP 21xx Basic Moving-Head Disc Loader (BMDL-7905) */
|
||||
050, /* loader starting index */
|
||||
076, /* DMA index */
|
||||
034, /* FWA index */
|
||||
{ 0002401, /* 77700: PTAPE CLA,RSS Paper Tape start */
|
||||
0063722, /* 77701: LDA 77722 */
|
||||
0107700, /* 77702: CLC 0,C */
|
||||
0002307, /* 77703: CCE,INA,SZA,RSS */
|
||||
0102077, /* 77704: HLT 77 */
|
||||
0017735, /* 77705: JSB 77735 */
|
||||
0007307, /* 77706: CMB,CCE,INB,SZB,RSS */
|
||||
0027702, /* 77707: JMP 77702 */
|
||||
0077733, /* 77710: STB 77733 */
|
||||
0017735, /* 77711: JSB 77735 */
|
||||
0017735, /* 77712: JSB 77735 */
|
||||
0074000, /* 77713: STB 0 */
|
||||
0077747, /* 77714: STB 77747 */
|
||||
0047734, /* 77715: ADB 77734 */
|
||||
0002140, /* 77716: SEZ,CLE */
|
||||
0102055, /* 77717: HLT 55 */
|
||||
0017735, /* 77720: JSB 77735 */
|
||||
0040001, /* 77721: ADA 1 */
|
||||
0177747, /* 77722: STB 77747,I */
|
||||
0067747, /* 77723: LDB 77747 */
|
||||
0006104, /* 77724: CLE,INB */
|
||||
0037733, /* 77725: ISZ 77733 */
|
||||
0027714, /* 77726: JMP 77714 */
|
||||
0017735, /* 77727: JSB 77735 */
|
||||
0054000, /* 77730: CPB 0 */
|
||||
0027701, /* 77731: JMP 77701 */
|
||||
0102011, /* 77732: HLT 11 */
|
||||
0000000, /* 77733: NOP */
|
||||
0100100, /* 77734: RRL 16 */
|
||||
0000000, /* 77735: NOP */
|
||||
0006400, /* 77736: CLB */
|
||||
0103710, /* 77737: STC 10,C */
|
||||
0102310, /* 77740: SFS 10 */
|
||||
0027740, /* 77741: JMP 77740 */
|
||||
0106410, /* 77742: MIB 10 */
|
||||
0002240, /* 77743: SEZ,CME */
|
||||
0127735, /* 77744: JMP 77735,I */
|
||||
0005727, /* 77745: BLF,BLF */
|
||||
0027737, /* 77746: JMP 77737 */
|
||||
0000000, /* 77747: NOP */
|
||||
0067777, /* 77750: DISC LDB 77777 */
|
||||
0174001, /* 77751: STB 1,I */
|
||||
0006004, /* 77752: INB */
|
||||
0063732, /* 77753: LDA 77732 */
|
||||
0170001, /* 77754: STA 1,I */
|
||||
0067776, /* 77755: LDB 77776 */
|
||||
0106606, /* 77756: OTB 6 */
|
||||
0106702, /* 77757: CLC 2 */
|
||||
0102602, /* 77760: OTA 2 */
|
||||
0102702, /* 77761: STC 2 */
|
||||
0063751, /* 77762: LDA 77751 */
|
||||
0102602, /* 77763: OTA 2 */
|
||||
0102501, /* 77764: LIA 1 */
|
||||
0001027, /* 77765: ALS,ALF */
|
||||
0013767, /* 77766: AND 77767 */
|
||||
0000160, /* 77767: CLE,ALS */
|
||||
0106710, /* 77770: CLC 10 */
|
||||
0103610, /* 77771: OTA 10,C */
|
||||
0103706, /* 77772: STC 6,C */
|
||||
0102310, /* 77773: SFS 10 */
|
||||
0027773, /* 77774: JMP 77773 */
|
||||
0117717, /* 77775: JSB 77717,I */
|
||||
0000010, /* 77776: SLA */
|
||||
0002055 } }, /* 77777: SEZ,SLA,INA,RSS */
|
||||
|
||||
const BOOT_ROM ds_rom = {
|
||||
0017727, /* START JSB STAT GET STATUS */
|
||||
0002021, /* SSA,RSS IS DRIVE READY ? */
|
||||
0027742, /* JMP DMA YES, SET UP DMA */
|
||||
0013714, /* AND B20 NO, CHECK STATUS BITS */
|
||||
0002002, /* SZA IS DRIVE FAULTY OR HARD DOWN ? */
|
||||
0102030, /* HLT 30B YES, HALT 30B, "RUN" TO TRY AGAIN */
|
||||
0027700, /* JMP START NO, TRY AGAIN FOR DISC READY */
|
||||
0102011, /* ADDR1 OCT 102011 */
|
||||
0102055, /* ADDR2 OCT 102055 */
|
||||
0164000, /* CNT DEC -6144 */
|
||||
0000007, /* D7 OCT 7 */
|
||||
0001400, /* STCMD OCT 1400 */
|
||||
0000020, /* B20 OCT 20 */
|
||||
0017400, /* STMSK OCT 17400 */
|
||||
0000000, /* NOP */
|
||||
0000000, /* NOP */
|
||||
0000000, /* NOP */
|
||||
0000000, /* NOP */
|
||||
0000000, /* NOP */
|
||||
0000000, /* NOP */
|
||||
0000000, /* NOP */
|
||||
0000000, /* NOP */
|
||||
0000000, /* NOP */
|
||||
0000000, /* STAT NOP STATUS CHECK SUBROUTINE */
|
||||
0107710, /* CLC DC,C SET STATUS COMMAND MODE */
|
||||
0063713, /* LDA STCMD GET STATUS COMMAND */
|
||||
0102610, /* OTA DC OUTPUT STATUS COMMAND */
|
||||
0102310, /* SFS DC WAIT FOR STATUS#1 WORD */
|
||||
0027733, /* JMP *-1 */
|
||||
0107510, /* LIB DC,C B-REG = STATUS#1 WORD */
|
||||
0102310, /* SFS DC WAIT FOR STATUS#2 WORD */
|
||||
0027736, /* JMP *-1 */
|
||||
0103510, /* LIA DC,C A-REG = STATUS#2 WORD */
|
||||
0127727, /* JMP STAT,I RETURN */
|
||||
0067776, /* DMA LDB DMACW GET DMA CONTROL WORD */
|
||||
0106606, /* OTB 6 OUTPUT DMA CONTROL WORD */
|
||||
0067707, /* LDB ADDR1 GET MEMORY ADDRESS */
|
||||
0106702, /* CLC 2 SET MEMORY ADDRESS INPUT MODE */
|
||||
0106602, /* OTB 2 OUTPUT MEMORY ADDRESS TO DMA */
|
||||
0102702, /* STC 2 SET WORD COUNT INPUT MODE */
|
||||
0067711, /* LDB CNT GET WORD COUNT */
|
||||
0106602, /* OTB 2 OUTPUT WORD COUNT TO DMA */
|
||||
0106710, /* CLDLD CLC DC SET COMMAND INPUT MODE */
|
||||
0102501, /* LIA 1 LOAD SWITCH */
|
||||
0106501, /* LIB 1 REGISTER SETTINGS */
|
||||
0013712, /* AND D7 ISOLATE HEAD NUMBER */
|
||||
0005750, /* BLF,CLE,SLB BIT 12=0? */
|
||||
0027762, /* JMP *+3 NO,MANUAL BOOT */
|
||||
0002002, /* SZA YES,RPL BOOT. HEAD#=0? */
|
||||
0001000, /* ALS NO,HEAD#1, MAKE HEAD#=2 */
|
||||
0001720, /* ALF,ALS FORM COLD LOAD */
|
||||
0001000, /* ALS COMMAND WORD */
|
||||
0103706, /* STC 6,C ACTIVATE DMA */
|
||||
0103610, /* OTA DC,C OUTPUT COLD LOAD COMMAND */
|
||||
0102310, /* SFS DC IS COLD LOAD COMPLETED ? */
|
||||
0027766, /* JMP *-1 NO, WAIT */
|
||||
0017727, /* JSB STAT YES, GET STATUS */
|
||||
0060001, /* LDA 1 */
|
||||
0013715, /* AND STMSK A-REG = STATUS BITS OF STATUS#1 WD */
|
||||
0002002, /* SZA IS TRANSFER OK ? */
|
||||
0027700, /* JMP START NO,TRY AGAIN */
|
||||
0117710, /* EXIT JSB ADDR2,I YES, EXEC LOADED PROGRAM _@ 2055B */
|
||||
0000010, /* DMACW ABS DC */
|
||||
0170100, /* ABS -START */
|
||||
{ /* HP 1000 Loader ROM (12992B) */
|
||||
IBL_START, /* loader starting index */
|
||||
IBL_DMA, /* DMA index */
|
||||
IBL_FWA, /* FWA index */
|
||||
{ 0017727, /* 77700: START JSB STAT GET STATUS */
|
||||
0002021, /* 77701: SSA,RSS IS DRIVE READY ? */
|
||||
0027742, /* 77702: JMP DMA YES, SET UP DMA */
|
||||
0013714, /* 77703: AND B20 NO, CHECK STATUS BITS */
|
||||
0002002, /* 77704: SZA IS DRIVE FAULTY OR HARD DOWN ? */
|
||||
0102030, /* 77705: HLT 30B YES, HALT 30B, "RUN" TO TRY AGAIN */
|
||||
0027700, /* 77706: JMP START NO, TRY AGAIN FOR DISC READY */
|
||||
0102011, /* 77707: ADDR1 OCT 102011 */
|
||||
0102055, /* 77710: ADDR2 OCT 102055 */
|
||||
0164000, /* 77711: CNT DEC -6144 */
|
||||
0000007, /* 77712: D7 OCT 7 */
|
||||
0001400, /* 77713: STCMD OCT 1400 */
|
||||
0000020, /* 77714: B20 OCT 20 */
|
||||
0017400, /* 77715: STMSK OCT 17400 */
|
||||
0000000, /* 77716: NOP */
|
||||
0000000, /* 77717: NOP */
|
||||
0000000, /* 77720: NOP */
|
||||
0000000, /* 77721: NOP */
|
||||
0000000, /* 77722: NOP */
|
||||
0000000, /* 77723: NOP */
|
||||
0000000, /* 77724: NOP */
|
||||
0000000, /* 77725: NOP */
|
||||
0000000, /* 77726: NOP */
|
||||
0000000, /* 77727: STAT NOP STATUS CHECK SUBROUTINE */
|
||||
0107710, /* 77730: CLC DC,C SET STATUS COMMAND MODE */
|
||||
0063713, /* 77731: LDA STCMD GET STATUS COMMAND */
|
||||
0102610, /* 77732: OTA DC OUTPUT STATUS COMMAND */
|
||||
0102310, /* 77733: SFS DC WAIT FOR STATUS#1 WORD */
|
||||
0027733, /* 77734: JMP *-1 */
|
||||
0107510, /* 77735: LIB DC,C B-REG = STATUS#1 WORD */
|
||||
0102310, /* 77736: SFS DC WAIT FOR STATUS#2 WORD */
|
||||
0027736, /* 77737: JMP *-1 */
|
||||
0103510, /* 77740: LIA DC,C A-REG = STATUS#2 WORD */
|
||||
0127727, /* 77741: JMP STAT,I RETURN */
|
||||
0067776, /* 77742: DMA LDB DMACW GET DMA CONTROL WORD */
|
||||
0106606, /* 77743: OTB 6 OUTPUT DMA CONTROL WORD */
|
||||
0067707, /* 77744: LDB ADDR1 GET MEMORY ADDRESS */
|
||||
0106702, /* 77745: CLC 2 SET MEMORY ADDRESS INPUT MODE */
|
||||
0106602, /* 77746: OTB 2 OUTPUT MEMORY ADDRESS TO DMA */
|
||||
0102702, /* 77747: STC 2 SET WORD COUNT INPUT MODE */
|
||||
0067711, /* 77750: LDB CNT GET WORD COUNT */
|
||||
0106602, /* 77751: OTB 2 OUTPUT WORD COUNT TO DMA */
|
||||
0106710, /* 77752: CLDLD CLC DC SET COMMAND INPUT MODE */
|
||||
0102501, /* 77753: LIA 1 LOAD SWITCH */
|
||||
0106501, /* 77754: LIB 1 REGISTER SETTINGS */
|
||||
0013712, /* 77755: AND D7 ISOLATE HEAD NUMBER */
|
||||
0005750, /* 77756: BLF,CLE,SLB BIT 12=0? */
|
||||
0027762, /* 77757: JMP *+3 NO,MANUAL BOOT */
|
||||
0002002, /* 77760: SZA YES,RPL BOOT. HEAD#=0? */
|
||||
0001000, /* 77761: ALS NO,HEAD#1, MAKE HEAD#=2 */
|
||||
0001720, /* 77762: ALF,ALS FORM COLD LOAD */
|
||||
0001000, /* 77763: ALS COMMAND WORD */
|
||||
0103706, /* 77764: STC 6,C ACTIVATE DMA */
|
||||
0103610, /* 77765: OTA DC,C OUTPUT COLD LOAD COMMAND */
|
||||
0102310, /* 77766: SFS DC IS COLD LOAD COMPLETED ? */
|
||||
0027766, /* 77767: JMP *-1 NO, WAIT */
|
||||
0017727, /* 77770: JSB STAT YES, GET STATUS */
|
||||
0060001, /* 77771: LDA 1 */
|
||||
0013715, /* 77772: AND STMSK A-REG = STATUS BITS OF STATUS#1 WD */
|
||||
0002002, /* 77773: SZA IS TRANSFER OK ? */
|
||||
0027700, /* 77774: JMP START NO,TRY AGAIN */
|
||||
0117710, /* 77775: EXIT JSB ADDR2,I YES, EXEC LOADED PROGRAM @ 2055B */
|
||||
0000010, /* 77776: DMACW ABS DC */
|
||||
0170100 } } /* 77777: ABS -START */
|
||||
};
|
||||
|
||||
|
||||
/* Device boot routine.
|
||||
|
||||
This routine is called directly by the BOOT DS and LOAD DS commands to copy
|
||||
the device bootstrap into the upper 64 words of the logical address space.
|
||||
It is also called indirectly by a BOOT CPU or LOAD CPU command when the
|
||||
specified HP 1000 loader ROM socket contains a 12992B ROM.
|
||||
|
||||
When called in response to a BOOT DS or LOAD DS command, the "unitno"
|
||||
parameter indicates the unit number specified in the BOOT command or is zero
|
||||
for the LOAD command, and "dptr" points at the DS device structure. The
|
||||
bootstrap supports loading only from unit 0, and the command will be rejected
|
||||
if another unit is specified (e.g., BOOT DS1). Otherwise, depending on the
|
||||
current CPU model, the BMDL or 12992B loader ROM will be copied into memory
|
||||
and configured for the DS select code. If the CPU is a 1000, the S register
|
||||
will be set as it would be by the front-panel microcode.
|
||||
|
||||
When called for a BOOT/LOAD CPU command, the "unitno" parameter indicates the
|
||||
select code to be used for configuration, and "dptr" will be NULL. As above,
|
||||
the BMDL or 12992B loader ROM will be copied into memory and configured for
|
||||
the specified select code. The S register is assumed to be set correctly on
|
||||
entry and is not modified.
|
||||
|
||||
In either case, if the CPU is a 21xx model, the paper tape portion of the
|
||||
BMDL will be automatically configured for the select code of the paper tape
|
||||
reader.
|
||||
|
||||
For the 12992B boot loader ROM for the HP 1000, the S register is set as
|
||||
follows:
|
||||
|
||||
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| ROM # | 0 1 | select code | reserved | 0 | head |
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
|
||||
Bit 12 must be 1 for a manual boot. Bits 5-3 are nominally zero but are
|
||||
reserved for the target operating system. For example, RTE uses bit 5 to
|
||||
indicate whether a standard (0) or reconfiguration (1) boot is desired.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. In hardware, the BMDL was hand-configured for the disc and paper tape
|
||||
reader select codes when it was installed on a given system. Under
|
||||
simulation, the LOAD and BOOT commands automatically configure the BMDL
|
||||
to the current select codes of the PTR and DS devices.
|
||||
|
||||
2. The HP 1000 Loader ROMs manual indicates that bits 2-0 select the head to
|
||||
use, implying that heads 0-7 are valid. However, Table 5 has entries
|
||||
only for heads 0-3, and the boot loader code will malfunction if heads
|
||||
4-7 are specified. The code masks the head number to three bits but
|
||||
forms the Cold Load Read command by shifting the head number six bits to
|
||||
the left. As the head field in the command is only two bits wide,
|
||||
specifying heads 4-7 will result in bit 2 being shifted into the opcode
|
||||
field, resulting in a Recalibrate command.
|
||||
*/
|
||||
|
||||
t_stat ds_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
if (unitno != 0) /* boot supported on drive unit 0 only */
|
||||
return SCPE_NOFNC; /* report "Command not allowed" if attempted */
|
||||
static const HP_WORD ds_preserved = 0000073u; /* S-register bits 5-3 and 1-0 are preserved */
|
||||
static const HP_WORD ds_manual_boot = 0010000u; /* S-register bit 12 set for a manual boot */
|
||||
|
||||
if (ibl_copy (ds_rom, ds_dib.select_code, /* copy the boot ROM to memory and configure */
|
||||
IBL_OPT | IBL_DS_HEAD, /* the S register accordingly */
|
||||
IBL_DS | IBL_MAN | IBL_SET_SC (ds_dib.select_code)))
|
||||
return SCPE_IERR; /* return an internal error if the copy failed */
|
||||
else
|
||||
return SCPE_OK;
|
||||
if (dptr == NULL) /* if we are being called for a BOOT/LOAD CPU */
|
||||
return cpu_copy_loader (ds_loaders, unitno, /* then copy the boot loader to memory */
|
||||
IBL_S_NOCLEAR, IBL_S_NOSET); /* but do not alter the S register */
|
||||
|
||||
else if (unitno != 0) /* otherwise a BOOT DS for a non-zero unit */
|
||||
return SCPE_NOFNC; /* is rejected as unsupported */
|
||||
|
||||
else /* otherwise this is a BOOT/LOAD DS */
|
||||
return cpu_copy_loader (ds_loaders, ds_dib.select_code, /* so copy the boot loader to memory */
|
||||
ds_preserved, ds_manual_boot); /* and configure the S register if 1000 CPU */
|
||||
}
|
||||
|
||||
|
||||
@@ -1273,23 +1424,16 @@ if (uptr) { /* did the command start
|
||||
if (time) /* was the unit scheduled? */
|
||||
activate_unit (uptr); /* activate it (and clear the "wait" field) */
|
||||
|
||||
if (DEBUG_PRI (ds_dev, DEB_RWSC)) {
|
||||
unit = uptr - ds_unit; /* get the unit number */
|
||||
if (time == 0) /* was the unit busy? */
|
||||
tprintf (ds_dev, DEB_RWSC, "Unit %d %s in progress\n",
|
||||
uptr - ds_unit, dl_opcode_name (MAC, drive_command));
|
||||
|
||||
if (time == 0) /* was the unit busy? */
|
||||
fprintf (sim_deb, ">>DS rwsc: Unit %d %s in progress\n",
|
||||
unit, dl_opcode_name (MAC, drive_command));
|
||||
|
||||
fputs (">>DS rwsc: ", sim_deb);
|
||||
|
||||
if (unit > DL_MAXDRIVE)
|
||||
fputs ("Controller ", sim_deb);
|
||||
else
|
||||
fprintf (sim_deb, "Unit %d position %" T_ADDR_FMT "d ", unit, uptr->pos);
|
||||
|
||||
fprintf (sim_deb, "%s command initiated\n",
|
||||
if (uptr - ds_unit > DL_MAXDRIVE)
|
||||
tprintf (ds_dev, DEB_RWSC, "Controller %s command initiated\n",
|
||||
dl_opcode_name (MAC, mac_cntlr.opcode));
|
||||
}
|
||||
else
|
||||
tprintf (ds_dev, DEB_RWSC, "Unit %d position %" T_ADDR_FMT "d %s command initiated\n",
|
||||
uptr - ds_unit, uptr->pos, dl_opcode_name (MAC, mac_cntlr.opcode));
|
||||
}
|
||||
|
||||
else /* the command failed to start */
|
||||
@@ -1380,8 +1524,7 @@ static void fifo_load (uint16 data)
|
||||
uint32 index;
|
||||
|
||||
if (FIFO_FULL) { /* is the FIFO already full? */
|
||||
if (DEBUG_PRI (ds_dev, DEB_BUF))
|
||||
fprintf (sim_deb, ">>DS buf: Attempted load to full FIFO, data %06o\n", data);
|
||||
tprintf (ds_dev, DEB_BUF, "Attempted load to full FIFO, data %06o\n", data);
|
||||
|
||||
return; /* return with the load ignored */
|
||||
}
|
||||
@@ -1391,9 +1534,8 @@ index = (ds.fifo_reg->qptr + ds.fifo_count) % FIFO_SIZE; /* calculate the ind
|
||||
ds.fifo [index] = data; /* store the word in the FIFO */
|
||||
ds.fifo_count = ds.fifo_count + 1; /* increment the count of words stored */
|
||||
|
||||
if (DEBUG_PRI (ds_dev, DEB_BUF))
|
||||
fprintf (sim_deb, ">>DS buf: Data %06o loaded into FIFO (%d)\n",
|
||||
data, ds.fifo_count);
|
||||
tprintf (ds_dev, DEB_BUF, "Data %06o loaded into FIFO (%d)\n",
|
||||
data, ds.fifo_count);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1418,9 +1560,7 @@ static uint16 fifo_unload (void)
|
||||
uint16 data;
|
||||
|
||||
if (FIFO_EMPTY) { /* is the FIFO already empty? */
|
||||
if (DEBUG_PRI (ds_dev, DEB_BUF))
|
||||
fputs (">>DS buf: Attempted unload from empty FIFO\n", sim_deb);
|
||||
|
||||
tprintf (ds_dev, DEB_BUF, "Attempted unload from empty FIFO\n");
|
||||
return 0; /* return with no data */
|
||||
}
|
||||
|
||||
@@ -1429,9 +1569,8 @@ data = ds.fifo [ds.fifo_reg->qptr]; /* get the word from
|
||||
ds.fifo_reg->qptr = (ds.fifo_reg->qptr + 1) % FIFO_SIZE; /* update the FIFO queue pointer */
|
||||
ds.fifo_count = ds.fifo_count - 1; /* decrement the count of words stored */
|
||||
|
||||
if (DEBUG_PRI (ds_dev, DEB_BUF))
|
||||
fprintf (sim_deb, ">>DS buf: Data %06o unloaded from FIFO (%d)\n",
|
||||
data, ds.fifo_count);
|
||||
tprintf (ds_dev, DEB_BUF, "Data %06o unloaded from FIFO (%d)\n",
|
||||
data, ds.fifo_count);
|
||||
|
||||
return data;
|
||||
}
|
||||
@@ -1446,8 +1585,7 @@ static void fifo_clear (void)
|
||||
{
|
||||
ds.fifo_count = 0; /* clear the FIFO */
|
||||
|
||||
if (DEBUG_PRI (ds_dev, DEB_BUF))
|
||||
fputs (">>DS buf: FIFO cleared\n", sim_deb);
|
||||
tprintf (ds_dev, DEB_BUF, "FIFO cleared\n");
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1461,19 +1599,14 @@ return;
|
||||
|
||||
static t_stat activate_unit (UNIT *uptr)
|
||||
{
|
||||
int32 unit;
|
||||
t_stat result;
|
||||
|
||||
if (DEBUG_PRI (ds_dev, DEB_SERV)) {
|
||||
unit = uptr - ds_unit; /* calculate the unit number */
|
||||
|
||||
if (uptr == &ds_cntlr)
|
||||
fprintf (sim_deb, ">>DS serv: Controller delay %d service scheduled\n",
|
||||
uptr->wait);
|
||||
else
|
||||
fprintf (sim_deb, ">>DS serv: Unit %d delay %d service scheduled\n",
|
||||
unit, uptr->wait);
|
||||
}
|
||||
if (uptr == &ds_cntlr)
|
||||
tprintf (ds_dev, DEB_SERV, "Controller delay %d service scheduled\n",
|
||||
uptr->wait);
|
||||
else
|
||||
tprintf (ds_dev, DEB_SERV, "Unit %d delay %d service scheduled\n",
|
||||
uptr - ds_unit, uptr->wait);
|
||||
|
||||
result = sim_activate (uptr, uptr->wait); /* activate the unit */
|
||||
uptr->wait = 0; /* reset the activation time */
|
||||
|
||||
@@ -1,28 +1,30 @@
|
||||
/* hp2100_fp.c: HP 2100 floating point instructions
|
||||
|
||||
Copyright (c) 2002-2015, Robert M. Supnik
|
||||
Copyright (c) 2017 J. David Bryan
|
||||
|
||||
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:
|
||||
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.
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHOR 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
|
||||
Except as contained in this notice, the names of the authors 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.
|
||||
in this Software without prior written authorization from the authors.
|
||||
|
||||
26-Jun-17 JDB Replaced SEXT with SEXT16
|
||||
03-Jan-15 JDB Made the utility routines static
|
||||
21-Jan-08 JDB Corrected fp_unpack mantissa high-word return
|
||||
(from Mark Pizzolato)
|
||||
@@ -228,13 +230,13 @@ UnpackFP (&fop1, FPAB); /* unpack A-B */
|
||||
UnpackFP (&fop2, opnd); /* unpack op */
|
||||
if (fop1.fr && fop2.fr) { /* if both != 0 */
|
||||
res.exp = fop1.exp + fop2.exp + 1; /* exp = sum */
|
||||
shi1 = SEXT (fop1.fr >> 16); /* mpy hi */
|
||||
shi2 = SEXT (fop2.fr >> 16); /* mpc hi */
|
||||
shi1 = SEXT16 (UPPER_WORD (fop1.fr)); /* mpy hi */
|
||||
shi2 = SEXT16 (UPPER_WORD (fop2.fr)); /* mpc hi */
|
||||
t1 = shi2 * ((int32) ((fop1.fr >> 1) & 077600)); /* mpc hi * (mpy lo/2) */
|
||||
t2 = shi1 * ((int32) ((fop2.fr >> 1) & 077600)); /* mpc lo * (mpy hi/2) */
|
||||
t3 = t1 + t2; /* cross product */
|
||||
t4 = (shi1 * shi2) & ~1; /* mpy hi * mpc hi */
|
||||
t5 = (SEXT (t3 >> 16)) << 1; /* add in cross */
|
||||
t5 = SEXT16 (UPPER_WORD (t3)) << 1; /* add in cross */
|
||||
res.fr = (t4 + t5) & DMASK32; /* bit<0> is lost */
|
||||
}
|
||||
return StoreFP (&res); /* store */
|
||||
@@ -282,7 +284,7 @@ if (fop1.fr) { /* dvd != 0? */
|
||||
q1 = divx (ba, dvrh, NULL); /* Q1 = rem / dvrh */
|
||||
ba = (fop2.fr & 0xFF00) << 13; /* dvrl / 8 */
|
||||
q2 = divx (ba, dvrh, NULL); /* dvrl / dvrh */
|
||||
ba = -(SEXT (q2)) * (SEXT (q0)); /* -Q0 * Q2 */
|
||||
ba = - SEXT16 (LOWER_WORD (q2)) * SEXT16 (LOWER_WORD (q0)); /* -Q0 * Q2 */
|
||||
ba = (ba >> 16) & 0xFFFF; /* save ms half */
|
||||
if (q1 & SIGN) quo.fr = quo.fr - 0x00010000; /* Q1 < 0? -1 */
|
||||
if (ba & SIGN) quo.fr = quo.fr - 0x00010000; /* -Q0*Q2 < 0? */
|
||||
@@ -372,8 +374,8 @@ uint32 val;
|
||||
fop.fr = ((uint32) mantissa.fpk[0] << 16) | mantissa.fpk[1];
|
||||
fop.exp = exponent;
|
||||
val = PackFP (&fop);
|
||||
result->fpk[0] = (int16) (val >> 16);
|
||||
result->fpk[1] = (int16) val;
|
||||
result->fpk[0] = UPPER_WORD (val);
|
||||
result->fpk[1] = LOWER_WORD (val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -401,8 +403,8 @@ uint32 operand;
|
||||
|
||||
operand = ((uint32) packed.fpk[0] << 16) | packed.fpk[1];
|
||||
UnpackFP (&fop, operand);
|
||||
mantissa->fpk[0] = (uint16) (fop.fr >> 16);
|
||||
mantissa->fpk[1] = (uint16) fop.fr;
|
||||
mantissa->fpk[0] = UPPER_WORD (fop.fr);
|
||||
mantissa->fpk[1] = LOWER_WORD (fop.fr);
|
||||
*exponent = fop.exp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
/* hp2100_fp.h: HP 2100/21MX floating point definitions
|
||||
/* hp2100_fp.h: HP 2100/21MX floating point declarations
|
||||
|
||||
Copyright (c) 2002-2013, Robert M. Supnik
|
||||
Copyright (c) 2017, J. David Bryan
|
||||
|
||||
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:
|
||||
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.
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS 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
|
||||
Except as contained in this notice, the names of the authors 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.
|
||||
in this Software without prior written authorization from the authors.
|
||||
|
||||
15-Feb-17 JDB Deleted unneeded guard macro definition
|
||||
14-Mar-13 MP Changed guard macro name to avoid reserved namespace
|
||||
01-Dec-06 JDB Reworked FFP helpers for 1000-F support, deleted f_pwr2
|
||||
26-Sep-06 JDB Moved from hp2100_fp.c to simplify extensions
|
||||
*/
|
||||
|
||||
#ifndef HP2100_FP_H_
|
||||
#define HP2100_FP_H_
|
||||
|
||||
/* Firmware floating-point routines */
|
||||
|
||||
@@ -44,5 +44,3 @@ uint32 f_flt (void); /* FLT */
|
||||
uint32 fp_pack (OP *result, OP mantissa, int32 exponent, OPSIZE precision);
|
||||
uint32 fp_nrpack (OP *result, OP mantissa, int32 exponent, OPSIZE precision);
|
||||
uint32 fp_unpack (OP *mantissa, int32 *exponent, OP packed, OPSIZE precision);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* hp2100_fp1.c: HP 1000 multiple-precision floating point routines
|
||||
|
||||
Copyright (c) 2005-2016, J. David Bryan
|
||||
Copyright (c) 2005-2017, J. David Bryan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -23,6 +23,7 @@
|
||||
in advertising or otherwise to promote the sale, use or other dealings in
|
||||
this Software without prior written authorization from the author.
|
||||
|
||||
07-Sep-17 JDB Replaced "uint16" casts with "HP_WORD" for OP assignments
|
||||
16-May-16 JDB Reformulated the definitions of op_mask
|
||||
24-Dec-14 JDB Added casts for explicit downward conversions
|
||||
Changed fp_ucom return from uint32 to uint16
|
||||
@@ -480,7 +481,7 @@ int32 i;
|
||||
OP packed;
|
||||
|
||||
if (precision == in_s)
|
||||
packed.word = (uint16) (unpacked >> 48) & DMASK; /* pack single integer */
|
||||
packed.word = (HP_WORD) (unpacked >> 48) & DMASK; /* pack single integer */
|
||||
|
||||
else if (precision == in_d)
|
||||
packed.dword = (uint32) (unpacked >> 32) & DMASK32; /* pack double integer */
|
||||
@@ -490,7 +491,7 @@ else {
|
||||
precision = fp_t; /* only four mantissa words */
|
||||
|
||||
for (i = 3; i >= 0; i--) { /* pack fp 2 to 4 words */
|
||||
packed.fpk[i] = (uint16) unpacked & DMASK;
|
||||
packed.fpk[i] = (HP_WORD) unpacked & DMASK;
|
||||
unpacked = unpacked >> 16;
|
||||
}
|
||||
}
|
||||
@@ -530,8 +531,8 @@ switch (unpacked.precision) { /* merge exponent into c
|
||||
break;
|
||||
|
||||
case fp_e: /* place in separate word */
|
||||
packed.fpk[4] = (uint16) (unpacked.exponent << FP_V_EXP |
|
||||
(unpacked.exponent < 0) << FP_V_ESIGN);
|
||||
packed.fpk[4] = (HP_WORD) (unpacked.exponent << FP_V_EXP |
|
||||
(unpacked.exponent < 0) << FP_V_ESIGN);
|
||||
break;
|
||||
|
||||
case fp_a: /* no action for value in accum */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* hp2100_fp1.h: HP 2100/1000 multiple-precision floating point definitions
|
||||
/* hp2100_fp1.h: HP 2100/1000 multiple-precision floating point declarations
|
||||
|
||||
Copyright (c) 2005-2014, J. David Bryan
|
||||
Copyright (c) 2005-2017, J. David Bryan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -23,14 +23,13 @@
|
||||
in advertising or otherwise to promote the sale, use or other dealings in
|
||||
this Software without prior written authorization from the author.
|
||||
|
||||
15-Feb-17 JDB Deleted unneeded guard macro definition
|
||||
24-Dec-14 JDB Changed fp_ucom return from uint32 to uint16
|
||||
14-Mar-13 MP Changed guard macro name to avoid reserved namespace
|
||||
16-Oct-06 JDB Generalized FP calling sequences for F-Series
|
||||
12-Oct-06 JDB Altered x_trun for F-Series FFP compatibility
|
||||
*/
|
||||
|
||||
#ifndef HP2100_FP1_H_
|
||||
#define HP2100_FP1_H_ 0
|
||||
|
||||
|
||||
/* Special operands. */
|
||||
@@ -51,5 +50,3 @@ uint16 fp_ucom (OP *mantissa, OPSIZE precision);
|
||||
uint32 fp_pcom (OP *packed, OPSIZE precision);
|
||||
uint32 fp_trun (OP *result, OP source, OPSIZE precision);
|
||||
uint32 fp_cvt (OP *result, OPSIZE source_precision, OPSIZE dest_precision);
|
||||
|
||||
#endif
|
||||
|
||||
2168
HP2100/hp2100_ipl.c
2168
HP2100/hp2100_ipl.c
File diff suppressed because it is too large
Load Diff
@@ -1,31 +1,35 @@
|
||||
/* hp2100_lps.c: HP 2100 12653A/2767 line printer simulator
|
||||
/* hp2100_lps.c: HP 2100 12653A Line Printer Interface simulator
|
||||
|
||||
Copyright (c) 1993-2016, Robert M. Supnik
|
||||
Copyright (c) 2017, J. David Bryan
|
||||
|
||||
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:
|
||||
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.
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS 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
|
||||
Except as contained in this notice, the names of the authors 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.
|
||||
in this Software without prior written authorization from the authors.
|
||||
|
||||
LPS 12653A 2767 line printer
|
||||
12566B microcircuit interface with loopback diagnostic connector
|
||||
LPS HP 12653A Line Printer Interface
|
||||
|
||||
03-Aug-17 JDB Changed perror call for I/O errors to cprintf
|
||||
20-Jul-17 JDB Removed "lps_stopioe" variable and register
|
||||
17-Mar-17 JDB Added "-N" handling to the attach routine
|
||||
15-Mar-17 JDB Changed DEBUG_PRS calls to tprintfs
|
||||
13-May-16 JDB Modified for revised SCP API function parameter types
|
||||
10-Feb-12 JDB Deprecated DEVNO in favor of SC
|
||||
28-Mar-11 JDB Tidied up signal handling
|
||||
@@ -58,30 +62,17 @@
|
||||
15-Oct-00 RMS Added variable device number support
|
||||
|
||||
References:
|
||||
- 2767A Line Printer Operating and Service Manual (02767-90002, Oct-1973)
|
||||
- 12566B, 12566B-001, 12566B-002, 12566B-003 Microcircuit Interface Kits
|
||||
Operating and Service Manual (12566-90015, Apr-1976)
|
||||
|
||||
|
||||
This module simulates two different devices. In "diagnostic mode," it
|
||||
simulates a 12566B microcircuit interface card with a loopback connector. In
|
||||
non-diagnostic mode, it simulates a 12653A line printer interface card and a
|
||||
2767 line printer.
|
||||
|
||||
In diagnostic mode, the 12566B interface has a loopback connector that ties
|
||||
the output data lines to the input data lines and the device command output
|
||||
to the device flag input. In addition, card configuration jumpers are set as
|
||||
needed for the diagnostic programs.
|
||||
|
||||
Jumper settings depend on the CPU model. For the 2114/15/16 CPUs, jumper W1
|
||||
is installed in position B and jumper W2 in position C. In these positions,
|
||||
the card flag sets two instructions after the STC, allowing DMA to steal
|
||||
every third cycle. For the 2100 and 1000 CPUs, jumper W1 is installed in
|
||||
position C and jumper W2 in position B. In these positions, the card flag
|
||||
sets one instruction after the STC, allowing DMA to steal every other cycle.
|
||||
For all CPUs, jumpers W3 and W4 are installed in position B, W5-W8 are
|
||||
installed, and W9 is installed in position A.
|
||||
- 2767A Line Printer Operating and Service Manual
|
||||
(02767-90002, October 1973)
|
||||
- General Purpose Register Diagnostic Reference Manual
|
||||
(24391-90001, April 1982)
|
||||
|
||||
The HP 12653A Line Printer Interface Kit connects the 2767A printer to the HP
|
||||
1000 family. The subsystem consists of an interface card employing TTL-level
|
||||
line drivers and receivers, an interconnecting cable, and an HP 2767A (from
|
||||
356 to 1110 lines per minute) line printer. The interface is supported by
|
||||
RTE and DOS drivers DVR12. The interface supports DMA transfers, but the OS
|
||||
drivers do not use them.
|
||||
|
||||
The 2767 impact printer has a rotating drum with 80 columns of 64 raised
|
||||
characters. ASCII codes 32 through 95 (SPACE through "_") form the print
|
||||
@@ -131,45 +122,75 @@
|
||||
2. Print operation in progress sets BUSY instead of NOT READY.
|
||||
3. Characters not in the print repertoire are replaced with blanks.
|
||||
4. The 81st and succeeding characters overprint the current line.
|
||||
*/
|
||||
|
||||
The "General Purpose Register Diagnostic Reference Manual" states that the
|
||||
12653A is a "special microcircuit interface," suggesting that it is a
|
||||
derivative of the 12566B Microcircuit Interface Kit. No specific manual for
|
||||
this interface kit has been found.
|
||||
|
||||
A diagnostic mode is provided to simulate the installation of the 1251-0332
|
||||
loopback connecctor, modified to connect pins Z/22 to pins AA/23 as required
|
||||
by the diagnostic. This ties the output data lines to the input data lines
|
||||
and the device command output to the device flag input.
|
||||
|
||||
Jumper settings depend on the CPU model. For the 2114/15/16 CPUs, jumper W1
|
||||
is installed in position B and jumper W2 in position C. In these positions,
|
||||
the card flag sets two instructions after the STC, allowing DMA to steal
|
||||
every third cycle. For the 2100 and 1000 CPUs, jumper W1 is installed in
|
||||
position C and jumper W2 in position B. In these positions, the card flag
|
||||
sets one instruction after the STC, allowing DMA to steal every other cycle.
|
||||
For all CPUs, jumpers W3 and W4 are installed in position B, W5-W8 are
|
||||
installed, and W9 is installed in position A.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "hp2100_defs.h"
|
||||
#include "hp2100_cpu.h"
|
||||
|
||||
#define LPS_ZONECNT 20 /* zone char count */
|
||||
#define LPS_PAGECNT 80 /* page char count */
|
||||
#define LPS_PAGELNT 60 /* page line length */
|
||||
#define LPS_FORMLNT 66 /* form line length */
|
||||
|
||||
|
||||
/* Printer program constants */
|
||||
|
||||
#define CR '\r' /* carriage return */
|
||||
#define LF '\n' /* line feed */
|
||||
#define FF '\f' /* form feed */
|
||||
|
||||
#define DATA_MASK 0177u /* printer uses only 7 bits for data */
|
||||
|
||||
#define LPS_ZONECNT 20 /* zone char count */
|
||||
#define LPS_PAGECNT 80 /* page char count */
|
||||
#define LPS_PAGELNT 60 /* page line length */
|
||||
#define LPS_FORMLNT 66 /* form line length */
|
||||
|
||||
/* Printer power states */
|
||||
|
||||
#define LPS_ON 0 /* power is on */
|
||||
#define LPS_OFF 1 /* power is off */
|
||||
#define LPS_TURNING_ON 2 /* power is turning on */
|
||||
#define LPS_ON 0 /* power is on */
|
||||
#define LPS_OFF 1 /* power is off */
|
||||
#define LPS_TURNING_ON 2 /* power is turning on */
|
||||
|
||||
#define LPS_BUSY 0000001 /* busy status */
|
||||
#define LPS_NRDY 0100000 /* not ready status */
|
||||
#define LPS_PWROFF LPS_BUSY | LPS_NRDY /* power-off status */
|
||||
#define LPS_BUSY 0000001 /* busy status */
|
||||
#define LPS_NRDY 0100000 /* not ready status */
|
||||
#define LPS_PWROFF LPS_BUSY | LPS_NRDY /* power-off status */
|
||||
|
||||
#define UNIT_V_DIAG (UNIT_V_UF + 0) /* diagnostic mode */
|
||||
#define UNIT_V_POWEROFF (UNIT_V_UF + 1) /* unit powered off */
|
||||
#define UNIT_V_OFFLINE (UNIT_V_UF + 2) /* unit offline */
|
||||
#define UNIT_V_DIAG (UNIT_V_UF + 0) /* diagnostic mode */
|
||||
#define UNIT_V_POWEROFF (UNIT_V_UF + 1) /* unit powered off */
|
||||
#define UNIT_V_OFFLINE (UNIT_V_UF + 2) /* unit offline */
|
||||
#define UNIT_DIAG (1 << UNIT_V_DIAG)
|
||||
#define UNIT_POWEROFF (1 << UNIT_V_POWEROFF)
|
||||
#define UNIT_OFFLINE (1 << UNIT_V_OFFLINE)
|
||||
|
||||
struct {
|
||||
FLIP_FLOP control; /* control flip-flop */
|
||||
FLIP_FLOP flag; /* flag flip-flop */
|
||||
FLIP_FLOP flagbuf; /* flag buffer flip-flop */
|
||||
static struct {
|
||||
FLIP_FLOP control; /* control flip-flop */
|
||||
FLIP_FLOP flag; /* flag flip-flop */
|
||||
FLIP_FLOP flagbuf; /* flag buffer flip-flop */
|
||||
} lps = { CLEAR, CLEAR, CLEAR };
|
||||
|
||||
int32 lps_ccnt = 0; /* character count */
|
||||
int32 lps_lcnt = 0; /* line count */
|
||||
int32 lps_stopioe = 0; /* stop on error */
|
||||
int32 lps_sta = 0; /* printer status */
|
||||
int32 lps_timing = 1; /* timing type */
|
||||
uint32 lps_power = LPS_ON; /* power state */
|
||||
static int32 lps_ccnt = 0; /* character count */
|
||||
static int32 lps_lcnt = 0; /* line count */
|
||||
static int32 lps_sta = 0; /* printer status */
|
||||
static int32 lps_timing = 1; /* timing type */
|
||||
static uint32 lps_power = LPS_ON; /* power state */
|
||||
|
||||
/* Hardware timing:
|
||||
(based on 1580 instr/msec) instr msec calc msec
|
||||
@@ -191,32 +212,32 @@ uint32 lps_power = LPS_ON; /* power state */
|
||||
three-fourths when not executing on an E/F.
|
||||
*/
|
||||
|
||||
int32 lps_ctime = 0; /* char xfer time */
|
||||
int32 lps_ptime = 0; /* zone printing time */
|
||||
int32 lps_stime = 0; /* paper slew time */
|
||||
int32 lps_rtime = 0; /* power-on ready time */
|
||||
static int32 lps_ctime = 0; /* char xfer time */
|
||||
static int32 lps_ptime = 0; /* zone printing time */
|
||||
static int32 lps_stime = 0; /* paper slew time */
|
||||
static int32 lps_rtime = 0; /* power-on ready time */
|
||||
|
||||
typedef int32 TIMESET[4]; /* set of controller times */
|
||||
typedef int32 TIMESET[4]; /* set of controller times */
|
||||
|
||||
int32 *const lps_timers[] = { &lps_ctime, &lps_ptime, &lps_stime, &lps_rtime };
|
||||
static int32 *const lps_timers[] = { &lps_ctime, &lps_ptime, &lps_stime, &lps_rtime };
|
||||
|
||||
const TIMESET lps_times[2] = {
|
||||
{ 2, 55300, 17380, 158000 }, /* REALTIME */
|
||||
{ 2, 1000, 1000, 1000 } /* FASTTIME */
|
||||
static const TIMESET lps_times[2] = {
|
||||
{ 2, 55300, 17380, 158000 }, /* REALTIME */
|
||||
{ 2, 1000, 1000, 1000 } /* FASTTIME */
|
||||
};
|
||||
|
||||
DEVICE lps_dev;
|
||||
|
||||
IOHANDLER lpsio;
|
||||
static IOHANDLER lpsio;
|
||||
|
||||
t_stat lps_svc (UNIT *uptr);
|
||||
t_stat lps_reset (DEVICE *dptr);
|
||||
t_stat lps_restart (UNIT *uptr, int32 value, CONST char *cptr, void *desc);
|
||||
t_stat lps_poweroff (UNIT *uptr, int32 value, CONST char *cptr, void *desc);
|
||||
t_stat lps_poweron (UNIT *uptr, int32 value, CONST char *cptr, void *desc);
|
||||
t_stat lps_attach (UNIT *uptr, CONST char *cptr);
|
||||
t_stat lps_set_timing (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||||
t_stat lps_show_timing (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
||||
static t_stat lps_svc (UNIT *uptr);
|
||||
static t_stat lps_reset (DEVICE *dptr);
|
||||
static t_stat lps_restart (UNIT *uptr, int32 value, CONST char *cptr, void *desc);
|
||||
static t_stat lps_poweroff (UNIT *uptr, int32 value, CONST char *cptr, void *desc);
|
||||
static t_stat lps_poweron (UNIT *uptr, int32 value, CONST char *cptr, void *desc);
|
||||
static t_stat lps_attach (UNIT *uptr, CONST char *cptr);
|
||||
static t_stat lps_set_timing (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||||
static t_stat lps_show_timing (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
||||
|
||||
/* LPS data structures
|
||||
|
||||
@@ -225,57 +246,89 @@ t_stat lps_show_timing (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
||||
lps_reg LPS register list
|
||||
*/
|
||||
|
||||
DIB lps_dib = { &lpsio, LPS };
|
||||
static DIB lps_dib = { &lpsio, LPS };
|
||||
|
||||
UNIT lps_unit = {
|
||||
static UNIT lps_unit = {
|
||||
UDATA (&lps_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_DISABLE+UNIT_TEXT, 0)
|
||||
};
|
||||
|
||||
REG lps_reg[] = {
|
||||
{ ORDATA (BUF, lps_unit.buf, 16) },
|
||||
{ ORDATA (STA, lps_sta, 16) },
|
||||
{ ORDATA (POWER, lps_power, 2), REG_RO },
|
||||
{ FLDATA (CTL, lps.control, 0) },
|
||||
{ FLDATA (FLG, lps.flag, 0) },
|
||||
{ FLDATA (FBF, lps.flagbuf, 0) },
|
||||
{ DRDATA (CCNT, lps_ccnt, 7), PV_LEFT },
|
||||
{ DRDATA (LCNT, lps_lcnt, 7), PV_LEFT },
|
||||
{ DRDATA (POS, lps_unit.pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (CTIME, lps_ctime, 24), PV_LEFT },
|
||||
{ DRDATA (PTIME, lps_ptime, 24), PV_LEFT },
|
||||
{ DRDATA (STIME, lps_stime, 24), PV_LEFT },
|
||||
{ DRDATA (RTIME, lps_rtime, 24), PV_LEFT },
|
||||
{ FLDATA (TIMING, lps_timing, 0), REG_HRO },
|
||||
{ FLDATA (STOP_IOE, lps_stopioe, 0) },
|
||||
{ ORDATA (SC, lps_dib.select_code, 6), REG_HRO },
|
||||
{ ORDATA (DEVNO, lps_dib.select_code, 6), REG_HRO },
|
||||
static REG lps_reg[] = {
|
||||
/* Macro Name Location Width Offset Flags */
|
||||
/* ------ ------ ------------------- --------- ------ ------- */
|
||||
{ ORDATA (BUF, lps_unit.buf, 16), REG_X },
|
||||
{ ORDATA (STA, lps_sta, 16) },
|
||||
{ ORDATA (POWER, lps_power, 2), REG_RO },
|
||||
{ FLDATA (CTL, lps.control, 0) },
|
||||
{ FLDATA (FLG, lps.flag, 0) },
|
||||
{ FLDATA (FBF, lps.flagbuf, 0) },
|
||||
{ DRDATA (CCNT, lps_ccnt, 7), PV_LEFT },
|
||||
{ DRDATA (LCNT, lps_lcnt, 7), PV_LEFT },
|
||||
{ DRDATA (POS, lps_unit.pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (CTIME, lps_ctime, 24), PV_LEFT },
|
||||
{ DRDATA (PTIME, lps_ptime, 24), PV_LEFT },
|
||||
{ DRDATA (STIME, lps_stime, 24), PV_LEFT },
|
||||
{ DRDATA (RTIME, lps_rtime, 24), PV_LEFT },
|
||||
{ FLDATA (TIMING, lps_timing, 0), REG_HRO },
|
||||
{ ORDATA (SC, lps_dib.select_code, 6), REG_HRO },
|
||||
{ ORDATA (DEVNO, lps_dib.select_code, 6), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB lps_mod[] = {
|
||||
{ UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", NULL },
|
||||
{ UNIT_DIAG, 0, "printer mode", "PRINTER", NULL },
|
||||
{ UNIT_POWEROFF, UNIT_POWEROFF, "power off", "POWEROFF", lps_poweroff },
|
||||
{ UNIT_POWEROFF, 0, "power on", "POWERON", lps_poweron },
|
||||
{ UNIT_OFFLINE, UNIT_OFFLINE, "offline", "OFFLINE", NULL },
|
||||
{ UNIT_OFFLINE, 0, "online", "ONLINE", lps_restart },
|
||||
{ MTAB_XTD | MTAB_VDV, 0, NULL, "REALTIME",
|
||||
&lps_set_timing, NULL, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 1, NULL, "FASTTIME",
|
||||
&lps_set_timing, NULL, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 0, "TIMING", NULL,
|
||||
NULL, &lps_show_timing, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 0, "SC", "SC", &hp_setsc, &hp_showsc, &lps_dev },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &lps_dev },
|
||||
static MTAB lps_mod[] = {
|
||||
/* Mask Value Match Value Print String Match String Validation Display Descriptor */
|
||||
/* ------------- ------------- ----------------- ------------- ------------------ ------- ---------- */
|
||||
{ UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAGNOSTIC", NULL, NULL, NULL },
|
||||
{ UNIT_DIAG, 0, "printer mode", "PRINTER", NULL, NULL, NULL },
|
||||
|
||||
{ UNIT_OFFLINE, UNIT_OFFLINE, "offline", "OFFLINE", NULL, NULL, NULL },
|
||||
{ UNIT_OFFLINE, 0, "online", "ONLINE", &lps_restart, NULL, NULL },
|
||||
|
||||
{ UNIT_POWEROFF, UNIT_POWEROFF, "power off", "POWEROFF", &lps_poweroff, NULL, NULL },
|
||||
{ UNIT_POWEROFF, 0, "power on", "POWERON", &lps_poweron, NULL, NULL },
|
||||
|
||||
/* Entry Flags Value Print String Match String Validation Display Descriptor */
|
||||
/* ------------------- ----- ------------ ------------ ---------------- ----------------- ----------------- */
|
||||
{ MTAB_XDV, 1, NULL, "FASTTIME", &lps_set_timing, NULL, NULL },
|
||||
{ MTAB_XDV, 0, NULL, "REALTIME", &lps_set_timing, NULL, NULL },
|
||||
{ MTAB_XDV, 0, "TIMING", NULL, NULL, &lps_show_timing, NULL },
|
||||
|
||||
{ MTAB_XDV, 1u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &lps_dib },
|
||||
{ MTAB_XDV | MTAB_NMO, ~1u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &lps_dib },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static DEBTAB lps_deb [] = {
|
||||
{ "CMDS", DEB_CMDS },
|
||||
{ "CPU", DEB_CPU },
|
||||
{ "XFER", DEB_XFER },
|
||||
{ "STATE", TRACE_STATE },
|
||||
{ "IOBUS", TRACE_IOBUS }, /* interface I/O bus signals and data words */
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
DEVICE lps_dev = {
|
||||
"LPS", &lps_unit, lps_reg, lps_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &lps_reset,
|
||||
NULL, &lps_attach, NULL,
|
||||
&lps_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG
|
||||
"LPS", /* device name */
|
||||
&lps_unit, /* unit array */
|
||||
lps_reg, /* register array */
|
||||
lps_mod, /* modifier array */
|
||||
1, /* number of units */
|
||||
10, /* address radix */
|
||||
31, /* address width */
|
||||
1, /* address increment */
|
||||
8, /* data radix */
|
||||
8, /* data width */
|
||||
NULL, /* examine routine */
|
||||
NULL, /* deposit routine */
|
||||
&lps_reset, /* reset routine */
|
||||
NULL, /* boot routine */
|
||||
&lps_attach, /* attach routine */
|
||||
NULL, /* detach routine */
|
||||
&lps_dib, /* device information block */
|
||||
DEV_DISABLE | DEV_DIS | DEV_DEBUG, /* device flags */
|
||||
0, /* debug control flags */
|
||||
lps_deb, /* debug flag name table */
|
||||
NULL, /* memory size change routine */
|
||||
NULL /* logical device name */
|
||||
};
|
||||
|
||||
|
||||
@@ -288,9 +341,9 @@ DEVICE lps_dev = {
|
||||
assertion of STC and CLC simultaneously will not.
|
||||
*/
|
||||
|
||||
uint32 lpsio (DIB *dibptr, IOCYCLE signal_set, uint32 stat_data)
|
||||
static uint32 lpsio (DIB *dibptr, IOCYCLE signal_set, uint32 stat_data)
|
||||
{
|
||||
int32 sched;
|
||||
int32 current_line, current_char;
|
||||
IOSIGNAL signal;
|
||||
IOCYCLE working_set = IOADDSIR (signal_set); /* add ioSIR if needed */
|
||||
|
||||
@@ -335,18 +388,17 @@ while (working_set) {
|
||||
lps_sta = LPS_PWROFF;
|
||||
}
|
||||
|
||||
stat_data = IORETURN (SCPE_OK, lps_sta); /* diag, rtn status */
|
||||
stat_data = IORETURN (SCPE_OK, lps_sta); /* diag, rtn status */
|
||||
|
||||
if (DEBUG_PRS (lps_dev))
|
||||
fprintf (sim_deb, ">>LPS LIx: Status %06o returned\n", lps_sta);
|
||||
tprintf (lps_dev, DEB_CPU, "Status %06o returned\n", lps_sta);
|
||||
break;
|
||||
|
||||
|
||||
case ioIOO: /* I/O data output */
|
||||
lps_unit.buf = IODATA (stat_data);
|
||||
|
||||
if (DEBUG_PRS (lps_dev))
|
||||
fprintf (sim_deb, ">>LPS OTx: Character %06o output\n", lps_unit.buf);
|
||||
tprintf (lps_dev, DEB_CPU, "Control %06o (%s) output\n",
|
||||
lps_unit.buf, fmt_char (lps_unit.buf & DATA_MASK));
|
||||
break;
|
||||
|
||||
|
||||
@@ -381,48 +433,47 @@ while (working_set) {
|
||||
}
|
||||
|
||||
else { /* real lpt, sched */
|
||||
if (DEBUG_PRS (lps_dev)) fprintf (sim_deb,
|
||||
">>LPS STC: Character %06o scheduled for line %d, column %d, ",
|
||||
lps_unit.buf, lps_lcnt + 1, lps_ccnt + 1);
|
||||
current_char = lps_ccnt + 1;
|
||||
current_line = lps_lcnt + 1;
|
||||
|
||||
if ((lps_unit.buf != '\f') &&
|
||||
(lps_unit.buf != '\n') &&
|
||||
(lps_unit.buf != '\r')) { /* normal char */
|
||||
if ((lps_unit.buf != FF) &&
|
||||
(lps_unit.buf != LF) &&
|
||||
(lps_unit.buf != CR)) { /* normal char */
|
||||
lps_ccnt = lps_ccnt + 1; /* incr char counter */
|
||||
if (lps_ccnt % LPS_ZONECNT == 0) /* end of zone? */
|
||||
sched = lps_ptime; /* print zone */
|
||||
lps_unit.wait = lps_ptime; /* print zone */
|
||||
else
|
||||
sched = lps_ctime; /* xfer char */
|
||||
lps_unit.wait = lps_ctime; /* xfer char */
|
||||
}
|
||||
|
||||
else { /* print cmd */
|
||||
if (lps_ccnt % LPS_ZONECNT == 0) /* last zone printed? */
|
||||
sched = lps_ctime; /* yes, so just char time */
|
||||
lps_unit.wait = lps_ctime; /* yes, so just char time */
|
||||
else
|
||||
sched = lps_ptime; /* no, so print needed */
|
||||
lps_unit.wait = lps_ptime; /* no, so print needed */
|
||||
|
||||
lps_ccnt = 0; /* reset char counter */
|
||||
|
||||
if (lps_unit.buf == '\n') { /* line advance */
|
||||
if (lps_unit.buf == LF) { /* line advance */
|
||||
lps_lcnt = (lps_lcnt + 1) % LPS_PAGELNT;
|
||||
|
||||
if (lps_lcnt > 0)
|
||||
sched = sched + lps_stime;
|
||||
lps_unit.wait += lps_stime;
|
||||
else
|
||||
sched = sched + /* allow for perf skip */
|
||||
lps_stime * (LPS_FORMLNT - LPS_PAGELNT);
|
||||
lps_unit.wait += /* allow for perf skip */
|
||||
lps_stime * (LPS_FORMLNT - LPS_PAGELNT);
|
||||
}
|
||||
|
||||
else if (lps_unit.buf == '\f') { /* form advance */
|
||||
sched = sched + lps_stime * (LPS_FORMLNT - lps_lcnt);
|
||||
else if (lps_unit.buf == FF) { /* form advance */
|
||||
lps_unit.wait += lps_stime * (LPS_FORMLNT - lps_lcnt);
|
||||
lps_lcnt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
sim_activate (&lps_unit, sched);
|
||||
sim_activate (&lps_unit, lps_unit.wait);
|
||||
|
||||
if (DEBUG_PRS (lps_dev))
|
||||
fprintf (sim_deb, "time = %d\n", sched);
|
||||
tprintf (lps_dev, DEB_CMDS, "Character %s scheduled for line %d, column %d, time = %d\n",
|
||||
fmt_char (lps_unit.buf & DATA_MASK), current_line, current_char, lps_unit.wait);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -450,66 +501,78 @@ return stat_data;
|
||||
}
|
||||
|
||||
|
||||
/* Unit service */
|
||||
/* Unit service.
|
||||
|
||||
t_stat lps_svc (UNIT *uptr)
|
||||
As a convenience to the user, the printer output file is flushed when a TOF
|
||||
operation is performed.
|
||||
*/
|
||||
|
||||
static t_stat lps_svc (UNIT *uptr)
|
||||
{
|
||||
int32 c = uptr->buf & 0177;
|
||||
int32 c = uptr->buf & DATA_MASK;
|
||||
|
||||
if (lps_power == LPS_TURNING_ON) { /* printer warmed up? */
|
||||
lps_power = LPS_ON; /* change state */
|
||||
lps_restart (uptr, 0, NULL, NULL); /* restart I/O if hung */
|
||||
if (DEBUG_PRS (lps_dev))
|
||||
fputs (">>LPS svc: Power state is ON\n", sim_deb);
|
||||
tprintf (lps_dev, TRACE_STATE, "Power state is ON\n");
|
||||
return SCPE_OK; /* done */
|
||||
}
|
||||
|
||||
if (uptr->flags & UNIT_DIAG) { /* diagnostic? */
|
||||
lpsio (&lps_dib, ioENF, 0); /* set flag */
|
||||
return SCPE_OK; /* done */
|
||||
}
|
||||
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
|
||||
return IOERROR (lps_stopioe, SCPE_UNATT);
|
||||
else if (uptr->flags & UNIT_OFFLINE) /* offline? */
|
||||
return IOERROR (lps_stopioe, STOP_OFFLINE);
|
||||
else if (uptr->flags & UNIT_POWEROFF) /* powered off? */
|
||||
return IOERROR (lps_stopioe, STOP_PWROFF);
|
||||
|
||||
if ((uptr->flags & (UNIT_ATT | UNIT_OFFLINE | UNIT_POWEROFF)) != UNIT_ATT) /* not ready? */
|
||||
return SCPE_OK;
|
||||
|
||||
lpsio (&lps_dib, ioENF, 0); /* set flag */
|
||||
|
||||
if (((c < ' ') || (c > '_')) && /* non-printing char? */
|
||||
(c != '\f') && (c != '\n') && (c != '\r')) {
|
||||
if (DEBUG_PRS (lps_dev))
|
||||
fprintf (sim_deb, ">>LPS svc: Character %06o erased\n", c);
|
||||
(c != FF) && (c != LF) && (c != CR)) {
|
||||
tprintf (lps_dev, DEB_XFER, "Character %s erased\n", fmt_char (c));
|
||||
c = ' '; /* replace with blank */
|
||||
}
|
||||
|
||||
if (lps_ccnt > LPS_PAGECNT) { /* 81st character? */
|
||||
fputc ('\r', uptr->fileref); /* return to line start */
|
||||
fputc (CR, uptr->fileref); /* return to line start */
|
||||
uptr->pos = uptr->pos + 1; /* update pos */
|
||||
lps_ccnt = 1; /* reset char counter */
|
||||
if (DEBUG_PRS (lps_dev))
|
||||
fputs (">>LPS svc: Line wraparound to column 1\n", sim_deb);
|
||||
tprintf (lps_dev, DEB_XFER, "Line wraparound to column 1\n");
|
||||
}
|
||||
|
||||
fputc (c, uptr->fileref); /* "print" char */
|
||||
uptr->pos = uptr->pos + 1; /* update pos */
|
||||
if (DEBUG_PRS (lps_dev))
|
||||
fprintf (sim_deb, ">>LPS svc: Character %06o printed\n", c);
|
||||
if ((lps_lcnt == 0) && (c == '\n')) { /* LF did TOF? */
|
||||
fputc ('\f', uptr->fileref); /* do perf skip */
|
||||
uptr->pos = uptr->pos + 1; /* update pos */
|
||||
if (DEBUG_PRS (lps_dev))
|
||||
fputs (">>LPS svc: Perforation skip to TOF\n", sim_deb);
|
||||
|
||||
tprintf (lps_dev, DEB_XFER, "Character %s printed\n", fmt_char (c));
|
||||
|
||||
if (lps_lcnt == 0) { /* if the printer is at the TOF */
|
||||
fflush (uptr->fileref); /* then flush the file buffer for inspection */
|
||||
|
||||
if (c == LF) { /* LF did TOF? */
|
||||
fputc (FF, uptr->fileref); /* do perf skip */
|
||||
uptr->pos = uptr->pos + 1; /* update pos */
|
||||
tprintf (lps_dev, DEB_XFER, "Perforation skip to TOF\n");
|
||||
}
|
||||
}
|
||||
if (ferror (uptr->fileref)) {
|
||||
perror ("LPS I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
|
||||
if (ferror (uptr->fileref)) { /* if a host file I/O error occurred */
|
||||
cprintf ("%s simulator printer I/O error: %s\n", /* then report the error to the console */
|
||||
sim_name, strerror (errno));
|
||||
|
||||
clearerr (uptr->fileref); /* clear the error */
|
||||
|
||||
lps_unit.flags |= UNIT_OFFLINE; /* set offline */
|
||||
return SCPE_IOERR;
|
||||
}
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat lps_reset (DEVICE *dptr)
|
||||
static t_stat lps_reset (DEVICE *dptr)
|
||||
{
|
||||
if (sim_switches & SWMASK ('P')) { /* power-on reset? */
|
||||
lps_power = LPS_ON; /* power is on */
|
||||
@@ -538,7 +601,7 @@ return SCPE_OK;
|
||||
original I/O request.
|
||||
*/
|
||||
|
||||
t_stat lps_restart (UNIT *uptr, int32 value, CONST char *cptr, void *desc)
|
||||
static t_stat lps_restart (UNIT *uptr, int32 value, CONST char *cptr, void *desc)
|
||||
{
|
||||
if (lps.control && !sim_is_active (uptr))
|
||||
sim_activate (uptr, 0); /* reschedule I/O */
|
||||
@@ -547,40 +610,68 @@ return SCPE_OK;
|
||||
|
||||
/* Printer power off */
|
||||
|
||||
t_stat lps_poweroff (UNIT *uptr, int32 value, CONST char *cptr, void *desc)
|
||||
static t_stat lps_poweroff (UNIT *uptr, int32 value, CONST char *cptr, void *desc)
|
||||
{
|
||||
lps_power = LPS_OFF; /* change state */
|
||||
if (DEBUG_PRS (lps_dev)) fputs (">>LPS set: Power state is OFF\n", sim_deb);
|
||||
tprintf (lps_dev, TRACE_STATE, "Power state is OFF\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Printer power on */
|
||||
|
||||
t_stat lps_poweron (UNIT *uptr, int32 value, CONST char *cptr, void *desc)
|
||||
static t_stat lps_poweron (UNIT *uptr, int32 value, CONST char *cptr, void *desc)
|
||||
{
|
||||
if (lps_unit.flags & UNIT_DIAG) { /* diag mode? */
|
||||
lps_power = LPS_ON; /* no delay */
|
||||
if (DEBUG_PRS (lps_dev))
|
||||
fputs (">>LPS set: Power state is ON\n", sim_deb);
|
||||
tprintf (lps_dev, TRACE_STATE, "Power state is ON\n");
|
||||
}
|
||||
else {
|
||||
lps_power = LPS_TURNING_ON; /* change state */
|
||||
lps_unit.flags |= UNIT_OFFLINE; /* set offline */
|
||||
sim_activate (&lps_unit, lps_rtime); /* schedule ready */
|
||||
if (DEBUG_PRS (lps_dev)) fprintf (sim_deb,
|
||||
">>LPS set: Power state is TURNING ON, scheduled time = %d\n",
|
||||
lps_rtime );
|
||||
tprintf (lps_dev, TRACE_STATE, "Power state is TURNING ON, scheduled time = %d\n",
|
||||
lps_rtime);
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Attach routine */
|
||||
/* Attach the printer image file.
|
||||
|
||||
t_stat lps_attach (UNIT *uptr, CONST char *cptr)
|
||||
The specified file is attached to the indicated unit. This is the simulation
|
||||
equivalent of loading paper into the printer and pressing the ONLINE button.
|
||||
The transition from offline to online typically generates an interrupt.
|
||||
|
||||
A new image file may be requested by giving the "-N" switch to the ATTACH
|
||||
command. If an existing file is specified with "-N", it will be cleared; if
|
||||
specified without "-N", printer output will be appended to the end of the
|
||||
existing file content. In all cases, the paper is positioned at the top of
|
||||
the form.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. If we are called during a RESTORE command to reattach a file previously
|
||||
attached when the simulation was SAVEd, the device status and file
|
||||
position are not altered. This is because SIMH 4.x restores the register
|
||||
contents before reattaching, while 3.x reattaches before restoring the
|
||||
registers.
|
||||
*/
|
||||
|
||||
static t_stat lps_attach (UNIT *uptr, CONST char *cptr)
|
||||
{
|
||||
lps_ccnt = lps_lcnt = 0; /* top of form */
|
||||
lps_restart (uptr, 0, NULL, NULL); /* restart I/O if hung */
|
||||
return attach_unit (uptr, cptr);
|
||||
t_stat result;
|
||||
|
||||
result = hp_attach (uptr, cptr); /* attach the specified printer image file for appending */
|
||||
|
||||
if (result == SCPE_OK /* if the attach was successful */
|
||||
&& (sim_switches & SIM_SW_REST) == 0) { /* and we are not being called during a RESTORE command */
|
||||
lps_ccnt = 0; /* then clear the character counter */
|
||||
lps_lcnt = 0; /* and set top of form */
|
||||
|
||||
lps_restart (uptr, 0, NULL, NULL); /* restart I/O if hung */
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Set printer timing
|
||||
@@ -588,7 +679,7 @@ return attach_unit (uptr, cptr);
|
||||
Realistic timing is factored, depending on CPU model, to account for the
|
||||
timing method employed by the diagnostic. */
|
||||
|
||||
t_stat lps_set_timing (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
||||
static t_stat lps_set_timing (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
||||
{
|
||||
uint32 i, factor = 1;
|
||||
|
||||
@@ -604,7 +695,7 @@ return SCPE_OK;
|
||||
|
||||
/* Show printer timing */
|
||||
|
||||
t_stat lps_show_timing (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
|
||||
static t_stat lps_show_timing (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
|
||||
{
|
||||
if (lps_timing) fputs ("fast timing", st);
|
||||
else fputs ("realistic timing", st);
|
||||
|
||||
2230
HP2100/hp2100_lpt.c
2230
HP2100/hp2100_lpt.c
File diff suppressed because it is too large
Load Diff
3189
HP2100/hp2100_mpx.c
3189
HP2100/hp2100_mpx.c
File diff suppressed because it is too large
Load Diff
@@ -1,31 +1,42 @@
|
||||
/* hp2100_ms.c: HP 2100 13181A/13183A magnetic tape simulator
|
||||
/* hp2100_ms.c: HP 2100 13181B/13183B Digital Magnetic Tape Unit Interface simulator
|
||||
|
||||
Copyright (c) 1993-2016, Robert M. Supnik
|
||||
Copyright (c) 2017-2018, J. David Bryan
|
||||
|
||||
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:
|
||||
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.
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHOR 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
|
||||
Except as contained in this notice, the names of the authors 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.
|
||||
in this Software without prior written authorization from the authors.
|
||||
|
||||
MS 13181A 7970B 800bpi nine track magnetic tape
|
||||
13183A 7970E 1600bpi nine track magnetic tape
|
||||
MS 13181B Digital Magnetic Tape Unit Interface
|
||||
13183B Digital Magnetic Tape Unit Interface
|
||||
|
||||
28-Feb-18 JDB Added the BMTL
|
||||
23-Feb-18 JDB Eliminated "msc_boot" references to A and S registers
|
||||
20-Jul-17 JDB Removed "msc_stopioe" variable and register
|
||||
11-Jul-17 JDB Renamed "ibl_copy" to "cpu_ibl"
|
||||
15-Mar-17 JDB Trace flags are now global
|
||||
Changed DEBUG_PRI calls to tprintfs
|
||||
13-Mar-17 JDB Deprecated LOCKED/WRITEENABLED for ATTACH -R
|
||||
10-Mar-17 JDB Added IOBUS to the debug table
|
||||
27-Feb-17 JDB ibl_copy no longer returns a status code
|
||||
17-Jan-17 JDB Modified to use "odd_parity" array in hp2100_sys.c
|
||||
13-May-16 JDB Modified for revised SCP API function parameter types
|
||||
30-Dec-14 JDB Added S-register parameters to ibl_copy
|
||||
24-Dec-14 JDB Use T_ADDR_FMT with t_addr values for 64-bit compatibility
|
||||
@@ -75,18 +86,22 @@
|
||||
22-Apr-02 RMS Added maximum record length test
|
||||
|
||||
References:
|
||||
- 13181B Digital Magnetic Tape Unit Interface Kit Operating and Service Manual
|
||||
(13181-90901, Nov-1982)
|
||||
- 13183B Digital Magnetic Tape Unit Interface Kit Operating and Service Manual
|
||||
(13183-90901, Nov-1983)
|
||||
- SIMH Magtape Representation and Handling (Bob Supnik, 30-Aug-2006)
|
||||
- 13181B Digital Magnetic Tape Unit Interface Kit Operating and Service Manual
|
||||
(13181-90901, November 1982)
|
||||
- 13183B Digital Magnetic Tape Unit Interface Kit Operating and Service Manual
|
||||
(13183-90901, November 1983)
|
||||
- SIMH Magtape Representation and Handling
|
||||
(Bob Supnik, 30-Aug-2006)
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "hp2100_defs.h"
|
||||
#include "hp2100_cpu.h"
|
||||
#include "sim_tape.h"
|
||||
|
||||
|
||||
|
||||
#define UNIT_V_OFFLINE (MTUF_V_UF + 0) /* unit offline */
|
||||
#define UNIT_OFFLINE (1 << UNIT_V_OFFLINE)
|
||||
|
||||
@@ -103,12 +118,6 @@
|
||||
#define GAP_13183 30 /* gap is 3.0 inches for 13183 cntlr */
|
||||
#define TCAP (300 * 12 * 800) /* 300 ft capacity at 800 bpi */
|
||||
|
||||
/* Debug flags */
|
||||
|
||||
#define DEB_CMDS (1 << 0) /* command init and compl */
|
||||
#define DEB_CPU (1 << 1) /* CPU I/O */
|
||||
#define DEB_RWS (1 << 2) /* tape reads, writes, status */
|
||||
|
||||
/* Command - msc_fnc */
|
||||
|
||||
#define FNC_CLR 00110 /* clear */
|
||||
@@ -180,7 +189,6 @@ int32 msc_sta = 0; /* status */
|
||||
int32 msc_buf = 0; /* buffer */
|
||||
int32 msc_usl = 0; /* unit select */
|
||||
int32 msc_1st = 0; /* first service */
|
||||
int32 msc_stopioe = 1; /* stop on error */
|
||||
|
||||
struct {
|
||||
FLIP_FLOP control; /* control flip-flop */
|
||||
@@ -220,12 +228,12 @@ int32 msc_xtime = 0; /* data xfer time / word
|
||||
|
||||
typedef int32 TIMESET[6]; /* set of controller times */
|
||||
|
||||
int32 *const timers[] = { &msc_btime, &msc_ctime, &msc_gtime,
|
||||
&msc_itime, &msc_rtime, &msc_xtime };
|
||||
int32 *const timers [] = { &msc_btime, &msc_ctime, &msc_gtime,
|
||||
&msc_itime, &msc_rtime, &msc_xtime };
|
||||
|
||||
const TIMESET msc_times[3] = {
|
||||
{ 161512, 14044, 175553, 24885, 878, 88 }, /* 13181A */
|
||||
{ 252800, 17556, 105333, 27387, 878, 44 }, /* 13183A */
|
||||
const TIMESET msc_times [3] = {
|
||||
{ 161512, 14044, 175553, 24885, 878, 88 }, /* 13181B */
|
||||
{ 252800, 17556, 105333, 27387, 878, 44 }, /* 13183B */
|
||||
{ 1, 1000, 1, 1, 100, 10 } /* FAST */
|
||||
};
|
||||
|
||||
@@ -284,9 +292,11 @@ REG msd_reg[] = {
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB msd_mod[] = {
|
||||
{ MTAB_XTD | MTAB_VDV, 1, "SC", "SC", &hp_setsc, &hp_showsc, &msd_dev },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &msd_dev },
|
||||
MTAB msd_mod [] = {
|
||||
/* Entry Flags Value Print String Match String Validation Display Descriptor */
|
||||
/* ------------------- ----- ------------ ------------ ------------ ------------- ---------------- */
|
||||
{ MTAB_XDV, 2u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &ms_dib },
|
||||
{ MTAB_XDV | MTAB_NMO, ~2u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &ms_dib },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
@@ -337,46 +347,67 @@ REG msc_reg[] = {
|
||||
{ DRDATA (RTIME, msc_rtime, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (XTIME, msc_xtime, 24), REG_NZ + PV_LEFT },
|
||||
{ FLDATA (TIMING, ms_timing, 0), REG_HRO },
|
||||
{ FLDATA (STOP_IOE, msc_stopioe, 0) },
|
||||
{ FLDATA (CTYPE, ms_ctype, 0), REG_HRO },
|
||||
{ ORDATA (SC, msc_dib.select_code, 6), REG_HRO },
|
||||
{ ORDATA (DEVNO, msc_dib.select_code, 6), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB msc_mod[] = {
|
||||
{ UNIT_OFFLINE, UNIT_OFFLINE, "offline", "OFFLINE", NULL },
|
||||
{ UNIT_OFFLINE, 0, "online", "ONLINE", msc_online },
|
||||
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
|
||||
{ MTAB_XTD | MTAB_VUN, 0, "CAPACITY", "CAPACITY",
|
||||
&ms_set_reelsize, &ms_show_reelsize, NULL },
|
||||
{ MTAB_XTD | MTAB_VUN | MTAB_NMO, 1, "REEL", "REEL",
|
||||
&ms_set_reelsize, &ms_show_reelsize, NULL },
|
||||
{ MTAB_XTD | MTAB_VUN, 0, "FORMAT", "FORMAT",
|
||||
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 0, NULL, "13181A",
|
||||
&ms_settype, NULL, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 1, NULL, "13183A",
|
||||
&ms_settype, NULL, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 0, "TYPE", NULL,
|
||||
NULL, &ms_showtype, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 0, NULL, "REALTIME",
|
||||
&ms_set_timing, NULL, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 1, NULL, "FASTTIME",
|
||||
&ms_set_timing, NULL, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 0, "TIMING", NULL,
|
||||
NULL, &ms_show_timing, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 1, "SC", "SC", &hp_setsc, &hp_showsc, &msd_dev },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &msd_dev },
|
||||
/* Modifier list.
|
||||
|
||||
The LOCKED and WRITEENABLED modifiers are deprecated. The supported method
|
||||
of write-protecting a tape drive is to attach the tape image with the -R
|
||||
(read-only) switch or by setting the host operating system's read-only
|
||||
attribute on the tape image file. This simulates removing the write ring
|
||||
from the tape reel before mounting it on the drive. There is no hardware
|
||||
method of write-protecting a mounted and positioned tape reel.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. The UNIT_RO modifier displays "write ring" if the flag is not set. There
|
||||
is no corresponding entry for the opposite condition because "read only"
|
||||
is automatically printed after the attached filename.
|
||||
*/
|
||||
|
||||
MTAB msc_mod [] = {
|
||||
/* Mask Value Match Value Print String Match String Validation Display Descriptor */
|
||||
/* ------------- ------------- ---------------- --------------- ------------ ------- ---------- */
|
||||
{ UNIT_RO, 0, "write ring", NULL, NULL, NULL, NULL },
|
||||
|
||||
{ UNIT_OFFLINE, UNIT_OFFLINE, "offline", "OFFLINE", NULL, NULL, NULL },
|
||||
{ UNIT_OFFLINE, 0, "online", "ONLINE", &msc_online, NULL, NULL },
|
||||
|
||||
{ MTUF_WLK, 0, NULL, "WRITEENABLED", NULL, NULL, NULL },
|
||||
{ MTUF_WLK, MTUF_WLK, NULL, "LOCKED", NULL, NULL, NULL },
|
||||
|
||||
|
||||
/* Entry Flags Value Print String Match String Validation Display Descriptor */
|
||||
/* ------------------- ----- ------------ ------------ ----------------- ------------------ ---------------- */
|
||||
{ MTAB_XUN, 0, "CAPACITY", "CAPACITY", &ms_set_reelsize, &ms_show_reelsize, NULL },
|
||||
{ MTAB_XUN | MTAB_NMO, 1, "REEL", "REEL", &ms_set_reelsize, &ms_show_reelsize, NULL },
|
||||
{ MTAB_XUN, 0, "FORMAT", "FORMAT", &sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
|
||||
|
||||
{ MTAB_XDV, 0, NULL, "13181A/B", &ms_settype, NULL, NULL },
|
||||
{ MTAB_XDV, 1, NULL, "13183A/B", &ms_settype, NULL, NULL },
|
||||
{ MTAB_XDV, 0, "TYPE", NULL, NULL, &ms_showtype, NULL },
|
||||
|
||||
{ MTAB_XDV, 0, NULL, "REALTIME", &ms_set_timing, NULL, NULL },
|
||||
{ MTAB_XDV, 1, NULL, "FASTTIME", &ms_set_timing, NULL, NULL },
|
||||
{ MTAB_XDV, 0, "TIMING", NULL, NULL, &ms_show_timing, NULL },
|
||||
|
||||
{ MTAB_XDV, 2u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &ms_dib },
|
||||
{ MTAB_XDV | MTAB_NMO, ~2u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &ms_dib },
|
||||
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEBTAB msc_deb[] = {
|
||||
{ "CMDS", DEB_CMDS },
|
||||
{ "CPU", DEB_CPU },
|
||||
{ "RWS", DEB_RWS },
|
||||
{ NULL, 0 }
|
||||
{ "CMDS", DEB_CMDS },
|
||||
{ "RWS", DEB_RWS },
|
||||
{ "CPU", DEB_CPU },
|
||||
{ "IOBUS", TRACE_IOBUS }, /* interface I/O bus signals and data words */
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
DEVICE msc_dev = {
|
||||
@@ -554,11 +585,10 @@ while (working_set) {
|
||||
else
|
||||
data = data | STA_TBSY | STA_LOCAL;
|
||||
|
||||
if (ms_ctype == A13183) /* 13183A? */
|
||||
if (ms_ctype == A13183) /* 13183? */
|
||||
data = data | STA_PE | (uint16) (msc_usl << STA_V_SEL);
|
||||
|
||||
if (DEBUG_PRI (msc_dev, DEB_CPU))
|
||||
fprintf (sim_deb, ">>MSC LIx: Status = %06o\n", data);
|
||||
tprintf (msc_dev, DEB_CPU, "Status = %06o\n", data);
|
||||
|
||||
stat_data = IORETURN (SCPE_OK, data); /* merge in return status */
|
||||
break;
|
||||
@@ -567,8 +597,7 @@ while (working_set) {
|
||||
case ioIOO: /* I/O data output */
|
||||
msc_buf = IODATA (stat_data); /* clear supplied status */
|
||||
|
||||
if (DEBUG_PRI (msc_dev, DEB_CPU))
|
||||
fprintf (sim_deb, ">>MSC OTx: Command = %06o\n", msc_buf);
|
||||
tprintf (msc_dev, DEB_CPU, "Command = %06o\n", msc_buf);
|
||||
|
||||
msc_sta = msc_sta & ~STA_REJ; /* clear reject */
|
||||
|
||||
@@ -583,8 +612,7 @@ while (working_set) {
|
||||
if (msc_buf & FNF_CHS) { /* select change */
|
||||
msc_usl = map_sel[FNC_GETSEL (msc_buf)]; /* is immediate */
|
||||
uptr = msc_dev.units + msc_usl;
|
||||
if (DEBUG_PRI (msc_dev, DEB_CMDS))
|
||||
fprintf (sim_deb, ">>MSC OTx: Unit %d selected\n", msc_usl);
|
||||
tprintf (msc_dev, DEB_CMDS, "Unit %d selected\n", msc_usl);
|
||||
}
|
||||
|
||||
if (((msc_buf & FNF_MOT) && sim_is_active (uptr)) ||
|
||||
@@ -614,8 +642,7 @@ while (working_set) {
|
||||
|
||||
working_set = working_set & ~ioCLF; /* eliminate possible CLF */
|
||||
|
||||
if (DEBUG_PRI (msc_dev, DEB_CMDS))
|
||||
fputs (">>MSC STC: Controller cleared\n", sim_deb);
|
||||
tprintf (msc_dev, DEB_CMDS, "Controller cleared\n");
|
||||
|
||||
break; /* command completes immediately */
|
||||
}
|
||||
@@ -645,16 +672,14 @@ while (working_set) {
|
||||
if (msc_buf & ~FNC_SEL) { /* NOP for unit sel alone */
|
||||
sim_activate (uptr, sched_time); /* else schedule op */
|
||||
|
||||
if (DEBUG_PRI (msc_dev, DEB_CMDS))
|
||||
fprintf (sim_deb,
|
||||
">>MSC STC: Unit %d command %03o (%s) scheduled, "
|
||||
"pos = %" T_ADDR_FMT "d, time = %d\n",
|
||||
msc_usl, uptr->FNC, ms_cmd_name (uptr->FNC),
|
||||
uptr->pos, sched_time);
|
||||
tprintf (msc_dev, DEB_CMDS, "Unit %d command %03o (%s) scheduled, "
|
||||
"pos = %" T_ADDR_FMT "d, time = %d\n",
|
||||
msc_usl, uptr->FNC, ms_cmd_name (uptr->FNC),
|
||||
uptr->pos, sched_time);
|
||||
}
|
||||
|
||||
else if (DEBUG_PRI (msc_dev, DEB_CMDS))
|
||||
fputs (">>MSC STC: Unit select (NOP)\n", sim_deb);
|
||||
else
|
||||
tprintf (msc_dev, DEB_CMDS, "Unit select (NOP)\n");
|
||||
|
||||
msc_sta = STA_BUSY; /* ctrl is busy */
|
||||
msc_1st = 1;
|
||||
@@ -713,7 +738,7 @@ unum = uptr - msc_unit; /* get unit number */
|
||||
if ((uptr->FNC != FNC_RWS) && (uptr->flags & UNIT_OFFLINE)) { /* offline? */
|
||||
msc_sta = (msc_sta | STA_REJ) & ~STA_BUSY; /* reject */
|
||||
mscio (&msc_dib, ioENF, 0); /* set flag */
|
||||
return IOERROR (msc_stopioe, SCPE_UNATT);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
switch (uptr->FNC) { /* case on function */
|
||||
@@ -741,10 +766,8 @@ switch (uptr->FNC) { /* case on function */
|
||||
goto DO_WFM; /* do plain file mark */
|
||||
/* else fall into GAP */
|
||||
case FNC_GAP: /* erase gap */
|
||||
if (DEBUG_PRI (msc_dev, DEB_RWS))
|
||||
fprintf (sim_deb,
|
||||
">>MSC svc: Unit %d wrote gap\n",
|
||||
unum);
|
||||
tprintf (msc_dev, DEB_RWS, "Unit %d wrote gap\n", unum);
|
||||
|
||||
r = ms_write_gap (uptr); /* write tape gap*/
|
||||
|
||||
if (r || (uptr->FNC != FNC_GFM)) /* if error or not GFM */
|
||||
@@ -752,10 +775,8 @@ switch (uptr->FNC) { /* case on function */
|
||||
/* else drop into WFM */
|
||||
case FNC_WFM: /* write file mark */
|
||||
if ((ms_timing == 0) && sim_tape_bot (uptr)) { /* realistic timing + BOT? */
|
||||
if (DEBUG_PRI (msc_dev, DEB_RWS))
|
||||
fprintf (sim_deb,
|
||||
">>MSC svc: Unit %d wrote initial gap\n",
|
||||
unum);
|
||||
tprintf (msc_dev, DEB_RWS, "Unit %d wrote initial gap\n", unum);
|
||||
|
||||
st = ms_write_gap (uptr); /* write initial gap*/
|
||||
if (st != MTSE_OK) { /* error? */
|
||||
r = ms_map_err (uptr, st); /* map error */
|
||||
@@ -763,10 +784,8 @@ switch (uptr->FNC) { /* case on function */
|
||||
}
|
||||
}
|
||||
DO_WFM:
|
||||
if (DEBUG_PRI (msc_dev, DEB_RWS))
|
||||
fprintf (sim_deb,
|
||||
">>MSC svc: Unit %d wrote file mark\n",
|
||||
unum);
|
||||
tprintf (msc_dev, DEB_RWS, "Unit %d wrote file mark\n", unum);
|
||||
|
||||
st = sim_tape_wrtmk (uptr); /* write tmk */
|
||||
if (st != MTSE_OK) /* error? */
|
||||
r = ms_map_err (uptr, st); /* map error */
|
||||
@@ -808,10 +827,8 @@ switch (uptr->FNC) { /* case on function */
|
||||
if (msc_1st) { /* first svc? */
|
||||
msc_1st = ms_ptr = ms_max = 0; /* clr 1st flop */
|
||||
st = sim_tape_rdrecf (uptr, msxb, &ms_max, DBSIZE); /* read rec */
|
||||
if (DEBUG_PRI (msc_dev, DEB_RWS))
|
||||
fprintf (sim_deb,
|
||||
">>MSC svc: Unit %d read %d word record\n",
|
||||
unum, ms_max / 2);
|
||||
tprintf (msc_dev, DEB_RWS, "Unit %d read %d word record\n",
|
||||
unum, ms_max / 2);
|
||||
if (st == MTSE_RECE) msc_sta = msc_sta | STA_PAR; /* rec in err? */
|
||||
else if (st != MTSE_OK) { /* other error? */
|
||||
r = ms_map_err (uptr, st); /* map error */
|
||||
@@ -823,7 +840,7 @@ switch (uptr->FNC) { /* case on function */
|
||||
break; /* err, done */
|
||||
}
|
||||
if (ms_ctype == A13183)
|
||||
msc_sta = msc_sta | STA_ODD; /* set ODD for 13183A */
|
||||
msc_sta = msc_sta | STA_ODD; /* set ODD for 13183 */
|
||||
}
|
||||
if (msd.control && (ms_ptr < ms_max)) { /* DCH on, more data? */
|
||||
if (msd.flag) msc_sta = msc_sta | STA_TIM | STA_PAR;
|
||||
@@ -854,10 +871,8 @@ switch (uptr->FNC) { /* case on function */
|
||||
if (msc_1st) { /* first service? */
|
||||
msc_1st = ms_ptr = 0; /* no data xfer on first svc */
|
||||
if ((ms_timing == 0) && sim_tape_bot (uptr)) { /* realistic timing + BOT? */
|
||||
if (DEBUG_PRI (msc_dev, DEB_RWS))
|
||||
fprintf (sim_deb,
|
||||
">>MSC svc: Unit %d wrote initial gap\n",
|
||||
unum);
|
||||
tprintf (msc_dev, DEB_RWS, "Unit %d wrote initial gap\n", unum);
|
||||
|
||||
st = ms_write_gap (uptr); /* write initial gap */
|
||||
if (st != MTSE_OK) { /* error? */
|
||||
r = ms_map_err (uptr, st); /* map error */
|
||||
@@ -879,10 +894,8 @@ switch (uptr->FNC) { /* case on function */
|
||||
return SCPE_OK;
|
||||
}
|
||||
if (ms_ptr) { /* any data? write */
|
||||
if (DEBUG_PRI (msc_dev, DEB_RWS))
|
||||
fprintf (sim_deb,
|
||||
">>MSC svc: Unit %d wrote %d word record\n",
|
||||
unum, ms_ptr / 2);
|
||||
tprintf (msc_dev, DEB_RWS, "Unit %d wrote %d word record\n",
|
||||
unum, ms_ptr / 2);
|
||||
st = sim_tape_wrrecf (uptr, msxb, ms_ptr); /* write */
|
||||
if (st != MTSE_OK) {
|
||||
r = ms_map_err (uptr, st); /* map error */
|
||||
@@ -900,19 +913,16 @@ switch (uptr->FNC) { /* case on function */
|
||||
|
||||
case FNC_RRR: /* not supported */
|
||||
default: /* unknown command */
|
||||
if (DEBUG_PRI (msc_dev, DEB_CMDS))
|
||||
fprintf (sim_deb,
|
||||
">>MSC svc: Unit %d command %03o is unknown (NOP)\n",
|
||||
unum, uptr->FNC);
|
||||
tprintf (msc_dev, DEB_CMDS, "Unit %d command %03o is unknown (NOP)\n",
|
||||
unum, uptr->FNC);
|
||||
break;
|
||||
}
|
||||
|
||||
mscio (&msc_dib, ioENF, 0); /* set flag */
|
||||
msc_sta = msc_sta & ~STA_BUSY; /* update status */
|
||||
if (DEBUG_PRI (msc_dev, DEB_CMDS))
|
||||
fprintf (sim_deb,
|
||||
">>MSC svc: Unit %d command %03o (%s) complete\n",
|
||||
unum, uptr->FNC & 0377, ms_cmd_name (uptr->FNC));
|
||||
|
||||
tprintf (msc_dev, DEB_CMDS, "Unit %d command %03o (%s) complete\n",
|
||||
unum, uptr->FNC & 0377, ms_cmd_name (uptr->FNC));
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -939,10 +949,7 @@ t_stat ms_map_err (UNIT *uptr, t_stat st)
|
||||
{
|
||||
int32 unum = uptr - msc_unit; /* get unit number */
|
||||
|
||||
if (DEBUG_PRI (msc_dev, DEB_RWS))
|
||||
fprintf (sim_deb,
|
||||
">>MSC err: Unit %d tape library status = %d\n",
|
||||
unum, st);
|
||||
tprintf (msc_dev, DEB_RWS, "Unit %d tape library status = %d\n", unum, st);
|
||||
|
||||
switch (st) {
|
||||
|
||||
@@ -963,7 +970,7 @@ switch (st) {
|
||||
msc_sta = msc_sta | STA_EOF;
|
||||
|
||||
if (ms_ctype == A13181)
|
||||
msc_sta = msc_sta | STA_ODD; /* EOF also sets ODD for 13181A */
|
||||
msc_sta = msc_sta | STA_ODD; /* EOF also sets ODD for 13181B */
|
||||
break;
|
||||
|
||||
case MTSE_INVRL: /* invalid rec lnt */
|
||||
@@ -972,8 +979,7 @@ switch (st) {
|
||||
|
||||
case MTSE_IOERR: /* IO error */
|
||||
msc_sta = msc_sta | STA_PAR; /* error */
|
||||
if (msc_stopioe) return SCPE_IOERR;
|
||||
break;
|
||||
return SCPE_IOERR;
|
||||
|
||||
case MTSE_RECE: /* record in error */
|
||||
msc_sta = msc_sta | STA_PAR; /* error */
|
||||
@@ -1002,9 +1008,7 @@ for (i = 0; i < MS_NUMDR; i++) { /* look for write in pro
|
||||
if (sim_is_active (uptr) && /* unit active? */
|
||||
(uptr->FNC == FNC_WC) && /* and last cmd write? */
|
||||
(ms_ptr > 0)) { /* and partial buffer? */
|
||||
if (DEBUG_PRI (msc_dev, DEB_RWS))
|
||||
fprintf (sim_deb,
|
||||
">>MSC rws: Unit %d wrote %d word partial record\n", i, ms_ptr / 2);
|
||||
tprintf (msc_dev, DEB_RWS, "Unit %d wrote %d word partial record\n", i, ms_ptr / 2);
|
||||
|
||||
st = sim_tape_wrrecf (uptr, msxb, ms_ptr | MTR_ERF);
|
||||
|
||||
@@ -1143,9 +1147,9 @@ return SCPE_OK;
|
||||
t_stat ms_showtype (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
|
||||
{
|
||||
if (ms_ctype == A13183)
|
||||
fprintf (st, "13183A");
|
||||
fprintf (st, "13183B");
|
||||
else
|
||||
fprintf (st, "13181A");
|
||||
fprintf (st, "13181B");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
@@ -1237,120 +1241,240 @@ switch (cmd & 0377) {
|
||||
}
|
||||
}
|
||||
|
||||
/* 7970B/7970E bootstrap routine (HP 12992D ROM) */
|
||||
|
||||
const BOOT_ROM ms_rom = {
|
||||
0106501, /*ST LIB 1 ; read sw */
|
||||
0006011, /* SLB,RSS ; bit 0 set? */
|
||||
0027714, /* JMP RD ; no read */
|
||||
0003004, /* CMA,INA ; A is ctr */
|
||||
0073775, /* STA WC ; save */
|
||||
0067772, /* LDA SL0RW ; sel 0, rew */
|
||||
0017762, /*FF JSB CMD ; do cmd */
|
||||
0102311, /* SFS CC ; done? */
|
||||
0027707, /* JMP *-1 ; wait */
|
||||
0067774, /* LDB FFC ; get file fwd */
|
||||
0037775, /* ISZ WC ; done files? */
|
||||
0027706, /* JMP FF ; no */
|
||||
0067773, /*RD LDB RDCMD ; read cmd */
|
||||
0017762, /* JSB CMD ; do cmd */
|
||||
0103710, /* STC DC,C ; start dch */
|
||||
0102211, /* SFC CC ; read done? */
|
||||
0027752, /* JMP STAT ; no, get stat */
|
||||
0102310, /* SFS DC ; any data? */
|
||||
0027717, /* JMP *-3 ; wait */
|
||||
0107510, /* LIB DC,C ; get rec cnt */
|
||||
0005727, /* BLF,BLF ; move to lower */
|
||||
0007000, /* CMB ; make neg */
|
||||
0077775, /* STA WC ; save */
|
||||
0102211, /* SFC CC ; read done? */
|
||||
0027752, /* JMP STAT ; no, get stat */
|
||||
0102310, /* SFS DC ; any data? */
|
||||
0027727, /* JMP *-3 ; wait */
|
||||
0107510, /* LIB DC,C ; get load addr */
|
||||
0074000, /* STB 0 ; start csum */
|
||||
0077762, /* STA CMD ; save address */
|
||||
0027742, /* JMP *+4 */
|
||||
0177762, /*NW STB CMD,I ; store data */
|
||||
0040001, /* ADA 1 ; add to csum */
|
||||
0037762, /* ISZ CMD ; adv addr ptr */
|
||||
0102310, /* SFS DC ; any data? */
|
||||
0027742, /* JMP *-1 ; wait */
|
||||
0107510, /* LIB DC,C ; get word */
|
||||
0037775, /* ISZ WC ; done? */
|
||||
0027737, /* JMP NW ; no */
|
||||
0054000, /* CPB 0 ; csum ok? */
|
||||
0027717, /* JMP RD+3 ; yes, cont */
|
||||
0102011, /* HLT 11 ; no, halt */
|
||||
0102511, /*ST LIA CC ; get status */
|
||||
0001727, /* ALF,ALF ; get eof bit */
|
||||
0002020, /* SSA ; set? */
|
||||
0102077, /* HLT 77 ; done */
|
||||
0001727, /* ALF,ALF ; put status back */
|
||||
0001310, /* RAR,SLA ; read ok? */
|
||||
0102000, /* HLT 0 ; no */
|
||||
0027714, /* JMP RD ; read next */
|
||||
0000000, /*CMD 0 */
|
||||
0106611, /* OTB CC ; output cmd */
|
||||
0102511, /* LIA CC ; check for reject */
|
||||
0001323, /* RAR,RAR */
|
||||
0001310, /* RAR,SLA */
|
||||
0027763, /* JMP CMD+1 ; try again */
|
||||
0103711, /* STC CC,C ; start command */
|
||||
0127762, /* JMP CMD,I ; exit */
|
||||
0001501, /*SL0RW 001501 ; select 0, rewind */
|
||||
0001423, /*RDCMD 001423 ; read record */
|
||||
0000203, /*FFC 000203 ; space forward file */
|
||||
0000000, /*WC 000000 */
|
||||
0000000,
|
||||
0000000
|
||||
/* 7970B/7970E bootstrap loaders (BMTL and 12992D).
|
||||
|
||||
The Basic Magnetic Tape Loader (BMTL) reads an absolute binary program from
|
||||
tape into memory. Before execution, the S register must be set as follows:
|
||||
|
||||
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| - - - - - - - - - - | file number |
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
|
||||
If S-register bits 5-0 are zero, the file located at the current tape
|
||||
position is read. If the bits are non-zero, the tape is rewound, and the
|
||||
file number (1 - n) specified by the bits is read.
|
||||
|
||||
The 12992D boot loader ROM reads an absolute program from tape into memory.
|
||||
If S-register bit 0 is 0, the file located at the current tape position is
|
||||
read. If bit 0 is 1, the tape is rewound, and the file number (1 - n)
|
||||
specified by the A-register value is read.
|
||||
|
||||
For either loader, the tape format must be absolute binary, and a tape mark
|
||||
must end the file. Loader execution ends with one of the following
|
||||
instructions:
|
||||
|
||||
* HLT 00 - a tape read (parity) error occurred.
|
||||
* HLT 11 - a checksum error occurred; A/B = the calculated/tape value.
|
||||
* HLT 77 - the end of the file was reached with a successful read.
|
||||
*/
|
||||
|
||||
static const LOADER_ARRAY ms_loaders = {
|
||||
{ /* HP 21xx Basic Magnetic Tape Loader (BMTL) */
|
||||
000, /* loader starting index */
|
||||
IBL_NA, /* DMA index */
|
||||
IBL_NA, /* FWA index */
|
||||
{ 0102501, /* 77700: MTAPE LIA 1 */
|
||||
0013775, /* 77701: AND 77775 */
|
||||
0003007, /* 77702: CMA,INA,SZA,RSS */
|
||||
0027714, /* 77703: JMP 77714 */
|
||||
0073777, /* 77704: STA 77777 */
|
||||
0067771, /* 77705: LDB 77771 */
|
||||
0017761, /* 77706: JSB 77761 */
|
||||
0102311, /* 77707: SFS 11 */
|
||||
0027707, /* 77710: JMP 77707 */
|
||||
0067773, /* 77711: LDB 77773 */
|
||||
0037777, /* 77712: ISZ 77777 */
|
||||
0027706, /* 77713: JMP 77706 */
|
||||
0067772, /* 77714: LDB 77772 */
|
||||
0017761, /* 77715: JSB 77761 */
|
||||
0103710, /* 77716: STC 10,C */
|
||||
0017740, /* 77717: JSB 77740 */
|
||||
0005727, /* 77720: BLF,BLF */
|
||||
0007004, /* 77721: CMB,INB */
|
||||
0077777, /* 77722: STB 77777 */
|
||||
0017740, /* 77723: JSB 77740 */
|
||||
0074000, /* 77724: STB 0 */
|
||||
0077776, /* 77725: STB 77776 */
|
||||
0017740, /* 77726: JSB 77740 */
|
||||
0177776, /* 77727: STB 77776,I */
|
||||
0040001, /* 77730: ADA 1 */
|
||||
0037776, /* 77731: ISZ 77776 */
|
||||
0037777, /* 77732: ISZ 77777 */
|
||||
0027726, /* 77733: JMP 77726 */
|
||||
0017740, /* 77734: JSB 77740 */
|
||||
0054000, /* 77735: CPB 0 */
|
||||
0017740, /* 77736: JSB 77740 */
|
||||
0102011, /* 77737: HLT 11 */
|
||||
0000000, /* 77740: NOP */
|
||||
0102310, /* 77741: SFS 10 */
|
||||
0027745, /* 77742: JMP 77745 */
|
||||
0107510, /* 77743: LIB 10,C */
|
||||
0127740, /* 77744: JMP 77740,I */
|
||||
0102311, /* 77745: SFS 11 */
|
||||
0027741, /* 77746: JMP 77741 */
|
||||
0102511, /* 77747: LIA 11 */
|
||||
0013774, /* 77750: AND 77774 */
|
||||
0067777, /* 77751: LDB 77777 */
|
||||
0001727, /* 77752: ALF,ALF */
|
||||
0002020, /* 77753: SSA */
|
||||
0102077, /* 77754: HLT 77 */
|
||||
0002003, /* 77755: SZA,RSS */
|
||||
0006002, /* 77756: SZB */
|
||||
0102000, /* 77757: HLT 0 */
|
||||
0027714, /* 77760: JMP 77714 */
|
||||
0000000, /* 77761: NOP */
|
||||
0106611, /* 77762: OTB 11 */
|
||||
0102511, /* 77763: LIA 11 */
|
||||
0001323, /* 77764: RAR,RAR */
|
||||
0001310, /* 77765: RAR,SLA */
|
||||
0027762, /* 77766: JMP 77762 */
|
||||
0103711, /* 77767: STC 11,C */
|
||||
0127761, /* 77770: JMP 77761,I */
|
||||
0001501, /* 77771: OCT 1501 */
|
||||
0001423, /* 77772: OCT 1423 */
|
||||
0000203, /* 77773: OCT 203 */
|
||||
0016263, /* 77774: OCT 16263 */
|
||||
0000077, /* 77775: OCT 77 */
|
||||
0000000, /* 77776: NOP */
|
||||
0000000 } }, /* 77777: NOP */
|
||||
|
||||
{ /* HP 1000 Loader ROM (12992D) */
|
||||
IBL_START, /* loader starting index */
|
||||
IBL_DMA, /* DMA index */
|
||||
IBL_FWA, /* FWA index */
|
||||
{ 0106501, /* 77700: ST LIB 1 ; read sw */
|
||||
0006011, /* 77701: SLB,RSS ; bit 0 set? */
|
||||
0027714, /* 77702: JMP RD ; no read */
|
||||
0003004, /* 77703: CMA,INA ; A is ctr */
|
||||
0073775, /* 77704: STA WC ; save */
|
||||
0067772, /* 77705: LDA SL0RW ; sel 0, rew */
|
||||
0017762, /* 77706: FF JSB CMD ; do cmd */
|
||||
0102311, /* 77707: SFS CC ; done? */
|
||||
0027707, /* 77710: JMP *-1 ; wait */
|
||||
0067774, /* 77711: LDB FFC ; get file fwd */
|
||||
0037775, /* 77712: ISZ WC ; done files? */
|
||||
0027706, /* 77713: JMP FF ; no */
|
||||
0067773, /* 77714: RD LDB RDCMD ; read cmd */
|
||||
0017762, /* 77715: JSB CMD ; do cmd */
|
||||
0103710, /* 77716: STC DC,C ; start dch */
|
||||
0102211, /* 77717: SFC CC ; read done? */
|
||||
0027752, /* 77720: JMP STAT ; no, get stat */
|
||||
0102310, /* 77721: SFS DC ; any data? */
|
||||
0027717, /* 77722: JMP *-3 ; wait */
|
||||
0107510, /* 77723: LIB DC,C ; get rec cnt */
|
||||
0005727, /* 77724: BLF,BLF ; move to lower */
|
||||
0007000, /* 77725: CMB ; make neg */
|
||||
0077775, /* 77726: STA WC ; save */
|
||||
0102211, /* 77727: SFC CC ; read done? */
|
||||
0027752, /* 77730: JMP STAT ; no, get stat */
|
||||
0102310, /* 77731: SFS DC ; any data? */
|
||||
0027727, /* 77732: JMP *-3 ; wait */
|
||||
0107510, /* 77733: LIB DC,C ; get load addr */
|
||||
0074000, /* 77734: STB 0 ; start csum */
|
||||
0077762, /* 77735: STA CMD ; save address */
|
||||
0027742, /* 77736: JMP *+4 */
|
||||
0177762, /* 77737: NW STB CMD,I ; store data */
|
||||
0040001, /* 77740: ADA 1 ; add to csum */
|
||||
0037762, /* 77741: ISZ CMD ; adv addr ptr */
|
||||
0102310, /* 77742: SFS DC ; any data? */
|
||||
0027742, /* 77743: JMP *-1 ; wait */
|
||||
0107510, /* 77744: LIB DC,C ; get word */
|
||||
0037775, /* 77745: ISZ WC ; done? */
|
||||
0027737, /* 77746: JMP NW ; no */
|
||||
0054000, /* 77747: CPB 0 ; csum ok? */
|
||||
0027717, /* 77750: JMP RD+3 ; yes, cont */
|
||||
0102011, /* 77751: HLT 11 ; no, halt */
|
||||
0102511, /* 77752: ST LIA CC ; get status */
|
||||
0001727, /* 77753: ALF,ALF ; get eof bit */
|
||||
0002020, /* 77754: SSA ; set? */
|
||||
0102077, /* 77755: HLT 77 ; done */
|
||||
0001727, /* 77756: ALF,ALF ; put status back */
|
||||
0001310, /* 77757: RAR,SLA ; read ok? */
|
||||
0102000, /* 77760: HLT 0 ; no */
|
||||
0027714, /* 77761: JMP RD ; read next */
|
||||
0000000, /* 77762: CMD NOP */
|
||||
0106611, /* 77763: OTB CC ; output cmd */
|
||||
0102511, /* 77764: LIA CC ; check for reject */
|
||||
0001323, /* 77765: RAR,RAR */
|
||||
0001310, /* 77766: RAR,SLA */
|
||||
0027763, /* 77767: JMP CMD+1 ; try again */
|
||||
0103711, /* 77770: STC CC,C ; start command */
|
||||
0127762, /* 77771: JMP CMD,I ; exit */
|
||||
0001501, /* 77772: SL0RW OCT 1501 ; select 0, rewind */
|
||||
0001423, /* 77773: RDCMD OCT 1423 ; read record */
|
||||
0000203, /* 77774: FFC OCT 203 ; space forward file */
|
||||
0000000, /* 77775: WC NOP */
|
||||
0000000, /* 77776: NOP */
|
||||
0000000 } } /* 77777: NOP */
|
||||
};
|
||||
|
||||
|
||||
/* Device boot routine.
|
||||
|
||||
This routine is called directly by the BOOT MSC and LOAD MSC commands to copy
|
||||
the device bootstrap into the upper 64 words of the logical address space.
|
||||
It is also called indirectly by a BOOT CPU or LOAD CPU command when the
|
||||
specified HP 1000 loader ROM socket contains a 12992D ROM.
|
||||
|
||||
When called in response to a BOOT MSC or LOAD MSC command, the "unitno"
|
||||
parameter indicates the unit number specified in the BOOT command or is zero
|
||||
for the LOAD command, and "dptr" points at the MSC device structure. The
|
||||
bootstrap supports loading only from unit 0, and the command will be rejected
|
||||
if another unit is specified (e.g., BOOT MSC1). Otherwise, depending on the
|
||||
current CPU model, the BMTL or 12992D loader ROM will be copied into memory
|
||||
and configured for the MSD/MSC select code pair. If the CPU is a 1000, the S
|
||||
register will be set as it would be by the front-panel microcode.
|
||||
|
||||
When called for a BOOT/LOAD CPU command, the "unitno" parameter indicates the
|
||||
select code to be used for configuration, and "dptr" will be NULL. As above,
|
||||
the BMTL or 12992D loader ROM will be copied into memory and configured for
|
||||
the specified select code. The S register is assumed to be set correctly on
|
||||
entry and is not modified.
|
||||
|
||||
For the 12992D boot loader ROM for the HP 1000, the S register is set as
|
||||
follows:
|
||||
|
||||
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| ROM # | 0 0 | select code | 0 0 0 0 0 | F |
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
|
||||
Where:
|
||||
|
||||
F = Read current/specified file (0/1)
|
||||
|
||||
If bit 0 is 0, the file located at the current tape position is read. If bit
|
||||
0 is 1, the tape is rewound, and the file number (1 - n) specified by the
|
||||
A-register content is read.
|
||||
*/
|
||||
|
||||
t_stat msc_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
const int32 dev = msd_dib.select_code; /* get data chan device no */
|
||||
static const HP_WORD ms_preserved = 0000000u; /* no S-register bits are preserved */
|
||||
static const HP_WORD ms_reposition = 0000001u; /* S-register bit 0 set for a repositioning boot */
|
||||
|
||||
if (unitno != 0) /* boot supported on drive unit 0 only */
|
||||
return SCPE_NOFNC; /* report "Command not allowed" if attempted */
|
||||
if (dptr == NULL) /* if we are being called for a BOOT/LOAD CPU */
|
||||
return cpu_copy_loader (ms_loaders, unitno, /* then copy the boot loader to memory */
|
||||
IBL_S_NOCLEAR, IBL_S_NOSET); /* but do not alter the S register */
|
||||
|
||||
if (ibl_copy (ms_rom, dev, IBL_OPT, /* copy the boot ROM to memory and configure */
|
||||
IBL_MS | IBL_SET_SC (dev))) /* the S register accordingly */
|
||||
return SCPE_IERR; /* return an internal error if the copy failed */
|
||||
else if (unitno != 0) /* otherwise a BOOT MSC for a non-zero unit */
|
||||
return SCPE_NOFNC; /* is rejected as unsupported */
|
||||
|
||||
if ((sim_switches & SWMASK ('S')) && AR) /* if -S is specified and the A register is non-zero */
|
||||
SR = SR | 1; /* then set to skip to the file number in A */
|
||||
|
||||
return SCPE_OK;
|
||||
else /* otherwise this is a BOOT/LOAD MSC */
|
||||
return cpu_copy_loader (ms_loaders, msd_dib.select_code, /* so copy the boot loader to memory */
|
||||
ms_preserved, /* and configure the S register if 1000 CPU */
|
||||
sim_switches & SWMASK ('S') ? ms_reposition : 0);
|
||||
}
|
||||
|
||||
|
||||
/* Calculate tape record CRC and LRC characters */
|
||||
|
||||
#define E 0400 /* parity bit for odd parity */
|
||||
#define O 0000 /* parity bit for odd parity */
|
||||
|
||||
static const uint16 odd_parity [256] = { /* parity table */
|
||||
E, O, O, E, O, E, E, O, O, E, E, O, E, O, O, E, /* 000-017 */
|
||||
O, E, E, O, E, O, O, E, E, O, O, E, O, E, E, O, /* 020-037 */
|
||||
O, E, E, O, E, O, O, E, E, O, O, E, O, E, E, O, /* 040-067 */
|
||||
E, O, O, E, O, E, E, O, O, E, E, O, E, O, O, E, /* 060-077 */
|
||||
O, E, E, O, E, O, O, E, E, O, O, E, O, E, E, O, /* 100-117 */
|
||||
E, O, O, E, O, E, E, O, O, E, E, O, E, O, O, E, /* 120-137 */
|
||||
E, O, O, E, O, E, E, O, O, E, E, O, E, O, O, E, /* 140-157 */
|
||||
O, E, E, O, E, O, O, E, E, O, O, E, O, E, E, O, /* 160-177 */
|
||||
O, E, E, O, E, O, O, E, E, O, O, E, O, E, E, O, /* 200-217 */
|
||||
E, O, O, E, O, E, E, O, O, E, E, O, E, O, O, E, /* 220-237 */
|
||||
E, O, O, E, O, E, E, O, O, E, E, O, E, O, O, E, /* 240-267 */
|
||||
O, E, E, O, E, O, O, E, E, O, O, E, O, E, E, O, /* 260-277 */
|
||||
E, O, O, E, O, E, E, O, O, E, E, O, E, O, O, E, /* 300-317 */
|
||||
O, E, E, O, E, O, O, E, E, O, O, E, O, E, E, O, /* 320-337 */
|
||||
O, E, E, O, E, O, O, E, E, O, O, E, O, E, E, O, /* 340-357 */
|
||||
E, O, O, E, O, E, E, O, O, E, E, O, E, O, O, E /* 360-377 */
|
||||
};
|
||||
|
||||
static uint32 calc_crc_lrc (uint8 *buffer, t_mtrlnt length)
|
||||
{
|
||||
uint32 i;
|
||||
uint16 byte, crc, lrc;
|
||||
HP_WORD byte, crc, lrc;
|
||||
|
||||
lrc = crc = 0;
|
||||
|
||||
|
||||
@@ -1,30 +1,33 @@
|
||||
/* hp2100_mt.c: HP 2100 12559A magnetic tape simulator
|
||||
/* hp2100_mt.c: HP 2100 12559C 9-Track Magnetic Tape Unit Interface
|
||||
|
||||
Copyright (c) 1993-2016, Robert M. Supnik
|
||||
Copyright (c) 2017, J. David Bryan
|
||||
|
||||
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:
|
||||
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.
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS 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
|
||||
Except as contained in this notice, the names of the authors 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.
|
||||
in this Software without prior written authorization from the authors.
|
||||
|
||||
MT 12559A 3030 nine track magnetic tape
|
||||
MT 12559C 9-Track Magnetic Tape Unit Interface
|
||||
|
||||
20-Jul-17 JDB Removed "mtc_stopioe" variable and register
|
||||
13-Mar-17 JDB Deprecated LOCKED/WRITEENABLED for ATTACH -R
|
||||
13-May-16 JDB Modified for revised SCP API function parameter types
|
||||
24-Dec-14 JDB Added casts for explicit downward conversions
|
||||
10-Jan-13 MP Added DEV_TAPE to DEVICE flags
|
||||
@@ -58,9 +61,10 @@
|
||||
04-Oct-98 RMS V2.4 magtape format
|
||||
|
||||
References:
|
||||
- 12559A 9-Track Magnetic Tape Unit Interface Kit Operating and Service Manual
|
||||
(12559-9001, Jul-1970)
|
||||
- SIMH Magtape Representation and Handling (Bob Supnik, 30-Aug-2006)
|
||||
- 12559A 9-Track Magnetic Tape Unit Interface Kit Operating and Service Manual
|
||||
(12559-9001, July 1970)
|
||||
- SIMH Magtape Representation and Handling
|
||||
(Bob Supnik, 30-Aug-2006)
|
||||
|
||||
|
||||
The 3030 was one of HP's earliest tape drives. The 12559A controller
|
||||
@@ -76,6 +80,7 @@
|
||||
feature of the 12578A DMA card for the 2116 computer. The second meant that
|
||||
software drivers had to pad short records with blanks or nulls.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. The HP 3030 Magnetic Tape Subsystem diagnostic, part number 20433-60001,
|
||||
@@ -84,9 +89,12 @@
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "hp2100_defs.h"
|
||||
#include "sim_tape.h"
|
||||
|
||||
|
||||
|
||||
#define DB_V_SIZE 16 /* max data buf */
|
||||
#define DBSIZE (1 << DB_V_SIZE) /* max data cmd */
|
||||
|
||||
@@ -132,7 +140,6 @@ int32 mtc_1st = 0; /* first svc flop */
|
||||
int32 mtc_ctime = 40; /* command wait */
|
||||
int32 mtc_gtime = 1000; /* gap stop time */
|
||||
int32 mtc_xtime = 15; /* data xfer time */
|
||||
int32 mtc_stopioe = 1; /* stop on error */
|
||||
uint8 mtxb[DBSIZE] = { 0 }; /* data buffer */
|
||||
t_mtrlnt mt_ptr = 0, mt_max = 0; /* buffer ptrs */
|
||||
static const uint32 mtc_cmd[] = {
|
||||
@@ -180,8 +187,10 @@ REG mtd_reg[] = {
|
||||
};
|
||||
|
||||
MTAB mtd_mod[] = {
|
||||
{ MTAB_XTD | MTAB_VDV, 1, "SC", "SC", &hp_setsc, &hp_showsc, &mtd_dev },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &mtd_dev },
|
||||
/* Entry Flags Value Print String Match String Validation Display Descriptor */
|
||||
/* ------------------- ----- ------------ ------------ ------------ ------------- ---------------- */
|
||||
{ MTAB_XDV, 2u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &mt_dib },
|
||||
{ MTAB_XDV | MTAB_NMO, ~2u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &mt_dib },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
@@ -216,19 +225,47 @@ REG mtc_reg[] = {
|
||||
{ DRDATA (CTIME, mtc_ctime, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (GTIME, mtc_gtime, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (XTIME, mtc_xtime, 24), REG_NZ + PV_LEFT },
|
||||
{ FLDATA (STOP_IOE, mtc_stopioe, 0) },
|
||||
{ ORDATA (SC, mtc_dib.select_code, 6), REG_HRO },
|
||||
{ ORDATA (DEVNO, mtc_dib.select_code, 6), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB mtc_mod[] = {
|
||||
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 0, "FORMAT", "FORMAT",
|
||||
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 1, "SC", "SC", &hp_setsc, &hp_showsc, &mtd_dev },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &mtd_dev },
|
||||
/* Modifier list.
|
||||
|
||||
The LOCKED and WRITEENABLED modifiers are deprecated. The supported method
|
||||
of write-protecting a tape drive is to attach the tape image with the -R
|
||||
(read-only) switch or by setting the host operating system's read-only
|
||||
attribute on the tape image file. This simulates removing the write ring
|
||||
from the tape reel before mounting it on the drive. There is no hardware
|
||||
method of write-protecting a mounted and positioned tape reel.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. The UNIT_RO modifier displays "write ring" if the flag is not set. There
|
||||
is no corresponding entry for the opposite condition because "read only"
|
||||
is automatically printed after the attached filename.
|
||||
|
||||
2. FORMAT is really a unit option, but as there is only one unit, it is
|
||||
specified as MTAB_XDV so that SHOW MTC FORMAT is accepted, rather than
|
||||
requiring SHOW MTC0 FORMAT.
|
||||
*/
|
||||
|
||||
MTAB mtc_mod [] = {
|
||||
/* Mask Value Match Value Print String Match String Validation Display Descriptor */
|
||||
/* ------------- ------------- ---------------- --------------- ------------ ------- ---------- */
|
||||
{ UNIT_RO, 0, "write ring", NULL, NULL, NULL, NULL },
|
||||
|
||||
{ MTUF_WLK, 0, NULL, "WRITEENABLED", NULL, NULL, NULL },
|
||||
{ MTUF_WLK, MTUF_WLK, NULL, "LOCKED", NULL, NULL, NULL },
|
||||
|
||||
|
||||
/* Entry Flags Value Print String Match String Validation Display Descriptor */
|
||||
/* ------------------- ----- ------------ ------------ ----------------- ------------------ ---------------- */
|
||||
{ MTAB_XDV, 0, "FORMAT", "FORMAT", &sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
|
||||
|
||||
{ MTAB_XDV, 2u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &mt_dib },
|
||||
{ MTAB_XDV | MTAB_NMO, ~2u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &mt_dib },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
@@ -484,7 +521,7 @@ t_stat st, r = SCPE_OK;
|
||||
if ((mtc_unit.flags & UNIT_ATT) == 0) { /* offline? */
|
||||
mtc_sta = STA_LOCAL | STA_REJ; /* rejected */
|
||||
mtcio (&mtc_dib, ioENF, 0); /* set cch flg */
|
||||
return IOERROR (mtc_stopioe, SCPE_UNATT);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
switch (mtc_fnc) { /* case on function */
|
||||
@@ -603,7 +640,7 @@ switch (st) {
|
||||
|
||||
case MTSE_IOERR: /* IO error */
|
||||
mtc_sta = mtc_sta | STA_PAR; /* error */
|
||||
if (mtc_stopioe) return SCPE_IOERR;
|
||||
return SCPE_IOERR;
|
||||
break;
|
||||
|
||||
case MTSE_INVRL: /* invalid rec lnt */
|
||||
|
||||
1207
HP2100/hp2100_mux.c
1207
HP2100/hp2100_mux.c
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
/* hp2100_pif.c: HP 12620A/12936A privileged interrupt fence simulator
|
||||
/* hp2100_pif.c: HP 12620A/12936A Privileged Interrupt Fence simulator
|
||||
|
||||
Copyright (c) 2008-2016, J. David Bryan
|
||||
Copyright (c) 2008-2017, J. David Bryan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -23,8 +23,11 @@
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from the author.
|
||||
|
||||
PIF 12620A/12936A privileged interrupt fence
|
||||
PIF 12620A/12936A Privileged Interrupt Fence
|
||||
|
||||
15-Mar-17 JDB Trace flags are now global
|
||||
11-Mar-17 JDB Revised the trace outputs
|
||||
17-Jan-17 JDB Changed "hp_---sc" and "hp_---dev" to "hp_---_dib"
|
||||
13-May-16 JDB Modified for revised SCP API function parameter types
|
||||
10-Feb-12 JDB Deprecated DEVNO in favor of SC
|
||||
28-Mar-11 JDB Tidied up signal handling
|
||||
@@ -33,10 +36,10 @@
|
||||
18-Jun-08 JDB Created PIF device
|
||||
|
||||
References:
|
||||
- 12620A Breadboard Interface Kit Operating and Service Manual
|
||||
(12620-90001, May-1978)
|
||||
- 12936A Privileged Interrupt Fence Accessory Installation and Service Manual
|
||||
(12936-90001, Mar-1974)
|
||||
- 12620A Breadboard Interface Kit Operating and Service Manual
|
||||
(12620-90001, May 1978)
|
||||
- 12936A Privileged Interrupt Fence Accessory Installation and Service Manual
|
||||
(12936-90001, March 1974)
|
||||
|
||||
|
||||
The Privileged Interupt Fence (PIF) was used in DOS and RTE systems to
|
||||
@@ -95,9 +98,11 @@
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "hp2100_defs.h"
|
||||
|
||||
|
||||
|
||||
/* Device flags */
|
||||
|
||||
#define DEV_V_12936 (DEV_V_UF + 0) /* 12936A card */
|
||||
@@ -158,14 +163,26 @@ REG pif_reg [] = {
|
||||
};
|
||||
|
||||
MTAB pif_mod [] = {
|
||||
{ MTAB_XTD | MTAB_VDV, 0, NULL, "12620A", &pif_set_card, NULL, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 1, NULL, "12936A", &pif_set_card, NULL, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 0, "TYPE", NULL, NULL, &pif_show_card, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 0, "SC", "SC", &hp_setsc, &hp_showsc, &pif_dev },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &pif_dev },
|
||||
/* Entry Flags Value Print String Match String Validation Display Descriptor */
|
||||
/* ------------------- ----- ------------ ------------ -------------- -------------- ----------------- */
|
||||
{ MTAB_XDV, 0, NULL, "12620A", &pif_set_card, NULL, NULL },
|
||||
{ MTAB_XDV, 1, NULL, "12936A", &pif_set_card, NULL, NULL },
|
||||
{ MTAB_XDV, 0, "TYPE", NULL, NULL, &pif_show_card, NULL },
|
||||
|
||||
{ MTAB_XDV, 1u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &pif_dib },
|
||||
{ MTAB_XDV | MTAB_NMO, ~1u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &pif_dib },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
/* Debugging trace list */
|
||||
|
||||
static DEBTAB pif_deb [] = {
|
||||
{ "CMD", TRACE_CMD }, /* interface commands */
|
||||
{ "IOBUS", TRACE_IOBUS }, /* interface I/O bus signals and data words */
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
||||
DEVICE pif_dev = {
|
||||
"PIF", /* device name */
|
||||
&pif_unit, /* unit array */
|
||||
@@ -186,7 +203,7 @@ DEVICE pif_dev = {
|
||||
&pif_dib, /* device information block */
|
||||
DEV_DEBUG | DEV_DISABLE, /* device flags */
|
||||
0, /* debug control flags */
|
||||
NULL, /* debug flag name table */
|
||||
pif_deb, /* debug flag name table */
|
||||
NULL, /* memory size change routine */
|
||||
NULL }; /* logical device name */
|
||||
|
||||
@@ -218,9 +235,7 @@ DEVICE pif_dev = {
|
||||
|
||||
uint32 pif_io (DIB *dibptr, IOCYCLE signal_set, uint32 stat_data)
|
||||
{
|
||||
const char *hold_or_clear = (signal_set & ioCLF ? ",C" : "");
|
||||
const t_bool is_rte_pif = (pif_dev.flags & DEV_12936) == 0;
|
||||
|
||||
IOSIGNAL signal;
|
||||
IOCYCLE working_set = IOADDSIR (signal_set); /* add ioSIR if needed */
|
||||
|
||||
@@ -231,19 +246,13 @@ while (working_set) {
|
||||
|
||||
case ioCLF: /* clear flag flip-flop */
|
||||
pif.flag = pif.flagbuf = CLEAR; /* clear flag buffer and flag */
|
||||
|
||||
if (DEBUG_PRS (pif_dev))
|
||||
fputs (">>PIF: [CLF] Flag cleared\n", sim_deb);
|
||||
break;
|
||||
|
||||
|
||||
case ioSTF: /* set flag flip-flop */
|
||||
if (is_rte_pif) { /* RTE PIF? */
|
||||
if (is_rte_pif) /* RTE PIF? */
|
||||
pif.flag = pif.flagbuf = SET; /* set flag buffer and flag */
|
||||
|
||||
if (DEBUG_PRS (pif_dev))
|
||||
fputs (">>PIF: [STF] Flag set\n", sim_deb);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -263,9 +272,6 @@ while (working_set) {
|
||||
if (!is_rte_pif) { /* DOS PIF? */
|
||||
pif.flag = pif.flagbuf = SET; /* set flag buffer and flag */
|
||||
working_set = working_set | ioSIR; /* set SIR (not normally done for IOO) */
|
||||
|
||||
if (DEBUG_PRS (pif_dev))
|
||||
fprintf (sim_deb, ">>PIF: [OTx%s] Flag set\n", hold_or_clear);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -274,27 +280,22 @@ while (working_set) {
|
||||
pif.flag = pif.flagbuf = /* set or clear flag and flag buffer */
|
||||
(is_rte_pif ? SET : CLEAR);
|
||||
|
||||
if (DEBUG_PRS (pif_dev))
|
||||
fprintf (sim_deb, ">>PIF: [POPIO] Flag %s\n",
|
||||
(is_rte_pif ? "set" : "cleared"));
|
||||
tprintf (pif_dev, TRACE_CMD, "Power-on reset\n");
|
||||
break;
|
||||
|
||||
|
||||
case ioCRS: /* control reset */
|
||||
tprintf (pif_dev, TRACE_CMD, "Control reset\n");
|
||||
|
||||
/* fall into ioCLC handler */
|
||||
|
||||
case ioCLC: /* clear control flip-flop */
|
||||
pif.control = CLEAR; /* clear control */
|
||||
|
||||
if (DEBUG_PRS (pif_dev))
|
||||
fprintf (sim_deb, ">>PIF: [%s%s] Control cleared\n",
|
||||
(signal == ioCRS ? "CRS" : "CLC"), hold_or_clear);
|
||||
break;
|
||||
|
||||
|
||||
case ioSTC: /* set control flip-flop */
|
||||
pif.control = SET; /* set control */
|
||||
|
||||
if (DEBUG_PRS (pif_dev))
|
||||
fprintf (sim_deb, ">>PIF: [STC%s] Control set\n", hold_or_clear);
|
||||
break;
|
||||
|
||||
|
||||
@@ -310,10 +311,9 @@ while (working_set) {
|
||||
setIRQ (dibptr->select_code, !pif.control & pif.flag & pif.flagbuf);
|
||||
}
|
||||
|
||||
if (DEBUG_PRS (pif_dev))
|
||||
fprintf (sim_deb, ">>PIF: [SIR] PRL = %d, IRQ = %d\n",
|
||||
PRL (dibptr->select_code),
|
||||
IRQ (dibptr->select_code));
|
||||
tprintf (pif_dev, TRACE_CMD, "Fence %s%s lower-priority interrupts\n",
|
||||
(IRQ (dibptr->select_code) ? "requests an interrupt and " : ""),
|
||||
(PRL (dibptr->select_code) ? "allows" : "inhibits"));
|
||||
break;
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
SIMH/HP 2100 RELEASE NOTES
|
||||
==========================
|
||||
Last update: 2017-05-01
|
||||
Last update: 2018-05-23
|
||||
|
||||
|
||||
This file documents the release history of the simulator for the Hewlett-Packard
|
||||
@@ -56,7 +56,7 @@ The simulator has been tested with the following operating systems:
|
||||
|
||||
- SIO, BCS, and MTS.
|
||||
|
||||
- 2000E, 2000F, and 2000/Access Time-Shared BASIC.
|
||||
- 2000E, 2000F, and 2000 Access Time-Shared BASIC.
|
||||
|
||||
- DOS, DOS-M, and DOS-III.
|
||||
|
||||
@@ -68,6 +68,18 @@ PDF version of the same manual is available at:
|
||||
|
||||
http://alum.mit.edu/www/jdbryan/hp2100_doc.pdf
|
||||
|
||||
For those intending to run 2000F or 2000/Access Time-Shared BASIC, a monograph
|
||||
entitled "Running HP 2000 Time-Shared BASIC on SIMH" is available at:
|
||||
|
||||
http://simh.trailing-edge.com/docs/running_hp_2000_tsb.pdf
|
||||
|
||||
It discusses the requirements for successful TSB startup and operation and the
|
||||
issues involved in synchronizing the dual-CPU simulation setup required by TSB.
|
||||
TSB has run successfully on SIMH for many years, but the advent of multi-core
|
||||
host machines has increased the difficulty in getting the two SIMH instances to
|
||||
coordinate properly. The paper presents some configuration guidelines that
|
||||
improve the probability of successfully running TSB.
|
||||
|
||||
|
||||
------------------
|
||||
Available Software
|
||||
@@ -98,6 +110,15 @@ restore programs is available from the HP Computer Museum at:
|
||||
|
||||
The archive contains instructions and a simulator command file.
|
||||
|
||||
Preconfigured 2000E, 2000F, and 2000 Access software kits are available from the
|
||||
SIMH software repository here:
|
||||
|
||||
http://simh.trailing-edge.com/software.html
|
||||
|
||||
Each kit contains a bootable disc image and associated command files that
|
||||
automate the system startup process. Command files to perform new system
|
||||
generations are also included.
|
||||
|
||||
QCTerm, an HP 700 terminal emulator for Microsoft Windows, is available from the
|
||||
HP Computer Museum at:
|
||||
|
||||
@@ -157,6 +178,535 @@ Revision 5010:
|
||||
|
||||
|
||||
|
||||
======================
|
||||
Release 28, 2018-05-23
|
||||
======================
|
||||
|
||||
This release of the HP 2100 simulator adds the following features:
|
||||
|
||||
- The IPLI and IPLO devices now use shared memory instead of network sockets to
|
||||
simulate the 12875A Processor Interconnect kit that is used to communicate
|
||||
between the System Processor and the I/O Processor of the HP 2000B, C, F, and
|
||||
Access Time-Shared BASIC operating systems. This change, in addition to a
|
||||
new, adaptive service scheduling routine, improves data transfer time between
|
||||
the processes by a factor of 7 to 1.
|
||||
|
||||
- Commands have been added to the IPL device to permit synchronization between
|
||||
the two simulator processes running the HP 2000 Time-Shared BASIC operating
|
||||
system. This greatly improves system startup reliability and permits the use
|
||||
of the HP-documented startup procedure of cross-loading the I/O Processor
|
||||
program from the System Processor.
|
||||
|
||||
- The DIAGNOSTIC options of the IPLI and IPLO devices have been reworked to
|
||||
permit testing with the HP General Register Diagnostic as well as the
|
||||
Processor Interconnect Cable Diagnostic.
|
||||
|
||||
- The DEBUG options of the IPLI and IPLO devices have been expanded.
|
||||
|
||||
- The BOOT command now installs the correct binary loader for the CPU model.
|
||||
For example, BOOT PTR installs and runs the Basic Binary Loader (BBL) if the
|
||||
CPU is configured as a 2114/15/16 or 2100, or the 12992K Paper Tape Loader
|
||||
ROM if the CPU is configured as a 1000 M/E/F-Series. Prior releases
|
||||
installed the HP 1000 loader ROM regardless of the CPU model.
|
||||
|
||||
- The LOAD command has been extended to permit copying of internal device boot
|
||||
loaders into memory. LOAD <dev> is identical to BOOT <dev> except that the
|
||||
CPU is neither preset nor run. In particular, LOAD CPU is the equivalent of
|
||||
pressing the IBL button on the HP 1000 front panel.
|
||||
|
||||
- The new SET CPU ROMS command permits altering the set of preinstalled boot
|
||||
loader ROMs for 1000 CPUs. The new SHOW CPU ROMS command displays the
|
||||
currently installed set.
|
||||
|
||||
- The -N (new file) option to the ATTACH command for disc devices now creates a
|
||||
full-size image file, equivalent to formatting the new disc before use.
|
||||
|
||||
|
||||
--------------------
|
||||
Implementation Notes
|
||||
--------------------
|
||||
|
||||
- The abbreviated "SET CPU 21MX" command no longer sets the CPU to an E-Series
|
||||
model (i.e., to a 21MX-E, a.k.a. 1000-E); instead, it configures the CPU as
|
||||
an original 21MX (a.k.a. 1000-M). If an E-Series configuration is desired,
|
||||
it must be requested explicitly with the "SET CPU 21MX-E" command.
|
||||
|
||||
- The "RESET -P CPU" command no longer restores the BBL to the protected memory
|
||||
area of 21xx machines. The "LOAD PTR" command may be used to perform this
|
||||
function.
|
||||
|
||||
- The previous behavior of the "ATTACH -N" command for disc devices, i.e.,
|
||||
creating a new zero-length image file, may be emulated by first deleting the
|
||||
file and then attaching it without specifying the -N switch. For instance,
|
||||
the "DELETE <file>" and "ATTACH <unit> <file>" commands produce a new
|
||||
zero-length file as "ATTACH -N <unit> <file>" did before this change. The
|
||||
"ATTACH -N" behavior of other devices, e.g., magnetic tape drives and
|
||||
printers, did not change; a zero-length file is still created.
|
||||
|
||||
- With the change to a shared-memory implementation, only a single "ATTACH IPL"
|
||||
command is required per instance to establish communication. The System
|
||||
Processor instance issues an "ATTACH -S IPL <code>" command, and the I/O
|
||||
Processor instance must issue a corresponding "ATTACH -I IPL <code>" command,
|
||||
where the <code> parameter is a user-selected decimal number that identifies
|
||||
the instance pair. The prior "ATTACH [-L | -C] [ IPLI | IPLO ] <port>"
|
||||
commands are deprecated but retained, so that existing command files will
|
||||
still work. However, they too will use shared memory rather than network
|
||||
connections. Consequently, the SP and IOP instances are now required to
|
||||
execute on the same machine, and the <ip-address> option is no longer
|
||||
supported.
|
||||
|
||||
- Multiple consecutive CLC 0 instruction executions now cause only a single CRS
|
||||
assertion to the I/O devices. Therefore, IOBUS tracing when running HP 2000
|
||||
Time-Shared BASIC systems no longer generates a pair of trace lines for each
|
||||
of the 131,072 consecutive CLC 0 executions typically used to initialize the
|
||||
12920A Asynchronous Multiplexer.
|
||||
|
||||
- The 12875A Processor Interconnect section of the HP2100 User's Guide has been
|
||||
revised to describe the new ATTACH protocol and process synchronization
|
||||
commands.
|
||||
|
||||
- A list of device boot loaders installed for given device/CPU combinations has
|
||||
been added to the user's guide.
|
||||
|
||||
- The "21MX-M" and "21MX-E" CPU options that had been inadvertently omitted
|
||||
from the last release of the user's guide have been restored.
|
||||
|
||||
- The "Running HP 2000 Time-Shared BASIC on SIMH" monograph has been revised to
|
||||
cover the application of the new process synchronization commands to TSB
|
||||
startup command files.
|
||||
|
||||
- Preconfigured software kits for 2000E, 2000F, and 2000 Access that employ
|
||||
the new shared memory and process synchronization commands are now available;
|
||||
see the "Available Software" section above for details.
|
||||
|
||||
|
||||
----------
|
||||
Bugs Fixed
|
||||
----------
|
||||
|
||||
1. PROBLEM: Serial port output stalls are not handled properly.
|
||||
|
||||
VERSION: Release 27.
|
||||
|
||||
OBSERVATION: The TTY, BACI, MPX, and MUX devices support I/O via host
|
||||
serial ports as well as via Telnet connections. While TTY, BACI, and MPX
|
||||
output via Telnet works correctly, output via serial ports fails. TTY
|
||||
output drops characters if the serial port stalls. Attempting to output to
|
||||
the BACI results in "Console Telnet output stall" and a simulator stop.
|
||||
Output to the MPX results in dropped characters and eventually an "IOPE"
|
||||
(parity error) message from RTE.
|
||||
|
||||
CAUSE: The terminal multiplexer library (sim_tmxr.c, part of the SIMH
|
||||
framework) had provided a 256-byte output buffer for each line, independent
|
||||
of the connection type (Telnet or serial). The library was changed to
|
||||
reduce the serial buffer size to one byte. The BACI and MPX devices are
|
||||
internally buffered and default to a "FASTTIME" mode that sends the entire
|
||||
internal buffer to the library output routine. When the routine receives
|
||||
the second character, it returns SCPE_STALL status to indicate a buffer
|
||||
overflow. The device simulations did not expect and did not properly
|
||||
handle this status.
|
||||
|
||||
The TTY and MUX devices are not buffered internally and were not affected
|
||||
by the loss of serial buffering. However, the TTY would drop output
|
||||
characters if the host serial buffer overflowed.
|
||||
|
||||
RESOLUTION: Modify "tto_svc" (hp2100_stddev.c), "baci_term_svc"
|
||||
(hp2100_baci.c), and "line_service" (hp2100_mpx.c) to handle terminal
|
||||
multiplexer library buffer overflows properly.
|
||||
|
||||
STATUS: Fixed in Release 28.
|
||||
|
||||
|
||||
2. PROBLEM: The PTR device DIAGNOSTIC option shown in the user's guide does
|
||||
not exist.
|
||||
|
||||
VERSION: Release 27.
|
||||
|
||||
OBSERVATION: The "HP2100 Simulator User's Guide" says that specifying the
|
||||
DIAGNOSTIC option for the PTR device "converts the attached paper tape
|
||||
image into a continuous loop" for use by the paper tape reader diagnostic
|
||||
program. However, entering a "SET PTR DIAGNOSTIC" command gives a
|
||||
"Non-existent parameter" error.
|
||||
|
||||
CAUSE: The option name specified in the PTR device's modifier table is
|
||||
"DIAG". It should be "DIAGNOSTIC" to match the option names used in the
|
||||
other device simulations.
|
||||
|
||||
RESOLUTION: Modify "ptr_mod" (hp_stddev.c) to use the correct option name.
|
||||
|
||||
STATUS: Fixed in Release 28.
|
||||
|
||||
|
||||
3. PROBLEM: First Status is not cleared properly on the DP device.
|
||||
|
||||
VERSION: Release 27.
|
||||
|
||||
OBSERVATION: Execution of the RTE-I paper tape bootstrap for the 7900A and
|
||||
the 2000F loader for the 7900A halts with disc errors. The offending disc
|
||||
status word is 040001 octal, which denotes First Status and Any Error.
|
||||
Both programs expect disc status to be clear after an initial Seek and Read
|
||||
are performed. However, the disc drive and interface manuals state that
|
||||
First Status is cleared by a Status Check command, which is not being
|
||||
issued.
|
||||
|
||||
CAUSE: Examination of the schematics in the 7900A Disc Drive Operating and
|
||||
Service Manual (07900-90002 February 1975) and the 13210A Disc Drive
|
||||
Interface Kit Operating and Service Manual (13210-90003 November 1974)
|
||||
shows that, contrary to the documentation, First Status is cleared on a
|
||||
Read, Write, Check Data, or Initialize command, as well as on a Status
|
||||
Check command. The current DP implementation follows the manual
|
||||
description rather than the schematics, so it fails to clear First Status
|
||||
when the initial Read is performed.
|
||||
|
||||
RESOLUTION: Modify "dp_goc" (hp2100_dp.c) to clear First Status as well as
|
||||
Attention when one of the applicable commands is performed.
|
||||
|
||||
STATUS: Fixed in Release 28.
|
||||
|
||||
|
||||
4. PROBLEM: 2000F and Access will not boot from a 7900 drive using the BMDL.
|
||||
|
||||
VERSION: Release 27.
|
||||
|
||||
OBSERVATION: Attempting to boot Time-Shared BASIC from a 7900 using the
|
||||
Basic Moving-Head Disc Loader for the HP 2100 CPU results in a HLT 1
|
||||
(unrecoverable disc error) in the TSB loader. Booting the same system with
|
||||
the 12992A loader ROM for the HP 1000 succeeds.
|
||||
|
||||
The BMDL configures DMA for an oversize (~32000 word) transfer and expects
|
||||
the disc to terminate the operation with End of Cylinder (EOC) status. The
|
||||
TSB bootstrap successfully loads into memory. When it starts, it issues a
|
||||
CLC 0,C followed by a Check Status command that is expected to return zero,
|
||||
i.e., all status bits clear. However, the EOC bit is set, and the
|
||||
bootstrap halts with a HLT 1.
|
||||
|
||||
CAUSE: The "Disc Interface 1 PCA Schematic Diagram" in the HP 13210A Disc
|
||||
Drive Interface Kit Operating and Service Manual (13210-90003, August 1974)
|
||||
shows that the CRS signal, which is generated by the CLC 0 instruction,
|
||||
does not affect the Status Register contents. However, examination of an
|
||||
actual hardware interface PCA shows that CRS assertion does clear the
|
||||
register.
|
||||
|
||||
RESOLUTION: Modify "dpcio" (hp2100_dp.c) to clear the status register on
|
||||
receipt of a CRS signal. Note that later versions of the service manual
|
||||
(May 1975 and May 1978) show the correct CRS connection.
|
||||
|
||||
STATUS: Fixed in Release 28.
|
||||
|
||||
|
||||
5. PROBLEM: Forcibly disconnected 2000E multiplexer ports are unresponsive.
|
||||
|
||||
VERSION: Release 27.
|
||||
|
||||
OBSERVATION: The HP Time-Shared BASIC system sets a limit on the time
|
||||
allowed between dataset connection and login. By default, this is 120
|
||||
seconds but may be changed by the PHONES system operator command. If the
|
||||
user does not complete a login within the time allowed, the dataset will be
|
||||
disconnected.
|
||||
|
||||
This action occurs as expected on the 2000E system, but while reconnecting
|
||||
to the port succeeds, the line is unresponsive. More importantly,
|
||||
attempting to SLEEP the system hangs after responding to the "MAG TAPE
|
||||
SLEEP?" question.
|
||||
|
||||
CAUSE: Examining the source code where the SLEEP hang occurs shows that
|
||||
the system is waiting in a loop for output to complete on the disconnected
|
||||
port. The forced disconnect code, which is shared by the PHONES, KILLID,
|
||||
and SLEEP commands, calls the BYE processor to log out an active user.
|
||||
However, for a PHONES disconnect, the user is not logged in. The BYE
|
||||
processor handles this condition correctly, but it returns to a common
|
||||
routine (LLEND) that outputs a line feed to the port. The multiplexer
|
||||
simulation omits a write to a disconnected port but also erroneously omits
|
||||
the output completion interrupt request. Consequently, TSB believes that
|
||||
the output is still in progress and therefore waits, in an infinite loop,
|
||||
for the completion interrupt that never occurs. Also, while the port is in
|
||||
output mode, input is turned off, so the port appears to be unresponsive
|
||||
when reconnected.
|
||||
|
||||
RESOLUTION: Modify "muxo_svc" (hp2100_mux.c) to set "mux_xdon" to 1 to
|
||||
trigger the completion interrupt regardless of whether or not the port is
|
||||
connected to a Telnet session.
|
||||
|
||||
STATUS: Fixed in Release 28.
|
||||
|
||||
|
||||
|
||||
======================
|
||||
Release 27, 2017-09-06
|
||||
======================
|
||||
|
||||
This release of the HP 2100 simulator adds the following features:
|
||||
|
||||
- Support for the HP 2613, 2617, and 2618 line printers has been added to the
|
||||
LPT device. The default printer remains the HP 2607.
|
||||
|
||||
- The LPT device simulation has been rewritten to support realistic and
|
||||
optimized timing, compact and expanded output modes, custom VFU tape images,
|
||||
and tracing of internal operations.
|
||||
|
||||
- The LOAD command has been rewritten to load files containing absolute binary
|
||||
loaders into the protected address space of the 21xx machines and configure
|
||||
the I/O instructions. For the 1000, LOAD can also be used to load boot
|
||||
loader ROM images other than those provided directly by the simulator.
|
||||
|
||||
- The DUMP command has been added to write the binary loader currently resident
|
||||
in memory to an absolute binary file.
|
||||
|
||||
- The TTY punch unit and the LPS, LPT, and PTP devices now position a newly
|
||||
attached file at the end of the file rather than at the start. As a result,
|
||||
output will append to, rather than overwrite, the existing content.
|
||||
|
||||
- The DA, DP, DQ, and DS disc devices add the PROTECT and UNPROTECT options.
|
||||
These replace the now-deprecated LOCKED and WRITEENABLED options and more
|
||||
accurately reflect the labelling of the data protection switches on the disc
|
||||
drives.
|
||||
|
||||
- The simulator message that is displayed when a programmed halt occurs has
|
||||
been changed to indicate that the halt code comes from the T-register value.
|
||||
|
||||
- The Basic Binary Loader (BBL) is now installed by default in the 21xx
|
||||
machines. It is automatically configured to the select code of the paper
|
||||
tape reader. It may be overwritten with a different loader (e.g., the Basic
|
||||
Binary Disc Loader or Basic Moving-head Disc Loader) using the LOAD command.
|
||||
Performing a power-on reset of the CPU reinstalls the BBL.
|
||||
|
||||
- Symbolic display and entry has been rewritten to improve efficiency and
|
||||
expanded to cover the full instruction set including optional microcode
|
||||
extensions that are currently enabled.
|
||||
|
||||
- CPU instruction execution and data accesses may be selectively traced. The
|
||||
resulting trace listing is similar to the output of a logic analyzer
|
||||
connected to the CPU and I/O buses.
|
||||
|
||||
- DMA/DCPC commands, status, and data accesses may be selectively traced.
|
||||
|
||||
- TBG commands, status, and service entries may be selectively traced.
|
||||
|
||||
- The DIAG option of the TBG device has been replaced with the REALTIME, W1A,
|
||||
W1B, W2A, and W2B options. Configuring the TBG to run its diagnostic now
|
||||
uses the REALTIME and W2B options, and restoring the normal configuration
|
||||
uses the CALTIME and W2A options. The W1A and W1B options extend the
|
||||
software compatibility of the TBG.
|
||||
|
||||
- The MUXM device has been renamed MUXC to reflect that it is the multiplexer
|
||||
control card. The previous MUXM name is deprecated but will still work in
|
||||
existing simulation command files.
|
||||
|
||||
- The multiplexer control card (MUXC) may be enabled and disabled independently
|
||||
of the upper and lower data cards (MUX and MUXL), reflecting its optional
|
||||
status in hardware configurations.
|
||||
|
||||
- Memory address parsing for commands has been changed to add <page>.<offset>
|
||||
format for physical addresses, where both the page and the offset range from
|
||||
0 to 1777 octal. Linear addressing is now restricted to the 32K logical
|
||||
address space (0 to 77777 octal). Memory display uses linear addressing for
|
||||
locations within the logical address space; locations above 32K use the
|
||||
physical address format.
|
||||
|
||||
- The previously separate STOP_INST, STOP_DEV, STOP_IOE, and INDMAX
|
||||
pseudo-registers used to stop the simulator under certain conditions have
|
||||
been replaced by the SET CPU STOP=<stopname>[,<stopname>...] and the SET CPU
|
||||
INDIR=<limit> commands. Stops may be temporarily bypassed by adding the -B
|
||||
switch to the command that resumes execution.
|
||||
|
||||
- The HP 2100 Simulator User's Guide has been rewritten and significantly
|
||||
expanded.
|
||||
|
||||
|
||||
--------------------
|
||||
Implementation Notes
|
||||
--------------------
|
||||
|
||||
- The simulator passes the HP 2613/17/18 line printer diagnostic as described
|
||||
in the "hp2100_diag.txt" file.
|
||||
|
||||
- The line printer terminates each print line with the HP-standard CR/LF pair.
|
||||
If the output file is to be retained as a text file on a Unix system, removal
|
||||
of the carriage returns, e.g., via the "dos2unix" utility, may be desirable.
|
||||
|
||||
- The LOAD command can no longer be used to read general absolute binary paper
|
||||
tape images into memory. The ATTACH PTR and BOOT PTR commands must now be
|
||||
used to read paper tapes.
|
||||
|
||||
- The OS, OSTBG, VMA, EMA, VIS, and SIGNAL CPU debug flags have been removed.
|
||||
Tracing of these firmware instructions is now performed by specifying SET CPU
|
||||
DEBUG=EXEC and SET CPU EXEC with the appropriate opcode range and mask, as
|
||||
follows:
|
||||
|
||||
* SET CPU DEBUG=OS => SET CPU EXEC=105340;177760
|
||||
* SET CPU DEBUG=VMA => SET CPU EXEC=105240;177760
|
||||
* SET CPU DEBUG=EMA => SET CPU EXEC=105240;177760
|
||||
* SET CPU DEBUG=VIS => SET CPU EXEC=101460;173760
|
||||
* SET CPU DEBUG=SIGNAL => SET CPU EXEC=105600;177760
|
||||
|
||||
- The separate tracing of time-base generator interrupt instructions provided
|
||||
by the OS and OSTBG CPU debug flags is no longer supported. Entering the
|
||||
replacement command above traces all OS instructions, including the TBG
|
||||
interrupt instructions.
|
||||
|
||||
- The TIMER, RRR 16, .FLUN, and the OS/VMA, VIS, and SIGNAL self-test
|
||||
instructions are no longer exempt from the undefined/unimplemented
|
||||
instruction stop tests. Attempted execution of these instructions without
|
||||
the appropriate firmware options installed will cause simulation stops if the
|
||||
UNDEF (TIMER and RRR) or UNIMPL (.FLUN and self-tests) option is enabled.
|
||||
Because of this change, the default state of the unimplemented instruction
|
||||
stop has been reversed from "on" to "off".
|
||||
|
||||
- The "stop on I/O error" features controlled by the STOP_IOE register values
|
||||
have been removed from the DR, LPS, LPT, MSC, MTC, and PTP devices, as all of
|
||||
these report I/O error status to the CPU via their interface input registers.
|
||||
STOP_IOE has been removed from the PTR device and replaced with SET CPU
|
||||
STOP=IOERR, as this device does not report I/O error status to the CPU
|
||||
through its interface.
|
||||
|
||||
- The LOCKED and WRITEENABLED options for the MSC and MTC devices are
|
||||
deprecated. The supported method of write-protecting a tape drive is to
|
||||
attach the tape image with the -R (read-only) switch or by setting the host
|
||||
operating system's read-only attribute on the tape image file. This
|
||||
simulates removing the write ring from the tape reel before mounting it on
|
||||
the drive. There is no hardware method of write-protecting a mounted and
|
||||
positioned tape reel.
|
||||
|
||||
- If the previous ATTACH behavior (overwriting rather than appending) is
|
||||
desired for the TTY punch unit and the LPS, LPT, and PTP devices, set the
|
||||
device's (P)POS register to 0 after attaching.
|
||||
|
||||
|
||||
----------
|
||||
Bugs Fixed
|
||||
----------
|
||||
|
||||
1. PROBLEM: EXAMINE -M for addresses > 32K displays misleading operands.
|
||||
|
||||
VERSION: Release 26.
|
||||
|
||||
OBSERVATION: Current-page memory references of instructions residing above
|
||||
the 32K logical address space are printed as though they reside at their
|
||||
locations modulo 32K. For example, DEPOSIT 170001 026020 and EXAMINE -M
|
||||
170001 displays JMP 70020, and DEPOSIT 200001 026020 displays JMP 20.
|
||||
|
||||
CAUSE: The printed addresses assume that the instructions will be executed
|
||||
from their respective pages (modulo 32). However, instructions can be
|
||||
executed only when they are mapped into the logical address space, and any
|
||||
given physical page may be mapped to any arbitrary logical page.
|
||||
Therefore, the address printed may not represent the actual logical address
|
||||
after mapping.
|
||||
|
||||
RESOLUTION: Modify "fprint_cpu" (hp2100_sys.c) to use Z/C address notation
|
||||
for memory references in instructions residing in physical memory above
|
||||
32K.
|
||||
|
||||
STATUS: Fixed in Release 27.
|
||||
|
||||
|
||||
2. PROBLEM: Enabling IOP firmware should not be allowed on the 1000 F-Series.
|
||||
|
||||
VERSION: Release 26.
|
||||
|
||||
OBSERVATION: The command "SET CPU 1000-F,IOP" is allowed, but it should
|
||||
not be, as the IOP firmware is not supported on this machine.
|
||||
|
||||
CAUSE: The F-Series does not provide the firmware mapping table entries
|
||||
that permit operation of the 2000/Access I/O Processor firmware. IOP
|
||||
instruction opcodes 10x400-17 and 10x420-37 are marked as "HP Reserved" in
|
||||
the F-Series mapping table, and opcodes 10x460-77 are dedicated to the VIS
|
||||
microcode.
|
||||
|
||||
RESOLUTION: Modify the "cpu_features" array (hp2100_cpu.c) to remove the
|
||||
IOP option from the 1000 F-Series entry.
|
||||
|
||||
STATUS: Fixed in Release 27.
|
||||
|
||||
|
||||
3. PROBLEM: A rejected model change still changes the CPU options.
|
||||
|
||||
VERSION: Release 26.
|
||||
|
||||
OBSERVATION: Changing to a CPU model that does not support the current
|
||||
memory size will reduce memory to the maximum supported by the new model.
|
||||
If the truncated portion contains non-zero values, the simulator will ask
|
||||
for confirmation before proceeding. If the truncation is rejected, the CPU
|
||||
options are still set to those of the new model, even though the old model
|
||||
is retained. For example:
|
||||
|
||||
sim> SET CPU 1000-F,128K
|
||||
sim> SHOW CPU
|
||||
CPU idle disabled
|
||||
128KW, 1000-F, EAU
|
||||
FP, no IOP, DMS
|
||||
FFP, DBI, no EMA/VMA
|
||||
no VIS, no SIGNAL
|
||||
sim> DEPOSIT 100000 1
|
||||
sim> SET CPU 2116
|
||||
Really truncate memory [N]?NO
|
||||
Command not completed
|
||||
sim> SHOW CPU
|
||||
CPU idle disabled
|
||||
128KW, 1000-F, no EAU
|
||||
no FP, no IOP, no DMS
|
||||
no FFP, no DBI, no EMA/VMA
|
||||
no VIS, no SIGNAL
|
||||
|
||||
CAUSE: The CPU options are set before the memory size is changed, so when
|
||||
the size change is rejected, the new CPU options are retained.
|
||||
|
||||
RESOLUTION: Modify "cpu_set_model" (hp2100_cpu.c) to perform the memory
|
||||
size change first, so that if it is rejected, the CPU options have not been
|
||||
changed.
|
||||
|
||||
STATUS: Fixed in Release 27.
|
||||
|
||||
|
||||
4. PROBLEM: Virtual memory mapping fails for accesses above 126 MB.
|
||||
|
||||
VERSION: Release 26.
|
||||
|
||||
OBSERVATION: A program using virtual memory provided by the RTE-6/VM
|
||||
operating system may access up to 128 MB of data, although VMA programs
|
||||
default to a 16 MB limit. Accesses to data in virtual memory are mapped
|
||||
through the last two DMS user map registers. Normally, each VMA access
|
||||
maps in the memory page corresponding to the virtual address plus the
|
||||
following memory page. This allows access to single items up to 1024 words
|
||||
in size starting at any offset within the (first) page.
|
||||
|
||||
If a data item resides in the last 2 MB of virtual memory, access to an
|
||||
item that crosses the page boundary is incorrect. Instead of accessing
|
||||
words in the second page, the accesses wrap around within the first page.
|
||||
|
||||
CAUSE: The suit number part of the virtual address is not restored before
|
||||
checking the allocation status of the page table entry corresponding to the
|
||||
second (spillover) page. As a result, an unallocated second page in the
|
||||
last 2 MB of virtual memory is seen as beyond the VM area limit, and
|
||||
instead of generating a page fault to allocate the second page, the map
|
||||
registers are set up to prevent access to the second page by setting the
|
||||
first page address into both map registers.
|
||||
|
||||
RESOLUTION: Modify "cpu_vma_lbp" (hp2100_cpu5.c) to check for spill page
|
||||
allocation correctly.
|
||||
|
||||
STATUS: Fixed in Release 27.
|
||||
|
||||
|
||||
5. PROBLEM: Memory expansion is not disabled when DMS is disabled.
|
||||
|
||||
VERSION: Release 26.
|
||||
|
||||
OBSERVATION: If the Memory Expansion Module in a 1000-Series CPU has been
|
||||
enabled, and then the DMS firmware option is disabled or the CPU is changed
|
||||
to a model that does not support memory expansion (e.g., a 2100), memory
|
||||
expansion remains enabled. In this case, memory accesses should revert to
|
||||
physical addressing, but instead logical-to-physical address translation
|
||||
through the currently enabled map remains in effect.
|
||||
|
||||
CAUSE: Disabling DMS should set the "dms_enb" flag to 0, but it does not.
|
||||
|
||||
RESOLUTION: Modify "set_model" and "set_option" (hp2100_cpu.c) to clear
|
||||
the "dms_enb" flag if DMS is not enabled after the model or option change.
|
||||
|
||||
STATUS: Fixed in Release 27.
|
||||
|
||||
|
||||
|
||||
======================
|
||||
Release 26, 2017-05-01
|
||||
======================
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
5771
HP2100/hp2100_sys.c
5771
HP2100/hp2100_sys.c
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Reference in New Issue
Block a user