HP2100: Release 28
See HP2100/hp2100_release.txt for details of the release.
This commit is contained in:
parent
c1f249ec66
commit
486427c9fe
23 changed files with 5151 additions and 1785 deletions
|
@ -25,6 +25,7 @@
|
|||
|
||||
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
|
||||
|
@ -87,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
|
||||
|
@ -122,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
|
||||
|
@ -318,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 */
|
||||
|
@ -391,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
|
||||
|
@ -405,13 +406,13 @@ 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 */
|
||||
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 [] = {
|
||||
|
@ -466,15 +467,15 @@ 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, 1u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &baci_dib },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, ~1u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &baci_dib },
|
||||
{ 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 }
|
||||
};
|
||||
|
||||
|
@ -768,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.
|
||||
|
||||
|
@ -808,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
|
||||
|
@ -826,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)
|
||||
|
@ -834,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 */
|
||||
|
@ -864,6 +909,14 @@ while (xmit_loop && (baci_uart_thr & IN_VALID)) { /* valid character in UA
|
|||
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 */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -879,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 */
|
||||
}
|
||||
|
||||
|
||||
|
@ -971,12 +1025,11 @@ 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:
|
||||
|
@ -1025,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)
|
||||
{
|
||||
|
@ -1044,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;
|
||||
}
|
||||
|
@ -1105,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;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* hp2100_cpu.c: HP 21xx/1000 Central Processing Unit/MEM/MP/DCPC 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
|
||||
|
@ -30,6 +30,11 @@
|
|||
DCPC1,DCPC2 12897B Dual Channel Port Controller
|
||||
MP 12581A/12892B Memory Protect
|
||||
|
||||
21-May-18 JDB Changed "access" to "mem_access" to avoid clashing
|
||||
07-May-18 JDB Modified "io_dispatch" to display outbound signals
|
||||
01-May-18 JDB Multiple consecutive CLC 0 operations are now omitted
|
||||
02-Apr-18 JDB SET CPU 21MX now configures an M-Series model
|
||||
22-Feb-18 JDB Reworked "cpu_ibl" into "cpu_copy_loader"
|
||||
11-Aug-17 JDB MEM must be disabled when DMS is disabled
|
||||
01-Aug-17 JDB Changed SET/SHOW CPU [NO]IDLE to use sim_*_idle routines
|
||||
22-Jul-17 JDB Renamed "intaddr" to CIR; added IR
|
||||
|
@ -892,14 +897,6 @@
|
|||
|
||||
|
||||
|
||||
/* External data */
|
||||
|
||||
extern DIB clk_dib; /* CLK DIB for idle check */
|
||||
extern DIB ptr_dib; /* PTR DIB for BBL configuration */
|
||||
|
||||
extern const BOOT_ROM ptr_rom, dq_rom, ms_rom, ds_rom; /* boot ROMs for cpu_boot routine */
|
||||
|
||||
|
||||
/* CPU program constants */
|
||||
|
||||
|
||||
|
@ -961,6 +958,7 @@ REG *pcq_r = NULL; /* PC queue reg ptr */
|
|||
|
||||
uint32 cpu_configuration; /* the current CPU option set and model */
|
||||
uint32 cpu_speed = 1; /* the CPU speed, expressed as a multiplier of a real machine */
|
||||
t_bool is_1000 = FALSE; /* TRUE if the CPU is a 1000 M/E/F-Series */
|
||||
|
||||
uint32 dev_prl [2] = { ~0u, ~0u }; /* device priority low bit vector */
|
||||
uint32 dev_irq [2] = { 0u, 0u }; /* device interrupt request bit vector */
|
||||
|
@ -988,6 +986,10 @@ static uint32 jsb_plb = 2; /* protected lower bound for JSB
|
|||
static uint32 exec_mask = 0; /* the current instruction execution trace mask */
|
||||
static uint32 exec_match = D16_UMAX; /* the current instruction execution trace matching value */
|
||||
static uint32 indirect_limit = 16; /* the indirect chain length limit */
|
||||
static uint32 last_select_code = 0; /* the last select code sent over the I/O backplane */
|
||||
|
||||
static uint32 tbg_select_code = 0; /* the time-base generator select code (for RTE idle check) */
|
||||
static DEVICE *loader_rom [4] = { NULL }; /* the four boot loader ROM sockets in a 1000 CPU */
|
||||
|
||||
|
||||
/* Memory Expansion Unit local state */
|
||||
|
@ -1013,30 +1015,6 @@ static t_bool defer_tab [] = { /* deferral table, indexed by I/
|
|||
};
|
||||
|
||||
|
||||
/* Basic Binary Loader */
|
||||
|
||||
static const BOOT_ROM bbl = {
|
||||
0107700, 0063770, 0106501, 0004010,
|
||||
0002400, 0006020, 0063771, 0073736,
|
||||
0006401, 0067773, 0006006, 0027717,
|
||||
0107700, 0102077, 0027700, 0017762,
|
||||
0002003, 0027712, 0003104, 0073774,
|
||||
0017762, 0017753, 0070001, 0073775,
|
||||
0063775, 0043772, 0002040, 0027751,
|
||||
0017753, 0044000, 0000000, 0002101,
|
||||
0102000, 0037775, 0037774, 0027730,
|
||||
0017753, 0054000, 0027711, 0102011,
|
||||
0027700, 0102055, 0027700, 0000000,
|
||||
0017762, 0001727, 0073776, 0017762,
|
||||
0033776, 0127753, 0000000, 0103710,
|
||||
0102310, 0027764, 0102510, 0127762,
|
||||
0173775, 0153775, 0100100, 0177765,
|
||||
0000000, 0000000, 0000000, 0000000
|
||||
};
|
||||
|
||||
#define BBL_FWA 072 /* BBL location to store negative FWA */
|
||||
|
||||
|
||||
/* CPU features table.
|
||||
|
||||
The feature table is used to validate CPU feature changes within the subset
|
||||
|
@ -1122,10 +1100,12 @@ static t_stat set_model (UNIT *uptr, int32 new_model, CONST char *cptr, void
|
|||
static t_stat set_option (UNIT *uptr, int32 option, CONST char *cptr, void *desc);
|
||||
static t_stat clear_option (UNIT *uptr, int32 option, CONST char *cptr, void *desc);
|
||||
static t_stat set_loader (UNIT *uptr, int32 enable, CONST char *cptr, void *desc);
|
||||
static t_stat set_roms (UNIT *uptr, int32 option, CONST char *cptr, void *desc);
|
||||
static t_stat set_exec (UNIT *uptr, int32 option, CONST char *cptr, void *desc);
|
||||
|
||||
static t_stat show_stops (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
||||
static t_stat show_model (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
||||
static t_stat show_roms (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
||||
static t_stat show_exec (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
||||
static t_stat show_speed (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
|
||||
|
||||
|
@ -1269,14 +1249,15 @@ static MTAB cpu_mod [] = {
|
|||
{ UNIT_MODEL_MASK, UNIT_2114, "", "2114", &set_model, &show_model, (void *) "2114" },
|
||||
{ UNIT_MODEL_MASK, UNIT_2100, "", "2100", &set_model, &show_model, (void *) "2100" },
|
||||
{ UNIT_MODEL_MASK, UNIT_1000_E, "", "1000-E", &set_model, &show_model, (void *) "1000-E" },
|
||||
{ UNIT_MODEL_MASK, UNIT_1000_E, NULL, "21MX-E", &set_model, &show_model, (void *) "1000-E" },
|
||||
{ UNIT_MODEL_MASK, UNIT_1000_M, "", "1000-M", &set_model, &show_model, (void *) "1000-M" },
|
||||
{ UNIT_MODEL_MASK, UNIT_1000_M, NULL, "21MX-M", &set_model, &show_model, (void *) "1000-M" },
|
||||
|
||||
#if defined (HAVE_INT64)
|
||||
{ UNIT_MODEL_MASK, UNIT_1000_F, "", "1000-F", &set_model, &show_model, (void *) "1000-F" },
|
||||
#endif
|
||||
|
||||
{ UNIT_MODEL_MASK, UNIT_1000_M, NULL, "21MX-M", &set_model, &show_model, (void *) "1000-M" },
|
||||
{ UNIT_MODEL_MASK, UNIT_1000_E, NULL, "21MX-E", &set_model, &show_model, (void *) "1000-E" },
|
||||
|
||||
{ UNIT_EAU, UNIT_EAU, "EAU", "EAU", &set_option, NULL, NULL },
|
||||
{ UNIT_EAU, 0, "no EAU", NULL, NULL, NULL, NULL },
|
||||
{ MTAB_XDV, UNIT_EAU, NULL, "NOEAU", &clear_option, NULL, NULL },
|
||||
|
@ -1345,6 +1326,8 @@ static MTAB cpu_mod [] = {
|
|||
{ MTAB_XDV, 512 * 1024, NULL, "512K", &set_size, NULL, NULL },
|
||||
{ MTAB_XDV, 1024 * 1024, NULL, "1024K", &set_size, NULL, NULL },
|
||||
|
||||
{ MTAB_XDV | MTAB_NMO, 0, "ROMS", "ROMS", &set_roms, &show_roms, NULL },
|
||||
|
||||
{ MTAB_XDV | MTAB_NMO, 1, "STOPS", "STOP", &set_stops, &show_stops, NULL },
|
||||
{ MTAB_XDV, 0, NULL, "NOSTOP", &set_stops, NULL, NULL },
|
||||
{ MTAB_XDV | MTAB_NMO, 2, "INDIR", "INDIR", &set_stops, &show_stops, NULL },
|
||||
|
@ -1472,7 +1455,7 @@ typedef struct {
|
|||
const char *name; /* the classification name */
|
||||
} ACCESS_PROPERTIES;
|
||||
|
||||
static const ACCESS_PROPERTIES access [] = { /* indexed by ACCESS_CLASS */
|
||||
static const ACCESS_PROPERTIES mem_access [] = { /* indexed by ACCESS_CLASS */
|
||||
/* debug_flag name */
|
||||
/* ------------ ------------------- */
|
||||
{ TRACE_FETCH, "instruction fetch" }, /* instruction fetch */
|
||||
|
@ -1718,7 +1701,6 @@ t_bool mp_mem_changed; /* TRUE if the MP or MEM registe
|
|||
static FLIP_FLOP mp_flag = CLEAR; /* MP flag flip-flop */
|
||||
static FLIP_FLOP mp_flagbuf = CLEAR; /* MP flag buffer flip-flop */
|
||||
static FLIP_FLOP mp_evrff = SET; /* enable violation register flip-flop */
|
||||
static t_bool is_1000 = FALSE; /* TRUE if the CPU is a 1000 M/E/F-Series */
|
||||
static char meu_indicator; /* last map access indicator (S | U | A | B | -) */
|
||||
static uint32 meu_page; /* last physical page number accessed */
|
||||
|
||||
|
@ -1820,24 +1802,31 @@ static const BITSET_NAME inbound_names [] = { /* Inbound signal names, in IOSI
|
|||
"ENF", /* 000000000002 */
|
||||
"IOI", /* 000000000004 */
|
||||
"IOO", /* 000000000010 */
|
||||
"SKF", /* 000000000020 */
|
||||
"SFS", /* 000000000040 */
|
||||
"SFC", /* 000000000100 */
|
||||
"STC", /* 000000000200 */
|
||||
"CLC", /* 000000000400 */
|
||||
"STF", /* 000000001000 */
|
||||
"CLF", /* 000000002000 */
|
||||
"EDT", /* 000000004000 */
|
||||
"CRS", /* 000000010000 */
|
||||
"POPIO", /* 000000020000 */
|
||||
"IAK", /* 000000040000 */
|
||||
"SIR" /* 000000100000 */
|
||||
"SFS", /* 000000000020 */
|
||||
"SFC", /* 000000000040 */
|
||||
"STC", /* 000000000100 */
|
||||
"CLC", /* 000000000200 */
|
||||
"STF", /* 000000000400 */
|
||||
"CLF", /* 000000001000 */
|
||||
"EDT", /* 000000002000 */
|
||||
"CRS", /* 000000004000 */
|
||||
"POPIO", /* 000000010000 */
|
||||
"IAK", /* 000000020000 */
|
||||
"SIR" /* 000000040000 */
|
||||
};
|
||||
|
||||
static const BITSET_FORMAT inbound_format = /* names, offset, direction, alternates, bar */
|
||||
{ FMT_INIT (inbound_names, 0, lsb_first, no_alt, no_bar) };
|
||||
|
||||
|
||||
static const BITSET_NAME outbound_names [] = { /* Outbound signal names, in IOSIGNAL order */
|
||||
"SKF" /* 000000200000 */
|
||||
};
|
||||
|
||||
static const BITSET_FORMAT outbound_format = /* names, offset, direction, alternates, bar */
|
||||
{ FMT_INIT (outbound_names, 16, lsb_first, no_alt, no_bar) };
|
||||
|
||||
|
||||
/* I/O instruction sub-opcodes */
|
||||
|
||||
#define soHLT 0 /* halt */
|
||||
|
@ -1890,9 +1879,10 @@ static uint32 io_dispatch (uint32 select_code, IOCYCLE signal_set, HP_WORD dat
|
|||
execution. This involves verifying that there are no device conflicts (e.g.,
|
||||
two devices with the same select code) and initializing the I/O state. These
|
||||
actions accommodate reconfiguration of the I/O device settings and program
|
||||
counter while the simulator was stopped. The prelude also responds to one
|
||||
command-line switch: if "-B" is specified, the current set of simulation stop
|
||||
conditions is bypassed for the first instruction executed.
|
||||
counter while the simulator was stopped. The prelude also picks up the
|
||||
time-base generator's select code for use in idle testing, and it checks for
|
||||
one command-line switch: if "-B" is specified, the current set of simulation
|
||||
stop conditions is bypassed for the first instruction executed.
|
||||
|
||||
Second, the memory protect abort mechanism is set up. MP aborts utilize the
|
||||
"setjmp/longjmp" mechanism to transfer control out of the instruction
|
||||
|
@ -2139,6 +2129,7 @@ static const char *const mp_mem_formats [] = { /* MP/MEM regist
|
|||
|
||||
static uint32 exec_save; /* the trace flag settings saved by an EXEC match */
|
||||
static uint32 idle_save; /* the trace flag settings saved by an idle match */
|
||||
DEVICE *tbg_dptr;
|
||||
int abortval;
|
||||
uint32 intrq, dmarq; /* set after setjmp */
|
||||
t_bool exec_test; /* set after setjmp */
|
||||
|
@ -2158,6 +2149,13 @@ sim_switches &= ~SWMASK ('P'); /* clear the power-on sw
|
|||
if (hp_device_conflict ()) /* if device assignment is inconsistent */
|
||||
return SCPE_STOP; /* then inhibit execution */
|
||||
|
||||
tbg_dptr = find_dev ("CLK"); /* get a pointer to the time-base generator device */
|
||||
|
||||
if (tbg_dptr == NULL) /* if the TBG device is not present */
|
||||
return SCPE_IERR; /* then something is seriously wrong */
|
||||
else /* otherwise */
|
||||
tbg_select_code = ((DIB *) tbg_dptr->ctxt)->select_code; /* get the select code from the device's DIB */
|
||||
|
||||
io_initialize (); /* set up the I/O data structures */
|
||||
cpu_ioerr_uptr = NULL; /* and clear the I/O error unit pointer */
|
||||
|
||||
|
@ -2450,26 +2448,56 @@ return;
|
|||
/* CPU global utility routines */
|
||||
|
||||
|
||||
/* Install an initial binary loader into memory.
|
||||
/* Install a bootstrap loader into memory.
|
||||
|
||||
This routine copies the initial binary loader contained in "rom" to the last
|
||||
64 words of main memory, limited by a 32K memory size. If "dev" contains a
|
||||
This routine copies the bootstrap loader specified by "boot" into the last 64
|
||||
words of main memory, limited by a 32K memory size. If "sc" contains the
|
||||
select code of an I/O interface (i.e., select code 10 or above), this routine
|
||||
will configure the I/O instructions in the IBL to the supplied select code.
|
||||
On exit, P will be set to point at the first word of the loader, and S will
|
||||
be altered as directed by the "sr_clear" and "sr_set" masks.
|
||||
will configure the I/O instructions in the loader to the supplied select
|
||||
code. On exit, P will be set to point at the loader starting program
|
||||
address, and S will be altered as directed by the "sr_clear" and "sr_set"
|
||||
masks if the current CPU is a 1000.
|
||||
|
||||
If I/O configuration is requested, each instruction in the IBL is examined as
|
||||
it is copied to memory. If the instruction is a non-HLT I/O instruction
|
||||
referencing a select code >= 10, the select code will be reset by subtracting
|
||||
10 and adding the value of the select code supplied in the "dev" parameter.
|
||||
This permits configuration of IBLs that address two- or three-card
|
||||
interfaces. Passing a "dev" value of 0 will inhibit configuration.
|
||||
The currently configured CPU family (21xx or 1000) determines which of two
|
||||
BOOT_LOADER structures is accessed from the "boot" array. Each structure
|
||||
contains the 64-word loader array and three indicies into the loader
|
||||
array that specify the start of program execution, the element containing the
|
||||
DMA control word, and the element containing the (negative) address of the
|
||||
first loader word in memory.
|
||||
|
||||
As an example, passing a "dev" value of 24 octal will alter these
|
||||
21xx-series loaders consist of subsections handling one or two devices. A
|
||||
two-part loader is indicated by a starting program index other than 0, i.e.,
|
||||
other than the beginning of the loader. An example is the Basic Moving-Head
|
||||
Disc Loader (BMDL), which consists of a paper tape loader section starting at
|
||||
index 0 and a disc loader section starting at index 50 octal. For these
|
||||
loaders, I/O configuration depends on the "start_index" field of the selected
|
||||
BOOTSTRAP structure: I/O instructions before the starting index are
|
||||
configured to the current paper-tape reader select code, and instructions at
|
||||
or after the starting index are configured to the device select code
|
||||
specified by "sc". Single-part loaders specify a starting index of 0, and
|
||||
all I/O instructions are configured to the "sc" select code.
|
||||
|
||||
1000-series loaders are always single part and always start at index 0, so
|
||||
they are always configured to use the "sc" select code.
|
||||
|
||||
If a given device does not have both a 21xx-series and a 1000-series loader,
|
||||
the "start_index" field of the undefined loader will be set to the "IBL_NA"
|
||||
value. If this routine is called to copy an undefined loader, it will reject
|
||||
the call with a "Command not allowed" error.
|
||||
|
||||
If I/O configuration is requested, each instruction in the loader array is
|
||||
examined as it is copied to memory. If the instruction is a non-HLT I/O
|
||||
instruction referencing a select code >= 10, the select code will be reset by
|
||||
subtracting 10 and adding the value of the select code supplied by the "sc"
|
||||
parameter (or the paper-tape reader select code, as above). This permits
|
||||
configuration of loaders that address two- or three-card interfaces. Passing
|
||||
an "sc" value of 0 will inhibit configuration, and the loader array will be
|
||||
copied verbatim.
|
||||
|
||||
As an example, passing an "sc" value of 24 octal will alter these I/O-group
|
||||
instructions as follows:
|
||||
|
||||
IBL Configured
|
||||
Loader Configured
|
||||
Instruction Instruction Note
|
||||
----------- ----------- ------------------------------
|
||||
OTA 10 OTA 24 Normal configuration
|
||||
|
@ -2477,46 +2505,92 @@ return;
|
|||
STC 6 STC 6 DCPC configuration not changed
|
||||
HLT 11 HLT 11 Halt instruction not changed
|
||||
|
||||
If configuration is performed, the routine will also alter the next-to-last
|
||||
word unconditionally as above. This word is assumed to contain a DCPC
|
||||
control word; it is configured to reference the supplied select code.
|
||||
If configuration is performed, two additional operations may be performed.
|
||||
First, the routine will alter the word at the index specified by the
|
||||
"dma_index" field of the selected BOOTSTRAP structure unconditionally as
|
||||
above. This word is assumed to contain a DMA control word; it is configured
|
||||
to reference the supplied select code. Second, it will set the word at the
|
||||
index specified by the "fwa_index" field to the two's-complement of the
|
||||
starting address of the loader in memory. This value may be used by the
|
||||
loader to check that it will not be overwritten by loaded data.
|
||||
|
||||
Finally, the routine sets the last word to the two's-complement of the
|
||||
starting address of the IBL. This value may be used by the loader to check
|
||||
that it will not be overwritten by loaded data.
|
||||
If either field is set to the IBL_NA value, then the corresponding
|
||||
modification is not made. For example, the 21xx Basic Binary Loader (BBL)
|
||||
does not use DMA, so its "dma_index" field is set to IBL_NA, and so no DMA
|
||||
control word modification is done.
|
||||
|
||||
This routine also unconditionally sets the P register to the starting
|
||||
address for loader execution. This is derived from the "start_index" field
|
||||
and the starting memory address to which the loader is copied.
|
||||
|
||||
Finally, if the current CPU is a 1000-series machine, the S register bits
|
||||
corresponding to those set in the "sr_clear" value are masked off, and the
|
||||
bits corresponding to those in the "sr_set" value are set. In addition, the
|
||||
select code from the "sc" value is shifted left and ORed into the value.
|
||||
This action presets the S-register to the correct value for the selected
|
||||
loader.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. The paper-tape reader's select code is determined on each entry to the
|
||||
routine to accommodate select code reassignment by the user.
|
||||
*/
|
||||
|
||||
void cpu_ibl (const BOOT_ROM rom, int32 dev, HP_WORD sr_clear, HP_WORD sr_set)
|
||||
t_stat cpu_copy_loader (const LOADER_ARRAY boot, uint32 sc, HP_WORD sr_clear, HP_WORD sr_set)
|
||||
{
|
||||
int32 i;
|
||||
MEMORY_WORD wd;
|
||||
uint32 index, base, ptr_sc;
|
||||
MEMORY_WORD word;
|
||||
DEVICE *ptr_dptr;
|
||||
|
||||
set_loader (NULL, TRUE, NULL, NULL); /* enable loader (ignore errors) */
|
||||
if (boot [is_1000].start_index == IBL_NA) /* if the bootstrap is not defined for the current CPU */
|
||||
return SCPE_NOFNC; /* then reject the command */
|
||||
|
||||
PR = ((MEMSIZE - 1) & ~IBL_MASK) & VAMASK; /* start at mem top */
|
||||
|
||||
for (i = 0; i < IBL_LNT; i++) { /* copy bootstrap */
|
||||
wd = rom [i]; /* get word */
|
||||
|
||||
if (dev >= VARDEV /* if reconfiguration is desired */
|
||||
&& (wd & I_NMRMASK) == I_IO /* and this is an I/O instruction */
|
||||
&& (wd & I_DEVMASK) >= VARDEV /* and the referenced select code is >= 10B */
|
||||
&& I_GETIOOP (wd) != soHLT) /* and it's not a halt instruction */
|
||||
M [PR + i] = (wd + (dev - VARDEV)) & DMASK; /* then reconfigure the select code */
|
||||
else if (boot [is_1000].start_index > 0 && sc > 0) { /* if this is a two-part loader with I/O reconfiguration */
|
||||
ptr_dptr = find_dev ("PTR"); /* then get a pointer to the paper tape reader device */
|
||||
|
||||
if (ptr_dptr == NULL) /* if the PTR device is not present */
|
||||
return SCPE_IERR; /* then something is seriously wrong */
|
||||
else /* otherwise */
|
||||
M [PR + i] = wd; /* copy the instruction verbatim */
|
||||
ptr_sc = ((DIB *) ptr_dptr->ctxt)->select_code; /* get the select code from the device's DIB */
|
||||
}
|
||||
|
||||
if (dev >= VARDEV) /* if reconfiguration was performed */
|
||||
M [PR + IBL_DPC] = M [PR + IBL_DPC] + dev - VARDEV /* then patch the DMA control word */
|
||||
& DMASK;
|
||||
else /* otherwise this is a single-part loader */
|
||||
ptr_sc = 0; /* or I/O reconfiguration is not requested */
|
||||
|
||||
M [PR + IBL_END] = (~PR + 1) & DMASK; /* fill in start of boot */
|
||||
base = MEMSIZE - 1 & ~IBL_MASK & LA_MASK; /* get the base memory address of the loader */
|
||||
PR = base + boot [is_1000].start_index & R_MASK; /* and store the starting program address in P */
|
||||
|
||||
SR = (SR & sr_clear) | sr_set; /* modify the S register as indicated */
|
||||
set_loader (NULL, TRUE, NULL, NULL); /* enable the loader (ignore errors if not 21xx) */
|
||||
|
||||
return;
|
||||
for (index = 0; index < IBL_SIZE; index++) { /* copy the bootstrap loader to memory */
|
||||
word = boot [is_1000].loader [index]; /* get the next word */
|
||||
|
||||
if (sc == 0) /* if reconfiguration is not requested */
|
||||
M [base + index] = word; /* then copy the instruction verbatim */
|
||||
|
||||
else if ((word & I_NMRMASK) == I_IO /* otherwise if this is an I/O instruction */
|
||||
&& (word & I_DEVMASK) >= VARDEV /* and the referenced select code is >= 10B */
|
||||
&& I_GETIOOP (word) != soHLT) /* and it's not a halt instruction */
|
||||
if (index < boot [is_1000].start_index) /* then if this is a split loader */
|
||||
M [base + index] = word + (ptr_sc - VARDEV) & DV_MASK; /* then reconfigure the paper tape reader */
|
||||
else /* otherwise */
|
||||
M [base + index] = word + (sc - VARDEV) & DV_MASK; /* reconfigure the target device */
|
||||
|
||||
else if (index == boot [is_1000].dma_index) /* otherwise if this is the DMA configuration word */
|
||||
M [base + index] = word + (sc - VARDEV) & DV_MASK; /* then reconfigure the target device */
|
||||
|
||||
else if (index == boot [is_1000].fwa_index) /* otherwise if this is the starting address word */
|
||||
M [base + index] = NEG16 (base); /* then set the negative starting address of the bootstrap */
|
||||
|
||||
else /* otherwise the word is not a special one */
|
||||
M [base + index] = word; /* so simply copy it */
|
||||
}
|
||||
|
||||
if (is_1000) /* if the CPU is a 1000 */
|
||||
SR = SR & sr_clear | sr_set | IBL_TO_SC (sc); /* then modify the S register as indicated */
|
||||
|
||||
return SCPE_OK; /* return success with the loader copied to memory */
|
||||
}
|
||||
|
||||
|
||||
|
@ -2561,6 +2635,10 @@ return;
|
|||
do this in preference to calling the recalculation routines directly, as
|
||||
some extended firmware instructions call this routine multiple times, and
|
||||
there is no point in recalculating until all calls are complete.
|
||||
|
||||
6. The I/O dispatcher returns NOTE_SKIP if the interface asserted the SKF
|
||||
signal. We must recalculate interrupts if the originating SFS or SFC
|
||||
instruction included the CLF signal (e.g., SFS 0,C).
|
||||
*/
|
||||
|
||||
t_stat cpu_iog (HP_WORD IR, t_bool iotrap)
|
||||
|
@ -2605,12 +2683,13 @@ ioreturn = io_dispatch (dev, signal_set, iodata); /* dispatch the I/O sign
|
|||
iostat = IOSTATUS (ioreturn); /* extract status */
|
||||
iodata = IODATA (ioreturn); /* extract return data value */
|
||||
|
||||
if (iostat == SCPE_OK) { /* if instruction execution succeeded */
|
||||
if ((sop == soSFC || sop == soSFS) /* then if it is an SFC or SFS */
|
||||
&& (IOSIGNAL) iodata == ioSKF) /* and SKF is asserted */
|
||||
if (iostat == NOTE_SKIP) { /* if the interface asserted SKF */
|
||||
PR = PR + 1 & LA_MASK; /* then bump P to skip then next instruction */
|
||||
return (IR & I_HC ? NOTE_IOG : SCPE_OK); /* and request recalculation of interrupts if needed */
|
||||
}
|
||||
|
||||
else if (sop == soLIX) /* otherwise if is it an LIA or LIB */
|
||||
else if (iostat == SCPE_OK) { /* otherwise if instruction execution succeeded */
|
||||
if (sop == soLIX) /* then if is it an LIA or LIB */
|
||||
ABREG [ab] = iodata; /* then load the returned data */
|
||||
|
||||
else if (sop == soMIX) /* otherwise if it is an MIA or MIB */
|
||||
|
@ -2926,11 +3005,11 @@ if (index <= 1 && map < PAMAP) /* if the A/B register i
|
|||
else /* otherwise */
|
||||
TR = (HP_WORD) M [index]; /* return the physical memory value */
|
||||
|
||||
tpprintf (dptr, access [classification].debug_flag,
|
||||
tpprintf (dptr, mem_access [classification].debug_flag,
|
||||
DMS_FORMAT " %s%s\n",
|
||||
meu_indicator, meu_page, MR, TR,
|
||||
access [classification].name,
|
||||
access [classification].debug_flag == TRACE_FETCH ? "" : " read");
|
||||
mem_access [classification].name,
|
||||
mem_access [classification].debug_flag == TRACE_FETCH ? "" : " read");
|
||||
|
||||
return TR;
|
||||
}
|
||||
|
@ -3056,10 +3135,10 @@ else if (index < fwanxm) /* otherwise if the loca
|
|||
|
||||
TR = value; /* save the value */
|
||||
|
||||
tpprintf (dptr, access [classification].debug_flag,
|
||||
tpprintf (dptr, mem_access [classification].debug_flag,
|
||||
DMS_FORMAT " %s write\n",
|
||||
meu_indicator, meu_page, MR, TR,
|
||||
access [classification].name);
|
||||
mem_access [classification].name);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -3393,10 +3472,21 @@ return;
|
|||
interrupt system and turn it off."
|
||||
|
||||
4. Select code 0 cannot interrupt, so there is no SIR handler.
|
||||
|
||||
5. To guarantee proper initialization, the 12920A terminal multiplexer
|
||||
requires that the Control Reset (CRS) I/O signal be asserted for a
|
||||
minimum of 100 milliseconds. In practice, this is achieved by executing
|
||||
131,072 (128K) CLC 0 instructions in a tight loop. This is not necessary
|
||||
in simulation, and in fact is detrimental, as 262,000+ trace lines will
|
||||
be written for each device that enables IOBUS tracing. To avoid this,
|
||||
consecutive CLC 0 operations after the first are omitted. This is
|
||||
detected by checking the select code and signal set of the last I/O
|
||||
operation.
|
||||
*/
|
||||
|
||||
static uint32 cpuio (DIB *dibptr, IOCYCLE signal_set, uint32 stat_data)
|
||||
{
|
||||
static IOCYCLE last_signal_set = ioNONE; /* the last set of I/O signals processed */
|
||||
uint32 sc;
|
||||
IOSIGNAL signal;
|
||||
IOCYCLE working_set = signal_set; /* no SIR handler needed */
|
||||
|
@ -3459,7 +3549,10 @@ while (working_set) {
|
|||
break;
|
||||
|
||||
case ioCLC: /* clear control flip-flop */
|
||||
for (sc = CRSDEV; sc <= MAXDEV; sc++) /* send CRS to devices */
|
||||
if (last_select_code != 0 /* if the last I/O instruction */
|
||||
|| (last_signal_set & ioCLC) == 0) /* was not a CLC 0 */
|
||||
for (sc = CRSDEV; sc <= MAXDEV; sc++) /* then assert the CRS signal */
|
||||
if (devs [sc] != NULL) /* to all occupied I/O slots */
|
||||
io_dispatch (sc, ioCRS, 0); /* from select code 6 and up */
|
||||
break;
|
||||
|
||||
|
@ -3470,6 +3563,8 @@ while (working_set) {
|
|||
working_set = working_set & ~signal; /* remove current signal from set */
|
||||
}
|
||||
|
||||
last_signal_set = signal_set; /* save the current signal set for the next call */
|
||||
|
||||
return stat_data;
|
||||
}
|
||||
|
||||
|
@ -3682,11 +3777,10 @@ return SCPE_OK; /* return success status
|
|||
If this is the first call after simulator startup, the initial memory array
|
||||
is allocated, the default CPU and memory size configuration is set, and the
|
||||
SCP-required program counter pointer is set to point to the REG array element
|
||||
corresponding to the P register.
|
||||
|
||||
If this is a power-on reset ("RESET -P"), the default Basic Binary Loader is
|
||||
installed in protected memory (the upper 64 words of the defined memory
|
||||
size).
|
||||
corresponding to the P register. In addition, the loader ROM sockets of the
|
||||
1000-series CPUs are populated with the initial ROM set, and the Basic Binary
|
||||
Loader (BBL) is installed in protected memory (the upper 64 words of the
|
||||
defined memory size).
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
@ -3695,30 +3789,33 @@ return SCPE_OK; /* return success status
|
|||
order automatically. A fixed setting runs the risk of it not being
|
||||
updated if a change in the register order is made.
|
||||
|
||||
2. A power-on reset installs the BBL in 21xx machines. The IBL copy routine
|
||||
sets the last loader word to the two's complement of the loader starting
|
||||
address and configures the second-to-last word (nominally the DMA control
|
||||
word) to the I/O select code. For the BBL, the starting address location
|
||||
is five locations back, and the DMA control word is not used, so these
|
||||
fixups are performed after copying.
|
||||
2. The initial set of installed HP 1000 boot loader ROMs is:
|
||||
|
||||
Socket ROM Boot Device
|
||||
------ ------ ------------------------
|
||||
0 12992K 2748 Paper Tape Reader
|
||||
1 12992A 7900 or 2883 Disc Drive
|
||||
2 12992D 7970 Magnetic Tape Drive
|
||||
3 12992B 7905/06/20/25 Disc Drive
|
||||
*/
|
||||
|
||||
static t_stat cpu_reset (DEVICE *dptr)
|
||||
{
|
||||
if (M == NULL) { /* initial call after startup? */
|
||||
pcq_r = find_reg ("PCQ", NULL, dptr); /* get PC queue pointer */
|
||||
if (M == NULL) { /* if this is the initial call after simulator startup */
|
||||
pcq_r = find_reg ("PCQ", NULL, dptr); /* then get the PC queue pointer */
|
||||
|
||||
if (pcq_r) /* defined? */
|
||||
pcq_r->qptr = 0; /* initialize queue */
|
||||
else /* not defined */
|
||||
return SCPE_IERR; /* internal error */
|
||||
if (pcq_r == NULL) /* if the PCQ register is not present */
|
||||
return SCPE_IERR; /* then something is seriously wrong */
|
||||
else /* otherwise */
|
||||
pcq_r->qptr = 0; /* initialize the register's queue pointer */
|
||||
|
||||
M = (MEMORY_WORD *) calloc (PASIZE, sizeof (MEMORY_WORD)); /* alloc mem */
|
||||
M = (MEMORY_WORD *) calloc (PASIZE, /* allocate and zero the main memory array */
|
||||
sizeof (MEMORY_WORD)); /* to the maximum configurable size */
|
||||
|
||||
if (M == NULL) /* alloc fail? */
|
||||
return SCPE_MEM;
|
||||
if (M == NULL) /* if the allocation failed */
|
||||
return SCPE_MEM; /* then report a "Memory exhausted" error */
|
||||
|
||||
else { /* do one-time init */
|
||||
else { /* otherwise perform one-time initialization */
|
||||
for (sim_PC = dptr->registers; /* find the P register entry */
|
||||
sim_PC->loc != &PR && sim_PC->loc != NULL; /* in the register array */
|
||||
sim_PC++); /* for the SCP interface */
|
||||
|
@ -3728,27 +3825,22 @@ if (M == NULL) { /* initial call after st
|
|||
|
||||
MEMSIZE = 32768; /* set the initial memory size */
|
||||
set_model (NULL, UNIT_2116, NULL, NULL); /* and the initial CPU model */
|
||||
|
||||
loader_rom [0] = find_dev ("PTR"); /* install the 12992K ROM in socket 0 */
|
||||
loader_rom [1] = find_dev ("DQC"); /* and the 12992A ROM in socket 1 */
|
||||
loader_rom [2] = find_dev ("MSC"); /* and the 12992D ROM in socket 2 */
|
||||
loader_rom [3] = find_dev ("DS"); /* and the 12992B ROM in socket 3 */
|
||||
|
||||
loader_rom [0]->boot (0, loader_rom [0]); /* install the BBL via the paper tape reader boot routine */
|
||||
set_loader (NULL, FALSE, NULL, NULL); /* and then disable the loader, which was enabled */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (sim_switches & SWMASK ('P')) { /* if this is a power-on reset */
|
||||
if (! is_1000) { /* then if the CPU is configured as a 21xx machine */
|
||||
cpu_ibl (bbl, ptr_dib.select_code, /* then install the BBL and configure it */
|
||||
IBL_S_NOCLR, IBL_S_NOSET); /* to the paper tape reader's select code */
|
||||
|
||||
M [PR + BBL_FWA] = M [PR + IBL_END]; /* move the BBL starting address to correct location */
|
||||
M [PR + IBL_DPC] = bbl [IBL_DPC]; /* and restore the last two words of the BBL */
|
||||
M [PR + IBL_END] = bbl [IBL_END]; /* that are overwritten by the 1000 IBL */
|
||||
|
||||
set_loader (NULL, FALSE, NULL, NULL); /* disable the loader, which was enabled by cpu_ibl */
|
||||
}
|
||||
|
||||
IOPOWERON (&cpu_dib); /* issue the PON signal to the CPU */
|
||||
}
|
||||
|
||||
else /* PRESET */
|
||||
IOPRESET (&cpu_dib);
|
||||
if (sim_switches & SWMASK ('P')) /* if this is a power-on reset */
|
||||
IOPOWERON (&cpu_dib); /* then issue the PON signal to the CPU */
|
||||
else /* otherwise */
|
||||
IOPRESET (&cpu_dib); /* issue a PRESET */
|
||||
|
||||
sim_brk_dflt = SWMASK ('N'); /* the default breakpoint type is "nomap" as MEM is disabled */
|
||||
|
||||
|
@ -3756,36 +3848,68 @@ return SCPE_OK;
|
|||
}
|
||||
|
||||
|
||||
/* IBL routine (CPU boot) */
|
||||
/* Device boot routine.
|
||||
|
||||
This routine is called by the BOOT CPU and LOAD CPU commands to copy the
|
||||
specified boot loader ROM program into the upper 64 words of the logical
|
||||
address space. It is equivalent to pressing the IBL (Initial Binary Loader)
|
||||
button on the front panel of a 1000 M/E/F-Series CPU.
|
||||
|
||||
On entry, the S register must be set to indicate the specific boot loader ROM
|
||||
and the associated device select code to be copied, as follows:
|
||||
|
||||
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| ROM # | - - | select code | - - - - - - |
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
|
||||
Bits 15-14 select one of four loader ROM sockets on the CPU board that may
|
||||
contain ROMs. If the specified socket does, the contents of the ROM are
|
||||
copied into the upper 64 words of memory and configured to use the specified
|
||||
select code. The unspecified bits of the S register are available for use by
|
||||
the bootstrap program.
|
||||
|
||||
If the select code is less than 10 octal, the loader is not copied, and the
|
||||
O (overflow) register is set to 1. A successful copy and configuration
|
||||
clears the O register.
|
||||
|
||||
The 21xx-series CPUs do not provide the IBL function. If this routine is
|
||||
invoked while the CPU is configured as one of these machines, the command is
|
||||
rejected.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. In hardware, a non-existent ROM (i.e., an empty socket) reads as though
|
||||
all words contain 177777 octal. This would result in the loader area of
|
||||
memory containing 62 all-ones words, followed by a word set to 177777 +
|
||||
SC - 000010, where SC is the configured select code, followed by a word
|
||||
set to the negative starting address of the loader. This is not
|
||||
simulated; instead, an attempt to boot from an empty socket is rejected
|
||||
with "Command not allowed."
|
||||
*/
|
||||
|
||||
static t_stat cpu_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
int32 dev = (SR >> IBL_V_DEV) & I_DEVMASK;
|
||||
int32 sel = (SR >> IBL_V_SEL) & IBL_M_SEL;
|
||||
const int32 select_code = IBL_SC (SR); /* the select code from S register bits 11-6 */
|
||||
const int32 rom_socket = IBL_ROM (SR); /* the ROM socket number from S register bits 15-14 */
|
||||
|
||||
if (dev < 010)
|
||||
return SCPE_NOFNC;
|
||||
|
||||
switch (sel) {
|
||||
|
||||
case 0: /* PTR boot */
|
||||
cpu_ibl (ptr_rom, dev, IBL_S_NOCLR, IBL_S_NOSET);
|
||||
break;
|
||||
|
||||
case 1: /* DP/DQ boot */
|
||||
cpu_ibl (dq_rom, dev, IBL_S_NOCLR, IBL_S_NOSET);
|
||||
break;
|
||||
|
||||
case 2: /* MS boot */
|
||||
cpu_ibl (ms_rom, dev, IBL_S_NOCLR, IBL_S_NOSET);
|
||||
break;
|
||||
|
||||
case 3: /* DS boot */
|
||||
cpu_ibl (ds_rom, dev, IBL_S_NOCLR, IBL_S_NOSET);
|
||||
break;
|
||||
if (is_1000) /* if this is a 1000-series CPU */
|
||||
if (select_code < VARDEV) { /* then if the select code is invalid */
|
||||
O = 1; /* then set the overflow register */
|
||||
return SCPE_ARG; /* and reject the IBL with "Invalid argument" */
|
||||
}
|
||||
|
||||
return SCPE_OK;
|
||||
else if (loader_rom [rom_socket] == NULL) /* otherwise if the ROM socket is empty */
|
||||
return SCPE_NXDEV; /* then reject with "Non-existent device" */
|
||||
|
||||
else { /* otherwise */
|
||||
O = 0; /* clear overflow to indicate a good IBL */
|
||||
return loader_rom [rom_socket]->boot (select_code, NULL); /* and copy the ROM into memory */
|
||||
}
|
||||
|
||||
else /* otherwise this is a 21xx machine */
|
||||
return SCPE_NOFNC; /* and IBL isn't supported */
|
||||
}
|
||||
|
||||
|
||||
|
@ -3930,7 +4054,7 @@ if (is_1000) /* loader unsupported */
|
|||
else { /* 21xx CPU? */
|
||||
set_loader (uptr, FALSE, NULL, NULL); /* save loader to shadow RAM */
|
||||
MEMSIZE = new_size; /* set new memory size */
|
||||
fwanxm = (uint32) MEMSIZE - IBL_LNT; /* reserve memory for loader */
|
||||
fwanxm = (uint32) MEMSIZE - IBL_SIZE; /* reserve memory for loader */
|
||||
}
|
||||
|
||||
for (i = fwanxm; i < old_size; i++) /* zero non-existent memory */
|
||||
|
@ -4052,7 +4176,7 @@ if (result == SCPE_OK) { /* if the ch
|
|||
if (is_1000)
|
||||
fwanxm = (uint32) MEMSIZE; /* loader reserved only for 21xx */
|
||||
else /* 2100 or 211x */
|
||||
fwanxm = (uint32) MEMSIZE - IBL_LNT; /* reserve memory for loader */
|
||||
fwanxm = (uint32) MEMSIZE - IBL_SIZE; /* reserve memory for loader */
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -4188,23 +4312,23 @@ return SCPE_OK;
|
|||
|
||||
static t_stat set_loader (UNIT *uptr, int32 enable, CONST char *cptr, void *desc)
|
||||
{
|
||||
static BOOT_ROM loader;
|
||||
int32 i;
|
||||
static MEMORY_WORD loader [IBL_SIZE];
|
||||
uint32 i;
|
||||
t_bool is_enabled = (fwanxm == MEMSIZE);
|
||||
|
||||
if (is_1000 || MEMSIZE == 0) /* valid only for 21xx and for initialized memory */
|
||||
return SCPE_NOFNC;
|
||||
|
||||
if (is_enabled && (enable == 0)) { /* disable loader? */
|
||||
fwanxm = (uint32) MEMSIZE - IBL_LNT; /* decrease available memory */
|
||||
for (i = 0; i < IBL_LNT; i++) { /* copy loader */
|
||||
fwanxm = (uint32) MEMSIZE - IBL_SIZE; /* decrease available memory */
|
||||
for (i = 0; i < IBL_SIZE; i++) { /* copy loader */
|
||||
loader [i] = M [fwanxm + i]; /* from memory */
|
||||
M [fwanxm + i] = 0; /* and zero location */
|
||||
}
|
||||
}
|
||||
|
||||
else if ((!is_enabled) && (enable == 1)) { /* enable loader? */
|
||||
for (i = 0; i < IBL_LNT; i++) /* copy loader */
|
||||
for (i = 0; i < IBL_SIZE; i++) /* copy loader */
|
||||
M [fwanxm + i] = loader [i]; /* to memory */
|
||||
fwanxm = (uint32) MEMSIZE; /* increase available memory */
|
||||
}
|
||||
|
@ -4213,6 +4337,100 @@ return SCPE_OK;
|
|||
}
|
||||
|
||||
|
||||
/* Change the set of installed loader ROMs.
|
||||
|
||||
This validation routine is called to install loader ROMs in the four
|
||||
available sockets of a 1000-series CPU. The routine processes commands of
|
||||
the form:
|
||||
|
||||
SET CPU ROMS=[<dev0>][;[<dev1>][;[<dev2>][;[<dev3>]]]]
|
||||
|
||||
On entry, "cptr" points at the the first character of the ROM list. The
|
||||
option value and the unit and description pointers are not used.
|
||||
|
||||
All four ROM sockets are set for each command. If no devices are specified,
|
||||
then all sockets are emptied. Otherwise, specifying a valid device name
|
||||
installs the device loader ROM into the socket corresponding to the position
|
||||
of the device name in the list. Sockets may be left empty by omitting the
|
||||
corresponding device name or by supplying fewer than four device names.
|
||||
|
||||
Loader ROMs may only be altered if the current CPU model is a 1000-series
|
||||
machine, and a device must be bootable and have a loader ROM assigned, or the
|
||||
command will be rejected. A rejected command does not alter any of the ROM
|
||||
assignments.
|
||||
|
||||
Example commands and their effects on the installed ROM sockets follow:
|
||||
|
||||
Command Action
|
||||
--------------------- -------------------------------------------------
|
||||
SET CPU ROMS= Remove ROMs from sockets 0-3
|
||||
SET CPU ROMS=PTR Install PTR in 0; leave 1-3 empty
|
||||
SET CPU ROMS=DS;MS Install DS in 0 and MS in 1; leave 2 and 3 empty
|
||||
SET CPU ROMS=;;DPC Install DPC in 2; leave 0, 1, and 3 empty
|
||||
SET CPU ROMS=DQC;;;DA Install DQC in 0 and DA in 3; leave 1 and 2 empty
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. Entering "SET CPU ROMS" without an equals sign or list is rejected with a
|
||||
"Missing value" error. This is to prevent accidental socket clearing
|
||||
when "SHOW CPU ROMS" was intended.
|
||||
*/
|
||||
|
||||
static t_stat set_roms (UNIT *uptr, int32 option, CONST char *cptr, void *desc)
|
||||
{
|
||||
DEVICE *dptr;
|
||||
char gbuf [CBUFSIZE];
|
||||
uint32 socket = 0;
|
||||
DEVICE *rom [4] = { NULL };
|
||||
|
||||
if (is_1000 == FALSE) /* if the CPU is not a 1000-series unit */
|
||||
return SCPE_NOFNC; /* then reject the command */
|
||||
|
||||
else if (cptr == NULL) /* otherwise if the list is not specified */
|
||||
return SCPE_MISVAL; /* then report that the list is missing */
|
||||
|
||||
else if (*cptr == '\0') { /* otherwise if the list is null */
|
||||
loader_rom [0] = NULL; /* then empty */
|
||||
loader_rom [1] = NULL; /* all of the */
|
||||
loader_rom [2] = NULL; /* ROM sockets */
|
||||
loader_rom [3] = NULL;
|
||||
}
|
||||
|
||||
else { /* otherwise */
|
||||
while (*cptr) { /* loop through the arguments */
|
||||
cptr = get_glyph (cptr, gbuf, ';'); /* get the next argument */
|
||||
|
||||
if (socket == 4) /* if all four sockets have been set */
|
||||
return SCPE_2MARG; /* then reject the command */
|
||||
|
||||
else if (gbuf [0] == '\0') /* otherwise if the device name is omitted */
|
||||
rom [socket++] = NULL; /* then empty the corresponding socket */
|
||||
|
||||
else { /* otherwise we have a device name */
|
||||
dptr = find_dev (gbuf); /* so find the associated DEVICE pointer */
|
||||
|
||||
if (dptr == NULL) /* if the device name is not valid */
|
||||
return SCPE_NXDEV; /* then reject the command */
|
||||
|
||||
else if (dptr->boot == NULL) /* otherwise if it's valid but not bootable */
|
||||
return SCPE_NOFNC; /* then reject the command */
|
||||
|
||||
else /* otherwise */
|
||||
rom [socket++] = dptr; /* install the boot loader ROM */
|
||||
}
|
||||
}
|
||||
|
||||
loader_rom [0] = rom [0]; /* install the ROM set */
|
||||
loader_rom [1] = rom [1]; /* now that we have */
|
||||
loader_rom [2] = rom [2]; /* a valid */
|
||||
loader_rom [3] = rom [3]; /* device list */
|
||||
}
|
||||
|
||||
return SCPE_OK; /* report that the command succeeded */
|
||||
}
|
||||
|
||||
|
||||
/* Change the instruction execution trace criteria.
|
||||
|
||||
This validation routine is called to configure the criteria that select
|
||||
|
@ -4363,6 +4581,75 @@ return SCPE_OK;
|
|||
}
|
||||
|
||||
|
||||
/* Show the set of installed loader ROMs.
|
||||
|
||||
This display routine is called to show the set of installed loader ROMs in
|
||||
the four available sockets of a 1000-series CPU. On entry, the "st"
|
||||
parameter is the open output stream. The other parameters are not used.
|
||||
|
||||
The routine prints a table of ROMs in this format:
|
||||
|
||||
Socket Device ROM
|
||||
------ ------- ------
|
||||
0 PTR 12992K
|
||||
1 DQC 12992A
|
||||
2 DS 12992B
|
||||
3 <empty>
|
||||
|
||||
If a given socket contains a ROM, the associated device name and HP part
|
||||
number for the loader ROM are printed.
|
||||
|
||||
This routine services an extended modifier entry, so it must add the trailing
|
||||
newline to the output before returning.
|
||||
*/
|
||||
|
||||
static t_stat show_roms (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
|
||||
{
|
||||
struct LOOKUP_TABLE {
|
||||
char *name; /* device name */
|
||||
char suffix; /* ROM part number suffix */
|
||||
};
|
||||
|
||||
static const struct LOOKUP_TABLE lookup [] = { /* table of device names and ROM part numbers */
|
||||
{ "DQC", 'A' }, /* 12992A 7900/7901/2883 Disc Loader */
|
||||
{ "DS", 'B' }, /* 12992B 7905/7906/7920/7925 Disc Loader */
|
||||
{ "MSC", 'D' }, /* 12992D 7970 Magnetic Tape Loader */
|
||||
{ "DPC", 'F' }, /* 12992F 7900/7901 Disc Loader */
|
||||
{ "DA", 'H' }, /* 12992H 7906H/7920H/7925H/9885 Disc Loader */
|
||||
{ "IPLI", 'K' }, /* 12992K Paper Tape Loader */
|
||||
{ "PTR", 'K' }, /* 12992K Paper Tape Loader */
|
||||
{ NULL, '?' }
|
||||
};
|
||||
|
||||
CONST char *dname;
|
||||
uint32 socket, index;
|
||||
char letter = '?';
|
||||
|
||||
fputc ('\n', st); /* skip a line */
|
||||
fputs ("Socket Device ROM\n", st); /* and print */
|
||||
fputs ("------ ------- ------\n", st); /* the table header */
|
||||
|
||||
for (socket = 0; socket < 4; socket++) /* loop through the sockets */
|
||||
if (loader_rom [socket] == NULL) /* if the socket is empty */
|
||||
fprintf (st, " %u <empty>\n", socket); /* then report it as such */
|
||||
|
||||
else { /* otherwise the socket is occupied */
|
||||
dname = loader_rom [socket]->name; /* so get the device name */
|
||||
|
||||
for (index = 0; lookup [index].name; index++) /* search the lookup table */
|
||||
if (strcmp (lookup [index].name, dname) == 0) { /* for a match to the device name */
|
||||
letter = lookup [index].suffix; /* and get the part number suffix */
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf (st, " %u %-4s 12992%c\n", /* print the ROM information */
|
||||
socket, dname, letter);
|
||||
}
|
||||
|
||||
return SCPE_OK; /* return success status */
|
||||
}
|
||||
|
||||
|
||||
/* Show the instruction execution trace criteria.
|
||||
|
||||
This display routine is called to show the criteria that select instruction
|
||||
|
@ -4722,7 +5009,7 @@ switch (UPPER_BYTE (IR)) { /* dispatch on bits 15-8
|
|||
&& (mem_fast_read (PR, dms_ump) & I_MRG) == I_ISZ) /* and *-1 is ISZ <n> */
|
||||
&& mp_fence == 0 /* and the MP fence is zero */
|
||||
&& M [xeqt] == 0 /* and no program is executing */
|
||||
&& M [tbg] == clk_dib.select_code) /* and the TBG select code is set */
|
||||
&& M [tbg] == tbg_select_code) /* and the TBG select code is set */
|
||||
|
||||
|| PR == err_PC - 3 /* or the jump target is *-3 (DOS through DOS-III) */
|
||||
&& M [PR] == I_STF /* and *-3 is STF 0 */
|
||||
|
@ -5827,7 +6114,8 @@ for (i = 0; sim_devices [i] != NULL; i++) { /* loop through all of t
|
|||
devs [dibptr->select_code] = dptr; /* then set the device pointer into the device table */
|
||||
dibs [dibptr->select_code] = dibptr; /* and set the DIB pointer into the dispatch table */
|
||||
|
||||
dibptr->io_handler (dibptr, ioSIR, 0); /* set the interrupt request state */
|
||||
if (dibptr->select_code >= SIRDEV) /* if this device receives SIR */
|
||||
dibptr->io_handler (dibptr, ioSIR, 0); /* then set the interrupt request state */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5876,17 +6164,15 @@ return;
|
|||
(high on the 1000, low on the 21xx). For select codes >= 10 octal, an
|
||||
IOI reads the floating I/O bus (low on all machines).
|
||||
|
||||
2. If the UNSC simulation stop is set, a stop will occur when an unassigned
|
||||
device is accessed. An exception is a CLC 0 instruction, which asserts
|
||||
the CRS signal to all I/O devices from select code 6 up. This is a
|
||||
legitimate access and does not cause a stop.
|
||||
2. The last select code used is saved for use by the CPU I/O handler in
|
||||
detecting consecutive CLC 0 executions.
|
||||
*/
|
||||
|
||||
static uint32 io_dispatch (uint32 select_code, IOCYCLE signal_set, HP_WORD data)
|
||||
{
|
||||
uint32 stat_data;
|
||||
|
||||
if (devs [select_code] != NULL) { /* if the I/O slot is occupied */
|
||||
if (dibs [select_code] != NULL) { /* if the I/O slot is occupied */
|
||||
tpprintf (devs [select_code], TRACE_IOBUS, "Received data %06o with signals %s\n",
|
||||
data, fmt_bitset (signal_set, inbound_format));
|
||||
|
||||
|
@ -5895,11 +6181,14 @@ if (devs [select_code] != NULL) { /* if the I/O slot i
|
|||
signal_set,
|
||||
IORETURN (SCPE_OK, data));
|
||||
|
||||
tpprintf (devs [select_code], TRACE_IOBUS, "Returned data %06o\n", IODATA (stat_data));
|
||||
}
|
||||
tpprintf (devs [select_code], TRACE_IOBUS, "Returned data %06o with signals %s\n",
|
||||
IODATA (stat_data), fmt_bitset (stat_data, outbound_format));
|
||||
|
||||
else if (signal_set == ioCRS) /* otherwise the slot is empty, but if this is a CRS */
|
||||
return SCPE_OK; /* then it's legal to send it to unassigned slots */
|
||||
last_select_code = select_code; /* save the select code for CLC 0 detection */
|
||||
|
||||
if (stat_data & ioSKF) /* if the interface asserted SKF */
|
||||
stat_data = IORETURN (NOTE_SKIP, 0); /* then notify the caller to increment P */
|
||||
}
|
||||
|
||||
else if (signal_set & ioIOI) /* otherwise if it is an input request */
|
||||
if (select_code < VARDEV && is_1000) /* then if it is an internal device of a 1000 CPU */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* hp2100_cpu.h: HP 2100 CPU declarations
|
||||
|
||||
Copyright (c) 2005-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
|
||||
|
@ -24,6 +24,8 @@
|
|||
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"
|
||||
|
@ -507,32 +509,50 @@
|
|||
#define I_SFS 0102300u /* SFS instruction */
|
||||
#define I_STF 0102100u /* STF instruction */
|
||||
|
||||
/* IBL assignments */
|
||||
|
||||
#define IBL_V_SEL 14 /* ROM select <15:14> */
|
||||
#define IBL_M_SEL 03
|
||||
#define IBL_PTR 0000000u /* ROM 0: 12992K paper tape reader (PTR) */
|
||||
#define IBL_DP 0040000u /* ROM 1: 12992A 7900 disc (DP) */
|
||||
#define IBL_DQ 0060000u /* ROM 1: 12992A 2883 disc (DQ) */
|
||||
#define IBL_MS 0100000u /* ROM 2: 12992D 7970 tape (MS) */
|
||||
#define IBL_DS 0140000u /* ROM 3: 12992B 7905/06/20/25 disc (DS) */
|
||||
#define IBL_MAN 0010000u /* RPL/manual boot <13:12> */
|
||||
#define IBL_V_DEV 6 /* select code <11:6> */
|
||||
#define IBL_OPT 0000070u /* options in <5:3> */
|
||||
#define IBL_DP_REM 0000001u /* DP removable <0:0> */
|
||||
#define IBL_DS_HEAD 0000003u /* 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 */
|
||||
/* Initial Binary Loader.
|
||||
|
||||
#define IBL_S_CLR 0000000u /* cpu_ibl mask to clear the S register */
|
||||
#define IBL_S_NOCLR 0177777u /* cpu_ibl mask to preserve the S register */
|
||||
#define IBL_S_NOSET 0000000u /* cpu_ibl mask to preserve the S register */
|
||||
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| ROM # | - - | select code | - - - - - - |
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
*/
|
||||
|
||||
#define IBL_SET_SC(s) ((HP_WORD) ((s) << IBL_V_DEV)) /* position the select code in the S register */
|
||||
#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 */
|
||||
|
||||
typedef MEMORY_WORD BOOT_ROM [IBL_LNT]; /* boot ROM data */
|
||||
#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 */
|
||||
|
||||
|
||||
/* Memory management */
|
||||
|
@ -641,6 +661,7 @@ extern UNIT *cpu_ioerr_uptr; /* pointer to a unit with an unr
|
|||
|
||||
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 global SCP support routines declared in scp.h
|
||||
|
@ -656,7 +677,7 @@ extern void cpu_post_cmd (t_bool from_scp);
|
|||
|
||||
/* CPU global utility routines */
|
||||
|
||||
extern void cpu_ibl (const BOOT_ROM rom, int32 dev, HP_WORD sr_clear, HP_WORD sr_set);
|
||||
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);
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
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
|
||||
|
@ -871,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 */
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
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
|
||||
|
@ -480,11 +481,11 @@ switch (entry) { /* decode IR<3:0> */
|
|||
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) */
|
||||
|
@ -659,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)*/
|
||||
|
@ -675,8 +676,8 @@ switch (entry) { /* decode IR<4:0> */
|
|||
|
||||
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) */
|
||||
|
@ -698,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) */
|
||||
|
@ -714,8 +715,8 @@ switch (entry) { /* decode IR<4:0> */
|
|||
|
||||
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 */
|
||||
|
@ -1044,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) */
|
||||
|
|
|
@ -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
|
||||
|
@ -315,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) {
|
||||
|
@ -712,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 */
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
CPU5 RTE-6/VM and RTE-IV firmware option instructions
|
||||
|
||||
07-Sep-17 JDB Replaced "uint16" casts with "HP_WORD" for A/B assignments
|
||||
15-Jul-17 JDB Replaced "vma_resolve" with "resolve"
|
||||
26-Jun-17 JDB Replaced SEXT with SEXT16
|
||||
06-Jun-17 HV Fixed bug in cpu_vma_lbp "last suit + 1" handler
|
||||
|
@ -623,7 +624,7 @@ if (!p30) /* matched suit for 1st
|
|||
* must be in idx 0 of PTE */
|
||||
if (pgidx==01777) { /* suit switch situation */
|
||||
pgidx = 0; /* select correct idx 0 */
|
||||
suit = (uint16) (pagid + 1); /* suit needs increment */
|
||||
suit = (HP_WORD) (pagid + 1 & D16_MASK); /* suit needs increment with wraparound */
|
||||
if (suit==0) { /* is it page 65536? */
|
||||
offset += 02000; /* adjust to 2nd page */
|
||||
suit = NILPAGE;
|
||||
|
@ -653,8 +654,8 @@ else {
|
|||
return cpu_vma_fault(IR, pagid+1,page31,31,ptepg,faultab,faultpc);
|
||||
}
|
||||
|
||||
AR = (uint16) pagid; /* return pagid in A */
|
||||
BR = (uint16) (page30 + offset); /* mapped address in B */
|
||||
AR = (HP_WORD) pagid; /* return pagid in A */
|
||||
BR = (HP_WORD) (page30 + offset); /* mapped address in B */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -1261,7 +1262,7 @@ YR = ReadW(MA);
|
|||
WriteW(vout++, MA); vin++; /* copy address of N */
|
||||
|
||||
if (imax==0) goto easy; /* easy case */
|
||||
AR = (uint16) (k / imax); AR++; /* calculate K/IMAX */
|
||||
AR = (HP_WORD) (k / imax); AR++; /* calculate K/IMAX */
|
||||
if (negflag) goto hard; /* had a negative index? */
|
||||
if (YR > AR) goto hard;
|
||||
|
||||
|
@ -1427,7 +1428,7 @@ if ((idext0 & 0100000) || /* was nonstd MSEG? */
|
|||
e->npgs = msnum==e->msegno ? lastpgs : e->msegsz; /* for last MSEG, only map available pgs */
|
||||
if (!cpu_ema_mmap01(e)) return FALSE; /* map npgs pages at ipgs */
|
||||
}
|
||||
BR = (uint16) (e->mseg + e->msoff); /* return address of element */
|
||||
BR = (HP_WORD) (e->mseg + e->msoff); /* return address of element */
|
||||
return TRUE; /* and everything done */
|
||||
}
|
||||
|
||||
|
@ -1481,7 +1482,7 @@ if (npgs < e->msegsz) {
|
|||
e->mseg = mseg; /* logical stat of MSEG */
|
||||
if (!cpu_ema_emat(e)) goto em16; /* do a std mapping */
|
||||
} else {
|
||||
BR = (uint16) (mseg + e->offs); /* logical start of buffer */
|
||||
BR = (HP_WORD) (mseg + e->offs); /* logical start of buffer */
|
||||
e->npgs = bufpgs; /* S5 # pgs required */
|
||||
e->ipgs = e->pgoff; /* S6 page offset to reqd pg */
|
||||
if (!cpu_ema_mmap02(e)) goto em16; /* do nonstd mapping */
|
||||
|
@ -1561,7 +1562,7 @@ if (xidex) { /* is EMA declared? */
|
|||
idext0 = ReadWA(xidex+0) | 0100000; /* set NS flag in id extension */
|
||||
WriteS (xidex + 0, idext0); /* save back value */
|
||||
AR = 0; /* was successful */
|
||||
BR = (uint16) (mseg + offs); /* calculate log address */
|
||||
BR = (HP_WORD) (mseg + offs); /* calculate log address */
|
||||
(*rtn)++; /* return via good exit */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -1584,7 +1585,7 @@ while (ndim > 0) {
|
|||
if (sum & 0xffff8000) goto em15; /* overflow? */
|
||||
ndim--;
|
||||
}
|
||||
BR = (uint16) (abase + sum); /* add displacement */
|
||||
BR = (HP_WORD) (abase + sum); /* add displacement */
|
||||
(*rtn)++; /* return via good exit */
|
||||
return SCPE_OK;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* 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
|
||||
|
@ -24,6 +24,9 @@
|
|||
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
|
||||
|
@ -185,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"
|
||||
|
@ -330,9 +334,9 @@
|
|||
#define STOP_NOTAPE 8 /* no tape */
|
||||
#define STOP_EOT 9 /* end of tape */
|
||||
|
||||
#define NOTE_IOG 10 /* I/O instr executed */
|
||||
#define NOTE_INDINT 11 /* indirect intr */
|
||||
|
||||
#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 */
|
||||
|
@ -742,6 +746,7 @@ 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 */
|
||||
|
@ -781,9 +786,9 @@ typedef enum { INITIAL, SERVICE } POLLMODE; /* poll synchronization
|
|||
|
||||
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
|
||||
|
@ -818,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 */
|
||||
|
@ -1003,7 +1009,7 @@ struct dib { /* the Device Information Block
|
|||
#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))
|
||||
|
@ -1023,7 +1029,7 @@ struct dib { /* the Device Information Block
|
|||
|
||||
/* Bitset formatting.
|
||||
|
||||
See the comments at the "fmt_bitset" function (hp3000_sys.c) for details of
|
||||
See the comments at the "fmt_bitset" function (hp2100_sys.c) for details of
|
||||
the specification of bitset names and format structures.
|
||||
*/
|
||||
|
||||
|
|
|
@ -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,7 @@
|
|||
|
||||
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
|
||||
|
@ -1080,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:
|
||||
|
||||
|
@ -1091,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_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 */
|
||||
}
|
||||
|
||||
|
||||
|
@ -1130,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.
|
||||
|
||||
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
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| 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
|
||||
|
@ -1149,83 +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 */
|
||||
|
||||
cpu_ibl (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));
|
||||
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 */
|
||||
|
||||
return SCPE_OK;
|
||||
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 */
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
SIMH/HP 21XX DIAGNOSTICS PERFORMANCE
|
||||
====================================
|
||||
Last update: 2017-02-15
|
||||
Last update: 2018-05-15
|
||||
|
||||
|
||||
The HP 24396 diagnostic suite has been run against the SIMH HP 21xx 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
|
||||
|
@ -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.
|
||||
|
||||
|
||||
|
||||
---------------------------------------------------
|
||||
|
@ -2128,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
|
||||
|
@ -2136,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
|
||||
|
@ -3355,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
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* 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
|
||||
|
@ -27,6 +27,10 @@
|
|||
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
|
||||
|
@ -82,7 +86,7 @@
|
|||
- 7900A Disc Drive Operating and Service Manual
|
||||
(07900-90002, February 1975)
|
||||
- 13210A Disc Drive Interface Kit Operating and Service Manual
|
||||
(13210-90003, November 1974)
|
||||
(13210-90003, May 1978)
|
||||
- 12557A Cartridge Disc Interface Kit Operating and Service Manual
|
||||
(12557-90001, Sepember 1970)
|
||||
|
||||
|
@ -124,12 +128,103 @@
|
|||
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.
|
||||
*/
|
||||
|
||||
|
||||
|
@ -158,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
|
||||
|
@ -197,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 {
|
||||
|
@ -329,12 +446,38 @@ MTAB dpd_mod [] = {
|
|||
{ 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
|
||||
|
@ -405,12 +548,38 @@ MTAB dpc_mod [] = {
|
|||
{ 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 */
|
||||
};
|
||||
|
||||
|
||||
|
@ -549,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
|
||||
|
@ -558,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)
|
||||
|
@ -625,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;
|
||||
|
||||
|
||||
|
@ -654,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 */
|
||||
|
@ -732,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;
|
||||
}
|
||||
|
@ -755,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)
|
||||
|
@ -836,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 */
|
||||
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? */
|
||||
|
@ -1063,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 */
|
||||
}
|
||||
|
||||
|
||||
|
@ -1140,82 +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 */
|
||||
|
||||
cpu_ibl (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));
|
||||
else if (unitno != 0) /* otherwise a BOOT DPC for a non-zero unit */
|
||||
return SCPE_NOFNC; /* is rejected as unsupported */
|
||||
|
||||
return SCPE_OK;
|
||||
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,7 +1,7 @@
|
|||
/* hp2100_dq.c: HP 2100 12565A Disc Interface and 2883 disc drive simulator
|
||||
|
||||
Copyright (c) 1993-2006, Bill McDermith
|
||||
Copyright (c) 2004-2017, 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
|
||||
|
@ -26,6 +26,8 @@
|
|||
|
||||
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
|
||||
|
@ -885,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 */
|
||||
|
@ -915,84 +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 */
|
||||
|
||||
cpu_ibl (dq_rom, dev, IBL_OPT, /* copy the boot ROM to memory and configure */
|
||||
IBL_DQ | IBL_SET_SC (dev)); /* the S register accordingly */
|
||||
else if (unitno != 0) /* otherwise a BOOT DQC for a non-zero unit */
|
||||
return SCPE_NOFNC; /* is rejected as unsupported */
|
||||
|
||||
return SCPE_OK;
|
||||
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,7 +1,7 @@
|
|||
/* hp2100_dr.c: HP 2100 12606B/12610B fixed head disk/drum 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
|
||||
|
@ -27,6 +27,8 @@
|
|||
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
|
||||
|
@ -637,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 */
|
||||
|
@ -712,125 +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 cpu_ibl 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 cpu_ibl 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 HP_WORD dev = (HP_WORD) 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 */
|
||||
|
||||
cpu_ibl (dr_rom, dev, IBL_S_NOCLR, IBL_S_NOSET); /* copy the boot ROM to memory and configure */
|
||||
|
||||
mem_deposit (PR + BBDL_MAX_ADDR, mem_examine (PR + IBL_END)); /* move the maximum address word */
|
||||
mem_deposit (PR + BBDL_DMA_CNTL, (HP_WORD) dr_rom [BBDL_DMA_CNTL] + dev); /* set up the DMA control word */
|
||||
|
||||
mem_deposit (PR + IBL_DPC, (HP_WORD) dr_rom [IBL_DPC]); /* restore the overwritten word */
|
||||
mem_deposit (PR + IBL_END, (HP_WORD) 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-2017 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,9 @@
|
|||
|
||||
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
|
||||
|
@ -436,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;
|
||||
|
@ -542,10 +544,8 @@ 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;
|
||||
|
||||
|
@ -1015,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_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 */
|
||||
}
|
||||
|
||||
|
||||
|
@ -1056,115 +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 */
|
||||
|
||||
cpu_ibl (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));
|
||||
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 */
|
||||
|
||||
return SCPE_OK;
|
||||
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 */
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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,7 +531,7 @@ switch (unpacked.precision) { /* merge exponent into c
|
|||
break;
|
||||
|
||||
case fp_e: /* place in separate word */
|
||||
packed.fpk[4] = (uint16) (unpacked.exponent << FP_V_EXP |
|
||||
packed.fpk[4] = (HP_WORD) (unpacked.exponent << FP_V_EXP |
|
||||
(unpacked.exponent < 0) << FP_V_ESIGN);
|
||||
break;
|
||||
|
||||
|
|
2042
HP2100/hp2100_ipl.c
2042
HP2100/hp2100_ipl.c
File diff suppressed because it is too large
Load diff
|
@ -25,6 +25,7 @@
|
|||
|
||||
MPX 12792C 8-Channel Asynchronous Multiplexer
|
||||
|
||||
01-Nov-17 JDB Fixed serial output buffer overflow handling
|
||||
26-Jul-17 JDB Changed BITFIELD macros to field constructors
|
||||
22-Apr-17 JDB Corrected missing compound statements
|
||||
15-Mar-17 JDB Trace flags are now global
|
||||
|
@ -73,8 +74,8 @@
|
|||
character editing, echoing, ENQ/ACK handshaking, and read terminator
|
||||
detection, substantially reducing the load on the CPU over the earlier 12920
|
||||
multiplexer. It was supported by HP under RTE-MIII, RTE-IVB, and RTE-6/VM.
|
||||
Under simulation, it connects with HP terminal emulators via Telnet to a
|
||||
user-specified port.
|
||||
Under simulation, it connects with HP terminal emulators via Telnet or serial
|
||||
ports.
|
||||
|
||||
The single interface card contained a Z80 CPU, DMA controller, CTC, four
|
||||
two-channel SIO UARTs, 16K of RAM, 8K of ROM, and I/O backplane latches and
|
||||
|
@ -246,7 +247,7 @@
|
|||
#define MPX_CNTLS 2 /* number of control units */
|
||||
|
||||
#define mpx_cntl (mpx_unit [MPX_PORTS + 0]) /* controller unit */
|
||||
#define mpx_poll (mpx_unit [MPX_PORTS + 1]) /* Telnet polling unit */
|
||||
#define mpx_poll (mpx_unit [MPX_PORTS + 1]) /* polling unit */
|
||||
|
||||
|
||||
/* Character constants */
|
||||
|
@ -826,7 +827,7 @@ static int32 mpx_iolen = 0; /* length of current I/O xfer */
|
|||
static t_bool mpx_uien = FALSE; /* unsolicited interrupts enabled */
|
||||
static uint32 mpx_uicode = 0; /* unsolicited interrupt reason and port */
|
||||
|
||||
struct {
|
||||
static struct {
|
||||
FLIP_FLOP control; /* control flip-flop */
|
||||
FLIP_FLOP flag; /* flag flip-flop */
|
||||
FLIP_FLOP flagbuf; /* flag buffer flip-flop */
|
||||
|
@ -955,16 +956,16 @@ static DIB mpx_dib = {
|
|||
/* Unit list.
|
||||
|
||||
The first eight units correspond to the eight multiplexer line ports. These
|
||||
handle character I/O via the Telnet library. A ninth unit acts as the card
|
||||
controller, executing commands and transferring data to and from the I/O
|
||||
buffers. A tenth unit is responsible for polling for connections and socket
|
||||
I/O. It also holds the master socket.
|
||||
handle character I/O via the multiplexer library. A ninth unit acts as the
|
||||
card controller, executing commands and transferring data to and from the I/O
|
||||
buffers. A tenth unit is responsible for polling for connections and line
|
||||
I/O. It also holds the master socket for Telnet connections.
|
||||
|
||||
The character I/O service routines run only when there are characters to read
|
||||
or write. They operate at the approximate baud rates of the terminals (in
|
||||
CPU instructions per second) in order to be compatible with the OS drivers.
|
||||
The controller service routine runs only when a command is executing or a
|
||||
data transfer to or from the CPU is in progress. The Telnet poll must run
|
||||
data transfer to or from the CPU is in progress. The poll service must run
|
||||
continuously, but it may 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
|
||||
|
@ -986,7 +987,7 @@ static UNIT mpx_unit [] = {
|
|||
{ UDATA (&line_service, UNIT_FASTTIME, 0) }, /* terminal I/O line 6 */
|
||||
{ UDATA (&line_service, UNIT_FASTTIME, 0) }, /* terminal I/O line 7 */
|
||||
{ UDATA (&cntl_service, UNIT_DIS, 0) }, /* controller unit */
|
||||
{ UDATA (&poll_service, POLL_FLAGS, 0), POLL_FIRST } /* Telnet poll unit */
|
||||
{ UDATA (&poll_service, POLL_FLAGS, 0), POLL_FIRST } /* poll unit */
|
||||
};
|
||||
|
||||
|
||||
|
@ -1626,21 +1627,20 @@ return SCPE_OK;
|
|||
/* Multiplexer line service.
|
||||
|
||||
The line service routine is used to transmit and receive characters. It is
|
||||
started when a buffer is ready for output or when the Telnet poll routine
|
||||
started when a buffer is ready for output or when the poll service routine
|
||||
determines that there are characters ready for input, and it is stopped when
|
||||
there are no more characters to output or input. When a line is quiescent,
|
||||
this routine does not run. Service times are selected to approximate the
|
||||
baud rate setting of the multiplexer port.
|
||||
|
||||
"Fast timing" mode enables three optimizations. First, buffered characters
|
||||
are transferred via Telnet in blocks, rather than a character at a time; this
|
||||
reduces network traffic and decreases simulator overhead (there is only one
|
||||
service routine entry per block, rather than one per character). Second,
|
||||
ENQ/ACK handshaking is done locally, without involving the Telnet client.
|
||||
Third, when editing and echo is enabled, entering BS echoes a backspace, a
|
||||
space, and a backspace, and entering DEL echoes a backslash, a carriage
|
||||
return, and a line feed, providing better compatibility with prior RTE
|
||||
terminal drivers.
|
||||
are transferred in blocks, rather than a character at a time; this reduces
|
||||
line traffic and decreases simulator overhead (there is only one service
|
||||
routine entry per block, rather than one per character). Second, ENQ/ACK
|
||||
handshaking is done locally, without involving the client. Third, when
|
||||
editing and echo is enabled, entering BS echoes a backspace, a space, and a
|
||||
backspace, and entering DEL echoes a backslash, a carriage return, and a line
|
||||
feed, providing better compatibility with prior RTE terminal drivers.
|
||||
|
||||
Each read and write buffer begins with a reserved header byte that stores
|
||||
per-buffer information, such as whether handshaking should be suppressed
|
||||
|
@ -1654,7 +1654,7 @@ return SCPE_OK;
|
|||
write buffer is freed, and a UI check is made if the controller is idle, in
|
||||
case a write buffer request is pending.
|
||||
|
||||
For input, the character is retrieved from the Telnet buffer. If a BREAK was
|
||||
For input, the character is retrieved from the line buffer. If a BREAK was
|
||||
received, break status is set, and the character is discarded (the current
|
||||
multiplexer library implementation always returns a NUL with a BREAK
|
||||
indication). If the character is an XOFF, and XON/XOFF pacing is enabled, a
|
||||
|
@ -1685,6 +1685,59 @@ return SCPE_OK;
|
|||
service entry. This allows the CPU time to unload the first buffer
|
||||
before the second fills up. Once the first buffer is freed, the routine
|
||||
shifts back to burst mode to fill the remainder of the second buffer.
|
||||
|
||||
4. 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.
|
||||
|
||||
5. 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.
|
||||
|
||||
6. The serial transmit buffer provided by the terminal multiplexer library
|
||||
is restricted to one character. Therefore, attempting to send several
|
||||
characters in response to input, e.g., echoing "<BS> <space> <BS>" in
|
||||
response to receiving a <BS>, will fail with SCPE_STALL. Calling
|
||||
"tmxr_poll_tx" between characters will not clear the buffer if the line
|
||||
speed has been set explicitly.
|
||||
|
||||
To avoid having to do our own buffering for echoed characters, we call
|
||||
the "tmxr_linemsg" routine which loops internally until the characters
|
||||
have been transmitted. This is ugly but is a consequence of the buffer
|
||||
restriction imposed by the TMXR library.
|
||||
|
||||
7. Because ENQ/ACK handshaking is handled entirely on the multiplexer card
|
||||
with no OS involvement, FASTTIME "local handling" consists simply of
|
||||
omitting the handshake even if it is configured by the multiplexer.
|
||||
*/
|
||||
|
||||
static t_stat line_service (UNIT *uptr)
|
||||
|
@ -1700,14 +1753,19 @@ int32 chx;
|
|||
uint32 buffer_count, write_count;
|
||||
t_stat status = SCPE_OK;
|
||||
t_bool recv_loop = !fast_binary_read; /* bypass if fast binary read */
|
||||
t_bool xmit_loop = !(fast_binary_read || /* bypass if fast read or output suspended */
|
||||
(mpx_flags [port] & (FL_WAITACK | FL_XOFF)));
|
||||
t_bool xmit_loop = !(fast_binary_read /* bypass if fast read */
|
||||
|| mpx_flags [port] & (FL_WAITACK | FL_XOFF) /* or output suspended */
|
||||
|| mpx_ldsc [port].xmte == 0); /* or buffer full */
|
||||
|
||||
|
||||
tprintf (mpx_dev, DEB_CMDS, "Port %d service entered\n", port);
|
||||
|
||||
/* Transmission service */
|
||||
|
||||
if (mpx_ldsc [port].xmte == 0) /* if the transmit buffer is full */
|
||||
tprintf (mpx_dev, DEB_XFER, "Port %d transmission stalled for full buffer\n",
|
||||
port);
|
||||
|
||||
write_count = buf_len (iowrite, port, get); /* get the output buffer length */
|
||||
|
||||
while (xmit_loop && write_count > 0) { /* character available to output? */
|
||||
|
@ -1723,16 +1781,17 @@ while (xmit_loop && write_count > 0) { /* character available t
|
|||
continue; /* continue with the first output character */
|
||||
}
|
||||
|
||||
if (mpx_flags [port] & FL_DO_ENQACK) /* do handshake for this buffer? */
|
||||
mpx_enq_cntr [port] = mpx_enq_cntr [port] + 1; /* bump character counter */
|
||||
|
||||
if (mpx_enq_cntr [port] > ENQ_LIMIT) { /* ready for ENQ? */
|
||||
mpx_enq_cntr [port] = 0; /* clear ENQ counter */
|
||||
mpx_ack_wait [port] = 0; /* clear ACK wait timer */
|
||||
|
||||
mpx_flags [port] |= FL_WAITACK; /* set wait for ACK */
|
||||
if (mpx_enq_cntr [port] >= ENQ_LIMIT) { /* ready for ENQ? */
|
||||
ch = ENQ;
|
||||
status = tmxr_putc_ln (&mpx_ldsc [port], ch); /* transmit ENQ */
|
||||
|
||||
if (status == SCPE_OK || status == SCPE_LOST) { /* if transmission succeeded or is ignored */
|
||||
mpx_enq_cntr [port] = 0; /* then clear the ENQ counter */
|
||||
mpx_ack_wait [port] = 0; /* and the ACK wait timer */
|
||||
|
||||
mpx_flags [port] |= FL_WAITACK; /* set wait for ACK */
|
||||
}
|
||||
|
||||
xmit_loop = FALSE; /* stop further transmission */
|
||||
}
|
||||
|
||||
|
@ -1740,17 +1799,32 @@ while (xmit_loop && write_count > 0) { /* character available t
|
|||
ch = buf_get (iowrite, port) & data_mask; /* get char and mask to bit width */
|
||||
status = tmxr_putc_ln (&mpx_ldsc [port], ch); /* transmit the character */
|
||||
|
||||
write_count = write_count - 1; /* count the character */
|
||||
xmit_loop = (status == SCPE_OK) && fast_timing; /* and continue transmission if enabled */
|
||||
if (status == SCPE_OK || status == SCPE_LOST) { /* if transmission succeeded or is ignored */
|
||||
write_count = write_count - 1; /* then count the character */
|
||||
|
||||
xmit_loop = (fast_timing /* continue transmission if enabled */
|
||||
&& mpx_ldsc [port].xmte != 0); /* and buffer space is available */
|
||||
|
||||
if (mpx_flags [port] & FL_DO_ENQACK) /* if ENQ/ACK handshaking is enabled */
|
||||
mpx_enq_cntr [port] += 1; /* then bump the character counter */
|
||||
}
|
||||
|
||||
if (status != SCPE_OK) /* if the transmission failed */
|
||||
xmit_loop = FALSE; /* then exit the loop */
|
||||
else /* otherwise transmission failed */
|
||||
xmit_loop = FALSE; /* so exit the loop */
|
||||
}
|
||||
|
||||
else
|
||||
if (status == SCPE_OK)
|
||||
tprintf (mpx_dev, DEB_XFER, "Port %d character %s transmitted\n",
|
||||
port, fmt_char (ch));
|
||||
|
||||
else {
|
||||
tprintf (mpx_dev, DEB_XFER, "Port %d character %s transmission failed with status %d\n",
|
||||
port, fmt_char (ch), status);
|
||||
|
||||
if (status == SCPE_LOST) /* if the line is not connected */
|
||||
status = SCPE_OK; /* then ignore the output */
|
||||
}
|
||||
|
||||
if (write_count == 0) { /* buffer complete? */
|
||||
buf_free (iowrite, port); /* free buffer */
|
||||
|
||||
|
@ -1831,10 +1905,8 @@ while (recv_loop) { /* OK to process? */
|
|||
if (rt & RT_ENAB_ECHO) { /* echo enabled? */
|
||||
tmxr_putc_ln (&mpx_ldsc [port], BS); /* echo BS */
|
||||
|
||||
if (fast_timing) { /* fast timing mode? */
|
||||
tmxr_putc_ln (&mpx_ldsc [port], ' '); /* echo space */
|
||||
tmxr_putc_ln (&mpx_ldsc [port], BS); /* echo BS */
|
||||
}
|
||||
if (fast_timing) /* fast timing mode? */
|
||||
tmxr_linemsg (&mpx_ldsc [port], " \b"); /* echo space and BS */
|
||||
}
|
||||
|
||||
continue;
|
||||
|
@ -1847,8 +1919,7 @@ while (recv_loop) { /* OK to process? */
|
|||
if (fast_timing) /* fast timing mode? */
|
||||
tmxr_putc_ln (&mpx_ldsc [port], '\\'); /* echo backslash */
|
||||
|
||||
tmxr_putc_ln (&mpx_ldsc [port], CR); /* echo CR */
|
||||
tmxr_putc_ln (&mpx_ldsc [port], LF); /* and LF */
|
||||
tmxr_linemsg (&mpx_ldsc [port], "\r\n"); /* echo CR and LF */
|
||||
}
|
||||
|
||||
continue;
|
||||
|
@ -1865,7 +1936,8 @@ while (recv_loop) { /* OK to process? */
|
|||
|
||||
if ((ch == CR) && (rt & RT_END_ON_CR)) {
|
||||
if (rt & RT_ENAB_ECHO) /* echo enabled? */
|
||||
tmxr_putc_ln (&mpx_ldsc [port], LF); /* send LF */
|
||||
tmxr_linemsg (&mpx_ldsc [port], "\n"); /* send LF */
|
||||
|
||||
mpx_param = RS_ETC_CR; /* set termination condition */
|
||||
}
|
||||
|
||||
|
@ -1981,15 +2053,15 @@ else { /* normal service */
|
|||
tprintf (mpx_dev, DEB_CMDS, "Port %d service stopped\n", port);
|
||||
}
|
||||
|
||||
return SCPE_OK;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* Telnet poll service.
|
||||
/* Poll service.
|
||||
|
||||
This service routine is used to poll for Telnet connections and incoming
|
||||
characters. 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.
|
||||
It is started when the listening socket or a serial line is attached and is
|
||||
stopped when the socket and all lines are detached.
|
||||
|
||||
Each line is then checked for a pending ENQ/ACK handshake. If one is
|
||||
pending, the ACK counter is incremented, and if it times out, another ENQ is
|
||||
|
@ -2054,10 +2126,10 @@ return SCPE_OK;
|
|||
1. Under simulation, we also clear the input buffer register, even though
|
||||
the hardware doesn't.
|
||||
|
||||
2. We set up the first poll for Telnet connections to occur "immediately"
|
||||
upon execution, so that clients will be connected before execution
|
||||
begins. Otherwise, a fast program may access the multiplexer before the
|
||||
poll service routine activates.
|
||||
2. We set up the first poll for connections to occur "immediately" upon
|
||||
execution, so that clients will be connected before execution begins.
|
||||
Otherwise, a fast program may access the multiplexer before the poll
|
||||
service routine activates.
|
||||
|
||||
3. We must set the "emptying_flags" and "filling_flags" values here, because
|
||||
they cannot be initialized statically, even though the values are
|
||||
|
@ -2079,10 +2151,10 @@ mpx_ibuf = 0; /* clear input buffer */
|
|||
|
||||
if (mpx_poll.flags & UNIT_ATT) { /* network attached? */
|
||||
mpx_poll.wait = POLL_FIRST; /* set up poll */
|
||||
sim_activate (&mpx_poll, mpx_poll.wait); /* start Telnet poll immediately */
|
||||
sim_activate (&mpx_poll, mpx_poll.wait); /* start poll immediately */
|
||||
}
|
||||
else
|
||||
sim_cancel (&mpx_poll); /* else stop Telnet poll */
|
||||
sim_cancel (&mpx_poll); /* else stop poll */
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -2092,23 +2164,32 @@ return SCPE_OK;
|
|||
|
||||
We are called by the ATTACH MPX <port> command to attach the multiplexer to
|
||||
the listening port indicated by <port>. Logically, it is the multiplexer
|
||||
device that is attached; however, SIMH only allows units to be attached.
|
||||
This makes sense for devices such as tape drives, where the attached media is
|
||||
a property of a specific drive. In our case, though, the listening port is a
|
||||
property of the multiplexer card, not of any given serial line. As ATTACH
|
||||
MPX is equivalent to ATTACH MPX0, the port would, by default, be attached to
|
||||
the first serial line and be reported there in a SHOW MPX command.
|
||||
device that is attached; however, SIMH only allows units to be attached. This
|
||||
makes sense for devices such as tape drives, where the attached media is a
|
||||
property of a specific drive. In our case, though, the listening port is a
|
||||
property of the multiplexer card, not of any given line. As ATTACH MPX is
|
||||
equivalent to ATTACH MPX0, the port would, by default, be attached to the
|
||||
first line and be reported there in a SHOW MPX command.
|
||||
|
||||
To preserve the logical picture, we attach the port to the Telnet poll unit,
|
||||
which is normally disabled to inhibit its display. Attaching to a disabled
|
||||
unit is not allowed, so we first enable the unit, then attach it, then
|
||||
disable it again. Attachment is reported by the "show_status" routine below.
|
||||
To preserve the logical picture, we attach the listening port to the poll
|
||||
unit (unit 9), which is normally disabled to inhibit its display. Serial
|
||||
ports are attached to line units 0-7 normally. Attachment is reported by the
|
||||
"show_status" routine below.
|
||||
|
||||
A direct attach to the poll unit is only allowed when restoring a previously
|
||||
saved session.
|
||||
The connection poll service routine is synchronized with the other input
|
||||
polling devices in the simulator to facilitate idling.
|
||||
|
||||
The Telnet poll service routine is synchronized with the other input polling
|
||||
devices in the simulator to facilitate idling.
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. If we are being called as part of RESTORE processing, we may see a
|
||||
request to attach the poll unit (unit 9). This will occur if unit 9 was
|
||||
attached when the SAVE was done. In this case, the SIM_SW_REST flag will
|
||||
be set in "sim_switches", and we will allow the call to succeed.
|
||||
|
||||
2. If the poll unit is attached, it will be enabled as part of RESTORE
|
||||
processing. We always unilaterally disable this unit to ensure that it
|
||||
remains hidden.
|
||||
*/
|
||||
|
||||
static t_stat mpx_attach (UNIT *uptr, CONST char *cptr)
|
||||
|
@ -2133,15 +2214,21 @@ return status;
|
|||
|
||||
/* Detach the multiplexer.
|
||||
|
||||
Normally, we are called by the DETACH MPX command, which is equivalent to
|
||||
DETACH MPX0. However, we may be called with other units in two cases.
|
||||
We are called by the DETACH MPX command to detach the listening port and all
|
||||
Telnet sessions. We will also be called by DETACH ALL, RESTORE, and during
|
||||
simulator shutdown. For DETACH ALL and RESTORE, we must not fail the call,
|
||||
or processing of other units will cease.
|
||||
|
||||
A DETACH ALL command will call us for unit 9 (the poll unit) if it is
|
||||
attached. Also, during simulator shutdown, we will be called for units 0-8
|
||||
(detach_all in scp.c calls the detach routines of all units that do NOT have
|
||||
UNIT_ATTABLE), as well as for unit 9 if it is attached. In both cases, it is
|
||||
imperative that we return SCPE_OK, otherwise any remaining device detaches
|
||||
will not be performed.
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. During simulator shutdown, we will be called for units 0-8 (detach_all in
|
||||
scp.c calls the detach routines of all units that do NOT have
|
||||
UNIT_ATTABLE), as well as for unit 9 if it is attached.
|
||||
|
||||
2. We cannot fail a direct DETACH MPX9 (poll unit), because we cannot tell
|
||||
that case apart from a DETACH ALL (a RESTORE will have the SIM_SW_REST
|
||||
flag set in "sim_switches").
|
||||
*/
|
||||
|
||||
static t_stat mpx_detach (UNIT *uptr)
|
||||
|
@ -2157,7 +2244,7 @@ if ((uptr == mpx_unit) || (uptr == &mpx_poll)) { /* base unit or poll uni
|
|||
sim_cancel (&mpx_unit [i]); /* cancel any scheduled I/O */
|
||||
}
|
||||
|
||||
sim_cancel (&mpx_poll); /* stop Telnet poll */
|
||||
sim_cancel (&mpx_poll); /* stop poll */
|
||||
}
|
||||
|
||||
return status;
|
||||
|
@ -2413,9 +2500,8 @@ switch (mpx_cmd) {
|
|||
mpx_enq_cntr [0] = 0; /* clear port 0 ENQ counter */
|
||||
mpx_ack_wait [0] = 0; /* clear port 0 ACK wait timer */
|
||||
|
||||
tmxr_putc_ln (&mpx_ldsc [0], ESC); /* send fast binary read */
|
||||
tmxr_putc_ln (&mpx_ldsc [0], 'e'); /* escape sequence to port 0 */
|
||||
tmxr_poll_tx (&mpx_desc); /* flush output */
|
||||
tmxr_linemsg (&mpx_ldsc [0], "\033e"); /* send the fast binary read escape sequence to port 0 */
|
||||
tmxr_poll_tx (&mpx_desc); /* and flush the output */
|
||||
|
||||
next_state = exec; /* set execution state */
|
||||
break;
|
||||
|
@ -2557,7 +2643,7 @@ return set_flag;
|
|||
}
|
||||
|
||||
|
||||
/* Poll for new Telnet connections */
|
||||
/* Poll for new connections */
|
||||
|
||||
static void poll_connection (void)
|
||||
{
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* hp2100_ms.c: HP 2100 13181B/13183B Digital Magnetic Tape Unit Interface 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
|
||||
|
@ -27,6 +27,8 @@
|
|||
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
|
||||
|
@ -1239,91 +1241,234 @@ 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 */
|
||||
|
||||
cpu_ibl (ms_rom, dev, IBL_OPT, /* copy the boot ROM to memory and configure */
|
||||
IBL_MS | IBL_SET_SC (dev)); /* the S register accordingly */
|
||||
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 */
|
||||
|
||||
static uint32 calc_crc_lrc (uint8 *buffer, t_mtrlnt length)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* hp2100_mux.c: HP 2100 12920A Asynchronous Multiplexer Interface simulator
|
||||
|
||||
Copyright (c) 2002-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
|
||||
|
@ -26,6 +26,8 @@
|
|||
|
||||
MUX,MUXL,MUXC 12920A Asynchronous Multiplexer Interface
|
||||
|
||||
01-May-18 JDB Removed ioCRS counter, as consecutive ioCRS calls are no longer made
|
||||
28-Apr-18 JDB Fixed output completion IRQ when port is not connected
|
||||
03-Aug-17 JDB Control card device renamed from MUXM to MUXC
|
||||
MUXC now enabled/disabled independently of MUX and MUXL
|
||||
Modified to use the "odd_parity" array in hp2100_sys.c
|
||||
|
@ -101,6 +103,124 @@
|
|||
801-type automatic dialers). Under simulation, only one control card is
|
||||
supported.
|
||||
|
||||
The multiplexer responds to I/O instructions as follows:
|
||||
|
||||
Upper Data Card output word format (OTA and OTB):
|
||||
|
||||
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| - | channel number | - - - - - - - - - - |
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
|
||||
|
||||
Upper Data Card input word format (LIA, LIB, MIA, and MIB):
|
||||
|
||||
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| S | channel number | - - - - - - | D | B | L | R |
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
|
||||
Where:
|
||||
|
||||
S = Seeking
|
||||
D = Diagnose
|
||||
B = Break status
|
||||
L = Character lost
|
||||
R = Receive/send (0/1) character interrupt
|
||||
|
||||
|
||||
Lower Data Card output control word format (OTA and OTB):
|
||||
|
||||
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| 1 | R | I | E | D | char size | baud rate |
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
|
||||
Where:
|
||||
|
||||
R = Receive/send (0/1) configuration
|
||||
I = Enable interrupt
|
||||
E = Echo (receive)/parity (send)
|
||||
D = Diagnose
|
||||
|
||||
Character size:
|
||||
|
||||
The three least-significant bits of the sum of the data, parity, and stop
|
||||
bits. For example, 7E1 is 1001, so 001 is coded.
|
||||
|
||||
Baud rate:
|
||||
|
||||
The value (14400 / device bit rate) - 1. For example, 2400 baud is 005.
|
||||
|
||||
|
||||
Lower Data Card output data word format (OTA and OTB):
|
||||
|
||||
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| 0 | 1 | - - | S | transmit data |
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
|
||||
Where:
|
||||
|
||||
S = Sync bit
|
||||
|
||||
Transmit data:
|
||||
|
||||
Right-justified with leading one bits.
|
||||
|
||||
|
||||
Lower Data Card input word format (LIA, LIB, MIA, and MIB):
|
||||
|
||||
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| P | channel | receive data |
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
|
||||
Where:
|
||||
|
||||
P = Computed parity
|
||||
|
||||
Receive data:
|
||||
|
||||
Right-justified with leading one bits
|
||||
|
||||
|
||||
Control Card output word format (OTA and OTB):
|
||||
|
||||
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| S | U |channel number | - - |EC2|EC1|C2 |C1 |ES2|ES1|SS2|SS1|
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
|
||||
|
||||
Control Card input word format (LIA, LIB, MIA, and MIB):
|
||||
|
||||
15 |14 13 12 |11 10 9 | 8 7 6 | 5 4 3 | 2 1 0
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| 1 1 |channel number |I2 |I1 | 0 0 0 0 |ES2|ES1|S2 |S1 |
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
|
||||
Where:
|
||||
|
||||
S = Scan
|
||||
U = Update
|
||||
ECx = Enable command bit x
|
||||
Cx = Command bit x
|
||||
ESx = Enable status bit x
|
||||
Sx = Status bit x
|
||||
SSx = Stored status bit x
|
||||
Ix = Interrupt bit x
|
||||
|
||||
The control card provides two serial control outputs and two serial status
|
||||
inputs for each of the 16 channels. The card connects to the Request to Send
|
||||
(CA) and Data Terminal Ready (CD) control lines and the Data Carrier Detect
|
||||
(CF) and Data Set Ready (CC) status lines. Addressable latches hold the
|
||||
control line values and assert them continuously to the 16 channels. In
|
||||
addition, a 16-word by 4-bit RAM holds the expected state for each channel's
|
||||
status lines and the corresponding interrupt enable bits to provide
|
||||
notification if those lines change.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. If a BREAK is detected during an input poll, and we are not in diagnostic
|
||||
|
@ -142,6 +262,23 @@
|
|||
before the output character transmit interrupt). If an output operation
|
||||
is not in progress, then the BREAK will be recognized at the next input
|
||||
poll.
|
||||
|
||||
2. In simulation, establishing a port connection asserts DSR to the control
|
||||
card. If the port is configured as a dataset connection (SET MUXLn
|
||||
DATASET), DCD is also asserted. Disconnecting denies DSR and DCD. The
|
||||
control card responds to DTR denying by dropping the port connection.
|
||||
The RTS setting has no effect.
|
||||
|
||||
3. When a Bell 103 dataset answers a call, it asserts DSR first. After the
|
||||
handshake with the remote dataset completes, DCD asserts, typically
|
||||
between 1.3 and 3.6 seconds later. Similarly, when the remote dataset
|
||||
terminates the call by sending a long (1.5 second) space, the local
|
||||
dataset drops DSR first, followed by DCD after approximately 30
|
||||
milliseconds. The dataset simulation does not model these delays; DSR
|
||||
and DCD transition up and down together. This implies that the control
|
||||
card software driver will see only one interrupt for each transition pair
|
||||
instead of the expected two (presuming both DSR and DCD are enabled to
|
||||
interrupt).
|
||||
*/
|
||||
|
||||
|
||||
|
@ -181,6 +318,7 @@
|
|||
#define UNIT_MDM (1 << UNIT_V_MDM)
|
||||
#define UNIT_DIAG (1 << UNIT_V_DIAG)
|
||||
|
||||
|
||||
/* Channel number (OTA upper, LIA lower or upper) */
|
||||
|
||||
#define MUX_V_CHAN 10 /* channel num */
|
||||
|
@ -205,12 +343,47 @@
|
|||
#define OTL_CHAR 03777 /* char mask */
|
||||
#define OTL_PAR 0200 /* char parity */
|
||||
|
||||
#define BAUD_RATE(p) ((28800 / (OTL_BAUD (p) + 1) + 1) / 2)
|
||||
|
||||
static const uint32 bits_per_char [8] = { /* bits per character, indexed by OTL_LNT encoding */
|
||||
9, 10, 11, 12, 5, 6, 7, 8
|
||||
};
|
||||
|
||||
static const BITSET_NAME lower_parameter_names [] = { /* lower data card parameter word names */
|
||||
"\1send\0receive", /* bit 14 */
|
||||
"enable interrupt", /* bit 13 */
|
||||
"enable parity/echo", /* bit 12 */
|
||||
"diagnose" /* bit 11 */
|
||||
};
|
||||
|
||||
static const BITSET_FORMAT lower_parameter_format = /* names, offset, direction, alternates, bar */
|
||||
{ FMT_INIT (lower_parameter_names, 11, msb_first, has_alt, append_bar) };
|
||||
|
||||
static const BITSET_NAME lower_data_names [] = { /* lower data card output data word names */
|
||||
"send", /* bit 14 */
|
||||
NULL, /* bit 13 */
|
||||
NULL, /* bit 12 */
|
||||
"sync" /* bit 11 */
|
||||
};
|
||||
|
||||
static const BITSET_FORMAT lower_data_format = /* names, offset, direction, alternates, bar */
|
||||
{ FMT_INIT (lower_data_names, 11, msb_first, no_alt, append_bar) };
|
||||
|
||||
|
||||
/* LIA, lower = received data */
|
||||
|
||||
#define LIL_PAR 0100000 /* parity */
|
||||
#define PUT_DCH(x) (((x) & MUX_M_CHAN) << MUX_V_CHAN)
|
||||
#define LIL_CHAR 01777 /* character */
|
||||
|
||||
static const BITSET_NAME lower_input_names [] = { /* lower data card input data word names */
|
||||
"\1odd parity\0even parity", /* bit 15 */
|
||||
};
|
||||
|
||||
static const BITSET_FORMAT lower_input_format = /* names, offset, direction, alternates, bar */
|
||||
{ FMT_INIT (lower_input_names, 0, msb_first, has_alt, append_bar) };
|
||||
|
||||
|
||||
/* LIA, upper = status */
|
||||
|
||||
#define LIU_SEEK 0100000 /* seeking NI */
|
||||
|
@ -219,6 +392,29 @@
|
|||
#define LIU_LOST 0000002 /* char lost */
|
||||
#define LIU_TR 0000001 /* trans/rcv */
|
||||
|
||||
static const BITSET_NAME upper_status_names [] = { /* upper data card status word names */
|
||||
"seeking", /* bit 15 */
|
||||
NULL, /* bit 14 */
|
||||
NULL, /* bit 13 */
|
||||
NULL, /* bit 12 */
|
||||
NULL, /* bit 11 */
|
||||
NULL, /* bit 10 */
|
||||
NULL, /* bit 9 */
|
||||
NULL, /* bit 8 */
|
||||
NULL, /* bit 7 */
|
||||
NULL, /* bit 6 */
|
||||
NULL, /* bit 5 */
|
||||
NULL, /* bit 4 */
|
||||
"diagnose", /* bit 3 */
|
||||
"break" /* bit 2 */
|
||||
"lost", /* bit 1 */
|
||||
"\1send\0receive" /* bit 0 */
|
||||
};
|
||||
|
||||
static const BITSET_FORMAT upper_status_format = /* names, offset, direction, alternates, bar */
|
||||
{ FMT_INIT (upper_status_names, 0, msb_first, has_alt, no_bar) };
|
||||
|
||||
|
||||
/* OTA, control */
|
||||
|
||||
#define OTC_SCAN 0100000 /* scan */
|
||||
|
@ -237,8 +433,29 @@
|
|||
#define OTC_SS2 0000002 /* SSn flops */
|
||||
#define OTC_SS1 0000001
|
||||
#define OTC_RW (OTC_ES2|OTC_ES1|OTC_SS2|OTC_SS1)
|
||||
#define RTS OTC_C2 /* C2 = rts */
|
||||
#define DTR OTC_C1 /* C1 = dtr */
|
||||
|
||||
static const BITSET_NAME cntl_control_names [] = { /* control card control word names */
|
||||
"scan", /* bit 15 */
|
||||
"update", /* bit 14 */
|
||||
NULL, /* bit 13 */
|
||||
NULL, /* bit 12 */
|
||||
NULL, /* bit 11 */
|
||||
NULL, /* bit 10 */
|
||||
NULL, /* bit 9 */
|
||||
NULL, /* bit 8 */
|
||||
"EC2", /* bit 7 */
|
||||
"EC1", /* bit 6 */
|
||||
"\1C2\0~C2", /* bit 5 */
|
||||
"\1C1\0~C1", /* bit 4 */
|
||||
"ES2", /* bit 3 */
|
||||
"ES1", /* bit 2 */
|
||||
"\1S2\0~S2", /* bit 1 */
|
||||
"\1S1\0~S1" /* bit 0 */
|
||||
};
|
||||
|
||||
static const BITSET_FORMAT cntl_control_format = /* names, offset, direction, alternates, bar */
|
||||
{ FMT_INIT (cntl_control_names, 0, msb_first, has_alt, no_bar) };
|
||||
|
||||
|
||||
/* LIA, control */
|
||||
|
||||
|
@ -251,13 +468,46 @@
|
|||
#define LIC_S2 0000002 /* Sn flops */
|
||||
#define LIC_S1 0000001
|
||||
#define LIC_V_I 8 /* S1 to I1 */
|
||||
#define CDET LIC_S2 /* S2 = cdet */
|
||||
#define DSR LIC_S1 /* S1 = dsr */
|
||||
|
||||
#define LIC_TSTI(ch) (((muxc_lia[ch] ^ muxc_ota[ch]) & \
|
||||
((muxc_ota[ch] & (OTC_ES2|OTC_ES1)) >> OTC_V_ES)) \
|
||||
<< LIC_V_I)
|
||||
|
||||
static const BITSET_NAME cntl_status_names [] = { /* control card status word names */
|
||||
"I2", /* bit 9 */
|
||||
"I1", /* bit 8 */
|
||||
NULL, /* bit 7 */
|
||||
NULL, /* bit 6 */
|
||||
NULL, /* bit 5 */
|
||||
NULL, /* bit 4 */
|
||||
"ES2", /* bit 3 */
|
||||
"ES1", /* bit 2 */
|
||||
"\1S2\0~S2", /* bit 1 */
|
||||
"\1S1\0~S1" /* bit 0 */
|
||||
};
|
||||
|
||||
static const BITSET_FORMAT cntl_status_format = /* names, offset, direction, alternates, bar */
|
||||
{ FMT_INIT (cntl_status_names, 0, msb_first, has_alt, no_bar) };
|
||||
|
||||
/* Control card #1 serial line bits */
|
||||
|
||||
#define RTS OTC_C2 /* Control card #1 C2 = Request to Send */
|
||||
#define DTR OTC_C1 /* Control card #1 C1 = Data Terminal Ready */
|
||||
#define DCD LIC_S2 /* Control card #1 S2 = Data Carrier Detect */
|
||||
#define DSR LIC_S1 /* Control card #1 S1 = Data Set Ready */
|
||||
|
||||
static const BITSET_NAME cntl_line_names [] = { /* Control card serial line status names */
|
||||
"RTS", /* bit 5 */
|
||||
"DTR", /* bit 4 */
|
||||
NULL, /* bit 3 */
|
||||
NULL, /* bit 2 */
|
||||
"DCD", /* bit 1 */
|
||||
"DSR" /* bit 0 */
|
||||
};
|
||||
|
||||
static const BITSET_FORMAT cntl_line_format = /* names, offset, direction, alternates, bar */
|
||||
{ FMT_INIT (cntl_line_names, 0, msb_first, no_alt, no_bar) };
|
||||
|
||||
|
||||
/* Program constants */
|
||||
|
||||
|
@ -440,9 +690,9 @@ static MTAB muxl_mod [] = {
|
|||
/* Debugging trace list */
|
||||
|
||||
static DEBTAB muxl_deb [] = {
|
||||
{ "CMDS", DEB_CMDS },
|
||||
{ "CPU", DEB_CPU },
|
||||
{ "XFER", DEB_XFER },
|
||||
{ "CSRW", TRACE_CSRW }, /* Interface control, status, read, and write actions */
|
||||
{ "SERV", TRACE_SERV }, /* Channel unit service scheduling calls */
|
||||
{ "XFER", TRACE_XFER }, /* Data receptions and transmissions */
|
||||
{ "IOBUS", TRACE_IOBUS }, /* interface I/O bus signals and data words */
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
@ -520,7 +770,8 @@ static MTAB muxu_mod [] = {
|
|||
/* Debugging trace list */
|
||||
|
||||
static DEBTAB muxu_deb [] = {
|
||||
{ "CPU", DEB_CPU },
|
||||
{ "CSRW", TRACE_CSRW }, /* Interface control, status, read, and write actions */
|
||||
{ "PSERV", TRACE_PSERV }, /* Poll unit service scheduling calls */
|
||||
{ "IOBUS", TRACE_IOBUS }, /* interface I/O bus signals and data words */
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
@ -601,8 +852,8 @@ static MTAB muxc_mod [] = {
|
|||
/* Debugging trace list */
|
||||
|
||||
static DEBTAB muxc_deb [] = {
|
||||
{ "CMDS", DEB_CMDS },
|
||||
{ "CPU", DEB_CPU },
|
||||
{ "CSRW", TRACE_CSRW }, /* Interface control, status, read, and write actions */
|
||||
{ "XFER", TRACE_XFER }, /* Data receptions and transmissions */
|
||||
{ "IOBUS", TRACE_IOBUS }, /* interface I/O bus signals and data words */
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
@ -646,26 +897,16 @@ DEVICE muxc_dev = {
|
|||
1. The operating manual says that "at least 100 milliseconds of CLC 0s must
|
||||
be programmed" by systems employing the multiplexer to ensure that the
|
||||
multiplexer resets. In practice, such systems issue 128K CLC 0
|
||||
instructions. As we provide debug logging of multiplexer resets, a CRS
|
||||
counter is used to ensure that only one debug line is printed in response
|
||||
to these 128K CRS invocations.
|
||||
instructions. In simulation, only one ioCRS invocation is required to
|
||||
reset the multiplexer.
|
||||
*/
|
||||
|
||||
uint32 muxlio (DIB *dibptr, IOCYCLE signal_set, uint32 stat_data)
|
||||
{
|
||||
int32 ln;
|
||||
const char *hold_or_clear = (signal_set & ioCLF ? ",C" : "");
|
||||
static uint32 crs_count = 0; /* cntr for ioCRS repeat */
|
||||
IOSIGNAL signal;
|
||||
IOCYCLE working_set = IOADDSIR (signal_set); /* add ioSIR if needed */
|
||||
|
||||
if (crs_count && !(signal_set & ioCRS)) { /* counting CRSes and not present? */
|
||||
tprintf (muxl_dev, DEB_CMDS, "[CRS] Multiplexer reset %d times\n",
|
||||
crs_count);
|
||||
|
||||
crs_count = 0; /* clear counter */
|
||||
}
|
||||
|
||||
while (working_set) {
|
||||
signal = IONEXT (working_set); /* isolate next signal */
|
||||
|
||||
|
@ -673,9 +914,6 @@ while (working_set) {
|
|||
|
||||
case ioCLF: /* clear flag flip-flop */
|
||||
muxl.flag = muxl.flagbuf = CLEAR;
|
||||
|
||||
tprintf (muxl_dev, DEB_CMDS, "[CLF] Flag cleared\n");
|
||||
|
||||
mux_data_int (); /* look for new int */
|
||||
break;
|
||||
|
||||
|
@ -683,8 +921,6 @@ while (working_set) {
|
|||
case ioSTF: /* set flag flip-flop */
|
||||
case ioENF: /* enable flag */
|
||||
muxl.flag = muxl.flagbuf = SET;
|
||||
|
||||
tprintf (muxl_dev, DEB_CMDS, "[STF] Flag set\n");
|
||||
break;
|
||||
|
||||
|
||||
|
@ -699,19 +935,28 @@ while (working_set) {
|
|||
|
||||
|
||||
case ioIOI: /* I/O data input */
|
||||
stat_data = IORETURN (SCPE_OK, muxl_ibuf); /* merge in return status */
|
||||
tprintf (muxl_dev, TRACE_CSRW, "Input data is channel %u | %s%04o\n",
|
||||
MUX_CHAN (muxl_ibuf),
|
||||
fmt_bitset (muxl_ibuf, lower_input_format),
|
||||
muxl_ibuf & LIL_CHAR);
|
||||
|
||||
tprintf (muxl_dev, DEB_CPU, "[LIx%s] Data = %06o\n", hold_or_clear, muxl_ibuf);
|
||||
stat_data = IORETURN (SCPE_OK, muxl_ibuf); /* merge in return status */
|
||||
break;
|
||||
|
||||
|
||||
case ioIOO: /* I/O data output */
|
||||
muxl_obuf = IODATA (stat_data); /* store data */
|
||||
|
||||
|
||||
if (muxl_obuf & OTL_P)
|
||||
tprintf (muxl_dev, DEB_CPU, "[OTx%s] Parameter = %06o\n", hold_or_clear, muxl_obuf);
|
||||
tprintf (muxl_dev, TRACE_CSRW, "Parameter is %s%u bits | %u baud\n",
|
||||
fmt_bitset (muxl_obuf, lower_parameter_format),
|
||||
bits_per_char [OTL_LNT (muxl_obuf)],
|
||||
BAUD_RATE (muxl_obuf));
|
||||
else
|
||||
tprintf (muxl_dev, DEB_CPU, "[OTx%s] Data = %06o\n", hold_or_clear, muxl_obuf);
|
||||
tprintf (muxl_dev, TRACE_CSRW, "Output data is %s%04o\n",
|
||||
fmt_bitset (muxl_obuf, lower_data_format),
|
||||
muxl_obuf & OTL_CHAR);
|
||||
break;
|
||||
|
||||
|
||||
|
@ -721,7 +966,6 @@ while (working_set) {
|
|||
|
||||
|
||||
case ioCRS: /* control reset */
|
||||
if (crs_count == 0) { /* first reset? */
|
||||
muxl.control = CLEAR; /* clear control flip-flop */
|
||||
|
||||
for (ln = 0; ln < SEND_CHAN_COUNT; ln++) { /* clear transmit info */
|
||||
|
@ -733,16 +977,12 @@ while (working_set) {
|
|||
mux_rbuf[ln] = mux_rpar[ln] = 0; /* clear receive info */
|
||||
mux_sta[ln] = mux_rchp[ln] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
crs_count = crs_count + 1; /* increment count */
|
||||
break;
|
||||
|
||||
|
||||
case ioCLC: /* clear control flip-flop */
|
||||
muxl.control = CLEAR;
|
||||
|
||||
tprintf (muxl_dev, DEB_CMDS, "[CLC%s] Data interrupt inhibited\n", hold_or_clear);
|
||||
break;
|
||||
|
||||
|
||||
|
@ -751,53 +991,62 @@ while (working_set) {
|
|||
|
||||
ln = MUX_CHAN (muxu_obuf); /* get chan # */
|
||||
|
||||
if (muxl_obuf & OTL_TX) { /* transmit? */
|
||||
if (ln < SEND_CHAN_COUNT) { /* line valid? */
|
||||
if (muxl_obuf & OTL_P) { /* parameter? */
|
||||
mux_xpar[ln] = (uint16) muxl_obuf; /* store param value */
|
||||
tprintf (muxl_dev, DEB_CMDS, "[STC%s] Transmit channel %d parameter %06o stored\n",
|
||||
hold_or_clear, ln, muxl_obuf);
|
||||
if (muxl_obuf & OTL_TX) /* if this is a send parameter or data */
|
||||
if (ln >= SEND_CHAN_COUNT) /* then report if the channel number is out of range */
|
||||
tprintf (muxl_dev, TRACE_CSRW, "Send channel %d invalid\n",
|
||||
ln);
|
||||
|
||||
else if (muxl_obuf & OTL_P) { /* otherwise if this is a parameter store */
|
||||
mux_xpar[ln] = (uint16) muxl_obuf; /* then save it */
|
||||
|
||||
tprintf (muxl_dev, TRACE_CSRW, "Channel %d send parameter %06o stored\n",
|
||||
ln, muxl_obuf);
|
||||
}
|
||||
|
||||
else { /* data */
|
||||
if (mux_xpar[ln] & OTL_TPAR) /* parity requested? */
|
||||
muxl_obuf = /* add parity bit */
|
||||
muxl_obuf & ~OTL_PAR |
|
||||
XMT_PAR(muxl_obuf);
|
||||
else { /* otherwise this is a data store */
|
||||
if (mux_xpar[ln] & OTL_TPAR) /* if parity is enabled */
|
||||
muxl_obuf = muxl_obuf & ~OTL_PAR /* then replace the parity bit */
|
||||
| XMT_PAR (muxl_obuf); /* with the calculated value */
|
||||
|
||||
mux_xbuf[ln] = (uint16) muxl_obuf; /* load buffer */
|
||||
|
||||
if (sim_is_active (&muxl_unit[ln])) { /* still working? */
|
||||
mux_sta[ln] = mux_sta[ln] | LIU_LOST; /* char lost */
|
||||
tprintf (muxl_dev, DEB_CMDS, "[STC%s] Transmit channel %d data overrun\n",
|
||||
hold_or_clear, ln);
|
||||
|
||||
tprintf (muxl_dev, TRACE_CSRW, "Channel %d send data overrun\n",
|
||||
ln);
|
||||
}
|
||||
|
||||
else {
|
||||
if (muxu_unit.flags & UNIT_DIAG) /* loopback? */
|
||||
mux_ldsc[ln].conn = 1; /* connect this line */
|
||||
|
||||
sim_activate (&muxl_unit[ln], muxl_unit[ln].wait);
|
||||
tprintf (muxl_dev, DEB_CMDS, "[STC%s] Transmit channel %d data %06o scheduled\n",
|
||||
hold_or_clear, ln, muxl_obuf);
|
||||
|
||||
tprintf (muxl_dev, TRACE_CSRW, "Channel %d send data %06o stored\n",
|
||||
ln, muxl_obuf);
|
||||
|
||||
tprintf (muxl_dev, TRACE_SERV, "Channel %d delay %d service scheduled\n",
|
||||
ln, muxl_unit [ln].wait);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
tprintf (muxl_dev, DEB_CMDS, "[STC%s] Transmit channel %d invalid\n", hold_or_clear, ln);
|
||||
}
|
||||
|
||||
else /* receive */
|
||||
if (ln < RECV_CHAN_COUNT) /* line valid? */
|
||||
if (muxl_obuf & OTL_P) { /* parameter? */
|
||||
mux_rpar[ln] = (uint16) muxl_obuf; /* store param value */
|
||||
tprintf (muxl_dev, DEB_CMDS, "Receive channel %d parameter %06o stored\n",
|
||||
else /* otherwise this is a receive parameter */
|
||||
if (ln >= RECV_CHAN_COUNT) /* report if the channel number is out of range */
|
||||
tprintf (muxl_dev, TRACE_CSRW, "Receive channel %d invalid\n",
|
||||
ln);
|
||||
|
||||
else if (muxl_obuf & OTL_P) { /* otherwise if this is a parameter store */
|
||||
mux_rpar[ln] = (uint16) muxl_obuf; /* then save it */
|
||||
|
||||
tprintf (muxl_dev, TRACE_CSRW, "Channel %d receive parameter %06o stored\n",
|
||||
ln, muxl_obuf);
|
||||
}
|
||||
|
||||
else
|
||||
tprintf (muxl_dev, DEB_CMDS, "Receive channel %d parameter %06o invalid action\n",
|
||||
else /* otherwise a data store to a receive channel is invalid */
|
||||
tprintf (muxl_dev, TRACE_CSRW, "Channel %d receive output data word %06o invalid\n",
|
||||
ln, muxl_obuf);
|
||||
|
||||
else
|
||||
tprintf (muxl_dev, DEB_CMDS, "[STC%s] Receive channel %d invalid\n", hold_or_clear, ln);
|
||||
break;
|
||||
|
||||
|
||||
|
@ -850,15 +1099,17 @@ while (working_set) {
|
|||
case ioIOI: /* I/O data input */
|
||||
stat_data = IORETURN (SCPE_OK, muxu_ibuf); /* merge in return status */
|
||||
|
||||
tprintf (muxu_dev, DEB_CPU, "[LIx] Status = %06o, channel = %d\n",
|
||||
muxu_ibuf, MUX_CHAN(muxu_ibuf));
|
||||
tprintf (muxu_dev, TRACE_CSRW, "Status is channel %u | %s\n",
|
||||
MUX_CHAN (muxu_ibuf),
|
||||
fmt_bitset (muxu_ibuf, upper_status_format));
|
||||
break;
|
||||
|
||||
|
||||
case ioIOO: /* I/O data output */
|
||||
muxu_obuf = IODATA (stat_data); /* store data */
|
||||
|
||||
tprintf (muxu_dev, DEB_CPU, "[OTx] Data channel = %d\n", MUX_CHAN(muxu_obuf));
|
||||
tprintf (muxu_dev, TRACE_CSRW, "Channel %d is selected\n",
|
||||
MUX_CHAN (muxu_obuf));
|
||||
break;
|
||||
|
||||
|
||||
|
@ -882,7 +1133,6 @@ return stat_data;
|
|||
|
||||
uint32 muxcio (DIB *dibptr, IOCYCLE signal_set, uint32 stat_data)
|
||||
{
|
||||
const char *hold_or_clear = (signal_set & ioCLF ? ",C" : "");
|
||||
uint16 data;
|
||||
int32 ln, old;
|
||||
IOSIGNAL signal;
|
||||
|
@ -895,9 +1145,6 @@ while (working_set) {
|
|||
|
||||
case ioCLF: /* clear flag flip-flop */
|
||||
muxc.flag = muxc.flagbuf = CLEAR;
|
||||
|
||||
tprintf (muxc_dev, DEB_CMDS, "[CLF] Flag cleared\n");
|
||||
|
||||
mux_ctrl_int (); /* look for new int */
|
||||
break;
|
||||
|
||||
|
@ -905,8 +1152,6 @@ while (working_set) {
|
|||
case ioSTF: /* set flag flip-flop */
|
||||
case ioENF: /* enable flag */
|
||||
muxc.flag = muxc.flagbuf = SET;
|
||||
|
||||
tprintf (muxc_dev, DEB_CMDS, "[STF] Flag set\n");
|
||||
break;
|
||||
|
||||
|
||||
|
@ -926,8 +1171,8 @@ while (working_set) {
|
|||
(muxc_ota[muxc_chan] & (OTC_ES2 | OTC_ES1)) | /* ES2, ES1 */
|
||||
(muxc_lia[muxc_chan] & (LIC_S2 | LIC_S1))); /* S2, S1 */
|
||||
|
||||
tprintf (muxc_dev, DEB_CPU, "[LIx%s] Status = %06o, channel = %d\n",
|
||||
hold_or_clear, data, muxc_chan);
|
||||
tprintf (muxc_dev, TRACE_CSRW, "Status is channel %u | %s\n",
|
||||
muxc_chan, fmt_bitset (data, cntl_status_format));
|
||||
|
||||
muxc_chan = (muxc_chan + 1) & LIC_M_CHAN; /* incr channel */
|
||||
stat_data = IORETURN (SCPE_OK, data); /* merge in return status */
|
||||
|
@ -938,6 +1183,9 @@ while (working_set) {
|
|||
data = IODATA (stat_data); /* clear supplied status */
|
||||
ln = muxc_chan = OTC_CHAN (data); /* set channel */
|
||||
|
||||
tprintf (muxc_dev, TRACE_CSRW, "Control is channel %u | %s\n",
|
||||
muxc_chan, fmt_bitset (data, cntl_control_format));
|
||||
|
||||
if (data & OTC_SCAN) muxc_scan = 1; /* set scan flag */
|
||||
else muxc_scan = 0;
|
||||
|
||||
|
@ -954,14 +1202,22 @@ while (working_set) {
|
|||
muxc_ota[ln] =
|
||||
(muxc_ota[ln] & ~OTC_C1) | (data & OTC_C1);
|
||||
|
||||
if (muxu_unit.flags & UNIT_DIAG) /* loopback? */
|
||||
tprintf (muxc_dev, TRACE_XFER, "Channel %d line status is %s\n",
|
||||
ln, fmt_bitset (muxc_ota [ln], cntl_line_format));
|
||||
|
||||
if (muxu_unit.flags & UNIT_DIAG) { /* loopback? */
|
||||
muxc_lia[ln ^ 1] = /* set S1, S2 to C1, C2 */
|
||||
(muxc_lia[ln ^ 1] & ~(LIC_S2 | LIC_S1)) |
|
||||
(muxc_ota[ln] & (OTC_C1 | OTC_C2)) >> OTC_V_C;
|
||||
|
||||
tprintf (muxc_dev, TRACE_XFER, "Channel %d line status is %s\n",
|
||||
ln ^ 1, fmt_bitset (muxc_lia [ln ^ 1], cntl_line_format));
|
||||
}
|
||||
|
||||
else if ((muxl_unit[ln].flags & UNIT_MDM) /* modem ctrl? */
|
||||
&& (old & DTR) && !(muxc_ota[ln] & DTR)) { /* DTR drop? */
|
||||
tprintf (muxc_dev, DEB_CMDS, "Channel %d disconnected by DTR drop\n", ln);
|
||||
tprintf (muxc_dev, TRACE_CSRW, "Channel %d disconnected by DTR drop\n",
|
||||
ln);
|
||||
|
||||
tmxr_linemsg (&mux_ldsc[ln], "\r\nDisconnected from the ");
|
||||
tmxr_linemsg (&mux_ldsc[ln], sim_name);
|
||||
|
@ -969,12 +1225,12 @@ while (working_set) {
|
|||
|
||||
tmxr_reset_ln (&mux_ldsc[ln]); /* reset line */
|
||||
muxc_lia[ln] = 0; /* dataset off */
|
||||
|
||||
tprintf (muxc_dev, TRACE_XFER, "Channel %d disconnect dropped DCD and DSR\n",
|
||||
ln);
|
||||
}
|
||||
} /* end update */
|
||||
|
||||
tprintf (muxc_dev, DEB_CPU, "[OTx%s] Parameter = %06o, channel = %d\n",
|
||||
hold_or_clear, data, ln);
|
||||
|
||||
if ((muxu_unit.flags & UNIT_DIAG) && (!muxc.flag)) /* loopback and flag clear? */
|
||||
mux_ctrl_int (); /* status chg may interrupt */
|
||||
break;
|
||||
|
@ -1030,6 +1286,9 @@ t_stat muxi_svc (UNIT *uptr)
|
|||
int32 ln, c;
|
||||
t_bool loopback;
|
||||
|
||||
tprintf (muxu_dev, TRACE_PSERV, "Poll delay %d service entered\n",
|
||||
uptr->wait);
|
||||
|
||||
loopback = ((muxu_unit.flags & UNIT_DIAG) != 0); /* diagnostic mode? */
|
||||
|
||||
if (!loopback) { /* terminal mode? */
|
||||
|
@ -1043,12 +1302,17 @@ if (!loopback) { /* terminal mode? */
|
|||
ln = tmxr_poll_conn (&mux_desc); /* look for connect */
|
||||
|
||||
if (ln >= 0) { /* got one? */
|
||||
mux_ldsc[ln].rcve = 1; /* rcv enabled */
|
||||
muxc_lia[ln] = muxc_lia[ln] | DSR; /* set dsr */
|
||||
|
||||
if ((muxl_unit[ln].flags & UNIT_MDM) && /* modem ctrl? */
|
||||
(muxc_ota[ln] & DTR)) /* DTR? */
|
||||
muxc_lia[ln] = muxc_lia[ln] | CDET; /* set cdet */
|
||||
muxc_lia[ln] = muxc_lia[ln] | DSR; /* set dsr */
|
||||
mux_ldsc[ln].rcve = 1; /* rcv enabled */
|
||||
muxc_lia[ln] = muxc_lia[ln] | DCD; /* set DCD */
|
||||
|
||||
tprintf (muxc_dev, TRACE_XFER, "Channel %d connected\n",
|
||||
ln);
|
||||
}
|
||||
|
||||
tmxr_poll_rx (&mux_desc); /* poll for input */
|
||||
}
|
||||
|
||||
|
@ -1065,7 +1329,7 @@ for (ln = 0; ln < SEND_CHAN_COUNT; ln++) { /* loop thru lines
|
|||
c = SCPE_BREAK; /* supply it now */
|
||||
|
||||
else
|
||||
c = tmxr_getc_ln (&mux_ldsc[ln]); /* get char from Telnet */
|
||||
c = tmxr_getc_ln (&mux_ldsc[ln]); /* get char from line */
|
||||
|
||||
if (c) /* valid char? */
|
||||
mux_receive (ln, c, loopback); /* process it */
|
||||
|
@ -1086,19 +1350,21 @@ return SCPE_OK;
|
|||
|
||||
t_stat muxo_svc (UNIT *uptr)
|
||||
{
|
||||
int32 c, fc, ln, altln;
|
||||
const int32 ln = uptr - muxl_unit; /* line # */
|
||||
const int32 altln = ln ^ 1; /* alt. line for diag mode */
|
||||
int32 c, fc;
|
||||
t_bool loopback;
|
||||
t_stat result = SCPE_OK;
|
||||
|
||||
ln = uptr - muxl_unit; /* line # */
|
||||
altln = ln ^ 1; /* alt. line for diag mode */
|
||||
tprintf (muxl_dev, TRACE_SERV, "Channel %d service entered\n",
|
||||
ln);
|
||||
|
||||
fc = mux_xbuf[ln] & OTL_CHAR; /* full character data */
|
||||
c = fc & 0377; /* Telnet character data */
|
||||
c = fc & 0377; /* line character data */
|
||||
|
||||
loopback = ((muxu_unit.flags & UNIT_DIAG) != 0); /* diagnostic mode? */
|
||||
|
||||
if (mux_ldsc[ln].conn) { /* connected? */
|
||||
if (mux_ldsc[ln].xmte) { /* xmt enabled? */
|
||||
if (mux_ldsc[ln].xmte) { /* xmt enabled? */
|
||||
if (loopback) /* diagnostic mode? */
|
||||
mux_ldsc[ln].conn = 0; /* clear connection */
|
||||
|
||||
|
@ -1119,24 +1385,34 @@ if (mux_ldsc[ln].conn) { /* connected? */
|
|||
|
||||
else { /* no loopback */
|
||||
if (c >= 0) /* valid? */
|
||||
tmxr_putc_ln (lp, c); /* output char */
|
||||
result = tmxr_putc_ln (lp, c); /* output char */
|
||||
tmxr_poll_tx (&mux_desc); /* poll xmt */
|
||||
}
|
||||
}
|
||||
|
||||
else if (mux_ldsc [ln].conn == 0) /* sync character isn't seen by receiver */
|
||||
result = SCPE_LOST; /* so report transfer success if connected */
|
||||
|
||||
mux_xdon[ln] = 1; /* set for xmit irq */
|
||||
|
||||
if (loopback || c >= 0)
|
||||
tprintf (muxl_dev, DEB_XFER, "Channel %d character %s sent\n",
|
||||
if (result == SCPE_LOST)
|
||||
tprintf (muxl_dev, TRACE_XFER, "Channel %d character %s discarded by connection loss\n",
|
||||
ln, fmt_char ((uint8) (loopback ? fc : c)));
|
||||
else
|
||||
tprintf (muxl_dev, TRACE_XFER, "Channel %d character %s sent\n",
|
||||
ln, fmt_char ((uint8) (loopback ? fc : c)));
|
||||
}
|
||||
|
||||
else { /* buf full */
|
||||
else { /* buf full */
|
||||
tmxr_poll_tx (&mux_desc); /* poll xmt */
|
||||
sim_activate (uptr, muxl_unit[ln].wait); /* wait */
|
||||
|
||||
tprintf (muxl_dev, TRACE_SERV, "Channel %d delay %d service rescheduled\n",
|
||||
ln, muxl_unit [ln].wait);
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (!muxl.flag) mux_data_int (); /* scan for int */
|
||||
return SCPE_OK;
|
||||
|
@ -1154,15 +1430,15 @@ if (c & SCPE_BREAK) { /* break? */
|
|||
mux_sta[ln] = mux_sta[ln] | LIU_BRK; /* set break status */
|
||||
|
||||
if (diag)
|
||||
tprintf (muxl_dev, DEB_XFER, "Channel %d break detected\n", ln);
|
||||
tprintf (muxl_dev, TRACE_XFER, "Channel %d break detected\n", ln);
|
||||
else
|
||||
tprintf (muxl_dev, DEB_XFER, "Channel %d deferred break processed\n", ln);
|
||||
tprintf (muxl_dev, TRACE_XFER, "Channel %d deferred break processed\n", ln);
|
||||
}
|
||||
|
||||
else {
|
||||
mux_defer[ln] = 1; /* defer break */
|
||||
|
||||
tprintf (muxl_dev, DEB_XFER, "Channel %d break detected and deferred\n", ln);
|
||||
tprintf (muxl_dev, TRACE_XFER, "Channel %d break detected and deferred\n", ln);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -1184,7 +1460,7 @@ else { /* normal */
|
|||
|
||||
mux_rchp[ln] = 1; /* char pending */
|
||||
|
||||
tprintf (muxl_dev, DEB_XFER, "Channel %d character %s received\n",
|
||||
tprintf (muxl_dev, TRACE_XFER, "Channel %d character %s received\n",
|
||||
ln, fmt_char ((uint8) c));
|
||||
|
||||
if (mux_rpar[ln] & OTL_DIAG) /* diagnose this line? */
|
||||
|
@ -1209,7 +1485,8 @@ for (i = FIRST_TERM; i <= LAST_TERM; i++) { /* rcv lines */
|
|||
mux_rchp[i] = 0; /* clr char, stat */
|
||||
mux_sta[i] = 0;
|
||||
|
||||
tprintf (muxl_dev, DEB_CMDS, "Receive channel %d interrupt requested\n", i);
|
||||
tprintf (muxl_dev, TRACE_CSRW, "Channel %d receive interrupt requested\n",
|
||||
i);
|
||||
|
||||
muxlio (&muxl_dib, ioENF, 0); /* interrupt */
|
||||
return;
|
||||
|
@ -1224,7 +1501,8 @@ for (i = FIRST_TERM; i <= LAST_TERM; i++) { /* xmt lines */
|
|||
mux_xdon[i] = 0; /* clr done, stat */
|
||||
mux_sta[i] = 0;
|
||||
|
||||
tprintf (muxl_dev, DEB_CMDS, "Transmit channel %d interrupt requested\n", i);
|
||||
tprintf (muxl_dev, TRACE_CSRW, "Channel %d send interrupt requested\n",
|
||||
i);
|
||||
|
||||
muxlio (&muxl_dib, ioENF, 0); /* interrupt */
|
||||
return;
|
||||
|
@ -1239,7 +1517,8 @@ for (i = FIRST_AUX; i <= LAST_AUX; i++) { /* diag lines */
|
|||
mux_rchp[i] = 0; /* clr char, stat */
|
||||
mux_sta[i] = 0;
|
||||
|
||||
tprintf (muxl_dev, DEB_CMDS, "Receive channel %d interrupt requested\n", i);
|
||||
tprintf (muxl_dev, TRACE_CSRW, "Channel %d receive interrupt requested\n",
|
||||
i);
|
||||
|
||||
muxlio (&muxl_dib, ioENF, 0); /* interrupt */
|
||||
return;
|
||||
|
@ -1267,10 +1546,10 @@ line_count = (muxc_scan ? TERM_COUNT : 1); /* check one or all line
|
|||
for (i = 0; i < line_count; i++) {
|
||||
if (muxc_scan) /* scanning? */
|
||||
muxc_chan = (muxc_chan + 1) & LIC_M_CHAN; /* step channel */
|
||||
if (LIC_TSTI (muxc_chan)) { /* status change? */
|
||||
|
||||
tprintf (muxc_dev, DEB_CMDS, "Control channel %d interrupt requested (poll = %d)\n",
|
||||
muxc_chan, i + 1);
|
||||
if (LIC_TSTI (muxc_chan)) { /* status change? */
|
||||
tprintf (muxc_dev, TRACE_CSRW, "Channel %u interrupt requested\n",
|
||||
muxc_chan);
|
||||
|
||||
muxcio (&muxc_dib, ioENF, 0); /* set flag */
|
||||
break;
|
||||
|
@ -1310,10 +1589,12 @@ mux_rpar[i] = mux_xpar[i] = 0;
|
|||
mux_rchp[i] = mux_xdon[i] = 0;
|
||||
mux_sta[i] = mux_defer[i] = 0;
|
||||
muxc_ota[i] = muxc_lia[i] = 0; /* clear modem */
|
||||
if (mux_ldsc[i].conn && /* connected? */
|
||||
((muxu_unit.flags & UNIT_DIAG) == 0)) /* term mode? */
|
||||
muxc_lia[i] = muxc_lia[i] | DSR | /* cdet, dsr */
|
||||
(muxl_unit[i].flags & UNIT_MDM? CDET: 0);
|
||||
|
||||
if (mux_ldsc [i].conn /* connected? */
|
||||
&& (muxu_unit.flags & UNIT_DIAG) == 0) /* term mode? */
|
||||
muxc_lia[i] = muxc_lia[i] | DSR /* DCD, dsr */
|
||||
| (muxl_unit[i].flags & UNIT_MDM ? DCD : 0);
|
||||
|
||||
sim_cancel (&muxl_unit[i]);
|
||||
return;
|
||||
}
|
||||
|
@ -1342,7 +1623,7 @@ muxc_chan = muxc_scan = 0; /* init modem scan */
|
|||
|
||||
if (muxu_unit.flags & UNIT_ATT) { /* master att? */
|
||||
muxu_unit.wait = POLL_FIRST; /* set up poll */
|
||||
sim_activate (&muxu_unit, muxu_unit.wait); /* start Telnet poll immediately */
|
||||
sim_activate (&muxu_unit, muxu_unit.wait); /* start poll immediately */
|
||||
}
|
||||
else
|
||||
sim_cancel (&muxu_unit); /* else stop */
|
||||
|
@ -1370,7 +1651,7 @@ status = tmxr_attach (&mux_desc, uptr, cptr); /* attach */
|
|||
|
||||
if (status == SCPE_OK) {
|
||||
muxu_unit.wait = POLL_FIRST; /* set up poll */
|
||||
sim_activate (&muxu_unit, muxu_unit.wait); /* start Telnet poll immediately */
|
||||
sim_activate (&muxu_unit, muxu_unit.wait); /* start poll immediately */
|
||||
}
|
||||
|
||||
return status;
|
||||
|
@ -1418,7 +1699,7 @@ t_stat mux_setdiag (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
|||
int32 ln;
|
||||
|
||||
if (val) { /* set diag? */
|
||||
mux_detach (uptr); /* detach lines */
|
||||
mux_detach (uptr); /* detach Telnet lines */
|
||||
for (ln = 0; ln < TERM_COUNT; ln++) /* enable transmission */
|
||||
mux_ldsc[ln].xmte = 1; /* on all lines */
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
SIMH/HP 2100 RELEASE NOTES
|
||||
==========================
|
||||
Last update: 2017-09-06
|
||||
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,259 @@ 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
|
||||
======================
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* hp2100_stddev.c: HP2100 standard devices 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
|
||||
|
@ -29,6 +29,9 @@
|
|||
TTY 12531C buffered teleprinter interface
|
||||
TBG 12539C time base generator
|
||||
|
||||
27-Feb-18 JDB Added the BBL
|
||||
22-Nov-17 JDB Fixed TTY serial output buffer overflow handling
|
||||
18-Sep-17 JDB Changed PTR "DIAG" modifier to "DIAGNOSTIC"
|
||||
03-Aug-17 JDB PTP and TTY now append to existing file data
|
||||
18-Jul-17 JDB The PTR device now handles the IOERR simulation stop
|
||||
11-Jul-17 JDB Renamed "ibl_copy" to "cpu_ibl"
|
||||
|
@ -370,7 +373,7 @@ REG ptr_reg[] = {
|
|||
};
|
||||
|
||||
MTAB ptr_mod[] = {
|
||||
{ UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", NULL },
|
||||
{ UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAGNOSTIC", NULL },
|
||||
{ UNIT_DIAG, 0, "reader mode", "READER", NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 1u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &ptr_dib },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, ~1u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &ptr_dib },
|
||||
|
@ -710,69 +713,223 @@ return SCPE_OK;
|
|||
}
|
||||
|
||||
|
||||
/* Paper tape reader bootstrap routine (HP 12992K ROM) */
|
||||
/* Paper tape reader bootstrap loaders (BBL and 12992K).
|
||||
|
||||
const BOOT_ROM ptr_rom = {
|
||||
0107700, /*ST CLC 0,C ; intr off */
|
||||
0002401, /* CLA,RSS ; skip in */
|
||||
0063756, /*CN LDA M11 ; feed frame */
|
||||
0006700, /* CLB,CCE ; set E to rd byte */
|
||||
0017742, /* JSB READ ; get #char */
|
||||
0007306, /* CMB,CCE,INB,SZB ; 2's comp */
|
||||
0027713, /* JMP *+5 ; non-zero byte */
|
||||
0002006, /* INA,SZA ; feed frame ctr */
|
||||
0027703, /* JMP *-3 */
|
||||
0102077, /* HLT 77B ; stop */
|
||||
0027700, /* JMP ST ; next */
|
||||
0077754, /* STA WC ; word in rec */
|
||||
0017742, /* JSB READ ; get feed frame */
|
||||
0017742, /* JSB READ ; get address */
|
||||
0074000, /* STB 0 ; init csum */
|
||||
0077755, /* STB AD ; save addr */
|
||||
0067755, /*CK LDB AD ; check addr */
|
||||
0047777, /* ADB MAXAD ; below loader */
|
||||
0002040, /* SEZ ; E =0 => OK */
|
||||
0027740, /* JMP H55 */
|
||||
0017742, /* JSB READ ; get word */
|
||||
0040001, /* ADA 1 ; cont checksum */
|
||||
0177755, /* STA AD,I ; store word */
|
||||
0037755, /* ISZ AD */
|
||||
0000040, /* CLE ; force wd read */
|
||||
0037754, /* ISZ WC ; block done? */
|
||||
0027720, /* JMP CK ; no */
|
||||
0017742, /* JSB READ ; get checksum */
|
||||
0054000, /* CPB 0 ; ok? */
|
||||
0027702, /* JMP CN ; next block */
|
||||
0102011, /* HLT 11 ; bad csum */
|
||||
0027700, /* JMP ST ; next */
|
||||
0102055, /*H55 HALT 55 ; bad address */
|
||||
0027700, /* JMP ST ; next */
|
||||
0000000, /*RD 0 */
|
||||
0006600, /* CLB,CME ; E reg byte ptr */
|
||||
0103710, /* STC RDR,C ; start reader */
|
||||
0102310, /* SFS RDR ; wait */
|
||||
0027745, /* JMP *-1 */
|
||||
0106410, /* MIB RDR ; get byte */
|
||||
0002041, /* SEZ,RSS ; E set? */
|
||||
0127742, /* JMP RD,I ; no, done */
|
||||
0005767, /* BLF,CLE,BLF ; shift byte */
|
||||
0027744, /* JMP RD+2 ; again */
|
||||
0000000, /*WC 000000 ; word count */
|
||||
0000000, /*AD 000000 ; address */
|
||||
0177765, /*M11 -11 ; feed count */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, /* unused */
|
||||
0, 0, 0, 0, 0, 0, 0, /* unused */
|
||||
0000000 /*MAXAD -ST ; max addr */
|
||||
The Basic Binary Loader (BBL) performs three functions, depending on the
|
||||
setting of the S register, as follows:
|
||||
|
||||
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| C | - - - - - - - - - - - - - - | V |
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
|
||||
Where:
|
||||
|
||||
C = Compare the paper tape to memory
|
||||
V = Verify checksums on the paper tape
|
||||
|
||||
If bit 15 is set to 1, the loader will compare the absolute program on tape
|
||||
to the contents of memory. If bit 0 is set to 1, the loader will verify the
|
||||
checksums of the absolute binary records on tape without altering memory. If
|
||||
neither bit is set, the loader will read the absolute program on the paper
|
||||
tape into memory. Loader execution ends with one of the following halt
|
||||
instructions:
|
||||
|
||||
* HLT 00 - a comparison error occurred; A = the tape value.
|
||||
* HLT 11 - a checksum error occurred; A/B = the tape/calculated value.
|
||||
* HLT 55 - the program load address would overlay the loader.
|
||||
* HLT 77 - the end of tape was reached with a successful read.
|
||||
|
||||
The 12992K boot loader ROM reads an absolute program on the paper tape into
|
||||
memory. The S register setting does not affect loader operation. Loader
|
||||
execution ends with one of the following halt instructions:
|
||||
|
||||
* HLT 11 - a checksum error occurred; A/B = the calculated/tape value.
|
||||
* HLT 55 - the program load address would overlay the ROM loader.
|
||||
* HLT 77 - the end of tape was reached with a successful read.
|
||||
|
||||
Note that the A/B register contents are in the opposite order of those in the
|
||||
BBL when a checksum error occurs.
|
||||
*/
|
||||
|
||||
static const LOADER_ARRAY ptr_loaders = {
|
||||
{ /* HP 21xx Basic Binary Loader (BBL) */
|
||||
000, /* loader starting index */
|
||||
IBL_NA, /* DMA index (not used) */
|
||||
072, /* FWA index */
|
||||
{ 0107700, /* 77700: START CLC 0,C */
|
||||
0063770, /* 77701: LDA 77770 */
|
||||
0106501, /* 77702: LIB 1 */
|
||||
0004010, /* 77703: SLB */
|
||||
0002400, /* 77704: CLA */
|
||||
0006020, /* 77705: SSB */
|
||||
0063771, /* 77706: LDA 77771 */
|
||||
0073736, /* 77707: STA 77736 */
|
||||
0006401, /* 77710: CLB,RSS */
|
||||
0067773, /* 77711: LDB 77773 */
|
||||
0006006, /* 77712: INB,SZB */
|
||||
0027717, /* 77713: JMP 77717 */
|
||||
0107700, /* 77714: CLC 0,C */
|
||||
0102077, /* 77715: HLT 77 */
|
||||
0027700, /* 77716: JMP 77700 */
|
||||
0017762, /* 77717: JSB 77762 */
|
||||
0002003, /* 77720: SZA,RSS */
|
||||
0027712, /* 77721: JMP 77712 */
|
||||
0003104, /* 77722: CMA,CLE,INA */
|
||||
0073774, /* 77723: STA 77774 */
|
||||
0017762, /* 77724: JSB 77762 */
|
||||
0017753, /* 77725: JSB 77753 */
|
||||
0070001, /* 77726: STA 1 */
|
||||
0073775, /* 77727: STA 77775 */
|
||||
0063775, /* 77730: LDA 77775 */
|
||||
0043772, /* 77731: ADA 77772 */
|
||||
0002040, /* 77732: SEZ */
|
||||
0027751, /* 77733: JMP 77751 */
|
||||
0017753, /* 77734: JSB 77753 */
|
||||
0044000, /* 77735: ADB 0 */
|
||||
0000000, /* 77736: NOP */
|
||||
0002101, /* 77737: CLE,RSS */
|
||||
0102000, /* 77740: HLT 0 */
|
||||
0037775, /* 77741: ISZ 77775 */
|
||||
0037774, /* 77742: ISZ 77774 */
|
||||
0027730, /* 77743: JMP 77730 */
|
||||
0017753, /* 77744: JSB 77753 */
|
||||
0054000, /* 77745: CPB 0 */
|
||||
0027711, /* 77746: JMP 77711 */
|
||||
0102011, /* 77747: HLT 11 */
|
||||
0027700, /* 77750: JMP 77700 */
|
||||
0102055, /* 77751: HLT 55 */
|
||||
0027700, /* 77752: JMP 77700 */
|
||||
0000000, /* 77753: NOP */
|
||||
0017762, /* 77754: JSB 77762 */
|
||||
0001727, /* 77755: ALF,ALF */
|
||||
0073776, /* 77756: STA 77776 */
|
||||
0017762, /* 77757: JSB 77762 */
|
||||
0033776, /* 77760: IOR 77776 */
|
||||
0127753, /* 77761: JMP 77753,I */
|
||||
0000000, /* 77762: NOP */
|
||||
0103710, /* 77763: STC 10,C */
|
||||
0102310, /* 77764: SFS 10 */
|
||||
0027764, /* 77765: JMP 77764 */
|
||||
0102510, /* 77766: LIA 10 */
|
||||
0127762, /* 77767: JMP 77762,I */
|
||||
0173775, /* 77770: STA 77775,I */
|
||||
0153775, /* 77771: CPA 77775,I */
|
||||
0100100, /* 77772: RRL 16 */
|
||||
0177765, /* 77773: STB 77765,I */
|
||||
0000000, /* 77774: NOP */
|
||||
0000000, /* 77775: NOP */
|
||||
0000000, /* 77776: NOP */
|
||||
0000000 } }, /* 77777: NOP */
|
||||
|
||||
{ /* HP 1000 Loader ROM (12992K) */
|
||||
IBL_START, /* loader starting index */
|
||||
IBL_DMA, /* DMA index */
|
||||
IBL_FWA, /* FWA index */
|
||||
{ 0107700, /* 77700: ST CLC 0,C ; intr off */
|
||||
0002401, /* 77701: CLA,RSS ; skip in */
|
||||
0063756, /* 77702: CN LDA M11 ; feed frame */
|
||||
0006700, /* 77703: CLB,CCE ; set E to rd byte */
|
||||
0017742, /* 77704: JSB READ ; get #char */
|
||||
0007306, /* 77705: CMB,CCE,INB,SZB ; 2's comp */
|
||||
0027713, /* 77706: JMP *+5 ; non-zero byte */
|
||||
0002006, /* 77707: INA,SZA ; feed frame ctr */
|
||||
0027703, /* 77710: JMP *-3 */
|
||||
0102077, /* 77711: HLT 77B ; stop */
|
||||
0027700, /* 77712: JMP ST ; next */
|
||||
0077754, /* 77713: STA WC ; word in rec */
|
||||
0017742, /* 77714: JSB READ ; get feed frame */
|
||||
0017742, /* 77715: JSB READ ; get address */
|
||||
0074000, /* 77716: STB 0 ; init csum */
|
||||
0077755, /* 77717: STB AD ; save addr */
|
||||
0067755, /* 77720: CK LDB AD ; check addr */
|
||||
0047777, /* 77721: ADB MAXAD ; below loader */
|
||||
0002040, /* 77722: SEZ ; E =0 => OK */
|
||||
0027740, /* 77723: JMP H55 */
|
||||
0017742, /* 77724: JSB READ ; get word */
|
||||
0040001, /* 77725: ADA 1 ; cont checksum */
|
||||
0177755, /* 77726: STA AD,I ; store word */
|
||||
0037755, /* 77727: ISZ AD */
|
||||
0000040, /* 77730: CLE ; force wd read */
|
||||
0037754, /* 77731: ISZ WC ; block done? */
|
||||
0027720, /* 77732: JMP CK ; no */
|
||||
0017742, /* 77733: JSB READ ; get checksum */
|
||||
0054000, /* 77734: CPB 0 ; ok? */
|
||||
0027702, /* 77735: JMP CN ; next block */
|
||||
0102011, /* 77736: HLT 11 ; bad csum */
|
||||
0027700, /* 77737: JMP ST ; next */
|
||||
0102055, /* 77740: H55 HLT 55 ; bad address */
|
||||
0027700, /* 77741: JMP ST ; next */
|
||||
0000000, /* 77742: RD NOP */
|
||||
0006600, /* 77743: CLB,CME ; E reg byte ptr */
|
||||
0103710, /* 77744: STC RDR,C ; start reader */
|
||||
0102310, /* 77745: SFS RDR ; wait */
|
||||
0027745, /* 77746: JMP *-1 */
|
||||
0106410, /* 77747: MIB RDR ; get byte */
|
||||
0002041, /* 77750: SEZ,RSS ; E set? */
|
||||
0127742, /* 77751: JMP RD,I ; no, done */
|
||||
0005767, /* 77752: BLF,CLE,BLF ; shift byte */
|
||||
0027744, /* 77753: JMP RD+2 ; again */
|
||||
0000000, /* 77754: WC 000000 ; word count */
|
||||
0000000, /* 77755: AD 000000 ; address */
|
||||
0177765, /* 77756: M11 DEC -11 ; feed count */
|
||||
0000000, /* 77757: NOP */
|
||||
0000000, /* 77760: NOP */
|
||||
0000000, /* 77761: NOP */
|
||||
0000000, /* 77762: NOP */
|
||||
0000000, /* 77763: NOP */
|
||||
0000000, /* 77764: NOP */
|
||||
0000000, /* 77765: NOP */
|
||||
0000000, /* 77766: NOP */
|
||||
0000000, /* 77767: NOP */
|
||||
0000000, /* 77770: NOP */
|
||||
0000000, /* 77771: NOP */
|
||||
0000000, /* 77772: NOP */
|
||||
0000000, /* 77773: NOP */
|
||||
0000000, /* 77774: NOP */
|
||||
0000000, /* 77775: NOP */
|
||||
0000000, /* 77776: NOP */
|
||||
0100100 } } /* 77777: MAXAD ABS -ST ; max addr */
|
||||
};
|
||||
|
||||
|
||||
/* Device boot routine.
|
||||
|
||||
This routine is called directly by the BOOT PTR and LOAD PTR 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 12992K 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 PTR device structure.
|
||||
Depending on the current CPU model, the BBL or 12992K loader ROM will be
|
||||
copied into memory and configured for the PTR 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 BBL or 12992K 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 12992K boot loader ROM, the S register will be set as follows:
|
||||
|
||||
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
| ROM # | 0 0 | PTR select code | 0 0 0 0 0 0 |
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
*/
|
||||
|
||||
t_stat ptr_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
const int32 dev = ptr_dib.select_code; /* get device no */
|
||||
if (dptr == NULL) /* if we are being called for a BOOT/LOAD CPU */
|
||||
return cpu_copy_loader (ptr_loaders, unitno, /* then copy the boot loader to memory */
|
||||
IBL_S_NOCLEAR, IBL_S_NOSET); /* but do not alter the S register */
|
||||
|
||||
cpu_ibl (ptr_rom, dev, IBL_S_CLR, /* copy the boot ROM to memory and configure */
|
||||
IBL_PTR | IBL_SET_SC (dev)); /* the S register accordingly */
|
||||
|
||||
return SCPE_OK;
|
||||
else /* otherwise this is a BOOT/LOAD PTR */
|
||||
return cpu_copy_loader (ptr_loaders, ptr_dib.select_code, /* so copy the boot loader to memory */
|
||||
IBL_S_CLEAR, IBL_S_NOSET); /* and configure the S register if 1000 CPU */
|
||||
}
|
||||
|
||||
|
||||
|
@ -1132,23 +1289,23 @@ return SCPE_OK;
|
|||
|
||||
t_stat tto_svc (UNIT *uptr)
|
||||
{
|
||||
int32 c;
|
||||
t_stat r;
|
||||
|
||||
c = tty_buf; /* get char */
|
||||
tty_buf = tty_shin; /* shift in */
|
||||
tty_shin = 0377; /* line inactive */
|
||||
r = tto_out (tty_buf); /* output the character */
|
||||
|
||||
r = tto_out (c); /* output the character */
|
||||
if (r == SCPE_OK) { /* if the output succeeded */
|
||||
tty_buf = tty_shin; /* then shift the input line into the buffer */
|
||||
tty_shin = 0377; /* and set the input line to the marking state */
|
||||
|
||||
if (r != SCPE_OK) { /* if an error occurred */
|
||||
sim_activate (uptr, uptr->wait); /* then schedule a retry */
|
||||
return (r == SCPE_STALL ? SCPE_OK : r); /* report a stall as success */
|
||||
ttyio (&tty_dib, ioENF, 0); /* set the flag */
|
||||
return SCPE_OK; /* and return success */
|
||||
}
|
||||
|
||||
ttyio (&tty_dib, ioENF, 0); /* set flag */
|
||||
else { /* otherwise an error occurred */
|
||||
sim_activate (uptr, uptr->wait); /* so schedule a retry */
|
||||
|
||||
return SCPE_OK;
|
||||
return (r == SCPE_STALL ? SCPE_OK : r); /* report a stall as success */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* hp2100_sys.c: HP 2100 system common interface
|
||||
|
||||
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
|
||||
|
@ -24,6 +24,9 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from the authors.
|
||||
|
||||
07-Mar-18 JDB Added the GET_SWITCHES macro from scp.c
|
||||
22-Feb-18 JDB Added the <dev> option to the LOAD command
|
||||
07-Sep-17 JDB Replaced "uint16" cast with "MEMORY_WORD" for loader ROM
|
||||
07-Aug-17 JDB Added "hp_attach" to attach a file for appending
|
||||
01-Aug-17 JDB Added "ispunct" test for implied mnemonic parse
|
||||
20-Jul-17 JDB Removed STOP_OFFLINE, STOP_PWROFF messages
|
||||
|
@ -108,6 +111,12 @@
|
|||
|
||||
|
||||
|
||||
/* Command-line switch parsing from scp.c */
|
||||
|
||||
#define GET_SWITCHES(cp) \
|
||||
if ((cp = get_sim_sw (cp)) == NULL) return SCPE_INVSW
|
||||
|
||||
|
||||
/* External I/O data structures */
|
||||
|
||||
extern DEVICE mp_dev; /* Memory Protect */
|
||||
|
@ -1807,6 +1816,7 @@ static t_addr parse_addr (DEVICE *dptr, CONST char *cptr, CONST char **tptr)
|
|||
static t_stat hp_exdep_cmd (int32 arg, CONST char *buf);
|
||||
static t_stat hp_run_cmd (int32 arg, CONST char *buf);
|
||||
static t_stat hp_brk_cmd (int32 arg, CONST char *buf);
|
||||
static t_stat hp_load_cmd (int32 arg, CONST char *buf);
|
||||
|
||||
|
||||
/* System interface local utility routines */
|
||||
|
@ -1953,6 +1963,8 @@ static CTAB aux_cmds [] = {
|
|||
{ "BREAK", &hp_brk_cmd, 0, NULL },
|
||||
{ "NOBREAK", &hp_brk_cmd, 0, NULL },
|
||||
|
||||
{ "LOAD", &hp_load_cmd, 0, NULL },
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
@ -2041,16 +2053,19 @@ t_stat sim_load (FILE *fptr, CONST char *cptr, CONST char *fnam, int flag)
|
|||
const int reclen [2] = { TO_WORD (57, 0), /* the two DUMP record length words */
|
||||
TO_WORD (7, 0) };
|
||||
const int reccnt [2] = { 57, 7 }; /* the two DUMP record word counts */
|
||||
BOOT_ROM loader; /* an array of 64 words */
|
||||
int record, count, address, word, checksum;
|
||||
t_stat result;
|
||||
int32 trailer = 1; /* > 0 while reading leader, < 0 while reading trailer */
|
||||
HP_WORD select_code = 0; /* select code to configure; 0 implies no configuration */
|
||||
LOADER_ARRAY boot = { /* an array of two BOOT_LOADER structures */
|
||||
{ 000, IBL_NA, IBL_NA, { 0 } }, /* HP 21xx Loader */
|
||||
{ IBL_START, IBL_DMA, IBL_FWA, { 0 } } /* HP 1000 Loader */
|
||||
};
|
||||
|
||||
if (flag == 0) { /* if this is a LOAD command */
|
||||
if (*cptr != '\0') { /* then if a parameter follows */
|
||||
select_code = (HP_WORD) get_uint (cptr, 8, /* then parse it as an octal number */
|
||||
MAXDEV, &result);
|
||||
select_code = /* then parse it as an octal number */
|
||||
(HP_WORD) get_uint (cptr, 8, MAXDEV, &result);
|
||||
|
||||
if (result != SCPE_OK) /* if a parse error occurred */
|
||||
return result; /* then report it */
|
||||
|
@ -2059,8 +2074,6 @@ if (flag == 0) { /* if this is a LOAD com
|
|||
return SCPE_ARG; /* then report a bad argument */
|
||||
}
|
||||
|
||||
memset (loader, 0, sizeof loader); /* clear the boot loader ROM */
|
||||
|
||||
while (TRUE) { /* read absolute binary records from the file */
|
||||
do { /* skip any blank leader or trailer present */
|
||||
count = fgetc (fptr); /* get the next byte from the tape */
|
||||
|
@ -2103,7 +2116,8 @@ if (flag == 0) { /* if this is a LOAD com
|
|||
return SCPE_FMT; /* then the tape format is bad */
|
||||
|
||||
else { /* otherwise */
|
||||
loader [address++] = (uint16) word; /* save the data word in the loader array */
|
||||
boot [0].loader [address] = (MEMORY_WORD) word; /* save the data word in */
|
||||
boot [1].loader [address++] = (MEMORY_WORD) word; /* both loader arrays */
|
||||
checksum = checksum + word; /* and include it in the record checksum */
|
||||
}
|
||||
}
|
||||
|
@ -2121,8 +2135,8 @@ if (flag == 0) { /* if this is a LOAD com
|
|||
trailer = -10; /* so prepare for a potential trailer */
|
||||
} /* and loop until all records are read */
|
||||
|
||||
cpu_ibl (loader, select_code, /* install the loader */
|
||||
IBL_S_NOCLR, IBL_S_NOSET); /* and configure the select code if requested */
|
||||
cpu_copy_loader (boot, select_code, /* install the loader */
|
||||
IBL_S_NOCLEAR, IBL_S_NOSET); /* and configure the select code if requested */
|
||||
}
|
||||
|
||||
|
||||
|
@ -3249,7 +3263,7 @@ while ((bitfmt.alternate || bitset) /* while more bits */
|
|||
bnptr = bitfmt.names [index]; /* point at the name for the current bit */
|
||||
|
||||
if (bnptr) /* if the name is defined */
|
||||
if (*bnptr == '\1') /* then if this name has an alternate */
|
||||
if (*bnptr == '\1' && bitfmt.alternate) /* then if this name has an alternate */
|
||||
if (bitset & test_bit) /* then if the bit is asserted */
|
||||
bnptr++; /* then point at the name for the "1" state */
|
||||
else /* otherwise */
|
||||
|
@ -3854,6 +3868,62 @@ return brk_cmd (arg, buf); /* return the result of
|
|||
}
|
||||
|
||||
|
||||
/* Execute the LOAD command.
|
||||
|
||||
This command is intercepted to permit a device boot routine to be loaded
|
||||
into memory. The following command forms are valid:
|
||||
|
||||
LOAD <dev>
|
||||
LOAD <filename> [ <select-code> ]
|
||||
|
||||
If the first form is used, and the device name is valid and bootable, the
|
||||
corresponding boot loader is copied into memory in the highest 64 locations
|
||||
of the logical address space. Upon return, the loader will have been
|
||||
configured for the device's select code or for the device and paper tape
|
||||
reader select codes, in the case of a dual-use 21xx boot loader, and the P
|
||||
register will have been set to point at the start of the loader. The loader
|
||||
then may be executed by a RUN command. If the device name is valid, but the
|
||||
device is not bootable, or no boot loader exists for the current CPU
|
||||
configuration, the command is rejected.
|
||||
|
||||
If the second form is used, the file containing a loader in absolute binary
|
||||
form is read into memory and configured as above. See the "sim_load"
|
||||
comments for details of this operation.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. The "find_dev" routine requires that the device name be in upper case to
|
||||
match. The "get_glyph" routine performs case-shifting on the input
|
||||
buffer.
|
||||
*/
|
||||
|
||||
static t_stat hp_load_cmd (int32 arg, CONST char *buf)
|
||||
{
|
||||
CONST char *cptr;
|
||||
char cbuf [CBUFSIZE];
|
||||
DEVICE *dptr = NULL;
|
||||
|
||||
GET_SWITCHES (buf); /* parse any switches present */
|
||||
|
||||
cptr = get_glyph (buf, cbuf, '\0'); /* parse a potential device name */
|
||||
|
||||
if (cbuf [0] != '\0') { /* if the name is present */
|
||||
dptr = find_dev (cbuf); /* then see if it matches a device */
|
||||
|
||||
if (dptr != NULL) /* if it does */
|
||||
if (dptr->boot == NULL) /* then if the device is not bootable */
|
||||
return SCPE_NOFNC; /* then report "Command not allowed" */
|
||||
else if (*cptr != '\0') /* otherwise if more characters follow */
|
||||
return SCPE_2MARG; /* then report "Too many arguments" */
|
||||
else /* otherwise the device name stands alone */
|
||||
return dptr->boot (0, dptr); /* so load the corresponding boot loader */
|
||||
}
|
||||
|
||||
return load_cmd (arg, buf); /* if it's not a device name, then try loading a file */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* System interface local utility routines */
|
||||
|
||||
|
|
Binary file not shown.
Loading…
Add table
Reference in a new issue