diff --git a/0readme_33.txt b/0readme_33.txt index b9ba0667..9393ec85 100644 --- a/0readme_33.txt +++ b/0readme_33.txt @@ -1,143 +1,63 @@ -Notes For V3.3 +Notes For V3.3-1 -RESTRICTION: The HP DS disk is not debugged. DO NOT enable this -feature for normal operations. -WARNING: Massive changes in the PDP-11 make all previous SAVEd -file obsolete. Do not attempt to use a PDP-11 SAVE file from a -prior release with V3.3! +1. New Features in 3.3-1 -1. New Features in 3.3 +1.1 H316 -1.1 SCP +TTY - implemented paper-tape reader and punch + - added ASCII file support -- Added -p (powerup) qualifier to RESET -- Changed SET ONLINE/OFFLINE to SET ENABLED/DISABLED -- Moved SET DEBUG under SET CONSOLE hierarchy -- Added optional parameter value to SHOW command -- Added output file option to SHOW command +PTR,PTP - added ASCII file support -1.2 PDP-11 +1.2 HP2100 -- Separated RH Massbus adapter from RP controller -- Added TU tape support -- Added model emulation framework -- Added model details +CPU - added SET CPU 21MX-M, 21MX-E (from Dave Brian) + - disabled TIMER/EXECUTE/DIAG instructions for 21MX-M (from Dave Bryan) + - added post-processor to maintain T/M consistency (from Dave Bryan) -1.3 VAX +DS - released 13037 disk controller -- Separated out CVAX-specific features from core instruction simulator -- Implemented capability for CIS, octaword, compatibility mode instructions -- Added instruction display and parse for compatibility mode -- Changed SET CPU VIRTUAL=n to SHOW CPU VIRTUAL=n -- Added =n optional parameter to SHOW CPU HISTORY +1.3 Interdata -1.4 Unibus/Qbus simulators (PDP-11, VAX, PDP-10) +MT - added read-only file support -- Simplified DMA API's -- Modified DMA peripherals to use simplified API's +1.4 SDS -1.5 HP2100 (all changes from Dave Bryan) +MT - added read-only file support -CPU - moved MP into its own device; added MP option jumpers - - modified DMA to allow disabling - - modified SET CPU 2100/2116 to truncate memory > 32K - - added -F switch to SET CPU to force memory truncation - - modified WRU to be REG_HRO - - added BRK and DEL to save console settings +1.5 PDP-11 -DR - provided protected tracks and "Writing Enabled" status bit - - added "parity error" status return on writes for 12606 - - added track origin test for 12606 - - added SCP test for 12606 - - added "Sector Flag" status bit - - added "Read Inhibit" status bit for 12606 - - added TRACKPROT modifier - -LPS - added SET OFFLINE/ONLINE, POWEROFF/POWERON - - added fast/realistic timing - - added debug printouts - -LPT - added SET OFFLINE/ONLINE, POWEROFF/POWERON - -PTR - added paper tape loop mode, DIAG/READER modifiers to PTR - - added PV_LEFT to PTR TRLLIM register - -CLK - modified CLK to permit disable - -1.6 IBM 1401, IBM 1620, Interdata 16b, SDS 940, PDP-10 - -- Added instruction history - -1.7 H316, PDP-15, PDP-8 - -- Added =n optional value to SHOW CPU HISTORY +TM,TS - added read-only file support 2. Bugs Fixed in 3.3 -2.1 SCP +2.1 H316 -- Fixed comma-separated SET options (from Dave Bryan) -- Fixed duplicate HELP displays with user-specified commands +CPU - fixed bug in divide -2.2 PDP-10 +LPT - fixed bug in DMA/DMC support + +MT - fixed bug in DMA/DMC support + +DP - fixed bug in skip on not seeking + +TTY - fixed bugs in SKS '104, '504 + +2.2 HP2100 + +CPU - fixed DMA reset to clear alternate CTL flop (from Dave Bryan) + - fixed bug in JPY (from Dave Bryan) + - fixed bugs in CBS, SBS, TBS + - separate A/B from M[0/1] for DMA (found by Dave Bryan) + + +LPS - added restart when set online, etc. (from Dave Bryan) + - fixed col count for non-printing chars (from Dave Bryan) + +LPT - added restart when set online, etc. (from Dave Bryan) -- Replicated RP register state per drive -- Fixed TU to set FCE on short record -- Fixed TU to return bit<15> in drive type -- Fixed TU format specification, 1:0 are don't cares -- Fixed TU handling of TMK status -- Fixed TU handling of DONE, ATA at end of operation -- Implemented TU write check 2.3 PDP-11 -- Replicated RP register state per drive -- Fixed RQ, TQ to report correct controller type and stage 1 configuration - flags on a Unibus system -- Fixed HK CS2 flag +CPU - fixed WAIT to work in all modes (from John Dundas) -2.4 VAX - -- Fixed parsing of indirect displacement modes in instruction input - -2.5 HP2100 (all fixes from Dave Bryan) - -CPU - fixed S-register behavior on 2116 - - fixed LIx/MIx behavior for DMA on 2116 and 2100 - - fixed LIx/MIx behavior for empty I/O card slots - -DP - fixed enable/disable from either device - - fixed ANY ERROR status for 12557A interface - - fixed unattached drive status for 12557A interface - - status cmd without prior STC DC now completes (12557A) - - OTA/OTB CC on 13210A interface also does CLC CC - - fixed RAR model - - fixed seek check on 13210 if sector out of range - -DQ - fixed enable/disable from either device - - shortened xtime from 5 to 3 (drive avg 156KW/second) - - fixed not ready/any error status - - fixed RAR model - -DR - fixed enable/disable from either device - - fixed sector return in status word - - fixed DMA last word write, incomplete sector fill value - - fixed 12610 SFC operation - - fixed current-sector determination - -IPL - fixed enable/disable from either device - -LPS - fixed status returns for error conditions - - fixed handling of non-printing characters - - fixed handling of characters after column 80 - - improved timing model accuracy for RTE - -LPT - fixed status returns for error conditions - - fixed TOF handling so form remains on line 0 - -SYS - fixed display of CCA/CCB/CCE instructions - -2.5 PDP-15 - -FPP - fixed URFST to mask low 9b of fraction - - fixed exception PC setting diff --git a/H316/h316_cpu.c b/H316/h316_cpu.c index 46b300c8..f3efe3cc 100644 --- a/H316/h316_cpu.c +++ b/H316/h316_cpu.c @@ -25,6 +25,7 @@ cpu H316/H516 CPU + 01-Dec-04 RMS Fixed bug in DIV 06-Nov-04 RMS Added =n to SHOW HISTORY 04-Jan-04 RMS Removed unnecessary compare 31-Dec-03 RMS Fixed bug in cpu_set_hist @@ -496,11 +497,10 @@ case 003: case 023: case 043: case 063: /* ANA */ case 004: case 024: case 044: case 064: /* STA */ if (reason = Ea (MB, &Y)) break; /* eff addr */ + Write (Y, AR); /* store A */ if (dp) { /* double prec? */ - if ((Y & 1) == 0) Write (Y, AR); /* if even, store A */ Write (Y | 1, BR); /* store B */ sc = 0; } - else Write (Y, AR); /* no, store word */ break; case 005: case 025: case 045: case 065: /* ERA */ @@ -585,7 +585,7 @@ case 017: case 037: case 057: case 077: /* DIV */ if (reason = Ea (MB, &Y)) break; /* eff addr */ t2 = SEXT (Read (Y)); /* divr */ if (t2) { /* divr != 0? */ - t1 = GETDBL_S (AR, BR); /* get A'B */ + t1 = GETDBL_S (SEXT (AR), BR); /* get A'B signed */ BR = (t1 % t2) & DMASK; /* remainder */ t1 = t1 / t2; /* quotient */ AR = t1 & DMASK; @@ -934,8 +934,8 @@ int32 Add16 (int32 v1, int32 v2) { int32 r = v1 + v2; -C = 0; if (((v1 ^ ~v2) & (v1 ^ r)) & SIGN) C = 1; +else C = 0; return (r & DMASK); } @@ -943,8 +943,8 @@ int32 Add31 (int32 v1, int32 v2) { int32 r = v1 + v2; -C = 0; -if (((v1 ^ ~v2) & (v1 ^ r)) & (1u << 30)) C = 1; +if (((v1 ^ ~v2) & (v1 ^ r)) & DP_SIGN) C = 1; +else C = 0; return r; } @@ -1196,7 +1196,7 @@ if (cptr == NULL) return SCPE_ARG; newmax = get_uint (cptr, 10, DMA_MAX, &r); /* get new max */ if ((r != SCPE_OK) || (newmax == dma_nch)) return r; /* err or no chg? */ dma_nch = newmax; /* set new max */ -for (i = newmax; i set ptr binary -- binary mode + sim> set ptr ascii -- ASCII mode + sim> set ptr uascii -- Unix ASCII mode + +The mode can also be set by a switch setting in the attach command: + + sim> att -b ptr -- binary mode + sim> att -a ptr -- ASCII mode + sim> att -u ptr -- Unix ASCII mode + +In ASCII or Unix ASCII mode, all non-zero characters have the high +order bit forced on. In Unix ASCII mode, newline is converted to +CR, and LF in inserted as the following character. + The paper tape reader supports the BOOT command. BOOT PTR copies the absolute binary loader into memory and starts it running. @@ -207,6 +224,23 @@ The paper tape punch (PTP) writes data to a disk file. The POS register specifies the number of the next data item to be written. Thus, by changing POS, the user can backspace or advance the punch. +The paper tape punch can bet set to operate in binary, ASCII, or +Unix ASCII mode: + + sim> set ptp binary -- binary mode + sim> set ptp ascii -- ASCII mode + sim> set ptp uascii -- Unix ASCII mode + +The mode can also be set by a switch setting in the attach command: + + sim> att -b ptp -- binary mode + sim> att -a ptp -- ASCII mode + sim> att -u ptp -- Unix ASCII mode + +In ASCII or Unix ASCII mode, all characters are masked to 7b +before being written to the output file. In Unix ASCII mode, LF +is converted to newline, and CR is discarded. + The paper tape punch implements these registers: name size comments @@ -232,15 +266,65 @@ Error handling is as follows: 2.2.3 316/516-33 Console Teletype (TTY) -The Teletype units (TTY0, TTY1) can be set to one of three modes: +The console Teletype (TTY) consists of four separate units: + + TTY0 keyboard + TTY1 printer + TTY2 paper tape reader + TTY3 paper tape punch + +The keyboard and printer (TTY0, TTY1) can be set to one of three modes: KSR, 7B, or 8B. In KSR mode, lower case input and output characters are automatically converted to upper case, and the high order bit is forced to one on input. In 7B mode, input and output characters are masked to 7 bits. In 8B mode, characters are not modified. Changing -the mode of either unit changes both. The default mode is KSR. +the mode of either unit changes both. The default mode is KSR. The +Teletype keyboard reads from the console keyboard, and the printer +prites to the simulator console window. -The Teletype reads from the console keyboard and writes to the -simulator console window. It implements these registers: +The paper tape reader (TTY2) can bet set to operate in binary, ASCII, or +Unix ASCII mode: + + sim> set tty2 binary -- binary mode + sim> set tty2 ascii -- ASCII mode + sim> set tty2 uascii -- Unix ASCII mode + +The mode can also be set by a switch setting in the attach command: + + sim> att -b tty2 -- binary mode + sim> att -a tty2 -- ASCII mode + sim> att -u tty2 -- Unix ASCII mode + +In ASCII or Unix ASCII mode, all non-zero characters have the high +order bit forced on. In Unix ASCII mode, newline is converted to +CR, and LF in inserted as the following character. + +The paper tape reader is started by program output of XON or by +the command SET TTY2 START. The paper tape reader is stopped by +reader input of XOFF or by the command SET TTY2 STOP. + +The paper tape punch (TTY3) can bet set to operate in binary, ASCII, or +Unix ASCII mode: + + sim> set tty3 binary -- binary mode + sim> set tty3 ascii -- ASCII mode + sim> set tty3 uascii -- Unix ASCII mode + +The mode can also be set by a switch setting in the attach command: + + sim> att -b tty3 -- binary mode + sim> att -a tty3 -- ASCII mode + sim> att -u tty3 -- Unix ASCII mode + +In ASCII or Unix ASCII mode, all characters are masked to 7b +before being written to the output file. In Unix ASCII mode, LF +is converted to newline, and CR is discarded. + +The paper tape punch is started by program output of TAPE or by +the command SET TTY3 START. The paper tape punch is stopped by +program output of XOFF or by the command SET TTY3 STOP. + +It implements these registers: name size comments @@ -249,10 +333,12 @@ simulator console window. It implements these registers: INTREQ 1 device interrupt request READY 1 device ready ENABLE 1 device interrupts enabled - KPOS 32 number of characters input + KPOS 32 number of keyboard characters input KTIME 24 keyboard polling interval - TPOS 32 number of characters output + TPOS 32 number of printer characters output TTIME 24 time from I/O initiation to interrupt + RPOS 32 current reader character position + PPOS 32 current punch character position 2.2.4 316/516-12 Real Time Clock (CLK) diff --git a/H316/h316_dp.c b/H316/h316_dp.c index fe943062..c8496242 100644 --- a/H316/h316_dp.c +++ b/H316/h316_dp.c @@ -27,6 +27,8 @@ 4651 disk subsystem 4720 disk subsystem + 01-Dec-04 RMS Fixed bug in skip on !seeking + The Honeywell disks have the unique characteristic of supporting variable formatting, on a per track basis. To accomodate this, each track is simulated as 2048 words, divided into records. (2048 words accomodates @@ -433,7 +435,8 @@ case ioSKS: /* SKS */ u = fnc - 011; case 007: /* !not seeking 7 */ if (!sim_is_active (&dp_unit[u]) || /* quiescent? */ - (dp_unit[u].FNC & 017) != FNC_SEEK) return IOSKIP (dat); + (dp_unit[u].FNC != (FNC_SEEK | FNC_2ND))) + return IOSKIP (dat); /* seeking sets late */ break; } break; case ioEND: /* end of range */ @@ -816,6 +819,8 @@ for (i = 0; i < DP_NUMDRV; i++) { /* loop thru drives */ sim_cancel (&dp_unit[i]); /* cancel activity */ dp_unit[i].FNC = 0; /* clear function */ dp_unit[i].CYL = 0; } +CLR_INT (INT_DP); /* clear int, enb */ +CLR_ENB (INT_DP); return SCPE_OK; } diff --git a/H316/h316_lp.c b/H316/h316_lp.c index 3f2faa3c..a726c3ce 100644 --- a/H316/h316_lp.c +++ b/H316/h316_lp.c @@ -25,6 +25,7 @@ lpt line printer + 01-Dec-04 RMS Fixed bug in DMA/DMC support 24-Oct-03 RMS Added DMA/DMC support 25-Apr-03 RMS Revised for extended file support 30-May-02 RMS Widened POS to 32b @@ -153,13 +154,13 @@ case ioOCP: /* OCP */ lpt_wdpos = 0; /* init scan pos */ lpt_eor = 0; if (ch >= 0) lpt_dma = 1; /* try for DMA/DMC */ - lpt_dma = 0; + else lpt_dma = 0; if (!sim_is_active (&lpt_unit)) { lpt_rdy = 1; if (lpt_dma) SET_CH_REQ (ch); } CLR_INT (INT_LPT); /* clear int */ break; - case 007: /* init scan IO bus*/ + case 007: /* init scan IO bus */ lpt_prdn = 0; /* clear pr done */ lpt_wdpos = 0; /* init scan pos */ lpt_eor = 0; diff --git a/H316/h316_mt.c b/H316/h316_mt.c index ed904de9..e5d66d72 100644 --- a/H316/h316_mt.c +++ b/H316/h316_mt.c @@ -25,6 +25,8 @@ mt 516-4100 seven track magnetic tape + 01-Dec-04 RMS Fixed bug in DMA/DMC support + Magnetic tapes are represented as a series of variable records of the form: @@ -183,7 +185,8 @@ case ioOCP: case FNC_DMANM: /* set DMA/DMC */ case FNC_DMAAU: mt_usel = u; /* save unit select */ - if (mt_dib.chan) mt_dma = 1; /* if configured */ + if (mt_dib.chan) mt_dma = 1; /* set DMA if configured */ + else mt_dma = 0; break; case FNC_IOBUS: /* set IOBUS */ mt_usel = u; /* save unit select */ @@ -382,7 +385,7 @@ case FNC_WBCD2: case FNC_WBIN2: case FNC_WBIN3: /* write first */ case FNC_WBCD2 | FNC_2ND: /* write, word */ case FNC_WBIN2 | FNC_2ND: case FNC_WBIN3 | FNC_2ND: - if (mt_eor || mt_rdy) { /* done or no data? */ + if (mt_eor || mt_rdy) { /* done or no data? */ if (!mt_rdy) mt_wrwd (uptr, mt_buf); /* write last word */ if (mt_ptr) { /* any data? */ if (st = sim_tape_wrrecf (uptr, mtxb, mt_ptr)) /* write, err? */ diff --git a/H316/h316_stddev.c b/H316/h316_stddev.c index 51737f4c..d991f8a0 100644 --- a/H316/h316_stddev.c +++ b/H316/h316_stddev.c @@ -28,6 +28,11 @@ tty 316/516-33 teleprinter clk/options 316/516-12 real time clocks/internal options + 01-Dec-04 RMS Fixed problem in SKS '104 (reported by Philipp Hachtmann) + Fixed bug in SKS '504 + Added PTR detach routine, stops motion + Added PTR/PTP ASCII file support + Added TTR/TTP support 24-Oct-03 RMS Added DMA/DMC support 25-Apr-03 RMS Revised for extended file support 01-Mar-03 RMS Added SET/SHOW CLK FREQ support @@ -37,26 +42,72 @@ 03-Nov-01 RMS Implemented upper case for console output 29-Nov-01 RMS Added read only unit support 07-Sep-01 RMS Moved function prototypes + + The ASR-33/35 reader/punch logic, and the ASCII file support for all paper tape + devices, logic is taken, with grateful thanks, from Adrian Wise's H316 emulator. + + Teletype reader transitions: + + - SET TTY2 START puts the reader in RUN + - XOFF from keyboard/reader stops the reader after 1-2 more characters are read + - XON from program starts the reader + - Detach, SET TTY2 STOP, or end of file stops the reader + + Teletype punch transitions: + + - SET TTY3 START puts the punch in RUN + - XOFF from program stops the punch after 1 more character is punched + - TAPE from program starts the punch after 1 character delay + - Detach or SET TTY3 STOP stops the punch */ #include "h316_defs.h" #include +#define CHAR_FLAG(c) (1u << (c)) + +#define BEL_FLAG CHAR_FLAG('\a') +#define LF_FLAG CHAR_FLAG('\n') +#define CR_FLAG CHAR_FLAG('\r') +#define HT_FLAG CHAR_FLAG('\t') + +#define CNTL_SET (BEL_FLAG | HT_FLAG | LF_FLAG | CR_FLAG) + #define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */ #define UNIT_V_KSR (UNIT_V_UF + 1) /* KSR33 */ +#define UNIT_V_ASC (UNIT_V_UF + 2) /* ASCII */ +#define UNIT_V_UASC (UNIT_V_UF + 3) /* Unix ASCII */ #define UNIT_8B (1 << UNIT_V_8B) #define UNIT_KSR (1 << UNIT_V_KSR) +#define UNIT_ASC (1 << UNIT_V_ASC) +#define UNIT_UASC (1 << UNIT_V_UASC) +#define STA u3 /* state bits */ +#define LF_PEND 01 /* lf pending */ +#define RUNNING 02 /* tape running */ + +#define XON 0021 +#define TAPE 0022 +#define XOFF 0023 +#define RUBOUT 0377 extern uint16 M[]; extern int32 PC; extern int32 stop_inst; extern int32 C, dp, ext, extoff_pending, sc; extern int32 dev_int, dev_enb; +extern int32 sim_switches; extern UNIT cpu_unit; -int32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */ -int32 ptp_power = 0, ptp_ptime; /* punch power, time */ -int32 tty_mode = 0, tty_buf = 0; /* tty mode, buf */ +uint32 ptr_stopioe = 0; /* stop on error */ +uint32 ptp_stopioe = 0; +uint32 ptp_power = 0; /* punch power, time */ +int32 ptp_ptime; +uint32 ttr_stopioe = 0; +uint32 tty_mode = 0; /* input (0), output (1) */ +uint32 tty_buf = 0; /* tty buffer */ +uint32 ttr_xoff_read = 0; +uint32 ttp_tape_rcvd = 0; +uint32 ttp_xoff_rcvd = 0; int32 clk_tps = 60; /* ticks per second */ int32 ptrio (int32 inst, int32 fnc, int32 dat, int32 dev); @@ -70,12 +121,18 @@ int32 ttyio (int32 inst, int32 fnc, int32 dat, int32 dev); t_stat tti_svc (UNIT *uptr); t_stat tto_svc (UNIT *uptr); t_stat tty_reset (DEVICE *dptr); -t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat ttio_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat ttrp_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc); +t_stat ttrp_set_start_stop (UNIT *uptr, int32 val, char *cptr, void *desc); int32 clkio (int32 inst, int32 fnc, int32 dat, int32 dev); t_stat clk_svc (UNIT *uptr); t_stat clk_reset (DEVICE *dptr); t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc); t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc); +t_stat pt_attach (UNIT *uptr, char *cptr); +t_stat pt_detach (UNIT *uptr); +t_stat tto_write (int32 c); +t_stat ttp_write (int32 c); /* PTR data structures @@ -97,14 +154,20 @@ REG ptr_reg[] = { { FLDATA (ENABLE, dev_enb, INT_V_PTR) }, { DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT }, { DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT }, + { ORDATA (RSTATE, ptr_unit.STA, 2), REG_HIDDEN }, { FLDATA (STOP_IOE, ptr_stopioe, 0) }, { NULL } }; +MTAB pt_mod[] = { + { UNIT_ATT+UNIT_ASC+UNIT_UASC, UNIT_ATT+UNIT_ASC, "ASCII", NULL }, + { UNIT_ATT+UNIT_ASC+UNIT_UASC, UNIT_ATT+UNIT_ASC+UNIT_UASC, "Unix ASCII", NULL }, + { 0 } }; + DEVICE ptr_dev = { - "PTR", &ptr_unit, ptr_reg, NULL, + "PTR", &ptr_unit, ptr_reg, pt_mod, 1, 10, 31, 1, 8, 8, NULL, NULL, &ptr_reset, - &ptr_boot, NULL, NULL, + &ptr_boot, &pt_attach, &pt_detach, &ptr_dib, 0 }; /* PTP data structures @@ -126,16 +189,17 @@ REG ptp_reg[] = { { FLDATA (ENABLE, dev_enb, INT_V_PTP) }, { FLDATA (POWER, ptp_power, 0) }, { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT }, + { ORDATA (PSTATE, ptp_unit.STA, 2), REG_HIDDEN }, { DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT }, { DRDATA (PWRTIME, ptp_ptime, 24), PV_LEFT }, { FLDATA (STOP_IOE, ptp_stopioe, 0) }, { NULL } }; DEVICE ptp_dev = { - "PTP", &ptp_unit, ptp_reg, NULL, + "PTP", &ptp_unit, ptp_reg, pt_mod, 1, 10, 31, 1, 8, 8, NULL, NULL, &ptp_reset, - NULL, NULL, NULL, + NULL, &pt_attach, NULL, &ptp_dib, 0 }; /* TTY data structures @@ -148,12 +212,16 @@ DEVICE ptp_dev = { #define TTI 0 #define TTO 1 +#define TTR 2 +#define TTP 3 DIB tty_dib = { TTY, IOBUS, 1, &ttyio }; UNIT tty_unit[] = { { UDATA (&tti_svc, UNIT_KSR, 0), KBD_POLL_WAIT }, - { UDATA (&tto_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT } }; + { UDATA (&tto_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT }, + { UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0) }, + { UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) } }; REG tty_reg[] = { { ORDATA (BUF, tty_buf, 8) }, @@ -164,19 +232,35 @@ REG tty_reg[] = { { DRDATA (KTIME, tty_unit[TTI].wait, 24), REG_NZ + PV_LEFT }, { DRDATA (TPOS, tty_unit[TTO].pos, T_ADDR_W), PV_LEFT }, { DRDATA (TTIME, tty_unit[TTO].wait, 24), REG_NZ + PV_LEFT }, + { ORDATA (RXOFF, ttr_xoff_read, 2), REG_HIDDEN }, + { ORDATA (RSTATE, tty_unit[TTR].STA, 2), REG_HIDDEN }, + { DRDATA (RPOS, tty_unit[TTR].pos, T_ADDR_W), PV_LEFT }, + { ORDATA (PTAPE, ttp_tape_rcvd, 2), REG_HIDDEN }, + { ORDATA (PXOFF, ttp_xoff_rcvd, 2), REG_HIDDEN }, + { ORDATA (PSTATE, tty_unit[TTP].STA, 2), REG_HIDDEN }, + { DRDATA (PPOS, tty_unit[TTP].pos, T_ADDR_W), PV_LEFT }, + { FLDATA (STOP_IOE, ttr_stopioe, 0) }, { NULL } }; MTAB tty_mod[] = { - { UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tty_set_mode }, - { UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode }, - { UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode }, + { UNIT_KSR+UNIT_8B+UNIT_ATTABLE, UNIT_KSR, "KSR", "KSR", &ttio_set_mode }, + { UNIT_KSR+UNIT_8B+UNIT_ATTABLE, 0 , "7b" , "7B" , &ttio_set_mode }, + { UNIT_KSR+UNIT_8B+UNIT_ATTABLE, UNIT_8B , "8b" , "8B" , &ttio_set_mode }, + { UNIT_ATTABLE+UNIT_ASC+UNIT_UASC, UNIT_ATTABLE, NULL, "BINARY", + &ttrp_set_mode }, + { UNIT_ATTABLE+UNIT_ASC+UNIT_UASC, UNIT_ATTABLE+UNIT_ASC, "ASCII", "ASCII", + &ttrp_set_mode }, + { UNIT_ATTABLE+UNIT_ASC+UNIT_UASC, UNIT_ATTABLE+UNIT_ASC+UNIT_UASC, "Unix ASCII", "UASCII", + &ttrp_set_mode }, + { MTAB_XTD|MTAB_VUN|MTAB_NMO, 1, NULL, "START", &ttrp_set_start_stop }, + { MTAB_XTD|MTAB_VUN|MTAB_NMO, 0, NULL, "STOP", &ttrp_set_start_stop }, { 0 } }; DEVICE tty_dev = { "TTY", tty_unit, tty_reg, tty_mod, - 2, 10, 31, 1, 8, 8, + 4, 10, 31, 1, 8, 8, NULL, NULL, &tty_reset, - NULL, NULL, NULL, + NULL, &pt_attach, &pt_detach, &tty_dib, 0 }; /* CLK data structures @@ -227,8 +311,8 @@ case ioOCP: /* OCP */ break; case ioSKS: /* SKS */ if (fnc & 013) return IOBADFNC (dat); /* only fnc 0,4 */ - if (((fnc == 0) && TST_INT (INT_PTR)) || /* fnc 0? skip rdy */ - ((fnc == 4) && !TST_INTREQ (INT_PTR))) /* fnc 4? skip !int */ + if (((fnc == 000) && TST_INT (INT_PTR)) || /* fnc 0? skip rdy */ + ((fnc == 004) && !TST_INTREQ (INT_PTR))) /* fnc 4? skip !int */ return IOSKIP (dat); break; case ioINA: /* INA */ @@ -244,24 +328,61 @@ return dat; t_stat ptr_svc (UNIT *uptr) { -int32 temp; +int32 c; -if ((ptr_unit.flags & UNIT_ATT) == 0) /* attached? */ +if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ return IORETURN (ptr_stopioe, SCPE_UNATT); -if ((temp = getc (ptr_unit.fileref)) == EOF) { /* read byte */ - if (feof (ptr_unit.fileref)) { - if (ptr_stopioe) printf ("PTR end of file\n"); - else return SCPE_OK; } - else perror ("PTR I/O error"); - clearerr (ptr_unit.fileref); - return SCPE_IOERR; } +if (uptr->STA & LF_PEND) { /* lf pending? */ + uptr->STA &= ~LF_PEND; /* clear flag */ + c = 0212; /* insert LF */ + } +else { if ((c = getc (uptr->fileref)) == EOF) { /* read byte */ + if (feof (uptr->fileref)) { + if (ptr_stopioe) printf ("PTR end of file\n"); + else return SCPE_OK; } + else perror ("PTR I/O error"); + clearerr (uptr->fileref); + return SCPE_IOERR; } + if ((uptr->flags & UNIT_UASC) && (c == '\n')) { /* Unix newline? */ + c = 0215; /* insert CR */ + uptr->STA |= LF_PEND; } /* lf pending */ + else if ((uptr->flags & UNIT_ASC) && (c != 0)) /* ASCII? */ + c = c | 0200; + uptr->pos = ftell (uptr->fileref); /* update pos */ + } SET_INT (INT_PTR); /* set ready flag */ -ptr_unit.buf = temp & 0377; /* get byte */ -ptr_unit.pos = ftell (ptr_unit.fileref); /* update pos */ -sim_activate (&ptr_unit, ptr_unit.wait); /* reactivate */ +uptr->buf = c & 0377; /* get byte */ +sim_activate (uptr, uptr->wait); /* reactivate */ return SCPE_OK; } +/* Paper tape attach routine - set or clear ASC/UASC flags if specified */ + +t_stat pt_attach (UNIT *uptr, char *cptr) +{ +t_stat r; + +if (!(uptr->flags & UNIT_ATTABLE)) return SCPE_NOFNC; +if (r = attach_unit (uptr, cptr)) return r; +if (sim_switches & SWMASK ('A')) /* -a? ASCII */ + uptr->flags |= UNIT_ASC; +else if (sim_switches & SWMASK ('U')) /* -u? Unix ASCII */ + uptr->flags |= (UNIT_ASC|UNIT_UASC); +else if (sim_switches & SWMASK ('B')) /* -b? binary */ + uptr->flags &= ~(UNIT_ASC|UNIT_UASC); +uptr->STA = 0; +return r; +} + +/* Detach routine - stop motion if not restore */ + +t_stat pt_detach (UNIT *uptr) +{ +if (!(sim_switches & SIM_SW_REST)) sim_cancel (uptr); /* stop motion */ +uptr->STA = 0; +return detach_unit (uptr); +} + /* Reset routine */ t_stat ptr_reset (DEVICE *dptr) @@ -269,6 +390,7 @@ t_stat ptr_reset (DEVICE *dptr) CLR_INT (INT_PTR); /* clear ready, enb */ CLR_ENB (INT_PTR); ptr_unit.buf = 0; /* clear buffer */ +ptr_unit.STA = 0; sim_cancel (&ptr_unit); /* deactivate unit */ return SCPE_OK; } @@ -323,10 +445,10 @@ case ioOCP: /* OCP */ case ioSKS: /* SKS */ if ((fnc & 012) || (fnc == 005)) /* only 0, 1, 4 */ return IOBADFNC (dat); - if (((fnc == 00) && TST_INT (INT_PTP)) || /* fnc 0? skip rdy */ - ((fnc == 01) /* fnc 1? skip ptp on */ - && (ptp_power || sim_is_active (&ptp_unit))) || - ((fnc == 04) && !TST_INTREQ (INT_PTP))) /* fnc 4? skip !int */ + if (((fnc == 000) && TST_INT (INT_PTP)) || /* fnc 0? skip rdy */ + ((fnc == 001) && /* fnc 1? skip ptp on */ + (ptp_power || sim_is_active (&ptp_unit))) || + ((fnc == 004) && !TST_INTREQ (INT_PTP))) /* fnc 4? skip !int */ return IOSKIP (dat); break; case ioOTA: /* OTA */ @@ -344,18 +466,25 @@ return dat; t_stat ptp_svc (UNIT *uptr) { +int32 c; SET_INT (INT_PTP); /* set flag */ if (ptp_power == 0) { /* power on? */ ptp_power = 1; /* ptp is ready */ return SCPE_OK; } -if ((ptp_unit.flags & UNIT_ATT) == 0) /* attached? */ +if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ return IORETURN (ptp_stopioe, SCPE_UNATT); -if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) { /* output byte */ +if (uptr->flags & UNIT_ASC) { /* ASCII? */ + c = uptr->buf & 0177; /* mask to 7b */ + if ((uptr->flags & UNIT_UASC) && (c == 015)) /* cr? drop if Unix */ + return SCPE_OK; + else if (c == 012) c = '\n'; } /* lf? cvt to nl */ +else c = uptr->buf & 0377; /* no, binary */ +if (putc (c, uptr->fileref) == EOF) { /* output byte */ perror ("PTP I/O error"); - clearerr (ptp_unit.fileref); + clearerr (uptr->fileref); return SCPE_IOERR; } -ptp_unit.pos = ftell (ptp_unit.fileref); /* update pos */ +uptr->pos = ftell (uptr->fileref); /* update pos */ return SCPE_OK; } @@ -367,6 +496,7 @@ CLR_INT (INT_PTP); /* clear ready, enb */ CLR_ENB (INT_PTP); ptp_power = 0; /* power off */ ptp_unit.buf = 0; /* clear buffer */ +ptp_unit.STA = 0; sim_cancel (&ptp_unit); /* deactivate unit */ return SCPE_OK; } @@ -388,12 +518,12 @@ case ioOCP: /* OCP */ break; case ioSKS: /* SKS */ if (fnc & 012) return IOBADFNC (dat); /* fnc 0,1,4,5 */ - if (((fnc == 0) && TST_INT (INT_TTY)) || /* fnc 0? skip rdy */ - ((fnc == 1) && /* fnc 1? skip !busy */ - tty_mode && !sim_is_active (&tty_unit[TTO])) || - ((fnc == 4) && !TST_INTREQ (INT_TTY)) || /* fnc 4? skip !int */ - ((fnc == 5) && /* fnc 5? skip !xoff */ - !tty_mode && ((tty_buf & 0177) == 023))) + if (((fnc == 000) && TST_INT (INT_TTY)) || /* fnc 0? skip rdy */ + ((fnc == 001) && /* fnc 1? skip !busy */ + (!tty_mode || !sim_is_active (&tty_unit[TTO]))) || + ((fnc == 004) && !TST_INTREQ (INT_TTY)) || /* fnc 4? skip !int */ + ((fnc == 005) && (tty_mode || /* fnc 5? skip !xoff */ + ((tty_buf & 0177) != XOFF)))) /* input & XOFF char */ return IOSKIP (dat); break; case ioINA: /* INA */ @@ -418,42 +548,132 @@ case ioOTA: return dat; } -/* Unit service routines */ +/* Input service - keyboard and reader */ t_stat tti_svc (UNIT *uptr) { int32 out, c; +UNIT *ruptr = &tty_unit[TTR]; -sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* continue poll */ -if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */ -out = c & 0177; /* mask echo to 7b */ -if (c & SCPE_BREAK) c = 0; /* break? */ -else if (tty_unit[TTI].flags & UNIT_KSR) { /* KSR? */ - if (islower (out)) out = toupper (out); /* cvt to UC */ - c = out | 0200; } /* add TTY bit */ -else c = c & ((tty_unit[TTI].flags & UNIT_8B)? 0377: 0177); +sim_activate (uptr, uptr->wait); /* continue poll */ +if ((c = sim_poll_kbd ()) >= SCPE_KFLAG) { /* character? */ + out = c & 0177; /* mask echo to 7b */ + if (c & SCPE_BREAK) c = 0; /* break? */ + else if (uptr->flags & UNIT_KSR) { /* KSR? */ + if (islower (out)) out = toupper (out); /* cvt to UC */ + c = out | 0200; } /* add TTY bit */ + else if (!(uptr->flags & UNIT_8B)) c = out; /* 7b? */ + uptr->pos = uptr->pos + 1; + } +else if (c != SCPE_OK) return c; /* error? */ +else if ((ruptr->flags & UNIT_ATT) && /* TTR attached */ + (ruptr->STA & RUNNING)) { /* and running? */ + if (ruptr->STA & LF_PEND) { /* lf pending? */ + c = 0212; /* char is lf */ + ruptr->STA &= LF_PEND; } /* clear flag */ + else { /* normal read */ + if ((c = getc (ruptr->fileref)) == EOF) { /* read byte */ + if (feof (ruptr->fileref)) { /* EOF? */ + ruptr->STA &= ~RUNNING; /* stop reader */ + if (ttr_stopioe) printf ("TTR end of file\n"); + else return SCPE_OK; } + else perror ("TTR I/O error"); + clearerr (ruptr->fileref); + return SCPE_IOERR; } + if ((ruptr->flags & UNIT_UASC) && (c == '\n')) { + c = 0215; /* Unix ASCII NL? */ + ruptr->STA |= LF_PEND; } /* LF pending */ + else if ((ruptr->flags & UNIT_ASC) && (c != 0)) + c = c | 0200; /* ASCII nz? cvt */ + ruptr->pos = ftell (ruptr->fileref); + } + if (ttr_xoff_read != 0) { /* reader stopping? */ + if (c == RUBOUT) ttr_xoff_read = 0; /* rubout? stop */ + else ttr_xoff_read--; /* else decr state */ + if (ttr_xoff_read == 0) /* delay done? */ + ruptr->STA &= ~RUNNING; } /* stop reader */ + else if ((c & 0177) == XOFF) ttr_xoff_read = 2; /* XOFF read? */ + out = c; /* echo char */ + } +else return SCPE_OK; /* no char */ if (tty_mode == 0) { /* input mode? */ - tty_buf = c; /* put char in buf */ - tty_unit[TTI].pos = tty_unit[TTI].pos + 1; - SET_INT (INT_TTY); /* set flag */ - if (out) sim_putchar (out); } /* echo */ -return SCPE_OK; + tty_buf = c & 0377; /* put char in buf */ + SET_INT (INT_TTY); } /* set flag */ +tto_write (out); /* echo to printer */ +return ttp_write (out); /* and punch */ } +/* Output service - printer and punch */ + t_stat tto_svc (UNIT *uptr) { -int32 c; +uint32 c7b; +UNIT *ruptr = &tty_unit[TTR]; +UNIT *puptr = &tty_unit[TTP]; t_stat r; -if (tty_unit[TTO].flags & UNIT_KSR) { /* UC only? */ - c = tty_buf & 0177; /* mask to 7b */ - if (islower (c)) c = toupper (c); } /* cvt to UC */ -else c = tty_buf & ((tty_unit[TTO].flags & UNIT_8B)? 0377: 0177); -if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */ +c7b = tty_buf & 0177; +if (ttp_tape_rcvd != 0) { /* prev = tape? */ + ttp_tape_rcvd--; /* decrement state */ + if ((ttp_tape_rcvd == 0) && (puptr->flags & UNIT_ATT)) + puptr->STA |= RUNNING; } /* start after delay */ +else if (c7b == TAPE) ttp_tape_rcvd = 2; /* char = TAPE? */ +if (ttp_xoff_rcvd != 0) { /* prev = XOFF? */ + ttp_xoff_rcvd--; /* decrement state */ + if (ttp_xoff_rcvd == 0) puptr->STA &= RUNNING; } /* stop after delay */ +else if (c7b == XOFF) ttp_xoff_rcvd = 2; /* char = XOFF? */ +if ((c7b == XON) && (ruptr->flags & UNIT_ATT)) { /* char = XON? */ + ruptr->STA |= RUNNING; /* start reader */ + ttr_xoff_read = 0; } /* cancel stop */ +if ((r = tto_write (tty_buf)) != SCPE_OK) { /* print; error? */ sim_activate (uptr, uptr->wait); /* try again */ return ((r == SCPE_STALL)? SCPE_OK: r); } /* !stall? report */ +if ((r = ttp_write (tty_buf)) != SCPE_OK) return r; /* punch; error? */ SET_INT (INT_TTY); /* set done flag */ -tty_unit[TTO].pos = tty_unit[TTO].pos + 1; +return SCPE_OK; +} + +/* Output to printer */ + +t_stat tto_write (int32 c) +{ +uint32 c7b; +UNIT *tuptr = &tty_unit[TTO]; + +c7b = c & 0177; +if (!(tuptr->flags & UNIT_8B)) { /* 7b or KSR? */ + if (c7b == 0) return SCPE_OK; /* supress NUL */ + if (tuptr->flags & UNIT_KSR) { /* KSR? */ + if ((c7b < 040) && /* not in ctrl set? */ + !(CNTL_SET & CHAR_FLAG (c7b))) return SCPE_OK; + if (islower (c7b)) c = toupper (c7b); } /* cvt to UC */ + else c = c7b; } /* full 7b */ +tuptr->pos = tuptr->pos + 1; +return sim_putchar_s (c); +} + +/* Output to punch */ + +t_stat ttp_write (int32 c) +{ +uint32 p, c7b; +UNIT *puptr = &tty_unit[TTP]; + +if ((puptr->flags & UNIT_ATT) && /* TTP attached */ + (puptr->STA & RUNNING)) { /* and running? */ + c7b = c & 0177; + if (!(puptr->flags & UNIT_UASC) || (c7b != 015)) { + if (puptr->flags & UNIT_ASC) { /* ASCII? */ + if (c7b == 012) p = '\n'; /* cvt LF */ + else p = c7b; } /* else 7b */ + else p = c; /* untouched */ + if (putc (p, puptr->fileref) == EOF) { /* output byte */ + perror ("TTP I/O error"); + clearerr (puptr->fileref); + return SCPE_IOERR; } + puptr->pos = ftell (puptr->fileref); /* update pos */ + } + } return SCPE_OK; } @@ -465,17 +685,47 @@ CLR_INT (INT_TTY); /* clear ready, enb */ CLR_ENB (INT_TTY); tty_mode = 0; /* mode = input */ tty_buf = 0; +ttr_xoff_read = 0; /* clr TTR, TTP flags */ +ttp_tape_rcvd = 0; +ttp_xoff_rcvd = 0; +tty_unit[TTR].STA = 0; +tty_unit[TTP].STA = 0; sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* activate poll */ sim_cancel (&tty_unit[TTO]); /* cancel output */ return SCPE_OK; } -t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) +/* Set keyboard/printer mode - make sure flags agree */ + +t_stat ttio_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) { +if (uptr->flags & UNIT_ATTABLE) return SCPE_NOFNC; /* not TTR, TTP */ tty_unit[TTI].flags = (tty_unit[TTI].flags & ~(UNIT_KSR | UNIT_8B)) | val; tty_unit[TTO].flags = (tty_unit[TTO].flags & ~(UNIT_KSR | UNIT_8B)) | val; return SCPE_OK; } + +/* Set reader/punch mode */ + +t_stat ttrp_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +if (!(uptr->flags & UNIT_ATTABLE)) return SCPE_NOFNC; /* TTR, TTP only */ +if (!(val & UNIT_UASC)) uptr->STA &= ~LF_PEND; +return SCPE_OK; +} + +/* Set reader/punch start/stop */ + +t_stat ttrp_set_start_stop (UNIT *uptr, int32 val, char *cptr, void *desc) +{ +if (!(uptr->flags & UNIT_ATTABLE)) return SCPE_NOFNC; /* TTR, TTP only */ +if (!(uptr->flags & UNIT_ATT)) return SCPE_UNATT; /* must be attached */ +if (val) uptr->STA |= RUNNING; /* start? set running */ +else uptr->STA &= ~RUNNING; /* stop? clr running */ +if (uptr->flags & UNIT_ROABLE) ttr_xoff_read = 0; /* TTR? cancel stop */ +else ttp_tape_rcvd = ttp_xoff_rcvd = 0; /* TTP? cancel all */ +return SCPE_OK; +} /* Clock/options: IO routine */ @@ -492,7 +742,7 @@ case ioOCP: /* OCP */ sim_rtc_init (clk_unit.wait)); } /* init calibr */ break; case ioSKS: /* SKS */ - if (fnc == 0) { /* clock skip !int */ + if (fnc == 000) { /* clock skip !int */ if (!TST_INTREQ (INT_CLK)) return IOSKIP (dat); } else if ((fnc & 007) == 002) { /* mem parity? */ if (((fnc == 002) && !TST_INT (INT_MPE)) || diff --git a/H316/h316_sys.c b/H316/h316_sys.c index a15eb970..96f5dcc6 100644 --- a/H316/h316_sys.c +++ b/H316/h316_sys.c @@ -23,6 +23,7 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 01-Dec-04 RMS Fixed fprint_opr calling sequence 24-Oct-03 RMS Added DMA/DMC support 17-Sep-01 RMS Removed multiconsole support */ @@ -196,17 +197,17 @@ static const int32 opc_val[] = { status = space needed */ -int32 fprint_opr (FILE *of, int32 inst, int32 class, int32 sp) +void fprint_opr (FILE *of, int32 inst, int32 class) { -int32 i, j; +int32 i, j, sp; -for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ +for (i = sp = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */ if ((j == class) && (opc_val[i] & inst)) { /* same class? */ inst = inst & ~opc_val[i]; /* mask bit set? */ fprintf (of, (sp? " %s": "%s"), opcode[i]); sp = 1; } } -return sp; +return; } /* Symbolic decode @@ -268,8 +269,8 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */ fprintf (of, "%s %o", opcode[i], disp); break; case I_V_SK0: case I_V_SK1: /* skips */ - fprint_opr (of, inst & 0777, j, 0); /* print skips */ - break; } /* end case */ + fprint_opr (of, inst & 0777, j); /* print skips */ + break; } /* end case */ return SCPE_OK; } /* end if */ } /* end for */ return SCPE_ARG; diff --git a/HP2100/hp2100_cpu.c b/HP2100/hp2100_cpu.c index 61cd501f..a872e9c0 100644 --- a/HP2100/hp2100_cpu.c +++ b/HP2100/hp2100_cpu.c @@ -23,10 +23,19 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. - CPU 2116A/2100A/21MXE central processing unit + CPU 2116A/2100A/21MX-M/21MX-E central processing unit MP 12892B memory protect DMA0,DMA1 12895A/12897B direct memory access/dual channel port controller + 26-Dec-04 RMS DMA reset doesn't clear alternate CTL flop (from Dave Bryan) + DMA reset shouldn't clear control words (from Dave Bryan) + Alternate CTL flop not visible as register (from Dave Bryan) + Fixed CBS, SBS, TBS to perform virtual reads + Separated A/B from M[0/1] for DMA IO (from Dave Bryan) + Fixed bug in JPY (from Dave Bryan) + 25-Dec-04 JDB Added SET CPU 21MX-M, 21MX-E (21MX defaults to MX-E) + TIMER/EXECUTE/DIAG instructions disabled for 21MX-M + T-register reflects changes in M-register when halted 25-Sep-04 JDB Moved MP into its own device; added MP option jumpers Modified DMA to allow disabling Modified SET CPU 2100/2116 to truncate memory > 32K @@ -327,13 +336,14 @@ #define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = err_PC #define UNIT_V_2100 (UNIT_V_UF + 0) /* 2100 */ -#define UNIT_V_21MX (UNIT_V_UF + 1) /* 21MX */ +#define UNIT_V_21MX (UNIT_V_UF + 1) /* 21MX-E or 21MX-M */ #define UNIT_V_EAU (UNIT_V_UF + 2) /* EAU */ #define UNIT_V_FP (UNIT_V_UF + 3) /* FP */ #define UNIT_V_DMS (UNIT_V_UF + 4) /* DMS */ #define UNIT_V_IOP (UNIT_V_UF + 5) /* 2100 IOP */ #define UNIT_V_IOPX (UNIT_V_UF + 6) /* 21MX IOP */ #define UNIT_V_MSIZE (UNIT_V_UF + 7) /* dummy mask */ +#define UNIT_V_MXM (UNIT_V_UF + 8) /* 21MX is M-series */ #define UNIT_2116 (0) #define UNIT_2100 (1 << UNIT_V_2100) #define UNIT_21MX (1 << UNIT_V_21MX) @@ -343,6 +353,7 @@ #define UNIT_IOP (1 << UNIT_V_IOP) #define UNIT_IOPX (1 << UNIT_V_IOPX) #define UNIT_MSIZE (1 << UNIT_V_MSIZE) +#define UNIT_MXM (1 << UNIT_V_MXM) #define UNIT_V_MP_JSB (UNIT_V_UF + 0) /* MP jumper W5 out */ #define UNIT_V_MP_INT (UNIT_V_UF + 1) /* MP jumper W6 out */ @@ -365,6 +376,7 @@ uint16 *M = NULL; /* memory */ uint32 saved_AR = 0; /* A register */ uint32 saved_BR = 0; /* B register */ +uint16 ABREG[2]; /* during execution */ uint32 PC = 0; /* P register */ uint32 SR = 0; /* S register */ uint32 MR = 0; /* M register */ @@ -433,11 +445,14 @@ uint16 ReadW (uint32 addr); uint16 ReadWA (uint32 addr); uint32 ReadF (uint32 addr); uint16 ReadIO (uint32 addr, uint32 map); +uint16 ReadPW (uint32 addr); +uint16 ReadTAB (uint32 addr); void WriteB (uint32 addr, uint32 dat); void WriteBA (uint32 addr, uint32 dat); void WriteW (uint32 addr, uint32 dat); void WriteWA (uint32 addr, uint32 dat); void WriteIO (uint32 addr, uint32 dat, uint32 map); +void WritePW (uint32 addr, uint32 dat); t_stat iogrp (uint32 ir, uint32 iotrap); uint32 dms (uint32 va, uint32 map, uint32 prot); uint32 dms_io (uint32 va, uint32 map); @@ -460,6 +475,7 @@ t_stat dma1_reset (DEVICE *dptr); t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); t_stat cpu_set_opt (UNIT *uptr, int32 val, char *cptr, void *desc); t_bool dev_conflict (void); +void hp_post_cmd (t_bool from_scp); extern uint32 f_as (uint32 op, t_bool sub); extern uint32 f_mul (uint32 op); @@ -467,6 +483,7 @@ extern uint32 f_div (uint32 op); extern uint32 f_fix (void); extern uint32 f_flt (void); extern int32 clk_delay (int32 flg); +extern void (*sim_vm_post) (t_bool from_scp); /* CPU data structures @@ -525,12 +542,16 @@ MTAB cpu_mod[] = { { UNIT_2116+UNIT_2100+UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_DMS+UNIT_IOP+UNIT_IOPX, UNIT_2100+UNIT_EAU, NULL, "2100", &cpu_set_opt, NULL, (void *) UNIT_2100 }, - { UNIT_2116+UNIT_2100+UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_DMS+UNIT_IOP+UNIT_IOPX, - UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_DMS, NULL, "21MX", &cpu_set_opt, + { UNIT_2116+UNIT_2100+UNIT_21MX+UNIT_MXM+UNIT_EAU+UNIT_FP+UNIT_DMS+UNIT_IOP+UNIT_IOPX, + UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_DMS, NULL, "21MX-E", &cpu_set_opt, + NULL, (void *) UNIT_21MX }, + { UNIT_2116+UNIT_2100+UNIT_21MX+UNIT_MXM+UNIT_EAU+UNIT_FP+UNIT_DMS+UNIT_IOP+UNIT_IOPX, + UNIT_21MX+UNIT_MXM+UNIT_EAU+UNIT_FP+UNIT_DMS, NULL, "21MX-M", &cpu_set_opt, NULL, (void *) UNIT_21MX }, { UNIT_2116+UNIT_2100+UNIT_21MX, UNIT_2116, "2116", NULL, NULL }, { UNIT_2116+UNIT_2100+UNIT_21MX, UNIT_2100, "2100", NULL, NULL }, - { UNIT_2116+UNIT_2100+UNIT_21MX, UNIT_21MX, "21MX", NULL, NULL }, + { UNIT_2116+UNIT_2100+UNIT_21MX+UNIT_MXM, UNIT_21MX, "21MX-E", NULL, NULL }, + { UNIT_2116+UNIT_2100+UNIT_21MX+UNIT_MXM, UNIT_21MX+UNIT_MXM, "21MX-M", NULL, NULL }, { UNIT_EAU, UNIT_EAU, "EAU", "EAU", &cpu_set_opt, NULL, (void *) UNIT_EAU }, { UNIT_EAU, 0, "no EAU", "NOEAU", &cpu_set_opt, @@ -616,6 +637,7 @@ REG dma0_reg[] = { { FLDATA (CTL, dev_ctl[DMA0/32], INT_V (DMA0)) }, { FLDATA (FLG, dev_flg[DMA0/32], INT_V (DMA0)) }, { FLDATA (FBF, dev_fbf[DMA0/32], INT_V (DMA0)) }, + { FLDATA (CTLALT, dev_ctl[DMALT0/32], INT_V (DMALT0)) }, { ORDATA (CW1, dmac[0].cw1, 16) }, { ORDATA (CW2, dmac[0].cw2, 16) }, { ORDATA (CW3, dmac[0].cw3, 16) }, @@ -635,6 +657,7 @@ REG dma1_reg[] = { { FLDATA (CTL, dev_ctl[DMA1/32], INT_V (DMA1)) }, { FLDATA (FLG, dev_flg[DMA1/32], INT_V (DMA1)) }, { FLDATA (FBF, dev_fbf[DMA1/32], INT_V (DMA1)) }, + { FLDATA (CTLALT, dev_ctl[DMALT1/32], INT_V (DMALT1)) }, { ORDATA (CW1, dmac[1].cw1, 16) }, { ORDATA (CW2, dmac[1].cw2, 16) }, { ORDATA (CW3, dmac[1].cw3, 16) }, @@ -735,7 +758,7 @@ static const uint32 e_inst[512] = { X_MR,X_NO,X_MR,X_MR,X_NO,X_MR,X_MR,X_NO, /* S*X,C*X,L*X,STX,CX*,LDX,ADX,X*X */ X_MR,X_NO,X_MR,X_MR,X_NO,X_MR,X_MR,X_NO, /* S*Y,C*Y,L*Y,STY,CY*,LDY,ADY,X*Y */ X_NO,X_NO,X_MR,X_NO,X_NO,X_AZ,X_AZ,X_NO, /* ISX,DSX,JLY,LBT,SBT,MBT,CBT,SFB */ - X_NO,X_NO,X_MR,X_AA,X_AA,X_AA,X_AZ,X_AZ }; /* ISY,DSY,JPY,SBS,CBS,TBS,CMW,MVW */ + X_NO,X_NO,X_NO,X_AA,X_AA,X_AA,X_AZ,X_AZ }; /* ISY,DSY,JPY,SBS,CBS,TBS,CMW,MVW */ /* Interrupt defer table */ @@ -1095,16 +1118,31 @@ case 0214:case 0215:case 0216:case 0217: intrq = calc_int (); /* recalc interrupts */ break; /* end if I/O */ -/* Extended arithmetic */ +/* Extended arithmetic + + The 21MX-E adds three "special instructions" that do not exist in earlier + CPUs, including the 21MX-M. They are: TIMER (100060), EXECUTE (100120), and + DIAG (100000). On the 21MX-M, these instruction codes map to the + microroutines for MPY, ASL, and RRL, respectively. + + Under simulation, these cause undefined instruction stops if the CPU is set + to 2100 or 2116. They do not cause stops on the 21MX-M, as TIMER in + particular is used by several HP programs to differentiate between M- and + E-series machines. */ case 0200: /* EAU group 0 */ if ((cpu_unit.flags & UNIT_EAU) == 0) { /* implemented? */ reason = stop_inst; break; } switch ((IR >> 4) & 017) { /* decode IR<7:4> */ - case 000: /* diagnostic */ - break; - case 001: /* ASL */ + case 005: /* EXECUTE */ + if (!(cpu_unit.flags & UNIT_21MX)) { /* must be 21MX */ + reason = stop_inst; /* trap if not */ + break; } + else if (!(cpu_unit.flags & UNIT_MXM)) { /* E-series? */ + PC = (PC + 1) & VAMASK; /* not simulated */ + break; } + case 001: /* ASL (+ EXECUTE on 21MX-M) */ sc = (IR & 017)? (IR & 017): 16; /* get sc */ O = 0; /* clear ovflo */ while (sc-- != 0) { /* bit by bit */ @@ -1118,17 +1156,27 @@ case 0200: /* EAU group 0 */ BR = ((BR << sc) | (AR >> (16 - sc))) & DMASK; AR = (AR << sc) & DMASK; /* BR'AR lsh left */ break; - case 003: /* TIMER */ - BR = (BR + 1) & DMASK; /* increment B */ - if (BR) PC = err_PC; /* if !=0, repeat */ - break; - case 004: /* RRL */ + case 000: /* DIAG */ + if (!(cpu_unit.flags & UNIT_21MX)) { /* must be 21MX */ + reason = stop_inst; /* trap if not */ + break; } + else if (!(cpu_unit.flags & UNIT_MXM)) /* E-series? */ + break; /* is NOP unless halted */ + case 004: /* RRL (+ DIAG on 21MX-M) */ sc = (IR & 017)? (IR & 017): 16; /* get sc */ t = BR; /* BR'AR rot left */ BR = ((BR << sc) | (AR >> (16 - sc))) & DMASK; AR = ((AR << sc) | (t >> (16 - sc))) & DMASK; break; - case 010: /* MPY */ + case 003: /* TIMER */ + if (!(cpu_unit.flags & UNIT_21MX)) { /* must be 21MX */ + reason = stop_inst; /* trap if not */ + break; } + else if (!(cpu_unit.flags & UNIT_MXM)) { /* E-series? */ + BR = (BR + 1) & DMASK; /* increment B */ + if (BR) PC = err_PC; /* if !=0, repeat */ + break; } + case 010: /* MPY (+ TIMER on 21MX-M) */ if (reason = Ea1 (&MA, intrq)) break; /* get opnd addr */ sop1 = SEXT (AR); /* sext AR */ sop2 = SEXT (ReadW (MA)); /* sext mem */ @@ -1844,13 +1892,19 @@ case 0203:case 0213: /* MAC1 ext */ /* Bit, word instructions */ case 0773: /* SBS (E_AA) */ - WriteW (M1, M[M1] | M [MA]); /* set bit */ + v1 = ReadW (MA); + v2 = ReadW (M1); + WriteW (M1, v2 | v1); /* set bit */ break; case 0774: /* CBS (E_AA) */ - WriteW (M1, M[M1] & ~M[MA]); /* clear bit */ + v1 = ReadW (MA); + v2 = ReadW (M1); + WriteW (M1, v2 & ~v1); /* clear bit */ break; case 0775: /* TBS (E_AA) */ - if ((M[MA] & M[M1]) != M[MA]) /* test bit */ + v1 = ReadW (MA); + v2 = ReadW (M1); + if ((v2 & v1) != v1) /* test bits */ PC = (PC + 1) & VAMASK; break; case 0776: /* CMW (E_AZ) */ @@ -1900,13 +1954,13 @@ if (reason == STOP_INDINT) { /* indirect intr? */ /* Simulation halted */ -if (iotrap && (reason == STOP_HALT)) MR = intaddr; /* HLT in trap cell? */ -else MR = (PC - 1) & VAMASK; /* no, M = P - 1 */ -TR = ReadIO (MR, dms_ump); /* last word fetched */ -if ((reason == STOP_RSRV) || (reason == STOP_IODV) || /* instr error? */ - (reason == STOP_IND)) PC = err_PC; /* back up PC */ saved_AR = AR & DMASK; saved_BR = BR & DMASK; +if (iotrap && (reason == STOP_HALT)) MR = intaddr; /* HLT in trap cell? */ +else MR = (PC - 1) & VAMASK; /* no, M = P - 1 */ +TR = ReadTAB (MR); /* last word fetched */ +if ((reason == STOP_RSRV) || (reason == STOP_IODV) || /* instr error? */ + (reason == STOP_IND)) PC = err_PC; /* back up PC */ dms_upd_sr (); /* update dms_sr */ for (i = 0; dptr = sim_devices[i]; i++) { /* loop thru dev */ dibp = (DIB *) dptr->ctxt; /* get DIB */ @@ -2096,8 +2150,8 @@ int32 pa; if (dms_enb) pa = dms (va >> 1, dms_ump, RD); else pa = va >> 1; -if (va & 1) return (M[pa] & 0377); -else return ((M[pa] >> 8) & 0377); +if (va & 1) return (ReadPW (pa) & 0377); +else return ((ReadPW (pa) >> 8) & 0377); } uint8 ReadBA (uint32 va) @@ -2106,8 +2160,8 @@ uint32 pa; if (dms_enb) pa = dms (va >> 1, dms_ump ^ MAP_LNT, RD); else pa = va >> 1; -if (va & 1) return (M[pa] & 0377); -else return ((M[pa] >> 8) & 0377); +if (va & 1) return (ReadPW (pa) & 0377); +else return ((ReadPW (pa) >> 8) & 0377); } uint16 ReadW (uint32 va) @@ -2116,7 +2170,7 @@ uint32 pa; if (dms_enb) pa = dms (va, dms_ump, RD); else pa = va; -return M[pa]; +return ReadPW (pa); } uint16 ReadWA (uint32 va) @@ -2125,7 +2179,7 @@ uint32 pa; if (dms_enb) pa = dms (va, dms_ump ^ MAP_LNT, RD); else pa = va; -return M[pa]; +return ReadPW (pa); } uint32 ReadF (uint32 va) @@ -2144,6 +2198,19 @@ else pa = va; return M[pa]; } +uint16 ReadPW (uint32 pa) +{ +if (pa <= 1) return ABREG[pa]; +return M[pa]; +} + +uint16 ReadTAB (uint32 addr) +{ +if (addr == 0) return saved_AR; +else if (addr == 1) return saved_BR; +else return ReadIO (addr, dms_ump); +} + /* Memory protection test for writes From Dave Bryan: The problem is that memory writes aren't being checked for @@ -2157,20 +2224,22 @@ return M[pa]; void WriteB (uint32 va, uint32 dat) { -uint32 pa; +uint32 pa, t; if (dms_enb) pa = dms (va >> 1, dms_ump, WR); else pa = va >> 1; if (MP_TEST (va >> 1)) ABORT (ABORT_PRO); if (MEM_ADDR_OK (pa)) { - if (va & 1) M[pa] = (M[pa] & 0177400) | (dat & 0377); - else M[pa] = (M[pa] & 0377) | ((dat & 0377) << 8); } + t = ReadPW (pa); + if (va & 1) t = (t & 0177400) | (dat & 0377); + else t = (t & 0377) | ((dat & 0377) << 8); + WritePW (pa, t); } return; } void WriteBA (uint32 va, uint32 dat) { -uint32 pa; +uint32 pa, t; if (dms_enb) { dms_viol (va >> 1, MVI_WPR); /* viol if prot */ @@ -2178,8 +2247,10 @@ if (dms_enb) { else pa = va >> 1; if (MP_TEST (va >> 1)) ABORT (ABORT_PRO); if (MEM_ADDR_OK (pa)) { - if (va & 1) M[pa] = (M[pa] & 0177400) | (dat & 0377); - else M[pa] = (M[pa] & 0377) | ((dat & 0377) << 8); } + t = ReadPW (pa); + if (va & 1) t = (t & 0177400) | (dat & 0377); + else t = (t & 0377) | ((dat & 0377) << 8); + WritePW (pa, t); } return; } @@ -2190,7 +2261,7 @@ uint32 pa; if (dms_enb) pa = dms (va, dms_ump, WR); else pa = va; if (MP_TEST (va)) ABORT (ABORT_PRO); -if (MEM_ADDR_OK (pa)) M[pa] = dat; +if (MEM_ADDR_OK (pa)) WritePW (pa, dat); return; } @@ -2203,7 +2274,7 @@ if (dms_enb) { pa = dms (va, dms_ump ^ MAP_LNT, WR); } else pa = va; if (MP_TEST (va)) ABORT (ABORT_PRO); -if (MEM_ADDR_OK (pa)) M[pa] = dat; +if (MEM_ADDR_OK (pa)) WritePW (pa, dat); return; } @@ -2213,7 +2284,14 @@ uint32 pa; if (dms_enb) pa = dms_io (va, map); else pa = va; -if (MEM_ADDR_OK (pa)) M[pa] = dat; +if (MEM_ADDR_OK (pa)) M[pa] = dat & DMASK; +return; +} + +void WritePW (uint32 pa, uint32 dat) +{ +if (pa <= 1) ABREG[pa] = dat & DMASK; +else M[pa] = dat & DMASK; return; } @@ -2630,6 +2708,7 @@ if (M == NULL) M = calloc (PASIZE, sizeof (uint16)); if (M == NULL) return SCPE_MEM; if (pcq_r) pcq_r->qptr = 0; else return SCPE_IERR; +sim_vm_post = &hp_post_cmd; /* set cmd post proc */ return SCPE_OK; } @@ -2652,7 +2731,9 @@ clrCMD (DMA0); clrCTL (DMA0); setFLG (DMA0); clrSRQ (DMA0); -dmac[0].cw1 = dmac[0].cw2 = dmac[0].cw3 = 0; +clrCTL (DMALT0); +if (sim_switches & SWMASK ('P')) /* power up? */ + dmac[0].cw1 = dmac[0].cw2 = dmac[0].cw3 = 0; return SCPE_OK; } @@ -2663,7 +2744,9 @@ clrCMD (DMA1); clrCTL (DMA1); setFLG (DMA1); clrSRQ (DMA1); -dmac[1].cw1 = dmac[1].cw2 = dmac[1].cw3 = 0; +clrCTL (DMALT1); +if (sim_switches & SWMASK ('P')) /* power up? */ + dmac[1].cw1 = dmac[1].cw2 = dmac[1].cw3 = 0; return SCPE_OK; } @@ -2675,8 +2758,8 @@ int32 d; addr = dms_cons (addr, sw); if (addr >= MEMSIZE) return SCPE_NXM; -if (addr == 0) d = saved_AR; -else if (addr == 1) d = saved_BR; +if (!(sw & SIM_SW_REST) && (addr == 0)) d = saved_AR; +else if (!(sw & SIM_SW_REST) && (addr == 1)) d = saved_BR; else d = M[addr]; if (vptr != NULL) *vptr = d & DMASK; return SCPE_OK; @@ -2688,8 +2771,8 @@ t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw) { addr = dms_cons (addr, sw); if (addr >= MEMSIZE) return SCPE_NXM; -if (addr == 0) saved_AR = val & DMASK; -else if (addr == 1) saved_BR = val & DMASK; +if (!(sw & SIM_SW_REST) && (addr == 0)) saved_AR = val & DMASK; +else if (!(sw & SIM_SW_REST) && (addr == 1)) saved_BR = val & DMASK; else M[addr] = val & DMASK; return SCPE_OK; } @@ -2758,6 +2841,16 @@ else dcp->flags = dcp->flags & ~DEV_DIS; return; } +/* Command post-processor + + Update T register to contents of memory addressed by M register. */ + +void hp_post_cmd (t_bool from_scp) +{ +TR = ReadTAB (MR); /* sync T with M */ +return; +} + /* Test for device conflict */ t_bool dev_conflict (void) diff --git a/HP2100/hp2100_defs.h b/HP2100/hp2100_defs.h index 2abd4619..64239252 100644 --- a/HP2100/hp2100_defs.h +++ b/HP2100/hp2100_defs.h @@ -23,6 +23,8 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 30-Dec-04 JDB Added IBL_DS_HEAD head number mask + 19-Nov-04 JDB Added STOP_OFFLINE, STOP_PWROFF stop codes 25-Apr-04 RMS Added additional IBL definitions Added DMA EDT I/O pseudo-opcode 25-Apr-03 RMS Revised for extended file support @@ -35,7 +37,7 @@ 14-Apr-99 RMS Changed t_addr to unsigned The author gratefully acknowledges the help of Jeff Moffat in answering - questions about the HP2100; and of Dave Bryan in adding featurs and + questions about the HP2100; and of Dave Bryan in adding features and correcting errors throughout the simulator. */ @@ -50,6 +52,8 @@ #define STOP_IND 5 /* indirect loop */ #define STOP_INDINT 6 /* indirect intr */ #define STOP_NOCONN 7 /* no connection */ +#define STOP_OFFLINE 8 /* device offline */ +#define STOP_PWROFF 9 /* device powered off */ #define ABORT_PRO 1 /* protection abort */ @@ -69,9 +73,8 @@ #define SIGN32 020000000000 /* 32b sign */ #define SIGN 0100000 /* 16b sign */ #define DMASK 0177777 /* 16b data mask */ -#define AR M[0] /* A = location 0 */ -#define BR M[1] /* B = location 1 */ -#define ABREG M /* register array */ +#define AR ABREG[0] /* A = reg 0 */ +#define BR ABREG[1] /* B = reg 1 */ #define SEXT(x) ((int32) (((x) & SIGN)? ((x) | ~DMASK): ((x) & DMASK))) /* Memory reference instructions */ @@ -232,6 +235,7 @@ struct DMA { /* DMA channel */ #define IBL_V_DEV 6 /* dev in <11:6> */ #define IBL_OPT 0000070 /* options in <5:3> */ #define IBL_DP_REM 0000001 /* DP removable */ +#define IBL_DS_HEAD 0000003 /* DS head number */ #define IBL_LNT 64 /* boot length */ #define IBL_MASK (IBL_LNT - 1) /* boot length mask */ #define IBL_DPC (IBL_LNT - 2) /* DMA ctrl word */ diff --git a/HP2100/hp2100_diag.txt b/HP2100/hp2100_diag.txt index a996c6ec..967ef06d 100644 --- a/HP2100/hp2100_diag.txt +++ b/HP2100/hp2100_diag.txt @@ -1,6 +1,6 @@ SIMH/HP 21XX DIAGNOSTICS PERFORMANCE ==================================== - Last update: 2004-11-02 + Last update: 2004-12-29 The HP 24396 diagnostic suite has been run against the SIMH HP 21xx simulation. @@ -28,7 +28,7 @@ The results of the diagnostic runs are summarized below: 101100 Memory Reference Instruction Group 1624 3.2-3 Passed 101001 Alter-Skip Instruction Group 1431 3.2-3 Passed 101002 Shift-Rotate Instruction Group 1431 3.2-3 Passed -102200 Core Memory (2100/16/15/14) 1624 - No simulation +102200 Core Memory (2100/16/15/14) 1624 3.3-0 Passed 102104 Semiconductor Memory (21MX) 1644 3.2-3 Passed 101004 EAU Instruction Group 1431 3.2-3 Passed @@ -75,7 +75,7 @@ The results of the diagnostic runs are summarized below: 111104 12732 Flexible Disc Subsystem 1708 - No simulation 151302 7900/01 Cartridge Disc 1805 3.2-3 Partial -151403 7905/06/20/25 Disc 1805 - No simulation +151403 7905/06/20/25 Disc 1805 3.3-1 Partial 104117 92900 Terminal Subsystem 1814 - No simulation 112200 9-Track Magnetic Tape (7970, 13181/3) 2040 3.2-3 Partial @@ -225,6 +225,24 @@ TEST RESULT: Passed. +---------------------------------------- +DSN 102200 - Core Memory (2100/16/15/14) +---------------------------------------- + +TESTED DEVICE: CPU (hp2100_cpu.c) + +CONFIGURATION: sim> set CPU 2100 + sim> set CPU 32K + sim> deposit S 000000 + sim> reset + sim> go 100 + +TEST REPORT: HALT instruction 102077 + +TEST RESULT: Passed. + + + --------------------------------- DSN 102104 - Semiconductor Memory --------------------------------- @@ -953,17 +971,381 @@ TEST NOTES: Steps 4, 7, 8, and 9 test the defective and protected cylinder -------------------------------- -DSN 151403 - 7905/06/20/25 Disc -------------------------------- +----------------------------------------------- +DSN 151403 - 7905/06/20/25 Disc (multiple unit) +----------------------------------------------- TESTED DEVICE: DS (hp2100_ds.c) -CONFIGURATION: +CONFIGURATION: sim> set DS0 7905 + sim> set DS1 7906 + sim> set DS2 7920 + sim> set DS3 7925 + sim> set DS4 7905 + sim> set DS5 7906 + sim> set DS6 7920 + sim> set DS7 7925 + sim> attach DS0 scratch.U0.7905.disc + sim> attach DS1 scratch.U1.7906.disc + sim> attach DS2 scratch.U2.7920.disc + sim> attach DS3 scratch.U3.7925.disc + sim> attach DS4 scratch.U4.7905.disc + sim> attach DS5 scratch.U5.7906.disc + sim> attach DS6 scratch.U6.7920.disc + sim> attach DS7 scratch.U7.7925.disc + sim> deposit S 000034 + sim> reset + sim> go 100 -TEST REPORT: + HALT instruction 102074 -TEST RESULT: Not tested. + sim> deposit S 000004 + sim> reset + sim> go + + H0 79XX/13037 DISC MEMORY DIAGNOSTIC + H37 UNIT TABLE: 01 DRIVE(S); 0 + H25 WISH TO CHANGE? + YES + + H34 ENTER UNIT NUMBERS(0-7)SEPARATED BY COMMAS + 0,1,2,3,4,5,6,7 + + H37 UNIT TABLE: 08 DRIVE(S); 0 1 2 3 4 5 6 7 + H25 WISH TO CHANGE? + NO + + ENTER:(U)NIT,(?) ERRS,(H)EAD,(O)UTPUT,(P)ATT,(S)OFT,(C)YL,(M)CPU,(E)XIT + H + + H62 HEAD TABLE; UNIT 0 7905A , 02 HEAD(S) 0 1 + H62 HEAD TABLE; UNIT 1 7906A , 02 HEAD(S) 0 1 + H62 HEAD TABLE; UNIT 2 7920A , 05 HEAD(S) 0 1 2 3 4 + H62 HEAD TABLE; UNIT 3 7925A , 09 HEAD(S) 0 1 2 3 4 5 6 7 8 + H62 HEAD TABLE; UNIT 4 7905A , 02 HEAD(S) 0 1 + H62 HEAD TABLE; UNIT 5 7906A , 02 HEAD(S) 0 1 + H62 HEAD TABLE; UNIT 6 7920A , 05 HEAD(S) 0 1 2 3 4 + H62 HEAD TABLE; UNIT 7 7925A , 09 HEAD(S) 0 1 2 3 4 5 6 7 8 + H25 WISH TO CHANGE? + YES + + H132 TYPE UNITS YOU WISH TO CHANGE SEPERATED BY COMMAS + 0,1,4,5 + + H62 HEAD TABLE; UNIT 0 7905A , 02 HEAD(S) 0 1 + H106 ENTER HEADS SEPARATED BY COMMAS + 0,1,2 + + H62 HEAD TABLE; UNIT 0 7905A , 03 HEAD(S) 0 1 2 + H25 WISH TO CHANGE? + NO + + H62 HEAD TABLE; UNIT 1 7906A , 02 HEAD(S) 0 1 + H106 ENTER HEADS SEPARATED BY COMMAS + 0,1,2,3 + + H62 HEAD TABLE; UNIT 1 7906A , 04 HEAD(S) 0 1 2 3 + H25 WISH TO CHANGE? + NO + + H62 HEAD TABLE; UNIT 4 7905A , 02 HEAD(S) 0 1 + H106 ENTER HEADS SEPARATED BY COMMAS + 0,1,2 + + H62 HEAD TABLE; UNIT 4 7905A , 03 HEAD(S) 0 1 2 + H25 WISH TO CHANGE? + NO + + H62 HEAD TABLE; UNIT 5 7906A , 02 HEAD(S) 0 1 + H106 ENTER HEADS SEPARATED BY COMMAS + 0,1,2,3 + + H62 HEAD TABLE; UNIT 5 7906A , 04 HEAD(S) 0 1 2 3 + H25 WISH TO CHANGE? + NO + + ENTER:(U)NIT,(?) ERRS,(H)EAD,(O)UTPUT,(P)ATT,(S)OFT,(C)YL,(M)CPU,(E)XIT + E + +TEST REPORT: H121 WARNING-FORMAT SWITCH OFF + H65 LONG PASS 0001,HEAD 012 ,UNIT 0,0000 ERRORS-0000 SOFT + H65 LONG PASS 0002,HEAD 0123 ,UNIT 1,0000 ERRORS-0000 SOFT + H65 LONG PASS 0003,HEAD 01234 ,UNIT 2,0000 ERRORS-0000 SOFT + H65 LONG PASS 0004,HEAD 012345678,UNIT 3,0000 ERRORS-0000 SOFT + H65 LONG PASS 0005,HEAD 012 ,UNIT 4,0000 ERRORS-0000 SOFT + H65 LONG PASS 0006,HEAD 0123 ,UNIT 5,0000 ERRORS-0000 SOFT + H65 LONG PASS 0007,HEAD 01234 ,UNIT 6,0000 ERRORS-0000 SOFT + H65 LONG PASS 0008,HEAD 012345678,UNIT 7,0000 ERRORS-0000 SOFT,MULTI-UNIT + + [CTRL+E] + Simulation stopped + +TEST RESULT: Passed. + +TEST NOTES: Eight passes are required to test all head/unit combinations. + + + +-------------------------------------------------- +DSN 151403 - 7905/06/20/25 Disc (user interaction) +-------------------------------------------------- + +TESTED DEVICE: DS (hp2100_ds.c) + +CONFIGURATION: sim> set DS0 7905 + sim> attach DS0 scratch.U0.7905.disc + sim> deposit S 000034 + sim> reset + sim> go 100 + + HALT instruction 102074 + + sim> deposit S 000120 + sim> reset + sim> go + + H0 79XX/13037 DISC MEMORY DIAGNOSTIC + H37 UNIT TABLE: 01 DRIVE(S); 0 + H25 WISH TO CHANGE? + NO + +TEST REPORT: H66 SET FORMAT SWITCH ON UNIT 0,PUSH RUN + + HALT instruction 102002 + + sim> set DS0 FORMAT + sim> go + + H46 READ IN STEP 04 + H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B + E64 STATUS IS 0 0 0 00000 0000 0000 / 0 000010 0 0 0 1 0 0 0 0 0 + SHOULD BE 0 1 0 00000 XXXX XXXX / 0 000010 0 0 0 1 0 0 0 0 0 + H137 TERMINATION STATUS IS "NORMAL COMPLET" + START 0000/00/00-LAST 0000/00/01 WORD COUNT 00128,OLD CYL 0000,UNIT 00 + + HALT instruction 102001 + + sim> go + + H22 VERIFY IN STEP 04 + H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B + E64 STATUS IS 0 0 0 00000 0000 0000 / 0 000010 0 0 0 1 0 0 0 0 0 + SHOULD BE 0 1 0 00000 XXXX XXXX / 0 000010 0 0 0 1 0 0 0 0 0 + H137 TERMINATION STATUS IS "NORMAL COMPLET" + START 0000/00/00-LAST 0001/00/00 WORD COUNT 00048,OLD CYL 0000,UNIT 00 + + HALT instruction 102001 + + sim> go + + H67 CLEAR FORMAT SWITCH ON UNIT 0,PUSH RUN + + HALT instruction 102002 + + sim> set DS0 NOFORMAT + sim> go + + H46 READ IN STEP 07 + H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B + E64 STATUS IS 0 0 0 00000 0000 0000 / 0 000010 0 0 0 0 0 0 0 0 0 + SHOULD BE 0 0 1 10001 XXXX XXXX / 0 000010 0 0 0 0 0 0 0 0 0 + H137 TERMINATION STATUS IS "NORMAL COMPLET" SHOULD BE "DEFECTIVE TRK " + START 0001/00/00-LAST 0001/00/01 WORD COUNT 00128,OLD CYL 0000,UNIT 00 + + HALT instruction 102001 + + sim> go + + H45 WRITE IN STEP 08 + H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B + E64 STATUS IS 0 0 0 00000 0000 0000 / 0 000010 0 0 0 0 0 0 0 0 0 + SHOULD BE 0 1 0 10110 XXXX XXXX / 0 000010 0 0 0 0 0 0 0 0 0 + H137 TERMINATION STATUS IS "NORMAL COMPLET" SHOULD BE "WRT PROTEC TRK" + START 0000/00/00-LAST 0000/00/01 WORD COUNT 00128,OLD CYL 0001,UNIT 00 + + HALT instruction 102001 + + sim> go + + H66 SET FORMAT SWITCH ON UNIT 0,PUSH RUN + + HALT instruction 102002 + + sim> set DS0 FORMAT + sim> go + + H45 WRITE IN STEP 10 + H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B + E64 STATUS IS 0 0 0 00000 0000 0000 / 0 000010 0 0 0 1 0 0 0 0 0 + SHOULD BE 0 1 0 00000 XXXX XXXX / 0 000010 0 0 0 1 0 0 0 0 0 + H137 TERMINATION STATUS IS "NORMAL COMPLET" + START 0000/00/00-LAST 0000/00/08 WORD COUNT 01024,OLD CYL 0000,UNIT 00 + + HALT instruction 102001 + + sim> go + + H70 UNLOAD UNIT 0,PUSH RUN + + HALT instruction 102002 + + sim> detach DS0 + sim> go + + H107 READY UNIT 0 + + [CTRL+E] + Simulation stopped + + sim> attach DS0 scratch.U0.7905.disc + sim> go + + H142 PROTECT U/D,PUSH RUN + + HALT instruction 102002 + + sim> set DS0 LOCKED + sim> go + + H143 CLEAR U/D PROTECT,PUSH RUN + + HALT instruction 102002 + + sim> set DS0 WRITEENABLED + sim> go + + H110 PRESS PRESET(S),PRESS RUN + + HALT instruction 102002 + + sim> reset + sim> go + + H46 READ IN STEP 38 + H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B + E64 STATUS IS 0 0 0 00000 0000 0000 / 0 000010 0 0 0 1 0 0 0 0 0 + SHOULD BE 0 0 0 00111 0000 0000 / 0 000010 0 0 0 X 0 0 0 0 0 + H137 TERMINATION STATUS IS "NORMAL COMPLET" SHOULD BE "CYL CMP ERROR " + START 0000/00/01-LAST 0000/00/03 WORD COUNT 00138,OLD CYL 0000,UNIT 00 + + HALT instruction 102001 + + sim> go + + H46 READ IN STEP 39 + H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B + E64 STATUS IS 0 0 0 00000 0000 0000 / 0 000010 0 0 0 1 0 0 0 0 0 + SHOULD BE 0 0 0 01001 XXXX XXXX / 0 000010 0 0 0 X 0 0 0 0 0 + H137 TERMINATION STATUS IS "NORMAL COMPLET" SHOULD BE "HD/SEC CMP ERR" + START 0000/00/01-LAST 0000/00/03 WORD COUNT 00138,OLD CYL 0000,UNIT 00 + + HALT instruction 102001 + + sim> go + + H46 READ IN STEP 40 + H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B + E64 STATUS IS 0 0 0 00000 0000 0000 / 0 000010 0 0 0 1 0 0 0 0 0 + SHOULD BE 0 0 0 01001 XXXX XXXX / 0 000010 0 0 0 X 0 0 0 0 0 + H137 TERMINATION STATUS IS "NORMAL COMPLET" SHOULD BE "HD/SEC CMP ERR" + START 0000/00/01-LAST 0000/00/03 WORD COUNT 00138,OLD CYL 0000,UNIT 00 + + HALT instruction 102001 + + sim> go + + H46 READ IN STEP 41 + E47 DATA WORD 0065 IS 075126 SHOULD BE 030400 + E47 DATA WORD 0066 IS 000762 SHOULD BE 030400 + H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B + E64 STATUS IS 0 0 0 00000 0000 0000 / 0 000010 0 0 0 1 0 0 0 0 0 + SHOULD BE 0 0 0 01111 XXXX XXXX / 0 000010 0 0 0 X 0 0 0 0 0 + H137 TERMINATION STATUS IS "NORMAL COMPLET" SHOULD BE "POSS CORR DATA" + START 0000/00/00-LAST 0000/00/03 WORD COUNT 00128,OLD CYL 0000,UNIT 00 + + HALT instruction 102001 + + sim> go + + H46 READ IN STEP 42 + H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B + E64 STATUS IS 0 0 0 00000 0000 0000 / 0 000010 0 0 0 1 0 0 0 0 0 + SHOULD BE 0 0 0 01000 XXXX XXXX / 0 000010 0 0 0 X 0 0 0 0 0 + H137 TERMINATION STATUS IS "NORMAL COMPLET" SHOULD BE "UNCOR DATA ERR" + START 0000/00/00-LAST 0000/00/03 WORD COUNT 00276,OLD CYL 0000,UNIT 00 + + HALT instruction 102001 + + sim> go + + H22 VERIFY IN STEP 43 + H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B + E64 STATUS IS 0 0 0 00000 0000 0000 / 0 000010 0 0 0 1 0 0 0 0 0 + SHOULD BE 0 0 1 10001 XXXX XXXX / 0 000010 0 0 0 X 0 0 0 0 0 + H137 TERMINATION STATUS IS "NORMAL COMPLET" SHOULD BE "DEFECTIVE TRK " + START 0016/00/00-LAST 0017/00/00 WORD COUNT 00048,OLD CYL 0128,UNIT 00 + + HALT instruction 102001 + + sim> go + + H22 VERIFY IN STEP 43 + H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B + E64 STATUS IS 0 0 0 00000 0000 0000 / 0 000010 0 0 0 1 0 0 0 0 0 + SHOULD BE 1 0 0 10000 XXXX XXXX / 0 000010 0 0 0 X 0 0 0 0 0 + H137 TERMINATION STATUS IS "NORMAL COMPLET" SHOULD BE "SPR TRK ACCESS" + START 0128/01/00-LAST 0129/01/00 WORD COUNT 00048,OLD CYL 0016,UNIT 00 + + HALT instruction 102001 + + sim> go + + H45 WRITE IN STEP 43 + H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B + E64 STATUS IS 0 0 0 00000 0000 0000 / 0 000010 0 0 0 1 0 0 0 0 0 + SHOULD BE 1 0 0 00000 XXXX XXXX / 0 000010 0 0 0 X 0 0 0 0 0 + H137 TERMINATION STATUS IS "NORMAL COMPLET" + START 0016/00/33-LAST 0016/00/34 WORD COUNT 00128,OLD CYL 0128,UNIT 00 + + HALT instruction 102001 + + sim> go + + H46 READ IN STEP 43 + H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B + E64 STATUS IS 0 0 0 00000 0000 0000 / 0 000010 0 0 0 1 0 0 0 0 0 + SHOULD BE 1 0 0 00000 XXXX XXXX / 0 000010 0 0 0 X 0 0 0 0 0 + H137 TERMINATION STATUS IS "NORMAL COMPLET" + START 0016/00/33-LAST 0016/00/34 WORD COUNT 00128,OLD CYL 0016,UNIT 00 + + HALT instruction 102001 + + sim> go + + H46 READ IN STEP 43 + H135 S P D TSTAT XXXX UNIT / E DRTYPE X A P F DF FS SC NR B + E64 STATUS IS 0 0 0 00111 0000 0000 / 0 000010 0 0 0 1 0 0 0 0 0 + SHOULD BE 1 0 0 00000 XXXX XXXX / 0 000010 0 0 0 X 0 0 0 0 0 + H137 TERMINATION STATUS IS "CYL CMP ERROR " SHOULD BE "NORMAL COMPLET" + E13 0000 WORDS TRANSFERRED 0128 EXPECTED + START 0016/00/33-LAST 0016/00/33 WORD COUNT 00128,OLD CYL 0016,UNIT 00 + + HALT instruction 102001 + + sim> go + + H65 SHORT PASS 0001,HEAD 01 ,UNIT 0,0015 ERRORS-0015 SOFT + + [CTRL+E] + Simulation stopped + +TEST RESULT: Partially passed. + +TEST NOTES: Steps 4, 8, and 10 test the protected cylinder bit. Step 7 + tests the defective cylinder bit. Steps 38, 39, and 40 test the + Write Full Sector command. Steps 41 and 42 test error + correction. Step 43 tests the spare cylinder bit and track + sparing. These features are not simulated. diff --git a/HP2100/hp2100_doc.txt b/HP2100/hp2100_doc.txt index 45c7d86a..c45dc9db 100644 --- a/HP2100/hp2100_doc.txt +++ b/HP2100/hp2100_doc.txt @@ -1,7 +1,7 @@ To: Users From: Bob Supnik Subj: HP2100 Simulator Usage -Date: 26-Oct-2004 +Date: 22-Dec-2004 COPYRIGHT NOTICE @@ -59,6 +59,7 @@ sim/hp2100/ hp2100_defs.h hp2100_dp.c hp2100_dq.c hp2100_dr.c + hp2100_ds.c hp2100_ipl.c hp2100_lps.c hp2100_lpt.c @@ -77,7 +78,7 @@ name(s) CPU 2116 CPU with 32KW memory 2100 CPU with 32KW memory, FP or IOP instructions - 21MX CPU with 1024KW memory, FP, DMS, and/or IOP instructions + 21MX-M/E CPU with 1024KW memory, FP, DMS, and/or IOP instructions MP 12892B memory protect DMA0, DMA1 12895A/12897B direct memory access/dual channel port controller PTR 12597A duplex register interface with 2748 paper tape reader @@ -93,6 +94,7 @@ DP 12557A disk controller with four 2871 drives DQ 12565A disk controller with two 2883 drives DR 12606B fixed head disk controller with 2770/2771 disk 12610B drum controller with 2773/2774/2775 drum +DS 13037 disk controller with eight 7905/7906/7920/7925 drives MT 12559C magnetic tape controller with one 3030 drive MS 13181A magnetic tape controller with four 7970B drives 13183A magnetic tape controller with four 7970E drives @@ -120,7 +122,8 @@ Options that may be specified are: SET CPU 2116 2116 CPU SET CPU 2100 2100 CPU - SET CPU 21MX 21MX CPU + SET CPU 21MX-M 21MX M-series CPU + SET CPU 21MX-E 21MX E-series CPU SET CPU EAU EAU instructions (2116 only) SET CPU NOEAU no EAU instructions (2116 only) SET CPU FP FP instructions (2100 only) @@ -141,7 +144,9 @@ Options that may be specified are: On the 2100, EAU is standard, and the FP and IOP options are mutually exclusive. On the 21MX, EAU and FP are standard. The 21MX optionally -includes DMS (dynamic mapping system) and IOP instructions. +includes DMS (dynamic mapping system) and IOP instructions. The 21MX-E +supports the TIMER instruction; on the 21MX-M, this instruction decodes +as MPY. Setting the CPU type to 2116, 2100, or 21MX establishes a consistent set of common options. Additional SET CPU commands may follow to fine-tune @@ -274,6 +279,7 @@ DMA1). Each DMA channel has the following visible state: CTL 1 interrupt enabled FLG 1 channel ready FBF 1 channel ready buffer + CTLALT 1 command word 2/3 selector CW1 16 command word 1 CW2 16 command word 2 CW3 16 command word 3 @@ -532,8 +538,18 @@ In printer mode, error handling is as follows: not attached 1 report error and stop 0 out of paper + SET POWEROFF 1 report error and stop + 0 powered off + + SET OFFLINE 1 report error and stop + 0 offline + OS I/O error x report error and stop +With STOP_IOE set to 0, output performed when the device is powered off +or offline will initiate but then hang, waiting for the device to be +returned online. When it is, the output operation will complete. + In diagnostic mode, there are no errors; data sent to the output buffer is looped back to the status register with a fixed delay of 1. @@ -573,8 +589,18 @@ Error handling is as follows: not attached 1 report error and stop 0 out of paper + SET POWEROFF 1 report error and stop + 0 powered off + + SET OFFLINE 1 report error and stop + 0 offline + OS I/O error x report error and stop +With STOP_IOE set to 0, output performed when the device is powered off +or offline will initiate but then hang, waiting for the device to be +returned online. When it is, the output operation will complete. + 2.5.6 12539C Time Base Generator (CLK) The time base generator (CLK) may be set for diagnostic mode: @@ -754,8 +780,10 @@ Both IPLI and IPLO implement these registers: TIME 24 polling interval for input STOP_IOE 1 stop on I/O error -2.6 12557A Disk Controller (DPC, DPD) with Four 2781 Drives - 13210A Disk Controller (DPC, DPD) with Four 7900 Drives +2.6 Disk Controllers + +2.6.1 12557A Disk Controller (DPC, DPD) with Four 2781 Drives + 13210A Disk Controller (DPC, DPD) with Four 7900 Drives The 12557A/13210A disk controller can be configured as either a 12557A, supporting 2.5MB drives, or a 13210A, supporting 5MB drives, @@ -773,9 +801,19 @@ a command channel. The data channel includes a 128-word (one sector) buffer for reads and writes. The command channel includes the four disk drives. Disk drives can be set DISABLED or ENABLED. +Individual drives may be protected against writing. These commands +simulate the Upper/Lower Disc Protect switches on the drives: + + SET DPCn LOCKED set unit n write locked + SET DPCn WRITEENABLED set unit n write enabled + +Separate protection for the upper and lower platters of the 7900 drive +is not supported. Also, the drive Protect/Override switch is not +supported; drive protection is permanently overridden. + The 12557A/13210A supports the BOOT command. BOOT DPC copies the IBL for 7900 class disks into memory and starts it running. BOOT -R DPC -boots from the removable platter (head 2). The switch register (S) is +boots from the removable platter (head 0). The switch register (S) is set automatically to the value expected by the IBL loader: <15:14> = 01 @@ -827,21 +865,26 @@ The command channel implements these registers: Error handling is as follows: - error processed as + error processed as - not attached disk not ready + not attached disk not ready (drive unloaded) - end of file assume rest of disk is zero + end of file assume rest of disk is zero - OS I/O error report error and stop + OS I/O error report error and stop -2.7 12565A Disk Controller (DQC, DQD) with Two 2883 Drives +2.6.2 12565A Disk Controller (DQC, DQD) with Two 2883 Drives The 12565A disk controller has two separate devices, a data channel and a command channel. The data channel includes a 128-word (one sector) buffer for reads and writes. The command channel includes the two disk drives. Disk drives can be set DISABLED or ENABLED. +Individual drives may be protected against writing: + + SET DQCn LOCKED set unit n write locked + SET DQCn WRITEENABLED set unit n write enabled + The 12565A supports the BOOT command. BOOT DQC copies the IBL for 2883 class disks into memory and starts it running. The switch register (S) is set automatically to the value expected by the IBL loader: @@ -892,16 +935,16 @@ The command channel implements these registers: Error handling is as follows: - error processed as + error processed as - not attached disk not ready + not attached disk not ready - end of file assume rest of disk is zero + end of file assume rest of disk is zero - OS I/O error report error and stop + OS I/O error report error and stop -2.8 12606B Fixed Head Disk Controller (DRC, DRD) with 2770/2771 Disk - 12610B Drum Controller (DRC, DRD) with 2773/2774/2775 Drum +2.6.3 12606B Fixed Head Disk Controller (DRC, DRD) with 2770/2771 Disk + 12610B Drum Controller (DRC, DRD) with 2773/2774/2775 Drum The 12606B/12610B fixed head disk/drum controller has two separate devices, a data channel and a command channel. @@ -982,7 +1025,93 @@ Error handling is as follows: 12606B/12610B data files are buffered in memory; therefore, end of file and OS I/O errors cannot occur. -2.9 12559C Magnetic Tape Controller (MTC, MTD) with One 3030 Drive +2.6.4 13037 Disk Controller (DS) with Eight 7905/7906/7920/7925 Drives + +The 13037 disk controller supports 7905 (15MB), 7906 (20MB), 7920 (50MB), +or 7925 (120MB) disk drives, as well as autosizing, based on the size +of the disk image file: + + SET DSn 7905 drive n is a 15MB drive + SET DSn 7906 drive n is a 20MB drive + SET DSn 7920 drive n is a 50MB drive + SET DSn 7925 drive n is a 120MB drive + SET DSn AUTOSIZE drive n type based on file size at attach + +Drive types can be intermixed. The 7905 is selected by default. Drives +can be set DISABLED or ENABLED. + +Individual drives may be protected against writing. These commands +simulate the Disc Protect/Read Only switches on the drives: + + SET DSn LOCKED set unit n write locked + SET DSn WRITEENABLED set unit n write enabled + +Separate protection for the upper and lower platters of the 7905 and +7906 drives is not supported. Protecting a 7905 or 7906 drive behaves +as though both of the Disc Protect switches were on. + +The setting of the drive Format switch may be changed with: + + SET DSn FORMAT set format enabled + SET DSn NOFORMAT set format disabled + +The 13037 supports the BOOT command. BOOT DS copies the IBL loader for +the 13037 controller into memory and starts it running. The switch register +(S) is set automatically to the value expected by the IBL loader: + + <15:14> = 11 + <13:12> = 01 + <11:6> = data channel device code + <5:3> = unchanged + <2> = 0 + <1:0> = unchanged (head number) + +The DS controller implements these registers: + + name size comments + + CMD 16 command register + FIFO[0:15] 16 data FIFO + SR1 16 status register 1 + VCTR 16 verify counter + FMASK 8 file mask + CYL 16 cylinder address register + HS 16 head/sector address register + STATE 2 controller state + LASTA 3 last unit polled for attention flag + FIP 4 FIFO insertion pointer + FRP 4 FIFO removal pointer + FCNT 5 FIFO counter + CTL 1 interrupt enable + FLG 1 ready flag + FBF 1 ready flag buffer + SRQ 1 DMA service request + BUSY 1 visible busy status + CMDF 1 command follows flag + CMDP 1 command pending flag + EOC 1 end of cylinder flag + EOD 1 end of data flag + DBUF[0:127] 16 sector buffer + DPTR 8 sector buffer pointer + CTIME 24 command response time + DTIME 24 data transfer response time + STIME 24 seek time (per cylinder) + RTIME 24 rotation time + TIMEOUT 31 controller timeout + +Error handling is as follows: + + error processed as + + not attached disk not ready + + end of file assume rest of disk is zero + + OS I/O error report error and stop + +2.7 Magnetic Tape + +2.7.1 12559C Magnetic Tape Controller (MTC, MTD) with One 3030 Drive Magnetic tape options include the ability to make the unit write enabled or write locked. @@ -1037,8 +1166,8 @@ Error handling is as follows: OS I/O error parity error; if STOP_IOE, stop -2.10 13181A Magnetic Tape Controller (MSC, MSD) with Four 7970B Drives - 18183A Magnetic Tape Controller (MSC, MSD) with Four 7970E Drives +2.7.2 13181A Magnetic Tape Controller (MSC, MSD) with Four 7970B Drives + 18183A Magnetic Tape Controller (MSC, MSD) with Four 7970E Drives Magnetic tape options include the ability to make the unit write enabled or write locked, and the ability to select the 13181A (800 bpi) controller @@ -1126,7 +1255,7 @@ Error handling is as follows: OS I/O error parity error; if STOP_IOE, stop -2.11 Symbolic Display and Input +2.8 Symbolic Display and Input The HP2100 simulator implements symbolic display and input. Display is controlled by command line switches: diff --git a/HP2100/hp2100_dp.c b/HP2100/hp2100_dp.c index 48f45bc6..42395a42 100644 --- a/HP2100/hp2100_dp.c +++ b/HP2100/hp2100_dp.c @@ -199,7 +199,6 @@ #define STA_UNLOADED (dp_ctype ? (STA_NRDY | STA_BSY) : STA_NRDY) #define STA_MBZ13 (STA_ATN | STA_RWU | STA_SKI) /* zero in 13210 */ -extern uint16 *M; extern uint32 PC, SR; extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2]; extern int32 sim_switches; diff --git a/HP2100/hp2100_dq.c b/HP2100/hp2100_dq.c index 471dfdd7..84b1f2c0 100644 --- a/HP2100/hp2100_dq.c +++ b/HP2100/hp2100_dq.c @@ -136,7 +136,6 @@ #define STA_ERR 0000001 /* any error */ #define STA_ANYERR (STA_NRDY | STA_EOC | STA_AER | STA_FLG | STA_DTE) -extern uint16 *M; extern uint32 PC, SR; extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2]; extern int32 sim_switches; diff --git a/HP2100/hp2100_ds.c b/HP2100/hp2100_ds.c index 04a8c4bb..7aa53c0d 100644 --- a/HP2100/hp2100_ds.c +++ b/HP2100/hp2100_ds.c @@ -39,6 +39,11 @@ - Busy. The controller is processing a command. The controller does not respond to new commands or to drive attention interrupts. + The controller busy state is loosely related to the testable (visible) busy + flop. If the visible busy flop is set, the controller is in the busy state; + but the controller can also be busy (processing an invalid opcode or invalid + unit) while visible busy is clear. + Omissions: the following features are not implemented: - Drive hold. Since this is a single CPU implementation, the drives are @@ -46,6 +51,9 @@ - Spare, defective, protected. The disk files carry only data. - Formatting. The disk files carry only data. - ECC. Data errors are always uncorrectable. + + Reference: + - 13037 Disc Controller Technical Information Package (13037-90902, Aug-1980) */ #include "hp2100_defs.h" @@ -60,10 +68,9 @@ #define DS_FHS 2 #define DS_FDATA 3 #define DS_FIFO_SIZE 16 /* fifo size */ +#define DS_FIFO_EMPTY (ds_fifo_cnt == 0) #define ds_ctrl ds_unit[DS_NUMDR] /* ctrl thread */ #define ds_timer ds_unit[DS_NUMDR + 1] /* timeout thread */ -#define GET_DA(x,y,z,t) \ - ((((((x) * drv_tab[t].hd) + (y)) * drv_tab[t].sc) + (z)) * DS_NUMWD) #define GET_CURSEC(x,d) ((int32) fmod (sim_gtime() / ((double) (x)), \ ((double) (drv_tab[d].sc)))) @@ -112,9 +119,9 @@ #define DSC_RFULL 006 /* read full */ #define DSC_VFY 007 /* verify */ #define DSC_WRITE 010 /* write */ -#define DSC_WFULL 011 /* write full - na */ +#define DSC_WFULL 011 /* write full */ #define DSC_CLEAR 012 /* clear */ -#define DSC_INIT 013 /* initialize - na */ +#define DSC_INIT 013 /* initialize */ #define DSC_AREC 014 /* address record */ #define DSC_RSYN 015 /* request syndrome */ #define DSC_ROFF 016 /* read with offset */ @@ -124,7 +131,7 @@ #define DSC_RDA 024 /* request disk addr */ #define DSC_END 025 /* end */ #define DSC_WAKE 026 /* wakeup */ -#define DSC_ATTN 035 /* pseudo: ATTN */ +#define DSC_ATN 035 /* pseudo: ATN */ #define DSC_BADU 036 /* pseudo: bad unit */ #define DSC_BADF 037 /* pseudo: bad opcode */ #define DSC_NEXT 0040 /* state increment */ @@ -138,24 +145,30 @@ #define DSC_V_RTY 4 /* retry count */ #define DSC_M_RTY 017 #define DSC_V_DECR 3 /* seek decrement */ -#define DSC_V_SPAR 2 /* enable sparing */ +#define DSC_V_SPEN 2 /* enable sparing */ #define DSC_V_CYLM 1 /* cylinder mode */ #define DSC_V_AUTO 0 /* auto seek */ #define DSC_V_HOLD 7 /* hold flag */ #define DSC_V_UNIT 0 /* unit */ #define DSC_M_UNIT 017 +#define DSC_V_SPAR 15 /* INIT spare */ +#define DSC_V_PROT 14 /* INIT protected */ +#define DSC_V_DFCT 13 /* INIT defective */ #define DSC_HOLD (1u << DSC_V_HOLD) #define DSC_DECR (1u << DSC_V_DECR) -#define DSC_SPAR (1u << DSC_V_SPAR) +#define DSC_SPEN (1u << DSC_V_SPEN) #define DSC_CYLM (1u << DSC_V_CYLM) #define DSC_AUTO (1u << DSC_V_AUTO) #define DSC_FMASK ((DSC_M_RTY << DSC_V_RTY)|DSC_DECR|\ - DSC_SPAR|DSC_CYLM|DSC_AUTO) + DSC_SPEN|DSC_CYLM|DSC_AUTO) #define DSC_GETOP(x) (((x) >> DSC_V_OP) & DSC_M_OP) #define DSC_GETUNIT(x) (((x) >> DSC_V_UNIT) & DSC_M_UNIT) #define DSC_GETCHD(x) (((x) >> DSC_V_CHD) & DSC_M_CHD) #define DSC_GETCSC(x) (((x) >> DSC_V_CSC) & DSC_M_CSC) +#define DSC_SPAR (1u << DSC_V_SPAR) +#define DSC_PROT (1u << DSC_V_PROT) +#define DSC_DFCT (1u << DSC_V_DFCT) /* Command flags */ @@ -199,15 +212,19 @@ #define DS1_S2ERR (023 << DS1_V_STAT) /* status 2 error */ #define DS1_TKPER (026 << DS1_V_STAT) /* protected trk - na */ #define DS1_UNAVL (027 << DS1_V_STAT) /* illegal unit */ -#define DS1_ATTN (037 << DS1_V_STAT) /* attention */ +#define DS1_ATN (037 << DS1_V_STAT) /* attention */ #define DS1_V_UNIT 0 +#define DS1_SPAR (1u << DS1_V_SPAR) +#define DS1_PROT (1u << DS1_V_PROT) +#define DS1_DFCT (1u << DS1_V_DFCT) /* Status 2, ^ = kept in unit status, * = dynamic */ #define DS2_ERR 0100000 /* *error */ +#define DS2_V_ID 9 /* drive type */ #define DS2_ATN 0000200 /* ^attention */ #define DS2_RO 0000100 /* *read only */ -#define DS2_FRM 0000040 /* format - na */ +#define DS2_FRM 0000040 /* *format */ #define DS2_FLT 0000020 /* fault - na */ #define DS2_FS 0000010 /* ^first status */ #define DS2_SC 0000004 /* ^seek error */ @@ -234,34 +251,69 @@ In theory, each drive can be a different type. The size field in each unit selects the drive capacity for each drive and thus the drive type. DISKS MUST BE DECLARED IN ASCENDING SIZE. + + The 7905 and 7906 have fixed and removable platters. Consequently, + they are almost always accessed with cylinders limited to each + platter. The 7920 and 7925 have multiple-platter packs, and so are + almost always accessed with cylinders that span all surfaces. + + Disk image files are arranged as a linear set of tracks. To improve + locality, tracks on the 7905 and 7906 images are grouped per-platter, + i.e., all tracks on heads 0 and 1, followed by all tracks on head 2 + (and, for the 7906, head 3), whereas tracks on the 7920 and 7925 are + sequential by cylinder and head number. + + This variable-access geometry is accomplished by defining a "heads + per cylinder" value for the fixed and removable sections of each + drive that indicates the number of heads that should be grouped for + locality. The removable values are set to 2 on the 7905 and 7906, + indicating that those drives typically use cylinders of two surfaces. + They are set to the number of surfaces per drive for the 7920 and + 7925, as those typically use cylinders encompassing the entire + spindle. */ +#define GET_DA(x,y,z,t) \ + (((((y) < drv_tab[t].rh)? \ + (x) * drv_tab[t].rh + (y): \ + drv_tab[t].cyl * drv_tab[t].rh + \ + ((x) * drv_tab[t].fh + (y) - drv_tab[t].rh)) * \ + drv_tab[t].sc + (z)) * DS_NUMWD) + #define D7905_DTYPE 0 #define D7905_SECT 48 #define D7905_SURF 3 +#define D7905_RH 2 +#define D7905_FH (D7905_SURF - D7905_RH) #define D7905_CYL 411 -#define D7905_ID 2 +#define D7905_ID (2 << DS2_V_ID) #define D7905_SIZE (D7905_SECT * D7905_SURF * D7905_CYL * DS_NUMWD) #define D7906_DTYPE 1 #define D7906_SECT 48 #define D7906_SURF 4 +#define D7906_RH 2 +#define D7906_FH (D7906_SURF - D7906_RH) #define D7906_CYL 411 -#define D7906_ID 0 +#define D7906_ID (0 << DS2_V_ID) #define D7906_SIZE (D7906_SECT * D7906_SURF * D7906_CYL * DS_NUMWD) #define D7920_DTYPE 2 #define D7920_SECT 48 #define D7920_SURF 5 +#define D7920_RH D7920_SURF +#define D7920_FH (D7920_SURF - D7920_RH) #define D7920_CYL 823 -#define D7920_ID 1 +#define D7920_ID (1 << DS2_V_ID) #define D7920_SIZE (D7920_SECT * D7920_SURF * D7920_CYL * DS_NUMWD) #define D7925_DTYPE 3 #define D7925_SECT 64 #define D7925_SURF 9 +#define D7925_RH D7925_SURF +#define D7925_FH (D7925_SURF - D7925_RH) #define D7925_CYL 823 -#define D7925_ID 3 +#define D7925_ID (3 << DS2_V_ID) #define D7925_SIZE (D7925_SECT * D7925_SURF * D7925_CYL * DS_NUMWD) struct drvtyp { @@ -270,16 +322,17 @@ struct drvtyp { uint32 cyl; /* cylinders */ uint32 size; /* #blocks */ uint32 id; /* device type */ + uint32 rh; /* removable surfaces */ + uint32 fh; /* fixed surfaces */ }; static struct drvtyp drv_tab[] = { - { D7905_SECT, D7905_SURF, D7905_CYL, D7905_SIZE, D7905_ID }, - { D7906_SECT, D7906_SURF, D7906_CYL, D7906_SIZE, D7906_ID }, - { D7920_SECT, D7920_SURF, D7920_CYL, D7920_SIZE, D7920_ID }, - { D7925_SECT, D7925_SURF, D7925_CYL, D7925_SIZE, D7925_ID }, + { D7905_SECT, D7905_SURF, D7905_CYL, D7905_SIZE, D7905_ID, D7905_RH, D7905_FH }, + { D7906_SECT, D7906_SURF, D7906_CYL, D7906_SIZE, D7906_ID, D7906_RH, D7906_FH }, + { D7920_SECT, D7920_SURF, D7920_CYL, D7920_SIZE, D7920_ID, D7920_RH, D7920_FH }, + { D7925_SECT, D7925_SURF, D7925_CYL, D7925_SIZE, D7925_ID, D7925_RH, D7925_FH }, { 0 } }; -extern uint16 *M; extern uint32 PC, SR; extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2]; extern int32 sim_switches; @@ -291,7 +344,6 @@ uint32 ds_fifo_rp = 0; /* removal ptr */ uint32 ds_fifo_cnt = 0; /* count */ uint32 ds_cmd = 0; /* command word */ uint32 ds_sr1 = 0; /* status word 1 */ -uint32 ds_u = 0; /* saved unit */ uint32 ds_busy = 0; /* busy flag */ uint32 ds_eoc = 0; /* end of cylinder */ uint32 ds_eod = 0; /* end of data */ @@ -302,12 +354,12 @@ uint32 ds_cyl = 0; /* disk address: cyl */ uint32 ds_hs = 0; /* disk address: hs */ uint32 ds_vctr = 0; /* verify counter */ uint32 ds_state = 0; /* controller state */ -uint32 ds_lastatn = 0; /* last attn intr */ +uint32 ds_lastatn = 0; /* last atn intr */ int32 ds_stime = 100; /* seek time */ int32 ds_rtime = 100; /* inter-sector time */ int32 ds_ctime = 3; /* command time */ int32 ds_dtime = 1; /* dch time */ -int32 ds_tmo = 1000000; /* timeout */ +int32 ds_tmo = 2749200; /* timeout = 1.74 sec */ uint32 ds_ptr = 0; /* buffer ptr */ uint16 dsxb[DS_NUMWDF]; /* sector buffer */ @@ -351,7 +403,6 @@ t_stat ds_svc_c (UNIT *uptr); t_stat ds_svc_u (UNIT *uptr); t_stat ds_svc_t (UNIT *uptr); t_stat ds_reset (DEVICE *dptr); -t_stat ds_vlock (UNIT *uptr, int32 val); t_stat ds_attach (UNIT *uptr, char *cptr); t_stat ds_detach (UNIT *uptr); t_stat ds_boot (int32 unitno, DEVICE *dptr); @@ -359,7 +410,7 @@ t_stat ds_set_size (UNIT *uptr, int32 val, char *cptr, void *desc); void ds_poll (void); void ds_docmd (uint32 cmd); void ds_doatn (void); -uint32 ds_updds2 (UNIT *uptr, uint32 clear); +uint32 ds_updds2 (UNIT *uptr); void ds_cmd_done (t_bool sf, uint32 sr1); void ds_wait_for_cpu (UNIT *uptr, uint32 newst); void ds_set_idle (void); @@ -376,7 +427,7 @@ t_stat ds_cont_wr (UNIT *uptr, uint32 off, uint32 bsize); void ds_end_rw (UNIT *uptr, uint32 newst); t_stat ds_set_uncorr (UNIT *uptr); t_stat ds_reset_cmn (DEVICE *dptr); -void ds_sched_attn (UNIT *uptr); +void ds_sched_atn (UNIT *uptr); uint32 ds_fifo_read (void); void ds_fifo_write (uint32 dat); void ds_fifo_reset (void); @@ -416,7 +467,6 @@ REG ds_reg[] = { { BRDATA (FIFO, ds_fifo, 8, 16, DS_FIFO_SIZE) }, { ORDATA (SR1, ds_sr1, 16) }, { ORDATA (VCTR, ds_vctr, 16) }, - { ORDATA (UNIT, ds_u, 4) }, { ORDATA (FMASK, ds_fmask, 8) }, { ORDATA (CYL, ds_cyl, 16) }, { ORDATA (HS, ds_hs, 16) }, @@ -440,9 +490,9 @@ REG ds_reg[] = { { DRDATA (CTIME, ds_ctime, 24), PV_LEFT + REG_NZ }, { DRDATA (DTIME, ds_dtime, 24), PV_LEFT + REG_NZ }, { DRDATA (STIME, ds_stime, 24), PV_LEFT + REG_NZ }, - { DRDATA (TTIME, ds_rtime, 24), PV_LEFT + REG_NZ }, + { DRDATA (RTIME, ds_rtime, 24), PV_LEFT + REG_NZ }, { DRDATA (TIMEOUT, ds_tmo, 31), PV_LEFT + REG_NZ }, - { URDATA (UCYL, ds_unit[0].CYL, 10, 8, 0, + { URDATA (UCYL, ds_unit[0].CYL, 10, 10, 0, DS_NUMDR + 1, PV_LEFT | REG_HRO) }, { URDATA (UFNC, ds_unit[0].FNC, 8, 8, 0, DS_NUMDR + 1, REG_HRO) }, @@ -493,15 +543,14 @@ DEVICE ds_dev = { DS_NUMDR + 2, 8, 27, 1, 8, 16, NULL, NULL, &ds_reset, &ds_boot, &ds_attach, &ds_detach, - &ds_dib, DEV_DISABLE | DEV_DIS }; + &ds_dib, DEV_DISABLE }; /* IO instructions */ int32 dsio (int32 inst, int32 IR, int32 dat) { -int32 dev; +uint32 dev = IR & I_DEVMASK; -dev = IR & I_DEVMASK; /* get device no */ switch (inst) { /* case on opcode */ case ioFLG: /* flag clear/set */ if ((IR & I_HC) == 0) { setFLG (dev); } /* STF */ @@ -516,7 +565,8 @@ case ioOTX: /* output */ if (ds_cmdf) { /* expecting command? */ ds_cmd = dat; /* save command */ ds_cmdf = 0; - ds_cmdp = 1; } /* command present */ + ds_cmdp = 1; /* command present */ + } else ds_fifo_write (dat); /* put in fifo */ break; case ioMIX: /* merge */ @@ -530,9 +580,11 @@ case ioCTL: /* control clear/set */ clrCTL (dev); /* clear control */ ds_cmdf = 1; /* expecting command */ ds_cmdp = 0; /* none pending */ - ds_fifo_reset (); } /* clear fifo */ + ds_fifo_reset (); /* clear fifo */ + } else { /* STC */ - setCTL (dev); } /* set ctl */ + setCTL (dev); /* set ctl */ + } break; case ioEDT: /* end of transfer */ ds_eod = 1; /* flag end transfer */ @@ -546,7 +598,7 @@ return dat; /* Run the controller polling loop, based on ds_state: - IDLE commands and ATTN interrupts + IDLE commands and ATN interrupts WAIT commands only BUSY nothing */ @@ -556,7 +608,7 @@ void ds_poll (void) int32 dev = ds_dib.devno; if ((ds_state != DS_BUSY) && ds_cmdp) ds_docmd (ds_cmd);/* cmd pending? */ -if ((ds_state == DS_IDLE) && CTL (dev)) ds_doatn (); /* idle? chk atn */ +if ((ds_state == DS_IDLE) && CTL (dev)) ds_doatn (); /* idle? check ATN */ return; } @@ -571,29 +623,31 @@ return; void ds_docmd (uint32 cmd) { -uint32 op, f, dtyp; +uint32 op, f, dtyp, unum; op = DSC_GETOP (cmd); /* operation */ f = ds_opflags[op]; /* flags */ -if (op == DSC_COLD) ds_u = 0; /* boot force unit 0 */ -else ds_u = DSC_GETUNIT (cmd); /* get unit */ -if ((f & CMF_UIDLE) && (ds_u < DS_NUMDR) && /* idle required */ - sim_is_active (&ds_unit[ds_u])) { /* but unit busy? */ +if (op == DSC_COLD) unum = 0; /* boot force unit 0 */ +else unum = DSC_GETUNIT (cmd); /* get unit */ +if ((f & CMF_UIDLE) && (unum < DS_NUMDR) && /* idle required */ + sim_is_active (&ds_unit[unum])) { /* but unit busy? */ ds_state = DS_WAIT; /* wait */ - return; } + return; + } ds_cmdp = 0; /* flush command */ ds_state = DS_BUSY; /* ctrl is busy */ if (f & CMF_CLRS) ds_sr1 = 0; /* clear status */ if (f & CMF_CLREC) ds_eoc = 0; /* clear end cyl */ if (f & CMF_UNDF) { /* illegal op? */ - ds_sched_ctrl_op (DSC_BADF, 0, CLR_BUSY); /* sched, not busy */ - return; } + ds_sched_ctrl_op (DSC_BADF, 0, CLR_BUSY); /* sched, clr busy */ + return; + } switch (op) { /* Drive commands */ case DSC_COLD: /* cold load read */ - ds_fmask = DSC_SPAR; /* sparing enabled */ + ds_fmask = DSC_SPEN; /* sparing enabled */ ds_cyl = 0; /* cylinder 0 */ ds_hs = (DSC_GETCHD (ds_cmd) << DSHS_V_HD) | /* reformat hd/sec */ (DSC_GETCSC (ds_cmd) << DSHS_V_SC); @@ -607,13 +661,19 @@ case DSC_VFY: /* verify */ case DSC_WRITE: /* write */ case DSC_WFULL: /* write full */ case DSC_INIT: /* init */ - ds_sr1 = ds_u; /* init status */ - if (ds_u >= DS_NUMDR) { /* invalid unit? */ - ds_sched_ctrl_op (DSC_BADU, ds_u, CLR_BUSY);/* sched, not busy */ - return; } - ds_unit[ds_u].FNC = op; /* save op */ - ds_unit[ds_u].STA &= ~DS2_ATN; /* clear ATTN */ - sim_activate (&ds_unit[ds_u], ds_ctime); /* schedule unit */ + ds_sr1 = unum; /* init status */ + if (unum >= DS_NUMDR) { /* invalid unit? */ + ds_sched_ctrl_op (DSC_BADU, unum, CLR_BUSY);/* sched, not busy */ + return; + } + if (op == DSC_INIT) ds_sr1 |= /* init? */ + ((cmd & DSC_SPAR)? DS1_SPAR: 0) | /* copy SPD to stat1 */ + ((cmd & DSC_PROT)? DS1_PROT: 0) | + ((cmd & DSC_DFCT)? DS1_DFCT: 0); + ds_unit[unum].FNC = op; /* save op */ + ds_unit[unum].STA &= ~DS2_ATN; /* clear ATN */ + sim_cancel (&ds_unit[unum]); /* cancel current */ + sim_activate (&ds_unit[unum], ds_ctime); /* schedule unit */ ds_busy = 1; /* set visible busy */ break; @@ -621,12 +681,15 @@ case DSC_INIT: /* init */ case DSC_RSTA: /* read status */ dsxb[1] = ds_sr1; /* return SR1 */ - if (ds_u >= DS_NUMDR) dsxb[0] = DS2_ERR|DS2_NR|ds_u; /* SR2 */ - else dsxb[0] = ds_updds2 (&ds_unit[ds_u], DS2_FS); + if (unum < DS_NUMDR) { /* and SR2 */ + dsxb[0] = ds_updds2 (&ds_unit[unum]); + ds_unit[unum].STA &= ~DS2_FS; /* clear 1st */ + } + else dsxb[0] = DS2_ERR|DS2_NR; ds_sched_ctrl_op (DSC_RSTA, 2, SET_BUSY); /* sched 2 wds, busy */ break; case DSC_RSA: /* read sector address */ - dtyp = GET_DTYPE (ds_unit[ds_u].flags); /* get unit type */ + dtyp = GET_DTYPE (ds_unit[unum].flags); /* get unit type */ dsxb[0] = GET_CURSEC (ds_dtime * DS_NUMWD, dtyp); /* rot position */ ds_sched_ctrl_op (DSC_RSTA, 1, SET_BUSY); /* sched 1 wd, busy */ break; @@ -653,7 +716,8 @@ case DSC_WTIO: /* write TIO */ case DSC_END: /* end */ ds_set_idle (); /* idle ctrl */ - break; } + break; + } return; } @@ -669,9 +733,11 @@ for (i = 0; i < DS_NUMDR; i++) { /* intr disabled? */ if (ds_unit[ds_lastatn].STA & DS2_ATN) { /* ATN set? */ ds_unit[ds_lastatn].STA &= ~DS2_ATN; /* clear ATN */ setFLG (dev); /* request interrupt */ - ds_sr1 = DS1_ATTN | ds_lastatn; /* set up status 1 */ - ds_state = DS_WAIT; /* block attn intrs */ - return; } } + ds_sr1 = DS1_ATN | ds_lastatn; /* set up status 1 */ + ds_state = DS_WAIT; /* block atn intrs */ + return; + } + } return; } @@ -691,28 +757,31 @@ case DSC_AREC: /* address record */ ds_wait_for_cpu (uptr, DSC_AREC|DSC_2ND); /* set flag, new state */ break; case DSC_AREC | DSC_2ND: /* poll done */ - if (!FLG (dev)) { /* OTA x,C? */ + if (!DS_FIFO_EMPTY) { /* OTA ds? */ ds_cyl = ds_fifo_read (); /* save cylinder */ - ds_wait_for_cpu (uptr, DSC_AREC|DSC_3RD); }/* set flag, new state */ + ds_wait_for_cpu (uptr, DSC_AREC|DSC_3RD); /* set flag, new state */ + } else sim_activate (uptr, ds_ctime); /* no, continue poll */ break; case DSC_AREC | DSC_3RD: /* poll done */ - if (!FLG (dev)) { /* OTA x,C? */ + if (!DS_FIFO_EMPTY) { /* OTA ds? */ ds_hs = ds_fifo_read (); /* save head/sector */ - ds_cmd_done (0, DS1_OK); } /* op done, no flag */ + ds_cmd_done (0, DS1_OK); /* op done, no flag */ + } else sim_activate (uptr, ds_ctime); /* no, continue poll */ break; case DSC_RSTA: /* rd stat (all forms) */ - if (!FLG (dev)) { /* buffer clear? */ + if (DS_FIFO_EMPTY) { /* fifo empty? */ uptr->CYL--; ds_fifo_write (dsxb[uptr->CYL]); /* store next status */ ds_wait_for_cpu (uptr, DSC_RSTA | - (uptr->CYL? 0: DSC_2ND)); } /* set flag, new state */ + (uptr->CYL? 0: DSC_2ND)); /* set flag, new state */ + } else sim_activate (uptr, ds_ctime); /* no, continue poll */ break; case DSC_RSTA | DSC_2ND: /* poll done */ - if (!FLG (dev)) ds_cmd_done (0, DS1_OK); /* op done? no flag */ + if (DS_FIFO_EMPTY) ds_cmd_done (0, DS1_OK); /* op done? no flag */ else sim_activate (uptr, ds_ctime); /* no, continue poll */ break; @@ -758,7 +827,7 @@ t_stat ds_svc_t (UNIT *uptr) { int32 i; -for (i = 0; i < DS_NUMDR; i++) /* cancel all ops */ +for (i = 0; i < (DS_NUMDR + 1); i++) /* cancel all ops */ sim_cancel (&ds_unit[i]); ds_set_idle (); /* idle the controller */ ds_fmask = 0; /* clear file mask */ @@ -783,7 +852,8 @@ switch (op) { /* case on function */ case DSC_RECAL: /* recalibrate */ if (uptr->flags & UNIT_ATT) { /* attached? */ ds_start_seek (uptr, 0, DSC_RECAL|DSC_2ND); /* set up seek */ - ds_set_idle (); } /* ctrl is idle */ + ds_set_idle (); /* ctrl is idle */ + } else ds_cmd_done (1, DS1_S2ERR); /* not ready error */ break; case DSC_RECAL | DSC_2ND: /* recal complete */ @@ -794,18 +864,21 @@ case DSC_SEEK: /* seek */ ds_wait_for_cpu (uptr, DSC_SEEK|DSC_2ND); /* set flag, new state */ break; case DSC_SEEK | DSC_2ND: /* waiting for word 1 */ - if (!FLG (dev)) { /* OTA x,C? */ + if (!DS_FIFO_EMPTY) { /* OTA ds? */ ds_cyl = ds_fifo_read (); /* save cylinder */ - ds_wait_for_cpu (uptr, DSC_SEEK|DSC_3RD); }/* set flag, new state */ + ds_wait_for_cpu (uptr, DSC_SEEK|DSC_3RD); /* set flag, new state */ + } else sim_activate (uptr, ds_ctime); /* no, continue poll */ break; case DSC_SEEK | DSC_3RD: /* waiting for word 2 */ - if (!FLG (dev)) { /* OTA x,C? */ + if (!DS_FIFO_EMPTY) { /* OTA ds? */ ds_hs = ds_fifo_read (); /* save head/sector */ if (uptr->flags & UNIT_ATT) { /* attached? */ ds_start_seek (uptr, ds_cyl, DSC_SEEK|DSC_4TH); /* set up seek */ - ds_set_idle (); } /* ctrl is idle */ - else ds_cmd_done (1, DS1_S2ERR); } /* else not ready error */ + ds_set_idle (); /* ctrl is idle */ + } + else ds_cmd_done (1, DS1_S2ERR); /* else not ready error */ + } else sim_activate (uptr, ds_ctime); /* continue poll */ break; case DSC_SEEK | DSC_4TH: /* seek complete */ @@ -818,7 +891,11 @@ case DSC_ROFF: /* read with offset */ ds_wait_for_cpu (uptr, DSC_ROFF|DSC_2ND); /* set flag, new state */ break; case DSC_ROFF | DSC_2ND: /* poll done */ - if (!FLG (dev)) uptr->FNC = DSC_READ; /* OTA x,C? new state */ + if (!DS_FIFO_EMPTY) { /* OTA ds? new state */ + ds_fifo_read (); /* drain fifo */ + uptr->FNC = DSC_READ; + setFLG (dev); /* handshake */ + } sim_activate (uptr, ds_ctime); /* schedule unit */ break; @@ -829,8 +906,7 @@ case DSC_COLD: /* cold load read */ break; case DSC_READ: /* read */ - if (r = ds_start_rd (uptr, 0, 1)) /* new sector; error? */ - return r; + if (r = ds_start_rd (uptr, 0, 1)) return r; /* new sector; error? */ break; case DSC_READ | DSC_2ND: /* word transfer */ ds_cont_rd (uptr, DS_NUMWD); /* xfr wd, check end */ @@ -840,8 +916,7 @@ case DSC_READ | DSC_3RD: /* end of sector */ break; case DSC_RNOVFY: /* read, no verify */ - if (r = ds_start_rd (uptr, 0, 0)) /* new sector; error? */ - return r; + if (r = ds_start_rd (uptr, 0, 0)) return r; /* new sector; error? */ break; case DSC_RNOVFY | DSC_2ND: /* word transfer */ ds_cont_rd (uptr, DS_NUMWD); /* xfr wd, check end */ @@ -868,10 +943,11 @@ case DSC_VFY: /* verify */ ds_wait_for_cpu (uptr, DSC_VFY|DSC_2ND); /* set flag, new state */ break; case DSC_VFY | DSC_2ND: /* poll done */ - if (!FLG (dev)) { /* OTA x,C? */ + if (!DS_FIFO_EMPTY) { /* OTA ds? */ ds_vctr = ds_fifo_read (); /* save count */ uptr->FNC = DSC_VFY | DSC_3RD; /* next state */ - sim_activate (uptr, ds_rtime); } /* delay for transfer */ + sim_activate (uptr, ds_rtime); /* delay for transfer */ + } else sim_activate (uptr, ds_ctime); /* no, continue poll */ break; case DSC_VFY | DSC_3RD: /* start sector */ @@ -978,9 +1054,9 @@ sim_activate (&ds_timer, ds_tmo); return; } -/* Return drive status (status word 2), clear specified flags */ +/* Return drive status (status word 2) */ -uint32 ds_updds2 (UNIT *uptr, uint32 clear) +uint32 ds_updds2 (UNIT *uptr) { uint32 sta; uint32 dtyp = GET_DTYPE (uptr->flags); @@ -988,10 +1064,10 @@ uint32 dtyp = GET_DTYPE (uptr->flags); sta = drv_tab[dtyp].id | /* form status */ uptr->STA | /* static bits */ ((uptr->flags & UNIT_WPR)? DS2_RO: 0) | /* dynamic bits */ - ((uptr->flags & UNIT_ATT)? 0: DS2_NR) | + ((uptr->flags & UNIT_FMT)? DS2_FRM: 0) | + ((uptr->flags & UNIT_ATT)? 0: DS2_NR | DS2_BS) | (sim_is_active (uptr)? DS2_BS: 0); if (sta & DS2_ALLERR) sta = sta | DS2_ERR; /* set error */ -uptr->STA = uptr->STA & ~clear; /* clear static */ return sta; } @@ -1022,16 +1098,23 @@ return; void ds_start_seek (UNIT *uptr, uint32 cyl, uint32 newst) { int32 t; +uint32 hd, sc; uint32 dtyp = GET_DTYPE (uptr->flags); uptr->FNC = newst; /* set new state */ if (cyl >= drv_tab[dtyp].cyl) { /* out of bounds? */ - uptr->CYL = t = drv_tab[dtyp].cyl; /* put off edge */ - uptr->STA = uptr->STA | DS2_SC; } /* set seek check */ -else { /* seek in range */ - t = abs (uptr->CYL - cyl); /* delta cylinders */ + t = 0; /* don't change cyl */ + uptr->STA = uptr->STA | DS2_SC; /* set seek check */ + } +else { t = abs (uptr->CYL - cyl); /* delta cylinders */ uptr->CYL = cyl; /* put on cylinder */ - uptr->STA = uptr->STA & ~DS2_SC; } /* clear seek check */ + hd = DSHS_GETHD (ds_hs); /* invalid head or sec? */ + sc = DSHS_GETSC (ds_hs); + if ((hd >= drv_tab[dtyp].hd) || + (sc >= drv_tab[dtyp].sc)) + uptr->STA = uptr->STA | DS2_SC; /* set seek check */ + else uptr->STA = uptr->STA & ~DS2_SC; /* clear seek check */ + } sim_activate (uptr, ds_stime * (t + 1)); /* schedule */ return; } @@ -1048,29 +1131,36 @@ t_bool ds_start_rw (UNIT *uptr, int32 tm, t_bool vfy) uint32 da, hd, sc; uint32 dtyp = GET_DTYPE (uptr->flags); -ds_eod = 0; /* clear eod */ +ds_eod = 0; /* init eod */ +ds_ptr = 0; /* init buffer ptr */ if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */ ds_cmd_done (1, DS1_S2ERR); - return TRUE; } + return TRUE; + } if (ds_eoc) { /* at end of cylinder? */ ds_next_cyl (uptr); /* auto seek to next */ - return TRUE; } /* or error */ -if (vfy && ((uint32) uptr->CYL != ds_cyl)) { /* on proper cylinder? */ - ds_cmd_done (1, DS1_CYLCE); /* no, error */ - return TRUE; } + return TRUE; /* or error */ + } +if (vfy && ((uint32) uptr->CYL != ds_cyl)) { /* on wrong cylinder? */ + if (ds_cyl >= drv_tab[dtyp].cyl) /* seeking to bad? */ + ds_cmd_done (1, DS1_CYLCE); /* lose */ + else ds_start_seek (uptr, ds_cyl, uptr->FNC); /* seek right cyl */ + return TRUE; + } hd = DSHS_GETHD (ds_hs); sc = DSHS_GETSC (ds_hs); if ((uint32) uptr->CYL >= drv_tab[dtyp].cyl) { /* valid cylinder? */ uptr->STA = uptr->STA | DS2_SC; /* set seek check */ ds_cmd_done (1, DS1_S2ERR); /* error */ - return TRUE; } + return TRUE; + } if ((hd >= drv_tab[dtyp].hd) || /* valid head, sector? */ (sc >= drv_tab[dtyp].sc)) { ds_cmd_done (1, DS1_HSCE); /* no, error */ - return TRUE; } + return TRUE; + } da = GET_DA (uptr->CYL, hd, sc, dtyp); /* position in file */ sim_fseek (uptr->fileref, da * sizeof (uint16), SEEK_SET); /* set file pos */ -ds_ptr = 0; /* init buffer ptr */ uptr->FNC += DSC_NEXT; /* next state */ sim_activate (uptr, tm); /* activate unit */ return FALSE; @@ -1080,7 +1170,8 @@ return FALSE; - Do common start for read and write - If error, return, command has been terminated, nothing scheduled - - If no error, state has been advanced and unit scheduled + - If implicit seek, return, seek scheduled + - If no error or seek, state has been advanced and unit scheduled - Read sector - If read error, terminate command and return, nothing scheduled - If no error, advance head/sector, next state scheduled */ @@ -1089,8 +1180,7 @@ t_stat ds_start_rd (UNIT *uptr, uint32 off, t_bool vfy) { uint32 t; -if (ds_start_rw (uptr, ds_rtime, vfy)) /* new sector; error? */ - return SCPE_OK; /* nothing scheduled */ +if (ds_start_rw (uptr, ds_rtime, vfy)) return SCPE_OK; /* new sec; err or seek? */ t = sim_fread (dsxb + off, sizeof (uint16), DS_NUMWD, uptr->fileref); for (t = t + off ; t < DS_NUMWDF; t++) dsxb[t] = 0; /* fill sector */ if (ferror (uptr->fileref)) /* error? */ @@ -1103,20 +1193,22 @@ return SCPE_OK; - Do common start for read and write - If error, return, command has been terminated, nothing scheduled - - If no error, state has been advanced and unit scheduled + - If implicit seek, return, seek scheduled + - If no error or seek, state has been advanced and unit scheduled - Clear buffer - Set service request */ void ds_start_wr (UNIT *uptr, t_bool vfy) { -uint32 i, dev; +uint32 i; +uint32 dev = ds_dib.devno; -dev = ds_dib.devno; if ((uptr->flags & UNIT_WPR) || /* write protected? */ (!vfy && ((uptr->flags & UNIT_FMT) == 0))) { /* format, not enbl? */ ds_cmd_done (1, DS1_S2ERR); /* error */ - return; } -if (ds_start_rw (uptr, ds_rtime, vfy)) return; /* new sector; error? */ + return; + } +if (ds_start_rw (uptr, ds_rtime, vfy)) return; /* new sec; err or seek? */ for (i = 0; i < DS_NUMWDF; i++) dsxb[i] = 0; /* clear buffer */ setSRQ (dev); /* request word */ return; @@ -1134,7 +1226,8 @@ ds_hs = ds_hs & ~DSHS_SC; /* yes, wrap sector */ if (ds_fmask & DSC_CYLM) { /* cylinder mode? */ ds_hs = ds_hs + (1 << DSHS_V_HD); /* increment head */ if (DSHS_GETHD (ds_hs) < drv_tab[dtyp].hd) return; /* end of cyl? */ - ds_hs = ds_hs & ~DSHS_HD; } /* 0 head */ + ds_hs = ds_hs & ~DSHS_HD; /* 0 head */ + } ds_eoc = 1; /* flag end cylinder */ return; } @@ -1146,13 +1239,12 @@ return; void ds_next_cyl (UNIT *uptr) { -uint32 dtyp = GET_DTYPE (uptr->flags); - if (ds_fmask & DSC_AUTO) { /* auto seek allowed? */ if (ds_fmask & DSC_DECR) ds_cyl = (ds_cyl - 1) & DMASK; else ds_cyl = (ds_cyl + 1) & DMASK; ds_eoc = 0; /* clear end cylinder */ - ds_start_seek (uptr, ds_cyl, uptr->FNC); } /* seek, same state */ + ds_start_seek (uptr, ds_cyl, uptr->FNC); /* seek, same state */ + } else ds_cmd_done (1, DS1_EOCYL); /* no, end of cyl err */ return; } @@ -1167,10 +1259,15 @@ void ds_cont_rd (UNIT *uptr, uint32 bsize) uint32 dev = ds_dib.devno; if (ds_eod) ds_cmd_done (1, DS1_OK); /* DMA end? done */ +else if (SRQ (dev)) { /* overrun? */ + ds_cmd_done (1, DS1_OVRUN); /* set done */ + return; + } else { ds_fifo_write (dsxb[ds_ptr++]); /* next word */ setSRQ (dev); /* request service */ if (ds_ptr >= bsize) uptr->FNC += DSC_NEXT; /* sec done? next state */ - sim_activate (uptr, ds_dtime); } /* schedule */ + sim_activate (uptr, ds_dtime); /* schedule */ + } return; } @@ -1183,18 +1280,26 @@ return; t_stat ds_cont_wr (UNIT *uptr, uint32 off, uint32 bsize) { +uint32 i, dat; uint32 dev = ds_dib.devno; -dsxb[ds_ptr++] = ds_fifo_read (); /* next word */ +if (SRQ (dev)) { /* overrun? */ + ds_cmd_done (1, DS1_OVRUN); /* set done */ + return SCPE_OK; + } +dsxb[ds_ptr++] = dat = ds_fifo_read (); /* next word */ if (ds_eod || (ds_ptr >= bsize)) { /* xfr or sector done? */ + for (i = ds_ptr; i < bsize; i++) dsxb[i] = dat; /* fill sector */ sim_fwrite (dsxb + off, sizeof (uint16), DS_NUMWD, uptr->fileref); if (ferror (uptr->fileref)) /* error on write? */ return ds_set_uncorr (uptr); /* uncorrectable */ ds_next_sec (uptr); /* increment hd, sc */ if (ds_eod) { /* end data? */ ds_cmd_done (1, DS1_OK); /* set done */ - return SCPE_OK; } - else uptr->FNC += DSC_NEXT; } /* no, next state */ + return SCPE_OK; + } + else uptr->FNC += DSC_NEXT; /* no, next state */ + } else { setSRQ (dev); } /* request next word */ sim_activate (uptr, ds_dtime); /* schedule */ return SCPE_OK; @@ -1278,7 +1383,8 @@ for (i = 0; i < DS_NUMDR; i++) { /* loop thru drives */ sim_cancel (&ds_unit[i]); /* cancel activity */ ds_unit[i].FNC = 0; /* clear function */ ds_unit[i].CYL = 0; - ds_unit[i].STA = 0; } + ds_unit[i].STA = 0; + } sim_cancel (&ds_ctrl); sim_cancel (&ds_timer); return SCPE_OK; @@ -1305,14 +1411,16 @@ uptr->capac = drv_tab[GET_DTYPE (uptr->flags)].size; r = attach_unit (uptr, cptr); /* attach unit */ if (r != SCPE_OK) return r; /* error? */ uptr->STA = DS2_ATN | DS2_FS; /* update drive status */ -ds_sched_attn (uptr); /* schedule attention */ +ds_sched_atn (uptr); /* schedule attention */ if (((uptr->flags & UNIT_AUTO) == 0) || /* static size? */ ((p = sim_fsize (uptr->fileref)) == 0)) return SCPE_OK; /* new file? */ for (i = 0; drv_tab[i].sc != 0; i++) { /* find best fit */ - if (p <= (drv_tab[i].size * sizeof (uint16))) { - uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE); - uptr->capac = drv_tab[i].size; - return SCPE_OK; } } + if (p <= (drv_tab[i].size * sizeof (uint16))) { + uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE); + uptr->capac = drv_tab[i].size; + return SCPE_OK; + } + } return SCPE_OK; } @@ -1321,20 +1429,21 @@ return SCPE_OK; t_stat ds_detach (UNIT *uptr) { uptr->STA = DS2_ATN; /* update drive status */ -ds_sched_attn (uptr); /* schedule attention */ +ds_sched_atn (uptr); /* schedule attention */ return detach_unit (uptr); } /* Schedule attention interrupt if CTL set, not restore, and controller idle */ -void ds_sched_attn (UNIT *uptr) +void ds_sched_atn (UNIT *uptr) { int32 i; if (!ds_dib.ctl || (sim_switches & SIM_SW_REST)) return; for (i = 0; i < (DS_NUMDR + 1); i++) { /* check units, ctrl */ - if (sim_is_active (ds_dev.units + i)) return; } -uptr->FNC = DSC_ATTN; /* pseudo operation */ + if (sim_is_active (ds_dev.units + i)) return; + } +uptr->FNC = DSC_ATN; /* pseudo operation */ sim_activate (uptr, 1); /* do immediately */ return; } @@ -1424,6 +1533,6 @@ int32 dev; if (unitno != 0) return SCPE_NOFNC; /* only unit 0 */ dev = ds_dib.devno; /* get data chan dev */ if (ibl_copy (ds_rom, dev)) return SCPE_IERR; /* copy boot to memory */ -SR = (SR & IBL_OPT) | IBL_DS | IBL_MAN | (dev << IBL_V_DEV); /* set SR */ +SR = (SR & (IBL_OPT | IBL_DS_HEAD)) | IBL_DS | IBL_MAN | (dev << IBL_V_DEV); return SCPE_OK; } diff --git a/HP2100/hp2100_fp.c b/HP2100/hp2100_fp.c index 70a8027b..3ab11978 100644 --- a/HP2100/hp2100_fp.c +++ b/HP2100/hp2100_fp.c @@ -23,6 +23,7 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 26-Dec-04 RMS Separated A/B from M[0/1] for DMA IO (from Dave Bryan) 15-Jul-03 RMS Fixed signed/unsigned warning 21-Oct-02 RMS Recoded for compatibility with 21MX microcode algorithms @@ -102,7 +103,7 @@ struct ufp { /* unpacked fp */ #define FR_NEG(v) ((~(v) + 1) & DMASK32) -extern uint16 *M; +extern uint16 ABREG[2]; uint32 UnpackFP (struct ufp *fop, uint32 opnd); void NegFP (struct ufp *fop); void NormFP (struct ufp *fop); diff --git a/HP2100/hp2100_lps.c b/HP2100/hp2100_lps.c index ae4ec4d4..573eeb17 100644 --- a/HP2100/hp2100_lps.c +++ b/HP2100/hp2100_lps.c @@ -26,6 +26,8 @@ lps 12653A 2767 line printer (based on 12566B microcircuit interface) + 19-Nov-04 JDB Added restart when set online, etc. + Fixed col count for non-printing chars 01-Oct-04 JDB Added SET OFFLINE/ONLINE, POWEROFF/POWERON Fixed status returns for error conditions Fixed handling of non-printing characters @@ -164,6 +166,9 @@ DEVICE lps_dev; int32 lpsio (int32 inst, int32 IR, int32 dat); t_stat lps_svc (UNIT *uptr); t_stat lps_reset (DEVICE *dptr); +t_stat lps_restart (UNIT *uptr, int32 value, char *cptr, void *desc); +t_stat lps_poweroff (UNIT *uptr, int32 value, char *cptr, void *desc); +t_stat lps_poweron (UNIT *uptr, int32 value, char *cptr, void *desc); t_stat lps_attach (UNIT *uptr, char *cptr); t_stat lps_set_timing (UNIT *uptr, int32 val, char *cptr, void *desc); t_stat lps_show_timing (FILE *st, UNIT *uptr, int32 val, void *desc); @@ -204,10 +209,10 @@ REG lps_reg[] = { MTAB lps_mod[] = { { UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", NULL }, { UNIT_DIAG, 0, "printer mode", "PRINTER", NULL }, - { UNIT_POWEROFF, UNIT_POWEROFF, "power off", "POWEROFF", NULL }, - { UNIT_POWEROFF, 0, "power on", "POWERON", NULL }, + { UNIT_POWEROFF, UNIT_POWEROFF, "power off", "POWEROFF", lps_poweroff }, + { UNIT_POWEROFF, 0, "power on", "POWERON", lps_poweron }, { UNIT_OFFLINE, UNIT_OFFLINE, "offline", "OFFLINE", NULL }, - { UNIT_OFFLINE, 0, "online", "ONLINE", NULL }, + { UNIT_OFFLINE, 0, "online", "ONLINE", lps_restart }, { MTAB_XTD | MTAB_VDV, 0, NULL, "REALTIME", &lps_set_timing, NULL, NULL }, { MTAB_XTD | MTAB_VDV, 1, NULL, "FASTTIME", @@ -250,27 +255,13 @@ case ioOTX: /* output */ case ioLIX: /* load */ dat = 0; /* default sta = 0 */ case ioMIX: /* merge */ - if ((lps_unit.flags & UNIT_DIAG) == 0) { /* real lpt? */ - if (lps_power == LPS_ON) { /* power on? */ - if (lps_unit.flags & UNIT_POWEROFF) { /* power just turned off? */ - lps_power = LPS_OFF; /* change state */ - lps_sta = LPS_PWROFF; - if (DEBUG_PRS (lps_dev)) - fputs (">>LPS LIx: Power state is OFF\n", sim_deb); } - else if (((lps_unit.flags & UNIT_ATT) == 0) || - (lps_unit.flags & UNIT_OFFLINE) || - sim_is_active (&lps_unit)) lps_sta = LPS_BUSY; - else lps_sta = 0; } - else if (lps_power == LPS_TURNING_ON) /* printer warming up? */ - lps_sta = LPS_PWROFF; - else if (!(lps_unit.flags & UNIT_POWEROFF)) { /* power just turned on? */ - lps_power = LPS_TURNING_ON; /* change state */ - lps_unit.flags |= UNIT_OFFLINE; /* set offline */ - sim_activate (&lps_unit, lps_rtime); /* schedule printer ready */ - lps_sta = LPS_PWROFF; - if (DEBUG_PRS (lps_dev)) fprintf (sim_deb, - ">>LPS LIx: Power state is TURNING ON, scheduled time = %d\n", - lps_rtime ); } } + if ((lps_unit.flags & UNIT_DIAG) == 0) /* real lpt? */ + if (lps_power == LPS_ON) /* power on? */ + if (((lps_unit.flags & UNIT_ATT) == 0) || /* paper out? */ + (lps_unit.flags & UNIT_OFFLINE) || /* offline? */ + sim_is_active (&lps_unit)) lps_sta = LPS_BUSY; + else lps_sta = 0; + else lps_sta = LPS_PWROFF; dat = dat | lps_sta; /* diag, rtn status */ if (DEBUG_PRS (lps_dev)) fprintf (sim_deb, ">>LPS LIx: Status %06o returned\n", dat); @@ -291,13 +282,10 @@ case ioCTL: /* control clear/set */ if ((lps_unit.buf != '\f') && (lps_unit.buf != '\n') && (lps_unit.buf != '\r')) { /* normal char */ - if ((lps_unit.buf < ' ') || (lps_unit.buf > '_')) - sched = lps_ctime; /* non-printing char */ - else { /* printing char */ - lps_ccnt = lps_ccnt + 1; /* incr char counter */ - if (lps_ccnt % LPS_ZONECNT == 0)/* end of zone? */ - sched = lps_ptime; /* print zone */ - else sched = lps_ctime; } } /* xfer char */ + lps_ccnt = lps_ccnt + 1; /* incr char counter */ + if (lps_ccnt % LPS_ZONECNT == 0) /* end of zone? */ + sched = lps_ptime; /* print zone */ + else sched = lps_ctime; } /* xfer char */ else { /* print cmd */ if (lps_ccnt % LPS_ZONECNT == 0) /* last zone printed? */ sched = lps_ctime; /* yes, so just char time */ @@ -328,22 +316,29 @@ int32 c = uptr->buf & 0177; if (lps_power == LPS_TURNING_ON) { /* printer warmed up? */ lps_power = LPS_ON; /* change state */ + lps_restart (uptr, 0, NULL, NULL); /* restart I/O if hung */ if (DEBUG_PRS (lps_dev)) fputs (">>LPS svc: Power state is ON\n", sim_deb); return SCPE_OK; } /* done */ dev = lps_dib.devno; /* get dev no */ -clrCMD (dev); /* clear cmd */ -setFSR (dev); /* set flag, fbf */ if (uptr->flags & UNIT_DIAG) { /* diagnostic? */ lps_sta = uptr->buf; /* loop back */ + clrCMD (dev); /* clear cmd */ + setFSR (dev); /* set flag, fbf */ return SCPE_OK; } /* done */ -if ((uptr->flags & UNIT_ATT) == 0) /* real lpt, att? */ +if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ return IORETURN (lps_stopioe, SCPE_UNATT); +else if (uptr->flags & UNIT_OFFLINE) /* offline? */ + return IORETURN (lps_stopioe, STOP_OFFLINE); +else if (uptr->flags & UNIT_POWEROFF) /* powered off? */ + return IORETURN (lps_stopioe, STOP_PWROFF); +clrCMD (dev); /* clear cmd */ +setFSR (dev); /* set flag, fbf */ if (((c < ' ') || (c > '_')) && /* non-printing char? */ (c != '\f') && (c != '\n') && (c != '\r')) { - c = ' '; /* replace with blank */ if (DEBUG_PRS (lps_dev)) - fprintf (sim_deb, ">>LPS svc: Character %06o erased\n", c); } + fprintf (sim_deb, ">>LPS svc: Character %06o erased\n", c); + c = ' '; } /* replace with blank */ if (lps_ccnt > LPS_PAGECNT) { /* 81st character? */ fputc ('\r', uptr->fileref); /* return to line start */ uptr->pos = uptr->pos + 1; /* update pos */ @@ -379,11 +374,60 @@ lps_set_timing (NULL, lps_timing, NULL, NULL); /* init timing set */ return SCPE_OK; } +/* Restart I/O routine + + If I/O is started via STC, and the printer is powered off, offline, + or out of paper, the CTL and CMD flip-flops will set, a service event + will be scheduled, and the service routine will be entered. If + STOP_IOE is not set, the I/O operation will "hang" at that point + until the printer is powered on, set online, or paper is supplied + (attached). + + If a pending operation is "hung" when this routine is called, it is + restarted, which clears CTL and sets FBF and FLG, completing the + original I/O request. + */ + +t_stat lps_restart (UNIT *uptr, int32 value, char *cptr, void *desc) +{ +if (lps_dib.cmd && lps_dib.ctl && !sim_is_active (uptr)) + sim_activate (uptr, 0); /* reschedule I/O */ +return SCPE_OK; +} + +/* Printer power off */ + +t_stat lps_poweroff (UNIT *uptr, int32 value, char *cptr, void *desc) +{ +lps_power = LPS_OFF; /* change state */ +if (DEBUG_PRS (lps_dev)) fputs (">>LPS set: Power state is OFF\n", sim_deb); +return SCPE_OK; +} + +/* Printer power on */ + +t_stat lps_poweron (UNIT *uptr, int32 value, char *cptr, void *desc) +{ +if (lps_unit.flags & UNIT_DIAG) { /* diag mode? */ + lps_power = LPS_ON; /* no delay */ + if (DEBUG_PRS (lps_dev)) + fputs (">>LPS set: Power state is ON\n", sim_deb); } +else { + lps_power = LPS_TURNING_ON; /* change state */ + lps_unit.flags |= UNIT_OFFLINE; /* set offline */ + sim_activate (&lps_unit, lps_rtime); /* schedule ready */ + if (DEBUG_PRS (lps_dev)) fprintf (sim_deb, + ">>LPS set: Power state is TURNING ON, scheduled time = %d\n", + lps_rtime ); } +return SCPE_OK; +} + /* Attach routine */ t_stat lps_attach (UNIT *uptr, char *cptr) { lps_ccnt = lps_lcnt = 0; /* top of form */ +lps_restart (uptr, 0, NULL, NULL); /* restart I/O if hung */ return attach_unit (uptr, cptr); } diff --git a/HP2100/hp2100_lpt.c b/HP2100/hp2100_lpt.c index 66298715..3363a610 100644 --- a/HP2100/hp2100_lpt.c +++ b/HP2100/hp2100_lpt.c @@ -25,6 +25,7 @@ lpt 12845B 2607 line printer + 19-Nov-04 JDB Added restart when set online, etc. 29-Sep-04 JDB Added SET OFFLINE/ONLINE, POWEROFF/POWERON Fixed status returns for error conditions Fixed TOF handling so form remains on line 0 @@ -97,6 +98,7 @@ DEVICE lpt_dev; int32 lptio (int32 inst, int32 IR, int32 dat); t_stat lpt_svc (UNIT *uptr); t_stat lpt_reset (DEVICE *dptr); +t_stat lpt_restart (UNIT *uptr, int32 value, char *cptr, void *desc); t_stat lpt_attach (UNIT *uptr, char *cptr); /* LPT data structures @@ -128,9 +130,9 @@ REG lpt_reg[] = { MTAB lpt_mod[] = { { UNIT_POWEROFF, UNIT_POWEROFF, "power off", "POWEROFF", NULL }, - { UNIT_POWEROFF, 0, "power on", "POWERON", NULL }, + { UNIT_POWEROFF, 0, "power on", "POWERON", lpt_restart }, { UNIT_OFFLINE, UNIT_OFFLINE, "offline", "OFFLINE", NULL }, - { UNIT_OFFLINE, 0, "online", "ONLINE", NULL }, + { UNIT_OFFLINE, 0, "online", "ONLINE", lpt_restart }, { MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &lpt_dev }, { 0 } }; @@ -196,9 +198,13 @@ t_stat lpt_svc (UNIT *uptr) int32 i, skip, chan, dev; dev = lpt_dib.devno; /* get dev no */ -clrCMD (dev); /* clear cmd */ if ((uptr->flags & UNIT_ATT) == 0) /* attached? */ return IORETURN (lpt_stopioe, SCPE_UNATT); +else if (uptr->flags & UNIT_OFFLINE) /* offline? */ + return IORETURN (lpt_stopioe, STOP_OFFLINE); +else if (uptr->flags & UNIT_POWEROFF) /* powered off? */ + return IORETURN (lpt_stopioe, STOP_PWROFF); +clrCMD (dev); /* clear cmd */ setFSR (dev); /* set flag, fbf */ if (uptr->buf & LPT_CTL) { /* control word? */ if (uptr->buf & LPT_CHAN) { @@ -237,10 +243,32 @@ sim_cancel (&lpt_unit); /* deactivate unit */ return SCPE_OK; } +/* Restart I/O routine + + If I/O is started via STC, and the printer is powered off, offline, + or out of paper, the CTL and CMD flip-flops will set, a service event + will be scheduled, and the service routine will be entered. If + STOP_IOE is not set, the I/O operation will "hang" at that point + until the printer is powered on, set online, or paper is supplied + (attached). + + If a pending operation is "hung" when this routine is called, it is + restarted, which clears CTL and sets FBF and FLG, completing the + original I/O request. + */ + +t_stat lpt_restart (UNIT *uptr, int32 value, char *cptr, void *desc) +{ +if (lpt_dib.cmd && lpt_dib.ctl && !sim_is_active (uptr)) + sim_activate (uptr, 0); /* reschedule I/O */ +return SCPE_OK; +} + /* Attach routine */ t_stat lpt_attach (UNIT *uptr, char *cptr) { lpt_lcnt = 0; /* top of form */ +lpt_restart (uptr, 0, NULL, NULL); /* restart I/O if hung */ return attach_unit (uptr, cptr); } diff --git a/HP2100/hp2100_ms.c b/HP2100/hp2100_ms.c index 1ec5a452..c94cd85f 100644 --- a/HP2100/hp2100_ms.c +++ b/HP2100/hp2100_ms.c @@ -133,7 +133,6 @@ #define STA_LOCAL 0000001 /* local (d) */ #define STA_DYN (STA_PE|STA_SEL|STA_TBSY|STA_WLK|STA_LOCAL) -extern uint16 *M; extern uint32 PC, SR; extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2]; extern int32 sim_switches; @@ -854,12 +853,13 @@ const uint16 ms_rom[IBL_LNT] = { t_stat msc_boot (int32 unitno, DEVICE *dptr) { int32 dev; +extern uint32 saved_AR; if (unitno != 0) return SCPE_NOFNC; /* only unit 0 */ dev = msd_dib.devno; /* get data chan dev */ if (ibl_copy (ms_rom, dev)) return SCPE_IERR; /* copy boot to memory */ SR = (SR & IBL_OPT) | IBL_MS | (dev << IBL_V_DEV); /* set SR */ -if ((sim_switches & SWMASK ('S')) && AR) SR = SR | 1; /* skip? */ +if ((sim_switches & SWMASK ('S')) && saved_AR) SR = SR | 1; /* skip? */ return SCPE_OK; } diff --git a/HP2100/hp2100_stddev.c b/HP2100/hp2100_stddev.c index 8377262e..371afa27 100644 --- a/HP2100/hp2100_stddev.c +++ b/HP2100/hp2100_stddev.c @@ -115,7 +115,6 @@ #define CLK_V_ERROR 4 /* clock overrun */ #define CLK_ERROR (1 << CLK_V_ERROR) -extern uint16 *M; extern uint32 PC, SR; extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2]; extern UNIT cpu_unit; diff --git a/HP2100/hp2100_sys.c b/HP2100/hp2100_sys.c index 958de47a..3ab12a1f 100644 --- a/HP2100/hp2100_sys.c +++ b/HP2100/hp2100_sys.c @@ -23,6 +23,7 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 19-Nov-04 JDB Added STOP_OFFLINE, STOP_PWROFF messages 25-Sep-04 JDB Added memory protect device Fixed display of CCA/CCB/CCE instructions 01-Jun-04 RMS Added latent 13037 support @@ -108,7 +109,9 @@ const char *sim_stop_messages[] = { "Breakpoint", "Indirect address loop", "Indirect address interrupt (should not happen!)", - "No connection on interprocessor link" }; + "No connection on interprocessor link", + "Device/unit offline", + "Device/unit powered off" }; /* Binary loader diff --git a/I1401/i1401_sys.c b/I1401/i1401_sys.c index 8f475a17..88d2aed8 100644 --- a/I1401/i1401_sys.c +++ b/I1401/i1401_sys.c @@ -1,6 +1,6 @@ /* i1401_sys.c: IBM 1401 simulator interface - Copyright (c) 1993-2004, Robert M. Supnik + Copyright (c) 1993-2005, Robert M. Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -23,6 +23,7 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 04-Jan-05 WVS Added address argument support 14-Nov-04 WVS Added data printout support 16-Mar-03 RMS Fixed mnemonic for MCS 03-Jun-02 RMS Added 1311 support @@ -173,7 +174,7 @@ void fprint_addr (FILE *of, t_value *dig) int32 addr, xa; extern int32 hun_table[64], ten_table[64], one_table[64]; -addr = hun_table[dig[0]] + ten_table[dig[1]] + one_table[dig[2]]; +addr = hun_table[dig[0] & CHAR] + ten_table[dig[1]] + one_table[dig[2]]; xa = (addr >> V_INDEX) & M_INDEX; if (xa) fprintf (of, " %d,%d", addr & ADDRMASK, ((xa - (X1 >> V_INDEX)) / 5) + 1); else if (addr >= MAXMEMSIZE) fprintf (of, " %d*", addr & ADDRMASK); @@ -246,12 +247,17 @@ for (ilnt = 1; ilnt < sim_emax; ilnt++) if (val[ilnt] & WM) break; if ((flags & (NOWM | HNOP)) && (ilnt > 7)) ilnt = 7; /* cs, swm, h, nop? */ else if ((op == OP_B) && (ilnt > 4) && (val[4] == BCD_BLANK)) ilnt = 4; else if ((ilnt > 8) && (op != OP_NOP)) ilnt = 8; /* cap length */ -if (((flags & len_table[ilnt]) == 0) && /* invalid lnt, */ - (op != OP_NOP)) return dcw (of, op, val); /* not nop? */ +if (ilnt == 3) { /* lnt = 3? */ + fprintf (of, "DSA"); /* assume DSA */ + fprint_addr (of, val); /* print addr */ + return -(ilnt - 1); } +if ((((flags & len_table[ilnt]) == 0) && /* invalid lnt, */ + (op != OP_NOP)) || /* not nop? */ + (opcode[op] == NULL)) return dcw (of, op, val); /* or undef? */ fprintf (of, "%s",opcode[op]); /* print opcode */ if (ilnt > 2) { /* A address? */ if (((flags & IO) || (op == OP_NOP)) && (val[1] == BCD_PERCNT)) - fprintf (of, " %%%c%c", bcd_to_ascii[val[2]], bcd_to_ascii[val[3]]); + fprintf (of, " %%%c%c", bcd_to_ascii[val[2]], bcd_to_ascii[val[3]]); else fprint_addr (of, &val[1]); } if (ilnt > 5) fprint_addr (of, &val[4]); /* B address? */ if ((ilnt == 2) || (ilnt == 5) || (ilnt == 8)) /* d character? */ diff --git a/Interdata/id_mt.c b/Interdata/id_mt.c index a205f999..e80e5bcd 100644 --- a/Interdata/id_mt.c +++ b/Interdata/id_mt.c @@ -25,6 +25,7 @@ mt M46-494 dual density 9-track magtape controller + 07-Dec-04 RMS Added read-only file support 25-Apr-03 RMS Revised for extended file support 28-Mar-03 RMS Added multiformat support 28-Feb-03 RMS Revised for magtape library @@ -117,10 +118,10 @@ t_stat mt_map_err (UNIT *uptr, t_stat st); DIB mt_dib = { d_MT, 0, v_MT, mt_tplte, &mt, NULL }; UNIT mt_unit[] = { - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) } }; + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) } }; REG mt_reg[] = { { HRDATA (STA, mt_sta, 8) }, diff --git a/LGP/lgp_cpu.c b/LGP/lgp_cpu.c index a8c4a5dd..d16fd003 100644 --- a/LGP/lgp_cpu.c +++ b/LGP/lgp_cpu.c @@ -1,6 +1,6 @@ /* lgp_cpu.c: LGP CPU simulator - Copyright (c) 2004, Robert M. Supnik + Copyright (c) 2004-2005, Robert M. Supnik 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,8 @@ cpu LGP-30 [LGP-21] CPU + 04-Jan-05 RMS Modified VM pointer setup + The system state for the LGP-30 [LGP-21] is: A<0:31> accumulator @@ -167,6 +169,7 @@ uint32 shift_in (uint32 a, uint32 dat, uint32 sh4); extern t_stat op_p (uint32 dev, uint32 ch); extern t_stat op_i (uint32 dev, uint32 ch, uint32 sh4); +extern void lgp_vm_init (void); /* CPU data structures @@ -578,6 +581,7 @@ out_strt = 0; out_done = 0; lgp21_sov = 0; delay = 0; +lgp_vm_init (); pcq_r = find_reg ("CQ", NULL, dptr); if (pcq_r) pcq_r->qptr = 0; else return SCPE_IERR; diff --git a/LGP/lgp_sys.c b/LGP/lgp_sys.c index f5a955aa..a4d22080 100644 --- a/LGP/lgp_sys.c +++ b/LGP/lgp_sys.c @@ -1,6 +1,6 @@ /* lgp_sys.c: LGP-30 simulator interface - Copyright (c) 2004, Robert M Supnik + Copyright (c) 2004-2005, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -22,6 +22,8 @@ Except as contained in this notice, the name of Robert M Supnik shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + + 04-Jan-05 RMS Modified VM pointer setup */ #include "lgp_defs.h" @@ -41,7 +43,6 @@ extern uint32 ts_flag; extern int32 sim_switches; extern int32 flex_to_ascii[128], ascii_to_flex[128]; -void (*sim_vm_init) (void) = &lgp_init; extern void (*sim_vm_fprint_addr) (FILE *st, DEVICE *dptr, t_addr addr); extern t_addr (*sim_vm_parse_addr) (DEVICE *dptr, char *cptr, char **tptr); @@ -221,7 +222,7 @@ else ea = (t_addr) strtotv (cptr, tptr, dptr->aradix); return ea; } -void lgp_init (void) +void lgp_vm_init (void) { sim_vm_fprint_addr = &lgp_fprint_addr; sim_vm_parse_addr = &lgp_parse_addr; @@ -304,7 +305,7 @@ if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { if (uptr && (uptr != &cpu_unit)) return SCPE_ARG; /* must be CPU */ if (!parse_sym_m (cptr, val, sw)) return SCPE_OK; /* symbolic parse? */ -if ((sw & SWMASK ('L')) || /* LGP hex? */ +if ((sw & SWMASK ('L')) || /* LGP hex? */ ((cpu_unit.flags & UNIT_LGPH_D) && !(sw & SWMASK ('H')))) { val[0] = 0; while (isspace (*cptr)) cptr++; /* absorb spaces */ diff --git a/PDP11/pdp11_cpu.c b/PDP11/pdp11_cpu.c index 5160e524..4f44ee9f 100644 --- a/PDP11/pdp11_cpu.c +++ b/PDP11/pdp11_cpu.c @@ -25,6 +25,7 @@ cpu PDP-11 CPU + 22-Dec-04 RMS Fixed WAIT to work in all modes (from John Dundas) 02-Oct-04 RMS Added model emulation 25-Jan-04 RMS Removed local debug logging support 29-Dec-03 RMS Formalized 18b Qbus support @@ -785,7 +786,7 @@ case 000: else setTRAP (TRAP_ILL); /* no, ill inst */ break; case 1: /* WAIT */ - if ((cm == MD_KER) && wait_enable) wait_state = 1; + if (wait_enable) wait_state = 1; break; case 3: /* BPT */ setTRAP (TRAP_BPT); diff --git a/PDP11/pdp11_tm.c b/PDP11/pdp11_tm.c index 1d41ef34..c32d5c39 100644 --- a/PDP11/pdp11_tm.c +++ b/PDP11/pdp11_tm.c @@ -25,6 +25,7 @@ tm TM11/TU10 magtape + 07-Dec-04 RMS Added read-only file support 30-Sep-04 RMS Revised Unibus interface 25-Jan-04 RMS Revised for device debug support 29-Dec-03 RMS Added 18b Qbus support @@ -188,14 +189,14 @@ DIB tm_dib = { IOBA_TM, IOLN_TM, &tm_rd, &tm_wr, 1, IVCL (TM), VEC_TM, { NULL } }; UNIT tm_unit[] = { - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) } }; + { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, + { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, + { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, + { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, + { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, + { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, + { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, + { UDATA (&tm_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) } }; REG tm_reg[] = { { ORDATA (MTS, tm_sta, 16) }, diff --git a/PDP11/pdp11_ts.c b/PDP11/pdp11_ts.c index ec26c2f1..020ea5a1 100644 --- a/PDP11/pdp11_ts.c +++ b/PDP11/pdp11_ts.c @@ -25,6 +25,7 @@ ts TS11/TSV05 magtape + 07-Dec-04 RMS Added read-only file support 30-Sep-04 RMS Revised Unibus interface 25-Jan-04 RMS Revised for device debug support 19-May-03 RMS Revised for new conditional compilation scheme @@ -301,7 +302,7 @@ int32 ts_map_status (t_stat st); DIB ts_dib = { IOBA_TS, IOLN_TS, &ts_rd, &ts_wr, 1, IVCL (TS), VEC_TS, { NULL } }; -UNIT ts_unit = { UDATA (&ts_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }; +UNIT ts_unit = { UDATA (&ts_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }; REG ts_reg[] = { { GRDATA (TSSR, tssr, DEV_RDX, 16, 0) }, diff --git a/SDS/sds_mt.c b/SDS/sds_mt.c index 0acfdf9f..60982272 100644 --- a/SDS/sds_mt.c +++ b/SDS/sds_mt.c @@ -25,6 +25,7 @@ mt 7 track magnetic tape + 07-Dec-04 RMS Added read-only file support 25-Apr-03 RMS Revised for extended file support 28-Mar-03 RMS Added multiformat support 28-Feb-03 RMS Revised for magtape library @@ -114,14 +115,14 @@ static const char bcd_to_sds[64] = { DIB mt_dib = { CHAN_W, DEV_MT, XFR_MT0, mt_tplt, &mt }; UNIT mt_unit[] = { - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) }, - { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) } }; + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) }, + { UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) } }; REG mt_reg[] = { { BRDATA (BUF, mtxb, 8, 8, MT_MAXFR) }, diff --git a/VAX/vax780_defs.h b/VAX/vax780_defs.h index 65a31a03..beb8fd41 100644 --- a/VAX/vax780_defs.h +++ b/VAX/vax780_defs.h @@ -52,7 +52,6 @@ #define VAX780_PLANT (0 << 12) /* plant (Salem NH) */ #define VAX780_SN (1234) #define CON_HLTPIN 0x0200 /* external CPU halt */ -#define CON_PWRUP 0x0300 /* powerup code */ #define CON_HLTINS 0x0600 /* HALT instruction */ #define MCHK_RD_F 0x00 /* read fault */ #define MCHK_RD_A 0xF4 /* read abort */ @@ -77,7 +76,7 @@ #define TR_MBA1 9 #define NEXUS_HLVL (IPL_HMAX - IPL_HMIN + 1) #define SCB_NEXUS 0x100 /* nexus intr base */ -#define SBI_FAULTS 0xFC000000 /* SBI fault flags - ni */ +#define SBI_FAULTS 0xFC000000 /* SBI fault flags */ /* Internal I/O interrupts - relative except for clock and console */ @@ -195,7 +194,6 @@ #define VH_MUXES 4 /* max # of DHQ muxes */ #define MT_MAXFR (1 << 16) /* magtape max rec */ #define AUTO_LNT 34 /* autoconfig ranks */ -#define DIB_MAX 100 /* max DIBs */ #define DEV_V_UBUS (DEV_V_UF + 0) /* Unibus */ #define DEV_V_MBUS (DEV_V_UF + 1) /* Massbus */ diff --git a/VAX/vax780_mba.c b/VAX/vax780_mba.c index d993b597..daaecd8a 100644 --- a/VAX/vax780_mba.c +++ b/VAX/vax780_mba.c @@ -77,7 +77,7 @@ #define MBASR_NFD 0x00040000 /* nx drive - W1C int */ #define MBASR_MCPE 0x00020000 /* ctl perr - ni W1C int */ #define MBASR_ATA 0x00010000 /* attn - W1C int */ -#define MBASR_SPE 0x00004000 /* silo par err - ni W1C int */ +#define MBASR_SPE 0x00004000 /* silo perr - ni W1C int */ #define MBASR_DTCMP 0x00002000 /* xfr done - W1C int */ #define MBASR_DTABT 0x00001000 /* abort - W1C int */ #define MBASR_DLT 0x00000800 /* dat late - ni W1C abt */ @@ -125,8 +125,6 @@ #define MBACMD_OF 0x7 -#define MBAMAX_OF 0x8 - /* External registers */ #define MBA_CS1 0x00 /* device CSR1 */ @@ -180,7 +178,6 @@ extern void WriteL (uint32 pa, int32 val); static MBACTX *ctxmap[MBA_NUM] = { &massbus[0], &massbus[1] }; static DEVICE *devmap[MBA_NUM] = { &mba0_dev, &mba1_dev }; -static DIB *dibmap[MBA_NUM] = { &mba0_dib, &mba1_dib }; /* Massbus register dispatches */ @@ -268,7 +265,6 @@ switch (rtype) { /* case on type */ case MBART_INT: /* internal */ ofs = MBA_INTOFS (pa); /* check range */ - if (ofs >= MBAMAX_OF) return SCPE_NXM; switch (ofs) { case MBACNF_OF: /* CNF */ *val = (mbp->cnf & MBACNF_RD) | MBACNF_CODE; @@ -337,7 +333,6 @@ switch (rtype) { /* case on type */ case MBART_INT: /* internal */ ofs = MBA_INTOFS (pa); /* check range */ - if (ofs >= MBAMAX_OF) return SCPE_NXM; switch (ofs) { case MBACNF_OF: /* CNF */ mbp->cnf = mbp->cnf & ~(val & MBACNF_W1C); @@ -391,7 +386,7 @@ case MBART_EXT: /* external */ r = mbregW[mb] (val, ofs, drv); /* write dev reg */ if (r == MBE_NXD) mba_upd_sr (MBASR_NFD, 0, mb);/* nx drive? */ else if (r == MBE_NXR) return SCPE_NXM; /* nx reg? */ - if (cs1dt && (r == SCPE_OK)) /* did dt start? */ + if (cs1dt && (r == SCPE_OK)) /* did dt start? */ mbp->sr = (mbp->sr | MBASR_DTBUSY) & ~MBASR_W1C; break; @@ -498,7 +493,7 @@ for (i = 0; i < bc; i = i + pbc) { /* loop by pages */ } } } -return 0; +return i; } int32 mba_chbufW (uint32 mb, int32 bc, uint16 *buf) @@ -575,7 +570,7 @@ MBACTX *mbp; if (mb >= MBA_NUM) return 0; mbp = ctxmap[mb]; -return ((0x10000 - (mbp->bc >> MBABC_V_CNT)) & MBABC_WR); +return (((MBABC_WR + 1) - (mbp->bc >> MBABC_V_CNT)) & MBABC_WR); } void mba_set_int (uint32 mb) @@ -621,12 +616,14 @@ return; t_stat mba_reset (DEVICE *dptr) { int32 i, mb; +DIB *dibp; MBACTX *mbp; -for (mb = 0; mb < MBA_NUM; mb++) { - mbp = ctxmap[mb]; - if (dptr == devmap[mb]) break; - } +dibp = (DIB *) dptr->ctxt; +if (dibp == NULL) return SCPE_IERR; +mb = dibp->ba - TR_MBA0; +if ((mb < 0) || (mb >= MBA_NUM)) return SCPE_IERR; +mbp = ctxmap[mb]; mbp->cnf = 0; mbp->cr = mbp->cr & MBACR_MNT; mbp->sr = 0; diff --git a/VAX/vax780_sbimem.c b/VAX/vax780_sbimem.c index cb29d5d0..5ccfba35 100644 --- a/VAX/vax780_sbimem.c +++ b/VAX/vax780_sbimem.c @@ -53,7 +53,6 @@ #define SBISC_RD 0xFFFF0000 /* SBI silo comp */ #define SBISC_WR 0x7FFF0000 #define SBISC_LOCK 0x80000000 /* lock */ -#define SBISC_CNT 0x000F0000 /* count */ #define SBIMT_RD 0xFFFFFF00 /* SBI maint */ #define SBIMT_WR 0xFFFFF900 @@ -498,8 +497,7 @@ case MT_SBIFS: /* SBIFS */ sbi_fs = sbi_fs & ~(val & SBIFS_W1C); break; case MT_SBISC: /* SBISC */ - sbi_sc = (sbi_sc & ~SBISC_WR) | (val & SBISC_WR); - if ((val & SBISC_CNT) != SBISC_CNT) sbi_sc = sbi_sc & ~SBISC_LOCK; + sbi_sc = (sbi_sc & ~(SBISC_LOCK|SBISC_WR)) | (val & SBISC_WR); break; case MT_SBIMT: /* SBIMT */ sbi_mt = (sbi_mt & ~SBIMT_WR) | (val & SBIMT_WR); diff --git a/VAX/vax780_stddev.c b/VAX/vax780_stddev.c index 977d0b39..1cb12abf 100644 --- a/VAX/vax780_stddev.c +++ b/VAX/vax780_stddev.c @@ -31,8 +31,8 @@ 08-Sep-04 RMS Cloned from vax_stddev.c, vax_sysdev.c, and pdp11_rx.c - The console floppy protocol is a guess, because VMS only uses read and write. - Based on triangulation of the boot and full drivers: + The console floppy protocol is based on the description in the 1982 VAX + Architecture Reference Manual: TXDB<11:8> = 0 -> normal console output TXDB<11:8> = 1 -> data output to floppy @@ -122,6 +122,11 @@ #define FL_STADDA 0x040 #define FL_STAERR 0x080 #define FL_CPROT 0x905 /* protocol error */ +#define FL_MISC 0xF00 /* misc communications */ +#define FL_SWDN 0x1 /* software done */ +#define FL_BOOT 0x2 /* reboot */ +#define FL_CLWS 0x3 /* clear warm start */ +#define FL_CLCS 0x4 /* clear cold start */ #define FL_GETFNC(x) (((x) >> FL_V_FNC) & FL_M_FNC) #define TRACK u3 /* current track */ @@ -340,7 +345,7 @@ int32 rxdb_rd (void) int32 t = tti_buf; /* char + error */ tti_csr = tti_csr & ~CSR_DONE; /* clr done */ -tti_buf = tti_buf & 0xFF; /* clr errors */ +tti_buf = tti_buf & BMASK; /* clr errors */ tti_int = 0; return t; } @@ -635,7 +640,7 @@ todr_reg = (base * 100) + 0x10000000; /* cvt to VAX form */ return SCPE_OK; } -/* Console write, txdb<11:8> != 1 (console unit) */ +/* Console write, txdb<11:8> != 0 (console unit) */ t_stat fl_wr_txdb (int32 data) { diff --git a/VAX/vax780_uba.c b/VAX/vax780_uba.c index 3679ae81..9c31b05b 100644 --- a/VAX/vax780_uba.c +++ b/VAX/vax780_uba.c @@ -64,7 +64,8 @@ #define UBA_USEFIE_SR (UBASR_RDTO|UBASR_RDS|UBASR_CRD|UBASR_CXTER| \ UBASR_CXTO|UBASR_DPPE|UBASR_IVMR|UBASR_MRPF) #define UBA_SUEFIE_SR (UBASR_UBSTO|UBASR_UBTMO) -#define UBA_CNFIE_CR (UBACNF_ADPDN|UBACNF_ADPUP|UBACNF_UBINIT|UBACNF_UBPDN|UBACNF_UBIC) +#define UBA_CNFIE_CR (UBACNF_ADPDN|UBACNF_ADPUP|UBACNF_UBINIT|\ + UBACNF_UBPDN|UBACNF_UBIC) /* Status register */ @@ -129,8 +130,6 @@ #define UBADPR_RD 0xC0FFFFFF #define UBADPR_W1C 0xC0000000 -#define UBAMAX_OF 0x020 - /* Map registers */ #define UBAMAP_OF 0x200 @@ -285,7 +284,6 @@ if (ofs >= UBAMAP_OF) { /* map range */ idx = ofs - UBAMAP_OF; *val = uba_map[idx] & UBAMAP_RD; return SCPE_OK; } -if (ofs >= UBAMAX_OF) return SCPE_NXM; /* check range */ switch (ofs) { /* case on offset */ @@ -358,8 +356,8 @@ if (ofs >= UBAMAP_OF) { /* map? */ idx = ofs - UBAMAP_OF; uba_map[idx] = val & UBAMAP_WR; return SCPE_OK; } -if (ofs >= UBAMAX_OF) return SCPE_NXM; /* check range */ -switch (ofs) { /* case on offset */ + +switch (ofs) { /* case on offset */ case UBACNF_OF: /* CNF */ uba_cnf = uba_cnf & ~(val & UBACNF_W1C); /* W1C bits */ diff --git a/VAX/vax_cis.c b/VAX/vax_cis.c index f99d0765..8c9a8c3a 100644 --- a/VAX/vax_cis.c +++ b/VAX/vax_cis.c @@ -349,7 +349,7 @@ case MATCHC: Registers if PSL = 1: R[0] = result R[1] = table address - R[2] = source string length + R[2] = delta-PC/0/source string length R[3] = source string address Condition codes: @@ -578,7 +578,6 @@ case DIVP: NibbleLshift (&src2, 1, 0); /* shift dividend */ NibbleLshift (&dst, 1, 0); /* shift quotient */ } /* end divide loop */ - dst.sign = src1.sign ^ src2.sign; /* calculate sign */ } /* end if */ cc = WriteDstr (op[4], op[5], &dst, 0, acc); /* store result */ R[0] = 0; @@ -982,7 +981,7 @@ case EDITPC: sign = C_SPACE; } fill = C_SPACE; - R[0] = R[4] = op[0] & WMASK; /* src len */ + R[0] = R[4] = op[0]; /* src len */ R[1] = op[1]; /* src addr */ R[2] = STR_PACK (0, (sign << ED_V_SIGN) | (fill << ED_V_FILL)); /* delta PC, sign, fill */ @@ -990,7 +989,7 @@ case EDITPC: R[5] = op[3]; /* dst addr */ PSL = PSL | PSL_FPD; /* set FPD */ } - for (;; ) { /* loop thru pattern */ + for ( ;; ) { /* loop thru pattern */ pop = Read (R[3], L_BYTE, RA); /* rd pattern op */ if (pop == EO_END) break; /* end? */ if (pop & EO_RPT_FLAG) { /* repeat class? */ diff --git a/VAX/vax_cmode.c b/VAX/vax_cmode.c index 8dbb2a46..95cae643 100644 --- a/VAX/vax_cmode.c +++ b/VAX/vax_cmode.c @@ -140,7 +140,7 @@ case 000: /* 00xxxx */ case 002: /* 0002xx */ if (IR < 000210) { /* RTS */ dstspec = dstspec & 07; - if (dstspec != 7) { /* PC <- r */ + if (dstspec != 7) { /* PC <- r */ CMODE_JUMP (RdRegW (dstspec)); } dst = RdMemW (R[6]); /* t <- (sp)+ */ @@ -157,7 +157,7 @@ case 000: /* 00xxxx */ case 003: /* SWAB */ if (dstreg) src = RdRegW (dstspec); else src = RdMemMW (ea = GeteaW (dstspec)); - dst = ((src & 0xFF) << 8) | ((src >> 8) & 0xFF); + dst = ((src & BMASK) << 8) | ((src >> 8) & BMASK); if (dstreg) WrRegW (dst, dstspec); else WrMemW (dst, ea); CC_IIZZ_B ((dst & BMASK)); @@ -216,7 +216,7 @@ case 000: /* 00xxxx */ src = RdRegW (srcspec); /* get src reg */ WrMemW (src, (R[6] - 2) & WMASK); /* -(sp) <- r */ R[6] = (R[6] - 2) & WMASK; - if (srcspec != 7) R[srcspec] = PC; /* r <- PC */ + if (srcspec != 7) WrRegW (PC, srcspec); /* r <- PC */ CMODE_JUMP (dst); /* PC <- dst */ } break; /* end JSR */ @@ -562,7 +562,8 @@ case 007: /* EIS */ break; default: - CMODE_FAULT (CMODE_RSVI); } /* end switch EIS */ + CMODE_FAULT (CMODE_RSVI); /* end switch EIS */ + } break; /* end case 007 */ /* Opcode 10: branches, traps, SOPs */ @@ -627,7 +628,7 @@ case 010: /* Opcode 10, continued: SOPs */ case 050: /* CLRB */ - if (dstreg) R[dstspec] = R[dstspec] & ~BMASK; + if (dstreg) WrRegB (0, dstspec); else WrMemB (0, GeteaB (dstspec)); cc = CC_Z; break; diff --git a/VAX/vax_doc.txt b/VAX/vax_doc.txt index ae7b5d72..54a3b774 100644 --- a/VAX/vax_doc.txt +++ b/VAX/vax_doc.txt @@ -183,7 +183,7 @@ Notes on memory size: non-zero data, the simulator asks for confirmation. Data in the truncated portion of memory is lost. - If the simulator is running VMS, the operating system may have a SYSGEN - parameter set called PHYSICXAL PAGES (viewable from "MCR SYSGEN SHOW + parameter set called PHYSICAL PAGES (viewable from "MCR SYSGEN SHOW PHYSICALPAGES"). PHYSICALPAGES limits the maximum number of physical pages of memory the OS will recognize. If it is set to a lower value than the new memory size of the machine, then only the first PHYSICALPAGES of diff --git a/VAX/vax_octa.c b/VAX/vax_octa.c index ea747c49..d735b0f9 100644 --- a/VAX/vax_octa.c +++ b/VAX/vax_octa.c @@ -68,8 +68,7 @@ typedef struct ufph UFPH; #define UH_HRND 0x00004000 /* H round */ #define UH_V_NM 127 -int32 op_movh (int32 val); -int32 op_mnegh (int32 val); +int32 op_tsth (int32 val); int32 op_cmph (int32 *hf1, int32 *hf2); int32 op_cvtih (int32 val, int32 *hf); int32 op_cvthi (int32 *hf, int32 *flg, int32 opc); @@ -82,7 +81,7 @@ int32 op_mulh (int32 *opnd, int32 *hf); int32 op_divh (int32 *opnd, int32 *hf); int32 op_emodh (int32 *opnd, int32 *hflt, int32 *intgr, int32 *flg); void op_polyh (int32 *opnd, int32 acc); -void h_write_bwl (int32 spec, int32 va, int32 val, int32 lnt, int32 acc); +void h_write_l (int32 spec, int32 va, int32 val, int32 acc); void h_write_q (int32 spec, int32 va, int32 vl, int32 vh, int32 acc); void h_write_o (int32 spec, int32 va, int32 *val, int32 acc); void vax_hadd (UFPH *a, UFPH *b); @@ -104,14 +103,15 @@ void h_normh (UFPH *a); int32 h_rpackfd (UFPH *a, int32 *rl); int32 h_rpackg (UFPH *a, int32 *rl); int32 h_rpackh (UFPH *a, int32 *hflt); + +static int32 z_octa[4] = { 0, 0, 0, 0 }; /* Octaword instructions */ int32 op_octa (int32 *opnd, int32 cc, int32 opc, int32 acc, int32 spec, int32 va) { -int32 r, rh, temp, flg; -int32 z_octa[4] = { 0, 0, 0, 0 }; -int32 r_octa[4] = { 0, 0, 0, 0 }; +int32 r, rh, temp, flg, rn; +int32 r_octa[4]; switch (opc) { @@ -135,7 +135,7 @@ case PUSHAO: */ case MOVAO: - h_write_bwl (spec, va, opnd[0], L_LONG, acc); /* write operand */ + h_write_l (spec, va, opnd[0], acc); /* write operand */ CC_IIZP_L (opnd[0]); /* set cc's */ break; @@ -157,7 +157,7 @@ case CLRO: */ case TSTH: - r = op_movh (opnd[0]); /* test for -0 */ + r = op_tsth (opnd[0]); /* test for 0 */ CC_IIZZ_FP (r); /* set cc's */ break; @@ -174,16 +174,18 @@ case MOVO: CC_IIZP_O (opnd[0], opnd[1], opnd[2], opnd[3]); /* set cc's */ break; case MOVH: - if ((opnd[0] = op_movh (opnd[0])) == 0) /* test for -0 */ - opnd[1] = opnd[2] = opnd[3] = 0; /* result is 0 */ - h_write_o (spec, va, opnd, acc); /* write result */ - CC_IIZP_FP (opnd[0]); /* set cc's */ + if (r = op_tsth (opnd[0])) /* test for 0 */ + h_write_o (spec, va, opnd, acc); /* nz, write result */ + else h_write_o (spec, va, z_octa, acc); /* zero, write 0 */ + CC_IIZP_FP (r); /* set cc's */ break; case MNEGH: - if ((opnd[0] = op_mnegh (opnd[0])) == 0) /* test for -0 */ - opnd[1] = opnd[2] = opnd[3] = 0; /* result is 0 */ - h_write_o (spec, va, opnd, acc); /* write result */ - CC_IIZZ_FP (opnd[0]); /* set cc's */ + if (r = op_tsth (opnd[0])) { /* test for 0 */ + opnd[0] = opnd[0] ^ FPSIGN; /* nz, invert sign */ + h_write_o (spec, va, opnd, acc); /* write result */ + } + else h_write_o (spec, va, z_octa, acc); /* zero, write 0 */ + CC_IIZZ_FP (r); /* set cc's */ break; /* CMPH @@ -230,19 +232,25 @@ case CVTLH: case CVTHB: r = op_cvthi (opnd, &temp, opc) & BMASK; /* convert */ - h_write_bwl (spec, va, r, L_BYTE, acc); /* write result */ + if (spec > (GRN | nPC)) Write (va, r, L_BYTE, WA); + else { + rn = spec & 0xF; + R[rn] = (R[rn] & ~BMASK) | r; } CC_IIZZ_B (r); /* set cc's */ cc = cc | temp; /* or in V */ break; case CVTHW: r = op_cvthi (opnd, &temp, opc) & WMASK; /* convert */ - h_write_bwl (spec, va, r, L_WORD, acc); /* write result */ + if (spec > (GRN | nPC)) Write (va, r, L_WORD, WA); + else { + rn = spec & 0xF; + R[rn] = (R[rn] & ~WMASK) | r; } CC_IIZZ_W (r); /* set cc's */ cc = cc | temp; /* or in V */ break; case CVTHL: case CVTRHL: r = op_cvthi (opnd, &temp, opc) & LMASK; /* convert */ - h_write_bwl (spec, va, r, L_LONG, acc); /* write result */ + h_write_l (spec, va, r, acc); /* write result */ CC_IIZZ_L (r); /* set cc's */ cc = cc | temp; /* or in V */ break; @@ -290,7 +298,7 @@ case CVTGH: case CVTHF: r = op_cvthfd (opnd, NULL); /* convert */ - h_write_bwl (spec, va, r, L_LONG, acc); /* write result */ + h_write_l (spec, va, r, acc); /* write result */ CC_IIZZ_FP (r); /* set cc's */ break; case CVTHD: @@ -402,25 +410,18 @@ default: return cc; } -/* Move/test/move negated h_floating +/* Test h_floating Note that only the high 32b is processed. If the high 32b is not zero, the rest of the fraction is unchanged. */ -int32 op_movh (int32 val) +int32 op_tsth (int32 val) { if (val & H_EXP) return val; /* non-zero? */ if (val & FPSIGN) RSVD_OPND_FAULT; /* reserved? */ return 0; /* clean 0 */ } -int32 op_mnegh (int32 val) -{ -if (val & H_EXP) return (val ^ FPSIGN); /* non-zero? */ -if (val & FPSIGN) RSVD_OPND_FAULT; /* reserved? */ -return 0; /* clean 0 */ -} - /* Compare h_floating */ int32 op_cmph (int32 *hf1, int32 *hf2) @@ -454,7 +455,7 @@ if (val < 0) { /* negative? */ } else a.sign = 0; /* else sign = + */ a.exp = 32 + H_BIAS; /* initial exp */ -a.frac.f3 = val & LMASK; /* fraction hi */ +a.frac.f3 = val & LMASK; /* fraction hi */ a.frac.f2 = a.frac.f1 = a.frac.f0 = 0; h_normh (&a); /* normalize */ return h_rpackh (&a, hf); /* round and pack */ @@ -620,7 +621,7 @@ UFPH a, b; h_unpackh (&opnd[0], &a); /* unpack operands */ h_unpackh (&opnd[5], &b); -a.frac.f3 = a.frac.f3 | opnd[4]; /* extend src1 */ +a.frac.f0 = a.frac.f0 | opnd[4]; /* extend src1 */ vax_hmul (&a, &b); /* multiply */ vax_hmod (&a, intgr, flg); /* sep int & frac */ return h_rpackh (&a, hflt); /* round and pack frac */ @@ -984,8 +985,8 @@ int32 h_rpackfd (UFPH *r, int32 *rh) static UQP f_round = { 0, 0, 0, UH_FRND }; static UQP d_round = { 0, 0, UH_DRND, 0 }; -if ((r->frac.f0 == 0) && (r->frac.f1 == 0) && /* if fraction = 0 */ - (r->frac.f2 == 0) && (r->frac.f3 == 0)) return 0; +if (rh) *rh = 0; /* assume 0 */ +if (r->exp == 0) return 0; /* exp = 0? done */ qp_add (&r->frac, rh? &d_round: &f_round); if ((r->frac.f3 & UH_NM_H) == 0) { /* carry out? */ qp_rsh (&r->frac, 1); /* renormalize */ @@ -999,7 +1000,7 @@ if (r->exp <= 0) { /* underflow? */ qp_rsh (&r->frac, FD_GUARD); /* remove guard */ if (rh) *rh = WORDSWAP (r->frac.f2); return r->sign | (r->exp << FD_V_EXP) | - (WORDSWAP (r->frac.f0) & ~(FD_HB | FPSIGN | FD_EXP)); + (WORDSWAP (r->frac.f3) & ~(FD_HB | FPSIGN | FD_EXP)); } int32 h_rpackg (UFPH *r, int32 *rh) @@ -1007,8 +1008,7 @@ int32 h_rpackg (UFPH *r, int32 *rh) static UQP g_round = { 0, 0, UH_GRND, 0 }; *rh = 0; /* assume 0 */ -if ((r->frac.f0 == 0) && (r->frac.f1 == 0) && /* if fraction = 0 */ - (r->frac.f2 == 0) && (r->frac.f3 == 0)) return 0; +if (r->exp == 0) return 0; /* exp = 0? done */ qp_add (&r->frac, &g_round); /* round */ if ((r->frac.f3 & UH_NM_H) == 0) { /* carry out? */ qp_rsh (&r->frac, 1); /* renormalize */ @@ -1030,8 +1030,7 @@ int32 h_rpackh (UFPH *r, int32 *hflt) static UQP h_round = { UH_HRND, 0, 0, 0 }; hflt[0] = hflt[1] = hflt[2] = hflt[3] = 0; /* assume 0 */ -if ((r->frac.f0 == 0) && (r->frac.f1 == 0) && /* if fraction = 0 */ - (r->frac.f2 == 0) && (r->frac.f3 == 0)) return 0; +if (r->exp == 0) return 0; /* exp = 0? done */ qp_add (&r->frac, &h_round); /* round */ if ((r->frac.f3 & UH_NM_H) == 0) { /* carry out? */ qp_rsh (&r->frac, 1); /* renormalize */ @@ -1051,15 +1050,10 @@ hflt[3] = WORDSWAP (r->frac.f0); return hflt[0]; } -void h_write_bwl (int32 spec, int32 va, int32 val, int32 lnt, int32 acc) +void h_write_l (int32 spec, int32 va, int32 val, int32 acc) { -int32 rn; - -if (spec >= (GRN | nPC)) Write (va, val, lnt, WA); -else { rn = spec & 0xF; - if (lnt == L_BYTE) R[rn] = (R[rn] & ~BMASK) | val; - else if (lnt == L_WORD) R[rn] = (R[rn] & ~WMASK) | val; - else R[rn] = val; } +if (spec > (GRN | nPC)) Write (va, val, L_LONG, WA); +else R[spec & 0xF] = val; return; } diff --git a/VAX/vaxmod_defs.h b/VAX/vaxmod_defs.h index 2f5af1e4..c286c036 100644 --- a/VAX/vaxmod_defs.h +++ b/VAX/vaxmod_defs.h @@ -226,7 +226,6 @@ #define VH_MUXES 4 /* max # of DHQ muxes */ #define MT_MAXFR (1 << 16) /* magtape max rec */ #define AUTO_LNT 34 /* autoconfig ranks */ -#define DIB_MAX 100 /* max DIBs */ #define DEV_V_UBUS (DEV_V_UF + 0) /* Unibus */ #define DEV_V_QBUS (DEV_V_UF + 1) /* Qbus */ diff --git a/scp.c b/scp.c index bb84eeb6..6b59ea07 100644 --- a/scp.c +++ b/scp.c @@ -23,6 +23,8 @@ be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 26-Dec-04 RMS Qualified SAVE examine, RESTORE deposit with SIM_SW_REST + 10-Nov-04 JDB Fixed logging of errors from cmds in "do" file 05-Nov-04 RMS Moved SET/SHOW DEBUG under CONSOLE hierarchy Renamed unit OFFLINE/ONLINE to DISABLED/ENABLED (from Dave Bryan) Revised to flush output files after simulation stop (from Dave Bryan) @@ -734,8 +736,10 @@ do { cptr = read_line (cbuf, CBUFSIZE, fpin); /* get cmd line */ if (cmdp = find_cmd (gbuf)) /* lookup command */ stat = cmdp->action (cmdp->arg, cptr); /* if found, exec */ else stat = SCPE_UNK; - if (stat >= SCPE_BASE) /* error? */ + if (stat >= SCPE_BASE) { /* error? */ printf ("%s\n", scp_error_messages[stat - SCPE_BASE]); + if (sim_log) fprintf (sim_log, "%s\n", + scp_error_messages[stat - SCPE_BASE]); } if (sim_vm_post != NULL) (*sim_vm_post) (TRUE); } while (stat != SCPE_EXIT); @@ -1798,7 +1802,7 @@ for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru devices */ zeroflg = TRUE; for (l = 0; (l < SRBSIZ) && (k < high); l++, k = k + (dptr->aincr)) { /* check for 0 block */ - r = dptr->examine (&val, k, uptr, 0); + r = dptr->examine (&val, k, uptr, SIM_SW_REST); if (r != SCPE_OK) return r; if (val) zeroflg = FALSE; SZ_STORE (sz, val, mbuf, l); @@ -1963,7 +1967,7 @@ for ( ;; ) { /* device loop */ for (j = 0; j < limit; j++, k = k + (dptr->aincr)) { if (blkcnt < 0) val = 0; /* compressed? */ else SZ_LOAD (sz, val, mbuf, j);/* saved value */ - r = dptr->deposit (val, k, uptr, 0); + r = dptr->deposit (val, k, uptr, SIM_SW_REST); if (r != SCPE_OK) return r; } /* end for j */ } /* end for k */ diff --git a/sim_rev.h b/sim_rev.h index 8cd1799a..697c2965 100644 --- a/sim_rev.h +++ b/sim_rev.h @@ -1,6 +1,6 @@ /* sim_rev.h: simulator revisions and current rev level - Copyright (c) 1993-2004, Robert M Supnik + Copyright (c) 1993-2005, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -29,13 +29,60 @@ #define SIM_MAJOR 3 #define SIM_MINOR 3 -#define SIM_PATCH 0 +#define SIM_PATCH 1 /* V3.3 revision history patch date module(s) and fix(es) - 0 tbd scp.c: + 1 05-Jan-05 h316_cpu.c: fixed bug in DIV + + h316_stddev.c: + - fixed bug in SKS '104 (reported by Philipp Hachtmann) + - fixed bug in SKS '504 + - adder reader/punch ASCII file support + - added Teletype reader/punch support + + h316_dp.c: fixed bug in skip on !seeking + + h316_mt.c: fixed bug in DMA/DMC support + + h316_lp.c: fixed bug in DMA/DMC support + + hp2100_cpu.c: + - fixed DMA reset to clear alternate CTL flop (from Dave Bryan) + - fixed DMA reset to not clear control words (from Dave Bryan) + - fixed SBS, CBS, TBS to do virtual reads + - separated A/B from M[0/1], for DMA IO (from Dave Bryan) + - added SET CPU 21MX-M, 21MX-E (from Dave Brian) + - disabled TIMER/EXECUTE/DIAG instructions for 21MX-M (from Dave Bryan) + - added post-processor to maintain T/M consistency (from Dave Bryan) + + hp2100_ds.c: first release + + hp2100_lps.c (all changes from Dave Bryan) + - added restart when set online, etc. + - fixed col count for non-printing chars + + hp2100_lpt.c (all changes from Dave Bryan) + - added restart when set online, etc. + + hp2100_sys.c (all changes from Dave Bryan): + - added STOP_OFFLINE, STOP_PWROFF messages + + i1401_sys.c: added address argument support (from Van Snyder) + + id_mt.c: added read-only file support + + lgp_cpu.c, lgp_sys.c: modified VM pointer setup + + pdp11_cpu.c: fixed WAIT to work in all modes (from John Dundas) + + pdp11_tm.c, pdp11_ts.c: added read-only file support + + sds_mt.c: added read-only file support + + 0 23-Nov-04 scp.c: - added reset_all_p (powerup) - fixed comma-separated SET options (from Dave Bryan) - changed ONLINE/OFFLINE to ENABLED/DISABLED (from Dave Bryan)