1
0
mirror of https://github.com/simh/simh.git synced 2026-04-18 08:57:25 +00:00

HP3000: HP 3000 release 7

See HP3000/hp3000_release.txt for details of the release
This commit is contained in:
Mark Pizzolato
2018-01-12 15:06:04 -08:00
parent 0dc94bf3ec
commit 5f94c22f00
13 changed files with 815 additions and 362 deletions

View File

@@ -1,6 +1,6 @@
/* hp3000_atc.c: HP 3000 30032B Asynchronous Terminal Controller simulator /* hp3000_atc.c: HP 3000 30032B Asynchronous Terminal Controller simulator
Copyright (c) 2014-2016, J. David Bryan Copyright (c) 2014-2017, J. David Bryan
Copyright (c) 2002-2012, Robert M Supnik Copyright (c) 2002-2012, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -26,6 +26,10 @@
ATCD,ATCC HP 30032B Asynchronous Terminal Controller ATCD,ATCC HP 30032B Asynchronous Terminal Controller
18-Dec-17 JDB Return event time instead of status from "activate_unit"
11-Dec-17 JDB Reschedule "line_service" if receive buffer has data
26-Oct-17 JDB Call "tmxr_poll_tx" if transmit buffer is full
05-Sep-17 JDB Changed REG_A (permit any symbolic override) to REG_X
16-Sep-16 JDB Fixed atcd_detach to skip channel cancel if SIM_SW_REST 16-Sep-16 JDB Fixed atcd_detach to skip channel cancel if SIM_SW_REST
12-Sep-16 JDB Changed DIB register macro usage from SRDATA to DIB_REG 12-Sep-16 JDB Changed DIB register macro usage from SRDATA to DIB_REG
20-Jul-16 JDB Corrected poll_unit "wait" field initializer. 20-Jul-16 JDB Corrected poll_unit "wait" field initializer.
@@ -782,7 +786,7 @@ static void tci_master_reset (void);
static t_stat line_service (UNIT *uptr); static t_stat line_service (UNIT *uptr);
static t_stat poll_service (UNIT *uptr); static t_stat poll_service (UNIT *uptr);
static t_stat activate_unit (UNIT *uptr, ACTIVATOR reason); static int32 activate_unit (UNIT *uptr, ACTIVATOR reason);
static uint32 service_time (HP_WORD control, ACTIVATOR reason); static uint32 service_time (HP_WORD control, ACTIVATOR reason);
static void store (HP_WORD control, HP_WORD data); static void store (HP_WORD control, HP_WORD data);
static void receive (int32 channel, int32 data, t_bool loopback); static void receive (int32 channel, int32 data, t_bool loopback);
@@ -926,17 +930,17 @@ static REG atcd_reg [] = {
/* ------ ------ ------------------- ----- ----- ------ ---------------- --------------- */ /* ------ ------ ------------------- ----- ----- ------ ---------------- --------------- */
{ ORDATA (CNTL, tdi_control_word, 16), REG_FIT }, { ORDATA (CNTL, tdi_control_word, 16), REG_FIT },
{ ORDATA (STAT, tdi_status_word, 16), REG_FIT }, { ORDATA (STAT, tdi_status_word, 16), REG_FIT },
{ ORDATA (READ, tdi_read_word, 16), REG_A | REG_FIT }, { ORDATA (READ, tdi_read_word, 16), REG_X | REG_FIT },
{ ORDATA (WRITE, tdi_write_word, 16), REG_A | REG_FIT }, { ORDATA (WRITE, tdi_write_word, 16), REG_X | REG_FIT },
{ FLDATA (FLAG, tdi_data_flag, 0) }, { FLDATA (FLAG, tdi_data_flag, 0) },
{ FLDATA (MASK, tdi_interrupt_mask, 0) }, { FLDATA (MASK, tdi_interrupt_mask, 0) },
{ DRDATA (FTIME, fast_data_time, 24), PV_LEFT }, { DRDATA (FTIME, fast_data_time, 24), PV_LEFT },
{ BRDATA (RSTAT, recv_status, 8, 16, RECV_CHAN_COUNT) }, { BRDATA (RSTAT, recv_status, 8, 16, RECV_CHAN_COUNT) },
{ BRDATA (RPARM, recv_param, 8, 16, RECV_CHAN_COUNT) }, { BRDATA (RPARM, recv_param, 8, 16, RECV_CHAN_COUNT) },
{ BRDATA (RBUFR, recv_buffer, 8, 16, RECV_CHAN_COUNT), REG_A }, { BRDATA (RBUFR, recv_buffer, 8, 16, RECV_CHAN_COUNT), REG_X },
{ BRDATA (SSTAT, send_status, 8, 16, SEND_CHAN_COUNT) }, { BRDATA (SSTAT, send_status, 8, 16, SEND_CHAN_COUNT) },
{ BRDATA (SPARM, send_param, 8, 16, SEND_CHAN_COUNT) }, { BRDATA (SPARM, send_param, 8, 16, SEND_CHAN_COUNT) },
{ BRDATA (SBUFR, send_buffer, 8, 16, SEND_CHAN_COUNT), REG_A }, { BRDATA (SBUFR, send_buffer, 8, 16, SEND_CHAN_COUNT), REG_X },
{ FLDATA (POLL, atc_is_polling, 0), REG_HRO }, { FLDATA (POLL, atc_is_polling, 0), REG_HRO },
DIB_REGS (atcd_dib), DIB_REGS (atcd_dib),
@@ -1723,6 +1727,7 @@ tdi_master_reset (); /* perform a master rese
if (sim_switches & SWMASK ('P')) { /* if this is a power-on reset */ if (sim_switches & SWMASK ('P')) { /* if this is a power-on reset */
sim_rtcn_init (poll_unit.wait, TMR_ATC); /* then initialize the poll timer */ sim_rtcn_init (poll_unit.wait, TMR_ATC); /* then initialize the poll timer */
fast_data_time = FAST_IO_TIME; /* restore the initial fast data time */ fast_data_time = FAST_IO_TIME; /* restore the initial fast data time */
atcd_ldsc [0].xmte = 1; /* enable transmission on the system console port */
} }
if (atc_is_polling) { /* if we're polling for the simulation console */ if (atc_is_polling) { /* if we're polling for the simulation console */
@@ -1825,6 +1830,14 @@ return status;
unit 16 if it is attached. In all cases, it is imperative that we not reject unit 16 if it is attached. In all cases, it is imperative that we not reject
the request for unit 16; otherwise any remaining device detaches will not be the request for unit 16; otherwise any remaining device detaches will not be
performed. performed.
Implementation notes:
1. Detaching the multiplexer resets each line first, which flushes the
output buffer. This ensures that buffered data that has not been output
via a poll_service entry before the DETACH command was issued is written
before the line is disconnected.
*/ */
static t_stat atcd_detach (UNIT *uptr) static t_stat atcd_detach (UNIT *uptr)
@@ -1975,8 +1988,9 @@ return;
The channel service routine runs only when there are characters to read or The channel service routine runs only when there are characters to read or
write. It is scheduled either at a realistic rate corresponding to the write. It is scheduled either at a realistic rate corresponding to the
programmed baud rate of the channel to be serviced, or at a somewhat faster programmed baud rate of the channel to be serviced, or at a somewhat faster
optimized rate. It is entered when a channel buffer is ready for output or optimized rate. It is entered when a channel buffer is ready for output,
when the poll routine determines that there are characters ready for input. when the poll routine determines that there are characters ready for input,
or while waiting for an ACK to complete an ENQ/ACK handshake.
On entry, the receive channel buffer is checked for a character. If one is On entry, the receive channel buffer is checked for a character. If one is
not already present, then the terminal multiplexer library is called to not already present, then the terminal multiplexer library is called to
@@ -1984,6 +1998,12 @@ return;
processed. If the receive channel has its "diagnose" bit set, the character processed. If the receive channel has its "diagnose" bit set, the character
is also passed to the auxiliary channels. is also passed to the auxiliary channels.
If a received character is not available, then the unit's "wait" field is
checked to see if an ACK is expected in reply to an earlier ENQ. If a wait
time is present, it is doubled, and the service is rescheduled. However, if
the new wait time is longer than the current poll time, service rescheduling
is abandoned in favor of the normal poll for received characters.
The send channel buffer is then checked for a character to output. If one is The send channel buffer is then checked for a character to output. If one is
present, then if it is an all-mark (sync) character, it is discarded, as the present, then if it is an all-mark (sync) character, it is discarded, as the
receiver would never see it. Otherwise, if the TDI is in diagnostic mode, receiver would never see it. Otherwise, if the TDI is in diagnostic mode,
@@ -1998,18 +2018,36 @@ return;
simulation console (if output is to channel 0) or to the terminal multiplexer simulation console (if output is to channel 0) or to the terminal multiplexer
library for output via Telnet or a serial port on the host machine. If the library for output via Telnet or a serial port on the host machine. If the
channel has its "diagnose" bit set, the character is also passed to the channel has its "diagnose" bit set, the character is also passed to the
auxiliary channels. auxiliary channels. If an ENQ was transmitted, service is rescheduled to
wait for reception of the ACK.
If the data flag is clear, the indicated receive and send channels are If the data flag is clear, the indicated receive and send channels are
checked for completion flags. If either is set, an interrupt is requested. checked for completion flags. If either is set, an interrupt is requested.
If characters remain in the Telnet receive buffer, the service routine is
rescheduled to receive the next one. Otherwise, the routine goes idle until
the next character is output or the next poll determines that there are
characters to receive.
Implementation notes: Implementation notes:
1. Calling "tmxr_getc_ln" for channel 0 is OK, as reception is disabled by 1. The "wait" fields of the channel units are not used (i.e., are set to
zero) except when channels are waiting for ACKs. Because we want to
retrieve the ACK as quickly as possible but also minimize the load on the
host system, we initially wait the normal reception time (fast or
realistic) and then double the wait each time it expires without
reception. Therefore, a non-zero "wait" value indicates that an ACK is
expected.
2. Receipt of any character cancels a pending ACK wait, even though it is
possible that the character is not an ACK (for example, if the character
was received but not processed before the ENQ was sent).
3. Calling "tmxr_getc_ln" for channel 0 is OK, as reception is disabled by
default and therefore will return 0. default and therefore will return 0.
2. The send channel buffer will always be non-zero if a character is present 4. The send channel buffer will always be non-zero if a character is present
(even a NUL) because the data word will have DDS_IS_SEND set. (even a NUL) because the data word will have DDS_IS_SEND set.
The receive buffer will always be non-zero if a character is present The receive buffer will always be non-zero if a character is present
@@ -2018,27 +2056,45 @@ return;
TMXR_VALID set, and characters looped back from sending will have TMXR_VALID set, and characters looped back from sending will have
DDS_IS_SEND set. DDS_IS_SEND set.
3. Reception of a loopback character is performed immediately because the 5. Reception of a loopback character is performed immediately because the
reception occurs concurrently with transmission. Reception of a locally reception occurs concurrently with transmission. Reception of a locally
generated ACK is scheduled with a one-character delay to reflect the generated ACK is scheduled with a one-character delay to reflect the
remote device transmission delay. remote device transmission delay.
4. If storing an ACK locally overwrites a character already present but not 6. If storing an ACK locally overwrites a character already present but not
yet processed, then the receive routine will set the character lost flag. yet processed, then the receive routine will set the character lost flag.
5. Both TMXR_VALID and SCPE_KFLAG are set on internally generated ACKs only 7. Both TMXR_VALID and SCPE_KFLAG are set on internally generated ACKs only
so that a debug trace will record the generation correctly. so that a debug trace will record the generation correctly.
6. The console library "sim_putchar_s" routine and the terminal multiplexer 8. The console library "sim_putchar_s" routine and the terminal multiplexer
library "tmxr_putc_ln" routine return SCPE_STALL if the Telnet output library "tmxr_putc_ln" routine return SCPE_STALL if they are called when
buffer is full. In this case, transmission is rescheduled with a delay the transmit buffer is full. When called to add the last character to
to allow the buffer to drain. the buffer, the routines return SCPE_OK but also change the "xmte" field
of the terminal multiplexer line (TMLN) structure from 1 to 0 to indicate
that further calls will be rejected; the value is set back to 1 when the
transmit buffer empties.
They also return SCPE_LOST if the line has been dropped on the remote Entry with the transmit buffer full causes the service to be rescheduled
end. We ignore the error here to allow the simulation to continue while to retry the write after a short delay. The "tmxr_poll_tx" routine must
ignoring the output. be called in this case, as it is responsible for transmitting the buffer
contents and therefore freeing space in the buffer.
7. The receive/send completion flag (buffer flag) will not set unless the Both library "put" routines also return SCPE_LOST if the line has been
dropped on the remote end. We ignore that error here to allow the
simulation to continue while ignoring the output to a disconnected
terminal.
9. Characters written using "tmxr_putc_ln" are buffered and not transmitted
until the buffer is full, the character is an ENQ (and so we will be
waiting to receive an ACK), or the next input poll is performed. The
last case ensures that the buffer is flushed when output is complete, as
there is no indication from the CPU that the last character has been
sent. This does incur a delay of up to 10 milliseconds, but this is
imperceptible by the user. Buffering offers significantly better
throughput compared to transmitting each character as it is written.
10. The receive/send completion flag (buffer flag) will not set unless the
interrupt enable flag for that channel is also set. If enable is not interrupt enable flag for that channel is also set. If enable is not
set, the completion indication will be lost. set, the completion indication will be lost.
*/ */
@@ -2057,18 +2113,36 @@ dprintf (atcd_dev, DEB_SERV, "Channel %d service entered\n",
/* Reception service */ /* Reception service */
recv_data = recv_buffer [channel]; /* get the current buffer character */ recv_data = recv_buffer [channel]; /* get the current buffer character */
if (recv_data == 0) /* if there's none present */ if (recv_data == 0) { /* if no character is present */
recv_data = tmxr_getc_ln (&atcd_ldsc [channel]); /* then see if there's a character ready via Telnet */ if (uptr->wait) /* then if the channel is waiting for an ACK */
tmxr_poll_rx (&atcd_mdsc); /* then poll the line to see if it has arrived */
if (recv_data & ~DDR_DATA_MASK) { /* if we now have a valid character */ recv_data = tmxr_getc_ln (&atcd_ldsc [channel]); /* see if there's now a character ready */
receive (channel, recv_data, loopback); /* then process the reception */
if (recv_param [channel] & DPI_DIAGNOSE) /* if a diagnosis is requested */
diagnose (recv_param [channel], recv_data); /* then route the data to the auxiliary channels */
} }
if (recv_data & ~DDR_DATA_MASK) { /* if we now have a valid character */
receive (channel, recv_data, loopback); /* then process the reception */
if (recv_param [channel] & DPI_DIAGNOSE) /* if a diagnosis is requested */
diagnose (recv_param [channel], recv_data); /* then route the data to the auxiliary channels */
uptr->wait = 0; /* clear any pending ACK wait */
}
else if (uptr->wait) { /* otherwise if an ACK is expected but has not arrived */
uptr->wait = uptr-> wait * 2; /* then double the wait time for the next check */
if (uptr->wait < poll_unit.wait) { /* if the wait is shorter than the standard poll wait */
sim_activate (uptr, uptr->wait); /* then reschedule the line service */
dprintf (atcd_dev, DEB_SERV, "Channel %d delay %d service rescheduled for ACK\n",
channel, uptr->wait);
}
}
/* Transmission service */ /* Transmission service */
if (send_buffer [channel]) { /* if data is available to send */ if (send_buffer [channel]) { /* if data is available to send */
@@ -2132,43 +2206,56 @@ if (send_buffer [channel]) { /* if data is availa
cvtd_data = sim_tt_outcvt (LOWER_BYTE (send_data), /* so convert it as directed */ cvtd_data = sim_tt_outcvt (LOWER_BYTE (send_data), /* so convert it as directed */
TT_GET_MODE (uptr->flags)); /* by the output mode flag */ TT_GET_MODE (uptr->flags)); /* by the output mode flag */
if (cvtd_data >= 0) /* if the converted character is printable */ if (cvtd_data >= 0 && atcd_ldsc [channel].xmte == 0) { /* if it's printable but the transmit buffer is full */
if (channel == 0) /* then if we are writing to channel 0 */
result = sim_putchar_s (cvtd_data); /* then output it to the simulation console */
else /* otherwise */
result = tmxr_putc_ln (&atcd_ldsc [channel], /* output it to the multiplexer line */
cvtd_data);
if (result == SCPE_STALL) { /* if the buffer is full */
activate_unit (uptr, Stall); /* then retry the output a while later */ activate_unit (uptr, Stall); /* then retry the output a while later */
result = SCPE_OK; /* and return OK to continue */
tmxr_poll_tx (&atcd_mdsc); /* transmit the line buffer */
dprintf (atcd_dev, DEB_XFER, "Channel %d character %s transmission stalled for full buffer\n",
channel, fmt_char (cvtd_data));
} }
else if (result == SCPE_OK || result == SCPE_LOST) { /* otherwise if the character is queued to transmit */ else { /* otherwise the character will be consumed */
tmxr_poll_tx (&atcd_mdsc); /* then send (or ignore) it */ if (cvtd_data >= 0) /* if the converted character is printable */
if (channel == 0) /* then if we are writing to channel 0 */
result = sim_putchar_s (cvtd_data); /* then output it to the simulation console */
if (DPRINTING (atcd_dev, DEB_XFER)) else { /* otherwise */
if (result == SCPE_LOST) result = tmxr_putc_ln (&atcd_ldsc [channel], /* output it to the multiplexer line */
hp_debug (&atcd_dev, DEB_XFER, "Channel %d character %s discarded by connection loss\n", cvtd_data);
channel, fmt_char (char_data));
else if (cvtd_data >= 0) if (char_data == ENQ /* if sending an ENQ */
hp_debug (&atcd_dev, DEB_XFER, "Channel %d character %s sent\n", || atcd_ldsc [channel].xmte == 0) /* or the output buffer is full */
channel, fmt_char (cvtd_data)); tmxr_poll_tx (&atcd_mdsc); /* then transmit the line buffer */
}
else if (result == SCPE_OK || result == SCPE_LOST) { /* if the character is queued to transmit */
hp_debug (&atcd_dev, DEB_XFER, "Channel %d character %s discarded by output filter\n", if (DPRINTING (atcd_dev, DEB_XFER))
channel, fmt_char (char_data)); if (result == SCPE_LOST)
hp_debug (&atcd_dev, DEB_XFER, "Channel %d character %s discarded by connection loss\n",
channel, fmt_char (char_data));
if (send_param [channel] & DPI_DIAGNOSE) /* if a diagnosis is requested */ else if (cvtd_data >= 0)
diagnose (send_param [channel], send_data); /* then route the data to the auxiliary channels */ hp_debug (&atcd_dev, DEB_XFER, "Channel %d character %s sent\n",
channel, fmt_char (cvtd_data));
send_buffer [channel] = 0; /* clear the buffer */ else
hp_debug (&atcd_dev, DEB_XFER, "Channel %d character %s discarded by output filter\n",
channel, fmt_char (char_data));
if (send_param [channel] & DPI_ENABLE_IRQ) /* if this channel is enabled to interrupt */ if (send_param [channel] & DPI_DIAGNOSE) /* if a diagnosis is requested */
send_status [channel] |= DST_COMPLETE; /* then set the completion flag */ diagnose (send_param [channel], send_data); /* then route the data to the auxiliary channels */
result = SCPE_OK; /* return OK in case the connection was lost */ send_buffer [channel] = 0; /* clear the buffer */
if (send_param [channel] & DPI_ENABLE_IRQ) /* if this channel is enabled to interrupt */
send_status [channel] |= DST_COMPLETE; /* then set the completion flag */
if (cvtd_data == ENQ && result == SCPE_OK) /* if an ENQ was successfully sent */
uptr->wait = activate_unit (uptr, Receive); /* then schedule the ACK reception */
result = SCPE_OK; /* return OK in case the connection was lost */
}
} }
} }
} }
@@ -2177,6 +2264,9 @@ if (send_buffer [channel]) { /* if data is availa
if (tdi_data_flag == CLEAR) /* if an interrupt is not currently pending */ if (tdi_data_flag == CLEAR) /* if an interrupt is not currently pending */
scan_channels (channel); /* then scan the channels for completion flags */ scan_channels (channel); /* then scan the channels for completion flags */
if (tmxr_rqln (&atcd_ldsc [channel])) /* if characters are still available on this channel */
activate_unit (uptr, Receive); /* then reschedule the line service */
return result; /* return the result of the service */ return result; /* return the result of the service */
} }
@@ -2184,10 +2274,9 @@ return result; /* return the result of
/* Multiplexer poll service. /* Multiplexer poll service.
The poll service routine is used to poll for Telnet connections and incoming The poll service routine is used to poll for Telnet connections and incoming
characters. It also polls the simulation console for channel 0. Polling characters. It also polls the simulation console for channel 0 and flushes
starts at simulator startup or when the TDI is enabled and stops when it is the output buffers for all channels. Polling starts at simulator startup or
disabled. when the TDI is enabled and stops when it is disabled.
Implementation notes: Implementation notes:
@@ -2200,20 +2289,30 @@ return result; /* return the result of
may be shorter than the channel service time, and as the console provides may be shorter than the channel service time, and as the console provides
no buffering, a second character received before the channel service had no buffering, a second character received before the channel service had
been entered would be lost. been entered would be lost.
3. A channel that is waiting for an ACK to complete an ENQ/ACK handshake has
its unit "wait" field set non-zero. If the field value is greater than
the realistic reception time, then the line service is scheduled
immediately, as the channel has already waited the minimum time necessary
(the "wait" field value is doubled each time the line service is entered
before the ACK has been received). Otherwise, the service is scheduled
using the normal reception time.
*/ */
static t_stat poll_service (UNIT *uptr) static t_stat poll_service (UNIT *uptr)
{ {
int32 chan, line_state; int32 chan, line_state;
t_stat status = SCPE_OK; t_stat status = SCPE_OK;
dprintf (atcd_dev, DEB_PSERV, "Poll service entered\n"); dprintf (atcd_dev, DEB_PSERV, "Poll delay %d service entered\n",
uptr->wait);
if ((atcc_dev.flags & DEV_DIS) == 0) if ((atcc_dev.flags & DEV_DIS) == 0)
dprintf (atcc_dev, DEB_PSERV, "Poll service entered\n"); dprintf (atcc_dev, DEB_PSERV, "Poll delay %d service entered\n",
uptr->wait);
if ((atcd_dev.flags & DEV_DIAG) == 0) { /* if we're not in diagnostic mode */ if ((atcd_dev.flags & DEV_DIAG) == 0) { /* if we're not in diagnostic mode */
chan = tmxr_poll_conn (&atcd_mdsc); /* then check for a new multiplex connection */ chan = tmxr_poll_conn (&atcd_mdsc); /* then check for a new multiplexer connection */
if (chan != -1) { /* if a new connection was established */ if (chan != -1) { /* if a new connection was established */
atcd_ldsc [chan].rcve = TRUE; /* then enable the channel to receive */ atcd_ldsc [chan].rcve = TRUE; /* then enable the channel to receive */
@@ -2223,7 +2322,8 @@ if ((atcd_dev.flags & DEV_DIAG) == 0) { /* if we're not in diagn
} }
} }
tmxr_poll_rx (&atcd_mdsc); /* poll the multiplex connections for input */ tmxr_poll_tx (&atcd_mdsc); /* flush the multiplexer output buffers */
tmxr_poll_rx (&atcd_mdsc); /* and poll the multiplexer connections for input */
if ((atcc_dev.flags & (DEV_DIAG | DEV_DIS)) == 0) /* if we're not in diagnostic mode or are disabled */ if ((atcc_dev.flags & (DEV_DIAG | DEV_DIS)) == 0) /* if we're not in diagnostic mode or are disabled */
for (chan = FIRST_TERM; chan <= LAST_TERM; chan++) /* then scan the channels for line state changes */ for (chan = FIRST_TERM; chan <= LAST_TERM; chan++) /* then scan the channels for line state changes */
@@ -2257,9 +2357,15 @@ if (status >= SCPE_KFLAG) { /* if a character was pr
line_service (&line_unit [0]); /* run the system console's I/O service */ line_service (&line_unit [0]); /* run the system console's I/O service */
} }
for (chan = FIRST_TERM; chan <= LAST_TERM; chan++) /* check each of the receive channels for available input */ for (chan = FIRST_TERM; chan <= LAST_TERM; chan++) /* check each of the channels for available input */
if (tmxr_rqln (&atcd_ldsc [chan])) /* if characters are available on this channel */ if (tmxr_rqln (&atcd_ldsc [chan])) /* if characters are available on this channel */
activate_unit (&line_unit [chan], Receive); /* then activate the channel's I/O service */ if (line_unit [chan].wait > line_unit [chan].recv_time) { /* then if the channel is waiting for an ACK */
sim_cancel (&line_unit [chan]); /* then cancel any current wait */
activate_unit (&line_unit [chan], Loop); /* and activate the line service immediately */
}
else /* otherwise this is a normal input */
activate_unit (&line_unit [chan], Receive); /* so schedule with the normal receive timing */
if (cpu_is_calibrated) /* if the process clock is calibrated */ if (cpu_is_calibrated) /* if the process clock is calibrated */
uptr->wait = sim_activate_time (cpu_pclk_uptr); /* then synchronize with it */ uptr->wait = sim_activate_time (cpu_pclk_uptr); /* then synchronize with it */
@@ -2291,7 +2397,7 @@ return status; /* return the service st
called. called.
*/ */
static t_stat activate_unit (UNIT *uptr, ACTIVATOR reason) static int32 activate_unit (UNIT *uptr, ACTIVATOR reason)
{ {
const int32 channel = (int32) (uptr - line_unit); /* the channel number */ const int32 channel = (int32) (uptr - line_unit); /* the channel number */
int32 delay = 0; int32 delay = 0;
@@ -2339,7 +2445,8 @@ else /* otherwise, we are in
dprintf (atcd_dev, DEB_SERV, "Channel %d delay %d service scheduled\n", dprintf (atcd_dev, DEB_SERV, "Channel %d delay %d service scheduled\n",
channel, delay); channel, delay);
return sim_activate (uptr, delay); /* activate the unit and return the activation status */ sim_activate (uptr, delay); /* activate the unit */
return delay; /* and return the activation delay */
} }
@@ -2639,17 +2746,20 @@ else { /* otherwise a normal ch
recv_buffer [channel] = recv_data | pad; /* and replace the character in the buffer */ recv_buffer [channel] = recv_data | pad; /* and replace the character in the buffer */
} }
if (recv_param [channel] & DPI_ENABLE_ECHO) { /* if the channel has echo enabled */ if (recv_param [channel] & DPI_ENABLE_ECHO) { /* if the channel has echo enabled */
char_echo = sim_tt_outcvt (recv_data, /* then convert the character per the output mode */ char_echo = sim_tt_outcvt (recv_data, /* then convert the character per the output mode */
TT_GET_MODE (line_unit [channel].flags)); TT_GET_MODE (line_unit [channel].flags));
if (char_echo >= 0) { /* if the converted character is valid for the mode */ if (char_echo >= 0) { /* if the converted character is valid for the mode */
if (channel == 0) /* then if this is for channel 0 */ if (channel == 0) /* then if this is for channel 0 */
sim_putchar (char_echo); /* then write it back to the simulation console */ sim_putchar (char_echo); /* then write it back to the simulation console */
else { /* otherwise */ else { /* otherwise */
tmxr_putc_ln (&atcd_ldsc [channel], char_echo); /* write it to the multiplexer output line */ tmxr_putc_ln (&atcd_ldsc [channel], /* write it to the multiplexer output line */
tmxr_poll_tx (&atcd_mdsc); /* and poll to transmit it now */ char_echo);
if (atcd_ldsc [channel].xmte == 0) /* if the output buffer is full */
tmxr_poll_tx (&atcd_mdsc); /* then transmit the line buffer */
} }
dprintf (atcd_dev, DEB_XFER, ("Channel %d character %s echoed\n"), dprintf (atcd_dev, DEB_XFER, ("Channel %d character %s echoed\n"),

View File

@@ -25,6 +25,8 @@
CPU HP 3000 Series III Central Processing Unit CPU HP 3000 Series III Central Processing Unit
05-Sep-17 JDB Removed the -B (binary display) option; use -2 instead
Changed REG_A (permit any symbolic override) to REG_X
19-Jan-17 JDB Added comments describing the OPND and EXEC trace options 19-Jan-17 JDB Added comments describing the OPND and EXEC trace options
29_Dec-16 JDB Changed the status mnemonic flag from REG_S to REG_T 29_Dec-16 JDB Changed the status mnemonic flag from REG_S to REG_T
07-Nov-16 JDB Renamed cpu_byte_to_word_ea to cpu_byte_ea 07-Nov-16 JDB Renamed cpu_byte_to_word_ea to cpu_byte_ea
@@ -1024,8 +1026,7 @@ UNIT cpu_unit [] = {
modification. User flags describe the permitted and default display formats, modification. User flags describe the permitted and default display formats,
as follows: as follows:
- REG_A permits any display - REG_X permits any symbolic display
- REG_B permits binary display
- REG_M defaults to CPU instruction mnemonic display - REG_M defaults to CPU instruction mnemonic display
- REG_T defaults to CPU status mnemonic display - REG_T defaults to CPU status mnemonic display
@@ -1058,15 +1059,15 @@ static REG cpu_reg [] = {
{ ORDATA (SR, SR, 3), REG_FIT }, /* stack register counter */ { ORDATA (SR, SR, 3), REG_FIT }, /* stack register counter */
{ ORDATA (Z, Z, 16), REG_FIT }, /* stack limit register */ { ORDATA (Z, Z, 16), REG_FIT }, /* stack limit register */
{ ORDATA (SBANK, SBANK, 4), REG_FIT }, /* stack segment bank register */ { ORDATA (SBANK, SBANK, 4), REG_FIT }, /* stack segment bank register */
{ ORDATA (RA, TR [0], 16), REG_A | REG_FIT }, /* top of stack register */ { ORDATA (RA, TR [0], 16), REG_X | REG_FIT }, /* top of stack register */
{ ORDATA (RB, TR [1], 16), REG_A | REG_FIT }, /* top of stack - 1 register */ { ORDATA (RB, TR [1], 16), REG_X | REG_FIT }, /* top of stack - 1 register */
{ ORDATA (RC, TR [2], 16), REG_A | REG_FIT }, /* top of stack - 2 register */ { ORDATA (RC, TR [2], 16), REG_X | REG_FIT }, /* top of stack - 2 register */
{ ORDATA (RD, TR [3], 16), REG_A | REG_FIT }, /* top of stack - 3 register */ { ORDATA (RD, TR [3], 16), REG_X | REG_FIT }, /* top of stack - 3 register */
{ ORDATA (X, X, 16), REG_A | REG_FIT }, /* index register */ { ORDATA (X, X, 16), REG_X | REG_FIT }, /* index register */
{ ORDATA (STA, STA, 16), REG_T | REG_B | REG_FIT }, /* status register */ { ORDATA (STA, STA, 16), REG_T | REG_FIT }, /* status register */
{ ORDATA (SWCH, SWCH, 16), REG_A | REG_FIT }, /* switch register */ { ORDATA (SWCH, SWCH, 16), REG_X | REG_FIT }, /* switch register */
{ ORDATA (CPX1, CPX1, 16), REG_B | REG_FIT }, /* run-mode interrupt flags */ { ORDATA (CPX1, CPX1, 16), REG_FIT }, /* run-mode interrupt flags */
{ ORDATA (CPX2, CPX2, 16), REG_B | REG_FIT }, /* halt-mode interrupt flags */ { ORDATA (CPX2, CPX2, 16), REG_FIT }, /* halt-mode interrupt flags */
{ ORDATA (PCLK, PCLK, 16), REG_FIT }, /* process clock register */ { ORDATA (PCLK, PCLK, 16), REG_FIT }, /* process clock register */
{ ORDATA (CNTR, CNTR, 6), REG_HRO | REG_FIT }, /* microcode counter */ { ORDATA (CNTR, CNTR, 6), REG_HRO | REG_FIT }, /* microcode counter */
{ ORDATA (MOD, MOD, 16), REG_HRO | REG_FIT }, /* module control register */ { ORDATA (MOD, MOD, 16), REG_HRO | REG_FIT }, /* module control register */
@@ -1331,8 +1332,8 @@ DEVICE cpu_dev = {
volatile-qualified type and have been changed between the setjmp volatile-qualified type and have been changed between the setjmp
invocation and longjmp call are indeterminate." invocation and longjmp call are indeterminate."
Therefore, after a microcode abort, we cannot depend upon the values of Therefore, the "device" and "status" variables are marked volatile to
any local variables. ensure that they are reloaded after a longjmp caused by a micrcode abort.
2. In hardware, the NEXT microcode order present at the end of each 2. In hardware, the NEXT microcode order present at the end of each
instruction transfers the NIR content to the CIR, reads the memory word instruction transfers the NIR content to the CIR, reads the memory word
@@ -1398,10 +1399,11 @@ static const char *const stack_formats [] = { /* stack register displa
}; };
int abortval; int abortval;
HP_WORD label, parameter, device; HP_WORD label, parameter;
TRAP_CLASS trap; TRAP_CLASS trap;
t_bool exec_test; t_bool exec_test;
t_stat status = SCPE_OK; volatile HP_WORD device;
volatile t_stat status = SCPE_OK;
/* Instruction prelude */ /* Instruction prelude */

View File

@@ -1,6 +1,6 @@
/* hp3000_defs.h: HP 3000 simulator general declarations /* hp3000_defs.h: HP 3000 simulator general declarations
Copyright (c) 2016, J. David Bryan Copyright (c) 2016-2017, J. David Bryan
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@@ -23,7 +23,8 @@
in advertising or otherwise to promote the sale, use or other dealings in in advertising or otherwise to promote the sale, use or other dealings in
this Software without prior written authorization from the author. this Software without prior written authorization from the author.
29_Dec-16 JDB Changed the status mnemonic flag from REG_S to REG_T 16-Oct-17 JDB Suppressed logical-not-parentheses warning on clang
29-Dec-16 JDB Changed the status mnemonic flag from REG_S to REG_T
20-Nov-16 JDB Added mapped memory access classes 20-Nov-16 JDB Added mapped memory access classes
24-Oct-16 JDB Added half-byte definitions for CIS decoding 24-Oct-16 JDB Added half-byte definitions for CIS decoding
10-Oct-16 JDB Moved ACCESS_CLASS definition here from hp3000_cpu.h 10-Oct-16 JDB Moved ACCESS_CLASS definition here from hp3000_cpu.h
@@ -134,6 +135,7 @@
*/ */
#if defined (__clang__) #if defined (__clang__)
#pragma clang diagnostic ignored "-Wlogical-not-parentheses"
#pragma clang diagnostic ignored "-Wlogical-op-parentheses" #pragma clang diagnostic ignored "-Wlogical-op-parentheses"
#pragma clang diagnostic ignored "-Wbitwise-op-parentheses" #pragma clang diagnostic ignored "-Wbitwise-op-parentheses"
#pragma clang diagnostic ignored "-Wshift-op-parentheses" #pragma clang diagnostic ignored "-Wshift-op-parentheses"
@@ -147,10 +149,12 @@
/* Device register display mode flags */ /* Device register display mode flags */
#define REG_A (1u << REG_V_UF + 0) /* permit any display */ #define REG_X REG_VMIO /* permit symbolic display overrides */
#define REG_B (1u << REG_V_UF + 1) /* permit binary display */
#define REG_M (1u << REG_V_UF + 2) /* default to instruction mnemonic display */ #define REG_A (1u << REG_V_UF + 0) /* default format is -A (one ASCII character) */
#define REG_T (1u << REG_V_UF + 3) /* default to status mnemonic display */ #define REG_C (1u << REG_V_UF + 1) /* default format is -C (two ASCII characters) */
#define REG_M (1u << REG_V_UF + 2) /* default format is -M (mnemonic) */
#define REG_T (1u << REG_V_UF + 3) /* default format is -T (status mnemonic) */
/* Register macros. /* Register macros.

View File

@@ -1,6 +1,6 @@
/* hp3000_ds.c: HP 3000 30229B Cartridge Disc Interface simulator /* hp3000_ds.c: HP 3000 30229B Cartridge Disc Interface simulator
Copyright (c) 2016, J. David Bryan Copyright (c) 2016-2017, J. David Bryan
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@@ -25,6 +25,7 @@
DS HP 30229B Cartridge Disc Interface DS HP 30229B Cartridge Disc Interface
05-Sep-17 JDB Changed REG_A (permit any symbolic override) to REG_X
12-Sep-16 JDB Changed DIB register macro usage from SRDATA to DIB_REG 12-Sep-16 JDB Changed DIB register macro usage from SRDATA to DIB_REG
09-Jun-16 JDB Added casts for ptrdiff_t to int32 values 09-Jun-16 JDB Added casts for ptrdiff_t to int32 values
08-Jun-16 JDB Corrected %d format to %u for unsigned values 08-Jun-16 JDB Corrected %d format to %u for unsigned values
@@ -435,7 +436,7 @@ static REG ds_reg [] = {
{ FLDATA (OVRUN, flags, 5) }, { FLDATA (OVRUN, flags, 5) },
{ FLDATA (XFRNG, flags, 6) }, { FLDATA (XFRNG, flags, 6) },
{ ORDATA (BUFFER, buffer_word, 16), REG_A | REG_FIT | PV_RZRO }, { ORDATA (BUFFER, buffer_word, 16), REG_X | REG_FIT | PV_RZRO },
{ ORDATA (STATUS, status_word, 16), REG_FIT | PV_RZRO }, { ORDATA (STATUS, status_word, 16), REG_FIT | PV_RZRO },
{ DRDATA (RETRY, retry_counter, 4), REG_FIT | PV_LEFT }, { DRDATA (RETRY, retry_counter, 4), REG_FIT | PV_LEFT },

View File

@@ -321,15 +321,15 @@ struct dib { /* the Device Information Block
}; };
#define DIB_REGS(dib) \ #define DIB_REGS(dib) \
/* Macro Name Location Width Flags */ \ /* Macro Name Location Width Flags */ \
/* ------ ------- -------------------------- ----- ------- */ \ /* ------ ------- -------------------------- ----- ------- */ \
{ DRDATA (DIBDN, dib.device_number, 32), REG_HRO }, \ { DRDATA (DIBDN, dib.device_number, 32), REG_HRO }, \
{ DRDATA (DIBSRN, dib.service_request_number, 32), REG_HRO }, \ { DRDATA (DIBSRN, dib.service_request_number, 32), REG_HRO }, \
{ DRDATA (DIBPRI, dib.interrupt_priority, 32), REG_HRO }, \ { DRDATA (DIBPRI, dib.interrupt_priority, 32), REG_HRO }, \
{ ORDATA (DIBMASK, dib.interrupt_mask, 32), REG_HRO }, \ { ORDATA (DIBMASK, dib.interrupt_mask, 32), REG_HRO }, \
{ ORDATA (DIBIRQ, dib.interrupt_request, 32), REG_HRO }, \ { ORDATA (DIBIRQ, dib.interrupt_request, 32), REG_HRO }, \
{ ORDATA (DIBACT, dib.interrupt_active, 32), REG_HRO }, \ { ORDATA (DIBACT, dib.interrupt_active, 32), REG_HRO }, \
{ ORDATA (DIBSR, dib.service_request, 32), REG_HRO } { ORDATA (DIBSR, dib.service_request, 32), REG_HRO }
/* Calibrated timer numbers */ /* Calibrated timer numbers */

View File

@@ -25,6 +25,12 @@
LP HP 30209A Line Printer Interface LP HP 30209A Line Printer Interface
07-Sep-17 JDB Changed PCHR and UPCHR registers to PUNCHR and UNPCHR
Changed PRTBUF, OVPCHR, PUNCHR, and UNPCHR to REG_A
05-Sep-17 JDB Changed REG_A (permit any symbolic override) to REG_X
20-Jul-17 JDB Added a forced detach option (-F switch) to "lp_detach"
24-Jun-17 JDB Added "report_error", fixed "lp_set_model" times bug
22-Jun-17 JDB Moved deferred offline/detach cancel to SET ONLINE
26-Apr-17 JDB Fixed "lp_service" return for VFU channel not punched 26-Apr-17 JDB Fixed "lp_service" return for VFU channel not punched
Restricted auto-print on buffer full to the 2607 Restricted auto-print on buffer full to the 2607
Paper fault is now delayed until the TOF for the 2607 Paper fault is now delayed until the TOF for the 2607
@@ -205,19 +211,17 @@
issued while the print buffer contains data or the printer unit is busy issued while the print buffer contains data or the printer unit is busy
executing a print action. executing a print action.
The SET LP OFFLINE and SET LP DETACH commands check for data in the print The SET LP OFFLINE and DETACH LP commands check for data in the print buffer
buffer or a print operation in progress. If either condition is true, they or a print operation in progress. If either condition is true, they set
set their respective deferred-action flags and display "Command deferred." A their respective deferred-action flags and display "Command not completed."
SHOW LP will show that the device is still online and attached. Once A SHOW LP will show that the device is still online and attached. Once
simulation is resumed and the print operation completes, the printer is set simulation is resumed and the print operation completes, the printer is set
offline or detached as requested. No console message reports this, as it is offline or detached as requested. No console message reports this, as it is
assumed that the executing program will detect the condition and report assumed that the executing program will detect the condition and report
accordingly. A subsequent SHOW LP will indicate the new status. accordingly. A subsequent SHOW LP will indicate the new status.
A SET LP ONLINE or ATTACH LP command when the corresponding deferred-action A SET LP ONLINE command when a deferred-action flag is set simply clears the
flag is set simply clears the flag. In particular, an ATTACH LP command must flag, which cancels the pending offline or detach condition.
not specify a new image filename; if one is specified while a deferred detach
is in progress, the routine returns SCPE_NOFNC ("Command not allowed").
A RESET LP command also clears the deferred-action flags and so clears any A RESET LP command also clears the deferred-action flags and so clears any
pending offline or detach. However, it also clears the print buffer and pending offline or detach. However, it also clears the print buffer and
@@ -480,11 +484,22 @@
#define DEV_REALTIME (1u << DEV_REALTIME_SHIFT) /* realistic timing flag */ #define DEV_REALTIME (1u << DEV_REALTIME_SHIFT) /* realistic timing flag */
/* Printer unit flags */ /* Printer unit flags.
#define UNIT_MODEL_SHIFT (UNIT_V_UF + 0) /* bits 0-2: printer model ID */ UNIT_V_UF + 7 6 5 4 3 2 1 0
#define UNIT_EXPAND_SHIFT (UNIT_V_UF + 3) /* bits 3-3: printer uses expanded output */ +---+---+---+---+---+---+---+---+
#define UNIT_OFFLINE_SHIFT (UNIT_V_UF + 4) /* bits 4-4: printer is offline */ | - | - | - | O | E | model |
+---+---+---+---+---+---+---+---+
Where:
O = offline
E = expanded output
*/
#define UNIT_MODEL_SHIFT (UNIT_V_UF + 0) /* printer model ID */
#define UNIT_EXPAND_SHIFT (UNIT_V_UF + 3) /* printer uses expanded output */
#define UNIT_OFFLINE_SHIFT (UNIT_V_UF + 4) /* printer is offline */
#define UNIT_MODEL_MASK 0000007u /* model ID mask */ #define UNIT_MODEL_MASK 0000007u /* model ID mask */
@@ -541,10 +556,10 @@ typedef enum {
This table contains the characteristics that vary between printer models. This table contains the characteristics that vary between printer models.
The "char_set" field values reflect printer Option 001, 96/128-character set. The "char_set" field values reflect printer Option 001, 96/128-character set.
The "not_ready" field indicates whether a paper fault sets not-ready status The "not_ready" field indicates whether a paper fault sets a separate
or simply takes the printer offline. The "fault_at_eol" field indicates not-ready status or simply takes the printer offline. The "fault_at_eol"
whether a paper fault is reported at the end of any line (TRUE) or only at field indicates whether a paper fault is reported at the end of any line or
the top of the next form (FALSE). only at the top of the next form.
*/ */
typedef struct { typedef struct {
@@ -579,9 +594,10 @@ static const PRINTER_PROPS print_props [] = { /* printer properties, indexed b
Implementation notes: Implementation notes:
1. Although all of the printers operate more slowly with a 96/128-character 1. Although all of the printers operate more slowly with a 96/128-character
set than with a 64-character set, the times reflect the smaller set size. set installed than with a 64-character set, the times reflect the smaller
Also, some models provide different print rates, depending on how many set size. Also, some models provide different print rates, depending on
and/or which characters are printed. These variances are not simulated. how many and/or which characters are printed. These variations are not
simulated.
*/ */
typedef struct { typedef struct {
@@ -1046,7 +1062,7 @@ static t_bool power_warning = FALSE; /* PFWARN is not asserted to the
/* Printer state */ /* Printer state */
static t_bool paper_fault = TRUE; /* TRUE if the printer is out of paper */ static t_bool paper_fault = TRUE; /* TRUE if the printer is out of paper */
static t_bool tape_fault = FALSE; /* TRUE if there is no punch in a VFU channel command */ static t_bool tape_fault = FALSE; /* TRUE if there is no punch in a commanded VFU channel */
static t_bool offline_pending = FALSE; /* TRUE if an offline request is waiting for the printer to finish */ static t_bool offline_pending = FALSE; /* TRUE if an offline request is waiting for the printer to finish */
static uint32 overprint_char = DEL; /* character to use if overprinted */ static uint32 overprint_char = DEL; /* character to use if overprinted */
static uint32 current_line = 1; /* current form line */ static uint32 current_line = 1; /* current form line */
@@ -1077,6 +1093,7 @@ static t_stat ui_reset (DEVICE *dptr);
static t_stat master_reset (t_bool programmed_clear); static t_stat master_reset (t_bool programmed_clear);
static void clear_interface_logic (void); static void clear_interface_logic (void);
static void activate_unit (UNIT *uptr); static void activate_unit (UNIT *uptr);
static void report_error (FILE *stream);
static OUTBOUND_SET set_interrupt (uint32 interrupt); static OUTBOUND_SET set_interrupt (uint32 interrupt);
static OUTBOUND_SET set_device_status (uint32 status_mask, uint32 new_status_word); static OUTBOUND_SET set_device_status (uint32 status_mask, uint32 new_status_word);
static OUTBOUND_SET handshake_xfer (void); static OUTBOUND_SET handshake_xfer (void);
@@ -1177,12 +1194,12 @@ static REG lp_reg [] = {
{ ORDATA (CNTL, control_word, 16), PV_RZRO }, { ORDATA (CNTL, control_word, 16), PV_RZRO },
{ ORDATA (ISTAT, int_status_word, 16), PV_RZRO }, { ORDATA (ISTAT, int_status_word, 16), PV_RZRO },
{ ORDATA (DSTAT, dev_status_word, 16), PV_RZRO }, { ORDATA (DSTAT, dev_status_word, 16), PV_RZRO },
{ ORDATA (READ, read_word, 16), PV_RZRO | REG_A }, { ORDATA (READ, read_word, 16), PV_RZRO | REG_X },
{ ORDATA (WRITE, write_word, 16), PV_RZRO | REG_A }, { ORDATA (WRITE, write_word, 16), PV_RZRO | REG_X },
{ YRDATA (J2WX, jumper_set, 10, PV_RZRO) }, { YRDATA (J2WX, jumper_set, 10, PV_RZRO) },
{ ORDATA (DATOUT, data_out, 16), PV_RZRO | REG_A }, { ORDATA (DATOUT, data_out, 16), PV_RZRO | REG_X },
{ ORDATA (DATIN, data_in, 16), PV_RZRO | REG_A }, { ORDATA (DATIN, data_in, 16), PV_RZRO | REG_X },
{ FLDATA (DCOUT, device_command_out, 0) }, { FLDATA (DCOUT, device_command_out, 0) },
{ FLDATA (DFIN, device_flag_in, 0) }, { FLDATA (DFIN, device_flag_in, 0) },
@@ -1206,8 +1223,8 @@ static REG lp_reg [] = {
{ DRDATA (FORMLN, form_length, 8), PV_LEFT | REG_RO }, { DRDATA (FORMLN, form_length, 8), PV_LEFT | REG_RO },
{ BRDATA (TITLE, vfu_title, 8, 8, LINE_SIZE), REG_HRO }, { BRDATA (TITLE, vfu_title, 8, 8, LINE_SIZE), REG_HRO },
{ BRDATA (VFU, VFU, 2, VFU_WIDTH, VFU_SIZE), PV_RZRO | REG_RO }, { BRDATA (VFU, VFU, 2, VFU_WIDTH, VFU_SIZE), PV_RZRO | REG_RO },
{ ORDATA (PCHR, punched_char, 8), PV_RZRO | REG_A }, { ORDATA (PUNCHR, punched_char, 8), PV_RZRO | REG_A },
{ ORDATA (UPCHR, unpunched_char, 8), PV_RZRO | REG_A }, { ORDATA (UNPCHR, unpunched_char, 8), PV_RZRO | REG_A },
{ DRDATA (BTIME, fast_times.buffer_load, 24), PV_LEFT | REG_NZ }, { DRDATA (BTIME, fast_times.buffer_load, 24), PV_LEFT | REG_NZ },
{ DRDATA (PTIME, fast_times.print, 24), PV_LEFT | REG_NZ }, { DRDATA (PTIME, fast_times.print, 24), PV_LEFT | REG_NZ },
@@ -1795,7 +1812,7 @@ return SCPE_OK; /* return success */
Implementation notes: Implementation notes:
1. Calling "master_clear" with a FALSE parameter indicates that this is a 1. Calling "master_reset" with a FALSE parameter indicates that this is a
commanded reset. This allows the connected device-specific reset commanded reset. This allows the connected device-specific reset
routines to distinguish from a Programmed Master Clear. routines to distinguish from a Programmed Master Clear.
*/ */
@@ -1911,6 +1928,23 @@ return;
} }
/* Report a stream I/O error to the console.
If a stream I/O error has been detected, this routine will print an error
message to the simulation console and clear the stream's error indicator.
*/
static void report_error (FILE *stream)
{
cprintf ("%s simulator printer I/O error: %s\n", /* report the error to the console */
sim_name, strerror (errno));
clearerr (stream); /* clear the error */
return;
}
/* Set an interrupt. /* Set an interrupt.
The interrupt bit specified is set in the interrupt status word. If enabled, The interrupt bit specified is set in the interrupt status word. If enabled,
@@ -2491,11 +2525,12 @@ return outbound_signals; /* return INTREQ if any
conclude the handshake. conclude the handshake.
Control word bit 10 determines whether the code on the data out lines is Control word bit 10 determines whether the code on the data out lines is
interpreted as a character (0) or a format command (1). Character data is interpreted as a character (0) or a format command (1). If there is room in
loaded into the buffer; if the line length is exceeded, the printer the print buffer, the character is loaded. If not, then depending on the
automatically prints the buffer contents, advances the paper one line, and model, the printer either discards the character or automatically prints the
stores the new character in the empty buffer. If a control character is sent buffer contents, advances the paper one line, and stores the new character in
but the printer cannot print it, a space is loaded in its place. the empty buffer. If a control character is sent but the printer cannot
print it, a space is loaded in its place.
A format command causes the current buffer to be printed, and then the paper A format command causes the current buffer to be printed, and then the paper
is advanced by a prescribed amount. Two output modes are provided: compact is advanced by a prescribed amount. Two output modes are provided: compact
@@ -2545,14 +2580,18 @@ return outbound_signals; /* return INTREQ if any
Implementation notes: Implementation notes:
1. Because attached files are opened in binary mode, newline translation 1. When a paper-out condition is detected, the 2607 printer goes offline
only when the next top-of-form is reached. The 2613/17/18 printers go
offline as soon as the current line completes.
2. Because attached files are opened in binary mode, newline translation
(i.e., from LF to CR LF) is not performed by the host system. Therefore, (i.e., from LF to CR LF) is not performed by the host system. Therefore,
we write explicit CR LF pairs to end lines, even in compact mode, as we write explicit CR LF pairs to end lines, even in compact mode, as
required for fidelity to HP peripherals. If bare LFs are used by the required for fidelity to HP peripherals. If bare LFs are used by the
host system, the printer output file must be postprocessed to remove the host system, the printer output file must be postprocessed to remove the
CRs. CRs.
2. Overprinting in expanded mode is simulated by merging the lines in the 3. Overprinting in expanded mode is simulated by merging the lines in the
buffer. A format command to suppress spacing resets the buffer index but buffer. A format command to suppress spacing resets the buffer index but
saves the previous buffer length as a "high water mark" that will be saves the previous buffer length as a "high water mark" that will be
extended if the overlaying line is longer. This process may be repeated extended if the overlaying line is longer. This process may be repeated
@@ -2565,25 +2604,31 @@ return outbound_signals; /* return INTREQ if any
"overprint character" (which defaults to DEL, but can be changed by the "overprint character" (which defaults to DEL, but can be changed by the
user) replaces the character in the buffer. user) replaces the character in the buffer.
3. Printers that support 12-channel VFUs treat the VFU format command as 4. Printers that support 12-channel VFUs treat the VFU format command as
modulo 16. Printers that support 8-channel VFUs treat the command as modulo 16. Printers that support 8-channel VFUs treat the command as
modulo 8. modulo 8.
4. As a convenience to the user, the printer output file is flushed when a 5. As a convenience to the user, the printer output file is flushed when a
TOF operation is performed. TOF operation is performed. This permits inspection of the output file
from the SCP command prompt while output is ongoing.
5. The user may examine the TFAULT and PFAULT registers to determine why the 6. The user may examine the TFAULT and PFAULT registers to determine why the
printer went offline. printer went offline.
6. The transfer service may be called with a null pointer to update the 7. The transfer service may be called with a null pointer to update the
potential change in the flag state. potential change in the flag state.
7. If printing is attempted with the printer offline, this routine will be 8. If printing is attempted with the printer offline, this routine will be
called with STROBE asserted (device_command_in TRUE) and DEMAND denied called with STROBE asserted (device_command_in TRUE) and DEMAND denied
(device_flag_in TRUE). The printer ignores STROBE if DEMAND is not (device_flag_in TRUE). The printer ignores STROBE if DEMAND is not
asserted, so we simply return in this case. This will hang the handshake asserted, so we simply return in this case. This will hang the handshake
until the printer is set online, and we are reentered with DEMAND until the printer is set online, and we are reentered with DEMAND
asserted. asserted. As a consequence, explicit protection against "uptr->fileref"
being NULL is not required.
9. Explicit tests for lowercase and control characters are much faster and
are used rather than calls to "islower" and "iscntrl", which must
consider the current locale.
*/ */
static t_stat lp_service (UNIT *uptr) static t_stat lp_service (UNIT *uptr)
@@ -2828,14 +2873,11 @@ else if (device_flag_in == FALSE) { /* otherwise if STROBE h
slew_count, (slew_count == 1 ? "" : "s"), current_line); slew_count, (slew_count == 1 ? "" : "s"), current_line);
} }
if (ferror (uptr->fileref)) { /* if a host file system error occurred */ if (ferror (uptr->fileref)) { /* if a host file system error occurred */
cprintf ("%s simulator printer I/O error: %s\n", /* then report the error to the console */ report_error (uptr->fileref); /* then report the error to the console */
sim_name, strerror (errno));
clearerr (uptr->fileref); /* clear the error */ lp_set_alarm (uptr); /* set an alarm condition */
return SCPE_IOERR; /* and stop the simulator */
lp_set_alarm (uptr); /* set an alarm condition */
return SCPE_IOERR; /* and stop the simulator */
} }
} }
@@ -2849,7 +2891,7 @@ return SCPE_OK; /* return event service
equivalent of loading paper into the printer and pressing the ONLINE button. equivalent of loading paper into the printer and pressing the ONLINE button.
The transition from offline to online causes an interrupt. The transition from offline to online causes an interrupt.
A new image file may be requested by giving the "-N" switch to the attach A new image file may be requested by giving the "-N" switch to the ATTACH
command. If an existing file is specified with "-N", it will be cleared; if command. If an existing file is specified with "-N", it will be cleared; if
specified without "-N", printer output will be appended to the end of the specified without "-N", printer output will be appended to the end of the
existing file content. In all cases, the paper is positioned at the top of existing file content. In all cases, the paper is positioned at the top of
@@ -2869,7 +2911,7 @@ return SCPE_OK; /* return event service
static t_stat lp_attach (UNIT *uptr, CONST char *cptr) static t_stat lp_attach (UNIT *uptr, CONST char *cptr)
{ {
t_stat result = SCPE_OK; t_stat result;
result = attach_unit (uptr, cptr); /* attach the specified printer image file */ result = attach_unit (uptr, cptr); /* attach the specified printer image file */
@@ -2879,15 +2921,20 @@ if (result == SCPE_OK /* if the attach was suc
current_line = 1; /* reset the line counter to the top of the form */ current_line = 1; /* reset the line counter to the top of the form */
if (sim_switches & SWMASK ('N')) /* if a new (empty) file was requested */ if (fseek (uptr->fileref, 0, SEEK_END) == 0) { /* append by seeking to the end of the file */
uptr->pos = 0; /* then position at the start of the file */
else if (fseek (uptr->fileref, 0, SEEK_END) == 0) /* otherwise append by seeking to the end of the file */
uptr->pos = (t_addr) ftell (uptr->fileref); /* and repositioning if the seek succeeded */ uptr->pos = (t_addr) ftell (uptr->fileref); /* and repositioning if the seek succeeded */
dprintf (lp_dev, DEB_CMD, "Printer paper loaded\n"); dprintf (lp_dev, DEB_CMD, "Printer paper loaded\n");
lp_set_locality (uptr, Online); /* set the printer online */ lp_set_locality (uptr, Online); /* set the printer online */
}
else { /* otherwise a host file system error occurred */
report_error (uptr->fileref); /* so report the error to the console */
lp_set_alarm (uptr); /* set an alarm condition */
result = SCPE_IOERR; /* and report that the attached failed */
}
} }
paper_fault = FALSE; /* clear any existing paper fault */ paper_fault = FALSE; /* clear any existing paper fault */
@@ -2904,10 +2951,10 @@ return result; /* return the result of
/* Detach the printer image file. /* Detach the printer image file.
The specified file is detached from the indicated unit. This is the The specified file is detached from the indicated unit. This is the
simulation equivalent to unloading the paper from the printer or the printer simulation equivalent of running out of paper or unloading the paper from the
running out of paper. The out-of-paper condition cause a paper fault alarm, printer. The out-of-paper condition cause a paper fault alarm, and the
and the printer goes offline. The transition from online to offline causes printer goes offline. The transition from online to offline causes an
an interrupt. interrupt.
When the printer runs out of paper, it will not go offline until characters When the printer runs out of paper, it will not go offline until characters
present in the buffer are printed and paper motion stops. In addition, the present in the buffer are printed and paper motion stops. In addition, the
@@ -2916,7 +2963,10 @@ return result; /* return the result of
In simulation, entering a DETACH LP command while the printer is busy will In simulation, entering a DETACH LP command while the printer is busy will
defer the file detach until print operations reach the top of the next form defer the file detach until print operations reach the top of the next form
(2607) or until the current print operation completes (2613/17/18). (2607) or until the current print operation completes (2613/17/18). An
immediate detach may be forced by adding the -F switch to the DETACH command.
This simulates physically removing the paper from the printer and succeeds
regardless of the current printer state.
Implementation notes: Implementation notes:
@@ -2943,25 +2993,32 @@ if (uptr->flags & UNIT_ATTABLE) /* if we're being called
if ((uptr->flags & UNIT_ATT) == 0) /* then if the unit is not currently attached */ if ((uptr->flags & UNIT_ATT) == 0) /* then if the unit is not currently attached */
return SCPE_UNATT; /* then report it */ return SCPE_UNATT; /* then report it */
else if ((print_props [model].fault_at_eol /* otherwise if the printer faults at the end of any line */ else {
|| current_line == 1) /* or the printer is at the top of the form */ if (sim_switches & (SWMASK ('F') | SIM_SW_SHUT)) { /* if this is a forced detach or shut down request */
&& lp_set_alarm (uptr) /* and a paper alarm is accepted */ current_line = 1; /* then reset the printer to TOF to enable detaching */
|| (sim_switches & SIM_SW_SHUT)) { /* or this is a shutdown call */ sim_cancel (uptr); /* and terminate */
paper_fault = TRUE; /* then set the out-of-paper condition */ device_command_out = FALSE; /* any print action in progress */
}
dprintf (lp_dev, DEB_CMD, "Printer is out of paper\n"); if ((print_props [model].fault_at_eol /* otherwise if the printer faults at the end of any line */
|| current_line == 1) /* or the printer is at the top of the form */
&& lp_set_alarm (uptr)) { /* and a paper alarm is accepted */
paper_fault = TRUE; /* then set the out-of-paper condition */
return detach_unit (uptr); /* and detach the unit */ dprintf (lp_dev, DEB_CMD, "Printer is out of paper\n");
}
else { /* otherwise the alarm was rejected at this time */ return detach_unit (uptr); /* and detach the unit */
paper_fault = TRUE; /* so set the out-of-paper condition */ }
offline_pending = TRUE; /* but defer the detach */
dprintf (lp_dev, DEB_CMD, "Paper out request deferred until print completes\n"); else { /* otherwise the alarm was rejected at this time */
paper_fault = TRUE; /* so set the out-of-paper condition */
offline_pending = TRUE; /* but defer the detach */
cputs ("Command deferred\n"); /* but the actual detach must be deferred */ dprintf (lp_dev, DEB_CMD, "Paper out request deferred until print completes\n");
return SCPE_OK; /* until the buffer prints */
cprintf ("%s\n", sim_error_text (SCPE_INCOMP)); /* report that the actual detach must be deferred */
return SCPE_OK; /* until the buffer has been printed */
}
} }
else /* otherwise */ else /* otherwise */
@@ -3018,7 +3075,7 @@ switch ((DEVICE_MODES) value) { /* dispatch the mode to
break; break;
} }
return SCPE_OK; /* the mode change succeeds */ return SCPE_OK; /* mode changes always succeed */
} }
@@ -3033,7 +3090,7 @@ return SCPE_OK; /* the mode change succe
static t_stat lp_set_model (UNIT *uptr, int32 value, CONST char *cptr, void *desc) static t_stat lp_set_model (UNIT *uptr, int32 value, CONST char *cptr, void *desc)
{ {
if (lp_dev.flags & DEV_REALTIME) /* if the printer is in real-time mode */ if (lp_dev.flags & DEV_REALTIME) /* if the printer is in real-time mode */
dlyptr = &real_times [GET_MODEL (uptr->flags)]; /* then use the times for the new model */ dlyptr = &real_times [GET_MODEL (value)]; /* then use the times for the new model */
return SCPE_OK; /* allow the reassignment to proceed */ return SCPE_OK; /* allow the reassignment to proceed */
} }
@@ -3044,26 +3101,29 @@ return SCPE_OK; /* allow the reassignmen
This validation routine is called to set the printer online or offline. The This validation routine is called to set the printer online or offline. The
"value" parameter is UNIT_OFFLINE if the printer is going offline and is zero "value" parameter is UNIT_OFFLINE if the printer is going offline and is zero
if the printer is going online. This simulates pressing the ON/OFFLINE if the printer is going online. This simulates pressing the ON/OFFLINE
button on the printer. button on the printer. The unit must be attached (i.e., paper must be
loaded), before the printer may be set online or offline.
If the printer is being taken offline, the buffer is checked to see if any If the printer is being taken offline, the buffer is checked to see if any
characters are present. If they are, or if the printer unit is currently characters are present. If they are, or if the printer unit is currently
scheduled (i.e., executing a print operation), the offline request is scheduled (i.e., executing a print operation), the offline request is
deferred until printing completes, and the routine prints "Command deferred" deferred until printing completes, and the routine returns "Command not
to inform the user. Otherwise, the unit is set offline, DEMAND is denied, complete" status to inform the user. Otherwise, the unit is set offline,
and DEV END is asserted to indicate that the printer is not ready. DEMAND is denied, and DEV END is asserted to indicate that the printer is not
// ready.
As a special case, a detach (out-of-paper condition) that has been deferred
until printing completes may be cancelled by setting the printer online.
If the printer is being put online, the unit must be attached (i.e., paper If the printer is being put online and paper is present, the unit is set
must be loaded), or the command is rejected. If paper is present, the unit online, and any paper or tape fault present is cleared. If the sequencer
is set online, and any tape fault present is cleared. If the sequencer
indicates an incomplete handshake, as would occur if paper ran out while indicates an incomplete handshake, as would occur if paper ran out while
printing, the transfer service is called to complete the handshake by printing, the transfer service is called to complete the handshake by
asserting DEMAND. Otherwise, DEMAND is asserted explicitly, and DEV END is asserting DEMAND. Otherwise, DEMAND is asserted explicitly, and DEV END is
denied. denied.
As a special case, a detach (out-of-paper condition) or offline request that
has been deferred until printing completes may be cancelled by setting the
printer online. No other action is taken, because the printer has never
transitioned to the offline state.
Transitions between the offline and online state cause interrupts, and INTREQ Transitions between the offline and online state cause interrupts, and INTREQ
is asserted to the IOP if a transition occurred (but not, e.g., for a SET LP is asserted to the IOP if a transition occurred (but not, e.g., for a SET LP
OFFLINE command where the printer is already offline). OFFLINE command where the printer is already offline).
@@ -3071,9 +3131,9 @@ return SCPE_OK; /* allow the reassignmen
Implementation notes: Implementation notes:
1. Because a deferred offline request is not fatal, we return SCPE_OK to 1. Although a deferred offline request is not fatal, we return SCPE_INCOMP
allow command files to continue to execute, but we print a warning to the to prevent "set_cmd" from setting the UNIT_OFFLINE bit in the unit flags
user. before the printer actually goes offline.
*/ */
static t_stat lp_set_on_offline (UNIT *uptr, int32 value, CONST char *cptr, void *desc) static t_stat lp_set_on_offline (UNIT *uptr, int32 value, CONST char *cptr, void *desc)
@@ -3091,8 +3151,8 @@ else if (value == UNIT_ONLINE) /* otherwise if this is
lp_set_locality (uptr, Online); /* so set the printer online */ lp_set_locality (uptr, Online); /* so set the printer online */
else if (lp_set_locality (uptr, Offline) == FALSE) { /* otherwise if it cannot be set offline now */ else if (lp_set_locality (uptr, Offline) == FALSE) { /* otherwise if it cannot be set offline now */
cputs ("Command deferred\n"); /* then let the user know */
dprintf (lp_dev, DEB_CMD, "Offline request deferred until print completes\n"); dprintf (lp_dev, DEB_CMD, "Offline request deferred until print completes\n");
return SCPE_INCOMP; /* then let the user know */
} }
return SCPE_OK; /* return operation success */ return SCPE_OK; /* return operation success */
@@ -3189,8 +3249,8 @@ static t_stat lp_show_vfu (FILE *st, UNIT *uptr, int32 value, CONST void *desc)
static const char header_1 [] = " Ch 1 Ch 2 Ch 3 Ch 4 Ch 5 Ch 6 Ch 7 Ch 8 Ch 9 Ch10 Ch11 Ch12"; static const char header_1 [] = " Ch 1 Ch 2 Ch 3 Ch 4 Ch 5 Ch 6 Ch 7 Ch 8 Ch 9 Ch10 Ch11 Ch12";
static const char header_2 [] = " ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----"; static const char header_2 [] = " ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----";
const PRINTER_TYPE model = GET_MODEL (uptr->flags); const PRINTER_TYPE model = GET_MODEL (uptr->flags); /* the printer model number */
const uint32 channel_count = print_props [model].vfu_channels; const uint32 channel_count = print_props [model].vfu_channels; /* the count of VFU channels */
uint32 chan, line, current_channel; uint32 chan, line, current_channel;
if (value == 0) /* if we're called for a summary display */ if (value == 0) /* if we're called for a summary display */
@@ -3328,8 +3388,8 @@ return NO_SIGNALS; /* no special control ac
This routine is called when an alarm condition exists. An alarm occurs when This routine is called when an alarm condition exists. An alarm occurs when
paper is out (paper fault) or a VFU command addresses a channel that does not paper is out (paper fault) or a VFU command addresses a channel that does not
contain a punch (tape fault). In response, the printer goes not ready and contain a punch (tape fault). In response, the printer goes offline and,
offline. for all models except the 2607, becomes not-ready.
On entry, the routine attempts to set the printer offline. If this succeeds, On entry, the routine attempts to set the printer offline. If this succeeds,
the printer is set not-ready. If it fails (for reasons explained in the the printer is set not-ready. If it fails (for reasons explained in the
@@ -3430,9 +3490,8 @@ dprintf (lp_dev, DEB_CMD, "Printer set %s\n",
if (signals & INTREQ) /* if the transition caused an interrupt */ if (signals & INTREQ) /* if the transition caused an interrupt */
iop_assert_INTREQ (&lp_dib); /* then assert the INTREQ signal */ iop_assert_INTREQ (&lp_dib); /* then assert the INTREQ signal */
offline_pending = FALSE; offline_pending = FALSE; /* the operation completed */
return TRUE; /* successfully */
return TRUE;
} }
@@ -3442,8 +3501,8 @@ return TRUE;
associated with the stream "vf" or with the standard 66-line tape if the associated with the stream "vf" or with the standard 66-line tape if the
stream is NULL. The "uptr" parameter points to the printer unit. stream is NULL. The "uptr" parameter points to the printer unit.
The standard VFU tape (1535-2655 for the 8-channel HP 2607 and 2613-80001 for The standard VFU tape (02607-80024 for the 8-channel HP 2607 and 02613-80001
the 12-channel HP 2613, 2617, and 2618) defines the channels as: for the 12-channel HP 2613, 2617, and 2618) defines the channels as:
Chan Description Chan Description
---- -------------- ---- --------------
@@ -3457,12 +3516,12 @@ return TRUE;
8 Sixth page 8 Sixth page
9 Bottom of form 9 Bottom of form
...with channels 10-12 uncommitted. A custom tape must dedicate channel 1 to ...with channels 10-12 uncommitted.
the top-of-form, but the other channels may be defined as desired.
A custom tape file starts with a VFU definition line and then contains one A custom tape file starts with a VFU definition line and then contains one
channel-definition line for each line of the form. The number of lines channel-definition line for each line of the form. The number of lines
establishes the form length. establishes the form length. Channel 1 must be dedicated to the top-of-form,
but the other channels may be defined as desired.
A semicolon appearing anywhere on a line begins a comment, and the semicolon A semicolon appearing anywhere on a line begins a comment, and the semicolon
and all following characters are ignored. Zero-length lines, including lines and all following characters are ignored. Zero-length lines, including lines
@@ -3542,7 +3601,7 @@ return TRUE;
static t_stat lp_load_vfu (UNIT *uptr, FILE *vf) static t_stat lp_load_vfu (UNIT *uptr, FILE *vf)
{ {
const PRINTER_TYPE model = GET_MODEL (uptr->flags); /* get the printer type */ const PRINTER_TYPE model = GET_MODEL (uptr->flags); /* the printer model number */
uint32 line, channel, vfu_status; uint32 line, channel, vfu_status;
int32 len; int32 len;
char buffer [LINE_SIZE], punch [LINE_SIZE], no_punch; char buffer [LINE_SIZE], punch [LINE_SIZE], no_punch;
@@ -3550,10 +3609,8 @@ char *bptr, *tptr;
uint16 tape [VFU_SIZE] = { 0 }; uint16 tape [VFU_SIZE] = { 0 };
if (vf == NULL) { /* if the standard VFU is requested */ if (vf == NULL) { /* if the standard VFU is requested */
strcpy (vfu_title, "Standard VFU"); /* then set the title */ tape [ 1] = VFU_CHANNEL_1; /* then punch channel 1 for the top of form */
tape [60] = VFU_CHANNEL_2 | VFU_CHANNEL_9; /* and channels 2 and 9 for the bottom of form */
tape [ 1] = VFU_CHANNEL_1; /* punch channel 1 for the top of form */
tape [60] = VFU_CHANNEL_2 | VFU_CHANNEL_9; /* punch channels 2 and 9 for the bottom of form */
for (line = 1; line <= 60; line++) { /* load each of the 60 printable lines */ for (line = 1; line <= 60; line++) { /* load each of the 60 printable lines */
tape [line] |= VFU_CHANNEL_3 /* punch channel 3 for single space */ tape [line] |= VFU_CHANNEL_3 /* punch channel 3 for single space */
@@ -3567,6 +3624,7 @@ if (vf == NULL) { /* if the standard VFU i
} }
form_length = 66; /* set the form length */ form_length = 66; /* set the form length */
strcpy (vfu_title, "Standard VFU"); /* and set the title */
} }
else { /* otherwise load a custom VFU from the file */ else { /* otherwise load a custom VFU from the file */
@@ -3690,12 +3748,9 @@ while (len == 0) {
if (feof (vf)) /* then if the end of file was seen */ if (feof (vf)) /* then if the end of file was seen */
return 0; /* then return an EOF indication */ return 0; /* then return an EOF indication */
else { /* otherwise report the error to the console */ else { /* otherwise */
cprintf ("%s simulator line printer I/O error: %s\n", report_error (vf); /* report the error to the console */
sim_name, strerror (errno)); return -1; /* and return an error indication */
clearerr (vf); /* clear the error */
return -1; /* and return an error indication */
} }
len = strlen (line); /* get the current line length */ len = strlen (line); /* get the current line length */

View File

@@ -1,6 +1,6 @@
/* hp3000_ms.c: HP 3000 30215A Magnetic Tape Controller Interface simulator /* hp3000_ms.c: HP 3000 30215A Magnetic Tape Controller Interface simulator
Copyright (c) 2016, J. David Bryan Copyright (c) 2016-2017, J. David Bryan
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@@ -25,6 +25,7 @@
MS HP 30215A Magnetic Tape Controller Interface MS HP 30215A Magnetic Tape Controller Interface
05-Sep-17 JDB Changed REG_A (permit any symbolic override) to REG_X
12-Sep-16 JDB Changed DIB register macro usage from SRDATA to DIB_REG 12-Sep-16 JDB Changed DIB register macro usage from SRDATA to DIB_REG
09-Jun-16 JDB Added casts for ptrdiff_t to int32 values 09-Jun-16 JDB Added casts for ptrdiff_t to int32 values
08-Jun-16 JDB Corrected %d format to %u for unsigned values 08-Jun-16 JDB Corrected %d format to %u for unsigned values
@@ -514,7 +515,7 @@ static REG ms_reg [] = {
{ FLDATA (UINTRP, unit_interrupt, 0) }, { FLDATA (UINTRP, unit_interrupt, 0) },
{ FLDATA (DEVEND, device_end, 0) }, { FLDATA (DEVEND, device_end, 0) },
{ FLDATA (XFRERR, xfer_error, 0) }, { FLDATA (XFRERR, xfer_error, 0) },
{ ORDATA (BUFWRD, buffer_word, 16), REG_A | REG_FIT | PV_RZRO }, { ORDATA (BUFWRD, buffer_word, 16), REG_X | REG_FIT | PV_RZRO },
{ DRDATA (ATUNIT, attention_unit, 16), REG_FIT | PV_LEFT }, { DRDATA (ATUNIT, attention_unit, 16), REG_FIT | PV_LEFT },
{ DRDATA (CLASS, command_class, 4), PV_LEFT }, { DRDATA (CLASS, command_class, 4), PV_LEFT },
{ YRDATA (FLAGS, flags, 8, PV_RZRO) }, { YRDATA (FLAGS, flags, 8, PV_RZRO) },

View File

@@ -1,6 +1,6 @@
SIMH/HP 3000 RELEASE NOTES SIMH/HP 3000 RELEASE NOTES
========================== ==========================
Last update: 2017-04-30 Last update: 2018-01-12
This file documents the release history of the Hewlett-Packard 3000 simulator. This file documents the release history of the Hewlett-Packard 3000 simulator.
@@ -47,7 +47,7 @@ General Information
The simulator passes the HP 32230 offline diagnostic suite with some expected The simulator passes the HP 32230 offline diagnostic suite with some expected
failures due to unimplemented features. For example, the disc diagnostic failures due to unimplemented features. For example, the disc diagnostic
error-correction logic tests and the tape diagnostic CRCC and LRCC tests fail, error-correction logic tests and the tape diagnostic CRCC and LRCC tests fail,
as these features are not supported. However, all features that are required as these features are not simulated. However, all features that are required
for MPE operation pass their respective diagnostic tests. for MPE operation pass their respective diagnostic tests.
The simulator has been tested with MPE-V/R version E.01.00. Specifically: The simulator has been tested with MPE-V/R version E.01.00. Specifically:
@@ -176,6 +176,180 @@ the MPE version used:
=====================
Release 7, 2018-01-12
=====================
This release of the HP 3000 simulator adds the following features:
- Reading and writing to terminal sessions connected to the ATC have been
improved significantly. File uploads via Telnet using the Reflection
terminal emulator are now over 100 times faster than before, e.g., the
transfer time for a one-megabyte file has decreased from 69 minutes to 30
seconds. Block mode reads show similar speed improvements. Copy-and-paste
into the terminal window, Reflection file downloads, and output to the
terminal window in REMOTEACK mode show speed improvements of five to fifteen
times. Output in LOCALACK mode has been improved by around 50%.
- Information regarding Reflection file transfers and serial port disconnection
options has been added to Section 4.1.1, "Terminal Data Interface," of the HP
3000 Simulator User's Guide.
--------------------
Implementation Notes
--------------------
- File transfer using the Reflection terminal emulator requires an 8-bit data
path. To achieve this, the session must use MPE terminal type 12 (this may
be configured either during a system reload or by specifying the TERM=12
parameter when logging on with :HELLO), and the channel must be set to 8B,
REMOTEACK, and NOCAPSLOCK modes. Note that MPE's default terminal type 10
writes 7-bit data with odd parity, and characters with the parity bit on may
be displayed by the terminal emulator as extended characters in the Roman-8
symbol set. To avoid a garbled display when using the TERM=12 parameter to
override the default, the channel should be set to 8B mode after logging on
and back to 7B after logging off.
- The MPE-V/R software kit has been updated to increase the number of terminal
buffers per port from 3 to 5. Using the default of 3 may cause the system
to report "MPE Table TBUF has overflowed!!!" to the system console while
performing Reflection file uploads.
----------
Bugs Fixed
----------
1. PROBLEM: Serial port output stalls are not handled properly.
VERSION: Release 6.
OBSERVATION: The ATCD device supports I/O via host serial ports as well as
via Telnet connections. While output via Telnet works correctly, output
via serial ports fails. Attempting to output to the ATCD results in a few
characters written, and then the line hangs. Sometimes pressing ENTER at
the system console (ATCD channel 0) causes a few more characters to appear
on the serial terminal. Eventually, the line hangs permanently.
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. If the library output routine
receives the second character before the first one has been written to the
serial port, it returns SCPE_STALL status to indicate a buffer overflow.
The ATCD simulation correctly responds to this status by rescheduling the
output attempt. However, it fails to call the "tmxr_poll_tx" routine to
write to the serial port, so the rescheduled attempt fails as well.
RESOLUTION: Modify "line_service" (hp3000_atc.c) to call "tmxr_poll_tx" if
a buffer overflow occurs.
STATUS: Fixed in Release 7.
=====================
Release 6, 2017-09-07
=====================
This release of the HP 3000 simulator adds the following features:
- The new "-F" switch to the DETACH LP command forces an immediate detach,
regardless of the current paper position. This is the simulation equivalent
of physically removing the paper from the printer. Without the switch,
detaching is the equivalent of running out of paper, which permits printing
to continue to the end of the line (2613/17/18) or the page (2607) before the
printer goes offline.
- The HP 3000 Simulator User's Guide has been revised to add a new section
describing the simulator commands corresponding to hardware actions and to
rewrite the "Realistic, Calibrated, and Optimized Timing" section to describe
the three timing modes more clearly.
--------------------
Implementation Notes
--------------------
- The LP device's PCHR (punched channel character) and UPCHR (unpunched channel
character) registers have been renamed to PUNCHR and UNPCHR, respectively,
for compatibility with the HP 2100 simulator's LPT device.
- The manual clarifies that the display radix for shift counts, bit positions,
starting bits and counts, and the CIR values for the PAUS and HALT
instructions may be overridden with command-line switches.
----------
Bugs Fixed
----------
1. PROBLEM: Cancelling a deferred detach with ATTACH LP is rejected.
VERSION: Release 5.
OBSERVATION: The line printer "Unit Options" section of the HP 3000
Simulator User's Guide states that a DETACH LP command will be deferred if
there are characters in the print buffer. It further states that entering
ATTACH LP without specifying a filename will cancel the action. This does
not work. Entering ATTACH LP prints "Too few arguments" and does not alter
a pending detach.
CAUSE: The SCP routine "attach_cmd" checks for the presence of a filename
before calling the line printer simulator's "lp_attach" routine. If the
filename is omitted, "lp_attach" is never called to cancel the pending
detach.
RESOLUTION: Modify "lp_set_on_offline" (hp3000_lp.c) to cancel a deferred
detach, and modify the User's Guide to state that SET LP ONLINE is used to
cancel both the deferred offline and deferred detach actions.
STATUS: Fixed in Release 6.
2. PROBLEM: Changing printer models does not change the REALTIME delays.
VERSION: Release 5.
OBSERVATION: In REALTIME mode, the line printer simulator attempts to
model the print buffer load and print-and-space operation delays inherent
in the physical hardware. However, after setting a different model, the
buffer load, print, and paper advance times have not been changed.
CAUSE: The "lp_set_model" routine that is called in response to a "SET
LP <model>" command sets the realistic times to those of the current model
rather than those of the new model.
RESOLUTION: Modify "lp_set_model" (hp3000_lp.c) to use the new model value
to index into the realistic times array.
STATUS: Fixed in Release 6.
3. PROBLEM: Paper cannot be removed from a 2607 printer except at the TOF.
VERSION: Release 5.
OBSERVATION: Printing a few lines on a 2607 and then attempting to remove
the paper with the DETACH LP command displays "Command not completed" on
the simulation console. The file remains attached and therefore cannot be
manipulated externally.
CAUSE: The DETACH command simulates both running out of paper and removing
the paper from the printer. For the former, the 2607 continues to print
until the current form is complete (i.e., the top of what would be the next
form is reached). For the latter, the paper may be physically removed by
the operator while at any print position. The simulator incorrectly
forbids the latter operation unless the paper is positioned at the TOF.
RESOLUTION: Modify "lp_detach" (hp3000_lp.c) to add a "forced detach"
option ("DETACH -F LP") to detach the printer regardless of print position.
STATUS: Fixed in Release 6.
===================== =====================
Release 5, 2017-04-30 Release 5, 2017-04-30
===================== =====================

View File

@@ -1,6 +1,6 @@
/* hp3000_sel.c: HP 3000 30030C Selector Channel simulator /* hp3000_sel.c: HP 3000 30030C Selector Channel simulator
Copyright (c) 2016, J. David Bryan Copyright (c) 2016-2017, J. David Bryan
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@@ -25,6 +25,7 @@
SEL HP 3000 Series III Selector Channel SEL HP 3000 Series III Selector Channel
05-Sep-17 JDB Changed REG_A (permit any symbolic override) to REG_X
10-Oct-16 JDB Renumbered debug flags to start at 0 10-Oct-16 JDB Renumbered debug flags to start at 0
Added port_read_memory, port_write_memory macros Added port_read_memory, port_write_memory macros
11-Jul-16 JDB Change "sel_unit" from a UNIT to an array of one UNIT 11-Jul-16 JDB Change "sel_unit" from a UNIT to an array of one UNIT
@@ -458,8 +459,8 @@ static REG sel_reg [] = {
{ ORDATA (CNBUF, control_buffer, 16), REG_FIT }, { ORDATA (CNBUF, control_buffer, 16), REG_FIT },
{ ORDATA (ADDR, address_word, 16), REG_FIT }, { ORDATA (ADDR, address_word, 16), REG_FIT },
{ ORDATA (ADBUF, address_buffer, 16), REG_FIT }, { ORDATA (ADBUF, address_buffer, 16), REG_FIT },
{ ORDATA (INBUF, input_buffer, 16), REG_A | REG_FIT }, { ORDATA (INBUF, input_buffer, 16), REG_X | REG_FIT },
{ ORDATA (OUTBUF, output_buffer, 16), REG_A | REG_FIT }, { ORDATA (OUTBUF, output_buffer, 16), REG_X | REG_FIT },
{ NULL } { NULL }
}; };

View File

@@ -23,6 +23,9 @@
in advertising or otherwise to promote the sale, use or other dealings in in advertising or otherwise to promote the sale, use or other dealings in
this Software without prior written authorization from the author. this Software without prior written authorization from the author.
05-Sep-17 JDB Removed the -B (binary display) option; use -2 instead
Rewrote "fprint_sym" for better coverage
11-May-17 JDB Corrected comment in "fprint_value"
28-Apr-17 JDB Added void cast to "fprint_instruction" call for left stackop 28-Apr-17 JDB Added void cast to "fprint_instruction" call for left stackop
03-Mar-17 JDB Added an implementation note to the "parse_sym" routine 03-Mar-17 JDB Added an implementation note to the "parse_sym" routine
29-Dec-16 JDB Changed the switch for STA format from -S to -T; 29-Dec-16 JDB Changed the switch for STA format from -S to -T;
@@ -33,7 +36,7 @@
27-Sep-16 JDB Added COBOL firmware mnemonics 27-Sep-16 JDB Added COBOL firmware mnemonics
Modified "fprint_instruction" to handle two-word instructions Modified "fprint_instruction" to handle two-word instructions
15-Sep-16 JDB Modified "one_time_init" to set aux_cmds "message" field 15-Sep-16 JDB Modified "one_time_init" to set aux_cmds "message" field
03-Sep-16 JDB Added the STOP_POWER and STOP_ARSINH messages 03-Sep-16 JDB Added the STOP_POWER and STOP_ARSINH status messages
01-Sep-16 JDB Moved the "hp_cold_cmd" routine to the CPU (as "cpu_cold_cmd") 01-Sep-16 JDB Moved the "hp_cold_cmd" routine to the CPU (as "cpu_cold_cmd")
Added the POWER command Added the POWER command
03-Aug-16 JDB Improved "fmt_char" and "fmt_bitset" to allow multiple calls 03-Aug-16 JDB Improved "fmt_char" and "fmt_bitset" to allow multiple calls
@@ -100,6 +103,26 @@ extern DEVICE ms_dev; /* 7970 Magnetic Tape */
#define SCPE_OK_3_WORDS ((t_stat) -2) /* three words produced or consumed */ #define SCPE_OK_3_WORDS ((t_stat) -2) /* three words produced or consumed */
/* Symbolic mode and format override switches */
#define A_SWITCH SWMASK ('A')
#define B_SWITCH SWMASK ('B')
#define C_SWITCH SWMASK ('C')
#define D_SWITCH SWMASK ('D')
#define E_SWITCH SWMASK ('E')
#define H_SWITCH SWMASK ('H')
#define I_SWITCH SWMASK ('I')
#define M_SWITCH SWMASK ('M')
#define O_SWITCH SWMASK ('O')
#define T_SWITCH SWMASK ('T')
#define MODE_SWITCHES (C_SWITCH | E_SWITCH | I_SWITCH | M_SWITCH | T_SWITCH)
#define FORMAT_SWITCHES (A_SWITCH | B_SWITCH | D_SWITCH | H_SWITCH | O_SWITCH)
#define SYMBOLIC_SWITCHES (MODE_SWITCHES | A_SWITCH) /* -A is both a mode and a format switch */
#define ALL_SWITCHES (MODE_SWITCHES | FORMAT_SWITCHES)
/* Address parsing configuration flags */ /* Address parsing configuration flags */
typedef enum { typedef enum {
@@ -952,7 +975,7 @@ static t_stat hp_brk_cmd (int32 arg, CONST char *buf);
/* System interface local utility routines */ /* System interface local utility routines */
static void fprint_value (FILE *ofile, t_value val, uint32 radix, uint32 width, uint32 format); static t_stat fprint_value (FILE *ofile, t_value val, uint32 radix, uint32 width, uint32 format);
static t_stat fprint_order (FILE *ofile, t_value *val, uint32 radix); static t_stat fprint_order (FILE *ofile, t_value *val, uint32 radix);
static t_stat fprint_subop (FILE *ofile, t_value *val, uint32 radix, t_addr addr, int32 switches); static t_stat fprint_subop (FILE *ofile, t_value *val, uint32 radix, t_addr addr, int32 switches);
static t_stat fprint_instruction (FILE *ofile, const OP_TABLE ops, t_value *val, static t_stat fprint_instruction (FILE *ofile, const OP_TABLE ops, t_value *val,
@@ -1177,58 +1200,85 @@ return SCPE_ARG; /* return an error if ca
/* Print a value in symbolic format. /* Print a value in symbolic format.
Print the data value in the format specified by the optional switches on the This routine prints a data value in the format specified by the optional
output stream supplied. This routine is called to print: switches on the output stream provided. On entry, "ofile" is the opened
output stream, and the other parameters depend on the reason the routine was
called, as follows:
- the next instruction mnemonic when the simulator stops * To print the next instruction mnemonic when the simulator stops:
- the result of EXAMining a register marked with a user flag - addr = the program counter
- the result of EXAMining a memory address - val = a pointer to sim_eval [0]
- the result of EVALuating a symbol - uptr = NULL
- sw = "-M" | SIM_SW_STOP
On entry, "ofile" is the opened output stream, "addr" is respectively the * To print the result of EXAMining a register with REG_VMIO or a user flag:
program counter, register radix and flags, memory address, or symbol index, - addr = the ORed register radix and user flags
"val" is a pointer to an array of t_values of depth "sim_emax" representing - val = a pointer to a single t_value
the value to be printed, "uptr" is respectively NULL, NULL, a pointer to the - uptr = NULL
named unit, or a pointer to the default unit, and "sw" contains any switches - sw = the command line switches | SIM_SW_REG
passed on the command line. "sw" also includes SIM_SW_STOP for a simulator
stop call or SIM_SW_REG for a register call. * To print the result of EXAMining a memory address:
- addr = the memory address
- val = a pointer to sim_eval [0]
- uptr = a pointer to the named unit
- sw = the command line switches
* To print the result of EVALuating a symbol:
- addr = the symbol index
- val = a pointer to sim_eval [addr]
- uptr = a pointer to the default unit (cpu_unit)
- sw = the command line switches
On exit, a status code is returned to the caller. If the format requested is On exit, a status code is returned to the caller. If the format requested is
not supported, SCPE_ARG status is returned, which causes the caller to print not supported, SCPE_ARG status is returned, which causes the caller to print
the value in numeric format. Otherwise, SCPE_OK status is returned if a the value in numeric format with the default radix. Otherwise, SCPE_OK
single-word value was consumed, or the negative number of extra words (beyond status is returned if a single-word value was consumed, or the negative
the first) consumed in printing the symbol is returned. For example, number of extra words (beyond the first) consumed in printing the symbol is
printing a two-word symbol would return SCPE_OK_2_WORDS (= -1). returned. For example, printing a two-word symbol would return
SCPE_OK_2_WORDS (= -1).
The following symbolic formats are supported by the listed switches: The following symbolic modes are supported by including the indicated
switches on the command line:
Switch Interpretation Switch Display Interpretation
------ -------------------------------------------------- ------ --------------------------------------------------
-a a single character in the right-hand byte -A a single character in the right-hand byte
-b a 16-bit binary value -C a two-character packed string
-c a two-character packed string -E an EDIT instruction subprogram mnemonic
-e an EDIT instruction subprogram mnemonic -ER an EDIT mnemonic starting with the right-hand byte
-i an I/O program instruction mnemonic -I an I/O program instruction mnemonic
-m a CPU instruction mnemonic -M a CPU instruction mnemonic
-s a CPU status mnemonic -T a CPU status mnemonic
-o override numeric output to octal In the absence of a mode switch, the value is displayed in a numeric format.
-d override numeric output to decimal
-h override numeric output to hex
-r begin EDIT interpretation with the right-hand byte
Memory may be displayed in any format. All registers may be overridden to When displaying data in one of the mnemonic modes, an additional switch may
display in octal, decimal, or hexadecimal numeric format. Only registers be specified to indicate the desired operand format, as follows:
marked with the REG_A flag may be displayed in any format. Registers marked
with REG_B may be displayed in binary format. Registers marked with REG_M
will default to CPU instruction mnemonic display. Registers marked with
REG_T will default to CPU status mnemonic display.
When displaying mnemonics, operand values are displayed in a radix suitable Switch Operand Interpretation
to the type of the value. Address values are displayed in the CPU's address ------ --------------------------------------------------
radix, which is octal, and data values are displayed in the CPU's data radix, -A a single character in the right-hand byte
which defaults to octal but may be set to a different radix or overridden by -B a binary value
a switch on the command line. -O an octal value
-D a decimal value
-H a hexadecimal value
Except for -B, these switches may be used without a mode switch to display a
numeric value in the specified form. To summarize, the valid switch
combinations are:
-A
-C
-E [ -R ] [ -A | -B | -O | -D | -H ]
-I [ -A | -B | -O | -D | -H ]
-M [ -A | -B | -O | -D | -H ]
-T [ -A | -B | -O | -D | -H ]
When displaying mnemonics, operand values by default are displayed in a radix
suitable to the type of the value. Address values are displayed in the CPU's
address radix, which is octal, and data values are displayed in the CPU's
data radix, which defaults to octal but may be set to a different radix or
overridden by a switch on the command line.
Implementation notes: Implementation notes:
@@ -1241,76 +1291,116 @@ return SCPE_ARG; /* return an error if ca
2. Displaying a register having a symbolic default format (e.g., CIR) will 2. Displaying a register having a symbolic default format (e.g., CIR) will
use the default unless the radix is overridden on the command line. For use the default unless the radix is overridden on the command line. For
example, "EXAMINE CIR" displays the CIR value as an instruction mnemonic, example, "EXAMINE CIR" displays the CIR value as an instruction mnemonic,
whereas "EXAMINE -O CIR" displays the value as octal. Adding "-M" will whereas "EXAMINE -D CIR" displays the value as decimal. Adding "-M" will
force mnemonic display and allow the radix switch to override the operand force mnemonic display and allow the radix switch to override the operand
display. For example, "EXAMINE -M -O CIR" displays the value as mnemonic display. For example, "EXAMINE -M -D CIR" displays the value as mnemonic
and overrides the operand radix to octal. and overrides the operand radix to decimal.
3. We return SCPE_INVSW when multiple modes or formats are specified, but
the callers do not act on this; they use the fallback formatter if any
status error is returned. We could work around this by printing "Invalid
switch" to the console and returning SCPE_OK, but this does not stop
IEXAMINE from prompting for the replacement value(s) or EXAMINE from
printing a range.
4. Radix switches and the -C switch are conceptually mutually exclusive.
However, if we return an error when "format" is non-zero, then -C will be
ignored, and the fallback formatter will use the radix switch. The other
choice is to process -C and ignore the radix switch; this is the option
implemented.
5. Because -A is both a mode and a format switch, we must check its presence
using SYMBOLIC_SWITCHES separately from the other modes to allow (e.g.)
both "EXAMINE -A" and "EXAMINE -M -A". If -A is added to MODE_SWITCHES,
the latter form would be rejected as having conflicting modes.
6. The penultimate condition of the multiway "if-else if" mode test checks
for no mode switches. This succeeds when -A is specified alone because
the earlier SYMBOLIC_SWITCHES test failed (so -A is present), but none of
the other mode switches are present.
*/ */
t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, UNIT *uptr, int32 sw) t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val, UNIT *uptr, int32 sw)
{ {
const t_bool is_reg = (sw & SIM_SW_REG) != 0; /* TRUE if this is a register access */ int32 formats, modes;
uint32 radix_override; uint32 radix;
if (sw & SWMASK ('A') && (!is_reg || addr & REG_A)) /* if ASCII character display is requested and permitted */ if ((sw & (SIM_SW_REG | ALL_SWITCHES)) == SIM_SW_REG) /* if we are formatting a register without overrides */
if (val [0] <= D8_SMAX) { /* then if the value is a single character */ if (addr & REG_A) /* then if the default format is character */
fputs (fmt_char ((uint32) val [0]), ofile); /* then format and print it */ sw |= A_SWITCH; /* then set the -A switch */
return SCPE_OK;
}
else /* otherwise */ else if (addr & REG_C) /* otherwise if the default mode is string */
return SCPE_ARG; /* report that it cannot be displayed */ sw |= C_SWITCH; /* then set the -C switch */
else if (sw & SWMASK ('C') && (!is_reg || addr & REG_A)) { /* if ASCII string display is requested and permitted */ else if (addr & REG_M) /* otherwise if the default mode is instruction mnemonic */
fputs (fmt_char (UPPER_BYTE (val [0])), ofile); /* then format and print the upper byte */ sw |= M_SWITCH; /* then set the -M switch */
fputc (',', ofile); /* followed by a separator */
fputs (fmt_char (LOWER_BYTE (val [0])), ofile); /* then format and print the lower byte */ else if (addr & REG_T) /* otherwise if the default mode is status */
sw |= T_SWITCH; /* then set the -T switch */
if ((sw & SYMBOLIC_SWITCHES) == 0) /* if there are no symbolic mode overrides */
return SCPE_ARG; /* then return an error to use the standard formatter */
formats = sw & FORMAT_SWITCHES; /* separate the format switches */
modes = sw & MODE_SWITCHES; /* from the mode switches */
if (formats == A_SWITCH) /* if the -A switch is specified */
radix = 256; /* then override the radix to character */
else if (formats == B_SWITCH) /* otherwise if the -B switch is specified */
radix = 2; /* then override the radix to binary */
else if (formats == D_SWITCH) /* otherwise if the -D switch is specified */
radix = 10; /* then override the radix to decimal */
else if (formats == H_SWITCH) /* otherwise if the -H switch is specified */
radix = 16; /* then override the radix to hexadecimal */
else if (formats == O_SWITCH) /* otherwise if the -O switch is specified */
radix = 8; /* then override the radix to octal */
else if (formats == 0) /* otherwise if no format switch is specified */
radix = 0; /* then indicate that the default radix is to be used */
else /* otherwise more than one format is specified */
return SCPE_INVSW; /* so return an error */
if (modes == M_SWITCH) /* if mnemonic mode is specified */
return fprint_cpu (ofile, val, radix, sw); /* then format and print the value in mnemonic format */
else if (modes == I_SWITCH) /* otherwise if I/O channel order mode is specified */
return fprint_order (ofile, val, radix); /* then format and print it */
else if (modes == E_SWITCH) /* otherwise if an EDIT subop memory display is requested */
return fprint_subop (ofile, val, radix, addr, sw); /* then format and print it */
else if (modes == T_SWITCH) { /* otherwise if status display is requested */
fputs (fmt_status ((uint32) val [0]), ofile); /* then format the status flags and condition code */
fputc (' ', ofile); /* and add a separator */
if (fprint_value (ofile, STATUS_CS (val [0]), /* if the code segment number */
(radix ? radix : cpu_dev.dradix), /* prints with the specified radix */
STATUS_CS_WIDTH, PV_RZRO) == SCPE_OK)
return SCPE_OK; /* then return success */
else /* otherwise print it */
return fprint_val (ofile, STATUS_CS (val [0]), /* in the CPU's default data radix */
cpu_dev.dradix, D8_WIDTH, PV_RZRO);
}
else if (modes == C_SWITCH) { /* otherwise if ASCII string mode is specified */
fputs (fmt_char (UPPER_BYTE (val [0])), ofile); /* then format and print the upper byte */
fputc (',', ofile); /* followed by a separator */
fputs (fmt_char (LOWER_BYTE (val [0])), ofile); /* followed by the lower byte */
return SCPE_OK; return SCPE_OK;
} }
else if (sw & SWMASK ('B') /* if binary display is requested */ else if (modes == 0) /* otherwise if single-character mode was specified */
&& (!is_reg || addr & (REG_A | REG_B))) { /* and is permitted */ return fprint_value (ofile, val [0], radix, 0, 0); /* then format and print it */
fprint_val (ofile, val [0], 2, DV_WIDTH, PV_RZRO); /* then format and print the value */
return SCPE_OK;
}
else { /* otherwise display as numeric or mnemonic */ else /* otherwise the modes conflict */
if (sw & SWMASK ('O')) /* if an octal override is present */ return SCPE_INVSW; /* so return an error */
radix_override = 8; /* then print the value in base 8 */
else if (sw & SWMASK ('D')) /* otherwise if a decimal override is present */
radix_override = 10; /* then print the value in base 10 */
else if (sw & SWMASK ('H')) /* otherwise if a hex override is present */
radix_override = 16; /* then print the value in base 16 */
else /* otherwise */
radix_override = 0; /* use the default radix setting */
if (sw & SWMASK ('I') && !is_reg) /* if I/O channel order memory display is requested */
return fprint_order (ofile, val, radix_override); /* then format and print it */
else if (sw & SWMASK ('E') && !is_reg) /* otherwise if an EDIT subop memory display is requested */
return fprint_subop (ofile, val, radix_override, addr, sw);
else if (sw & SWMASK ('M') /* otherwise if CPU instruction display is requested */
&& (!is_reg || addr & (REG_A | REG_M)) /* and is permitted */
|| is_reg && addr & REG_M && radix_override == 0) /* or if displaying a register that defaults to mnemonic */
return fprint_cpu (ofile, val, radix_override, sw); /* then format and print it */
else if (sw & SWMASK ('T') /* otherwise if status display is requested */
&& (!is_reg || addr & (REG_A | REG_T)) /* and is permitted */
|| is_reg && addr & REG_T && radix_override == 0) { /* or if displaying a register that defaults to status */
fputs (fmt_status ((uint32) val [0]), ofile); /* then format the status flags and condition code */
fputc (' ', ofile); /* and add a separator */
fprint_value (ofile, STATUS_CS (val [0]), /* print the code segment number */
(radix_override ? radix_override : cpu_dev.dradix),
STATUS_CS_WIDTH, PV_RZRO);
return SCPE_OK;
}
else /* otherwise */
return SCPE_ARG; /* request that the value be printed numerically */
}
} }
@@ -2025,11 +2115,11 @@ return formatted; /* return a pointer to t
/* Format a character for printing. /* Format a character for printing.
This routine formats single 8-bit character value into a printable string and This routine formats a single 8-bit character value into a printable string
returns a pointer to that string. Printable characters retain their original and returns a pointer to that string. Printable characters retain their
form but are enclosed in single quotes. Control characters are translated to original form but are enclosed in single quotes. Control characters are
readable strings. Characters outside of the ASCII range are presented as translated to readable strings. Characters outside of the ASCII range are
escaped octal values. presented as escaped octal values.
Implementation notes: Implementation notes:
@@ -2914,24 +3004,39 @@ return status; /* return the handler st
/* System interface local utility routines */ /* System interface local utility routines */
/* Print a numeric value with a radix identifier. /* Print a numeric value in a given radix with a radix identifier.
This routine prints a numeric value with a leading radix indicator if the This routine prints a numeric value using the specified radix, width, and
specified print radix is not the same as the current CPU data radix. It uses output format. If the radix is 256, then the value is printed as a single
the HP 3000 convention of a leading "%", "#", or "!" character to indicate character. Otherwise, it is printed as a numeric value with a leading radix
an octal, decimal, or hexadecimal number. indicator if the specified print radix is not the same as the current CPU
data radix. It uses the HP 3000 convention of a leading "%", "#", or "!"
character to indicate an octal, decimal, or hexadecimal number (there is no
binary convention, so a leading "@" is used arbitrarily).
On entry, the "ofile" parameter is the opened output stream, "val" is the On entry, the "ofile" parameter is the opened output stream, "val" is the
value to print, "radix" is the desired print radix, "width" is the number of value to print, "radix" is the desired print radix, "width" is the number of
significant bits in the value, and "format" is a format specifier (PV_RZRO, significant bits in the value, and "format" is a format specifier (PV_RZRO,
PV_RSPC, or PV_LEFT). On exit, the status of the print operation is PV_RSPC, or PV_LEFT). On exit, the routine returns SCPE_OK if the value was
returned. printed successfully, or SCPE_ARG if the value could not be printed.
*/ */
static void fprint_value (FILE *ofile, t_value val, uint32 radix, uint32 width, uint32 format) static t_stat fprint_value (FILE *ofile, t_value val, uint32 radix, uint32 width, uint32 format)
{ {
if (radix != cpu_dev.dradix) /* if the requested radix is not the current data radix */ if (radix == 256) /* if ASCII character display is requested */
if (radix == 8) /* then if the requested radix is octal */ if (val <= D8_SMAX) { /* then if the value is a single character */
fputs (fmt_char ((uint32) val), ofile); /* then format and print it */
return SCPE_OK; /* and report success */
}
else /* otherwise */
return SCPE_ARG; /* report that it cannot be displayed */
else if (radix != cpu_dev.dradix) /* otherwise if the requested radix is not the current data radix */
if (radix == 2) /* then if the requested radix is binary */
fputc ('@', ofile); /* then print the binary indicator */
else if (radix == 8) /* otherwise if the requested radix is octal */
fputc ('%', ofile); /* then print the octal indicator */ fputc ('%', ofile); /* then print the octal indicator */
else if (radix == 10) /* otherwise if it is decimal */ else if (radix == 10) /* otherwise if it is decimal */
@@ -2945,7 +3050,7 @@ if (radix != cpu_dev.dradix) /* if the requested radi
fprint_val (ofile, val, radix, width, format); /* print the value in the radix specified */ fprint_val (ofile, val, radix, width, format); /* print the value in the radix specified */
return; return SCPE_OK; /* return success */
} }
@@ -2979,16 +3084,15 @@ return;
- Address values are printed in the CPU's address radix, which is octal. - Address values are printed in the CPU's address radix, which is octal.
- Counts are printed in decimal. - Counts are printed by default in decimal.
- Control and status values are printed in the CPU's data radix, which - Control and status values are printed in the CPU's data radix, which
defaults to octal but may be set to a different radix with SET CPU defaults to octal.
OCT|DEC|HEX.
The radix for operand values other than addresses may be overridden by a The radix for operand values other than addresses may be overridden by a
switch on the command line. A value printed in a radix other than the switch on the command line. A value printed in a radix other than the
current data radix is preceded by a radix identifier ("%" for octal, "#" for current data radix is preceded by a radix identifier ("@" for binary, "%" for
decimal, or "!" for hexadecimal). octal, "#" for decimal, or "!" for hexadecimal).
The routine returns SCPE_OK_2_WORDS to indicate that two words were consumed. The routine returns SCPE_OK_2_WORDS to indicate that two words were consumed.
@@ -3031,7 +3135,7 @@ switch (order) { /* dispatch operand prin
case sioJUMP: case sioJUMP:
case sioJUMPC: /* print the jump target address */ case sioJUMPC: /* print the jump target address */
fprint_value (ofile, ioaw, cpu_dev.aradix, fprint_value (ofile, ioaw, cpu_dev.aradix, /* in the CPU's address radix */
LA_WIDTH, PV_RZRO); LA_WIDTH, PV_RZRO);
break; break;
@@ -3042,7 +3146,7 @@ switch (order) { /* dispatch operand prin
break; break;
case sioSBANK: /* print the bank address */ case sioSBANK: /* print the bank address */
fprint_value (ofile, ioaw & BA_MASK, fprint_value (ofile, ioaw & BA_MASK, /* in the CPU's address radix */
cpu_dev.aradix, BA_WIDTH, PV_RZRO); cpu_dev.aradix, BA_WIDTH, PV_RZRO);
break; break;
@@ -3078,7 +3182,7 @@ switch (order) { /* dispatch operand prin
fputc (',', ofile); fputc (',', ofile);
fprint_value (ofile, ioaw, cpu_dev.aradix, fprint_value (ofile, ioaw, cpu_dev.aradix, /* prnit the address in the CPU's address radix */
LA_WIDTH, PV_RZRO); LA_WIDTH, PV_RZRO);
break; break;
} }
@@ -3562,7 +3666,6 @@ switch (ops [op_index].operand) { /* dispatch by the opera
prefix = " "; /* so just use a space to separate the value */ prefix = " "; /* so just use a space to separate the value */
op_value = (op_value & ~op_mask [opS11]) >> EIS_SDEC_SHIFT; /* remove the flags from the S decrement value */ op_value = (op_value & ~op_mask [opS11]) >> EIS_SDEC_SHIFT; /* remove the flags from the S decrement value */
op_radix = (radix ? radix : cpu_dev.dradix); /* and set the print radix */
break; break;

View File

@@ -1,6 +1,6 @@
/* hp_disclib.h: HP MAC/ICD disc controller simulator library declarations /* hp_disclib.h: HP MAC/ICD disc controller simulator library declarations
Copyright (c) 2011-2016, J. David Bryan Copyright (c) 2011-2017, J. David Bryan
Copyright (c) 2004-2011, Robert M. Supnik Copyright (c) 2004-2011, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -24,6 +24,7 @@
in advertising or otherwise to promote the sale, use or other dealings in in advertising or otherwise to promote the sale, use or other dealings in
this Software without prior written authorization from the authors. this Software without prior written authorization from the authors.
05-Sep-17 JDB Changed REG_A (permit any symbolic override) to REG_X
10-Oct-16 JDB Moved "hp3000_defs.h" inclusion to "hp_disclib.c" 10-Oct-16 JDB Moved "hp3000_defs.h" inclusion to "hp_disclib.c"
13-May-16 JDB Modified for revised SCP API function parameter types 13-May-16 JDB Modified for revised SCP API function parameter types
24-Mar-16 JDB Added the DL_BUFFER type to define the disc buffer array 24-Mar-16 JDB Added the DL_BUFFER type to define the disc buffer array
@@ -479,7 +480,7 @@ typedef CNTLR_VARS *CVPTR; /* pointer to a controller state
{ DRDATA (HEAD, (cntlr).head, 6), PV_LEFT }, \ { DRDATA (HEAD, (cntlr).head, 6), PV_LEFT }, \
{ DRDATA (SECTOR, (cntlr).sector, 8), PV_LEFT }, \ { DRDATA (SECTOR, (cntlr).sector, 8), PV_LEFT }, \
{ DRDATA (COUNT, (cntlr).count, 16), PV_LEFT }, \ { DRDATA (COUNT, (cntlr).count, 16), PV_LEFT }, \
{ BRDATA (SECBUF, (buffer), 8, 16, DL_BUFSIZE), REG_A }, \ { BRDATA (SECBUF, (buffer), 8, 16, DL_BUFSIZE), REG_X }, \
{ DRDATA (INDEX, (cntlr).index, 8), PV_LEFT }, \ { DRDATA (INDEX, (cntlr).index, 8), PV_LEFT }, \
{ DRDATA (LENGTH, (cntlr).length, 8), PV_LEFT }, \ { DRDATA (LENGTH, (cntlr).length, 8), PV_LEFT }, \
{ DRDATA (POLLU, (cntlr).poll_unit, 4), REG_HRO }, \ { DRDATA (POLLU, (cntlr).poll_unit, 4), REG_HRO }, \

View File

@@ -1,6 +1,6 @@
/* hp_tapelib.h: HP magnetic tape controller simulator library declarations /* hp_tapelib.h: HP magnetic tape controller simulator library declarations
Copyright (c) 2013-2016, J. David Bryan Copyright (c) 2013-2017, J. David Bryan
Copyright (c) 2004-2011, Robert M. Supnik Copyright (c) 2004-2011, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -24,6 +24,7 @@
in advertising or otherwise to promote the sale, use or other dealings in in advertising or otherwise to promote the sale, use or other dealings in
this Software without prior written authorization from the authors. this Software without prior written authorization from the authors.
05-Sep-17 JDB Changed REG_A (permit any symbolic override) to REG_X
10-Oct-16 JDB Moved "hp3000_defs.h" inclusion to "hp_tapelib.c" 10-Oct-16 JDB Moved "hp3000_defs.h" inclusion to "hp_tapelib.c"
13-May-16 JDB Modified for revised SCP API function parameter types 13-May-16 JDB Modified for revised SCP API function parameter types
24-Mar-16 JDB Added the TL_BUFFER type to define the tape buffer array 24-Mar-16 JDB Added the TL_BUFFER type to define the tape buffer array
@@ -419,7 +420,7 @@ typedef CNTLR_VARS *CVPTR; /* a pointer to a controller sta
{ ORDATA (STATUS, (cntlr).status, 16), REG_RO }, \ { ORDATA (STATUS, (cntlr).status, 16), REG_RO }, \
{ DRDATA (USEL, (cntlr).unit_selected, 4), PV_LEFT | REG_RO }, \ { DRDATA (USEL, (cntlr).unit_selected, 4), PV_LEFT | REG_RO }, \
{ YRDATA (UATTN, (cntlr).unit_attention, 4, PV_RZRO) }, \ { YRDATA (UATTN, (cntlr).unit_attention, 4, PV_RZRO) }, \
{ BRDATA (RECBUF, (buffer), 8, 8, TL_BUFSIZE), REG_A }, \ { BRDATA (RECBUF, (buffer), 8, 8, TL_BUFSIZE), REG_X }, \
{ DRDATA (LIBSTA, (cntlr).call_status, 16), PV_LEFT }, \ { DRDATA (LIBSTA, (cntlr).call_status, 16), PV_LEFT }, \
{ DRDATA (LENGTH, (cntlr).length, 24), PV_LEFT }, \ { DRDATA (LENGTH, (cntlr).length, 24), PV_LEFT }, \
{ DRDATA (INDEX, (cntlr).index, 24), PV_LEFT }, \ { DRDATA (INDEX, (cntlr).index, 24), PV_LEFT }, \

Binary file not shown.