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:
@@ -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"),
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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 },
|
||||||
|
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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) },
|
||||||
|
|||||||
@@ -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
|
||||||
=====================
|
=====================
|
||||||
|
|||||||
@@ -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 }
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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 }, \
|
||||||
|
|||||||
@@ -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.
Reference in New Issue
Block a user