HP3000, HP2100: Updated simulators from Dave Bryan
- This release of the HP 3000 simulator adds the following device simulation: - 30209A Line Printer Controller with One 2607/13/17/18 Line Printer The simulation supports the use of custom VFU tape images, as well as the built-in HP-standard VFU tape. The simulated device name is "LP". The full set of configurable options is detailed in a new section of the HP 3000 Simulator User's Guide. In addition, the preconfigured MPE-V/R disc image has been updated to add the following features: - The MPE cold load command files attach the line printer to the "lp.txt" output file and specify the "-n" option to clear the file before use. - Preinstalled User-Defined Commands (UDCs) provide access to the COBOL 74 compiler with the MPE-V/E :COBOLII, :COBOLIIPREP, and :COBOLIIGO commands, and to the COBOL 85 compiler with :COBOLIIX, :COBOLIIXPREP, and :COBOLIIXGO. However, see the implementation note below. -------------------- Implementation Notes -------------------- - MPE requires a line printer, so it is recommended that the MPE startup simulator command file include an ATTACH LP <filename> command to load paper into the printer before cold loading. If the printer is not attached, it will appear to MPE to be out of paper. - The line printer terminates each print line with an HP-standard CR/LF pair. If the output file is to be retained as a text file on a Unix system, removal of the carriage returns, e.g., via the "dos2unix" utility, may be desirable. - The simulator currently does not provide the HP 32234A COBOL II firmware instructions, so programs generated by the COBOLII compiler will abort at run time with an "ILLEGAL INSTRUCTION" error. Programs generated by the COBOL compiler do not use these instructions and therefore are not affected. ---------- Bugs Fixed ---------- 1. PROBLEM: The effective address of a byte pointer with a negative index is calculated incorrectly. VERSION: Release 1 OBSERVATION: Defining a :WELCOME message in MPE appears to work, but when the next logon attempts to print the message, an infinite number of CRLFs are printed instead. CAUSE: The welcome message is stored in an extra data segment. The format for each message line is a line length stored in the lower byte of the word preceding the message string. The code defines BYTE POINTER NEXTLINE and points NEXTLINE to the first message character. The line length is set with NEXTLINE(-1) := IOCOUNT. This generates a LOAD <IOCOUNT> ; LDXN 1 ; STB <NEXTLINE>,I,X sequence. In the "cpu_ea" routine, the indexing adds the X register value (-1) to the byte pointer (NEXTLINE). This causes an overflow that is not masked to 16 bits. For a word access, this displacement is added to the base register and then masked to 16 bits, which gives the correct value. However, for byte accesses, the displacement is divided by 2 and then added, and the sum is masked. Dividing by 2 shifts the overflow bit into the MSB, causing the addition result to be off by 32K. The STB goes to the wrong location, the original zero in the length byte location is retained, and when the welcome message is printed, a zero-length line is printed, and the byte pointer is incremented by zero, so the null line is printed forever. RESOLUTION: Modify "cpu_ea" (hp3000_cpu.c) to mask indexed displacements to 16 bits after adding the X register value. STATUS: Fixed in Release 2. 2. PROBLEM: An SMSK instruction may clear the interrupt mask flip-flop of a device that specifies that it is should be "always enabled." VERSION: Release 1 OBSERVATION: If the TOS word is zero, an SMSK instruction will clear the interrupt mask flip-flop of a device whose mask jumper is set to "E" (always enabled). CAUSE: In response to a DSETMASK signal, device interfaces set their interrupt mask flip-flops by "anding" the incoming data word with the interrupt mask jumper setting. The jumper setting value for "always enabled" is %177777, which sets the mask flip-flop in all cases, except when the data word is zero. RESOLUTION: Modify hp3000_atc.c, hp3000_ds.c, and hp3000_ms.c to set their mask flip-flops unconditionally if the jumper setting is "E". STATUS: Fixed in Release 2. 3. PROBLEM: The "SET <dev> INTMASK=<n>" command sets the wrong bit in the device interface's interrupt mask jumper setting. VERSION: Release 1 OBSERVATION: The interrupt mask jumper on a device interface is set by specifying the mask bit number in a "SET <dev> INTMASK=<n>" command. This sets a bit in the device's interrupt mask jumper word corresponding to the bit number requested. However, the bit numbering is incorrect; setting the jumper for bit 15, for example, sets bit 0 of the jumper word. Therefore, the interface's mask flip-flop is not set as expected when an SMSK instruction is executed. CAUSE: The bit numbers were counted from the wrong end of the word. RESOLUTION: Modify "hp_set_dib" and "hp_show_dib" (hp3000_sys.c) to number the bits from the MSB instead of the LSB. STATUS: Fixed in Release 2. 4. PROBLEM: The Multiplexer Channel is not generating the ACKSR signal correctly. VERSION: Release 1 OBSERVATION: The line printer controller hangs when an SIO chained write is performed. The first programmed write completes normally, but the second does not start. The channel is waiting for a service request that does not occur. CAUSE: The service request from the last write of the first block transfer is being cleared by an ACKSR generated by the Multiplexer Channel when it performs the IOCW fetch in State A for the second write request. The channel should omit this ACKSR when the previous I/O order was a chained read or write. However, the simulator is testing the order just fetched (Write) instead of the order that has just completed (Write Chained). RESOLUTION: Modify "mpx_service" (hp3000_mpx.c) to test the correct I/O order in State A. STATUS: Fixed in Release 2.
This commit is contained in:
parent
73a9475c9d
commit
07f99bb8c3
29 changed files with 5719 additions and 1269 deletions
|
@ -1,6 +1,6 @@
|
|||
/* hp2100_cpu6.c: HP 1000 RTE-6/VM OS instructions
|
||||
|
||||
Copyright (c) 2006-2014, J. David Bryan
|
||||
Copyright (c) 2006-2016, J. David Bryan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -25,6 +25,7 @@
|
|||
|
||||
CPU6 RTE-6/VM OS instructions
|
||||
|
||||
17-May-16 JDB Set local variable instead of call parameter for .SIP test
|
||||
24-Dec-14 JDB Added casts for explicit downward conversions
|
||||
18-Mar-13 JDB Use MP abort handler declaration in hp2100_cpu.h
|
||||
09-May-12 JDB Separated assignments from conditional expressions
|
||||
|
@ -380,7 +381,7 @@ t_stat cpu_rte_os (uint32 IR, uint32 intrq, uint32 iotrap)
|
|||
t_stat reason = SCPE_OK;
|
||||
OPS op;
|
||||
OP_PAT pattern;
|
||||
uint32 entry, count, cp, sa, da, i, ma, eqta;
|
||||
uint32 entry, count, cp, sa, da, i, ma, eqta, irq;
|
||||
uint16 vectors, save_area, priv_fence, eoreg, eqt, key;
|
||||
char test[6], target[6];
|
||||
jmp_buf mp_handler;
|
||||
|
@ -644,16 +645,16 @@ switch (entry) { /* decode IR<3:0> */
|
|||
|
||||
case 010: /* .SIP 105350 (OP_N) */
|
||||
reason = iogrp (STF_0, iotrap); /* turn interrupt system on */
|
||||
intrq = calc_int (); /* check for interrupt requests */
|
||||
irq = calc_int (); /* check for interrupt requests */
|
||||
reason = iogrp (CLF_0, iotrap); /* turn interrupt system off */
|
||||
|
||||
if (intrq) /* was interrupt pending? */
|
||||
if (irq) /* was interrupt pending? */
|
||||
PC = (PC + 1) & VAMASK; /* P+1 return for pending IRQ */
|
||||
/* P+0 return for no pending IRQ */
|
||||
if (debug_print) /* debugging? */
|
||||
fprintf (sim_deb, /* print return registers */
|
||||
", CIR = %02o, return = P+%d",
|
||||
intrq, PC - (err_PC + 1));
|
||||
irq, PC - (err_PC + 1));
|
||||
break;
|
||||
|
||||
case 011: /* .YLD 105351 (OP_C) */
|
||||
|
|
|
@ -26,7 +26,11 @@
|
|||
|
||||
ATCD,ATCC HP 30032B Asynchronous Terminal Controller
|
||||
|
||||
26-Jun-16 JDB Removed tmxr_set_modem_control_passthru call in atcc_reset
|
||||
09-Jun-16 JDB Added casts for ptrdiff_t to int32 values
|
||||
16-May-16 JDB Fixed interrupt mask setting
|
||||
13-May-16 JDB Modified for revised SCP API function parameter types
|
||||
21-Mar-16 JDB Changed uint16 types to HP_WORD
|
||||
26-Aug-15 JDB First release version
|
||||
31-Jul-15 JDB Passes the terminal control diagnostic (D438A)
|
||||
11-Aug-14 JDB Passes the terminal data diagnostic (D427A)
|
||||
|
@ -315,7 +319,7 @@
|
|||
#define NUL '\000' /* null */
|
||||
#define ENQ '\005' /* enquire */
|
||||
#define ACK '\006' /* acknowledge */
|
||||
#define ASCII_MASK 000177 /* 7-bit ASCII character set mask */
|
||||
#define ASCII_MASK 000177u /* 7-bit ASCII character set mask */
|
||||
|
||||
#define GEN_ACK (TMXR_VALID | SCPE_KFLAG | ACK) /* a generated ACK character */
|
||||
|
||||
|
@ -330,14 +334,14 @@
|
|||
|
||||
/* Debug flags */
|
||||
|
||||
#define DEB_CSRW (1 << 0) /* trace command initiations and completions */
|
||||
#define DEB_XFER (1 << 1) /* trace data receptions and transmissions */
|
||||
#define DEB_IOB (1 << 2) /* trace I/O bus signals and data words */
|
||||
#define DEB_SERV (1 << 3) /* trace channel service scheduling calls */
|
||||
#define DEB_PSERV (1 << 4) /* trace poll service scheduling calls */
|
||||
#define DEB_CSRW (1u << 0) /* trace command initiations and completions */
|
||||
#define DEB_XFER (1u << 1) /* trace data receptions and transmissions */
|
||||
#define DEB_IOB (1u << 2) /* trace I/O bus signals and data words */
|
||||
#define DEB_SERV (1u << 3) /* trace channel service scheduling calls */
|
||||
#define DEB_PSERV (1u << 4) /* trace poll service scheduling calls */
|
||||
|
||||
|
||||
/* Per-unit state */
|
||||
/* Common per-unit multiplexer channel state variables */
|
||||
|
||||
#define recv_time u3 /* realistic receive time in event ticks */
|
||||
#define send_time u4 /* realistic send time in event ticks */
|
||||
|
@ -349,8 +353,8 @@
|
|||
#define DEV_DIAG_SHIFT (DEV_V_UF + 0) /* diagnostic loopback */
|
||||
#define DEV_REALTIME_SHIFT (DEV_V_UF + 1) /* timing mode is realistic */
|
||||
|
||||
#define DEV_DIAG (1 << DEV_DIAG_SHIFT) /* diagnostic mode flag */
|
||||
#define DEV_REALTIME (1 << DEV_REALTIME_SHIFT) /* realistic timing flag */
|
||||
#define DEV_DIAG (1u << DEV_DIAG_SHIFT) /* diagnostic mode flag */
|
||||
#define DEV_REALTIME (1u << DEV_REALTIME_SHIFT) /* realistic timing flag */
|
||||
|
||||
|
||||
/* Unit flags */
|
||||
|
@ -359,9 +363,9 @@
|
|||
#define UNIT_LOCALACK_SHIFT (TTUF_V_UF + 1) /* local ACK mode */
|
||||
#define UNIT_MODEM_SHIFT (TTUF_V_UF + 2) /* modem control */
|
||||
|
||||
#define UNIT_CAPSLOCK (1 << UNIT_CAPSLOCK_SHIFT) /* caps lock is down flag */
|
||||
#define UNIT_LOCALACK (1 << UNIT_LOCALACK_SHIFT) /* ENQ/ACK mode is local flag */
|
||||
#define UNIT_MODEM (1 << UNIT_MODEM_SHIFT) /* channel connects to a data set flag */
|
||||
#define UNIT_CAPSLOCK (1u << UNIT_CAPSLOCK_SHIFT) /* caps lock is down flag */
|
||||
#define UNIT_LOCALACK (1u << UNIT_LOCALACK_SHIFT) /* ENQ/ACK mode is local flag */
|
||||
#define UNIT_MODEM (1u << UNIT_MODEM_SHIFT) /* channel connects to a data set flag */
|
||||
|
||||
|
||||
/* Unit references */
|
||||
|
@ -388,11 +392,11 @@ typedef enum {
|
|||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
*/
|
||||
|
||||
#define DCN_MR 0100000 /* (M) master reset */
|
||||
#define DCN_IRQ_RESET 0040000 /* (R) interrupt request reset */
|
||||
#define DCN_CHAN_MASK 0037000 /* channel number mask */
|
||||
#define DCN_ENABLE 0000002 /* (E) enable store of preceding data or parameter word */
|
||||
#define DCN_ACKN 0000001 /* (A) acknowledge interrupt */
|
||||
#define DCN_MR 0100000u /* (M) master reset */
|
||||
#define DCN_IRQ_RESET 0040000u /* (R) interrupt request reset */
|
||||
#define DCN_CHAN_MASK 0037000u /* channel number mask */
|
||||
#define DCN_ENABLE 0000002u /* (E) enable store of preceding data or parameter word */
|
||||
#define DCN_ACKN 0000001u /* (A) acknowledge interrupt */
|
||||
|
||||
#define DCN_CHAN_SHIFT 9 /* channel number alignment shift */
|
||||
|
||||
|
@ -429,13 +433,13 @@ static const BITSET_FORMAT tdi_control_format = /* names, offset, direct
|
|||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
*/
|
||||
|
||||
#define DST_DIO_OK 0040000 /* (D) direct I/O OK to use */
|
||||
#define DST_IRQ 0020000 /* (I) interrupt requested */
|
||||
#define DST_COMPLETE 0004000 /* (C) operation is complete and channel is ready to interrupt */
|
||||
#define DST_SEND_IRQ 0002000 /* (R) interrupt request is for character sent */
|
||||
#define DST_CHAR_LOST 0001000 /* (L) character was lost */
|
||||
#define DST_BREAK 0000400 /* (B) break occurred */
|
||||
#define DST_DIAGNOSE 0000000 /* status is from an auxiliary channel (not used on ATC) */
|
||||
#define DST_DIO_OK 0040000u /* (D) direct I/O OK to use */
|
||||
#define DST_IRQ 0020000u /* (I) interrupt requested */
|
||||
#define DST_COMPLETE 0004000u /* (C) operation is complete and channel is ready to interrupt */
|
||||
#define DST_SEND_IRQ 0002000u /* (R) interrupt request is for character sent */
|
||||
#define DST_CHAR_LOST 0001000u /* (L) character was lost */
|
||||
#define DST_BREAK 0000400u /* (B) break occurred */
|
||||
#define DST_DIAGNOSE 0000000u /* status is from an auxiliary channel (not used on ATC) */
|
||||
|
||||
#define DST_CHAN(n) 0 /* position channel number for status (not used on ATC) */
|
||||
|
||||
|
@ -480,14 +484,14 @@ static const BITSET_FORMAT tdi_status_format = /* names, offset, direct
|
|||
the number of stop bits from the receive parameter word.
|
||||
*/
|
||||
|
||||
#define DPI_IS_PARAM 0100000 /* value is a parameter (always set) */
|
||||
#define DPI_IS_SEND 0040000 /* (R) value is a send parameter */
|
||||
#define DPI_ENABLE_IRQ 0020000 /* (I) enable interrupt requests */
|
||||
#define DPI_ENABLE_PARITY 0010000 /* (E) enable parity for send */
|
||||
#define DPI_ENABLE_ECHO 0010000 /* (E) enable echo for receive */
|
||||
#define DPI_DIAGNOSE 0004000 /* (D) connect to the auxiliary channels */
|
||||
#define DPI_SIZE_MASK 0003400 /* character size mask */
|
||||
#define DPI_RATE_MASK 0000377 /* baud rate mask */
|
||||
#define DPI_IS_PARAM 0100000u /* value is a parameter (always set) */
|
||||
#define DPI_IS_SEND 0040000u /* (R) value is a send parameter */
|
||||
#define DPI_ENABLE_IRQ 0020000u /* (I) enable interrupt requests */
|
||||
#define DPI_ENABLE_PARITY 0010000u /* (E) enable parity for send */
|
||||
#define DPI_ENABLE_ECHO 0010000u /* (E) enable echo for receive */
|
||||
#define DPI_DIAGNOSE 0004000u /* (D) connect to the auxiliary channels */
|
||||
#define DPI_SIZE_MASK 0003400u /* character size mask */
|
||||
#define DPI_RATE_MASK 0000377u /* baud rate mask */
|
||||
|
||||
#define DPI_CHAR_CONFIG (DPI_SIZE_MASK | DPI_RATE_MASK) /* character configuration data */
|
||||
|
||||
|
@ -499,7 +503,7 @@ static const BITSET_FORMAT tdi_status_format = /* names, offset, direct
|
|||
|
||||
#define BAUD_RATE(p) ((28800 / (DPI_BAUD_RATE (p) + 1) + 1) / 2)
|
||||
|
||||
#define PAD_BITS(c) (~((1 << bits_per_char [DPI_CHAR_SIZE (c)] - 2) - 1))
|
||||
#define PAD_BITS(c) (~((1u << bits_per_char [DPI_CHAR_SIZE (c)] - 2) - 1))
|
||||
|
||||
|
||||
static const uint32 bits_per_char [8] = { /* bits per character, indexed by DPI_CHAR_SIZE encoding */
|
||||
|
@ -525,10 +529,10 @@ static const BITSET_FORMAT tdi_parameter_format = /* names, offset, direct
|
|||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
*/
|
||||
|
||||
#define DDS_IS_SEND 0040000 /* value is a send data word (always set) */
|
||||
#define DDS_SYNC 0004000 /* (S) sync */
|
||||
#define DDS_DATA_MASK 0003777 /* data value mask */
|
||||
#define DDS_PARITY 0000200 /* data parity bit */
|
||||
#define DDS_IS_SEND 0040000u /* value is a send data word (always set) */
|
||||
#define DDS_SYNC 0004000u /* (S) sync */
|
||||
#define DDS_DATA_MASK 0003777u /* data value mask */
|
||||
#define DDS_PARITY 0000200u /* data parity bit */
|
||||
|
||||
#define DDS_MARK (DDS_SYNC | DDS_DATA_MASK) /* all-mark character */
|
||||
|
||||
|
@ -554,9 +558,9 @@ static const BITSET_FORMAT tdi_output_data_format = /* names, offset, direct
|
|||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
*/
|
||||
|
||||
#define DDR_CHAN_MASK 0174000 /* channel number mask */
|
||||
#define DDR_PARITY 0002000 /* (P) computed parity bit */
|
||||
#define DDR_DATA_MASK 0001777 /* data value mask */
|
||||
#define DDR_CHAN_MASK 0174000u /* channel number mask */
|
||||
#define DDR_PARITY 0002000u /* (P) computed parity bit */
|
||||
#define DDR_DATA_MASK 0001777u /* data value mask */
|
||||
|
||||
#define DDR_CHAN_SHIFT 11 /* channel number alignment shift */
|
||||
#define DDR_DATA_SHIFT 0 /* data alignment shift */
|
||||
|
@ -584,24 +588,24 @@ static const BITSET_FORMAT tdi_input_data_format = /* names, offset, direct
|
|||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
*/
|
||||
|
||||
#define CCN_MR 0100000 /* (M) master reset */
|
||||
#define CCN_IRQ_RESET 0040000 /* (R) interrupt request reset */
|
||||
#define CCN_SCAN 0020000 /* (S) scan enable */
|
||||
#define CCN_UPDATE 0010000 /* (U) update enable */
|
||||
#define CCN_CHAN_MASK 0007400 /* channel number mask */
|
||||
#define CCN_ECX_MASK 0000300 /* control output enable mask */
|
||||
#define CCN_EC2 0000200 /* (W) C2 output enable */
|
||||
#define CCN_EC1 0000100 /* (X) C1 output enable */
|
||||
#define CCN_CX_MASK 0000060 /* output mask */
|
||||
#define CCN_C2 0000040 /* (Q) C2 output [RTS] */
|
||||
#define CCN_C1 0000020 /* (T) C1 output [DTR] */
|
||||
#define CCN_STAT_MASK 0000017 /* status RAM mask */
|
||||
#define CCN_ESX_MASK 0000014 /* status interrupt enable mask */
|
||||
#define CCN_ES2 0000010 /* (Y) S2 interrupt enable */
|
||||
#define CCN_ES1 0000004 /* (Z) S1 interrupt enable */
|
||||
#define CCN_SX_MASK 0000003 /* status mask */
|
||||
#define CCN_S2 0000002 /* (C) S2 status [DCD]*/
|
||||
#define CCN_S1 0000001 /* (D) S1 status [DSR] */
|
||||
#define CCN_MR 0100000u /* (M) master reset */
|
||||
#define CCN_IRQ_RESET 0040000u /* (R) interrupt request reset */
|
||||
#define CCN_SCAN 0020000u /* (S) scan enable */
|
||||
#define CCN_UPDATE 0010000u /* (U) update enable */
|
||||
#define CCN_CHAN_MASK 0007400u /* channel number mask */
|
||||
#define CCN_ECX_MASK 0000300u /* control output enable mask */
|
||||
#define CCN_EC2 0000200u /* (W) C2 output enable */
|
||||
#define CCN_EC1 0000100u /* (X) C1 output enable */
|
||||
#define CCN_CX_MASK 0000060u /* output mask */
|
||||
#define CCN_C2 0000040u /* (Q) C2 output [RTS] */
|
||||
#define CCN_C1 0000020u /* (T) C1 output [DTR] */
|
||||
#define CCN_STAT_MASK 0000017u /* status RAM mask */
|
||||
#define CCN_ESX_MASK 0000014u /* status interrupt enable mask */
|
||||
#define CCN_ES2 0000010u /* (Y) S2 interrupt enable */
|
||||
#define CCN_ES1 0000004u /* (Z) S1 interrupt enable */
|
||||
#define CCN_SX_MASK 0000003u /* status mask */
|
||||
#define CCN_S2 0000002u /* (C) S2 status [DCD]*/
|
||||
#define CCN_S1 0000001u /* (D) S1 status [DSR] */
|
||||
|
||||
#define CCN_CHAN_SHIFT 8 /* channel number alignment shift */
|
||||
#define CCN_CX_SHIFT 4 /* control alignment shift */
|
||||
|
@ -644,19 +648,19 @@ static const BITSET_FORMAT tci_control_format = /* names, offset, direct
|
|||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
*/
|
||||
|
||||
#define CST_DIO_OK 0040000 /* direct I/O OK to use (always set) */
|
||||
#define CST_IRQ 0020000 /* (I) interrupt request */
|
||||
#define CST_ON 0010000 /* (always set) */
|
||||
#define CST_CHAN_MASK 0007400 /* channel number mask */
|
||||
#define CST_IX_MASK 0000060 /* status interrupt mask */
|
||||
#define CST_I2 0000040 /* (J) S2 interrupt */
|
||||
#define CST_I1 0000020 /* (K) S1 interrupt */
|
||||
#define CST_ESX_MASK 0000014 /* status interrupt enable mask */
|
||||
#define CST_ES2 0000010 /* (Y) S2 interrupt enable */
|
||||
#define CST_ES1 0000004 /* (Z) S1 interrupt enable */
|
||||
#define CST_SX_MASK 0000003 /* status mask */
|
||||
#define CST_S2 0000002 /* (C) S2 status [DCD] */
|
||||
#define CST_S1 0000001 /* (D) S1 status [DSR] */
|
||||
#define CST_DIO_OK 0040000u /* direct I/O OK to use (always set) */
|
||||
#define CST_IRQ 0020000u /* (I) interrupt request */
|
||||
#define CST_ON 0010000u /* (always set) */
|
||||
#define CST_CHAN_MASK 0007400u /* channel number mask */
|
||||
#define CST_IX_MASK 0000060u /* status interrupt mask */
|
||||
#define CST_I2 0000040u /* (J) S2 interrupt */
|
||||
#define CST_I1 0000020u /* (K) S1 interrupt */
|
||||
#define CST_ESX_MASK 0000014u /* status interrupt enable mask */
|
||||
#define CST_ES2 0000010u /* (Y) S2 interrupt enable */
|
||||
#define CST_ES1 0000004u /* (Z) S1 interrupt enable */
|
||||
#define CST_SX_MASK 0000003u /* status mask */
|
||||
#define CST_S2 0000002u /* (C) S2 status [DCD] */
|
||||
#define CST_S1 0000001u /* (D) S1 status [DSR] */
|
||||
|
||||
#define CST_CHAN_SHIFT 8 /* channel number alignment shift */
|
||||
#define CST_IX_SHIFT 4 /* status interrupt alignment shift */
|
||||
|
@ -712,12 +716,12 @@ t_bool atc_is_polling = TRUE; /* TRUE if the ATC is polling fo
|
|||
|
||||
/* TDI interface state */
|
||||
|
||||
static uint16 tdi_control_word = 0; /* control word */
|
||||
static uint16 tdi_status_word = 0; /* status word */
|
||||
static uint16 tdi_read_word = 0; /* read word */
|
||||
static uint16 tdi_write_word = 0; /* write word */
|
||||
static HP_WORD tdi_control_word = 0; /* control word */
|
||||
static HP_WORD tdi_status_word = 0; /* status word */
|
||||
static HP_WORD tdi_read_word = 0; /* read word */
|
||||
static HP_WORD tdi_write_word = 0; /* write word */
|
||||
|
||||
static FLIP_FLOP tdi_interrupt_mask = CLEAR; /* interrupt mask flip-flop */
|
||||
static FLIP_FLOP tdi_interrupt_mask = SET; /* interrupt mask flip-flop */
|
||||
static FLIP_FLOP tdi_data_flag = CLEAR; /* data flag */
|
||||
|
||||
static int32 fast_data_time = FAST_IO_TIME; /* fast receive/send time */
|
||||
|
@ -725,22 +729,22 @@ static int32 fast_data_time = FAST_IO_TIME; /* fast receive/send time */
|
|||
|
||||
/* TDI per-channel state */
|
||||
|
||||
static uint16 recv_status [RECV_CHAN_COUNT]; /* receive status words */
|
||||
static uint16 recv_param [RECV_CHAN_COUNT]; /* receive parameter words */
|
||||
static uint16 recv_buffer [RECV_CHAN_COUNT]; /* receive character buffers */
|
||||
static HP_WORD recv_status [RECV_CHAN_COUNT]; /* receive status words */
|
||||
static HP_WORD recv_param [RECV_CHAN_COUNT]; /* receive parameter words */
|
||||
static HP_WORD recv_buffer [RECV_CHAN_COUNT]; /* receive character buffers */
|
||||
|
||||
static uint16 send_status [SEND_CHAN_COUNT]; /* send status words */
|
||||
static uint16 send_param [SEND_CHAN_COUNT]; /* send parameter words */
|
||||
static uint16 send_buffer [SEND_CHAN_COUNT]; /* send character buffers */
|
||||
static HP_WORD send_status [SEND_CHAN_COUNT]; /* send status words */
|
||||
static HP_WORD send_param [SEND_CHAN_COUNT]; /* send parameter words */
|
||||
static HP_WORD send_buffer [SEND_CHAN_COUNT]; /* send character buffers */
|
||||
|
||||
|
||||
/* TCI interface state */
|
||||
|
||||
static uint16 tci_control_word = 0; /* control word */
|
||||
static uint16 tci_status_word = 0; /* status word */
|
||||
static uint32 tci_cntr = 0; /* channel counter */
|
||||
static HP_WORD tci_control_word = 0; /* control word */
|
||||
static HP_WORD tci_status_word = 0; /* status word */
|
||||
static uint32 tci_cntr = 0; /* channel counter */
|
||||
|
||||
static FLIP_FLOP tci_interrupt_mask = CLEAR; /* interrupt mask flip-flop */
|
||||
static FLIP_FLOP tci_interrupt_mask = SET; /* interrupt mask flip-flop */
|
||||
static FLIP_FLOP tci_scan = CLEAR; /* scanning enabled flip-flop */
|
||||
|
||||
|
||||
|
@ -773,15 +777,15 @@ static void tdi_set_interrupt (void);
|
|||
static void tdi_master_reset (void);
|
||||
static void tci_master_reset (void);
|
||||
|
||||
static t_stat line_service (UNIT *uptr);
|
||||
static t_stat poll_service (UNIT *uptr);
|
||||
static t_stat activate_unit (UNIT *uptr, ACTIVATOR reason);
|
||||
static uint32 service_time (uint16 control, ACTIVATOR reason);
|
||||
static void store (uint16 control, uint16 data);
|
||||
static void receive (int32 channel, int32 data, t_bool loopback);
|
||||
static void diagnose (uint16 control, int32 data);
|
||||
static void scan_channels (int32 channel);
|
||||
static uint16 scan_status (void);
|
||||
static t_stat line_service (UNIT *uptr);
|
||||
static t_stat poll_service (UNIT *uptr);
|
||||
static t_stat activate_unit (UNIT *uptr, ACTIVATOR reason);
|
||||
static uint32 service_time (HP_WORD control, ACTIVATOR reason);
|
||||
static void store (HP_WORD control, HP_WORD data);
|
||||
static void receive (int32 channel, int32 data, t_bool loopback);
|
||||
static void diagnose (HP_WORD control, int32 data);
|
||||
static void scan_channels (int32 channel);
|
||||
static HP_WORD scan_status (void);
|
||||
|
||||
|
||||
/* ATC SCP data structures */
|
||||
|
@ -910,8 +914,8 @@ static UNIT atcc_unit [] = { /* a dummy unit to satisfy SCP r
|
|||
Implementation notes:
|
||||
|
||||
1. The TCI control and status line register definitions use the VM-defined
|
||||
FBDATA macro. This macro defines a bit slice longitudinally through an
|
||||
array.
|
||||
FBDATA macro. This macro defines a flag that is replicated in the same
|
||||
bit position in each element of an array.
|
||||
*/
|
||||
|
||||
static REG atcd_reg [] = {
|
||||
|
@ -931,31 +935,31 @@ static REG atcd_reg [] = {
|
|||
{ BRDATA (SPARM, send_param, 8, 16, SEND_CHAN_COUNT) },
|
||||
{ BRDATA (SBUFR, send_buffer, 8, 16, SEND_CHAN_COUNT), REG_A },
|
||||
{ FLDATA (POLL, atc_is_polling, 0), REG_HRO },
|
||||
{ SRDATA (DIB, atcd_dib), REG_HRO },
|
||||
{ SRDATA (DIB, atcd_dib, REG_HRO) },
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static REG atcc_reg [] = {
|
||||
/* Macro Name Location Width Offset Depth Flags */
|
||||
/* ------ ------ ------------------- ----- ------ ---------- ------- */
|
||||
{ ORDATA (CNTL, tci_control_word, 16), REG_FIT },
|
||||
{ ORDATA (STAT, tci_status_word, 16), REG_FIT },
|
||||
{ DRDATA (CNTR, tci_cntr, 4) },
|
||||
{ FLDATA (SCAN, tci_scan, 0) },
|
||||
{ FLDATA (MASK, tci_interrupt_mask, 0) },
|
||||
/* Macro Name Location Width Offset Depth Flags */
|
||||
/* ------ ------ ------------------- ----- ------ ---------- ------- */
|
||||
{ ORDATA (CNTL, tci_control_word, 16), REG_FIT },
|
||||
{ ORDATA (STAT, tci_status_word, 16), REG_FIT },
|
||||
{ DRDATA (CNTR, tci_cntr, 4) },
|
||||
{ FLDATA (SCAN, tci_scan, 0) },
|
||||
{ FLDATA (MASK, tci_interrupt_mask, 0) },
|
||||
|
||||
{ FBDATA (C2, cntl_status, 5, TERM_COUNT) },
|
||||
{ FBDATA (C1, cntl_status, 4, TERM_COUNT) },
|
||||
{ FBDATA (S2, cntl_status, 1, TERM_COUNT) },
|
||||
{ FBDATA (S1, cntl_status, 0, TERM_COUNT) },
|
||||
{ FBDATA (C2, cntl_status, 5, TERM_COUNT, PV_RZRO) },
|
||||
{ FBDATA (C1, cntl_status, 4, TERM_COUNT, PV_RZRO) },
|
||||
{ FBDATA (S2, cntl_status, 1, TERM_COUNT, PV_RZRO) },
|
||||
{ FBDATA (S1, cntl_status, 0, TERM_COUNT, PV_RZRO) },
|
||||
|
||||
{ FBDATA (ES2, cntl_param, 3, TERM_COUNT) },
|
||||
{ FBDATA (ES1, cntl_param, 2, TERM_COUNT) },
|
||||
{ FBDATA (MS2, cntl_param, 1, TERM_COUNT) },
|
||||
{ FBDATA (MS1, cntl_param, 0, TERM_COUNT) },
|
||||
{ FBDATA (ES2, cntl_param, 3, TERM_COUNT, PV_RZRO) },
|
||||
{ FBDATA (ES1, cntl_param, 2, TERM_COUNT, PV_RZRO) },
|
||||
{ FBDATA (MS2, cntl_param, 1, TERM_COUNT, PV_RZRO) },
|
||||
{ FBDATA (MS1, cntl_param, 0, TERM_COUNT, PV_RZRO) },
|
||||
|
||||
{ SRDATA (DIB, atcc_dib), REG_HRO },
|
||||
{ SRDATA (DIB, atcc_dib, REG_HRO) },
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
@ -1167,11 +1171,11 @@ DEVICE atcc_dev = {
|
|||
the request.
|
||||
*/
|
||||
|
||||
static SIGNALS_DATA atcd_interface (DIB *dibptr, INBOUND_SET inbound_signals, uint16 inbound_value)
|
||||
static SIGNALS_DATA atcd_interface (DIB *dibptr, INBOUND_SET inbound_signals, HP_WORD inbound_value)
|
||||
{
|
||||
INBOUND_SIGNAL signal;
|
||||
INBOUND_SET working_set = inbound_signals;
|
||||
uint16 outbound_value = 0;
|
||||
HP_WORD outbound_value = 0;
|
||||
OUTBOUND_SET outbound_signals = NO_SIGNALS;
|
||||
|
||||
dprintf (atcd_dev, DEB_IOB, "Received data %06o with signals %s\n",
|
||||
|
@ -1184,7 +1188,7 @@ while (working_set) { /* while signals remain
|
|||
|
||||
case DCONTSTB:
|
||||
dprintf (atcd_dev, DEB_CSRW, (inbound_value & DCN_ENABLE
|
||||
? "Control is %s | channel %d\n"
|
||||
? "Control is %s | channel %u\n"
|
||||
: "Control is %s\n"),
|
||||
fmt_bitset (inbound_value, tdi_control_format),
|
||||
DCN_CHAN (inbound_value));
|
||||
|
@ -1221,7 +1225,7 @@ while (working_set) { /* while signals remain
|
|||
else /* to indicate */
|
||||
tdi_status_word &= ~DST_COMPLETE; /* whether or not a channel has completed */
|
||||
|
||||
outbound_value = (uint16) tdi_status_word; /* return the status word */
|
||||
outbound_value = tdi_status_word; /* return the status word */
|
||||
|
||||
dprintf (atcd_dev, DEB_CSRW, "Status is %s\n",
|
||||
fmt_bitset (outbound_value, tdi_status_format));
|
||||
|
@ -1233,7 +1237,7 @@ while (working_set) { /* while signals remain
|
|||
|
||||
if (DPRINTING (atcd_dev, DEB_CSRW))
|
||||
if (inbound_value & DPI_IS_PARAM)
|
||||
hp_debug (&atcd_dev, DEB_CSRW, "Parameter is %s%d bits | %d baud\n",
|
||||
hp_debug (&atcd_dev, DEB_CSRW, "Parameter is %s%u bits | %u baud\n",
|
||||
fmt_bitset (inbound_value, tdi_parameter_format),
|
||||
bits_per_char [DPI_CHAR_SIZE (inbound_value)],
|
||||
BAUD_RATE (inbound_value));
|
||||
|
@ -1248,7 +1252,7 @@ while (working_set) { /* while signals remain
|
|||
case DREADSTB:
|
||||
outbound_value = tdi_read_word; /* return the data word */
|
||||
|
||||
dprintf (atcd_dev, DEB_CSRW, "Input data is channel %d | %s%04o\n",
|
||||
dprintf (atcd_dev, DEB_CSRW, "Input data is channel %u | %s%04o\n",
|
||||
DDR_TO_CHAN (outbound_value),
|
||||
fmt_bitset (outbound_value, tdi_input_data_format),
|
||||
DDR_TO_DATA (outbound_value));
|
||||
|
@ -1282,8 +1286,11 @@ while (working_set) { /* while signals remain
|
|||
|
||||
|
||||
case DSETMASK:
|
||||
tdi_interrupt_mask = /* set the mask flip-flop */
|
||||
D_FF (dibptr->interrupt_mask & inbound_value); /* from the mask bit and the mask value */
|
||||
if (dibptr->interrupt_mask == INTMASK_E) /* if the mask is always enabled */
|
||||
tdi_interrupt_mask = SET; /* then set the mask flip-flop */
|
||||
else /* otherwise */
|
||||
tdi_interrupt_mask = D_FF (dibptr->interrupt_mask /* set the mask flip-flop if the mask bit */
|
||||
& inbound_value); /* is present in the mask value */
|
||||
|
||||
if (tdi_interrupt_mask && dibptr->interrupt_request) /* if the mask is enabled and a request is pending */
|
||||
outbound_signals |= INTREQ; /* then assert INTREQ */
|
||||
|
@ -1360,11 +1367,11 @@ return IORETURN (outbound_signals, outbound_value); /* return the outbound s
|
|||
the request.
|
||||
*/
|
||||
|
||||
static SIGNALS_DATA atcc_interface (DIB *dibptr, INBOUND_SET inbound_signals, uint16 inbound_value)
|
||||
static SIGNALS_DATA atcc_interface (DIB *dibptr, INBOUND_SET inbound_signals, HP_WORD inbound_value)
|
||||
{
|
||||
INBOUND_SIGNAL signal;
|
||||
INBOUND_SET working_set = inbound_signals;
|
||||
uint16 outbound_value = 0;
|
||||
HP_WORD outbound_value = 0;
|
||||
OUTBOUND_SET outbound_signals = NO_SIGNALS;
|
||||
int32 set_lines, clear_lines;
|
||||
|
||||
|
@ -1379,7 +1386,7 @@ while (working_set) { /* while signals remain
|
|||
case DCONTSTB:
|
||||
tci_cntr = CCN_CHAN (inbound_value); /* set the counter to the target channel */
|
||||
|
||||
dprintf (atcc_dev, DEB_CSRW, "Control is channel %d | %s\n",
|
||||
dprintf (atcc_dev, DEB_CSRW, "Control is channel %u | %s\n",
|
||||
tci_cntr, fmt_bitset (inbound_value, tci_control_format));
|
||||
|
||||
tci_control_word = inbound_value; /* save the control word */
|
||||
|
@ -1398,7 +1405,7 @@ while (working_set) { /* while signals remain
|
|||
& CCN_ECX (tci_control_word) /* that are enabled */
|
||||
& tci_control_word; /* in the control word */
|
||||
|
||||
dprintf (atcc_dev, DEB_XFER, "Channel %d line status is %s\n",
|
||||
dprintf (atcc_dev, DEB_XFER, "Channel %u line status is %s\n",
|
||||
tci_cntr, fmt_bitset (cntl_status [tci_cntr], tci_line_format));
|
||||
|
||||
if (atcc_dev.flags & DEV_DIAG) { /* if the interface is in diagnostic mode */
|
||||
|
@ -1406,7 +1413,7 @@ while (working_set) { /* while signals remain
|
|||
cntl_status [tci_cntr ^ 1] & ~CCN_SX_MASK /* back to the alternate channel */
|
||||
| CCN_CX (cntl_status [tci_cntr]); /* from the selected channel */
|
||||
|
||||
dprintf (atcc_dev, DEB_XFER, "Channel %d line status is %s\n",
|
||||
dprintf (atcc_dev, DEB_XFER, "Channel %u line status is %s\n",
|
||||
tci_cntr ^ 1, fmt_bitset (cntl_status [tci_cntr ^ 1], tci_line_format));
|
||||
}
|
||||
|
||||
|
@ -1427,7 +1434,7 @@ while (working_set) { /* while signals remain
|
|||
clear_lines |= TMXR_MDM_DTR; /* set it down */
|
||||
|
||||
if (cntl_status [tci_cntr] & DCD) /* setting DTR down will disconnect the channel */
|
||||
dprintf (atcc_dev, DEB_CSRW, "Channel %d disconnected by DTR drop\n",
|
||||
dprintf (atcc_dev, DEB_CSRW, "Channel %u disconnected by DTR drop\n",
|
||||
tci_cntr);
|
||||
}
|
||||
|
||||
|
@ -1458,9 +1465,9 @@ while (working_set) { /* while signals remain
|
|||
if (dibptr->interrupt_request == SET) /* reflect the interrupt request value */
|
||||
tci_status_word |= CST_IRQ; /* in the status word */
|
||||
|
||||
outbound_value = (uint16) tci_status_word; /* return the status word */
|
||||
outbound_value = tci_status_word; /* return the status word */
|
||||
|
||||
dprintf (atcc_dev, DEB_CSRW, "Status is channel %d | %s\n",
|
||||
dprintf (atcc_dev, DEB_CSRW, "Status is channel %u | %s\n",
|
||||
tci_cntr, fmt_bitset (outbound_value, tci_status_format));
|
||||
break;
|
||||
|
||||
|
@ -1492,8 +1499,11 @@ while (working_set) { /* while signals remain
|
|||
|
||||
|
||||
case DSETMASK:
|
||||
tci_interrupt_mask = /* set the mask flip-flop */
|
||||
D_FF (dibptr->interrupt_mask & inbound_value); /* from the mask bit and the mask value */
|
||||
if (dibptr->interrupt_mask == INTMASK_E) /* if the mask is always enabled */
|
||||
tci_interrupt_mask = SET; /* then set the mask flip-flop */
|
||||
else /* otherwise */
|
||||
tci_interrupt_mask = D_FF (dibptr->interrupt_mask /* set the mask flip-flop if the mask bit */
|
||||
& inbound_value); /* is present in the mask value */
|
||||
|
||||
if (tci_interrupt_mask && dibptr->interrupt_request) /* if the mask is enabled and a request is pending */
|
||||
outbound_signals |= INTREQ; /* then assert INTREQ */
|
||||
|
@ -1733,8 +1743,8 @@ return SCPE_OK;
|
|||
simulation equivalent of the IORESET signal, which is asserted by the front
|
||||
panel LOAD and DUMP switches.
|
||||
|
||||
If a power-on reset (RESET -P) is being done, local modem control is
|
||||
established, and DTR is set on all channels. This is necessary so that
|
||||
If a power-on reset (RESET -P) is being done, then local modem control is
|
||||
established by setting DTR on all channels. This is necessary so that
|
||||
channels not controlled by the TCI will be able to connect (TCI-controlled
|
||||
channels will have their DTR and RTS state set by the MPE TCI initialization
|
||||
routine).
|
||||
|
@ -1743,20 +1753,17 @@ return SCPE_OK;
|
|||
static t_stat atcc_reset (DEVICE *dptr)
|
||||
{
|
||||
uint32 channel;
|
||||
t_stat status = SCPE_OK;
|
||||
|
||||
tci_master_reset (); /* perform a master reset */
|
||||
|
||||
if (sim_switches & SWMASK ('P')) { /* if this is a power-on reset */
|
||||
status = tmxr_set_modem_control_passthru (&atcd_mdsc); /* then establish local modem control */
|
||||
|
||||
for (channel = 0; channel < TERM_COUNT; channel++) /* for each terminal channel */
|
||||
tmxr_set_get_modem_bits (&atcd_ldsc [channel], /* set the DTR line on */
|
||||
TMXR_MDM_DTR, /* to allow non-TCI channels to connect */
|
||||
for (channel = 0; channel < TERM_COUNT; channel++) /* then for each terminal channel */
|
||||
tmxr_set_get_modem_bits (&atcd_ldsc [channel], /* set the DTR line on */
|
||||
TMXR_MDM_DTR, /* to allow non-TCI channels to connect */
|
||||
0, NULL);
|
||||
}
|
||||
|
||||
return status;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1885,7 +1892,7 @@ atcd_dib.interrupt_active = CLEAR; /* interrupt request *
|
|||
tdi_interrupt_mask = SET; /* set the interrupt mask */
|
||||
|
||||
tdi_status_word = 0; /* clear the status word */
|
||||
tdi_data_flag = 0; /* and the data flag */
|
||||
tdi_data_flag = CLEAR; /* and the data flag */
|
||||
|
||||
for (chan = FIRST_TERM; chan <= LAST_TERM; chan++) { /* for each terminal channel */
|
||||
recv_buffer [chan] = 0; /* clear the receive data buffer */
|
||||
|
@ -2030,9 +2037,9 @@ return;
|
|||
|
||||
static t_stat line_service (UNIT *uptr)
|
||||
{
|
||||
const int32 channel = uptr - line_unit; /* channel number */
|
||||
const int32 channel = (int32) (uptr - line_unit); /* the channel number */
|
||||
const int32 alt_channel = channel ^ 1; /* alternate channel number for diagnostic mode */
|
||||
const t_bool loopback = (atcd_dev.flags & DEV_DIAG) != 0; /* device is set for diagnostic mode */
|
||||
const t_bool loopback = (atcd_dev.flags & DEV_DIAG) != 0; /* TRUE if device is set for diagnostic mode */
|
||||
int32 recv_data, send_data, char_data, cvtd_data;
|
||||
t_stat result = SCPE_OK;
|
||||
|
||||
|
@ -2236,7 +2243,7 @@ if ((atcc_dev.flags & (DEV_DIAG | DEV_DIS)) == 0) /* if we're not in diagn
|
|||
status = sim_poll_kbd (); /* poll the simulation console keyboard for input */
|
||||
|
||||
if (status >= SCPE_KFLAG) { /* if a character was present */
|
||||
recv_buffer [0] = (uint16) status; /* then save it for processing */
|
||||
recv_buffer [0] = (HP_WORD) status; /* then save it for processing */
|
||||
status = SCPE_OK; /* and then clear the status */
|
||||
|
||||
line_service (&line_unit [0]); /* run the system console's I/O service */
|
||||
|
@ -2278,7 +2285,7 @@ return status; /* return the service st
|
|||
|
||||
static t_stat activate_unit (UNIT *uptr, ACTIVATOR reason)
|
||||
{
|
||||
const int32 channel = uptr - line_unit; /* the channel number */
|
||||
const int32 channel = (int32) (uptr - line_unit); /* the channel number */
|
||||
int32 delay = 0;
|
||||
|
||||
if (atcd_dev.flags & (DEV_DIAG | DEV_REALTIME)) /* if either diagnostic or real-time mode is set */
|
||||
|
@ -2438,7 +2445,7 @@ return sim_activate (uptr, delay); /* activate the unit and
|
|||
"addition" of the receive overhead may actually be a subtraction.
|
||||
*/
|
||||
|
||||
static uint32 service_time (uint16 control, ACTIVATOR reason)
|
||||
static uint32 service_time (HP_WORD control, ACTIVATOR reason)
|
||||
{
|
||||
const double recirc_time = 69.44; /* microseconds per memory recirculation */
|
||||
const uint32 recirc_per_bit = DPI_BAUD_RATE (control) + 1; /* number of memory recirculations per bit */
|
||||
|
@ -2483,13 +2490,13 @@ return (uint32) (usec_per_char / USEC_PER_EVENT); /* return the service ti
|
|||
from the parameter word.
|
||||
*/
|
||||
|
||||
static void store (uint16 control, uint16 data)
|
||||
static void store (HP_WORD control, HP_WORD data)
|
||||
{
|
||||
const uint32 channel = DCN_CHAN (control); /* current channel number */
|
||||
|
||||
if (data & DDS_IS_SEND) /* if this is a send parameter or data */
|
||||
if (channel > LAST_TERM) /* then report if the channel number is out of range */
|
||||
dprintf (atcd_dev, DEB_CSRW, "Send channel %d invalid\n",
|
||||
dprintf (atcd_dev, DEB_CSRW, "Send channel %u invalid\n",
|
||||
channel);
|
||||
|
||||
else if (data & DPI_IS_PARAM) { /* otherwise if this is a parameter store */
|
||||
|
@ -2497,7 +2504,7 @@ if (data & DDS_IS_SEND) /* if this is a send par
|
|||
line_unit [channel].send_time = /* and set the service time */
|
||||
service_time (data, Send);
|
||||
|
||||
dprintf (atcd_dev, DEB_CSRW, "Channel %d send parameter %06o stored\n",
|
||||
dprintf (atcd_dev, DEB_CSRW, "Channel %u send parameter %06o stored\n",
|
||||
channel, data);
|
||||
}
|
||||
|
||||
|
@ -2508,7 +2515,7 @@ if (data & DDS_IS_SEND) /* if this is a send par
|
|||
|
||||
send_buffer [channel] = data; /* store it in the buffer */
|
||||
|
||||
dprintf (atcd_dev, DEB_CSRW, "Channel %d send data %06o stored\n",
|
||||
dprintf (atcd_dev, DEB_CSRW, "Channel %u send data %06o stored\n",
|
||||
channel, data);
|
||||
|
||||
activate_unit (&line_unit [channel], Send); /* schedule the transmission event */
|
||||
|
@ -2516,7 +2523,7 @@ if (data & DDS_IS_SEND) /* if this is a send par
|
|||
|
||||
else /* otherwise this is a receive parameter */
|
||||
if (channel >= RECV_CHAN_COUNT) /* report if the channel number is out of range */
|
||||
dprintf (atcd_dev, DEB_CSRW, "Receive channel %d invalid\n",
|
||||
dprintf (atcd_dev, DEB_CSRW, "Receive channel %u invalid\n",
|
||||
channel);
|
||||
|
||||
else if (data & DPI_IS_PARAM) { /* otherwise this is a parameter store */
|
||||
|
@ -2530,12 +2537,12 @@ else /* otherwise this is a r
|
|||
PAD_BITS (data);
|
||||
}
|
||||
|
||||
dprintf (atcd_dev, DEB_CSRW, "Channel %d receive parameter %06o stored\n",
|
||||
dprintf (atcd_dev, DEB_CSRW, "Channel %u receive parameter %06o stored\n",
|
||||
channel, data);
|
||||
}
|
||||
|
||||
else /* otherwise a data store to a receive channel is invalid */
|
||||
dprintf (atcd_dev, DEB_CSRW, "Channel %d receive output data word %06o invalid\n",
|
||||
dprintf (atcd_dev, DEB_CSRW, "Channel %u receive output data word %06o invalid\n",
|
||||
channel, data);
|
||||
}
|
||||
|
||||
|
@ -2605,11 +2612,11 @@ else { /* otherwise a normal ch
|
|||
channel);
|
||||
}
|
||||
|
||||
recv_buffer [channel] = (uint16) (recv_data | pad); /* save the character and padding in the buffer */
|
||||
recv_buffer [channel] = recv_data | pad; /* save the character and padding in the buffer */
|
||||
|
||||
if (loopback) { /* if this channel has a loopback cable installed */
|
||||
if (recv_param [channel] & DPI_ENABLE_ECHO) { /* and the channel has echo enabled */
|
||||
recv_buffer [channel ^ 1] = (uint16) data; /* then send the data back to the other channel */
|
||||
if (loopback) { /* if this channel has a loopback cable installed */
|
||||
if (recv_param [channel] & DPI_ENABLE_ECHO) { /* and the channel has echo enabled */
|
||||
recv_buffer [channel ^ 1] = data; /* then send the data back to the other channel */
|
||||
|
||||
activate_unit (&line_unit [channel ^ 1], Loop); /* schedule the reception */
|
||||
|
||||
|
@ -2618,10 +2625,10 @@ else { /* otherwise a normal ch
|
|||
}
|
||||
}
|
||||
|
||||
else if (channel <= LAST_TERM) { /* otherwise if it's a receive channel */
|
||||
if (line_unit [channel].flags & UNIT_CAPSLOCK) { /* then if caps lock is down */
|
||||
recv_data = toupper (recv_data); /* then convert to upper case if lower */
|
||||
recv_buffer [channel] = (uint16) (recv_data | pad); /* and replace the character in the buffer */
|
||||
else if (channel <= LAST_TERM) { /* otherwise if it's a receive channel */
|
||||
if (line_unit [channel].flags & UNIT_CAPSLOCK) { /* then if caps lock is down */
|
||||
recv_data = toupper (recv_data); /* then convert to upper case if lower */
|
||||
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 */
|
||||
|
@ -2679,9 +2686,9 @@ return;
|
|||
character only if it is configured for the same baud rate and character size.
|
||||
*/
|
||||
|
||||
static void diagnose (uint16 control, int32 data)
|
||||
static void diagnose (HP_WORD control, int32 data)
|
||||
{
|
||||
const uint16 config = control & DPI_CHAR_CONFIG; /* main channel character size and baud rate */
|
||||
const HP_WORD config = control & DPI_CHAR_CONFIG; /* main channel character size and baud rate */
|
||||
int32 channel;
|
||||
|
||||
for (channel = FIRST_AUX; channel <= LAST_AUX; channel++) /* scan the auxiliary channels */
|
||||
|
@ -2812,10 +2819,10 @@ return; /* no channel has co
|
|||
pointing at the interrupting channel.
|
||||
*/
|
||||
|
||||
static uint16 scan_status (void)
|
||||
static HP_WORD scan_status (void)
|
||||
{
|
||||
uint32 chan_count;
|
||||
uint16 interrupts;
|
||||
uint32 chan_count;
|
||||
HP_WORD interrupts;
|
||||
|
||||
if (tci_scan) /* if the control interface is scanning */
|
||||
chan_count = TERM_COUNT; /* then look at all of the channels */
|
||||
|
@ -2835,7 +2842,7 @@ while (chan_count > 0) { /* scan the control
|
|||
|
||||
tci_scan = CLEAR; /* stop the scan at the current channel */
|
||||
|
||||
dprintf (atcc_dev, DEB_CSRW, "Channel %d interrupt requested\n",
|
||||
dprintf (atcc_dev, DEB_CSRW, "Channel %u interrupt requested\n",
|
||||
tci_cntr);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,9 @@
|
|||
|
||||
CLK HP 30135A System Clock/Fault Logging Interface
|
||||
|
||||
09-Jun-16 JDB Clarified the IRQ FF set code in DRESETINT
|
||||
08-Jun-16 JDB Corrected %d format to %u for unsigned values
|
||||
21-Mar-16 JDB Changed inbound_value and outbound_value types to HP_WORD
|
||||
08-Jun-15 JDB First release version
|
||||
12-Aug-14 JDB Passed the system clock diagnostic (D426A)
|
||||
05-Jul-14 JDB Created
|
||||
|
@ -221,14 +224,14 @@ static const int32 scale [8] = { /* prescaler counts per clock ti
|
|||
|
||||
#define UNIT_CALTIME_SHIFT (UNIT_V_UF + 0) /* calibrated timing mode */
|
||||
|
||||
#define UNIT_CALTIME (1 << UNIT_CALTIME_SHIFT)
|
||||
#define UNIT_CALTIME (1u << UNIT_CALTIME_SHIFT)
|
||||
|
||||
|
||||
/* Debug flags */
|
||||
|
||||
#define DEB_CSRW (1 << 0) /* trace commands received and status returned */
|
||||
#define DEB_PSERV (1 << 1) /* trace unit service scheduling calls */
|
||||
#define DEB_IOB (1 << 2) /* trace I/O bus signals and data words exchanged */
|
||||
#define DEB_CSRW (1u << 0) /* trace commands received and status returned */
|
||||
#define DEB_PSERV (1u << 1) /* trace unit service scheduling calls */
|
||||
#define DEB_IOB (1u << 2) /* trace I/O bus signals and data words exchanged */
|
||||
|
||||
|
||||
/* Control word.
|
||||
|
@ -239,14 +242,14 @@ static const int32 scale [8] = { /* prescaler counts per clock ti
|
|||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
*/
|
||||
|
||||
#define CN_MR 0100000 /* (M) master reset (if bit 3 = 0) */
|
||||
#define CN_RATE_MASK 0160000 /* clock rate selector mask (if bit 3 = 1) */
|
||||
#define CN_RESET_LOAD_SEL 0010000 /* (E) select reset/load rate (0/1) */
|
||||
#define CN_IRQ_RESET_MASK 0003400 /* interrupt request reset selector mask */
|
||||
#define CN_COUNT_RESET 0000200 /* (C) reset count register after LR=CR interrupt */
|
||||
#define CN_LIMIT_COUNT_SEL 0000100 /* (L) select limit/count (0/1) register */
|
||||
#define CN_IRQ_RESET_ALL 0000040 /* (A) reset all interrupt requests */
|
||||
#define CN_IRQ_ENABLE 0000001 /* (I) enable clock interrupts */
|
||||
#define CN_MR 0100000u /* (M) master reset (if bit 3 = 0) */
|
||||
#define CN_RATE_MASK 0160000u /* clock rate selector mask (if bit 3 = 1) */
|
||||
#define CN_RESET_LOAD_SEL 0010000u /* (E) select reset/load rate (0/1) */
|
||||
#define CN_IRQ_RESET_MASK 0003400u /* interrupt request reset selector mask */
|
||||
#define CN_COUNT_RESET 0000200u /* (C) reset count register after LR=CR interrupt */
|
||||
#define CN_LIMIT_COUNT_SEL 0000100u /* (L) select limit/count (0/1) register */
|
||||
#define CN_IRQ_RESET_ALL 0000040u /* (A) reset all interrupt requests */
|
||||
#define CN_IRQ_ENABLE 0000001u /* (I) enable clock interrupts */
|
||||
|
||||
#define CN_RATE_SHIFT 13 /* clock rate alignment shift */
|
||||
#define CN_IRQ_RESET_SHIFT 8 /* interrupt request reset alignment shift */
|
||||
|
@ -266,14 +269,14 @@ static const char *const rate_name [8] = { /* clock rate selector names */
|
|||
};
|
||||
|
||||
static const char *const irq_reset_name [8] = { /* IRQ reset selector names */
|
||||
NULL, /* 000 = none */
|
||||
"reset LR = CR irq", /* 001 = LR equal CR */
|
||||
"reset LR = CR overflow irq", /* 010 = LR equal CR overflow */
|
||||
"reset SIN irq", /* 011 = I/O system */
|
||||
NULL, /* 100 = unused */
|
||||
NULL, /* 101 = unused */
|
||||
NULL, /* 110 = unused */
|
||||
NULL, /* 111 = unused */
|
||||
"", /* 000 = none */
|
||||
" | reset LR = CR irq", /* 001 = LR equal CR */
|
||||
" | reset LR = CR overflow irq", /* 010 = LR equal CR overflow */
|
||||
" | reset SIN irq", /* 011 = I/O system */
|
||||
"", /* 100 = unused */
|
||||
"", /* 101 = unused */
|
||||
"", /* 110 = unused */
|
||||
"" /* 111 = unused */
|
||||
};
|
||||
|
||||
static const BITSET_NAME control_names [] = { /* Control word names */
|
||||
|
@ -307,13 +310,13 @@ static const BITSET_FORMAT control_format = /* names, offset, direction, alt
|
|||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
*/
|
||||
|
||||
#define ST_DIO_OK 0040000 /* (D) direct I/O OK to use */
|
||||
#define ST_RATE_MASK 0034000 /* clock rate mask */
|
||||
#define ST_LR_EQ_CR 0000040 /* (C) limit register = count register */
|
||||
#define ST_LR_EQ_CR_OVFL 0000020 /* (F) limit register = count register overflow */
|
||||
#define ST_SYSTEM_IRQ 0000004 /* (I) I/O system interrupt request */
|
||||
#define ST_LIMIT_COUNT_SEL 0000002 /* (L) limit/count (0/1) register selected */
|
||||
#define ST_COUNT_RESET 0000001 /* (R) count register is reset after LR=CR interrupt */
|
||||
#define ST_DIO_OK 0040000u /* (D) direct I/O OK to use */
|
||||
#define ST_RATE_MASK 0034000u /* clock rate mask */
|
||||
#define ST_LR_EQ_CR 0000040u /* (C) limit register = count register */
|
||||
#define ST_LR_EQ_CR_OVFL 0000020u /* (F) limit register = count register overflow */
|
||||
#define ST_SYSTEM_IRQ 0000004u /* (I) I/O system interrupt request */
|
||||
#define ST_LIMIT_COUNT_SEL 0000002u /* (L) limit/count (0/1) register selected */
|
||||
#define ST_COUNT_RESET 0000001u /* (R) count register is reset after LR=CR interrupt */
|
||||
|
||||
#define ST_RATE_SHIFT 11 /* clock rate alignment shift */
|
||||
|
||||
|
@ -349,12 +352,12 @@ static FLIP_FLOP system_irq = CLEAR; /* SIN interrupt request flip-fl
|
|||
static FLIP_FLOP limit_irq = CLEAR; /* limit = count interrupt request flip-flop */
|
||||
static FLIP_FLOP lost_tick_irq = CLEAR; /* limit = count overflow interrupt request flip-flop */
|
||||
|
||||
static uint32 control_word; /* control word */
|
||||
static uint32 status_word; /* status word */
|
||||
static uint32 count_register; /* counter register */
|
||||
static uint32 limit_register; /* limit register */
|
||||
static uint32 rate; /* clock rate */
|
||||
static uint32 prescaler; /* clock rate prescaler */
|
||||
static HP_WORD control_word; /* control word */
|
||||
static HP_WORD status_word; /* status word */
|
||||
static HP_WORD count_register; /* counter register */
|
||||
static HP_WORD limit_register; /* limit register */
|
||||
static uint32 rate; /* clock rate */
|
||||
static uint32 prescaler; /* clock rate prescaler */
|
||||
|
||||
static uint32 increment = 1; /* count register increment */
|
||||
static t_bool coschedulable = FALSE; /* TRUE if the clock can be coscheduled with PCLK */
|
||||
|
@ -395,21 +398,21 @@ static UNIT clk_unit = {
|
|||
/* Register list */
|
||||
|
||||
static REG clk_reg [] = {
|
||||
/* Macro Name Location Width Offset Flags */
|
||||
/* ------ ------ --------------- ----- ------ ------- */
|
||||
{ ORDATA (CNTL, control_word, 16) },
|
||||
{ ORDATA (STAT, status_word, 16) },
|
||||
{ ORDATA (COUNT, count_register, 16) },
|
||||
{ ORDATA (LIMIT, limit_register, 16) },
|
||||
{ ORDATA (RATE, rate, 3) },
|
||||
{ FLDATA (SYSIRQ, system_irq, 0) },
|
||||
{ FLDATA (LIMIRQ, limit_irq, 0) },
|
||||
{ FLDATA (OVFIRQ, lost_tick_irq, 0) },
|
||||
{ DRDATA (SCALE, prescaler, 16), REG_HRO },
|
||||
{ DRDATA (INCR, increment, 16), REG_HRO },
|
||||
{ FLDATA (COSOK, coschedulable, 0), REG_HRO },
|
||||
{ FLDATA (COSCH, coscheduled, 0), REG_HRO },
|
||||
{ SRDATA (DIB, clk_dib), REG_HRO },
|
||||
/* Macro Name Location Width Offset Flags */
|
||||
/* ------ ------ --------------- ----- ------ ------- */
|
||||
{ ORDATA (CNTL, control_word, 16) },
|
||||
{ ORDATA (STAT, status_word, 16) },
|
||||
{ ORDATA (COUNT, count_register, 16) },
|
||||
{ ORDATA (LIMIT, limit_register, 16) },
|
||||
{ ORDATA (RATE, rate, 3) },
|
||||
{ FLDATA (SYSIRQ, system_irq, 0) },
|
||||
{ FLDATA (LIMIRQ, limit_irq, 0) },
|
||||
{ FLDATA (OVFIRQ, lost_tick_irq, 0) },
|
||||
{ DRDATA (SCALE, prescaler, 16), REG_HRO },
|
||||
{ DRDATA (INCR, increment, 16), REG_HRO },
|
||||
{ FLDATA (COSOK, coschedulable, 0), REG_HRO },
|
||||
{ FLDATA (COSCH, coscheduled, 0), REG_HRO },
|
||||
{ SRDATA (DIB, clk_dib, REG_HRO) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
@ -543,11 +546,11 @@ return;
|
|||
rate name parameter without printing when the rate is not specified.
|
||||
*/
|
||||
|
||||
static SIGNALS_DATA clk_interface (DIB *dibptr, INBOUND_SET inbound_signals, uint16 inbound_value)
|
||||
static SIGNALS_DATA clk_interface (DIB *dibptr, INBOUND_SET inbound_signals, HP_WORD inbound_value)
|
||||
{
|
||||
INBOUND_SIGNAL signal;
|
||||
INBOUND_SET working_set = inbound_signals;
|
||||
uint16 outbound_value = 0;
|
||||
HP_WORD outbound_value = 0;
|
||||
OUTBOUND_SET outbound_signals = NO_SIGNALS;
|
||||
|
||||
dprintf (clk_dev, DEB_IOB, "Received data %06o with signals %s\n",
|
||||
|
@ -610,11 +613,12 @@ while (working_set) {
|
|||
if (dibptr->interrupt_active == CLEAR) /* if no interrupt is active */
|
||||
working_set |= DRESETINT; /* then recalculate interrupt requests */
|
||||
|
||||
dprintf (clk_dev, DEB_CSRW, (control_word & CN_RESET_LOAD_SEL
|
||||
? "Control is %s | %s rate\n"
|
||||
: "Control is %s%.0s\n"),
|
||||
dprintf (clk_dev, DEB_CSRW, (inbound_value & CN_RESET_LOAD_SEL
|
||||
? "Control is %s | %s rate%s\n"
|
||||
: "Control is %s%.0s%s\n"),
|
||||
fmt_bitset (inbound_value, control_format),
|
||||
rate_name [CN_RATE (inbound_value)]);
|
||||
rate_name [CN_RATE (inbound_value)],
|
||||
irq_reset_name [CN_RESET (inbound_value)]);
|
||||
break;
|
||||
|
||||
|
||||
|
@ -636,7 +640,7 @@ while (working_set) {
|
|||
if (control_word & CN_COUNT_RESET) /* if the reset-after-interrupt selector is set */
|
||||
status_word |= ST_COUNT_RESET; /* set the corresponding status bit */
|
||||
|
||||
outbound_value = (uint16) status_word; /* return the status word */
|
||||
outbound_value = status_word; /* return the status word */
|
||||
|
||||
dprintf (clk_dev, DEB_CSRW, "Status is %s%s rate\n",
|
||||
fmt_bitset (outbound_value, status_format),
|
||||
|
@ -648,7 +652,7 @@ while (working_set) {
|
|||
clk_update_counter (); /* update the clock counter register */
|
||||
outbound_value = LOWER_WORD (count_register); /* and then read it */
|
||||
|
||||
dprintf (clk_dev, DEB_CSRW, "Count register value %d returned\n",
|
||||
dprintf (clk_dev, DEB_CSRW, "Count register value %u returned\n",
|
||||
count_register);
|
||||
break;
|
||||
|
||||
|
@ -664,7 +668,7 @@ while (working_set) {
|
|||
else { /* otherwise */
|
||||
limit_register = inbound_value; /* set the limit register to the supplied value */
|
||||
|
||||
dprintf (clk_dev, DEB_CSRW, "Limit register value %d set\n",
|
||||
dprintf (clk_dev, DEB_CSRW, "Limit register value %u set\n",
|
||||
limit_register);
|
||||
|
||||
coschedulable = (ticks [rate] == 1000 /* the clock can be coscheduled if the rate */
|
||||
|
@ -684,9 +688,11 @@ while (working_set) {
|
|||
case DRESETINT:
|
||||
dibptr->interrupt_active = CLEAR; /* clear the Interrupt Active flip-flop */
|
||||
|
||||
dibptr->interrupt_request = system_irq /* recalculate the interrupt request signal */
|
||||
|| control_word & CN_IRQ_ENABLE
|
||||
&& (limit_irq | lost_tick_irq);
|
||||
if ((limit_irq == SET || lost_tick_irq == SET) /* if the limit or lost tick flip-flops are set */
|
||||
&& control_word & CN_IRQ_ENABLE) /* and interrupts are enabled */
|
||||
dibptr->interrupt_request = SET; /* then set the interrupt request flip-flop */
|
||||
else /* otherwise */
|
||||
dibptr->interrupt_request = system_irq; /* request an interrupt if the system flip-flop is set */
|
||||
|
||||
if (dibptr->interrupt_request) /* if a request is pending */
|
||||
outbound_signals |= INTREQ; /* then notify the IOP */
|
||||
|
@ -767,7 +773,7 @@ return IORETURN (outbound_signals, outbound_value); /* return the outbound s
|
|||
|
||||
static t_stat clk_service (UNIT *uptr)
|
||||
{
|
||||
dprintf (clk_dev, DEB_PSERV, "Service entered with counter %d increment %d limit %d\n",
|
||||
dprintf (clk_dev, DEB_PSERV, "Service entered with counter %u increment %u limit %u\n",
|
||||
count_register, increment, limit_register);
|
||||
|
||||
prescaler = prescaler - 1; /* decrement the prescaler count */
|
||||
|
|
|
@ -25,7 +25,11 @@
|
|||
|
||||
CPU HP 3000 Series III Central Processing Unit
|
||||
|
||||
08-Jun-16 JDB Corrected %d format to %u for unsigned values
|
||||
16-May-16 JDB ACCESS_PROPERTIES.name is now a pointer-to-constant
|
||||
13-May-16 JDB Modified for revised SCP API function parameter types
|
||||
24-Mar-16 JDB Changed memory word type from uint16 to MEMORY_WORD
|
||||
21-Mar-16 JDB Changed cpu_ccb_table type from uint16 to HP_WORD
|
||||
11-Mar-16 JDB Fixed byte EA calculations with negative indexes
|
||||
22-Dec-15 JDB First release version
|
||||
01-Apr-15 JDB First successful run of MPE-V/R through account login
|
||||
|
@ -73,12 +77,12 @@
|
|||
|
||||
Memory protection is accomplished by checking program, data, and stack
|
||||
accesses against segment base and limit registers, which can be set only by
|
||||
MPE. Bounds violations cause automatic hardware traps to a handler routine
|
||||
MPE. Bounds violations cause automatic hardware traps to a handler routine
|
||||
within MPE. Some violations may be permitted; for example, a Stack Overflow
|
||||
trap may cause MPE to allocate a larger stack and then restart the
|
||||
interrupted instruction. Almost all memory references are position-
|
||||
independent, so moving segments to accommodate expansion requires only
|
||||
resetting of the segment registers to point at the new location. Code
|
||||
resetting of the segment registers to point at the new locations. Code
|
||||
segments are fully reentrant and shareable, and both code and data are
|
||||
virtual, as the hardware supports absent code and data segment traps.
|
||||
|
||||
|
@ -737,7 +741,7 @@ HP_WORD CNTR = 0; /* microcode counter */
|
|||
condition code appropriate for the supplied operand into the status word.
|
||||
*/
|
||||
|
||||
const uint16 cpu_ccb_table [256] = {
|
||||
const HP_WORD cpu_ccb_table [256] = {
|
||||
CFL, CFL, CFL, CFL, CFL, CFL, CFL, CFL, /* NUL SOH STX ETX EOT ENQ ACK BEL */
|
||||
CFL, CFL, CFL, CFL, CFL, CFL, CFL, CFL, /* BS HT LF VT FF CR SO SI */
|
||||
CFL, CFL, CFL, CFL, CFL, CFL, CFL, CFL, /* DLE DC1 DC2 DC3 DC4 NAK SYN ETB */
|
||||
|
@ -781,7 +785,7 @@ uint32 cpu_stop_flags; /* the simulation stop flag set
|
|||
EXEC_STATE cpu_micro_state = halted; /* the microcode execution state */
|
||||
t_bool cpu_base_changed = FALSE; /* TRUE if any base register is changed */
|
||||
t_bool cpu_is_calibrated = TRUE; /* TRUE if the process clock is calibrated */
|
||||
UNIT *cpu_pclk_uptr = &cpu_unit; /* a pointer to the process clock unit */
|
||||
UNIT *cpu_pclk_uptr = &cpu_unit; /* a (constant) pointer to the process clock unit */
|
||||
|
||||
|
||||
/* CPU local state */
|
||||
|
@ -798,7 +802,7 @@ static uint32 pclk_increment = 1; /* the process clock increment p
|
|||
|
||||
#define MEMSIZE (cpu_unit.capac) /* the current memory size in 16-bit words */
|
||||
|
||||
static uint16 *M = NULL; /* the pointer to the main memory allocation */
|
||||
static MEMORY_WORD *M = NULL; /* the pointer to the main memory allocation */
|
||||
|
||||
|
||||
/* Interrupt classification names */
|
||||
|
@ -900,11 +904,11 @@ static const struct FEATURE_TABLE cpu_features [] = { /* features indexed by C
|
|||
/* Memory access classification table */
|
||||
|
||||
typedef struct {
|
||||
HP_WORD *bank_ptr; /* a pointer to the bank register */
|
||||
DEVICE *device_ptr; /* a pointer to the accessing device */
|
||||
uint32 debug_flag; /* the debug flag for tracing */
|
||||
t_bool irq; /* TRUE if an interrupt is requested on error */
|
||||
char *const name; /* the classification name */
|
||||
HP_WORD *bank_ptr; /* a pointer to the bank register */
|
||||
DEVICE *device_ptr; /* a pointer to the accessing device */
|
||||
uint32 debug_flag; /* the debug flag for tracing */
|
||||
t_bool irq; /* TRUE if an interrupt is requested on error */
|
||||
const char *name; /* the classification name */
|
||||
} ACCESS_PROPERTIES;
|
||||
|
||||
|
||||
|
@ -1796,7 +1800,7 @@ else { /* otherwise the access
|
|||
case absolute:
|
||||
case data:
|
||||
case stack:
|
||||
M [address] = (uint16) value; /* write the value to memory */
|
||||
M [address] = (MEMORY_WORD) value; /* write the value to memory */
|
||||
break;
|
||||
|
||||
|
||||
|
@ -1804,7 +1808,7 @@ else { /* otherwise the access
|
|||
if (offset > SM && offset <= SM + SR && bank == SBANK) /* if the offset is within the TOS */
|
||||
TR [SM + SR - offset] = value; /* then write the value to a TOS register */
|
||||
else /* otherwise */
|
||||
M [address] = (uint16) value; /* write the value to memory */
|
||||
M [address] = (MEMORY_WORD) value; /* write the value to memory */
|
||||
break;
|
||||
|
||||
|
||||
|
@ -1814,7 +1818,7 @@ else { /* otherwise the access
|
|||
TR [SM + SR - offset] = value; /* then write the value to a TOS register */
|
||||
|
||||
if (DL <= offset && offset <= SM + SR || PRIV) /* if the offset is within bounds or is privileged */
|
||||
M [address] = (uint16) value; /* then write the value to memory */
|
||||
M [address] = (MEMORY_WORD) value; /* then write the value to memory */
|
||||
else /* otherwise */
|
||||
MICRO_ABORT (trap_Bounds_Violation); /* trap for a bounds violation */
|
||||
break;
|
||||
|
@ -3167,7 +3171,8 @@ return SCPE_OK; /* return the success of
|
|||
static t_stat cpu_reset (DEVICE *dptr)
|
||||
{
|
||||
if (M == NULL) { /* if this is the first call after simulator start */
|
||||
M = (uint16 *) calloc (PA_MAX, sizeof (uint16)); /* then allocate the maximum amount of memory needed */
|
||||
M = (MEMORY_WORD *) calloc (PA_MAX, /* then allocate the maximum amount of memory needed */
|
||||
sizeof (MEMORY_WORD));
|
||||
|
||||
if (M == NULL) /* if the allocation failed */
|
||||
return SCPE_MEM; /* then report the error and abort the simulation */
|
||||
|
@ -3410,7 +3415,7 @@ if (MEMSIZE == 0 /* if this is the initia
|
|||
|| MEMSIZE > cpu_features [new_index].maxmem) /* or if the current memory size is unsupported */
|
||||
new_memsize = cpu_features [new_index].maxmem; /* then set the new size to the maximum supported size */
|
||||
else /* otherwise the current size is valid for the new model */
|
||||
new_memsize = MEMSIZE; /* so leave it unchanged */
|
||||
new_memsize = (uint32) MEMSIZE; /* so leave it unchanged */
|
||||
|
||||
status = set_size (uptr, new_memsize, NULL, NULL); /* set the new memory size */
|
||||
|
||||
|
@ -3502,7 +3507,7 @@ return SCPE_OK; /* report the success of
|
|||
|
||||
static t_stat show_speed (FILE *st, UNIT *uptr, int32 val, CONST void *desc)
|
||||
{
|
||||
fprintf (st, "Simulation speed = %dx\n", cpu_speed); /* display the current CPU speed */
|
||||
fprintf (st, "Simulation speed = %ux\n", cpu_speed); /* display the current CPU speed */
|
||||
return SCPE_OK; /* and report success */
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
21-Mar-16 JDB Changed cpu_ccb_table type from uint16 to HP_WORD
|
||||
14-Feb-16 JDB First release version
|
||||
11-Dec-12 JDB Created
|
||||
|
||||
|
@ -39,6 +40,28 @@
|
|||
|
||||
|
||||
|
||||
/* Architectural constants.
|
||||
|
||||
The type used to represent a main memory word value is defined. An array of
|
||||
this type is used to simulate the CPU main memory.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. The MEMORY_WORD type is a 16-bit unsigned type, corresponding with the
|
||||
16-bit main memory in the HP 3000. Unlike the general data type, which
|
||||
is a 32-bit type for speed, main memory does not benefit from the faster
|
||||
32-bit execution on IA-32 processors, as only one instruction in the
|
||||
cpu_read_memory and cpu_write_memory routines has an operand override
|
||||
that invokes the slower instruction fetch path. There is a negligible
|
||||
difference in the Memory Pattern Test diagnostic execution speeds for the
|
||||
uint32 vs. uint16 definition, whereas the VM requirements are doubled for
|
||||
the former.
|
||||
*/
|
||||
|
||||
typedef uint16 MEMORY_WORD; /* HP 16-bit memory word representation */
|
||||
|
||||
|
||||
/* Supported breakpoint switches */
|
||||
|
||||
#define BP_EXEC (SWMASK ('E')) /* an execution breakpoint */
|
||||
|
@ -51,14 +74,14 @@
|
|||
#define UNIT_EIS_SHIFT (UNIT_V_UF + 1) /* the Extended Instruction Set firmware option */
|
||||
#define UNIT_CALTIME_SHIFT (UNIT_V_UF + 2) /* the process clock timing mode */
|
||||
|
||||
#define UNIT_MODEL_MASK 0000001 /* model ID mask */
|
||||
#define UNIT_MODEL_MASK 0000001u /* model ID mask */
|
||||
|
||||
#define UNIT_MODEL (UNIT_MODEL_MASK << UNIT_MODEL_SHIFT)
|
||||
|
||||
#define UNIT_SERIES_III (0 << UNIT_MODEL_SHIFT) /* the CPU is a Series III */
|
||||
#define UNIT_SERIES_II (1 << UNIT_MODEL_SHIFT) /* the CPU is a Series II */
|
||||
#define UNIT_EIS (1 << UNIT_EIS_SHIFT) /* the Extended Instruction Set is installed */
|
||||
#define UNIT_CALTIME (1 << UNIT_CALTIME_SHIFT) /* the process clock is calibrated to wall time */
|
||||
#define UNIT_SERIES_III (0u << UNIT_MODEL_SHIFT) /* the CPU is a Series III */
|
||||
#define UNIT_SERIES_II (1u << UNIT_MODEL_SHIFT) /* the CPU is a Series II */
|
||||
#define UNIT_EIS (1u << UNIT_EIS_SHIFT) /* the Extended Instruction Set is installed */
|
||||
#define UNIT_CALTIME (1u << UNIT_CALTIME_SHIFT) /* the process clock is calibrated to wall time */
|
||||
|
||||
#define UNIT_CPU_MODEL (cpu_unit.flags & UNIT_MODEL_MASK)
|
||||
|
||||
|
@ -67,11 +90,11 @@
|
|||
|
||||
/* CPU debug flags */
|
||||
|
||||
#define DEB_MDATA (1 << 0) /* trace memory data accesses */
|
||||
#define DEB_INSTR (1 << 1) /* trace instruction execution */
|
||||
#define DEB_FETCH (1 << 2) /* trace instruction fetches */
|
||||
#define DEB_REG (1 << 3) /* trace register values */
|
||||
#define DEB_PSERV (1 << 4) /* trace PCLK service events */
|
||||
#define DEB_MDATA (1u << 0) /* trace memory data accesses */
|
||||
#define DEB_INSTR (1u << 1) /* trace instruction execution */
|
||||
#define DEB_FETCH (1u << 2) /* trace instruction fetches */
|
||||
#define DEB_REG (1u << 3) /* trace register values */
|
||||
#define DEB_PSERV (1u << 4) /* trace PCLK service events */
|
||||
|
||||
#define BOV_FORMAT "%02o.%06o %06o " /* bank-offset-value trace format string */
|
||||
|
||||
|
@ -140,22 +163,22 @@ typedef enum {
|
|||
*/
|
||||
|
||||
typedef enum {
|
||||
cpx1_INTOVFL = 0100000, /* integer overflow */
|
||||
cpx1_BNDVIOL = 0040000, /* bounds violation */
|
||||
cpx1_ILLADDR = 0020000, /* illegal address */
|
||||
cpx1_CPUTIMER = 0010000, /* CPU timer */
|
||||
cpx1_SYSPAR = 0004000, /* system parity error */
|
||||
cpx1_ADDRPAR = 0002000, /* address parity error */
|
||||
cpx1_DATAPAR = 0001000, /* data parity error */
|
||||
cpx1_MODINTR = 0000400, /* module interrupt */
|
||||
cpx1_EXTINTR = 0000200, /* external interrupt */
|
||||
cpx1_PFINTR = 0000100, /* power fail interrupt */
|
||||
/* cpx1_UNUSED = 0000040, unused, always 0 */
|
||||
cpx1_ICSFLAG = 0000020, /* ICS flag */
|
||||
cpx1_DISPFLAG = 0000010, /* dispatcher-is-active flag */
|
||||
cpx1_EMULATOR = 0000004, /* emulator-in-use flag */
|
||||
cpx1_IOTIMER = 0000002, /* I/O timeout */
|
||||
cpx1_OPTION = 0000001 /* option present */
|
||||
cpx1_INTOVFL = 0100000u, /* integer overflow */
|
||||
cpx1_BNDVIOL = 0040000u, /* bounds violation */
|
||||
cpx1_ILLADDR = 0020000u, /* illegal address */
|
||||
cpx1_CPUTIMER = 0010000u, /* CPU timer */
|
||||
cpx1_SYSPAR = 0004000u, /* system parity error */
|
||||
cpx1_ADDRPAR = 0002000u, /* address parity error */
|
||||
cpx1_DATAPAR = 0001000u, /* data parity error */
|
||||
cpx1_MODINTR = 0000400u, /* module interrupt */
|
||||
cpx1_EXTINTR = 0000200u, /* external interrupt */
|
||||
cpx1_PFINTR = 0000100u, /* power fail interrupt */
|
||||
/* cpx1_UNUSED = 0000040u, unused, always 0 */
|
||||
cpx1_ICSFLAG = 0000020u, /* ICS flag */
|
||||
cpx1_DISPFLAG = 0000010u, /* dispatcher-is-active flag */
|
||||
cpx1_EMULATOR = 0000004u, /* emulator-in-use flag */
|
||||
cpx1_IOTIMER = 0000002u, /* I/O timeout */
|
||||
cpx1_OPTION = 0000001u /* option present */
|
||||
} CPX1FLAG;
|
||||
|
||||
#define CPX1_IRQ_SET (cpx1_INTOVFL | cpx1_BNDVIOL | \
|
||||
|
@ -165,22 +188,22 @@ typedef enum {
|
|||
cpx1_EXTINTR | cpx1_PFINTR) /* the set of CPX1 interrupt requests */
|
||||
|
||||
typedef enum {
|
||||
cpx2_RUNSWCH = 0100000, /* RUN switch */
|
||||
cpx2_DUMPSWCH = 0040000, /* DUMP switch */
|
||||
cpx2_LOADSWCH = 0020000, /* LOAD switch */
|
||||
cpx2_LOADREG = 0010000, /* load register */
|
||||
cpx2_LOADADDR = 0004000, /* load address */
|
||||
cpx2_LOADMEM = 0002000, /* load memory */
|
||||
cpx2_DISPMEM = 0001000, /* display memory */
|
||||
cpx2_SNGLINST = 0000400, /* single instruction */
|
||||
cpx2_EXECSWCH = 0000200, /* EXECUTE switch */
|
||||
cpx2_INCRADDR = 0000100, /* increment address */
|
||||
cpx2_DECRADDR = 0000040, /* decrement address */
|
||||
/* cpx2_UNUSED = 0000020, unused, always 0 */
|
||||
/* cpx2_UNUSED = 0000010, unused, always 0 */
|
||||
cpx2_INHPFARS = 0000004, /* inhibit power fail autorestart */
|
||||
cpx2_SYSHALT = 0000002, /* system halt */
|
||||
cpx2_RUN = 0000001 /* run flip-flop */
|
||||
cpx2_RUNSWCH = 0100000u, /* RUN switch */
|
||||
cpx2_DUMPSWCH = 0040000u, /* DUMP switch */
|
||||
cpx2_LOADSWCH = 0020000u, /* LOAD switch */
|
||||
cpx2_LOADREG = 0010000u, /* load register */
|
||||
cpx2_LOADADDR = 0004000u, /* load address */
|
||||
cpx2_LOADMEM = 0002000u, /* load memory */
|
||||
cpx2_DISPMEM = 0001000u, /* display memory */
|
||||
cpx2_SNGLINST = 0000400u, /* single instruction */
|
||||
cpx2_EXECSWCH = 0000200u, /* EXECUTE switch */
|
||||
cpx2_INCRADDR = 0000100u, /* increment address */
|
||||
cpx2_DECRADDR = 0000040u, /* decrement address */
|
||||
/* cpx2_UNUSED = 0000020u, unused, always 0 */
|
||||
/* cpx2_UNUSED = 0000010u, unused, always 0 */
|
||||
cpx2_INHPFARS = 0000004u, /* inhibit power fail autorestart */
|
||||
cpx2_SYSHALT = 0000002u, /* system halt */
|
||||
cpx2_RUN = 0000001u /* run flip-flop */
|
||||
} CPX2FLAG;
|
||||
|
||||
#define CPX2_IRQ_SET (cpx2_RUNSWCH | cpx2_DUMPSWCH | \
|
||||
|
@ -335,21 +358,21 @@ typedef enum {
|
|||
11 = invalid
|
||||
*/
|
||||
|
||||
#define STATUS_M 0100000 /* mode flag */
|
||||
#define STATUS_I 0040000 /* interrupt flag */
|
||||
#define STATUS_T 0020000 /* trap flag */
|
||||
#define STATUS_R 0010000 /* right-hand stack op flag */
|
||||
#define STATUS_O 0004000 /* overflow flag */
|
||||
#define STATUS_C 0002000 /* carry flag */
|
||||
#define STATUS_M 0100000u /* mode flag */
|
||||
#define STATUS_I 0040000u /* interrupt flag */
|
||||
#define STATUS_T 0020000u /* trap flag */
|
||||
#define STATUS_R 0010000u /* right-hand stack op flag */
|
||||
#define STATUS_O 0004000u /* overflow flag */
|
||||
#define STATUS_C 0002000u /* carry flag */
|
||||
|
||||
#define STATUS_CCG 0000000 /* condition code greater than */
|
||||
#define STATUS_CCL 0000400 /* condition code less than */
|
||||
#define STATUS_CCE 0001000 /* condition code equal to */
|
||||
#define STATUS_CCG 0000000u /* condition code greater than */
|
||||
#define STATUS_CCL 0000400u /* condition code less than */
|
||||
#define STATUS_CCE 0001000u /* condition code equal to */
|
||||
|
||||
#define STATUS_CC_MASK 0001400 /* condition code mask */
|
||||
#define STATUS_CC_MASK 0001400u /* condition code mask */
|
||||
#define STATUS_CC_SHIFT 8 /* condition code alignment */
|
||||
|
||||
#define STATUS_CS_MASK 0000377 /* code segment mask */
|
||||
#define STATUS_CS_MASK 0000377u /* code segment mask */
|
||||
#define STATUS_CS_WIDTH 8 /* code segment mask width */
|
||||
|
||||
#define STATUS_OVTRAP (STATUS_T | STATUS_O)
|
||||
|
@ -390,9 +413,9 @@ typedef enum {
|
|||
register to a condition code flag.
|
||||
*/
|
||||
|
||||
#define CFL 0000400 /* condition code flag less than */
|
||||
#define CFE 0001000 /* condition code flag equal to */
|
||||
#define CFG 0002000 /* condition code flag greater than */
|
||||
#define CFL 0000400u /* condition code flag less than */
|
||||
#define CFE 0001000u /* condition code flag equal to */
|
||||
#define CFG 0002000u /* condition code flag greater than */
|
||||
|
||||
#define TO_CCF(s) ((s) & STATUS_CC_MASK ? (s) & STATUS_CC_MASK : CFG)
|
||||
|
||||
|
@ -615,47 +638,47 @@ typedef enum {
|
|||
|
||||
/* Machine instruction bit-field accessors */
|
||||
|
||||
#define BITS_0_3_MASK 0170000 /* bits 0-3 mask */
|
||||
#define BITS_0_3_MASK 0170000u /* bits 0-3 mask */
|
||||
#define BITS_0_3_SHIFT 12 /* bits 0-3 alignment shift */
|
||||
|
||||
#define BITS_0_3(v) (((v) & BITS_0_3_MASK) >> BITS_0_3_SHIFT)
|
||||
|
||||
#define BITS_4_5_MASK 0006000 /* bits 4-5 mask */
|
||||
#define BITS_4_5_MASK 0006000u /* bits 4-5 mask */
|
||||
#define BITS_4_5_SHIFT 10 /* bits 4-5 alignment shift */
|
||||
|
||||
#define BITS_4_5(v) (((v) & BITS_4_5_MASK) >> BITS_4_5_SHIFT)
|
||||
|
||||
#define BITS_4_7_MASK 0007400 /* bits 4-7 mask */
|
||||
#define BITS_4_7_MASK 0007400u /* bits 4-7 mask */
|
||||
#define BITS_4_7_SHIFT 8 /* bits 4-7 alignment shift */
|
||||
|
||||
#define BITS_4_7(v) (((v) & BITS_4_7_MASK) >> BITS_4_7_SHIFT)
|
||||
|
||||
#define BITS_4_9_MASK 0007700 /* bits 4-9 mask */
|
||||
#define BITS_4_9_MASK 0007700u /* bits 4-9 mask */
|
||||
#define BITS_4_9_SHIFT 6 /* bits 4-9 alignment shift */
|
||||
|
||||
#define BITS_4_9(v) (((v) & BITS_4_9_MASK) >> BITS_4_9_SHIFT)
|
||||
|
||||
#define BITS_5_9_MASK 0003700 /* bits 5-9 mask */
|
||||
#define BITS_5_9_MASK 0003700u /* bits 5-9 mask */
|
||||
#define BITS_5_9_SHIFT 6 /* bits 5-9 alignment shift */
|
||||
|
||||
#define BITS_5_9(v) (((v) & BITS_5_9_MASK) >> BITS_5_9_SHIFT)
|
||||
|
||||
#define BITS_8_11_MASK 0000360 /* bits 8-11 mask */
|
||||
#define BITS_8_11_MASK 0000360u /* bits 8-11 mask */
|
||||
#define BITS_8_11_SHIFT 4 /* bits 8-11 alignment shift */
|
||||
|
||||
#define BITS_8_11(v) (((v) & BITS_8_11_MASK) >> BITS_8_11_SHIFT)
|
||||
|
||||
#define BITS_8_12_MASK 0000370 /* bits 8-12 mask */
|
||||
#define BITS_8_12_MASK 0000370u /* bits 8-12 mask */
|
||||
#define BITS_8_12_SHIFT 3 /* bits 8-12 alignment shift */
|
||||
|
||||
#define BITS_8_12(v) (((v) & BITS_8_12_MASK) >> BITS_8_12_SHIFT)
|
||||
|
||||
#define BITS_10_15_MASK 0000077 /* bits 10-15 mask */
|
||||
#define BITS_10_15_MASK 0000077u /* bits 10-15 mask */
|
||||
#define BITS_10_15_SHIFT 0 /* bits 10-15 alignment shift */
|
||||
|
||||
#define BITS_10_15(v) (((v) & BITS_10_15_MASK) >> BITS_10_15_SHIFT)
|
||||
|
||||
#define BITS_12_15_MASK 0000017 /* bits 12-15 mask */
|
||||
#define BITS_12_15_MASK 0000017u /* bits 12-15 mask */
|
||||
#define BITS_12_15_SHIFT 0 /* bits 12-15 alignment shift */
|
||||
|
||||
#define BITS_12_15(v) (((v) & BITS_12_15_MASK) >> BITS_12_15_SHIFT)
|
||||
|
@ -718,158 +741,158 @@ typedef enum {
|
|||
|
||||
/* Specific instruction accessors */
|
||||
|
||||
#define IOOP_K_MASK 0000017 /* I/O K-field mask */
|
||||
#define IOOP_K_SHIFT 0000000 /* I/O K-field alignment shift */
|
||||
#define IOOP_K_MASK 0000017u /* I/O K-field mask */
|
||||
#define IOOP_K_SHIFT 0000000u /* I/O K-field alignment shift */
|
||||
#define IO_K(v) (((v) & IOOP_K_MASK) >> IOOP_K_SHIFT)
|
||||
|
||||
#define X_FLAG 0004000 /* index flag in bit 4 */
|
||||
#define I_FLAG_BIT_4 0004000 /* indirect flag in bit 4 */
|
||||
#define I_FLAG_BIT_5 0002000 /* indirect flag in bit 5 */
|
||||
#define M_FLAG 0001000 /* memory subop flag in bit 6 */
|
||||
#define X_FLAG 0004000u /* index flag in bit 4 */
|
||||
#define I_FLAG_BIT_4 0004000u /* indirect flag in bit 4 */
|
||||
#define I_FLAG_BIT_5 0002000u /* indirect flag in bit 5 */
|
||||
#define M_FLAG 0001000u /* memory subop flag in bit 6 */
|
||||
|
||||
#define START_BIT_MASK 0000360 /* start bit mask for bit field instructions */
|
||||
#define START_BIT_MASK 0000360u /* start bit mask for bit field instructions */
|
||||
#define START_BIT_SHIFT 4 /* start bit alignment shift */
|
||||
#define START_BIT(v) (((v) & START_BIT_MASK) >> START_BIT_SHIFT)
|
||||
|
||||
#define BIT_COUNT_MASK 0000017 /* bit count mask for bit field instructions */
|
||||
#define BIT_COUNT_MASK 0000017u /* bit count mask for bit field instructions */
|
||||
#define BIT_COUNT_SHIFT 0 /* bit count alignment shift */
|
||||
#define BIT_COUNT(v) (((v) & BIT_COUNT_MASK) >> BIT_COUNT_SHIFT)
|
||||
|
||||
#define BIT_POSITION_MASK 0000077 /* bit position mask for bit test instructions */
|
||||
#define BIT_POSITION_MASK 0000077u /* bit position mask for bit test instructions */
|
||||
#define BIT_POSITION_SHIFT 0 /* bit position alignment shift */
|
||||
#define BIT_POSITION(v) (((v) & BIT_POSITION_MASK) >> BIT_POSITION_SHIFT)
|
||||
|
||||
#define SHIFT_COUNT_MASK 0000077 /* shift count mask for shift instructions */
|
||||
#define SHIFT_COUNT_MASK 0000077u /* shift count mask for shift instructions */
|
||||
#define SHIFT_COUNT_SHIFT 0 /* shift count alignment shift */
|
||||
#define SHIFT_COUNT(v) (((v) & SHIFT_COUNT_MASK) >> SHIFT_COUNT_SHIFT)
|
||||
|
||||
#define SHIFT_RIGHT_FLAG 0000100 /* shift instructions left/right (0/1) flag */
|
||||
#define SHIFT_RIGHT_FLAG 0000100u /* shift instructions left/right (0/1) flag */
|
||||
|
||||
#define MODE_DISP_MASK 0001777 /* memory-reference mode and displacement mask */
|
||||
#define MODE_MASK 0001700 /* memory-reference mode mask */
|
||||
#define MODE_DISP_MASK 0001777u /* memory-reference mode and displacement mask */
|
||||
#define MODE_MASK 0001700u /* memory-reference mode mask */
|
||||
#define MODE_SHIFT 6 /* memory-reference mode alignment shift */
|
||||
|
||||
#define DISPL_31_SIGN 0000040 /* sign bit for 0-31 displacements */
|
||||
#define DISPL_255_SIGN 0000400 /* sign bit for 0-255 displacements */
|
||||
#define DISPL_31_SIGN 0000040u /* sign bit for 0-31 displacements */
|
||||
#define DISPL_255_SIGN 0000400u /* sign bit for 0-255 displacements */
|
||||
|
||||
#define DISPL_31_MASK 0000037 /* mask for 0-31 displacements */
|
||||
#define DISPL_63_MASK 0000077 /* mask for 0-63 displacements */
|
||||
#define DISPL_127_MASK 0000177 /* mask for 0-127 displacements */
|
||||
#define DISPL_255_MASK 0000377 /* mask for 0-255 displacements */
|
||||
#define DISPL_31_MASK 0000037u /* mask for 0-31 displacements */
|
||||
#define DISPL_63_MASK 0000077u /* mask for 0-63 displacements */
|
||||
#define DISPL_127_MASK 0000177u /* mask for 0-127 displacements */
|
||||
#define DISPL_255_MASK 0000377u /* mask for 0-255 displacements */
|
||||
|
||||
#define DISPL_P_FLAG 0001000 /* P-relative displacement flag */
|
||||
#define DISPL_DB_FLAG 0000400 /* DB-relative displacement flag */
|
||||
#define DISPL_QPOS_FLAG 0000200 /* positive Q-relative displacement flag */
|
||||
#define DISPL_QNEG_FLAG 0000100 /* negative Q-relative displacement flag */
|
||||
#define DISPL_P_FLAG 0001000u /* P-relative displacement flag */
|
||||
#define DISPL_DB_FLAG 0000400u /* DB-relative displacement flag */
|
||||
#define DISPL_QPOS_FLAG 0000200u /* positive Q-relative displacement flag */
|
||||
#define DISPL_QNEG_FLAG 0000100u /* negative Q-relative displacement flag */
|
||||
|
||||
#define IMMED_MASK 0000377 /* mask for immediate values */
|
||||
#define IMMED_MASK 0000377u /* mask for immediate values */
|
||||
|
||||
#define SDEC2_MASK 0000003 /* two-bit S-decrement mask for move instructions */
|
||||
#define SDEC3_MASK 0000007 /* three-bit S-decrement mask for move instructions */
|
||||
#define SDEC2_MASK 0000003u /* two-bit S-decrement mask for move instructions */
|
||||
#define SDEC3_MASK 0000007u /* three-bit S-decrement mask for move instructions */
|
||||
#define SDEC_SHIFT 0 /* S-decrement alignment shift */
|
||||
#define SDEC2(v) (((v) & SDEC2_MASK) >> SDEC_SHIFT)
|
||||
#define SDEC3(v) (((v) & SDEC3_MASK) >> SDEC_SHIFT)
|
||||
|
||||
#define DB_FLAG 0000020 /* PB/DB base flag */
|
||||
#define DB_FLAG 0000020u /* PB/DB base flag */
|
||||
|
||||
#define MVBW_CCF 0000030 /* MVBW condition code flags */
|
||||
#define MVBW_N_FLAG 0000020 /* MVBW numeric flag */
|
||||
#define MVBW_A_FLAG 0000010 /* MVBW alphabetic flag */
|
||||
#define MVBW_S_FLAG 0000004 /* MVBW upshift flag */
|
||||
#define MVBW_CCF 0000030u /* MVBW condition code flags */
|
||||
#define MVBW_N_FLAG 0000020u /* MVBW numeric flag */
|
||||
#define MVBW_A_FLAG 0000010u /* MVBW alphabetic flag */
|
||||
#define MVBW_S_FLAG 0000004u /* MVBW upshift flag */
|
||||
#define MVBW_CCF_SHIFT 6 /* CCF alignment in MVBW instruction */
|
||||
|
||||
#define NABS_FLAG 0000100 /* CVDA negative absolute value flag */
|
||||
#define ABS_FLAG 0000040 /* CVDA absolute value flag */
|
||||
#define NABS_FLAG 0000100u /* CVDA negative absolute value flag */
|
||||
#define ABS_FLAG 0000040u /* CVDA absolute value flag */
|
||||
|
||||
#define EIS_SDEC_SHIFT 4 /* EIS S-decrement alignment shift */
|
||||
|
||||
|
||||
/* Explicit instruction opcodes and accessors */
|
||||
|
||||
#define NOP 0000000 /* no operation */
|
||||
#define QASR 0015700 /* quadruple arithmetic right shift */
|
||||
#define DMUL 0020570 /* double integer multiply */
|
||||
#define DDIV 0020571 /* double integer divide */
|
||||
#define SED_1 0030041 /* set enable interrupt */
|
||||
#define HALT_10 0030370 /* halt 10 */
|
||||
#define NOP 0000000u /* no operation */
|
||||
#define QASR 0015700u /* quadruple arithmetic right shift */
|
||||
#define DMUL 0020570u /* double integer multiply */
|
||||
#define DDIV 0020571u /* double integer divide */
|
||||
#define SED_1 0030041u /* set enable interrupt */
|
||||
#define HALT_10 0030370u /* halt 10 */
|
||||
|
||||
#define MTFDS_MASK 0177730 /* move to/from data segment mask */
|
||||
#define MTFDS 0020130 /* move to/from data segment */
|
||||
#define MTFDS_MASK 0177730u /* move to/from data segment mask */
|
||||
#define MTFDS 0020130u /* move to/from data segment */
|
||||
|
||||
#define EXIT_MASK 0177400 /* exit procedure mask */
|
||||
#define EXIT 0031400 /* exit procedure */
|
||||
#define EXIT_MASK 0177400u /* exit procedure mask */
|
||||
#define EXIT 0031400u /* exit procedure */
|
||||
|
||||
#define PAUS_MASK 0177760 /* pause mask */
|
||||
#define PAUS 0030020 /* pause */
|
||||
#define PAUS_MASK 0177760u /* pause mask */
|
||||
#define PAUS 0030020u /* pause */
|
||||
|
||||
#define BR_MASK 0173000 /* conditional and unconditional branch mask */
|
||||
#define BR_DBQS_I 0143000 /* branch unconditionally DB/Q/S-relative indirect */
|
||||
#define BCC 0141000 /* branch conditionally */
|
||||
#define BR_MASK 0173000u /* conditional and unconditional branch mask */
|
||||
#define BR_DBQS_I 0143000u /* branch unconditionally DB/Q/S-relative indirect */
|
||||
#define BCC 0141000u /* branch conditionally */
|
||||
#define BCC_CCF_SHIFT 2 /* CCF alignment in BCC instruction */
|
||||
|
||||
#define LSDX_MASK 0175000 /* load/store double-word indexed mask */
|
||||
#define LDD_X 0155000 /* load double-word indexed */
|
||||
#define STD_X 0165000 /* store double-word indexed */
|
||||
#define LSDX_MASK 0175000u /* load/store double-word indexed mask */
|
||||
#define LDD_X 0155000u /* load double-word indexed */
|
||||
#define STD_X 0165000u /* store double-word indexed */
|
||||
|
||||
#define TBR_MASK 0177000 /* test and branch mask */
|
||||
#define TBA 0050000 /* test and branch, limit in A */
|
||||
#define MTBA 0052000 /* modify, test and branch, limit in A */
|
||||
#define TBX 0054000 /* test and branch, limit in X */
|
||||
#define MTBX 0056000 /* modify, test and branch, limit in X */
|
||||
#define TBR_MASK 0177000u /* test and branch mask */
|
||||
#define TBA 0050000u /* test and branch, limit in A */
|
||||
#define MTBA 0052000u /* modify, test and branch, limit in A */
|
||||
#define TBX 0054000u /* test and branch, limit in X */
|
||||
#define MTBX 0056000u /* modify, test and branch, limit in X */
|
||||
|
||||
|
||||
/* PSHR/SETR instruction accessors */
|
||||
|
||||
#define PSR_RL_MASK 0000001 /* PSHR/SETR register right-to-left mask */
|
||||
#define PSR_LR_MASK 0000200 /* PSHR/SETR register left-to-right mask */
|
||||
#define PSR_RL_MASK 0000001u /* PSHR/SETR register right-to-left mask */
|
||||
#define PSR_LR_MASK 0000200u /* PSHR/SETR register left-to-right mask */
|
||||
|
||||
#define PSR_SBANK 0000200 /* Stack bank register */
|
||||
#define PSR_DB_DBANK 0000100 /* Data base and data bank registers */
|
||||
#define PSR_DL 0000040 /* Data limit register */
|
||||
#define PSR_Z 0000020 /* Stack limit register */
|
||||
#define PSR_STA 0000010 /* Status register */
|
||||
#define PSR_X 0000004 /* Index register */
|
||||
#define PSR_Q 0000002 /* Frame pointer */
|
||||
#define PSR_S 0000001 /* Stack pointer */
|
||||
#define PSR_SBANK 0000200u /* Stack bank register */
|
||||
#define PSR_DB_DBANK 0000100u /* Data base and data bank registers */
|
||||
#define PSR_DL 0000040u /* Data limit register */
|
||||
#define PSR_Z 0000020u /* Stack limit register */
|
||||
#define PSR_STA 0000010u /* Status register */
|
||||
#define PSR_X 0000004u /* Index register */
|
||||
#define PSR_Q 0000002u /* Frame pointer */
|
||||
#define PSR_S 0000001u /* Stack pointer */
|
||||
|
||||
#define PSR_PRIV (PSR_SBANK | PSR_DB_DBANK | PSR_DL | PSR_Z)
|
||||
|
||||
|
||||
/* Reserved memory addresses */
|
||||
|
||||
#define CSTB_POINTER 0000000 /* code segment table base pointer */
|
||||
#define CSTX_POINTER 0000001 /* code segment table extension pointer */
|
||||
#define DST_POINTER 0000002 /* data segment table pointer */
|
||||
#define ICS_Q 0000005 /* interrupt control stack marker pointer (QI) */
|
||||
#define ICS_Z 0000006 /* interrupt control stack limit (ZI) */
|
||||
#define INTERRUPT_MASK 0000007 /* interrupt mask */
|
||||
#define SGT_POINTER 0001000 /* system global tables pointer */
|
||||
#define CSTB_POINTER 0000000u /* code segment table base pointer */
|
||||
#define CSTX_POINTER 0000001u /* code segment table extension pointer */
|
||||
#define DST_POINTER 0000002u /* data segment table pointer */
|
||||
#define ICS_Q 0000005u /* interrupt control stack marker pointer (QI) */
|
||||
#define ICS_Z 0000006u /* interrupt control stack limit (ZI) */
|
||||
#define INTERRUPT_MASK 0000007u /* interrupt mask */
|
||||
#define SGT_POINTER 0001000u /* system global tables pointer */
|
||||
|
||||
|
||||
/* Code Segment Table accessors */
|
||||
|
||||
#define CST_A_BIT 0100000 /* code segment is absent */
|
||||
#define CST_M_BIT 0040000 /* code segment is privileged */
|
||||
#define CST_R_BIT 0020000 /* code segment has been referenced flag */
|
||||
#define CST_T_BIT 0010000 /* code segment is to be traced */
|
||||
#define CST_SEGLEN_MASK 0007777 /* code segment length mask */
|
||||
#define CST_BANK_MASK 0000017 /* code segment bank mask */
|
||||
#define CST_A_BIT 0100000u /* code segment is absent */
|
||||
#define CST_M_BIT 0040000u /* code segment is privileged */
|
||||
#define CST_R_BIT 0020000u /* code segment has been referenced flag */
|
||||
#define CST_T_BIT 0010000u /* code segment is to be traced */
|
||||
#define CST_SEGLEN_MASK 0007777u /* code segment length mask */
|
||||
#define CST_BANK_MASK 0000017u /* code segment bank mask */
|
||||
|
||||
#define CST_RESERVED 0000300 /* number of CST entries reserved for the system */
|
||||
#define CST_RESERVED 0000300u /* number of CST entries reserved for the system */
|
||||
|
||||
|
||||
/* Data Segment Table accessors */
|
||||
|
||||
#define DST_A_BIT 0100000 /* data segment is absent */
|
||||
#define DST_C_BIT 0040000 /* data segment is clean (not modified) */
|
||||
#define DST_R_BIT 0020000 /* data segment has been referenced */
|
||||
#define DST_SEGLEN_MASK 0017777 /* data segment length mask */
|
||||
#define DST_BANK_MASK 0000017 /* data segment bank mask */
|
||||
#define DST_A_BIT 0100000u /* data segment is absent */
|
||||
#define DST_C_BIT 0040000u /* data segment is clean (not modified) */
|
||||
#define DST_R_BIT 0020000u /* data segment has been referenced */
|
||||
#define DST_SEGLEN_MASK 0017777u /* data segment length mask */
|
||||
#define DST_BANK_MASK 0000017u /* data segment bank mask */
|
||||
|
||||
|
||||
/* Segment Transfer Table accessors */
|
||||
|
||||
#define STT_LENGTH_MASK 0000377 /* STT length mask */
|
||||
#define STT_LENGTH_MASK 0000377u /* STT length mask */
|
||||
|
||||
#define STT_LENGTH_SHIFT 0 /* STT length alignment shift */
|
||||
|
||||
|
@ -878,15 +901,15 @@ typedef enum {
|
|||
|
||||
/* Program label accessors */
|
||||
|
||||
#define LABEL_EXTERNAL 0100000 /* external program label flag */
|
||||
#define LABEL_STTN_MASK 0077400 /* external program label STT number mask */
|
||||
#define LABEL_SEGMENT_MASK 0000377 /* external program label segment mask */
|
||||
#define LABEL_EXTERNAL 0100000u /* external program label flag */
|
||||
#define LABEL_STTN_MASK 0077400u /* external program label STT number mask */
|
||||
#define LABEL_SEGMENT_MASK 0000377u /* external program label segment mask */
|
||||
|
||||
#define LABEL_STTN_SHIFT 8 /* STT number alignment shift */
|
||||
#define LABEL_SEGMENT_SHIFT 0 /* segment number alignment shift */
|
||||
|
||||
#define LABEL_UNCALLABLE 0040000 /* local program label uncallable flag */
|
||||
#define LABEL_ADDRESS_MASK 0037777 /* local program label address mask */
|
||||
#define LABEL_UNCALLABLE 0040000u /* local program label uncallable flag */
|
||||
#define LABEL_ADDRESS_MASK 0037777u /* local program label address mask */
|
||||
|
||||
#define STT_NUMBER(l) (((l) & LABEL_STTN_MASK) >> LABEL_STTN_SHIFT)
|
||||
#define STT_SEGMENT(l) (((l) & LABEL_SEGMENT_MASK) >> LABEL_SEGMENT_SHIFT)
|
||||
|
@ -901,10 +924,10 @@ typedef enum {
|
|||
|
||||
/* Stack marker accessors */
|
||||
|
||||
#define STMK_D 0100000 /* dispatcher flag */
|
||||
#define STMK_T 0100000 /* trace flag */
|
||||
#define STMK_M 0040000 /* mapped flag */
|
||||
#define STMK_RTN_ADDR 0037777 /* PB-relative return address */
|
||||
#define STMK_D 0100000u /* dispatcher flag */
|
||||
#define STMK_T 0100000u /* trace flag */
|
||||
#define STMK_M 0040000u /* mapped flag */
|
||||
#define STMK_RTN_ADDR 0037777u /* PB-relative return address */
|
||||
|
||||
|
||||
/* CPU registers */
|
||||
|
@ -952,7 +975,7 @@ extern UNIT cpu_unit; /* CPU unit structure (needed fo
|
|||
|
||||
/* Condition Code B mapping table */
|
||||
|
||||
extern const uint16 cpu_ccb_table [256]; /* byte-value to condition-code map */
|
||||
extern const HP_WORD cpu_ccb_table [256]; /* byte-value to condition-code map */
|
||||
|
||||
|
||||
/* Global CPU functions */
|
||||
|
|
|
@ -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.
|
||||
|
||||
11-Jun-16 JDB Bit mask constants are now unsigned
|
||||
13-Jan-16 JDB First release version
|
||||
11-Dec-12 JDB Created
|
||||
|
||||
|
@ -76,13 +77,13 @@ extern DEVICE cpu_dev; /* Central Processing Unit */
|
|||
|
||||
/* Program constants */
|
||||
|
||||
#define SIO_OK 0100000 /* TIO bit 0 = SIO OK */
|
||||
#define DIO_OK 0040000 /* TIO bit 1 = DIO OK */
|
||||
#define SIO_OK 0100000u /* TIO bit 0 = SIO OK */
|
||||
#define DIO_OK 0040000u /* TIO bit 1 = DIO OK */
|
||||
|
||||
#define NORM_BIT (D48_SIGN >> 6) /* triple normalizing examines bit 6 */
|
||||
#define NORM_MASK (D48_MASK >> 6) /* triple normalizing masks off bits 0-5 */
|
||||
|
||||
#define TO_UPPERCASE(b) ((b) & ~040) /* alphabetic byte upshift */
|
||||
#define TO_UPPERCASE(b) ((b) & ~040u) /* alphabetic byte upshift */
|
||||
|
||||
|
||||
/* CPU base set global data structures */
|
||||
|
|
|
@ -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.
|
||||
|
||||
11-Jun-16 JDB Bit mask constants are now unsigned
|
||||
03-Feb-16 JDB First release version
|
||||
25-Aug-15 JDB Fixed FSUB zero subtrahend bug (from Norwin Malmberg)
|
||||
01-Apr-15 JDB Passes the floating point tests in the CPU diagnostic (D420A1)
|
||||
|
@ -112,18 +113,18 @@
|
|||
#define MIN_EXPONENT -256 /* the smallest representable exponent */
|
||||
#define MAX_EXPONENT +255 /* the largest representable exponent */
|
||||
|
||||
#define EXPONENT_MASK 0077700 /* the mask to isolate the exponent in the first word */
|
||||
#define MANTISSA_MASK 0000077 /* the mask to isolate the mantissa in the first word */
|
||||
#define EXPONENT_MASK 0077700u /* the mask to isolate the exponent in the first word */
|
||||
#define MANTISSA_MASK 0000077u /* the mask to isolate the mantissa in the first word */
|
||||
|
||||
#define EXPONENT_SHIFT 6 /* the exponent alignment shift */
|
||||
#define MANTISSA_SHIFT 0 /* the mantissa alignment shift */
|
||||
|
||||
#define UNPACKED_BITS 54 /* the number of significant bits in the unpacked mantissa */
|
||||
|
||||
#define IMPLIED_BIT ((t_uint64) 1 << UNPACKED_BITS) /* the implied MSB in the mantissa */
|
||||
#define CARRY_BIT ((t_uint64) 1 << UNPACKED_BITS + 1) /* the carry from the MSB in the mantissa */
|
||||
#define IMPLIED_BIT ((t_uint64) 1uL << UNPACKED_BITS) /* the implied MSB in the mantissa */
|
||||
#define CARRY_BIT ((t_uint64) 1uL << UNPACKED_BITS + 1) /* the carry from the MSB in the mantissa */
|
||||
|
||||
#define DELTA_ALIGNMENT (D64_WIDTH - UNPACKED_BITS) /* net shift to align the binary point */
|
||||
#define DELTA_ALIGNMENT (D64_WIDTH - UNPACKED_BITS) /* net shift to align the binary point */
|
||||
|
||||
|
||||
/* Floating-point accessors */
|
||||
|
|
|
@ -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.
|
||||
|
||||
11-Jun-16 JDB Bit mask constants are now unsigned
|
||||
21-Jan-16 JDB First release version
|
||||
29-Mar-15 JDB Created
|
||||
|
||||
|
@ -35,10 +36,10 @@
|
|||
|
||||
/* Program constants */
|
||||
|
||||
#define SIGN_BIT 0100000
|
||||
#define EXPONENT_BITS 0077700
|
||||
#define ASSUMED_BIT 0000100
|
||||
#define FRACTION_BITS 0000077
|
||||
#define SIGN_BIT 0100000u
|
||||
#define EXPONENT_BITS 0077700u
|
||||
#define ASSUMED_BIT 0000100u
|
||||
#define FRACTION_BITS 0000077u
|
||||
|
||||
|
||||
/* Operand precisions:
|
||||
|
|
|
@ -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.
|
||||
|
||||
11-Jun-16 JDB Bit mask constants are now unsigned
|
||||
05-Sep-15 JDB First release version
|
||||
11-Dec-12 JDB Created
|
||||
|
||||
|
@ -98,13 +99,13 @@ typedef enum {
|
|||
identifies all four cases.
|
||||
*/
|
||||
|
||||
#define IOCW_DC 0100000 /* data chain */
|
||||
#define IOCW_SIO_MASK 0070000 /* general SIO order mask */
|
||||
#define IOCW_ORDER_MASK 0174000 /* fully decoded I/O order mask */
|
||||
#define IOCW_CNTL_MASK 0007777 /* control word mask */
|
||||
#define IOCW_WCNT_MASK 0007777 /* word count mask */
|
||||
#define IOCW_DC 0100000u /* data chain */
|
||||
#define IOCW_SIO_MASK 0070000u /* general SIO order mask */
|
||||
#define IOCW_ORDER_MASK 0174000u /* fully decoded I/O order mask */
|
||||
#define IOCW_CNTL_MASK 0007777u /* control word mask */
|
||||
#define IOCW_WCNT_MASK 0007777u /* word count mask */
|
||||
|
||||
#define IOAW_BANK_MASK 0000017 /* bank number mask */
|
||||
#define IOAW_BANK_MASK 0000017u /* bank number mask */
|
||||
|
||||
#define IOCW_ORDER_SHIFT 11 /* I/O order alignment shift */
|
||||
#define IOCW_CNTL_SHIFT 0 /* control word alignment shift */
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
this Software without prior written authorization from the author.
|
||||
|
||||
13-May-16 JDB Modified for revised SCP API function parameter types
|
||||
21-Mar-16 JDB Changed uint16 types to HP_WORD
|
||||
19-Mar-16 JDB Added UNDEFs for the additional register macros
|
||||
04-Feb-16 JDB First release version
|
||||
11-Dec-12 JDB Created
|
||||
|
||||
|
@ -33,6 +35,73 @@
|
|||
|
||||
The author gratefully acknowledges the help of Frank McConnell in answering
|
||||
questions about the HP 3000.
|
||||
|
||||
|
||||
-----------------------------------------------------
|
||||
Implementation Note -- Compiling the Simulator as C++
|
||||
-----------------------------------------------------
|
||||
|
||||
Although simulators are written in C, the SIMH project encourages developers
|
||||
to compile them with a C++ compiler to obtain the more careful type checking
|
||||
provided. To obtain successful compilations, the simulator must be written
|
||||
in the subset of C that is also valid C++. Using valid C features beyond
|
||||
that subset, as the HP 3000 simulator does, will produce C++ compiler errors.
|
||||
|
||||
The standard C features used by the simulator that prevent error-free C++
|
||||
compilation are:
|
||||
|
||||
1. Incomplete types.
|
||||
|
||||
In C, mutually recursive type definitions are allowed by the use of
|
||||
incomplete type declarations, such as "DEVICE ms_dev;" followed later by
|
||||
"DEVICE ms_dev {...};". Several HP device simulators use this feature to
|
||||
place a pointer to the device structure in the "desc" field of an MTAB
|
||||
array element, typically when the associated validation or display
|
||||
routine handles multiple devices. As the DEVICE contains a pointer to
|
||||
the MTAB array, and an MTAB array element contains a pointer to the
|
||||
DEVICE, the definitions are mutually recursive, and incomplete types are
|
||||
employed. C++ does not permit incomplete types.
|
||||
|
||||
2. Implicit conversion of ints to enums.
|
||||
|
||||
In C, enumeration types are compatible with integer types, and its
|
||||
members are constants having type "int". As such, they are semantically
|
||||
equivalent to and may be used interchangeably with integers. For the
|
||||
developer, though, C enumerations have some advantages. In particular,
|
||||
the compiler may check a "switch" statement to ensure that all of the
|
||||
enumeration cases are covered. Also, a mathematical set may be modeled
|
||||
by an enumeration type with disjoint enumerator values, with the bitwise
|
||||
integer OR and AND operators modeling the set union and intersection
|
||||
operations. The latter has direct support in the "gdb" debugger, which
|
||||
will display an enumerated type value as a union of the various
|
||||
enumerators. The HP simulator makes extensive use of both features to
|
||||
model hardware signal buses (e.g., INBOUND_SET, OUTBOUND_SET) and so
|
||||
performs bitwise integer operations on the enumerations to model signal
|
||||
assertion and denial. In C++, implicit conversion from enumerations to
|
||||
integers is allowed, but conversion from integers to enumerations is
|
||||
illegal without explicit casts. Therefore, the idiom employed by the
|
||||
simulator to assert a signal (e.g., "outbound_signals |= INTREQ") is
|
||||
rejected by the C++ compiler.
|
||||
|
||||
3. Implicit increment operations on enums.
|
||||
|
||||
Because enums are compatible with integers in C, no special enumerator
|
||||
increment operator is provided. To cycle through the range of an
|
||||
enumeration type, e.g. in a "for" statement, the standard integer
|
||||
increment operator, "++", is used. In C++, the "++" operator must be
|
||||
overloaded with a version specific to the enumeration type; applying the
|
||||
integer "++" to an enumeration is illegal.
|
||||
|
||||
4. Use of C++ keywords as variable names.
|
||||
|
||||
C++ reserves a number of additional keywords beyond those reserved by C.
|
||||
Use of any of these keywords as a variable or type name is legal C but
|
||||
illegal C++. The HP simulator uses variables named "class" and
|
||||
"operator", which are keywords in C++.
|
||||
|
||||
The HP simulator is written in ISO standard C and will compile cleanly with a
|
||||
compiler implementing the 1999 C standard. Compilation as C++ is not a goal
|
||||
of the simulator and cannot work, given the incompatibilities listed above.
|
||||
*/
|
||||
|
||||
|
||||
|
@ -71,15 +140,16 @@
|
|||
|
||||
#elif defined (_MSC_VER)
|
||||
#pragma warning (disable: 4114 4554 4996)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Device register display mode flags */
|
||||
|
||||
#define REG_A (1 << REG_V_UF + 0) /* permit any display */
|
||||
#define REG_B (1 << REG_V_UF + 1) /* permit binary display */
|
||||
#define REG_M (1 << REG_V_UF + 2) /* default to instruction mnemonic display */
|
||||
#define REG_S (1 << REG_V_UF + 3) /* default to status mnemonic display */
|
||||
#define REG_A (1u << REG_V_UF + 0) /* permit any display */
|
||||
#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_S (1u << REG_V_UF + 3) /* default to status mnemonic display */
|
||||
|
||||
|
||||
/* Register macros.
|
||||
|
@ -90,12 +160,12 @@
|
|||
SRDATA -- an array of bytes large enough to hold a structure
|
||||
YRDATA -- a binary register
|
||||
|
||||
The FBDATA macro defines flag bits that are replicated in the same place in
|
||||
each element of an array; the array element size is assumed to be the minimum
|
||||
necessary to hold the bit at the given offset. The SRDATA macro is used
|
||||
solely to SAVE data stored in a structure so that it may be RESTOREd later.
|
||||
The YRDATA macro extends the functionality of the ORDATA, DRDATA, and HRDATA
|
||||
macros to registers with binary (base 2) representation.
|
||||
The FBDATA macro defines a flag that is replicated in the same bit position
|
||||
in each element of an array; the array element size is assumed to be the
|
||||
minimum necessary to hold the bit at the given offset. The SRDATA macro is
|
||||
used solely to SAVE data stored in a structure so that it may be RESTOREd
|
||||
later. The YRDATA macro extends the functionality of the ORDATA, DRDATA, and
|
||||
HRDATA macros to registers with binary (base 2) representation.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
@ -107,22 +177,42 @@
|
|||
offsets 3 and 13 cannot be used, as the first implies 8-bit elements, and
|
||||
the second implies 16-bit elements.
|
||||
|
||||
2. The REG structure for version 4.0 contains two extra fields that are not
|
||||
present in 3.x versions.
|
||||
2. The macro names are UNDEFed to avoid potential name clashes with
|
||||
sim_def.h macros.
|
||||
|
||||
3. The REG structure for version 4.0 contains several fields that are not
|
||||
present in 3.x versions. The 4.x REGDATA macro maps to the REG strcture
|
||||
in a field-order- and preprocessor-independent manner. There is no
|
||||
corresponding macro in 3.x, so we must handle standard vs. non-standard
|
||||
preprocessor differences by creating our own REGMAP macro to handle the
|
||||
mapping.
|
||||
*/
|
||||
|
||||
/* Macro name loc radix width offset depth desc fields */
|
||||
/* ---------------------- ---- ------- ----- ----- ------ ---------- ---- ------ */
|
||||
#undef FBDATA
|
||||
#undef SRDATA
|
||||
#undef YRDATA
|
||||
#undef REGMAP
|
||||
|
||||
#if (SIM_MAJOR >= 4)
|
||||
#define FBDATA(nm,loc,ofs,dep) #nm, &(loc), 2, 1, (ofs), (dep), NULL, NULL
|
||||
#define SRDATA(nm,loc) #nm, &(loc), 8, 8, 0, sizeof loc, NULL, NULL
|
||||
#define YRDATA(nm,loc,wid) #nm, &(loc), 2, (wid), 0, 1, NULL, NULL
|
||||
#define REGMAP(nm,loc,rdx,wd,off,dep,fl) \
|
||||
REGDATA (nm, loc, rdx, wd, off, dep, NULL, NULL, fl, 0, 0)
|
||||
|
||||
#elif defined (__STDC__) || defined (_WIN32)
|
||||
#define REGMAP(nm,loc,rdx,wd,off,dep,fl) \
|
||||
#nm, &(loc), (rdx), (wd), (off), (dep), (fl), 0
|
||||
|
||||
#else
|
||||
#define FBDATA(nm,loc,ofs,dep) #nm, &(loc), 2, 1, (ofs), (dep)
|
||||
#define SRDATA(nm,loc) #nm, &(loc), 8, 8, 0, sizeof loc
|
||||
#define YRDATA(nm,loc,wid) #nm, &(loc), 2, (wid), 0, 1
|
||||
#define REGMAP(nm,loc,rdx,wd,off,dep,fl) \
|
||||
"nm", &(loc), (rdx), (wd), (off), (dep), (fl), 0
|
||||
|
||||
#endif
|
||||
|
||||
/* Macro name loc radix width offset depth flags */
|
||||
/* ------------------------- ---- ------ ----- ----- ------ ---------- ----- */
|
||||
#define FBDATA(nm,loc,ofs,dep,fl) REGMAP (nm, (loc), 2, 1, (ofs), (dep), (fl) )
|
||||
#define SRDATA(nm,loc,fl) REGMAP (nm, (loc), 8, 8, 0, sizeof loc, (fl) )
|
||||
#define YRDATA(nm,loc,wid,fl) REGMAP (nm, (loc), 2, (wid), 0, 1, (fl) )
|
||||
|
||||
|
||||
/* Debugging and console output.
|
||||
|
||||
|
@ -260,13 +350,17 @@
|
|||
simulator. In addition, masks for 16-bit and 32-bit overflow are defined (an
|
||||
overflow is indicated if the masked bits are not all ones or all zeros).
|
||||
|
||||
The HP_WORD type is used to declare variables that represent 16-bit registers
|
||||
or buses in hardware.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. The HP_WORD type is a 32-bit unsigned type, instead of the more logical
|
||||
16-bit unsigned type. This is because IA-32 processors execute
|
||||
instructions with 32-bit operands much faster than those with 16-bit
|
||||
operands.
|
||||
16-bit unsigned type. There are two reasons for this. First, SCP
|
||||
requires that scalars referenced by REG (register) entries be 32 bits in
|
||||
size. Second, IA-32 processors execute instructions with 32-bit operands
|
||||
much faster than those with 16-bit operands.
|
||||
|
||||
Using 16-bit operands omits the masking required for 32-bit values. For
|
||||
example, the code generated for the following operations is as follows:
|
||||
|
@ -295,7 +389,7 @@
|
|||
HP 3000 memory diagnostic to run about 10% slower.
|
||||
*/
|
||||
|
||||
#define HP_WORD uint32 /* HP 16-bit word representation */
|
||||
typedef uint32 HP_WORD; /* HP 16-bit data word representation */
|
||||
|
||||
#define R_MASK 0177777u /* 16-bit register mask */
|
||||
|
||||
|
@ -343,23 +437,23 @@
|
|||
|
||||
/* Memory constants */
|
||||
|
||||
#define LA_WIDTH 16 /* logical address bit width */
|
||||
#define LA_MASK ((1 << LA_WIDTH) - 1) /* logical address mask (2 ** 16 - 1) */
|
||||
#define LA_MAX ((1 << LA_WIDTH) - 1) /* logical address maximum (2 ** 16 - 1) */
|
||||
#define LA_WIDTH 16 /* logical address bit width */
|
||||
#define LA_MASK ((1u << LA_WIDTH) - 1) /* logical address mask (2 ** 16 - 1) */
|
||||
#define LA_MAX ((1u << LA_WIDTH) - 1) /* logical address maximum (2 ** 16 - 1) */
|
||||
|
||||
#define BA_WIDTH 4 /* bank address bit width */
|
||||
#define BA_MASK ((1 << BA_WIDTH) - 1) /* bank address mask (2 ** 4 - 1) */
|
||||
#define BA_MAX ((1 << BA_WIDTH) - 1) /* bank address maximum (2 ** 4 - 1) */
|
||||
#define BA_WIDTH 4 /* bank address bit width */
|
||||
#define BA_MASK ((1u << BA_WIDTH) - 1) /* bank address mask (2 ** 4 - 1) */
|
||||
#define BA_MAX ((1u << BA_WIDTH) - 1) /* bank address maximum (2 ** 4 - 1) */
|
||||
|
||||
#define PA_WIDTH (LA_WIDTH + BA_WIDTH) /* physical address bit width */
|
||||
#define PA_MASK ((1 << PA_WIDTH) - 1) /* physical address mask (2 ** 20 - 1) */
|
||||
#define PA_MAX ((1 << PA_WIDTH) - 1) /* physical address maximum (2 ** 20 - 1) */
|
||||
#define PA_WIDTH (LA_WIDTH + BA_WIDTH) /* physical address bit width */
|
||||
#define PA_MASK ((1u << PA_WIDTH) - 1) /* physical address mask (2 ** 20 - 1) */
|
||||
#define PA_MAX ((1u << PA_WIDTH) - 1) /* physical address maximum (2 ** 20 - 1) */
|
||||
|
||||
#define DV_WIDTH 16 /* data value bit width */
|
||||
#define DV_MASK ((1 << DV_WIDTH) - 1) /* data value mask (2 ** 16 - 1) */
|
||||
#define DV_SIGN (1 << (DV_WIDTH - 1)) /* data value sign (2 ** 15) */
|
||||
#define DV_UMAX ((1 << DV_WIDTH) - 1) /* data value unsigned maximum (2 ** 16 - 1) */
|
||||
#define DV_SMAX ((1 << (DV_WIDTH - 1)) - 1) /* data value signed maximum (2 ** 15 - 1) */
|
||||
#define DV_WIDTH 16 /* data value bit width */
|
||||
#define DV_MASK ((1u << DV_WIDTH) - 1) /* data value mask (2 ** 16 - 1) */
|
||||
#define DV_SIGN ( 1u << (DV_WIDTH - 1)) /* data value sign (2 ** 15) */
|
||||
#define DV_UMAX ((1u << DV_WIDTH) - 1) /* data value unsigned maximum (2 ** 16 - 1) */
|
||||
#define DV_SMAX ((1u << (DV_WIDTH - 1)) - 1) /* data value signed maximum (2 ** 15 - 1) */
|
||||
|
||||
|
||||
/* Memory address macros.
|
||||
|
@ -372,11 +466,11 @@
|
|||
- TO_OFFSET -- extract the offset part of a physical address
|
||||
|
||||
|
||||
Implementation notes:
|
||||
Implementation notes:
|
||||
|
||||
1. The TO_PA offset parameter is not masked to 16 bits, as this value is
|
||||
almost always derived from a value that is inherently 16 bits in size. In
|
||||
the few cases where it is not, explicit masking is required.
|
||||
1. The TO_PA offset parameter is not masked to 16 bits, as this value is
|
||||
almost always derived from a value that is inherently 16 bits in size.
|
||||
In the few cases where it is not, explicit masking is required.
|
||||
*/
|
||||
|
||||
#define TO_PA(b,o) (((uint32) (b) & BA_MASK) << LA_WIDTH | (uint32) (o))
|
||||
|
@ -465,9 +559,9 @@ typedef enum {
|
|||
SET = 1 /* the flip-flop is set */
|
||||
} FLIP_FLOP;
|
||||
|
||||
#define TOGGLE(ff) ff = (ff ^ 1) /* toggle a flip-flop variable */
|
||||
#define TOGGLE(ff) ff = (FLIP_FLOP) (ff ^ 1) /* toggle a flip-flop variable */
|
||||
|
||||
#define D_FF(b) ((b) != 0) /* use a Boolean expression for a D flip-flop */
|
||||
#define D_FF(b) (FLIP_FLOP) ((b) != 0) /* use a Boolean expression for a D flip-flop */
|
||||
|
||||
|
||||
/* Bitset formatting.
|
||||
|
@ -491,7 +585,7 @@ typedef enum { /* trailing separator */
|
|||
append_bar /* append a trailing separator */
|
||||
} BITSET_BAR;
|
||||
|
||||
typedef const char *const BITSET_NAME; /* a bit name string pointer */
|
||||
typedef const char *const BITSET_NAME; /* a bit name string pointer */
|
||||
|
||||
typedef struct { /* bit set format descriptor */
|
||||
uint32 name_count; /* count of bit names */
|
||||
|
@ -511,7 +605,7 @@ typedef struct { /* bit set format descriptor */
|
|||
|
||||
/* System interface global data structures */
|
||||
|
||||
extern const uint16 odd_parity [256]; /* a table of parity bits for odd parity */
|
||||
extern const HP_WORD odd_parity [256]; /* a table of parity bits for odd parity */
|
||||
|
||||
extern const BITSET_FORMAT inbound_format; /* the inbound signal format structure */
|
||||
extern const BITSET_FORMAT outbound_format; /* the outbound signal format structure */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
SIMH/HP 3000 DIAGNOSTICS PERFORMANCE
|
||||
====================================
|
||||
Last update: 2016-02-09
|
||||
Last update: 2016-05-31
|
||||
|
||||
|
||||
The HP 32230 offline diagnostic suite has been run against the SIMH HP 3000
|
||||
|
@ -57,11 +57,12 @@ The results of the diagnostic runs are summarized below:
|
|||
PD433A 7970B/E Nine-Track Magnetic Tape 01.04 Partial
|
||||
PD434A Synchronous Line Controller 01.03 No simulation
|
||||
PD434B Asynchronous Line Controller 01.04 No simulation
|
||||
PD435A Universal Interface 01.01 No simulation
|
||||
PD435A Universal Interface 01.01 Passed
|
||||
PD438A Terminal Control Interface 01.00 Passed
|
||||
PD439A CALCOMP Plotter Interface 01.01 No simulation
|
||||
PD441A COBOL-II A Firmware 00.00 No simulation
|
||||
PD442A COBOL-II B Firmware 00.00 No simulation
|
||||
PD466A Online Line Printer Verifier 01.06 Passed
|
||||
|
||||
The "Result" column indicates the level of success in passing the given
|
||||
diagnostic:
|
||||
|
@ -92,9 +93,9 @@ Each configuration below presumes that the target diagnostic has been cold
|
|||
loaded from the appropriate magnetic tape.
|
||||
|
||||
|
||||
--------------------------------
|
||||
D420A - CPU Diagnostic Section 1
|
||||
--------------------------------
|
||||
---------------------
|
||||
D420A - CPU Section 1
|
||||
---------------------
|
||||
|
||||
TESTED DEVICE: CPU (hp3000_cpu.c)
|
||||
|
||||
|
@ -154,9 +155,9 @@ TEST NOTES: The Internal Switch Register (2000) and Section Select Register
|
|||
|
||||
|
||||
|
||||
---------------------------------
|
||||
D420A1 - CPU Diagnostic Section 2
|
||||
---------------------------------
|
||||
----------------------
|
||||
D420A1 - CPU Section 2
|
||||
----------------------
|
||||
|
||||
TESTED DEVICE: CPU (hp3000_cpu.c)
|
||||
|
||||
|
@ -173,9 +174,9 @@ TEST NOTES: The Internal Switch Register (2000) and Section Select Register
|
|||
|
||||
|
||||
|
||||
---------------------------------
|
||||
D420A2 - CPU Diagnostic Section 3
|
||||
---------------------------------
|
||||
----------------------
|
||||
D420A2 - CPU Section 3
|
||||
----------------------
|
||||
|
||||
TESTED DEVICE: CPU (hp3000_cpu.c)
|
||||
|
||||
|
@ -202,9 +203,9 @@ TEST NOTES: The Internal Switch Register (2000) and Section Select Register
|
|||
|
||||
|
||||
|
||||
---------------------------------
|
||||
D420A3 - CPU Diagnostic Section 4
|
||||
---------------------------------
|
||||
----------------------
|
||||
D420A3 - CPU Section 4
|
||||
----------------------
|
||||
|
||||
TESTED DEVICE: CPU (hp3000_cpu.c)
|
||||
|
||||
|
@ -257,9 +258,9 @@ TEST NOTES: The Internal Switch Register (2000) and Section Select Register
|
|||
|
||||
|
||||
|
||||
---------------------------------
|
||||
D420A4 - CPU Diagnostic Section 5
|
||||
---------------------------------
|
||||
----------------------
|
||||
D420A4 - CPU Section 5
|
||||
----------------------
|
||||
|
||||
TESTED DEVICE: CPU (hp3000_cpu.c)
|
||||
|
||||
|
@ -276,113 +277,113 @@ TEST NOTES: The Internal Switch Register (2000) and Section Select Register
|
|||
|
||||
|
||||
|
||||
---------------------------------
|
||||
D420A5 - CPU Diagnostic Section 6
|
||||
---------------------------------
|
||||
----------------------
|
||||
D420A5 - CPU Section 6
|
||||
----------------------
|
||||
|
||||
TESTED DEVICE: CPU (hp3000_cpu.c)
|
||||
|
||||
CONFIGURATION: sim> go
|
||||
|
||||
TEST REPORT: System halt, P: 010011 (SETR STATUS)
|
||||
TEST REPORT: System halt 3, P: 010011 (SETR STATUS)
|
||||
|
||||
TEST RESULT: Passed.
|
||||
|
||||
|
||||
|
||||
---------------------------------
|
||||
D420A6 - CPU Diagnostic Section 7
|
||||
---------------------------------
|
||||
----------------------
|
||||
D420A6 - CPU Section 7
|
||||
----------------------
|
||||
|
||||
TESTED DEVICE: CPU (hp3000_cpu.c)
|
||||
|
||||
CONFIGURATION: sim> go
|
||||
|
||||
TEST REPORT: System halt, P: 010011 (SETR STATUS)
|
||||
TEST REPORT: System halt 33, P: 010011 (SETR STATUS)
|
||||
|
||||
TEST RESULT: Passed.
|
||||
|
||||
|
||||
|
||||
---------------------------------
|
||||
D420A7 - CPU Diagnostic Section 8
|
||||
---------------------------------
|
||||
----------------------
|
||||
D420A7 - CPU Section 8
|
||||
----------------------
|
||||
|
||||
TESTED DEVICE: CPU (hp3000_cpu.c)
|
||||
|
||||
CONFIGURATION: sim> go
|
||||
|
||||
TEST REPORT: System halt, P: 010014 (PCAL 0)
|
||||
TEST REPORT: System halt 13, P: 010014 (PCAL 0)
|
||||
|
||||
TEST RESULT: Passed.
|
||||
|
||||
|
||||
|
||||
---------------------------------
|
||||
D420A8 - CPU Diagnostic Section 9
|
||||
---------------------------------
|
||||
----------------------
|
||||
D420A8 - CPU Section 9
|
||||
----------------------
|
||||
|
||||
TESTED DEVICE: CPU (hp3000_cpu.c)
|
||||
|
||||
CONFIGURATION: sim> go
|
||||
|
||||
TEST REPORT: System halt, P: 010016 (PCAL 0)
|
||||
TEST REPORT: System halt 2, P: 010016 (PCAL 0)
|
||||
|
||||
TEST RESULT: Passed.
|
||||
|
||||
|
||||
|
||||
----------------------------------
|
||||
D420A9 - CPU Diagnostic Section 10
|
||||
----------------------------------
|
||||
-----------------------
|
||||
D420A9 - CPU Section 10
|
||||
-----------------------
|
||||
|
||||
TESTED DEVICE: CPU (hp3000_cpu.c)
|
||||
|
||||
CONFIGURATION: sim> go
|
||||
|
||||
TEST REPORT: System halt, P: 010052 (IXIT)
|
||||
TEST REPORT: System halt 6, P: 010052 (IXIT)
|
||||
|
||||
TEST RESULT: Passed.
|
||||
|
||||
|
||||
|
||||
-----------------------------------
|
||||
D420A10 - CPU Diagnostic Section 11
|
||||
-----------------------------------
|
||||
------------------------
|
||||
D420A10 - CPU Section 11
|
||||
------------------------
|
||||
|
||||
TESTED DEVICE: CPU (hp3000_cpu.c)
|
||||
|
||||
CONFIGURATION: sim> go
|
||||
|
||||
TEST REPORT: System halt, P: 010011 (PSEB)
|
||||
TEST REPORT: System halt 9, P: 010011 (PSEB)
|
||||
|
||||
TEST RESULT: Passed.
|
||||
|
||||
|
||||
|
||||
-----------------------------------
|
||||
D420A11 - CPU Diagnostic Section 12
|
||||
-----------------------------------
|
||||
------------------------
|
||||
D420A11 - CPU Section 12
|
||||
------------------------
|
||||
|
||||
TESTED DEVICE: CPU (hp3000_cpu.c)
|
||||
|
||||
CONFIGURATION: sim> go
|
||||
|
||||
TEST REPORT: System halt, P: 010005 (SETR STATUS)
|
||||
TEST REPORT: System halt 1, P: 010005 (SETR STATUS)
|
||||
|
||||
TEST RESULT: Passed.
|
||||
|
||||
|
||||
|
||||
-----------------------------------
|
||||
D420A12 - CPU Diagnostic Section 13
|
||||
-----------------------------------
|
||||
------------------------
|
||||
D420A12 - CPU Section 13
|
||||
------------------------
|
||||
|
||||
TESTED DEVICE: CPU (hp3000_cpu.c)
|
||||
|
||||
CONFIGURATION: sim> go
|
||||
|
||||
TEST REPORT: System halt, P: 010010 (ADDS 0)
|
||||
TEST REPORT: System halt 4, P: 010010 (ADDS 0)
|
||||
|
||||
TEST RESULT: Passed.
|
||||
|
||||
|
@ -396,15 +397,15 @@ TESTED DEVICE: CPU (hp3000_cpu.c)
|
|||
|
||||
CONFIGURATION: sim> go
|
||||
|
||||
TEST REPORT: System halt, P: 010003 (LDI 0)
|
||||
TEST REPORT: System halt 4, P: 010003 (LDI 0)
|
||||
|
||||
TEST RESULT: Passed.
|
||||
|
||||
|
||||
|
||||
------------------------------------------
|
||||
D419A - 7905A Disc Cartridge (interactive)
|
||||
------------------------------------------
|
||||
-----------------------------------------
|
||||
D419A - Cartridge Disc (user interaction)
|
||||
-----------------------------------------
|
||||
|
||||
TESTED DEVICE: DS (hp3000_ds.c)
|
||||
|
||||
|
@ -582,9 +583,9 @@ TEST NOTES: The diagnostic overrides supply the expected status returns for
|
|||
|
||||
|
||||
|
||||
--------------------------------------------
|
||||
D419A - 7905A Disc Cartridge (multiple unit)
|
||||
--------------------------------------------
|
||||
--------------------------------------------------
|
||||
D419A - Cartridge Disc (multiple unit, short pass)
|
||||
--------------------------------------------------
|
||||
|
||||
TESTED DEVICE: DS (hp3000_ds.c)
|
||||
|
||||
|
@ -665,9 +666,9 @@ TEST NOTES: Section 1 is not selected to avoid specifying diagnostic
|
|||
|
||||
|
||||
|
||||
----------------------
|
||||
D421A - Memory Pattern
|
||||
----------------------
|
||||
--------------------------
|
||||
D421 - Memory Pattern Test
|
||||
--------------------------
|
||||
|
||||
TESTED DEVICE: CPU (hp3000_cpu.c)
|
||||
|
||||
|
@ -1128,9 +1129,9 @@ TEST RESULT: Passed.
|
|||
|
||||
|
||||
|
||||
-------------------------------------------------------------
|
||||
D433A - 7970B/E Nine-Track Magnetic Tape (7970B, single unit)
|
||||
-------------------------------------------------------------
|
||||
----------------------------------------------------
|
||||
D433A - 7970B Nine-Track Magnetic Tape (single unit)
|
||||
----------------------------------------------------
|
||||
|
||||
TESTED DEVICE: MS (hp3000_ms.c)
|
||||
|
||||
|
@ -1153,8 +1154,8 @@ TEST REPORT: [CR entered]
|
|||
A'CR'-AUTO, R'CR'-RESTART,
|
||||
M'CR'-MANU, 'CR'-RESUME, YOUR CODE? A
|
||||
D015 PRESENT SECTION REGISTER:%077414 DO YOU WISH TO CHANGE?(YES/NO)YES
|
||||
D015 UPDATE SECTION REGISTER:%067414
|
||||
D015 PRESENT SECTION REGISTER:%067414 DO YOU WISH TO CHANGE?(YES/NO)NO
|
||||
D015 UPDATE SECTION REGISTER:%067400
|
||||
D015 PRESENT SECTION REGISTER:%067400 DO YOU WISH TO CHANGE?(YES/NO)NO
|
||||
|
||||
Q019 AUTO-PROCESS: ENTER TAPE UNIT(B,E,NO) AT
|
||||
Q020 DRIVE 0? B
|
||||
|
@ -1196,9 +1197,9 @@ TEST NOTES: Section 3 (tape mark tests) is not selected, as the simulation
|
|||
|
||||
|
||||
|
||||
---------------------------------------------------------------
|
||||
D433A - 7970B/E Nine-Track Magnetic Tape (7970E, multiple unit)
|
||||
---------------------------------------------------------------
|
||||
------------------------------------------------------
|
||||
D433A - 7970E Nine-Track Magnetic Tape (multiple unit)
|
||||
------------------------------------------------------
|
||||
|
||||
TESTED DEVICE: MS (hp3000_ms.c)
|
||||
|
||||
|
@ -1223,7 +1224,9 @@ TEST REPORT: [CR entered]
|
|||
P005 TYPE FOLLOWING CONTROL
|
||||
A'CR'-AUTO, R'CR'-RESTART,
|
||||
M'CR'-MANU, 'CR'-RESUME, YOUR CODE? A
|
||||
D015 PRESENT SECTION REGISTER:%077414 DO YOU WISH TO CHANGE?(YES/NO)NO
|
||||
D015 PRESENT SECTION REGISTER:%077414 DO YOU WISH TO CHANGE?(YES/NO)YES
|
||||
D015 UPDATE SECTION REGISTER:%077400
|
||||
D015 PRESENT SECTION REGISTER:%077400 DO YOU WISH TO CHANGE?(YES/NO)NO
|
||||
|
||||
Q019 AUTO-PROCESS: ENTER TAPE UNIT(B,E,NO) AT
|
||||
Q020 DRIVE 0? E
|
||||
|
@ -1264,9 +1267,9 @@ TEST RESULT: Passed.
|
|||
|
||||
|
||||
|
||||
-------------------------------------------------------------
|
||||
D433A - 7970B/E Nine-Track Magnetic Tape (7970E, interactive)
|
||||
-------------------------------------------------------------
|
||||
---------------------------------------------------------
|
||||
D433A - 7970E Nine-Track Magnetic Tape (user interaction)
|
||||
---------------------------------------------------------
|
||||
|
||||
TESTED DEVICE: MS (hp3000_ms.c)
|
||||
|
||||
|
@ -1534,6 +1537,289 @@ TEST RESULT: Passed.
|
|||
|
||||
|
||||
|
||||
---------------------------
|
||||
D435A - Universal Interface
|
||||
---------------------------
|
||||
|
||||
TESTED DEVICE: LP (hp3000_lp.c)
|
||||
|
||||
CONFIGURATION: sim> set lp diagnostic,intmask=8
|
||||
sim> set clk realtime
|
||||
sim> go
|
||||
|
||||
TEST REPORT: D100 UNIV. INTERFACE TEST (HP D435A.01.01)
|
||||
(C)COPYRIGHT HEWLETT PACKARD COMPANY 1976.
|
||||
****************** WARNING ******************
|
||||
this diagnostic has tests which will produce error
|
||||
conditions on interface boards which have datecodes
|
||||
PRIOR TO 1504.
|
||||
|
||||
Q110 DEVICE NUMBER? 14
|
||||
Q112 INTERRUPT MASK? 8
|
||||
Q113 NEGATIVE TRUE? NO
|
||||
Q114 CHANGE INTERNAL SWITCH REGISTER? ? YES
|
||||
P114 INTERNAL SWITCH REGISTER
|
||||
|
||||
Programmed halt, CIR: 030366 (HALT 6), P: 026015 (DDEL,DDEL)
|
||||
|
||||
sim> deposit SWCH 100111
|
||||
sim> go
|
||||
|
||||
Q115 SECTION LIST?
|
||||
Q116 READER-PUNCH INTERFACE ? NO
|
||||
D102 END SECTION 0
|
||||
|
||||
D100 UNIV. INTERFACE TEST (HP D435A.01.01)
|
||||
(C)COPYRIGHT HEWLETT PACKARD COMPANY 1976.
|
||||
****************** WARNING ******************
|
||||
this diagnostic has tests which will produce error
|
||||
conditions on interface boards which have datecodes
|
||||
PRIOR TO 1504.
|
||||
P120 CONT6 ON, REST OFF
|
||||
|
||||
Programmed halt, CIR: 030367 (HALT 7), P: 022145 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP CONT=10000
|
||||
sim> go
|
||||
|
||||
P120 CONT7 ON, REST OFF
|
||||
|
||||
Programmed halt, CIR: 030367 (HALT 7), P: 022145 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP CONT=01000
|
||||
sim> go
|
||||
|
||||
P120 CONT8 ON, REST OFF
|
||||
|
||||
Programmed halt, CIR: 030367 (HALT 7), P: 022145 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP CONT=00100
|
||||
sim> go
|
||||
|
||||
P120 CONT9 ON, REST OFF
|
||||
|
||||
Programmed halt, CIR: 030367 (HALT 7), P: 022145 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP CONT=00010
|
||||
sim> go
|
||||
|
||||
P120 CONT10 ON, REST OFF
|
||||
|
||||
Programmed halt, CIR: 030367 (HALT 7), P: 022145 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP CONT=00001
|
||||
sim> go
|
||||
|
||||
P121 JUMPER J2W1 LOW, REST HIGH
|
||||
|
||||
Programmed halt, CIR: 030370 (HALT 10), P: 022056 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP J2WX=0000000001
|
||||
sim> go
|
||||
|
||||
P121 JUMPER J2W2 LOW, REST HIGH
|
||||
|
||||
Programmed halt, CIR: 030370 (HALT 10), P: 022056 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP J2WX=0000000010
|
||||
sim> go
|
||||
|
||||
P121 JUMPER J2W3 LOW, REST HIGH
|
||||
|
||||
Programmed halt, CIR: 030370 (HALT 10), P: 022056 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP J2WX=0000000100
|
||||
sim> go
|
||||
|
||||
P121 JUMPER J2W4 LOW, REST HIGH
|
||||
|
||||
Programmed halt, CIR: 030370 (HALT 10), P: 022056 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP J2WX=0000001000
|
||||
sim> go
|
||||
|
||||
P121 JUMPER J2W5 LOW, REST HIGH
|
||||
|
||||
Programmed halt, CIR: 030370 (HALT 10), P: 022056 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP J2WX=0000010000
|
||||
sim> go
|
||||
|
||||
P121 JUMPER J2W6 LOW, REST HIGH
|
||||
|
||||
Programmed halt, CIR: 030370 (HALT 10), P: 022056 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP J2WX=0000100000
|
||||
sim> go
|
||||
|
||||
P121 JUMPER J2W7 LOW, REST HIGH
|
||||
|
||||
Programmed halt, CIR: 030370 (HALT 10), P: 022056 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP J2WX=0001000000
|
||||
sim> go
|
||||
|
||||
P121 JUMPER J2W8 LOW, REST HIGH
|
||||
|
||||
Programmed halt, CIR: 030370 (HALT 10), P: 022056 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP J2WX=0010000000
|
||||
sim> go
|
||||
|
||||
P121 JUMPER J2W9 LOW, REST HIGH
|
||||
|
||||
Programmed halt, CIR: 030370 (HALT 10), P: 022056 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP J2WX=0100000000
|
||||
sim> go
|
||||
|
||||
P121 JUMPER J2W10 LOW, REST HIGH
|
||||
|
||||
Programmed halt, CIR: 030370 (HALT 10), P: 022056 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP J2WX=1000000000
|
||||
sim> go
|
||||
|
||||
P122 DEVICE END ASSERTED
|
||||
|
||||
Programmed halt, CIR: 030371 (HALT 11), P: 021505 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP DEVEND=1
|
||||
sim> go
|
||||
|
||||
P124 BIT 0 HIGH, REST LOW
|
||||
|
||||
Programmed halt, CIR: 030373 (HALT 13), P: 021407 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP READ=100000
|
||||
sim> go
|
||||
|
||||
P124 BIT 1 HIGH, REST LOW
|
||||
|
||||
Programmed halt, CIR: 030373 (HALT 13), P: 021407 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP READ=040000
|
||||
sim> go
|
||||
|
||||
P124 BIT 2 HIGH, REST LOW
|
||||
|
||||
Programmed halt, CIR: 030373 (HALT 13), P: 021407 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP READ=020000
|
||||
sim> go
|
||||
|
||||
P124 BIT 3 HIGH, REST LOW
|
||||
|
||||
Programmed halt, CIR: 030373 (HALT 13), P: 021407 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP READ=010000
|
||||
sim> go
|
||||
|
||||
P124 BIT 4 HIGH, REST LOW
|
||||
|
||||
Programmed halt, CIR: 030373 (HALT 13), P: 021407 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP READ=004000
|
||||
sim> go
|
||||
|
||||
P124 BIT 5 HIGH, REST LOW
|
||||
|
||||
Programmed halt, CIR: 030373 (HALT 13), P: 021407 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP READ=002000
|
||||
sim> go
|
||||
|
||||
P124 BIT 6 HIGH, REST LOW
|
||||
|
||||
Programmed halt, CIR: 030373 (HALT 13), P: 021407 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP READ=001000
|
||||
sim> go
|
||||
|
||||
P124 BIT 7 HIGH, REST LOW
|
||||
|
||||
Programmed halt, CIR: 030373 (HALT 13), P: 021407 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP READ=000400
|
||||
sim> go
|
||||
|
||||
P124 BIT 8 HIGH, REST LOW
|
||||
|
||||
Programmed halt, CIR: 030373 (HALT 13), P: 021407 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP READ=000200
|
||||
sim> go
|
||||
|
||||
P124 BIT 9 HIGH, REST LOW
|
||||
|
||||
Programmed halt, CIR: 030373 (HALT 13), P: 021407 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP READ=000100
|
||||
sim> go
|
||||
|
||||
P124 BIT 10 HIGH, REST LOW
|
||||
|
||||
Programmed halt, CIR: 030373 (HALT 13), P: 021407 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP READ=000040
|
||||
sim> go
|
||||
|
||||
P124 BIT 11 HIGH, REST LOW
|
||||
|
||||
Programmed halt, CIR: 030373 (HALT 13), P: 021407 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP READ=000020
|
||||
sim> go
|
||||
|
||||
P124 BIT 12 HIGH, REST LOW
|
||||
|
||||
Programmed halt, CIR: 030373 (HALT 13), P: 021407 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP READ=000010
|
||||
sim> go
|
||||
|
||||
P124 BIT 13 HIGH, REST LOW
|
||||
|
||||
Programmed halt, CIR: 030373 (HALT 13), P: 021407 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP READ=000004
|
||||
sim> go
|
||||
|
||||
P124 BIT 14 HIGH, REST LOW
|
||||
|
||||
Programmed halt, CIR: 030373 (HALT 13), P: 021407 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP READ=000002
|
||||
sim> go
|
||||
|
||||
P124 BIT 15 HIGH, REST LOW
|
||||
|
||||
Programmed halt, CIR: 030373 (HALT 13), P: 021407 (DDEL,DDEL)
|
||||
|
||||
sim> assert LP READ=000001
|
||||
sim> go
|
||||
|
||||
D102 END SECTION 1
|
||||
D102 END SECTION 2
|
||||
D102 END SECTION 3
|
||||
D102 END SECTION 4
|
||||
D102 END SECTION 5
|
||||
D102 END SECTION 6
|
||||
D102 END SECTION 7
|
||||
D102 END SECTION 8
|
||||
D102 END SECTION 9
|
||||
D102 END SECTION 10
|
||||
P103 PASS 1
|
||||
|
||||
Programmed halt, CIR: 030375 (HALT 15), P: 010265 (DDEL,DDEL)
|
||||
|
||||
TEST RESULT: Passed.
|
||||
|
||||
TEST NOTES: The interrupt mask number is changed from "E" (always enabled) to
|
||||
a numeric value to allow the mask circuits to be tested.
|
||||
|
||||
|
||||
|
||||
----------------------------------
|
||||
D438A - Terminal Control Interface
|
||||
----------------------------------
|
||||
|
@ -1562,3 +1848,56 @@ TEST REPORT: Programmed halt, CIR: 030366 (HALT 6), P: 010670 (LRA P+4)
|
|||
Programmed halt, CIR: 030375 (HALT 15), P: 010225 (BR P+7)
|
||||
|
||||
TEST RESULT: Passed.
|
||||
|
||||
|
||||
|
||||
------------------------------------
|
||||
D466A - Online Line Printer Verifier
|
||||
------------------------------------
|
||||
|
||||
TESTED DEVICE: LP (hp3000_lp.c)
|
||||
|
||||
CONFIGURATION: :STOPSPOOL 6
|
||||
:RUN PD466A.HP32230.SUPPORT
|
||||
|
||||
TEST REPORT: D1 ONLINE LINE PRINTER VERIFIER (HP D466A.01.06)
|
||||
(C) COPYRIGHT HEWLETT-PACKARD COMPANY 1978.
|
||||
PRINTER MUST BE SET TO 6 LINES PER INCH
|
||||
Q1 WHICH MODEL? 2607/08/10/13/14/17/18/19: 2617
|
||||
Q2 64/96 CHARACTER SET?96
|
||||
Q3 LOGICAL DEVICE ?6
|
||||
Q4 FLAGS?
|
||||
PRESS 'ON/OFF' LINE SWITCH 'ON' THEN 'OFF'
|
||||
D7 PRESS 'CR' TO CONTINUE
|
||||
|
||||
[CTRL+E]
|
||||
|
||||
Simulation stopped, P: 071144 (PAUS 0)
|
||||
|
||||
sim> set lp offline
|
||||
sim> go
|
||||
|
||||
19:44/3/LDEV #6 NOT READY
|
||||
COMPUTER CONSOLE SHOULD PRINT 'IO/X:XX/LDEV# XXX NOT READY'
|
||||
PRESS 'ON/OFF' SWITCH 'ON'
|
||||
D7 PRESS 'CR' TO CONTINUE
|
||||
|
||||
[CTRL+E]
|
||||
|
||||
Simulation stopped, P: 071144 (PAUS 0)
|
||||
|
||||
sim> set lp online
|
||||
sim> go
|
||||
|
||||
D6 END OF SECTION 1
|
||||
D6 END OF SECTION 2
|
||||
D6 END OF SECTION 3
|
||||
D6 END OF SECTION 4
|
||||
D6 END OF SECTION 5
|
||||
D6 END OF SECTION 6
|
||||
D6 END OF SECTION 7
|
||||
LINE PRINTER VERIFIER TEST TERMINATED
|
||||
|
||||
END OF PROGRAM
|
||||
|
||||
TEST RESULT: Passed.
|
||||
|
|
|
@ -25,7 +25,12 @@
|
|||
|
||||
DS HP 30229B Cartridge Disc Interface
|
||||
|
||||
09-Jun-16 JDB Added casts for ptrdiff_t to int32 values
|
||||
08-Jun-16 JDB Corrected %d format to %u for unsigned values
|
||||
16-May-16 JDB Fixed interrupt mask setting
|
||||
13-May-16 JDB Modified for revised SCP API function parameter types
|
||||
24-Mar-16 JDB Changed the buffer element type from uint16 to DL_BUFFER
|
||||
21-Mar-16 JDB Changed uint16 types to HP_WORD
|
||||
21-Jul-15 JDB First release version
|
||||
15-Jun-15 JDB Passes the cartridge disc diagnostic (D419A)
|
||||
15-Feb-15 JDB Created
|
||||
|
@ -237,7 +242,7 @@
|
|||
/* Debug flags (interface-specific) */
|
||||
|
||||
#define DEB_IOB DL_DEB_IOB /* trace I/O bus signals and data words */
|
||||
#define DEB_CSRW (1 << DL_DEB_V_UF + 0) /* trace control, status, read, and write commands */
|
||||
#define DEB_CSRW (1u << DL_DEB_V_UF + 0) /* trace control, status, read, and write commands */
|
||||
|
||||
|
||||
/* Control word.
|
||||
|
@ -252,13 +257,13 @@
|
|||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
*/
|
||||
|
||||
#define CN_MR 0100000 /* (M) master reset */
|
||||
#define CN_RIN 0040000 /* (R) reset interrupt */
|
||||
#define CN_TEST 0020000 /* (T) test mode */
|
||||
#define CN_MR 0100000u /* (M) master reset */
|
||||
#define CN_RIN 0040000u /* (R) reset interrupt */
|
||||
#define CN_TEST 0020000u /* (T) test mode */
|
||||
|
||||
#define CN_WAIT 0000001 /* (W) wait for data */
|
||||
#define CN_WAIT 0000001u /* (W) wait for data */
|
||||
|
||||
#define CN_OPCODE_MASK 0017400 /* command word opcode mask */
|
||||
#define CN_OPCODE_MASK 0017400u /* command word opcode mask */
|
||||
|
||||
#define CN_OPCODE_SHIFT 8 /* controller opcode alignment shift */
|
||||
|
||||
|
@ -282,11 +287,11 @@ static const BITSET_FORMAT control_format = /* names, offset, direction, alt
|
|||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
*/
|
||||
|
||||
#define ST_SIO_OK 0100000 /* (S) SIO OK to use */
|
||||
#define ST_TEST 0040000 /* (T) test mode enabled */
|
||||
#define ST_INTREQ 0020000 /* (I) interrupt requested */
|
||||
#define ST_STATUS_MASK 0017400 /* encoded termination status mask */
|
||||
#define ST_UNIT_MASK 0000017 /* unit number mask */
|
||||
#define ST_SIO_OK 0100000u /* (S) SIO OK to use */
|
||||
#define ST_TEST 0040000u /* (T) test mode enabled */
|
||||
#define ST_INTREQ 0020000u /* (I) interrupt requested */
|
||||
#define ST_STATUS_MASK 0017400u /* encoded termination status mask */
|
||||
#define ST_UNIT_MASK 0000017u /* unit number mask */
|
||||
|
||||
#define ST_MASK ~(ST_SIO_OK | ST_TEST | ST_INTREQ)
|
||||
|
||||
|
@ -295,8 +300,8 @@ static const BITSET_FORMAT control_format = /* names, offset, direction, alt
|
|||
|
||||
#define ST_STATUS(n) ((n) << ST_STATUS_SHIFT & ST_STATUS_MASK)
|
||||
|
||||
#define ST_TO_UNIT(s) (((s) & ST_UNIT_MASK) >> ST_UNIT_SHIFT)
|
||||
#define ST_TO_STATUS(s) (((s) & ST_STATUS_MASK) >> ST_STATUS_SHIFT)
|
||||
#define ST_TO_UNIT(s) (((s) & ST_UNIT_MASK) >> ST_UNIT_SHIFT)
|
||||
#define ST_TO_STATUS(s) (CNTLR_STATUS) (((s) & ST_STATUS_MASK) >> ST_STATUS_SHIFT)
|
||||
|
||||
|
||||
static const BITSET_NAME status_names [] = { /* Status word names */
|
||||
|
@ -334,7 +339,7 @@ static FLIP_FLOP sio_busy = CLEAR; /* SIO busy flip-flop */
|
|||
static FLIP_FLOP device_sr = CLEAR; /* device service request flip-flop */
|
||||
static FLIP_FLOP input_xfer = CLEAR; /* input transfer flip-flop */
|
||||
static FLIP_FLOP output_xfer = CLEAR; /* output transfer flip-flop */
|
||||
static FLIP_FLOP interrupt_mask = CLEAR; /* interrupt mask flip-flop */
|
||||
static FLIP_FLOP interrupt_mask = SET; /* interrupt mask flip-flop */
|
||||
static FLIP_FLOP jump_met = CLEAR; /* jump met flip-flop */
|
||||
static FLIP_FLOP device_end = CLEAR; /* device end flip-flop */
|
||||
static FLIP_FLOP data_overrun = CLEAR; /* data overrun flip-flop */
|
||||
|
@ -342,12 +347,12 @@ static FLIP_FLOP end_of_data = CLEAR; /* end of data flip-flop */
|
|||
static FLIP_FLOP test_mode = CLEAR; /* test mode flip-flop */
|
||||
static FLIP_FLOP data_wait = CLEAR; /* wait flip-flop */
|
||||
|
||||
static uint16 status_word = 0; /* status register */
|
||||
static uint16 buffer_word = 0; /* data buffer register */
|
||||
static uint16 retry_counter = 0; /* retry counter */
|
||||
static CNTLR_FLAG_SET flags = 0; /* disc controller interface flag set */
|
||||
static HP_WORD status_word = 0; /* status register */
|
||||
static HP_WORD buffer_word = 0; /* data buffer register */
|
||||
static HP_WORD retry_counter = 0; /* retry counter */
|
||||
static CNTLR_FLAG_SET flags = NO_FLAGS; /* disc controller interface flag set */
|
||||
|
||||
static uint16 buffer [DL_BUFSIZE]; /* command/status/sector buffer */
|
||||
static DL_BUFFER buffer [DL_BUFSIZE]; /* command/status/sector buffer */
|
||||
|
||||
DEVICE ds_dev; /* incomplete device structure */
|
||||
|
||||
|
@ -433,8 +438,8 @@ static REG ds_reg [] = {
|
|||
{ ORDATA (STATUS, status_word, 16), REG_FIT | PV_RZRO },
|
||||
{ DRDATA (RETRY, retry_counter, 4), REG_FIT | PV_LEFT },
|
||||
|
||||
{ SRDATA (DIAG, overrides), REG_HRO },
|
||||
{ SRDATA (DIB, ds_dib), REG_HRO },
|
||||
{ SRDATA (DIAG, overrides, REG_HRO) },
|
||||
{ SRDATA (DIB, ds_dib, REG_HRO) },
|
||||
|
||||
DL_REGS (mac_cntlr, ds_unit, UNIT_COUNT, buffer, fast_times),
|
||||
|
||||
|
@ -581,11 +586,11 @@ DEVICE ds_dev = {
|
|||
the request.
|
||||
*/
|
||||
|
||||
static SIGNALS_DATA ds_interface (DIB *dibptr, INBOUND_SET inbound_signals, uint16 inbound_value)
|
||||
static SIGNALS_DATA ds_interface (DIB *dibptr, INBOUND_SET inbound_signals, HP_WORD inbound_value)
|
||||
{
|
||||
INBOUND_SIGNAL signal;
|
||||
INBOUND_SET working_set = inbound_signals;
|
||||
uint16 outbound_value = 0;
|
||||
HP_WORD outbound_value = 0;
|
||||
OUTBOUND_SET outbound_signals = NO_SIGNALS;
|
||||
|
||||
dprintf (ds_dev, DEB_IOB, "Received data %06o with signals %s\n",
|
||||
|
@ -614,8 +619,11 @@ while (working_set) {
|
|||
|
||||
|
||||
case DSETMASK:
|
||||
interrupt_mask = (dibptr->interrupt_mask /* set the mask flip-flop */
|
||||
& inbound_value) != 0; /* from the mask bit and the mask value */
|
||||
if (dibptr->interrupt_mask == INTMASK_E) /* if the mask is always enabled */
|
||||
interrupt_mask = SET; /* then set the mask flip-flop */
|
||||
else /* otherwise */
|
||||
interrupt_mask = D_FF (dibptr->interrupt_mask /* set the mask flip-flop if the mask bit */
|
||||
& inbound_value); /* is present in the mask value */
|
||||
|
||||
if (interrupt_mask && dibptr->interrupt_request) /* if the mask is enabled and a request is pending */
|
||||
outbound_signals |= INTREQ; /* then assert the INTREQ signal */
|
||||
|
@ -632,7 +640,7 @@ while (working_set) {
|
|||
if (inbound_value & CN_RIN) /* if the reset interrupt bit is set */
|
||||
dibptr->interrupt_request = CLEAR; /* then clear the interrupt request */
|
||||
|
||||
test_mode = (inbound_value & CN_TEST) != 0; /* set the test mode flip-flop from the test bit */
|
||||
test_mode = D_FF (inbound_value & CN_TEST); /* set the test mode flip-flop from the test bit */
|
||||
break;
|
||||
|
||||
|
||||
|
@ -649,7 +657,7 @@ while (working_set) {
|
|||
if (dibptr->interrupt_request == SET) /* if an interrupt request is pending */
|
||||
outbound_value |= ST_INTREQ; /* then add the IRQ status bit */
|
||||
|
||||
dprintf (ds_dev, DEB_CSRW, "Status is %s%s | unit %d\n",
|
||||
dprintf (ds_dev, DEB_CSRW, "Status is %s%s | unit %u\n",
|
||||
fmt_bitset (outbound_value, status_format),
|
||||
dl_status_name (ST_TO_STATUS (outbound_value)),
|
||||
ST_TO_UNIT (outbound_value));
|
||||
|
@ -715,7 +723,7 @@ while (working_set) {
|
|||
|
||||
|
||||
case PCMD1:
|
||||
data_wait = inbound_value & CN_WAIT; /* set the wait flip-flop from the supplied value */
|
||||
data_wait = D_FF (inbound_value & CN_WAIT); /* set the wait flip-flop from the supplied value */
|
||||
|
||||
if (data_wait == SET) /* if the wait flip-flip is set */
|
||||
flags |= DTRDY; /* then the data ready flag is forced true */
|
||||
|
@ -797,7 +805,7 @@ while (working_set) {
|
|||
if (device_end == SET) { /* if the device end flip-flop is set */
|
||||
outbound_signals |= DEVEND | CHANSR; /* then assert DEVEND and CHANSR to the channel */
|
||||
|
||||
device_end = input_xfer | output_xfer; /* clear device end if the transfer has stopped */
|
||||
device_end = D_FF (input_xfer | output_xfer); /* clear device end if the transfer has stopped */
|
||||
}
|
||||
|
||||
else if (device_sr == SET || test_mode == SET) /* if the interface requests service */
|
||||
|
@ -851,7 +859,7 @@ static t_stat ds_service (UNIT *uptr)
|
|||
dprintf (ds_dev, DL_DEB_SERV, (uptr == &ds_cntlr
|
||||
? "Controller unit service entered\n"
|
||||
: "Unit %d service entered\n"),
|
||||
uptr - &ds_unit [0]);
|
||||
(int32) (uptr - &ds_unit [0]));
|
||||
|
||||
call_controller (uptr); /* call the controller */
|
||||
|
||||
|
@ -1221,8 +1229,8 @@ else /* otherwise */
|
|||
|
||||
|
||||
do { /* call the controller potentially more than once */
|
||||
result = dl_controller (&mac_cntlr, uptr, /* to start or continue a command */
|
||||
flag_set, buffer_word);
|
||||
result = /* to start or continue a command */
|
||||
dl_controller (&mac_cntlr, uptr, flag_set, (CNTLR_IBUS) buffer_word);
|
||||
|
||||
command_set = DLIFN (result) & ~UNUSED_COMMANDS; /* strip the commands we don't use as an efficiency */
|
||||
|
||||
|
@ -1236,7 +1244,7 @@ do { /* call the controller p
|
|||
data_overrun = SET; /* then this input overruns it */
|
||||
|
||||
else { /* otherwise the buffer is empty */
|
||||
device_sr = ! end_of_data; /* so request the next word unless EOT */
|
||||
device_sr = D_FF (! end_of_data); /* so request the next word unless EOT */
|
||||
|
||||
if ((input_xfer == CLEAR /* if not configured to read */
|
||||
|| output_xfer == SET) /* or configured to write */
|
||||
|
|
|
@ -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.
|
||||
|
||||
11-Jun-16 JDB Bit mask constants are now unsigned
|
||||
21-Mar-16 JDB Changed type of inbound_value of CNTLR_INTRF to HP_WORD
|
||||
20-Jan-16 JDB First release version
|
||||
11-Dec-12 JDB Created
|
||||
|
||||
|
@ -141,7 +143,7 @@ typedef enum { /* --- source of signal --- */
|
|||
/* = 020000000000 (available) */
|
||||
} INBOUND_SIGNAL;
|
||||
|
||||
typedef INBOUND_SIGNAL INBOUND_SET; /* a set of INBOUND_SIGNALs */
|
||||
typedef INBOUND_SIGNAL INBOUND_SET; /* a set of INBOUND_SIGNALs */
|
||||
|
||||
|
||||
typedef enum { /* --- destination of signal --- */
|
||||
|
@ -163,10 +165,10 @@ typedef enum { /* --- destination of signal ---
|
|||
/* = 020000000000 (available) */
|
||||
} OUTBOUND_SIGNAL;
|
||||
|
||||
typedef OUTBOUND_SIGNAL OUTBOUND_SET; /* a set of OUTBOUND_SIGNALs */
|
||||
typedef OUTBOUND_SIGNAL OUTBOUND_SET; /* a set of OUTBOUND_SIGNALs */
|
||||
|
||||
|
||||
typedef uint32 SIGNALS_DATA; /* a combined outbound signal set and data value */
|
||||
typedef uint32 SIGNALS_DATA; /* a combined outbound signal set and data value */
|
||||
|
||||
|
||||
/* I/O macros.
|
||||
|
@ -224,11 +226,11 @@ typedef uint32 SIGNALS_DATA; /* a combined outbound signal se
|
|||
#define IOPRIORITY(P) ((P) & ~(P) + 1)
|
||||
|
||||
#define IONEXTSIG(S) ((INBOUND_SIGNAL) IOPRIORITY (S))
|
||||
#define IOCLEARSIG(S,L) S ^= (L)
|
||||
#define IOCLEARSIG(S,L) S = (INBOUND_SIGNAL) ((S) ^ (L))
|
||||
|
||||
#define IORETURN(S,D) ((SIGNALS_DATA) ((S) & ~D16_MASK | (D) & D16_MASK))
|
||||
#define IOSIGNALS(C) ((OUTBOUND_SET) ((C) & ~D16_MASK))
|
||||
#define IODATA(C) ((uint16) ((C) & D16_MASK))
|
||||
#define IODATA(C) ((HP_WORD) ((C) & D16_MASK))
|
||||
|
||||
|
||||
/* I/O structures.
|
||||
|
@ -270,33 +272,33 @@ typedef uint32 SIGNALS_DATA; /* a combined outbound signal se
|
|||
*/
|
||||
|
||||
#define DEVNO_MAX 127 /* the maximum device number */
|
||||
#define DEVNO_MASK 0177 /* the mask for the device number */
|
||||
#define DEVNO_MASK 0177u /* the mask for the device number */
|
||||
#define DEVNO_BASE 10 /* the radix for the device number */
|
||||
#define DEVNO_UNUSED D32_UMAX /* the unused device number indicator */
|
||||
|
||||
#define INTMASK_MAX 15 /* the maximum interrupt mask number */
|
||||
#define INTMASK_MASK 017 /* the mask for the interrupt mask number */
|
||||
#define INTMASK_MASK 017u /* the mask for the interrupt mask number */
|
||||
#define INTMASK_BASE 10 /* the radix for the interrupt mask number */
|
||||
#define INTMASK_D 0000000 /* the interrupt mask disabled always value */
|
||||
#define INTMASK_E 0177777 /* the interrupt mask enabled always value */
|
||||
#define INTMASK_D 0000000u /* the interrupt mask disabled always value */
|
||||
#define INTMASK_E 0177777u /* the interrupt mask enabled always value */
|
||||
#define INTMASK_UNUSED D32_UMAX /* the unused interrupt mask indicator */
|
||||
|
||||
#define INTPRI_MAX 31 /* the maximum interrupt priority */
|
||||
#define INTPRI_MASK 037 /* the mask for the interrupt priority */
|
||||
#define INTPRI_MASK 037u /* the mask for the interrupt priority */
|
||||
#define INTPRI_BASE 10 /* the radix for the interrupt priority */
|
||||
#define INTPRI_UNUSED D32_UMAX /* the unused interrupt priority indicator */
|
||||
|
||||
#define SRNO_MAX 15 /* the maximum service request number */
|
||||
#define SRNO_MASK 017 /* the mask for the service request number */
|
||||
#define SRNO_MASK 017u /* the mask for the service request number */
|
||||
#define SRNO_BASE 10 /* the radix for the service request number */
|
||||
#define SRNO_UNUSED D32_UMAX /* the unused service request number indicator */
|
||||
|
||||
typedef struct dib DIB; /* an incomplete definition */
|
||||
typedef struct dib DIB; /* an incomplete definition */
|
||||
|
||||
typedef SIGNALS_DATA CNTLR_INTRF /* the I/O device controller interface function prototype */
|
||||
(DIB *dibptr, /* a pointer to the device information block */
|
||||
INBOUND_SET inbound_signals, /* a set of inbound signals */
|
||||
uint16 inbound_value); /* a 16-bit inbound value */
|
||||
HP_WORD inbound_value); /* a 16-bit inbound value */
|
||||
|
||||
struct dib { /* the Device Information Block */
|
||||
CNTLR_INTRF *io_interface; /* the controller I/O interface function pointer */
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
IOP HP 3000 Series III I/O Processor
|
||||
|
||||
30-Jun-16 JDB Changed REG type of filter array to BRDATA
|
||||
08-Jun-16 JDB Corrected %d format to %u for unsigned values
|
||||
13-May-16 JDB Modified for revised SCP API function parameter types
|
||||
28-Aug-15 JDB First release version
|
||||
11-Dec-12 JDB Created
|
||||
|
@ -191,10 +193,10 @@
|
|||
1. Bit 0 is reserved for the memory data trace flag.
|
||||
*/
|
||||
|
||||
#define DEB_DIO (1 << 1) /* trace direct I/O commands */
|
||||
#define DEB_IRQ (1 << 2) /* trace interrupt requests */
|
||||
#define DEB_DIO (1u << 1) /* trace direct I/O commands */
|
||||
#define DEB_IRQ (1u << 2) /* trace interrupt requests */
|
||||
|
||||
#define FILTER(d) (1 << (d) % 32 & filter [(d) / 32])
|
||||
#define FILTER(d) (1u << (d) % 32 & filter [(d) / 32])
|
||||
|
||||
|
||||
/* IOP global data structures */
|
||||
|
@ -262,8 +264,8 @@ uint32 iop_interrupt_request_set = 0; /* the set of interfaces request
|
|||
static uint32 IOA = 0; /* I/O Address Register */
|
||||
|
||||
static uint32 interrupt_poll_set = 0; /* the set of interfaces breaking the poll chain */
|
||||
static DIB *devs [DEVNO_MAX + 1]; /* index by device number for I/O instruction dispatch */
|
||||
static DIB *irqs [INTPRI_MAX + 1]; /* index by interrupt priority number for interrupt requests */
|
||||
static DIB *devs [DEVNO_MAX + 1]; /* index by device number for I/O instruction dispatch */
|
||||
static DIB *irqs [INTPRI_MAX + 1]; /* index by interrupt priority number for interrupt requests */
|
||||
|
||||
static uint32 filter [4] = { /* filter bitmap for device numbers 0-127 */
|
||||
TRACE_ALL,
|
||||
|
@ -299,10 +301,10 @@ static UNIT iop_unit [] = { /* a dummy unit to satisfy SCP r
|
|||
*/
|
||||
|
||||
static REG iop_reg [] = {
|
||||
/* Macro Name Location Width Flags */
|
||||
/* ------ ------ -------- ----- ------- */
|
||||
{ ORDATA (IOA, IOA, 8), REG_RO }, /* I/O Address Register */
|
||||
{ SRDATA (FILTER, filter), REG_HRO },
|
||||
/* Macro Name Location Radix Width Depth Flags */
|
||||
/* ------ ------ -------- ----- ----- ----- ------- */
|
||||
{ ORDATA (IOA, IOA, 8), REG_RO },
|
||||
{ BRDATA (FILTER, filter, 2, 32, 4), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
@ -530,7 +532,7 @@ if (outbound & INTACK) { /* if the interface ackn
|
|||
CPX1 |= cpx1_EXTINTR; /* and tell the CPU */
|
||||
|
||||
dprintf (iop_dev, FILTER (dibptr->device_number) ? DEB_IRQ : 0,
|
||||
"Device number %d acknowledged interrupt request at priority %d\n",
|
||||
"Device number %u acknowledged interrupt request at priority %u\n",
|
||||
dibptr->device_number, ipn);
|
||||
}
|
||||
|
||||
|
@ -539,7 +541,7 @@ else if (outbound & INTPOLLOUT) { /* otherwise if the inte
|
|||
interrupt_poll_set &= ~priority_mask; /* and the associated bit in the poll set */
|
||||
|
||||
dprintf (iop_dev, FILTER (dibptr->device_number) ? DEB_IRQ : 0,
|
||||
"Device number %d canceled interrupt request at priority %d\n",
|
||||
"Device number %u canceled interrupt request at priority %u\n",
|
||||
dibptr->device_number, ipn);
|
||||
}
|
||||
|
||||
|
@ -615,7 +617,7 @@ if (io_cmd == ioSMSK) { /* if the I/O order
|
|||
&& dibptr->interrupt_mask != INTMASK_UNUSED) { /* and uses the interrupt mask */
|
||||
|
||||
dprintf (iop_dev, FILTER (devno) ? DEB_DIO : 0,
|
||||
"%s order sent to device number %d\n",
|
||||
"%s order sent to device number %u\n",
|
||||
io_command_name [io_cmd], devno);
|
||||
|
||||
outbound =
|
||||
|
@ -637,7 +639,7 @@ else { /* otherwise a devic
|
|||
device_number = device_number & DEVNO_MASK; /* restrict the device number to 0-127 */
|
||||
|
||||
dprintf (iop_dev, FILTER (device_number) ? DEB_DIO : 0,
|
||||
"%s order sent to device number %d\n",
|
||||
"%s order sent to device number %u\n",
|
||||
io_command_name [io_cmd], device_number);
|
||||
|
||||
dibptr = devs [device_number]; /* get the device information block pointer */
|
||||
|
@ -682,7 +684,7 @@ void iop_assert_INTREQ (DIB *dibptr)
|
|||
uint32 irq;
|
||||
|
||||
dprintf (iop_dev, FILTER (dibptr->device_number) ? DEB_IRQ : 0,
|
||||
"Device number %d asserted INTREQ at priority %d\n",
|
||||
"Device number %u asserted INTREQ at priority %u\n",
|
||||
dibptr->device_number, dibptr->interrupt_priority);
|
||||
|
||||
if (dibptr->interrupt_priority != INTPRI_UNUSED) { /* if the interrupt priority is valid */
|
||||
|
@ -743,7 +745,7 @@ if (value == 1) { /* if we are setting the
|
|||
if ((cptr == NULL) || (*cptr == '\0')) /* then if a line range was not supplied */
|
||||
return SCPE_MISVAL; /* then report a "Missing value" error */
|
||||
|
||||
mptr = malloc (strlen (cptr) + 2); /* allocate space for the string, a semicolon, and a NUL */
|
||||
mptr = (char *) malloc (strlen (cptr) + 2); /* allocate space for the string, a semicolon, and a NUL */
|
||||
|
||||
if (mptr == NULL) /* if the allocation failed */
|
||||
return SCPE_MEM; /* report memory exhaustion */
|
||||
|
|
3671
HP3000/hp3000_lp.c
Normal file
3671
HP3000/hp3000_lp.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -25,6 +25,10 @@
|
|||
|
||||
MPX HP 3000 Series III Multiplexer Channel
|
||||
|
||||
08-Jun-16 JDB Corrected %d format to %u for unsigned values
|
||||
07-Jun-16 JDB Corrected ACKSR assertion in State A for chained orders
|
||||
16-May-16 JDB abort_channel parameter is now a pointer-to-constant
|
||||
21-Mar-16 JDB Changed uint16 types to HP_WORD
|
||||
06-Oct-15 JDB First release version
|
||||
11-Sep-14 JDB Passes the multiplexer channel diagnostic (D422A)
|
||||
10-Feb-13 JDB Created
|
||||
|
@ -396,11 +400,11 @@ static const uint8 state_parity [16] = { /* State RAM parity */
|
|||
|
||||
/* Debug flags */
|
||||
|
||||
#define DEB_CSRW (1 << 0) /* trace diagnostic and channel command initiations and completions */
|
||||
#define DEB_PIO (1 << 1) /* trace programmed I/O commands */
|
||||
#define DEB_IOB (1 << 2) /* trace I/O bus signals and data words */
|
||||
#define DEB_STATE (1 << 3) /* trace state changes */
|
||||
#define DEB_SR (1 << 4) /* trace service requests */
|
||||
#define DEB_CSRW (1u << 0) /* trace diagnostic and channel command initiations and completions */
|
||||
#define DEB_PIO (1u << 1) /* trace programmed I/O commands */
|
||||
#define DEB_IOB (1u << 2) /* trace I/O bus signals and data words */
|
||||
#define DEB_STATE (1u << 3) /* trace state changes */
|
||||
#define DEB_SR (1u << 4) /* trace service requests */
|
||||
|
||||
|
||||
/* Control word.
|
||||
|
@ -411,13 +415,13 @@ static const uint8 state_parity [16] = { /* State RAM parity */
|
|||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
*/
|
||||
|
||||
#define CN_MR 0100000 /* (M) master reset */
|
||||
#define CN_RAM_ADDR_MASK 0036000 /* RAM address mask */
|
||||
#define CN_ADDR_RAM 0001000 /* (A) select the address RAM and register */
|
||||
#define CN_ORDER_RAM 0000400 /* (O) select the order RAM and register */
|
||||
#define CN_STATE_RAM 0000200 /* (S) select the state RAM and register */
|
||||
#define CN_LOAD_REGS 0000100 /* (L) load registers from RAM */
|
||||
#define CN_INCR_REGS 0000040 /* (I) increment registers */
|
||||
#define CN_MR 0100000u /* (M) master reset */
|
||||
#define CN_RAM_ADDR_MASK 0036000u /* RAM address mask */
|
||||
#define CN_ADDR_RAM 0001000u /* (A) select the address RAM and register */
|
||||
#define CN_ORDER_RAM 0000400u /* (O) select the order RAM and register */
|
||||
#define CN_STATE_RAM 0000200u /* (S) select the state RAM and register */
|
||||
#define CN_LOAD_REGS 0000100u /* (L) load registers from RAM */
|
||||
#define CN_INCR_REGS 0000040u /* (I) increment registers */
|
||||
|
||||
#define CN_RAM_ADDR_SHIFT 10 /* RAM address alignment shift */
|
||||
|
||||
|
@ -449,9 +453,9 @@ static const BITSET_FORMAT control_format = /* names, offset, direction, alt
|
|||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
*/
|
||||
|
||||
#define ST_DIO_OK 0040000 /* (D) direct I/O OK (always set) */
|
||||
#define ST_STATE_PARITY 0010000 /* (E) a state error exists */
|
||||
#define ST_RAM_ADDR_MASK 0007400 /* RAM address mask */
|
||||
#define ST_DIO_OK 0040000u /* (D) direct I/O OK (always set) */
|
||||
#define ST_STATE_PARITY 0010000u /* (E) a state error exists */
|
||||
#define ST_RAM_ADDR_MASK 0007400u /* RAM address mask */
|
||||
|
||||
#define ST_RAM_ADDR_SHIFT 8 /* RAM address alignment shift */
|
||||
|
||||
|
@ -481,10 +485,10 @@ static const BITSET_FORMAT status_format = /* names, offset, direction, alt
|
|||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
*/
|
||||
|
||||
#define WR_ORDER_MASK 0170000 /* order mask */
|
||||
#define WR_COUNT_MASK 0007777 /* word count mask */
|
||||
#define WR_STATE_MASK 0036000 /* state mask */
|
||||
#define WR_BANK_MASK 0000017 /* bank number mask */
|
||||
#define WR_ORDER_MASK 0170000u /* order mask */
|
||||
#define WR_COUNT_MASK 0007777u /* word count mask */
|
||||
#define WR_STATE_MASK 0036000u /* state mask */
|
||||
#define WR_BANK_MASK 0000017u /* bank number mask */
|
||||
|
||||
#define WR_ORDER_SHIFT 12 /* order alignment shift */
|
||||
#define WR_COUNT_SHIFT 0 /* word count alignment shift */
|
||||
|
@ -509,15 +513,15 @@ static const BITSET_FORMAT status_format = /* names, offset, direction, alt
|
|||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
*/
|
||||
|
||||
#define RD_ADDR_MASK 0177777 /* address mask */
|
||||
#define RD_ORDER_MASK 0170000 /* order mask */
|
||||
#define RD_COUNT_MASK 0007777 /* word count mask */
|
||||
#define RD_BANK_MASK 0007400 /* bank number mask */
|
||||
#define RD_XFER_COMPLETE 0000200 /* (T) transfer complete */
|
||||
#define RD_STATE_MASK 0000170 /* (A/B/C/D) state mask */
|
||||
#define RD_XFER_END 0000004 /* (E) end of transfer */
|
||||
#define RD_ADDR_PARITY 0000002 /* (P) address parity */
|
||||
#define RD_STATE_PARITY 0000001 /* (S) state parity */
|
||||
#define RD_ADDR_MASK 0177777u /* address mask */
|
||||
#define RD_ORDER_MASK 0170000u /* order mask */
|
||||
#define RD_COUNT_MASK 0007777u /* word count mask */
|
||||
#define RD_BANK_MASK 0007400u /* bank number mask */
|
||||
#define RD_XFER_COMPLETE 0000200u /* (T) transfer complete */
|
||||
#define RD_STATE_MASK 0000170u /* (A/B/C/D) state mask */
|
||||
#define RD_XFER_END 0000004u /* (E) end of transfer */
|
||||
#define RD_ADDR_PARITY 0000002u /* (P) address parity */
|
||||
#define RD_STATE_PARITY 0000001u /* (S) state parity */
|
||||
|
||||
#define RD_ORDER_SHIFT 12 /* order alignment shift */
|
||||
#define RD_COUNT_SHIFT 0 /* word count alignment shift */
|
||||
|
@ -588,17 +592,17 @@ static const BITSET_FORMAT read_format = /* names, offset, direction, alt
|
|||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
*/
|
||||
|
||||
#define AUX_IB 040 /* auxiliary RAM in-block flag */
|
||||
#define AUX_TC 020 /* auxiliary RAM terminal count flag */
|
||||
#define AUX_BANK_MASK 017 /* auxiliary RAM bank mask */
|
||||
#define AUX_IB 040u /* auxiliary RAM in-block flag */
|
||||
#define AUX_TC 020u /* auxiliary RAM terminal count flag */
|
||||
#define AUX_BANK_MASK 017u /* auxiliary RAM bank mask */
|
||||
|
||||
#define AUX_BANK(r) ((r) & AUX_BANK_MASK)
|
||||
|
||||
#define ORDER_DC 020 /* order RAM data chain flag */
|
||||
#define ORDER_MASK 017 /* order RAM current order mask */
|
||||
#define ORDER_DC 020u /* order RAM data chain flag */
|
||||
#define ORDER_MASK 017u /* order RAM current order mask */
|
||||
|
||||
#define CNTR_MASK 0007777 /* counter RAM word count mask */
|
||||
#define CNTR_MAX 0007777 /* counter RAM word count maximum value */
|
||||
#define CNTR_MASK 0007777u /* counter RAM word count mask */
|
||||
#define CNTR_MAX 0007777u /* counter RAM word count maximum value */
|
||||
|
||||
static const BITSET_NAME aux_names [] = { /* Auxiliary RAM word */
|
||||
"in block", /* bit 2 */
|
||||
|
@ -667,7 +671,7 @@ static t_stat mpx_reset (DEVICE *dptr);
|
|||
|
||||
static uint8 next_state (uint8 current_state, SIO_ORDER order, t_bool abort);
|
||||
static void end_channel (DIB *dibptr);
|
||||
static SIGNALS_DATA abort_channel (DIB *dibptr, char *reason);
|
||||
static SIGNALS_DATA abort_channel (DIB *dibptr, const char *reason);
|
||||
|
||||
|
||||
/* Channel SCP data structures */
|
||||
|
@ -683,12 +687,14 @@ static DIB mpx_dib = {
|
|||
INTMASK_UNUSED /* interrupt mask */
|
||||
};
|
||||
|
||||
|
||||
/* Unit list */
|
||||
|
||||
static UNIT mpx_unit [] = { /* a dummy unit to satisfy SCP requirements */
|
||||
{ UDATA (NULL, 0, 0) }
|
||||
};
|
||||
|
||||
|
||||
/* Register list.
|
||||
|
||||
|
||||
|
@ -703,34 +709,35 @@ static UNIT mpx_unit [] = { /* a dummy unit to satisfy SCP r
|
|||
*/
|
||||
|
||||
static REG mpx_reg [] = {
|
||||
/* Macro Name Location Radix Width Depth Flags */
|
||||
/* ------ ------ ------------- ----- ----- ----------- ----------------- */
|
||||
{ FLDATA (IDLE, mpx_is_idle, 0) },
|
||||
{ DRDATA (COUNT, active_count, 32), PV_LEFT },
|
||||
{ DRDATA (EXCESS, excess_cycles, 32), PV_LEFT },
|
||||
/* Macro Name Location Radix Width Depth Flags */
|
||||
/* ------ ------ ------------- ----- ----- ----------- ----------------- */
|
||||
{ FLDATA (IDLE, mpx_is_idle, 0) },
|
||||
{ DRDATA (COUNT, active_count, 32), PV_LEFT },
|
||||
{ DRDATA (EXCESS, excess_cycles, 32), PV_LEFT },
|
||||
|
||||
{ ORDATA (CNTL, control_word, 16), REG_FIT },
|
||||
{ ORDATA (STAT, status_word, 16), REG_FIT },
|
||||
{ FLDATA (ROLOVR, rollover, 0) },
|
||||
{ FLDATA (DEVEND, device_end, 0) },
|
||||
{ ORDATA (CNTL, control_word, 16), REG_FIT },
|
||||
{ ORDATA (STAT, status_word, 16), REG_FIT },
|
||||
{ FLDATA (ROLOVR, rollover, 0) },
|
||||
{ FLDATA (DEVEND, device_end, 0) },
|
||||
|
||||
{ BRDATA (STATR, state_ram, 2, 4, INTRF_COUNT) },
|
||||
{ BRDATA (AUX, aux_ram, 8, 6, INTRF_COUNT) },
|
||||
{ BRDATA (ORDER, order_ram, 8, 4, INTRF_COUNT) },
|
||||
{ BRDATA (CNTR, cntr_ram, 8, 12, INTRF_COUNT) },
|
||||
{ BRDATA (ADDR, addr_ram, 8, 16, INTRF_COUNT) },
|
||||
{ BRDATA (STATR, state_ram, 2, 4, INTRF_COUNT) },
|
||||
{ BRDATA (AUX, aux_ram, 8, 6, INTRF_COUNT) },
|
||||
{ BRDATA (ORDER, order_ram, 8, 4, INTRF_COUNT) },
|
||||
{ BRDATA (CNTR, cntr_ram, 8, 12, INTRF_COUNT) },
|
||||
{ BRDATA (ADDR, addr_ram, 8, 16, INTRF_COUNT) },
|
||||
|
||||
{ ORDATA (STAREG, state_reg, 8), REG_FIT | REG_HRO },
|
||||
{ ORDATA (AUXREG, aux_reg, 8), REG_FIT | REG_HRO },
|
||||
{ ORDATA (ORDREG, order_reg, 8), REG_FIT | REG_HRO },
|
||||
{ ORDATA (CTRREG, cntr_reg, 16), REG_FIT | REG_HRO },
|
||||
{ ORDATA (ADRREG, addr_reg, 16), REG_FIT | REG_HRO },
|
||||
{ ORDATA (STAREG, state_reg, 8), REG_FIT | REG_HRO },
|
||||
{ ORDATA (AUXREG, aux_reg, 8), REG_FIT | REG_HRO },
|
||||
{ ORDATA (ORDREG, order_reg, 8), REG_FIT | REG_HRO },
|
||||
{ ORDATA (CTRREG, cntr_reg, 16), REG_FIT | REG_HRO },
|
||||
{ ORDATA (ADRREG, addr_reg, 16), REG_FIT | REG_HRO },
|
||||
|
||||
{ SRDATA (DIB, mpx_dib), REG_HRO },
|
||||
{ SRDATA (DIB, mpx_dib, REG_HRO) },
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
||||
/* Modifier list */
|
||||
|
||||
static MTAB mpx_mod [] = {
|
||||
|
@ -740,6 +747,7 @@ static MTAB mpx_mod [] = {
|
|||
{ 0 }
|
||||
};
|
||||
|
||||
|
||||
/* Debugging trace list */
|
||||
|
||||
static DEBTAB mpx_deb [] = {
|
||||
|
@ -751,6 +759,7 @@ static DEBTAB mpx_deb [] = {
|
|||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
||||
/* Device descriptor */
|
||||
|
||||
DEVICE mpx_dev = {
|
||||
|
@ -856,7 +865,7 @@ void mpx_assert_REQ (DIB *dibptr)
|
|||
{
|
||||
const uint32 srn = dibptr->service_request_number; /* get the SR number for the RAM index */
|
||||
|
||||
dprintf (mpx_dev, DEB_CSRW, "Device number %d asserted REQ for channel initialization\n",
|
||||
dprintf (mpx_dev, DEB_CSRW, "Device number %u asserted REQ for channel initialization\n",
|
||||
dibptr->device_number);
|
||||
|
||||
state_ram [srn] = State_C; /* set up the initial sequencer state */
|
||||
|
@ -893,7 +902,7 @@ return;
|
|||
void mpx_assert_SRn (DIB *dibptr)
|
||||
{
|
||||
if (dibptr->service_request == FALSE)
|
||||
dprintf (mpx_dev, DEB_SR, "Device number %d asserted SR%d\n",
|
||||
dprintf (mpx_dev, DEB_SR, "Device number %u asserted SR%u\n",
|
||||
dibptr->device_number, dibptr->service_request_number);
|
||||
|
||||
dibptr->service_request = TRUE; /* set the service request flag */
|
||||
|
@ -952,7 +961,10 @@ return;
|
|||
All I/O orders except Set Bank, Read, and Write execute states C, A, and B,
|
||||
in that order. The Set Bank order executes state C, A, and D. The Read and
|
||||
Write orders execute states C, A, B, and then one D state for each word
|
||||
transferred. Some actions are dependent on external signals or conditions.
|
||||
transferred. Some actions are dependent on external signals (JMPMET or
|
||||
DEVEND) or internal conditions (terminal count reached [TC] or in a chained
|
||||
block transfer [IB]).
|
||||
|
||||
The actions for the orders are:
|
||||
|
||||
Jump (sioJUMP)
|
||||
|
@ -965,7 +977,7 @@ return;
|
|||
C IOPP write DEVNODB
|
||||
|
||||
|
||||
Jump Conditional (sioJUMPC)
|
||||
Conditional Jump (sioJUMPC)
|
||||
|
||||
State Condition Action Signals
|
||||
----- --------------- ---------- ------------------------------------------
|
||||
|
@ -1012,7 +1024,7 @@ return;
|
|||
----- --------------- ---------- ------------------------------------------
|
||||
C IOPP read DEVNODB
|
||||
A IOCW read --
|
||||
B IOAW write TOGGLESIOOK | TOGGLESR | PSTATSTB
|
||||
B IOAW write TOGGLESR | PSTATSTB | TOGGLESIOOK
|
||||
idle
|
||||
|
||||
|
||||
|
@ -1022,7 +1034,7 @@ return;
|
|||
----- --------------- ---------- ------------------------------------------
|
||||
C IOPP read DEVNODB
|
||||
A IOCW read --
|
||||
B IOAW write TOGGLESIOOK | TOGGLESR | PSTATSTB | SETINT
|
||||
B IOAW write TOGGLESR | SETINT | PSTATSTB | TOGGLESIOOK
|
||||
idle
|
||||
|
||||
|
||||
|
@ -1030,10 +1042,10 @@ return;
|
|||
|
||||
State Condition Action Signals
|
||||
----- --------------- ---------- ------------------------------------------
|
||||
C IOPP read DEVNODB | ACKSR | TOGGLESR
|
||||
A IOCW read PCMD1 | TOGGLESR
|
||||
C IOPP read DEVNODB
|
||||
A IOCW read TOGGLESR | PCMD1
|
||||
B IOAW read ACKSR | PCONTSTB
|
||||
C IOPP read DEVNODB | TOGGLESR
|
||||
C IOPP read ACKSR | TOGGLESR | DEVNODB
|
||||
|
||||
|
||||
Sense (sioSENSE)
|
||||
|
@ -1057,11 +1069,12 @@ return;
|
|||
|
||||
/ D ~ TC data write ACKSR | PWRITESTB
|
||||
\ D TC data write ACKSR | PWRITESTB | EOT | TOGGLEOUTXFER
|
||||
/ D DEVEND * ~ TC IOPP read EOT | TOGGLESR | TOGGLEOUTXFER
|
||||
\ D DEVEND * TC IOPP read TOGGLESR
|
||||
/ D DEVEND * ~ TC IOPP read ACKSR | TOGGLESR | EOT | TOGGLEOUTXFER
|
||||
\ D DEVEND * TC IOPP read ACKSR | TOGGLESR
|
||||
|
||||
/ C ~ DEVEND IOPP read ACKSR | DEVNODB | TOGGLESR
|
||||
\ A DEVEND IOCW read --
|
||||
/ C ~ DEVEND IOPP read ACKSR | TOGGLESR | DEVNODB
|
||||
/ A ~ DEVEND IOCW read ACKSR
|
||||
\ A DEVEND IOCW read ACKSR
|
||||
|
||||
|
||||
Write Chained (sioWRITEC)
|
||||
|
@ -1074,8 +1087,8 @@ return;
|
|||
\ B IB IOAW read TOGGLESR
|
||||
|
||||
/ D ~ TC data write ACKSR | PWRITESTB
|
||||
\ D TC data write ACKSR | PWRITESTB | EOT | TOGGLESR
|
||||
/ D DEVEND * ~ TC IOPP read EOT | TOGGLESR
|
||||
\ D TC data write ACKSR | TOGGLESR | PWRITESTB | EOT
|
||||
/ D DEVEND * ~ TC IOPP read ACKSR | EOT | TOGGLESR
|
||||
\ D DEVEND * TC IOPP read --
|
||||
|
||||
/ C ~ DEVEND IOPP read DEVNODB
|
||||
|
@ -1087,17 +1100,18 @@ return;
|
|||
State Condition Action Signals
|
||||
----- --------------- ---------- ------------------------------------------
|
||||
C IOPP read DEVNODB
|
||||
A IOCW read ACKSR
|
||||
/ B ~ IB IOAW read READNEXTWD | TOGGLESR | TOGGLEINXFER
|
||||
\ B IB IOAW read READNEXTWD | TOGGLESR
|
||||
A IOCW read --
|
||||
/ B ~ IB IOAW read TOGGLESR | TOGGLEINXFER | READNEXTWD
|
||||
\ B IB IOAW read TOGGLESR | READNEXTWD
|
||||
|
||||
/ D ~ TC data write ACKSR | PREADSTB | READNEXTWD
|
||||
\ D TC data write ACKSR | PREADSTB | EOT | TOGGLEINXFER
|
||||
/ D DEVEND * ~ TC IOPP read EOT | TOGGLESR | TOGGLEINXFER
|
||||
\ D DEVEND * TC IOPP read TOGGLESR
|
||||
/ D DEVEND * ~ TC IOPP read ACKSR | TOGGLESR | EOT | TOGGLEINXFER
|
||||
\ D DEVEND * TC IOPP read ACKSR | TOGGLESR
|
||||
|
||||
/ C ~ DEVEND IOPP read ACKSR | DEVNODB | TOGGLESR
|
||||
\ A DEVEND IOCW read --
|
||||
/ C ~ DEVEND IOPP read ACKSR | TOGGLESR | DEVNODB
|
||||
/ A ~ DEVEND IOCW read ACKSR
|
||||
\ A DEVEND IOCW read ACKSR
|
||||
|
||||
|
||||
Read Chained (sioREADC)
|
||||
|
@ -1106,17 +1120,18 @@ return;
|
|||
----- --------------- ---------- ------------------------------------------
|
||||
C IOPP read DEVNODB
|
||||
A IOCW read --
|
||||
/ B ~ IB IOAW read READNEXTWD | TOGGLESR | TOGGLEINXFER
|
||||
\ B IB IOAW read READNEXTWD | TOGGLESR
|
||||
/ B ~ IB IOAW read TOGGLESR | TOGGLEINXFER | READNEXTWD
|
||||
\ B IB IOAW read TOGGLESR | READNEXTWD
|
||||
|
||||
/ D ~ TC data write ACKSR | PREADSTB | READNEXTWD
|
||||
\ D TC data write ACKSR | PREADSTB | EOT | TOGGLESR
|
||||
/ D DEVEND * ~ TC IOPP read EOT | TOGGLESR
|
||||
\ D TC data write ACKSR | TOGGLESR | PREADSTB | EOT
|
||||
/ D DEVEND * ~ TC IOPP read ACKSR | TOGGLESR | EOT
|
||||
\ D DEVEND * TC IOPP read --
|
||||
|
||||
/ C ~ DEVEND IOPP read DEVNODB
|
||||
\ A DEVEND IOCW read --
|
||||
|
||||
|
||||
Summarizing the State D signals sent to the interface:
|
||||
|
||||
Normal transfer
|
||||
|
@ -1127,9 +1142,9 @@ return;
|
|||
|
||||
DEVEND asserted after a normal transfer
|
||||
---------------------------------------
|
||||
- not the last word and not chained: EOT | TOGGLESR | TOGGLEioXFER
|
||||
- not the last word and chained: EOT | TOGGLESR
|
||||
- the last word and not chained: TOGGLESR
|
||||
- not the last word and not chained: ACKSR | TOGGLESR | EOT | TOGGLEioXFER
|
||||
- not the last word and chained: ACKSR | TOGGLESR | EOT
|
||||
- the last word and not chained: ACKSR | TOGGLESR
|
||||
- the last word and chained: (none)
|
||||
|
||||
In all cases where signals are generated, CHANSO is also included.
|
||||
|
@ -1198,15 +1213,21 @@ while (cycles > 0) { /* execute as long as cy
|
|||
cntr_reg = cntr_ram [srn];
|
||||
addr_reg = addr_ram [srn];
|
||||
|
||||
sio_order = order_reg & ORDER_MASK; /* map the order */
|
||||
sio_order = (SIO_ORDER) (order_reg & ORDER_MASK); /* map the order */
|
||||
}
|
||||
|
||||
dprintf (mpx_dev, DEB_STATE, "Channel SR %d entered %s with %d clock cycles remaining\n",
|
||||
dprintf (mpx_dev, DEB_STATE, "Channel SR %u entered %s with %d clock cycles remaining\n",
|
||||
srn, state_name [state_reg], cycles);
|
||||
|
||||
switch (state_reg) { /* dispatch based on the multiplexer state */
|
||||
|
||||
case State_A:
|
||||
if (sio_order == sioREAD /* if the previous order */
|
||||
|| sio_order == sioWRITE) /* was an unchained Read or Write */
|
||||
inbound_signals = ACKSR | CHANSO; /* then acknowledge the final service request */
|
||||
else /* otherwise */
|
||||
inbound_signals = NO_SIGNALS; /* no acknowledgement is needed */
|
||||
|
||||
cpu_read_memory (absolute_iop, addr_reg, &iocw); /* fetch the IOCW from memory */
|
||||
cycles = cycles - CYCLES_PER_READ; /* and count the memory access */
|
||||
|
||||
|
@ -1215,22 +1236,20 @@ while (cycles > 0) { /* execute as long as cy
|
|||
if (iocw & IOCW_DC) /* if the data chain bit is set */
|
||||
order_reg |= ORDER_DC; /* then set the data chain flag */
|
||||
|
||||
sio_order = order_reg & ORDER_MASK; /* isolate the I/O order */
|
||||
sio_order = (SIO_ORDER) (order_reg & ORDER_MASK); /* isolate the I/O order */
|
||||
|
||||
if (sio_order != sioRTRES) /* if this is not a Return Residue order */
|
||||
cntr_reg = IOCW_WCNT (iocw); /* then load the word count */
|
||||
|
||||
dprintf (mpx_dev, DEB_PIO, "Channel SR %d loaded IOCW %06o (%s) from address %06o\n",
|
||||
dprintf (mpx_dev, DEB_PIO, "Channel SR %u loaded IOCW %06o (%s) from address %06o\n",
|
||||
srn, iocw, sio_order_name [sio_order], addr_reg);
|
||||
|
||||
if (sio_order == sioCNTL) /* assert the proper signals for a Control order */
|
||||
outbound = dibptr->io_interface (dibptr, PCMD1 | TOGGLESR | CHANSO, iocw);
|
||||
if (sio_order == sioCNTL) /* if this a Control order */
|
||||
inbound_signals |= PCMD1 | TOGGLESR | CHANSO; /* then assert the first command strobe */
|
||||
|
||||
else if (sio_order == sioREAD /* otherwise assert the proper signals */
|
||||
|| sio_order == sioWRITE) /* for an unchained Read or Write order */
|
||||
outbound = dibptr->io_interface (dibptr, ACKSR | CHANSO, iocw);
|
||||
|
||||
else /* otherwise no assertion is needed */
|
||||
if (inbound_signals) /* call the interface if there are signals to assert */
|
||||
outbound = dibptr->io_interface (dibptr, inbound_signals, iocw);
|
||||
else /* otherwise the interface isn't involved */
|
||||
outbound = IORETURN (SRn, 0); /* but assert a service request to continue the program */
|
||||
|
||||
addr_reg = addr_reg + 1 & R_MASK; /* point at the IOAW program word */
|
||||
|
@ -1309,7 +1328,7 @@ while (cycles > 0) { /* execute as long as cy
|
|||
cpu_read_memory (absolute_iop, addr_reg, &ioaw); /* then load the IOAW from memory */
|
||||
cycles = cycles - CYCLES_PER_READ; /* and count the memory access */
|
||||
|
||||
dprintf (mpx_dev, DEB_PIO, "Channel SR %d loaded IOAW %06o from address %06o\n",
|
||||
dprintf (mpx_dev, DEB_PIO, "Channel SR %u loaded IOAW %06o from address %06o\n",
|
||||
srn, ioaw, addr_reg);
|
||||
}
|
||||
|
||||
|
@ -1325,7 +1344,7 @@ while (cycles > 0) { /* execute as long as cy
|
|||
cpu_write_memory (absolute_iop, addr_reg, ioaw); /* and store it in memory */
|
||||
cycles = cycles - CYCLES_PER_WRITE; /* count the memory access */
|
||||
|
||||
dprintf (mpx_dev, DEB_PIO, "Channel SR %d stored IOAW %06o to address %06o\n",
|
||||
dprintf (mpx_dev, DEB_PIO, "Channel SR %u stored IOAW %06o to address %06o\n",
|
||||
srn, ioaw, addr_reg);
|
||||
}
|
||||
|
||||
|
@ -1348,7 +1367,7 @@ while (cycles > 0) { /* execute as long as cy
|
|||
case sioENDIN:
|
||||
end_channel (dibptr); /* end the channel program */
|
||||
|
||||
dprintf (mpx_dev, DEB_STATE, "Channel SR %d entered the %s\n",
|
||||
dprintf (mpx_dev, DEB_STATE, "Channel SR %u entered the %s\n",
|
||||
srn, state_name [State_Idle]);
|
||||
break;
|
||||
|
||||
|
@ -1392,7 +1411,7 @@ while (cycles > 0) { /* execute as long as cy
|
|||
cpu_read_memory (absolute_iop, addr_reg, &ioaw); /* then read the IOAW */
|
||||
cycles = cycles - CYCLES_PER_READ; /* and count the memory access */
|
||||
|
||||
dprintf (mpx_dev, DEB_PIO, "Channel SR %d loaded IOAW %06o from address %06o\n",
|
||||
dprintf (mpx_dev, DEB_PIO, "Channel SR %u loaded IOAW %06o from address %06o\n",
|
||||
srn, ioaw, addr_reg);
|
||||
|
||||
addr_reg = ioaw; /* store the IOAW into the address register */
|
||||
|
@ -1451,14 +1470,14 @@ while (cycles > 0) { /* execute as long as cy
|
|||
addr_reg + 2 & R_MASK);
|
||||
cycles = cycles - CYCLES_PER_READ - CYCLES_PER_WRITE; /* count the two memory accesses */
|
||||
|
||||
if (cntr_reg == CNTR_MAX) /* if the word count is now exhausted */
|
||||
if (order_reg & ORDER_DC) /* then if the order is chained */
|
||||
inbound_signals = NO_SIGNALS; /* then all required signals have been sent */
|
||||
else /* otherwise */
|
||||
inbound_signals = TOGGLESR | CHANSO; /* toggle the channel SR flip-flop */
|
||||
if (cntr_reg == CNTR_MAX) /* if the word count is now exhausted */
|
||||
if (order_reg & ORDER_DC) /* then if the order is chained */
|
||||
inbound_signals = NO_SIGNALS; /* then all required signals have been sent */
|
||||
else /* otherwise */
|
||||
inbound_signals = ACKSR | TOGGLESR | CHANSO; /* toggle the channel SR flip-flop */
|
||||
|
||||
else { /* otherwise the transfer is incomplete */
|
||||
inbound_signals = EOT | TOGGLESR | CHANSO; /* so assert EOT and toggle the channel SR flip-flop */
|
||||
else { /* otherwise the transfer is incomplete */
|
||||
inbound_signals = ACKSR | EOT | TOGGLESR | CHANSO; /* so assert EOT and toggle the channel SR FF */
|
||||
|
||||
if (! (order_reg & ORDER_DC)) { /* if the order is not chained */
|
||||
aux_reg &= ~AUX_IB; /* then clear the in-block bit in RAM */
|
||||
|
@ -1521,7 +1540,7 @@ while (cycles > 0) { /* execute as long as cy
|
|||
|
||||
priority_mask = 0; /* request SR priority recalculation */
|
||||
|
||||
dprintf (mpx_dev, DEB_SR, "Device number %d denied SR%d\n",
|
||||
dprintf (mpx_dev, DEB_SR, "Device number %u denied SR%u\n",
|
||||
dibptr->device_number, dibptr->service_request_number);
|
||||
}
|
||||
|
||||
|
@ -1603,13 +1622,13 @@ return;
|
|||
selected registers are enabled to the active-low IOD bus).
|
||||
*/
|
||||
|
||||
static SIGNALS_DATA mpx_interface (DIB *dibptr, INBOUND_SET inbound_signals, uint16 inbound_value)
|
||||
static SIGNALS_DATA mpx_interface (DIB *dibptr, INBOUND_SET inbound_signals, HP_WORD inbound_value)
|
||||
{
|
||||
uint32 address;
|
||||
SIO_ORDER sio_order;
|
||||
INBOUND_SIGNAL signal;
|
||||
INBOUND_SET working_set = inbound_signals;
|
||||
uint16 outbound_value = 0;
|
||||
HP_WORD outbound_value = 0;
|
||||
OUTBOUND_SET outbound_signals = NO_SIGNALS;
|
||||
|
||||
dprintf (mpx_dev, DEB_IOB, "Received data %06o with signals %s\n",
|
||||
|
@ -1658,7 +1677,7 @@ while (working_set) {
|
|||
if (state_reg == State_B) /* if the current state is State B */
|
||||
rollover = CLEAR; /* then clear the word count rollover flip-flop */
|
||||
|
||||
dprintf (mpx_dev, DEB_CSRW, "RAM [%d] stored address %06o | %s | "
|
||||
dprintf (mpx_dev, DEB_CSRW, "RAM [%u] stored address %06o | %s | "
|
||||
"counter %04o | %s | %sbank %02o\n",
|
||||
address, addr_ram [address], sio_order_name [sio_order],
|
||||
cntr_ram [address], state_name [state_ram [address]],
|
||||
|
@ -1679,7 +1698,7 @@ while (working_set) {
|
|||
|
||||
sio_order = RD_SIO_ORDER (order_reg, cntr_reg); /* get the current SIO order */
|
||||
|
||||
dprintf (mpx_dev, DEB_CSRW, "RAM [%d] loaded address %06o | %s | "
|
||||
dprintf (mpx_dev, DEB_CSRW, "RAM [%u] loaded address %06o | %s | "
|
||||
"counter %04o | %s | %sbank %02o\n",
|
||||
address, addr_reg, sio_order_name [sio_order],
|
||||
cntr_reg, state_name [state_reg],
|
||||
|
@ -1755,7 +1774,7 @@ while (working_set) {
|
|||
outbound_value = ST_DIO_OK | status_word; /* get the last state parity error, if any */
|
||||
|
||||
dprintf (mpx_dev, DEB_CSRW, (status_word & ST_STATE_PARITY)
|
||||
? "Status is %sRAM address %d\n"
|
||||
? "Status is %sRAM address %u\n"
|
||||
: "Status is DIO OK\n",
|
||||
fmt_bitset (outbound_value, status_format),
|
||||
ST_TO_RAM_ADDR (outbound_value));
|
||||
|
@ -1768,7 +1787,7 @@ while (working_set) {
|
|||
if (control_word & CN_MR) /* if a master reset is indicated */
|
||||
mpx_reset (&mpx_dev); /* then perform an IORESET */
|
||||
|
||||
dprintf (mpx_dev, DEB_CSRW, "Control is %sRAM address %d\n",
|
||||
dprintf (mpx_dev, DEB_CSRW, "Control is %sRAM address %u\n",
|
||||
fmt_bitset (inbound_value, control_format),
|
||||
CN_RAM_ADDR (control_word));
|
||||
break;
|
||||
|
@ -1911,7 +1930,7 @@ static void end_channel (DIB *dibptr)
|
|||
active_count = active_count - 1; /* decrease the reference count */
|
||||
mpx_is_idle = (active_count == 0); /* and idle the channel if no more work */
|
||||
|
||||
dprintf (mpx_dev, DEB_CSRW, "Channel SR %d program ended\n",
|
||||
dprintf (mpx_dev, DEB_CSRW, "Channel SR %u program ended\n",
|
||||
dibptr->service_request_number);
|
||||
|
||||
return;
|
||||
|
@ -1926,11 +1945,11 @@ return;
|
|||
internal logic in response.
|
||||
*/
|
||||
|
||||
static SIGNALS_DATA abort_channel (DIB *dibptr, char *reason)
|
||||
static SIGNALS_DATA abort_channel (DIB *dibptr, const char *reason)
|
||||
{
|
||||
SIGNALS_DATA outbound;
|
||||
|
||||
dprintf (mpx_dev, DEB_CSRW, "Channel SR %d asserted XFERERROR for %s\n",
|
||||
dprintf (mpx_dev, DEB_CSRW, "Channel SR %u asserted XFERERROR for %s\n",
|
||||
dibptr->service_request_number, reason);
|
||||
|
||||
outbound = dibptr->io_interface (dibptr, XFERERROR | CHANSO, 0); /* tell the device that the channel has aborted */
|
||||
|
|
|
@ -25,7 +25,12 @@
|
|||
|
||||
MS HP 30215A Magnetic Tape Controller Interface
|
||||
|
||||
09-Jun-16 JDB Added casts for ptrdiff_t to int32 values
|
||||
08-Jun-16 JDB Corrected %d format to %u for unsigned values
|
||||
16-May-16 JDB Fixed interrupt mask setting
|
||||
13-May-16 JDB Modified for revised SCP API function parameter types
|
||||
24-Mar-16 JDB Changed the buffer element type from uint8 to TL_BUFFER
|
||||
21-Mar-16 JDB Changed uint16 types to HP_WORD
|
||||
10-Nov-15 JDB First release version
|
||||
26-Oct-14 JDB Passes the magnetic tape diagnostic (D433A)
|
||||
10-Feb-13 JDB Created
|
||||
|
@ -265,7 +270,7 @@
|
|||
|
||||
#define DEB_IOB TL_DEB_IOB /* trace I/O bus signals and data words */
|
||||
#define DEB_SERV TL_DEB_SERV /* trace unit service scheduling calls */
|
||||
#define DEB_CSRW (1 << TL_DEB_V_UF + 0) /* trace control, status, read, and write actions */
|
||||
#define DEB_CSRW (1u << TL_DEB_V_UF + 0) /* trace control, status, read, and write actions */
|
||||
|
||||
|
||||
/* Control word.
|
||||
|
@ -280,13 +285,13 @@
|
|||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
*/
|
||||
|
||||
#define CN_MR 0100000 /* (M) master reset */
|
||||
#define CN_RIN 0040000 /* (R) reset interrupt */
|
||||
#define CN_UNIT_MASK 0001400 /* unit number mask */
|
||||
#define CN_RSVD_MASK 0000360 /* reserved mask */
|
||||
#define CN_CMD_MASK 0000017 /* command code mask */
|
||||
#define CN_MR 0100000u /* (M) master reset */
|
||||
#define CN_RIN 0040000u /* (R) reset interrupt */
|
||||
#define CN_UNIT_MASK 0001400u /* unit number mask */
|
||||
#define CN_RSVD_MASK 0000360u /* reserved mask */
|
||||
#define CN_CMD_MASK 0000017u /* command code mask */
|
||||
|
||||
#define CN_CMD_RDR 0000006 /* Read Record command */
|
||||
#define CN_CMD_RDR 0000006u /* Read Record command */
|
||||
|
||||
#define CN_UNIT_SHIFT 8 /* unit number alignment shift */
|
||||
#define CN_CMD_SHIFT 0 /* command code alignment shift */
|
||||
|
@ -320,19 +325,19 @@ static const BITSET_FORMAT control_format = /* names, offset, direction, alt
|
|||
reporting the controller status.
|
||||
*/
|
||||
|
||||
#define ST_SIO_OK 0100000 /* (S) SIO OK to use */
|
||||
/* ST_ODD_COUNT 0040000 */ /* (B) byte count is odd (supplied by hp_tapelib) */
|
||||
#define ST_INTREQ 0020000 /* (I) interrupt requested */
|
||||
#define ST_UNIT_MASK 0014000 /* unit selected mask */
|
||||
/* ST_EOT 0002000 */ /* (E) end of tape (supplied by hp_tapelib) */
|
||||
/* ST_PROTECTED 0001000 */ /* (P) write protected (supplied by hp_tapelib) */
|
||||
/* ST_READY 0000400 */ /* (R) unit ready (supplied by hp_tapelib) */
|
||||
/* ST_LOAD_POINT 0000200 */ /* (L) load point (supplied by hp_tapelib) */
|
||||
/* ST_DENSITY_1600 0000100 */ /* (D) 1600 bpi density (supplied by hp_tapelib) */
|
||||
/* ST_WRITE_STATUS 0000040 */ /* (W) write status (supplied by hp_tapelib) */
|
||||
/* ST_TAPE_MARK 0000020 */ /* (M) tape mark (supplied by hp_tapelib) */
|
||||
#define ST_ERROR_MASK 0000016 /* encoded error field mask */
|
||||
/* ST_7_TRACK 0000001 */ /* (T) 7-track unit (always off) */
|
||||
#define ST_SIO_OK 0100000u /* (S) SIO OK to use */
|
||||
/* ST_ODD_COUNT 0040000u */ /* (B) byte count is odd (supplied by hp_tapelib) */
|
||||
#define ST_INTREQ 0020000u /* (I) interrupt requested */
|
||||
#define ST_UNIT_MASK 0014000u /* unit selected mask */
|
||||
/* ST_EOT 0002000u */ /* (E) end of tape (supplied by hp_tapelib) */
|
||||
/* ST_PROTECTED 0001000u */ /* (P) write protected (supplied by hp_tapelib) */
|
||||
/* ST_READY 0000400u */ /* (R) unit ready (supplied by hp_tapelib) */
|
||||
/* ST_LOAD_POINT 0000200u */ /* (L) load point (supplied by hp_tapelib) */
|
||||
/* ST_DENSITY_1600 0000100u */ /* (D) 1600 bpi density (supplied by hp_tapelib) */
|
||||
/* ST_WRITE_STATUS 0000040u */ /* (W) write status (supplied by hp_tapelib) */
|
||||
/* ST_TAPE_MARK 0000020u */ /* (M) tape mark (supplied by hp_tapelib) */
|
||||
#define ST_ERROR_MASK 0000016u /* encoded error field mask */
|
||||
/* ST_7_TRACK 0000001u */ /* (T) 7-track unit (always off) */
|
||||
|
||||
#define ST_UNIT_SHIFT 11 /* unit number alignment shift */
|
||||
#define ST_ERROR_SHIFT 1 /* encoded error alignment shift */
|
||||
|
@ -345,14 +350,14 @@ static const BITSET_FORMAT control_format = /* names, offset, direction, alt
|
|||
|
||||
/* Error codes (complements of the values returned) */
|
||||
|
||||
#define ST_UNITIRQ 0000016 /* unit interrupt */
|
||||
#define ST_XFER 0000014 /* transfer error */
|
||||
/* ST_REJECT 0000012 */ /* command reject (supplied by hp_tapelib) */
|
||||
/* ST_RUNAWAY 0000010 */ /* tape runaway (supplied by hp_tapelib) */
|
||||
/* ST_TIMING 0000006 */ /* timing error (supplied by hp_tapelib) */
|
||||
/* ST_PARITY 0000004 */ /* tape error (supplied by hp_tapelib) */
|
||||
/* ST_RESERVED 0000002 */ /* (reserved) */
|
||||
/* ST_NOERROR 0000000 */ /* no error */
|
||||
#define ST_UNITIRQ 0000016u /* unit interrupt */
|
||||
#define ST_XFER 0000014u /* transfer error */
|
||||
/* ST_REJECT 0000012u */ /* command reject (supplied by hp_tapelib) */
|
||||
/* ST_RUNAWAY 0000010u */ /* tape runaway (supplied by hp_tapelib) */
|
||||
/* ST_TIMING 0000006u */ /* timing error (supplied by hp_tapelib) */
|
||||
/* ST_PARITY 0000004u */ /* tape error (supplied by hp_tapelib) */
|
||||
/* ST_RESERVED 0000002u */ /* (reserved) */
|
||||
/* ST_NOERROR 0000000u */ /* no error */
|
||||
|
||||
static const BITSET_NAME status_names [] = { /* Status word names */
|
||||
"SIO OK", /* bit 0 */
|
||||
|
@ -434,17 +439,17 @@ static FLIP_FLOP channel_sr = CLEAR; /* channel service reque
|
|||
static FLIP_FLOP device_sr = CLEAR; /* device service request flip-flop */
|
||||
static FLIP_FLOP input_xfer = CLEAR; /* input transfer flip-flop */
|
||||
static FLIP_FLOP output_xfer = CLEAR; /* output transfer flip-flop */
|
||||
static FLIP_FLOP interrupt_mask = CLEAR; /* interrupt mask flip-flop */
|
||||
static FLIP_FLOP interrupt_mask = SET; /* interrupt mask flip-flop */
|
||||
static FLIP_FLOP unit_interrupt = CLEAR; /* unit ready flip-flop */
|
||||
static FLIP_FLOP device_end = CLEAR; /* device end flip-flop */
|
||||
static FLIP_FLOP xfer_error = CLEAR; /* transfer error flip-flop */
|
||||
|
||||
static uint16 buffer_word = 0; /* data buffer word */
|
||||
static uint16 attention_unit = 0; /* number of the unit requesting attention */
|
||||
static HP_WORD buffer_word = 0; /* data buffer word */
|
||||
static HP_WORD attention_unit = 0; /* number of the unit requesting attention */
|
||||
static CNTLR_CLASS command_class = Class_Invalid; /* current command classification */
|
||||
static CNTLR_FLAG_SET flags = INTOK; /* tape controller interface flag set */
|
||||
|
||||
static uint8 buffer [TL_BUFSIZE]; /* the tape record buffer */
|
||||
static TL_BUFFER buffer [TL_BUFSIZE]; /* the tape record buffer */
|
||||
|
||||
DEVICE ms_dev; /* incomplete device structure */
|
||||
|
||||
|
@ -497,22 +502,22 @@ static UNIT ms_unit [UNIT_COUNT] = {
|
|||
/* Register list */
|
||||
|
||||
static REG ms_reg [] = {
|
||||
/* Macro Name Location Width Offset Flags */
|
||||
/* ------ ------ -------------- ----- ------ ------------------------- */
|
||||
{ FLDATA (SIOBSY, sio_busy, 0) },
|
||||
{ FLDATA (CHANSR, channel_sr, 0) },
|
||||
{ FLDATA (DEVSR, device_sr, 0) },
|
||||
{ FLDATA (INXFR, input_xfer, 0) },
|
||||
{ FLDATA (OUTXFR, output_xfer, 0) },
|
||||
{ FLDATA (INTMSK, interrupt_mask, 0) },
|
||||
{ FLDATA (UINTRP, unit_interrupt, 0) },
|
||||
{ FLDATA (DEVEND, device_end, 0) },
|
||||
{ FLDATA (XFRERR, xfer_error, 0) },
|
||||
{ ORDATA (BUFWRD, buffer_word, 16), REG_A | REG_FIT | PV_RZRO },
|
||||
{ DRDATA (ATUNIT, attention_unit, 16), REG_FIT | PV_LEFT },
|
||||
{ DRDATA (CLASS, command_class, 4), PV_LEFT },
|
||||
{ YRDATA (FLAGS, flags, 8) },
|
||||
{ SRDATA (DIB, ms_dib), REG_HRO },
|
||||
/* Macro Name Location Width Offset Flags */
|
||||
/* ------ ------ -------------- ----- ------ ------------------------- */
|
||||
{ FLDATA (SIOBSY, sio_busy, 0) },
|
||||
{ FLDATA (CHANSR, channel_sr, 0) },
|
||||
{ FLDATA (DEVSR, device_sr, 0) },
|
||||
{ FLDATA (INXFR, input_xfer, 0) },
|
||||
{ FLDATA (OUTXFR, output_xfer, 0) },
|
||||
{ FLDATA (INTMSK, interrupt_mask, 0) },
|
||||
{ FLDATA (UINTRP, unit_interrupt, 0) },
|
||||
{ FLDATA (DEVEND, device_end, 0) },
|
||||
{ FLDATA (XFRERR, xfer_error, 0) },
|
||||
{ ORDATA (BUFWRD, buffer_word, 16), REG_A | REG_FIT | PV_RZRO },
|
||||
{ DRDATA (ATUNIT, attention_unit, 16), REG_FIT | PV_LEFT },
|
||||
{ DRDATA (CLASS, command_class, 4), PV_LEFT },
|
||||
{ YRDATA (FLAGS, flags, 8, PV_RZRO) },
|
||||
{ SRDATA (DIB, ms_dib, REG_HRO) },
|
||||
|
||||
TL_REGS (ms_cntlr, ms_unit, DRIVE_COUNT, buffer, fast_times),
|
||||
|
||||
|
@ -679,12 +684,12 @@ DEVICE ms_dev = {
|
|||
JMPMET signal is asserted continuously when enabled by CHANSO.
|
||||
*/
|
||||
|
||||
static SIGNALS_DATA ms_interface (DIB *dibptr, INBOUND_SET inbound_signals, uint16 inbound_value)
|
||||
static SIGNALS_DATA ms_interface (DIB *dibptr, INBOUND_SET inbound_signals, HP_WORD inbound_value)
|
||||
{
|
||||
CNTLR_OPCODE opcode;
|
||||
INBOUND_SIGNAL signal;
|
||||
INBOUND_SET working_set = inbound_signals;
|
||||
uint16 outbound_value = 0;
|
||||
HP_WORD outbound_value = 0;
|
||||
OUTBOUND_SET outbound_signals = NO_SIGNALS;
|
||||
|
||||
dprintf (ms_dev, DEB_IOB, "Received data %06o with signals %s\n",
|
||||
|
@ -737,10 +742,13 @@ while (working_set) {
|
|||
|
||||
|
||||
case DSETMASK:
|
||||
interrupt_mask = /* set the mask flip-flop */
|
||||
D_FF (dibptr->interrupt_mask & inbound_value); /* from the mask bit and the mask value */
|
||||
if (dibptr->interrupt_mask == INTMASK_E) /* if the mask is always enabled */
|
||||
interrupt_mask = SET; /* then set the mask flip-flop */
|
||||
else /* otherwise */
|
||||
interrupt_mask = D_FF (dibptr->interrupt_mask /* set the mask flip-flop if the mask bit */
|
||||
& inbound_value); /* is present in the mask value */
|
||||
|
||||
if (interrupt_mask & dibptr->interrupt_request) /* if the mask is enabled and a request is pending */
|
||||
if (interrupt_mask && dibptr->interrupt_request) /* if the mask is enabled and a request is pending */
|
||||
outbound_signals |= INTREQ; /* then assert the INTREQ signal */
|
||||
break;
|
||||
|
||||
|
@ -786,7 +794,7 @@ while (working_set) {
|
|||
if (dibptr->interrupt_request) /* if an interrupt request is pending */
|
||||
outbound_value |= ST_INTREQ; /* then set the status bit */
|
||||
|
||||
dprintf (ms_dev, DEB_CSRW, "Status is %s%s | unit %d\n",
|
||||
dprintf (ms_dev, DEB_CSRW, "Status is %s%s | unit %u\n",
|
||||
fmt_bitset (outbound_value, status_format),
|
||||
error_names [ST_TO_ERROR (outbound_value)],
|
||||
ST_TO_UNIT (outbound_value));
|
||||
|
@ -879,9 +887,9 @@ while (working_set) {
|
|||
inbound_value, tl_opcode_name (opcode));
|
||||
|
||||
if ((inbound_value & CN_RSVD_MASK) != 0) /* if the reserved bits aren't zero */
|
||||
buffer_word = (uint16) Invalid_Opcode; /* then reject the command */
|
||||
buffer_word = (HP_WORD) Invalid_Opcode; /* then reject the command */
|
||||
else /* otherwise */
|
||||
buffer_word = (uint16) opcode; /* store the opcode in the data buffer register */
|
||||
buffer_word = (HP_WORD) opcode; /* store the opcode in the data buffer register */
|
||||
|
||||
flags |= CMRDY | CMXEQ; /* set the command ready and execute flags */
|
||||
|
||||
|
@ -993,7 +1001,7 @@ static t_stat ms_service (UNIT *uptr)
|
|||
t_stat result;
|
||||
|
||||
dprintf (ms_dev, DEB_SERV, "%s service entered\n",
|
||||
tl_unit_name (uptr - ms_unit));
|
||||
tl_unit_name ((int32) (uptr - ms_unit)));
|
||||
|
||||
result = call_controller (uptr); /* call the controller */
|
||||
|
||||
|
@ -1017,12 +1025,6 @@ return result;
|
|||
|
||||
static t_stat ms_reset (DEVICE *dptr)
|
||||
{
|
||||
t_stat status;
|
||||
|
||||
master_reset (); /* perform a master reset */
|
||||
|
||||
status = tl_reset (&ms_cntlr); /* reset the controller */
|
||||
|
||||
if (sim_switches & SWMASK ('P')) { /* if this is a power-on reset */
|
||||
fast_times.rewind_start = MS_REW_START; /* then reset the rewind initiation time, */
|
||||
fast_times.rewind_rate = MS_REW_RATE; /* the rewind time per inch, */
|
||||
|
@ -1032,7 +1034,9 @@ if (sim_switches & SWMASK ('P')) { /* if this is a power-on
|
|||
fast_times.overhead = MS_OVERHEAD; /* and the controller execution overhead */
|
||||
}
|
||||
|
||||
return status; /* return the result of the reset */
|
||||
master_reset (); /* perform a master reset */
|
||||
|
||||
return tl_reset (&ms_cntlr); /* reset the controller and return the result */
|
||||
}
|
||||
|
||||
|
||||
|
@ -1261,7 +1265,7 @@ CNTLR_IFN command;
|
|||
t_stat status = SCPE_OK;
|
||||
|
||||
result = /* call the controller to start or continue a command */
|
||||
tl_controller (&ms_cntlr, uptr, flags, buffer_word);
|
||||
tl_controller (&ms_cntlr, uptr, flags, (CNTLR_IBUS) buffer_word);
|
||||
|
||||
command_set = TLIFN (result) & ~UNUSED_COMMANDS; /* strip the commands we don't use as an efficiency */
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
SIMH/HP 3000 RELEASE NOTES
|
||||
==========================
|
||||
Last update: 2016-03-06
|
||||
Last update: 2016-07-05
|
||||
|
||||
|
||||
This file documents the release history of the Hewlett-Packard 3000 simulator.
|
||||
|
@ -71,8 +71,8 @@ Manuals describing MPE operation are also available from Bitsavers at:
|
|||
http://www.bitsavers.org/pdf/hp/3000/
|
||||
|
||||
HP created MPE-V/R-specific manuals. However, very few of them survive. In
|
||||
general, the MPE-IV manuals will describe a subset of MPE-V/R commands, whereas
|
||||
the MPE-V/E manuals describe a superset. Relying on the MPE-IV manuals and the
|
||||
general, the MPE-IV manuals describe a subset of MPE-V/R commands, whereas the
|
||||
MPE-V/E manuals describe a superset. Relying on the MPE-IV manuals and the
|
||||
online help available within MPE for those commands that do not appear in the
|
||||
manuals is perhaps the best compromise.
|
||||
|
||||
|
@ -158,6 +158,153 @@ the MPE version used:
|
|||
|
||||
|
||||
|
||||
=====================
|
||||
Release 2, 2016-07-05
|
||||
=====================
|
||||
|
||||
This release of the HP 3000 simulator adds the following device simulation:
|
||||
|
||||
- 30209A Line Printer Controller with One 2607/13/17/18 Line Printer
|
||||
|
||||
The simulation supports the use of custom VFU tape images, as well as the
|
||||
built-in HP-standard VFU tape. The simulated device name is "LP". The full set
|
||||
of configurable options is detailed in a new section of the HP 3000 Simulator
|
||||
User's Guide.
|
||||
|
||||
In addition, the preconfigured MPE-V/R disc image has been updated to add the
|
||||
following features:
|
||||
|
||||
- The MPE cold load command files attach the line printer to the "lp.txt"
|
||||
output file and specify the "-n" option to clear the file before use.
|
||||
|
||||
- Preinstalled User-Defined Commands (UDCs) provide access to the COBOL 74
|
||||
compiler with the MPE-V/E :COBOLII, :COBOLIIPREP, and :COBOLIIGO commands,
|
||||
and to the COBOL 85 compiler with :COBOLIIX, :COBOLIIXPREP, and :COBOLIIXGO.
|
||||
However, see the implementation note below.
|
||||
|
||||
|
||||
--------------------
|
||||
Implementation Notes
|
||||
--------------------
|
||||
|
||||
- MPE requires a line printer, so it is recommended that the MPE startup
|
||||
simulator command file include an ATTACH LP <filename> command to load paper
|
||||
into the printer before cold loading. If the printer is not attached, it
|
||||
will appear to MPE to be out of paper.
|
||||
|
||||
- The line printer terminates each print line with an HP-standard CR/LF pair.
|
||||
If the output file is to be retained as a text file on a Unix system, removal
|
||||
of the carriage returns, e.g., via the "dos2unix" utility, may be desirable.
|
||||
|
||||
- The simulator currently does not provide the HP 32234A COBOL II firmware
|
||||
instructions, so programs generated by the COBOLII compiler will abort at run
|
||||
time with an "ILLEGAL INSTRUCTION" error. Programs generated by the COBOL
|
||||
compiler do not use these instructions and therefore are not affected.
|
||||
|
||||
|
||||
----------
|
||||
Bugs Fixed
|
||||
----------
|
||||
|
||||
1. PROBLEM: The effective address of a byte pointer with a negative index is
|
||||
calculated incorrectly.
|
||||
|
||||
VERSION: Release 1
|
||||
|
||||
OBSERVATION: Defining a :WELCOME message in MPE appears to work, but when
|
||||
the next logon attempts to print the message, an infinite number of CRLFs
|
||||
are printed instead.
|
||||
|
||||
CAUSE: The welcome message is stored in an extra data segment. The format
|
||||
for each message line is a line length stored in the lower byte of the word
|
||||
preceding the message string. The code defines BYTE POINTER NEXTLINE and
|
||||
points NEXTLINE to the first message character. The line length is set
|
||||
with NEXTLINE(-1) := IOCOUNT. This generates a LOAD <IOCOUNT> ; LDXN 1 ;
|
||||
STB <NEXTLINE>,I,X sequence.
|
||||
|
||||
In the "cpu_ea" routine, the indexing adds the X register value (-1) to the
|
||||
byte pointer (NEXTLINE). This causes an overflow that is not masked to 16
|
||||
bits. For a word access, this displacement is added to the base register
|
||||
and then masked to 16 bits, which gives the correct value. However, for
|
||||
byte accesses, the displacement is divided by 2 and then added, and the sum
|
||||
is masked. Dividing by 2 shifts the overflow bit into the MSB, causing the
|
||||
addition result to be off by 32K. The STB goes to the wrong location, the
|
||||
original zero in the length byte location is retained, and when the welcome
|
||||
message is printed, a zero-length line is printed, and the byte pointer is
|
||||
incremented by zero, so the null line is printed forever.
|
||||
|
||||
RESOLUTION: Modify "cpu_ea" (hp3000_cpu.c) to mask indexed displacements
|
||||
to 16 bits after adding the X register value.
|
||||
|
||||
STATUS: Fixed in Release 2.
|
||||
|
||||
|
||||
2. PROBLEM: An SMSK instruction may clear the interrupt mask flip-flop of a
|
||||
device that specifies that it is should be "always enabled."
|
||||
|
||||
VERSION: Release 1
|
||||
|
||||
OBSERVATION: If the TOS word is zero, an SMSK instruction will clear the
|
||||
interrupt mask flip-flop of a device whose mask jumper is set to "E"
|
||||
(always enabled).
|
||||
|
||||
CAUSE: In response to a DSETMASK signal, device interfaces set their
|
||||
interrupt mask flip-flops by "anding" the incoming data word with the
|
||||
interrupt mask jumper setting. The jumper setting value for "always
|
||||
enabled" is %177777, which sets the mask flip-flop in all cases, except
|
||||
when the data word is zero.
|
||||
|
||||
RESOLUTION: Modify hp3000_atc.c, hp3000_ds.c, and hp3000_ms.c to set their
|
||||
mask flip-flops unconditionally if the jumper setting is "E".
|
||||
|
||||
STATUS: Fixed in Release 2.
|
||||
|
||||
|
||||
3. PROBLEM: The "SET <dev> INTMASK=<n>" command sets the wrong bit in the
|
||||
device interface's interrupt mask jumper setting.
|
||||
|
||||
VERSION: Release 1
|
||||
|
||||
OBSERVATION: The interrupt mask jumper on a device interface is set by
|
||||
specifying the mask bit number in a "SET <dev> INTMASK=<n>" command. This
|
||||
sets a bit in the device's interrupt mask jumper word corresponding to the
|
||||
bit number requested. However, the bit numbering is incorrect; setting the
|
||||
jumper for bit 15, for example, sets bit 0 of the jumper word. Therefore,
|
||||
the interface's mask flip-flop is not set as expected when an SMSK
|
||||
instruction is executed.
|
||||
|
||||
CAUSE: The bit numbers were counted from the wrong end of the word.
|
||||
|
||||
RESOLUTION: Modify "hp_set_dib" and "hp_show_dib" (hp3000_sys.c) to number
|
||||
the bits from the MSB instead of the LSB.
|
||||
|
||||
STATUS: Fixed in Release 2.
|
||||
|
||||
|
||||
4. PROBLEM: The Multiplexer Channel is not generating the ACKSR signal
|
||||
correctly.
|
||||
|
||||
VERSION: Release 1
|
||||
|
||||
OBSERVATION: The line printer controller hangs when an SIO chained write
|
||||
is performed. The first programmed write completes normally, but the
|
||||
second does not start. The channel is waiting for a service request that
|
||||
does not occur.
|
||||
|
||||
CAUSE: The service request from the last write of the first block transfer
|
||||
is being cleared by an ACKSR generated by the Multiplexer Channel when it
|
||||
performs the IOCW fetch in State A for the second write request. The
|
||||
channel should omit this ACKSR when the previous I/O order was a chained
|
||||
read or write. However, the simulator is testing the order just fetched
|
||||
(Write) instead of the order that has just completed (Write Chained).
|
||||
|
||||
RESOLUTION: Modify "mpx_service" (hp3000_mpx.c) to test the correct I/O
|
||||
order in State A.
|
||||
|
||||
STATUS: Fixed in Release 2.
|
||||
|
||||
|
||||
|
||||
=====================
|
||||
Release 1, 2016-03-07
|
||||
=====================
|
||||
|
|
|
@ -25,7 +25,9 @@
|
|||
|
||||
SCMB1,SCMB2 HP 30033A Selector Channel Maintenance Board
|
||||
|
||||
11-Jun-16 JDB Bit mask constants are now unsigned
|
||||
13-May-16 JDB Modified for revised SCP API function parameter types
|
||||
21-Mar-16 JDB Changed uint16 types to HP_WORD
|
||||
21-Sep-15 JDB First release version
|
||||
27-Jan-15 JDB Passes the selector channel diagnostic (D429A)
|
||||
12-Jan-15 JDB Passes the SCMB diagnostic (D429A)
|
||||
|
@ -87,7 +89,7 @@
|
|||
N = enable special device number
|
||||
T = terminate on terminal count
|
||||
C = terminate on compare failure
|
||||
L = enable clear interface on terminate
|
||||
L = enable device end/clear interface (0/1) on terminate
|
||||
|
||||
Load:
|
||||
00 = load the IOAW into the control word
|
||||
|
@ -205,7 +207,7 @@
|
|||
|
||||
#define UNIT_W1_SHIFT (UNIT_V_UF + 0) /* jumper W1 */
|
||||
|
||||
#define UNIT_W1_SEL (1 << UNIT_W1_SHIFT)
|
||||
#define UNIT_W1_SEL (1u << UNIT_W1_SHIFT)
|
||||
|
||||
#define MPX_BUS(card) ((scmb_unit [card].flags & UNIT_W1_SEL) == 0)
|
||||
#define SEL_BUS(card) ((scmb_unit [card].flags & UNIT_W1_SEL) != 0)
|
||||
|
@ -213,10 +215,10 @@
|
|||
|
||||
/* Debug flags */
|
||||
|
||||
#define DEB_CSRW (1 << 0) /* trace commands received and status returned */
|
||||
#define DEB_XFER (1 << 1) /* trace channel data reads and writes */
|
||||
#define DEB_SERV (1 << 2) /* trace unit service scheduling calls */
|
||||
#define DEB_IOB (1 << 3) /* trace I/O bus signals and data words */
|
||||
#define DEB_CSRW (1u << 0) /* trace commands received and status returned */
|
||||
#define DEB_XFER (1u << 1) /* trace channel data reads and writes */
|
||||
#define DEB_SERV (1u << 2) /* trace unit service scheduling calls */
|
||||
#define DEB_IOB (1u << 3) /* trace I/O bus signals and data words */
|
||||
|
||||
|
||||
/* Control word.
|
||||
|
@ -227,19 +229,19 @@
|
|||
+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
|
||||
*/
|
||||
|
||||
#define CN_MR 0100000 /* M = master reset */
|
||||
#define CN_IRQ_RESET 0040000 /* R = interrupt reset */
|
||||
#define CN_JMPMET 0020000 /* J = set jump met */
|
||||
#define CN_DEVEND 0010000 /* V = device end */
|
||||
#define CN_NOACK 0004000 /* A = inhibit channel acknowledge */
|
||||
#define CN_NOSR 0002000 /* S = inhibit service request */
|
||||
#define CN_LOAD_MASK 0001400 /* load operation mask */
|
||||
#define CN_HSREQ 0000200 /* H = high speed service request */
|
||||
#define CN_DEVNO 0000100 /* N = special device number */
|
||||
#define CN_TERM_COUNT 0000040 /* T = terminate on count */
|
||||
#define CN_TERM_COMP 0000020 /* C = terminate on miscompare */
|
||||
#define CN_CLEAR_IF 0000010 /* L = clear interface */
|
||||
#define CN_CNTR_MASK 0000007 /* counter operation mask */
|
||||
#define CN_MR 0100000u /* M = master reset */
|
||||
#define CN_IRQ_RESET 0040000u /* R = interrupt reset */
|
||||
#define CN_JMPMET 0020000u /* J = set jump met */
|
||||
#define CN_DEVEND 0010000u /* V = set device end */
|
||||
#define CN_NOACK 0004000u /* A = inhibit channel acknowledge */
|
||||
#define CN_NOSR 0002000u /* S = inhibit service request */
|
||||
#define CN_LOAD_MASK 0001400u /* load operation mask */
|
||||
#define CN_HSREQ 0000200u /* H = high speed service request */
|
||||
#define CN_DEVNO 0000100u /* N = special device number */
|
||||
#define CN_TERM_COUNT 0000040u /* T = terminate on count */
|
||||
#define CN_TERM_COMP 0000020u /* C = terminate on miscompare */
|
||||
#define CN_CLEAR_IF 0000010u /* L = clear interface */
|
||||
#define CN_CNTR_MASK 0000007u /* counter operation mask */
|
||||
|
||||
#define CN_LOAD_SHIFT 8 /* load operation alignment shift */
|
||||
#define CN_CNTR_SHIFT 0 /* counter operation alignment shift */
|
||||
|
@ -280,23 +282,23 @@ static const char *const count_names [8] = { /* indexed by CNTR_OP */
|
|||
"count PWRITESTB", /* 100 = count PWRITESTB */
|
||||
"count TOGGLEOUTXFER", /* 101 = count TOGGLEOUTXFER */
|
||||
"count EOT", /* 110 = count EOT */
|
||||
"count CHANSO", /* 111 = count CHANSO */
|
||||
"count CHANSO" /* 111 = count CHANSO */
|
||||
};
|
||||
|
||||
static const BITSET_NAME control_names [] = { /* Control word names */
|
||||
"master reset", /* bit 0 */
|
||||
"reset interrupt", /* bit 1 */
|
||||
"set JMPMET", /* bit 2 */
|
||||
"set DEVEND", /* bit 3 */
|
||||
"inhibit CHANACK", /* bit 4 */
|
||||
"inhibit SR", /* bit 5 */
|
||||
NULL, /* bit 6 */
|
||||
NULL, /* bit 7 */
|
||||
"high speed", /* bit 8 */
|
||||
"send DEVNO", /* bit 9 */
|
||||
"end on count", /* bit 10 */
|
||||
"end on miscompare", /* bit 11 */
|
||||
"\1clear interface\0device end", /* bit 12 */
|
||||
static const BITSET_NAME control_names [] = { /* Control word names */
|
||||
"master reset", /* bit 0 */
|
||||
"reset interrupt", /* bit 1 */
|
||||
"set JMPMET", /* bit 2 */
|
||||
"set DEVEND", /* bit 3 */
|
||||
"inhibit CHANACK", /* bit 4 */
|
||||
"inhibit SR", /* bit 5 */
|
||||
NULL, /* bit 6 */
|
||||
NULL, /* bit 7 */
|
||||
"high speed", /* bit 8 */
|
||||
"send DEVNO", /* bit 9 */
|
||||
"end on count", /* bit 10 */
|
||||
"end on miscompare", /* bit 11 */
|
||||
"\1end with clear interface\0end with device end" /* bit 12 */
|
||||
};
|
||||
|
||||
static const BITSET_FORMAT control_format = /* names, offset, direction, alternates, bar */
|
||||
|
@ -315,19 +317,19 @@ static const BITSET_FORMAT control_format = /* names, offset, direction, alt
|
|||
manual has the correct assignments.
|
||||
*/
|
||||
|
||||
#define ST_SIO_OK 0100000 /* S = SIO OK to use */
|
||||
#define ST_DIO_OK 0040000 /* D = direct I/O OK to use (always 1) */
|
||||
#define ST_INTREQ 0020000 /* R = interrupt requested */
|
||||
#define ST_INTACT 0010000 /* A = interrupt active */
|
||||
#define ST_XFERERR 0004000 /* X = transfer error is asserted */
|
||||
#define ST_SIOENABLED 0002000 /* N = SIO enabled is asserted */
|
||||
#define ST_DEVEND 0001000 /* V = device end is asserted */
|
||||
#define ST_EOT 0000400 /* E = end of transfer is asserted */
|
||||
#define ST_END_MISCMP 0000200 /* C = end on miscompare occurred */
|
||||
#define ST_END_COUNT 0000100 /* T = end on terminal count occurred */
|
||||
#define ST_INXFER 0000040 /* I = input transfer is asserted */
|
||||
#define ST_OUTXFER 0000020 /* O = output transfer is asserted */
|
||||
#define ST_CLEAR_IF 0000010 /* L = clear interface is asserted */
|
||||
#define ST_SIO_OK 0100000u /* S = SIO OK to use */
|
||||
#define ST_DIO_OK 0040000u /* D = direct I/O OK to use (always 1) */
|
||||
#define ST_INTREQ 0020000u /* R = interrupt requested */
|
||||
#define ST_INTACT 0010000u /* A = interrupt active */
|
||||
#define ST_XFERERR 0004000u /* X = transfer error is asserted */
|
||||
#define ST_SIOENABLED 0002000u /* N = SIO enabled is asserted */
|
||||
#define ST_DEVEND 0001000u /* V = device end is asserted */
|
||||
#define ST_EOT 0000400u /* E = end of transfer is asserted */
|
||||
#define ST_END_MISCMP 0000200u /* C = end on miscompare occurred */
|
||||
#define ST_END_COUNT 0000100u /* T = end on terminal count occurred */
|
||||
#define ST_INXFER 0000040u /* I = input transfer is asserted */
|
||||
#define ST_OUTXFER 0000020u /* O = output transfer is asserted */
|
||||
#define ST_CLEAR_IF 0000010u /* L = clear interface is asserted */
|
||||
|
||||
#define END_CONDITION (ST_END_MISCMP | ST_END_COUNT)
|
||||
|
||||
|
@ -359,11 +361,11 @@ typedef enum {
|
|||
} CARD_ID;
|
||||
|
||||
typedef struct {
|
||||
uint16 control_word; /* control word register */
|
||||
uint16 status_word; /* status word register */
|
||||
uint16 counter; /* counter/buffer register */
|
||||
uint16 flags; /* status flags */
|
||||
uint32 saved_srn; /* saved SR number */
|
||||
HP_WORD control_word; /* control word register */
|
||||
HP_WORD status_word; /* status word register */
|
||||
HP_WORD counter; /* counter/buffer register */
|
||||
HP_WORD flags; /* status flags */
|
||||
uint32 saved_srn; /* saved SR number */
|
||||
|
||||
FLIP_FLOP sio_busy; /* SIO busy flip-flop */
|
||||
FLIP_FLOP channel_sr; /* channel service request flip-flop */
|
||||
|
@ -439,55 +441,55 @@ static UNIT scmb_unit [] = {
|
|||
/* Register lists */
|
||||
|
||||
static REG scmb1_reg [] = {
|
||||
/* Macro Name Location Width Offset Flags */
|
||||
/* ------ ------ -------------------------- ----- ------ ----------------- */
|
||||
{ ORDATA (CNTL, scmb [card1].control_word, 16), REG_FIT },
|
||||
{ ORDATA (STAT, scmb [card1].status_word, 16), REG_FIT },
|
||||
{ ORDATA (CNTR, scmb [card1].counter, 16), REG_FIT },
|
||||
{ ORDATA (SRSAVE, scmb [card1].saved_srn, 8), REG_HRO },
|
||||
/* Macro Name Location Width Offset Flags */
|
||||
/* ------ ------ -------------------------- ----- ------ ----------------- */
|
||||
{ ORDATA (CNTL, scmb [card1].control_word, 16), REG_FIT },
|
||||
{ ORDATA (STAT, scmb [card1].status_word, 16), REG_FIT },
|
||||
{ ORDATA (CNTR, scmb [card1].counter, 16), REG_FIT },
|
||||
{ ORDATA (SRSAVE, scmb [card1].saved_srn, 8), REG_HRO },
|
||||
|
||||
{ FLDATA (SIOBSY, scmb [card1].sio_busy, 0) },
|
||||
{ FLDATA (CHANSR, scmb [card1].channel_sr, 0) },
|
||||
{ FLDATA (DEVSR, scmb [card1].device_sr, 0) },
|
||||
{ FLDATA (INXFR, scmb [card1].input_xfer, 0) },
|
||||
{ FLDATA (OUTXFR, scmb [card1].output_xfer, 0) },
|
||||
{ FLDATA (SIOBSY, scmb [card1].sio_busy, 0) },
|
||||
{ FLDATA (CHANSR, scmb [card1].channel_sr, 0) },
|
||||
{ FLDATA (DEVSR, scmb [card1].device_sr, 0) },
|
||||
{ FLDATA (INXFR, scmb [card1].input_xfer, 0) },
|
||||
{ FLDATA (OUTXFR, scmb [card1].output_xfer, 0) },
|
||||
|
||||
{ FLDATA (JMPMET, scmb [card1].jump_met, 0) },
|
||||
{ FLDATA (XFRERR, scmb [card1].flags, 11) },
|
||||
{ FLDATA (EOT, scmb [card1].flags, 8) },
|
||||
{ FLDATA (TRMCNT, scmb [card1].flags, 6) },
|
||||
{ FLDATA (MISCMP, scmb [card1].flags, 7) },
|
||||
{ FLDATA (DEVEND, scmb [card1].device_end, 0) },
|
||||
{ FLDATA (STOP, scmb [card1].stop_transfer, 0) },
|
||||
{ FLDATA (JMPMET, scmb [card1].jump_met, 0) },
|
||||
{ FLDATA (XFRERR, scmb [card1].flags, 11) },
|
||||
{ FLDATA (EOT, scmb [card1].flags, 8) },
|
||||
{ FLDATA (TRMCNT, scmb [card1].flags, 6) },
|
||||
{ FLDATA (MISCMP, scmb [card1].flags, 7) },
|
||||
{ FLDATA (DEVEND, scmb [card1].device_end, 0) },
|
||||
{ FLDATA (STOP, scmb [card1].stop_transfer, 0) },
|
||||
|
||||
{ SRDATA (DIB, scmb_dib [card1]), REG_HRO },
|
||||
{ SRDATA (DIB, scmb_dib [card1], REG_HRO) },
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static REG scmb2_reg [] = {
|
||||
/* Macro Name Location Width Offset Flags */
|
||||
/* ------ ------ -------------------------- ----- ------ ----------------- */
|
||||
{ ORDATA (CNTL, scmb [card2].control_word, 16), REG_FIT },
|
||||
{ ORDATA (STAT, scmb [card2].status_word, 16), REG_FIT },
|
||||
{ ORDATA (CNTR, scmb [card2].counter, 16), REG_FIT },
|
||||
{ ORDATA (SRSAVE, scmb [card2].saved_srn, 8), REG_HRO },
|
||||
/* Macro Name Location Width Offset Flags */
|
||||
/* ------ ------ -------------------------- ----- ------ ----------------- */
|
||||
{ ORDATA (CNTL, scmb [card2].control_word, 16), REG_FIT },
|
||||
{ ORDATA (STAT, scmb [card2].status_word, 16), REG_FIT },
|
||||
{ ORDATA (CNTR, scmb [card2].counter, 16), REG_FIT },
|
||||
{ ORDATA (SRSAVE, scmb [card2].saved_srn, 8), REG_HRO },
|
||||
|
||||
{ FLDATA (SIOBSY, scmb [card2].sio_busy, 0) },
|
||||
{ FLDATA (CHANSR, scmb [card2].channel_sr, 0) },
|
||||
{ FLDATA (DEVSR, scmb [card2].device_sr, 0) },
|
||||
{ FLDATA (INXFR, scmb [card2].input_xfer, 0) },
|
||||
{ FLDATA (OUTXFR, scmb [card2].output_xfer, 0) },
|
||||
{ FLDATA (SIOBSY, scmb [card2].sio_busy, 0) },
|
||||
{ FLDATA (CHANSR, scmb [card2].channel_sr, 0) },
|
||||
{ FLDATA (DEVSR, scmb [card2].device_sr, 0) },
|
||||
{ FLDATA (INXFR, scmb [card2].input_xfer, 0) },
|
||||
{ FLDATA (OUTXFR, scmb [card2].output_xfer, 0) },
|
||||
|
||||
{ FLDATA (JMPMET, scmb [card2].jump_met, 0) },
|
||||
{ FLDATA (XFRERR, scmb [card2].flags, 11) },
|
||||
{ FLDATA (EOT, scmb [card2].flags, 8) },
|
||||
{ FLDATA (TRMCNT, scmb [card2].flags, 6) },
|
||||
{ FLDATA (MISCMP, scmb [card2].flags, 7) },
|
||||
{ FLDATA (DEVEND, scmb [card2].device_end, 0) },
|
||||
{ FLDATA (STOP, scmb [card2].stop_transfer, 0) },
|
||||
{ FLDATA (JMPMET, scmb [card2].jump_met, 0) },
|
||||
{ FLDATA (XFRERR, scmb [card2].flags, 11) },
|
||||
{ FLDATA (EOT, scmb [card2].flags, 8) },
|
||||
{ FLDATA (TRMCNT, scmb [card2].flags, 6) },
|
||||
{ FLDATA (MISCMP, scmb [card2].flags, 7) },
|
||||
{ FLDATA (DEVEND, scmb [card2].device_end, 0) },
|
||||
{ FLDATA (STOP, scmb [card2].stop_transfer, 0) },
|
||||
|
||||
{ SRDATA (DIB, scmb_dib [card1]), REG_HRO },
|
||||
{ SRDATA (DIB, scmb_dib [card1], REG_HRO) },
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
@ -694,15 +696,15 @@ DEVICE scmb_dev [] = {
|
|||
use the DIB field to obtain the device number.
|
||||
*/
|
||||
|
||||
static SIGNALS_DATA scmb_interface (DIB *dibptr, INBOUND_SET inbound_signals, uint16 inbound_value)
|
||||
static SIGNALS_DATA scmb_interface (DIB *dibptr, INBOUND_SET inbound_signals, HP_WORD inbound_value)
|
||||
{
|
||||
const CARD_ID card = (CARD_ID) (dibptr->card_index); /* the ID number of the card */
|
||||
LOAD_OP load_operation;
|
||||
FLIP_FLOP assert_sr;
|
||||
uint16 saved_devno;
|
||||
HP_WORD saved_devno;
|
||||
INBOUND_SIGNAL signal;
|
||||
INBOUND_SET working_set = inbound_signals;
|
||||
uint16 outbound_value = 0;
|
||||
HP_WORD outbound_value = 0;
|
||||
OUTBOUND_SET outbound_signals = NO_SIGNALS;
|
||||
|
||||
dprintf (scmb_dev [card], DEB_IOB, "Received data %06o with signals %s\n",
|
||||
|
@ -875,7 +877,7 @@ while (working_set) { /* while there are signa
|
|||
scmb [card].flags &= ~ST_EOT; /* then clear the EOT flag */
|
||||
|
||||
scmb [card].device_end = /* set or clear device end status depending on */
|
||||
(scmb [card].control_word & CN_DEVEND) != 0; /* whether an immediate device end is enabled */
|
||||
D_FF (scmb [card].control_word & CN_DEVEND); /* whether an immediate device end is enabled */
|
||||
}
|
||||
|
||||
scmb [card].device_sr = SET; /* preset the device SR flip-flop */
|
||||
|
@ -892,7 +894,7 @@ while (working_set) { /* while there are signa
|
|||
scmb [card].flags &= ~ST_EOT; /* then clear the EOT flag */
|
||||
|
||||
scmb [card].device_end = /* set or clear device end status depending on */
|
||||
(scmb [card].control_word & CN_DEVEND) != 0; /* whether an immediate device end is enabled */
|
||||
D_FF (scmb [card].control_word & CN_DEVEND); /* whether an immediate device end is enabled */
|
||||
}
|
||||
|
||||
scmb [card].device_sr = SET; /* preset the device SR flip-flop */
|
||||
|
@ -1029,19 +1031,20 @@ if (scmb [card].flags & END_CONDITION) /* if a termination cond
|
|||
outbound_signals |= INTREQ; /* and request the interrupt */
|
||||
}
|
||||
|
||||
if (scmb [card].control_word & CN_HSREQ) /* if high-speed requests are enabled */
|
||||
assert_sr = scmb [card].channel_sr | scmb [card].device_sr; /* then assert SR immediately if indicated */
|
||||
if (scmb [card].control_word & CN_HSREQ) /* if high-speed requests are enabled */
|
||||
assert_sr = D_FF (scmb [card].channel_sr /* then assert SR immediately if indicated */
|
||||
| scmb [card].device_sr);
|
||||
|
||||
else { /* otherwise assert SR immediately */
|
||||
assert_sr = scmb [card].channel_sr; /* only if the channel is requesting service */
|
||||
else { /* otherwise assert SR immediately */
|
||||
assert_sr = scmb [card].channel_sr; /* only if the channel is requesting service */
|
||||
|
||||
if ((! assert_sr & scmb [card].device_sr) /* if a delayed device SR assertion is requested */
|
||||
&& (MPX_BUS (card) || outbound_signals & CHANACK) /* and we're on the MPX bus or CHANACK is not inhibited */
|
||||
&& (scmb [card].control_word & CN_NOSR) == 0) { /* and channel service is not inhibited */
|
||||
sim_activate (&scmb_unit [card], /* then schedule SR assertion in 5 microseconds */
|
||||
if ((! assert_sr & scmb [card].device_sr) /* if a delayed device SR assertion is requested */
|
||||
&& (MPX_BUS (card) || outbound_signals & CHANACK) /* and we're on the MPX bus or CHANACK is not inhibited */
|
||||
&& (scmb [card].control_word & CN_NOSR) == 0) { /* and channel service is not inhibited */
|
||||
sim_activate (&scmb_unit [card], /* then schedule SR assertion in 5 microseconds */
|
||||
scmb_unit [card].wait);
|
||||
|
||||
dprintf (scmb_dev [card], DEB_SERV, "Delay %d SR service scheduled\n",
|
||||
dprintf (scmb_dev [card], DEB_SERV, "Delay %u SR service scheduled\n",
|
||||
scmb_unit [card].wait);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,10 @@
|
|||
|
||||
SEL HP 3000 Series III Selector Channel
|
||||
|
||||
30-Jun-16 JDB Reestablish active_dib pointer during sel_initialize
|
||||
08-Jun-16 JDB Corrected %d format to %u for unsigned values
|
||||
16-May-16 JDB abort_channel parameter is now a pointer-to-constant
|
||||
21-Mar-16 JDB Changed uint16 types to HP_WORD
|
||||
23-Sep-15 JDB First release version
|
||||
27-Jan-15 JDB Passes the selector channel diagnostic (D429A)
|
||||
10-Feb-13 JDB Created
|
||||
|
@ -327,8 +331,8 @@
|
|||
|
||||
#define CYCLES_PER_EVENT (uint32) (USEC_PER_EVENT * 1000 / NS_PER_CYCLE)
|
||||
|
||||
#define CNTR_MASK 0007777 /* word counter count mask */
|
||||
#define CNTR_MAX 0007777 /* word counter maximum value */
|
||||
#define CNTR_MASK 0007777u /* word counter count mask */
|
||||
#define CNTR_MAX 0007777u /* word counter maximum value */
|
||||
|
||||
|
||||
typedef enum { /* selector channel sequencer state */
|
||||
|
@ -367,10 +371,10 @@ static const char *const action_name [] = { /* indexed by SEQ_STATE */
|
|||
1. Bit 0 is reserved for the memory data trace flag.
|
||||
*/
|
||||
|
||||
#define DEB_CSRW (1 << 1) /* trace channel command initiations and completions */
|
||||
#define DEB_PIO (1 << 2) /* trace programmed I/O commands */
|
||||
#define DEB_STATE (1 << 3) /* trace state changes */
|
||||
#define DEB_SR (1 << 4) /* trace service requests */
|
||||
#define DEB_CSRW (1u << 1) /* trace channel command initiations and completions */
|
||||
#define DEB_PIO (1u << 2) /* trace programmed I/O commands */
|
||||
#define DEB_STATE (1u << 3) /* trace state changes */
|
||||
#define DEB_SR (1u << 4) /* trace service requests */
|
||||
|
||||
|
||||
/* Channel global state */
|
||||
|
@ -384,6 +388,7 @@ t_bool sel_request = FALSE; /* TRUE if the channel sequencer
|
|||
static SEQ_STATE sequencer = Idle_Sequence; /* the current sequencer execution state */
|
||||
static SIO_ORDER order; /* the current SIO order */
|
||||
static DIB *active_dib; /* a pointer to the participating interface's DIB */
|
||||
static uint32 device_index; /* the index into the device table */
|
||||
static t_bool prefetch_control; /* TRUE if the IOCW should be prefetched */
|
||||
static t_bool prefetch_address; /* TRUE if the IOAW should be prefetched */
|
||||
|
||||
|
@ -410,10 +415,10 @@ static t_stat sel_reset (DEVICE *dptr);
|
|||
|
||||
/* Channel local utility routines */
|
||||
|
||||
static void end_channel (DIB *dibptr);
|
||||
static SIGNALS_DATA abort_channel (char *reason);
|
||||
static void load_control (HP_WORD *value);
|
||||
static void load_address (HP_WORD *value);
|
||||
static void end_channel (DIB *dibptr);
|
||||
static SIGNALS_DATA abort_channel (const char *reason);
|
||||
static void load_control (HP_WORD *value);
|
||||
static void load_address (HP_WORD *value);
|
||||
|
||||
|
||||
/* Channel SCP data structures */
|
||||
|
@ -428,30 +433,30 @@ static UNIT sel_unit = {
|
|||
/* Register list */
|
||||
|
||||
static REG sel_reg [] = {
|
||||
/* Macro Name Location Width Offset Flags */
|
||||
/* ------ ------ --------------- ----- ------ --------------- */
|
||||
{ FLDATA (IDLE, sel_is_idle, 0) },
|
||||
{ FLDATA (SREQ, sel_request, 0) },
|
||||
{ DRDATA (DEVNO, device_number, 8), PV_LEFT },
|
||||
{ DRDATA (EXCESS, excess_cycles, 32), PV_LEFT },
|
||||
{ ORDATA (DIB, active_dib, 32), REG_HRO },
|
||||
/* Macro Name Location Width Offset Flags */
|
||||
/* ------ ------ --------------- ----- ------ ----------------- */
|
||||
{ FLDATA (IDLE, sel_is_idle, 0) },
|
||||
{ FLDATA (SREQ, sel_request, 0) },
|
||||
{ DRDATA (DEVNO, device_number, 8), PV_LEFT },
|
||||
{ DRDATA (EXCESS, excess_cycles, 32), PV_LEFT },
|
||||
{ DRDATA (INDEX, device_index, 32), PV_LEFT | REG_HRO },
|
||||
|
||||
{ DRDATA (SEQ, sequencer, 3) },
|
||||
{ ORDATA (ORDER, order, 4) },
|
||||
{ FLDATA (ROLOVR, rollover, 0) },
|
||||
{ FLDATA (PFCNTL, prefetch_control, 0) },
|
||||
{ FLDATA (PFADDR, prefetch_address, 0) },
|
||||
{ DRDATA (SEQ, sequencer, 3) },
|
||||
{ ORDATA (ORDER, order, 4) },
|
||||
{ FLDATA (ROLOVR, rollover, 0) },
|
||||
{ FLDATA (PFCNTL, prefetch_control, 0) },
|
||||
{ FLDATA (PFADDR, prefetch_address, 0) },
|
||||
|
||||
{ ORDATA (BANK, bank, 4), PV_LEFT },
|
||||
{ DRDATA (WCOUNT, word_count, 12) },
|
||||
{ ORDATA (BANK, bank, 4), PV_LEFT },
|
||||
{ DRDATA (WCOUNT, word_count, 12) },
|
||||
|
||||
{ ORDATA (PCNTR, program_counter, 16), REG_FIT },
|
||||
{ ORDATA (CNTL, control_word, 16), REG_FIT },
|
||||
{ ORDATA (CNBUF, control_buffer, 16), REG_FIT },
|
||||
{ ORDATA (ADDR, address_word, 16), REG_FIT },
|
||||
{ ORDATA (ADBUF, address_buffer, 16), REG_FIT },
|
||||
{ ORDATA (INBUF, input_buffer, 16), REG_A | REG_FIT },
|
||||
{ ORDATA (OUTBUF, output_buffer, 16), REG_A | REG_FIT },
|
||||
{ ORDATA (PCNTR, program_counter, 16), REG_FIT },
|
||||
{ ORDATA (CNTL, control_word, 16), REG_FIT },
|
||||
{ ORDATA (CNBUF, control_buffer, 16), REG_FIT },
|
||||
{ ORDATA (ADDR, address_word, 16), REG_FIT },
|
||||
{ ORDATA (ADBUF, address_buffer, 16), REG_FIT },
|
||||
{ ORDATA (INBUF, input_buffer, 16), REG_A | REG_FIT },
|
||||
{ ORDATA (OUTBUF, output_buffer, 16), REG_A | REG_FIT },
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
@ -509,7 +514,10 @@ DEVICE sel_dev = {
|
|||
|
||||
Implementation notes:
|
||||
|
||||
1. In simulation, we allow the device number to be changed during a
|
||||
1. The active DIB pointer is restored from the device context to support
|
||||
resuming after a SAVE and RESTORE is performed.
|
||||
|
||||
2. In simulation, we allow the device number to be changed during a
|
||||
simulation stop, so this routine must recover it from the device.
|
||||
Normally, the device number register would be reset from the device
|
||||
number field in the DIB. However, the SCMB may be spoofing the device
|
||||
|
@ -526,7 +534,9 @@ void sel_initialize (void)
|
|||
SIGNALS_DATA outbound;
|
||||
|
||||
if (sel_is_idle == FALSE) { /* if the channel is controlling a device */
|
||||
outbound = active_dib->io_interface (active_dib, DEVNODB, 0); /* then see if it responds to DEVNODB */
|
||||
active_dib = (DIB *) sim_devices [device_index]->ctxt; /* then restore the active DIB pointer */
|
||||
|
||||
outbound = active_dib->io_interface (active_dib, DEVNODB, 0); /* see if the device responds to DEVNODB */
|
||||
|
||||
if (IODATA (outbound) > 0) /* if it does (e.g., the SCMB) */
|
||||
device_number = IODATA (outbound) / 4; /* then use the returned device number */
|
||||
|
@ -568,7 +578,7 @@ return;
|
|||
void sel_assert_REQ (DIB *dibptr)
|
||||
{
|
||||
if (sel_is_idle) { /* if the channel is idle then set it up */
|
||||
dprintf (sel_dev, DEB_CSRW, "Device number %d asserted REQ for channel initialization\n",
|
||||
dprintf (sel_dev, DEB_CSRW, "Device number %u asserted REQ for channel initialization\n",
|
||||
dibptr->device_number);
|
||||
|
||||
sel_is_idle = FALSE; /* the channel is now busy */
|
||||
|
@ -581,6 +591,11 @@ if (sel_is_idle) { /* if the channel is idl
|
|||
rollover = CLEAR; /* and the word count rollover flip-flop */
|
||||
excess_cycles = 0; /* clear the excess cycle count */
|
||||
|
||||
device_index = 0; /* find the device index */
|
||||
/* corresponding to */
|
||||
while ((DIB *) sim_devices [device_index]->ctxt != dibptr) /* the active DIB pointer */
|
||||
device_index = device_index + 1; /* to aid later restoration */
|
||||
|
||||
active_dib = dibptr; /* save the interface's DIB pointer */
|
||||
device_number = dibptr->device_number; /* and set the device number register */
|
||||
|
||||
|
@ -589,7 +604,7 @@ if (sel_is_idle) { /* if the channel is idl
|
|||
}
|
||||
|
||||
else { /* otherwise abort the transfer in progress */
|
||||
dprintf (sel_dev, DEB_CSRW, "Device number %d asserted REQ for channel abort\n",
|
||||
dprintf (sel_dev, DEB_CSRW, "Device number %u asserted REQ for channel abort\n",
|
||||
device_number);
|
||||
|
||||
end_channel (dibptr); /* idle the channel */
|
||||
|
@ -616,7 +631,7 @@ return;
|
|||
|
||||
void sel_assert_CHANSR (DIB *dibptr)
|
||||
{
|
||||
dprintf (sel_dev, DEB_SR, "Device number %d asserted CHANSR\n",
|
||||
dprintf (sel_dev, DEB_SR, "Device number %u asserted CHANSR\n",
|
||||
device_number);
|
||||
|
||||
dibptr->service_request = TRUE; /* set the service request flag in the interface */
|
||||
|
@ -780,7 +795,7 @@ return;
|
|||
|
||||
void sel_service (uint32 ticks_elapsed)
|
||||
{
|
||||
uint16 inbound_data, outbound_data;
|
||||
HP_WORD inbound_data, outbound_data;
|
||||
INBOUND_SET inbound_signals;
|
||||
SIGNALS_DATA outbound;
|
||||
int32 cycles;
|
||||
|
@ -888,7 +903,7 @@ while (sel_request && cycles > 0) { /* execute as long as a
|
|||
control_word);
|
||||
|
||||
if ((outbound & CHANACK) == NO_SIGNALS) { /* if CHANACK was not returned */
|
||||
dprintf (sel_dev, DEB_SR, "Device number %d CHANACK timeout\n",
|
||||
dprintf (sel_dev, DEB_SR, "Device number %u CHANACK timeout\n",
|
||||
device_number);
|
||||
|
||||
end_channel (active_dib); /* terminate the channel program */
|
||||
|
@ -1267,7 +1282,7 @@ return;
|
|||
to complete the abort.
|
||||
*/
|
||||
|
||||
static SIGNALS_DATA abort_channel (char *reason)
|
||||
static SIGNALS_DATA abort_channel (const char *reason)
|
||||
{
|
||||
dprintf (sel_dev, DEB_CSRW, "Channel asserted XFERERROR for %s\n",
|
||||
reason);
|
||||
|
|
|
@ -23,7 +23,14 @@
|
|||
in advertising or otherwise to promote the sale, use or other dealings in
|
||||
this Software without prior written authorization from the author.
|
||||
|
||||
21-Jun-16 JDB Changed fprint_instruction mask type from t_value to uint32
|
||||
08-Jun-16 JDB Corrected %d format to %u for unsigned values
|
||||
16-May-16 JDB Prefix in fprint_instruction is now a pointer-to-constant
|
||||
13-May-16 JDB Modified for revised SCP API function parameter types
|
||||
20-Apr-16 JDB Added implementation notes to "fmt_bitset"
|
||||
14-Apr-16 JDB Fixed INTMASK setting and display
|
||||
24-Mar-16 JDB Added the LP device
|
||||
21-Mar-16 JDB Changed uint16 types to HP_WORD
|
||||
23-Nov-15 JDB First release version
|
||||
11-Dec-12 JDB Created
|
||||
|
||||
|
@ -63,6 +70,7 @@ extern DEVICE scmb_dev [2]; /* Selector Channel Maintenance
|
|||
extern DEVICE atcd_dev; /* Asynchronous Terminal Controller TDI */
|
||||
extern DEVICE atcc_dev; /* Asynchronous Terminal Controller TCI */
|
||||
extern DEVICE clk_dev; /* System Clock */
|
||||
extern DEVICE lp_dev; /* Line Printer */
|
||||
extern DEVICE ds_dev; /* 79xx MAC Disc */
|
||||
extern DEVICE ms_dev; /* 7970 Magnetic Tape */
|
||||
|
||||
|
@ -758,7 +766,7 @@ static t_stat hp_brk_cmd (int32 arg, CONST char *buf);
|
|||
static void 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_instruction (FILE *ofile, const OP_TABLE ops, t_value *instruction,
|
||||
t_value mask, uint32 shift, uint32 radix);
|
||||
uint32 mask, uint32 shift, uint32 radix);
|
||||
|
||||
static t_stat parse_cpu (CONST char *cptr, t_addr address, UNIT *uptr, t_value *value, int32 switches);
|
||||
|
||||
|
@ -773,10 +781,10 @@ static APC_FLAGS parse_config = apcNone; /* address parser configuration
|
|||
|
||||
/* System interface global data structures */
|
||||
|
||||
#define E 0400 /* parity bit for even parity */
|
||||
#define O 0000 /* parity bit for odd parity */
|
||||
#define E 0400u /* parity bit for even parity */
|
||||
#define O 0000u /* parity bit for odd parity */
|
||||
|
||||
const uint16 odd_parity [256] = { /* odd parity table */
|
||||
const HP_WORD odd_parity [256] = { /* odd parity table */
|
||||
E, O, O, E, O, E, E, O, O, E, E, O, E, O, O, E, /* 000-017 */
|
||||
O, E, E, O, E, O, O, E, E, O, O, E, O, E, E, O, /* 020-037 */
|
||||
O, E, E, O, E, O, O, E, E, O, O, E, O, E, E, O, /* 040-067 */
|
||||
|
@ -861,6 +869,7 @@ DEVICE *sim_devices [] = { /* an array of pointers to the s
|
|||
&scmb_dev [0], &scmb_dev [1], /* Selector Channel Maintenance Boards */
|
||||
&atcd_dev, &atcc_dev, /* Asynchronous Terminal Controller (TDI and TCI) */
|
||||
&clk_dev, /* System Clock */
|
||||
&lp_dev, /* Line Printer */
|
||||
&ds_dev, /* 7905/06/20/25 MAC Disc Interface */
|
||||
&ms_dev, /* 7970B/E Magnetic Tape Interface */
|
||||
NULL /* end of the device list */
|
||||
|
@ -1041,7 +1050,7 @@ uint32 radix_override;
|
|||
|
||||
if (sw & SWMASK ('A') && (!is_reg || addr & REG_A)) /* if ASCII character display is requested and permitted */
|
||||
if (val [0] <= D8_SMAX) { /* then if the value is a single character */
|
||||
fputs (fmt_char (val [0]), ofile); /* then format and print it */
|
||||
fputs (fmt_char ((uint32) val [0]), ofile); /* then format and print it */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -1212,8 +1221,8 @@ else /* otherwise */
|
|||
Implementation notes:
|
||||
|
||||
1. For a numeric interrupt mask entry value <n>, the value stored in the DIB
|
||||
is 2^<n>. For mask entry values "D" and "E", the stored values are 0 and
|
||||
0177777, respectively.
|
||||
is 2 ^ <15 - n> to match the HP 3000 bit numbering. For mask entry
|
||||
values "D" and "E", the stored values are 0 and 0177777, respectively.
|
||||
|
||||
2. The SCMB is the only device that may or may not have a service request
|
||||
number, depending on whether or not it is connected to the multiplexer
|
||||
|
@ -1252,8 +1261,8 @@ else /* otherwise a value is
|
|||
value = get_uint (cptr, INTMASK_BASE, /* parse the supplied numeric mask value */
|
||||
INTMASK_MAX, &status);
|
||||
|
||||
if (status == SCPE_OK) /* if it is valid */
|
||||
dibptr->interrupt_mask = 1 << value; /* then set the corresponding mask bit in the DIB */
|
||||
if (status == SCPE_OK) /* if it is valid */
|
||||
dibptr->interrupt_mask = D16_SIGN >> value; /* then set the corresponding mask bit in the DIB */
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1308,8 +1317,8 @@ return status; /* return the validation
|
|||
Implementation notes:
|
||||
|
||||
1. For a numeric interrupt mask entry value <n>, the value stored in the DIB
|
||||
is 2^<n>. For mask entry values "D" and "E", the stored values are 0 and
|
||||
0177777, respectively.
|
||||
is 2 ^ <15 - n> to match the HP 3000 bit numbering. For mask entry
|
||||
values "D" and "E", the stored values are 0 and 0177777, respectively.
|
||||
*/
|
||||
|
||||
t_stat hp_show_dib (FILE *st, UNIT *uptr, int32 code, CONST void *desc)
|
||||
|
@ -1320,7 +1329,7 @@ uint32 mask, value;
|
|||
switch (code) { /* display the requested value */
|
||||
|
||||
case VAL_DEVNO: /* show the device number */
|
||||
fprintf (st, "DEVNO=%d", dibptr->device_number);
|
||||
fprintf (st, "DEVNO=%u", dibptr->device_number);
|
||||
break;
|
||||
|
||||
case VAL_INTMASK: /* show the interrupt mask */
|
||||
|
@ -1335,22 +1344,22 @@ switch (code) { /* display the requested
|
|||
else { /* otherwise */
|
||||
mask = dibptr->interrupt_mask; /* display a specific mask value */
|
||||
|
||||
for (value = 0; !(mask & 1); value++) /* count the number of mask bit shifts */
|
||||
mask = mask >> 1; /* until the correct one is found */
|
||||
for (value = 0; !(mask & D16_SIGN); value++) /* count the number of mask bit shifts */
|
||||
mask = mask << 1; /* until the correct one is found */
|
||||
|
||||
fprintf (st, "%d", value); /* display the mask bit number */
|
||||
fprintf (st, "%u", value); /* display the mask bit number */
|
||||
}
|
||||
break;
|
||||
|
||||
case VAL_INTPRI: /* show the interrupt priority */
|
||||
fprintf (st, "INTPRI=%d", dibptr->interrupt_priority);
|
||||
fprintf (st, "INTPRI=%u", dibptr->interrupt_priority);
|
||||
break;
|
||||
|
||||
case VAL_SRNO: /* show the service request number */
|
||||
if (dibptr->service_request_number == SRNO_UNUSED) /* if the current setting is "unused" */
|
||||
fprintf (st, "SRNO not used"); /* then report it */
|
||||
else /* otherwise report the SR number */
|
||||
fprintf (st, "SRNO=%d", dibptr->service_request_number);
|
||||
fprintf (st, "SRNO=%u", dibptr->service_request_number);
|
||||
break;
|
||||
|
||||
default: /* if an illegal code was passed */
|
||||
|
@ -1502,7 +1511,7 @@ for (conf = Device; conf <= Service; conf++) { /* check for conflicts f
|
|||
if (conflicts [val] > 1) { /* if a conflict is present for this value */
|
||||
count = conflicts [val]; /* then get the number of conflicting devices */
|
||||
|
||||
cprintf ("%s %d conflict (", conflict_label [conf], val);
|
||||
cprintf ("%s %u conflict (", conflict_label [conf], val);
|
||||
|
||||
dev = 0; /* search for the devices that conflict */
|
||||
|
||||
|
@ -1784,6 +1793,20 @@ else { /* otherwise it's a prin
|
|||
Processing continues until there are no remaining significant bits (if no
|
||||
alternates are specified), or until there are no remaining names in the array
|
||||
(if alternates are specified).
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. The routine returns a pointer to a static buffer containing the printable
|
||||
string, so it cannot be called more than once per trace line, unless the
|
||||
buffer contents are copied upon return. In particular, this type of
|
||||
calling sequence:
|
||||
|
||||
dprintf (..., fmt_bitset (...), ..., fmt_bitset (...), ...);
|
||||
|
||||
...will fail, as the buffer will be overwritten by the second call before
|
||||
the result of the first call is printed.
|
||||
|
||||
*/
|
||||
|
||||
const char *fmt_bitset (uint32 bitset, const BITSET_FORMAT bitfmt)
|
||||
|
@ -2042,7 +2065,7 @@ else if (reason == STOP_CDUMP) { /* otherwise if this is
|
|||
}
|
||||
|
||||
else if (reason == STOP_SYSHALT) { /* otherwise if this is a system halt stop */
|
||||
fprintf (st, " %d", RA); /* then print the halt reason */
|
||||
fprintf (st, " %u", RA); /* then print the halt reason */
|
||||
return TRUE; /* and return TRUE to append the program counter */
|
||||
}
|
||||
|
||||
|
@ -2207,7 +2230,7 @@ static t_stat hp_cold_cmd (int32 arg, CONST char *buf)
|
|||
const char *cptr;
|
||||
char gbuf [CBUFSIZE];
|
||||
t_stat status;
|
||||
t_value value;
|
||||
HP_WORD value;
|
||||
|
||||
if (*buf != '\0') { /* if more characters exist on the command line */
|
||||
cptr = get_glyph (buf, gbuf, 0); /* then get the next glyph */
|
||||
|
@ -2215,8 +2238,8 @@ if (*buf != '\0') { /* if more characters ex
|
|||
if (*cptr != '\0') /* if that does not exhaust the input */
|
||||
return SCPE_2MARG; /* then report that there are too many arguments */
|
||||
|
||||
value = get_uint (gbuf, cpu_dev.dradix, /* get the parameter value */
|
||||
D16_UMAX, &status);
|
||||
value = (HP_WORD) get_uint (gbuf, cpu_dev.dradix, /* get the parameter value */
|
||||
D16_UMAX, &status);
|
||||
|
||||
if (status == SCPE_OK) /* if a valid number was present */
|
||||
SWCH = value; /* then set it into the switch register */
|
||||
|
@ -2224,7 +2247,7 @@ if (*buf != '\0') { /* if more characters ex
|
|||
return status; /* return the error status */
|
||||
}
|
||||
|
||||
cpu_front_panel (SWCH, arg); /* set up the cold load or dump microcode */
|
||||
cpu_front_panel (SWCH, (PANEL_TYPE) arg); /* set up the cold load or dump microcode */
|
||||
|
||||
return run_cmd (RU_RUN, ""); /* reset and execute the halt-mode routine */
|
||||
}
|
||||
|
@ -2596,17 +2619,17 @@ static const char *const register_name [] = { /* PSHR/SETR register names corr
|
|||
};
|
||||
|
||||
static t_stat fprint_instruction (FILE *ofile, const OP_TABLE ops, t_value *instruction,
|
||||
t_value mask, uint32 shift, uint32 radix)
|
||||
uint32 mask, uint32 shift, uint32 radix)
|
||||
{
|
||||
uint32 op_index, op_radix;
|
||||
int32 reg_index;
|
||||
t_bool reg_first;
|
||||
t_value op_value;
|
||||
char *prefix = NULL; /* base register label to print before the operand */
|
||||
t_bool index = FALSE; /* TRUE if the instruction is indexed */
|
||||
t_bool indirect = FALSE; /* TRUE if the instruction is indirect */
|
||||
uint32 op_index, op_radix;
|
||||
int32 reg_index;
|
||||
t_bool reg_first;
|
||||
t_value op_value;
|
||||
const char *prefix = NULL; /* base register label to print before the operand */
|
||||
t_bool index = FALSE; /* TRUE if the instruction is indexed */
|
||||
t_bool indirect = FALSE; /* TRUE if the instruction is indirect */
|
||||
|
||||
op_index = (instruction [0] & mask) >> shift; /* extract the opcode index */
|
||||
op_index = ((uint32) instruction [0] & mask) >> shift; /* extract the opcode index */
|
||||
|
||||
if (ops [op_index].mnemonic [0]) /* if a primary entry is defined */
|
||||
fputs (ops [op_index].mnemonic, ofile); /* then print the mnemonic */
|
||||
|
|
|
@ -24,7 +24,13 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from the authors.
|
||||
|
||||
09-Jun-16 JDB Added casts for ptrdiff_t to int32 values
|
||||
08-Jun-16 JDB Corrected %d format to %u for unsigned values
|
||||
16-May-16 JDB DRIVE_PROPS.name is now a pointer-to-constant
|
||||
13-May-16 JDB Modified for revised SCP API function parameter types
|
||||
03-May-16 JDB Added a trace to identify the unit requesting attention
|
||||
24-Mar-16 JDB Changed the buffer element type from uint16 to DL_BUFFER
|
||||
21-Mar-16 JDB Changed uint16 types to HP_WORD
|
||||
27-Jul-15 JDB First revised release version
|
||||
21-Feb-15 JDB Revised for new controller interface model
|
||||
24-Dec-14 JDB Added casts for explicit downward conversions
|
||||
|
@ -391,7 +397,7 @@
|
|||
|
||||
/* Unit flags accessor */
|
||||
|
||||
#define GET_MODEL(f) (((f) >> UNIT_MODEL_SHIFT) & UNIT_MODEL_MASK)
|
||||
#define GET_MODEL(f) (DRIVE_TYPE) ((f) >> UNIT_MODEL_SHIFT & UNIT_MODEL_MASK)
|
||||
|
||||
|
||||
/* Controller clear types */
|
||||
|
@ -453,24 +459,24 @@ typedef enum {
|
|||
Form 6 is used by the Cold Load Read command.
|
||||
*/
|
||||
|
||||
#define CM_OPCODE_MASK 0017400 /* operation code mask */
|
||||
#define CM_UNIT_MASK 0000017 /* unit number mask */
|
||||
#define CM_OPCODE_MASK 0017400u /* operation code mask */
|
||||
#define CM_UNIT_MASK 0000017u /* unit number mask */
|
||||
|
||||
#define CM_SPARE 0100000 /* spare track */
|
||||
#define CM_PROTECTED 0040000 /* protected track */
|
||||
#define CM_DEFECTIVE 0020000 /* defective track */
|
||||
#define CM_SPARE 0100000u /* spare track */
|
||||
#define CM_PROTECTED 0040000u /* protected track */
|
||||
#define CM_DEFECTIVE 0020000u /* defective track */
|
||||
#define CM_SPD_MASK (CM_SPARE | CM_PROTECTED | CM_DEFECTIVE)
|
||||
|
||||
#define CM_RETRY_MASK 0000360 /* retry count mask */
|
||||
#define CM_FILE_MASK_MASK 0000017 /* file mask mask */
|
||||
#define CM_RETRY_MASK 0000360u /* retry count mask */
|
||||
#define CM_FILE_MASK_MASK 0000017u /* file mask mask */
|
||||
|
||||
#define CM_DECR_SEEK 0000010 /* 0/1 = incremental/decremental seek */
|
||||
#define CM_SPARE_EN 0000004 /* sparing enabled */
|
||||
#define CM_CYL_MODE 0000002 /* 0/1 = surface/cylinder mode */
|
||||
#define CM_AUTO_SEEK_EN 0000001 /* auto-seek enabled */
|
||||
#define CM_DECR_SEEK 0000010u /* 0/1 = incremental/decremental seek */
|
||||
#define CM_SPARE_EN 0000004u /* sparing enabled */
|
||||
#define CM_CYL_MODE 0000002u /* 0/1 = surface/cylinder mode */
|
||||
#define CM_AUTO_SEEK_EN 0000001u /* auto-seek enabled */
|
||||
|
||||
#define CM_HEAD_MASK 0000300 /* cold load read head mask */
|
||||
#define CM_SECTOR_MASK 0000077 /* cold load read sector mask */
|
||||
#define CM_HEAD_MASK 0000300u /* cold load read head mask */
|
||||
#define CM_SECTOR_MASK 0000077u /* cold load read sector mask */
|
||||
|
||||
|
||||
#define CM_OPCODE_SHIFT 8
|
||||
|
@ -485,7 +491,8 @@ typedef enum {
|
|||
|
||||
#define CM_SPD(c) ((c) & CM_SPD_MASK)
|
||||
|
||||
#define CM_OPCODE(c) (((c) & CM_OPCODE_MASK) >> CM_OPCODE_SHIFT)
|
||||
#define CM_OPCODE(c) (CNTLR_OPCODE) (((c) & CM_OPCODE_MASK) >> CM_OPCODE_SHIFT)
|
||||
|
||||
#define CM_UNIT(c) (((c) & CM_UNIT_MASK) >> CM_UNIT_SHIFT)
|
||||
|
||||
#define CM_RETRY(c) (((c) & CM_RETRY_MASK) >> CM_RETRY_SHIFT)
|
||||
|
@ -572,11 +579,11 @@ static const BITSET_FORMAT file_mask_format = /* names, offset, direction,
|
|||
S = sign of cylinder offset
|
||||
*/
|
||||
|
||||
#define S1_SPARE 0100000 /* spare track */
|
||||
#define S1_PROTECTED 0040000 /* protected track */
|
||||
#define S1_DEFECTIVE 0020000 /* defective track */
|
||||
#define S1_STATUS_MASK 0017400 /* encoded termination status mask */
|
||||
#define S1_UNIT_MASK 0000017 /* unit number mask */
|
||||
#define S1_SPARE 0100000u /* spare track */
|
||||
#define S1_PROTECTED 0040000u /* protected track */
|
||||
#define S1_DEFECTIVE 0020000u /* defective track */
|
||||
#define S1_STATUS_MASK 0017400u /* encoded termination status mask */
|
||||
#define S1_UNIT_MASK 0000017u /* unit number mask */
|
||||
|
||||
#define S1_STATUS_SHIFT 8
|
||||
#define S1_UNIT_SHIFT 0
|
||||
|
@ -585,16 +592,16 @@ static const BITSET_FORMAT file_mask_format = /* names, offset, direction,
|
|||
#define S1_UNIT(n) ((n) << S1_UNIT_SHIFT & S1_UNIT_MASK)
|
||||
|
||||
|
||||
#define S2_ERROR 0100000 /* any error */
|
||||
#define S2_DRIVE_TYPE_MASK 0017000 /* drive type mask */
|
||||
#define S2_ATTENTION 0000200 /* attention */
|
||||
#define S2_READ_ONLY 0000100 /* read-only */
|
||||
#define S2_FORMAT_EN 0000040 /* format enabled */
|
||||
#define S2_FAULT 0000020 /* drive fault */
|
||||
#define S2_FIRST_STATUS 0000010 /* first status */
|
||||
#define S2_SEEK_CHECK 0000004 /* seek check */
|
||||
#define S2_NOT_READY 0000002 /* not ready */
|
||||
#define S2_BUSY 0000001 /* drive busy */
|
||||
#define S2_ERROR 0100000u /* any error */
|
||||
#define S2_DRIVE_TYPE_MASK 0017000u /* drive type mask */
|
||||
#define S2_ATTENTION 0000200u /* attention */
|
||||
#define S2_READ_ONLY 0000100u /* read-only */
|
||||
#define S2_FORMAT_EN 0000040u /* format enabled */
|
||||
#define S2_FAULT 0000020u /* drive fault */
|
||||
#define S2_FIRST_STATUS 0000010u /* first status */
|
||||
#define S2_SEEK_CHECK 0000004u /* seek check */
|
||||
#define S2_NOT_READY 0000002u /* not ready */
|
||||
#define S2_BUSY 0000001u /* drive busy */
|
||||
|
||||
#define S2_STOPS (S2_FAULT \
|
||||
| S2_SEEK_CHECK \
|
||||
|
@ -616,13 +623,13 @@ static const BITSET_FORMAT file_mask_format = /* names, offset, direction,
|
|||
#define S2_TO_DRIVE_TYPE(n) (((n) & S2_DRIVE_TYPE_MASK) >> S2_DRIVE_TYPE_SHIFT)
|
||||
|
||||
|
||||
#define PIO_HEAD_MASK 0017400 /* head mask */
|
||||
#define PIO_SECTOR_MASK 0000377 /* sector mask */
|
||||
#define PIO_HEAD_MASK 0017400u /* head mask */
|
||||
#define PIO_SECTOR_MASK 0000377u /* sector mask */
|
||||
|
||||
#define PI_ADV_CLOCK 0001000 /* advance clock */
|
||||
#define PI_DEL_CLOCK 0000400 /* delay clock */
|
||||
#define PI_NEG_OFFSET 0000200 /* 0/1 = positive/negative cylinder offset sign */
|
||||
#define PI_OFFSET_MASK 0000077 /* cylinder offset mask */
|
||||
#define PI_ADV_CLOCK 0001000u /* advance clock */
|
||||
#define PI_DEL_CLOCK 0000400u /* delay clock */
|
||||
#define PI_NEG_OFFSET 0000200u /* 0/1 = positive/negative cylinder offset sign */
|
||||
#define PI_OFFSET_MASK 0000077u /* cylinder offset mask */
|
||||
|
||||
|
||||
#define PIO_HEAD_SHIFT 8
|
||||
|
@ -724,13 +731,13 @@ static const BITSET_FORMAT offset_format = /* names, offset, direction, alt
|
|||
*/
|
||||
|
||||
typedef struct {
|
||||
char *name; /* drive name */
|
||||
uint32 sectors; /* sectors per head */
|
||||
uint32 heads; /* heads per cylinder*/
|
||||
uint32 cylinders; /* cylinders per drive */
|
||||
uint32 words; /* words per drive */
|
||||
uint32 remov_heads; /* number of removable-platter heads */
|
||||
uint32 fixed_heads; /* number of fixed-platter heads */
|
||||
const char *name; /* drive name */
|
||||
uint32 sectors; /* sectors per head */
|
||||
uint32 heads; /* heads per cylinder*/
|
||||
uint32 cylinders; /* cylinders per drive */
|
||||
uint32 words; /* words per drive */
|
||||
uint32 remov_heads; /* number of removable-platter heads */
|
||||
uint32 fixed_heads; /* number of fixed-platter heads */
|
||||
} DRIVE_PROPS;
|
||||
|
||||
static const DRIVE_PROPS drive_props [] = { /* indexed by DRIVE_TYPE */
|
||||
|
@ -1276,12 +1283,12 @@ static void idle_controller (CVPTR cvptr);
|
|||
|
||||
/* Disc library local utility routines */
|
||||
|
||||
static void set_address (CVPTR cvptr, uint32 index);
|
||||
static void wait_timer (CVPTR cvptr, FLIP_FLOP action);
|
||||
static uint16 drive_status (UNIT *uptr);
|
||||
static t_stat activate_unit (CVPTR cvptr, UNIT *uptr);
|
||||
static void set_rotation (CVPTR cvptr, UNIT *uptr);
|
||||
static void set_file_pos (CVPTR cvptr, UNIT *uptr, uint32 model);
|
||||
static void set_address (CVPTR cvptr, uint32 index);
|
||||
static void wait_timer (CVPTR cvptr, FLIP_FLOP action);
|
||||
static HP_WORD drive_status (UNIT *uptr);
|
||||
static t_stat activate_unit (CVPTR cvptr, UNIT *uptr);
|
||||
static void set_rotation (CVPTR cvptr, UNIT *uptr);
|
||||
static void set_file_pos (CVPTR cvptr, UNIT *uptr, uint32 model);
|
||||
|
||||
|
||||
|
||||
|
@ -1519,7 +1526,8 @@ return outbound;
|
|||
|
||||
6. ECC is not simulated, so the Request Syndrome command always returns zero
|
||||
values for the displacement and patterns and Uncorrectable Data Error for
|
||||
the status, unless a diagnostic override is in effect.
|
||||
the status. Correctable Data Error status cannot occur unless a
|
||||
diagnostic override is in effect.
|
||||
|
||||
7. The Wakeup command references a drive unit but is scheduled on the
|
||||
controller unit because it may be issued while the drive is seeking.
|
||||
|
@ -1533,6 +1541,7 @@ int32 seek_wait_time;
|
|||
PRPTR props;
|
||||
CNTLR_IFN_IBUS outbound;
|
||||
char s1_buffer [256], s2_buffer [256]; /* formatted bitset buffers for trace logging */
|
||||
DIAG_ENTRY *dop = NULL;
|
||||
|
||||
wait_timer (cvptr, CLEAR); /* stop the command wait timer */
|
||||
|
||||
|
@ -1566,21 +1575,24 @@ else { /* otherwise this is an
|
|||
cvptr->device->units + cvptr->poll_unit; /* when the controller structure was initialized */
|
||||
}
|
||||
|
||||
dpprintf (cvptr->device, DL_DEB_INCO, "Unit %d %s command started\n",
|
||||
dpprintf (cvptr->device, DL_DEB_INCO, "Unit %u %s command started\n",
|
||||
unit, opcode_name [cvptr->opcode]);
|
||||
|
||||
if (cvptr->dop_index >= 0) /* if the diagnostic override table is defined */
|
||||
dop = cvptr->dop_base + cvptr->dop_index; /* then point at the current entry */
|
||||
|
||||
if (cvptr->dop /* if the diagnostic override table is defined */
|
||||
&& cvptr->dop->cylinder == cvptr->cylinder /* and the cylinder, */
|
||||
&& cvptr->dop->head == cvptr->head /* head, */
|
||||
&& cvptr->dop->sector == cvptr->sector /* sector, */
|
||||
&& cvptr->dop->opcode == cvptr->opcode) { /* and opcode values match the current values */
|
||||
cvptr->spd_unit = cvptr->dop->spd | unit; /* then override the Spare/Protected/Defective */
|
||||
cvptr->status = cvptr->dop->status; /* and status values from the override entry */
|
||||
if (dop /* if the table entry exists */
|
||||
&& dop->cylinder == cvptr->cylinder /* and the cylinder, */
|
||||
&& dop->head == cvptr->head /* head, */
|
||||
&& dop->sector == cvptr->sector /* sector, */
|
||||
&& dop->opcode == cvptr->opcode) { /* and opcode values match the current values */
|
||||
cvptr->spd_unit = dop->spd | unit; /* then override the Spare/Protected/Defective */
|
||||
cvptr->status = dop->status; /* and status values from the override entry */
|
||||
|
||||
cvptr->dop++; /* point at the next table entry */
|
||||
cvptr->dop_index++; /* point at the */
|
||||
dop++; /* next table entry */
|
||||
|
||||
dpprintf (cvptr->device, DL_DEB_INCO, "Unit %d cylinder %d head %d sector %d diagnostic override\n",
|
||||
dpprintf (cvptr->device, DL_DEB_INCO, "Unit %u cylinder %u head %u sector %u diagnostic override\n",
|
||||
unit, cvptr->cylinder, cvptr->head, cvptr->sector);
|
||||
}
|
||||
|
||||
|
@ -1634,13 +1646,13 @@ else { /* otherwise the command
|
|||
if (start_seek (cvptr, duptr) == FALSE) /* start the seek; if it failed */
|
||||
set_completion (cvptr, cuptr, Status_2_Error); /* then set up the completion status */
|
||||
|
||||
dpprintf (cvptr->device, DL_DEB_CMD, "Unit %d %s from cylinder %d head %d sector %d\n",
|
||||
dpprintf (cvptr->device, DL_DEB_CMD, "Unit %u %s from cylinder %u head %u sector %u\n",
|
||||
unit, opcode_name [Cold_Load_Read], cvptr->cylinder, cvptr->head, cvptr->sector);
|
||||
break; /* wait for seek completion */
|
||||
|
||||
|
||||
case Recalibrate:
|
||||
dpprintf (cvptr->device, DL_DEB_CMD, "Unit %d %s to cylinder 0\n",
|
||||
dpprintf (cvptr->device, DL_DEB_CMD, "Unit %u %s to cylinder 0\n",
|
||||
unit, opcode_name [Recalibrate]);
|
||||
|
||||
if (duptr->PHASE == Seek_Phase) { /* if the unit is currently seeking */
|
||||
|
@ -1649,7 +1661,7 @@ else { /* otherwise the command
|
|||
sim_cancel (duptr); /* cancel the event to allow rescheduling */
|
||||
duptr->PHASE = Idle_Phase; /* and idle the drive so that the seek succeeds */
|
||||
|
||||
dpprintf (cvptr->device, DL_DEB_INCO, "Unit %d %s command waiting for seek completion\n",
|
||||
dpprintf (cvptr->device, DL_DEB_INCO, "Unit %u %s command waiting for seek completion\n",
|
||||
unit, opcode_name [Recalibrate]);
|
||||
}
|
||||
|
||||
|
@ -1667,7 +1679,7 @@ else { /* otherwise the command
|
|||
|
||||
|
||||
case Request_Status:
|
||||
cvptr->buffer [0] = (uint16) (cvptr->spd_unit /* set the Status-1 value */
|
||||
cvptr->buffer [0] = (DL_BUFFER) (cvptr->spd_unit /* set the Status-1 value */
|
||||
| S1_STATUS (cvptr->status)); /* into the buffer */
|
||||
|
||||
if (cvptr->type == MAC) /* if this a MAC controller */
|
||||
|
@ -1678,9 +1690,9 @@ else { /* otherwise the command
|
|||
else /* otherwise it is not a MAC controller */
|
||||
rptr = duptr; /* so the referenced unit is the current unit */
|
||||
|
||||
cvptr->buffer [1] = drive_status (rptr); /* set the Status-2 value into the buffer */
|
||||
cvptr->buffer [1] = (DL_BUFFER) drive_status (rptr); /* set the Status-2 value into the buffer */
|
||||
|
||||
dpprintf (cvptr->device, DL_DEB_CMD, "Unit %d %s returns %sunit %d | %s and %s%s | %s\n",
|
||||
dpprintf (cvptr->device, DL_DEB_CMD, "Unit %u %s returns %sunit %u | %s and %s%s | %s\n",
|
||||
unit, opcode_name [Request_Status],
|
||||
strcpy (s1_buffer, fmt_bitset (cvptr->spd_unit, status_1_format)),
|
||||
CM_UNIT (cvptr->spd_unit), dl_status_name (cvptr->status),
|
||||
|
@ -1706,9 +1718,9 @@ else { /* otherwise the command
|
|||
|
||||
else /* otherwise the drive is ready */
|
||||
cvptr->buffer [0] = /* so calculate the current sector address */
|
||||
(uint16) CURRENT_SECTOR (cvptr, duptr);
|
||||
(DL_BUFFER) CURRENT_SECTOR (cvptr, duptr);
|
||||
|
||||
dpprintf (cvptr->device, DL_DEB_CMD, "Unit %d %s returns sector %d\n",
|
||||
dpprintf (cvptr->device, DL_DEB_CMD, "Unit %u %s returns sector %u\n",
|
||||
unit, opcode_name [Request_Sector_Address], cvptr->buffer [0]);
|
||||
break;
|
||||
|
||||
|
@ -1722,13 +1734,14 @@ else { /* otherwise the command
|
|||
|
||||
|
||||
case Request_Syndrome:
|
||||
if (cvptr->status == Correctable_Data_Error) { /* if we've been called with a correction override */
|
||||
cvptr->buffer [3] = (uint16) cvptr->dop->spd; /* then load the displacement */
|
||||
cvptr->buffer [4] = (uint16) cvptr->dop->cylinder; /* and three */
|
||||
cvptr->buffer [5] = (uint16) cvptr->dop->head; /* syndrome words */
|
||||
cvptr->buffer [6] = (uint16) cvptr->dop->sector; /* from the override entry */
|
||||
if (cvptr->status == Correctable_Data_Error) { /* if this is a correction override */
|
||||
cvptr->buffer [3] = (DL_BUFFER) dop->spd; /* then load the displacement */
|
||||
cvptr->buffer [4] = (DL_BUFFER) dop->cylinder; /* and three */
|
||||
cvptr->buffer [5] = (DL_BUFFER) dop->head; /* syndrome words */
|
||||
cvptr->buffer [6] = (DL_BUFFER) dop->sector; /* from the override entry */
|
||||
|
||||
cvptr->dop++; /* point at the next entry */
|
||||
cvptr->dop_index++; /* point at the */
|
||||
dop++; /* next table entry */
|
||||
}
|
||||
|
||||
else { /* otherwise no correction data was supplied */
|
||||
|
@ -1741,12 +1754,12 @@ else { /* otherwise the command
|
|||
cvptr->status = Uncorrectable_Data_Error; /* then presume that an uncorrectable error occurred */
|
||||
}
|
||||
|
||||
cvptr->buffer [0] = (uint16) (cvptr->spd_unit /* save the Status-1 value */
|
||||
cvptr->buffer [0] = (DL_BUFFER) (cvptr->spd_unit /* save the Status-1 value */
|
||||
| S1_STATUS (cvptr->status)); /* in the buffer */
|
||||
|
||||
set_address (cvptr, 1); /* save the CHS values in the buffer */
|
||||
|
||||
dpprintf (cvptr->device, DL_DEB_CMD, "%s returns %sunit %d | %s | cylinder %d head %d sector %d | "
|
||||
dpprintf (cvptr->device, DL_DEB_CMD, "%s returns %sunit %u | %s | cylinder %u head %u sector %u | "
|
||||
"syndrome %06o %06o %06o %06o\n",
|
||||
opcode_name [Request_Syndrome], fmt_bitset (cvptr->spd_unit, status_1_format),
|
||||
CM_UNIT (cvptr->spd_unit), dl_status_name (cvptr->status),
|
||||
|
@ -1765,7 +1778,7 @@ else { /* otherwise the command
|
|||
|
||||
set_completion (cvptr, cuptr, Normal_Completion); /* schedule the command completion */
|
||||
|
||||
dpprintf (cvptr->device, DL_DEB_CMD, "%s to %sretries %d\n",
|
||||
dpprintf (cvptr->device, DL_DEB_CMD, "%s to %sretries %u\n",
|
||||
opcode_name [Set_File_Mask], fmt_bitset (cvptr->file_mask, file_mask_format),
|
||||
CM_RETRY (inbound_data));
|
||||
break;
|
||||
|
@ -1774,7 +1787,7 @@ else { /* otherwise the command
|
|||
case Request_Disc_Address:
|
||||
set_address (cvptr, 0); /* set the controller's CHS values into the buffer */
|
||||
|
||||
dpprintf (cvptr->device, DL_DEB_CMD, "Unit %d %s returns cylinder %d head %d sector %d\n",
|
||||
dpprintf (cvptr->device, DL_DEB_CMD, "Unit %u %s returns cylinder %u head %u sector %u\n",
|
||||
unit, opcode_name [Request_Disc_Address], cvptr->cylinder, cvptr->head, cvptr->sector);
|
||||
break;
|
||||
|
||||
|
@ -1789,7 +1802,7 @@ else { /* otherwise the command
|
|||
case Wakeup:
|
||||
set_completion (cvptr, cuptr, Unit_Available); /* schedule the command completion */
|
||||
|
||||
dpprintf (cvptr->device, DL_DEB_CMD, "Unit %d %s\n",
|
||||
dpprintf (cvptr->device, DL_DEB_CMD, "Unit %u %s\n",
|
||||
unit, opcode_name [Wakeup]);
|
||||
break;
|
||||
|
||||
|
@ -1812,7 +1825,7 @@ else { /* otherwise the command
|
|||
case Write:
|
||||
case Write_Full_Sector:
|
||||
if (duptr->PHASE == Seek_Phase) /* if the unit is currently seeking */
|
||||
dpprintf (cvptr->device, DL_DEB_INCO, "Unit %d %s command waiting for seek completion\n",
|
||||
dpprintf (cvptr->device, DL_DEB_INCO, "Unit %u %s command waiting for seek completion\n",
|
||||
unit, opcode_name [cvptr->opcode]);
|
||||
|
||||
else /* otherwise the unit is idle */
|
||||
|
@ -1978,7 +1991,7 @@ return outbound; /* return the data word
|
|||
|
||||
Implementation notes:
|
||||
|
||||
1. The "%.0d" print specification in the trace call absorbs the zero "unit"
|
||||
1. The "%.0u" print specification in the trace call absorbs the zero "unit"
|
||||
value parameter without printing when the controller unit is specified.
|
||||
|
||||
2. The Seek command does not check for Access Not Ready before issuing the
|
||||
|
@ -2040,10 +2053,11 @@ CNTLR_OPCODE opcode;
|
|||
CNTLR_PHASE phase;
|
||||
CNTLR_IFN_IBUS outbound;
|
||||
t_bool controller_service, controller_was_busy;
|
||||
uint32 unit, sector_count;
|
||||
int32 unit;
|
||||
uint32 sector_count;
|
||||
|
||||
if (service_entry) { /* if this is an event service entry */
|
||||
unit = uptr - cvptr->device->units; /* then get the unit number */
|
||||
unit = (int32) (uptr - cvptr->device->units); /* then get the unit number */
|
||||
|
||||
controller_service = (uptr == CNTLR_UPTR /* set TRUE if the controller is being serviced */
|
||||
&& cvptr->type == MAC);
|
||||
|
@ -2091,7 +2105,7 @@ switch (phase) { /* dispatch the phase */
|
|||
|
||||
outbound = NO_FUNCTIONS; /* clear the function set for an idle return */
|
||||
|
||||
dpprintf (cvptr->device, DL_DEB_INCO, "Unit %d %s command aborted with parameter wait timeout\n",
|
||||
dpprintf (cvptr->device, DL_DEB_INCO, "Unit %u %s command aborted with parameter wait timeout\n",
|
||||
CM_UNIT (cvptr->spd_unit), opcode_name [opcode]);
|
||||
}
|
||||
|
||||
|
@ -2115,7 +2129,8 @@ switch (phase) { /* dispatch the phase */
|
|||
|
||||
case Seek: /* these commands receive parameters */
|
||||
case Address_Record: /* from the interface */
|
||||
cvptr->buffer [cvptr->index++] = inbound_data; /* save the current one in the buffer */
|
||||
cvptr->buffer [cvptr->index++] = /* save the current one in the buffer */
|
||||
(DL_BUFFER) inbound_data;
|
||||
cvptr->length = cvptr->length - 1; /* and drop the parameter count */
|
||||
|
||||
if (cvptr->length > 0) /* if another parameter is expected */
|
||||
|
@ -2129,7 +2144,7 @@ switch (phase) { /* dispatch the phase */
|
|||
if (opcode == Address_Record) { /* if this is an Address Record command */
|
||||
cvptr->eoc = CLEAR; /* then clear the end-of-cylinder flag */
|
||||
|
||||
dpprintf (cvptr->device, DL_DEB_CMD, "%s to cylinder %d head %d sector %d\n",
|
||||
dpprintf (cvptr->device, DL_DEB_CMD, "%s to cylinder %u head %u sector %u\n",
|
||||
opcode_name [Address_Record],
|
||||
cvptr->cylinder, cvptr->head, cvptr->sector);
|
||||
|
||||
|
@ -2138,7 +2153,7 @@ switch (phase) { /* dispatch the phase */
|
|||
}
|
||||
|
||||
else { /* otherwise it's a Seek command */
|
||||
dpprintf (cvptr->device, DL_DEB_CMD, "Unit %d %s to cylinder %d head %d sector %d\n",
|
||||
dpprintf (cvptr->device, DL_DEB_CMD, "Unit %u %s to cylinder %u head %u sector %u\n",
|
||||
CM_UNIT (cvptr->spd_unit), opcode_name [Seek],
|
||||
cvptr->cylinder, cvptr->head, cvptr->sector);
|
||||
|
||||
|
@ -2165,7 +2180,7 @@ switch (phase) { /* dispatch the phase */
|
|||
|
||||
cvptr->count = sector_count * WORDS_PER_SECTOR; /* convert to the number of words to verify */
|
||||
|
||||
dpprintf (cvptr->device, DL_DEB_CMD, "Unit %d %s %d sector%s\n",
|
||||
dpprintf (cvptr->device, DL_DEB_CMD, "Unit %u %s %u sector%s\n",
|
||||
CM_UNIT (cvptr->spd_unit), opcode_name [Verify],
|
||||
sector_count, (sector_count == 1 ? "" : "s"));
|
||||
|
||||
|
@ -2177,7 +2192,7 @@ switch (phase) { /* dispatch the phase */
|
|||
if (uptr->PHASE == Seek_Phase) { /* if a seek is in progress, */
|
||||
uptr->wait = NO_EVENT; /* then wait for it to complete */
|
||||
|
||||
dpprintf (cvptr->device, DL_DEB_INCO, "Unit %d %s command waiting for seek completion\n",
|
||||
dpprintf (cvptr->device, DL_DEB_INCO, "Unit %u %s command waiting for seek completion\n",
|
||||
CM_UNIT (cvptr->spd_unit), opcode_name [Verify]);
|
||||
}
|
||||
|
||||
|
@ -2187,11 +2202,11 @@ switch (phase) { /* dispatch the phase */
|
|||
|
||||
|
||||
case Read_With_Offset:
|
||||
dpprintf (cvptr->device, DL_DEB_CMD, "Unit %d %s using %soffset %+d\n",
|
||||
dpprintf (cvptr->device, DL_DEB_CMD, "Unit %u %s using %soffset %+d\n",
|
||||
CM_UNIT (cvptr->spd_unit), opcode_name [Read_With_Offset],
|
||||
fmt_bitset (inbound_data, offset_format),
|
||||
(inbound_data & PI_NEG_OFFSET ? - (int) PI_OFFSET (inbound_data)
|
||||
: PI_OFFSET (inbound_data)));
|
||||
: (int) PI_OFFSET (inbound_data)));
|
||||
|
||||
wait_timer (cvptr, CLEAR); /* stop the parameter timer */
|
||||
|
||||
|
@ -2201,7 +2216,7 @@ switch (phase) { /* dispatch the phase */
|
|||
if (uptr->PHASE == Seek_Phase) { /* if a seek is in progress, */
|
||||
uptr->wait = NO_EVENT; /* then wait for it to complete */
|
||||
|
||||
dpprintf (cvptr->device, DL_DEB_INCO, "Unit %d %s command waiting for seek completion\n",
|
||||
dpprintf (cvptr->device, DL_DEB_INCO, "Unit %u %s command waiting for seek completion\n",
|
||||
CM_UNIT (cvptr->spd_unit), opcode_name [Read_With_Offset]);
|
||||
}
|
||||
|
||||
|
@ -2313,7 +2328,7 @@ switch (phase) { /* dispatch the phase */
|
|||
cvptr->count = cvptr->count + 1; /* count the */
|
||||
cvptr->length = cvptr->length - 1; /* transfer */
|
||||
|
||||
dpprintf (cvptr->device, DL_DEB_XFER, "Unit %d %s word %d is %06o\n",
|
||||
dpprintf (cvptr->device, DL_DEB_XFER, "Unit %d %s word %u is %06o\n",
|
||||
unit, opcode_name [opcode],
|
||||
cvptr->count, DLIBUS (outbound));
|
||||
}
|
||||
|
@ -2333,13 +2348,14 @@ switch (phase) { /* dispatch the phase */
|
|||
case Write:
|
||||
case Write_Full_Sector:
|
||||
case Initialize:
|
||||
if ((inbound_flags & EOD) == NO_FLAGS) { /* if the transfer continues */
|
||||
cvptr->buffer [cvptr->index++] = inbound_data; /* then store the next word in the buffer */
|
||||
if ((inbound_flags & EOD) == NO_FLAGS) { /* if the transfer continues */
|
||||
cvptr->buffer [cvptr->index++] = /* then store the next word in the buffer */
|
||||
(DL_BUFFER) inbound_data;
|
||||
|
||||
cvptr->count = cvptr->count + 1; /* count the */
|
||||
cvptr->length = cvptr->length - 1; /* transfer */
|
||||
cvptr->count = cvptr->count + 1; /* count the */
|
||||
cvptr->length = cvptr->length - 1; /* transfer */
|
||||
|
||||
dpprintf (cvptr->device, DL_DEB_XFER, "Unit %d %s word %d is %06o\n",
|
||||
dpprintf (cvptr->device, DL_DEB_XFER, "Unit %d %s word %u is %06o\n",
|
||||
unit, opcode_name [opcode],
|
||||
cvptr->count, inbound_data);
|
||||
}
|
||||
|
@ -2462,8 +2478,12 @@ for (unit = 0; unit <= DL_MAXDRIVE; unit++) { /* check each unit in tu
|
|||
|
||||
if (units [cvptr->poll_unit].STATUS & S2_ATTENTION) { /* if the unit is requesting attention, */
|
||||
units [cvptr->poll_unit].STATUS &= ~S2_ATTENTION; /* clear the Attention status */
|
||||
cvptr->spd_unit = cvptr->poll_unit; /* set the controller's unit number */
|
||||
cvptr->status = Drive_Attention; /* and status */
|
||||
|
||||
dpprintf (cvptr->device, DL_DEB_INCO, "Unit %u requested attention\n",
|
||||
cvptr->poll_unit);
|
||||
|
||||
cvptr->spd_unit = cvptr->poll_unit; /* set the controller's unit number */
|
||||
cvptr->status = Drive_Attention; /* and status */
|
||||
|
||||
cvptr->state = Wait_State; /* set the controller state to waiting */
|
||||
wait_timer (cvptr, SET); /* start the command wait timer */
|
||||
|
@ -2681,6 +2701,13 @@ else /* otherwise the status
|
|||
|
||||
The file specified by the supplied filename is attached to the indicated
|
||||
unit. If the attach was successful, the heads are loaded on the drive.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. The pointer to the appropriate event delay times is set in case we are
|
||||
being called during a RESTORE command (the assignment is redundant
|
||||
otherwise).
|
||||
*/
|
||||
|
||||
t_stat dl_attach (CVPTR cvptr, UNIT *uptr, CONST char *cptr)
|
||||
|
@ -2692,6 +2719,10 @@ result = attach_unit (uptr, cptr); /* attach the unit *
|
|||
if (result == SCPE_OK) /* if the attach succeeded */
|
||||
result = dl_load_unload (cvptr, uptr, TRUE); /* then load the heads */
|
||||
|
||||
dl_set_timing (cvptr->device->units, /* reestablish */
|
||||
(cvptr->device->flags & DEV_REALTIME), /* the delay times */
|
||||
NULL, (void *) cvptr); /* pointer(s) */
|
||||
|
||||
return result; /* return the command result status */
|
||||
}
|
||||
|
||||
|
@ -3023,7 +3054,7 @@ else if (value == 0) /* otherwise if this is
|
|||
return SCPE_2MARG; /* then report an error */
|
||||
|
||||
else { /* otherwise the command is valid */
|
||||
cvptr->dop = NULL; /* so clear the current entry pointer */
|
||||
cvptr->dop_index = -1; /* so clear the current entry pointer */
|
||||
cvptr->dop_base->cylinder = DL_OVEND; /* and mark the first entry as the end */
|
||||
}
|
||||
|
||||
|
@ -3031,7 +3062,7 @@ else if (cptr == NULL) /* otherwise if DIAG is
|
|||
if (cvptr->dop_base->cylinder == DL_OVEND) /* then if there are no entries in the table */
|
||||
return SCPE_MISVAL; /* then one must be entered first */
|
||||
else /* otherwise */
|
||||
cvptr->dop = cvptr->dop_base; /* reset the current pointer to the first entry */
|
||||
cvptr->dop_index = 0; /* reset the current pointer to the first entry */
|
||||
|
||||
else if (*cptr == '\0') /* otherwise if there are no parameters */
|
||||
return SCPE_MISVAL; /* then report a missing value */
|
||||
|
@ -3123,7 +3154,7 @@ else { /* otherwise at least on
|
|||
entry++; /* point at the next available entry */
|
||||
entry->cylinder = DL_OVEND; /* and mark it as the end of the list */
|
||||
|
||||
cvptr->dop = cvptr->dop_base; /* reset the current pointer to the start of the list */
|
||||
cvptr->dop_index = 0; /* reset the current pointer to the start of the list */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3173,7 +3204,7 @@ DIAG_ENTRY *entry;
|
|||
if (cvptr->dop_base == NULL) /* if the table isn't defined */
|
||||
return SCPE_NOFNC; /* then the command is illegal */
|
||||
|
||||
else if (cvptr->dop == NULL) { /* otherwise if overrides are currently disabled */
|
||||
else if (cvptr->dop_index < 0) { /* otherwise if overrides are currently disabled */
|
||||
fputs ("override disabled", st); /* then report it */
|
||||
|
||||
if (value > 0) /* if we were invoked by a SHOW DIAG command */
|
||||
|
@ -3213,12 +3244,12 @@ return SCPE_OK;
|
|||
|
||||
This validation routine is called to set the timing mode for the disc
|
||||
subsystem. As this is an extended MTAB call, the "uptr" parameter points to
|
||||
the unit array of the device. The "value" parameter is set to 1 to use
|
||||
the unit array of the device. The "value" parameter is set non-zero to use
|
||||
realistic timing and 0 to use fast timing. For a MAC controller, the "desc"
|
||||
parameter is a pointer to the controller. For ICD controllers, the "desc"
|
||||
parameter is a pointer to the first element of the controller array. There
|
||||
must be one controller for each unit defined by the device associated with
|
||||
the controllers.
|
||||
the controllers. The "cptr" parameter is not used.
|
||||
|
||||
If fast timing is selected, the controller's timing pointer is set to the
|
||||
fast timing pointer supplied by the interface when the controller was
|
||||
|
@ -3239,7 +3270,7 @@ t_stat dl_set_timing (UNIT *uptr, int32 value, CONST char *cptr, void *desc)
|
|||
{
|
||||
CVPTR cvptr = (CVPTR) desc; /* the controller pointer is supplied */
|
||||
const DELAY_PROPS *dpptr;
|
||||
int32 model;
|
||||
DRIVE_TYPE model;
|
||||
uint32 delay, cntlr_count;
|
||||
|
||||
if (cvptr->type == MAC) /* if this is a MAC controller */
|
||||
|
@ -3254,7 +3285,7 @@ while (cntlr_count--) { /* set each controller's
|
|||
|
||||
for (delay = 0; delay < DELAY_COUNT; delay++) /* search for the correct set of times */
|
||||
if (dpptr->type == cvptr->type /* if the controller types match */
|
||||
&& (dpptr->drive == HP_All /* and the drive times are identical */
|
||||
&& (dpptr->drive == HP_All /* and all drive times are the same */
|
||||
|| dpptr->drive == model)) { /* or the drive types match as well */
|
||||
cvptr->dlyptr = dpptr; /* then use this set of times */
|
||||
break;
|
||||
|
@ -3392,8 +3423,8 @@ else { /* otherwise */
|
|||
|
||||
if (cmd_props [cvptr->opcode].transfer_size > 0)
|
||||
dpprintf (cvptr->device, DL_DEB_CMD, (cvptr->opcode == Initialize
|
||||
? "Unit %d Initialize %s for %d words (%d sector%s)\n"
|
||||
: "Unit %d %s for %d words (%d sector%s)\n"),
|
||||
? "Unit %u Initialize %s for %u words (%u sector%s)\n"
|
||||
: "Unit %u %s for %u words (%u sector%s)\n"),
|
||||
CM_UNIT (cvptr->spd_unit),
|
||||
(cvptr->opcode == Initialize
|
||||
? fmt_bitset (cvptr->spd_unit, initialize_format)
|
||||
|
@ -3402,7 +3433,7 @@ if (cmd_props [cvptr->opcode].transfer_size > 0)
|
|||
cvptr->count / cmd_props [cvptr->opcode].transfer_size + (cvptr->length > 0),
|
||||
(cvptr->count <= cmd_props [cvptr->opcode].transfer_size ? "" : "s"));
|
||||
|
||||
dpprintf (cvptr->device, DL_DEB_INCO, "Unit %d %s command completed with %s status\n",
|
||||
dpprintf (cvptr->device, DL_DEB_INCO, "Unit %u %s command completed with %s status\n",
|
||||
CM_UNIT (cvptr->spd_unit), opcode_name [cvptr->opcode],
|
||||
dl_status_name (cvptr->status));
|
||||
|
||||
|
@ -3486,13 +3517,13 @@ else /* otherwise it's a norm
|
|||
if (position_sector (cvptr, uptr) == FALSE) /* position the sector; if it was not */
|
||||
return FALSE; /* then a seek is in progress or an error occurred */
|
||||
|
||||
dpprintf (cvptr->device, DL_DEB_INCO, "Unit %d %s from cylinder %d head %d sector %d\n",
|
||||
uptr - cvptr->device->units, opcode_name [opcode],
|
||||
dpprintf (cvptr->device, DL_DEB_INCO, "Unit %d %s from cylinder %u head %u sector %u\n",
|
||||
(int32) (uptr - cvptr->device->units), opcode_name [opcode],
|
||||
uptr->CYL, cvptr->head, cvptr->sector);
|
||||
|
||||
count = sim_fread (cvptr->buffer + offset, /* read the sector from the image */
|
||||
sizeof (uint16), WORDS_PER_SECTOR, /* into the sector buffer */
|
||||
uptr->fileref);
|
||||
sizeof (DL_BUFFER), /* into the sector buffer */
|
||||
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 */
|
||||
|
@ -3657,8 +3688,8 @@ else if (position_sector (cvptr, uptr) == TRUE) { /* otherwise if position
|
|||
cvptr->length = cmd_props [opcode].transfer_size; /* then set the appropriate transfer length */
|
||||
cvptr->index = 0; /* and reset the data index */
|
||||
|
||||
dpprintf (cvptr->device, DL_DEB_INCO, "Unit %d %s to cylinder %d head %d sector %d\n",
|
||||
uptr - cvptr->device->units, opcode_name [opcode],
|
||||
dpprintf (cvptr->device, DL_DEB_INCO, "Unit %d %s to cylinder %u head %u sector %u\n",
|
||||
(int32) (uptr - cvptr->device->units), opcode_name [opcode],
|
||||
uptr->CYL, cvptr->head, cvptr->sector);
|
||||
|
||||
return TRUE; /* the write was successfully started */
|
||||
|
@ -3708,7 +3739,7 @@ return FALSE; /* otherwise an error oc
|
|||
static void end_write (CVPTR cvptr, UNIT *uptr, CNTLR_FLAG_SET flags)
|
||||
{
|
||||
uint32 count;
|
||||
uint16 pad;
|
||||
DL_BUFFER pad;
|
||||
const CNTLR_OPCODE opcode = (CNTLR_OPCODE) uptr->OPCODE;
|
||||
const uint32 offset = (opcode == Write_Full_Sector ? 3 : 0);
|
||||
|
||||
|
@ -3727,7 +3758,7 @@ if (cvptr->index < WORDS_PER_SECTOR + offset) { /* if a partial sector w
|
|||
cvptr->buffer [count] = pad; /* pad the sector buffer as needed */
|
||||
}
|
||||
|
||||
sim_fwrite (cvptr->buffer + offset, sizeof (uint16), /* write the sector to the file */
|
||||
sim_fwrite (cvptr->buffer + offset, sizeof (DL_BUFFER), /* write the sector to the file */
|
||||
WORDS_PER_SECTOR, uptr->fileref);
|
||||
|
||||
if (ferror (uptr->fileref)) /* if a host file system error occurred, then report it */
|
||||
|
@ -3810,7 +3841,7 @@ return;
|
|||
|
||||
static t_bool position_sector (CVPTR cvptr, UNIT *uptr)
|
||||
{
|
||||
const uint32 model = GET_MODEL (uptr->flags); /* get the drive model */
|
||||
const DRIVE_TYPE model = GET_MODEL (uptr->flags); /* get the drive model */
|
||||
|
||||
if (cvptr->status != Normal_Completion /* if a diagnostic override is present */
|
||||
&& cvptr->status != Uncorrectable_Data_Error /* and it's not */
|
||||
|
@ -3826,8 +3857,8 @@ else if (cvptr->eoc == SET) /* otherwise if
|
|||
|
||||
start_seek (cvptr, uptr); /* start the auto-seek */
|
||||
|
||||
dpprintf (cvptr->device, DL_DEB_INCO, "Unit %d %s%s autoseek to cylinder %d head %d sector %d\n",
|
||||
uptr - cvptr->device->units, opcode_name [uptr->OPCODE],
|
||||
dpprintf (cvptr->device, DL_DEB_INCO, "Unit %d %s%s autoseek to cylinder %u head %u sector %u\n",
|
||||
(int32) (uptr - cvptr->device->units), opcode_name [uptr->OPCODE],
|
||||
(uptr->STATUS & S2_SEEK_CHECK ? " seek check on" : ""),
|
||||
cvptr->cylinder, cvptr->head, cvptr->sector);
|
||||
|
||||
|
@ -3845,8 +3876,8 @@ else if (cvptr->verify /* if address verifi
|
|||
&& (uint32) uptr->CYL != cvptr->cylinder) { /* and the positioner is on the wrong cylinder */
|
||||
start_seek (cvptr, uptr); /* then start a seek to the correct cylinder */
|
||||
|
||||
dpprintf (cvptr->device, DL_DEB_INCO, "Unit %d %s%s reseek to cylinder %d head %d sector %d\n",
|
||||
uptr - cvptr->device->units, opcode_name [uptr->OPCODE],
|
||||
dpprintf (cvptr->device, DL_DEB_INCO, "Unit %d %s%s reseek to cylinder %u head %u sector %u\n",
|
||||
(int32) (uptr - cvptr->device->units), opcode_name [uptr->OPCODE],
|
||||
(uptr->STATUS & S2_SEEK_CHECK ? " seek check on" : ""),
|
||||
cvptr->cylinder, cvptr->head, cvptr->sector);
|
||||
|
||||
|
@ -3911,7 +3942,7 @@ return FALSE; /* positioning failed or
|
|||
|
||||
static void next_sector (CVPTR cvptr, UNIT *uptr)
|
||||
{
|
||||
const uint32 model = GET_MODEL (uptr->flags); /* get the disc model */
|
||||
const DRIVE_TYPE model = GET_MODEL (uptr->flags); /* get the disc model */
|
||||
|
||||
cvptr->sector = cvptr->sector + 1; /* increment the sector number */
|
||||
|
||||
|
@ -3995,7 +4026,7 @@ static t_bool start_seek (CVPTR cvptr, UNIT *uptr)
|
|||
{
|
||||
int32 delta;
|
||||
uint32 target_cylinder;
|
||||
const uint32 model = GET_MODEL (uptr->flags); /* get the drive model */
|
||||
const DRIVE_TYPE model = GET_MODEL (uptr->flags); /* get the drive model */
|
||||
|
||||
if (uptr->flags & UNIT_UNLOAD) /* if the heads are unloaded */
|
||||
return FALSE; /* then the seek fails as the drive was not ready */
|
||||
|
@ -4112,10 +4143,10 @@ return;
|
|||
static void set_address (CVPTR cvptr, uint32 index)
|
||||
{
|
||||
cvptr->buffer [index] = /* update the cylinder if EOC is set */
|
||||
(uint16) cvptr->cylinder + (cvptr->eoc == SET ? 1 : 0);
|
||||
(DL_BUFFER) cvptr->cylinder + (cvptr->eoc == SET ? 1 : 0);
|
||||
|
||||
cvptr->buffer [index + 1] = /* merge the head and sector */
|
||||
(uint16) (PO_HEAD (cvptr->head) | PO_SECTOR (cvptr->sector));
|
||||
(DL_BUFFER) (PO_HEAD (cvptr->head) | PO_SECTOR (cvptr->sector));
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -4153,15 +4184,15 @@ return;
|
|||
respectively, when status is returned.
|
||||
*/
|
||||
|
||||
static uint16 drive_status (UNIT *uptr)
|
||||
static HP_WORD drive_status (UNIT *uptr)
|
||||
{
|
||||
uint16 status;
|
||||
HP_WORD status;
|
||||
|
||||
if (uptr == NULL) /* if the unit is invalid */
|
||||
return S2_ERROR | S2_NOT_READY; /* then it does not respond */
|
||||
|
||||
status = /* start with the drive type and unit status */
|
||||
(uint16) (S2_DRIVE_TYPE (GET_MODEL (uptr->flags)) | uptr->STATUS);
|
||||
S2_DRIVE_TYPE (GET_MODEL (uptr->flags)) | uptr->STATUS;
|
||||
|
||||
if (uptr->flags & UNIT_FMT) /* if the format switch is enabled */
|
||||
status |= S2_FORMAT_EN; /* then set the Format status bit */
|
||||
|
@ -4190,14 +4221,14 @@ return status; /* return the unit statu
|
|||
|
||||
Implementation notes:
|
||||
|
||||
1. The "%.0d" print specification in the trace call absorbs the zero "unit"
|
||||
1. The "%.0u" print specification in the trace call absorbs the zero "unit"
|
||||
value parameter without printing when the controller unit is specified.
|
||||
*/
|
||||
|
||||
static t_stat activate_unit (CVPTR cvptr, UNIT *uptr)
|
||||
{
|
||||
t_stat result;
|
||||
uint32 unit = uptr - cvptr->device->units;
|
||||
const int32 unit = (int32) (uptr - cvptr->device->units); /* the unit number */
|
||||
|
||||
dpprintf (cvptr->device, DL_DEB_SERV, (unit == CNTLR_UNIT
|
||||
? "Controller unit%.0d %s %s phase delay %d service scheduled\n"
|
||||
|
@ -4292,7 +4323,7 @@ else /* otherwise the
|
|||
+ cvptr->head - drive_props [model].remov_heads; /* by the size of the removable platter */
|
||||
|
||||
uptr->pos = (track * drive_props [model].sectors + cvptr->sector) /* set the byte offset in the file */
|
||||
* WORDS_PER_SECTOR * sizeof (uint16); /* of the CHS target sector */
|
||||
* WORDS_PER_SECTOR * sizeof (DL_BUFFER); /* of the CHS target sector */
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
this Software without prior written authorization from the authors.
|
||||
|
||||
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
|
||||
21-Mar-16 JDB Changed uint16 types to HP_WORD
|
||||
27-Jul-15 JDB First revised release version
|
||||
21-Feb-15 JDB Revised for new controller interface model
|
||||
24-Oct-12 JDB Changed CNTLR_OPCODE to title case to avoid name clash
|
||||
|
@ -44,6 +46,15 @@
|
|||
|
||||
|
||||
|
||||
/* Architectural constants.
|
||||
|
||||
The type of the disc buffer element is defined. This must be a 16-bit array
|
||||
for the file representation to be packed.
|
||||
*/
|
||||
|
||||
typedef uint16 DL_BUFFER; /* a buffer containing 16-bit disc data words */
|
||||
|
||||
|
||||
/* Program limits */
|
||||
|
||||
#define DL_MAXDRIVE 7 /* last valid drive number */
|
||||
|
@ -61,12 +72,12 @@
|
|||
|
||||
/* Debug flags */
|
||||
|
||||
#define DL_DEB_CMD (1 << 0) /* trace controller commands */
|
||||
#define DL_DEB_INCO (1 << 1) /* trace command initiations and completions */
|
||||
#define DL_DEB_STATE (1 << 2) /* trace command execution state changes */
|
||||
#define DL_DEB_SERV (1 << 3) /* trace unit service scheduling calls */
|
||||
#define DL_DEB_XFER (1 << 4) /* trace data reads and writes */
|
||||
#define DL_DEB_IOB (1 << 5) /* trace I/O bus signals and data words */
|
||||
#define DL_DEB_CMD (1u << 0) /* trace controller commands */
|
||||
#define DL_DEB_INCO (1u << 1) /* trace command initiations and completions */
|
||||
#define DL_DEB_STATE (1u << 2) /* trace command execution state changes */
|
||||
#define DL_DEB_SERV (1u << 3) /* trace unit service scheduling calls */
|
||||
#define DL_DEB_XFER (1u << 4) /* trace data reads and writes */
|
||||
#define DL_DEB_IOB (1u << 5) /* trace I/O bus signals and data words */
|
||||
#define DL_DEB_V_UF 6 /* first free debug flag bit */
|
||||
|
||||
|
||||
|
@ -82,7 +93,7 @@
|
|||
|
||||
#define DEV_REALTIME_SHIFT (DEV_V_UF + 0) /* bits 0-0: timing mode is realistic */
|
||||
|
||||
#define DEV_REALTIME (1 << DEV_REALTIME_SHIFT) /* realistic timing flag */
|
||||
#define DEV_REALTIME (1u << DEV_REALTIME_SHIFT) /* realistic timing flag */
|
||||
|
||||
|
||||
/* Unit flags and accessors */
|
||||
|
@ -93,15 +104,15 @@
|
|||
#define UNIT_FMT_SHIFT (UNIT_V_UF + 5) /* bits 5-5: format enabled */
|
||||
#define DL_V_UF (UNIT_V_UF + 6) /* first free unit flag bit */
|
||||
|
||||
#define UNIT_MODEL_MASK 0000003 /* model ID mask */
|
||||
#define UNIT_PROT_MASK 0000003 /* head protection mask */
|
||||
#define UNIT_MODEL_MASK 0000003u /* model ID mask */
|
||||
#define UNIT_PROT_MASK 0000003u /* head protection mask */
|
||||
|
||||
#define UNIT_MODEL (UNIT_MODEL_MASK << UNIT_MODEL_SHIFT)
|
||||
#define UNIT_PROT (UNIT_PROT_MASK << UNIT_PROT_SHIFT)
|
||||
#define UNIT_PROT_L (1 << UNIT_PROT_SHIFT + 0)
|
||||
#define UNIT_PROT_U (1 << UNIT_PROT_SHIFT + 1)
|
||||
#define UNIT_UNLOAD (1 << UNIT_UNLOAD_SHIFT)
|
||||
#define UNIT_FMT (1 << UNIT_FMT_SHIFT)
|
||||
#define UNIT_PROT_L (1u << UNIT_PROT_SHIFT + 0)
|
||||
#define UNIT_PROT_U (1u << UNIT_PROT_SHIFT + 1)
|
||||
#define UNIT_UNLOAD (1u << UNIT_UNLOAD_SHIFT)
|
||||
#define UNIT_FMT (1u << UNIT_FMT_SHIFT)
|
||||
|
||||
#define UNIT_7905 (HP_7905 << UNIT_MODEL_SHIFT)
|
||||
#define UNIT_7906 (HP_7906 << UNIT_MODEL_SHIFT)
|
||||
|
@ -187,35 +198,35 @@ typedef enum {
|
|||
*/
|
||||
|
||||
typedef enum { /* interface flags */
|
||||
CLEARF = 0000001,
|
||||
CMRDY = 0000002,
|
||||
DTRDY = 0000004,
|
||||
EOD = 0000010,
|
||||
INTOK = 0000020,
|
||||
OVRUN = 0000040,
|
||||
XFRNG = 0000100
|
||||
CLEARF = 0000001, /* Clear Controller */
|
||||
CMRDY = 0000002, /* Command Ready */
|
||||
DTRDY = 0000004, /* Data Ready */
|
||||
EOD = 0000010, /* End of Data */
|
||||
INTOK = 0000020, /* Interrupt OK */
|
||||
OVRUN = 0000040, /* Data Overrun */
|
||||
XFRNG = 0000100 /* Data Transfer No Good */
|
||||
} CNTLR_FLAG;
|
||||
|
||||
#define NO_FLAGS ((CNTLR_FLAG) 0) /* no flags are asserted */
|
||||
#define NO_FLAGS ((CNTLR_FLAG) 0) /* no flags are asserted */
|
||||
|
||||
typedef CNTLR_FLAG CNTLR_FLAG_SET; /* a set of CNTLR_FLAGs */
|
||||
typedef CNTLR_FLAG CNTLR_FLAG_SET; /* a set of CNTLR_FLAGs */
|
||||
|
||||
|
||||
typedef enum { /* interface function bus orders */
|
||||
BUSY = 000000200000,
|
||||
DSCIF = 000000400000,
|
||||
SELIF = 000001000000,
|
||||
IFIN = 000002000000,
|
||||
IFOUT = 000004000000,
|
||||
IFGTC = 000010000000,
|
||||
IFPRF = 000020000000,
|
||||
RQSRV = 000040000000,
|
||||
DVEND = 000100000000,
|
||||
SRTRY = 000200000000,
|
||||
STDFL = 000400000000,
|
||||
STINT = 001000000000,
|
||||
WRTIO = 002000000000,
|
||||
FREE = 004000000000
|
||||
BUSY = 000000200000, /* Set Interface Busy */
|
||||
DSCIF = 000000400000, /* Disconnect Interface */
|
||||
SELIF = 000001000000, /* Select Interface */
|
||||
IFIN = 000002000000, /* Interface In */
|
||||
IFOUT = 000004000000, /* Interface Out */
|
||||
IFGTC = 000010000000, /* Interface Get Command */
|
||||
IFPRF = 000020000000, /* Interface Prefetch Command */
|
||||
RQSRV = 000040000000, /* Request Service */
|
||||
DVEND = 000100000000, /* Device End */
|
||||
SRTRY = 000200000000, /* Set Retry Counter */
|
||||
STDFL = 000400000000, /* Set Data Flag */
|
||||
STINT = 001000000000, /* Set Interrupt */
|
||||
WRTIO = 002000000000, /* Write TIO Register */
|
||||
FREE = 004000000000 /* Set Interface Free */
|
||||
} CNTLR_IFN;
|
||||
|
||||
#define NO_FUNCTIONS ((CNTLR_IFN) 0) /* no functions are asserted */
|
||||
|
@ -223,13 +234,13 @@ typedef enum { /* interface function bus orders
|
|||
typedef CNTLR_IFN CNTLR_IFN_SET; /* a set of CNTLR_IFNs */
|
||||
|
||||
|
||||
typedef uint16 CNTLR_IBUS; /* the interface data bus */
|
||||
typedef HP_WORD CNTLR_IBUS; /* the interface data bus */
|
||||
|
||||
#undef NO_DATA /* remove winsock definition */
|
||||
#define NO_DATA (CNTLR_IBUS) 0 /* no data asserted */
|
||||
#define NO_DATA ((CNTLR_IBUS) 0) /* no data asserted */
|
||||
|
||||
|
||||
typedef uint32 CNTLR_IFN_IBUS; /* a combined interface function set and data bus value */
|
||||
typedef uint32 CNTLR_IFN_IBUS; /* a combined interface function set and data bus value */
|
||||
|
||||
|
||||
/* Controller opcodes */
|
||||
|
@ -379,7 +390,7 @@ typedef struct {
|
|||
} DELAY_PROPS;
|
||||
|
||||
#define DELAY_INIT(sk1,skf,scf,dxfr,isg,ovhd) \
|
||||
0, 0, \
|
||||
(CNTLR_TYPE) 0, (DRIVE_TYPE) 0, \
|
||||
(sk1), (skf), (scf), (dxfr), (isg), (ovhd)
|
||||
|
||||
|
||||
|
@ -400,16 +411,16 @@ typedef struct {
|
|||
uint32 sector; /* sector address */
|
||||
uint32 count; /* count of words transferred or to verify */
|
||||
uint32 poll_unit; /* last unit polled for attention */
|
||||
uint16 *buffer; /* data buffer pointer */
|
||||
DL_BUFFER *buffer; /* data buffer pointer */
|
||||
uint32 index; /* data buffer current index */
|
||||
uint32 length; /* data buffer valid length */
|
||||
DIAG_ENTRY *dop_base; /* pointer to the diagnostic override array */
|
||||
DIAG_ENTRY *dop; /* current diagnostic override entry pointer */
|
||||
int32 dop_index; /* current diagnostic override entry index */
|
||||
DELAY_PROPS *fastptr; /* pointer to the FASTTIME delays */
|
||||
const DELAY_PROPS *dlyptr; /* current delay property pointer */
|
||||
} CNTLR_VARS;
|
||||
|
||||
typedef CNTLR_VARS *CVPTR; /* pointer to a controller state variable structure */
|
||||
typedef CNTLR_VARS *CVPTR; /* pointer to a controller state variable structure */
|
||||
|
||||
|
||||
/* Controller state variable structure initialization.
|
||||
|
@ -418,7 +429,7 @@ typedef CNTLR_VARS *CVPTR; /* pointer to a controller state
|
|||
|
||||
ctype - the type of the controller (CNTLR_TYPE)
|
||||
dev - the device on which the controller operates (DEVICE)
|
||||
bufptr - a pointer to the data buffer (array of uint16)
|
||||
bufptr - a pointer to the data buffer (array of DL_BUFFER)
|
||||
doa - a pointer to the diagnostic override array (array of DIAG_ENTRY)
|
||||
or NULL if this facility is not used
|
||||
fast - a pointer to the fast timing values (DELAY_PROPS)
|
||||
|
@ -429,52 +440,54 @@ typedef CNTLR_VARS *CVPTR; /* pointer to a controller state
|
|||
CLEAR, FALSE, \
|
||||
0, 0, 0, 0, 0, 0, 0, \
|
||||
(bufptr), 0, 0, \
|
||||
(doa), NULL, \
|
||||
(doa), -1, \
|
||||
&(fast), &(fast)
|
||||
|
||||
|
||||
/* Disc controller device register definitions.
|
||||
|
||||
These definitions should be included AFTER any interface-specific registers.
|
||||
|
||||
The supplied parameters are:
|
||||
|
||||
cntlr - the controller state variable structure (CNTLR_VARS)
|
||||
units - the unit array (array of UNIT)
|
||||
numunits - the number of units in the unit array
|
||||
buffer - the sector buffer (array of uint16)
|
||||
buffer - the sector buffer (array of DL_BUFFER)
|
||||
times - the fast timing values structure (DELAY_PROPS)
|
||||
|
||||
These definitions should be included AFTER any interface-specific registers.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. The "CNTLR" register is present to ensure that the entire CNTLR_VARS
|
||||
structure is saved and restored.
|
||||
1. The CNTLR_VARS fields "type", "device", "buffer", "dop_base", "fastptr",
|
||||
and "dlyptr" do not need to appear in the REG array, as "dlyptr" is reset
|
||||
by the dl_attach routine during a RESTORE, and the others are static.
|
||||
|
||||
2. The fast timing structure does not use the controller and drive type
|
||||
fields, so they do not need to be SAVEd or RESTOREd, so they do not need
|
||||
to appear in hidden registers.
|
||||
fields, so they do not appear in hidden registers, as they need not be
|
||||
SAVEd or RESTOREd.
|
||||
*/
|
||||
|
||||
#define DL_REGS(cntlr,units,numunits,buffer,times) \
|
||||
/* Macro Name Location Radix Width Depth Flags */ \
|
||||
/* ------ -------- ------------------ ----- ----- ----------------- ---------------- */ \
|
||||
{ ORDATA (OPCODE, (cntlr).opcode, 5), REG_RO }, \
|
||||
{ ORDATA (CSTATS, (cntlr).status, 5), REG_RO }, \
|
||||
{ DRDATA (CSTATE, (cntlr).state, 2), PV_LEFT | REG_RO }, \
|
||||
{ FLDATA (EOC, (cntlr).eoc, 0) }, \
|
||||
{ FLDATA (VERIFY, (cntlr).verify, 0) }, \
|
||||
{ ORDATA (SPDU, (cntlr).spd_unit, 16) }, \
|
||||
{ ORDATA (FLMASK, (cntlr).file_mask, 4) }, \
|
||||
{ DRDATA (CYL, (cntlr).cylinder, 16), PV_LEFT }, \
|
||||
{ DRDATA (HEAD, (cntlr).head, 6), PV_LEFT }, \
|
||||
{ DRDATA (SECTOR, (cntlr).sector, 8), PV_LEFT }, \
|
||||
{ DRDATA (COUNT, (cntlr).count, 16), PV_LEFT }, \
|
||||
{ BRDATA (SECBUF, (buffer), 8, 16, DL_BUFSIZE), REG_A }, \
|
||||
{ DRDATA (INDEX, (cntlr).index, 8), PV_LEFT }, \
|
||||
{ DRDATA (LENGTH, (cntlr).length, 8), PV_LEFT }, \
|
||||
{ SRDATA (CNTLR, (cntlr)), REG_HRO }, \
|
||||
\
|
||||
/* Macro Name Location Radix Width Depth Flags */ \
|
||||
/* ------ -------- ------------------ ----- ----- ----------------- ----------------- */ \
|
||||
{ ORDATA (OPCODE, (cntlr).opcode, 5), REG_RO }, \
|
||||
{ ORDATA (CSTATS, (cntlr).status, 5), REG_RO }, \
|
||||
{ DRDATA (CSTATE, (cntlr).state, 2), PV_LEFT | REG_RO }, \
|
||||
{ FLDATA (EOC, (cntlr).eoc, 0) }, \
|
||||
{ FLDATA (VERIFY, (cntlr).verify, 0) }, \
|
||||
{ ORDATA (SPDU, (cntlr).spd_unit, 16) }, \
|
||||
{ ORDATA (FLMASK, (cntlr).file_mask, 4) }, \
|
||||
{ DRDATA (CYL, (cntlr).cylinder, 16), PV_LEFT }, \
|
||||
{ DRDATA (HEAD, (cntlr).head, 6), PV_LEFT }, \
|
||||
{ DRDATA (SECTOR, (cntlr).sector, 8), PV_LEFT }, \
|
||||
{ DRDATA (COUNT, (cntlr).count, 16), PV_LEFT }, \
|
||||
{ BRDATA (SECBUF, (buffer), 8, 16, DL_BUFSIZE), REG_A }, \
|
||||
{ DRDATA (INDEX, (cntlr).index, 8), PV_LEFT }, \
|
||||
{ DRDATA (LENGTH, (cntlr).length, 8), PV_LEFT }, \
|
||||
{ DRDATA (POLLU, (cntlr).poll_unit, 4), REG_HRO }, \
|
||||
{ DRDATA (DOINDX, (cntlr).dop_index, 16), PV_LEFT | REG_HRO }, \
|
||||
\
|
||||
/* Macro Name Location Width Flags */ \
|
||||
/* ------ ------ ------------------------ ----- ---------------- */ \
|
||||
{ DRDATA (TTIME, (times).seek_one, 24), PV_LEFT | REG_NZ }, \
|
||||
|
|
|
@ -24,7 +24,14 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from the authors.
|
||||
|
||||
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
|
||||
08-Jun-16 JDB Corrected %d format to %u for unsigned values
|
||||
16-May-16 JDB TAPELIB_PROPERTIES.action is now a pointer-to-constant
|
||||
13-May-16 JDB Modified for revised SCP API function parameter types
|
||||
03-May-16 JDB Changed clear/attach/on/offline trace from INCO to CMD
|
||||
24-Mar-16 JDB Changed the buffer element type from uint8 to TL_BUFFER
|
||||
21-Mar-16 JDB Changed uint16 types to HP_WORD
|
||||
20-Nov-15 JDB First release version
|
||||
24-Mar-13 JDB Created tape controller common library from MS simulator
|
||||
|
||||
|
@ -338,7 +345,7 @@
|
|||
|
||||
/* Unit flags accessor */
|
||||
|
||||
#define GET_MODEL(f) ((f) >> UNIT_MODEL_SHIFT & UNIT_MODEL_MASK)
|
||||
#define GET_MODEL(f) (DRIVE_TYPE) ((f) >> UNIT_MODEL_SHIFT & UNIT_MODEL_MASK)
|
||||
|
||||
|
||||
/* Per-unit property flags and accessors.
|
||||
|
@ -378,10 +385,10 @@
|
|||
#define PROP_UNIT_SHIFT 10 /* bits 12-10 */
|
||||
#define PROP_MODEL_SHIFT 13 /* bits 15-13 */
|
||||
|
||||
#define PROP_INDEX_MASK ((1 << PROP_INDEX_WIDTH) - 1 << PROP_INDEX_SHIFT)
|
||||
#define PROP_REEL_MASK ((1 << PROP_REEL_WIDTH) - 1 << PROP_REEL_SHIFT)
|
||||
#define PROP_UNIT_MASK ((1 << PROP_UNIT_WIDTH) - 1 << PROP_UNIT_SHIFT)
|
||||
#define PROP_MODEL_MASK ((1 << PROP_MODEL_WIDTH) - 1 << PROP_MODEL_SHIFT)
|
||||
#define PROP_INDEX_MASK ((1u << PROP_INDEX_WIDTH) - 1 << PROP_INDEX_SHIFT)
|
||||
#define PROP_REEL_MASK ((1u << PROP_REEL_WIDTH) - 1 << PROP_REEL_SHIFT)
|
||||
#define PROP_UNIT_MASK ((1u << PROP_UNIT_WIDTH) - 1 << PROP_UNIT_SHIFT)
|
||||
#define PROP_MODEL_MASK ((1u << PROP_MODEL_WIDTH) - 1 << PROP_MODEL_SHIFT)
|
||||
|
||||
#define PROP_INDEX(u) (((u)->PROP & PROP_INDEX_MASK) >> PROP_INDEX_SHIFT)
|
||||
#define PROP_REEL(u) (((u)->PROP & PROP_REEL_MASK) >> PROP_REEL_SHIFT)
|
||||
|
@ -758,9 +765,9 @@ typedef enum {
|
|||
|
||||
|
||||
typedef struct {
|
||||
t_bool gap_is_valid; /* call may involve an erase gap */
|
||||
t_bool data_is_valid; /* call may involve a data record */
|
||||
char *action; /* string describing the call action */
|
||||
t_bool gap_is_valid; /* call may involve an erase gap */
|
||||
t_bool data_is_valid; /* call may involve a data record */
|
||||
const char *action; /* string describing the call action */
|
||||
} TAPELIB_PROPERTIES;
|
||||
|
||||
|
||||
|
@ -911,7 +918,7 @@ return outbound;
|
|||
|
||||
t_stat tl_onoffline (CVPTR cvptr, UNIT *uptr, t_bool online)
|
||||
{
|
||||
const uint32 unit = uptr - cvptr->device->units; /* the unit number */
|
||||
const int32 unit = (int32) (uptr - cvptr->device->units); /* the unit number */
|
||||
t_stat status = SCPE_OK;
|
||||
|
||||
if (uptr->flags & UNIT_ATT) { /* if the unit is attached */
|
||||
|
@ -924,7 +931,7 @@ if (uptr->flags & UNIT_ATT) { /* if the unit is attach
|
|||
status = SCPE_INCOMP; /* then it must be called to poll the drives */
|
||||
}
|
||||
|
||||
dpprintf (cvptr->device, TL_DEB_INCO, "Unit %d set %s\n",
|
||||
dpprintf (cvptr->device, TL_DEB_CMD, "Unit %d set %s\n",
|
||||
unit, (online ? "online" : "offline"));
|
||||
}
|
||||
|
||||
|
@ -985,7 +992,7 @@ return status;
|
|||
busy" status and the complement of the SL signal as "unit local" status.
|
||||
*/
|
||||
|
||||
uint16 tl_status (CVPTR cvptr)
|
||||
HP_WORD tl_status (CVPTR cvptr)
|
||||
{
|
||||
UNIT *const uptr = cvptr->device->units + cvptr->unit_selected; /* a pointer to the selected unit */
|
||||
uint32 status;
|
||||
|
@ -1131,7 +1138,7 @@ for (unit = 0; unit < cvptr->device->numunits; unit++) { /* look for a write
|
|||
if (remaining_time) { /* if the unit is currently active */
|
||||
if (uptr->flags & UNIT_REWINDING) /* then a clear does not affect a rewind in progress */
|
||||
dpprintf (cvptr->device, TL_DEB_INCO,
|
||||
"Unit %d controller clear allowed %s to continue\n",
|
||||
"Unit %u controller clear allowed %s to continue\n",
|
||||
unit, opcode_names [uptr->OPCODE]);
|
||||
|
||||
else { /* but all other commands are aborted */
|
||||
|
@ -1147,7 +1154,7 @@ for (unit = 0; unit < cvptr->device->numunits; unit++) { /* look for a write
|
|||
else /* otherwise */
|
||||
reset_position = cvptr->initial_position + relative_position; /* move toward the EOT */
|
||||
|
||||
cvptr->gaplen -= relative_position; /* reduce the gap length by the amount not traversed */
|
||||
cvptr->gaplen -= (t_mtrlnt) relative_position; /* reduce the gap length by the amount not traversed */
|
||||
|
||||
while (cvptr->gaplen > sizeof (t_mtrlnt)) { /* align the reset position to a gap marker */
|
||||
if (sim_fseek (uptr->fileref, /* seek to the reset position */
|
||||
|
@ -1173,13 +1180,13 @@ for (unit = 0; unit < cvptr->device->numunits; unit++) { /* look for a write
|
|||
};
|
||||
|
||||
dpprintf (cvptr->device, TL_DEB_INCO,
|
||||
"Unit %d controller clear stopped tape motion at position %d\n",
|
||||
"Unit %u controller clear stopped tape motion at position %" T_ADDR_FMT "u\n",
|
||||
unit, uptr->pos);
|
||||
}
|
||||
|
||||
else /* otherwise FASTTIME mode is selected */
|
||||
dpprintf (cvptr->device, TL_DEB_INCO,
|
||||
"Unit %d controller clear aborted %s after partial completion\n",
|
||||
"Unit %u controller clear aborted %s after partial completion\n",
|
||||
unit, opcode_names [uptr->OPCODE]);
|
||||
|
||||
if (cmd_props [uptr->OPCODE].class == Class_Write /* if the last command was a write */
|
||||
|
@ -1199,7 +1206,7 @@ for (unit = 0; unit < cvptr->device->numunits; unit++) { /* look for a write
|
|||
|
||||
if (uptr->OPCODE != Clear_Controller) /* report the abort only if this isn't a clear command */
|
||||
dpprintf (cvptr->device, TL_DEB_INCO,
|
||||
"Unit %d controller clear aborted %s after partial completion\n",
|
||||
"Unit %u controller clear aborted %s after partial completion\n",
|
||||
unit, opcode_names [uptr->OPCODE]);
|
||||
}
|
||||
}
|
||||
|
@ -1211,7 +1218,7 @@ cvptr->unit_attention = 0; /* clear any pending uni
|
|||
if (cvptr->type == HP_30215) /* if this is the 3000 controller */
|
||||
cvptr->unit_selected = 0; /* then a clear selects unit 0 */
|
||||
|
||||
dpprintf (cvptr->device, TL_DEB_INCO, "Controller cleared\n");
|
||||
dpprintf (cvptr->device, TL_DEB_CMD, "Controller cleared\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -1242,7 +1249,7 @@ else /* otherwise */
|
|||
unit is invalid, an error string is returned.
|
||||
*/
|
||||
|
||||
const char *tl_unit_name (uint32 unit)
|
||||
const char *tl_unit_name (int32 unit)
|
||||
{
|
||||
if (unit <= TL_CNTLR_UNIT) /* if the unit number is valid */
|
||||
return unit_names [unit]; /* then return the unit designator */
|
||||
|
@ -1266,6 +1273,7 @@ else /* otherwise */
|
|||
polled automatically when the current command completes and the controller is
|
||||
idled.
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. The support library LOCKED and WRITEENABLED modifiers are not used to
|
||||
|
@ -1278,11 +1286,15 @@ else /* otherwise */
|
|||
|
||||
2. If we are called during a RESTORE command, the unit's flags are not
|
||||
changed to avoid upsetting the state that was SAVEd.
|
||||
|
||||
3. The pointer to the appropriate event delay times is set in case we are
|
||||
being called during a RESTORE command (the assignment is redundant
|
||||
otherwise).
|
||||
*/
|
||||
|
||||
t_stat tl_attach (CVPTR cvptr, UNIT *uptr, CONST char *cptr)
|
||||
{
|
||||
const uint32 unit = uptr - cvptr->device->units; /* the unit number */
|
||||
const int32 unit = (int32) (uptr - cvptr->device->units); /* the unit number */
|
||||
t_stat result;
|
||||
|
||||
result = sim_tape_attach (uptr, cptr); /* attach the tape image file to the unit */
|
||||
|
@ -1298,13 +1310,18 @@ if (result == SCPE_OK /* if the attach was suc
|
|||
|
||||
cvptr->unit_attention |= 1 << unit; /* drive attention sets on tape load */
|
||||
|
||||
dpprintf (cvptr->device, TL_DEB_INCO, "Unit %d tape loaded and set online\n",
|
||||
dpprintf (cvptr->device, TL_DEB_CMD, "Unit %d tape loaded and set online\n",
|
||||
unit);
|
||||
|
||||
if (cvptr->state == Idle_State) /* if the controller is idle */
|
||||
result = SCPE_INCOMP; /* then it must be called to poll the drives */
|
||||
}
|
||||
|
||||
if (cvptr->device->flags & DEV_REALTIME) /* if realistic timing is selected */
|
||||
cvptr->dlyptr = &real_times [PROP_INDEX (uptr)]; /* then get the real times pointer for this drive */
|
||||
else /* otherwise optimized timing is selected */
|
||||
cvptr->dlyptr = cvptr->fastptr; /* so use the fast times pointer */
|
||||
|
||||
return result; /* return the result of the attach */
|
||||
}
|
||||
|
||||
|
@ -1521,7 +1538,7 @@ return SCPE_OK;
|
|||
|
||||
t_stat tl_show_density (FILE *st, UNIT *uptr, int32 value, CONST void *desc)
|
||||
{
|
||||
fprintf (st, "%d bpi", drive_props [PROP_INDEX (uptr)].bpi);
|
||||
fprintf (st, "%u bpi", drive_props [PROP_INDEX (uptr)].bpi);
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -2018,6 +2035,10 @@ return outbound; /* return the functions
|
|||
the unit is online. The status cannot be inferred from the command, as
|
||||
the user may have set the unit offline or online explicitly before the
|
||||
rewind completed.
|
||||
|
||||
18. The "%.0u" print specification in the trace call absorbs the zero
|
||||
"length" value parameter without printing when the controller unit is
|
||||
specified.
|
||||
*/
|
||||
|
||||
static CNTLR_IFN_IBUS continue_command (CVPTR cvptr, UNIT *uptr, CNTLR_FLAG_SET inbound_flags, CNTLR_IBUS inbound_data)
|
||||
|
@ -2025,15 +2046,15 @@ static CNTLR_IFN_IBUS continue_command (CVPTR cvptr, UNIT *uptr, CNTLR_FLAG_SET
|
|||
const CNTLR_OPCODE opcode = (CNTLR_OPCODE) uptr->OPCODE; /* the current command opcode */
|
||||
const CNTLR_PHASE phase = (CNTLR_PHASE) uptr->PHASE; /* the current command phase */
|
||||
const t_bool service_entry = (phase > Wait_Phase); /* TRUE if entered via unit service */
|
||||
uint32 unit;
|
||||
uint8 data_byte;
|
||||
int32 unit;
|
||||
TL_BUFFER data_byte;
|
||||
t_mtrlnt error_flag;
|
||||
BYTE_SELECTOR selector;
|
||||
DRIVE_PROPS const *pptr;
|
||||
CNTLR_IFN_IBUS outbound = NO_ACTION;
|
||||
t_bool complete = FALSE;
|
||||
|
||||
unit = uptr - cvptr->device->units; /* get the unit number */
|
||||
unit = (int32) (uptr - cvptr->device->units); /* get the unit number */
|
||||
|
||||
dpprintf (cvptr->device, TL_DEB_STATE, "%s %s %s phase entered from %s\n",
|
||||
unit_names [unit], opcode_names [opcode], phase_names [phase],
|
||||
|
@ -2055,7 +2076,7 @@ switch (phase) { /* dispatch the phase */
|
|||
uptr->OPCODE = Invalid_Opcode; /* so clear the controller command */
|
||||
uptr->PHASE = Idle_Phase; /* and idle the unit */
|
||||
|
||||
unit = cvptr->unit_selected; /* get the selected unit number */
|
||||
unit = (int32) cvptr->unit_selected; /* get the selected unit number */
|
||||
uptr = cvptr->device->units + unit; /* and unit pointer */
|
||||
|
||||
uptr->PHASE = Start_Phase; /* set up the start phase */
|
||||
|
@ -2070,7 +2091,7 @@ switch (phase) { /* dispatch the phase */
|
|||
|
||||
|
||||
case Start_Phase:
|
||||
dpprintf (cvptr->device, TL_DEB_INCO, "Unit %d %s started at position %d\n",
|
||||
dpprintf (cvptr->device, TL_DEB_INCO, "Unit %d %s started at position %" T_ADDR_FMT "u\n",
|
||||
unit, opcode_names [opcode], uptr->pos);
|
||||
|
||||
pptr = &drive_props [PROP_INDEX (uptr)]; /* get the drive property pointer */
|
||||
|
@ -2204,7 +2225,7 @@ switch (phase) { /* dispatch the phase */
|
|||
uptr->PHASE = Traverse_Phase; /* and proceed to the rewinding phase */
|
||||
|
||||
uptr->wait = /* base the traversal time on the current tape position */
|
||||
(uptr->pos * cvptr->dlyptr->rewind_rate) / pptr->bpi;
|
||||
(int32) ((uptr->pos * cvptr->dlyptr->rewind_rate) / pptr->bpi);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -2314,7 +2335,7 @@ switch (phase) { /* dispatch the phase */
|
|||
outbound = /* then transfer one byte at a time */
|
||||
cvptr->buffer [cvptr->index++]; /* to the data register */
|
||||
|
||||
dpprintf (cvptr->device, TL_DEB_XFER, "Unit %d %s byte %d is %03o\n",
|
||||
dpprintf (cvptr->device, TL_DEB_XFER, "Unit %d %s byte %u is %03o\n",
|
||||
unit, opcode_names [opcode],
|
||||
cvptr->index, outbound);
|
||||
|
||||
|
@ -2329,7 +2350,7 @@ switch (phase) { /* dispatch the phase */
|
|||
outbound |= /* then merge in the low byte */
|
||||
cvptr->buffer [cvptr->index++];
|
||||
|
||||
dpprintf (cvptr->device, TL_DEB_XFER, "Unit %d %s word %d is %06o\n",
|
||||
dpprintf (cvptr->device, TL_DEB_XFER, "Unit %d %s word %u is %06o\n",
|
||||
unit, opcode_names [opcode],
|
||||
(cvptr->index + 1) / 2, outbound);
|
||||
|
||||
|
@ -2361,7 +2382,7 @@ switch (phase) { /* dispatch the phase */
|
|||
|
||||
uptr->wait = cvptr->dlyptr->data_xfer; /* schedule the next byte transfer */
|
||||
|
||||
dpprintf (cvptr->device, TL_DEB_XFER, "Unit %d %s byte %d is %06o\n",
|
||||
dpprintf (cvptr->device, TL_DEB_XFER, "Unit %d %s byte %u is %06o\n",
|
||||
unit, opcode_names [opcode],
|
||||
cvptr->index, inbound_data);
|
||||
}
|
||||
|
@ -2388,7 +2409,7 @@ switch (phase) { /* dispatch the phase */
|
|||
|
||||
uptr->wait = 2 * cvptr->dlyptr->data_xfer; /* schedule the next word transfer */
|
||||
|
||||
dpprintf (cvptr->device, TL_DEB_XFER, "Unit %d %s word %d is %06o\n",
|
||||
dpprintf (cvptr->device, TL_DEB_XFER, "Unit %d %s word %u is %06o\n",
|
||||
unit, opcode_names [opcode],
|
||||
(cvptr->index + 1) / 2, inbound_data);
|
||||
}
|
||||
|
@ -2536,8 +2557,8 @@ switch (phase) { /* dispatch the phase */
|
|||
|
||||
case Rewind:
|
||||
case Rewind_Offline:
|
||||
if ((uptr->flags & UNIT_OFFLINE) == 0) /* if the unit is online */
|
||||
cvptr->unit_attention |= 1 << unit; /* then attention sets on rewind completion */
|
||||
if ((uptr->flags & UNIT_OFFLINE) == 0) /* if the unit is online */
|
||||
cvptr->unit_attention |= 1u << unit; /* then attention sets on rewind completion */
|
||||
|
||||
uptr->flags &= ~UNIT_REWINDING; /* clear rewinding status */
|
||||
|
||||
|
@ -2586,12 +2607,12 @@ if (uptr->wait != NO_EVENT) /* if the unit has been
|
|||
|
||||
if (complete) { /* if the command is complete */
|
||||
dpprintf (cvptr->device, TL_DEB_INCO, /* then report the final tape position */
|
||||
"Unit %d %s completed at position %d\n",
|
||||
"Unit %d %s completed at position %" T_ADDR_FMT "u\n",
|
||||
unit, opcode_names [opcode], uptr->pos);
|
||||
|
||||
dpprintf (cvptr->device, TL_DEB_CMD, (cvptr->length > 0
|
||||
? "Unit %d %s of %d-byte record %s\n"
|
||||
: "Unit %d %s %.0d%s\n"),
|
||||
? "Unit %d %s of %u-byte record %s\n"
|
||||
: "Unit %d %s %.0u%s\n"),
|
||||
unit, opcode_names [opcode], cvptr->length,
|
||||
status_name [cvptr->call_status]);
|
||||
}
|
||||
|
@ -2660,7 +2681,7 @@ while (cvptr->unit_attention) /* loop through the atte
|
|||
if (cvptr->unit_attention & 1 << unit) { /* looking for the first one set */
|
||||
cvptr->unit_attention &= ~(1 << unit); /* and then clear it */
|
||||
|
||||
dpprintf (cvptr->device, TL_DEB_INCO, "Unit %d requested attention\n",
|
||||
dpprintf (cvptr->device, TL_DEB_INCO, "Unit %u requested attention\n",
|
||||
unit);
|
||||
|
||||
cvptr->unit_selected = unit; /* select the unit requesting attention */
|
||||
|
@ -2761,7 +2782,8 @@ return NO_ACTION; /* no drives are request
|
|||
static CNTLR_IFN_IBUS call_tapelib (CVPTR cvptr, UNIT *uptr, TAPELIB_CALL lib_call, t_mtrlnt parameter)
|
||||
{
|
||||
t_bool do_gap, do_data;
|
||||
uint32 unit, gap_inches, gap_tenths;
|
||||
int32 unit;
|
||||
uint32 gap_inches, gap_tenths;
|
||||
CNTLR_IFN_IBUS result = (CNTLR_IFN_IBUS) NO_FUNCTIONS; /* the expected case */
|
||||
|
||||
switch (lib_call) { /* dispatch to the selected routine */
|
||||
|
@ -2806,10 +2828,10 @@ switch (lib_call) { /* dispatch to the selec
|
|||
}
|
||||
|
||||
|
||||
if (cvptr->initial_position < uptr->pos) /* calculate the preliminary gap size */
|
||||
cvptr->gaplen = uptr->pos - cvptr->initial_position; /* for either forward motion */
|
||||
else /* or */
|
||||
cvptr->gaplen = cvptr->initial_position - uptr->pos; /* for reverse motion */
|
||||
if (cvptr->initial_position < uptr->pos) /* calculate the preliminary gap size */
|
||||
cvptr->gaplen = (t_mtrlnt) (uptr->pos - cvptr->initial_position); /* for either forward motion */
|
||||
else /* or */
|
||||
cvptr->gaplen = (t_mtrlnt) (cvptr->initial_position - uptr->pos); /* for reverse motion */
|
||||
|
||||
switch (cvptr->call_status) { /* dispatch on the call status */
|
||||
|
||||
|
@ -2911,7 +2933,7 @@ switch (cvptr->call_status) { /* dispatch on the call
|
|||
|
||||
|
||||
if (DPPRINTING (cvptr->device, TL_DEB_INCO)) { /* if tracing is enabled */
|
||||
unit = uptr - cvptr->device->units; /* then get the unit number */
|
||||
unit = (int32) (uptr - cvptr->device->units); /* then get the unit number */
|
||||
|
||||
do_data = /* TRUE if the data record length is valid and present */
|
||||
lib_props [lib_call].data_is_valid && cvptr->length > 0;
|
||||
|
@ -2928,7 +2950,7 @@ if (DPPRINTING (cvptr->device, TL_DEB_INCO)) { /* if tracing is enabled
|
|||
|
||||
if (do_gap && do_data) /* if both gap and data are present */
|
||||
hp_debug (cvptr->device, TL_DEB_INCO, /* then report both objects */
|
||||
"Unit %d %s call of %d.%d-inch erase gap and %d-word record %s\n",
|
||||
"Unit %d %s call of %u.%u-inch erase gap and %u-word record %s\n",
|
||||
unit, lib_props [lib_call].action,
|
||||
gap_inches, gap_tenths, /* using the movement calculated above */
|
||||
(cvptr->length + 1) / 2,
|
||||
|
@ -2936,14 +2958,14 @@ if (DPPRINTING (cvptr->device, TL_DEB_INCO)) { /* if tracing is enabled
|
|||
|
||||
else if (do_data) /* otherwise if data only are present */
|
||||
hp_debug (cvptr->device, TL_DEB_INCO, /* then report the record length */
|
||||
"Unit %d %s call of %d-word record %s\n",
|
||||
"Unit %d %s call of %u-word record %s\n",
|
||||
unit, lib_props [lib_call].action,
|
||||
(cvptr->length + 1) / 2,
|
||||
status_name [cvptr->call_status]);
|
||||
|
||||
else if (do_gap) /* otherwise if motion only is present */
|
||||
hp_debug (cvptr->device, TL_DEB_INCO, /* then report it */
|
||||
"Unit %d %s call of %d.%d%s %s\n",
|
||||
"Unit %d %s call of %u.%u%s %s\n",
|
||||
unit, lib_props [lib_call].action,
|
||||
gap_inches, gap_tenths,
|
||||
(lib_call == lib_rewind ? " inches" : "-inch erase gap"),
|
||||
|
@ -3002,17 +3024,13 @@ return SCP_STATUS (status); /* with the appropriat
|
|||
|
||||
static void reject_command (CVPTR cvptr, UNIT *uptr)
|
||||
{
|
||||
uint32 unit;
|
||||
|
||||
if (uptr) /* if a command is currently executing */
|
||||
uptr->PHASE = Idle_Phase; /* then idle the tape drive */
|
||||
else /* otherwise a command is attempting to start */
|
||||
uptr = CNTLR_UPTR; /* so set up action on the controller unit */
|
||||
|
||||
unit = uptr - cvptr->device->units; /* determine the unit number for tracing */
|
||||
|
||||
dpprintf (cvptr->device, TL_DEB_CMD, "%s %s command rejected\n",
|
||||
unit_names [unit], opcode_names [uptr->OPCODE]);
|
||||
unit_names [uptr - cvptr->device->units], opcode_names [uptr->OPCODE]);
|
||||
|
||||
cvptr->status = CST_REJECT; /* set the Command Reject status */
|
||||
cvptr->state = Error_State;
|
||||
|
@ -3067,8 +3085,8 @@ return;
|
|||
|
||||
static void add_crcc_lrcc (CVPTR cvptr, CNTLR_OPCODE opcode)
|
||||
{
|
||||
uint32 index;
|
||||
uint16 byte, crc, lrc;
|
||||
uint32 index;
|
||||
HP_WORD byte, crc, lrc;
|
||||
|
||||
crc = 0; /* initialize the CRC */
|
||||
lrc = 0; /* and LRC accumulators */
|
||||
|
@ -3126,10 +3144,9 @@ return;
|
|||
|
||||
static void activate_unit (CVPTR cvptr, UNIT *uptr)
|
||||
{
|
||||
const uint32 unit = uptr - cvptr->device->units; /* the unit number */
|
||||
|
||||
dpprintf (cvptr->device, TL_DEB_STATE, "%s %s %s phase delay %d service scheduled\n",
|
||||
unit_names [unit], opcode_names [uptr->OPCODE], phase_names [uptr->PHASE],
|
||||
unit_names [uptr - cvptr->device->units],
|
||||
opcode_names [uptr->OPCODE], phase_names [uptr->PHASE],
|
||||
uptr->wait);
|
||||
|
||||
sim_activate (uptr, uptr->wait); /* activate the unit */
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
this Software without prior written authorization from the authors.
|
||||
|
||||
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
|
||||
21-Mar-16 JDB Changed uint16 types to HP_WORD
|
||||
11-Nov-15 JDB First release version
|
||||
24-Mar-13 JDB Created tape controller common library from MS simulator
|
||||
|
||||
|
@ -42,6 +44,15 @@
|
|||
|
||||
|
||||
|
||||
/* Architectural constants.
|
||||
|
||||
The type of the tape buffer element is defined. This must be an 8-bit array
|
||||
for compatibility with the simulator tape support library (sim_tape).
|
||||
*/
|
||||
|
||||
typedef uint8 TL_BUFFER; /* a buffer containing 8-bit tape data words */
|
||||
|
||||
|
||||
/* Program limits */
|
||||
|
||||
#define TL_MAXDRIVE 3 /* last valid drive number */
|
||||
|
@ -54,12 +65,12 @@
|
|||
|
||||
/* Debug flags */
|
||||
|
||||
#define TL_DEB_CMD (1 << 0) /* trace controller commands */
|
||||
#define TL_DEB_INCO (1 << 1) /* trace command initiations and completions */
|
||||
#define TL_DEB_STATE (1 << 2) /* trace command execution state changes */
|
||||
#define TL_DEB_SERV (1 << 3) /* trace unit service scheduling calls */
|
||||
#define TL_DEB_XFER (1 << 4) /* trace data reads and writes */
|
||||
#define TL_DEB_IOB (1 << 5) /* trace I/O bus signals and data words */
|
||||
#define TL_DEB_CMD (1u << 0) /* trace controller commands */
|
||||
#define TL_DEB_INCO (1u << 1) /* trace command initiations and completions */
|
||||
#define TL_DEB_STATE (1u << 2) /* trace command execution state changes */
|
||||
#define TL_DEB_SERV (1u << 3) /* trace unit service scheduling calls */
|
||||
#define TL_DEB_XFER (1u << 4) /* trace data reads and writes */
|
||||
#define TL_DEB_IOB (1u << 5) /* trace I/O bus signals and data words */
|
||||
#define TL_DEB_V_UF 6 /* first free debug flag bit */
|
||||
|
||||
|
||||
|
@ -109,11 +120,11 @@
|
|||
|
||||
#define TL_UNIT_V_UF (MTUF_V_UF + 5) /* first free unit flag bit */
|
||||
|
||||
#define UNIT_MODEL_MASK 0000007 /* model ID mask */
|
||||
#define UNIT_MODEL_MASK 0000007u /* model ID mask */
|
||||
|
||||
#define UNIT_MODEL (UNIT_MODEL_MASK << UNIT_MODEL_SHIFT)
|
||||
#define UNIT_OFFLINE (1 << UNIT_OFFLINE_SHIFT)
|
||||
#define UNIT_REWINDING (1 << UNIT_REW_SHIFT)
|
||||
#define UNIT_OFFLINE (1u << UNIT_OFFLINE_SHIFT)
|
||||
#define UNIT_REWINDING (1u << UNIT_REW_SHIFT)
|
||||
|
||||
#define UNIT_7970B (HP_7970B << UNIT_MODEL_SHIFT)
|
||||
#define UNIT_7970E (HP_7970E << UNIT_MODEL_SHIFT)
|
||||
|
@ -216,7 +227,7 @@ typedef enum { /* interface function bus orders
|
|||
typedef CNTLR_IFN CNTLR_IFN_SET; /* a set of CNTLR_IFNs */
|
||||
|
||||
|
||||
typedef uint16 CNTLR_IBUS; /* the interface data bus */
|
||||
typedef HP_WORD CNTLR_IBUS; /* the interface data bus */
|
||||
|
||||
#undef NO_DATA /* remove winsock definition */
|
||||
#define NO_DATA (CNTLR_IBUS) 0 /* no data asserted */
|
||||
|
@ -344,7 +355,7 @@ typedef struct {
|
|||
(rstart), (rrate), (rstop), (bot), (ir), (dxfr), (ovhd)
|
||||
|
||||
|
||||
/* Tape controller state variable structure */
|
||||
/* Tape controller state */
|
||||
|
||||
typedef struct {
|
||||
CNTLR_TYPE type; /* controller type */
|
||||
|
@ -353,7 +364,7 @@ typedef struct {
|
|||
uint32 status; /* controller status */
|
||||
uint32 unit_selected; /* unit number currently selected */
|
||||
uint32 unit_attention; /* bitmap of units needing attention */
|
||||
uint8 *buffer; /* data buffer pointer */
|
||||
TL_BUFFER *buffer; /* data buffer pointer */
|
||||
t_stat call_status; /* simulator tape support library call status */
|
||||
t_mtrlnt length; /* data buffer valid length */
|
||||
t_mtrlnt index; /* data buffer current index */
|
||||
|
@ -372,7 +383,7 @@ typedef CNTLR_VARS *CVPTR; /* a pointer to a controller sta
|
|||
|
||||
ctype - the type of the controller (CNTLR_TYPE)
|
||||
dev - the device on which the controller operates (DEVICE)
|
||||
bufptr - a pointer to the data buffer (array of uint8)
|
||||
bufptr - a pointer to the data buffer (array of TL_BUFFER)
|
||||
fast - a pointer to the fast timing values (DELAY_PROPS)
|
||||
*/
|
||||
|
||||
|
@ -391,31 +402,31 @@ typedef CNTLR_VARS *CVPTR; /* a pointer to a controller sta
|
|||
cntlr -- the controller state variable structure (CNTLR_VARS)
|
||||
units -- the unit array (array of UNIT)
|
||||
numunits -- the number of tape drive units
|
||||
buffer -- the buffer array (array of uint8)
|
||||
buffer -- the buffer array (array of TL_BUFFER)
|
||||
times -- the structure containing the fast delay time values (DELAY_PROPS)
|
||||
|
||||
|
||||
Implementation notes:
|
||||
|
||||
1. The "CNTLR" register is present to ensure that the entire CNTLR_VARS
|
||||
structure is saved and restored.
|
||||
1. The CNTLR_VARS fields "type", "device", "buffer", "fastptr", and "dlyptr"
|
||||
do not need to appear in the REG array, as "dlyptr" is reset by the
|
||||
tl_attach routine during a RESTORE, and the others are static.
|
||||
*/
|
||||
|
||||
#define TL_REGS(cntlr,units,numunits,buffer,times) \
|
||||
/* Macro Name Location Radix Width Depth Flags */ \
|
||||
/* ------ ------ ------------------------ ----- -------- --------------- ----------------- */ \
|
||||
{ DRDATA (CSTATE, (cntlr).state, 4), PV_LEFT | REG_RO }, \
|
||||
{ ORDATA (STATUS, (cntlr).status, 16), REG_RO }, \
|
||||
{ DRDATA (USEL, (cntlr).unit_selected, 4), PV_LEFT | REG_RO }, \
|
||||
{ YRDATA (UATTN, (cntlr).unit_attention, 4) }, \
|
||||
{ BRDATA (RECBUF, (buffer), 8, 8, TL_BUFSIZE), REG_A }, \
|
||||
{ DRDATA (LIBSTA, (cntlr).call_status, 16), PV_LEFT }, \
|
||||
{ DRDATA (LENGTH, (cntlr).length, 24), PV_LEFT }, \
|
||||
{ DRDATA (INDEX, (cntlr).index, 24), PV_LEFT }, \
|
||||
{ DRDATA (GAPLEN, (cntlr).gaplen, 32), PV_LEFT }, \
|
||||
{ DRDATA (INPOS, (cntlr).initial_position, T_ADDR_W), PV_LEFT }, \
|
||||
{ SRDATA (CNTLR, (cntlr)), REG_HRO }, \
|
||||
\
|
||||
/* Macro Name Location Radix Width Depth Flags */ \
|
||||
/* ------ ------ ------------------------ ----- -------- --------------- ----------------- */ \
|
||||
{ DRDATA (CSTATE, (cntlr).state, 4), PV_LEFT | REG_RO }, \
|
||||
{ ORDATA (STATUS, (cntlr).status, 16), REG_RO }, \
|
||||
{ DRDATA (USEL, (cntlr).unit_selected, 4), PV_LEFT | REG_RO }, \
|
||||
{ YRDATA (UATTN, (cntlr).unit_attention, 4, PV_RZRO) }, \
|
||||
{ BRDATA (RECBUF, (buffer), 8, 8, TL_BUFSIZE), REG_A }, \
|
||||
{ DRDATA (LIBSTA, (cntlr).call_status, 16), PV_LEFT }, \
|
||||
{ DRDATA (LENGTH, (cntlr).length, 24), PV_LEFT }, \
|
||||
{ DRDATA (INDEX, (cntlr).index, 24), PV_LEFT }, \
|
||||
{ DRDATA (GAPLEN, (cntlr).gaplen, 32), PV_LEFT }, \
|
||||
{ DRDATA (INPOS, (cntlr).initial_position, T_ADDR_W), PV_LEFT }, \
|
||||
\
|
||||
/* Macro Name Location Width Flags */ \
|
||||
/* ------ ------- -------------------- ----- ---------------- */ \
|
||||
{ DRDATA (RSTART, (times).rewind_start, 24), PV_LEFT | REG_NZ }, \
|
||||
|
@ -462,17 +473,17 @@ typedef CNTLR_VARS *CVPTR; /* a pointer to a controller sta
|
|||
|
||||
/* Selectable drive type flags */
|
||||
|
||||
#define TL_7970B (1 << HP_7970B)
|
||||
#define TL_7970E (1 << HP_7970E)
|
||||
#define TL_7974 (1 << HP_7974)
|
||||
#define TL_7978 (1 << HP_7978)
|
||||
#define TL_7970B (1u << HP_7970B)
|
||||
#define TL_7970E (1u << HP_7970E)
|
||||
#define TL_7974 (1u << HP_7974)
|
||||
#define TL_7978 (1u << HP_7978)
|
||||
|
||||
/* Selectable drive density flags */
|
||||
|
||||
#define TL_FIXED 0
|
||||
#define TL_800 (1 << MT_DENS_800)
|
||||
#define TL_1600 (1 << MT_DENS_1600)
|
||||
#define TL_6250 (1 << MT_DENS_6250)
|
||||
#define TL_800 (1u << MT_DENS_800)
|
||||
#define TL_1600 (1u << MT_DENS_1600)
|
||||
#define TL_6250 (1u << MT_DENS_6250)
|
||||
|
||||
#define IFTYPE(t,s) (TL_##t & (s) ? #t : NULL), \
|
||||
(TL_##t & (s) ? #t : NULL)
|
||||
|
@ -514,14 +525,14 @@ typedef CNTLR_VARS *CVPTR; /* a pointer to a controller sta
|
|||
extern CNTLR_IFN_IBUS tl_controller (CVPTR cvptr, UNIT *uptr, CNTLR_FLAG_SET flags, CNTLR_IBUS data);
|
||||
extern t_stat tl_onoffline (CVPTR cvptr, UNIT *uptr, t_bool online);
|
||||
|
||||
extern uint16 tl_status (CVPTR cvptr);
|
||||
extern t_stat tl_reset (CVPTR cvptr);
|
||||
extern void tl_clear (CVPTR cvptr);
|
||||
extern HP_WORD tl_status (CVPTR cvptr);
|
||||
extern t_stat tl_reset (CVPTR cvptr);
|
||||
extern void tl_clear (CVPTR cvptr);
|
||||
|
||||
/* Tape library global utility routines */
|
||||
|
||||
extern const char *tl_opcode_name (CNTLR_OPCODE opcode);
|
||||
extern const char *tl_unit_name (uint32 unit);
|
||||
extern const char *tl_unit_name (int32 unit);
|
||||
|
||||
/* Tape library global SCP support routines */
|
||||
|
||||
|
|
|
@ -216,6 +216,10 @@
|
|||
RelativePath="..\HP3000\hp3000_iop.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\HP3000\hp3000_lp.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\HP3000\hp3000_mpx.c"
|
||||
>
|
||||
|
|
|
@ -432,6 +432,7 @@ HP3000_LIB1 = $(LIB_DIR)HP3000L1-$(ARCH).OLB
|
|||
HP3000_SOURCE1 = $(HP3000_DIR)HP3000_ATC.C,$(HP3000_DIR)HP3000_CLK.C,\
|
||||
$(HP3000_DIR)HP3000_CPU.C,$(HP3000_DIR)HP3000_CPU_BASE.C,\
|
||||
$(HP3000_DIR)HP3000_CPU_FP.C,$(HP3000_DIR)HP3000_DS.C,\
|
||||
$(HP3000_DIR)HP3000_LP.C,\
|
||||
$(HP3000_DIR)HP3000_IOP.C,$(HP3000_DIR)HP3000_MPX.C,\
|
||||
$(HP3000_DIR)HP3000_MS.C,$(HP3000_DIR)HP3000_SCMB.C,\
|
||||
$(HP3000_DIR)HP3000_SEL.C,$(HP3000_DIR)HP3000_SYS.C
|
||||
|
|
Binary file not shown.
2
makefile
2
makefile
|
@ -1206,7 +1206,7 @@ HP3000D = HP3000
|
|||
HP3000 = ${HP3000D}/hp_disclib.c ${HP3000D}/hp_tapelib.c ${HP3000D}/hp3000_atc.c \
|
||||
${HP3000D}/hp3000_clk.c ${HP3000D}/hp3000_cpu.c ${HP3000D}/hp3000_cpu_base.c \
|
||||
${HP3000D}/hp3000_cpu_fp.c ${HP3000D}/hp3000_ds.c ${HP3000D}/hp3000_iop.c \
|
||||
${HP3000D}/hp3000_mpx.c ${HP3000D}/hp3000_ms.c \
|
||||
${HP3000D}/hp3000_lp.c ${HP3000D}/hp3000_mpx.c ${HP3000D}/hp3000_ms.c \
|
||||
${HP3000D}/hp3000_scmb.c ${HP3000D}/hp3000_sel.c ${HP3000D}/hp3000_sys.c
|
||||
HP3000_OPT = -I ${HP3000D}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue