HP3000: HP 3000 release 5
See HP3000/hp3000_release.txt for details of the release
This commit is contained in:
parent
90e9c2f4a0
commit
f617f63ae0
10 changed files with 357 additions and 170 deletions
|
@ -197,7 +197,7 @@ static const int32 delay [8] = { /* clock delays, in event ticks
|
|||
mS (10), /* 100 = 10 milliseconds */
|
||||
mS (100), /* 101 = 100 milliseconds */
|
||||
S (1), /* 110 = 1 second */
|
||||
S (10), /* 111 = 10 seconds */
|
||||
S (10) /* 111 = 10 seconds */
|
||||
};
|
||||
|
||||
static const int32 ticks [8] = { /* clock ticks per second */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* hp3000_cpu_cis.c: HP 32234A COBOL II Instruction Set 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
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,6 +23,7 @@
|
|||
in advertising or otherwise to promote the sale, use or other dealings in
|
||||
this Software without prior written authorization from the author.
|
||||
|
||||
22-Apr-17 JDB Corrected the significance flag setting in "edit"
|
||||
29-Dec-16 JDB Disabled interrupt checks pending test generation
|
||||
19-Oct-16 JDB Passes the COBOL-II firmware "A" diagnostic (D441A)
|
||||
06-Oct-16 JDB Passes the COBOL-II firmware "B" diagnostic (D442A)
|
||||
|
@ -1331,9 +1332,9 @@ return trap; /* return the trap condi
|
|||
|
||||
If an interrupt is detected between operations, two words are pushed onto the
|
||||
stack before the interrupt handler is called. These words hold the current
|
||||
significance trigger (a flag indicating whether a significant digit has been
|
||||
seen or zero filling should occur), loop count, float character, and fill
|
||||
character, in this format:
|
||||
significance trigger (a flag indicating that a significant digit has been
|
||||
seen or that zero filling should occur), loop count, float character, and
|
||||
fill character, in this format:
|
||||
|
||||
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
||||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
|
@ -1389,6 +1390,12 @@ return trap; /* return the trap condi
|
|||
the address of the displacement byte. After reading the displacement
|
||||
byte, the address is incremented to the next location, so the operation
|
||||
subtracts 1 before adding the displacement value.
|
||||
|
||||
3. The significance trigger is represented by the "filling" flag; its value
|
||||
is the opposite of the trigger, i.e., FALSE if a significant digit has
|
||||
been seen, TRUE if all leading digits have been zeros, because that more
|
||||
clearly indicates that it controls leading zero suppression and
|
||||
replacement.
|
||||
*/
|
||||
|
||||
static t_bool edit (t_stat *status, uint32 *trap)
|
||||
|
@ -1406,7 +1413,7 @@ t_bool terminate = FALSE; /* TRUE if the operation
|
|||
*trap = trap_None; /* and trap condition */
|
||||
|
||||
if (RA != 0) { /* if this is a reentry after an interrupt */
|
||||
filling = ((RB & D16_SIGN) != 0); /* then reset the zero-filling flag */
|
||||
filling = ((RB & D16_SIGN) == 0); /* then reset the zero-filling flag */
|
||||
loop_count = LOWER_BYTE (RB); /* and the loop counter */
|
||||
fill_char = UPPER_BYTE (RC); /* reset the fill */
|
||||
float_char = LOWER_BYTE (RC); /* and float characters */
|
||||
|
@ -1773,8 +1780,8 @@ do { /* process operations wh
|
|||
|
||||
RA = D16_UMAX; /* set the resumption flag */
|
||||
|
||||
RB = TO_WORD ((filling ? D16_SIGN : 0), loop_count); /* save the significance trigger and loop count */
|
||||
RC = TO_WORD (fill_char, float_char); /* save the fill and float characters */
|
||||
RB = (filling ? 0 : D16_SIGN) | loop_count; /* save the significance trigger and loop count */
|
||||
RC = TO_WORD (fill_char, float_char); /* save the fill and float characters */
|
||||
|
||||
mem_update_byte (&target); /* update the last word written */
|
||||
return FALSE; /* and return with an interrupt set up or a status error */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* hp3000_lp.c: HP 3000 30209A Line Printer 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
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -25,6 +25,10 @@
|
|||
|
||||
LP HP 30209A Line Printer Interface
|
||||
|
||||
26-Apr-17 JDB Fixed "lp_service" return for VFU channel not punched
|
||||
Restricted auto-print on buffer full to the 2607
|
||||
Paper fault is now delayed until the TOF for the 2607
|
||||
Changed "activate_unit" to schedule zero-length delays
|
||||
12-Sep-16 JDB Changed DIB register macro usage from SRDATA to DIB_REG
|
||||
03-Sep-16 JDB Added power-fail detection
|
||||
08-Jul-16 JDB Added REG entry to save the transfer unit wait field
|
||||
|
@ -537,23 +541,30 @@ typedef enum {
|
|||
|
||||
This table contains the characteristics that vary between printer models.
|
||||
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
|
||||
or simply takes the printer offline. The "fault_at_eol" field indicates
|
||||
whether a paper fault is reported at the end of any line (TRUE) or only at
|
||||
the top of the next form (FALSE).
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
uint32 line_length; /* the maximum number of print positions */
|
||||
uint32 char_set; /* the size of the character set */
|
||||
uint32 vfu_channels; /* the number of VFU channels */
|
||||
t_bool not_ready; /* TRUE if the printer reports a separate not ready status */
|
||||
t_bool overprints; /* TRUE if the printer supports overprinting */
|
||||
t_bool autoprints; /* TRUE if the printer automatically prints on buffer overflow */
|
||||
t_bool fault_at_eol; /* TRUE if a paper fault is reported at the end of any line */
|
||||
} PRINTER_PROPS;
|
||||
|
||||
static const PRINTER_PROPS print_props [] = { /* printer properties, indexed by PRINTER_TYPE */
|
||||
/* line char VFU over */
|
||||
/* length set channels prints */
|
||||
/* ------ ----- -------- ------ */
|
||||
{ 132, 128, 8, FALSE }, /* HP_2607 */
|
||||
{ 136, 96, 12, TRUE }, /* HP_2613 */
|
||||
{ 136, 96, 12, TRUE }, /* HP_2617 */
|
||||
{ 132, 96, 12, TRUE } /* HP_2618 */
|
||||
/* line char VFU not over auto fault */
|
||||
/* length set channels ready prints prints at EOL */
|
||||
/* ------ ----- -------- ------ ------ ------ ------ */
|
||||
{ 132, 128, 8, FALSE, FALSE, TRUE, FALSE }, /* HP_2607 */
|
||||
{ 136, 96, 12, TRUE, TRUE, FALSE, TRUE }, /* HP_2613 */
|
||||
{ 136, 96, 12, TRUE, TRUE, FALSE, TRUE }, /* HP_2617 */
|
||||
{ 132, 96, 12, TRUE, TRUE, FALSE, TRUE } /* HP_2618 */
|
||||
};
|
||||
|
||||
|
||||
|
@ -1650,9 +1661,7 @@ return IORETURN (outbound_signals, outbound_value); /* return the outbound s
|
|||
|
||||
This service routine is called once for each state of the device transfer
|
||||
handshake. The handshake sequencer schedules the transfer events with the
|
||||
appropriate delays. If no delay is required, the service routine is entered
|
||||
directly from the sequencer. Otherwise, an event is scheduled, and the
|
||||
routine is entered when the event time expires.
|
||||
appropriate delays.
|
||||
|
||||
Jumper W10 determines the output polarity of the DEV CMD signal to the
|
||||
device, and jumpers W2 and W6 determine the input edges of the DEV FLAG
|
||||
|
@ -1679,10 +1688,9 @@ return IORETURN (outbound_signals, outbound_value); /* return the outbound s
|
|||
Device Flag is accomplished by comparing the current state to the prior
|
||||
state.
|
||||
|
||||
2. If the routine was entered by event timer expiration, the handshake
|
||||
2. As the routine was entered by an event timer expiration, the handshake
|
||||
sequencer must be called explicitly, and any returned backplane signals
|
||||
must be asserted explicitly. If the routine was called directly, the
|
||||
sequencer is responsible for asserting backplane signals as required.
|
||||
must be asserted explicitly.
|
||||
|
||||
3. This routine may be called with a NULL "uptr" parameter to update the
|
||||
saved last state of the "device_flag_in" variable. The NULL value
|
||||
|
@ -1692,7 +1700,6 @@ return IORETURN (outbound_signals, outbound_value); /* return the outbound s
|
|||
static t_stat xfer_service (UNIT *uptr)
|
||||
{
|
||||
static t_bool device_flag_last = FALSE;
|
||||
const t_bool timed_entry = (uptr != NULL && uptr->wait > 0); /* TRUE if entry was by event timer */
|
||||
t_stat result;
|
||||
OUTBOUND_SET signals;
|
||||
|
||||
|
@ -1718,15 +1725,13 @@ else /* otherwise Device Comm
|
|||
|
||||
device_flag_last = device_flag_in; /* save the current state of the flag */
|
||||
|
||||
if (timed_entry) { /* if this is a timed entry */
|
||||
signals = handshake_xfer (); /* then continue the handshake */
|
||||
signals = handshake_xfer (); /* continue the handshake */
|
||||
|
||||
if (signals & INTREQ) /* if an interrupt request was generated */
|
||||
iop_assert_INTREQ (&lp_dib); /* then assert the INTREQ signal */
|
||||
if (signals & INTREQ) /* if an interrupt request was generated */
|
||||
iop_assert_INTREQ (&lp_dib); /* then assert the INTREQ signal */
|
||||
|
||||
if (signals & SRn) /* if a service request was generated */
|
||||
mpx_assert_SRn (&lp_dib); /* then assert the SRn signal */
|
||||
}
|
||||
if (signals & SRn) /* if a service request was generated */
|
||||
mpx_assert_SRn (&lp_dib); /* then assert the SRn signal */
|
||||
|
||||
return result; /* return the result of the service call */
|
||||
}
|
||||
|
@ -1742,14 +1747,16 @@ return result; /* return the result of
|
|||
|
||||
static t_stat pulse_service (UNIT *uptr)
|
||||
{
|
||||
t_stat status;
|
||||
|
||||
dprintf (lp_dev, DEB_SERV, "Pulse service entered\n");
|
||||
|
||||
device_command = CLEAR; /* clear the device command flip-flop */
|
||||
|
||||
activate_unit (xfer_uptr); /* let the device know that command has denied */
|
||||
status = xfer_service (xfer_uptr); /* let the device know that command has denied */
|
||||
handshake_xfer (); /* and continue the handshake */
|
||||
|
||||
return SCPE_OK;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1880,23 +1887,25 @@ return;
|
|||
}
|
||||
|
||||
|
||||
/* Activate a unit.
|
||||
/* Activate the unit.
|
||||
|
||||
The specified unit is added to the event queue if a non-zero event time has
|
||||
been given. Otherwise, the event handler is called directly.
|
||||
The specified unit is activated using the unit's "wait" time. If tracing
|
||||
is enabled, the activation is logged to the debug file.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. A zero-length delay is scheduled, rather than calling the service routine
|
||||
directly, so that the status return value from the event service routine
|
||||
is correctly passed back to SCP.
|
||||
*/
|
||||
|
||||
static void activate_unit (UNIT *uptr)
|
||||
{
|
||||
if (uptr->wait > 0) { /* if the event time is set */
|
||||
dprintf (lp_dev, DEB_SERV, "%s delay %u service scheduled\n",
|
||||
unit_name [uptr - lp_unit], uptr->wait);
|
||||
dprintf (lp_dev, DEB_SERV, "%s delay %u service scheduled\n",
|
||||
unit_name [uptr - lp_unit], uptr->wait);
|
||||
|
||||
sim_activate (uptr, uptr->wait); /* then activate the unit */
|
||||
}
|
||||
|
||||
else /* otherwise */
|
||||
uptr->action (uptr); /* call the event handler directly */
|
||||
sim_activate (uptr, uptr->wait); /* activate the unit */
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -2022,29 +2031,15 @@ return outbound_signals; /* return INTREQ if
|
|||
The device service is scheduled after each state transition, except the
|
||||
return to the idle state, to detect the change in the Device Command signal
|
||||
or to schedule the change in the Device Flag. The device determines whether
|
||||
the service is entered immediately or after an event time expires.
|
||||
the service will be entered immediately (at the next poll) or after a delay
|
||||
time expires.
|
||||
|
||||
For the diagnostic device, the service routine is entered immediately for all
|
||||
transitions. If the DHA is configured for flag-follows-command mode, the
|
||||
full handshake cycle executes before returning from the routine. If it is
|
||||
configured for flag-follows-control-6, the routine returns after the Idle-to-
|
||||
Device_Command_1 state transition to wait for control word bit 6 to be set.
|
||||
When it is, the routine is reentered, transitions from Device_Command_1 to
|
||||
Device_Flag_1, and then returns to wait for control word bit 6 to be cleared.
|
||||
When it is, the routine is entered and completes the transition from
|
||||
Device_Flag_1 to the Idle state (assuming a word transfer).
|
||||
transitions. For the printer device, the service routine is entered
|
||||
immediately for Device Flag assertions, but flag denials are scheduled with a
|
||||
delay corresponding to the printer operation time. The operations are as
|
||||
follows:
|
||||
|
||||
For the printer device, the service routine is entered immediately for Device
|
||||
Flag assertions, but flag denials are scheduled with a delay corresponding to
|
||||
the printer operation time. The initial handshake entry transitions from
|
||||
Idle to Device_Command_1, calls the service routine, which sets Device Flag,
|
||||
transitions to Device_Flag_1, schedules the service routine, and returns to
|
||||
wait for the event timer to expire. When it does, the event service routine
|
||||
is entered, which clears Device Flag and calls this routine to continue the
|
||||
handshake. The routine transitions from Device_Flag_1 to Idle to complete
|
||||
the handshake sequence.
|
||||
|
||||
Summarizing:
|
||||
Diagnostic Service Diagnostic Service
|
||||
State Printer Service Flag follows Cmd Flag follows cont.6
|
||||
---------------- ---------------- ------------------ -------------------
|
||||
|
@ -2135,12 +2130,17 @@ return outbound_signals; /* return INTREQ if
|
|||
DATA OUT and DATA IN lines, so we must simulate the multiplexing
|
||||
accurately with respect to the intermediate values before the handshake
|
||||
is complete.
|
||||
|
||||
5. The sequencer loop is used only during a device end assertion to move
|
||||
from Idle to Device_Command_1 and back to Idle. All other transitions
|
||||
involve unit activation and so exit this routine after the sequence state
|
||||
is changed.
|
||||
*/
|
||||
|
||||
static OUTBOUND_SET handshake_xfer (void)
|
||||
{
|
||||
const SEQ_STATE entry_state = sequencer; /* the state of the sequencer at entry */
|
||||
t_bool started = FALSE; /* TRUE if the sequencer started */
|
||||
t_bool reset = FALSE; /* TRUE if the sequencer is reset */
|
||||
OUTBOUND_SET outbound_signals = NO_SIGNALS;
|
||||
SEQ_STATE last_state;
|
||||
|
||||
|
@ -2172,8 +2172,6 @@ do { /* run the sequencer as
|
|||
|
||||
activate_unit (xfer_uptr); /* schedule device flag assertion */
|
||||
}
|
||||
|
||||
started = TRUE; /* indicate that the sequencer was started */
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -2188,7 +2186,9 @@ do { /* run the sequencer as
|
|||
write_xfer = CLEAR; /* and write transfer flip-flops */
|
||||
|
||||
sequencer = Idle; /* idle the sequencer */
|
||||
device_sr = SET; /* and request channel service */
|
||||
reset = TRUE; /* and indicate that it was reset */
|
||||
|
||||
device_sr = SET; /* request channel service */
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2274,13 +2274,8 @@ if (DPRINTING (lp_dev, DEB_STATE))
|
|||
hp_debug (&lp_dev, DEB_STATE, "Sequencer transitioned from the %s state to the %s state\n",
|
||||
state_name [entry_state], state_name [sequencer]);
|
||||
|
||||
else if (started)
|
||||
if (device_end)
|
||||
hp_debug (&lp_dev, DEB_STATE, "Sequencer reset by device end\n");
|
||||
|
||||
else
|
||||
hp_debug (&lp_dev, DEB_STATE, "Sequencer executed a full %s-transfer cycle\n",
|
||||
(control_word & CN_BYTE_XFER ? "byte" : "word"));
|
||||
else if (reset && device_end)
|
||||
hp_debug (&lp_dev, DEB_STATE, "Sequencer reset by device end\n");
|
||||
|
||||
if (device_sr && sio_busy) /* if the interface has requested service */
|
||||
outbound_signals |= SRn; /* then assert SRn to the channel */
|
||||
|
@ -2478,13 +2473,13 @@ return outbound_signals; /* return INTREQ if any
|
|||
indicate that the buffer load or print operation is complete.
|
||||
|
||||
In simulation, this service routine is called twice for each transfer. It is
|
||||
called directly with Device Command set and then after a variable delay with
|
||||
Device Command clear. In response to the former call, the routine sets the
|
||||
Device Flag, loads the character buffer or prints the buffered line, and then
|
||||
sets up an event delay corresponding to the operation performed. In response
|
||||
to the latter call, the routine clears the Device Flag and then clears the
|
||||
event delay time, so that the routine will be reentered directly when Device
|
||||
Command sets again.
|
||||
called immediately with Device Command set and then after a variable delay
|
||||
with Device Command clear. In response to the former call, the routine sets
|
||||
the Device Flag, loads the character buffer or prints the buffered line, and
|
||||
then sets up an event delay corresponding to the operation performed. In
|
||||
response to the latter call, the routine clears the Device Flag and then
|
||||
clears the event delay time, so that the routine will be reentered
|
||||
immediately when Device Command sets again.
|
||||
|
||||
If a SET LP OFFLINE command or a DETACH LP command simulating an out-of-paper
|
||||
condition is given, the printer will not honor the command immediately if
|
||||
|
@ -2593,7 +2588,7 @@ return outbound_signals; /* return INTREQ if any
|
|||
|
||||
static t_stat lp_service (UNIT *uptr)
|
||||
{
|
||||
const t_bool printing = ((control_word & CN_FORMAT) != 0); /* TRUE if a print command was received */
|
||||
const t_bool printing = ((control_word & CN_FORMAT) != 0); /* TRUE if a print command was received */
|
||||
static uint32 overprint_index = 0;
|
||||
PRINTER_TYPE model;
|
||||
uint8 data_byte, format_byte;
|
||||
|
@ -2602,6 +2597,8 @@ uint32 line_count, slew_count, vfu_status;
|
|||
|
||||
if (uptr == NULL) /* if we're called for a state update */
|
||||
return SCPE_OK; /* then return with no other action */
|
||||
else /* otherwise */
|
||||
model = GET_MODEL (uptr->flags); /* get the printer type */
|
||||
|
||||
dprintf (lp_dev, DEB_SERV, "%s state printer service entered\n",
|
||||
state_name [sequencer]);
|
||||
|
@ -2610,12 +2607,16 @@ if (device_command_out == FALSE) { /* if STROBE has denied
|
|||
if (printing) { /* then if printing occurred */
|
||||
buffer_index = 0; /* then clear the buffer */
|
||||
|
||||
if (paper_fault) /* if an out-of-paper condition is pending */
|
||||
return lp_detach (uptr); /* then complete it now with the printer offline */
|
||||
if (paper_fault) { /* if an out-of-paper condition is pending */
|
||||
if (print_props [model].fault_at_eol /* then if the printer faults at the end of any line */
|
||||
|| current_line == 1) /* or the printer is at the top of the form */
|
||||
return lp_detach (uptr); /* then complete it now with the printer offline */
|
||||
}
|
||||
|
||||
else if (tape_fault) { /* otherwise if a referenced VFU channel was not punched */
|
||||
dprintf (lp_dev, DEB_CMD, "Commanded VFU channel is not punched\n");
|
||||
return lp_set_alarm (uptr); /* then take the printer offline now */
|
||||
lp_set_alarm (uptr); /* then set an alarm condition that takes the printer offline */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
else if (offline_pending) { /* otherwise if a non-alarm offline request is pending */
|
||||
|
@ -2631,8 +2632,6 @@ if (device_command_out == FALSE) { /* if STROBE has denied
|
|||
else if (device_flag_in == FALSE) { /* otherwise if STROBE has asserted while DEMAND is asserted */
|
||||
device_flag_in = TRUE; /* then deny DEMAND */
|
||||
|
||||
model = GET_MODEL (uptr->flags); /* get the printer type */
|
||||
|
||||
data_byte = (uint8) (data_out & DATA_MASK); /* only the lower 7 bits are connected */
|
||||
|
||||
if (printing == FALSE) { /* if loading the print buffer */
|
||||
|
@ -2657,9 +2656,12 @@ else if (device_flag_in == FALSE) { /* otherwise if STROBE h
|
|||
buffer_index++; /* increment the buffer index */
|
||||
|
||||
uptr->wait = dlyptr->buffer_load; /* schedule the buffer load delay */
|
||||
|
||||
dprintf (lp_dev, DEB_XFER, "Character %s sent to printer\n",
|
||||
fmt_char (data_byte));
|
||||
}
|
||||
|
||||
else { /* otherwise the buffer is full */
|
||||
else if (print_props [model].autoprints) { /* otherwise if a buffer overflow auto-prints */
|
||||
dprintf (lp_dev, DEB_CMD, "Buffer overflow printed %u characters on line %u\n",
|
||||
buffer_index, current_line);
|
||||
|
||||
|
@ -2669,7 +2671,7 @@ else if (device_flag_in == FALSE) { /* otherwise if STROBE h
|
|||
fwrite (buffer, sizeof buffer [0], /* write the buffer to the printer file */
|
||||
buffer_index, uptr->fileref);
|
||||
|
||||
uptr->pos = ftell (uptr->fileref); /* update the file position */
|
||||
uptr->pos = (t_addr) ftell (uptr->fileref); /* update the file position */
|
||||
|
||||
current_line = current_line + 1; /* move the paper one line */
|
||||
|
||||
|
@ -2687,10 +2689,17 @@ else if (device_flag_in == FALSE) { /* otherwise if STROBE h
|
|||
uptr->wait = dlyptr->print /* schedule the print delay */
|
||||
+ dlyptr->advance /* plus the paper advance delay */
|
||||
+ dlyptr->buffer_load; /* plus the buffer load delay */
|
||||
|
||||
dprintf (lp_dev, DEB_XFER, "Character %s sent to printer\n",
|
||||
fmt_char (data_byte));
|
||||
}
|
||||
|
||||
dprintf (lp_dev, DEB_XFER, "Character %s sent to printer\n",
|
||||
fmt_char (data_byte));
|
||||
else {
|
||||
uptr->wait = dlyptr->buffer_load; /* schedule the buffer load delay */
|
||||
|
||||
dprintf (lp_dev, DEB_CMD, "Buffer overflow discards character %s\n",
|
||||
fmt_char (data_byte));
|
||||
}
|
||||
}
|
||||
|
||||
else { /* otherwise this is a print format command */
|
||||
|
@ -2812,7 +2821,7 @@ else if (device_flag_in == FALSE) { /* otherwise if STROBE h
|
|||
uptr->wait = dlyptr->print /* schedule the print delay */
|
||||
+ slew_count * dlyptr->advance; /* plus the paper advance delay */
|
||||
|
||||
uptr->pos = ftell (uptr->fileref); /* update the file position */
|
||||
uptr->pos = (t_addr) ftell (uptr->fileref); /* update the file position */
|
||||
|
||||
if (slew_count > 0)
|
||||
dprintf (lp_dev, DEB_CMD, "Printer advanced %u line%s to line %u\n",
|
||||
|
@ -2842,15 +2851,10 @@ return SCPE_OK; /* return event service
|
|||
|
||||
A new image file may be requested by giving the "-N" switch to the attach
|
||||
command. If an existing file is specified with "-N", it will be cleared; if
|
||||
specified without "-P", 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
|
||||
the form.
|
||||
|
||||
As a special case, a detach (out-of-paper condition) that has been deferred
|
||||
until printing completes may be cancelled by giving an attach command without
|
||||
a filename, i.e., ATTACH LP. If a filename is given, but the detach is still
|
||||
pending, the routine returns a "Command not allowed" error.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
|
@ -2867,32 +2871,23 @@ static t_stat lp_attach (UNIT *uptr, CONST char *cptr)
|
|||
{
|
||||
t_stat result = SCPE_OK;
|
||||
|
||||
if (paper_fault && offline_pending) /* if an out-of-paper condition is deferred */
|
||||
if (cptr == NULL) /* then if an attach command is given without a filename */
|
||||
offline_pending = FALSE; /* then cancel the request, leaving the file attached */
|
||||
result = attach_unit (uptr, cptr); /* attach the specified printer image file */
|
||||
|
||||
else /* otherwise a filename was specified */
|
||||
return SCPE_NOFNC; /* but we can't attach until the previous file detaches */
|
||||
if (result == SCPE_OK /* if the attach was successful */
|
||||
&& (sim_switches & SIM_SW_REST) == 0) { /* and we are not being called during a RESTORE command */
|
||||
set_device_status (ST_NOT_READY, 0); /* then clear not-ready status */
|
||||
|
||||
else { /* otherwise no deferral is active */
|
||||
result = attach_unit (uptr, cptr); /* so attach the specified printer image file */
|
||||
current_line = 1; /* reset the line counter to the top of the form */
|
||||
|
||||
if (result == SCPE_OK /* if the attach was successful */
|
||||
&& (sim_switches & SIM_SW_REST) == 0) { /* and we are not being called during a RESTORE command */
|
||||
set_device_status (ST_NOT_READY, 0); /* then clear not-ready status */
|
||||
if (sim_switches & SWMASK ('N')) /* if a new (empty) file was requested */
|
||||
uptr->pos = 0; /* then position at the start of the file */
|
||||
|
||||
current_line = 1; /* reset the line counter to the top of the form */
|
||||
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 */
|
||||
|
||||
if (sim_switches & SWMASK ('N')) /* if a new (empty) file was requested */
|
||||
uptr->pos = 0; /* then position at the start of the file */
|
||||
dprintf (lp_dev, DEB_CMD, "Printer paper loaded\n");
|
||||
|
||||
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 */
|
||||
|
||||
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 */
|
||||
}
|
||||
|
||||
paper_fault = FALSE; /* clear any existing paper fault */
|
||||
|
@ -2915,9 +2910,13 @@ return result; /* return the result of
|
|||
an interrupt.
|
||||
|
||||
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 simulation,
|
||||
entering a DETACH LP command while the printer is busy will defer the file
|
||||
detach until the current print operation completes.
|
||||
present in the buffer are printed and paper motion stops. In addition, the
|
||||
2607 printer waits until the paper reaches the top-of-form position before
|
||||
going offline.
|
||||
|
||||
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
|
||||
(2607) or until the current print operation completes (2613/17/18).
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
@ -2931,24 +2930,36 @@ return result; /* return the result of
|
|||
2. The DETACH ALL command will fail if any detach routine returns a status
|
||||
other than SCPE_OK. Because a deferred detach is not fatal, we must
|
||||
return SCPE_OK, but we still want to print a warning to the user.
|
||||
|
||||
3. Because the 2607 only paper faults at TOF, we must explicitly set the
|
||||
offline_pending flag, as lp_set_alarm may not have been called.
|
||||
*/
|
||||
|
||||
static t_stat lp_detach (UNIT *uptr)
|
||||
{
|
||||
const PRINTER_TYPE model = GET_MODEL (uptr->flags); /* the printer model number */
|
||||
|
||||
if (uptr->flags & UNIT_ATTABLE) /* if we're being called for the printer unit */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) /* then if the unit is not currently attached */
|
||||
return SCPE_UNATT; /* then report it */
|
||||
|
||||
else if (lp_set_alarm (uptr) /* otherwise if a paper alarm is accepted */
|
||||
|| (sim_switches & SIM_SW_SHUT)) { /* or this is a shutdown call */
|
||||
paper_fault = TRUE; /* then set the out-of-paper condition */
|
||||
else 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 */
|
||||
|| (sim_switches & SIM_SW_SHUT)) { /* or this is a shutdown call */
|
||||
paper_fault = TRUE; /* then set the out-of-paper condition */
|
||||
|
||||
dprintf (lp_dev, DEB_CMD, "Printer is out of paper\n");
|
||||
|
||||
return detach_unit (uptr); /* and detach the unit */
|
||||
}
|
||||
|
||||
else { /* otherwise the alarm was rejected at this time */
|
||||
paper_fault = TRUE; /* so set the out-of-paper condition now */
|
||||
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");
|
||||
|
||||
cputs ("Command deferred\n"); /* but the actual detach must be deferred */
|
||||
return SCPE_OK; /* until the buffer prints */
|
||||
}
|
||||
|
@ -3041,6 +3052,9 @@ return SCPE_OK; /* allow the reassignmen
|
|||
deferred until printing completes, and the routine prints "Command deferred"
|
||||
to inform the user. Otherwise, the unit is set offline, 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
|
||||
must be loaded), or the command is rejected. If paper is present, the unit
|
||||
|
@ -3068,7 +3082,13 @@ if ((uptr->flags & UNIT_ATT) == 0) /* if the printer is det
|
|||
return SCPE_UNATT; /* then it can't be set online or offline */
|
||||
|
||||
else if (value == UNIT_ONLINE) /* otherwise if this is an online request */
|
||||
lp_set_locality (uptr, Online); /* then set the printer online */
|
||||
if (paper_fault && offline_pending) { /* then if an out-of-paper condition is deferred */
|
||||
paper_fault = FALSE; /* then cancel the request */
|
||||
offline_pending = FALSE; /* leaving the file attached */
|
||||
}
|
||||
|
||||
else /* otherwise it's a normal online request */
|
||||
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 */
|
||||
cputs ("Command deferred\n"); /* then let the user know */
|
||||
|
@ -3242,6 +3262,7 @@ return SCPE_OK;
|
|||
|
||||
static t_stat lp_reset (t_bool programmed_clear)
|
||||
{
|
||||
const PRINTER_TYPE model = GET_MODEL (xfer_unit.flags); /* the printer model number */
|
||||
OUTBOUND_SET signals;
|
||||
uint32 new_status = 0;
|
||||
t_stat result = SCPE_OK;
|
||||
|
@ -3263,7 +3284,7 @@ offline_pending = FALSE; /* cancel any pending of
|
|||
tape_fault = FALSE; /* clear any tape fault */
|
||||
paper_fault = ! (xfer_unit.flags & UNIT_ATT); /* and set paper fault if out of paper */
|
||||
|
||||
if (paper_fault) /* if a paper fault exists */
|
||||
if (paper_fault && print_props [model].not_ready) /* if paper is out and the printer reports it separately */
|
||||
new_status |= ST_NOT_READY; /* then set not-ready status */
|
||||
|
||||
if (xfer_unit.flags & UNIT_OFFLINE) { /* if the printer is offline */
|
||||
|
@ -3318,9 +3339,13 @@ return NO_SIGNALS; /* no special control ac
|
|||
|
||||
static t_bool lp_set_alarm (UNIT *uptr)
|
||||
{
|
||||
const PRINTER_TYPE model = GET_MODEL (uptr->flags); /* the printer model number */
|
||||
|
||||
if (lp_set_locality (uptr, Offline)) { /* if the printer went offline */
|
||||
set_device_status (ST_NOT_READY, ST_NOT_READY); /* then set the printer not-ready */
|
||||
return TRUE; /* and return completion success */
|
||||
if (print_props [model].not_ready) /* then if the printer reports ready status separately */
|
||||
set_device_status (ST_NOT_READY, ST_NOT_READY); /* then set the printer not-ready */
|
||||
|
||||
return TRUE; /* return completion success */
|
||||
}
|
||||
|
||||
else /* otherwise the offline request is pending */
|
||||
|
@ -3367,7 +3392,7 @@ if (printer_state == Offline) { /* if the printer is goi
|
|||
&& sim_is_active (uptr) == FALSE) { /* and the printer is idle */
|
||||
uptr->flags |= UNIT_OFFLINE; /* then set the printer offline now */
|
||||
|
||||
signals = set_device_status (ST_ONLINE, 0); /* then set the printer offline now */
|
||||
signals = set_device_status (ST_ONLINE, 0); /* update the printer status */
|
||||
|
||||
device_flag_in = TRUE; /* DEMAND denies while the printer is offline */
|
||||
device_end_in = TRUE; /* DEV END asserts while the printer is offline */
|
||||
|
@ -3377,7 +3402,7 @@ if (printer_state == Offline) { /* if the printer is goi
|
|||
|
||||
else { /* otherwise the request must wait */
|
||||
offline_pending = TRUE; /* until the line is printed */
|
||||
return FALSE; /* that the command is not complete */
|
||||
return FALSE; /* and the command is not complete */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
SIMH/HP 3000 RELEASE NOTES
|
||||
==========================
|
||||
Last update: 2017-01-23
|
||||
Last update: 2017-04-30
|
||||
|
||||
|
||||
This file documents the release history of the Hewlett-Packard 3000 simulator.
|
||||
|
@ -176,6 +176,133 @@ the MPE version used:
|
|||
|
||||
|
||||
|
||||
=====================
|
||||
Release 5, 2017-04-30
|
||||
=====================
|
||||
|
||||
This release of the HP 3000 simulator does not add any new features.
|
||||
|
||||
|
||||
--------------------
|
||||
Implementation Notes
|
||||
--------------------
|
||||
|
||||
- The 2607 line printer simulation now defers an out-of-paper alarm until the
|
||||
paper reaches the top-of-form position, consistent with the hardware
|
||||
behavior. The 2613/17/18 printers continue to defer only until the current
|
||||
line is printed.
|
||||
|
||||
|
||||
----------
|
||||
Bugs Fixed
|
||||
----------
|
||||
|
||||
1. PROBLEM: Host file system seek errors are not caught.
|
||||
|
||||
VERSION: Release 4.
|
||||
|
||||
OBSERVATION: The MAC/ICD disc library checks for host file system read or
|
||||
write errors and returns Uncorrectable Data Error status if an error is
|
||||
indicated. However, host file system seeks are simply assumed to succeed;
|
||||
no indication of an error is given if a call fails. A failed seek should
|
||||
be detected, and a Drive Fault (positioner error) should be returned.
|
||||
|
||||
CAUSE: Oversight.
|
||||
|
||||
RESOLUTION: Modify "position_sector" (hp_disclib.c) to test the
|
||||
"sim_fseek" call for error status and to simulate a Drive Fault (AGC error)
|
||||
if the call fails.
|
||||
|
||||
STATUS: Fixed in Release 5.
|
||||
|
||||
|
||||
2. PROBLEM: An interrupted EDIT instruction does not resume properly.
|
||||
|
||||
VERSION: Release 4.
|
||||
|
||||
OBSERVATION: The EDIT instruction is interruptible between operations. If
|
||||
an interrupt is detected, two words are pushed onto the stack before the
|
||||
interrupt handler is called. These words hold the current significance
|
||||
trigger, loop count, float character, and fill character. This allows the
|
||||
instruction to resume from the point of suspension. However, the
|
||||
significance trigger is not preserved properly; it is always clear after an
|
||||
interrupt.
|
||||
|
||||
CAUSE: The significance trigger is preserved in the MSB of the upper byte
|
||||
of the word pushed onto the stack, but a 16-bit value with the MSB set is
|
||||
used to set the upper byte. As only the lower 8 bits of the value are used
|
||||
to set the byte, the MSB is lost.
|
||||
|
||||
RESOLUTION: Modify "edit" (hp3000_cpu_cis.c) to use the full 16-bit value
|
||||
when storing the significance trigger.
|
||||
|
||||
STATUS: Fixed in Release 5.
|
||||
|
||||
|
||||
3. PROBLEM: Tracing a tape runaway error prints gibberish in the log file.
|
||||
|
||||
VERSION: Release 4.
|
||||
|
||||
OBSERVATION: Tracing tape controller commands or command initiations and
|
||||
completions reports the success or failure of calls to the simulator tape
|
||||
library, e.g., "write failed with no write ring." A call that fails with
|
||||
Tape Runaway status, such as a read across a long erase gap, should report
|
||||
that the operation "failed with tape runaway." Instead, it reports
|
||||
gibberish.
|
||||
|
||||
CAUSE: The descriptive lookup table is missing an entry for the MTSE_LEOT
|
||||
status that precedes MTSE_RUNAWAY. Attempting to look up the description
|
||||
for MTSE_RUNAWAY indexes beyond the end of the table.
|
||||
|
||||
RESOLUTION: Modify the "status_name" array (hp_tapelib.c) to include
|
||||
descriptions for all of the possible simulator tape library status returns.
|
||||
|
||||
STATUS: Fixed in Release 5.
|
||||
|
||||
|
||||
4. PROBLEM: Commanding a VFU channel that is not punched causes a simulator
|
||||
stop.
|
||||
|
||||
VERSION: Release 4.
|
||||
|
||||
OBSERVATION: A format command that specifies a slew to a VFU channel that
|
||||
is not punched causes a tape fault, and the printer goes offline. However,
|
||||
the simulator then incorrectly stops with a "System halt" message, rather
|
||||
than reflecting the "not ready" status back to MPE.
|
||||
|
||||
CAUSE: The return value from the "lp_set_alarm" routine is being passed
|
||||
back as the status of the "lp_service" call. However, the return value is
|
||||
a Boolean and is TRUE if the printer successfully went offline. When
|
||||
interpreted as a service status return value, TRUE is seen as STOP_SYSHALT
|
||||
and causes a system halt simulator stop.
|
||||
|
||||
RESOLUTION: Modify "lp_service" (hp3000_lp.c) to return SCPE_OK after the
|
||||
tape fault alarm is set, allowing the simulation to continue.
|
||||
|
||||
STATUS: Fixed in Release 5.
|
||||
|
||||
|
||||
5. PROBLEM: The 2613/17/18 printers do not ignore characters exceeding the
|
||||
line length.
|
||||
|
||||
VERSION: Release 4.
|
||||
|
||||
OBSERVATION: When characters are output in excess of the defined line
|
||||
length, the printer performs an automatic print-and-space operation and
|
||||
prints the excess characters on the following line. This operation is
|
||||
correct for the 2607 printer but not for the 2613/17/18 printers, which
|
||||
ignore output that exceeds the line length.
|
||||
|
||||
CAUSE: Excess character handling should be, but is not, model-specific.
|
||||
|
||||
RESOLUTION: Modify the "print_props" table (hp3000_lp.c) to add a field
|
||||
for automatic printing, and modify "lp_service" to check the field to
|
||||
decide if excess characters are printed or ignored.
|
||||
|
||||
STATUS: Fixed in Release 5.
|
||||
|
||||
|
||||
|
||||
=====================
|
||||
Release 4, 2017-01-08
|
||||
=====================
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* hp3000_sys.c: HP 3000 system common interface
|
||||
|
||||
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
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -23,6 +23,8 @@
|
|||
in advertising or otherwise to promote the sale, use or other dealings in
|
||||
this Software without prior written authorization from the author.
|
||||
|
||||
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
|
||||
29-Dec-16 JDB Changed the switch for STA format from -S to -T;
|
||||
changed the status mnemonic flag from REG_S to REG_T
|
||||
28-Nov-16 JDB hp_device_conflict accumulates names of active traces only
|
||||
|
@ -964,7 +966,7 @@ static t_stat parse_cpu (CONST char *cptr, t_addr address, UNIT *uptr,
|
|||
static size_t device_size = 0; /* maximum device name size */
|
||||
static size_t flag_size = 0; /* maximum debug flag name size */
|
||||
|
||||
static APC_FLAGS parse_config = apcNone; /* address parser configuration */
|
||||
static APC_FLAGS parse_config = apcNone; /* address parser configuration */
|
||||
|
||||
|
||||
/* System interface global data structures */
|
||||
|
@ -1085,7 +1087,7 @@ const char *sim_stop_messages [] = { /* an array of pointers to the s
|
|||
/* Local command table.
|
||||
|
||||
This table defines commands and command behaviors that are specific to this
|
||||
simulator. No new commands are defined, but several commands are repurposed
|
||||
simulator. One new command is defined, and several commands are repurposed
|
||||
or extended. Specifically:
|
||||
|
||||
* EXAMINE, DEPOSIT, IEXAMINE, and IDEPOSIT accept bank/offset form, implied
|
||||
|
@ -1100,6 +1102,8 @@ const char *sim_stop_messages [] = { /* an array of pointers to the s
|
|||
* LOAD and DUMP invoke the CPU cold load/cold dump facility, rather than
|
||||
loading or dumping binary files.
|
||||
|
||||
* POWER adds the ability to fail or restore power to the CPU.
|
||||
|
||||
The table is initialized with only those fields that differ from the standard
|
||||
command table. During one-time simulator initialization, the empty fields
|
||||
are filled in from the corresponding standard command table entries. This
|
||||
|
@ -1370,6 +1374,11 @@ else { /* otherwise display
|
|||
settings are used, even if the unit is a peripheral. For example,
|
||||
entering disc sector data as CPU instructions uses the CPU's address and
|
||||
data radix values, rather than the disc's values.
|
||||
|
||||
2. The "cptr" post-increments are logically ANDed with the tests for ' and "
|
||||
so that the increments are performed only if the tests succeed. The
|
||||
intent is to skip over the leading ' or " character. The increments
|
||||
themselves always succeed, so they don't affect the outcome of the tests.
|
||||
*/
|
||||
|
||||
t_stat parse_sym (CONST char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
|
||||
|
@ -1395,7 +1404,6 @@ else if (sw & SWMASK ('C') || *cptr == '"' && cptr++) /* otherwise if a ch
|
|||
else /* otherwise */
|
||||
return SCPE_ARG; /* report that the line cannot be parsed */
|
||||
|
||||
|
||||
else /* otherwise */
|
||||
return parse_cpu (cptr, addr, uptr, val, sw); /* attempt a mnemonic instruction parse */
|
||||
}
|
||||
|
@ -1607,6 +1615,10 @@ return SCPE_OK; /* return the display re
|
|||
status word is set, and the request is for a simulation stop, the
|
||||
left-hand opcode will print as dashes to indicate that it has already
|
||||
been executed.
|
||||
|
||||
2. The status return from "fprint_instruction" is always SCPE_OK for the
|
||||
stack_ops table, which is fully decoded, so the return value from
|
||||
printing the left stack opcode is not used.
|
||||
*/
|
||||
|
||||
t_stat fprint_cpu (FILE *ofile, t_value *val, uint32 radix, int32 switches)
|
||||
|
@ -1622,9 +1634,9 @@ switch (SUBOP (val [0])) { /* dispatch based on
|
|||
- strlen (stack_ops [STACKOP_A (val [0])].mnemonic), ofile);
|
||||
|
||||
else { /* otherwise */
|
||||
status = fprint_instruction (ofile, stack_ops, /* print the left operation */
|
||||
val, STACKOP_A_MASK,
|
||||
STACKOP_A_SHIFT, radix);
|
||||
(void) fprint_instruction (ofile, stack_ops, /* print the left operation */
|
||||
val, STACKOP_A_MASK, /* while discarding the status */
|
||||
STACKOP_A_SHIFT, radix);
|
||||
fputc (',', ofile); /* add a separator */
|
||||
}
|
||||
|
||||
|
@ -3172,7 +3184,8 @@ return -(t_stat) (total_bytes_used / 2 - 1); /* return the (biased) n
|
|||
if the print consumed a single-word value, or the negative number of extra
|
||||
words (beyond the first) consumed by printing the instruction is returned.
|
||||
For example, printing a symbol that resulted in two words being consumed
|
||||
(from val [0] and val [1]) would return SCPE_OK_2_WORDS (= -1).
|
||||
(from val [0] and val [1]) would return SCPE_OK_2_WORDS (= -1). If the
|
||||
supplied instruction is not in the table, SCPE_ARG is returned.
|
||||
|
||||
The classification table consists of a set of entries that are indexed by
|
||||
opcode, followed optionally by a set of entries that are searched linearly.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* hp_disclib.c: HP MAC/ICD disc controller simulator library
|
||||
|
||||
Copyright (c) 2011-2016, J. David Bryan
|
||||
Copyright (c) 2011-2017, J. David Bryan
|
||||
Copyright (c) 2004-2011, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
|
@ -24,6 +24,7 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from the authors.
|
||||
|
||||
22-Apr-17 JDB A failed sim_fseek call now causes a drive fault
|
||||
10-Oct-16 JDB Moved "hp3000_defs.h" inclusion from "hp_disclib.h"
|
||||
03-Aug-16 JDB "fmt_bitset" now allows multiple concurrent calls
|
||||
09-Jun-16 JDB Added casts for ptrdiff_t to int32 values
|
||||
|
@ -227,9 +228,9 @@
|
|||
|
||||
The drive status field contains only a subset of the status maintained by
|
||||
drives in hardware. Specifically, the Attention, Read-Only, First Status,
|
||||
and Seek Check bits are stored in the status field. The other bits (Format
|
||||
Enabled, Not Ready, and Drive Busy) are set dynamically whenever status is
|
||||
requested (the Drive Fault bit is not simulated).
|
||||
Fault, and Seek Check bits are stored in the status field. The other bits
|
||||
(Format Enabled, Not Ready, and Drive Busy) are set dynamically whenever
|
||||
status is requested.
|
||||
|
||||
Per-drive opcode and phase values allow seeks to be overlapped. For example,
|
||||
a Seek issued to unit 0 may be followed by a Read issued to unit 1. When the
|
||||
|
@ -1279,7 +1280,7 @@ static t_bool start_write (CVPTR cvptr, UNIT *uptr);
|
|||
static void end_write (CVPTR cvptr, UNIT *uptr, CNTLR_FLAG_SET flags);
|
||||
static t_bool position_sector (CVPTR cvptr, UNIT *uptr);
|
||||
static void next_sector (CVPTR cvptr, UNIT *uptr);
|
||||
static void io_error (CVPTR cvptr, UNIT *uptr);
|
||||
static void io_error (CVPTR cvptr, UNIT *uptr, CNTLR_STATUS status);
|
||||
static void set_completion (CVPTR cvptr, UNIT *uptr, CNTLR_STATUS status);
|
||||
static void clear_controller (CVPTR cvptr, CNTLR_CLEAR clear_type);
|
||||
static void idle_controller (CVPTR cvptr);
|
||||
|
@ -3528,7 +3529,7 @@ count = sim_fread (cvptr->buffer + offset, /* read the sector from
|
|||
WORDS_PER_SECTOR, uptr->fileref);
|
||||
|
||||
if (ferror (uptr->fileref)) { /* if a host file system error occurred */
|
||||
io_error (cvptr, uptr); /* then report it to the simulation console */
|
||||
io_error (cvptr, uptr, Uncorrectable_Data_Error); /* then report it to the simulation console */
|
||||
return FALSE; /* and terminate with Uncorrectable Data Error status */
|
||||
}
|
||||
|
||||
|
@ -3764,7 +3765,7 @@ sim_fwrite (cvptr->buffer + offset, sizeof (DL_BUFFER), /* write the sector to t
|
|||
WORDS_PER_SECTOR, uptr->fileref);
|
||||
|
||||
if (ferror (uptr->fileref)) /* if a host file system error occurred, then report it */
|
||||
io_error (cvptr, uptr); /* and terminate with Uncorrectable Data Error status */
|
||||
io_error (cvptr, uptr, Uncorrectable_Data_Error); /* and terminate with Uncorrectable Data Error status */
|
||||
|
||||
else if (cvptr->status != Normal_Completion) /* otherwise if a diagnostic override is present */
|
||||
end_command (cvptr, uptr, cvptr->status); /* then report the indicated status */
|
||||
|
@ -3828,9 +3829,12 @@ return;
|
|||
|
||||
If the addresses are valid, the drive is checked to ensure that it is ready
|
||||
for positioning. If it is, the file is positioned to a byte offset in the
|
||||
image file that is calculated from the CHS address. The data phase is set up
|
||||
to begin the data transfer, and the routine returns TRUE to indicate that the
|
||||
file position is set.
|
||||
image file that is calculated from the CHS address. If positioning succeeds,
|
||||
the data phase is set up to begin the data transfer, and the routine returns
|
||||
TRUE to indicate that the file position is set. If positioning fails with a
|
||||
host file system error, it is reported to the simulation console, and the
|
||||
routine returns FALSE to indicate that an AGC (drive positioner) fault
|
||||
occurred.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
@ -3900,17 +3904,24 @@ else if (uptr->flags & UNIT_UNLOAD) /* otherwise if the driv
|
|||
else { /* otherwise we are ready to move the heads */
|
||||
set_file_pos (cvptr, uptr, model); /* so calculate the new position */
|
||||
|
||||
sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set the image file position */
|
||||
if (sim_fseek (uptr->fileref, uptr->pos, SEEK_SET)) { /* set the image file position; if it failed */
|
||||
io_error (cvptr, uptr, Status_2_Error); /* then report it to the simulation console */
|
||||
|
||||
uptr->PHASE = Data_Phase; /* set up the data transfer phase */
|
||||
dl_load_unload (cvptr, uptr, FALSE); /* unload the heads */
|
||||
uptr->STATUS |= S2_FAULT; /* and set Fault status */
|
||||
}
|
||||
|
||||
if (cvptr->device->flags & DEV_REALTIME) /* if the real time mode is enabled */
|
||||
uptr->wait = cvptr->dlyptr->data_xfer /* then base the delay on the sector preamble size */
|
||||
* cmd_props [uptr->OPCODE].preamble_size;
|
||||
else /* otherwise */
|
||||
uptr->wait = cvptr->dlyptr->data_xfer; /* start the transfer with a nominal delay */
|
||||
else { /* otherwise the seek succeeded */
|
||||
uptr->PHASE = Data_Phase; /* so set up the data transfer phase */
|
||||
|
||||
return TRUE; /* report that positioning was accomplished */
|
||||
if (cvptr->device->flags & DEV_REALTIME) /* if the real time mode is enabled */
|
||||
uptr->wait = cvptr->dlyptr->data_xfer /* then base the delay on the sector preamble size */
|
||||
* cmd_props [uptr->OPCODE].preamble_size;
|
||||
else /* otherwise */
|
||||
uptr->wait = cvptr->dlyptr->data_xfer; /* start the transfer with a nominal delay */
|
||||
|
||||
return TRUE; /* report that positioning was accomplished */
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE; /* positioning failed or was deferred */
|
||||
|
@ -4085,22 +4096,24 @@ return TRUE; /* the seek is underway
|
|||
}
|
||||
|
||||
|
||||
/* Report an I/O error.
|
||||
/* Report a stream I/O error.
|
||||
|
||||
Errors indicated by the host file system are printed on the simulation
|
||||
console, and the current command is terminated with an Uncorrectable Data
|
||||
Error indication from the controller. The target OS will retry the
|
||||
operation; if it continues to fail, the OS will handle it appropriately.
|
||||
console, and the current command is terminated with the supplied status
|
||||
indication. The target OS will respond to the status return appropriately.
|
||||
*/
|
||||
|
||||
static void io_error (CVPTR cvptr, UNIT *uptr)
|
||||
static void io_error (CVPTR cvptr, UNIT *uptr, CNTLR_STATUS status)
|
||||
{
|
||||
cprintf ("%s simulator disc library I/O error: %s\n", /* report the error to the console */
|
||||
sim_name, strerror (errno));
|
||||
|
||||
dpprintf (cvptr->device, cvptr->device->dctrl, "Host system stream I/O call failed: %s\n",
|
||||
strerror (errno));
|
||||
|
||||
clearerr (uptr->fileref); /* clear the error */
|
||||
|
||||
end_command (cvptr, uptr, Uncorrectable_Data_Error); /* terminate the command with a bad data error */
|
||||
end_command (cvptr, uptr, status); /* terminate the command with the supplied status */
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -4174,9 +4187,9 @@ return;
|
|||
|
||||
Implementation notes:
|
||||
|
||||
1. The Attention, Read-Only, First Status, and Seek Check bits are stored
|
||||
in the unit status field. The other status bits are determined
|
||||
dynamically (the Drive Fault bit is not simulated).
|
||||
1. The Attention, Read-Only, First Status, Fault, and Seek Check bits are
|
||||
stored in the unit status field. The other status bits are determined
|
||||
dynamically.
|
||||
|
||||
2. The Drive Busy bit is set if the unit is in the seek phase. In hardware,
|
||||
this bit indicates that the heads are not positioned over a track, i.e.,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* hp_disclib.h: HP MAC/ICD disc controller simulator library definitions
|
||||
/* hp_disclib.h: HP MAC/ICD disc controller simulator library declarations
|
||||
|
||||
Copyright (c) 2011-2016, J. David Bryan
|
||||
Copyright (c) 2004-2011, Robert M. Supnik
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* hp_tapelib.c: HP magnetic tape controller simulator library
|
||||
|
||||
Copyright (c) 2013-2016, J. David Bryan
|
||||
Copyright (c) 2013-2017, J. David Bryan
|
||||
Copyright (c) 2004-2011, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
|
@ -24,6 +24,7 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from the authors.
|
||||
|
||||
22-Apr-17 JDB Corrected status_name array element count
|
||||
10-Oct-16 JDB Moved "hp3000_defs.h" inclusion from "hp_tapelib.h"
|
||||
01-Jul-16 JDB Changed tl_attach to reset the event delay times pointer
|
||||
09-Jun-16 JDB Added casts for ptrdiff_t to int32 values
|
||||
|
@ -801,6 +802,7 @@ static const char *status_name [] = { /* indexed by MTSE value */
|
|||
"terminated with end of medium seen", /* MTSE_EOM */
|
||||
"succeeded with data error", /* MTSE_RECE */
|
||||
"failed with no write ring", /* MTSE_WRP */
|
||||
"failed with logical end of tape", /* MTSE_LEOT */
|
||||
"failed with tape runaway" /* MTSE_RUNAWAY */
|
||||
};
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* hp_tapelib.h: HP magnetic tape controller simulator library definitions
|
||||
/* hp_tapelib.h: HP magnetic tape controller simulator library declarations
|
||||
|
||||
Copyright (c) 2013-2016, J. David Bryan
|
||||
Copyright (c) 2004-2011, Robert M. Supnik
|
||||
|
|
Binary file not shown.
Loading…
Add table
Reference in a new issue