Notes For V3.3
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 SCP - Added -p (powerup) qualifier to RESET - Changed SET <unit> ONLINE/OFFLINE to SET <unit> ENABLED/DISABLED - Moved SET DEBUG under SET CONSOLE hierarchy - Added optional parameter value to SHOW command - Added output file option to SHOW command 1.2 PDP-11 - Separated RH Massbus adapter from RP controller - Added TU tape support - Added model emulation framework - Added model details 1.3 VAX - 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.4 Unibus/Qbus simulators (PDP-11, VAX, PDP-10) - Simplified DMA API's - Modified DMA peripherals to use simplified API's 1.5 HP2100 (all changes from Dave Bryan) 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 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 2. Bugs Fixed in 3.3 2.1 SCP - Fixed comma-separated SET options (from Dave Bryan) - Fixed duplicate HELP displays with user-specified commands 2.2 PDP-10 - 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<output_ready> flag 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
This commit is contained in:
parent
2e00e1122f
commit
b6393b36b4
131 changed files with 20920 additions and 4845 deletions
|
@ -1,53 +0,0 @@
|
||||||
Notes For V3.2-3
|
|
||||||
|
|
||||||
RESTRICTION: The PDP-15 FPP is only partially debugged. Do NOT
|
|
||||||
enable this feature for normal operations.
|
|
||||||
RESTRICTION: The HP DS disk is not debugged. DO NOT enable this
|
|
||||||
feature for normal operations.
|
|
||||||
|
|
||||||
1. New Features in 3.2-3
|
|
||||||
|
|
||||||
1.1 SCP
|
|
||||||
|
|
||||||
- Added ECHO command (from Dave Bryan)
|
|
||||||
|
|
||||||
2. Bugs Fixed in 3.2-2
|
|
||||||
|
|
||||||
2.1 SCP
|
|
||||||
|
|
||||||
- Qualified RESTORE detach with SIM_SW_REST
|
|
||||||
- Fixed OS/2 issues in sim_console.c and sim_sock.h
|
|
||||||
|
|
||||||
2.2 HP2100 (all from Dave Bryan)
|
|
||||||
|
|
||||||
- Changed CPU error stops to report PC not PC + 1
|
|
||||||
|
|
||||||
- Fixed CLC to DR to stop operation in progress
|
|
||||||
|
|
||||||
- Functional and timing fixes to DP
|
|
||||||
> controller sets ATN for all commands except read status
|
|
||||||
> controller resumes polling for ATN interrupts after read status
|
|
||||||
> check status on unattached drive set busy and not ready
|
|
||||||
> check status tests wrong unit for write protect status
|
|
||||||
> drive on line sets ATN, will set FLG if polling
|
|
||||||
|
|
||||||
- Functional and timing fixes to MS
|
|
||||||
> fixed erroneous execution of rejected command
|
|
||||||
> fixed erroneous execution of select-only command
|
|
||||||
> fixed erroneous execution of clear command
|
|
||||||
> fixed odd byte handling for read
|
|
||||||
> fixed spurious odd byte status on 13183A EOF
|
|
||||||
> modified handling of end of medium
|
|
||||||
> added detailed timing, with fast and realistic modes
|
|
||||||
> added reel sizes to simulate end of tape
|
|
||||||
> added debug printouts
|
|
||||||
|
|
||||||
- Modified MT handling of end of medium
|
|
||||||
|
|
||||||
- Added tab to TTY control char set
|
|
||||||
|
|
||||||
2.3 VAX
|
|
||||||
|
|
||||||
- VAX RQ controllers start LUNs at 0 (from Andreas Cejna)
|
|
||||||
- Added compatibility mode definitions
|
|
||||||
- Fixed EMODD, EMODG to probe second longword of quadword destination
|
|
143
0readme_33.txt
Normal file
143
0readme_33.txt
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
Notes For V3.3
|
||||||
|
|
||||||
|
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 SCP
|
||||||
|
|
||||||
|
- Added -p (powerup) qualifier to RESET
|
||||||
|
- Changed SET <unit> ONLINE/OFFLINE to SET <unit> ENABLED/DISABLED
|
||||||
|
- Moved SET DEBUG under SET CONSOLE hierarchy
|
||||||
|
- Added optional parameter value to SHOW command
|
||||||
|
- Added output file option to SHOW command
|
||||||
|
|
||||||
|
1.2 PDP-11
|
||||||
|
|
||||||
|
- Separated RH Massbus adapter from RP controller
|
||||||
|
- Added TU tape support
|
||||||
|
- Added model emulation framework
|
||||||
|
- Added model details
|
||||||
|
|
||||||
|
1.3 VAX
|
||||||
|
|
||||||
|
- 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.4 Unibus/Qbus simulators (PDP-11, VAX, PDP-10)
|
||||||
|
|
||||||
|
- Simplified DMA API's
|
||||||
|
- Modified DMA peripherals to use simplified API's
|
||||||
|
|
||||||
|
1.5 HP2100 (all changes from Dave Bryan)
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
2. Bugs Fixed in 3.3
|
||||||
|
|
||||||
|
2.1 SCP
|
||||||
|
|
||||||
|
- Fixed comma-separated SET options (from Dave Bryan)
|
||||||
|
- Fixed duplicate HELP displays with user-specified commands
|
||||||
|
|
||||||
|
2.2 PDP-10
|
||||||
|
|
||||||
|
- 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<output_ready> flag
|
||||||
|
|
||||||
|
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
|
|
@ -173,7 +173,7 @@ return (SCPE_OK);
|
||||||
status = error code
|
status = error code
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int32 fprint_sym (FILE *of, int32 addr, unsigned int32 *val,
|
int32 fprint_sym (FILE *of, int32 addr, uint32 *val,
|
||||||
UNIT *uptr, int32 sw)
|
UNIT *uptr, int32 sw)
|
||||||
{
|
{
|
||||||
int32 cflag, c1, c2, inst, adr;
|
int32 cflag, c1, c2, inst, adr;
|
||||||
|
@ -220,7 +220,7 @@ return -(oplen[inst] - 1);
|
||||||
status = error status
|
status = error status
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int32 parse_sym (char *cptr, int32 addr, UNIT *uptr, unsigned int32 *val, int32 sw)
|
int32 parse_sym (char *cptr, int32 addr, UNIT *uptr, uint32 *val, int32 sw)
|
||||||
{
|
{
|
||||||
int32 cflag, i = 0, j, r;
|
int32 cflag, i = 0, j, r;
|
||||||
char gbuf[CBUFSIZE];
|
char gbuf[CBUFSIZE];
|
||||||
|
@ -229,11 +229,11 @@ cflag = (uptr == NULL) || (uptr == &cpu_unit);
|
||||||
while (isspace (*cptr)) cptr++; /* absorb spaces */
|
while (isspace (*cptr)) cptr++; /* absorb spaces */
|
||||||
if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */
|
if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */
|
||||||
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
|
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
|
||||||
val[0] = (unsigned int) cptr[0];
|
val[0] = (uint32) cptr[0];
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII string? */
|
if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* ASCII string? */
|
||||||
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
|
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
|
||||||
val[0] = ((unsigned int) cptr[0] << 8) + (unsigned int) cptr[1];
|
val[0] = ((uint32) cptr[0] << 8) + (uint32) cptr[1];
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
|
|
||||||
/* An instruction: get opcode (all characters until null, comma,
|
/* An instruction: get opcode (all characters until null, comma,
|
||||||
|
|
|
@ -1,914 +0,0 @@
|
||||||
Altair 8800 Simulator with Z80 support
|
|
||||||
======================================
|
|
||||||
|
|
||||||
0. Revision History
|
|
||||||
|
|
||||||
- 26-Jan-2004, Peter Schorn (added support for t-state stepping)
|
|
||||||
- 25-Feb-2003, Peter Schorn (added support for real time simulation)
|
|
||||||
- 9-Oct-2002, Peter Schorn (added support for simulated hard disk)
|
|
||||||
- 28-Sep-2002, Peter Schorn (number of tracks per disk can be configured)
|
|
||||||
- 19-Sep-2002, Peter Schorn (added WARNROM feature)
|
|
||||||
- 31-Aug-2002, Peter Schorn (added extended ROM features suggested
|
|
||||||
by Scott LaBombard)
|
|
||||||
- 4-May-2002, Peter Schorn (added description of MP/M II sample software)
|
|
||||||
- 28-Apr-2002, Peter Schorn (added periodic timer interrupts and three
|
|
||||||
additional consoles)
|
|
||||||
- 15-Apr-2002, Peter Schorn (added memory breakpoint)
|
|
||||||
- 7-Apr-2002, Peter Schorn (added ROM / NOROM switch)
|
|
||||||
Original version of this document written by Charles E Owen
|
|
||||||
|
|
||||||
|
|
||||||
1. Background.
|
|
||||||
|
|
||||||
The MITS (Micro Instrumentation and Telemetry Systems) Altair 8800 was
|
|
||||||
announced on the January 1975 cover of Popular Electronics, which boasted
|
|
||||||
you could buy and build this powerful computer kit for only $397. The kit
|
|
||||||
consisted at that time of only the parts to build a case, power supply,
|
|
||||||
card cage (18 slots), CPU card, and memory card with 256 *bytes* of memory.
|
|
||||||
Still, thousands were ordered within the first few months after the
|
|
||||||
announcement, starting the personal computer revolution as we know it
|
|
||||||
today.
|
|
||||||
|
|
||||||
Many laugh at the small size of the that first kit, noting there were no
|
|
||||||
peripherals and the 256 byte memory size. But the computer was an open
|
|
||||||
system, and by 1977 MITS and many other small startups had added many
|
|
||||||
expansion cards to make the Altair quite a respectable little computer. The
|
|
||||||
"Altair Bus" that made this possible was soon called the S-100 Bus, later
|
|
||||||
adopted as an industry standard, and eventually became the IEE-696 Bus.
|
|
||||||
|
|
||||||
|
|
||||||
2. Hardware
|
|
||||||
|
|
||||||
We are simulating a fairly "loaded" Altair 8800 from about 1977, with the
|
|
||||||
following configuration:
|
|
||||||
|
|
||||||
device simulates
|
|
||||||
name(s)
|
|
||||||
|
|
||||||
CPU Altair 8800 with Intel 8080 CPU board, 62KB
|
|
||||||
of RAM, 2K of EPROM with start boot ROM.
|
|
||||||
SIO MITS 88-2SIO Dual Serial Interface Board. Port 1
|
|
||||||
is assumed to be connected to a serial "glass
|
|
||||||
TTY" that is your terminal running the Simulator.
|
|
||||||
PTR Paper Tape Reader attached to port 2 of the 2SIO board.
|
|
||||||
PTP Paper Tape Punch attached to port 2 of the
|
|
||||||
2SIO board. This also doubles as a printer port.
|
|
||||||
DSK MITS 88-DISK Floppy Disk controller with up
|
|
||||||
to eight drives.
|
|
||||||
|
|
||||||
|
|
||||||
2.1 CPU
|
|
||||||
|
|
||||||
We have 2 CPU options that were not present on the original machine but
|
|
||||||
are useful in the simulator. We also allow you to select memory sizes, but
|
|
||||||
be aware that some sample software requires the full 64K (i.e. CP/M) and
|
|
||||||
the MITS Disk Basic and Altair DOS require about a minimum of 24K.
|
|
||||||
|
|
||||||
SET CPU 8080 Simulates the 8080 CPU (normal)
|
|
||||||
SET CPU Z80 Simulates the Z80 CPU. Note that some software (e.g. most
|
|
||||||
original Altair software such as 4K Basic) requires an 8080 CPU and
|
|
||||||
will not or not properly run on a Z80. This is mainly due to the use
|
|
||||||
of the parity flag on the 8080 which has not always the same
|
|
||||||
semantics on the Z80.
|
|
||||||
|
|
||||||
SET CPU ITRAP Causes the simulator to halt if an invalid opcode
|
|
||||||
is detected (depending on the chosen CPU).
|
|
||||||
SET CPU NOITRAP Does not stop on an invalid Opcode. This is
|
|
||||||
how the real 8080 works.
|
|
||||||
|
|
||||||
SET CPU 4K
|
|
||||||
SET CPU 8K
|
|
||||||
SET CPU 12K
|
|
||||||
SET CPU 16K
|
|
||||||
...... (in 4K steps)
|
|
||||||
SET CPU 64K All these set various CPU memory configurations.
|
|
||||||
|
|
||||||
SET CPU BANKED Enables the banked memory support. The simulated memory
|
|
||||||
has eight banks with address range 0..'common' (see registers below)
|
|
||||||
and a common area from 'common' to 0xfff which is common to all
|
|
||||||
banks. The currently active bank is determined by register 'bank'
|
|
||||||
(see below). You can only switch to banked memory if the memory
|
|
||||||
is set to 64K. The banked memory is used by CP/M 3.
|
|
||||||
|
|
||||||
SET CPU NONBANKED Disables banked memory support.
|
|
||||||
|
|
||||||
SET CPU ROM Enables the ROM from address 'ROMLOW' to 'ROMHIGH'
|
|
||||||
(see below under CPU Registers) and prevents write access
|
|
||||||
to these locations. This is the default setting.
|
|
||||||
|
|
||||||
SET CPU NOROM Disables the ROM.
|
|
||||||
|
|
||||||
SET CPU ALTAIRROM Enables the slightly modified but downwards compatible
|
|
||||||
Altair boot ROM at addresses 0FF00 to 0FFFF. This is the default.
|
|
||||||
|
|
||||||
SET CPU NOALTAIRROM Disables standard Altair ROM behavior.
|
|
||||||
|
|
||||||
SET CPU WARNROM Enables warning messages to be printed when the CPU
|
|
||||||
attempts to write into ROM or into non-existing memory. Also prints
|
|
||||||
a warning message if the CPU attempts to read from non-existing
|
|
||||||
memory.
|
|
||||||
|
|
||||||
SET CPU NOWARNROM Suppreses all warning message of "WARNROM". Note that
|
|
||||||
some software tries on purpose to write to ROM in order to detect
|
|
||||||
the available RAM.
|
|
||||||
|
|
||||||
The BOOT EPROM card starts at address 0FF00 if it has been enabled by
|
|
||||||
'SET CPU ALTAIRROM'. Jumping to this address will boot drive 0 of the
|
|
||||||
floppy controller (CPU must be set to ROM or equivalent code must be
|
|
||||||
present). If no valid bootable software is present there the machine
|
|
||||||
crashes. This is historically accurate behavior.
|
|
||||||
|
|
||||||
The real 8080, on receiving a HLT (Halt) instruction, freezes the
|
|
||||||
processor and only an interrupt or CPU hardware reset will restore it. The
|
|
||||||
simulator is alot nicer, it will halt but send you back to the simulator
|
|
||||||
command line.
|
|
||||||
|
|
||||||
CPU Registers include the following:
|
|
||||||
|
|
||||||
Name Size Comment
|
|
||||||
|
|
||||||
PC 16 The Program Counter
|
|
||||||
AF 16 The accumulator and the flag register
|
|
||||||
F = S Z - AC - P/V N C
|
|
||||||
S = Sign flag.
|
|
||||||
Z = Zero Flag.
|
|
||||||
AC = Auxillary Carry flag.
|
|
||||||
P/V = Parity flag on 8080
|
|
||||||
Parity / Overflow flag on Z80
|
|
||||||
- = not used (undefined)
|
|
||||||
N = Internal sign flag
|
|
||||||
C = Carry flag.
|
|
||||||
BC 16 The BC register pair.
|
|
||||||
Register B is the high 8 bits, C is the lower 8 bits
|
|
||||||
DE 16 The DE register pair.
|
|
||||||
Register D is the high 8 bits, E is the lower 8 bits.
|
|
||||||
HL 16 The HL register pair.
|
|
||||||
Register H is the high 8 bits, L is the lower 8 bits.
|
|
||||||
AF1 16 The alternate AF register (on Z80 only)
|
|
||||||
BC1 16 The alternate BC register (on Z80 only)
|
|
||||||
DE1 16 The alternate DE register (on Z80 only)
|
|
||||||
HL1 16 The alternate HL register (on Z80 only)
|
|
||||||
IX 16 The IX index register (on Z80 only)
|
|
||||||
IY 16 The IY index register (on Z80 only)
|
|
||||||
IFF 8 Interrupt flag (on Z80 only)
|
|
||||||
INT 8 Interrupt register (on Z80 only)
|
|
||||||
|
|
||||||
SR 16 The front panel switches (use D SR 8 for 4k Basic).
|
|
||||||
WRU 8 The interrupt character. This starts as 5
|
|
||||||
(ctrl-E) but some Altair software uses this
|
|
||||||
keystroke so best to change this to something
|
|
||||||
exotic such as 035 (which is Ctl-]).
|
|
||||||
|
|
||||||
BANK 3 The currently active memory bank (if banked memory
|
|
||||||
is activated - see memory options above)
|
|
||||||
COMMON 16 The starting address of common memory. Originally set
|
|
||||||
to 0xc000 (note this setting must agree with the
|
|
||||||
value supplied to GENCPM for CP/M 3 system generation)
|
|
||||||
ROMLOW 16 The starting address of the ROM. Default is 0FF00.
|
|
||||||
ROMHIGH 16 The final address of the ROM. Default is 0FFFF.
|
|
||||||
CLOCK 32 The clock speed of the simulated CPU in kHz or 0 to run
|
|
||||||
at maximum speed. To set the clock speed for a typical
|
|
||||||
4 MHz Z80 CPU, use D CLOCK 4000. The CP/M utility SPEED
|
|
||||||
measures the clock speed of the simulated CPU.
|
|
||||||
|
|
||||||
|
|
||||||
2.2 The Serial I/O Card (2SIO)
|
|
||||||
|
|
||||||
This simple programmed I/O device provides 2 serial ports to the outside
|
|
||||||
world, which could be hardware jumpered to support RS-232 plugs or a TTY
|
|
||||||
current loop interface. The standard I/O addresses assigned by MITS was
|
|
||||||
10-11 (hex) for the first port, and 12-13 (hex) for the second. We follow
|
|
||||||
this standard in the Simulator.
|
|
||||||
|
|
||||||
The simulator directs I/O to/from the first port to the screen. The
|
|
||||||
second port reads from an attachable "tape reader" file on input, and
|
|
||||||
writes to an attachable "punch file" on output. These files are considered
|
|
||||||
a simple stream of 8-bit bytes.
|
|
||||||
|
|
||||||
The SIO can be configured in SIMH with the following commands:
|
|
||||||
|
|
||||||
SET SIO TTY Bit 8 is set to zero on console output
|
|
||||||
SET SIO ANSI Bit 8 is not touched on console output
|
|
||||||
|
|
||||||
SET SIO ALL Console input support lower- and upper case
|
|
||||||
SET SIO UPPER Console input is transformed to upper case characters only
|
|
||||||
(This feature is useful for most Altair software)
|
|
||||||
|
|
||||||
SET SIO BS Map the delete character to backspace
|
|
||||||
SET SIO DEL Map the backspace character to delete
|
|
||||||
|
|
||||||
SET SIO QUIET Do not print warning messages
|
|
||||||
SET SIO VERBOSE Print warning messages (useful for debugging)
|
|
||||||
The register SIOWL determines how often the same warning
|
|
||||||
is displayed. The default is 3.
|
|
||||||
|
|
||||||
You can also attach the SIO to a port:
|
|
||||||
|
|
||||||
ATTACH SIO 23 Console IO goes via a Telnet connection on port 23
|
|
||||||
DETACH SIO Console IO goes via the regular SIMH console
|
|
||||||
|
|
||||||
|
|
||||||
2.3 The SIMH pseudo device
|
|
||||||
|
|
||||||
The SIMH pseudo device facilitates the communication between the
|
|
||||||
simulated ALTAIR and the simulator environment. This device defines a
|
|
||||||
number of (most R/O) registers (see source code) which are primarily useful
|
|
||||||
for debugging purposes.
|
|
||||||
|
|
||||||
The SIMH pseudo device can be configured with
|
|
||||||
|
|
||||||
SET SIMH QUIET Do not print warning messages
|
|
||||||
SET SIMH VERBOSE Print warning messages (useful for debugging)
|
|
||||||
|
|
||||||
SET SIMH TIMERON Start periodic timer interrupts
|
|
||||||
SET SIMH TIMEROFF Stop the periodic timer interrupts
|
|
||||||
|
|
||||||
The following variables determine the behavior of the timer:
|
|
||||||
|
|
||||||
TIMD This is the delay between consecutive interrupts in milliseconds.
|
|
||||||
Use D TIMD 20 for a 50 Hz clock.
|
|
||||||
TIMH This is the address of the interrupt handler to call for a
|
|
||||||
timer interrupt.
|
|
||||||
|
|
||||||
|
|
||||||
2.4 The 88-DISK controller.
|
|
||||||
|
|
||||||
The MITS 88-DISK is a simple programmed I/O interface to the MITS 8-inch
|
|
||||||
floppy drive, which was basically a Pertec FD-400 with a power supply and
|
|
||||||
buffer board builtin. The controller supports neither interrupts nor DMA,
|
|
||||||
so floppy access required the sustained attention of the CPU. The standard
|
|
||||||
I/O addresses were 8, 9, and 0A (hex), and we follow the standard. Details
|
|
||||||
on controlling this hardware are in the altair_dsk.c source file.
|
|
||||||
|
|
||||||
The only difference is that the simulated disks may be larger than the
|
|
||||||
original ones: The original disk had 77 tracks while the simulated disks
|
|
||||||
support up to 254 tracks (only relevant for CP/M). You can change the
|
|
||||||
number of tracks per disk by setting the appropriate value in TRACKS[..].
|
|
||||||
For example "D TRACKS[0] 77" sets the number of tracks for disk 0 to the
|
|
||||||
original number of 77. The command "D TRACKS[0-7] 77" changes the highest
|
|
||||||
track number for all disks to 77.
|
|
||||||
|
|
||||||
For debugging purposes you can set the trace level of some disk I/O
|
|
||||||
functions. To do so the following bits in TRACE (a register of the disk)
|
|
||||||
have been defined with the following meaning:
|
|
||||||
|
|
||||||
1 Trace all IN and OUT instructions on the disk ports 8 and 9
|
|
||||||
2 Trace all read and writes to full sectors on the disk
|
|
||||||
4 Print a message whenever an unnecessary step-in or step out of the
|
|
||||||
disk head occurs (often an indication of an infinite loop)
|
|
||||||
8 Print a message whenever the disk head appears to be waiting for a
|
|
||||||
sector which does not show up (often an indication of an infinite
|
|
||||||
loop)
|
|
||||||
|
|
||||||
For example the command "D TRACE 10" will trace options 2+8 from above.
|
|
||||||
|
|
||||||
The DSK device can be configured with
|
|
||||||
|
|
||||||
SET DSK<n> QUIET Do not print warning messages for disk <n>
|
|
||||||
SET DSK<n> VERBOSE Print warning messages for disk <n>
|
|
||||||
(useful for debugging)
|
|
||||||
The register DSKWL determines how often the
|
|
||||||
same warning is displayed. The default is 3.
|
|
||||||
|
|
||||||
SET DSK<n> WRITEENABLED Allow write operations for disk <n>
|
|
||||||
SET DSK<n> LOCKED Disk <n> is locked, i.e. no write operations
|
|
||||||
will be allowed.
|
|
||||||
|
|
||||||
|
|
||||||
2.5 The simulated hard disk
|
|
||||||
|
|
||||||
In order to increase the available storage capacity, the simulator
|
|
||||||
features 8 simulated hard disks with a capacity of 8MB (HDSK0 to HDSK7).
|
|
||||||
Currently only CP/M supports two hard disks as devices I: and J:.
|
|
||||||
|
|
||||||
For debugging purposes one can set the trace flag by executing the
|
|
||||||
command "D HDTRACE 1". The default for "HDTRACE" is 0 (no trace).
|
|
||||||
|
|
||||||
The HDSK device can be configured with
|
|
||||||
|
|
||||||
SET HDSK<n> QUIET Do not print warning messages for hard disk <n>
|
|
||||||
SET HDSK<n> VERBOSE Print warning messages for hard disk <n>
|
|
||||||
(useful for debugging)
|
|
||||||
|
|
||||||
SET HDSK<n> WRITEENABLED Allow write operations for hard disk <n>
|
|
||||||
SET HDSK<n> LOCKED Hard disk <n> is locked, i.e. no
|
|
||||||
write operations will be allowed.
|
|
||||||
|
|
||||||
|
|
||||||
3. Sample Software
|
|
||||||
|
|
||||||
Running an Altair in 1977 you would be running either MITS Disk Extended
|
|
||||||
BASIC, or the brand new and sexy CP/M Operating System from Digital
|
|
||||||
Research. Or possibly, you ordered Altair DOS back when it was promised in
|
|
||||||
1975, and are still waiting for it to be delivered in early 1977.
|
|
||||||
|
|
||||||
We have samples of all three for you to check out. We can't go into the
|
|
||||||
details of how they work, but we'll give you a few hints.
|
|
||||||
|
|
||||||
|
|
||||||
3.1 CP/M Version 2.2
|
|
||||||
|
|
||||||
This version is my own port of the standard CP/M to the Altair. There
|
|
||||||
were some "official" versions but I don't have them. None were endorsed or
|
|
||||||
sold by MITS to my knowledge, however.
|
|
||||||
|
|
||||||
To boot CP/M:
|
|
||||||
|
|
||||||
sim> attach dsk cpm2.dsk
|
|
||||||
sim> boot dsk
|
|
||||||
|
|
||||||
CP/M feels like DOS, sort of. DIR will work. I have included all the
|
|
||||||
standard CP/M utilities, plus a few common public-domain ones. I also
|
|
||||||
include the sources to the customized BIOS and some other small programs.
|
|
||||||
TYPE will print an ASCII file. DUMP will dump a binary one. LS is a
|
|
||||||
better DIR than DIR. ASM will assemble .ASM files to Hex, LOAD will "load"
|
|
||||||
them to binary format (.COM). ED is a simple editor, #A command will bring
|
|
||||||
the source file to the buffer, T command will "type" lines, L will move
|
|
||||||
lines, E exits the editor. 20L20T will move down 20 lines, and type 20.
|
|
||||||
Very DECish. DDT is the debugger, DO is a batch-type command processor. A
|
|
||||||
sample batch file that will assemble and write out the bootable CP/M image
|
|
||||||
(on drive A) is "SYSCPM2.SUB". To run it, type "DO SYSCPM2".
|
|
||||||
|
|
||||||
In order to efficiently transfer files into the CP/M environment use the
|
|
||||||
included program R <filename.ext>. If you have a file named foo.ext in the
|
|
||||||
current directory (i.e. the directory where SIMH is), executing R FOO.EXT
|
|
||||||
under CP/M will transfer the file onto the CP/M disk. Transferring a file
|
|
||||||
from the CP/M environment to the SIMH environment is accomplished by
|
|
||||||
W <filename.ext> for text files or by W <filename.ext> B for binary files.
|
|
||||||
The simplest way for transferring multiple files is to create a ".SUB"
|
|
||||||
batch file which contains the necessary R resp. W commands.
|
|
||||||
|
|
||||||
If you need more storage space you can use a simulated hard disk on
|
|
||||||
drives I: and J:. To use do "attach HDSK0 hdi.dsk" and issue the
|
|
||||||
"XFORMAT I:" resp. "XFORMAT J:" command from CP/M do initialize the disk
|
|
||||||
to an empty state.
|
|
||||||
|
|
||||||
The disk "cpm2.dsk" contains the following files:
|
|
||||||
Name Ext Size Comment
|
|
||||||
ASM .COM 8K ; CP/M assembler
|
|
||||||
BDOS .MAC 68K ; Basic Disk Operating System assembler source code
|
|
||||||
BOOT .COM 1K ; transfer control to boot ROM
|
|
||||||
BOOT .MAC 2K ; source for BOOT.COM
|
|
||||||
BOOTGEN .COM 2K ; put a program on the boot sectors
|
|
||||||
CBIOSX .MAC 48K ; CP/M 2 BIOS source for Altair
|
|
||||||
CCP .MAC 26K ; Console Command Processor assembler source code
|
|
||||||
COPY .COM 2K ; copy disks
|
|
||||||
CPMBOOT .COM 12K ; CP/M operating system
|
|
||||||
CPU .COM 2K ; get and set the CPU type (8080 or Z80)
|
|
||||||
CPU .MAC 2K ; source for CPU.COM
|
|
||||||
CREF80 .COM 4K ; cross reference utility
|
|
||||||
DDT .COM 6K ; 8080 debugger
|
|
||||||
DDTZ .COM 10K ; Z80 debugger
|
|
||||||
DIF .COM 4K ; determine differences between two files
|
|
||||||
DO .COM 2K ; batch processing
|
|
||||||
DSKBOOT .MAC 8K ; source for boot ROM
|
|
||||||
DUMP .COM 2K ; hex dump a file
|
|
||||||
ED .COM 8K ; line editor
|
|
||||||
ELIZA .BAS 10K ; Eliza game in Basic
|
|
||||||
EX8080 .COM 12K ; exercise 8080 instruction set
|
|
||||||
EXZ80N .COM 12K ; exercise Z80 instruction set, No undefined status bits
|
|
||||||
EXZ80U .COM 12K ; exercise Z80 instruction set, Undefined status bits
|
|
||||||
EXZ80 .MAC 54K ; source for EX8080.COM, EXZ80N.COM, EXZ80U.COM
|
|
||||||
EX .SUB 2K ; benchmark execution of EX8080.COM, EXZ80N.COM, EXZ80U.COM
|
|
||||||
FORMAT .COM 2K ; format disks
|
|
||||||
GO .COM 0K ; start the currently loaded program at 100H
|
|
||||||
HDSKBOOT.MAC 6K ; boot code for hard disk
|
|
||||||
L80 .COM 12K ; Microsoft linker
|
|
||||||
LADDER .COM 40K ; game
|
|
||||||
LADDER .DAT 2K ; high score file for LADDER.COM
|
|
||||||
LIB80 .COM 6K ; library utility
|
|
||||||
LOAD .COM 2K ; load hex files
|
|
||||||
LS .COM 4K ; directory utility
|
|
||||||
LU .COM 20K ; library utility
|
|
||||||
M80 .COM 20K ; Microsoft macro assembler
|
|
||||||
MBASIC .COM 24K ; Microsoft Basic interpreter
|
|
||||||
MC .SUB 2K ; assemble and link an assembler program
|
|
||||||
MCC .SUB 2K ; read, assemble and link an assembler program
|
|
||||||
MCCL .SUB 2K ; assemble, link and produce listing
|
|
||||||
MEMCFG .LIB 2K ; defines the memory configuration
|
|
||||||
MOVER .MAC 2K ; moves operating system in place
|
|
||||||
OTHELLO .COM 12K ; Othello (Reversi) game
|
|
||||||
PIP .COM 8K ; Peripheral Interchange Program
|
|
||||||
PRELIM .COM 2K ; preliminary CPU tests
|
|
||||||
PRELIM .MAC 6K ; source code for PRELIM.COM
|
|
||||||
R .COM 4K ; read files from SIMH environment
|
|
||||||
RSETSIMH.COM 2K ; reset SIMH interface
|
|
||||||
RSETSIMH.MAC 2K ; assembler source for RSETSIMH.COM
|
|
||||||
SHOWSEC .COM 3K ; show sectors on a disk
|
|
||||||
SID .COM 8K ; debugger for 8080
|
|
||||||
SPEED .COM 2K ; utility to measure the clock speed of the simulated CPU
|
|
||||||
STAT .COM 6K ; provide information about currently logged disks
|
|
||||||
SURVEY .COM 2K ; system survey
|
|
||||||
SURVEY .MAC 16K ; assembler source for SURVEY.COM
|
|
||||||
SYSCOPY .COM 2K ; copy system tracks between disks
|
|
||||||
SYSCPM2 .SUB 2K ; create CP/M 2 on drive A:
|
|
||||||
TIMER .COM 2K ; perform various timer operations
|
|
||||||
TIMER .MAC 2K ; source code for TIMER.COM
|
|
||||||
UNCR .COM 8K ; un-crunch utility
|
|
||||||
UNERA .COM 2K ; un-erase a file
|
|
||||||
UNERA .MAC 16K ; source for UNERA.COM
|
|
||||||
USQ .COM 2K ; un-squeeze utility
|
|
||||||
W .COM 4K ; write files to SIMH environment
|
|
||||||
WM .COM 12K ; word master screen editor
|
|
||||||
WM .HLP 3K ; help file for WM.COM
|
|
||||||
WORM .COM 4K ; worm game for VT100 terminal
|
|
||||||
XFORMAT .COM 2K ; initialise a drive (floppy or hard disk)
|
|
||||||
XSUB .COM 2K ; support for DO.COM
|
|
||||||
ZAP .COM 10K ; SuperZap 5.2 disk editor configured for VT100
|
|
||||||
ZSID .COM 10K ; debugger for Z80
|
|
||||||
ZTRAN4 .COM 4K ; translate 8080 mnemonics into Z80 equivalents
|
|
||||||
|
|
||||||
|
|
||||||
3.2 CP/M Version 3 with banked memory
|
|
||||||
|
|
||||||
CP/M 3 is the successor to CP/M 2.2. A customised BIOS (BIOS3.MAC) is
|
|
||||||
included to facilitate modification if so desired. The defaults supplied in
|
|
||||||
GENCPM.DAT for system generation can be used. BOOTGEN.COM is used to place
|
|
||||||
the CP/M loader (LDR.COM) on the boot tracks of a disk.
|
|
||||||
|
|
||||||
Running CP/M 3 with banked memory:
|
|
||||||
sim> attach dsk cpm3.dsk
|
|
||||||
sim> reset cpu
|
|
||||||
sim> set cpu banked
|
|
||||||
sim> set cpu itrap
|
|
||||||
sim> boot dsk
|
|
||||||
|
|
||||||
Executing "DO SYSCPM3" will re-generate the banked version of CP/M 3. You
|
|
||||||
can boot CP/M 3 with or without a Z80 CPU. The Z80 CPU is needed for both
|
|
||||||
sysgens due to the use of BOOTGEN.COM which requires it.
|
|
||||||
|
|
||||||
The disk "cpm3.dsk" contains the following files:
|
|
||||||
ASM .COM 8K ; CP/M assembler
|
|
||||||
ASSIGN .SYS 2K
|
|
||||||
BDOS3 .SPR 10K
|
|
||||||
BIOS3 .MAC 28K ; CP/M 3 BIOS source for Altair SIMH
|
|
||||||
BIOS3 .SPR 4K
|
|
||||||
BNKBDOS3.SPR 14K
|
|
||||||
BNKBIOS3.SPR 4K
|
|
||||||
BOOT .COM 2K ; transfer control to boot ROM
|
|
||||||
BOOTGEN .COM 2K ; put a program on the boot sectors
|
|
||||||
CCP .COM 4K
|
|
||||||
COPYSYS .COM 2K
|
|
||||||
CPM3 .SYS 18K
|
|
||||||
CPMLDR .MAC 38K ; CP/M 3 loader assembler source
|
|
||||||
DATE .COM 4K ; date utility
|
|
||||||
DDT .COM 6K ; 8080 debugger
|
|
||||||
DDTZ .COM 10K ; Z80 debugger
|
|
||||||
DEFS .LIB 2K ; include file for BIOS3.MAC to create banked CP/M 3
|
|
||||||
DEVICE .COM 8K
|
|
||||||
DIF .COM 4K ; determine differences between two files
|
|
||||||
DIR .COM 16K ; directory utility
|
|
||||||
DO .COM 6K ; batch processing
|
|
||||||
DUMP .COM 2K
|
|
||||||
ED .COM 10K
|
|
||||||
ERASE .COM 4K
|
|
||||||
GENCOM .COM 16K
|
|
||||||
GENCPM .COM 22K
|
|
||||||
GENCPM .DAT 4K ; CP/M generation information for banked version
|
|
||||||
GENCPMNB.DAT 4K ; CP/M generation information for non-banked version
|
|
||||||
GET .COM 8K
|
|
||||||
HELP .COM 8K ; help utility
|
|
||||||
HELP .HLP 62K ; help files
|
|
||||||
HEXCOM .CPM 2K
|
|
||||||
HIST .UTL 2K
|
|
||||||
INITDIR .COM 32K
|
|
||||||
L80 .COM 12K ; Microsoft linker
|
|
||||||
LDR .COM 4K ; CP/M loader with optimised loader BIOS
|
|
||||||
LDRBIOS3.MAC 14K ; optimised (for space) loader BIOS
|
|
||||||
LIB .COM 8K ; Digital Research librarian
|
|
||||||
LINK .COM 16K ; Digital Research linker
|
|
||||||
LOAD .COM 2K
|
|
||||||
M80 .COM 20K ; Microsoft macro assembler
|
|
||||||
MC .SUB 2K ; assemble and link an assmbler program
|
|
||||||
MCC .SUB 2K ; read, assemble and link an assembler program
|
|
||||||
PATCH .COM 4K
|
|
||||||
PIP .COM 10K ; Peripheral Interchange Program
|
|
||||||
PROFILE .SUB 2K ; commands to be executed at start up
|
|
||||||
PUT .COM 8K
|
|
||||||
R .COM 4K ; read files from SIMH environment
|
|
||||||
RENAME .COM 4K
|
|
||||||
RESBDOS3.SPR 2K
|
|
||||||
RMAC .COM 14K ; Digital Research macro assembler
|
|
||||||
RSETSIMH.COM 2K ; reset SIMH interface
|
|
||||||
SAVE .COM 2K
|
|
||||||
SCB .MAC 2K
|
|
||||||
SET .COM 12K
|
|
||||||
SETDEF .COM 6K
|
|
||||||
SHOW .COM 10K
|
|
||||||
SHOWSEC .COM 4K ; show sectors on a disk
|
|
||||||
SID .COM 8K ; 8080 debugger
|
|
||||||
SYSCOPY .COM 2K ; copy system tracks between disks
|
|
||||||
SYSCPM3 .SUB 2K ; create banked CP/M 3 system
|
|
||||||
TRACE .UTL 2K
|
|
||||||
TSHOW .COM 2K ; show split time
|
|
||||||
TSTART .COM 2K ; create timer and start it
|
|
||||||
TSTOP .COM 2K ; show final time and stop timer
|
|
||||||
TYPE .COM 4K
|
|
||||||
UNERA .COM 2K ; un-erase a file
|
|
||||||
W .COM 4K ; write files to SIMH environment
|
|
||||||
XREF .COM 16K ; cross reference utility
|
|
||||||
ZSID .COM 10K ; Z80 debugger
|
|
||||||
|
|
||||||
|
|
||||||
3.3 MP/M II with banked memory
|
|
||||||
|
|
||||||
MP/M II is an acronym for MultiProgramming Monitor Control Program for
|
|
||||||
Microprocessors. It is a multiuser operating system for an eight bit
|
|
||||||
microcomputer. MP/M II supports multiprogramming at each terminal. This
|
|
||||||
version supports four terminals available via Telnet. To boot:
|
|
||||||
|
|
||||||
sim> attach dsk mpm.dsk
|
|
||||||
sim> set cpu itrap
|
|
||||||
sim> set cpu z80
|
|
||||||
sim> set cpu rom
|
|
||||||
sim> set cpu banked
|
|
||||||
sim> attach sio 23
|
|
||||||
sim> d common b000
|
|
||||||
sim> boot dsk
|
|
||||||
|
|
||||||
Now connect a Telnet session to the simulator and type "MPM" at the "A>"
|
|
||||||
prompt. Now you can connect up to three additional terminals via Telnet to
|
|
||||||
the Altair running MP/M II. To re-generate the system perform "DO SYSMPM"
|
|
||||||
in the CP/M environment (not possible under MP/M since XSUB is needed).
|
|
||||||
|
|
||||||
The disk "mpm.dsk" contains the following files:
|
|
||||||
Name Ext Size Comment
|
|
||||||
ABORT .PRL 2K ; abort a process
|
|
||||||
ABORT .RSP 2K
|
|
||||||
ASM .PRL 10K ; MP/M assembler
|
|
||||||
BNKBDOS .SPR 12K ; banked BDOS
|
|
||||||
BNKXDOS .SPR 2K ; banked XDOS
|
|
||||||
BNKXIOS .SPR 4K ; banked XIOS
|
|
||||||
BOOTGEN .COM 2K ; copy an executable to the boot section
|
|
||||||
CONSOLE .PRL 2K ; print console number
|
|
||||||
CPM .COM 2K ; return to CP/M
|
|
||||||
CPM .MAC 2K ; source for CPM.COM
|
|
||||||
DDT .COM 6K ; MP/M DDT
|
|
||||||
DDT2 .COM 6K ; CP/M DDT
|
|
||||||
DDTZ .COM 10K ; CP/M DDT with Z80 support
|
|
||||||
DIF .COM 4K ; difference between two files
|
|
||||||
DIR .PRL 2K ; directory command
|
|
||||||
DO .COM 2K ; CP/M submit
|
|
||||||
DSKRESET.PRL 2K ; disk reset command
|
|
||||||
DUMP .MAC 6K ; source for DUMP.PRL
|
|
||||||
DUMP .PRL 2K ; dump command
|
|
||||||
ED .PRL 10K ; MP/M line editor
|
|
||||||
ERA .PRL 2K ; erase command
|
|
||||||
ERAQ .PRL 4K ; erase comand (verbose)
|
|
||||||
GENHEX .COM 2K
|
|
||||||
GENMOD .COM 2K
|
|
||||||
GENSYS .COM 10K
|
|
||||||
L80 .COM 12K ; Microsoft linker
|
|
||||||
LDRBIOS .MAC 14K ; loader BIOS
|
|
||||||
LIB .COM 8K ; library utility
|
|
||||||
LINK .COM 16K ; linker
|
|
||||||
LOAD .COM 2K ; loader
|
|
||||||
M80 .COM 20K ; Microsoft macro assembler
|
|
||||||
MC .SUB 2K ; assemble and link an assmbler program
|
|
||||||
MCC .SUB 2K ; read, assemble and link an assembler program
|
|
||||||
MPM .COM 8K ; start MP/M II
|
|
||||||
MPM .SYS 26K ; MP/M system file
|
|
||||||
MPMD .LIB 2K ; define a banked system
|
|
||||||
MPMLDR .COM 6K ; MP/M loader without LDRBIOS
|
|
||||||
MPMSTAT .BRS 6K ; status of MP/M system
|
|
||||||
MPMSTAT .PRL 6K
|
|
||||||
MPMSTAT .RSP 2K
|
|
||||||
MPMXIOS .MAC 26K ; XIOS for MP/M
|
|
||||||
PIP .PRL 10K ; MP/M peripheral interchange program
|
|
||||||
PIP2 .COM 8K ; CP/M peripheral interchange program
|
|
||||||
PRINTER .PRL 2K
|
|
||||||
PRLCOM .PRL 4K
|
|
||||||
R .COM 4K ; read a file from the SIMH environment
|
|
||||||
RDT .PRL 8K ; debugger for page relocatable programs
|
|
||||||
REN .PRL 4K ; rename a file
|
|
||||||
RESBDOS .SPR 4K ; non-banked BDOS
|
|
||||||
RMAC .COM 14K ; Digital Research macro assembler
|
|
||||||
RSETSIMH.COM 2K ; reset SIMH interface
|
|
||||||
SCHED .BRS 2K ; schedule a job
|
|
||||||
SCHED .PRL 4K
|
|
||||||
SCHED .RSP 2K
|
|
||||||
SDIR .PRL 18K ; fancy directory command
|
|
||||||
SET .PRL 8K ; set parameters
|
|
||||||
SHOW .PRL 8K ; show status of disks
|
|
||||||
SPOOL .BRS 4K ; spool utility
|
|
||||||
SPOOL .PRL 4K
|
|
||||||
SPOOL .RSP 2K
|
|
||||||
STAT .COM 6K ; CP/M stat command
|
|
||||||
STAT .PRL 10K ; MP/M stat command
|
|
||||||
STOPSPLR.PRL 2K ; stop spooler
|
|
||||||
SUBMIT .PRL 6K ; MP/M submit
|
|
||||||
SYSCOPY .COM 2K ; copy system tracks
|
|
||||||
SYSMPM .SUB 2K ; do a system generation
|
|
||||||
SYSTEM .DAT 2K ; default values for system generation
|
|
||||||
TMP .SPR 2K
|
|
||||||
TOD .PRL 4K ; time of day
|
|
||||||
TSHOW .COM 2K ; show split time
|
|
||||||
TSTART .COM 2K ; create timer and start it
|
|
||||||
TSTOP .COM 2K ; show final time and stop timer
|
|
||||||
TYPE .PRL 2K ; type a file on the screen
|
|
||||||
USER .PRL 2K ; set user area
|
|
||||||
W .COM 4K ; write a file to SIMH environment
|
|
||||||
XDOS .SPR 10K ; XDOS
|
|
||||||
XREF .COM 16K ; cross reference utility
|
|
||||||
XSUB .COM 2K ; for CP/M DO
|
|
||||||
|
|
||||||
|
|
||||||
3.4 CP/M application software
|
|
||||||
|
|
||||||
There is also a small collection of sample application software
|
|
||||||
containing the following items:
|
|
||||||
|
|
||||||
- SPL: a Small Programming Language with a suite of sample programs
|
|
||||||
- PROLOGZ: a Prolog interpreter written in SPL with sources
|
|
||||||
- PASCFORM: a Pascal pretty printer written in Pascal
|
|
||||||
- Pascal MT+: Pascal language system needed to compile PASCFORM
|
|
||||||
|
|
||||||
The sample software comes on "app.dsk" and to use it do
|
|
||||||
|
|
||||||
sim> attach dsk1 app.dsk
|
|
||||||
|
|
||||||
before booting CP/M.
|
|
||||||
|
|
||||||
The disk "app.dsk" contains the following files:
|
|
||||||
Name Ext Size Comment
|
|
||||||
BOOTGEN .COM 2K
|
|
||||||
BOOTGEN .SPL 6K ; SPL source for BOOTGEN.COM
|
|
||||||
C .SUB 2K ; batch file for compiling an SPL source file
|
|
||||||
CALC .PRO 4K ; Prolog demo program: Calculator
|
|
||||||
CC .SUB 2K ; compile an SPL source which is on the underlying
|
|
||||||
file system
|
|
||||||
DECLARAT. 12K ; common include file, SPL source
|
|
||||||
DIF .COM 4K
|
|
||||||
DIF .SPL 10K ; SPL source for DIF.COM
|
|
||||||
EDIT .SPL 10K ; screen editor for PROLOGZ, SPL source
|
|
||||||
FAMILY .PRO 4K ; Prolog demo program: Family relations
|
|
||||||
INTEGER .PRO 2K ; Prolog demo program: Integer arithmetic
|
|
||||||
KNAKE .PRO 2K ; Prolog demo program: Logic puzzle
|
|
||||||
LINKMT .COM 12K ; Pascal MT+ 5.5 linker
|
|
||||||
MAIN .SPL 14K ; main module for PROLOGZ, SPL source
|
|
||||||
MOVE .MAC 4K ; helper functions for PROLOGZ in assembler
|
|
||||||
MTERRS .TXT 6K ; Pascal MT+ error messages
|
|
||||||
MTPLUS .000 14K ; Pascal MT+ 5.5 compiler file
|
|
||||||
MTPLUS .001 12K ; Pascal MT+ 5.5 compiler file
|
|
||||||
MTPLUS .002 8K ; Pascal MT+ 5.5 compiler file
|
|
||||||
MTPLUS .003 8K ; Pascal MT+ 5.5 compiler file
|
|
||||||
MTPLUS .004 18K ; Pascal MT+ 5.5 compiler file
|
|
||||||
MTPLUS .005 8K ; Pascal MT+ 5.5 compiler file
|
|
||||||
MTPLUS .006 6K ; Pascal MT+ 5.5 compiler file
|
|
||||||
MTPLUS .COM 36K ; Pascal MT+ 5.5 compiler
|
|
||||||
PASCFORM.COM 36K ; Pascal formatter
|
|
||||||
PASCFORM.PAS 54K ; Pascal formatter source code
|
|
||||||
PASCFORM.SUB 2K ; create Pascal formatter
|
|
||||||
PASLIB .ERL 24K ; Pascal MT+ 5.5 run time library
|
|
||||||
PINST .COM 4K ; terminal installation program for PROLOGZ
|
|
||||||
PINST .SPL 16K ; terminal installation program for PROLOGZ,
|
|
||||||
SPL source
|
|
||||||
PROLOGZ .COM 18K ; PROLOGZ interpreter and screen editor
|
|
||||||
PROLOGZ .SPL 2K ; PROLOGZ main program, SPL source
|
|
||||||
PROLOGZ .TXT 40K ; PROLOGZ documentation in German
|
|
||||||
PROVE .SPL 16K ; backtrack theorem prover for PROLOGZ, SPL source
|
|
||||||
PZCLEAN .SUB 2K ; PROLOGZ: remove all created ".rel" and ".lst" files
|
|
||||||
PZLINK .SUB 2K ; PROLOGZ: create PINST, PROLOGZ and personalise the
|
|
||||||
serial number
|
|
||||||
PZMAKE .SUB 2K ; PROLOGZ: compiles the sources (you can ignore
|
|
||||||
any compiler errors)
|
|
||||||
QUEEN .PRO 2K ; Prolog demo program: N-queens problem
|
|
||||||
READ .COM 4K
|
|
||||||
READ .SPL 10K ; SPL source for R.COM
|
|
||||||
SHOWSEC .COM 4K
|
|
||||||
SHOWSEC .SPL 6K ; SPL source for SHOWSEC.COM
|
|
||||||
SPEED .COM 2K ; utility to measure the clock speed of the simulated CPU
|
|
||||||
SPEED .SPL 2K ; SPL source for SPEED.COM, requires SWLIB.MAC
|
|
||||||
SPL .COM 38K ; the SPL compiler itself
|
|
||||||
SPL .TXT 56K ; SPL language and compiler documentation in German
|
|
||||||
SPLERROR.DAT 12K ; error messages of the compiler (in German)
|
|
||||||
SPLIB .REL 6K ; SPL runtime library
|
|
||||||
STDIO . 2K ; include file for SPL programs
|
|
||||||
SWLIB .MAC 2K ; assembler utility routines needed by SPEED.SPL
|
|
||||||
SYSCOPY .COM 2K
|
|
||||||
SYSCOPY .SPL 6K ; SPL source for SYSCOPY.COM
|
|
||||||
TERMBDOS.SPL 2K ; terminal interface to CP/M for PROLOGZ, SPL source
|
|
||||||
UTIL .SPL 18K ; utility functions for PROLOGZ, SPL source
|
|
||||||
WRITE .COM 4K
|
|
||||||
WRITE .SPL 8K ; SPL source for W.COM
|
|
||||||
XFORMAT .COM 2K
|
|
||||||
XFORMAT .SPL 6K ; SPL source for XFORMAT.COM
|
|
||||||
|
|
||||||
|
|
||||||
3.5 MITS Disk Extended BASIC Version 4.1
|
|
||||||
|
|
||||||
This was the commonly used software for serious users of the Altair
|
|
||||||
computer. It is a powerful (but slow) BASIC with some extended commands to
|
|
||||||
allow it to access and manage the disk. There was no operating system it
|
|
||||||
ran under. To boot:
|
|
||||||
|
|
||||||
sim> set cpu 8080 ;Z80 will not work
|
|
||||||
sim> attach dsk mbasic.dsk
|
|
||||||
sim> set sio upper
|
|
||||||
sim> go ff00
|
|
||||||
|
|
||||||
MEMORY SIZE? [return]
|
|
||||||
LINEPRINTER? [C return]
|
|
||||||
HIGHEST DISK NUMBER? [0 return] (0 here = 1 drive system)
|
|
||||||
NUMBER OF FILES? [3 return]
|
|
||||||
NUMBER OF RANDOM FILES? [2 return]
|
|
||||||
|
|
||||||
44041 BYTES FREE
|
|
||||||
ALTAIR BASIC REV. 4.1
|
|
||||||
[DISK EXTENDED VERSION]
|
|
||||||
COPYRIGHT 1977 BY MITS INC.
|
|
||||||
OK
|
|
||||||
[MOUNT 0]
|
|
||||||
OK
|
|
||||||
[FILES]
|
|
||||||
|
|
||||||
|
|
||||||
3.6 Altair DOS Version 1.0
|
|
||||||
|
|
||||||
This was long promised but not delivered until it was almost irrelevant.
|
|
||||||
A short attempted tour will reveal it to be a dog, far inferior to CP/M. To
|
|
||||||
boot:
|
|
||||||
|
|
||||||
sim> d tracks[0-7] 77 ;set to Altair settings
|
|
||||||
sim> set cpu altairrom
|
|
||||||
sim> attach dsk altdos.dsk
|
|
||||||
sim> set sio upper
|
|
||||||
sim> go ff00
|
|
||||||
|
|
||||||
MEMORY SIZE? [return]
|
|
||||||
INTERRUPTS? N [return]
|
|
||||||
HIGHEST DISK NUMBER? [0 return] (3 here = 4 drive system)
|
|
||||||
HOW MANY DISK FILES? [3 return]
|
|
||||||
HOW MANY RANDOM FILES? [2 return]
|
|
||||||
|
|
||||||
056449 BYTES AVAILABLE
|
|
||||||
DOS MONITOR VER 1.0
|
|
||||||
COPYRIGHT 1977 BY MITS INC
|
|
||||||
.[MNT 0]
|
|
||||||
|
|
||||||
.[DIR 0]
|
|
||||||
|
|
||||||
|
|
||||||
3.7 Altair Basic 3.2 (4k)
|
|
||||||
|
|
||||||
In order to run the famous 4k Basic, use the following commands (the
|
|
||||||
trick is to get the Switch Register right).
|
|
||||||
|
|
||||||
sim> set cpu 8080 ;note 4k Basic will not run on a Z80 CPU
|
|
||||||
sim> set sio upper ;4k Basic does not like lower case letters as input
|
|
||||||
sim> set sio ansi ;4k Basic produces 8-bit output, strip to seven bits
|
|
||||||
sim> d sr 8 ;good setting for the Switch Register
|
|
||||||
sim> load 4kbas.bin 0 ;load it at 0
|
|
||||||
sim> go 0 ;and start it
|
|
||||||
MEMORY SIZE? [return]
|
|
||||||
TERMINAL WIDTH? [return]
|
|
||||||
WANT SIN? [Y]
|
|
||||||
|
|
||||||
61911 BYTES FREE
|
|
||||||
|
|
||||||
BASIC VERSION 3.2
|
|
||||||
[4K VERSION]
|
|
||||||
|
|
||||||
OK
|
|
||||||
|
|
||||||
|
|
||||||
3.8 Altair 8k Basic
|
|
||||||
Running 8k Basic follows the procedure for 4k Basic.
|
|
||||||
|
|
||||||
sim> set cpu 8080 ;note 8k Basic will not run on a Z80 CPU
|
|
||||||
sim> set sio upper ;8k Basic does not like lower case letters as input
|
|
||||||
sim> set sio ansi ;8k Basic produces 8-bit output, strip to seven bits
|
|
||||||
sim> d sr 8 ;good setting for the Switch Register
|
|
||||||
sim> load 8kbas.bin 0 ;load it at 0
|
|
||||||
sim> go 0 ;and start it
|
|
||||||
MEMORY SIZE? [A]
|
|
||||||
|
|
||||||
WRITTEN FOR ROYALTIES BY MICRO-SOFT
|
|
||||||
|
|
||||||
MEMORY SIZE? [return]
|
|
||||||
TERMINAL WIDTH? [return]
|
|
||||||
WANT SIN-COS-TAN-ATN? [Y]
|
|
||||||
|
|
||||||
58756 BYTES FREE
|
|
||||||
ALTAIR BASIC REV. 4.0
|
|
||||||
[EIGHT-K VERSION]
|
|
||||||
COPYRIGHT 1976 BY MITS INC.
|
|
||||||
OK
|
|
||||||
|
|
||||||
|
|
||||||
3.9 Altair Basic 4.0
|
|
||||||
|
|
||||||
Execute the following commands to run Altair Extended Basic:
|
|
||||||
|
|
||||||
sim> set sio upper ;Extended Basic does not like lower case letters as input
|
|
||||||
sim> set sio ansi ;Extended Basic produces 8-bit output, strip to seven bits
|
|
||||||
sim> d sr 8 ;good setting for the Switch Register
|
|
||||||
sim> load exbas.bin 0 ;load it at 0
|
|
||||||
sim> go 0 ;and start it
|
|
||||||
16384 Bytes loaded at 0.
|
|
||||||
|
|
||||||
MEMORY SIZE? [return]
|
|
||||||
WANT SIN-COS-TAN-ATN? [Y]
|
|
||||||
|
|
||||||
50606 BYTES FREE
|
|
||||||
ALTAIR BASIC REV. 4.0
|
|
||||||
[EXTENDED VERSION]
|
|
||||||
COPYRIGHT 1977 BY MITS INC.
|
|
||||||
OK
|
|
||||||
|
|
||||||
|
|
||||||
3.10 Altair Disk Extended Basic Version 300-5-C
|
|
||||||
|
|
||||||
This version of Basic was provided by Scott LaBombard. To execute use the
|
|
||||||
following commands:
|
|
||||||
|
|
||||||
sim> d tracks[0-7] 77 ;set to Altair settings
|
|
||||||
sim> at dsk extbas5.dsk
|
|
||||||
sim> g 0
|
|
||||||
|
|
||||||
MEMORY SIZE? [return]
|
|
||||||
LINEPRINTER? [C]
|
|
||||||
HIGHEST DISK NUMBER? [0]
|
|
||||||
HOW MANY FILES? [3]
|
|
||||||
HOW MANY RANDOM FILES? [3]
|
|
||||||
|
|
||||||
42082 BYTES FREE
|
|
||||||
|
|
||||||
ALTAIR DISK EXTENDED BASIC
|
|
||||||
VERSION 300-5-C [01NOV78]
|
|
||||||
COPYRIGHT 1978 BY MITS INC.
|
|
||||||
|
|
||||||
OK
|
|
||||||
|
|
||||||
|
|
||||||
4. Special simulator features
|
|
||||||
|
|
||||||
|
|
||||||
4.1 Memory access breakpoints
|
|
||||||
|
|
||||||
In addition to the regular SIMH features such as PC queue, breakpoints
|
|
||||||
etc., this simulator supports memory access breakpoints. A memory access
|
|
||||||
breakpoint is triggered when a pre-defined memory location is accessed
|
|
||||||
(read, write or update). To set a memory location breakpoint enter
|
|
||||||
|
|
||||||
sim> break -m <location>
|
|
||||||
|
|
||||||
Execution will stop whenever an operation accesses <location>. Note that
|
|
||||||
a memory access breakpoint is not triggered by fetching code from memory
|
|
||||||
(this is the job of regular breakpoints). This feature has been implemented
|
|
||||||
by using the typing facility of the SIMH breakpoints.
|
|
||||||
|
|
||||||
|
|
||||||
4.2 T-state stepping
|
|
||||||
|
|
||||||
The SIMH step command supports the "-t" modifier to allow steppping for
|
|
||||||
a predefined number of t-states. For example
|
|
||||||
|
|
||||||
sim> step -t 1000
|
|
||||||
|
|
||||||
will cause the simulated CPU to execute 1000 t-states (note that the shortest
|
|
||||||
instruction will have 4 t-states). On the other hand, the command
|
|
||||||
|
|
||||||
sim> step 1000
|
|
||||||
|
|
||||||
will cause the simulated CPU to execute 1000 instructions.
|
|
||||||
|
|
||||||
|
|
||||||
5. Brief summary of all major changes to the original Altair simulator
|
|
||||||
- Full support for Z80. CP/M software requiring a Z80 CPU now runs
|
|
||||||
properly. DDTZ and PROLOGZ are included for demonstration purposes.
|
|
||||||
- Added banked memory support.
|
|
||||||
- PC queue implemented.
|
|
||||||
- Full assembler and dis-assembler support for Z80 and 8080 mnemonics.
|
|
||||||
Depending on the current setting of the CPU, the appropriate mnemonics
|
|
||||||
are used.
|
|
||||||
- The BOOT ROM was changed to fully load the software from disk. The
|
|
||||||
original code basically loaded a copy of itself from the disk and
|
|
||||||
executed it.
|
|
||||||
- ROM and memory size settings are now fully honored. This means that you
|
|
||||||
cannot write into the ROM or outside the defined RAM (e.g. when the RAM size
|
|
||||||
was truncated with the SET CPU commands). This feature allows programs which
|
|
||||||
check for the size of available RAM to run properly (e.g. 4k Basic). In
|
|
||||||
addition one can enable and disable the ROM which is useful in special cases
|
|
||||||
(e.g. when testing a new version of the ROM).
|
|
||||||
- The console can also be used via Telnet. This is useful when a terminal is
|
|
||||||
needed which supports cursor control such as a VT100. PROLOGZ for example
|
|
||||||
has a built-in screen editor which works under Telnet.
|
|
||||||
- Simplified file exchange for CP/M. Using the READ program under CP/M one
|
|
||||||
can easily import files into CP/M from the regular file system. Note that PIP
|
|
||||||
does not work properly on non-text files on PTR.
|
|
||||||
- The WRITE program can be used to transfer files from the CP/M environment to
|
|
||||||
the regular environment (binary or ASCII transfer).
|
|
||||||
- The last character read from PTR is always Control-Z (the EOF character for
|
|
||||||
CP/M). This makes sure that PIP (Peripheral Interchange Program on CP/M) will
|
|
||||||
terminate properly.
|
|
||||||
- Fixed a bug in the BIOS warm boot routine which caused CP/M to crash.
|
|
||||||
- Modified the BIOS for CP/M to support 8 disks.
|
|
||||||
- Added CP/M 3 banked version as sample software
|
|
||||||
- Changed from octal to hex
|
|
||||||
- Made the DSK and SIO device more robust (previously malicious code could
|
|
||||||
crash the simulator)
|
|
||||||
- Added memory access break points
|
|
||||||
- Added periodic timer interrupts (useful for MP/M)
|
|
||||||
- Added additional consoles (useful for MP/M)
|
|
||||||
- Added MP/M II banked version as sample software
|
|
|
@ -90,11 +90,30 @@ static uint16 IFF;
|
||||||
#define SetPV2(x) ((cpu_unit.flags & UNIT_CHIP) ? (((temp == (x)) << 2)) : (parity(temp)))
|
#define SetPV2(x) ((cpu_unit.flags & UNIT_CHIP) ? (((temp == (x)) << 2)) : (parity(temp)))
|
||||||
|
|
||||||
/* checkCPU8080 must be invoked whenever a Z80 only instruction is executed */
|
/* checkCPU8080 must be invoked whenever a Z80 only instruction is executed */
|
||||||
|
/*
|
||||||
#define checkCPU8080 \
|
#define checkCPU8080 \
|
||||||
if (((cpu_unit.flags & UNIT_CHIP) == 0) && (cpu_unit.flags & UNIT_OPSTOP)) {\
|
if (((cpu_unit.flags & UNIT_CHIP) == 0) && (cpu_unit.flags & UNIT_OPSTOP)) {\
|
||||||
reason = STOP_OPCODE; \
|
reason = STOP_OPCODE; \
|
||||||
goto end_decode; \
|
goto end_decode; \
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* checkCPU8080 must be invoked whenever a Z80 only instruction is executed
|
||||||
|
In case a Z80 instruction is executed on an 8080 the following two cases exist:
|
||||||
|
1) Trapping is enabled: execution stops
|
||||||
|
2) Trapping is not enabled: decoding continues with the next byte
|
||||||
|
*/
|
||||||
|
#define checkCPU8080 \
|
||||||
|
if ((cpu_unit.flags & UNIT_CHIP) == 0) { \
|
||||||
|
if (cpu_unit.flags & UNIT_OPSTOP) { \
|
||||||
|
reason = STOP_OPCODE; \
|
||||||
|
goto end_decode; \
|
||||||
|
} \
|
||||||
|
else { \
|
||||||
|
sim_brk_pend = FALSE; \
|
||||||
|
continue; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
/* checkCPUZ80 must be invoked whenever a non Z80 instruction is executed */
|
/* checkCPUZ80 must be invoked whenever a non Z80 instruction is executed */
|
||||||
#define checkCPUZ80 \
|
#define checkCPUZ80 \
|
||||||
|
|
|
@ -64,6 +64,8 @@
|
||||||
#define UNIT_BS (1 << UNIT_V_BS)
|
#define UNIT_BS (1 << UNIT_V_BS)
|
||||||
#define UNIT_V_SIO_VERBOSE (UNIT_V_UF + 3) /* verbose mode, i.e. show error messages */
|
#define UNIT_V_SIO_VERBOSE (UNIT_V_UF + 3) /* verbose mode, i.e. show error messages */
|
||||||
#define UNIT_SIO_VERBOSE (1 << UNIT_V_SIO_VERBOSE)
|
#define UNIT_SIO_VERBOSE (1 << UNIT_V_SIO_VERBOSE)
|
||||||
|
#define UNIT_V_MAP (UNIT_V_UF + 4) /* mapping mode on */
|
||||||
|
#define UNIT_MAP (1 << UNIT_V_MAP)
|
||||||
|
|
||||||
#define UNIT_V_SIMH_VERBOSE (UNIT_V_UF + 0) /* verbose mode for SIMH pseudo device */
|
#define UNIT_V_SIMH_VERBOSE (UNIT_V_UF + 0) /* verbose mode for SIMH pseudo device */
|
||||||
#define UNIT_SIMH_VERBOSE (1 << UNIT_V_SIMH_VERBOSE)
|
#define UNIT_SIMH_VERBOSE (1 << UNIT_V_SIMH_VERBOSE)
|
||||||
|
@ -187,7 +189,7 @@ static SIO_TERMINAL sio_terminals[Terminals] =
|
||||||
static TMLN TerminalLines[Terminals] = { {0} }; /* four terminals */
|
static TMLN TerminalLines[Terminals] = { {0} }; /* four terminals */
|
||||||
static TMXR altairTMXR = {Terminals, 0, 0, TerminalLines}; /* mux descriptor */
|
static TMXR altairTMXR = {Terminals, 0, 0, TerminalLines}; /* mux descriptor */
|
||||||
|
|
||||||
static UNIT sio_unit = { UDATA (&sio_svc, UNIT_ATTABLE, 0), KBD_POLL_WAIT };
|
static UNIT sio_unit = { UDATA (&sio_svc, UNIT_ATTABLE + UNIT_MAP, 0), KBD_POLL_WAIT };
|
||||||
|
|
||||||
static REG sio_reg[] = {
|
static REG sio_reg[] = {
|
||||||
{ HRDATA (DATA0, sio_terminals[0].data, 8) },
|
{ HRDATA (DATA0, sio_terminals[0].data, 8) },
|
||||||
|
@ -215,6 +217,8 @@ static MTAB sio_mod[] = {
|
||||||
{ UNIT_SIO_VERBOSE, 0, "QUIET", "QUIET", NULL }, /* quiet, no error messages */
|
{ UNIT_SIO_VERBOSE, 0, "QUIET", "QUIET", NULL }, /* quiet, no error messages */
|
||||||
{ UNIT_SIO_VERBOSE, UNIT_SIO_VERBOSE, "VERBOSE", "VERBOSE", &sio_set_verbose },
|
{ UNIT_SIO_VERBOSE, UNIT_SIO_VERBOSE, "VERBOSE", "VERBOSE", &sio_set_verbose },
|
||||||
/* verbose, display warning messages */
|
/* verbose, display warning messages */
|
||||||
|
{ UNIT_MAP, 0, "NOMAP", "NOMAP", NULL }, /* disable character mapping */
|
||||||
|
{ UNIT_MAP, UNIT_MAP, "MAP", "MAP", NULL }, /* enable all character mapping */
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
|
||||||
DEVICE sio_dev = {
|
DEVICE sio_dev = {
|
||||||
|
@ -491,6 +495,7 @@ int32 sio0d(const int32 port, const int32 io, const int32 data) {
|
||||||
sio_terminals[ti].data = tmxr_getc_ln(&TerminalLines[ti]) & 0xff;
|
sio_terminals[ti].data = tmxr_getc_ln(&TerminalLines[ti]) & 0xff;
|
||||||
}
|
}
|
||||||
sio_terminals[ti].status &= 0xfe;
|
sio_terminals[ti].status &= 0xfe;
|
||||||
|
if (sio_unit.flags & UNIT_MAP) {
|
||||||
if (sio_unit.flags & UNIT_BS) {
|
if (sio_unit.flags & UNIT_BS) {
|
||||||
if (sio_terminals[ti].data == BACKSPACE_CHAR) {
|
if (sio_terminals[ti].data == BACKSPACE_CHAR) {
|
||||||
sio_terminals[ti].data = DELETE_CHAR;
|
sio_terminals[ti].data = DELETE_CHAR;
|
||||||
|
@ -501,7 +506,9 @@ int32 sio0d(const int32 port, const int32 io, const int32 data) {
|
||||||
sio_terminals[ti].data = BACKSPACE_CHAR;
|
sio_terminals[ti].data = BACKSPACE_CHAR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (sio_unit.flags & UNIT_UPPER) ? toupper(sio_terminals[ti].data) : sio_terminals[ti].data;
|
}
|
||||||
|
return ((sio_unit.flags & UNIT_UPPER) && (sio_unit.flags & UNIT_MAP)) ?
|
||||||
|
toupper(sio_terminals[ti].data) : sio_terminals[ti].data;
|
||||||
}
|
}
|
||||||
else { /* OUT */
|
else { /* OUT */
|
||||||
int32 d = sio_unit.flags & UNIT_ANSI ? data & 0x7f : data;
|
int32 d = sio_unit.flags & UNIT_ANSI ? data & 0x7f : data;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
To: Users
|
To: Users
|
||||||
From: Peter Schorn
|
From: Peter Schorn
|
||||||
Subj: AltairZ80 Simulator Usage
|
Subj: AltairZ80 Simulator Usage
|
||||||
Date: 15-Feb-2004
|
Date: 12-Apr-2004
|
||||||
|
|
||||||
COPYRIGHT NOTICE
|
COPYRIGHT NOTICE
|
||||||
|
|
||||||
|
@ -61,6 +61,7 @@ sim/AltairZ80/altairz80_defs.h
|
||||||
|
|
||||||
2. Revision History
|
2. Revision History
|
||||||
|
|
||||||
|
- 12-Apr-2004, Peter Schorn (added MAP/NOMAP capability to switch off key mapping)
|
||||||
- 26-Jan-2004, Peter Schorn (added support for t-state stepping)
|
- 26-Jan-2004, Peter Schorn (added support for t-state stepping)
|
||||||
- 25-Feb-2003, Peter Schorn (added support for real time simulation)
|
- 25-Feb-2003, Peter Schorn (added support for real time simulation)
|
||||||
- 9-Oct-2002, Peter Schorn (added support for simulated hard disk)
|
- 9-Oct-2002, Peter Schorn (added support for simulated hard disk)
|
||||||
|
@ -132,7 +133,9 @@ the MITS Disk Basic and Altair DOS require about a minimum of 24K.
|
||||||
SET CPU ITRAP Causes the simulator to halt if an invalid opcode
|
SET CPU ITRAP Causes the simulator to halt if an invalid opcode
|
||||||
is detected (depending on the chosen CPU).
|
is detected (depending on the chosen CPU).
|
||||||
SET CPU NOITRAP Does not stop on an invalid Opcode. This is
|
SET CPU NOITRAP Does not stop on an invalid Opcode. This is
|
||||||
how the real 8080 works.
|
how the real 8080 works. Note that some software such as 4K Basic
|
||||||
|
apparently tries to execute nonexistent 8080 instructions. Therefore
|
||||||
|
it is advisable in this case to SET CPU NOITRAP.
|
||||||
|
|
||||||
SET CPU 4K
|
SET CPU 4K
|
||||||
SET CPU 8K
|
SET CPU 8K
|
||||||
|
@ -248,18 +251,29 @@ a simple stream of 8-bit bytes.
|
||||||
SET SIO TTY Bit 8 is set to zero on console output
|
SET SIO TTY Bit 8 is set to zero on console output
|
||||||
SET SIO ANSI Bit 8 is not touched on console output
|
SET SIO ANSI Bit 8 is not touched on console output
|
||||||
|
|
||||||
SET SIO ALL Console input support lower- and upper case
|
SET SIO ALL Console input remain unchanged
|
||||||
SET SIO UPPER Console input is transformed to upper case characters only
|
SET SIO UPPER Console input is transformed to upper case characters only
|
||||||
(This feature is useful for most Altair software)
|
(This feature is useful for most Altair software)
|
||||||
|
SET SIO MAP must also have been executed for this
|
||||||
|
option to take effect - otherwise no mapping occurs.
|
||||||
|
|
||||||
SET SIO BS Map the delete character to backspace
|
SET SIO BS Map the delete character to backspace
|
||||||
|
SET SIO MAP must also have been executed for this
|
||||||
|
option to take effect - otherwise no mapping occurs.
|
||||||
SET SIO DEL Map the backspace character to delete
|
SET SIO DEL Map the backspace character to delete
|
||||||
|
SET SIO MAP must also have been executed for this
|
||||||
|
option to take effect - otherwise no mapping occurs.
|
||||||
|
|
||||||
SET SIO QUIET Do not print warning messages
|
SET SIO QUIET Do not print warning messages
|
||||||
SET SIO VERBOSE Print warning messages (useful for debugging)
|
SET SIO VERBOSE Print warning messages (useful for debugging)
|
||||||
The register SIOWL determines how often the same warning
|
The register SIOWL determines how often the same warning
|
||||||
is displayed. The default is 3.
|
is displayed. The default is 3.
|
||||||
|
|
||||||
|
SET SIO MAP Enable mapping of characters
|
||||||
|
(see also SET SIO ALL/UPPER/BS/DEL)
|
||||||
|
SET SIO NOMAP Disable mapping of characters
|
||||||
|
(see also SET SIO ALL/UPPER/BS/DEL)
|
||||||
|
|
||||||
You can also attach the SIO to a port:
|
You can also attach the SIO to a port:
|
||||||
|
|
||||||
ATTACH SIO 23 Console IO goes via a Telnet connection on port 23
|
ATTACH SIO 23 Console IO goes via a Telnet connection on port 23
|
||||||
|
@ -814,6 +828,7 @@ trick is to get the Switch Register right).
|
||||||
|
|
||||||
sim> set cpu 8080 ;note 4k Basic will not run on a Z80 CPU
|
sim> set cpu 8080 ;note 4k Basic will not run on a Z80 CPU
|
||||||
sim> set sio upper ;4k Basic does not like lower case letters as input
|
sim> set sio upper ;4k Basic does not like lower case letters as input
|
||||||
|
sim> set cpu noitrap ;4k Basic likes to execute non 8080 instructions - ignore
|
||||||
sim> set sio ansi ;4k Basic produces 8-bit output, strip to seven bits
|
sim> set sio ansi ;4k Basic produces 8-bit output, strip to seven bits
|
||||||
sim> d sr 8 ;good setting for the Switch Register
|
sim> d sr 8 ;good setting for the Switch Register
|
||||||
sim> load 4kbas.bin 0 ;load it at 0
|
sim> load 4kbas.bin 0 ;load it at 0
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
cpu H316/H516 CPU
|
cpu H316/H516 CPU
|
||||||
|
|
||||||
|
06-Nov-04 RMS Added =n to SHOW HISTORY
|
||||||
04-Jan-04 RMS Removed unnecessary compare
|
04-Jan-04 RMS Removed unnecessary compare
|
||||||
31-Dec-03 RMS Fixed bug in cpu_set_hist
|
31-Dec-03 RMS Fixed bug in cpu_set_hist
|
||||||
24-Oct-03 RMS Added DMA/DMC support, instruction history
|
24-Oct-03 RMS Added DMA/DMC support, instruction history
|
||||||
|
@ -338,7 +339,7 @@ MTAB cpu_mod[] = {
|
||||||
&cpu_set_nchan, &cpu_show_nchan, NULL },
|
&cpu_set_nchan, &cpu_show_nchan, NULL },
|
||||||
{ UNIT_DMC, 0, "no DMC", "NODMC", NULL },
|
{ UNIT_DMC, 0, "no DMC", "NODMC", NULL },
|
||||||
{ UNIT_DMC, UNIT_DMC, "DMC", "DMC", NULL },
|
{ UNIT_DMC, UNIT_DMC, "DMC", "DMC", NULL },
|
||||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "HISTORY", "HISTORY",
|
{ MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY",
|
||||||
&cpu_set_hist, &cpu_show_hist },
|
&cpu_set_hist, &cpu_show_hist },
|
||||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "DMA1", NULL,
|
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "DMA1", NULL,
|
||||||
NULL, &cpu_show_dma, NULL },
|
NULL, &cpu_show_dma, NULL },
|
||||||
|
@ -1369,8 +1370,10 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)
|
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
{
|
{
|
||||||
int32 cr, k, di, op;
|
int32 cr, k, di, op, lnt;
|
||||||
|
char *cptr = (char *) desc;
|
||||||
t_value sim_eval;
|
t_value sim_eval;
|
||||||
|
t_stat r;
|
||||||
struct InstHistory *h;
|
struct InstHistory *h;
|
||||||
extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
|
extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
|
||||||
UNIT *uptr, int32 sw);
|
UNIT *uptr, int32 sw);
|
||||||
|
@ -1378,9 +1381,14 @@ static uint8 has_opnd[16] = {
|
||||||
0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 };
|
0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 };
|
||||||
|
|
||||||
if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */
|
if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */
|
||||||
|
if (cptr) {
|
||||||
|
lnt = (int32) get_uint (cptr, 10, hst_lnt, &r);
|
||||||
|
if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; }
|
||||||
|
else lnt = hst_lnt;
|
||||||
|
di = hst_p - lnt; /* work forward */
|
||||||
|
if (di < 0) di = di + hst_lnt;
|
||||||
fprintf (st, "PC C A B X ea IR\n\n");
|
fprintf (st, "PC C A B X ea IR\n\n");
|
||||||
di = hst_p; /* work forward */
|
for (k = 0; k < lnt; k++) { /* print specified */
|
||||||
for (k = 0; k < hst_lnt; k++) { /* print specified */
|
|
||||||
h = &hst[(++di) % hst_lnt]; /* entry pointer */
|
h = &hst[(++di) % hst_lnt]; /* entry pointer */
|
||||||
if (h->pc & HIST_PC) { /* instruction? */
|
if (h->pc & HIST_PC) { /* instruction? */
|
||||||
cr = (h->pc & HIST_C)? 1: 0; /* carry */
|
cr = (h->pc & HIST_C)? 1: 0; /* carry */
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
To: Users
|
To: Users
|
||||||
From: Bob Supnik
|
From: Bob Supnik
|
||||||
Subj: H316 Simulator Usage
|
Subj: H316 Simulator Usage
|
||||||
Date: 15-Feb-2004
|
Date: 15-Nov-2004
|
||||||
|
|
||||||
COPYRIGHT NOTICE
|
COPYRIGHT NOTICE
|
||||||
|
|
||||||
|
@ -155,6 +155,17 @@ control registers for the interrupt system.
|
||||||
most recent PC change first
|
most recent PC change first
|
||||||
WRU 8 interrupt character
|
WRU 8 interrupt character
|
||||||
|
|
||||||
|
The CPU can maintain a history of the most recently executed instructions.
|
||||||
|
This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands:
|
||||||
|
|
||||||
|
SET CPU HISTORY clear history buffer
|
||||||
|
SET CPU HISTORY=0 disable history
|
||||||
|
SET CPU HISTORY=n enable history, length = n
|
||||||
|
SHOW CPU HISTORY print CPU history
|
||||||
|
SHOW CPU HISTORY=n print first n entries of CPU history
|
||||||
|
|
||||||
|
The maximum length for the history is 65536 entries.
|
||||||
|
|
||||||
2.2 Programmed I/O Devices
|
2.2 Programmed I/O Devices
|
||||||
|
|
||||||
2.2.1 316/516-50 Paper Tape Reader (PTR)
|
2.2.1 316/516-50 Paper Tape Reader (PTR)
|
||||||
|
@ -373,7 +384,7 @@ or write locked.
|
||||||
SET MTn LOCKED set unit n write locked
|
SET MTn LOCKED set unit n write locked
|
||||||
SET MTn WRITEENABLED set unit n write enabled
|
SET MTn WRITEENABLED set unit n write enabled
|
||||||
|
|
||||||
Units can be set ONLINE or OFFLINE, and WRITEENABLED or write LOCKED.
|
Units can also be set ENABLED or DISABLED.
|
||||||
|
|
||||||
The magtape controller can be connected to the IO bus, a DMC channel, or
|
The magtape controller can be connected to the IO bus, a DMC channel, or
|
||||||
a DMA channel:
|
a DMA channel:
|
||||||
|
@ -428,7 +439,7 @@ disk packs; a 4651, supporting 2 surface disk packs; or a 4720, supporting
|
||||||
SET DP 4720 controller is 4720
|
SET DP 4720 controller is 4720
|
||||||
|
|
||||||
The default is 4651. All disk packs on the controller must be of the
|
The default is 4651. All disk packs on the controller must be of the
|
||||||
same type. Units can be set ONLINE or OFFLINE, and WRITEENABLED or
|
same type. Units can be set ENABLED or DISABLED, and WRITEENABLED or
|
||||||
write LOCKED.
|
write LOCKED.
|
||||||
|
|
||||||
The disk pack controller can be connected to a DMC channel or a DMA
|
The disk pack controller can be connected to a DMC channel or a DMA
|
||||||
|
|
|
@ -23,6 +23,22 @@
|
||||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
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.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
CPU 2116A/2100A/21MXE central processing unit
|
||||||
|
MP 12892B memory protect
|
||||||
|
DMA0,DMA1 12895A/12897B direct memory access/dual channel port controller
|
||||||
|
|
||||||
|
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
|
||||||
|
Added -F switch to SET CPU to force memory truncation
|
||||||
|
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
|
||||||
|
Modified WRU to be REG_HRO
|
||||||
|
Added BRK and DEL to save console settings
|
||||||
|
Fixed use of "unsigned int16" in cpu_reset
|
||||||
|
Modified memory size routine to return SCPE_INCOMP if
|
||||||
|
memory size truncation declined
|
||||||
20-Jul-04 RMS Fixed bug in breakpoint test (reported by Dave Bryan)
|
20-Jul-04 RMS Fixed bug in breakpoint test (reported by Dave Bryan)
|
||||||
Back up PC on instruction errors (from Dave Bryan)
|
Back up PC on instruction errors (from Dave Bryan)
|
||||||
14-May-04 RMS Fixed bugs and added features from Dave Bryan
|
14-May-04 RMS Fixed bugs and added features from Dave Bryan
|
||||||
|
@ -68,6 +84,12 @@
|
||||||
21-Nov-00 RMS Fixed bug in reset routine
|
21-Nov-00 RMS Fixed bug in reset routine
|
||||||
15-Oct-00 RMS Added dynamic device number support
|
15-Oct-00 RMS Added dynamic device number support
|
||||||
|
|
||||||
|
References:
|
||||||
|
- 21MX M-Series Computer, HP 2108B and HP 2112B, Operating and Reference Manual
|
||||||
|
(02108-90037, Apr-1979)
|
||||||
|
- HP 1000 M/E/F-Series Computers Engineering and Reference Documentation
|
||||||
|
(92851-90001, Mar-1981)
|
||||||
|
|
||||||
The register state for the HP 2116 CPU is:
|
The register state for the HP 2116 CPU is:
|
||||||
|
|
||||||
AR<15:0> A register - addressable as location 0
|
AR<15:0> A register - addressable as location 0
|
||||||
|
@ -308,21 +330,27 @@
|
||||||
#define UNIT_V_21MX (UNIT_V_UF + 1) /* 21MX */
|
#define UNIT_V_21MX (UNIT_V_UF + 1) /* 21MX */
|
||||||
#define UNIT_V_EAU (UNIT_V_UF + 2) /* EAU */
|
#define UNIT_V_EAU (UNIT_V_UF + 2) /* EAU */
|
||||||
#define UNIT_V_FP (UNIT_V_UF + 3) /* FP */
|
#define UNIT_V_FP (UNIT_V_UF + 3) /* FP */
|
||||||
#define UNIT_V_MPR (UNIT_V_UF + 4) /* mem prot */
|
#define UNIT_V_DMS (UNIT_V_UF + 4) /* DMS */
|
||||||
#define UNIT_V_DMS (UNIT_V_UF + 5) /* DMS */
|
#define UNIT_V_IOP (UNIT_V_UF + 5) /* 2100 IOP */
|
||||||
#define UNIT_V_IOP (UNIT_V_UF + 6) /* 2100 IOP */
|
#define UNIT_V_IOPX (UNIT_V_UF + 6) /* 21MX IOP */
|
||||||
#define UNIT_V_IOPX (UNIT_V_UF + 7) /* 21MX IOP */
|
#define UNIT_V_MSIZE (UNIT_V_UF + 7) /* dummy mask */
|
||||||
#define UNIT_V_MSIZE (UNIT_V_UF + 8) /* dummy mask */
|
#define UNIT_2116 (0)
|
||||||
#define UNIT_2100 (1 << UNIT_V_2100)
|
#define UNIT_2100 (1 << UNIT_V_2100)
|
||||||
#define UNIT_21MX (1 << UNIT_V_21MX)
|
#define UNIT_21MX (1 << UNIT_V_21MX)
|
||||||
#define UNIT_EAU (1 << UNIT_V_EAU)
|
#define UNIT_EAU (1 << UNIT_V_EAU)
|
||||||
#define UNIT_FP (1 << UNIT_V_FP)
|
#define UNIT_FP (1 << UNIT_V_FP)
|
||||||
#define UNIT_MPR (1 << UNIT_V_MPR)
|
|
||||||
#define UNIT_DMS (1 << UNIT_V_DMS)
|
#define UNIT_DMS (1 << UNIT_V_DMS)
|
||||||
#define UNIT_IOP (1 << UNIT_V_IOP)
|
#define UNIT_IOP (1 << UNIT_V_IOP)
|
||||||
#define UNIT_IOPX (1 << UNIT_V_IOPX)
|
#define UNIT_IOPX (1 << UNIT_V_IOPX)
|
||||||
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
|
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
|
||||||
|
|
||||||
|
#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 */
|
||||||
|
#define UNIT_V_MP_SEL1 (UNIT_V_UF + 2) /* MP jumper W7 out */
|
||||||
|
#define UNIT_MP_JSB (1 << UNIT_V_MP_JSB)
|
||||||
|
#define UNIT_MP_INT (1 << UNIT_V_MP_INT)
|
||||||
|
#define UNIT_MP_SEL1 (1 << UNIT_V_MP_SEL1)
|
||||||
|
|
||||||
#define MOD_2116 1
|
#define MOD_2116 1
|
||||||
#define MOD_2100 2
|
#define MOD_2100 2
|
||||||
#define MOD_21MX 4
|
#define MOD_21MX 4
|
||||||
|
@ -380,16 +408,21 @@ struct opt_table { /* options table */
|
||||||
static struct opt_table opt_val[] = {
|
static struct opt_table opt_val[] = {
|
||||||
{ UNIT_EAU, MOD_2116 },
|
{ UNIT_EAU, MOD_2116 },
|
||||||
{ UNIT_FP, MOD_2100 },
|
{ UNIT_FP, MOD_2100 },
|
||||||
{ UNIT_MPR, MOD_2100 | MOD_21MX },
|
|
||||||
{ UNIT_DMS, MOD_21MX },
|
{ UNIT_DMS, MOD_21MX },
|
||||||
{ UNIT_IOP, MOD_2100 | MOD_21MX },
|
{ UNIT_IOP, MOD_2100 | MOD_21MX },
|
||||||
|
{ UNIT_2116, MOD_2116 | MOD_2100 | MOD_21MX },
|
||||||
|
{ UNIT_2100, MOD_2116 | MOD_2100 | MOD_21MX },
|
||||||
|
{ UNIT_21MX, MOD_2116 | MOD_2100 | MOD_21MX },
|
||||||
{ 0, 0 } };
|
{ 0, 0 } };
|
||||||
|
|
||||||
extern int32 sim_interval;
|
extern int32 sim_interval;
|
||||||
extern int32 sim_int_char;
|
extern int32 sim_int_char;
|
||||||
|
extern int32 sim_brk_char;
|
||||||
|
extern int32 sim_del_char;
|
||||||
extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
|
extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
|
||||||
extern FILE *sim_log;
|
extern FILE *sim_log;
|
||||||
extern DEVICE *sim_devices[];
|
extern DEVICE *sim_devices[];
|
||||||
|
extern int32 sim_switches;
|
||||||
extern char halt_msg[];
|
extern char halt_msg[];
|
||||||
|
|
||||||
t_stat Ea (uint32 IR, uint32 *addr, uint32 irq);
|
t_stat Ea (uint32 IR, uint32 *addr, uint32 irq);
|
||||||
|
@ -421,6 +454,7 @@ t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
|
||||||
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
|
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
|
||||||
t_stat cpu_reset (DEVICE *dptr);
|
t_stat cpu_reset (DEVICE *dptr);
|
||||||
t_stat cpu_boot (int32 unitno, DEVICE *dptr);
|
t_stat cpu_boot (int32 unitno, DEVICE *dptr);
|
||||||
|
t_stat mp_reset (DEVICE *dptr);
|
||||||
t_stat dma0_reset (DEVICE *dptr);
|
t_stat dma0_reset (DEVICE *dptr);
|
||||||
t_stat dma1_reset (DEVICE *dptr);
|
t_stat dma1_reset (DEVICE *dptr);
|
||||||
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
@ -458,13 +492,6 @@ REG cpu_reg[] = {
|
||||||
{ FLDATA (ION, ion, 0) },
|
{ FLDATA (ION, ion, 0) },
|
||||||
{ FLDATA (ION_DEFER, ion_defer, 0) },
|
{ FLDATA (ION_DEFER, ion_defer, 0) },
|
||||||
{ ORDATA (CIR, intaddr, 6) },
|
{ ORDATA (CIR, intaddr, 6) },
|
||||||
{ FLDATA (MPCTL, dev_ctl[PRO/32], INT_V (PRO)) },
|
|
||||||
{ FLDATA (MPFLG, dev_flg[PRO/32], INT_V (PRO)) },
|
|
||||||
{ FLDATA (MPFBF, dev_fbf[PRO/32], INT_V (PRO)) },
|
|
||||||
{ ORDATA (MPFR, mp_fence, 15) },
|
|
||||||
{ ORDATA (MPVR, mp_viol, 16) },
|
|
||||||
{ FLDATA (MPMEV, mp_mevff, 0) },
|
|
||||||
{ FLDATA (MPEVR, mp_evrff, 0) },
|
|
||||||
{ FLDATA (DMSENB, dms_enb, 0) },
|
{ FLDATA (DMSENB, dms_enb, 0) },
|
||||||
{ FLDATA (DMSCUR, dms_ump, VA_N_PAG) },
|
{ FLDATA (DMSCUR, dms_ump, VA_N_PAG) },
|
||||||
{ ORDATA (DMSSR, dms_sr, 16) },
|
{ ORDATA (DMSSR, dms_sr, 16) },
|
||||||
|
@ -476,7 +503,9 @@ REG cpu_reg[] = {
|
||||||
{ DRDATA (INDMAX, ind_max, 16), REG_NZ + PV_LEFT },
|
{ DRDATA (INDMAX, ind_max, 16), REG_NZ + PV_LEFT },
|
||||||
{ BRDATA (PCQ, pcq, 8, 15, PCQ_SIZE), REG_RO+REG_CIRC },
|
{ BRDATA (PCQ, pcq, 8, 15, PCQ_SIZE), REG_RO+REG_CIRC },
|
||||||
{ ORDATA (PCQP, pcq_p, 6), REG_HRO },
|
{ ORDATA (PCQP, pcq_p, 6), REG_HRO },
|
||||||
{ ORDATA (WRU, sim_int_char, 8) },
|
{ ORDATA (WRU, sim_int_char, 8), REG_HRO },
|
||||||
|
{ ORDATA (BRK, sim_brk_char, 8), REG_HRO },
|
||||||
|
{ ORDATA (DEL, sim_del_char, 8), REG_HRO },
|
||||||
{ ORDATA (HCMD, dev_cmd[0], 32), REG_HRO },
|
{ ORDATA (HCMD, dev_cmd[0], 32), REG_HRO },
|
||||||
{ ORDATA (LCMD, dev_cmd[1], 32), REG_HRO },
|
{ ORDATA (LCMD, dev_cmd[1], 32), REG_HRO },
|
||||||
{ ORDATA (HCTL, dev_ctl[0], 32), REG_HRO },
|
{ ORDATA (HCTL, dev_ctl[0], 32), REG_HRO },
|
||||||
|
@ -490,15 +519,18 @@ REG cpu_reg[] = {
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
MTAB cpu_mod[] = {
|
MTAB cpu_mod[] = {
|
||||||
{ UNIT_2100+UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_MPR+UNIT_DMS+UNIT_IOP+UNIT_IOPX,
|
{ UNIT_2116+UNIT_2100+UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_DMS+UNIT_IOP+UNIT_IOPX,
|
||||||
0, NULL, "2116", NULL },
|
UNIT_2116, NULL, "2116", &cpu_set_opt,
|
||||||
{ UNIT_2100+UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_MPR+UNIT_DMS+UNIT_IOP+UNIT_IOPX,
|
NULL, (void *) UNIT_2116 },
|
||||||
UNIT_2100+UNIT_EAU, NULL, "2100", NULL },
|
{ UNIT_2116+UNIT_2100+UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_DMS+UNIT_IOP+UNIT_IOPX,
|
||||||
{ UNIT_2100+UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_MPR+UNIT_DMS+UNIT_IOP+UNIT_IOPX,
|
UNIT_2100+UNIT_EAU, NULL, "2100", &cpu_set_opt,
|
||||||
UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_MPR+UNIT_DMS, NULL, "21MX", NULL },
|
NULL, (void *) UNIT_2100 },
|
||||||
{ UNIT_2100+UNIT_21MX, 0, "2116", NULL, NULL },
|
{ UNIT_2116+UNIT_2100+UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_DMS+UNIT_IOP+UNIT_IOPX,
|
||||||
{ UNIT_2100+UNIT_21MX, UNIT_2100, "2100", NULL, NULL },
|
UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_DMS, NULL, "21MX", &cpu_set_opt,
|
||||||
{ UNIT_2100+UNIT_21MX, UNIT_21MX, "21MX", NULL, NULL },
|
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_EAU, UNIT_EAU, "EAU", "EAU", &cpu_set_opt,
|
{ UNIT_EAU, UNIT_EAU, "EAU", "EAU", &cpu_set_opt,
|
||||||
NULL, (void *) UNIT_EAU },
|
NULL, (void *) UNIT_EAU },
|
||||||
{ UNIT_EAU, 0, "no EAU", "NOEAU", &cpu_set_opt,
|
{ UNIT_EAU, 0, "no EAU", "NOEAU", &cpu_set_opt,
|
||||||
|
@ -507,10 +539,6 @@ MTAB cpu_mod[] = {
|
||||||
NULL, (void *) UNIT_FP },
|
NULL, (void *) UNIT_FP },
|
||||||
{ UNIT_FP, 0, "no FP", "NOFP", &cpu_set_opt,
|
{ UNIT_FP, 0, "no FP", "NOFP", &cpu_set_opt,
|
||||||
NULL, (void *) UNIT_FP },
|
NULL, (void *) UNIT_FP },
|
||||||
{ UNIT_MPR, UNIT_MPR, "MPR", "MPR", &cpu_set_opt,
|
|
||||||
NULL, (void *) UNIT_MPR },
|
|
||||||
{ UNIT_MPR, 0, "no MPR", "NOMPR", &cpu_set_opt,
|
|
||||||
NULL, (void *) UNIT_MPR },
|
|
||||||
{ UNIT_DMS, UNIT_DMS, "DMS", "DMS", &cpu_set_opt,
|
{ UNIT_DMS, UNIT_DMS, "DMS", "DMS", &cpu_set_opt,
|
||||||
NULL, (void *) UNIT_DMS },
|
NULL, (void *) UNIT_DMS },
|
||||||
{ UNIT_DMS, 0, "no DMS", "NODMS", &cpu_set_opt,
|
{ UNIT_DMS, 0, "no DMS", "NODMS", &cpu_set_opt,
|
||||||
|
@ -538,6 +566,43 @@ DEVICE cpu_dev = {
|
||||||
&cpu_ex, &cpu_dep, &cpu_reset,
|
&cpu_ex, &cpu_dep, &cpu_reset,
|
||||||
&cpu_boot, NULL, NULL };
|
&cpu_boot, NULL, NULL };
|
||||||
|
|
||||||
|
/* Memory protect data structures
|
||||||
|
|
||||||
|
mp_dev MP device descriptor
|
||||||
|
mp_unit MP unit descriptor
|
||||||
|
mp_reg MP register list
|
||||||
|
mp_mod MP modifiers list
|
||||||
|
*/
|
||||||
|
|
||||||
|
UNIT mp_unit = { UDATA (NULL, UNIT_MP_SEL1, 0) };
|
||||||
|
|
||||||
|
REG mp_reg[] = {
|
||||||
|
{ FLDATA (CTL, dev_ctl[PRO/32], INT_V (PRO)) },
|
||||||
|
{ FLDATA (FLG, dev_flg[PRO/32], INT_V (PRO)) },
|
||||||
|
{ FLDATA (FBF, dev_fbf[PRO/32], INT_V (PRO)) },
|
||||||
|
{ ORDATA (FR, mp_fence, 15) },
|
||||||
|
{ ORDATA (VR, mp_viol, 16) },
|
||||||
|
{ FLDATA (MEV, mp_mevff, 0) },
|
||||||
|
{ FLDATA (EVR, mp_evrff, 0) },
|
||||||
|
{ NULL } };
|
||||||
|
|
||||||
|
MTAB mp_mod[] = {
|
||||||
|
{ UNIT_MP_JSB, UNIT_MP_JSB, "JSB (W5) in", "JSBIN", NULL },
|
||||||
|
{ UNIT_MP_JSB, 0, "JSB (W5) out", "JSBOUT", NULL },
|
||||||
|
{ UNIT_MP_INT, UNIT_MP_INT, "INT (W6) in", "INTIN", NULL },
|
||||||
|
{ UNIT_MP_INT, 0, "INT (W6) out", "INTOUT", NULL },
|
||||||
|
{ UNIT_MP_SEL1, UNIT_MP_SEL1, "SEL1 (W7) in", "SEL1IN", NULL },
|
||||||
|
{ UNIT_MP_SEL1, 0, "SEL1 (W7) out", "SEL1OUT", NULL },
|
||||||
|
{ 0 } };
|
||||||
|
|
||||||
|
DEVICE mp_dev = {
|
||||||
|
"MP", &mp_unit, mp_reg, mp_mod,
|
||||||
|
1, 8, 1, 1, 8, 16,
|
||||||
|
NULL, NULL, &mp_reset,
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
NULL, DEV_DISABLE | DEV_DIS };
|
||||||
|
|
||||||
|
|
||||||
/* DMA controller data structures
|
/* DMA controller data structures
|
||||||
|
|
||||||
dmax_dev DMAx device descriptor
|
dmax_dev DMAx device descriptor
|
||||||
|
@ -560,7 +625,8 @@ DEVICE dma0_dev = {
|
||||||
"DMA0", &dma0_unit, dma0_reg, NULL,
|
"DMA0", &dma0_unit, dma0_reg, NULL,
|
||||||
1, 8, 1, 1, 8, 16,
|
1, 8, 1, 1, 8, 16,
|
||||||
NULL, NULL, &dma0_reset,
|
NULL, NULL, &dma0_reset,
|
||||||
NULL, NULL, NULL };
|
NULL, NULL, NULL,
|
||||||
|
NULL, DEV_DISABLE };
|
||||||
|
|
||||||
UNIT dma1_unit = { UDATA (NULL, 0, 0) };
|
UNIT dma1_unit = { UDATA (NULL, 0, 0) };
|
||||||
|
|
||||||
|
@ -578,7 +644,8 @@ DEVICE dma1_dev = {
|
||||||
"DMA1", &dma1_unit, dma1_reg, NULL,
|
"DMA1", &dma1_unit, dma1_reg, NULL,
|
||||||
1, 8, 1, 1, 8, 16,
|
1, 8, 1, 1, 8, 16,
|
||||||
NULL, NULL, &dma1_reset,
|
NULL, NULL, &dma1_reset,
|
||||||
NULL, NULL, NULL };
|
NULL, NULL, NULL,
|
||||||
|
NULL, DEV_DISABLE };
|
||||||
|
|
||||||
/* Extended instruction decode tables */
|
/* Extended instruction decode tables */
|
||||||
|
|
||||||
|
@ -715,6 +782,17 @@ reason = 0;
|
||||||
|
|
||||||
/* Restore I/O state */
|
/* Restore I/O state */
|
||||||
|
|
||||||
|
if (mp_dev.flags & DEV_DIS) dtab[PRO] = NULL;
|
||||||
|
else dtab[PRO] = &proio; /* set up MP dispatch */
|
||||||
|
if (dma0_dev.flags & DEV_DIS) dtab[DMA0] = dtab[DMALT0] = NULL;
|
||||||
|
else { /* set up DMA0 dispatch */
|
||||||
|
dtab[DMA0] = &dmpio;
|
||||||
|
dtab[DMALT0] = &dmsio; }
|
||||||
|
if (dma1_dev.flags & DEV_DIS) dtab[DMA1] = dtab[DMALT1] = NULL;
|
||||||
|
else { /* set up DMA1 dispatch */
|
||||||
|
dtab[DMA1] = &dmpio;
|
||||||
|
dtab[DMALT1] = &dmsio; }
|
||||||
|
|
||||||
for (i = VARDEV; i <= I_DEVMASK; i++) dtab[i] = NULL; /* clr disp table */
|
for (i = VARDEV; i <= I_DEVMASK; i++) dtab[i] = NULL; /* clr disp table */
|
||||||
dev_cmd[0] = dev_cmd[0] & M_FXDEV; /* clear dynamic info */
|
dev_cmd[0] = dev_cmd[0] & M_FXDEV; /* clear dynamic info */
|
||||||
dev_ctl[0] = dev_ctl[0] & M_FXDEV;
|
dev_ctl[0] = dev_ctl[0] & M_FXDEV;
|
||||||
|
@ -846,6 +924,8 @@ case 0034:case 0035:case 0036:case 0037:
|
||||||
case 0230:case 0231:case 0232:case 0233:
|
case 0230:case 0231:case 0232:case 0233:
|
||||||
case 0234:case 0235:case 0236:case 0237:
|
case 0234:case 0235:case 0236:case 0237:
|
||||||
if (reason = Ea (IR, &MA, intrq)) break; /* JSB */
|
if (reason = Ea (IR, &MA, intrq)) break; /* JSB */
|
||||||
|
if ((mp_unit.flags & UNIT_MP_JSB) && CTL (PRO) && (MA < mp_fence))
|
||||||
|
ABORT (ABORT_PRO); /* MP if W7 (JSB) out */
|
||||||
WriteW (MA, PC); /* store PC */
|
WriteW (MA, PC); /* store PC */
|
||||||
PCQ_ENTRY;
|
PCQ_ENTRY;
|
||||||
PC = (MA + 1) & VAMASK; /* jump */
|
PC = (MA + 1) & VAMASK; /* jump */
|
||||||
|
@ -1850,8 +1930,9 @@ uint32 i, MA;
|
||||||
MA = IR & (I_IA | I_DISP); /* ind + disp */
|
MA = IR & (I_IA | I_DISP); /* ind + disp */
|
||||||
if (IR & I_CP) MA = ((PC - 1) & I_PAGENO) | MA; /* current page? */
|
if (IR & I_CP) MA = ((PC - 1) & I_PAGENO) | MA; /* current page? */
|
||||||
for (i = 0; (i < ind_max) && (MA & I_IA); i++) { /* resolve multilevel */
|
for (i = 0; (i < ind_max) && (MA & I_IA); i++) { /* resolve multilevel */
|
||||||
if ((i >= 2) && irq && /* >3 levels, int req, */
|
if (irq && /* int req? */
|
||||||
(cpu_unit.flags & UNIT_MPR)) /* mprot installed? */
|
((i >= 2) || (mp_unit.flags & UNIT_MP_INT)) && /* ind > 3 or W6 out? */
|
||||||
|
!(mp_unit.flags & DEV_DIS)) /* MP installed? */
|
||||||
return STOP_INDINT; /* break out */
|
return STOP_INDINT; /* break out */
|
||||||
MA = ReadW (MA & VAMASK); }
|
MA = ReadW (MA & VAMASK); }
|
||||||
if (i >= ind_max) return STOP_IND; /* indirect loop? */
|
if (i >= ind_max) return STOP_IND; /* indirect loop? */
|
||||||
|
@ -1868,8 +1949,9 @@ uint32 i, MA;
|
||||||
MA = ReadW (PC); /* get next address */
|
MA = ReadW (PC); /* get next address */
|
||||||
PC = (PC + 1) & VAMASK;
|
PC = (PC + 1) & VAMASK;
|
||||||
for (i = 0; (i < ind_max) && (MA & I_IA); i++) { /* resolve multilevel */
|
for (i = 0; (i < ind_max) && (MA & I_IA); i++) { /* resolve multilevel */
|
||||||
if ((i >= 2) && irq && /* >3 levels, int req, */
|
if (irq && /* int req? */
|
||||||
(cpu_unit.flags & UNIT_MPR)) /* mprot installed? */
|
((i >= 2) || (mp_unit.flags & UNIT_MP_INT)) && /* ind > 3 or W6 out? */
|
||||||
|
!(mp_unit.flags & DEV_DIS)) /* MP installed? */
|
||||||
return STOP_INDINT; /* break out */
|
return STOP_INDINT; /* break out */
|
||||||
MA = ReadW (MA & VAMASK); }
|
MA = ReadW (MA & VAMASK); }
|
||||||
if (i >= ind_max) return STOP_IND; /* indirect loop? */
|
if (i >= ind_max) return STOP_IND; /* indirect loop? */
|
||||||
|
@ -1922,7 +2004,8 @@ uint32 dev, sop, iodata, ab;
|
||||||
ab = (ir & I_AB)? 1: 0; /* get A/B select */
|
ab = (ir & I_AB)? 1: 0; /* get A/B select */
|
||||||
dev = ir & I_DEVMASK; /* get device */
|
dev = ir & I_DEVMASK; /* get device */
|
||||||
sop = I_GETIOOP (ir); /* get subopcode */
|
sop = I_GETIOOP (ir); /* get subopcode */
|
||||||
if (!iotrap && CTL (PRO) && ((sop == ioHLT) || (dev != OVF))) { /* protected? */
|
if (!iotrap && CTL (PRO) && /* protected? */
|
||||||
|
((sop == ioHLT) || ((dev != OVF) && (mp_unit.flags & UNIT_MP_SEL1)))) {
|
||||||
if (sop == ioLIX) ABREG[ab] = 0; /* A/B writes anyway */
|
if (sop == ioLIX) ABREG[ab] = 0; /* A/B writes anyway */
|
||||||
ABORT (ABORT_PRO); }
|
ABORT (ABORT_PRO); }
|
||||||
iodata = devdisp (dev, sop, ir, ABREG[ab]); /* process I/O */
|
iodata = devdisp (dev, sop, ir, ABREG[ab]); /* process I/O */
|
||||||
|
@ -2248,6 +2331,8 @@ return dms_sr;
|
||||||
|
|
||||||
/* Device 0 (CPU) I/O routine
|
/* Device 0 (CPU) I/O routine
|
||||||
|
|
||||||
|
NOTE: LIx/MIx reads floating I/O bus (0 on all machines).
|
||||||
|
|
||||||
From Dave Bryan: RTE uses the undocumented instruction "SFS 0,C" to both test
|
From Dave Bryan: RTE uses the undocumented instruction "SFS 0,C" to both test
|
||||||
and turn off the interrupt system. This is confirmed in the "RTE-6/VM
|
and turn off the interrupt system. This is confirmed in the "RTE-6/VM
|
||||||
Technical Specifications" manual (HP 92084-90015), section 2.3.1 "Process
|
Technical Specifications" manual (HP 92084-90015), section 2.3.1 "Process
|
||||||
|
@ -2295,7 +2380,9 @@ if (IR & I_HC) ion = 0; /* HC option */
|
||||||
return dat;
|
return dat;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Device 1 (overflow) I/O routine */
|
/* Device 1 (overflow) I/O routine
|
||||||
|
|
||||||
|
NOTE: The S register is read-only on the 2115/2116. */
|
||||||
|
|
||||||
int32 ovfio (int32 inst, int32 IR, int32 dat)
|
int32 ovfio (int32 inst, int32 IR, int32 dat)
|
||||||
{
|
{
|
||||||
|
@ -2316,7 +2403,7 @@ case ioLIX: /* load */
|
||||||
dat = SR;
|
dat = SR;
|
||||||
break;
|
break;
|
||||||
case ioOTX: /* output */
|
case ioOTX: /* output */
|
||||||
SR = dat;
|
if (cpu_unit.flags & (UNIT_2100 | UNIT_21MX)) SR = dat;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break; }
|
break; }
|
||||||
|
@ -2348,8 +2435,6 @@ return dat;
|
||||||
|
|
||||||
int32 proio (int32 inst, int32 IR, int32 dat)
|
int32 proio (int32 inst, int32 IR, int32 dat)
|
||||||
{
|
{
|
||||||
if ((cpu_unit.flags & UNIT_MPR) == 0) /* not installed? */
|
|
||||||
return nulio (inst, IR, dat); /* non-existent dev */
|
|
||||||
switch (inst) { /* case on opcode */
|
switch (inst) { /* case on opcode */
|
||||||
case ioSFC: /* skip flag clear */
|
case ioSFC: /* skip flag clear */
|
||||||
if (!mp_mevff) PC = (PC + 1) & VAMASK; /* skip if mem prot */
|
if (!mp_mevff) PC = (PC + 1) & VAMASK; /* skip if mem prot */
|
||||||
|
@ -2407,7 +2492,9 @@ default:
|
||||||
return dat;
|
return dat;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Devices 6,7 (primary DMA) I/O routine */
|
/* Devices 6,7 (primary DMA) I/O routine
|
||||||
|
|
||||||
|
NOTE: LIx/MIx reads floating S-bus (1 on 21MX, 0 on 2116/2100). */
|
||||||
|
|
||||||
int32 dmpio (int32 inst, int32 IR, int32 dat)
|
int32 dmpio (int32 inst, int32 IR, int32 dat)
|
||||||
{
|
{
|
||||||
|
@ -2426,8 +2513,10 @@ case ioSFC: /* skip flag clear */
|
||||||
case ioSFS: /* skip flag set */
|
case ioSFS: /* skip flag set */
|
||||||
if (FLG (DMA0 + ch) != 0) PC = (PC + 1) & VAMASK;
|
if (FLG (DMA0 + ch) != 0) PC = (PC + 1) & VAMASK;
|
||||||
break;
|
break;
|
||||||
case ioMIX: case ioLIX: /* load, merge */
|
case ioLIX: /* load */
|
||||||
dat = DMASK;
|
dat = 0;
|
||||||
|
case ioMIX: /* merge */
|
||||||
|
if (cpu_unit.flags & UNIT_21MX) dat = DMASK;
|
||||||
break;
|
break;
|
||||||
case ioOTX: /* output */
|
case ioOTX: /* output */
|
||||||
dmac[ch].cw1 = dat;
|
dmac[ch].cw1 = dat;
|
||||||
|
@ -2495,19 +2584,27 @@ else { if (inp) { /* last cycle, input? */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unimplemented device routine */
|
/* Unimplemented device routine
|
||||||
|
|
||||||
|
NOTE: For SC < 10, LIx/MIx reads floating S-bus (-1 on 21MX, 0 on 2116/2100).
|
||||||
|
For SC >= 10, LIx/MIx reads floating I/O bus (0 on all machines). */
|
||||||
|
|
||||||
int32 nulio (int32 inst, int32 IR, int32 dat)
|
int32 nulio (int32 inst, int32 IR, int32 dat)
|
||||||
{
|
{
|
||||||
|
int32 devd;
|
||||||
|
|
||||||
|
devd = IR & I_DEVMASK; /* get device no */
|
||||||
switch (inst) { /* case on opcode */
|
switch (inst) { /* case on opcode */
|
||||||
case ioSFC: /* skip flag clear */
|
case ioSFC: /* skip flag clear */
|
||||||
PC = (PC + 1) & VAMASK;
|
PC = (PC + 1) & VAMASK;
|
||||||
return (stop_dev << IOT_V_REASON) | dat;
|
break;
|
||||||
case ioSFS: /* skip flag set */
|
case ioLIX: /* load */
|
||||||
return (stop_dev << IOT_V_REASON) | dat;
|
dat = 0;
|
||||||
|
case ioMIX: /* merge */
|
||||||
|
if ((devd < VARDEV) && (cpu_unit.flags & UNIT_21MX)) dat = DMASK;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break; }
|
break; }
|
||||||
if (IR & I_HC) { clrFLG (IR & I_DEVMASK); } /* HC option */
|
|
||||||
return (stop_dev << IOT_V_REASON) | dat;
|
return (stop_dev << IOT_V_REASON) | dat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2522,30 +2619,35 @@ clrCMD (PWR);
|
||||||
clrCTL (PWR);
|
clrCTL (PWR);
|
||||||
clrFLG (PWR);
|
clrFLG (PWR);
|
||||||
clrFBF (PWR);
|
clrFBF (PWR);
|
||||||
clrCMD (PRO);
|
|
||||||
clrCTL (PRO);
|
|
||||||
clrFLG (PRO);
|
|
||||||
clrFBF (PRO);
|
|
||||||
dev_srq[0] = dev_srq[0] & ~M_FXDEV;
|
dev_srq[0] = dev_srq[0] & ~M_FXDEV;
|
||||||
mp_fence = 0; /* init mprot */
|
|
||||||
mp_viol = 0;
|
|
||||||
mp_mevff = 0;
|
|
||||||
mp_evrff = 1;
|
|
||||||
dms_enb = dms_ump = 0; /* init DMS */
|
dms_enb = dms_ump = 0; /* init DMS */
|
||||||
dms_sr = 0;
|
dms_sr = 0;
|
||||||
dms_vr = 0;
|
dms_vr = 0;
|
||||||
pcq_r = find_reg ("PCQ", NULL, dptr);
|
pcq_r = find_reg ("PCQ", NULL, dptr);
|
||||||
sim_brk_types = ALL_BKPTS;
|
sim_brk_types = ALL_BKPTS;
|
||||||
sim_brk_dflt = SWMASK ('E');
|
sim_brk_dflt = SWMASK ('E');
|
||||||
if (M == NULL) M = calloc (PASIZE, sizeof (unsigned int16));
|
if (M == NULL) M = calloc (PASIZE, sizeof (uint16));
|
||||||
if (M == NULL) return SCPE_MEM;
|
if (M == NULL) return SCPE_MEM;
|
||||||
if (pcq_r) pcq_r->qptr = 0;
|
if (pcq_r) pcq_r->qptr = 0;
|
||||||
else return SCPE_IERR;
|
else return SCPE_IERR;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t_stat mp_reset (DEVICE *dptr)
|
||||||
|
{
|
||||||
|
clrCTL (PRO);
|
||||||
|
clrFLG (PRO);
|
||||||
|
clrFBF (PRO);
|
||||||
|
mp_fence = 0; /* init mprot */
|
||||||
|
mp_viol = 0;
|
||||||
|
mp_mevff = 0;
|
||||||
|
mp_evrff = 1;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
t_stat dma0_reset (DEVICE *tptr)
|
t_stat dma0_reset (DEVICE *tptr)
|
||||||
{
|
{
|
||||||
|
hp_enbdis_pair (&dma0_dev, &dma1_dev); /* make pair cons */
|
||||||
clrCMD (DMA0);
|
clrCMD (DMA0);
|
||||||
clrCTL (DMA0);
|
clrCTL (DMA0);
|
||||||
setFLG (DMA0);
|
setFLG (DMA0);
|
||||||
|
@ -2556,6 +2658,7 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat dma1_reset (DEVICE *tptr)
|
t_stat dma1_reset (DEVICE *tptr)
|
||||||
{
|
{
|
||||||
|
hp_enbdis_pair (&dma1_dev, &dma0_dev); /* make pair cons */
|
||||||
clrCMD (DMA1);
|
clrCMD (DMA1);
|
||||||
clrCTL (DMA1);
|
clrCTL (DMA1);
|
||||||
setFLG (DMA1);
|
setFLG (DMA1);
|
||||||
|
@ -2601,9 +2704,10 @@ uint32 i;
|
||||||
if ((val <= 0) || (val > PASIZE) || ((val & 07777) != 0) ||
|
if ((val <= 0) || (val > PASIZE) || ((val & 07777) != 0) ||
|
||||||
(!(uptr->flags & UNIT_21MX) && (val > 32768)))
|
(!(uptr->flags & UNIT_21MX) && (val > 32768)))
|
||||||
return SCPE_ARG;
|
return SCPE_ARG;
|
||||||
for (i = val; i < MEMSIZE; i++) mc = mc | M[i];
|
if (!(sim_switches & SWMASK ('F'))) { /* force truncation? */
|
||||||
if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE)))
|
for (i = val; i < MEMSIZE; i++) mc = mc | M[i];
|
||||||
return SCPE_OK;
|
if ((mc != 0) && (!get_yn ("Really truncate memory [N]?", FALSE)))
|
||||||
|
return SCPE_INCOMP; }
|
||||||
MEMSIZE = val;
|
MEMSIZE = val;
|
||||||
for (i = MEMSIZE; i < PASIZE; i++) M[i] = 0;
|
for (i = MEMSIZE; i < PASIZE; i++) M[i] = 0;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -2679,7 +2783,11 @@ for (i = 0; cdptr = sim_devices[i]; i++) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Configuration validation */
|
/* Configuration validation
|
||||||
|
|
||||||
|
Memory is trimmed to 32K if 2116 or 2100 is selected.
|
||||||
|
Memory protect is enabled if 2100 or 21MX or DMS is selected.
|
||||||
|
DMA is enabled if 2116 or 2100 or 21MX is selected. */
|
||||||
|
|
||||||
t_bool cpu_set_opt (UNIT *uptr, int32 val, char *cptr, void *desc)
|
t_bool cpu_set_opt (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
{
|
{
|
||||||
|
@ -2689,15 +2797,22 @@ int32 mod, i;
|
||||||
mod = MOD_2116;
|
mod = MOD_2116;
|
||||||
if (uptr->flags & UNIT_2100) mod = MOD_2100;
|
if (uptr->flags & UNIT_2100) mod = MOD_2100;
|
||||||
else if (uptr->flags & UNIT_21MX) mod = MOD_21MX;
|
else if (uptr->flags & UNIT_21MX) mod = MOD_21MX;
|
||||||
for (i = 0; opt_val[i].optf != 0; i++) {
|
for (i = 0; opt_val[i].cpuf != 0; i++) {
|
||||||
if ((opt == opt_val[i].optf) && (mod & opt_val[i].cpuf)) {
|
if ((opt == opt_val[i].optf) && (mod & opt_val[i].cpuf)) {
|
||||||
if ((mod == MOD_2100) && (val == UNIT_FP))
|
if ((mod == MOD_2100) && (val == UNIT_FP))
|
||||||
uptr->flags = uptr->flags & ~UNIT_IOP;
|
uptr->flags = uptr->flags & ~UNIT_IOP;
|
||||||
if ((opt == UNIT_IOP) && val) {
|
if ((opt == UNIT_IOP) && val) {
|
||||||
if (mod == MOD_2100) uptr->flags =
|
if (mod == MOD_2100)
|
||||||
(uptr->flags & ~UNIT_FP) | UNIT_IOP | UNIT_MPR;
|
uptr->flags = (uptr->flags & ~UNIT_FP) | UNIT_IOP;
|
||||||
if (mod == MOD_21MX) uptr->flags |= UNIT_IOPX | UNIT_MPR; }
|
if (mod == MOD_21MX) uptr->flags |= UNIT_IOPX; }
|
||||||
if (val == UNIT_DMS) uptr->flags |= UNIT_MPR;
|
if (opt == UNIT_2116) mp_dev.flags = mp_dev.flags | DEV_DIS;
|
||||||
|
else if ((val == UNIT_DMS) || (opt == UNIT_2100) || (opt == UNIT_21MX))
|
||||||
|
mp_dev.flags = mp_dev.flags & ~DEV_DIS;
|
||||||
|
if ((opt == UNIT_2116) || (opt == UNIT_2100) || (opt == UNIT_21MX)) {
|
||||||
|
dma0_dev.flags = dma0_dev.flags & ~DEV_DIS;
|
||||||
|
dma1_dev.flags = dma1_dev.flags & ~DEV_DIS; }
|
||||||
|
if (((opt == UNIT_2116) || (opt == UNIT_2100)) && (MEMSIZE > 32768))
|
||||||
|
return cpu_set_size (uptr, 32768, cptr, desc);
|
||||||
return SCPE_OK; } }
|
return SCPE_OK; } }
|
||||||
return SCPE_NOFNC;
|
return SCPE_NOFNC;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,8 @@
|
||||||
14-Apr-99 RMS Changed t_addr to unsigned
|
14-Apr-99 RMS Changed t_addr to unsigned
|
||||||
|
|
||||||
The author gratefully acknowledges the help of Jeff Moffat in answering
|
The author gratefully acknowledges the help of Jeff Moffat in answering
|
||||||
questions about the HP2100.
|
questions about the HP2100; and of Dave Bryan in adding featurs and
|
||||||
|
correcting errors throughout the simulator.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "sim_defs.h" /* simulator defns */
|
#include "sim_defs.h" /* simulator defns */
|
||||||
|
@ -195,12 +196,12 @@ struct DMA { /* DMA channel */
|
||||||
|
|
||||||
/* I/O devices - variable assignment defaults */
|
/* I/O devices - variable assignment defaults */
|
||||||
|
|
||||||
#define PTR 010 /* paper tape reader */
|
#define PTR 010 /* 12597A-002 paper tape reader */
|
||||||
#define TTY 011 /* console */
|
#define TTY 011 /* 12531C teleprinter */
|
||||||
#define PTP 012 /* paper tape punch */
|
#define PTP 012 /* 12597A-005 paper tape punch */
|
||||||
#define CLK 013 /* clock */
|
#define CLK 013 /* 12539C time-base generator */
|
||||||
#define LPS 014 /* 12653 line printer */
|
#define LPS 014 /* 12653A line printer */
|
||||||
#define LPT 015 /* 12845 line printer */
|
#define LPT 015 /* 12845A line printer */
|
||||||
#define MTD 020 /* 12559A data */
|
#define MTD 020 /* 12559A data */
|
||||||
#define MTC 021 /* 12559A control */
|
#define MTC 021 /* 12559A control */
|
||||||
#define DPD 022 /* 12557A data */
|
#define DPD 022 /* 12557A data */
|
||||||
|
@ -211,9 +212,9 @@ struct DMA { /* DMA channel */
|
||||||
#define DRC 027 /* 12610A control */
|
#define DRC 027 /* 12610A control */
|
||||||
#define MSD 030 /* 13181A data */
|
#define MSD 030 /* 13181A data */
|
||||||
#define MSC 031 /* 13181A control */
|
#define MSC 031 /* 13181A control */
|
||||||
#define IPLI 032 /* 12556B link in */
|
#define IPLI 032 /* 12566B link in */
|
||||||
#define IPLO 033 /* 12556B link out */
|
#define IPLO 033 /* 12566B link out */
|
||||||
#define DS 034 /* 13037 control */
|
#define DS 034 /* 13037A control */
|
||||||
#define MUXL 040 /* 12920A lower data */
|
#define MUXL 040 /* 12920A lower data */
|
||||||
#define MUXU 041 /* 12920A upper data */
|
#define MUXU 041 /* 12920A upper data */
|
||||||
#define MUXC 042 /* 12920A control */
|
#define MUXC 042 /* 12920A control */
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,7 +1,7 @@
|
||||||
To: Users
|
To: Users
|
||||||
From: Bob Supnik
|
From: Bob Supnik
|
||||||
Subj: HP2100 Simulator Usage
|
Subj: HP2100 Simulator Usage
|
||||||
Date: 20-Aug-2004
|
Date: 26-Oct-2004
|
||||||
|
|
||||||
COPYRIGHT NOTICE
|
COPYRIGHT NOTICE
|
||||||
|
|
||||||
|
@ -77,25 +77,27 @@ name(s)
|
||||||
|
|
||||||
CPU 2116 CPU with 32KW memory
|
CPU 2116 CPU with 32KW memory
|
||||||
2100 CPU with 32KW memory, FP or IOP instructions
|
2100 CPU with 32KW memory, FP or IOP instructions
|
||||||
21MX CPU with 1024KW memory, FP or DMS instructions
|
21MX CPU with 1024KW memory, FP, DMS, and/or IOP instructions
|
||||||
DMA0, DMA1 dual channel DMA controller
|
MP 12892B memory protect
|
||||||
PTR,PTP 12597A paper tape reader/punch
|
DMA0, DMA1 12895A/12897B direct memory access/dual channel port controller
|
||||||
TTY 12531C buffered terminal controller
|
PTR 12597A duplex register interface with 2748 paper tape reader
|
||||||
LPS 12653A printer controller with 2767 printer
|
PTP 12597A duplex register interface with 2895 paper tape punch
|
||||||
12566B microcircuit interface for diagnostics
|
TTY 12531C buffered teleprinter interface with 2752 teleprinter
|
||||||
LPT 12845A printer controller with 2607 printer
|
LPS 12653A printer controller with 2767 line printer
|
||||||
CLK 12539A/B/C time base generator
|
12566B microcircuit interface with loopback connector
|
||||||
MUXL,MUXU,MUXC 12920A terminal multiplexor
|
LPT 12845B printer controller with 2607 line printer
|
||||||
|
CLK 12539C time base generator
|
||||||
|
MUX,MUXL,MUXM 12920A terminal multiplexor
|
||||||
DP 12557A disk controller with four 2871 drives
|
DP 12557A disk controller with four 2871 drives
|
||||||
13210A disk controller with four 7900 drives
|
13210A disk controller with four 7900 drives
|
||||||
DQ 12565A disk controller with two 2883 drives
|
DQ 12565A disk controller with two 2883 drives
|
||||||
DR 12606B fixed head disk controller with 2770/2771 disks
|
DR 12606B fixed head disk controller with 2770/2771 disk
|
||||||
12610B drum controller with 2773/2774/2775 drums
|
12610B drum controller with 2773/2774/2775 drum
|
||||||
MT 12559C magnetic tape controller with one 3030 drive
|
MT 12559C magnetic tape controller with one 3030 drive
|
||||||
MS 13181A magnetic tape controller with four 7970B drives
|
MS 13181A magnetic tape controller with four 7970B drives
|
||||||
13183A magnetic tape controller with four 7970E drives
|
13183A magnetic tape controller with four 7970E drives
|
||||||
IPLI 12556B interprocessor link, input side
|
IPLI 12566B interprocessor link, input side
|
||||||
IPLO 12556B interprocessor link, output side
|
IPLO 12566B interprocessor link, output side
|
||||||
|
|
||||||
The HP2100 simulator implements several unique stop conditions:
|
The HP2100 simulator implements several unique stop conditions:
|
||||||
|
|
||||||
|
@ -109,7 +111,12 @@ command is not implemented.
|
||||||
|
|
||||||
2.1 CPU
|
2.1 CPU
|
||||||
|
|
||||||
CPU options include choice of instruction set and memory size.
|
CPU options include choice of instruction set and memory size. The
|
||||||
|
general command form is:
|
||||||
|
|
||||||
|
SET {-F} CPU <option>
|
||||||
|
|
||||||
|
Options that may be specified are:
|
||||||
|
|
||||||
SET CPU 2116 2116 CPU
|
SET CPU 2116 2116 CPU
|
||||||
SET CPU 2100 2100 CPU
|
SET CPU 2100 2100 CPU
|
||||||
|
@ -133,13 +140,21 @@ CPU options include choice of instruction set and memory size.
|
||||||
SET CPU 1024K set memory size = 1024K (21MX only)
|
SET CPU 1024K set memory size = 1024K (21MX only)
|
||||||
|
|
||||||
On the 2100, EAU is standard, and the FP and IOP options are mutually
|
On the 2100, EAU is standard, and the FP and IOP options are mutually
|
||||||
exclusive. On the 21MX, EAU and FP are standard. The 2100 and 21MX
|
exclusive. On the 21MX, EAU and FP are standard. The 21MX optionally
|
||||||
include memory protection as standard; the 21MX optionally includes
|
includes DMS (dynamic mapping system) and IOP instructions.
|
||||||
DMS (dynamic memory system).
|
|
||||||
|
|
||||||
If memory size is being reduced, and the memory being truncated contains
|
Setting the CPU type to 2116, 2100, or 21MX establishes a consistent set
|
||||||
non-zero data, the simulator asks for confirmation. Data in the truncated
|
of common options. Additional SET CPU commands may follow to fine-tune
|
||||||
portion of memory is lost. Initial memory size is 32K.
|
the desired feature set.
|
||||||
|
|
||||||
|
The initial memory size is 32K. Memory sizes larger than 32K are
|
||||||
|
supported only on the 21MX. If the memory size is being reduced, either
|
||||||
|
by setting a smaller size or by changing the CPU model from 21MX to 2116
|
||||||
|
or 2100 when the current memory size is more than 32K, and the memory
|
||||||
|
being truncated contains non-zero data, the simulator asks for
|
||||||
|
confirmation before proceeding. The confirmation request may be
|
||||||
|
suppressed by using the "-F" switch. Data in the truncated portion of
|
||||||
|
memory is lost.
|
||||||
|
|
||||||
These switches are recognized when examining or depositing in CPU memory:
|
These switches are recognized when examining or depositing in CPU memory:
|
||||||
|
|
||||||
|
@ -173,16 +188,9 @@ control registers for the interrupt system.
|
||||||
O all 1 overflow flag
|
O all 1 overflow flag
|
||||||
ION all 1 interrupt enable flag
|
ION all 1 interrupt enable flag
|
||||||
ION_DEFER all 1 interrupt defer flag
|
ION_DEFER all 1 interrupt defer flag
|
||||||
CIR all 6 current interrupt register
|
CIR all 6 central interrupt register
|
||||||
MPCTL 2100,21MX 1 memory protection enable
|
|
||||||
MPFLG 2100,21MX 1 memory protection flag
|
|
||||||
MPFBF 2100,21MX 1 memory protection flag buffer
|
|
||||||
MPFR 2100,21MX 15 memory protection fence
|
|
||||||
MPVR 2100,21MX 16 memory protection violation reg
|
|
||||||
MPEVR 2100,21MX 1 memory protection freeze flag
|
|
||||||
MPMEV 2100,21MX 1 memory protection DMS error flag
|
|
||||||
DMSENB 21MX 1 DMS enable
|
DMSENB 21MX 1 DMS enable
|
||||||
DMSCUR 21MX 1 DMS current mode
|
DMSCUR 21MX 1 DMS current map (1 = user map)
|
||||||
DMSSR 21MX 16 DMS status register
|
DMSSR 21MX 16 DMS status register
|
||||||
DMSVR 21MX 16 DMS violation register
|
DMSVR 21MX 16 DMS violation register
|
||||||
DMSMAP[128] 21MX 16 DMS maps
|
DMSMAP[128] 21MX 16 DMS maps
|
||||||
|
@ -195,12 +203,11 @@ control registers for the interrupt system.
|
||||||
INDMAX all 16 indirect address limit
|
INDMAX all 16 indirect address limit
|
||||||
PCQ[0:63] all 15 P of last JMP, JSB, or interrupt;
|
PCQ[0:63] all 15 P of last JMP, JSB, or interrupt;
|
||||||
most recent P change first
|
most recent P change first
|
||||||
WRU all 8 interrupt character
|
|
||||||
|
|
||||||
BOOT CPU implements the 21MX IBL facility. IBL is controlled by the switch
|
BOOT CPU implements the 21MX IBL facility. IBL is controlled by the switch
|
||||||
register S. S<15:14> selects the device to boot:
|
register S. S<15:14> selects the device to boot:
|
||||||
|
|
||||||
00 paper-tape reader (12992K ROM)
|
00 2748B paper-tape reader (12992K ROM)
|
||||||
01 7900A/2883 disk (12992A ROM)
|
01 7900A/2883 disk (12992A ROM)
|
||||||
10 7970B/E tape (12992D ROM)
|
10 7970B/E tape (12992D ROM)
|
||||||
11 undefined
|
11 undefined
|
||||||
|
@ -215,10 +222,51 @@ specifies the lower address. S<5:3> are passed to the bootstrap program.
|
||||||
S<2:0> specify options for the boot loader. IBL will not report an error if
|
S<2:0> specify options for the boot loader. IBL will not report an error if
|
||||||
the device address in S<11:6> is incorrect.
|
the device address in S<11:6> is incorrect.
|
||||||
|
|
||||||
2.2 DMA Controllers
|
2.2 Memory Protect
|
||||||
|
|
||||||
The HP2100 includes two DMA channel controllers (DMA0 and DMA1). Each
|
Memory protect is standard equipment on the 2100 (although it may be
|
||||||
DMA channel has the following visible state:
|
disabled by removing a jumper) and optional on the 2116 and 21MX. The
|
||||||
|
following registers are implemented:
|
||||||
|
|
||||||
|
name size comments
|
||||||
|
|
||||||
|
CTL 1 memory protection enable
|
||||||
|
FLG 1 protection violation flag
|
||||||
|
FBF 1 protection violation flag buffer
|
||||||
|
FR 15 fence register
|
||||||
|
VR 16 violation register
|
||||||
|
EVR 1 enable violation register flag
|
||||||
|
MEV 1 memory expansion (DMS) violation flag
|
||||||
|
|
||||||
|
The 21MX memory protect card (12892B) has three feature options that
|
||||||
|
are implemented by jumper settings. These are controlled by the
|
||||||
|
following commands:
|
||||||
|
|
||||||
|
SET MP JSBIN jumper W5 installed
|
||||||
|
SET MP JSBOUT jumper W5 removed
|
||||||
|
SET MP INTIN jumper W6 installed
|
||||||
|
SET MP INTOUT jumper W6 removed
|
||||||
|
SET MP SEL1IN jumper W7 installed
|
||||||
|
SET MP SEL1OUT jumper W7 removed
|
||||||
|
|
||||||
|
W5 determines whether JSB instructions referencing memory locations 0
|
||||||
|
and 1 are legal (installed) or illegal (removed). W6 controls whether
|
||||||
|
the first three levels of indirect addressing hold off (installed) or
|
||||||
|
permit (removed) pending interrupts. W7 determines whether I/O
|
||||||
|
instructions referencing select codes other than 1 are legal (installed)
|
||||||
|
or illegal (removed); note that I/O instructions referencing select code
|
||||||
|
1 are legal, and HLT instructions are illegal, regardless of the setting
|
||||||
|
of W7.
|
||||||
|
|
||||||
|
The default configuration is JSB (W5) installed, INT (W6) installed, and
|
||||||
|
SEL1 (W7) removed, providing compatibility with the 2116 and 2100 memory
|
||||||
|
protect cards.
|
||||||
|
|
||||||
|
2.3 DMA/DCPC Controllers
|
||||||
|
|
||||||
|
The direct memory access/dual channel port controller is an option for
|
||||||
|
all three CPUs. DMA/DCPC provides two channel controllers (DMA0 and
|
||||||
|
DMA1). Each DMA channel has the following visible state:
|
||||||
|
|
||||||
name size comments
|
name size comments
|
||||||
|
|
||||||
|
@ -230,7 +278,7 @@ DMA channel has the following visible state:
|
||||||
CW2 16 command word 2
|
CW2 16 command word 2
|
||||||
CW3 16 command word 3
|
CW3 16 command word 3
|
||||||
|
|
||||||
2.3 Variable Device Assignments
|
2.4 Variable Device Assignments
|
||||||
|
|
||||||
On the HP2100, I/O device take their device numbers from the backplane
|
On the HP2100, I/O device take their device numbers from the backplane
|
||||||
slot they are plugged into. Thus, device number assignments vary
|
slot they are plugged into. Thus, device number assignments vary
|
||||||
|
@ -253,25 +301,47 @@ changed; the higher is automatically set to the lower + 1. If a
|
||||||
device number conflict occurs, the simulator will return an error
|
device number conflict occurs, the simulator will return an error
|
||||||
when started.
|
when started.
|
||||||
|
|
||||||
In addition, most devices can be enabled or disabled. To enable a
|
2.4.1 Device State
|
||||||
device, use the SET <dev> ENABLED command:
|
|
||||||
|
|
||||||
sim> SET DPC ENABLED
|
All devices other than the CPU and TTY may be disabled or enabled.
|
||||||
|
Disabling a device simulates removing the associated interface from the
|
||||||
|
CPU card cage. To disable or enable a device, use:
|
||||||
|
|
||||||
To disable a device, use the SET <dev> DISABLED command:
|
SET <dev> DISABLED disable device
|
||||||
|
SET <dev> ENABLED enable device
|
||||||
sim> SET DPC DISABLED
|
|
||||||
|
|
||||||
For devices with more than one device number, disabling or enabling any
|
For devices with more than one device number, disabling or enabling any
|
||||||
device in the set disables all the devices.
|
device in the set disables or enables all of the devices.
|
||||||
|
|
||||||
2.4 Programmed I/O Devices
|
Devices consisting of multiple addressible units connected to a controller
|
||||||
|
typically allow the units to be individually enabled or disabled. Disabled
|
||||||
|
simulates disconnecting the associated unit from the controller. The
|
||||||
|
commands to set units enabled and disabled are:
|
||||||
|
|
||||||
2.4.1 12597A-002 Paper Tape Reader (PTR)
|
SET <unit> DISABLED disable unit
|
||||||
|
SET <unit> ENABLED enable unit
|
||||||
|
|
||||||
The paper tape reader (PTR) reads data from a disk file. The POS
|
Some devices and units allow simulation of power-down conditions. Power
|
||||||
register specifies the number of the next data item to be read.
|
settings are controlled by these commands:
|
||||||
Thus, by changing POS, the user can backspace or advance the reader.
|
|
||||||
|
SET <dev> POWEROFF turn power off
|
||||||
|
SET <dev> POWERON turn power on
|
||||||
|
|
||||||
|
Peripherals that provide operator-selectable disconnection, typically via an
|
||||||
|
"offline" switch, provide these simulation equivalents:
|
||||||
|
|
||||||
|
SET <dev> OFFLINE set peripheral offline
|
||||||
|
SET <dev> ONLINE set peripheral online
|
||||||
|
|
||||||
|
2.5 Programmed I/O Devices
|
||||||
|
|
||||||
|
2.5.1 12597A-002 Duplex Register Interface (PTR) with 2748 Paper Tape Reader
|
||||||
|
|
||||||
|
The paper tape reader (PTR) reads data from a disk file. For diagnostic
|
||||||
|
purposes, a tape loop may be simulated with the commands:
|
||||||
|
|
||||||
|
SET PTR DIAG rewind tape at EOF
|
||||||
|
SET PTR READER supply tape trailer at EOF
|
||||||
|
|
||||||
The paper tape reader supports the BOOT command. BOOT PTR copies the
|
The paper tape reader supports the BOOT command. BOOT PTR copies the
|
||||||
IBL into memory and starts it running. The switch register (S) is
|
IBL into memory and starts it running. The switch register (S) is
|
||||||
|
@ -298,6 +368,13 @@ The paper tape reader implements these registers:
|
||||||
TIME 24 time from I/O initiation to interrupt
|
TIME 24 time from I/O initiation to interrupt
|
||||||
STOP_IOE 1 stop on I/O error
|
STOP_IOE 1 stop on I/O error
|
||||||
|
|
||||||
|
The TRLLIM register specifies the number of nulls to supply as paper
|
||||||
|
tape trailer when EOF is detected. If TRLLIM is set to zero or the
|
||||||
|
count is exhausted, the reader will hang.
|
||||||
|
|
||||||
|
The POS register specifies the number of the next data item to be read.
|
||||||
|
Thus, by changing POS, the user can backspace or advance the reader.
|
||||||
|
|
||||||
Error handling is as follows:
|
Error handling is as follows:
|
||||||
|
|
||||||
error STOP_IOE processed as
|
error STOP_IOE processed as
|
||||||
|
@ -306,11 +383,11 @@ Error handling is as follows:
|
||||||
0 out of tape
|
0 out of tape
|
||||||
|
|
||||||
end of file 1 report error and stop
|
end of file 1 report error and stop
|
||||||
0 out of tape or paper
|
0 out of tape
|
||||||
|
|
||||||
OS I/O error x report error and stop
|
OS I/O error x report error and stop
|
||||||
|
|
||||||
2.4.2 12597A-005 Paper Tape Punch (PTP)
|
2.5.2 12597A-005 Duplex Register Interface (PTP) with 2895 Paper Tape Punch
|
||||||
|
|
||||||
The paper tape punch (PTP) writes data to a disk file. The POS
|
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.
|
register specifies the number of the next data item to be written.
|
||||||
|
@ -339,23 +416,22 @@ Error handling is as follows:
|
||||||
|
|
||||||
OS I/O error x report error and stop
|
OS I/O error x report error and stop
|
||||||
|
|
||||||
2.4.3 12531C Buffered Terminal (TTY)
|
2.5.3 12531C Buffered Teleprinter Interface (TTY) with 2752 Teleprinter
|
||||||
|
|
||||||
The console terminal has three units: keyboard (unit 0), printer
|
The console teleprinter has three units: keyboard (unit 0), printer
|
||||||
(unit 1), and punch (unit 2). The keyboard reads from the console
|
(unit 1), and punch (unit 2). The keyboard reads from the console
|
||||||
keyboard; the printer writes to the simulator console window. The
|
keyboard; the printer writes to the simulator console window. The punch
|
||||||
punch writes to a disk file. The keyboard and printer units (TTY0,
|
writes to a disk file. The keyboard and printer units (TTY0, TTY1) can
|
||||||
TTY1) can be set to one of three modes: UC, 7B, or 8B. In UC mode,
|
be set to one of three modes: UC, 7B, or 8B. In UC mode, lower case
|
||||||
lower case input and output characters are automatically converted to
|
input and output characters are automatically converted to upper case.
|
||||||
upper case. In 7B mode, input and output characters are masked to 7
|
In 7B mode, input and output characters are masked to 7 bits. In 8B
|
||||||
bits. In 8B mode, characters are not modified. In UC and 7B mode,
|
mode, characters are not modified. In UC and 7B mode, output of control
|
||||||
output of null characters is suppressed; in 8B mode, output of null
|
characters other than BEL, BS, HT, LF, and CR is suppressed; in 8B mode,
|
||||||
characters is permitted. Changing the mode of either the keyboard
|
output of all characters is permitted. Changing the mode of either the
|
||||||
or the printer changes both. The default mode is UC.
|
keyboard or the printer changes both. The default mode is UC.
|
||||||
|
|
||||||
Some HP software systems expect the console terminal to transmit
|
Some HP software systems expect the console to transmit line-feed
|
||||||
line-feed automatically following carriage-return. This feature is
|
automatically following carriage-return. This feature is enabled with:
|
||||||
enabled with:
|
|
||||||
|
|
||||||
SET TTY AUTOLF
|
SET TTY AUTOLF
|
||||||
|
|
||||||
|
@ -389,22 +465,43 @@ Error handling for the punch is as follows:
|
||||||
|
|
||||||
OS I/O error x report error and stop
|
OS I/O error x report error and stop
|
||||||
|
|
||||||
2.4.4 12653A Printer Controller (LPS) with 2767 Printer
|
2.5.4 12653A Printer Controller (LPS) with 2767 Line Printer
|
||||||
12566B Microcircuit Interface
|
12566B Microcircuit Interface with Loopback Connector
|
||||||
|
|
||||||
The 12653A line printer uses the 12566B microcircuit interface as
|
The 2767 line printer uses the 12653A line printer interface as
|
||||||
its controller. As a line printer, LPS writes data to a disk file.
|
its controller. As a line printer, LPS writes data to a disk file.
|
||||||
The POS register specifies the number of the next data item to be
|
The POS register specifies the number of the next data item to be
|
||||||
written. Thus, by changing POS, the user can backspace or advance
|
written. Thus, by changing POS, the user can backspace or advance
|
||||||
the printer.
|
the printer.
|
||||||
|
|
||||||
As a microcircuit interface, LPS provides the DMA test device for
|
The line printer responds to SET LPS POWEROFF as if the power were removed
|
||||||
running the dual channel port controller and DMS diagnostics. Printer
|
or the printer cable were disconnected and DETACH LPS as if the paper were
|
||||||
mode verus diagnostic mode is controlled by the commands:
|
out. It also provides these additional state commands:
|
||||||
|
|
||||||
|
SET LPS OFFLINE simulate ONLINE button up
|
||||||
|
SET LPS ONLINE simulate ONLINE button down
|
||||||
|
SET LPS REALTIME use realistic timing for print operations
|
||||||
|
SET LPS FASTTIME use optimized timing for print operations
|
||||||
|
|
||||||
|
As a 12566B microcircuit interface, LPS provides the test device for
|
||||||
|
running several of the HP diagnostics. Printer mode verus diagnostic
|
||||||
|
mode is controlled by the commands:
|
||||||
|
|
||||||
SET LPS PRINTER configure as line printer
|
SET LPS PRINTER configure as line printer
|
||||||
SET LPS DIAG configure for diagnostic tests
|
SET LPS DIAG configure for diagnostic tests
|
||||||
|
|
||||||
|
In diagnostic mode, LPS simulates the installation of the HP 1251-0332
|
||||||
|
diagnostic test (loopback) connector onto the 12566B card.
|
||||||
|
|
||||||
|
LPS may be configured to send debugging information to the previously
|
||||||
|
enabled debug output device using these commands:
|
||||||
|
|
||||||
|
SET LPS DEBUG provide debug printouts
|
||||||
|
SET LPS NODEBUG inhibit debug printouts
|
||||||
|
|
||||||
|
Diagnostic information includes characters supplied to and status received
|
||||||
|
from the interface, as well as data transfer initiations and completions.
|
||||||
|
|
||||||
The 12653A is disabled by default.
|
The 12653A is disabled by default.
|
||||||
|
|
||||||
The 12653A implements these registers:
|
The 12653A implements these registers:
|
||||||
|
@ -413,14 +510,19 @@ The 12653A implements these registers:
|
||||||
|
|
||||||
BUF 16 output buffer
|
BUF 16 output buffer
|
||||||
STA 16 input buffer or status
|
STA 16 input buffer or status
|
||||||
|
POWER 2 printer power state
|
||||||
CMD 1 printer enable
|
CMD 1 printer enable
|
||||||
CTL 1 device/interrupt enable
|
CTL 1 device/interrupt enable
|
||||||
FLG 1 device ready
|
FLG 1 device ready
|
||||||
FBF 1 device ready buffer
|
FBF 1 device ready buffer
|
||||||
SRQ 1 device DMA service request
|
SRQ 1 device DMA service request
|
||||||
|
CCNT 7 current character count
|
||||||
|
LCNT 7 current line count
|
||||||
POS 32 position in the output file
|
POS 32 position in the output file
|
||||||
CTIME 24 time between characters
|
CTIME 24 character transfer time
|
||||||
PTIME 24 time for a print operation
|
PTIME 24 per-zone print operation time
|
||||||
|
STIME 24 per-line paper slew time
|
||||||
|
RTIME 24 power-on ready delay time
|
||||||
STOP_IOE 1 stop on I/O error
|
STOP_IOE 1 stop on I/O error
|
||||||
|
|
||||||
In printer mode, error handling is as follows:
|
In printer mode, error handling is as follows:
|
||||||
|
@ -428,19 +530,26 @@ In printer mode, error handling is as follows:
|
||||||
error STOP_IOE processed as
|
error STOP_IOE processed as
|
||||||
|
|
||||||
not attached 1 report error and stop
|
not attached 1 report error and stop
|
||||||
0 out of tape or paper
|
0 out of paper
|
||||||
|
|
||||||
OS I/O error x report error and stop
|
OS I/O error x report error and stop
|
||||||
|
|
||||||
In diagnostic mode, there are no errors; data sent to the output
|
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.
|
buffer is looped back to the status register with a fixed delay of 1.
|
||||||
|
|
||||||
2.4.5 12845A Printer Controller (LPT)
|
2.5.5 12845B Printer Controller (LPT) with 2607 Line Printer
|
||||||
|
|
||||||
The line printer (LPT) writes data to a disk file. The POS register
|
The line printer (LPT) writes data to a disk file. The POS register
|
||||||
specifies the number of the next data item to be written. Thus,
|
specifies the number of the next data item to be written. Thus,
|
||||||
by changing POS, the user can backspace or advance the printer.
|
by changing POS, the user can backspace or advance the printer.
|
||||||
|
|
||||||
|
The line printer responds to SET LPT POWEROFF as if the power were
|
||||||
|
removed or the printer cable were disconnected and DETACH LPT as if the
|
||||||
|
paper were out. It also provides these additional state commands:
|
||||||
|
|
||||||
|
SET LPT OFFLINE simulate PAPER button up
|
||||||
|
SET LPT ONLINE simulate PAPER button down
|
||||||
|
|
||||||
The line printer implements these registers:
|
The line printer implements these registers:
|
||||||
|
|
||||||
name size comments
|
name size comments
|
||||||
|
@ -462,13 +571,22 @@ Error handling is as follows:
|
||||||
error STOP_IOE processed as
|
error STOP_IOE processed as
|
||||||
|
|
||||||
not attached 1 report error and stop
|
not attached 1 report error and stop
|
||||||
0 out of tape or paper
|
0 out of paper
|
||||||
|
|
||||||
OS I/O error x report error and stop
|
OS I/O error x report error and stop
|
||||||
|
|
||||||
2.4.6 12539A/B/C Time Base Generator (CLK)
|
2.5.6 12539C Time Base Generator (CLK)
|
||||||
|
|
||||||
The time base generator (CLK) implements these registers:
|
The time base generator (CLK) may be set for diagnostic mode:
|
||||||
|
|
||||||
|
SET CLK DIAG configure for diagnostic mode
|
||||||
|
SET CLK CALIBRATED configure for timing mode
|
||||||
|
|
||||||
|
Diagnostic mode corresponds to setting jumper W2 to position "B". This
|
||||||
|
turns off autocalibration and divides the longest time intervals down by
|
||||||
|
1000.
|
||||||
|
|
||||||
|
The time base generator implements these registers:
|
||||||
|
|
||||||
name size comments
|
name size comments
|
||||||
|
|
||||||
|
@ -485,7 +603,7 @@ The time base generator autocalibrates; the clock interval is adjusted
|
||||||
up or down so that the clock tracks actual elapsed time. Operation at
|
up or down so that the clock tracks actual elapsed time. Operation at
|
||||||
the fastest rates (100 usec, 1 msec) is not recommended.
|
the fastest rates (100 usec, 1 msec) is not recommended.
|
||||||
|
|
||||||
2.4.7 12920A Terminal Multiplexor (MUXL, MUXU, MUXC)
|
2.5.7 12920A Terminal Multiplexor (MUX, MUXL, MUXM)
|
||||||
|
|
||||||
The 12920A is a 16-line terminal multiplexor, with five additional
|
The 12920A is a 16-line terminal multiplexor, with five additional
|
||||||
receive-only diagnostic lines. It consists of three devices:
|
receive-only diagnostic lines. It consists of three devices:
|
||||||
|
@ -494,7 +612,7 @@ receive-only diagnostic lines. It consists of three devices:
|
||||||
to the upper data card)
|
to the upper data card)
|
||||||
MUXL individual lines (corresponding more or
|
MUXL individual lines (corresponding more or
|
||||||
less to the lower data card)
|
less to the lower data card)
|
||||||
MUXC modem control and status logic (corresponding
|
MUXM modem control and status logic (corresponding
|
||||||
to the control card)
|
to the control card)
|
||||||
|
|
||||||
The MUX performs input and output through Telnet sessions connected to a
|
The MUX performs input and output through Telnet sessions connected to a
|
||||||
|
@ -578,11 +696,11 @@ The modem control (MUXM) implements these registers:
|
||||||
|
|
||||||
|
|
||||||
The terminal multiplexor does not support save and restore. All open
|
The terminal multiplexor does not support save and restore. All open
|
||||||
connections are lost when the simulator shuts down or MUXU is detached.
|
connections are lost when the simulator shuts down or MUX is detached.
|
||||||
|
|
||||||
2.4.8 Interprocessor Link (IPLI, IPLO)
|
2.5.8 Interprocessor Link (IPLI, IPLO)
|
||||||
|
|
||||||
The interprocessor link is a pair of 12556B parallel interfaces that
|
The interprocessor link is a pair of 12566B parallel interfaces that
|
||||||
are cross coupled to provide interprocessor communications to a second
|
are cross coupled to provide interprocessor communications to a second
|
||||||
copy of the HP2100 simulator. The IPL is intended to support simulation
|
copy of the HP2100 simulator. The IPL is intended to support simulation
|
||||||
of a two system HP TimeShared Basic configuration. The links are actually
|
of a two system HP TimeShared Basic configuration. The links are actually
|
||||||
|
@ -636,8 +754,8 @@ Both IPLI and IPLO implement these registers:
|
||||||
TIME 24 polling interval for input
|
TIME 24 polling interval for input
|
||||||
STOP_IOE 1 stop on I/O error
|
STOP_IOE 1 stop on I/O error
|
||||||
|
|
||||||
2.5 12557A Disk Controller (DPC, DPD) with 2781 Drives
|
2.6 12557A Disk Controller (DPC, DPD) with Four 2781 Drives
|
||||||
13210A Disk Controller (DPC, DPD) with 7900 Drives
|
13210A Disk Controller (DPC, DPD) with Four 7900 Drives
|
||||||
|
|
||||||
The 12557A/13210A disk controller can be configured as either a
|
The 12557A/13210A disk controller can be configured as either a
|
||||||
12557A, supporting 2.5MB drives, or a 13210A, supporting 5MB drives,
|
12557A, supporting 2.5MB drives, or a 13210A, supporting 5MB drives,
|
||||||
|
@ -651,9 +769,9 @@ one type or the other. The 13210A (for 7900/7901 disks) is selected
|
||||||
by default.
|
by default.
|
||||||
|
|
||||||
The simulated controller has two separate devices, a data channel and
|
The simulated controller has two separate devices, a data channel and
|
||||||
a device controller. The data channel includes a 128-word (one sector)
|
a command channel. The data channel includes a 128-word (one sector)
|
||||||
buffer for reads and writes. The device controller includes the four
|
buffer for reads and writes. The command channel includes the four
|
||||||
disk drives. Disk drives can be set ONLINE or OFFLINE.
|
disk drives. Disk drives can be set DISABLED or ENABLED.
|
||||||
|
|
||||||
The 12557A/13210A supports the BOOT command. BOOT DPC copies the IBL
|
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
|
for 7900 class disks into memory and starts it running. BOOT -R DPC
|
||||||
|
@ -683,7 +801,7 @@ The data channel implements these registers:
|
||||||
XFER 1 transfer in progress flag
|
XFER 1 transfer in progress flag
|
||||||
WVAL 1 write data valid flag
|
WVAL 1 write data valid flag
|
||||||
|
|
||||||
The device controller implements these registers:
|
The command channel implements these registers:
|
||||||
|
|
||||||
name size comments
|
name size comments
|
||||||
|
|
||||||
|
@ -697,9 +815,10 @@ The device controller implements these registers:
|
||||||
SRQ 1 controller DMA service request
|
SRQ 1 controller DMA service request
|
||||||
EOC 1 end of cylinder pending
|
EOC 1 end of cylinder pending
|
||||||
POLL 1 attention polling enabled
|
POLL 1 attention polling enabled
|
||||||
RARC[0:3] 8 record address register cylinder, drives 0-3
|
RARC 8 record address register (cylinder)
|
||||||
RARH[0:3] 2 record address register head, drives 0-3
|
RARH 2 record address register (head)
|
||||||
RARS[0:3] 4 record address register sector, drives 0-3
|
RARS 4 record address register (sector)
|
||||||
|
CYL[0:3] 8 current cylinder, drives 0-3
|
||||||
STA[0:3] 16 drive status, drives 0-3
|
STA[0:3] 16 drive status, drives 0-3
|
||||||
CTIME 24 data transfer command delay time
|
CTIME 24 data transfer command delay time
|
||||||
DTIME 24 data channel command delay time
|
DTIME 24 data channel command delay time
|
||||||
|
@ -716,12 +835,12 @@ Error handling is as follows:
|
||||||
|
|
||||||
OS I/O error report error and stop
|
OS I/O error report error and stop
|
||||||
|
|
||||||
2.6 12565A Disk Controller (DQC, DQD) with 2883 Drives
|
2.7 12565A Disk Controller (DQC, DQD) with Two 2883 Drives
|
||||||
|
|
||||||
The 12565A disk controller has two separate devices, a data channel and
|
The 12565A disk controller has two separate devices, a data channel and
|
||||||
a device controller. The data channel includes a 128-word (one sector)
|
a command channel. The data channel includes a 128-word (one sector)
|
||||||
buffer for reads and writes. The device controller includes the two
|
buffer for reads and writes. The command channel includes the two
|
||||||
disk drives. Disk drives can be set ONLINE or OFFLINE.
|
disk drives. Disk drives can be set DISABLED or ENABLED.
|
||||||
|
|
||||||
The 12565A supports the BOOT command. BOOT DQC copies the IBL for 2883
|
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)
|
class disks into memory and starts it running. The switch register (S)
|
||||||
|
@ -748,22 +867,24 @@ The data channel implements these registers:
|
||||||
XFER 1 transfer in progress flag
|
XFER 1 transfer in progress flag
|
||||||
WVAL 1 write data valid flag
|
WVAL 1 write data valid flag
|
||||||
|
|
||||||
The device controller implements these registers:
|
The command channel implements these registers:
|
||||||
|
|
||||||
name size comments
|
name size comments
|
||||||
|
|
||||||
OBUF 16 output buffer
|
OBUF 16 output buffer
|
||||||
BUSY 2 busy (unit #, + 1, of active unit)
|
BUSY 2 busy (unit # + 1 of active unit)
|
||||||
CNT 9 check record count
|
CNT 9 check record count
|
||||||
CMD 1 controller enable
|
CMD 1 controller enable
|
||||||
CTL 1 interrupt enable
|
CTL 1 interrupt enable
|
||||||
FLG 1 controller ready
|
FLG 1 controller ready
|
||||||
FBF 1 controller ready buffer
|
FBF 1 controller ready buffer
|
||||||
SRQ 1 controller DMA service request
|
SRQ 1 controller DMA service request
|
||||||
RARC[0:1] 8 record address register cylinder, drives 0-1
|
RARC 8 record address register (cylinder)
|
||||||
RARH[0:1] 5 record address register head, drives 0-1
|
RARH 5 record address register (head)
|
||||||
RARS[0:1] 5 record address register sector, drives 0-1
|
RARS 5 record address register (sector)
|
||||||
STA[0:1] 16 drive status, drives 0-3
|
CYL[0:1] 8 current cylinder, drives 0-1
|
||||||
|
HED[0:1] 5 current head, drives 0-1
|
||||||
|
STA[0:1] 16 drive status, drives 0-1
|
||||||
CTIME 24 data transfer command delay time
|
CTIME 24 data transfer command delay time
|
||||||
DTIME 24 data channel command delay time
|
DTIME 24 data channel command delay time
|
||||||
STIME 24 seek delay time, per cylinder
|
STIME 24 seek delay time, per cylinder
|
||||||
|
@ -779,23 +900,45 @@ Error handling is as follows:
|
||||||
|
|
||||||
OS I/O error report error and stop
|
OS I/O error report error and stop
|
||||||
|
|
||||||
2.7 12606B Fixed Head Disk Controller (DRC, DRD) with 2770/2771 Disk
|
2.8 12606B Fixed Head Disk Controller (DRC, DRD) with 2770/2771 Disk
|
||||||
12610B Drum Controller (DRC, DRD) with 2773/2774/2775 Drum
|
12610B Drum Controller (DRC, DRD) with 2773/2774/2775 Drum
|
||||||
|
|
||||||
The 12606B/12610B fixed head disk/drum controller has two separate devices,
|
The 12606B/12610B fixed head disk/drum controller has two separate devices,
|
||||||
a data channel and a device controller. The device controller includes the
|
a data channel and a command channel.
|
||||||
actual drive. Ten different models are supported:
|
|
||||||
|
|
||||||
SET DRC 180K 12606B, 180K words
|
The command channel includes the actual drive. Ten different models are
|
||||||
SET DRC 360K 12606B, 360K words
|
supported:
|
||||||
SET DRC 720K 12606B, 720K words
|
|
||||||
SET DRC 384K 12610B, 84K words
|
command interface and size model
|
||||||
SET DRC 512K 12610B, 512K words
|
|
||||||
SET DRC 640K 12610B, 640K words
|
SET DRC 180K 12606B, 180K words 2770A
|
||||||
SET DRC 768K 12610B, 768K words
|
SET DRC 360K 12606B, 360K words 2771A
|
||||||
SET DRC 896K 12610B, 896K words
|
SET DRC 720K 12606B, 720K words 2771A-001
|
||||||
SET DRC 1024K 12610B, 1024K words
|
SET DRC 384K 12610B, 384K words 2773A
|
||||||
SET DRC 1536K 12610B, 1536K words
|
SET DRC 512K 12610B, 512K words 2773A-001
|
||||||
|
SET DRC 640K 12610B, 640K words 2773A-002
|
||||||
|
SET DRC 768K 12610B, 768K words 2774A
|
||||||
|
SET DRC 896K 12610B, 896K words 2774A-001
|
||||||
|
SET DRC 1024K 12610B, 1024K words 2774A-002
|
||||||
|
SET DRC 1536K 12610B, 1536K words 2775A
|
||||||
|
|
||||||
|
The command channel supports write-protected tracks. Track protection
|
||||||
|
is enabled with this command:
|
||||||
|
|
||||||
|
SET DRC PROTECTED
|
||||||
|
|
||||||
|
In addition, the number of protected tracks is specified by the command:
|
||||||
|
|
||||||
|
SET DRC TRACKPROT=count
|
||||||
|
|
||||||
|
The track protect count must be a power of two from 1 to 128 on the 12606
|
||||||
|
interface and from 1 to 512, or 768, on the 12610 interface. If the drive
|
||||||
|
has fewer tracks than the track protect count, then all tracks on the drive
|
||||||
|
are eligible for protection.
|
||||||
|
|
||||||
|
Track protection is disabled with this command:
|
||||||
|
|
||||||
|
SET DRC UNPROTECTED
|
||||||
|
|
||||||
The 12606B/12610B support the BOOT command. The BOOT command loads the
|
The 12606B/12610B support the BOOT command. The BOOT command loads the
|
||||||
first sector from the disk or drum into locations 0-77 and then jumps to 77.
|
first sector from the disk or drum into locations 0-77 and then jumps to 77.
|
||||||
|
@ -815,12 +958,13 @@ The data channel implements these registers:
|
||||||
SRQ 1 channel DMA service request
|
SRQ 1 channel DMA service request
|
||||||
BPTR 6 sector buffer pointer
|
BPTR 6 sector buffer pointer
|
||||||
|
|
||||||
The device controller implements these registers:
|
The command channel implements these registers:
|
||||||
|
|
||||||
name size comments
|
name size comments
|
||||||
|
|
||||||
CW 16 command word
|
CW 16 command word
|
||||||
STA 16 status
|
STA 16 status
|
||||||
|
RUN 1 run flip-flop
|
||||||
CMD 1 controller enable
|
CMD 1 controller enable
|
||||||
CTL 1 interrupt enable
|
CTL 1 interrupt enable
|
||||||
FLG 1 controller ready
|
FLG 1 controller ready
|
||||||
|
@ -838,7 +982,7 @@ Error handling is as follows:
|
||||||
12606B/12610B data files are buffered in memory; therefore, end of file
|
12606B/12610B data files are buffered in memory; therefore, end of file
|
||||||
and OS I/O errors cannot occur.
|
and OS I/O errors cannot occur.
|
||||||
|
|
||||||
2.8 12559C Magnetic Tape Controller (MTC, MTD) with 3030 Drive
|
2.9 12559C Magnetic Tape Controller (MTC, MTD) with One 3030 Drive
|
||||||
|
|
||||||
Magnetic tape options include the ability to make the unit write enabled
|
Magnetic tape options include the ability to make the unit write enabled
|
||||||
or write locked.
|
or write locked.
|
||||||
|
@ -847,8 +991,8 @@ or write locked.
|
||||||
SET MTC WRITEENABLED set unit write enabled
|
SET MTC WRITEENABLED set unit write enabled
|
||||||
|
|
||||||
The 12559C mag tape drive has two separate devices, a data channel and
|
The 12559C mag tape drive has two separate devices, a data channel and
|
||||||
a device controller. The data channel includes a maximum record sized
|
a command channel. The data channel includes a maximum record sized
|
||||||
buffer for reads and writes. The device controller includes the tape
|
buffer for reads and writes. The command channel includes the tape
|
||||||
unit.
|
unit.
|
||||||
|
|
||||||
The BOOT command is not supported. The 12559C was HP's earliest tape
|
The BOOT command is not supported. The 12559C was HP's earliest tape
|
||||||
|
@ -865,7 +1009,7 @@ The data channel implements these registers:
|
||||||
BPTR 16 buffer pointer (reads and writes)
|
BPTR 16 buffer pointer (reads and writes)
|
||||||
BMAX 16 buffer size (writes)
|
BMAX 16 buffer size (writes)
|
||||||
|
|
||||||
The device controller implements these registers:
|
The command channel implements these registers:
|
||||||
|
|
||||||
name size comments
|
name size comments
|
||||||
|
|
||||||
|
@ -893,8 +1037,8 @@ Error handling is as follows:
|
||||||
|
|
||||||
OS I/O error parity error; if STOP_IOE, stop
|
OS I/O error parity error; if STOP_IOE, stop
|
||||||
|
|
||||||
2.9 13181A Magnetic Tape Controller (MSC, MSD) with 7970B Drives
|
2.10 13181A Magnetic Tape Controller (MSC, MSD) with Four 7970B Drives
|
||||||
18183A Magnetic Tape Controller (MSC, MSD) with 7970E Drives
|
18183A Magnetic Tape Controller (MSC, MSD) with Four 7970E Drives
|
||||||
|
|
||||||
Magnetic tape options include the ability to make the unit write enabled
|
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
|
or write locked, and the ability to select the 13181A (800 bpi) controller
|
||||||
|
@ -905,29 +1049,38 @@ or the 13183A (1600 bpi) controller.
|
||||||
SET MSC 13181A set controller to 13181A
|
SET MSC 13181A set controller to 13181A
|
||||||
SET MSC 13183A set controller to 13183A
|
SET MSC 13183A set controller to 13183A
|
||||||
SET MSC REALTIME set controller to actual timing
|
SET MSC REALTIME set controller to actual timing
|
||||||
SET MSC FASTIME set controller to optimized timing (default)
|
SET MSC FASTTIME set controller to optimized timing (default)
|
||||||
SET MSCn REEL=length set unit tape reel size
|
SET MSCn REEL=length set unit tape reel size
|
||||||
0 = unlimited (default)
|
0 = unlimited (default)
|
||||||
600 = 600 feet
|
600 = 600 feet
|
||||||
1200 = 1200 feet
|
1200 = 1200 feet
|
||||||
2400 = 2400 feet
|
2400 = 2400 feet
|
||||||
|
|
||||||
|
MSC may be configured to send debugging information to the previously
|
||||||
|
enabled debug output device using these commands:
|
||||||
|
|
||||||
|
SET MSC DEBUG provide debug printouts
|
||||||
|
SET MSC NODEBUG inhibit debug printouts
|
||||||
|
|
||||||
|
Diagnostic information includes commands supplied to and status received
|
||||||
|
from the interface, as well as command initiations and completions.
|
||||||
|
|
||||||
The 13181A/13183A mag tape drive has two separate devices, a data channel
|
The 13181A/13183A mag tape drive has two separate devices, a data channel
|
||||||
and a device controller. The data channel includes a maximum record
|
and a command channel. The data channel includes a maximum record
|
||||||
sized buffer for reads and writes. The device controller includes the
|
sized buffer for reads and writes. The command channel includes the
|
||||||
tape units.
|
tape units.
|
||||||
|
|
||||||
The 13181A/13183A supports the BOOT command. BOOT MSC loads the IBL for
|
The 13181A/13183A supports the BOOT command. BOOT MSC loads the IBL for
|
||||||
7970B/E magnetic tape drives into memory and starts it running. BOOT -S
|
7970B/E magnetic tape drives into memory and starts it running. BOOT -S
|
||||||
MSC causes the loader to space forward the number of files specified in
|
MSC causes the loader to position to the file number specified in the A
|
||||||
the A register before starting to load data. The switch register (S) is
|
register before starting to load data. The switch register (S) is set
|
||||||
set automatically to the value expected by the IBL loader:
|
automatically to the value expected by the IBL loader:
|
||||||
|
|
||||||
<15:12> = 1000
|
<15:12> = 1000
|
||||||
<11:6> = data channel device code
|
<11:6> = data channel device code
|
||||||
<5:3> = unchanged
|
<5:3> = unchanged
|
||||||
<2:0> = 00
|
<2:0> = 00
|
||||||
<0> = 1 if space forward before loading
|
<0> = 1 if position tape before loading
|
||||||
|
|
||||||
The data channel implements these registers:
|
The data channel implements these registers:
|
||||||
|
|
||||||
|
@ -942,7 +1095,7 @@ The data channel implements these registers:
|
||||||
BPTR 17 buffer pointer (reads and writes)
|
BPTR 17 buffer pointer (reads and writes)
|
||||||
BMAX 17 buffer size (writes)
|
BMAX 17 buffer size (writes)
|
||||||
|
|
||||||
The device controller implements these registers:
|
The command channel implements these registers:
|
||||||
|
|
||||||
name size comments
|
name size comments
|
||||||
|
|
||||||
|
@ -973,7 +1126,7 @@ Error handling is as follows:
|
||||||
|
|
||||||
OS I/O error parity error; if STOP_IOE, stop
|
OS I/O error parity error; if STOP_IOE, stop
|
||||||
|
|
||||||
2.10 Symbolic Display and Input
|
2.11 Symbolic Display and Input
|
||||||
|
|
||||||
The HP2100 simulator implements symbolic display and input. Display is
|
The HP2100 simulator implements symbolic display and input. Display is
|
||||||
controlled by command line switches:
|
controlled by command line switches:
|
||||||
|
|
|
@ -26,6 +26,13 @@
|
||||||
dp 12557A 2871 disk subsystem
|
dp 12557A 2871 disk subsystem
|
||||||
13210A 7900 disk subsystem
|
13210A 7900 disk subsystem
|
||||||
|
|
||||||
|
07-Oct-04 JDB 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
|
||||||
20-Aug-04 JDB Fixes from Dave Bryan
|
20-Aug-04 JDB Fixes from Dave Bryan
|
||||||
- Check status on unattached drive set busy and not ready
|
- Check status on unattached drive set busy and not ready
|
||||||
- Check status tests wrong unit for write protect status
|
- Check status tests wrong unit for write protect status
|
||||||
|
@ -73,6 +80,34 @@
|
||||||
|
|
||||||
dpc_poll indicates whether seek completion polling can occur. It is cleared
|
dpc_poll indicates whether seek completion polling can occur. It is cleared
|
||||||
by reset and CLC CC and set by issuance of a seek or completion of check status.
|
by reset and CLC CC and set by issuance of a seek or completion of check status.
|
||||||
|
|
||||||
|
The controller's "Record Address Register" (RAR) contains the CHS address of
|
||||||
|
the last Seek or Address Record command executed. The RAR is shared among
|
||||||
|
all drives on the controller. In addition, each drive has an internal
|
||||||
|
position register that contains the last cylinder position transferred to the
|
||||||
|
drive during Seek command execution (data operations always start with the
|
||||||
|
RAR head and sector position).
|
||||||
|
|
||||||
|
In a real drive, the address field of the sector under the head is read and
|
||||||
|
compared to the RAR. When they match, the target sector is under the head
|
||||||
|
and is ready for reading or writing. If a match doesn't occur, an Address
|
||||||
|
Error is indicated. In the simulator, the address field is obtained from the
|
||||||
|
drive's current position register during a read, i.e., the "on-disc" address
|
||||||
|
field is assumed to match the current position.
|
||||||
|
|
||||||
|
References:
|
||||||
|
- 7900A Disc Drive Operating and Service Manual (07900-90002, Feb-1975)
|
||||||
|
- 13210A Disc Drive Interface Kit Operating and Service Manual
|
||||||
|
(13210-90003, Nov-1974)
|
||||||
|
- 12557A Cartridge Disc Interface Kit Operating and Service Manual
|
||||||
|
(12557-90001, Sep-1970)
|
||||||
|
|
||||||
|
The following implemented behaviors have been inferred from secondary sources
|
||||||
|
(diagnostics, operating system drivers, etc.), due to absent or contradictory
|
||||||
|
authoritative information; future correction may be needed:
|
||||||
|
|
||||||
|
1. Status bit 15 (ATTENTION) does not set bit 0 (ANY ERROR) on the 12557A.
|
||||||
|
2. Omitting STC DC before Status Check does not set DC flag but does poll.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "hp2100_defs.h"
|
#include "hp2100_defs.h"
|
||||||
|
@ -80,7 +115,7 @@
|
||||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
||||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
#define UNIT_WLK (1 << UNIT_V_WLK)
|
||||||
#define FNC u3 /* saved function */
|
#define FNC u3 /* saved function */
|
||||||
#define CYL u4 /* cylinder */
|
#define DRV u4 /* drive number (DC) */
|
||||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write prot */
|
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write prot */
|
||||||
|
|
||||||
#define DP_N_NUMWD 7
|
#define DP_N_NUMWD 7
|
||||||
|
@ -109,9 +144,9 @@
|
||||||
#define FNC_AR 013 /* address */
|
#define FNC_AR 013 /* address */
|
||||||
#define FNC_SEEK1 020 /* fake - seek1 */
|
#define FNC_SEEK1 020 /* fake - seek1 */
|
||||||
#define FNC_SEEK2 021 /* fake - seek2 */
|
#define FNC_SEEK2 021 /* fake - seek2 */
|
||||||
|
#define FNC_SEEK3 022 /* fake - seek3 */
|
||||||
#define FNC_CHK1 023 /* fake - check1 */
|
#define FNC_CHK1 023 /* fake - check1 */
|
||||||
#define FNC_AR1 024 /* fake - arec1 */
|
#define FNC_AR1 024 /* fake - arec1 */
|
||||||
#define FNC_STA1 025 /* fake - sta1 */
|
|
||||||
#define CW_V_DRV 0 /* drive */
|
#define CW_V_DRV 0 /* drive */
|
||||||
#define CW_M_DRV 03
|
#define CW_M_DRV 03
|
||||||
#define CW_GETDRV(x) (((x) >> CW_V_DRV) & CW_M_DRV)
|
#define CW_GETDRV(x) (((x) >> CW_V_DRV) & CW_M_DRV)
|
||||||
|
@ -152,10 +187,17 @@
|
||||||
#define STA_BSY 0000004 /* seeking */
|
#define STA_BSY 0000004 /* seeking */
|
||||||
#define STA_DTE 0000002 /* data error */
|
#define STA_DTE 0000002 /* data error */
|
||||||
#define STA_ERR 0000001 /* any error (d) */
|
#define STA_ERR 0000001 /* any error (d) */
|
||||||
#define STA_ALLERR (STA_ATN + STA_1ST + STA_OVR + STA_RWU + STA_ACU + \
|
|
||||||
STA_SKI + STA_SKE + STA_NRDY + STA_EOC + STA_AER + \
|
#define STA_ERSET2 (STA_1ST | STA_OVR | STA_RWU | STA_ACU | \
|
||||||
STA_FLG + STA_BSY + STA_DTE)
|
STA_SKI | STA_SKE | STA_NRDY | \
|
||||||
#define STA_MBZ13 (STA_ATN + STA_RWU + STA_SKI) /* zero in 13210 */
|
STA_EOC | STA_AER | STA_DTE) /* 12557A error set */
|
||||||
|
#define STA_ERSET3 (STA_ATN | STA_1ST | STA_OVR | STA_RWU | STA_ACU | \
|
||||||
|
STA_SKI | STA_SKE | STA_NRDY | STA_EOC | STA_AER | \
|
||||||
|
STA_FLG | STA_BSY | STA_DTE) /* 13210A error set */
|
||||||
|
#define STA_ANYERR (dp_ctype ? STA_ERSET3 : STA_ERSET2)
|
||||||
|
|
||||||
|
#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 uint16 *M;
|
||||||
extern uint32 PC, SR;
|
extern uint32 PC, SR;
|
||||||
|
@ -177,9 +219,10 @@ int32 dpc_obuf = 0; /* cch buffers */
|
||||||
int32 dpd_xfer = 0; /* xfer in prog */
|
int32 dpd_xfer = 0; /* xfer in prog */
|
||||||
int32 dpd_wval = 0; /* write data valid */
|
int32 dpd_wval = 0; /* write data valid */
|
||||||
int32 dp_ptr = 0; /* buffer ptr */
|
int32 dp_ptr = 0; /* buffer ptr */
|
||||||
uint8 dpc_rarc[DP_NUMDRV] = { 0 }; /* cylinder */
|
uint8 dpc_rarc = 0; /* RAR cylinder */
|
||||||
uint8 dpc_rarh[DP_NUMDRV] = { 0 }; /* head */
|
uint8 dpc_rarh = 0; /* RAR head */
|
||||||
uint8 dpc_rars[DP_NUMDRV] = { 0 }; /* sector */
|
uint8 dpc_rars = 0; /* RAR sector */
|
||||||
|
uint8 dpc_ucyl[DP_NUMDRV] = { 0 }; /* unit cylinder */
|
||||||
uint16 dpc_sta[DP_NUMDRV] = { 0 }; /* status regs */
|
uint16 dpc_sta[DP_NUMDRV] = { 0 }; /* status regs */
|
||||||
uint16 dpxb[DP_NUMWD]; /* sector buffer */
|
uint16 dpxb[DP_NUMWD]; /* sector buffer */
|
||||||
|
|
||||||
|
@ -216,6 +259,8 @@ UNIT dpd_unit = { UDATA (&dpd_svc, 0, 0) };
|
||||||
REG dpd_reg[] = {
|
REG dpd_reg[] = {
|
||||||
{ ORDATA (IBUF, dpd_ibuf, 16) },
|
{ ORDATA (IBUF, dpd_ibuf, 16) },
|
||||||
{ ORDATA (OBUF, dpd_obuf, 16) },
|
{ ORDATA (OBUF, dpd_obuf, 16) },
|
||||||
|
{ BRDATA (DBUF, dpxb, 8, 16, DP_NUMWD) },
|
||||||
|
{ DRDATA (BPTR, dp_ptr, DP_N_NUMWD) },
|
||||||
{ FLDATA (CMD, dpd_dib.cmd, 0) },
|
{ FLDATA (CMD, dpd_dib.cmd, 0) },
|
||||||
{ FLDATA (CTL, dpd_dib.ctl, 0) },
|
{ FLDATA (CTL, dpd_dib.ctl, 0) },
|
||||||
{ FLDATA (FLG, dpd_dib.flg, 0) },
|
{ FLDATA (FLG, dpd_dib.flg, 0) },
|
||||||
|
@ -223,8 +268,6 @@ REG dpd_reg[] = {
|
||||||
{ FLDATA (SRQ, dpd_dib.srq, 0) },
|
{ FLDATA (SRQ, dpd_dib.srq, 0) },
|
||||||
{ FLDATA (XFER, dpd_xfer, 0) },
|
{ FLDATA (XFER, dpd_xfer, 0) },
|
||||||
{ FLDATA (WVAL, dpd_wval, 0) },
|
{ FLDATA (WVAL, dpd_wval, 0) },
|
||||||
{ BRDATA (DBUF, dpxb, 8, 16, DP_NUMWD) },
|
|
||||||
{ DRDATA (BPTR, dp_ptr, DP_N_NUMWD) },
|
|
||||||
{ ORDATA (DEVNO, dpd_dib.devno, 6), REG_HRO },
|
{ ORDATA (DEVNO, dpd_dib.devno, 6), REG_HRO },
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
|
@ -238,7 +281,7 @@ DEVICE dpd_dev = {
|
||||||
1, 10, DP_N_NUMWD, 1, 8, 16,
|
1, 10, DP_N_NUMWD, 1, 8, 16,
|
||||||
NULL, NULL, &dpc_reset,
|
NULL, NULL, &dpc_reset,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
&dpd_dib, 0 };
|
&dpd_dib, DEV_DISABLE };
|
||||||
|
|
||||||
/* DPC data structures
|
/* DPC data structures
|
||||||
|
|
||||||
|
@ -269,17 +312,16 @@ REG dpc_reg[] = {
|
||||||
{ FLDATA (SRQ, dpc_dib.srq, 0) },
|
{ FLDATA (SRQ, dpc_dib.srq, 0) },
|
||||||
{ FLDATA (EOC, dpc_eoc, 0) },
|
{ FLDATA (EOC, dpc_eoc, 0) },
|
||||||
{ FLDATA (POLL, dpc_poll, 0) },
|
{ FLDATA (POLL, dpc_poll, 0) },
|
||||||
{ BRDATA (RARC, dpc_rarc, 8, 8, DP_NUMDRV) },
|
{ DRDATA (RARC, dpc_rarc, 8), PV_RZRO },
|
||||||
{ BRDATA (RARH, dpc_rarh, 8, 2, DP_NUMDRV) },
|
{ DRDATA (RARH, dpc_rarh, 2), PV_RZRO },
|
||||||
{ BRDATA (RARS, dpc_rars, 8, 4, DP_NUMDRV) },
|
{ DRDATA (RARS, dpc_rars, 5), PV_RZRO },
|
||||||
|
{ BRDATA (CYL, dpc_ucyl, 10, 8, DP_NUMDRV), PV_RZRO },
|
||||||
{ BRDATA (STA, dpc_sta, 8, 16, DP_NUMDRV) },
|
{ BRDATA (STA, dpc_sta, 8, 16, DP_NUMDRV) },
|
||||||
{ DRDATA (CTIME, dpc_ctime, 24), PV_LEFT },
|
{ DRDATA (CTIME, dpc_ctime, 24), PV_LEFT },
|
||||||
{ DRDATA (DTIME, dpc_dtime, 24), PV_LEFT },
|
{ DRDATA (DTIME, dpc_dtime, 24), PV_LEFT },
|
||||||
{ DRDATA (STIME, dpc_stime, 24), PV_LEFT },
|
{ DRDATA (STIME, dpc_stime, 24), PV_LEFT },
|
||||||
{ DRDATA (XTIME, dpc_xtime, 24), REG_NZ + PV_LEFT },
|
{ DRDATA (XTIME, dpc_xtime, 24), REG_NZ | PV_LEFT },
|
||||||
{ FLDATA (CTYPE, dp_ctype, 0), REG_HRO },
|
{ FLDATA (CTYPE, dp_ctype, 0), REG_HRO },
|
||||||
{ URDATA (UCYL, dpc_unit[0].CYL, 10, 8, 0,
|
|
||||||
DP_NUMDRV, PV_LEFT | REG_HRO) },
|
|
||||||
{ URDATA (UFNC, dpc_unit[0].FNC, 8, 8, 0,
|
{ URDATA (UFNC, dpc_unit[0].FNC, 8, 8, 0,
|
||||||
DP_NUMDRV, REG_HRO) },
|
DP_NUMDRV, REG_HRO) },
|
||||||
{ URDATA (CAPAC, dpc_unit[0].capac, 10, T_ADDR_W, 0,
|
{ URDATA (CAPAC, dpc_unit[0].capac, 10, T_ADDR_W, 0,
|
||||||
|
@ -367,15 +409,16 @@ case ioSFC: /* skip flag clear */
|
||||||
case ioSFS: /* skip flag set */
|
case ioSFS: /* skip flag set */
|
||||||
if (FLG (devc) != 0) PC = (PC + 1) & VAMASK;
|
if (FLG (devc) != 0) PC = (PC + 1) & VAMASK;
|
||||||
break;
|
break;
|
||||||
case ioOTX: /* output */
|
|
||||||
dpc_obuf = dat;
|
|
||||||
break;
|
|
||||||
case ioLIX: /* load */
|
case ioLIX: /* load */
|
||||||
dat = 0;
|
dat = 0;
|
||||||
case ioMIX: /* merge */
|
case ioMIX: /* merge */
|
||||||
for (i = 0; i < DP_NUMDRV; i++)
|
for (i = 0; i < DP_NUMDRV; i++)
|
||||||
if (dpc_sta[i] & STA_ATN) dat = dat | (1 << i);
|
if (dpc_sta[i] & STA_ATN) dat = dat | (1 << i);
|
||||||
break;
|
break;
|
||||||
|
case ioOTX: /* output */
|
||||||
|
dpc_obuf = dat;
|
||||||
|
if (!dp_ctype) break;
|
||||||
|
IR = IR | I_CTL; /* 13210 OTx causes CLC */
|
||||||
case ioCTL: /* control clear/set */
|
case ioCTL: /* control clear/set */
|
||||||
if (IR & I_CTL) { /* CLC? */
|
if (IR & I_CTL) { /* CLC? */
|
||||||
clrCTL (devc); /* clr cmd, ctl */
|
clrCTL (devc); /* clr cmd, ctl */
|
||||||
|
@ -419,7 +462,7 @@ return dat;
|
||||||
|
|
||||||
void dp_god (int32 fnc, int32 drv, int32 time)
|
void dp_god (int32 fnc, int32 drv, int32 time)
|
||||||
{
|
{
|
||||||
dpd_unit.CYL = drv; /* save unit */
|
dpd_unit.DRV = drv; /* save unit */
|
||||||
dpd_unit.FNC = fnc; /* save function */
|
dpd_unit.FNC = fnc; /* save function */
|
||||||
sim_activate (&dpd_unit, time);
|
sim_activate (&dpd_unit, time);
|
||||||
return;
|
return;
|
||||||
|
@ -450,7 +493,7 @@ return;
|
||||||
This routine handles the data channel transfers. It also handles
|
This routine handles the data channel transfers. It also handles
|
||||||
data transfers that are blocked by seek in progress.
|
data transfers that are blocked by seek in progress.
|
||||||
|
|
||||||
uptr->CYL = target drive
|
uptr->DRV = target drive
|
||||||
uptr->FNC = target function
|
uptr->FNC = target function
|
||||||
|
|
||||||
Seek substates
|
Seek substates
|
||||||
|
@ -468,62 +511,55 @@ t_stat dpd_svc (UNIT *uptr)
|
||||||
{
|
{
|
||||||
int32 i, drv, devc, devd, st;
|
int32 i, drv, devc, devd, st;
|
||||||
|
|
||||||
drv = uptr->CYL; /* get drive no */
|
drv = uptr->DRV; /* get drive no */
|
||||||
devc = dpc_dib.devno; /* get cch devno */
|
devc = dpc_dib.devno; /* get cch devno */
|
||||||
devd = dpd_dib.devno; /* get dch devno */
|
devd = dpd_dib.devno; /* get dch devno */
|
||||||
switch (uptr->FNC) { /* case function */
|
switch (uptr->FNC) { /* case function */
|
||||||
|
|
||||||
|
case FNC_AR: /* arec, need cyl */
|
||||||
case FNC_SEEK: /* seek, need cyl */
|
case FNC_SEEK: /* seek, need cyl */
|
||||||
if (CMD (devd)) { /* dch active? */
|
if (CMD (devd)) { /* dch active? */
|
||||||
dpc_rarc[drv] = DA_GETCYL (dpd_obuf); /* take cyl word */
|
dpc_rarc = DA_GETCYL (dpd_obuf); /* set RAR from cyl word */
|
||||||
dpd_wval = 0; /* clr data valid */
|
dpd_wval = 0; /* clr data valid */
|
||||||
setFSR (devd); /* set dch flg */
|
setFSR (devd); /* set dch flg */
|
||||||
clrCMD (devd); /* clr dch cmd */
|
clrCMD (devd); /* clr dch cmd */
|
||||||
uptr->FNC = FNC_SEEK1; } /* advance state */
|
if (uptr->FNC == FNC_AR) uptr->FNC = FNC_AR1;
|
||||||
|
else uptr->FNC = FNC_SEEK1; } /* advance state */
|
||||||
sim_activate (uptr, dpc_xtime); /* no, wait more */
|
sim_activate (uptr, dpc_xtime); /* no, wait more */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case FNC_AR1: /* arec, need hd/sec */
|
||||||
case FNC_SEEK1: /* seek, need hd/sec */
|
case FNC_SEEK1: /* seek, need hd/sec */
|
||||||
if (CMD (devd)) { /* dch active? */
|
if (CMD (devd)) { /* dch active? */
|
||||||
dpc_rarh[drv] = DA_GETHD (dpd_obuf); /* get head */
|
dpc_rarh = DA_GETHD (dpd_obuf); /* set RAR from head */
|
||||||
dpc_rars[drv] = DA_GETSC (dpd_obuf); /* get sector */
|
dpc_rars = DA_GETSC (dpd_obuf); /* set RAR from sector */
|
||||||
dpd_wval = 0; /* clr data valid */
|
dpd_wval = 0; /* clr data valid */
|
||||||
setFSR (devd); /* set dch flg */
|
setFSR (devd); /* set dch flg */
|
||||||
clrCMD (devd); /* clr dch cmd */
|
clrCMD (devd); /* clr dch cmd */
|
||||||
|
if (uptr->FNC == FNC_AR1) {
|
||||||
|
setFSR (devc); /* set cch flg */
|
||||||
|
clrCMD (devc); /* clr cch cmd */
|
||||||
|
dpc_sta[drv] = dpc_sta[drv] | STA_ATN; /* set drv attn */
|
||||||
|
break; } /* done if Address Record */
|
||||||
if (sim_is_active (&dpc_unit[drv])) { /* if busy, */
|
if (sim_is_active (&dpc_unit[drv])) { /* if busy, */
|
||||||
dpc_sta[drv] = dpc_sta[drv] | STA_SKE;
|
dpc_sta[drv] = dpc_sta[drv] | STA_SKE; /* seek check */
|
||||||
break; } /* error, ignore */
|
break; } /* allow prev seek to cmpl */
|
||||||
st = abs (dpc_rarc[drv] - dpc_unit[drv].CYL) * dpc_stime;
|
if ((dpc_rarc >= DP_NUMCY) || /* invalid cyl? */
|
||||||
|
(dp_ctype && (dpc_rars >= DP_NUMSC3))) { /* invalid sector? (13210A) */
|
||||||
|
dpc_sta[drv] = dpc_sta[drv] | STA_SKE; /* seek check */
|
||||||
|
sim_activate (&dpc_unit[drv], 1); /* schedule drive no-wait */
|
||||||
|
dpc_unit[drv].FNC = FNC_SEEK3; /* do immed compl w/poll */
|
||||||
|
break; }
|
||||||
|
st = abs (dpc_rarc - dpc_ucyl[drv]) * dpc_stime;
|
||||||
if (st == 0) st = dpc_stime; /* min time */
|
if (st == 0) st = dpc_stime; /* min time */
|
||||||
|
dpc_ucyl[drv] = dpc_rarc; /* transfer RAR */
|
||||||
sim_activate (&dpc_unit[drv], st); /* schedule drive */
|
sim_activate (&dpc_unit[drv], st); /* schedule drive */
|
||||||
dpc_sta[drv] = (dpc_sta[drv] | STA_BSY) &
|
dpc_sta[drv] = (dpc_sta[drv] | STA_BSY) &
|
||||||
~(STA_SKE | STA_SKI | STA_HUNT);
|
~(STA_SKE | STA_SKI | STA_HUNT);
|
||||||
dpc_unit[drv].CYL = dpc_rarc[drv]; /* on cylinder */
|
|
||||||
dpc_unit[drv].FNC = FNC_SEEK2; } /* set operation */
|
dpc_unit[drv].FNC = FNC_SEEK2; } /* set operation */
|
||||||
else sim_activate (uptr, dpc_xtime); /* no, wait more */
|
else sim_activate (uptr, dpc_xtime); /* no, wait more */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FNC_AR: /* arec, need cyl */
|
|
||||||
if (CMD (devd)) { /* dch active? */
|
|
||||||
dpc_rarc[drv] = DA_GETCYL (dpd_obuf); /* take cyl word */
|
|
||||||
dpd_wval = 0; /* clr data valid */
|
|
||||||
setFSR (devd); /* set dch flg */
|
|
||||||
clrCMD (devd); /* clr dch cmd */
|
|
||||||
uptr->FNC = FNC_AR1; } /* advance state */
|
|
||||||
sim_activate (uptr, dpc_xtime); /* no, wait more */
|
|
||||||
break;
|
|
||||||
case FNC_AR1: /* arec, need hd/sec */
|
|
||||||
if (CMD (devd)) { /* dch active? */
|
|
||||||
dpc_rarh[drv] = DA_GETHD (dpd_obuf); /* get head */
|
|
||||||
dpc_rars[drv] = DA_GETSC (dpd_obuf); /* get sector */
|
|
||||||
dpd_wval = 0; /* clr data valid */
|
|
||||||
setFSR (devc); /* set cch flg */
|
|
||||||
clrCMD (devc); /* clr cch cmd */
|
|
||||||
setFSR (devd); /* set dch flg */
|
|
||||||
clrCMD (devd); /* clr dch cmd */
|
|
||||||
dpc_sta[drv] = dpc_sta[drv] | STA_ATN; } /* set drv attn */
|
|
||||||
else sim_activate (uptr, dpc_xtime); /* no, wait more */
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FNC_STA: /* read status */
|
case FNC_STA: /* read status */
|
||||||
if (CMD (devd) || dp_ctype) { /* dch act or 13210? */
|
if (CMD (devd) || dp_ctype) { /* dch act or 13210? */
|
||||||
if (dpc_unit[drv].flags & UNIT_ATT) { /* attached? */
|
if (dpc_unit[drv].flags & UNIT_ATT) { /* attached? */
|
||||||
|
@ -531,20 +567,16 @@ case FNC_STA: /* read status */
|
||||||
if (dp_ctype) dpd_ibuf = /* 13210? */
|
if (dp_ctype) dpd_ibuf = /* 13210? */
|
||||||
(dpd_ibuf & ~(STA_MBZ13 | STA_PROT)) |
|
(dpd_ibuf & ~(STA_MBZ13 | STA_PROT)) |
|
||||||
(dpc_unit[drv].flags & UNIT_WPRT? STA_PROT: 0); }
|
(dpc_unit[drv].flags & UNIT_WPRT? STA_PROT: 0); }
|
||||||
else dpd_ibuf = STA_NRDY|STA_BSY; /* not ready */
|
else dpd_ibuf = STA_UNLOADED; /* not ready */
|
||||||
if (dpd_ibuf & STA_ALLERR) /* errors? set flg */
|
if (dpd_ibuf & STA_ANYERR) /* errors? set flg */
|
||||||
dpd_ibuf = dpd_ibuf | STA_ERR;
|
dpd_ibuf = dpd_ibuf | STA_ERR;
|
||||||
setFSR (devd); /* set dch flg */
|
setFSR (devd); /* set dch flg */
|
||||||
clrCMD (devd); /* clr dch cmd */
|
clrCMD (devd); /* clr dch cmd */
|
||||||
clrCMD (devc); /* clr cch cmd */
|
clrCMD (devc); } /* clr cch cmd */
|
||||||
dpc_sta[drv] = dpc_sta[drv] & /* clr sta flags */
|
dpc_sta[drv] = dpc_sta[drv] & /* clr sta flags */
|
||||||
~(STA_ATN | STA_1ST | STA_OVR |
|
~(STA_ATN | STA_1ST | STA_OVR |
|
||||||
STA_RWU | STA_ACU | STA_EOC |
|
STA_RWU | STA_ACU | STA_EOC |
|
||||||
STA_AER | STA_FLG | STA_DTE);
|
STA_AER | STA_FLG | STA_DTE);
|
||||||
uptr->FNC = FNC_STA1; } /* advance state */
|
|
||||||
sim_activate (uptr, dpc_xtime); /* no, wait more */
|
|
||||||
break;
|
|
||||||
case FNC_STA1: /* read sta, poll */
|
|
||||||
dpc_poll = 1; /* enable polling */
|
dpc_poll = 1; /* enable polling */
|
||||||
for (i = 0; i < DP_NUMDRV; i++) { /* loop thru drives */
|
for (i = 0; i < DP_NUMDRV; i++) { /* loop thru drives */
|
||||||
if (dpc_sta[i] & STA_ATN) { /* any ATN set? */
|
if (dpc_sta[i] & STA_ATN) { /* any ATN set? */
|
||||||
|
@ -556,8 +588,6 @@ case FNC_CHK: /* check, need cnt */
|
||||||
if (CMD (devd)) { /* dch active? */
|
if (CMD (devd)) { /* dch active? */
|
||||||
dpc_cnt = dpd_obuf & DA_CKMASK; /* get count */
|
dpc_cnt = dpd_obuf & DA_CKMASK; /* get count */
|
||||||
dpd_wval = 0; /* clr data valid */
|
dpd_wval = 0; /* clr data valid */
|
||||||
/* setFSR (devd); /* set dch flg */
|
|
||||||
/* clrCMD (devd); /* clr dch cmd */
|
|
||||||
dp_goc (FNC_CHK1, drv, dpc_xtime); } /* sched drv */
|
dp_goc (FNC_CHK1, drv, dpc_xtime); } /* sched drv */
|
||||||
else sim_activate (uptr, dpc_xtime); /* wait more */
|
else sim_activate (uptr, dpc_xtime); /* wait more */
|
||||||
break;
|
break;
|
||||||
|
@ -603,11 +633,10 @@ if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
switch (uptr->FNC) { /* case function */
|
switch (uptr->FNC) { /* case function */
|
||||||
|
|
||||||
case FNC_SEEK2: /* seek done */
|
case FNC_SEEK2: /* positioning done */
|
||||||
dpc_sta[drv] = (dpc_sta[drv] | STA_ATN) & ~STA_BSY;
|
dpc_sta[drv] = (dpc_sta[drv] | STA_ATN) & ~STA_BSY; /* fall into cmpl */
|
||||||
if (uptr->CYL >= DP_NUMCY) { /* invalid cyl? */
|
|
||||||
dpc_sta[drv] = dpc_sta[drv] | STA_SKE;
|
case FNC_SEEK3: /* seek complete */
|
||||||
uptr->CYL = DP_NUMCY - 1; }
|
|
||||||
if (dpc_poll) { /* polling enabled? */
|
if (dpc_poll) { /* polling enabled? */
|
||||||
setFSR (devc); /* set cch flg */
|
setFSR (devc); /* set cch flg */
|
||||||
clrCMD (devc); } /* clear cmd */
|
clrCMD (devc); } /* clear cmd */
|
||||||
|
@ -620,20 +649,19 @@ case FNC_RD: /* read */
|
||||||
case FNC_CHK1: /* check */
|
case FNC_CHK1: /* check */
|
||||||
if (dp_ptr == 0) { /* new sector? */
|
if (dp_ptr == 0) { /* new sector? */
|
||||||
if (!CMD (devd) && (uptr->FNC != FNC_CHK1)) break;
|
if (!CMD (devd) && (uptr->FNC != FNC_CHK1)) break;
|
||||||
if (uptr->CYL != dpc_rarc[drv]) /* wrong cyl? */
|
if (dpc_rarc != dpc_ucyl[drv]) /* RAR cyl miscompare? */
|
||||||
dpc_sta[drv] = dpc_sta[drv] | STA_AER; /* set flag, read */
|
dpc_sta[drv] = dpc_sta[drv] | STA_AER; /* set flag, read */
|
||||||
if (dpc_rars[drv] >= DP_NUMSC) { /* bad sector? */
|
if (dpc_rars >= DP_NUMSC) { /* bad sector? */
|
||||||
dpc_sta[drv] = dpc_sta[drv] | STA_AER; /* set flag, stop */
|
dpc_sta[drv] = dpc_sta[drv] | STA_AER; /* set flag, stop */
|
||||||
break; }
|
break; }
|
||||||
if (dpc_eoc) { /* end of cyl? */
|
if (dpc_eoc) { /* end of cyl? */
|
||||||
dpc_sta[drv] = dpc_sta[drv] | STA_EOC;
|
dpc_sta[drv] = dpc_sta[drv] | STA_EOC;
|
||||||
break; }
|
break; }
|
||||||
da = GETDA (dpc_rarc[drv], dpc_rarh[drv], dpc_rars[drv]);
|
da = GETDA (dpc_rarc, dpc_rarh, dpc_rars); /* calc disk addr */
|
||||||
dpc_rars[drv] = dpc_rars[drv] + 1; /* incr address */
|
dpc_rars = (dpc_rars + 1) % DP_NUMSC; /* incr sector */
|
||||||
if (dpc_rars[drv] >= DP_NUMSC) { /* end of surf? */
|
if (dpc_rars == 0) { /* wrap? */
|
||||||
dpc_rars[drv] = 0; /* wrap to */
|
dpc_rarh = dpc_rarh ^ 1; /* incr head */
|
||||||
dpc_rarh[drv] = dpc_rarh[drv] ^ 1; /* next head */
|
dpc_eoc = ((dpc_rarh & 1) == 0); } /* calc eoc */
|
||||||
dpc_eoc = ((dpc_rarh[drv] & 1) == 0); }/* calc eoc */
|
|
||||||
if (err = fseek (uptr->fileref, da * sizeof (int16),
|
if (err = fseek (uptr->fileref, da * sizeof (int16),
|
||||||
SEEK_SET)) break;
|
SEEK_SET)) break;
|
||||||
fxread (dpxb, sizeof (int16), DP_NUMWD, uptr->fileref);
|
fxread (dpxb, sizeof (int16), DP_NUMWD, uptr->fileref);
|
||||||
|
@ -657,9 +685,9 @@ case FNC_WD: /* write */
|
||||||
if (uptr->flags & UNIT_WPRT) { /* wr prot? */
|
if (uptr->flags & UNIT_WPRT) { /* wr prot? */
|
||||||
dpc_sta[drv] = dpc_sta[drv] | STA_FLG; /* set status */
|
dpc_sta[drv] = dpc_sta[drv] | STA_FLG; /* set status */
|
||||||
break; } /* done */
|
break; } /* done */
|
||||||
if ((uptr->CYL != dpc_rarc[drv]) || /* wrong cyl or */
|
if ((dpc_rarc != dpc_ucyl[drv]) || /* RAR cyl miscompare? */
|
||||||
(dpc_rars[drv] >= DP_NUMSC)) { /* bad sector? */
|
(dpc_rars >= DP_NUMSC)) { /* bad sector? */
|
||||||
dpc_sta[drv] = dpc_sta[drv] | STA_AER; /* set flag, stop */
|
dpc_sta[drv] = dpc_sta[drv] | STA_AER; /* address error */
|
||||||
break; }
|
break; }
|
||||||
if (dpc_eoc) { /* end of cyl? */
|
if (dpc_eoc) { /* end of cyl? */
|
||||||
dpc_sta[drv] = dpc_sta[drv] | STA_EOC; /* set status */
|
dpc_sta[drv] = dpc_sta[drv] | STA_EOC; /* set status */
|
||||||
|
@ -667,12 +695,11 @@ case FNC_WD: /* write */
|
||||||
dpxb[dp_ptr++] = dpd_wval? dpd_obuf: 0; /* store word/fill */
|
dpxb[dp_ptr++] = dpd_wval? dpd_obuf: 0; /* store word/fill */
|
||||||
dpd_wval = 0; /* clr data valid */
|
dpd_wval = 0; /* clr data valid */
|
||||||
if (dp_ptr >= DP_NUMWD) { /* buffer full? */
|
if (dp_ptr >= DP_NUMWD) { /* buffer full? */
|
||||||
da = GETDA (dpc_rarc[drv], dpc_rarh[drv], dpc_rars[drv]);
|
da = GETDA (dpc_rarc, dpc_rarh, dpc_rars); /* calc disk addr */
|
||||||
dpc_rars[drv] = dpc_rars[drv] + 1; /* incr address */
|
dpc_rars = (dpc_rars + 1) % DP_NUMSC; /* incr sector */
|
||||||
if (dpc_rars[drv] >= DP_NUMSC) { /* end of surf? */
|
if (dpc_rars == 0) { /* wrap? */
|
||||||
dpc_rars[drv] = 0; /* wrap to */
|
dpc_rarh = dpc_rarh ^ 1; /* incr head */
|
||||||
dpc_rarh[drv] = dpc_rarh[drv] ^ 1; /* next head */
|
dpc_eoc = ((dpc_rarh & 1) == 0); } /* calc eoc */
|
||||||
dpc_eoc = ((dpc_rarh[drv] & 1) == 0); }/* calc eoc */
|
|
||||||
if (err = fseek (uptr->fileref, da * sizeof (int16),
|
if (err = fseek (uptr->fileref, da * sizeof (int16),
|
||||||
SEEK_SET)) break;
|
SEEK_SET)) break;
|
||||||
fxwrite (dpxb, sizeof (int16), DP_NUMWD, uptr->fileref);
|
fxwrite (dpxb, sizeof (int16), DP_NUMWD, uptr->fileref);
|
||||||
|
@ -703,29 +730,30 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat dpc_reset (DEVICE *dptr)
|
t_stat dpc_reset (DEVICE *dptr)
|
||||||
{
|
{
|
||||||
int32 i;
|
int32 drv;
|
||||||
|
|
||||||
hp_enbdis_pair (&dpc_dev, &dpd_dev); /* make pair cons */
|
hp_enbdis_pair (dptr, /* make pair cons */
|
||||||
|
(dptr == &dpd_dev)? &dpc_dev: &dpd_dev);
|
||||||
dpd_ibuf = dpd_obuf = 0; /* clear buffers */
|
dpd_ibuf = dpd_obuf = 0; /* clear buffers */
|
||||||
dpc_busy = dpc_obuf = 0;
|
dpc_busy = dpc_obuf = 0;
|
||||||
dpc_eoc = 0;
|
dpc_eoc = 0;
|
||||||
dpc_poll = 0;
|
dpc_poll = 0;
|
||||||
dpd_xfer = dpd_wval = 0;
|
dpd_xfer = dpd_wval = 0;
|
||||||
dp_ptr = 0;
|
dp_ptr = 0;
|
||||||
|
dpc_rarc = dpc_rarh = dpc_rars = 0; /* clear RAR */
|
||||||
dpc_dib.cmd = dpd_dib.cmd = 0; /* clear cmd */
|
dpc_dib.cmd = dpd_dib.cmd = 0; /* clear cmd */
|
||||||
dpc_dib.ctl = dpd_dib.ctl = 0; /* clear ctl */
|
dpc_dib.ctl = dpd_dib.ctl = 0; /* clear ctl */
|
||||||
dpc_dib.fbf = dpd_dib.fbf = 1; /* set fbf */
|
dpc_dib.fbf = dpd_dib.fbf = 1; /* set fbf */
|
||||||
dpc_dib.flg = dpd_dib.flg = 1; /* set flg */
|
dpc_dib.flg = dpd_dib.flg = 1; /* set flg */
|
||||||
dpc_dib.srq = dpd_dib.flg = 1; /* srq follows flg */
|
dpc_dib.srq = dpd_dib.flg = 1; /* srq follows flg */
|
||||||
sim_cancel (&dpd_unit); /* cancel dch */
|
sim_cancel (&dpd_unit); /* cancel dch */
|
||||||
for (i = 0; i < DP_NUMDRV; i++) { /* loop thru drives */
|
for (drv = 0; drv < DP_NUMDRV; drv++) { /* loop thru drives */
|
||||||
sim_cancel (&dpc_unit[i]); /* cancel activity */
|
sim_cancel (&dpc_unit[drv]); /* cancel activity */
|
||||||
dpc_unit[i].FNC = 0; /* clear function */
|
dpc_unit[drv].FNC = 0; /* clear function */
|
||||||
dpc_unit[i].CYL = 0;
|
dpc_ucyl[drv] = 0; /* clear drive pos */
|
||||||
dpc_rarc[i] = dpc_rarh[i] = dpc_rars[i] = 0;
|
if (dpc_unit[drv].flags & UNIT_ATT)
|
||||||
if (dpc_unit[i].flags & UNIT_ATT)
|
dpc_sta[drv] = dpc_sta[drv] & STA_1ST; /* first seek status */
|
||||||
dpc_sta[i] = dpc_sta[i] & STA_1ST;
|
else dpc_sta[drv] = 0; } /* clear status */
|
||||||
else dpc_sta[i] = 0; }
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -847,4 +875,3 @@ SR = (SR & IBL_OPT) | IBL_DP | (dev << IBL_V_DEV); /* set SR */
|
||||||
if (sim_switches & SWMASK ('R')) SR = SR | IBL_DP_REM; /* boot from removable? */
|
if (sim_switches & SWMASK ('R')) SR = SR | IBL_DP_REM; /* boot from removable? */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,10 @@
|
||||||
|
|
||||||
dq 12565A 2883 disk system
|
dq 12565A 2883 disk system
|
||||||
|
|
||||||
|
07-Oct-04 JDB 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
|
||||||
21-Apr-04 RMS Fixed typo in boot loader (found by Dave Bryan)
|
21-Apr-04 RMS Fixed typo in boot loader (found by Dave Bryan)
|
||||||
26-Apr-04 RMS Fixed SFS x,C and SFC x,C
|
26-Apr-04 RMS Fixed SFS x,C and SFC x,C
|
||||||
Fixed SR setting in IBL
|
Fixed SR setting in IBL
|
||||||
|
@ -39,6 +43,29 @@
|
||||||
- 12565 does not set error on positioner busy
|
- 12565 does not set error on positioner busy
|
||||||
- 12565 does not set positioner busy if already on cylinder
|
- 12565 does not set positioner busy if already on cylinder
|
||||||
- 12565 does not need eoc logic, it will hit an invalid head number
|
- 12565 does not need eoc logic, it will hit an invalid head number
|
||||||
|
|
||||||
|
The controller's "Record Address Register" (RAR) contains the CHS address of
|
||||||
|
the last Position or Load Address command executed. The RAR is shared among
|
||||||
|
all drives on the controller. In addition, each drive has an internal
|
||||||
|
position register that contains the last cylinder and head position
|
||||||
|
transferred to the drive during Position command execution (sector operations
|
||||||
|
always start with the RAR sector position).
|
||||||
|
|
||||||
|
In a real drive, the address field of the sector under the head is read and
|
||||||
|
compared to the RAR. When they match, the target sector is under the head
|
||||||
|
and is ready for reading or writing. If a match doesn't occur, an Address
|
||||||
|
Error is indicated. In the simulator, the address field is obtained from the
|
||||||
|
drive's current position register during a read, i.e., the "on-disc" address
|
||||||
|
field is assumed to match the current position.
|
||||||
|
|
||||||
|
Reference:
|
||||||
|
- 12565A Disc Interface Kit Operating and Service Manual (12565-90003, Aug-1973)
|
||||||
|
|
||||||
|
The following implemented behaviors have been inferred from secondary sources
|
||||||
|
(diagnostics, operating system drivers, etc.), due to absent or contradictory
|
||||||
|
authoritative information; future correction may be needed:
|
||||||
|
|
||||||
|
1. Read Address command starts at the sector number in the RAR.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "hp2100_defs.h"
|
#include "hp2100_defs.h"
|
||||||
|
@ -46,7 +73,7 @@
|
||||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
||||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
#define UNIT_WLK (1 << UNIT_V_WLK)
|
||||||
#define FNC u3 /* saved function */
|
#define FNC u3 /* saved function */
|
||||||
#define CYL u4 /* cylinder */
|
#define DRV u4 /* drive number (DC) */
|
||||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write prot */
|
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write prot */
|
||||||
|
|
||||||
#define DQ_N_NUMWD 7
|
#define DQ_N_NUMWD 7
|
||||||
|
@ -107,7 +134,7 @@
|
||||||
#define STA_BSY 0000004 /* seeking */
|
#define STA_BSY 0000004 /* seeking */
|
||||||
#define STA_DTE 0000002 /* data error */
|
#define STA_DTE 0000002 /* data error */
|
||||||
#define STA_ERR 0000001 /* any error */
|
#define STA_ERR 0000001 /* any error */
|
||||||
#define STA_ALLERR (STA_NRDY + STA_EOC + STA_AER + STA_FLG + STA_DTE)
|
#define STA_ANYERR (STA_NRDY | STA_EOC | STA_AER | STA_FLG | STA_DTE)
|
||||||
|
|
||||||
extern uint16 *M;
|
extern uint16 *M;
|
||||||
extern uint32 PC, SR;
|
extern uint32 PC, SR;
|
||||||
|
@ -119,17 +146,19 @@ int32 dqc_busy = 0; /* cch xfer */
|
||||||
int32 dqc_cnt = 0; /* check count */
|
int32 dqc_cnt = 0; /* check count */
|
||||||
int32 dqc_stime = 100; /* seek time */
|
int32 dqc_stime = 100; /* seek time */
|
||||||
int32 dqc_ctime = 100; /* command time */
|
int32 dqc_ctime = 100; /* command time */
|
||||||
int32 dqc_xtime = 5; /* xfer time */
|
int32 dqc_xtime = 3; /* xfer time */
|
||||||
int32 dqc_dtime = 2; /* dch time */
|
int32 dqc_dtime = 2; /* dch time */
|
||||||
int32 dqd_obuf = 0, dqd_ibuf = 0; /* dch buffers */
|
int32 dqd_obuf = 0, dqd_ibuf = 0; /* dch buffers */
|
||||||
int32 dqc_obuf = 0; /* cch buffers */
|
int32 dqc_obuf = 0; /* cch buffers */
|
||||||
int32 dqd_xfer = 0; /* xfer in prog */
|
int32 dqd_xfer = 0; /* xfer in prog */
|
||||||
int32 dqd_wval = 0; /* write data valid */
|
int32 dqd_wval = 0; /* write data valid */
|
||||||
int32 dq_ptr = 0; /* buffer ptr */
|
int32 dq_ptr = 0; /* buffer ptr */
|
||||||
uint8 dqc_rarc[DQ_NUMDRV] = { 0 }; /* cylinder */
|
uint8 dqc_rarc = 0; /* RAR cylinder */
|
||||||
uint8 dqc_rarh[DQ_NUMDRV] = { 0 }; /* head */
|
uint8 dqc_rarh = 0; /* RAR head */
|
||||||
uint8 dqc_rars[DQ_NUMDRV] = { 0 }; /* sector */
|
uint8 dqc_rars = 0; /* RAR sector */
|
||||||
uint16 dqc_sta[DQ_NUMDRV] = { 0 }; /* status regs */
|
uint8 dqc_ucyl[DQ_NUMDRV] = { 0 }; /* unit cylinder */
|
||||||
|
uint8 dqc_uhed[DQ_NUMDRV] = { 0 }; /* unit head */
|
||||||
|
uint16 dqc_sta[DQ_NUMDRV] = { 0 }; /* unit status */
|
||||||
uint16 dqxb[DQ_NUMWD]; /* sector buffer */
|
uint16 dqxb[DQ_NUMWD]; /* sector buffer */
|
||||||
|
|
||||||
DEVICE dqd_dev, dqc_dev;
|
DEVICE dqd_dev, dqc_dev;
|
||||||
|
@ -161,6 +190,8 @@ UNIT dqd_unit = { UDATA (&dqd_svc, 0, 0) };
|
||||||
REG dqd_reg[] = {
|
REG dqd_reg[] = {
|
||||||
{ ORDATA (IBUF, dqd_ibuf, 16) },
|
{ ORDATA (IBUF, dqd_ibuf, 16) },
|
||||||
{ ORDATA (OBUF, dqd_obuf, 16) },
|
{ ORDATA (OBUF, dqd_obuf, 16) },
|
||||||
|
{ BRDATA (DBUF, dqxb, 8, 16, DQ_NUMWD) },
|
||||||
|
{ DRDATA (BPTR, dq_ptr, DQ_N_NUMWD) },
|
||||||
{ FLDATA (CMD, dqd_dib.cmd, 0) },
|
{ FLDATA (CMD, dqd_dib.cmd, 0) },
|
||||||
{ FLDATA (CTL, dqd_dib.ctl, 0) },
|
{ FLDATA (CTL, dqd_dib.ctl, 0) },
|
||||||
{ FLDATA (FLG, dqd_dib.flg, 0) },
|
{ FLDATA (FLG, dqd_dib.flg, 0) },
|
||||||
|
@ -168,8 +199,6 @@ REG dqd_reg[] = {
|
||||||
{ FLDATA (SRQ, dqd_dib.srq, 0) },
|
{ FLDATA (SRQ, dqd_dib.srq, 0) },
|
||||||
{ FLDATA (XFER, dqd_xfer, 0) },
|
{ FLDATA (XFER, dqd_xfer, 0) },
|
||||||
{ FLDATA (WVAL, dqd_wval, 0) },
|
{ FLDATA (WVAL, dqd_wval, 0) },
|
||||||
{ BRDATA (DBUF, dqxb, 8, 16, DQ_NUMWD) },
|
|
||||||
{ DRDATA (BPTR, dq_ptr, DQ_N_NUMWD) },
|
|
||||||
{ ORDATA (DEVNO, dqd_dib.devno, 6), REG_HRO },
|
{ ORDATA (DEVNO, dqd_dib.devno, 6), REG_HRO },
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
|
@ -183,7 +212,7 @@ DEVICE dqd_dev = {
|
||||||
1, 10, DQ_N_NUMWD, 1, 8, 16,
|
1, 10, DQ_N_NUMWD, 1, 8, 16,
|
||||||
NULL, NULL, &dqc_reset,
|
NULL, NULL, &dqc_reset,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
&dqd_dib, 0 };
|
&dqd_dib, DEV_DISABLE };
|
||||||
|
|
||||||
/* DQC data structures
|
/* DQC data structures
|
||||||
|
|
||||||
|
@ -208,16 +237,16 @@ REG dqc_reg[] = {
|
||||||
{ FLDATA (FLG, dqc_dib.flg, 0) },
|
{ FLDATA (FLG, dqc_dib.flg, 0) },
|
||||||
{ FLDATA (FBF, dqc_dib.fbf, 0) },
|
{ FLDATA (FBF, dqc_dib.fbf, 0) },
|
||||||
{ FLDATA (SRQ, dqc_dib.srq, 0) },
|
{ FLDATA (SRQ, dqc_dib.srq, 0) },
|
||||||
{ BRDATA (RARC, dqc_rarc, 8, 8, DQ_NUMDRV) },
|
{ DRDATA (RARC, dqc_rarc, 8), PV_RZRO },
|
||||||
{ BRDATA (RARH, dqc_rarh, 8, 5, DQ_NUMDRV) },
|
{ DRDATA (RARH, dqc_rarh, 5), PV_RZRO },
|
||||||
{ BRDATA (RARS, dqc_rars, 8, 5, DQ_NUMDRV) },
|
{ DRDATA (RARS, dqc_rars, 5), PV_RZRO },
|
||||||
|
{ BRDATA (CYL, dqc_ucyl, 10, 8, DQ_NUMDRV), PV_RZRO },
|
||||||
|
{ BRDATA (HED, dqc_uhed, 10, 5, DQ_NUMDRV), PV_RZRO },
|
||||||
{ BRDATA (STA, dqc_sta, 8, 16, DQ_NUMDRV) },
|
{ BRDATA (STA, dqc_sta, 8, 16, DQ_NUMDRV) },
|
||||||
{ DRDATA (CTIME, dqc_ctime, 24), PV_LEFT },
|
{ DRDATA (CTIME, dqc_ctime, 24), PV_LEFT },
|
||||||
{ DRDATA (DTIME, dqc_dtime, 24), PV_LEFT },
|
{ DRDATA (DTIME, dqc_dtime, 24), PV_LEFT },
|
||||||
{ DRDATA (STIME, dqc_stime, 24), PV_LEFT },
|
{ DRDATA (STIME, dqc_stime, 24), PV_LEFT },
|
||||||
{ DRDATA (XTIME, dqc_xtime, 24), REG_NZ + PV_LEFT },
|
{ DRDATA (XTIME, dqc_xtime, 24), REG_NZ + PV_LEFT },
|
||||||
{ URDATA (UCYL, dqc_unit[0].CYL, 10, 8, 0,
|
|
||||||
DQ_NUMDRV, PV_LEFT | REG_HRO) },
|
|
||||||
{ URDATA (UFNC, dqc_unit[0].FNC, 8, 8, 0,
|
{ URDATA (UFNC, dqc_unit[0].FNC, 8, 8, 0,
|
||||||
DQ_NUMDRV, REG_HRO) },
|
DQ_NUMDRV, REG_HRO) },
|
||||||
{ ORDATA (DEVNO, dqc_dib.devno, 6), REG_HRO },
|
{ ORDATA (DEVNO, dqc_dib.devno, 6), REG_HRO },
|
||||||
|
@ -273,7 +302,7 @@ case ioCTL: /* control clear/set */
|
||||||
setCTL (devd); /* set ctl, cmd */
|
setCTL (devd); /* set ctl, cmd */
|
||||||
setCMD (devd);
|
setCMD (devd);
|
||||||
if (dqc_busy && !dqd_xfer) /* overrun? */
|
if (dqc_busy && !dqd_xfer) /* overrun? */
|
||||||
dqc_sta[dqc_busy - 1] |= STA_DTE | STA_ERR; }
|
dqc_sta[dqc_busy - 1] |= STA_DTE; }
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break; }
|
break; }
|
||||||
|
@ -342,7 +371,7 @@ return dat;
|
||||||
|
|
||||||
void dq_god (int32 fnc, int32 drv, int32 time)
|
void dq_god (int32 fnc, int32 drv, int32 time)
|
||||||
{
|
{
|
||||||
dqd_unit.CYL = drv; /* save unit */
|
dqd_unit.DRV = drv; /* save unit */
|
||||||
dqd_unit.FNC = fnc; /* save function */
|
dqd_unit.FNC = fnc; /* save function */
|
||||||
sim_activate (&dqd_unit, time);
|
sim_activate (&dqd_unit, time);
|
||||||
return;
|
return;
|
||||||
|
@ -371,7 +400,7 @@ return;
|
||||||
This routine handles the data channel transfers. It also handles
|
This routine handles the data channel transfers. It also handles
|
||||||
data transfers that are blocked by seek in progress.
|
data transfers that are blocked by seek in progress.
|
||||||
|
|
||||||
uptr->CYL = target drive
|
uptr->DRV = target drive
|
||||||
uptr->FNC = target function
|
uptr->FNC = target function
|
||||||
|
|
||||||
Seek substates
|
Seek substates
|
||||||
|
@ -391,80 +420,69 @@ t_stat dqd_svc (UNIT *uptr)
|
||||||
{
|
{
|
||||||
int32 drv, devc, devd, st;
|
int32 drv, devc, devd, st;
|
||||||
|
|
||||||
drv = uptr->CYL; /* get drive no */
|
drv = uptr->DRV; /* get drive no */
|
||||||
devc = dqc_dib.devno; /* get cch devno */
|
devc = dqc_dib.devno; /* get cch devno */
|
||||||
devd = dqd_dib.devno; /* get dch devno */
|
devd = dqd_dib.devno; /* get dch devno */
|
||||||
switch (uptr->FNC) { /* case function */
|
switch (uptr->FNC) { /* case function */
|
||||||
|
|
||||||
|
case FNC_LA: /* arec, need cyl */
|
||||||
case FNC_SEEK: /* seek, need cyl */
|
case FNC_SEEK: /* seek, need cyl */
|
||||||
if (CMD (devd)) { /* dch active? */
|
if (CMD (devd)) { /* dch active? */
|
||||||
dqc_rarc[drv] = DA_GETCYL (dqd_obuf); /* take cyl word */
|
dqc_rarc = DA_GETCYL (dqd_obuf); /* set RAR from cyl word */
|
||||||
dqd_wval = 0; /* clr data valid */
|
dqd_wval = 0; /* clr data valid */
|
||||||
setFSR (devd); /* set dch flg */
|
setFSR (devd); /* set dch flg */
|
||||||
clrCMD (devd); /* clr dch cmd */
|
clrCMD (devd); /* clr dch cmd */
|
||||||
uptr->FNC = FNC_SEEK1; } /* advance state */
|
if (uptr->FNC == FNC_LA) uptr->FNC = FNC_LA1;
|
||||||
|
else uptr->FNC = FNC_SEEK1; } /* advance state */
|
||||||
sim_activate (uptr, dqc_xtime); /* no, wait more */
|
sim_activate (uptr, dqc_xtime); /* no, wait more */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case FNC_LA1: /* arec, need hd/sec */
|
||||||
case FNC_SEEK1: /* seek, need hd/sec */
|
case FNC_SEEK1: /* seek, need hd/sec */
|
||||||
if (CMD (devd)) { /* dch active? */
|
if (CMD (devd)) { /* dch active? */
|
||||||
dqc_rarh[drv] = DA_GETHD (dqd_obuf); /* get head */
|
dqc_rarh = DA_GETHD (dqd_obuf); /* set RAR from head */
|
||||||
dqc_rars[drv] = DA_GETSC (dqd_obuf); /* get sector */
|
dqc_rars = DA_GETSC (dqd_obuf); /* set RAR from sector */
|
||||||
dqd_wval = 0; /* clr data valid */
|
dqd_wval = 0; /* clr data valid */
|
||||||
setFSR (devd); /* set dch flg */
|
setFSR (devd); /* set dch flg */
|
||||||
clrCMD (devd); /* clr dch cmd */
|
clrCMD (devd); /* clr dch cmd */
|
||||||
if (sim_is_active (&dqc_unit[drv])) break; /* if busy */
|
if (uptr->FNC == FNC_LA1) {
|
||||||
st = abs (dqc_rarc[drv] - dqc_unit[drv].CYL) * dqc_stime;
|
setFSR (devc); /* set cch flg */
|
||||||
|
clrCMD (devc); /* clr cch cmd */
|
||||||
|
break; } /* done if Load Address */
|
||||||
|
if (sim_is_active (&dqc_unit[drv])) break; /* if busy, seek check */
|
||||||
|
st = abs (dqc_rarc - dqc_ucyl[drv]) * dqc_stime;
|
||||||
if (st == 0) st = dqc_xtime; /* if on cyl, min time */
|
if (st == 0) st = dqc_xtime; /* if on cyl, min time */
|
||||||
else dqc_sta[drv] = dqc_sta[drv] | STA_BSY; /* set busy */
|
else dqc_sta[drv] = dqc_sta[drv] | STA_BSY; /* set busy */
|
||||||
|
dqc_ucyl[drv] = dqc_rarc; /* transfer RAR */
|
||||||
|
dqc_uhed[drv] = dqc_rarh;
|
||||||
sim_activate (&dqc_unit[drv], st); /* schedule op */
|
sim_activate (&dqc_unit[drv], st); /* schedule op */
|
||||||
dqc_unit[drv].CYL = dqc_rarc[drv]; /* on cylinder */
|
|
||||||
dqc_unit[drv].FNC = FNC_SEEK2; } /* advance state */
|
dqc_unit[drv].FNC = FNC_SEEK2; } /* advance state */
|
||||||
else sim_activate (uptr, dqc_xtime); /* no, wait more */
|
else sim_activate (uptr, dqc_xtime); /* no, wait more */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FNC_RCL: /* recalibrate */
|
case FNC_RCL: /* recalibrate */
|
||||||
dqc_rarc[drv] = dqc_rarh[drv] = dqc_rars[drv] = 0; /* clear RAR */
|
dqc_rarc = dqc_rarh = dqc_rars = 0; /* clear RAR */
|
||||||
if (sim_is_active (&dqc_unit[drv])) break; /* ignore if busy */
|
if (sim_is_active (&dqc_unit[drv])) break; /* ignore if busy */
|
||||||
st = dqc_unit[drv].CYL * dqc_stime; /* calc diff */
|
st = dqc_ucyl[drv] * dqc_stime; /* calc diff */
|
||||||
if (st == 0) st = dqc_xtime; /* if on cyl, min time */
|
if (st == 0) st = dqc_xtime; /* if on cyl, min time */
|
||||||
else dqc_sta[drv] = dqc_sta[drv] | STA_BSY; /* set busy */
|
else dqc_sta[drv] = dqc_sta[drv] | STA_BSY; /* set busy */
|
||||||
sim_activate (&dqc_unit[drv], st); /* schedule drive */
|
sim_activate (&dqc_unit[drv], st); /* schedule drive */
|
||||||
dqc_unit[drv].CYL = 0; /* on cylinder */
|
dqc_ucyl[drv] = dqc_uhed[drv] = 0; /* clear drive pos */
|
||||||
dqc_unit[drv].FNC = FNC_SEEK2; /* advance state */
|
dqc_unit[drv].FNC = FNC_SEEK2; /* advance state */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FNC_LA: /* arec, need cyl */
|
|
||||||
if (CMD (devd)) { /* dch active? */
|
|
||||||
dqc_rarc[drv] = DA_GETCYL (dqd_obuf); /* take cyl word */
|
|
||||||
dqd_wval = 0; /* clr data valid */
|
|
||||||
setFSR (devd); /* set dch flg */
|
|
||||||
clrCMD (devd); /* clr dch cmd */
|
|
||||||
uptr->FNC = FNC_LA1; } /* advance state */
|
|
||||||
sim_activate (uptr, dqc_xtime); /* no, wait more */
|
|
||||||
break;
|
|
||||||
case FNC_LA1: /* arec, need hd/sec */
|
|
||||||
if (CMD (devd)) { /* dch active? */
|
|
||||||
dqc_rarh[drv] = DA_GETHD (dqd_obuf); /* get head */
|
|
||||||
dqc_rars[drv] = DA_GETSC (dqd_obuf); /* get sector */
|
|
||||||
dqd_wval = 0; /* clr data valid */
|
|
||||||
setFSR (devc); /* set cch flg */
|
|
||||||
clrCMD (devc); /* clr cch cmd */
|
|
||||||
setFSR (devd); /* set dch flg */
|
|
||||||
clrCMD (devd); } /* clr dch cmd */
|
|
||||||
else sim_activate (uptr, dqc_xtime); /* no, wait more */
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FNC_STA: /* read status */
|
case FNC_STA: /* read status */
|
||||||
if (CMD (devd)) { /* dch active? */
|
if (CMD (devd)) { /* dch active? */
|
||||||
if (dqc_unit[drv].flags & UNIT_ATT) /* attached? */
|
if (dqc_unit[drv].flags & UNIT_ATT) /* attached? */
|
||||||
dqd_ibuf = dqc_sta[drv] & ~STA_DID;
|
dqd_ibuf = dqc_sta[drv] & ~STA_DID;
|
||||||
else dqd_ibuf = STA_NRDY|STA_BSY;
|
else dqd_ibuf = STA_NRDY;
|
||||||
|
if (dqd_ibuf & STA_ANYERR) /* errors? set flg */
|
||||||
|
dqd_ibuf = dqd_ibuf | STA_ERR;
|
||||||
if (drv) dqd_ibuf = dqd_ibuf | STA_DID;
|
if (drv) dqd_ibuf = dqd_ibuf | STA_DID;
|
||||||
setFSR (devd); /* set dch flg */
|
setFSR (devd); /* set dch flg */
|
||||||
clrCMD (devd); /* clr dch cmd */
|
clrCMD (devd); /* clr dch cmd */
|
||||||
clrCMD (devc); /* clr cch cmd */
|
clrCMD (devc); /* clr cch cmd */
|
||||||
dqc_sta[drv] = dqc_sta[drv] & /* clr sta flags */
|
dqc_sta[drv] = dqc_sta[drv] & ~STA_ANYERR; /* clr sta flags */
|
||||||
~(STA_DTE | STA_FLG | STA_AER | STA_EOC | STA_ERR);
|
|
||||||
}
|
}
|
||||||
else sim_activate (uptr, dqc_xtime); /* wait more */
|
else sim_activate (uptr, dqc_xtime); /* wait more */
|
||||||
break;
|
break;
|
||||||
|
@ -473,8 +491,6 @@ case FNC_CHK: /* check, need cnt */
|
||||||
if (CMD (devd)) { /* dch active? */
|
if (CMD (devd)) { /* dch active? */
|
||||||
dqc_cnt = dqd_obuf & DA_CKMASK; /* get count */
|
dqc_cnt = dqd_obuf & DA_CKMASK; /* get count */
|
||||||
dqd_wval = 0; /* clr data valid */
|
dqd_wval = 0; /* clr data valid */
|
||||||
/* setFSR (devd); /* set dch flg */
|
|
||||||
/* clrCMD (devd); /* clr dch cmd */
|
|
||||||
dq_goc (FNC_CHK1, drv, dqc_ctime); } /* sched drv */
|
dq_goc (FNC_CHK1, drv, dqc_ctime); } /* sched drv */
|
||||||
else sim_activate (uptr, dqc_xtime); /* wait more */
|
else sim_activate (uptr, dqc_xtime); /* wait more */
|
||||||
break;
|
break;
|
||||||
|
@ -522,9 +538,9 @@ if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
|
||||||
switch (uptr->FNC) { /* case function */
|
switch (uptr->FNC) { /* case function */
|
||||||
|
|
||||||
case FNC_SEEK2: /* seek done */
|
case FNC_SEEK2: /* seek done */
|
||||||
if (uptr->CYL >= DQ_NUMCY) { /* out of range? */
|
if (dqc_ucyl[drv] >= DQ_NUMCY) { /* out of range? */
|
||||||
dqc_sta[drv] = dqc_sta[drv] | STA_BSY | STA_ERR;
|
dqc_sta[drv] = dqc_sta[drv] | STA_BSY | STA_ERR; /* seek check */
|
||||||
dqc_unit[drv].CYL = 0; }
|
dqc_ucyl[drv] = 0; } /* seek to cyl 0 */
|
||||||
else dqc_sta[drv] = dqc_sta[drv] & ~STA_BSY; /* drive not busy */
|
else dqc_sta[drv] = dqc_sta[drv] & ~STA_BSY; /* drive not busy */
|
||||||
case FNC_SEEK3:
|
case FNC_SEEK3:
|
||||||
if (dqc_busy || FLG (devc)) { /* ctrl busy? */
|
if (dqc_busy || FLG (devc)) { /* ctrl busy? */
|
||||||
|
@ -537,13 +553,11 @@ case FNC_SEEK3:
|
||||||
|
|
||||||
case FNC_RA: /* read addr */
|
case FNC_RA: /* read addr */
|
||||||
if (!CMD (devd)) break; /* dch clr? done */
|
if (!CMD (devd)) break; /* dch clr? done */
|
||||||
if (dq_ptr == 0) dqd_ibuf = uptr->CYL; /* 1st word? */
|
if (dq_ptr == 0) dqd_ibuf = dqc_ucyl[drv]; /* 1st word? */
|
||||||
else if (dq_ptr == 1) { /* second word? */
|
else if (dq_ptr == 1) { /* second word? */
|
||||||
dqd_ibuf = (dqc_rarh[drv] << DA_V_HD) |
|
dqd_ibuf = (dqc_uhed[drv] << DA_V_HD) | /* use drive head */
|
||||||
(dqc_rars[drv] << DA_V_SC);
|
(dqc_rars << DA_V_SC); /* and RAR sector */
|
||||||
dqc_rars[drv] = dqc_rars[drv] + 1; /* incr address */
|
dqc_rars = (dqc_rars + 1) % DQ_NUMSC; } /* incr sector */
|
||||||
if (dqc_rars[drv] >= DQ_NUMSC) /* end of surf? */
|
|
||||||
dqc_rars[drv] = 0; }
|
|
||||||
else break;
|
else break;
|
||||||
dq_ptr = dq_ptr + 1;
|
dq_ptr = dq_ptr + 1;
|
||||||
setFSR (devd); /* set dch flg */
|
setFSR (devd); /* set dch flg */
|
||||||
|
@ -556,18 +570,18 @@ case FNC_RD: /* read */
|
||||||
case FNC_CHK1: /* check */
|
case FNC_CHK1: /* check */
|
||||||
if (dq_ptr == 0) { /* new sector? */
|
if (dq_ptr == 0) { /* new sector? */
|
||||||
if (!CMD (devd) && (uptr->FNC != FNC_CHK1)) break;
|
if (!CMD (devd) && (uptr->FNC != FNC_CHK1)) break;
|
||||||
if ((uptr->CYL != dqc_rarc[drv]) || /* wrong cyl or */
|
if ((dqc_rarc != dqc_ucyl[drv]) || /* RAR cyl miscompare? */
|
||||||
(dqc_rars[drv] >= DQ_NUMSC)) { /* bad sector? */
|
(dqc_rarh != dqc_uhed[drv]) || /* RAR head miscompare? */
|
||||||
dqc_sta[drv] = dqc_sta[drv] | STA_AER | STA_ERR;
|
(dqc_rars >= DQ_NUMSC)) { /* bad sector? */
|
||||||
|
dqc_sta[drv] = dqc_sta[drv] | STA_AER; /* no record found err */
|
||||||
break; }
|
break; }
|
||||||
if (dqc_rarh[drv] >= DQ_NUMSF) { /* bad head? */
|
if (dqc_rarh >= DQ_NUMSF) { /* bad head? */
|
||||||
dqc_sta[drv] = dqc_sta[drv] | STA_EOC | STA_ERR;
|
dqc_sta[drv] = dqc_sta[drv] | STA_EOC; /* end of cyl err */
|
||||||
break; }
|
break; }
|
||||||
da = GETDA (dqc_rarc[drv], dqc_rarh[drv], dqc_rars[drv]);
|
da = GETDA (dqc_rarc, dqc_rarh, dqc_rars); /* calc disk addr */
|
||||||
dqc_rars[drv] = dqc_rars[drv] + 1; /* incr address */
|
dqc_rars = (dqc_rars + 1) % DQ_NUMSC; /* incr sector */
|
||||||
if (dqc_rars[drv] >= DQ_NUMSC) { /* end of surf? */
|
if (dqc_rars == 0) /* wrap? incr head */
|
||||||
dqc_rars[drv] = 0; /* wrap to */
|
dqc_uhed[drv] = dqc_rarh = dqc_rarh + 1;
|
||||||
dqc_rarh[drv] = dqc_rarh[drv] + 1; } /* next head */
|
|
||||||
if (err = fseek (uptr->fileref, da * sizeof (int16),
|
if (err = fseek (uptr->fileref, da * sizeof (int16),
|
||||||
SEEK_SET)) break;
|
SEEK_SET)) break;
|
||||||
fxread (dqxb, sizeof (int16), DQ_NUMWD, uptr->fileref);
|
fxread (dqxb, sizeof (int16), DQ_NUMWD, uptr->fileref);
|
||||||
|
@ -588,24 +602,24 @@ case FNC_WA: /* write address */
|
||||||
case FNC_WD: /* write */
|
case FNC_WD: /* write */
|
||||||
if (dq_ptr == 0) { /* sector start? */
|
if (dq_ptr == 0) { /* sector start? */
|
||||||
if (!CMD (devd) && !dqd_wval) break; /* xfer done? */
|
if (!CMD (devd) && !dqd_wval) break; /* xfer done? */
|
||||||
if(uptr->flags & UNIT_WPRT) { /* write protect? */
|
if (uptr->flags & UNIT_WPRT) { /* write protect? */
|
||||||
dqc_sta[drv] = dqc_sta[drv] | STA_FLG | STA_ERR;
|
dqc_sta[drv] = dqc_sta[drv] | STA_FLG;
|
||||||
break; } /* done */
|
break; } /* done */
|
||||||
if ((uptr->CYL != dqc_rarc[drv]) || /* wrong cyl or */
|
if ((dqc_rarc != dqc_ucyl[drv]) || /* RAR cyl miscompare? */
|
||||||
(dqc_rars[drv] >= DQ_NUMSC)) { /* bad sector? */
|
(dqc_rarh != dqc_uhed[drv]) || /* RAR head miscompare? */
|
||||||
dqc_sta[drv] = dqc_sta[drv] | STA_AER | STA_ERR;
|
(dqc_rars >= DQ_NUMSC)) { /* bad sector? */
|
||||||
|
dqc_sta[drv] = dqc_sta[drv] | STA_AER; /* no record found err */
|
||||||
break; }
|
break; }
|
||||||
if (dqc_rarh[drv] >= DQ_NUMSF) { /* bad head? */
|
if (dqc_rarh >= DQ_NUMSF) { /* bad head? */
|
||||||
dqc_sta[drv] = dqc_sta[drv] | STA_EOC | STA_ERR;
|
dqc_sta[drv] = dqc_sta[drv] | STA_EOC; /* end of cyl err */
|
||||||
break; } } /* done */
|
break; } }
|
||||||
dqxb[dq_ptr++] = dqd_wval? dqd_obuf: 0; /* store word/fill */
|
dqxb[dq_ptr++] = dqd_wval? dqd_obuf: 0; /* store word/fill */
|
||||||
dqd_wval = 0; /* clr data valid */
|
dqd_wval = 0; /* clr data valid */
|
||||||
if (dq_ptr >= DQ_NUMWD) { /* buffer full? */
|
if (dq_ptr >= DQ_NUMWD) { /* buffer full? */
|
||||||
da = GETDA (dqc_rarc[drv], dqc_rarh[drv], dqc_rars[drv]);
|
da = GETDA (dqc_rarc, dqc_rarh, dqc_rars); /* calc disk addr */
|
||||||
dqc_rars[drv] = dqc_rars[drv] + 1; /* incr address */
|
dqc_rars = (dqc_rars + 1) % DQ_NUMSC; /* incr sector */
|
||||||
if (dqc_rars[drv] >= DQ_NUMSC) { /* end of surf? */
|
if (dqc_rars == 0) /* wrap? incr head */
|
||||||
dqc_rars[drv] = 0; /* wrap to */
|
dqc_uhed[drv] = dqc_rarh = dqc_rarh + 1;
|
||||||
dqc_rarh[drv] = dqc_rarh[drv] + 1; } /* next head */
|
|
||||||
if (err = fseek (uptr->fileref, da * sizeof (int16),
|
if (err = fseek (uptr->fileref, da * sizeof (int16),
|
||||||
SEEK_SET)) return TRUE;
|
SEEK_SET)) return TRUE;
|
||||||
fxwrite (dqxb, sizeof (int16), DQ_NUMWD, uptr->fileref);
|
fxwrite (dqxb, sizeof (int16), DQ_NUMWD, uptr->fileref);
|
||||||
|
@ -635,25 +649,26 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat dqc_reset (DEVICE *dptr)
|
t_stat dqc_reset (DEVICE *dptr)
|
||||||
{
|
{
|
||||||
int32 i;
|
int32 drv;
|
||||||
|
|
||||||
hp_enbdis_pair (&dqc_dev, &dqd_dev); /* make pair cons */
|
hp_enbdis_pair (dptr, /* make pair cons */
|
||||||
|
(dptr == &dqd_dev)? &dqc_dev: &dqd_dev);
|
||||||
dqd_ibuf = dqd_obuf = 0; /* clear buffers */
|
dqd_ibuf = dqd_obuf = 0; /* clear buffers */
|
||||||
dqc_busy = dqc_obuf = 0;
|
dqc_busy = dqc_obuf = 0;
|
||||||
dqd_xfer = dqd_wval = 0;
|
dqd_xfer = dqd_wval = 0;
|
||||||
dq_ptr = 0;
|
dq_ptr = 0;
|
||||||
|
dqc_rarc = dqc_rarh = dqc_rars = 0; /* clear RAR */
|
||||||
dqc_dib.cmd = dqd_dib.cmd = 0; /* clear cmd */
|
dqc_dib.cmd = dqd_dib.cmd = 0; /* clear cmd */
|
||||||
dqc_dib.ctl = dqd_dib.ctl = 0; /* clear ctl */
|
dqc_dib.ctl = dqd_dib.ctl = 0; /* clear ctl */
|
||||||
dqc_dib.fbf = dqd_dib.fbf = 1; /* set fbf */
|
dqc_dib.fbf = dqd_dib.fbf = 1; /* set fbf */
|
||||||
dqc_dib.flg = dqd_dib.flg = 1; /* set flg */
|
dqc_dib.flg = dqd_dib.flg = 1; /* set flg */
|
||||||
dqc_dib.srq = dqd_dib.srq = 1; /* srq follows flg */
|
dqc_dib.srq = dqd_dib.srq = 1; /* srq follows flg */
|
||||||
sim_cancel (&dqd_unit); /* cancel dch */
|
sim_cancel (&dqd_unit); /* cancel dch */
|
||||||
for (i = 0; i < DQ_NUMDRV; i++) { /* loop thru drives */
|
for (drv = 0; drv < DQ_NUMDRV; drv++) { /* loop thru drives */
|
||||||
sim_cancel (&dqc_unit[i]); /* cancel activity */
|
sim_cancel (&dqc_unit[drv]); /* cancel activity */
|
||||||
dqc_unit[i].FNC = 0; /* clear function */
|
dqc_unit[drv].FNC = 0; /* clear function */
|
||||||
dqc_unit[i].CYL = 0;
|
dqc_ucyl[drv] = dqc_uhed[drv] = 0; /* clear drive pos */
|
||||||
dqc_rarc[i] = dqc_rarh[i] = dqc_rars[i] = 0; /* clear rar */
|
dqc_sta[drv] = 0; } /* clear status */
|
||||||
dqc_sta[i] = 0; }
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,9 +23,29 @@
|
||||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
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.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
fhd 12606B 2770/2771 fixed head disk
|
dr 12606B 2770/2771 fixed head disk
|
||||||
12610B 2773/2774/2775 drum
|
12610B 2773/2774/2775 drum
|
||||||
|
|
||||||
|
07-Oct-04 JDB Fixed enable/disable from either device
|
||||||
|
Fixed sector return in status word
|
||||||
|
Provided protected tracks and "Writing Enabled" status bit
|
||||||
|
Fixed DMA last word write, incomplete sector fill value
|
||||||
|
Added "parity error" status return on writes for 12606
|
||||||
|
Added track origin test for 12606
|
||||||
|
Added SCP test for 12606
|
||||||
|
Fixed 12610 SFC operation
|
||||||
|
Added "Sector Flag" status bit
|
||||||
|
Added "Read Inhibit" status bit for 12606
|
||||||
|
Fixed current-sector determination
|
||||||
|
Added PROTECTED, UNPROTECTED, TRACKPROT modifiers
|
||||||
|
26-Aug-04 RMS Fixed CLC to stop operation (from Dave Bryan)
|
||||||
|
26-Apr-04 RMS Fixed SFS x,C and SFC x,C
|
||||||
|
Revised boot rom to use IBL algorithm
|
||||||
|
Implemented DMA SRQ (follows FLG)
|
||||||
|
27-Jul-03 RMS Fixed drum sizes
|
||||||
|
Fixed variable capacity interaction with SAVE/RESTORE
|
||||||
|
10-Nov-02 RMS Added BOOT command
|
||||||
|
|
||||||
These head-per-track devices are buffered in memory, to minimize overhead.
|
These head-per-track devices are buffered in memory, to minimize overhead.
|
||||||
|
|
||||||
The drum data channel does not have a command flip-flop. Its control
|
The drum data channel does not have a command flip-flop. Its control
|
||||||
|
@ -35,13 +55,46 @@
|
||||||
|
|
||||||
The drum control channel does not have any of the traditional flip-flops.
|
The drum control channel does not have any of the traditional flip-flops.
|
||||||
|
|
||||||
26-Aug-04 RMS Fixed CLC to stop operation (from Dave Bryan)
|
The 12606 interface implements two diagnostic tests. An SFS CC instruction
|
||||||
26-Apr-04 RMS Fixed SFS x,C and SFC x,C
|
will skip if the disk has passed the track origin (sector 0) since the last
|
||||||
Revised boot rom to use IBL algorithm
|
CLF CC instruction, and an SFC CC instruction will skip if the Sector Clock
|
||||||
Implemented DMA SRQ (follows FLG)
|
Phase (SCP) flip-flop is clear, indicating that the current sector is
|
||||||
27-Jul-03 RMS Fixed drum sizes
|
accessible. The 12610 interface does not support these tests; the SKF signal
|
||||||
Fixed variable capacity interaction with SAVE/RESTORE
|
is not driven, so neither SFC CC nor SFS CC will skip.
|
||||||
10-Nov-02 RMS Added BOOT command
|
|
||||||
|
The interface implements a track protect mechanism via a switch and a set of
|
||||||
|
on-card diodes. The switch sets the protected/unprotected status, and the
|
||||||
|
particular diodes installed indicate the range of tracks (a power of 2) that
|
||||||
|
are read-only in the protected mode.
|
||||||
|
|
||||||
|
Somewhat unusually, writing to a protected track completes normally, but the
|
||||||
|
data isn't actually written, as the write current is inhibited. There is no
|
||||||
|
"failure" status indication. Instead, a program must note the lack of
|
||||||
|
"Writing Enabled" status before the write is attempted.
|
||||||
|
|
||||||
|
Specifications (2770/2771):
|
||||||
|
- 90 sectors per logical track
|
||||||
|
- 45 sectors per revolution
|
||||||
|
- 64 words per sector
|
||||||
|
- 2880 words per revolution
|
||||||
|
- 3450 RPM = 17.4 ms/revolution
|
||||||
|
- data timing = 6.0 us/word, 375 us/sector
|
||||||
|
- inst timing = 4 inst/word, 11520 inst/revolution
|
||||||
|
|
||||||
|
Specifications 2773/2774/2775:
|
||||||
|
- 32 sectors per logical track
|
||||||
|
- 32 sectors per revolution
|
||||||
|
- 64 words per sector
|
||||||
|
- 2048 words per revolution
|
||||||
|
- 3450 RPM = 17.4 ms/revolution
|
||||||
|
- data timing = 8.5 us/word, 550 us/sector
|
||||||
|
- inst timing = 6 inst/word, 12288 inst/revolution
|
||||||
|
|
||||||
|
References:
|
||||||
|
- 12606B Disc Memory Interface Kit Operating and Service Manual
|
||||||
|
(12606-90012, Mar-1970)
|
||||||
|
- 12610B Drum Memory Interface Kit Operating and Service Manual
|
||||||
|
(12610-9001, Feb-1970)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "hp2100_defs.h"
|
#include "hp2100_defs.h"
|
||||||
|
@ -54,8 +107,13 @@
|
||||||
#define DR_DNUMSC 32 /* drum sec/track */
|
#define DR_DNUMSC 32 /* drum sec/track */
|
||||||
#define DR_NUMSC ((drc_unit.flags & UNIT_DR)? DR_DNUMSC: DR_FNUMSC)
|
#define DR_NUMSC ((drc_unit.flags & UNIT_DR)? DR_DNUMSC: DR_FNUMSC)
|
||||||
#define DR_SIZE (512 * DR_DNUMSC * DR_NUMWD) /* initial size */
|
#define DR_SIZE (512 * DR_DNUMSC * DR_NUMWD) /* initial size */
|
||||||
#define UNIT_V_SZ (UNIT_V_UF) /* disk vs drum */
|
#define DR_FTIME 4 /* fhd per-word time */
|
||||||
|
#define DR_DTIME 6 /* drum per-word time */
|
||||||
|
#define DR_OVRHEAD 5 /* overhead words at track start */
|
||||||
|
#define UNIT_V_PROT (UNIT_V_UF + 0) /* track protect */
|
||||||
|
#define UNIT_V_SZ (UNIT_V_UF + 1) /* disk vs drum */
|
||||||
#define UNIT_M_SZ 017 /* size */
|
#define UNIT_M_SZ 017 /* size */
|
||||||
|
#define UNIT_PROT (1 << UNIT_V_PROT)
|
||||||
#define UNIT_SZ (UNIT_M_SZ << UNIT_V_SZ)
|
#define UNIT_SZ (UNIT_M_SZ << UNIT_V_SZ)
|
||||||
#define UNIT_DR (1 << UNIT_V_SZ) /* low order bit */
|
#define UNIT_DR (1 << UNIT_V_SZ) /* low order bit */
|
||||||
#define SZ_180K 000 /* disks */
|
#define SZ_180K 000 /* disks */
|
||||||
|
@ -95,21 +153,21 @@
|
||||||
(((x) & CW_M_DSEC) << CW_V_DSEC): \
|
(((x) & CW_M_DSEC) << CW_V_DSEC): \
|
||||||
(((x) & CW_M_FSEC) << CW_V_FSEC))
|
(((x) & CW_M_FSEC) << CW_V_FSEC))
|
||||||
|
|
||||||
/* Status register */
|
/* Status register, ^ = dynamic */
|
||||||
|
|
||||||
#define DRS_V_NS 8 /* next sector */
|
#define DRS_V_NS 8 /* ^next sector */
|
||||||
#define DRS_M_NS 0177
|
#define DRS_M_NS 0177
|
||||||
#define DRS_SEC 0100000 /* sector flag */
|
#define DRS_SEC 0100000 /* ^sector flag */
|
||||||
#define DRS_RDY 0000200 /* ready */
|
#define DRS_RDY 0000200 /* ^ready */
|
||||||
#define DRS_RIF 0000100 /* read inhibit */
|
#define DRS_RIF 0000100 /* ^read inhibit */
|
||||||
#define DRS_SAC 0000040 /* sector coincidence */
|
#define DRS_SAC 0000040 /* sector coincidence */
|
||||||
#define DRS_ABO 0000010 /* abort */
|
#define DRS_ABO 0000010 /* abort */
|
||||||
#define DRS_WEN 0000004 /* write enabled */
|
#define DRS_WEN 0000004 /* ^write enabled */
|
||||||
#define DRS_PER 0000002 /* parity error */
|
#define DRS_PER 0000002 /* parity error */
|
||||||
#define DRS_BSY 0000001 /* busy */
|
#define DRS_BSY 0000001 /* ^busy */
|
||||||
|
|
||||||
#define GET_CURSEC(x) ((int32) fmod (sim_gtime() / ((double) (x)), \
|
#define CALC_SCP(x) (((int32) fmod ((x) / (double) dr_time, \
|
||||||
((double) ((drc_unit.flags & UNIT_DR)? DR_DNUMSC: DR_FNUMSC))))
|
(double) (DR_NUMWD))) >= (DR_NUMWD - 3))
|
||||||
|
|
||||||
extern UNIT cpu_unit;
|
extern UNIT cpu_unit;
|
||||||
extern uint16 *M;
|
extern uint16 *M;
|
||||||
|
@ -118,11 +176,13 @@ extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2];
|
||||||
|
|
||||||
int32 drc_cw = 0; /* fnc, addr */
|
int32 drc_cw = 0; /* fnc, addr */
|
||||||
int32 drc_sta = 0; /* status */
|
int32 drc_sta = 0; /* status */
|
||||||
|
int32 drc_run = 0; /* run flip-flop */
|
||||||
int32 drd_ibuf = 0; /* input buffer */
|
int32 drd_ibuf = 0; /* input buffer */
|
||||||
int32 drd_obuf = 0; /* output buffer */
|
int32 drd_obuf = 0; /* output buffer */
|
||||||
int32 drd_ptr = 0; /* sector pointer */
|
int32 drd_ptr = 0; /* sector pointer */
|
||||||
|
int32 drc_pcount = 1; /* number of prot tracks */
|
||||||
int32 dr_stopioe = 1; /* stop on error */
|
int32 dr_stopioe = 1; /* stop on error */
|
||||||
int32 dr_time = 10; /* time per word */
|
int32 dr_time = DR_DTIME; /* time per word */
|
||||||
|
|
||||||
static int32 sz_tab[16] = {
|
static int32 sz_tab[16] = {
|
||||||
184320, 1048576, 368640, 1572864, 737280, 393216, 0, 524288,
|
184320, 1048576, 368640, 1572864, 737280, 393216, 0, 524288,
|
||||||
|
@ -136,6 +196,8 @@ t_stat drc_reset (DEVICE *dptr);
|
||||||
t_stat drc_attach (UNIT *uptr, char *cptr);
|
t_stat drc_attach (UNIT *uptr, char *cptr);
|
||||||
t_stat drc_boot (int32 unitno, DEVICE *dptr);
|
t_stat drc_boot (int32 unitno, DEVICE *dptr);
|
||||||
int32 dr_incda (int32 trk, int32 sec, int32 ptr);
|
int32 dr_incda (int32 trk, int32 sec, int32 ptr);
|
||||||
|
int32 dr_seccntr (double simtime);
|
||||||
|
t_stat dr_set_prot (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
t_stat dr_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat dr_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
|
||||||
/* DRD data structures
|
/* DRD data structures
|
||||||
|
@ -152,7 +214,12 @@ DIB dr_dib[] = {
|
||||||
#define drd_dib dr_dib[0]
|
#define drd_dib dr_dib[0]
|
||||||
#define drc_dib dr_dib[1]
|
#define drc_dib dr_dib[1]
|
||||||
|
|
||||||
UNIT drd_unit = { UDATA (NULL, 0, 0) };
|
UNIT drd_unit[] = {
|
||||||
|
{ UDATA (NULL, 0, 0) },
|
||||||
|
{ UDATA (NULL, UNIT_DIS, 0) } };
|
||||||
|
|
||||||
|
#define TMR_ORG 0 /* origin timer */
|
||||||
|
#define TMR_INH 1 /* inhibit timer */
|
||||||
|
|
||||||
REG drd_reg[] = {
|
REG drd_reg[] = {
|
||||||
{ ORDATA (IBUF, drd_ibuf, 16) },
|
{ ORDATA (IBUF, drd_ibuf, 16) },
|
||||||
|
@ -172,9 +239,9 @@ MTAB drd_mod[] = {
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
|
||||||
DEVICE drd_dev = {
|
DEVICE drd_dev = {
|
||||||
"DRD", &drd_unit, drd_reg, drd_mod,
|
"DRD", drd_unit, drd_reg, drd_mod,
|
||||||
1, 0, 0, 0, 0, 0,
|
2, 0, 0, 0, 0, 0,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, &drc_reset,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
&drd_dib, DEV_DISABLE };
|
&drd_dib, DEV_DISABLE };
|
||||||
|
|
||||||
|
@ -191,8 +258,10 @@ UNIT drc_unit =
|
||||||
UNIT_MUSTBUF+UNIT_DR+UNIT_BINK, DR_SIZE) };
|
UNIT_MUSTBUF+UNIT_DR+UNIT_BINK, DR_SIZE) };
|
||||||
|
|
||||||
REG drc_reg[] = {
|
REG drc_reg[] = {
|
||||||
|
{ DRDATA (PCNT, drc_pcount, 10), REG_HIDDEN | PV_LEFT },
|
||||||
{ ORDATA (CW, drc_cw, 16) },
|
{ ORDATA (CW, drc_cw, 16) },
|
||||||
{ ORDATA (STA, drc_sta, 16) },
|
{ ORDATA (STA, drc_sta, 16) },
|
||||||
|
{ FLDATA (RUN, drc_run, 0) },
|
||||||
{ FLDATA (CMD, drc_dib.cmd, 0) },
|
{ FLDATA (CMD, drc_dib.cmd, 0) },
|
||||||
{ FLDATA (CTL, drc_dib.ctl, 0) },
|
{ FLDATA (CTL, drc_dib.ctl, 0) },
|
||||||
{ FLDATA (FLG, drc_dib.flg, 0) },
|
{ FLDATA (FLG, drc_dib.flg, 0) },
|
||||||
|
@ -217,6 +286,10 @@ MTAB drc_mod[] = {
|
||||||
{ UNIT_SZ, (SZ_896K << UNIT_V_SZ), NULL, "896K", &dr_set_size },
|
{ UNIT_SZ, (SZ_896K << UNIT_V_SZ), NULL, "896K", &dr_set_size },
|
||||||
{ UNIT_SZ, (SZ_1024K << UNIT_V_SZ), NULL, "1024K", &dr_set_size },
|
{ UNIT_SZ, (SZ_1024K << UNIT_V_SZ), NULL, "1024K", &dr_set_size },
|
||||||
{ UNIT_SZ, (SZ_1536K << UNIT_V_SZ), NULL, "1536K", &dr_set_size },
|
{ UNIT_SZ, (SZ_1536K << UNIT_V_SZ), NULL, "1536K", &dr_set_size },
|
||||||
|
{ UNIT_PROT, UNIT_PROT, "protected", "PROTECTED", NULL },
|
||||||
|
{ UNIT_PROT, 0, "unprotected", "UNPROTECTED", NULL },
|
||||||
|
{ MTAB_XTD | MTAB_VDV | MTAB_VAL, 0, "tracks protected", "TRACKPROT",
|
||||||
|
&dr_set_prot, NULL, &drc_reg[0] },
|
||||||
{ MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO",
|
{ MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO",
|
||||||
&hp_setdev, &hp_showdev, &drd_dev },
|
&hp_setdev, &hp_showdev, &drd_dev },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
@ -249,15 +322,15 @@ case ioCTL: /* control clear/set */
|
||||||
if (IR & I_AB) { /* CLC */
|
if (IR & I_AB) { /* CLC */
|
||||||
clrCMD (devd); /* clr "ctl" */
|
clrCMD (devd); /* clr "ctl" */
|
||||||
clrFSR (devd); /* clr flg */
|
clrFSR (devd); /* clr flg */
|
||||||
sim_cancel (&drc_unit); /* cancel curr op */
|
if (!drc_run) sim_cancel (&drc_unit); /* cancel curr op */
|
||||||
drc_sta = drc_sta & ~DRS_SAC; } /* clear SAC flag */
|
drc_sta = drc_sta & ~DRS_SAC; } /* clear SAC flag */
|
||||||
else if (!CMD (devd)) { /* STC, not set? */
|
else if (!CMD (devd)) { /* STC, not set? */
|
||||||
setCMD (devd); /* set "ctl" */
|
setCMD (devd); /* set "ctl" */
|
||||||
if (drc_cw & CW_WR) { setFSR (devd); } /* prime DMA */
|
if (drc_cw & CW_WR) { setFSR (devd); } /* prime DMA */
|
||||||
drc_sta = 0; /* clear errors */
|
drc_sta = 0; /* clr status */
|
||||||
drd_ptr = 0; /* clear sec ptr */
|
drd_ptr = 0; /* clear sec ptr */
|
||||||
sim_cancel (&drc_unit); /* cancel curr op */
|
sim_cancel (&drc_unit); /* cancel curr op */
|
||||||
t = CW_GETSEC (drc_cw) - GET_CURSEC (dr_time * DR_NUMWD);
|
t = CW_GETSEC (drc_cw) - dr_seccntr (sim_gtime());
|
||||||
if (t <= 0) t = t + DR_NUMSC;
|
if (t <= 0) t = t + DR_NUMSC;
|
||||||
sim_activate (&drc_unit, t * DR_NUMWD * dr_time); }
|
sim_activate (&drc_unit, t * DR_NUMWD * dr_time); }
|
||||||
break;
|
break;
|
||||||
|
@ -269,23 +342,48 @@ return dat;
|
||||||
|
|
||||||
int32 drcio (int32 inst, int32 IR, int32 dat)
|
int32 drcio (int32 inst, int32 IR, int32 dat)
|
||||||
{
|
{
|
||||||
int32 st;
|
int32 sec;
|
||||||
|
|
||||||
switch (inst) { /* case on opcode */
|
switch (inst) { /* case on opcode */
|
||||||
|
case ioFLG: /* flag clear/set */
|
||||||
|
if ((IR & I_HC) && !(drc_unit.flags & UNIT_DR)) { /* CLF disk */
|
||||||
|
sec = dr_seccntr (sim_gtime ()); /* current sector */
|
||||||
|
sim_cancel (&drd_unit[TMR_ORG]); /* sched origin tmr */
|
||||||
|
sim_activate (&drd_unit[TMR_ORG],
|
||||||
|
(DR_FNUMSC - sec) * DR_NUMWD * dr_time); }
|
||||||
|
break;
|
||||||
case ioSFC: /* skip flag clear */
|
case ioSFC: /* skip flag clear */
|
||||||
PC = (PC + 1) & VAMASK;
|
if (drc_unit.flags & UNIT_DR) break; /* 12610 never skips */
|
||||||
|
if (!(CALC_SCP (sim_gtime()))) /* nearing end of sector? */
|
||||||
|
PC = (PC + 1) & VAMASK; /* skip if SCP clear */
|
||||||
|
break;
|
||||||
|
case ioSFS: /* skip flag set */
|
||||||
|
if (drc_unit.flags & UNIT_DR) break; /* 12610 never skips */
|
||||||
|
if (!sim_is_active (&drd_unit[TMR_ORG])) /* passed origin? */
|
||||||
|
PC = (PC + 1) & VAMASK; /* skip if origin seen */
|
||||||
break;
|
break;
|
||||||
case ioOTX: /* output */
|
case ioOTX: /* output */
|
||||||
drc_cw = dat;
|
if (!(drc_unit.flags & UNIT_DR)) { /* disk? */
|
||||||
|
sim_cancel (&drd_unit[TMR_INH]); /* schedule inhibit timer */
|
||||||
|
sim_activate (&drd_unit[TMR_INH], DR_FTIME * DR_NUMWD); }
|
||||||
|
drc_cw = dat; /* get control word */
|
||||||
break;
|
break;
|
||||||
case ioLIX: /* load */
|
case ioLIX: /* load */
|
||||||
dat = 0;
|
dat = 0;
|
||||||
case ioMIX: /* merge */
|
case ioMIX: /* merge */
|
||||||
if (drc_unit.flags & UNIT_ATT) /* attached? */
|
dat = dat | drc_sta; /* static bits */
|
||||||
st = GET_CURSEC (dr_time) | DRS_RDY | drc_sta |
|
if (!(drc_unit.flags & UNIT_PROT) || /* not protected? */
|
||||||
(sim_is_active (&drc_unit)? DRS_BSY: 0);
|
(CW_GETTRK(drc_cw) >= drc_pcount)) /* or not in range? */
|
||||||
else st = drc_sta;
|
dat = dat | DRS_WEN; /* set wrt enb status */
|
||||||
dat = dat | st; /* merge status */
|
if (drc_unit.flags & UNIT_ATT) { /* attached? */
|
||||||
|
dat = dat | (dr_seccntr (sim_gtime()) << DRS_V_NS) | DRS_RDY;
|
||||||
|
if (sim_is_active (&drc_unit)) /* op in progress? */
|
||||||
|
dat = dat | DRS_BSY;
|
||||||
|
if (CALC_SCP (sim_gtime())) /* SCP ff set? */
|
||||||
|
dat = dat | DRS_SEC; /* set sector flag */
|
||||||
|
if (sim_is_active (&drd_unit[TMR_INH]) && /* inhibit timer on? */
|
||||||
|
!(drc_cw & CW_WR))
|
||||||
|
dat = dat | DRS_RIF; } /* set read inh flag */
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break; }
|
break; }
|
||||||
|
@ -304,11 +402,12 @@ if ((uptr->flags & UNIT_ATT) == 0) {
|
||||||
drc_sta = DRS_ABO;
|
drc_sta = DRS_ABO;
|
||||||
return IORETURN (dr_stopioe, SCPE_UNATT); }
|
return IORETURN (dr_stopioe, SCPE_UNATT); }
|
||||||
|
|
||||||
drc_sta = drc_sta | DRS_SAC;
|
|
||||||
devd = drd_dib.devno; /* get dch devno */
|
devd = drd_dib.devno; /* get dch devno */
|
||||||
trk = CW_GETTRK (drc_cw);
|
trk = CW_GETTRK (drc_cw);
|
||||||
sec = CW_GETSEC (drc_cw);
|
sec = CW_GETSEC (drc_cw);
|
||||||
da = ((trk * DR_NUMSC) + sec) * DR_NUMWD;
|
da = ((trk * DR_NUMSC) + sec) * DR_NUMWD;
|
||||||
|
drc_sta = drc_sta | DRS_SAC;
|
||||||
|
drc_run = 1; /* set run ff */
|
||||||
|
|
||||||
if (drc_cw & CW_WR) { /* write? */
|
if (drc_cw & CW_WR) { /* write? */
|
||||||
if ((da < uptr->capac) && (sec < DR_NUMSC)) {
|
if ((da < uptr->capac) && (sec < DR_NUMSC)) {
|
||||||
|
@ -319,9 +418,13 @@ if (drc_cw & CW_WR) { /* write? */
|
||||||
if (CMD (devd)) { /* dch active? */
|
if (CMD (devd)) { /* dch active? */
|
||||||
setFSR (devd); /* set dch flg */
|
setFSR (devd); /* set dch flg */
|
||||||
sim_activate (uptr, dr_time); } /* sched next word */
|
sim_activate (uptr, dr_time); } /* sched next word */
|
||||||
else if (drd_ptr) { /* done, need to fill? */
|
else { /* done */
|
||||||
|
if (drd_ptr) /* need to fill? */
|
||||||
for ( ; drd_ptr < DR_NUMWD; drd_ptr++)
|
for ( ; drd_ptr < DR_NUMWD; drd_ptr++)
|
||||||
bptr[da + drd_ptr] = 0; }
|
bptr[da + drd_ptr] = drd_obuf; /* fill with last word */
|
||||||
|
if (!(drc_unit.flags & UNIT_DR)) /* disk? */
|
||||||
|
drc_sta = drc_sta | DRS_PER; /* parity bit sets on write */
|
||||||
|
drc_run = 0; } /* clear run ff */
|
||||||
} /* end write */
|
} /* end write */
|
||||||
else { /* read */
|
else { /* read */
|
||||||
if (CMD (devd)) { /* dch active? */
|
if (CMD (devd)) { /* dch active? */
|
||||||
|
@ -330,6 +433,7 @@ else { /* read */
|
||||||
drd_ptr = dr_incda (trk, sec, drd_ptr);
|
drd_ptr = dr_incda (trk, sec, drd_ptr);
|
||||||
setFSR (devd); /* set dch flg */
|
setFSR (devd); /* set dch flg */
|
||||||
sim_activate (uptr, dr_time); } /* sched next word */
|
sim_activate (uptr, dr_time); } /* sched next word */
|
||||||
|
else drc_run = 0; /* clear run ff */
|
||||||
}
|
}
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -351,11 +455,38 @@ if (ptr >= DR_NUMWD) { /* end sector? */
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Read the sector counter
|
||||||
|
|
||||||
|
The hardware sector counter contains the number of the next sector that will
|
||||||
|
pass under the heads (so it is one ahead of the current sector). For the
|
||||||
|
duration of the last sector of the track, the sector counter contains 90 for
|
||||||
|
the 12606 and 0 for the 12610. The sector counter resets to 0 at track
|
||||||
|
origin and increments at the start of the first sector. Therefore, the
|
||||||
|
counter value ranges from 0-90 for the 12606 and 0-31 for the 12610. The 0
|
||||||
|
state is quite short in the 12606 and long in the 12610, relative to the
|
||||||
|
other sector counter states.
|
||||||
|
|
||||||
|
The simulated sector counter is calculated from the simulation time, based on
|
||||||
|
the time per word and the number of words per track.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int32 dr_seccntr (double simtime)
|
||||||
|
{
|
||||||
|
int32 curword;
|
||||||
|
|
||||||
|
curword = (int32) fmod (simtime / (double) dr_time,
|
||||||
|
(double) (DR_NUMWD * DR_NUMSC + DR_OVRHEAD));
|
||||||
|
if (curword <= DR_OVRHEAD) return 0;
|
||||||
|
else return ((curword - DR_OVRHEAD) / DR_NUMWD +
|
||||||
|
((drc_unit.flags & UNIT_DR)? 0: 1));
|
||||||
|
}
|
||||||
|
|
||||||
/* Reset routine */
|
/* Reset routine */
|
||||||
|
|
||||||
t_stat drc_reset (DEVICE *dptr)
|
t_stat drc_reset (DEVICE *dptr)
|
||||||
{
|
{
|
||||||
hp_enbdis_pair (&drc_dev, &drd_dev); /* make pair cons */
|
hp_enbdis_pair (dptr, /* make pair cons */
|
||||||
|
(dptr == &drd_dev)? &drc_dev: &drd_dev);
|
||||||
drc_sta = drc_cw = drd_ptr = 0;
|
drc_sta = drc_cw = drd_ptr = 0;
|
||||||
drc_dib.cmd = drd_dib.cmd = 0; /* clear cmd */
|
drc_dib.cmd = drd_dib.cmd = 0; /* clear cmd */
|
||||||
drc_dib.ctl = drd_dib.ctl = 0; /* clear ctl */
|
drc_dib.ctl = drd_dib.ctl = 0; /* clear ctl */
|
||||||
|
@ -363,6 +494,8 @@ drc_dib.fbf = drd_dib.fbf = 0; /* clear fbf */
|
||||||
drc_dib.flg = drd_dib.flg = 0; /* clear flg */
|
drc_dib.flg = drd_dib.flg = 0; /* clear flg */
|
||||||
drc_dib.srq = drd_dib.srq = 0; /* srq follows flg */
|
drc_dib.srq = drd_dib.srq = 0; /* srq follows flg */
|
||||||
sim_cancel (&drc_unit);
|
sim_cancel (&drc_unit);
|
||||||
|
sim_cancel (&drd_unit[TMR_ORG]);
|
||||||
|
sim_cancel (&drd_unit[TMR_INH]);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,16 +510,53 @@ uptr->capac = sz;
|
||||||
return attach_unit (uptr, cptr);
|
return attach_unit (uptr, cptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set protected track count */
|
||||||
|
|
||||||
|
t_stat dr_set_prot (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
int32 count;
|
||||||
|
t_stat status;
|
||||||
|
|
||||||
|
if (cptr == NULL) return SCPE_ARG;
|
||||||
|
count = (int32) get_uint (cptr, 10, 768, &status);
|
||||||
|
if (status != SCPE_OK) return status;
|
||||||
|
else switch (count) {
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 4:
|
||||||
|
case 8:
|
||||||
|
case 16:
|
||||||
|
case 32:
|
||||||
|
case 64:
|
||||||
|
case 128:
|
||||||
|
drc_pcount = count;
|
||||||
|
break;
|
||||||
|
case 256:
|
||||||
|
case 512:
|
||||||
|
case 768:
|
||||||
|
if (drc_unit.flags & UNIT_DR) drc_pcount = count;
|
||||||
|
else return SCPE_ARG;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return SCPE_ARG; }
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* Set size routine */
|
/* Set size routine */
|
||||||
|
|
||||||
t_stat dr_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
t_stat dr_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
{
|
{
|
||||||
int32 sz;
|
int32 sz;
|
||||||
|
int32 szindex;
|
||||||
|
|
||||||
if (val < 0) return SCPE_IERR;
|
if (val < 0) return SCPE_IERR;
|
||||||
if ((sz = sz_tab[DR_GETSZ (val)]) == 0) return SCPE_IERR;
|
if ((sz = sz_tab[szindex = DR_GETSZ (val)]) == 0) return SCPE_IERR;
|
||||||
if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
|
if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
|
||||||
uptr->capac = sz;
|
uptr->capac = sz;
|
||||||
|
if (szindex & UNIT_DR) dr_time = DR_DTIME; /* drum */
|
||||||
|
else {
|
||||||
|
dr_time = DR_FTIME; /* disk */
|
||||||
|
if (drc_pcount > 128) drc_pcount = 128; } /* max prot track count */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -162,8 +162,7 @@
|
||||||
#define CMF_UNDF 001 /* undefined */
|
#define CMF_UNDF 001 /* undefined */
|
||||||
#define CMF_CLREC 002 /* clear eoc flag */
|
#define CMF_CLREC 002 /* clear eoc flag */
|
||||||
#define CMF_CLRS 004 /* clear status */
|
#define CMF_CLRS 004 /* clear status */
|
||||||
#define CMF_UNIT 010 /* validate unit */
|
#define CMF_UIDLE 010 /* requires unit no */
|
||||||
#define CMF_UIDLE 020 /* unit must be idle */
|
|
||||||
|
|
||||||
/* Cylinder words - 16b */
|
/* Cylinder words - 16b */
|
||||||
|
|
||||||
|
@ -216,7 +215,7 @@
|
||||||
#define DS2_BS 0000001 /* *busy */
|
#define DS2_BS 0000001 /* *busy */
|
||||||
#define DS2_ALLERR (DS2_FLT|DS2_SC|DS2_NR|DS2_BS)
|
#define DS2_ALLERR (DS2_FLT|DS2_SC|DS2_NR|DS2_BS)
|
||||||
|
|
||||||
/* Drive state */
|
/* Controller state */
|
||||||
|
|
||||||
#define DS_IDLE 0 /* idle */
|
#define DS_IDLE 0 /* idle */
|
||||||
#define DS_WAIT 1 /* command wait */
|
#define DS_WAIT 1 /* command wait */
|
||||||
|
@ -313,25 +312,25 @@ uint32 ds_ptr = 0; /* buffer ptr */
|
||||||
uint16 dsxb[DS_NUMWDF]; /* sector buffer */
|
uint16 dsxb[DS_NUMWDF]; /* sector buffer */
|
||||||
|
|
||||||
static const uint32 ds_opflags[32] = { /* flags for ops */
|
static const uint32 ds_opflags[32] = { /* flags for ops */
|
||||||
CMF_CLREC|CMF_CLRS|CMF_UNIT|CMF_UIDLE, /* cold read */
|
CMF_CLREC|CMF_CLRS|CMF_UIDLE, /* cold read */
|
||||||
CMF_CLREC|CMF_CLRS|CMF_UNIT|CMF_UIDLE, /* recalibrate */
|
CMF_CLREC|CMF_CLRS|CMF_UIDLE, /* recalibrate */
|
||||||
CMF_CLREC|CMF_CLRS|CMF_UNIT|CMF_UIDLE, /* seek */
|
CMF_CLREC|CMF_CLRS|CMF_UIDLE, /* seek */
|
||||||
0, /* read status */
|
0, /* read status */
|
||||||
CMF_CLRS, /* read sector */
|
CMF_CLRS, /* read sector */
|
||||||
CMF_CLRS|CMF_UNIT|CMF_UIDLE, /* read */
|
CMF_CLRS|CMF_UIDLE, /* read */
|
||||||
CMF_CLRS|CMF_UNIT|CMF_UIDLE, /* read full */
|
CMF_CLRS|CMF_UIDLE, /* read full */
|
||||||
CMF_CLRS|CMF_UNIT|CMF_UIDLE, /* verify */
|
CMF_CLRS|CMF_UIDLE, /* verify */
|
||||||
CMF_CLRS|CMF_UNIT|CMF_UIDLE, /* write */
|
CMF_CLRS|CMF_UIDLE, /* write */
|
||||||
CMF_CLRS|CMF_UNIT|CMF_UIDLE, /* write full */
|
CMF_CLRS|CMF_UIDLE, /* write full */
|
||||||
CMF_CLRS, /* clear */
|
CMF_CLRS, /* clear */
|
||||||
CMF_CLRS|CMF_UNIT|CMF_UIDLE, /* init */
|
CMF_CLRS|CMF_UIDLE, /* init */
|
||||||
CMF_CLREC|CMF_CLRS, /* addr record */
|
CMF_CLREC|CMF_CLRS, /* addr record */
|
||||||
0, /* read syndrome */
|
0, /* read syndrome */
|
||||||
CMF_CLRS|CMF_UNIT|CMF_UIDLE, /* read offset */
|
CMF_CLRS|CMF_UIDLE, /* read offset */
|
||||||
CMF_CLRS, /* set file mask */
|
CMF_CLRS, /* set file mask */
|
||||||
CMF_UNDF|CMF_CLRS, /* undefined */
|
CMF_UNDF|CMF_CLRS, /* undefined */
|
||||||
CMF_UNDF|CMF_CLRS, /* undefined */
|
CMF_UNDF|CMF_CLRS, /* undefined */
|
||||||
CMF_CLRS|CMF_UNIT|CMF_UIDLE, /* read no verify */
|
CMF_CLRS|CMF_UIDLE, /* read no verify */
|
||||||
CMF_CLRS, /* write TIO */
|
CMF_CLRS, /* write TIO */
|
||||||
CMF_CLRS, /* read disk addr */
|
CMF_CLRS, /* read disk addr */
|
||||||
CMF_CLRS, /* end */
|
CMF_CLRS, /* end */
|
||||||
|
@ -359,6 +358,7 @@ t_stat ds_boot (int32 unitno, DEVICE *dptr);
|
||||||
t_stat ds_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat ds_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
void ds_poll (void);
|
void ds_poll (void);
|
||||||
void ds_docmd (uint32 cmd);
|
void ds_docmd (uint32 cmd);
|
||||||
|
void ds_doatn (void);
|
||||||
uint32 ds_updds2 (UNIT *uptr, uint32 clear);
|
uint32 ds_updds2 (UNIT *uptr, uint32 clear);
|
||||||
void ds_cmd_done (t_bool sf, uint32 sr1);
|
void ds_cmd_done (t_bool sf, uint32 sr1);
|
||||||
void ds_wait_for_cpu (UNIT *uptr, uint32 newst);
|
void ds_wait_for_cpu (UNIT *uptr, uint32 newst);
|
||||||
|
@ -553,20 +553,10 @@ return dat;
|
||||||
|
|
||||||
void ds_poll (void)
|
void ds_poll (void)
|
||||||
{
|
{
|
||||||
uint32 i, dev;
|
int32 dev = ds_dib.devno;
|
||||||
|
|
||||||
dev = ds_dib.devno; /* device num */
|
if ((ds_state != DS_BUSY) && ds_cmdp) ds_docmd (ds_cmd);/* cmd pending? */
|
||||||
if (ds_state == DS_BUSY) return; /* ctrl busy? */
|
if ((ds_state == DS_IDLE) && CTL (dev)) ds_doatn (); /* idle? chk atn */
|
||||||
if (ds_cmdp) ds_docmd (ds_cmd); /* cmd pending? */
|
|
||||||
if ((ds_state != DS_IDLE) || !CTL (dev)) return; /* waiting for cmd or */
|
|
||||||
for (i = 0; i < DS_NUMDR; i++) { /* intr disabled? */
|
|
||||||
ds_lastatn = (ds_lastatn + 1) & DS_DRMASK; /* loop through units */
|
|
||||||
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; } }
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -598,11 +588,6 @@ if (f & CMF_CLREC) ds_eoc = 0; /* clear end cyl */
|
||||||
if (f & CMF_UNDF) { /* illegal op? */
|
if (f & CMF_UNDF) { /* illegal op? */
|
||||||
ds_sched_ctrl_op (DSC_BADF, 0, CLR_BUSY); /* sched, not busy */
|
ds_sched_ctrl_op (DSC_BADF, 0, CLR_BUSY); /* sched, not busy */
|
||||||
return; }
|
return; }
|
||||||
if (f & CMF_UNIT) { /* validate unit? */
|
|
||||||
if (f & CMF_CLRS) 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; } }
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
|
|
||||||
/* Drive commands */
|
/* Drive commands */
|
||||||
|
@ -622,6 +607,10 @@ case DSC_VFY: /* verify */
|
||||||
case DSC_WRITE: /* write */
|
case DSC_WRITE: /* write */
|
||||||
case DSC_WFULL: /* write full */
|
case DSC_WFULL: /* write full */
|
||||||
case DSC_INIT: /* init */
|
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].FNC = op; /* save op */
|
||||||
ds_unit[ds_u].STA &= ~DS2_ATN; /* clear ATTN */
|
ds_unit[ds_u].STA &= ~DS2_ATN; /* clear ATTN */
|
||||||
sim_activate (&ds_unit[ds_u], ds_ctime); /* schedule unit */
|
sim_activate (&ds_unit[ds_u], ds_ctime); /* schedule unit */
|
||||||
|
@ -667,6 +656,24 @@ case DSC_END: /* end */
|
||||||
break; }
|
break; }
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check for attention */
|
||||||
|
|
||||||
|
void ds_doatn (void)
|
||||||
|
{
|
||||||
|
uint32 i, dev;
|
||||||
|
|
||||||
|
dev = ds_dib.devno; /* device num */
|
||||||
|
for (i = 0; i < DS_NUMDR; i++) { /* intr disabled? */
|
||||||
|
ds_lastatn = (ds_lastatn + 1) & DS_DRMASK; /* loop through units */
|
||||||
|
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; } }
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Controller service
|
/* Controller service
|
||||||
|
|
||||||
|
@ -822,8 +829,7 @@ case DSC_COLD: /* cold load read */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DSC_READ: /* read */
|
case DSC_READ: /* read */
|
||||||
case DSC_RNOVFY: /* read, no verify */
|
if (r = ds_start_rd (uptr, 0, 1)) /* new sector; error? */
|
||||||
if (r = ds_start_rd (uptr, 0, op != DSC_RNOVFY)) /* new sector; error? */
|
|
||||||
return r;
|
return r;
|
||||||
break;
|
break;
|
||||||
case DSC_READ | DSC_2ND: /* word transfer */
|
case DSC_READ | DSC_2ND: /* word transfer */
|
||||||
|
@ -833,6 +839,17 @@ case DSC_READ | DSC_3RD: /* end of sector */
|
||||||
ds_end_rw (uptr, DSC_READ); /* see if more to do */
|
ds_end_rw (uptr, DSC_READ); /* see if more to do */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DSC_RNOVFY: /* read, no verify */
|
||||||
|
if (r = ds_start_rd (uptr, 0, 0)) /* new sector; error? */
|
||||||
|
return r;
|
||||||
|
break;
|
||||||
|
case DSC_RNOVFY | DSC_2ND: /* word transfer */
|
||||||
|
ds_cont_rd (uptr, DS_NUMWD); /* xfr wd, check end */
|
||||||
|
break;
|
||||||
|
case DSC_RNOVFY | DSC_3RD: /* end of sector */
|
||||||
|
ds_end_rw (uptr, DSC_RNOVFY); /* see if more to do */
|
||||||
|
break;
|
||||||
|
|
||||||
case DSC_RFULL: /* read full */
|
case DSC_RFULL: /* read full */
|
||||||
dsxb[DS_FSYNC] = 0100376; /* fill in header */
|
dsxb[DS_FSYNC] = 0100376; /* fill in header */
|
||||||
dsxb[DS_FCYL] = uptr->CYL;
|
dsxb[DS_FCYL] = uptr->CYL;
|
||||||
|
@ -864,15 +881,14 @@ case DSC_VFY | DSC_3RD: /* start sector */
|
||||||
break;
|
break;
|
||||||
case DSC_VFY | DSC_4TH: /* end sector */
|
case DSC_VFY | DSC_4TH: /* end sector */
|
||||||
ds_vctr = (ds_vctr - 1) & DMASK; /* decrement count */
|
ds_vctr = (ds_vctr - 1) & DMASK; /* decrement count */
|
||||||
if (ds_vctr) ds_end_rw (uptr, DSC_VFY | DSC_3RD); /* more to do? */
|
if (ds_vctr) ds_end_rw (uptr, DSC_VFY|DSC_3RD); /* more to do? */
|
||||||
else ds_cmd_done (1, DS1_OK); /* no, set done */
|
else ds_cmd_done (1, DS1_OK); /* no, set done */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Write variants */
|
/* Write variants */
|
||||||
|
|
||||||
case DSC_INIT: /* init */
|
|
||||||
case DSC_WRITE: /* write */
|
case DSC_WRITE: /* write */
|
||||||
ds_start_wr (uptr, op != DSC_INIT); /* new sector */
|
ds_start_wr (uptr, 1); /* new sector */
|
||||||
break;
|
break;
|
||||||
case DSC_WRITE | DSC_2ND:
|
case DSC_WRITE | DSC_2ND:
|
||||||
if (r = ds_cont_wr (uptr, 0, DS_NUMWD)) /* write word */
|
if (r = ds_cont_wr (uptr, 0, DS_NUMWD)) /* write word */
|
||||||
|
@ -882,12 +898,23 @@ case DSC_WRITE | DSC_3RD: /* end sector */
|
||||||
ds_end_rw (uptr, DSC_WRITE); /* see if more to do */
|
ds_end_rw (uptr, DSC_WRITE); /* see if more to do */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DSC_INIT: /* init */
|
||||||
|
ds_start_wr (uptr, 0); /* new sector */
|
||||||
|
break;
|
||||||
|
case DSC_INIT | DSC_2ND:
|
||||||
|
if (r = ds_cont_wr (uptr, 0, DS_NUMWD)) /* write word */
|
||||||
|
return r; /* error? */
|
||||||
|
break;
|
||||||
|
case DSC_INIT | DSC_3RD: /* end sector */
|
||||||
|
ds_end_rw (uptr, DSC_INIT); /* see if more to do */
|
||||||
|
break;
|
||||||
|
|
||||||
case DSC_WFULL: /* write full */
|
case DSC_WFULL: /* write full */
|
||||||
ds_start_wr (uptr, 0); /* new sector */
|
ds_start_wr (uptr, 0); /* new sector */
|
||||||
break;
|
break;
|
||||||
case DSC_WFULL | DSC_2ND:
|
case DSC_WFULL | DSC_2ND:
|
||||||
if (r = ds_cont_wr (uptr, DS_FDATA, DS_NUMWDF))
|
if (r = ds_cont_wr (uptr, DS_FDATA, DS_NUMWDF)) /* write word */
|
||||||
return r;
|
return r; /* error */
|
||||||
break;
|
break;
|
||||||
case DSC_WFULL | DSC_3RD:
|
case DSC_WFULL | DSC_3RD:
|
||||||
ds_end_rw (uptr, DSC_WFULL); /* see if more to do */
|
ds_end_rw (uptr, DSC_WFULL); /* see if more to do */
|
||||||
|
|
|
@ -23,8 +23,9 @@
|
||||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
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.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
ipli, iplo 12556B interprocessor link pair
|
ipli, iplo 12566B interprocessor link pair
|
||||||
|
|
||||||
|
07-Oct-04 JDB Fixed enable/disable from either device
|
||||||
26-Apr-04 RMS Fixed SFS x,C and SFC x,C
|
26-Apr-04 RMS Fixed SFS x,C and SFC x,C
|
||||||
Implemented DMA SRQ (follows FLG)
|
Implemented DMA SRQ (follows FLG)
|
||||||
21-Dec-03 RMS Adjusted ipl_ptime for TSB (from Mike Gemeny)
|
21-Dec-03 RMS Adjusted ipl_ptime for TSB (from Mike Gemeny)
|
||||||
|
@ -163,7 +164,7 @@ int32 iplio (UNIT *uptr, int32 inst, int32 IR, int32 dat)
|
||||||
{
|
{
|
||||||
uint32 u, dev, odev;
|
uint32 u, dev, odev;
|
||||||
int32 sta;
|
int32 sta;
|
||||||
int8 msg[2];
|
char msg[2];
|
||||||
|
|
||||||
dev = IR & I_DEVMASK; /* get device no */
|
dev = IR & I_DEVMASK; /* get device no */
|
||||||
switch (inst) { /* case on opcode */
|
switch (inst) { /* case on opcode */
|
||||||
|
@ -222,7 +223,7 @@ return dat;
|
||||||
t_stat ipl_svc (UNIT *uptr)
|
t_stat ipl_svc (UNIT *uptr)
|
||||||
{
|
{
|
||||||
int32 u, nb, dev;
|
int32 u, nb, dev;
|
||||||
int8 msg[2];
|
char msg[2];
|
||||||
|
|
||||||
u = uptr - ipl_unit; /* get link number */
|
u = uptr - ipl_unit; /* get link number */
|
||||||
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* not attached? */
|
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* not attached? */
|
||||||
|
@ -270,7 +271,8 @@ t_stat ipl_reset (DEVICE *dptr)
|
||||||
DIB *dibp = (DIB *) dptr->ctxt;
|
DIB *dibp = (DIB *) dptr->ctxt;
|
||||||
UNIT *uptr = dptr->units;
|
UNIT *uptr = dptr->units;
|
||||||
|
|
||||||
hp_enbdis_pair (&ipli_dev, &iplo_dev); /* make pair cons */
|
hp_enbdis_pair (dptr, /* make pair cons */
|
||||||
|
(dptr == &ipli_dev)? &iplo_dev: &ipli_dev);
|
||||||
dibp->cmd = dibp->ctl = 0; /* clear cmd, ctl */
|
dibp->cmd = dibp->ctl = 0; /* clear cmd, ctl */
|
||||||
dibp->flg = dibp->fbf = dibp->srq = 1; /* set flg, fbf, srq */
|
dibp->flg = dibp->fbf = dibp->srq = 1; /* set flg, fbf, srq */
|
||||||
uptr->IBUF = uptr->OBUF = 0; /* clr buffers */
|
uptr->IBUF = uptr->OBUF = 0; /* clr buffers */
|
||||||
|
|
|
@ -24,8 +24,15 @@
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
lps 12653A 2767 line printer
|
lps 12653A 2767 line printer
|
||||||
(based on 12556B microcircuit interface)
|
(based on 12566B microcircuit interface)
|
||||||
|
|
||||||
|
01-Oct-04 JDB Added SET OFFLINE/ONLINE, POWEROFF/POWERON
|
||||||
|
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
|
||||||
|
Added fast/realistic timing
|
||||||
|
Added debug printouts
|
||||||
03-Jun-04 RMS Fixed timing (found by Dave Bryan)
|
03-Jun-04 RMS Fixed timing (found by Dave Bryan)
|
||||||
26-Apr-04 RMS Fixed SFS x,C and SFC x,C
|
26-Apr-04 RMS Fixed SFS x,C and SFC x,C
|
||||||
Implemented DMA SRQ (follows FLG)
|
Implemented DMA SRQ (follows FLG)
|
||||||
|
@ -37,26 +44,129 @@
|
||||||
21-Nov-00 RMS Fixed flag, fbf power up state
|
21-Nov-00 RMS Fixed flag, fbf power up state
|
||||||
Added command flop
|
Added command flop
|
||||||
15-Oct-00 RMS Added variable device number support
|
15-Oct-00 RMS Added variable device number support
|
||||||
|
|
||||||
|
The 2767 impact printer has a rotating drum with 80 columns of 64 raised
|
||||||
|
characters. ASCII codes 32 through 95 (SPACE through "_") form the print
|
||||||
|
repertoire. The printer responds to the control characters FF, LF, and CR.
|
||||||
|
|
||||||
|
The 80 columns are divided into four zones of 20 characters each that are
|
||||||
|
addressed sequentially. Received characters are buffered in a 20-character
|
||||||
|
memory. When the 20th printable character is received, the current zone is
|
||||||
|
printed, and the memory is reset. In the absence of print command
|
||||||
|
characters, a zone print operation will commence after each group of 20
|
||||||
|
printable characters is transmitted to the printer.
|
||||||
|
|
||||||
|
The print command characters have these actions:
|
||||||
|
|
||||||
|
* CR -- print the characters in the current zone, reset to zone 1, and clear
|
||||||
|
the buffer memory.
|
||||||
|
* LF -- same as CR, plus advances the paper one line.
|
||||||
|
* FF -- same as CR, plus advances the paper to the top of the next form.
|
||||||
|
|
||||||
|
The 2767 provides two status bits via the interface:
|
||||||
|
|
||||||
|
bit 15 -- printer not ready
|
||||||
|
bit 0 -- printer busy
|
||||||
|
|
||||||
|
The expected status returns are:
|
||||||
|
|
||||||
|
100001 -- power off or cable disconnected
|
||||||
|
100001 -- initial power on, then changes to 000001 within sixty
|
||||||
|
seconds of initial power on
|
||||||
|
000001 -- power on, paper unloaded or printer offline or not idle
|
||||||
|
000000 -- power on, paper loaded and printer online and idle
|
||||||
|
|
||||||
|
These simulator commands provide the listed printer states:
|
||||||
|
|
||||||
|
SET LPS POWEROFF --> power off or cable disconnected
|
||||||
|
SET LPS POWERON --> power on
|
||||||
|
SET LPS OFFLINE --> printer offline
|
||||||
|
SET LPS ONLINE --> printer online
|
||||||
|
ATT LPS <file> --> paper loaded
|
||||||
|
DET LPS --> paper out
|
||||||
|
|
||||||
|
References:
|
||||||
|
- 2767A Line Printer Operating and Service Manual (02767-90002, Oct-1973)
|
||||||
|
- 12566B, 12566B-001, 12566B-002, 12566B-003 Microcircuit Interface Kits
|
||||||
|
Operating and Service Manual (12566-90015, Apr-1976)
|
||||||
|
|
||||||
|
The following implemented behaviors have been inferred from secondary sources
|
||||||
|
(diagnostics, operating system drivers, etc.), due to absent or contradictory
|
||||||
|
authoritative information; future correction may be needed:
|
||||||
|
|
||||||
|
1. Paper out sets BUSY instead of NOT READY.
|
||||||
|
2. Print operation in progress sets BUSY instead of NOT READY.
|
||||||
|
3. Characters not in the print repertoire are replaced with blanks.
|
||||||
|
4. The 81st and succeeding characters overprint the current line.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "hp2100_defs.h"
|
#include "hp2100_defs.h"
|
||||||
|
|
||||||
#define LPS_BUSY 0000001 /* busy */
|
#define LPS_ZONECNT 20 /* zone char count */
|
||||||
#define LPS_NRDY 0100000 /* not ready */
|
#define LPS_PAGECNT 80 /* page char count */
|
||||||
|
#define LPS_PAGELNT 60 /* page line length */
|
||||||
|
#define LPS_FORMLNT 66 /* form line length */
|
||||||
|
|
||||||
|
/* Printer power states */
|
||||||
|
|
||||||
|
#define LPS_ON 0 /* power is on */
|
||||||
|
#define LPS_OFF 1 /* power is off */
|
||||||
|
#define LPS_TURNING_ON 2 /* power is turning on */
|
||||||
|
|
||||||
|
#define LPS_BUSY 0000001 /* busy status */
|
||||||
|
#define LPS_NRDY 0100000 /* not ready status */
|
||||||
|
#define LPS_PWROFF LPS_BUSY | LPS_NRDY /* power-off status */
|
||||||
|
|
||||||
#define UNIT_V_DIAG (UNIT_V_UF + 0) /* diagnostic mode */
|
#define UNIT_V_DIAG (UNIT_V_UF + 0) /* diagnostic mode */
|
||||||
|
#define UNIT_V_POWEROFF (UNIT_V_UF + 1) /* unit powered off */
|
||||||
|
#define UNIT_V_OFFLINE (UNIT_V_UF + 2) /* unit offline */
|
||||||
#define UNIT_DIAG (1 << UNIT_V_DIAG)
|
#define UNIT_DIAG (1 << UNIT_V_DIAG)
|
||||||
|
#define UNIT_POWEROFF (1 << UNIT_V_POWEROFF)
|
||||||
|
#define UNIT_OFFLINE (1 << UNIT_V_OFFLINE)
|
||||||
|
|
||||||
extern uint32 PC;
|
extern uint32 PC;
|
||||||
extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2];
|
extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2];
|
||||||
int32 lps_ctime = 4; /* char time */
|
extern FILE *sim_deb;
|
||||||
int32 lps_ptime = 10000; /* print time */
|
|
||||||
|
int32 lps_ccnt = 0; /* character count */
|
||||||
|
int32 lps_lcnt = 0; /* line count */
|
||||||
int32 lps_stopioe = 0; /* stop on error */
|
int32 lps_stopioe = 0; /* stop on error */
|
||||||
int32 lps_sta = 0;
|
int32 lps_sta = 0; /* printer status */
|
||||||
|
int32 lps_timing = 1; /* timing type */
|
||||||
|
uint32 lps_power = LPS_ON; /* power state */
|
||||||
|
|
||||||
|
/* Hardware timing:
|
||||||
|
(based on 1580 instr/msec) instr msec calc msec
|
||||||
|
------------------------
|
||||||
|
- character transfer time : ctime = 2 2 us
|
||||||
|
- per-zone printing time : ptime = 55300 35 40
|
||||||
|
- per-line paper slew time : stime = 17380 11 13
|
||||||
|
- power-on ready delay time : rtime = 158000 100
|
||||||
|
|
||||||
|
NOTE: the printer acknowledges before the print motion has stopped to allow
|
||||||
|
for continuous slew, so the set times are a bit less than the calculated
|
||||||
|
operation time from the manual.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int32 lps_ctime = 0; /* char xfer time */
|
||||||
|
int32 lps_ptime = 0; /* zone printing time */
|
||||||
|
int32 lps_stime = 0; /* paper slew time */
|
||||||
|
int32 lps_rtime = 0; /* power-on ready time */
|
||||||
|
|
||||||
|
typedef int32 TIMESET[4]; /* set of controller times */
|
||||||
|
|
||||||
|
int32 *const lps_timers[] = { &lps_ctime, &lps_ptime, &lps_stime, &lps_rtime };
|
||||||
|
|
||||||
|
const TIMESET lps_times[2] = { { 2, 55300, 17380, 158000 }, /* REALTIME */
|
||||||
|
{ 2, 1000, 1000, 1000 } }; /* FASTTIME */
|
||||||
|
|
||||||
DEVICE lps_dev;
|
DEVICE lps_dev;
|
||||||
int32 lpsio (int32 inst, int32 IR, int32 dat);
|
int32 lpsio (int32 inst, int32 IR, int32 dat);
|
||||||
t_stat lps_svc (UNIT *uptr);
|
t_stat lps_svc (UNIT *uptr);
|
||||||
t_stat lps_reset (DEVICE *dptr);
|
t_stat lps_reset (DEVICE *dptr);
|
||||||
|
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);
|
||||||
|
|
||||||
/* LPS data structures
|
/* LPS data structures
|
||||||
|
|
||||||
|
@ -68,19 +178,25 @@ t_stat lps_reset (DEVICE *dptr);
|
||||||
DIB lps_dib = { LPS, 0, 0, 0, 0, 0, &lpsio };
|
DIB lps_dib = { LPS, 0, 0, 0, 0, 0, &lpsio };
|
||||||
|
|
||||||
UNIT lps_unit = {
|
UNIT lps_unit = {
|
||||||
UDATA (&lps_svc, UNIT_SEQ+UNIT_ATTABLE, 0) };
|
UDATA (&lps_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_DISABLE, 0) };
|
||||||
|
|
||||||
REG lps_reg[] = {
|
REG lps_reg[] = {
|
||||||
{ ORDATA (BUF, lps_unit.buf, 16) },
|
{ ORDATA (BUF, lps_unit.buf, 16) },
|
||||||
{ ORDATA (STA, lps_sta, 16) },
|
{ ORDATA (STA, lps_sta, 16) },
|
||||||
|
{ ORDATA (POWER, lps_power, 2), REG_RO },
|
||||||
{ FLDATA (CMD, lps_dib.cmd, 0) },
|
{ FLDATA (CMD, lps_dib.cmd, 0) },
|
||||||
{ FLDATA (CTL, lps_dib.ctl, 0) },
|
{ FLDATA (CTL, lps_dib.ctl, 0) },
|
||||||
{ FLDATA (FLG, lps_dib.flg, 0) },
|
{ FLDATA (FLG, lps_dib.flg, 0) },
|
||||||
{ FLDATA (FBF, lps_dib.fbf, 0) },
|
{ FLDATA (FBF, lps_dib.fbf, 0) },
|
||||||
{ FLDATA (SRQ, lps_dib.srq, 0) },
|
{ FLDATA (SRQ, lps_dib.srq, 0) },
|
||||||
|
{ DRDATA (CCNT, lps_ccnt, 7), PV_LEFT },
|
||||||
|
{ DRDATA (LCNT, lps_lcnt, 7), PV_LEFT },
|
||||||
{ DRDATA (POS, lps_unit.pos, T_ADDR_W), PV_LEFT },
|
{ DRDATA (POS, lps_unit.pos, T_ADDR_W), PV_LEFT },
|
||||||
{ DRDATA (CTIME, lps_ctime, 31), PV_LEFT },
|
{ DRDATA (CTIME, lps_ctime, 24), PV_LEFT },
|
||||||
{ DRDATA (PTIME, lps_ptime, 24), PV_LEFT },
|
{ DRDATA (PTIME, lps_ptime, 24), PV_LEFT },
|
||||||
|
{ DRDATA (STIME, lps_stime, 24), PV_LEFT },
|
||||||
|
{ DRDATA (RTIME, lps_rtime, 24), PV_LEFT },
|
||||||
|
{ FLDATA (TIMING, lps_timing, 0), REG_HRO },
|
||||||
{ FLDATA (STOP_IOE, lps_stopioe, 0) },
|
{ FLDATA (STOP_IOE, lps_stopioe, 0) },
|
||||||
{ ORDATA (DEVNO, lps_dib.devno, 6), REG_HRO },
|
{ ORDATA (DEVNO, lps_dib.devno, 6), REG_HRO },
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
@ -88,6 +204,16 @@ REG lps_reg[] = {
|
||||||
MTAB lps_mod[] = {
|
MTAB lps_mod[] = {
|
||||||
{ UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", NULL },
|
{ UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", NULL },
|
||||||
{ UNIT_DIAG, 0, "printer mode", "PRINTER", NULL },
|
{ UNIT_DIAG, 0, "printer mode", "PRINTER", NULL },
|
||||||
|
{ UNIT_POWEROFF, UNIT_POWEROFF, "power off", "POWEROFF", NULL },
|
||||||
|
{ UNIT_POWEROFF, 0, "power on", "POWERON", NULL },
|
||||||
|
{ UNIT_OFFLINE, UNIT_OFFLINE, "offline", "OFFLINE", NULL },
|
||||||
|
{ UNIT_OFFLINE, 0, "online", "ONLINE", NULL },
|
||||||
|
{ MTAB_XTD | MTAB_VDV, 0, NULL, "REALTIME",
|
||||||
|
&lps_set_timing, NULL, NULL },
|
||||||
|
{ MTAB_XTD | MTAB_VDV, 1, NULL, "FASTTIME",
|
||||||
|
&lps_set_timing, NULL, NULL },
|
||||||
|
{ MTAB_XTD | MTAB_VDV, 0, "TIMING", NULL,
|
||||||
|
NULL, &lps_show_timing, NULL },
|
||||||
{ MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO",
|
{ MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||||
&hp_setdev, &hp_showdev, &lps_dev },
|
&hp_setdev, &hp_showdev, &lps_dev },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
@ -96,14 +222,14 @@ DEVICE lps_dev = {
|
||||||
"LPS", &lps_unit, lps_reg, lps_mod,
|
"LPS", &lps_unit, lps_reg, lps_mod,
|
||||||
1, 10, 31, 1, 8, 8,
|
1, 10, 31, 1, 8, 8,
|
||||||
NULL, NULL, &lps_reset,
|
NULL, NULL, &lps_reset,
|
||||||
NULL, NULL, NULL,
|
NULL, &lps_attach, NULL,
|
||||||
&lps_dib, DEV_DISABLE | DEV_DIS };
|
&lps_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG };
|
||||||
|
|
||||||
/* Line printer IOT routine */
|
/* Line printer IOT routine */
|
||||||
|
|
||||||
int32 lpsio (int32 inst, int32 IR, int32 dat)
|
int32 lpsio (int32 inst, int32 IR, int32 dat)
|
||||||
{
|
{
|
||||||
int32 dev;
|
int32 dev, sched;
|
||||||
|
|
||||||
dev = IR & I_DEVMASK; /* get device no */
|
dev = IR & I_DEVMASK; /* get device no */
|
||||||
switch (inst) { /* case on opcode */
|
switch (inst) { /* case on opcode */
|
||||||
|
@ -117,18 +243,37 @@ case ioSFS: /* skip flag set */
|
||||||
if (FLG (dev) != 0) PC = (PC + 1) & VAMASK;
|
if (FLG (dev) != 0) PC = (PC + 1) & VAMASK;
|
||||||
break;
|
break;
|
||||||
case ioOTX: /* output */
|
case ioOTX: /* output */
|
||||||
|
if (DEBUG_PRS (lps_dev))
|
||||||
|
fprintf (sim_deb, ">>LPS OTx: Character %06o output\n", dat);
|
||||||
lps_unit.buf = dat;
|
lps_unit.buf = dat;
|
||||||
break;
|
break;
|
||||||
case ioLIX: /* load */
|
case ioLIX: /* load */
|
||||||
dat = 0; /* default sta = 0 */
|
dat = 0; /* default sta = 0 */
|
||||||
case ioMIX: /* merge */
|
case ioMIX: /* merge */
|
||||||
if ((lps_unit.flags & UNIT_DIAG) == 0) { /* real lpt? */
|
if ((lps_unit.flags & UNIT_DIAG) == 0) { /* real lpt? */
|
||||||
lps_sta = 0; /* create status */
|
if (lps_power == LPS_ON) { /* power on? */
|
||||||
if ((lps_unit.flags & UNIT_ATT) == 0)
|
if (lps_unit.flags & UNIT_POWEROFF) { /* power just turned off? */
|
||||||
lps_sta = lps_sta | LPS_BUSY | LPS_NRDY;
|
lps_power = LPS_OFF; /* change state */
|
||||||
else if (sim_is_active (&lps_unit))
|
lps_sta = LPS_PWROFF;
|
||||||
lps_sta = lps_sta | LPS_BUSY; }
|
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 ); } }
|
||||||
dat = dat | lps_sta; /* diag, rtn status */
|
dat = dat | lps_sta; /* diag, rtn status */
|
||||||
|
if (DEBUG_PRS (lps_dev))
|
||||||
|
fprintf (sim_deb, ">>LPS LIx: Status %06o returned\n", dat);
|
||||||
break;
|
break;
|
||||||
case ioCTL: /* control clear/set */
|
case ioCTL: /* control clear/set */
|
||||||
if (IR & I_CTL) { /* CLC */
|
if (IR & I_CTL) { /* CLC */
|
||||||
|
@ -139,8 +284,36 @@ case ioCTL: /* control clear/set */
|
||||||
setCTL (dev);
|
setCTL (dev);
|
||||||
if (lps_unit.flags & UNIT_DIAG) /* diagnostic? */
|
if (lps_unit.flags & UNIT_DIAG) /* diagnostic? */
|
||||||
sim_activate (&lps_unit, 1); /* loop back */
|
sim_activate (&lps_unit, 1); /* loop back */
|
||||||
else sim_activate (&lps_unit, /* real lpt, sched */
|
else { /* real lpt, sched */
|
||||||
(lps_unit.buf < 040)? lps_ptime: lps_ctime); }
|
if (DEBUG_PRS (lps_dev)) fprintf (sim_deb,
|
||||||
|
">>LPS STC: Character %06o scheduled for line %d, column %d, ",
|
||||||
|
lps_unit.buf, lps_lcnt + 1, lps_ccnt + 1);
|
||||||
|
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 */
|
||||||
|
else { /* print cmd */
|
||||||
|
if (lps_ccnt % LPS_ZONECNT == 0) /* last zone printed? */
|
||||||
|
sched = lps_ctime; /* yes, so just char time */
|
||||||
|
else sched = lps_ptime; /* no, so print needed */
|
||||||
|
lps_ccnt = 0; /* reset char counter */
|
||||||
|
if (lps_unit.buf == '\n') { /* line advance */
|
||||||
|
lps_lcnt = (lps_lcnt + 1) % LPS_PAGELNT;
|
||||||
|
if (lps_lcnt > 0) sched = sched + lps_stime;
|
||||||
|
else sched = sched + /* allow for perf skip */
|
||||||
|
lps_stime * (LPS_FORMLNT - LPS_PAGELNT); }
|
||||||
|
else if (lps_unit.buf == '\f') { /* form advance */
|
||||||
|
sched = sched + lps_stime * (LPS_FORMLNT - lps_lcnt);
|
||||||
|
lps_lcnt = 0; } }
|
||||||
|
sim_activate (&lps_unit, sched);
|
||||||
|
if (DEBUG_PRS (lps_dev))
|
||||||
|
fprintf (sim_deb, "time = %d\n", sched); } }
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break; }
|
break; }
|
||||||
|
@ -151,21 +324,45 @@ return dat;
|
||||||
t_stat lps_svc (UNIT *uptr)
|
t_stat lps_svc (UNIT *uptr)
|
||||||
{
|
{
|
||||||
int32 dev;
|
int32 dev;
|
||||||
int32 c = lps_unit.buf & 0177;
|
int32 c = uptr->buf & 0177;
|
||||||
|
|
||||||
|
if (lps_power == LPS_TURNING_ON) { /* printer warmed up? */
|
||||||
|
lps_power = LPS_ON; /* change state */
|
||||||
|
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 */
|
dev = lps_dib.devno; /* get dev no */
|
||||||
clrCMD (dev); /* clear cmd */
|
clrCMD (dev); /* clear cmd */
|
||||||
setFSR (dev); /* set flag, fbf */
|
setFSR (dev); /* set flag, fbf */
|
||||||
if (lps_unit.flags & UNIT_DIAG) { /* diagnostic? */
|
if (uptr->flags & UNIT_DIAG) { /* diagnostic? */
|
||||||
lps_sta = lps_unit.buf; /* loop back */
|
lps_sta = uptr->buf; /* loop back */
|
||||||
return SCPE_OK; } /* done */
|
return SCPE_OK; } /* done */
|
||||||
if ((lps_unit.flags & UNIT_ATT) == 0) /* real lpt, att? */
|
if ((uptr->flags & UNIT_ATT) == 0) /* real lpt, att? */
|
||||||
return IORETURN (lps_stopioe, SCPE_UNATT);
|
return IORETURN (lps_stopioe, SCPE_UNATT);
|
||||||
if (fputc (c, lps_unit.fileref) == EOF) {
|
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); }
|
||||||
|
if (lps_ccnt > LPS_PAGECNT) { /* 81st character? */
|
||||||
|
fputc ('\r', uptr->fileref); /* return to line start */
|
||||||
|
uptr->pos = uptr->pos + 1; /* update pos */
|
||||||
|
lps_ccnt = 1; /* reset char counter */
|
||||||
|
if (DEBUG_PRS (lps_dev))
|
||||||
|
fputs (">>LPS svc: Line wraparound to column 1\n", sim_deb); }
|
||||||
|
fputc (c, uptr->fileref); /* "print" char */
|
||||||
|
uptr->pos = uptr->pos + 1; /* update pos */
|
||||||
|
if (DEBUG_PRS (lps_dev))
|
||||||
|
fprintf (sim_deb, ">>LPS svc: Character %06o printed\n", c);
|
||||||
|
if ((lps_lcnt == 0) && (c == '\n')) { /* LF did TOF? */
|
||||||
|
fputc ('\f', uptr->fileref); /* do perf skip */
|
||||||
|
uptr->pos = uptr->pos + 1; /* update pos */
|
||||||
|
if (DEBUG_PRS (lps_dev))
|
||||||
|
fputs (">>LPS svc: Perforation skip to TOF\n", sim_deb); }
|
||||||
|
if (ferror (uptr->fileref)) {
|
||||||
perror ("LPS I/O error");
|
perror ("LPS I/O error");
|
||||||
clearerr (lps_unit.fileref);
|
clearerr (uptr->fileref);
|
||||||
return SCPE_IOERR; }
|
return SCPE_IOERR; }
|
||||||
lps_unit.pos = lps_unit.pos + 1; /* update pos */
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,6 +373,37 @@ t_stat lps_reset (DEVICE *dptr)
|
||||||
lps_dib.cmd = lps_dib.ctl = 0; /* clear cmd, ctl */
|
lps_dib.cmd = lps_dib.ctl = 0; /* clear cmd, ctl */
|
||||||
lps_dib.flg = lps_dib.fbf = lps_dib.srq = 1; /* set flg, fbf, srq */
|
lps_dib.flg = lps_dib.fbf = lps_dib.srq = 1; /* set flg, fbf, srq */
|
||||||
lps_sta = lps_unit.buf = 0;
|
lps_sta = lps_unit.buf = 0;
|
||||||
|
lps_power = LPS_ON; /* power is on */
|
||||||
sim_cancel (&lps_unit); /* deactivate unit */
|
sim_cancel (&lps_unit); /* deactivate unit */
|
||||||
|
lps_set_timing (NULL, lps_timing, NULL, NULL); /* init timing set */
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attach routine */
|
||||||
|
|
||||||
|
t_stat lps_attach (UNIT *uptr, char *cptr)
|
||||||
|
{
|
||||||
|
lps_ccnt = lps_lcnt = 0; /* top of form */
|
||||||
|
return attach_unit (uptr, cptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set printer timing */
|
||||||
|
|
||||||
|
t_stat lps_set_timing (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
int32 i;
|
||||||
|
|
||||||
|
lps_timing = (val != 0); /* determine choice */
|
||||||
|
for (i = 0; i < (sizeof (lps_timers) / sizeof (lps_timers[0])); i++)
|
||||||
|
*lps_timers[i] = lps_times[lps_timing][i]; /* assign times */
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Show printer timing */
|
||||||
|
|
||||||
|
t_stat lps_show_timing (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
|
{
|
||||||
|
if (lps_timing) fputs ("fast timing", st);
|
||||||
|
else fputs ("realistic timing", st);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* hp2100_lpt.c: HP 2100 12845A line printer simulator
|
/* hp2100_lpt.c: HP 2100 12845B line printer simulator
|
||||||
|
|
||||||
Copyright (c) 1993-2004, Robert M. Supnik
|
Copyright (c) 1993-2004, Robert M. Supnik
|
||||||
|
|
||||||
|
@ -23,13 +23,45 @@
|
||||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
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.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
lpt 12845A line printer
|
lpt 12845B 2607 line printer
|
||||||
|
|
||||||
|
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
|
||||||
03-Jun-04 RMS Fixed timing (found by Dave Bryan)
|
03-Jun-04 RMS Fixed timing (found by Dave Bryan)
|
||||||
26-Apr-04 RMS Fixed SFS x,C and SFC x,C
|
26-Apr-04 RMS Fixed SFS x,C and SFC x,C
|
||||||
Implemented DMA SRQ (follows FLG)
|
Implemented DMA SRQ (follows FLG)
|
||||||
25-Apr-03 RMS Revised for extended file support
|
25-Apr-03 RMS Revised for extended file support
|
||||||
24-Oct-02 RMS Cloned from 12653A
|
24-Oct-02 RMS Cloned from 12653A
|
||||||
|
|
||||||
|
The 2607 provides three status bits via the interface:
|
||||||
|
|
||||||
|
bit 15 -- printer ready (online)
|
||||||
|
bit 14 -- paper out
|
||||||
|
bit 0 -- printer idle
|
||||||
|
|
||||||
|
The expected status returns are:
|
||||||
|
|
||||||
|
140001 -- power off or cable disconnected
|
||||||
|
100001 -- power on, paper loaded, printer ready
|
||||||
|
100000 -- power on, paper loaded, printer busy
|
||||||
|
040000 -- power on, paper out (at bottom-of-form)
|
||||||
|
000000 -- power on, paper out (not at BOF) / print button up / platen open
|
||||||
|
|
||||||
|
Manual Note: "2-33. PAPER OUT SIGNAL. [...] The signal is asserted only
|
||||||
|
when the format tape in the line printer has reached the bottom of form."
|
||||||
|
|
||||||
|
These simulator commands provide the listed printer states:
|
||||||
|
|
||||||
|
SET LPT POWEROFF --> power off or cable disconnected
|
||||||
|
SET LPT POWERON --> power on
|
||||||
|
SET LPT OFFLINE --> print button up
|
||||||
|
SET LPT ONLINE --> print button down
|
||||||
|
ATT LPT <file> --> paper loaded
|
||||||
|
DET LPT --> paper out
|
||||||
|
|
||||||
|
Reference:
|
||||||
|
- 12845A Line Printer Operating and Service Manual (12845-90001, Aug-1972)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "hp2100_defs.h"
|
#include "hp2100_defs.h"
|
||||||
|
@ -39,12 +71,18 @@
|
||||||
#define LPT_NBSY 0000001 /* not busy */
|
#define LPT_NBSY 0000001 /* not busy */
|
||||||
#define LPT_PAPO 0040000 /* paper out */
|
#define LPT_PAPO 0040000 /* paper out */
|
||||||
#define LPT_RDY 0100000 /* ready */
|
#define LPT_RDY 0100000 /* ready */
|
||||||
|
#define LPT_PWROFF LPT_RDY | LPT_PAPO | LPT_NBSY /* power-off status */
|
||||||
|
|
||||||
#define LPT_CTL 0100000 /* control output */
|
#define LPT_CTL 0100000 /* control output */
|
||||||
#define LPT_CHAN 0000100 /* skip to chan */
|
#define LPT_CHAN 0000100 /* skip to chan */
|
||||||
#define LPT_SKIPM 0000077 /* line count mask */
|
#define LPT_SKIPM 0000077 /* line count mask */
|
||||||
#define LPT_CHANM 0000007 /* channel mask */
|
#define LPT_CHANM 0000007 /* channel mask */
|
||||||
|
|
||||||
|
#define UNIT_V_POWEROFF (UNIT_V_UF + 0) /* unit powered off */
|
||||||
|
#define UNIT_V_OFFLINE (UNIT_V_UF + 1) /* unit offline */
|
||||||
|
#define UNIT_POWEROFF (1 << UNIT_V_POWEROFF)
|
||||||
|
#define UNIT_OFFLINE (1 << UNIT_V_OFFLINE)
|
||||||
|
|
||||||
extern uint32 PC;
|
extern uint32 PC;
|
||||||
extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2];
|
extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2], dev_srq[2];
|
||||||
|
|
||||||
|
@ -71,7 +109,7 @@ t_stat lpt_attach (UNIT *uptr, char *cptr);
|
||||||
DIB lpt_dib = { LPT, 0, 0, 0, 0, 0, &lptio };
|
DIB lpt_dib = { LPT, 0, 0, 0, 0, 0, &lptio };
|
||||||
|
|
||||||
UNIT lpt_unit = {
|
UNIT lpt_unit = {
|
||||||
UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0) };
|
UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_DISABLE, 0) };
|
||||||
|
|
||||||
REG lpt_reg[] = {
|
REG lpt_reg[] = {
|
||||||
{ ORDATA (BUF, lpt_unit.buf, 7) },
|
{ ORDATA (BUF, lpt_unit.buf, 7) },
|
||||||
|
@ -89,6 +127,10 @@ REG lpt_reg[] = {
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
MTAB lpt_mod[] = {
|
MTAB lpt_mod[] = {
|
||||||
|
{ UNIT_POWEROFF, UNIT_POWEROFF, "power off", "POWEROFF", NULL },
|
||||||
|
{ UNIT_POWEROFF, 0, "power on", "POWERON", NULL },
|
||||||
|
{ UNIT_OFFLINE, UNIT_OFFLINE, "offline", "OFFLINE", NULL },
|
||||||
|
{ UNIT_OFFLINE, 0, "online", "ONLINE", NULL },
|
||||||
{ MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO",
|
{ MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||||
&hp_setdev, &hp_showdev, &lpt_dev },
|
&hp_setdev, &hp_showdev, &lpt_dev },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
@ -123,11 +165,15 @@ case ioOTX: /* output */
|
||||||
case ioLIX: /* load */
|
case ioLIX: /* load */
|
||||||
dat = 0; /* default sta = 0 */
|
dat = 0; /* default sta = 0 */
|
||||||
case ioMIX: /* merge */
|
case ioMIX: /* merge */
|
||||||
if (lpt_unit.flags & UNIT_ATT) {
|
if (lpt_unit.flags & UNIT_POWEROFF) /* power off? */
|
||||||
|
dat = dat | LPT_PWROFF;
|
||||||
|
else if (!(lpt_unit.flags & UNIT_OFFLINE)) /* online? */
|
||||||
|
if (lpt_unit.flags & UNIT_ATT) { /* paper loaded? */
|
||||||
dat = dat | LPT_RDY;
|
dat = dat | LPT_RDY;
|
||||||
if (!sim_is_active (&lpt_unit))
|
if (!sim_is_active (&lpt_unit)) /* printer busy? */
|
||||||
dat = dat | LPT_NBSY; }
|
dat = dat | LPT_NBSY; }
|
||||||
else dat = dat | LPT_PAPO;
|
else if (lpt_lcnt == LPT_PAGELNT - 1) /* paper out, at BOF? */
|
||||||
|
dat = dat | LPT_PAPO;
|
||||||
break;
|
break;
|
||||||
case ioCTL: /* control clear/set */
|
case ioCTL: /* control clear/set */
|
||||||
if (IR & I_CTL) { /* CLC */
|
if (IR & I_CTL) { /* CLC */
|
||||||
|
@ -160,7 +206,7 @@ if (uptr->buf & LPT_CTL) { /* control word? */
|
||||||
if (chan == 0) { /* top of form? */
|
if (chan == 0) { /* top of form? */
|
||||||
fputc ('\f', uptr->fileref); /* ffeed */
|
fputc ('\f', uptr->fileref); /* ffeed */
|
||||||
lpt_lcnt = 0; /* reset line cnt */
|
lpt_lcnt = 0; /* reset line cnt */
|
||||||
skip = 1; }
|
skip = 0; }
|
||||||
else if (chan == 1) skip = LPT_PAGELNT - lpt_lcnt - 1;
|
else if (chan == 1) skip = LPT_PAGELNT - lpt_lcnt - 1;
|
||||||
else skip = lpt_cct[chan] - (lpt_lcnt % lpt_cct[chan]);
|
else skip = lpt_cct[chan] - (lpt_lcnt % lpt_cct[chan]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
ms 13181A 7970B 800bpi nine track magnetic tape
|
ms 13181A 7970B 800bpi nine track magnetic tape
|
||||||
13183A 7970E 1600bpi nine track magnetic tape
|
13183A 7970E 1600bpi nine track magnetic tape
|
||||||
|
|
||||||
|
07-Oct-04 JDB Fixed enable/disable from either device
|
||||||
14-Aug-04 JDB Fixed many functional and timing problems (from Dave Bryan)
|
14-Aug-04 JDB Fixed many functional and timing problems (from Dave Bryan)
|
||||||
- fixed erroneous execution of rejected command
|
- fixed erroneous execution of rejected command
|
||||||
- fixed erroneous execution of select-only command
|
- fixed erroneous execution of select-only command
|
||||||
|
@ -63,6 +64,12 @@
|
||||||
|
|
||||||
If the byte count is odd, the record is padded with an extra byte
|
If the byte count is odd, the record is padded with an extra byte
|
||||||
of junk. File marks are represented by a byte count of 0.
|
of junk. File marks are represented by a byte count of 0.
|
||||||
|
|
||||||
|
References:
|
||||||
|
- 13181B Digital Magnetic Tape Unit Interface Kit Operating and Service Manual
|
||||||
|
(13181-90901, Nov-1982)
|
||||||
|
- 13183B Digital Magnetic Tape Unit Interface Kit Operating and Service Manual
|
||||||
|
(13183-90901, Nov-1983)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "hp2100_defs.h"
|
#include "hp2100_defs.h"
|
||||||
|
@ -233,7 +240,7 @@ DEVICE msd_dev = {
|
||||||
1, 10, DB_N_SIZE, 1, 8, 8,
|
1, 10, DB_N_SIZE, 1, 8, 8,
|
||||||
NULL, NULL, &msc_reset,
|
NULL, NULL, &msc_reset,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
&msd_dib, 0 };
|
&msd_dib, DEV_DISABLE };
|
||||||
|
|
||||||
/* MSC data structures
|
/* MSC data structures
|
||||||
|
|
||||||
|
@ -646,7 +653,8 @@ t_stat msc_reset (DEVICE *dptr)
|
||||||
int32 i;
|
int32 i;
|
||||||
UNIT *uptr;
|
UNIT *uptr;
|
||||||
|
|
||||||
hp_enbdis_pair (&msc_dev, &msd_dev); /* make pair cons */
|
hp_enbdis_pair (dptr, /* make pair cons */
|
||||||
|
(dptr == &msd_dev)? &msc_dev: &msd_dev);
|
||||||
msc_buf = msd_buf = 0;
|
msc_buf = msd_buf = 0;
|
||||||
msc_sta = msc_usl = 0;
|
msc_sta = msc_usl = 0;
|
||||||
msc_1st = 0;
|
msc_1st = 0;
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
mt 12559A 3030 nine track magnetic tape
|
mt 12559A 3030 nine track magnetic tape
|
||||||
|
|
||||||
|
07-Oct-04 JDB Allow enable/disable from either device
|
||||||
14-Aug-04 RMS Modified handling of end of medium (suggested by Dave Bryan)
|
14-Aug-04 RMS Modified handling of end of medium (suggested by Dave Bryan)
|
||||||
06-Jul-04 RMS Fixed spurious timing error after CLC (found by Dave Bryan)
|
06-Jul-04 RMS Fixed spurious timing error after CLC (found by Dave Bryan)
|
||||||
26-Apr-04 RMS Fixed SFS x,C and SFC x,C
|
26-Apr-04 RMS Fixed SFS x,C and SFC x,C
|
||||||
|
@ -111,6 +112,7 @@ DEVICE mtd_dev, mtc_dev;
|
||||||
int32 mtdio (int32 inst, int32 IR, int32 dat);
|
int32 mtdio (int32 inst, int32 IR, int32 dat);
|
||||||
int32 mtcio (int32 inst, int32 IR, int32 dat);
|
int32 mtcio (int32 inst, int32 IR, int32 dat);
|
||||||
t_stat mtc_svc (UNIT *uptr);
|
t_stat mtc_svc (UNIT *uptr);
|
||||||
|
t_stat mtd_reset (DEVICE *dptr);
|
||||||
t_stat mtc_reset (DEVICE *dptr);
|
t_stat mtc_reset (DEVICE *dptr);
|
||||||
t_stat mtc_attach (UNIT *uptr, char *cptr);
|
t_stat mtc_attach (UNIT *uptr, char *cptr);
|
||||||
t_stat mtc_detach (UNIT *uptr);
|
t_stat mtc_detach (UNIT *uptr);
|
||||||
|
@ -156,7 +158,7 @@ MTAB mtd_mod[] = {
|
||||||
DEVICE mtd_dev = {
|
DEVICE mtd_dev = {
|
||||||
"MTD", &mtd_unit, mtd_reg, mtd_mod,
|
"MTD", &mtd_unit, mtd_reg, mtd_mod,
|
||||||
1, 10, 16, 1, 8, 8,
|
1, 10, 16, 1, 8, 8,
|
||||||
NULL, NULL, &mtc_reset,
|
NULL, NULL, &mtd_reset,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
&mtd_dib, DEV_DISABLE | DEV_DIS };
|
&mtd_dib, DEV_DISABLE | DEV_DIS };
|
||||||
|
|
||||||
|
@ -447,6 +449,12 @@ return SCPE_OK;
|
||||||
|
|
||||||
/* Reset routine */
|
/* Reset routine */
|
||||||
|
|
||||||
|
t_stat mtd_reset (DEVICE *dptr)
|
||||||
|
{
|
||||||
|
hp_enbdis_pair (&mtd_dev, &mtc_dev); /* make pair cons */
|
||||||
|
return mtc_reset (dptr); /* do common reset */
|
||||||
|
}
|
||||||
|
|
||||||
t_stat mtc_reset (DEVICE *dptr)
|
t_stat mtc_reset (DEVICE *dptr)
|
||||||
{
|
{
|
||||||
hp_enbdis_pair (&mtc_dev, &mtd_dev); /* make pair cons */
|
hp_enbdis_pair (&mtc_dev, &mtd_dev); /* make pair cons */
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
mux,muxl,muxc 12920A terminal multiplexor
|
mux,muxl,muxc 12920A terminal multiplexor
|
||||||
|
|
||||||
|
07-Oct-04 JDB Allow enable/disable from any device
|
||||||
26-Apr-04 RMS Fixed SFS x,C and SFC x,C
|
26-Apr-04 RMS Fixed SFS x,C and SFC x,C
|
||||||
Implemented DMA SRQ (follows FLG)
|
Implemented DMA SRQ (follows FLG)
|
||||||
05-Jan-04 RMS Revised for tmxr library changes
|
05-Jan-04 RMS Revised for tmxr library changes
|
||||||
|
@ -41,6 +42,10 @@
|
||||||
|
|
||||||
The lower data card has no CMD flop; the control card has no CMD flop.
|
The lower data card has no CMD flop; the control card has no CMD flop.
|
||||||
The upper data card has none of the usual flops.
|
The upper data card has none of the usual flops.
|
||||||
|
|
||||||
|
Reference:
|
||||||
|
- 12920A Asynchronous Multiplexer Interface Kits Operating and Service
|
||||||
|
Manual (12920-90001, Oct-1972)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "hp2100_defs.h"
|
#include "hp2100_defs.h"
|
||||||
|
@ -163,7 +168,7 @@ int32 muxuio (int32 inst, int32 IR, int32 dat);
|
||||||
int32 muxcio (int32 inst, int32 IR, int32 dat);
|
int32 muxcio (int32 inst, int32 IR, int32 dat);
|
||||||
t_stat muxi_svc (UNIT *uptr);
|
t_stat muxi_svc (UNIT *uptr);
|
||||||
t_stat muxo_svc (UNIT *uptr);
|
t_stat muxo_svc (UNIT *uptr);
|
||||||
t_stat mux_reset (DEVICE *dptr);
|
t_stat muxc_reset (DEVICE *dptr);
|
||||||
t_stat mux_attach (UNIT *uptr, char *cptr);
|
t_stat mux_attach (UNIT *uptr, char *cptr);
|
||||||
t_stat mux_detach (UNIT *uptr);
|
t_stat mux_detach (UNIT *uptr);
|
||||||
t_stat mux_summ (FILE *st, UNIT *uptr, int32 val, void *desc);
|
t_stat mux_summ (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
|
@ -235,7 +240,7 @@ MTAB muxu_mod[] = {
|
||||||
DEVICE muxu_dev = {
|
DEVICE muxu_dev = {
|
||||||
"MUX", &muxu_unit, muxu_reg, muxu_mod,
|
"MUX", &muxu_unit, muxu_reg, muxu_mod,
|
||||||
1, 10, 31, 1, 8, 8,
|
1, 10, 31, 1, 8, 8,
|
||||||
&tmxr_ex, &tmxr_dep, &mux_reset,
|
&tmxr_ex, &tmxr_dep, &muxc_reset,
|
||||||
NULL, &mux_attach, &mux_detach,
|
NULL, &mux_attach, &mux_detach,
|
||||||
&muxu_dib, DEV_NET | DEV_DISABLE };
|
&muxu_dib, DEV_NET | DEV_DISABLE };
|
||||||
|
|
||||||
|
@ -301,9 +306,9 @@ REG muxl_reg[] = {
|
||||||
DEVICE muxl_dev = {
|
DEVICE muxl_dev = {
|
||||||
"MUXL", muxl_unit, muxl_reg, muxl_mod,
|
"MUXL", muxl_unit, muxl_reg, muxl_mod,
|
||||||
MUX_LINES, 10, 31, 1, 8, 8,
|
MUX_LINES, 10, 31, 1, 8, 8,
|
||||||
NULL, NULL, &mux_reset,
|
NULL, NULL, &muxc_reset,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
&muxl_dib, 0 };
|
&muxl_dib, DEV_DISABLE };
|
||||||
|
|
||||||
/* MUXM data structures
|
/* MUXM data structures
|
||||||
|
|
||||||
|
@ -338,9 +343,9 @@ MTAB muxc_mod[] = {
|
||||||
DEVICE muxc_dev = {
|
DEVICE muxc_dev = {
|
||||||
"MUXM", &muxc_unit, muxc_reg, muxc_mod,
|
"MUXM", &muxc_unit, muxc_reg, muxc_mod,
|
||||||
1, 10, 31, 1, 8, 8,
|
1, 10, 31, 1, 8, 8,
|
||||||
NULL, NULL, &mux_reset,
|
NULL, NULL, &muxc_reset,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
&muxc_dib, 0 };
|
&muxc_dib, DEV_DISABLE };
|
||||||
|
|
||||||
/* IOT routines: data cards */
|
/* IOT routines: data cards */
|
||||||
|
|
||||||
|
@ -634,15 +639,18 @@ return;
|
||||||
|
|
||||||
/* Reset routine */
|
/* Reset routine */
|
||||||
|
|
||||||
t_stat mux_reset (DEVICE *dptr)
|
t_stat muxc_reset (DEVICE *dptr)
|
||||||
{
|
{
|
||||||
int32 i, t;
|
int32 i, t;
|
||||||
|
|
||||||
if (muxu_dev.flags & DEV_DIS) { /* enb/dis dev */
|
if (dptr == &muxc_dev) { /* make all consistent */
|
||||||
muxl_dev.flags = muxu_dev.flags | DEV_DIS;
|
hp_enbdis_pair (dptr, &muxl_dev);
|
||||||
muxc_dev.flags = muxc_dev.flags | DEV_DIS; }
|
hp_enbdis_pair (dptr, &muxu_dev); }
|
||||||
else { muxl_dev.flags = muxl_dev.flags & ~DEV_DIS;
|
else if (dptr == &muxl_dev) {
|
||||||
muxc_dev.flags = muxc_dev.flags & ~DEV_DIS; }
|
hp_enbdis_pair (dptr, &muxc_dev);
|
||||||
|
hp_enbdis_pair (dptr, &muxu_dev); }
|
||||||
|
else { hp_enbdis_pair (dptr, &muxc_dev);
|
||||||
|
hp_enbdis_pair (dptr, &muxl_dev); }
|
||||||
muxl_dib.cmd = muxl_dib.ctl = 0; /* init lower */
|
muxl_dib.cmd = muxl_dib.ctl = 0; /* init lower */
|
||||||
muxl_dib.flg = muxl_dib.fbf = muxl_dib.srq = 1;
|
muxl_dib.flg = muxl_dib.fbf = muxl_dib.srq = 1;
|
||||||
muxu_dib.cmd = muxu_dib.ctl = 0; /* upper not */
|
muxu_dib.cmd = muxu_dib.ctl = 0; /* upper not */
|
||||||
|
|
|
@ -13,9 +13,9 @@
|
||||||
all copies or substantial portions of the Software.
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTI_CTLILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
ROBERT M SUPNIK BE LII_CTLLE FOR ANY CLAIM, DAMAGES OR OTHER LII_CTLILITY, WHETHER
|
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
@ -23,11 +23,14 @@
|
||||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
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.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
ptr 12597A-002 paper tape reader
|
ptr 12597A-002 paper tape reader interface
|
||||||
ptp 12597A-005 paper tape punch
|
ptp 12597A-005 paper tape punch interface
|
||||||
tty 12531C buffered teleprinter interface
|
tty 12531C buffered teleprinter interface
|
||||||
clk 12539C time base generator
|
clk 12539C time base generator
|
||||||
|
|
||||||
|
13-Sep-04 JDB Added paper tape loop mode, DIAG/READER modifiers to PTR
|
||||||
|
Added PV_LEFT to PTR TRLLIM register
|
||||||
|
Modified CLK to permit disable
|
||||||
15-Aug-04 RMS Added tab to control char set (from Dave Bryan)
|
15-Aug-04 RMS Added tab to control char set (from Dave Bryan)
|
||||||
14-Jul-04 RMS Generalized handling of control char echoing
|
14-Jul-04 RMS Generalized handling of control char echoing
|
||||||
(from Dave Bryan)
|
(from Dave Bryan)
|
||||||
|
@ -57,6 +60,10 @@
|
||||||
The reader and punch, like most HP devices, have a command flop. The
|
The reader and punch, like most HP devices, have a command flop. The
|
||||||
teleprinter and clock do not.
|
teleprinter and clock do not.
|
||||||
|
|
||||||
|
Reader diagnostic mode simulates a tape loop by rewinding the tape image file
|
||||||
|
upon EOF. Normal mode EOF action is to supply TRLLIM nulls and then either
|
||||||
|
return SCPE_IOERR or SCPE_OK without setting the device flag.
|
||||||
|
|
||||||
The clock autocalibrates. If the specified clock frequency is below
|
The clock autocalibrates. If the specified clock frequency is below
|
||||||
10Hz, the clock service routine runs at 10Hz and counts down a repeat
|
10Hz, the clock service routine runs at 10Hz and counts down a repeat
|
||||||
counter before generating an interrupt. Autocalibration will not work
|
counter before generating an interrupt. Autocalibration will not work
|
||||||
|
@ -66,6 +73,13 @@
|
||||||
This turns off autocalibration and divides the longest time intervals down
|
This turns off autocalibration and divides the longest time intervals down
|
||||||
by 10**3. The clk_time values were chosen to allow the diagnostic to
|
by 10**3. The clk_time values were chosen to allow the diagnostic to
|
||||||
pass its clock calibration test.
|
pass its clock calibration test.
|
||||||
|
|
||||||
|
References:
|
||||||
|
- 2748B Tape Reader Operating and Service Manual (02748-90041, Oct-1977)
|
||||||
|
- 12597A 8-Bit Duplex Register Interface Kit Operating and Service Manual
|
||||||
|
(12597-9002, Sep-1974)
|
||||||
|
- 12539C Time Base Generator Interface Kit Operating and Service Manual
|
||||||
|
(12539-90008, Jan-1975)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "hp2100_defs.h"
|
#include "hp2100_defs.h"
|
||||||
|
@ -170,7 +184,7 @@ REG ptr_reg[] = {
|
||||||
{ FLDATA (FBF, ptr_dib.fbf, 0) },
|
{ FLDATA (FBF, ptr_dib.fbf, 0) },
|
||||||
{ FLDATA (SRQ, ptr_dib.srq, 0) },
|
{ FLDATA (SRQ, ptr_dib.srq, 0) },
|
||||||
{ DRDATA (TRLCTR, ptr_trlcnt, 8), REG_HRO },
|
{ DRDATA (TRLCTR, ptr_trlcnt, 8), REG_HRO },
|
||||||
{ DRDATA (TRLLIM, ptr_trllim, 8) },
|
{ DRDATA (TRLLIM, ptr_trllim, 8), PV_LEFT },
|
||||||
{ DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },
|
{ DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },
|
||||||
{ DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT },
|
{ DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT },
|
||||||
{ FLDATA (STOP_IOE, ptr_stopioe, 0) },
|
{ FLDATA (STOP_IOE, ptr_stopioe, 0) },
|
||||||
|
@ -178,6 +192,8 @@ REG ptr_reg[] = {
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
MTAB ptr_mod[] = {
|
MTAB ptr_mod[] = {
|
||||||
|
{ UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", NULL },
|
||||||
|
{ UNIT_DIAG, 0, "reader mode", "READER", NULL },
|
||||||
{ MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO",
|
{ MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||||
&hp_setdev, &hp_showdev, &ptr_dev },
|
&hp_setdev, &hp_showdev, &ptr_dev },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
@ -327,7 +343,7 @@ DEVICE clk_dev = {
|
||||||
1, 0, 0, 0, 0, 0,
|
1, 0, 0, 0, 0, 0,
|
||||||
NULL, NULL, &clk_reset,
|
NULL, NULL, &clk_reset,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
&clk_dib, 0 };
|
&clk_dib, DEV_DISABLE };
|
||||||
|
|
||||||
/* Paper tape reader: IOT routine */
|
/* Paper tape reader: IOT routine */
|
||||||
|
|
||||||
|
@ -377,15 +393,20 @@ dev = ptr_dib.devno; /* get device no */
|
||||||
clrCMD (dev); /* clear cmd */
|
clrCMD (dev); /* clear cmd */
|
||||||
if ((ptr_unit.flags & UNIT_ATT) == 0) /* attached? */
|
if ((ptr_unit.flags & UNIT_ATT) == 0) /* attached? */
|
||||||
return IORETURN (ptr_stopioe, SCPE_UNATT);
|
return IORETURN (ptr_stopioe, SCPE_UNATT);
|
||||||
if ((temp = getc (ptr_unit.fileref)) == EOF) { /* read byte, error? */
|
while ((temp = getc (ptr_unit.fileref)) == EOF) { /* read byte, error? */
|
||||||
if (feof (ptr_unit.fileref)) { /* end of file? */
|
if (feof (ptr_unit.fileref)) { /* end of file? */
|
||||||
|
if ((ptr_unit.flags & UNIT_DIAG) && (ptr_unit.pos > 0)) {
|
||||||
|
rewind (ptr_unit.fileref); /* rewind if loop mode */
|
||||||
|
ptr_unit.pos = 0; }
|
||||||
|
else {
|
||||||
if (ptr_trlcnt >= ptr_trllim) { /* added all trailer? */
|
if (ptr_trlcnt >= ptr_trllim) { /* added all trailer? */
|
||||||
if (ptr_stopioe) { /* stop on error? */
|
if (ptr_stopioe) { /* stop on error? */
|
||||||
printf ("PTR end of file\n");
|
printf ("PTR end of file\n");
|
||||||
return SCPE_IOERR; }
|
return SCPE_IOERR; }
|
||||||
else return SCPE_OK; } /* no, just hang */
|
else return SCPE_OK; } /* no, just hang */
|
||||||
ptr_trlcnt++; /* count trailer */
|
ptr_trlcnt++; /* count trailer */
|
||||||
temp = 0; } /* read a zero */
|
temp = 0; /* read a zero */
|
||||||
|
break; } }
|
||||||
else { /* no, real error */
|
else { /* no, real error */
|
||||||
perror ("PTR I/O error");
|
perror ("PTR I/O error");
|
||||||
clearerr (ptr_unit.fileref);
|
clearerr (ptr_unit.fileref);
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
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.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
25-Sep-04 JDB Added memory protect device
|
||||||
|
Fixed display of CCA/CCB/CCE instructions
|
||||||
01-Jun-04 RMS Added latent 13037 support
|
01-Jun-04 RMS Added latent 13037 support
|
||||||
19-Apr-04 RMS Recognize SFS x,C and SFC x,C
|
19-Apr-04 RMS Recognize SFS x,C and SFC x,C
|
||||||
22-Mar-02 RMS Revised for dynamically allocated memory
|
22-Mar-02 RMS Revised for dynamically allocated memory
|
||||||
|
@ -43,6 +45,7 @@
|
||||||
|
|
||||||
extern DEVICE cpu_dev;
|
extern DEVICE cpu_dev;
|
||||||
extern UNIT cpu_unit;
|
extern UNIT cpu_unit;
|
||||||
|
extern DEVICE mp_dev;
|
||||||
extern DEVICE dma0_dev, dma1_dev;
|
extern DEVICE dma0_dev, dma1_dev;
|
||||||
extern DEVICE ptr_dev, ptp_dev;
|
extern DEVICE ptr_dev, ptp_dev;
|
||||||
extern DEVICE tty_dev, clk_dev;
|
extern DEVICE tty_dev, clk_dev;
|
||||||
|
@ -78,6 +81,7 @@ int32 sim_emax = 3;
|
||||||
|
|
||||||
DEVICE *sim_devices[] = {
|
DEVICE *sim_devices[] = {
|
||||||
&cpu_dev,
|
&cpu_dev,
|
||||||
|
&mp_dev,
|
||||||
&dma0_dev,
|
&dma0_dev,
|
||||||
&dma1_dev,
|
&dma1_dev,
|
||||||
&ptr_dev,
|
&ptr_dev,
|
||||||
|
@ -283,8 +287,8 @@ static const char *stab[] = {
|
||||||
static const int32 mtab[] = {
|
static const int32 mtab[] = {
|
||||||
0007700, 0007700, 0007700, 0007700, 0007700, 0007700, 0007700, 0007700,
|
0007700, 0007700, 0007700, 0007700, 0007700, 0007700, 0007700, 0007700,
|
||||||
0007700, 0007700, 0007700, 0007700, 0007700, 0007700, 0007700, 0007700,
|
0007700, 0007700, 0007700, 0007700, 0007700, 0007700, 0007700, 0007700,
|
||||||
0006400, 0007000, 0007400, 0006400, 0007000, 0007400,
|
0007400, 0007400, 0007400, 0007400, 0007400, 0007400,
|
||||||
0002040, 0002040, 0002100, 0002200, 0002300,
|
0002040, 0002040, 0002300, 0002300, 0002300,
|
||||||
0006020, 0006020, 0004010, 0004010,
|
0006020, 0006020, 0004010, 0004010,
|
||||||
0006027, 0006027, 0006027, 0006027, 0006027, 0006027, 0006027, 0006027,
|
0006027, 0006027, 0006027, 0006027, 0006027, 0006027, 0006027, 0006027,
|
||||||
0006027, 0006027, 0006027, 0006027, 0006027, 0006027, 0006027, 0006027,
|
0006027, 0006027, 0006027, 0006027, 0006027, 0006027, 0006027, 0006027,
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
Cards are represented as ASCII text streams terminated by newlines.
|
Cards are represented as ASCII text streams terminated by newlines.
|
||||||
This allows cards to be created and edited as normal files.
|
This allows cards to be created and edited as normal files.
|
||||||
|
|
||||||
|
14-Nov-04 WVS Added column binary support
|
||||||
25-Apr-03 RMS Revised for extended file support
|
25-Apr-03 RMS Revised for extended file support
|
||||||
30-May-02 RMS Widened POS to 32b
|
30-May-02 RMS Widened POS to 32b
|
||||||
30-Jan-02 RMS New zero footprint card bootstrap from Van Snyder
|
30-Jan-02 RMS New zero footprint card bootstrap from Van Snyder
|
||||||
|
@ -49,8 +50,9 @@ extern uint8 M[];
|
||||||
extern int32 ind[64], ssa, iochk;
|
extern int32 ind[64], ssa, iochk;
|
||||||
extern char bcd_to_ascii[64];
|
extern char bcd_to_ascii[64];
|
||||||
extern char ascii_to_bcd[128];
|
extern char ascii_to_bcd[128];
|
||||||
|
extern int16 colbin[64];
|
||||||
int32 s1sel, s2sel, s4sel, s8sel;
|
int32 s1sel, s2sel, s4sel, s8sel;
|
||||||
char rbuf[CBUFSIZE]; /* > CDR_WIDTH */
|
char rbuf[2 * CBUFSIZE]; /* > CDR_WIDTH */
|
||||||
t_stat cdr_svc (UNIT *uptr);
|
t_stat cdr_svc (UNIT *uptr);
|
||||||
t_stat cdr_boot (int32 unitno, DEVICE *dptr);
|
t_stat cdr_boot (int32 unitno, DEVICE *dptr);
|
||||||
t_stat cdr_attach (UNIT *uptr, char *cptr);
|
t_stat cdr_attach (UNIT *uptr, char *cptr);
|
||||||
|
@ -135,21 +137,24 @@ DEVICE stack_dev = {
|
||||||
/* Card read routine
|
/* Card read routine
|
||||||
|
|
||||||
Modifiers have been checked by the caller
|
Modifiers have been checked by the caller
|
||||||
No modifiers are recognized (column binary is not implemented)
|
C modifier is recognized (column binary is implemented)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
t_stat read_card (int32 ilnt, int32 mod)
|
t_stat read_card (int32 ilnt, int32 mod)
|
||||||
{
|
{
|
||||||
int32 i;
|
int32 i, j;
|
||||||
|
int16 c;
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
if (sim_is_active (&cdr_unit)) { /* busy? */
|
if (sim_is_active (&cdr_unit)) { /* busy? */
|
||||||
sim_cancel (&cdr_unit); /* cancel */
|
sim_cancel (&cdr_unit); /* cancel */
|
||||||
if (r = cdr_svc (&cdr_unit)) return r; } /* process */
|
if (r = cdr_svc (&cdr_unit)) return r; /* process */
|
||||||
|
}
|
||||||
if ((cdr_unit.flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */
|
if ((cdr_unit.flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */
|
||||||
ind[IN_READ] = ind[IN_LST] = s1sel = s2sel = 0; /* default stacker */
|
ind[IN_READ] = ind[IN_LST] = s1sel = s2sel = 0; /* default stacker */
|
||||||
for (i = 0; i < CBUFSIZE; i++) rbuf[i] = 0; /* clear buffer */
|
for (i = 0; i < 2 * CBUFSIZE; i++) rbuf[i] = 0; /* clear extended buf */
|
||||||
fgets (rbuf, CBUFSIZE, cdr_unit.fileref); /* read card */
|
fgets (rbuf, (mod == BCD_C)? 2 * CBUFSIZE: CBUFSIZE, /* rd bin/char card */
|
||||||
|
cdr_unit.fileref);
|
||||||
if (feof (cdr_unit.fileref)) return STOP_NOCD; /* eof? */
|
if (feof (cdr_unit.fileref)) return STOP_NOCD; /* eof? */
|
||||||
if (ferror (cdr_unit.fileref)) { /* error? */
|
if (ferror (cdr_unit.fileref)) { /* error? */
|
||||||
perror ("Card reader I/O error");
|
perror ("Card reader I/O error");
|
||||||
|
@ -162,9 +167,28 @@ if (ssa) { /* if last cd on */
|
||||||
getc (cdr_unit.fileref); /* see if more */
|
getc (cdr_unit.fileref); /* see if more */
|
||||||
if (feof (cdr_unit.fileref)) ind[IN_LST] = 1; /* eof? set flag */
|
if (feof (cdr_unit.fileref)) ind[IN_LST] = 1; /* eof? set flag */
|
||||||
fseek (cdr_unit.fileref, cdr_unit.pos, SEEK_SET); }
|
fseek (cdr_unit.fileref, cdr_unit.pos, SEEK_SET); }
|
||||||
for (i = 0; i < CDR_WIDTH; i++) { /* cvt to BCD */
|
if (mod == BCD_C) { /* column binary */
|
||||||
|
for (i = 0; i < 2 * CDR_WIDTH; i++) /* cvt to BCD */
|
||||||
rbuf[i] = ascii_to_bcd[rbuf[i]];
|
rbuf[i] = ascii_to_bcd[rbuf[i]];
|
||||||
M[CDR_BUF + i] = (M[CDR_BUF + i] & WM) | rbuf[i]; }
|
for (i = 0; i < CDR_WIDTH; i++) {
|
||||||
|
M[CD_CBUF1 + i] = (M[CD_CBUF1 + i] & WM) | rbuf[i];
|
||||||
|
M[CD_CBUF2 + i] = (M[CD_CBUF2 + i] & WM) | rbuf[CDR_WIDTH + i];
|
||||||
|
c = (rbuf[i] << 6) | rbuf[CDR_WIDTH + i];
|
||||||
|
M[CDR_BUF + i] = (M[CDR_BUF + i] & WM) | 077;
|
||||||
|
for (j = 0; j < 64; j++) { /* look for char */
|
||||||
|
if (c == colbin[j]) {
|
||||||
|
M[CDR_BUF + i] = (M[CDR_BUF + i] & WM) | j;
|
||||||
|
break;
|
||||||
|
} /* end if */
|
||||||
|
} /* end for j */
|
||||||
|
} /* end for i */
|
||||||
|
} /* end if col bin */
|
||||||
|
else { /* normal read */
|
||||||
|
for (i = 0; i < CDR_WIDTH; i++) { /* cvt to BCD */
|
||||||
|
rbuf[i] = ascii_to_bcd[rbuf[i]];
|
||||||
|
M[CDR_BUF + i] = (M[CDR_BUF + i] & WM) | rbuf[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
M[CDR_BUF - 1] = 060; /* mem mark */
|
M[CDR_BUF - 1] = 060; /* mem mark */
|
||||||
sim_activate (&cdr_unit, cdr_unit.wait); /* activate */
|
sim_activate (&cdr_unit, cdr_unit.wait); /* activate */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -199,13 +223,13 @@ return SCPE_OK;
|
||||||
/* Card punch routine
|
/* Card punch routine
|
||||||
|
|
||||||
Modifiers have been checked by the caller
|
Modifiers have been checked by the caller
|
||||||
No modifiers are recognized (column binary is not implemented)
|
C modifier is recognized (column binary is implemented)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
t_stat punch_card (int32 ilnt, int32 mod)
|
t_stat punch_card (int32 ilnt, int32 mod)
|
||||||
{
|
{
|
||||||
int32 i;
|
int32 i;
|
||||||
static char pbuf[CDP_WIDTH + 1]; /* + null */
|
static char pbuf[(2 * CDP_WIDTH) + 1]; /* + null */
|
||||||
UNIT *uptr;
|
UNIT *uptr;
|
||||||
|
|
||||||
if (s8sel) uptr = &stack_unit[2]; /* stack 8? */
|
if (s8sel) uptr = &stack_unit[2]; /* stack 8? */
|
||||||
|
@ -215,9 +239,22 @@ if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */
|
||||||
ind[IN_PNCH] = s4sel = s8sel = 0; /* clear flags */
|
ind[IN_PNCH] = s4sel = s8sel = 0; /* clear flags */
|
||||||
|
|
||||||
M[CDP_BUF - 1] = 012; /* set prev loc */
|
M[CDP_BUF - 1] = 012; /* set prev loc */
|
||||||
for (i = 0; i < CDP_WIDTH; i++) pbuf[i] = bcd_to_ascii[M[CDP_BUF + i] & CHAR];
|
if (mod == BCD_C) { /* column binary */
|
||||||
for (i = CDP_WIDTH - 1; (i >= 0) && (pbuf[i] == ' '); i--) pbuf[i] = 0;
|
for (i = 0; i < CDP_WIDTH; i++) {
|
||||||
pbuf[CDP_WIDTH] = 0; /* trailing null */
|
pbuf[i] = bcd_to_ascii[M[CD_CBUF1 + i] & CHAR];
|
||||||
|
pbuf[i + CDP_WIDTH] = bcd_to_ascii[M[CD_CBUF2 + i] & CHAR];
|
||||||
|
}
|
||||||
|
for (i = 2 * CDP_WIDTH - 1; (i >= 0) && (pbuf[i] == ' '); i--)
|
||||||
|
pbuf[i] = 0;
|
||||||
|
pbuf[2 * CDP_WIDTH] = 0; /* trailing null */
|
||||||
|
}
|
||||||
|
else { /* normal */
|
||||||
|
for (i = 0; i < CDP_WIDTH; i++)
|
||||||
|
pbuf[i] = bcd_to_ascii[M[CDP_BUF + i] & CHAR];
|
||||||
|
for (i = CDP_WIDTH - 1; (i >= 0) && (pbuf[i] == ' '); i--)
|
||||||
|
pbuf[i] = 0;
|
||||||
|
pbuf[CDP_WIDTH] = 0; /* trailing null */
|
||||||
|
}
|
||||||
fputs (pbuf, uptr->fileref); /* output card */
|
fputs (pbuf, uptr->fileref); /* output card */
|
||||||
fputc ('\n', uptr->fileref); /* plus new line */
|
fputc ('\n', uptr->fileref); /* plus new line */
|
||||||
if (ferror (uptr->fileref)) { /* error? */
|
if (ferror (uptr->fileref)) { /* error? */
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
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.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
14-Nov-04 WVS Added column binary support, debug support
|
||||||
|
06-Nov-04 RMS Added instruction history
|
||||||
12-Jul-03 RMS Moved ASCII/BCD tables to included file
|
12-Jul-03 RMS Moved ASCII/BCD tables to included file
|
||||||
Revised fetch to model hardware
|
Revised fetch to model hardware
|
||||||
Removed length checking in fetch phase
|
Removed length checking in fetch phase
|
||||||
|
@ -123,6 +125,13 @@
|
||||||
#define PCQ_MASK (PCQ_SIZE - 1)
|
#define PCQ_MASK (PCQ_SIZE - 1)
|
||||||
#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = saved_IS
|
#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = saved_IS
|
||||||
|
|
||||||
|
#define HIST_MIN 64
|
||||||
|
#define HIST_MAX 65536
|
||||||
|
struct InstHistory {
|
||||||
|
uint16 is;
|
||||||
|
uint16 ilnt;
|
||||||
|
uint8 inst[MAX_L]; };
|
||||||
|
|
||||||
/* These macros validate addresses. If an addresses error is detected,
|
/* These macros validate addresses. If an addresses error is detected,
|
||||||
they return an error status to the caller. These macros should only
|
they return an error status to the caller. These macros should only
|
||||||
be used in a routine that returns a t_stat value.
|
be used in a routine that returns a t_stat value.
|
||||||
|
@ -162,13 +171,22 @@ int32 ind[64] = { 0 }; /* indicators */
|
||||||
int32 ssa = 1; /* sense switch A */
|
int32 ssa = 1; /* sense switch A */
|
||||||
int32 prchk = 0; /* process check stop */
|
int32 prchk = 0; /* process check stop */
|
||||||
int32 iochk = 0; /* I/O check stop */
|
int32 iochk = 0; /* I/O check stop */
|
||||||
|
int32 hst_p = 0; /* history pointer */
|
||||||
|
int32 hst_lnt = 0; /* history length */
|
||||||
|
struct InstHistory *hst = NULL; /* instruction history */
|
||||||
|
|
||||||
extern int32 sim_int_char;
|
extern int32 sim_int_char;
|
||||||
|
extern int32 sim_emax;
|
||||||
|
extern t_value *sim_eval;
|
||||||
|
extern FILE *sim_deb;
|
||||||
extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
|
extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
|
||||||
|
|
||||||
t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
|
t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
|
||||||
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
|
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
|
||||||
t_stat cpu_reset (DEVICE *dptr);
|
t_stat cpu_reset (DEVICE *dptr);
|
||||||
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
int32 store_addr_h (int32 addr);
|
int32 store_addr_h (int32 addr);
|
||||||
int32 store_addr_t (int32 addr);
|
int32 store_addr_t (int32 addr);
|
||||||
int32 store_addr_u (int32 addr);
|
int32 store_addr_u (int32 addr);
|
||||||
|
@ -188,6 +206,7 @@ extern t_stat mt_io (int32 unit, int32 flag, int32 mod);
|
||||||
extern t_stat dp_io (int32 fnc, int32 flag, int32 mod);
|
extern t_stat dp_io (int32 fnc, int32 flag, int32 mod);
|
||||||
extern t_stat mt_func (int32 unit, int32 mod);
|
extern t_stat mt_func (int32 unit, int32 mod);
|
||||||
extern t_stat sim_activate (UNIT *uptr, int32 delay);
|
extern t_stat sim_activate (UNIT *uptr, int32 delay);
|
||||||
|
extern t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw);
|
||||||
|
|
||||||
/* CPU data structures
|
/* CPU data structures
|
||||||
|
|
||||||
|
@ -246,13 +265,16 @@ MTAB cpu_mod[] = {
|
||||||
{ UNIT_MSIZE, 8000, NULL, "8K", &cpu_set_size },
|
{ UNIT_MSIZE, 8000, NULL, "8K", &cpu_set_size },
|
||||||
{ UNIT_MSIZE, 12000, NULL, "12K", &cpu_set_size },
|
{ UNIT_MSIZE, 12000, NULL, "12K", &cpu_set_size },
|
||||||
{ UNIT_MSIZE, 16000, NULL, "16K", &cpu_set_size },
|
{ UNIT_MSIZE, 16000, NULL, "16K", &cpu_set_size },
|
||||||
|
{ MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY",
|
||||||
|
&cpu_set_hist, &cpu_show_hist },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
|
||||||
DEVICE cpu_dev = {
|
DEVICE cpu_dev = {
|
||||||
"CPU", &cpu_unit, cpu_reg, cpu_mod,
|
"CPU", &cpu_unit, cpu_reg, cpu_mod,
|
||||||
1, 10, 14, 1, 8, 7,
|
1, 10, 14, 1, 8, 7,
|
||||||
&cpu_ex, &cpu_dep, &cpu_reset,
|
&cpu_ex, &cpu_dep, &cpu_reset,
|
||||||
NULL, NULL, NULL };
|
NULL, NULL, NULL,
|
||||||
|
NULL, DEV_DEBUG };
|
||||||
|
|
||||||
/* Tables */
|
/* Tables */
|
||||||
|
|
||||||
|
@ -431,6 +453,8 @@ static const int32 cry_table[100] = {
|
||||||
|
|
||||||
/* Legal modifier tables */
|
/* Legal modifier tables */
|
||||||
|
|
||||||
|
static const int32 r_mod[] = { BCD_C, -1 };
|
||||||
|
static const int32 p_mod[] = { BCD_C, -1 };
|
||||||
static const int32 w_mod[] = { BCD_S, BCD_SQUARE, -1 };
|
static const int32 w_mod[] = { BCD_S, BCD_SQUARE, -1 };
|
||||||
static const int32 ss_mod[] = { 1, 2, 4, 8, -1 };
|
static const int32 ss_mod[] = { 1, 2, 4, 8, -1 };
|
||||||
static const int32 mtf_mod[] = { BCD_B, BCD_E, BCD_M, BCD_R, BCD_U, -1 };
|
static const int32 mtf_mod[] = { BCD_B, BCD_E, BCD_M, BCD_R, BCD_U, -1 };
|
||||||
|
@ -440,7 +464,7 @@ t_stat sim_instr (void)
|
||||||
extern int32 sim_interval;
|
extern int32 sim_interval;
|
||||||
int32 IS, ilnt, flags;
|
int32 IS, ilnt, flags;
|
||||||
int32 op, xa, t, wm, ioind, dev, unit;
|
int32 op, xa, t, wm, ioind, dev, unit;
|
||||||
int32 a, b, i, asave, bsave;
|
int32 a, b, i, k, asave, bsave;
|
||||||
int32 carry, lowprd, sign, ps;
|
int32 carry, lowprd, sign, ps;
|
||||||
int32 quo, ahigh, qs;
|
int32 quo, ahigh, qs;
|
||||||
int32 qzero, qawm, qbody, qsign, qdollar, qaster, qdecimal;
|
int32 qzero, qawm, qbody, qsign, qdollar, qaster, qdecimal;
|
||||||
|
@ -568,12 +592,30 @@ while (((t = M[IS]) & WM) == 0) { /* I-8: repeats until WM */
|
||||||
PP (IS); }
|
PP (IS); }
|
||||||
|
|
||||||
CHECK_LENGTH:
|
CHECK_LENGTH:
|
||||||
|
if ((flags & BREQ) && ADDR_ERR (BS)) { /* valid B? */
|
||||||
|
reason = STOP_INVB;
|
||||||
|
break; }
|
||||||
|
if ((flags & AREQ) && ADDR_ERR (AS)) { /* valid A? */
|
||||||
|
reason = STOP_INVA;
|
||||||
|
break; }
|
||||||
ilnt = IS - saved_IS; /* get lnt */
|
ilnt = IS - saved_IS; /* get lnt */
|
||||||
//if (((flags & len_table [(ilnt <= 8)? ilnt: 8]) == 0) && /* valid lnt? */
|
if (hst_lnt) { /* history enabled? */
|
||||||
// ((flags & HNOP) == 0)) reason = STOP_INVL;
|
hst_p = (hst_p + 1); /* next entry */
|
||||||
if ((flags & BREQ) && ADDR_ERR (BS)) reason = STOP_INVB; /* valid A? */
|
if (hst_p >= hst_lnt) hst_p = 0;
|
||||||
if ((flags & AREQ) && ADDR_ERR (AS)) reason = STOP_INVA; /* valid B? */
|
hst[hst_p].is = saved_IS; /* save IS */
|
||||||
if (reason) break; /* error in fetch? */
|
hst[hst_p].ilnt = ilnt;
|
||||||
|
for (i = 0; (i < MAX_L) && (i < ilnt); i++)
|
||||||
|
hst[hst_p].inst[i] = M[saved_IS + i];
|
||||||
|
}
|
||||||
|
if (DEBUG_PRS (cpu_dev)) {
|
||||||
|
fprint_val (sim_deb, saved_IS, 10, 5, PV_RSPC);
|
||||||
|
fprintf (sim_deb, ": " );
|
||||||
|
for (i = 0; i < sim_emax; i++) sim_eval[i] = 0;
|
||||||
|
for (i = 0, k = saved_IS; i < sim_emax; i++, k++) {
|
||||||
|
if (cpu_ex (&sim_eval[i], k, &cpu_unit, 0) != SCPE_OK) break; }
|
||||||
|
fprint_sym (sim_deb, saved_IS, sim_eval, &cpu_unit, SWMASK('M'));
|
||||||
|
fprintf (sim_deb, "\n" );
|
||||||
|
}
|
||||||
switch (op) { /* case on opcode */
|
switch (op) { /* case on opcode */
|
||||||
|
|
||||||
/* Move/load character instructions A check B check
|
/* Move/load character instructions A check B check
|
||||||
|
@ -858,7 +900,7 @@ case OP_C: /* compare */
|
||||||
*/
|
*/
|
||||||
|
|
||||||
case OP_R: /* read */
|
case OP_R: /* read */
|
||||||
if (reason = iomod (ilnt, D, NULL)) break; /* valid modifier? */
|
if (reason = iomod (ilnt, D, r_mod)) break; /* valid modifier? */
|
||||||
reason = read_card (ilnt, D); /* read card */
|
reason = read_card (ilnt, D); /* read card */
|
||||||
BS = CDR_BUF + CDR_WIDTH;
|
BS = CDR_BUF + CDR_WIDTH;
|
||||||
if ((ilnt == 4) || (ilnt == 5)) { BRANCH; } /* check for branch */
|
if ((ilnt == 4) || (ilnt == 5)) { BRANCH; } /* check for branch */
|
||||||
|
@ -872,7 +914,7 @@ case OP_W: /* write */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_P: /* punch */
|
case OP_P: /* punch */
|
||||||
if (reason = iomod (ilnt, D, NULL)) break; /* valid modifier? */
|
if (reason = iomod (ilnt, D, p_mod)) break; /* valid modifier? */
|
||||||
reason = punch_card (ilnt, D); /* punch card */
|
reason = punch_card (ilnt, D); /* punch card */
|
||||||
BS = CDP_BUF + CDP_WIDTH;
|
BS = CDP_BUF + CDP_WIDTH;
|
||||||
if ((ilnt == 4) || (ilnt == 5)) { BRANCH; } /* check for branch */
|
if ((ilnt == 4) || (ilnt == 5)) { BRANCH; } /* check for branch */
|
||||||
|
@ -1561,3 +1603,66 @@ if (MEMSIZE > 4000) cpu_unit.flags = cpu_unit.flags | MA;
|
||||||
else cpu_unit.flags = cpu_unit.flags & ~MA;
|
else cpu_unit.flags = cpu_unit.flags & ~MA;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set history */
|
||||||
|
|
||||||
|
t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
int32 i, lnt;
|
||||||
|
t_stat r;
|
||||||
|
|
||||||
|
if (cptr == NULL) {
|
||||||
|
for (i = 0; i < hst_lnt; i++) hst[i].ilnt = 0;
|
||||||
|
hst_p = 0;
|
||||||
|
return SCPE_OK; }
|
||||||
|
lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r);
|
||||||
|
if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG;
|
||||||
|
hst_p = 0;
|
||||||
|
if (hst_lnt) {
|
||||||
|
free (hst);
|
||||||
|
hst_lnt = 0;
|
||||||
|
hst = NULL; }
|
||||||
|
if (lnt) {
|
||||||
|
hst = calloc (sizeof (struct InstHistory), lnt);
|
||||||
|
if (hst == NULL) return SCPE_MEM;
|
||||||
|
hst_lnt = lnt; }
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Show history */
|
||||||
|
|
||||||
|
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
|
{
|
||||||
|
int32 i, k, di, lnt;
|
||||||
|
char *cptr = (char *) desc;
|
||||||
|
t_value sim_eval[MAX_L + 1];
|
||||||
|
t_stat r;
|
||||||
|
struct InstHistory *h;
|
||||||
|
extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
|
||||||
|
UNIT *uptr, int32 sw);
|
||||||
|
|
||||||
|
if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */
|
||||||
|
if (cptr) {
|
||||||
|
lnt = (int32) get_uint (cptr, 10, hst_lnt, &r);
|
||||||
|
if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; }
|
||||||
|
else lnt = hst_lnt;
|
||||||
|
di = hst_p - lnt; /* work forward */
|
||||||
|
if (di < 0) di = di + hst_lnt;
|
||||||
|
fprintf (st, "IS IR\n\n");
|
||||||
|
for (k = 0; k < lnt; k++) { /* print specified */
|
||||||
|
h = &hst[(++di) % hst_lnt]; /* entry pointer */
|
||||||
|
if (h->ilnt) { /* instruction? */
|
||||||
|
fprintf (st, "%05d ", h->is);
|
||||||
|
for (i = 0; i < h->ilnt; i++)
|
||||||
|
sim_eval[i] = h->inst[i];
|
||||||
|
sim_eval[h->ilnt] = WM;
|
||||||
|
if ((fprint_sym (st, h->is, sim_eval, &cpu_unit, SWMASK ('M'))) > 0) {
|
||||||
|
fprintf (st, "(undefined)");
|
||||||
|
for (i = 0; i < h->ilnt; i++)
|
||||||
|
fprintf (st, "% 02o", h->inst[i]);
|
||||||
|
}
|
||||||
|
fputc ('\n', st); /* end line */
|
||||||
|
} /* end else instruction */
|
||||||
|
} /* end for */
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
|
@ -20,7 +20,8 @@
|
||||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
Except as contained in this notice, the name of Robert M Supnik shall not
|
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
|
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.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -55,3 +56,16 @@ char bcd_to_ascii[64] = {
|
||||||
'Q', 'R', '!', '$', '*', ']', ';', '_',
|
'Q', 'R', '!', '$', '*', ']', ';', '_',
|
||||||
'&', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
|
'&', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
|
||||||
'H', 'I', '?', '.', ')', '[', '<', '"' };
|
'H', 'I', '?', '.', ')', '[', '<', '"' };
|
||||||
|
|
||||||
|
/* Column binary codes for valid punch combinations
|
||||||
|
High-order six bits are rows 12-3, low-order six bits are rows 4-9 */
|
||||||
|
|
||||||
|
int16 colbin[64] = {
|
||||||
|
00000, 00400, 00200, 00100, 00040, 00020, 00010, 00004,
|
||||||
|
00002, 00001, 01000, 00102, 00042, 00022, 00012, 00006,
|
||||||
|
07777, 01400, 01200, 01100, 01040, 01020, 01010, 01004,
|
||||||
|
01002, 01001, 01202, 01102, 01042, 01022, 01012, 01006,
|
||||||
|
02000, 02400, 02200, 02100, 02040, 02020, 02010, 02004,
|
||||||
|
02002, 02001, 03000, 02102, 02042, 02022, 02012, 02006,
|
||||||
|
04000, 04400, 04200, 04100, 04040, 04020, 04010, 04004,
|
||||||
|
04002, 04001, 05000, 04102, 04042, 04022, 04012, 04006 };
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
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.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
14-Nov-04 RMS Added column binary support
|
||||||
|
27-Oct-04 RMS Added maximum instruction length
|
||||||
16-Mar-03 RMS Fixed mnemonic for MCS
|
16-Mar-03 RMS Fixed mnemonic for MCS
|
||||||
03-Jun-02 RMS Added 1311 support
|
03-Jun-02 RMS Added 1311 support
|
||||||
14-Apr-99 RMS Converted t_addr to unsigned
|
14-Apr-99 RMS Converted t_addr to unsigned
|
||||||
|
@ -76,6 +78,8 @@
|
||||||
#define CDR_WIDTH 80 /* card rdr width */
|
#define CDR_WIDTH 80 /* card rdr width */
|
||||||
#define CDP_BUF 101 /* card punch buffer */
|
#define CDP_BUF 101 /* card punch buffer */
|
||||||
#define CDP_WIDTH 80 /* card punch width */
|
#define CDP_WIDTH 80 /* card punch width */
|
||||||
|
#define CD_CBUF1 401 /* r/p col bin buf 12-3 */
|
||||||
|
#define CD_CBUF2 501 /* r/p col bin buf 4-9 */
|
||||||
#define LPT_BUF 201 /* line print buffer */
|
#define LPT_BUF 201 /* line print buffer */
|
||||||
#define LPT_WIDTH 132 /* line print width */
|
#define LPT_WIDTH 132 /* line print width */
|
||||||
#define CCT_LNT 132 /* car ctrl length */
|
#define CCT_LNT 132 /* car ctrl length */
|
||||||
|
@ -110,6 +114,7 @@
|
||||||
#define L5 0010 /* 5: op aaa d */
|
#define L5 0010 /* 5: op aaa d */
|
||||||
#define L7 0020 /* 7: op aaa bbb */
|
#define L7 0020 /* 7: op aaa bbb */
|
||||||
#define L8 0040 /* 8: op aaa bbb d */
|
#define L8 0040 /* 8: op aaa bbb d */
|
||||||
|
#define MAX_L 8 /* max length */
|
||||||
|
|
||||||
/* CPU options, stored in cpu_unit.flags */
|
/* CPU options, stored in cpu_unit.flags */
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
To: Users
|
To: Users
|
||||||
From: Bob Supnik
|
From: Bob Supnik
|
||||||
Subj: IBM 1401 Simulator Usage
|
Subj: IBM 1401 Simulator Usage
|
||||||
Date: 15-Feb-2004
|
Date: 15-Nov-2004
|
||||||
|
|
||||||
COPYRIGHT NOTICE
|
COPYRIGHT NOTICE
|
||||||
|
|
||||||
|
@ -174,6 +174,17 @@ interrupt system.
|
||||||
most recent IS change first
|
most recent IS change first
|
||||||
WRU 8 interrupt character
|
WRU 8 interrupt character
|
||||||
|
|
||||||
|
The CPU can maintain a history of the most recently executed instructions.
|
||||||
|
This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands:
|
||||||
|
|
||||||
|
SET CPU HISTORY clear history buffer
|
||||||
|
SET CPU HISTORY=0 disable history
|
||||||
|
SET CPU HISTORY=n enable history, length = n
|
||||||
|
SHOW CPU HISTORY print CPU history
|
||||||
|
SHOW CPU HISTORY=n print first n entries of CPU history
|
||||||
|
|
||||||
|
The maximum length for the history is 65536 entries.
|
||||||
|
|
||||||
2.2 1402 Card Reader/Punch (CDR, CDP, STKR)
|
2.2 1402 Card Reader/Punch (CDR, CDP, STKR)
|
||||||
|
|
||||||
The IBM 1402 card/reader punch is simulated as three independent devices:
|
The IBM 1402 card/reader punch is simulated as three independent devices:
|
||||||
|
@ -314,7 +325,7 @@ pack options include the ability to enable address writing (formatting).
|
||||||
SET DPn ADDROFF set unit n address enable off
|
SET DPn ADDROFF set unit n address enable off
|
||||||
SET DPn ADDRON set unit n address enable on
|
SET DPn ADDRON set unit n address enable on
|
||||||
|
|
||||||
Units can also be set ONLINE or OFFLINE.
|
Units can also be set ENABLED or DISABLED.
|
||||||
|
|
||||||
Unlike most simulated disks, the 1311 includes explicit representation
|
Unlike most simulated disks, the 1311 includes explicit representation
|
||||||
for sector addresses. This is to support non-standard formats, such as
|
for sector addresses. This is to support non-standard formats, such as
|
||||||
|
@ -367,7 +378,7 @@ or write locked.
|
||||||
SET MTn LOCKED set unit n write locked
|
SET MTn LOCKED set unit n write locked
|
||||||
SET MTn WRITEENABLED set unit n write enabled
|
SET MTn WRITEENABLED set unit n write enabled
|
||||||
|
|
||||||
Units can also be set ONLINE or OFFLINE. The magnetic tape simulator
|
Units can also be set ENABLED or DISABLED. The magnetic tape simulator
|
||||||
supports the BOOT command. BOOT MT reads the first record off tape,
|
supports the BOOT command. BOOT MT reads the first record off tape,
|
||||||
starting at location 1, and then branches to it.
|
starting at location 1, and then branches to it.
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
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.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
14-Nov-04 WVS Added data printout support
|
||||||
16-Mar-03 RMS Fixed mnemonic for MCS
|
16-Mar-03 RMS Fixed mnemonic for MCS
|
||||||
03-Jun-02 RMS Added 1311 support
|
03-Jun-02 RMS Added 1311 support
|
||||||
18-May-02 RMS Added -D feature from Van Snyder
|
18-May-02 RMS Added -D feature from Van Snyder
|
||||||
|
@ -157,7 +158,7 @@ return SCPE_OK;
|
||||||
|
|
||||||
const char *opcode[64] = {
|
const char *opcode[64] = {
|
||||||
NULL, "R", "W", "WR", "P", "RP", "WP", "WRP",
|
NULL, "R", "W", "WR", "P", "RP", "WP", "WRP",
|
||||||
"RF", "WF", NULL, "MA", "MUL", NULL, NULL, NULL,
|
"SRF", "SPF", NULL, "MA", "MUL", NULL, NULL, NULL,
|
||||||
NULL, "CS", "S", NULL, "MTF", "BWZ", "BBE", NULL,
|
NULL, "CS", "S", NULL, "MTF", "BWZ", "BBE", NULL,
|
||||||
"MZ", "MCS", NULL, "SWM", "DIV", NULL, NULL, NULL,
|
"MZ", "MCS", NULL, "SWM", "DIV", NULL, NULL, NULL,
|
||||||
NULL, NULL, "SS", "LCA", "MCW", "NOP", NULL, "MCM",
|
NULL, NULL, "SS", "LCA", "MCW", "NOP", NULL, "MCM",
|
||||||
|
@ -180,6 +181,21 @@ else fprintf (of, " %d", addr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Print unknown opcode as data */
|
||||||
|
|
||||||
|
t_stat dcw (FILE *of, int32 op, t_value *val)
|
||||||
|
{
|
||||||
|
int32 i;
|
||||||
|
|
||||||
|
fprintf (of, "DCW @%c", bcd_to_ascii[op]); /* assume it's data */
|
||||||
|
for (i = 1; i < sim_emax; i++) {
|
||||||
|
if (val[i] & WM) break;
|
||||||
|
fprintf (of, "%c", bcd_to_ascii[val[i]]);
|
||||||
|
}
|
||||||
|
fprintf (of, "@");
|
||||||
|
return -(i - 1); /* return # chars */
|
||||||
|
}
|
||||||
|
|
||||||
/* Symbolic decode
|
/* Symbolic decode
|
||||||
|
|
||||||
Inputs:
|
Inputs:
|
||||||
|
@ -224,13 +240,14 @@ if ((sw & SWMASK ('M')) == 0) return SCPE_ARG;
|
||||||
|
|
||||||
if ((val[0] & WM) == 0) return STOP_NOWM; /* WM under op? */
|
if ((val[0] & WM) == 0) return STOP_NOWM; /* WM under op? */
|
||||||
op = val[0]& CHAR; /* isolate op */
|
op = val[0]& CHAR; /* isolate op */
|
||||||
|
if (opcode[op] == NULL) return dcw (of, op, val); /* invalid op */
|
||||||
flags = op_table[op]; /* get flags */
|
flags = op_table[op]; /* get flags */
|
||||||
for (ilnt = 1; ilnt < sim_emax; ilnt++) if (val[ilnt] & WM) break;
|
for (ilnt = 1; ilnt < sim_emax; ilnt++) if (val[ilnt] & WM) break;
|
||||||
if ((flags & (NOWM | HNOP)) && (ilnt > 7)) ilnt = 7; /* cs, swm, h, nop? */
|
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 ((op == OP_B) && (ilnt > 4) && (val[4] == BCD_BLANK)) ilnt = 4;
|
||||||
else if ((ilnt > 8) && (op != OP_NOP)) ilnt = 8; /* cap length */
|
else if ((ilnt > 8) && (op != OP_NOP)) ilnt = 8; /* cap length */
|
||||||
if (((flags & len_table[ilnt]) == 0) && /* valid lnt, */
|
if (((flags & len_table[ilnt]) == 0) && /* invalid lnt, */
|
||||||
((op != OP_NOP) == 0)) return STOP_INVL; /* nop? */
|
(op != OP_NOP)) return dcw (of, op, val); /* not nop? */
|
||||||
fprintf (of, "%s",opcode[op]); /* print opcode */
|
fprintf (of, "%s",opcode[op]); /* print opcode */
|
||||||
if (ilnt > 2) { /* A address? */
|
if (ilnt > 2) { /* A address? */
|
||||||
if (((flags & IO) || (op == OP_NOP)) && (val[1] == BCD_PERCNT))
|
if (((flags & IO) || (op == OP_NOP)) && (val[1] == BCD_PERCNT))
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
This CPU module incorporates code and comments from the 1620 simulator by
|
This CPU module incorporates code and comments from the 1620 simulator by
|
||||||
Geoff Kuenning, with his permission.
|
Geoff Kuenning, with his permission.
|
||||||
|
|
||||||
|
07-Nov-04 RMS Added instruction history
|
||||||
26-Mar-04 RMS Fixed warnings with -std=c99
|
26-Mar-04 RMS Fixed warnings with -std=c99
|
||||||
02-Nov-03 RMS Fixed bug in branch digit (found by Dave Babcock)
|
02-Nov-03 RMS Fixed bug in branch digit (found by Dave Babcock)
|
||||||
21-Aug-03 RMS Fixed bug in immediate index add (found by Michael Short)
|
21-Aug-03 RMS Fixed bug in immediate index add (found by Michael Short)
|
||||||
|
@ -98,6 +99,14 @@
|
||||||
#define PCQ_MASK (PCQ_SIZE - 1)
|
#define PCQ_MASK (PCQ_SIZE - 1)
|
||||||
#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = saved_PC
|
#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = saved_PC
|
||||||
|
|
||||||
|
#define HIST_PC 0x40000000
|
||||||
|
#define HIST_MIN 64
|
||||||
|
#define HIST_MAX 65536
|
||||||
|
struct InstHistory {
|
||||||
|
uint16 vld;
|
||||||
|
uint16 pc;
|
||||||
|
uint8 inst[INST_LEN]; };
|
||||||
|
|
||||||
uint8 M[MAXMEMSIZE] = { 0 }; /* main memory */
|
uint8 M[MAXMEMSIZE] = { 0 }; /* main memory */
|
||||||
uint32 saved_PC = 0; /* saved PC */
|
uint32 saved_PC = 0; /* saved PC */
|
||||||
uint32 IR2 = 1; /* inst reg 2 */
|
uint32 IR2 = 1; /* inst reg 2 */
|
||||||
|
@ -113,6 +122,9 @@ int32 ind_max = 16; /* iadr nest limit */
|
||||||
uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
|
uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
|
||||||
int32 pcq_p = 0; /* PC queue ptr */
|
int32 pcq_p = 0; /* PC queue ptr */
|
||||||
REG *pcq_r = NULL; /* PC queue reg ptr */
|
REG *pcq_r = NULL; /* PC queue reg ptr */
|
||||||
|
int32 hst_p = 0; /* history pointer */
|
||||||
|
int32 hst_lnt = 0; /* history length */
|
||||||
|
struct InstHistory *hst = NULL; /* instruction history */
|
||||||
uint8 ind[NUM_IND] = { 0 }; /* indicators */
|
uint8 ind[NUM_IND] = { 0 }; /* indicators */
|
||||||
|
|
||||||
extern int32 sim_int_char;
|
extern int32 sim_int_char;
|
||||||
|
@ -129,6 +141,8 @@ t_stat cpu_set_model (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
t_stat cpu_set_save (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat cpu_set_save (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
t_stat cpu_set_table (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat cpu_set_table (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
|
|
||||||
int32 get_2d (uint32 ad);
|
int32 get_2d (uint32 ad);
|
||||||
t_stat get_addr (uint32 alast, int32 lnt, t_bool indexok, uint32 *addr);
|
t_stat get_addr (uint32 alast, int32 lnt, t_bool indexok, uint32 *addr);
|
||||||
|
@ -228,6 +242,8 @@ MTAB cpu_mod[] = {
|
||||||
{ UNIT_MSIZE, 60000, NULL, "60K", &cpu_set_size },
|
{ UNIT_MSIZE, 60000, NULL, "60K", &cpu_set_size },
|
||||||
{ UNIT_MSIZE, 0, NULL, "SAVE", &cpu_set_save },
|
{ UNIT_MSIZE, 0, NULL, "SAVE", &cpu_set_save },
|
||||||
{ UNIT_MSIZE, 0, NULL, "TABLE", &cpu_set_table },
|
{ UNIT_MSIZE, 0, NULL, "TABLE", &cpu_set_table },
|
||||||
|
{ MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY",
|
||||||
|
&cpu_set_hist, &cpu_show_hist },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
|
||||||
DEVICE cpu_dev = {
|
DEVICE cpu_dev = {
|
||||||
|
@ -484,6 +500,16 @@ if (flags & (IF_VQA | IF_4QA | IF_NQX)) { /* need Q? */
|
||||||
reason = reason + (STOP_INVQDG - STOP_INVPDG);
|
reason = reason + (STOP_INVQDG - STOP_INVPDG);
|
||||||
break; } }
|
break; } }
|
||||||
else if (flags & IF_IMM) QAR = qla; /* immediate? */
|
else if (flags & IF_IMM) QAR = qla; /* immediate? */
|
||||||
|
|
||||||
|
if (hst_lnt) { /* history enabled? */
|
||||||
|
hst_p = (hst_p + 1); /* next entry */
|
||||||
|
if (hst_p >= hst_lnt) hst_p = 0;
|
||||||
|
hst[hst_p].vld = 1;
|
||||||
|
hst[hst_p].pc = PC;
|
||||||
|
for (i = 0; i < INST_LEN; i++)
|
||||||
|
hst[hst_p].inst[i] = M[(PC + i) % MEMSIZE];
|
||||||
|
}
|
||||||
|
|
||||||
PC = PC + INST_LEN; /* advance PC */
|
PC = PC + INST_LEN; /* advance PC */
|
||||||
switch (op) { /* case on op */
|
switch (op) { /* case on op */
|
||||||
|
|
||||||
|
@ -1884,3 +1910,65 @@ if (((cpu_unit.flags & IF_MII) == 0) || val) { /* set add table */
|
||||||
M[ADD_TABLE + i] = std_add_table[i]; }
|
M[ADD_TABLE + i] = std_add_table[i]; }
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set history */
|
||||||
|
|
||||||
|
t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
int32 i, lnt;
|
||||||
|
t_stat r;
|
||||||
|
|
||||||
|
if (cptr == NULL) {
|
||||||
|
for (i = 0; i < hst_lnt; i++) hst[i].vld = 0;
|
||||||
|
hst_p = 0;
|
||||||
|
return SCPE_OK; }
|
||||||
|
lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r);
|
||||||
|
if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG;
|
||||||
|
hst_p = 0;
|
||||||
|
if (hst_lnt) {
|
||||||
|
free (hst);
|
||||||
|
hst_lnt = 0;
|
||||||
|
hst = NULL; }
|
||||||
|
if (lnt) {
|
||||||
|
hst = calloc (sizeof (struct InstHistory), lnt);
|
||||||
|
if (hst == NULL) return SCPE_MEM;
|
||||||
|
hst_lnt = lnt; }
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Show history */
|
||||||
|
|
||||||
|
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
|
{
|
||||||
|
int32 i, k, di, lnt;
|
||||||
|
char *cptr = (char *) desc;
|
||||||
|
t_value sim_eval[INST_LEN];
|
||||||
|
t_stat r;
|
||||||
|
struct InstHistory *h;
|
||||||
|
extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
|
||||||
|
UNIT *uptr, int32 sw);
|
||||||
|
|
||||||
|
if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */
|
||||||
|
if (cptr) {
|
||||||
|
lnt = (int32) get_uint (cptr, 10, hst_lnt, &r);
|
||||||
|
if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; }
|
||||||
|
else lnt = hst_lnt;
|
||||||
|
di = hst_p - lnt; /* work forward */
|
||||||
|
if (di < 0) di = di + hst_lnt;
|
||||||
|
fprintf (st, "PC IR\n\n");
|
||||||
|
for (k = 0; k < lnt; k++) { /* print specified */
|
||||||
|
h = &hst[(++di) % hst_lnt]; /* entry pointer */
|
||||||
|
if (h->vld) { /* instruction? */
|
||||||
|
fprintf (st, "%05d ", h->pc);
|
||||||
|
for (i = 0; i < INST_LEN; i++)
|
||||||
|
sim_eval[i] = h->inst[i];
|
||||||
|
if ((fprint_sym (st, h->pc, sim_eval, &cpu_unit, SWMASK ('M'))) > 0) {
|
||||||
|
fprintf (st, "(undefined)");
|
||||||
|
for (i = 0; i < INST_LEN; i++)
|
||||||
|
fprintf (st, "% 02X", h->inst[i]);
|
||||||
|
}
|
||||||
|
fputc ('\n', st); /* end line */
|
||||||
|
} /* end else instruction */
|
||||||
|
} /* end for */
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
To: Users
|
To: Users
|
||||||
From: Bob Supnik
|
From: Bob Supnik
|
||||||
Subj: IBM 1620 Simulator Usage
|
Subj: IBM 1620 Simulator Usage
|
||||||
Date: 15-Feb-2004
|
Date: 15-Nov-2004
|
||||||
|
|
||||||
COPYRIGHT NOTICE
|
COPYRIGHT NOTICE
|
||||||
|
|
||||||
|
@ -188,6 +188,17 @@ interrupt system.
|
||||||
most recent IR1 change first
|
most recent IR1 change first
|
||||||
WRU 8 interrupt character
|
WRU 8 interrupt character
|
||||||
|
|
||||||
|
The CPU can maintain a history of the most recently executed instructions.
|
||||||
|
This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands:
|
||||||
|
|
||||||
|
SET CPU HISTORY clear history buffer
|
||||||
|
SET CPU HISTORY=0 disable history
|
||||||
|
SET CPU HISTORY=n enable history, length = n
|
||||||
|
SHOW CPU HISTORY print CPU history
|
||||||
|
SHOW CPU HISTORY=n print first n entries of CPU history
|
||||||
|
|
||||||
|
The maximum length for the history is 65536 entries.
|
||||||
|
|
||||||
2.2 Console Typewriter (TTY)
|
2.2 Console Typewriter (TTY)
|
||||||
|
|
||||||
The console typewriter (TTY) is a half-duplex console. The typewriter
|
The console typewriter (TTY) is a half-duplex console. The typewriter
|
||||||
|
@ -361,7 +372,7 @@ pack options include the ability to enable address writing (formatting).
|
||||||
SET DPn ADDROFF set unit n address enable off
|
SET DPn ADDROFF set unit n address enable off
|
||||||
SET DPn ADDRON set unit n address enable on
|
SET DPn ADDRON set unit n address enable on
|
||||||
|
|
||||||
Units can also be set ONLINE or OFFLINE.
|
Units can also be set ENABLED or DISABLED.
|
||||||
|
|
||||||
Unlike most simulated disks, the 1311 includes explicit representation
|
Unlike most simulated disks, the 1311 includes explicit representation
|
||||||
for sector addresses. This is to support non-standard formats, such as
|
for sector addresses. This is to support non-standard formats, such as
|
||||||
|
|
|
@ -219,8 +219,8 @@ return STOP_RWRAP;
|
||||||
|
|
||||||
t_stat tti_rnum (int8 *c)
|
t_stat tti_rnum (int8 *c)
|
||||||
{
|
{
|
||||||
int8 flg = 0;
|
int8 raw, flg = 0;
|
||||||
char *cp, raw;
|
char *cp;
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
*c = -1; /* no char yet */
|
*c = -1; /* no char yet */
|
||||||
|
@ -240,7 +240,7 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat tti_ralp (int8 *c)
|
t_stat tti_ralp (int8 *c)
|
||||||
{
|
{
|
||||||
char raw;
|
int8 raw;
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
*c = -1; /* no char yet */
|
*c = -1; /* no char yet */
|
||||||
|
|
|
@ -75,7 +75,8 @@ BSC32_SBRS= \
|
||||||
$(INTDIR)/ibm1130_fmt.sbr \
|
$(INTDIR)/ibm1130_fmt.sbr \
|
||||||
$(INTDIR)/sim_console.sbr \
|
$(INTDIR)/sim_console.sbr \
|
||||||
$(INTDIR)/sim_fio.sbr \
|
$(INTDIR)/sim_fio.sbr \
|
||||||
$(INTDIR)/sim_timer.sbr
|
$(INTDIR)/sim_timer.sbr \
|
||||||
|
$(INTDIR)/ibm1130_ptrp.sbr
|
||||||
|
|
||||||
$(OUTDIR)/ibm1130.bsc : $(OUTDIR) $(BSC32_SBRS)
|
$(OUTDIR)/ibm1130.bsc : $(OUTDIR) $(BSC32_SBRS)
|
||||||
$(BSC32) @<<
|
$(BSC32) @<<
|
||||||
|
@ -105,7 +106,8 @@ LINK32_OBJS= \
|
||||||
$(INTDIR)/ibm1130_fmt.obj \
|
$(INTDIR)/ibm1130_fmt.obj \
|
||||||
$(INTDIR)/sim_console.obj \
|
$(INTDIR)/sim_console.obj \
|
||||||
$(INTDIR)/sim_fio.obj \
|
$(INTDIR)/sim_fio.obj \
|
||||||
$(INTDIR)/sim_timer.obj
|
$(INTDIR)/sim_timer.obj \
|
||||||
|
$(INTDIR)/ibm1130_ptrp.obj
|
||||||
|
|
||||||
$(OUTDIR)/ibm1130.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS)
|
$(OUTDIR)/ibm1130.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS)
|
||||||
$(LINK32) @<<
|
$(LINK32) @<<
|
||||||
|
@ -158,7 +160,8 @@ BSC32_SBRS= \
|
||||||
$(INTDIR)/ibm1130_fmt.sbr \
|
$(INTDIR)/ibm1130_fmt.sbr \
|
||||||
$(INTDIR)/sim_console.sbr \
|
$(INTDIR)/sim_console.sbr \
|
||||||
$(INTDIR)/sim_fio.sbr \
|
$(INTDIR)/sim_fio.sbr \
|
||||||
$(INTDIR)/sim_timer.sbr
|
$(INTDIR)/sim_timer.sbr \
|
||||||
|
$(INTDIR)/ibm1130_ptrp.sbr
|
||||||
|
|
||||||
$(OUTDIR)/ibm1130.bsc : $(OUTDIR) $(BSC32_SBRS)
|
$(OUTDIR)/ibm1130.bsc : $(OUTDIR) $(BSC32_SBRS)
|
||||||
$(BSC32) @<<
|
$(BSC32) @<<
|
||||||
|
@ -189,7 +192,8 @@ LINK32_OBJS= \
|
||||||
$(INTDIR)/ibm1130_fmt.obj \
|
$(INTDIR)/ibm1130_fmt.obj \
|
||||||
$(INTDIR)/sim_console.obj \
|
$(INTDIR)/sim_console.obj \
|
||||||
$(INTDIR)/sim_fio.obj \
|
$(INTDIR)/sim_fio.obj \
|
||||||
$(INTDIR)/sim_timer.obj
|
$(INTDIR)/sim_timer.obj \
|
||||||
|
$(INTDIR)/ibm1130_ptrp.obj
|
||||||
|
|
||||||
$(OUTDIR)/ibm1130.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS)
|
$(OUTDIR)/ibm1130.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS)
|
||||||
$(LINK32) @<<
|
$(LINK32) @<<
|
||||||
|
@ -377,10 +381,10 @@ DEP_SIM_C=\
|
||||||
\pdp11\supnik\sim_console.h\
|
\pdp11\supnik\sim_console.h\
|
||||||
\pdp11\supnik\sim_timer.h\
|
\pdp11\supnik\sim_timer.h\
|
||||||
\pdp11\supnik\sim_fio.h\
|
\pdp11\supnik\sim_fio.h\
|
||||||
d:\progra~1\micros~1\include\winsock2.h\
|
D:\PROGRA~1\MICROS~1\INCLUDE\WinSock2.h\
|
||||||
\MSVC20\INCLUDE\sys\TYPES.H\
|
\MSVC20\INCLUDE\sys\TYPES.H\
|
||||||
d:\progra~1\micros~1\include\qos.h\
|
D:\PROGRA~1\MICROS~1\INCLUDE\Qos.h\
|
||||||
d:\winddk\2600\inc\wxp\guiddef.h
|
D:\WINDDK\2600\inc\wxp\guiddef.h
|
||||||
|
|
||||||
$(INTDIR)/sim_console.obj : $(SOURCE) $(DEP_SIM_C) $(INTDIR)
|
$(INTDIR)/sim_console.obj : $(SOURCE) $(DEP_SIM_C) $(INTDIR)
|
||||||
$(CPP) $(CPP_PROJ) $(SOURCE)
|
$(CPP) $(CPP_PROJ) $(SOURCE)
|
||||||
|
@ -392,7 +396,7 @@ $(INTDIR)/sim_console.obj : $(SOURCE) $(DEP_SIM_C) $(INTDIR)
|
||||||
SOURCE=\pdp11\supnik\sim_fio.c
|
SOURCE=\pdp11\supnik\sim_fio.c
|
||||||
DEP_SIM_F=\
|
DEP_SIM_F=\
|
||||||
..\sim_defs.h\
|
..\sim_defs.h\
|
||||||
d:\progra~1\micros~1\include\BASETSD.H\
|
D:\PROGRA~1\MICROS~1\INCLUDE\BaseTsd.h\
|
||||||
\pdp11\supnik\scp.h\
|
\pdp11\supnik\scp.h\
|
||||||
\pdp11\supnik\sim_console.h\
|
\pdp11\supnik\sim_console.h\
|
||||||
\pdp11\supnik\sim_timer.h\
|
\pdp11\supnik\sim_timer.h\
|
||||||
|
@ -408,7 +412,7 @@ $(INTDIR)/sim_fio.obj : $(SOURCE) $(DEP_SIM_F) $(INTDIR)
|
||||||
SOURCE=\pdp11\supnik\sim_timer.c
|
SOURCE=\pdp11\supnik\sim_timer.c
|
||||||
DEP_SIM_TI=\
|
DEP_SIM_TI=\
|
||||||
..\sim_defs.h\
|
..\sim_defs.h\
|
||||||
d:\progra~1\micros~1\include\BASETSD.H\
|
D:\PROGRA~1\MICROS~1\INCLUDE\BaseTsd.h\
|
||||||
\pdp11\supnik\scp.h\
|
\pdp11\supnik\scp.h\
|
||||||
\pdp11\supnik\sim_console.h\
|
\pdp11\supnik\sim_console.h\
|
||||||
\pdp11\supnik\sim_timer.h\
|
\pdp11\supnik\sim_timer.h\
|
||||||
|
@ -417,6 +421,14 @@ DEP_SIM_TI=\
|
||||||
$(INTDIR)/sim_timer.obj : $(SOURCE) $(DEP_SIM_TI) $(INTDIR)
|
$(INTDIR)/sim_timer.obj : $(SOURCE) $(DEP_SIM_TI) $(INTDIR)
|
||||||
$(CPP) $(CPP_PROJ) $(SOURCE)
|
$(CPP) $(CPP_PROJ) $(SOURCE)
|
||||||
|
|
||||||
|
# End Source File
|
||||||
|
################################################################################
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\ibm1130_ptrp.c
|
||||||
|
|
||||||
|
$(INTDIR)/ibm1130_ptrp.obj : $(SOURCE) $(INTDIR)
|
||||||
|
|
||||||
# End Source File
|
# End Source File
|
||||||
# End Group
|
# End Group
|
||||||
# End Project
|
# End Project
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
18-Mar-03 BLK Fixed bug in divide instruction; didn't work with negative values
|
18-Mar-03 BLK Fixed bug in divide instruction; didn't work with negative values
|
||||||
23-Jul-03 BLK Prevented tti polling in CGI mode
|
23-Jul-03 BLK Prevented tti polling in CGI mode
|
||||||
24-Nov-03 BLK Fixed carry bit error in subtract and subtract double, found by Bob Flanders
|
24-Nov-03 BLK Fixed carry bit error in subtract and subtract double, found by Bob Flanders
|
||||||
|
20-Oct-04 BLK Changed "(unsigned int32)" to "(uint32)" to accomodate improved definitions of simh types
|
||||||
|
Also commented out my echo command as it's now a standard simh command
|
||||||
|
|
||||||
The register state for the IBM 1130 CPU is:
|
The register state for the IBM 1130 CPU is:
|
||||||
|
|
||||||
|
@ -127,6 +129,7 @@
|
||||||
#define UPDATE_BY_TIMER
|
#define UPDATE_BY_TIMER
|
||||||
#define ENABLE_BACKTRACE
|
#define ENABLE_BACKTRACE
|
||||||
#define CGI_SUPPORT
|
#define CGI_SUPPORT
|
||||||
|
// #define USE_MY_ECHO_CMD /* simh now has echo command built in */
|
||||||
|
|
||||||
static void cgi_start(void);
|
static void cgi_start(void);
|
||||||
static void cgi_stop(t_stat reason);
|
static void cgi_stop(t_stat reason);
|
||||||
|
@ -888,7 +891,7 @@ t_stat sim_instr (void)
|
||||||
ACC = (dst >> 16) & 0xFFFF;
|
ACC = (dst >> 16) & 0xFFFF;
|
||||||
EXT = dst & 0xFFFF;
|
EXT = dst & 0xFFFF;
|
||||||
|
|
||||||
C = (unsigned int32) dst < (unsigned int32) src;
|
C = (uint32) dst < (uint32) src;
|
||||||
if (! V)
|
if (! V)
|
||||||
V = DWSIGN_BIT((~src ^ src2) & (src ^ dst));
|
V = DWSIGN_BIT((~src ^ src2) & (src ^ dst));
|
||||||
break;
|
break;
|
||||||
|
@ -910,7 +913,7 @@ t_stat sim_instr (void)
|
||||||
ACC = (dst >> 16) & 0xFFFF;
|
ACC = (dst >> 16) & 0xFFFF;
|
||||||
EXT = dst & 0xFFFF;
|
EXT = dst & 0xFFFF;
|
||||||
|
|
||||||
C = (unsigned int32) src < (unsigned int32) src2;
|
C = (uint32) src < (uint32) src2;
|
||||||
if (! V)
|
if (! V)
|
||||||
V = DWSIGN_BIT((src ^ src2) & (src ^ dst));
|
V = DWSIGN_BIT((src ^ src2) & (src ^ dst));
|
||||||
break;
|
break;
|
||||||
|
@ -1280,6 +1283,7 @@ t_stat register_cmd (char *name, t_stat (*action)(int32 flag, char *ptr), int ar
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_MY_ECHO_CMD
|
||||||
/* ------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------
|
||||||
* echo_cmd - just echo the command line
|
* echo_cmd - just echo the command line
|
||||||
* ------------------------------------------------------------------------ */
|
* ------------------------------------------------------------------------ */
|
||||||
|
@ -1289,6 +1293,7 @@ static t_stat echo_cmd (int flag, char *cptr)
|
||||||
printf("%s\n", cptr);
|
printf("%s\n", cptr);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------
|
||||||
* sim_init - initialize simulator upon startup of scp, before reset
|
* sim_init - initialize simulator upon startup of scp, before reset
|
||||||
|
@ -1319,7 +1324,9 @@ void sim_init (void)
|
||||||
register_cmd("CGI", &cgi_cmd, 0, "cgi run simulator in CGI mode\n");
|
register_cmd("CGI", &cgi_cmd, 0, "cgi run simulator in CGI mode\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_MY_ECHO_CMD
|
||||||
register_cmd("ECHO", &echo_cmd, 0, "echo args... echo arguments passed to command\n");
|
register_cmd("ECHO", &echo_cmd, 0, "echo args... echo arguments passed to command\n");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
* This is not a supported product, but I welcome bug reports and fixes.
|
* This is not a supported product, but I welcome bug reports and fixes.
|
||||||
* Mail to simh@ibm1130.org
|
* Mail to simh@ibm1130.org
|
||||||
|
|
||||||
|
* Update 2004-06-05: Removed "feedcycle" from cr_reset. Reset should not touch the card reader.
|
||||||
|
|
||||||
* Update 2004-04-12: Changed ascii field of CPCODE to unsigned char, caught a couple
|
* Update 2004-04-12: Changed ascii field of CPCODE to unsigned char, caught a couple
|
||||||
other potential problems with signed characters used as subscript indexes.
|
other potential problems with signed characters used as subscript indexes.
|
||||||
|
|
||||||
|
@ -337,6 +339,7 @@ static t_stat cr_reset (DEVICE *dptr);
|
||||||
static t_stat cr_set_code (UNIT *uptr, int32 match, char *cptr, void *desc);
|
static t_stat cr_set_code (UNIT *uptr, int32 match, char *cptr, void *desc);
|
||||||
static t_stat cr_attach (UNIT *uptr, char *cptr);
|
static t_stat cr_attach (UNIT *uptr, char *cptr);
|
||||||
static int32 guess_cr_code (void);
|
static int32 guess_cr_code (void);
|
||||||
|
static void feedcycle (t_bool load, t_bool punching);
|
||||||
|
|
||||||
static t_stat cp_reset (DEVICE *dptr);
|
static t_stat cp_reset (DEVICE *dptr);
|
||||||
static t_stat cp_set_code (UNIT *uptr, int32 match, char *cptr, void *desc);
|
static t_stat cp_set_code (UNIT *uptr, int32 match, char *cptr, void *desc);
|
||||||
|
@ -400,7 +403,7 @@ static int32 cp_count= 0;
|
||||||
|
|
||||||
#define COLUMN u4 /* column field in unit record */
|
#define COLUMN u4 /* column field in unit record */
|
||||||
|
|
||||||
UNIT cr_unit = { UDATA (&cr_svc, UNIT_ATTABLE|UNIT_ROABLE, 0) };
|
UNIT cr_unit = { UDATA (&cr_svc, UNIT_ATTABLE|UNIT_ROABLE|UNIT_CR_EMPTY, 0) };
|
||||||
UNIT cp_unit = { UDATA (NULL, UNIT_ATTABLE, 0) };
|
UNIT cp_unit = { UDATA (NULL, UNIT_ATTABLE, 0) };
|
||||||
|
|
||||||
MTAB cr_mod[] = {
|
MTAB cr_mod[] = {
|
||||||
|
@ -916,7 +919,7 @@ t_stat load_cr_boot (int drvno, int switches)
|
||||||
t_stat cr_boot (int unitno, DEVICE *dptr)
|
t_stat cr_boot (int unitno, DEVICE *dptr)
|
||||||
{
|
{
|
||||||
t_stat rval;
|
t_stat rval;
|
||||||
uint16 buf[80];
|
// uint16 buf[80];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if ((rval = reset_all(0)) != SCPE_OK)
|
if ((rval = reset_all(0)) != SCPE_OK)
|
||||||
|
@ -933,13 +936,15 @@ t_stat cr_boot (int unitno, DEVICE *dptr)
|
||||||
if (cr_unit.fileref == NULL) /* this will happen if no file in deck file can be opened */
|
if (cr_unit.fileref == NULL) /* this will happen if no file in deck file can be opened */
|
||||||
return SCPE_IOERR;
|
return SCPE_IOERR;
|
||||||
|
|
||||||
if (fxread(buf, sizeof(buf[0]), 80, cr_unit.fileref) != 80)
|
feedcycle(TRUE, FALSE);
|
||||||
return SCPE_IOERR;
|
|
||||||
|
// if (fxread(buf, sizeof(buf[0]), 80, cr_unit.fileref) != 80)
|
||||||
|
// return SCPE_IOERR;
|
||||||
|
|
||||||
IAR = 0; /* Program Load sets IAR = 0 */
|
IAR = 0; /* Program Load sets IAR = 0 */
|
||||||
|
|
||||||
for (i = 0; i < 80; i++) /* shift 12 bits into 16 */
|
for (i = 0; i < 80; i++) /* shift 12 bits into 16 */
|
||||||
WriteW(i, (buf[i] & 0xF800) | ((buf[i] & 0x0400) ? 0x00C0 : 0x0000) | ((buf[i] & 0x03F0) >> 4));
|
WriteW(i, (readstation[i] & 0xF800) | ((readstation[i] & 0x0400) ? 0x00C0 : 0x0000) | ((readstation[i] & 0x03F0) >> 4));
|
||||||
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -1422,19 +1427,19 @@ static t_stat cr_reset (DEVICE *dptr)
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
SETBIT(cr_unit.flags, UNIT_CR_EMPTY); /* assume hopper empty */
|
// SETBIT(cr_unit.flags, UNIT_CR_EMPTY); /* assume hopper empty */
|
||||||
|
//
|
||||||
if (cr_unit.flags & UNIT_ATT) {
|
// if (cr_unit.flags & UNIT_ATT) {
|
||||||
// if (deckfile != NULL) { /* do NOT rewind the deck file */
|
// if (deckfile != NULL) { /* do NOT rewind the deck file */
|
||||||
// fseek(deckfile, 0, SEEK_SET);
|
// fseek(deckfile, 0, SEEK_SET);
|
||||||
// nextdeck();
|
// nextdeck();
|
||||||
// }
|
// }
|
||||||
// else
|
// else
|
||||||
// checkdeck();
|
// checkdeck();
|
||||||
|
//
|
||||||
if (cr_unit.fileref != NULL)
|
// if (cr_unit.fileref != NULL)
|
||||||
feedcycle(FALSE, FALSE);
|
// feedcycle(FALSE, FALSE);
|
||||||
}
|
// }
|
||||||
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -775,7 +775,7 @@ static void tracesector (int iswrite, int nwords, int addr, int sector)
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("* %04x: %3d /%04x %c %3d.%d ",
|
printf("* %04x: %3d /%04x %c %3d.%d ",
|
||||||
prev_IAR, nwords, addr, iswrite ? '>' : '<', sector/8, sector%8);
|
prev_IAR, nwords, addr, iswrite ? 'W' : 'R', sector/8, sector%8);
|
||||||
|
|
||||||
if (name == NULL) { // look up sector in SLET
|
if (name == NULL) { // look up sector in SLET
|
||||||
for (i = 0; i < MAXSLET; i++) {
|
for (i = 0; i < MAXSLET; i++) {
|
||||||
|
|
|
@ -46,6 +46,11 @@
|
||||||
#define UNIT_V_PHYSICAL_PTR (UNIT_V_UF + 10) /* NOTE: THESE MUST MATCH THE DEFINITION IN ibm1130_prt.c */
|
#define UNIT_V_PHYSICAL_PTR (UNIT_V_UF + 10) /* NOTE: THESE MUST MATCH THE DEFINITION IN ibm1130_prt.c */
|
||||||
#define UNIT_PHYSICAL_PTR (1u << UNIT_V_PHYSICAL_PTR)
|
#define UNIT_PHYSICAL_PTR (1u << UNIT_V_PHYSICAL_PTR)
|
||||||
|
|
||||||
|
// I think I had it wrong; Program Load actually does start the processor after
|
||||||
|
// reading in the card?
|
||||||
|
|
||||||
|
#define PROGRAM_LOAD_STARTS_CPU
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------
|
||||||
* Function declarations
|
* Function declarations
|
||||||
* ------------------------------------------------------------------------ */
|
* ------------------------------------------------------------------------ */
|
||||||
|
@ -1229,9 +1234,12 @@ void HandleCommand (HWND hWnd, WORD wNotify, WORD idCtl, HWND hwCtl)
|
||||||
case IDC_PROGRAM_LOAD:
|
case IDC_PROGRAM_LOAD:
|
||||||
if (! running) { /* if card reader is attached to a file, do cold start read of one card */
|
if (! running) { /* if card reader is attached to a file, do cold start read of one card */
|
||||||
IAR = 0; /* reset IAR */
|
IAR = 0; /* reset IAR */
|
||||||
// stuff_cmd("boot cr");
|
#ifdef PROGRAM_LOAD_STARTS_CPU
|
||||||
|
stuff_cmd("boot cr");
|
||||||
|
#else
|
||||||
if (cr_boot(0, NULL) != SCPE_OK) /* load boot card */
|
if (cr_boot(0, NULL) != SCPE_OK) /* load boot card */
|
||||||
remark_cmd("IPL failed");
|
remark_cmd("IPL failed");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
309
Ibm1130/ibm1130_ptrp.c
Normal file
309
Ibm1130/ibm1130_ptrp.c
Normal file
|
@ -0,0 +1,309 @@
|
||||||
|
/* ibm1130_ptrp.c: IBM 1130 paper tape reader/punch emulation
|
||||||
|
|
||||||
|
Based on the SIMH simulator package written by Robert M Supnik
|
||||||
|
|
||||||
|
Brian Knittel
|
||||||
|
Revision History
|
||||||
|
|
||||||
|
2004.10.22 - Written.
|
||||||
|
|
||||||
|
* (C) Copyright 2004, Brian Knittel.
|
||||||
|
* You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN
|
||||||
|
* RISK basis, there is no warranty of fitness for any purpose, and the rest of the
|
||||||
|
* usual yada-yada. Please keep this notice and the copyright in any distributions
|
||||||
|
* or modifications.
|
||||||
|
*
|
||||||
|
* This is not a supported product, but I welcome bug reports and fixes.
|
||||||
|
* Mail to simh@ibm1130.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ibm1130_defs.h"
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
* 1134 Paper Tape Reader device PTR
|
||||||
|
* 1055 Paper Tape Punch device PTP (shares DSW with PTR)
|
||||||
|
***************************************************************************************/
|
||||||
|
|
||||||
|
#define PTR1134_DSW_READER_RESPONSE 0x4000
|
||||||
|
#define PTR1134_DSW_PUNCH_RESPONSE 0x1000
|
||||||
|
#define PTR1134_DSW_READER_BUSY 0x0800
|
||||||
|
#define PTR1134_DSW_READER_NOT_READY 0x0400
|
||||||
|
#define PTR1134_DSW_PUNCH_BUSY 0x0200
|
||||||
|
#define PTR1134_DSW_PUNCH_NOT_READY 0x0100
|
||||||
|
|
||||||
|
#define IS_ONLINE(u) (((u)->flags & (UNIT_ATT|UNIT_DIS)) == UNIT_ATT)
|
||||||
|
|
||||||
|
static t_stat ptr_svc (UNIT *uptr);
|
||||||
|
static t_stat ptr_reset (DEVICE *dptr);
|
||||||
|
static t_stat ptr_attach (UNIT *uptr, char *cptr);
|
||||||
|
static t_stat ptr_detach (UNIT *uptr);
|
||||||
|
static t_stat ptr_boot (int unitno, DEVICE *dptr);
|
||||||
|
static t_stat ptp_svc (UNIT *uptr);
|
||||||
|
static t_stat ptp_reset (DEVICE *dptr);
|
||||||
|
static t_stat ptp_attach (UNIT *uptr, char *cptr);
|
||||||
|
static t_stat ptp_detach (UNIT *uptr);
|
||||||
|
|
||||||
|
static int16 ptr_dsw = 0; /* device status word */
|
||||||
|
static int32 ptr_wait = 1000; /* character read wait */
|
||||||
|
static uint8 ptr_char = 0; /* last character read */
|
||||||
|
static int32 ptp_wait = 1000; /* character punch wait */
|
||||||
|
|
||||||
|
UNIT ptr_unit[1] = {
|
||||||
|
{ UDATA (&ptr_svc, UNIT_ATTABLE, 0) },
|
||||||
|
};
|
||||||
|
|
||||||
|
REG ptr_reg[] = {
|
||||||
|
{ HRDATA (DSW, ptr_dsw, 16) }, /* device status word */
|
||||||
|
{ DRDATA (WTIME, ptr_wait, 24), PV_LEFT }, /* character read wait */
|
||||||
|
{ DRDATA (LASTCHAR, ptr_char, 8), PV_LEFT }, /* last character read */
|
||||||
|
{ NULL } };
|
||||||
|
|
||||||
|
DEVICE ptr_dev = {
|
||||||
|
"PTR", ptr_unit, ptr_reg, NULL,
|
||||||
|
1, 16, 16, 1, 16, 16,
|
||||||
|
NULL, NULL, ptr_reset,
|
||||||
|
ptr_boot, ptr_attach, ptr_detach};
|
||||||
|
|
||||||
|
UNIT ptp_unit[1] = {
|
||||||
|
{ UDATA (&ptp_svc, UNIT_ATTABLE, 0) },
|
||||||
|
};
|
||||||
|
|
||||||
|
REG ptp_reg[] = {
|
||||||
|
{ HRDATA (DSW, ptr_dsw, 16) }, /* device status word (this is the same as the reader's!) */
|
||||||
|
{ DRDATA (WTIME, ptp_wait, 24), PV_LEFT }, /* character punch wait */
|
||||||
|
{ NULL } };
|
||||||
|
|
||||||
|
DEVICE ptp_dev = {
|
||||||
|
"PTP", ptp_unit, ptp_reg, NULL,
|
||||||
|
1, 16, 16, 1, 16, 16,
|
||||||
|
NULL, NULL, ptp_reset,
|
||||||
|
NULL, ptp_attach, ptp_detach};
|
||||||
|
|
||||||
|
/* xio_1134_papertape - XIO command interpreter for the 1134 paper tape reader and 1055 paper tape punch */
|
||||||
|
|
||||||
|
void xio_1134_papertape (int iocc_addr, int iocc_func, int iocc_mod)
|
||||||
|
{
|
||||||
|
char msg[80];
|
||||||
|
|
||||||
|
switch (iocc_func) {
|
||||||
|
case XIO_READ: /* read: return last character read */
|
||||||
|
M[iocc_addr & mem_mask] = (uint16) (ptr_char << 8);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XIO_WRITE: /* write: initiate punch operation */
|
||||||
|
if ((ptr_dsw & PTR1134_DSW_PUNCH_NOT_READY) == 0 && IS_ONLINE(ptp_unit)) {
|
||||||
|
putc((M[iocc_addr & mem_mask] >> 8) & 0xFF, ptp_unit->fileref);
|
||||||
|
ptp_unit->pos++;
|
||||||
|
}
|
||||||
|
sim_activate(ptp_unit, ptp_wait); /* schedule interrupt */
|
||||||
|
SETBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY | PTR1134_DSW_PUNCH_BUSY);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XIO_SENSE_DEV: /* sense device status */
|
||||||
|
ACC = ptr_dsw;
|
||||||
|
if (iocc_mod & 0x01) { /* reset interrupts */
|
||||||
|
CLRBIT(ptr_dsw, PTR1134_DSW_READER_RESPONSE | PTR1134_DSW_PUNCH_RESPONSE);
|
||||||
|
CLRBIT(ILSW[4], ILSW_4_1134_TAPE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XIO_CONTROL: /* control: initiate character read */
|
||||||
|
sim_activate(ptr_unit, ptr_wait); /* schedule interrupt */
|
||||||
|
SETBIT(ptr_dsw, PTR1134_DSW_READER_BUSY | PTR1134_DSW_READER_NOT_READY);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
sprintf(msg, "Invalid 1134 reader/1055 punch XIO function %x", iocc_func);
|
||||||
|
xio_error(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ptr_svc - emulated timeout - 1134 read operation complete
|
||||||
|
|
||||||
|
static t_stat ptr_svc (UNIT *uptr)
|
||||||
|
{
|
||||||
|
CLRBIT(ptr_dsw, PTR1134_DSW_READER_BUSY); /* clear reader busy flag */
|
||||||
|
SETBIT(ptr_dsw, PTR1134_DSW_READER_NOT_READY); /* assume at end of file */
|
||||||
|
|
||||||
|
if (IS_ONLINE(uptr)) { /* fetch character from file */
|
||||||
|
ptr_char = getc(uptr->fileref);
|
||||||
|
uptr->pos++;
|
||||||
|
|
||||||
|
if (! feof(uptr->fileref)) /* there's more left */
|
||||||
|
CLRBIT(ptr_dsw, PTR1134_DSW_READER_NOT_READY);
|
||||||
|
}
|
||||||
|
|
||||||
|
SETBIT(ptr_dsw, PTR1134_DSW_READER_RESPONSE); /* indicate read complete */
|
||||||
|
|
||||||
|
SETBIT(ILSW[4], ILSW_4_1134_TAPE); /* initiate interrupt */
|
||||||
|
calc_ints();
|
||||||
|
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ptp_svc - emulated timeout -- 1055 punch operation complete
|
||||||
|
|
||||||
|
static t_stat ptp_svc (UNIT *uptr)
|
||||||
|
{
|
||||||
|
CLRBIT(ptr_dsw, PTR1134_DSW_PUNCH_BUSY); /* clear punch busy flag */
|
||||||
|
|
||||||
|
if (IS_ONLINE(uptr)) /* update punch ready status */
|
||||||
|
CLRBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY);
|
||||||
|
else
|
||||||
|
SETBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY);
|
||||||
|
|
||||||
|
SETBIT(ptr_dsw, PTR1134_DSW_PUNCH_RESPONSE); /* indicate punch complete */
|
||||||
|
|
||||||
|
SETBIT(ILSW[4], ILSW_4_1134_TAPE); /* initiate interrupt */
|
||||||
|
calc_ints();
|
||||||
|
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ptr_reset - reset emulated paper tape reader */
|
||||||
|
|
||||||
|
static t_stat ptr_reset (DEVICE *dptr)
|
||||||
|
{
|
||||||
|
sim_cancel(ptr_unit);
|
||||||
|
|
||||||
|
CLRBIT(ptr_dsw, PTR1134_DSW_READER_BUSY | PTR1134_DSW_READER_RESPONSE);
|
||||||
|
SETBIT(ptr_dsw, PTR1134_DSW_READER_NOT_READY);
|
||||||
|
|
||||||
|
if (IS_ONLINE(ptr_unit) && ! feof(ptr_unit->fileref))
|
||||||
|
CLRBIT(ptr_dsw, PTR1134_DSW_READER_NOT_READY);
|
||||||
|
|
||||||
|
if ((ptr_dsw & PTR1134_DSW_PUNCH_RESPONSE) == 0) { /* punch isn't interrupting either */
|
||||||
|
CLRBIT(ILSW[4], ILSW_4_1134_TAPE);
|
||||||
|
calc_ints();
|
||||||
|
}
|
||||||
|
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ptp_reset - reset emulated paper tape punch */
|
||||||
|
|
||||||
|
static t_stat ptp_reset (DEVICE *dptr)
|
||||||
|
{
|
||||||
|
sim_cancel(ptp_unit);
|
||||||
|
|
||||||
|
CLRBIT(ptr_dsw, PTR1134_DSW_PUNCH_BUSY | PTR1134_DSW_PUNCH_RESPONSE);
|
||||||
|
SETBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY);
|
||||||
|
|
||||||
|
if (IS_ONLINE(ptp_unit))
|
||||||
|
CLRBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY);
|
||||||
|
|
||||||
|
if ((ptr_dsw & PTR1134_DSW_READER_RESPONSE) == 0) { /* reader isn't interrupting either */
|
||||||
|
CLRBIT(ILSW[4], ILSW_4_1134_TAPE);
|
||||||
|
calc_ints();
|
||||||
|
}
|
||||||
|
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ptr_attach - attach file to simulated paper tape reader */
|
||||||
|
|
||||||
|
static t_stat ptr_attach (UNIT *uptr, char *cptr)
|
||||||
|
{
|
||||||
|
t_stat rval;
|
||||||
|
|
||||||
|
SETBIT(ptr_dsw, PTR1134_DSW_READER_NOT_READY); /* assume failure */
|
||||||
|
|
||||||
|
if ((rval = attach_unit(uptr, cptr)) != SCPE_OK) /* use standard attach */
|
||||||
|
return rval;
|
||||||
|
|
||||||
|
if ((ptr_dsw & PTR1134_DSW_READER_BUSY) == 0 && ! feof(uptr->fileref))
|
||||||
|
CLRBIT(ptr_dsw, PTR1134_DSW_READER_NOT_READY); /* we're in business */
|
||||||
|
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ptr_attach - detach file from simulated paper tape reader */
|
||||||
|
|
||||||
|
static t_stat ptr_detach (UNIT *uptr)
|
||||||
|
{
|
||||||
|
SETBIT(ptr_dsw, PTR1134_DSW_READER_NOT_READY);
|
||||||
|
|
||||||
|
return detach_unit(uptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ptr_attach - perform paper tape initial program load */
|
||||||
|
|
||||||
|
static t_stat ptr_boot (int unitno, DEVICE *dptr)
|
||||||
|
{
|
||||||
|
int ch, nch, val, addr;
|
||||||
|
t_bool leader = TRUE, start = FALSE;
|
||||||
|
t_stat rval;
|
||||||
|
|
||||||
|
addr = 0;
|
||||||
|
nch = 0;
|
||||||
|
val = 0;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if ((ch = getc(ptr_unit->fileref)) == EOF) {
|
||||||
|
printf("EOF on paper tape without finding Channel 5 end-of-load mark\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (leader) {
|
||||||
|
if ((ch & 0x7F) == 0x7F) // ignore leading rubouts or "delete" characters
|
||||||
|
continue;
|
||||||
|
|
||||||
|
leader = FALSE; // after first nonrubout, any punch in channel 5 terminates load
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is untested -- not sure of actual byte ordering
|
||||||
|
|
||||||
|
val = (val << 4) | (ch & 0x0F); // get next nybble
|
||||||
|
|
||||||
|
if (++nch == 4) { // if we now have four nybbles, store the word
|
||||||
|
M[addr & mem_mask] = (uint16) val;
|
||||||
|
|
||||||
|
addr++; // prepare for next word
|
||||||
|
nch = 0;
|
||||||
|
val = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch & 0x10) { // channel 5 punch terminates load
|
||||||
|
start = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! start) // if we didn't get a valid load, report EOF error
|
||||||
|
return SCPE_EOF;
|
||||||
|
|
||||||
|
if ((rval = reset_all(0)) != SCPE_OK) // force a reset
|
||||||
|
return rval;
|
||||||
|
|
||||||
|
IAR = 0; // start running at address 0
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ptp_attach - attach file to simulated paper tape punch */
|
||||||
|
|
||||||
|
static t_stat ptp_attach (UNIT *uptr, char *cptr)
|
||||||
|
{
|
||||||
|
t_stat rval;
|
||||||
|
|
||||||
|
SETBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY); /* assume failure */
|
||||||
|
|
||||||
|
if ((rval = attach_unit(uptr, cptr)) != SCPE_OK) /* use standard attach */
|
||||||
|
return rval;
|
||||||
|
|
||||||
|
fseek(uptr->fileref, 0, SEEK_END); /* if we opened an existing file, append to it */
|
||||||
|
uptr->pos = ftell(uptr->fileref);
|
||||||
|
|
||||||
|
if ((ptr_dsw & PTR1134_DSW_PUNCH_BUSY) == 0)
|
||||||
|
CLRBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY); /* we're in business */
|
||||||
|
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ptp_detach - detach file from simulated paper tape punch */
|
||||||
|
|
||||||
|
static t_stat ptp_detach (UNIT *uptr)
|
||||||
|
{
|
||||||
|
SETBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY);
|
||||||
|
|
||||||
|
return detach_unit(uptr);
|
||||||
|
}
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
Revision History:
|
Revision History:
|
||||||
|
|
||||||
|
2004.10.22 - Removed stub for xio_1134_papertape as it's now a supported device
|
||||||
|
|
||||||
2003.11.23 - Fixed bug in new routine "quotefix" that made sim crash
|
2003.11.23 - Fixed bug in new routine "quotefix" that made sim crash
|
||||||
for all non-Windows builds :(
|
for all non-Windows builds :(
|
||||||
|
|
||||||
|
@ -90,12 +92,11 @@
|
||||||
static void badio (char *dev)
|
static void badio (char *dev)
|
||||||
{
|
{
|
||||||
// the real 1130 just ignores attempts to use uninstalled devices. They get tested
|
// the real 1130 just ignores attempts to use uninstalled devices. They get tested
|
||||||
// at times, so it's best to be quiet about this
|
// at times, so it's best to just be quiet about this
|
||||||
// printf("%s I/O is not yet supported", dev);
|
// printf("%s I/O is not yet supported", dev);
|
||||||
// wait_state = WAIT_INVALID_OP;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void xio_1134_papertape (int32 addr, int32 func, int32 modify) {badio("papertape");}
|
// void xio_1134_papertape (int32 addr, int32 func, int32 modify) {badio("papertape");}
|
||||||
void xio_1627_plotter (int32 addr, int32 func, int32 modify) {badio("plotter");}
|
void xio_1627_plotter (int32 addr, int32 func, int32 modify) {badio("plotter");}
|
||||||
void xio_1231_optical (int32 addr, int32 func, int32 modify) {badio("optical mark");}
|
void xio_1231_optical (int32 addr, int32 func, int32 modify) {badio("optical mark");}
|
||||||
void xio_2501_card (int32 addr, int32 func, int32 modify) {badio("2501 card");}
|
void xio_2501_card (int32 addr, int32 func, int32 modify) {badio("2501 card");}
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
extern DEVICE cpu_dev, console_dev, dsk_dev, cr_dev, cp_dev;
|
extern DEVICE cpu_dev, console_dev, dsk_dev, cr_dev, cp_dev, ptr_dev, ptp_dev;
|
||||||
extern DEVICE tti_dev, tto_dev, prt_dev, log_dev;
|
extern DEVICE tti_dev, tto_dev, prt_dev, log_dev;
|
||||||
extern DEVICE gdu_dev, console_dev;
|
extern DEVICE gdu_dev, console_dev;
|
||||||
|
|
||||||
|
@ -59,6 +59,8 @@ DEVICE *sim_devices[] = {
|
||||||
&tti_dev, /* console keyboard, selectric printer */
|
&tti_dev, /* console keyboard, selectric printer */
|
||||||
&tto_dev,
|
&tto_dev,
|
||||||
&prt_dev, /* 1132 printer */
|
&prt_dev, /* 1132 printer */
|
||||||
|
&ptr_dev, /* 1134 paper tape reader */
|
||||||
|
&ptp_dev, /* 1055 paper tape punch */
|
||||||
&console_dev, /* console display (windows GUI) */
|
&console_dev, /* console display (windows GUI) */
|
||||||
&gdu_dev, /* 2250 display */
|
&gdu_dev, /* 2250 display */
|
||||||
NULL
|
NULL
|
||||||
|
|
|
@ -59,7 +59,7 @@ ibm1130 = ${ibm1130D}ibm1130_sys.c ${ibm1130D}ibm1130_cpu.c \
|
||||||
${ibm1130D}ibm1130_cr.c ${ibm1130D}ibm1130_disk.c \
|
${ibm1130D}ibm1130_cr.c ${ibm1130D}ibm1130_disk.c \
|
||||||
${ibm1130D}ibm1130_stddev.c ${ibm1130D}ibm1130_gdu.c \
|
${ibm1130D}ibm1130_stddev.c ${ibm1130D}ibm1130_gdu.c \
|
||||||
${ibm1130D}ibm1130_gui.c ${ibm1130D}ibm1130_prt.c \
|
${ibm1130D}ibm1130_gui.c ${ibm1130D}ibm1130_prt.c \
|
||||||
${ibm1130D}ibm1130_fmt.c
|
${ibm1130D}ibm1130_ptrp.c ${ibm1130D}ibm1130_fmt.c
|
||||||
|
|
||||||
ibm1130_INC = ibm1130res.h ibm1130_conin.h ibm1130_conout.h \
|
ibm1130_INC = ibm1130res.h ibm1130_conin.h ibm1130_conout.h \
|
||||||
ibm1130_defs.h ibm1130_prtwheel.h ibm1130_fmt.h \
|
ibm1130_defs.h ibm1130_prtwheel.h ibm1130_fmt.h \
|
||||||
|
|
|
@ -9,10 +9,27 @@
|
||||||
* Mail to sim@ibm1130.org
|
* Mail to sim@ibm1130.org
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define VERSION "ASM1130 CROSS ASSEMBLER V1.14"
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
// ASM1130 - IBM 1130 Cross Assembler
|
// ASM1130 - IBM 1130 Cross Assembler
|
||||||
//
|
//
|
||||||
// Version
|
// Version
|
||||||
|
// 1.14 - 2004Oct22 - Fixed problem with BSS complaining about negative
|
||||||
|
// sizes. This may be a fundamental problem with my using
|
||||||
|
// 32-bit expressions, but for now, it appears that just
|
||||||
|
// truncating the BSS size to 16 bits is sufficient to build DMS.
|
||||||
|
// 1.13 - 2004Jun05 - Fixed sign extension of constants in expressions. Statements
|
||||||
|
// like LD /FFFF were being assembled incorrectly.
|
||||||
|
// 1.12 - 2004Jun04 - Made WAIT instruction take a displacement value.
|
||||||
|
// Doesn't affect operation, but these are used as indicators
|
||||||
|
// in the IBM one-card diagnostic programs.
|
||||||
|
// Also -- should mention that the .IPL directive was
|
||||||
|
// removed some time ago. To create bootable cards,
|
||||||
|
// use -b flag to create binary output, and post-process the
|
||||||
|
// binary output with program "mkboot"
|
||||||
|
// 1.11 - 2004May22 - Added CMP, DCM, and DECS instructions for 1800,
|
||||||
|
// thanks to Kevin Everets.
|
||||||
// 1.10 - 2003Dec08 - Fixed opcode value for XCH instruction, thanks to
|
// 1.10 - 2003Dec08 - Fixed opcode value for XCH instruction, thanks to
|
||||||
// Roger Simpson.
|
// Roger Simpson.
|
||||||
// 1.09 - 2003Aug03 - Added fxwrite so asm will write little-endian files
|
// 1.09 - 2003Aug03 - Added fxwrite so asm will write little-endian files
|
||||||
|
@ -91,28 +108,14 @@
|
||||||
// >>> Look for "bug here" though, for things to check out.
|
// >>> Look for "bug here" though, for things to check out.
|
||||||
//
|
//
|
||||||
// Notes:
|
// Notes:
|
||||||
|
// We assume that the computer on which the assembler runs uses ANSI floating point.
|
||||||
|
// Also, the assembly of floating point values may be incorrect on non-Intel
|
||||||
|
// architectures, this needs to be investigated.
|
||||||
|
//
|
||||||
// org_advanced tells whether * in an expression refers to the address AFTER the
|
// org_advanced tells whether * in an expression refers to the address AFTER the
|
||||||
// instruction (1 or 2 words, depending on length). This is the case for opcodes
|
// instruction (1 or 2 words, depending on length). This is the case for opcodes
|
||||||
// but not all directives.
|
// but not all directives.
|
||||||
//
|
//
|
||||||
// Added special coldstart format directives:
|
|
||||||
//
|
|
||||||
// .IPL 1130,XXXXXXXX
|
|
||||||
// .IPL 1800,XXXXXXXX
|
|
||||||
//
|
|
||||||
// (these are not standard IBM)
|
|
||||||
//
|
|
||||||
// These directives cause the output file to be written in binary in either 1130 or
|
|
||||||
// 1800 IPL format. In 1130 format, the index bits are lost and the displacement
|
|
||||||
// is sign extended. In 1800 format, the data are punched 8 bits at a time into
|
|
||||||
// two columns per word. If an identifier is not given, data are punched into
|
|
||||||
// all 80 columns. If an identifier is given, data is punched in columns 0 through
|
|
||||||
// 72, and the identification XXXXXXXX is punched in columns 73 through 80. (If
|
|
||||||
// there are multiple output cards the last ident character is incremented). A
|
|
||||||
// warning is issued if 1130 assembly results in lost bits. These directives
|
|
||||||
// should be the first in the file as you don't want text and binary mixed in
|
|
||||||
// the same output file.
|
|
||||||
//
|
|
||||||
// Revision History
|
// Revision History
|
||||||
// 16Apr02 1.03 Added sector break, relocation flag output
|
// 16Apr02 1.03 Added sector break, relocation flag output
|
||||||
// 02Apr02 1.02 Fixed bug in BOSC: it CAN be a short instruction.
|
// 02Apr02 1.02 Fixed bug in BOSC: it CAN be a short instruction.
|
||||||
|
@ -133,7 +136,8 @@
|
||||||
// DEFINITIONS
|
// DEFINITIONS
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
// I have found some IBM source code where @ and ' seem interchangable.
|
// I have found some IBM source code where @ and ' seem interchangable (likely due to the
|
||||||
|
// use of 026 keypunches).
|
||||||
// Comment out this define to make @ and ' different in symbol names, keep to make equivalent
|
// Comment out this define to make @ and ' different in symbol names, keep to make equivalent
|
||||||
|
|
||||||
#if defined(VMS)
|
#if defined(VMS)
|
||||||
|
@ -162,8 +166,6 @@
|
||||||
#define TRUE 1
|
#define TRUE 1
|
||||||
#define FALSE 0
|
#define FALSE 0
|
||||||
|
|
||||||
#define VERSION "ASM1130 CROSS ASSEMBLER V1.08"
|
|
||||||
|
|
||||||
#define ISTV 0x33 // magic number from DMS R2V12 monitorm symbol @ISTV
|
#define ISTV 0x33 // magic number from DMS R2V12 monitorm symbol @ISTV
|
||||||
|
|
||||||
#define MAXLITERALS 300
|
#define MAXLITERALS 300
|
||||||
|
@ -233,7 +235,7 @@ typedef enum {OUTMODE_LOAD, OUTMODE_1130, OUTMODE_1800, OUTMODE_BINARY} OUTMODE;
|
||||||
|
|
||||||
// command line syntax
|
// command line syntax
|
||||||
char *usestr =
|
char *usestr =
|
||||||
"Usage: asm1130 [-bpsvwxy] [-o[file]] [-l[file]] [-rN.M] file...\n\n"
|
"Usage: asm1130 [-bpsvwxy8] [-o[file]] [-l[file]] [-rN.M] file...\n\n"
|
||||||
"-b binary (relocatable format) output; default is simulator LOAD format\n"
|
"-b binary (relocatable format) output; default is simulator LOAD format\n"
|
||||||
"-p count passes required; no assembly output is created with this flag"
|
"-p count passes required; no assembly output is created with this flag"
|
||||||
"-s add symbol table to listing\n"
|
"-s add symbol table to listing\n"
|
||||||
|
@ -244,10 +246,12 @@ char *usestr =
|
||||||
"-y preload system symbol table SYMBOLS.SYS\n"
|
"-y preload system symbol table SYMBOLS.SYS\n"
|
||||||
"-o set output file; default is first input file + .out or .bin\n"
|
"-o set output file; default is first input file + .out or .bin\n"
|
||||||
"-l create listing file; default is first input file + .lst\n"
|
"-l create listing file; default is first input file + .lst\n"
|
||||||
"-r set dms version to VN RM for system SBRK cards";
|
"-r set dms version to VN RM for system SBRK cards\n"
|
||||||
|
"-8 enable IBM 1800 instructions"; // (alternately, rename or link executable to asm1800.exe)
|
||||||
|
|
||||||
BOOL verbose = FALSE; // verbose mode flag
|
BOOL verbose = FALSE; // verbose mode flag
|
||||||
BOOL tabformat = FALSE; // TRUE if tabs were seen in the file
|
BOOL tabformat = FALSE; // TRUE if tabs were seen in the file
|
||||||
|
BOOL enable_1800 = FALSE; // TRUE if 1800 mode is enabled by flag or executable name
|
||||||
int pass; // current assembler pass (1 or 2)
|
int pass; // current assembler pass (1 or 2)
|
||||||
char curfn[256]; // current input file name
|
char curfn[256]; // current input file name
|
||||||
char progname[8]; // base name of primary input file
|
char progname[8]; // base name of primary input file
|
||||||
|
@ -349,6 +353,7 @@ int ascii_to_1403_table[128] =
|
||||||
// PROTOTYPES
|
// PROTOTYPES
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void init (int argc, char **argv);
|
||||||
void bail (char *msg);
|
void bail (char *msg);
|
||||||
void flag (char *arg);
|
void flag (char *arg);
|
||||||
void proc (char *fname);
|
void proc (char *fname);
|
||||||
|
@ -387,6 +392,7 @@ void bincard_endcard (void);
|
||||||
void handle_sbrk (char *line);
|
void handle_sbrk (char *line);
|
||||||
void bincard_typecard (void);
|
void bincard_typecard (void);
|
||||||
void namecode (unsigned short *words, char *tok);
|
void namecode (unsigned short *words, char *tok);
|
||||||
|
int signextend (int v);
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
// main routine
|
// main routine
|
||||||
|
@ -396,9 +402,7 @@ int main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
int i, sawfile = FALSE;
|
int i, sawfile = FALSE;
|
||||||
|
|
||||||
for (i = 1; i < argc; i++) // process command line switches
|
init(argc, argv); // initialize, process flags
|
||||||
if (*argv[i] == '-')
|
|
||||||
flag(argv[i]+1);
|
|
||||||
|
|
||||||
startpass(1); // first pass, process files
|
startpass(1); // first pass, process files
|
||||||
|
|
||||||
|
@ -460,6 +464,21 @@ int main (int argc, char **argv)
|
||||||
return 0; // all done
|
return 0; // all done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------
|
||||||
|
// init - initialize assembler, process command line flags
|
||||||
|
// ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void init (int argc, char **argv)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
enable_1800 = strstr(argv[0], "1800") != NULL; // if "1800" appears in the executable name, enable 1800 extensions
|
||||||
|
|
||||||
|
for (i = 1; i < argc; i++) // process command line switches
|
||||||
|
if (*argv[i] == '-')
|
||||||
|
flag(argv[i]+1);
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
// flag - process one command line switch
|
// flag - process one command line switch
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
|
@ -512,6 +531,10 @@ void flag (char *arg)
|
||||||
outmode = OUTMODE_BINARY;
|
outmode = OUTMODE_BINARY;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case '8':
|
||||||
|
enable_1800 = TRUE;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'r':
|
case 'r':
|
||||||
if (sscanf(arg, "%d.%d", &major, &minor) != 2)
|
if (sscanf(arg, "%d.%d", &major, &minor) != 2)
|
||||||
bail(usestr);
|
bail(usestr);
|
||||||
|
@ -1194,6 +1217,7 @@ void coltok (char *c, char *tok, int ifrom, int ito, BOOL condense, char *save)
|
||||||
#define IS_ABS 0x0002 // always uses absolute addressing mode (implied X)
|
#define IS_ABS 0x0002 // always uses absolute addressing mode (implied X)
|
||||||
#define NO_IDX 0x0004 // even with 1 or 2 modifier, this is not really indexed (for STX/LDX)
|
#define NO_IDX 0x0004 // even with 1 or 2 modifier, this is not really indexed (for STX/LDX)
|
||||||
#define NO_ARGS 0x0008 // statement takes no arguments
|
#define NO_ARGS 0x0008 // statement takes no arguments
|
||||||
|
#define IS_1800 0x0010 // 1800-only directive or instruction, flagged if 1800 mode is not enabled
|
||||||
#define TRAP 0x1000 // debug this instruction
|
#define TRAP 0x1000 // debug this instruction
|
||||||
|
|
||||||
struct tag_op { // OPCODE TABLE
|
struct tag_op { // OPCODE TABLE
|
||||||
|
@ -1230,6 +1254,7 @@ void x_bes (struct tag_op *op, char *label, char *mods, char *arg);
|
||||||
void x_bss (struct tag_op *op, char *label, char *mods, char *arg);
|
void x_bss (struct tag_op *op, char *label, char *mods, char *arg);
|
||||||
void x_dc (struct tag_op *op, char *label, char *mods, char *arg);
|
void x_dc (struct tag_op *op, char *label, char *mods, char *arg);
|
||||||
void x_dec (struct tag_op *op, char *label, char *mods, char *arg);
|
void x_dec (struct tag_op *op, char *label, char *mods, char *arg);
|
||||||
|
void x_decs (struct tag_op *op, char *label, char *mods, char *arg);
|
||||||
void x_ebc (struct tag_op *op, char *label, char *mods, char *arg);
|
void x_ebc (struct tag_op *op, char *label, char *mods, char *arg);
|
||||||
void x_end (struct tag_op *op, char *label, char *mods, char *arg);
|
void x_end (struct tag_op *op, char *label, char *mods, char *arg);
|
||||||
void x_ent (struct tag_op *op, char *label, char *mods, char *arg);
|
void x_ent (struct tag_op *op, char *label, char *mods, char *arg);
|
||||||
|
@ -1262,6 +1287,7 @@ struct tag_op ops[] = {
|
||||||
"BSS", 0, x_bss, E, NONE, 0,
|
"BSS", 0, x_bss, E, NONE, 0,
|
||||||
"DC", 0, x_dc, NONE, NONE, 0,
|
"DC", 0, x_dc, NONE, NONE, 0,
|
||||||
"DEC", 0, x_dec, E, E, IS_DBL,
|
"DEC", 0, x_dec, E, E, IS_DBL,
|
||||||
|
"DECS", 0, x_decs, E, E, IS_DBL, // this is an IBM 1800 directive
|
||||||
"DMES", 0, x_dmes, ANY, NONE, 0,
|
"DMES", 0, x_dmes, ANY, NONE, 0,
|
||||||
"DN", 0, x_dn, NONE, NONE, 0,
|
"DN", 0, x_dn, NONE, NONE, 0,
|
||||||
"DSA", 0, x_dsa, NONE, NONE, 0,
|
"DSA", 0, x_dsa, NONE, NONE, 0,
|
||||||
|
@ -1293,6 +1319,8 @@ struct tag_op ops[] = {
|
||||||
"AND", 0xE000, std_op, ALL, NONE, 0,
|
"AND", 0xE000, std_op, ALL, NONE, 0,
|
||||||
"BSI", 0x4000, bsi_op, ALL, NONE, 0,
|
"BSI", 0x4000, bsi_op, ALL, NONE, 0,
|
||||||
"CALL", 0x4000, x_call, ALL, L, 0, // alias for BSI L, or external call
|
"CALL", 0x4000, x_call, ALL, L, 0, // alias for BSI L, or external call
|
||||||
|
"CMP", 0xB000, std_op, ALL, NONE, IS_1800, // this is an IBM 1800-only instruction
|
||||||
|
"DCM", 0xB800, std_op, ALL, NONE, IS_1800, // this is an IBM 1800-only instruction
|
||||||
"D" , 0xA800, std_op, ALL, NONE, 0,
|
"D" , 0xA800, std_op, ALL, NONE, 0,
|
||||||
"EOR", 0xF000, std_op, ALL, NONE, 0,
|
"EOR", 0xF000, std_op, ALL, NONE, 0,
|
||||||
"LD", 0xC000, std_op, ALL, NONE, 0,
|
"LD", 0xC000, std_op, ALL, NONE, 0,
|
||||||
|
@ -1310,7 +1338,7 @@ struct tag_op ops[] = {
|
||||||
"STO", 0xD000, std_op, ALL, NONE, 0,
|
"STO", 0xD000, std_op, ALL, NONE, 0,
|
||||||
"STS", 0x2800, std_op, ALL, NONE, 0,
|
"STS", 0x2800, std_op, ALL, NONE, 0,
|
||||||
"STX", 0x6800, std_op, ALL, NONE, NO_IDX,
|
"STX", 0x6800, std_op, ALL, NONE, NO_IDX,
|
||||||
"WAIT", 0x3000, std_op, NONE, NONE, NO_ARGS,
|
"WAIT", 0x3000, std_op, NONE, NONE, IS_ABS,
|
||||||
"XCH", 0x18D0, std_op, NONE, NONE, 0, // same as RTE 16, 18C0 + 10
|
"XCH", 0x18D0, std_op, NONE, NONE, 0, // same as RTE 16, 18C0 + 10
|
||||||
"XIO", 0x0800, std_op, ALL, NONE, IS_DBL,
|
"XIO", 0x0800, std_op, ALL, NONE, IS_DBL,
|
||||||
|
|
||||||
|
@ -1850,6 +1878,9 @@ void parse_line (char *line)
|
||||||
|
|
||||||
org_advanced = strchr(mods, 'L') ? 2 : 1; // by default, * means address + 1 or 2. Sometimes it doesn't
|
org_advanced = strchr(mods, 'L') ? 2 : 1; // by default, * means address + 1 or 2. Sometimes it doesn't
|
||||||
(op->handler)(op, label, mods, arg);
|
(op->handler)(op, label, mods, arg);
|
||||||
|
|
||||||
|
if ((op->flags & IS_1800) && ! enable_1800)
|
||||||
|
asm_warning("%s is IBM 1800-specific; use the -8 command line option", op->mnem);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
|
@ -2178,6 +2209,9 @@ void convert_double_to_extended (double d, unsigned short *wd)
|
||||||
wd[2] = (unsigned short) (mantissa & 0xFFFF);
|
wd[2] = (unsigned short) (mantissa & 0xFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------
|
||||||
|
// ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
void convert_double_to_standard (double d, unsigned short *wd)
|
void convert_double_to_standard (double d, unsigned short *wd)
|
||||||
{
|
{
|
||||||
int neg, exp;
|
int neg, exp;
|
||||||
|
@ -2222,6 +2256,9 @@ void convert_double_to_standard (double d, unsigned short *wd)
|
||||||
// printf(" D %04x%04x\n", wd[0], wd[1]);
|
// printf(" D %04x%04x\n", wd[0], wd[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------
|
||||||
|
// ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
void convert_double_to_fixed (double d, unsigned short *wd, int bexp)
|
void convert_double_to_fixed (double d, unsigned short *wd, int bexp)
|
||||||
{
|
{
|
||||||
int neg, exp, rshift;
|
int neg, exp, rshift;
|
||||||
|
@ -2232,6 +2269,9 @@ void convert_double_to_fixed (double d, unsigned short *wd, int bexp)
|
||||||
wd[0] = wd[1] = 0;
|
wd[0] = wd[1] = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// note: we assume that this computer uses ANSI floating point
|
||||||
|
|
||||||
// 7 6 5 4 0
|
// 7 6 5 4 0
|
||||||
// d = ansi real*8 SXXX XXXX XXXX MMMM MMMM MMMM MMMM MMMM ... MMMM MMMM
|
// d = ansi real*8 SXXX XXXX XXXX MMMM MMMM MMMM MMMM MMMM ... MMMM MMMM
|
||||||
|
|
||||||
|
@ -2269,6 +2309,9 @@ void convert_double_to_fixed (double d, unsigned short *wd, int bexp)
|
||||||
wd[1] = (unsigned short) (mantissa & 0xFFFF);
|
wd[1] = (unsigned short) (mantissa & 0xFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------
|
||||||
|
// ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
void getDconstant (char *tok, unsigned short *wd)
|
void getDconstant (char *tok, unsigned short *wd)
|
||||||
{
|
{
|
||||||
unsigned long l;
|
unsigned long l;
|
||||||
|
@ -2312,14 +2355,15 @@ void getDconstant (char *tok, unsigned short *wd)
|
||||||
convert_double_to_standard(d, wd);
|
convert_double_to_standard(d, wd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------
|
||||||
// If the input value is an integer with no decimal point and no B or E,
|
// If the input value is an integer with no decimal point and no B or E,
|
||||||
// DEC generates a double INTEGER value.
|
// DEC generates a double INTEGER value.
|
||||||
// IBM documentation ranges from ambiguous to wrong on this point, but
|
// IBM documentation ranges from ambiguous to wrong on this point, but
|
||||||
// examination of the DMS microfiche supports this.
|
// examination of the DMS microfiche supports this.
|
||||||
|
// ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
void x_dec (struct tag_op *op, char *label, char *mods, char *arg)
|
void x_dec (struct tag_op *op, char *label, char *mods, char *arg)
|
||||||
{
|
{
|
||||||
// char *tok;
|
|
||||||
unsigned short wd[2];
|
unsigned short wd[2];
|
||||||
|
|
||||||
org_advanced = 2; // assume * means address after this location, since it's +1 for dc?
|
org_advanced = 2; // assume * means address after this location, since it's +1 for dc?
|
||||||
|
@ -2343,6 +2387,28 @@ void x_dec (struct tag_op *op, char *label, char *mods, char *arg)
|
||||||
// writew(wd[1], FALSE);
|
// writew(wd[1], FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------
|
||||||
|
// DECS directive. Writes just the high word of a DEC value
|
||||||
|
// ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void x_decs (struct tag_op *op, char *label, char *mods, char *arg)
|
||||||
|
{
|
||||||
|
unsigned short wd[2];
|
||||||
|
|
||||||
|
org_advanced = 1; // assume * means address after this location
|
||||||
|
|
||||||
|
setw(0, org, FALSE); // display the origin
|
||||||
|
|
||||||
|
if (*label) // define label
|
||||||
|
set_symbol(label, org, TRUE, relocate);
|
||||||
|
|
||||||
|
getDconstant(arg, wd);
|
||||||
|
writew(wd[0], FALSE); // write hiword ONLY
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------
|
||||||
|
// ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
void x_xflc (struct tag_op *op, char *label, char *mods, char *arg)
|
void x_xflc (struct tag_op *op, char *label, char *mods, char *arg)
|
||||||
{
|
{
|
||||||
char *tok, *b;
|
char *tok, *b;
|
||||||
|
@ -2854,9 +2920,10 @@ void x_bss (struct tag_op *op, char *label, char *mods, char *arg)
|
||||||
if (*label) // define label
|
if (*label) // define label
|
||||||
set_symbol(label, org, TRUE, relocate);
|
set_symbol(label, org, TRUE, relocate);
|
||||||
|
|
||||||
if (expr.value < 0)
|
expr.value &= 0xFFFF; // truncate to 16 bits
|
||||||
asm_warning("Negative BSS size");
|
|
||||||
|
|
||||||
|
if (expr.value & 0x8000)
|
||||||
|
asm_warning("Negative BSS size");
|
||||||
else if (expr.value > 0) {
|
else if (expr.value > 0) {
|
||||||
if (outmode == OUTMODE_LOAD) {
|
if (outmode == OUTMODE_LOAD) {
|
||||||
org += expr.value; // advance the origin by appropriate number of words
|
org += expr.value; // advance the origin by appropriate number of words
|
||||||
|
@ -3920,7 +3987,7 @@ void a1130_term (EXPR *ap)
|
||||||
c = GETNEXT;
|
c = GETNEXT;
|
||||||
|
|
||||||
if (ctype[c] == DIGIT) { /* number */
|
if (ctype[c] == DIGIT) { /* number */
|
||||||
ap->value = c_number(c,10,-1);
|
ap->value = signextend(c_number(c,10,-1));
|
||||||
ap->relative = ABSOLUTE;
|
ap->relative = ABSOLUTE;
|
||||||
}
|
}
|
||||||
else if (c == '+') { /* unary + */
|
else if (c == '+') { /* unary + */
|
||||||
|
@ -3931,7 +3998,7 @@ void a1130_term (EXPR *ap)
|
||||||
ap->value = - ap->value;
|
ap->value = - ap->value;
|
||||||
}
|
}
|
||||||
else if (c == '/') { /* / starts a hex constant */
|
else if (c == '/') { /* / starts a hex constant */
|
||||||
ap->value = c_number(c,16,-1);
|
ap->value = signextend(c_number(c,16,-1));
|
||||||
ap->relative = ABSOLUTE;
|
ap->relative = ABSOLUTE;
|
||||||
}
|
}
|
||||||
else if (c == '*') { /* asterisk alone = org */
|
else if (c == '*') { /* asterisk alone = org */
|
||||||
|
@ -3970,6 +4037,20 @@ void a1130_term (EXPR *ap)
|
||||||
exprerr(8);
|
exprerr(8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------
|
||||||
|
// signextend - sign-extend a 16-bit constant value to whatever "int" is.
|
||||||
|
// ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int signextend (int v)
|
||||||
|
{
|
||||||
|
v &= 0xFFFF; // clip to 16 bits (this may not be necessary, but best to be safe?)
|
||||||
|
|
||||||
|
if (v & 0x8000) // if sign bit is set
|
||||||
|
v |= ~0xFFFF; // sign extend
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
// c_expr - evalate an expression
|
// c_expr - evalate an expression
|
||||||
// ---------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------
|
||||||
|
@ -4168,15 +4249,15 @@ void c_term (EXPR *ap)
|
||||||
ap->value = c_esc(c);
|
ap->value = c_esc(c);
|
||||||
}
|
}
|
||||||
else if (ctype[c] == DIGIT) { /* number */
|
else if (ctype[c] == DIGIT) { /* number */
|
||||||
ap->value = c_number(c,10,-1);
|
ap->value = signextend(c_number(c,10,-1));
|
||||||
}
|
}
|
||||||
else if (c == '0') { /* 0 starts a hex or octal constant */
|
else if (c == '0') { /* 0 starts a hex or octal constant */
|
||||||
if ((c = GETNEXT) == 'x') {
|
if ((c = GETNEXT) == 'x') {
|
||||||
c = GETNEXT;
|
c = GETNEXT;
|
||||||
ap->value = c_number(c,16,-1);
|
ap->value = signextend(c_number(c,16,-1));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ap->value = c_number(c,8,-1);
|
ap->value = signextend(c_number(c,8,-1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (c == '*') { /* asterisk alone = org */
|
else if (c == '*') { /* asterisk alone = org */
|
||||||
|
@ -4501,3 +4582,4 @@ int strcmpi (char *a, char *b)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -30,9 +30,9 @@
|
||||||
// loads somefile.bin, writes object in 1130 IPL format to somefile.ipl
|
// loads somefile.bin, writes object in 1130 IPL format to somefile.ipl
|
||||||
// Up to 80 columns will be written depending on what the object actually uses
|
// Up to 80 columns will be written depending on what the object actually uses
|
||||||
//
|
//
|
||||||
// mkboot somefile.bin somefile.ipl 1130 0 48 SOMEF
|
// mkboot somefile.bin somefile.ipl 1130 /0 /47 SOMEF
|
||||||
//
|
//
|
||||||
// loads somefile.bin. Writes 72 columns (hex 48), with ident columns 73-80 = SOMEF001
|
// loads somefile.bin. Writes 72 columns (hex 0 to hex 47), with ident columns 73-80 = SOMEF001
|
||||||
//
|
//
|
||||||
// mkboot somefile.bin somefile.dat core 0 0 SOMEF001
|
// mkboot somefile.bin somefile.dat core 0 0 SOMEF001
|
||||||
//
|
//
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
cpu Interdata 16b CPU
|
cpu Interdata 16b CPU
|
||||||
|
|
||||||
|
07-Nov-04 RMS Added instruction history
|
||||||
22-Sep-03 RMS Added additional instruction decode types
|
22-Sep-03 RMS Added additional instruction decode types
|
||||||
07-Feb-03 RMS Fixed bug in SETM, SETMR (found by Mark Pizzolato)
|
07-Feb-03 RMS Fixed bug in SETM, SETMR (found by Mark Pizzolato)
|
||||||
|
|
||||||
|
@ -151,6 +152,17 @@
|
||||||
#define UNIT_816E (1 << UNIT_V_816E)
|
#define UNIT_816E (1 << UNIT_V_816E)
|
||||||
#define UNIT_TYPE (UNIT_ID4 | UNIT_716 | UNIT_816 | UNIT_816E)
|
#define UNIT_TYPE (UNIT_ID4 | UNIT_716 | UNIT_816 | UNIT_816E)
|
||||||
|
|
||||||
|
#define HIST_MIN 64
|
||||||
|
#define HIST_MAX 65536
|
||||||
|
struct InstHistory {
|
||||||
|
uint16 vld;
|
||||||
|
uint16 pc;
|
||||||
|
uint16 ir1;
|
||||||
|
uint16 ir2;
|
||||||
|
uint16 r1;
|
||||||
|
uint16 ea;
|
||||||
|
uint16 opnd; };
|
||||||
|
|
||||||
#define SEXT16(x) (((x) & SIGN16)? ((int32) ((x) | 0xFFFF8000)): \
|
#define SEXT16(x) (((x) & SIGN16)? ((int32) ((x) | 0xFFFF8000)): \
|
||||||
((int32) ((x) & 0x7FFF)))
|
((int32) ((x) & 0x7FFF)))
|
||||||
#define CC_GL_16(x) if ((x) & SIGN16) cc = CC_L; \
|
#define CC_GL_16(x) if ((x) & SIGN16) cc = CC_L; \
|
||||||
|
@ -190,7 +202,9 @@ REG *pcq_r = NULL; /* PC queue reg ptr */
|
||||||
uint32 dec_flgs = 0; /* decode flags */
|
uint32 dec_flgs = 0; /* decode flags */
|
||||||
uint32 fp_in_hwre = 0; /* ucode/hwre fp */
|
uint32 fp_in_hwre = 0; /* ucode/hwre fp */
|
||||||
uint32 pawidth = PAWIDTH16; /* phys addr mask */
|
uint32 pawidth = PAWIDTH16; /* phys addr mask */
|
||||||
uint32 cpu_log = 0; /* debug logging */
|
uint32 hst_p = 0; /* history pointer */
|
||||||
|
uint32 hst_lnt = 0; /* history length */
|
||||||
|
struct InstHistory *hst = NULL; /* instruction history */
|
||||||
struct BlockIO blk_io; /* block I/O status */
|
struct BlockIO blk_io; /* block I/O status */
|
||||||
uint32 (*dev_tab[DEVNO])(uint32 dev, uint32 op, uint32 datout) = { NULL };
|
uint32 (*dev_tab[DEVNO])(uint32 dev, uint32 op, uint32 datout) = { NULL };
|
||||||
|
|
||||||
|
@ -216,6 +230,8 @@ t_stat cpu_reset (DEVICE *dptr);
|
||||||
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
t_stat cpu_set_model (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat cpu_set_model (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
t_stat cpu_set_consint (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat cpu_set_consint (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
|
|
||||||
extern t_bool devtab_init (void);
|
extern t_bool devtab_init (void);
|
||||||
extern void int_eval (void);
|
extern void int_eval (void);
|
||||||
|
@ -478,7 +494,6 @@ REG cpu_reg[] = {
|
||||||
{ BRDATA (PCQ, pcq, 16, 16, PCQ_SIZE), REG_RO+REG_CIRC },
|
{ BRDATA (PCQ, pcq, 16, 16, PCQ_SIZE), REG_RO+REG_CIRC },
|
||||||
{ HRDATA (PCQP, pcq_p, 6), REG_HRO },
|
{ HRDATA (PCQP, pcq_p, 6), REG_HRO },
|
||||||
{ HRDATA (WRU, sim_int_char, 8) },
|
{ HRDATA (WRU, sim_int_char, 8) },
|
||||||
{ HRDATA (DBGLOG, cpu_log, 16), REG_HIDDEN },
|
|
||||||
{ HRDATA (BLKIOD, blk_io.dfl, 16), REG_HRO },
|
{ HRDATA (BLKIOD, blk_io.dfl, 16), REG_HRO },
|
||||||
{ HRDATA (BLKIOC, blk_io.cur, 16), REG_HRO },
|
{ HRDATA (BLKIOC, blk_io.cur, 16), REG_HRO },
|
||||||
{ HRDATA (BLKIOE, blk_io.end, 16), REG_HRO },
|
{ HRDATA (BLKIOE, blk_io.end, 16), REG_HRO },
|
||||||
|
@ -500,6 +515,8 @@ MTAB cpu_mod[] = {
|
||||||
{ UNIT_TYPE, UNIT_816E, "8/16E", "816E", &cpu_set_model },
|
{ UNIT_TYPE, UNIT_816E, "8/16E", "816E", &cpu_set_model },
|
||||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "CONSINT",
|
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "CONSINT",
|
||||||
&cpu_set_consint, NULL, NULL },
|
&cpu_set_consint, NULL, NULL },
|
||||||
|
{ MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY",
|
||||||
|
&cpu_set_hist, &cpu_show_hist },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
|
||||||
DEVICE cpu_dev = {
|
DEVICE cpu_dev = {
|
||||||
|
@ -659,6 +676,17 @@ case OP_RXH: /* reg-mem halfword */
|
||||||
default:
|
default:
|
||||||
return SCPE_IERR; }
|
return SCPE_IERR; }
|
||||||
|
|
||||||
|
if (hst_lnt) { /* instruction history? */
|
||||||
|
hst[hst_p].vld = 1;
|
||||||
|
hst[hst_p].pc = oPC;
|
||||||
|
hst[hst_p].ir1 = ir1;
|
||||||
|
hst[hst_p].ir2 = ir2;
|
||||||
|
hst[hst_p].r1 = R[r1];
|
||||||
|
hst[hst_p].ea = ea;
|
||||||
|
hst[hst_p].opnd = opnd;
|
||||||
|
hst_p = hst_p + 1;
|
||||||
|
if (hst_p >= hst_lnt) hst_p = 0; }
|
||||||
|
|
||||||
PC = (PC + 2) & VAMASK; /* increment PC */
|
PC = (PC + 2) & VAMASK; /* increment PC */
|
||||||
switch (op) { /* case on opcode */
|
switch (op) { /* case on opcode */
|
||||||
|
|
||||||
|
@ -1736,3 +1764,66 @@ if ((uptr->flags & (UNIT_716 | UNIT_816 | UNIT_816E)) == 0)
|
||||||
if (PSW & PSW_AIO) SET_INT (v_DS);
|
if (PSW & PSW_AIO) SET_INT (v_DS);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set history */
|
||||||
|
|
||||||
|
t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
uint32 i, lnt;
|
||||||
|
t_stat r;
|
||||||
|
|
||||||
|
if (cptr == NULL) {
|
||||||
|
for (i = 0; i < hst_lnt; i++) hst[i].vld = 0;
|
||||||
|
hst_p = 0;
|
||||||
|
return SCPE_OK; }
|
||||||
|
lnt = (uint32) get_uint (cptr, 10, HIST_MAX, &r);
|
||||||
|
if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG;
|
||||||
|
hst_p = 0;
|
||||||
|
if (hst_lnt) {
|
||||||
|
free (hst);
|
||||||
|
hst_lnt = 0;
|
||||||
|
hst = NULL; }
|
||||||
|
if (lnt) {
|
||||||
|
hst = calloc (sizeof (struct InstHistory), lnt);
|
||||||
|
if (hst == NULL) return SCPE_MEM;
|
||||||
|
hst_lnt = lnt; }
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Show history */
|
||||||
|
|
||||||
|
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
|
{
|
||||||
|
uint32 op, k, di, lnt;
|
||||||
|
char *cptr = (char *) desc;
|
||||||
|
t_value sim_eval[4];
|
||||||
|
t_stat r;
|
||||||
|
struct InstHistory *h;
|
||||||
|
extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
|
||||||
|
UNIT *uptr, int32 sw);
|
||||||
|
|
||||||
|
if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */
|
||||||
|
if (cptr) {
|
||||||
|
lnt = (int32) get_uint (cptr, 10, hst_lnt, &r);
|
||||||
|
if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; }
|
||||||
|
else lnt = hst_lnt;
|
||||||
|
di = hst_p - lnt; /* work forward */
|
||||||
|
if (di < 0) di = di + hst_lnt;
|
||||||
|
fprintf (st, "PC r1 opnd ea IR\n\n");
|
||||||
|
for (k = 0; k < lnt; k++) { /* print specified */
|
||||||
|
h = &hst[(di++) % hst_lnt]; /* entry pointer */
|
||||||
|
if (h->vld) { /* instruction? */
|
||||||
|
fprintf (st, "%04X %04X %04X ", h->pc, h->r1, h->opnd);
|
||||||
|
sim_eval[0] = op = (h->ir1 >> 8) & 0xFF;
|
||||||
|
sim_eval[1] = h->ir1 & 0xFF;
|
||||||
|
sim_eval[2] = (h->ir2 >> 8) & 0xFF;
|
||||||
|
sim_eval[3] = h->ir2 & 0xFF;
|
||||||
|
if (OP_TYPE (op) >= OP_RX) fprintf (st, "%04X ", h->ea);
|
||||||
|
else fprintf (st, " ");
|
||||||
|
if ((fprint_sym (st, h->pc, sim_eval, &cpu_unit, SWMASK ('M'))) > 0)
|
||||||
|
fprintf (st, "(undefined) %04X", h->ir1);
|
||||||
|
fputc ('\n', st); /* end line */
|
||||||
|
} /* end if instruction */
|
||||||
|
} /* end for */
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
cpu Interdata 32b CPU
|
cpu Interdata 32b CPU
|
||||||
|
|
||||||
|
06-Nov-04 RMS Added =n to SHOW HISTORY
|
||||||
25-Jan-04 RMS Revised for device debug support
|
25-Jan-04 RMS Revised for device debug support
|
||||||
31-Dec-03 RMS Fixed bug in cpu_set_hist
|
31-Dec-03 RMS Fixed bug in cpu_set_hist
|
||||||
22-Sep-03 RMS Added additional instruction decode types
|
22-Sep-03 RMS Added additional instruction decode types
|
||||||
|
@ -561,7 +562,7 @@ MTAB cpu_mod[] = {
|
||||||
{ UNIT_TYPE, UNIT_DPFP | UNIT_832, "8/32", "832", NULL },
|
{ UNIT_TYPE, UNIT_DPFP | UNIT_832, "8/32", "832", NULL },
|
||||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "CONSINT",
|
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "CONSINT",
|
||||||
&cpu_set_consint, NULL, NULL },
|
&cpu_set_consint, NULL, NULL },
|
||||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "HISTORY", "HISTORY",
|
{ MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY",
|
||||||
&cpu_set_hist, &cpu_show_hist },
|
&cpu_set_hist, &cpu_show_hist },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
|
||||||
|
@ -2106,16 +2107,23 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)
|
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
{
|
{
|
||||||
uint32 op, k, di;
|
uint32 op, k, di, lnt;
|
||||||
|
char *cptr = (char *) desc;
|
||||||
t_value sim_eval[6];
|
t_value sim_eval[6];
|
||||||
|
t_stat r;
|
||||||
struct InstHistory *h;
|
struct InstHistory *h;
|
||||||
extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
|
extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
|
||||||
UNIT *uptr, int32 sw);
|
UNIT *uptr, int32 sw);
|
||||||
|
|
||||||
if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */
|
if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */
|
||||||
|
if (cptr) {
|
||||||
|
lnt = (int32) get_uint (cptr, 10, hst_lnt, &r);
|
||||||
|
if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; }
|
||||||
|
else lnt = hst_lnt;
|
||||||
|
di = hst_p - lnt; /* work forward */
|
||||||
|
if (di < 0) di = di + hst_lnt;
|
||||||
fprintf (st, "PC r1 operand ea IR\n\n");
|
fprintf (st, "PC r1 operand ea IR\n\n");
|
||||||
di = hst_p; /* work forward */
|
for (k = 0; k < lnt; k++) { /* print specified */
|
||||||
for (k = 0; k < hst_lnt; k++) { /* print specified */
|
|
||||||
h = &hst[(di++) % hst_lnt]; /* entry pointer */
|
h = &hst[(di++) % hst_lnt]; /* entry pointer */
|
||||||
if (h->pc & HIST_PC) { /* instruction? */
|
if (h->pc & HIST_PC) { /* instruction? */
|
||||||
fprintf (st, "%06X %08X %08X ", h->pc & VAMASK32, h->r1, h->opnd);
|
fprintf (st, "%06X %08X %08X ", h->pc & VAMASK32, h->r1, h->opnd);
|
||||||
|
|
|
@ -73,8 +73,8 @@
|
||||||
/* Double precision floating point registers */
|
/* Double precision floating point registers */
|
||||||
|
|
||||||
struct dpr {
|
struct dpr {
|
||||||
unsigned int32 h; /* high 32b */
|
uint32 h; /* high 32b */
|
||||||
unsigned int32 l; /* low 32b */
|
uint32 l; /* low 32b */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct dpr dpr_t;
|
typedef struct dpr dpr_t;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
To: Users
|
To: Users
|
||||||
From: Bob Supnik
|
From: Bob Supnik
|
||||||
Subj: Interdata 16b/32b Simulator Usage
|
Subj: Interdata 16b/32b Simulator Usage
|
||||||
Date: 15-Feb-2004
|
Date: 15-Nov-2004
|
||||||
|
|
||||||
COPYRIGHT NOTICE
|
COPYRIGHT NOTICE
|
||||||
|
|
||||||
|
@ -205,6 +205,17 @@ control registers for the interrupt system.
|
||||||
most recent PC change first
|
most recent PC change first
|
||||||
WRU 8 interrupt character
|
WRU 8 interrupt character
|
||||||
|
|
||||||
|
The CPU can maintain a history of the most recently executed instructions.
|
||||||
|
This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands:
|
||||||
|
|
||||||
|
SET CPU HISTORY clear history buffer
|
||||||
|
SET CPU HISTORY=0 disable history
|
||||||
|
SET CPU HISTORY=n enable history, length = n
|
||||||
|
SHOW CPU HISTORY print CPU history
|
||||||
|
SHOW CPU HISTORY=n print first n entries of CPU history
|
||||||
|
|
||||||
|
The maximum length for the history is 65536 entries.
|
||||||
|
|
||||||
2.2 CPU (32b)
|
2.2 CPU (32b)
|
||||||
|
|
||||||
The CPU options include memory size and CPU type:
|
The CPU options include memory size and CPU type:
|
||||||
|
@ -270,8 +281,9 @@ This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands:
|
||||||
|
|
||||||
SET CPU HISTORY clear history buffer
|
SET CPU HISTORY clear history buffer
|
||||||
SET CPU HISTORY=0 disable history
|
SET CPU HISTORY=0 disable history
|
||||||
SET CPU HISTORY=n enable history, display length = n
|
SET CPU HISTORY=n enable history, length = n
|
||||||
SHOW CPU HISTORY print CPU history
|
SHOW CPU HISTORY print CPU history
|
||||||
|
SHOW CPU HISTORY=n print first n entries of CPU history
|
||||||
|
|
||||||
The maximum length for the history is 65536 entries.
|
The maximum length for the history is 65536 entries.
|
||||||
|
|
||||||
|
@ -547,7 +559,7 @@ write locked.
|
||||||
SET FDn LOCKED set unit n write locked
|
SET FDn LOCKED set unit n write locked
|
||||||
SET FDn WRITEENABLED set unit n write enabled
|
SET FDn WRITEENABLED set unit n write enabled
|
||||||
|
|
||||||
Units can also be set ONLINE or OFFLINE.
|
Units can also be set ENABLED or DISABLED.
|
||||||
|
|
||||||
The floppy disk supports the BOOT command. BOOT FDn copies an autoload
|
The floppy disk supports the BOOT command. BOOT FDn copies an autoload
|
||||||
sequence into memory and starts it running.
|
sequence into memory and starts it running.
|
||||||
|
@ -658,7 +670,7 @@ write locked, and to select the type of drive:
|
||||||
SET DPn 2315 set unit n to 2315 (2.5MB)
|
SET DPn 2315 set unit n to 2315 (2.5MB)
|
||||||
SET DPn 5440 set unit n to 5440 (10MB)
|
SET DPn 5440 set unit n to 5440 (10MB)
|
||||||
|
|
||||||
Units can also be set ONLINE or OFFLINE.
|
Units can also be set ENABLED or DISABLED.
|
||||||
|
|
||||||
The cartridge disk supports the BOOT command. To boot OS16/32, the hex
|
The cartridge disk supports the BOOT command. To boot OS16/32, the hex
|
||||||
form of the operating system file's extension must be placed in locations
|
form of the operating system file's extension must be placed in locations
|
||||||
|
@ -729,7 +741,7 @@ write enabled or write locked, and to select the type of drive:
|
||||||
(300MB formatted)
|
(300MB formatted)
|
||||||
|
|
||||||
Note that the disk bootstraps can ONLY boot the MSM80 and MSM300.
|
Note that the disk bootstraps can ONLY boot the MSM80 and MSM300.
|
||||||
Units can be set ONLINE or OFFLINE.
|
Units can also be set ENABLED or DISABLED.
|
||||||
|
|
||||||
The MSM/IDC controller supports the BOOT command. To boot OS16/32, the hex
|
The MSM/IDC controller supports the BOOT command. To boot OS16/32, the hex
|
||||||
form of the operating system file's extension must be placed in locations
|
form of the operating system file's extension must be placed in locations
|
||||||
|
@ -791,7 +803,7 @@ or write locked.
|
||||||
SET MTn LOCKED set unit n write locked
|
SET MTn LOCKED set unit n write locked
|
||||||
SET MTn WRITEENABLED set unit n write enabled
|
SET MTn WRITEENABLED set unit n write enabled
|
||||||
|
|
||||||
Units can also be set ONLINE or OFFLINE.
|
Units can also be set ENABLED or DISABLED.
|
||||||
|
|
||||||
The magnetic tape supports the BOOT command. BOOT MTn copies an autoload
|
The magnetic tape supports the BOOT command. BOOT MTn copies an autoload
|
||||||
sequence into memory and starts it running.
|
sequence into memory and starts it running.
|
||||||
|
|
|
@ -344,7 +344,7 @@
|
||||||
#define UNIT_UP (1 << UNIT_V_UP)
|
#define UNIT_UP (1 << UNIT_V_UP)
|
||||||
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
|
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
|
||||||
|
|
||||||
unsigned int16 M[MAXMEMSIZE] = { 0 }; /* memory */
|
uint16 M[MAXMEMSIZE] = { 0 }; /* memory */
|
||||||
int32 AC[4] = { 0 }; /* accumulators */
|
int32 AC[4] = { 0 }; /* accumulators */
|
||||||
int32 C = 0; /* carry flag */
|
int32 C = 0; /* carry flag */
|
||||||
int32 saved_PC = 0; /* program counter */
|
int32 saved_PC = 0; /* program counter */
|
||||||
|
@ -375,13 +375,13 @@ struct ndev dev_table[64]; /* dispatch table */
|
||||||
int32 hnext = 0; /* # of current entry */
|
int32 hnext = 0; /* # of current entry */
|
||||||
int32 hwrap = 0; /* 1 if wrapped */
|
int32 hwrap = 0; /* 1 if wrapped */
|
||||||
int32 hmax = HISTMAX; /* Maximum entries b4 wrap */
|
int32 hmax = HISTMAX; /* Maximum entries b4 wrap */
|
||||||
unsigned int16 hpc[HISTMAX];
|
uint16 hpc[HISTMAX];
|
||||||
unsigned int16 hinst[HISTMAX];
|
uint16 hinst[HISTMAX];
|
||||||
unsigned int16 hinst2[HISTMAX];
|
uint16 hinst2[HISTMAX];
|
||||||
unsigned int16 hac0[HISTMAX];
|
uint16 hac0[HISTMAX];
|
||||||
unsigned int16 hac1[HISTMAX];
|
uint16 hac1[HISTMAX];
|
||||||
unsigned int16 hac2[HISTMAX];
|
uint16 hac2[HISTMAX];
|
||||||
unsigned int16 hac3[HISTMAX];
|
uint16 hac3[HISTMAX];
|
||||||
unsigned short hflags[HISTMAX];
|
unsigned short hflags[HISTMAX];
|
||||||
|
|
||||||
/* Flags: 0x01 - carry bit
|
/* Flags: 0x01 - carry bit
|
||||||
|
@ -689,7 +689,7 @@ t_stat sim_instr (void)
|
||||||
{
|
{
|
||||||
extern int32 sim_interval;
|
extern int32 sim_interval;
|
||||||
register int32 PC, IR, i, t, MA, j, k, tac;
|
register int32 PC, IR, i, t, MA, j, k, tac;
|
||||||
register unsigned int32 mddata, uAC0, uAC1, uAC2, uAC3;
|
register uint32 mddata, uAC0, uAC1, uAC2, uAC3;
|
||||||
int16 sAC0, sAC1, sAC2;
|
int16 sAC0, sAC1, sAC2;
|
||||||
int32 sddata, mi1, mi2, fpnum32;
|
int32 sddata, mi1, mi2, fpnum32;
|
||||||
t_int64 fpnum, expon;
|
t_int64 fpnum, expon;
|
||||||
|
@ -1623,9 +1623,9 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */
|
||||||
/* Multiply / Divide */
|
/* Multiply / Divide */
|
||||||
|
|
||||||
if (IR == 0143710) { /* MUL: Unsigned Multiply */
|
if (IR == 0143710) { /* MUL: Unsigned Multiply */
|
||||||
uAC0 = (unsigned int32) AC[0];
|
uAC0 = (uint32) AC[0];
|
||||||
uAC1 = (unsigned int32) AC[1];
|
uAC1 = (uint32) AC[1];
|
||||||
uAC2 = (unsigned int32) AC[2];
|
uAC2 = (uint32) AC[2];
|
||||||
|
|
||||||
mddata = (uAC1 * uAC2) + uAC0;
|
mddata = (uAC1 * uAC2) + uAC0;
|
||||||
AC[0] = (mddata >> 16) & 0177777;
|
AC[0] = (mddata >> 16) & 0177777;
|
||||||
|
@ -1643,9 +1643,9 @@ if ((IR & 0100017) == 0100010) { /* This pattern for all */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (IR == 0153710) { /* DIV: Unsigned Divide */
|
if (IR == 0153710) { /* DIV: Unsigned Divide */
|
||||||
uAC0 = (unsigned int32) AC[0];
|
uAC0 = (uint32) AC[0];
|
||||||
uAC1 = (unsigned int32) AC[1];
|
uAC1 = (uint32) AC[1];
|
||||||
uAC2 = (unsigned int32) AC[2];
|
uAC2 = (uint32) AC[2];
|
||||||
|
|
||||||
if (uAC0 >= uAC2) C = 0200000;
|
if (uAC0 >= uAC2) C = 0200000;
|
||||||
else { C = 0;
|
else { C = 0;
|
||||||
|
@ -5930,7 +5930,6 @@ int32 Dump_History (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
char debmap[4], debion[4];
|
char debmap[4], debion[4];
|
||||||
t_value simeval[20];
|
t_value simeval[20];
|
||||||
int debcar;
|
int debcar;
|
||||||
FILE *Dumpf;
|
|
||||||
int start, end, ctr;
|
int start, end, ctr;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
|
@ -5939,7 +5938,6 @@ int32 Dump_History (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
printf("in DEBUG with bit 0 being 1 to build history.\n");
|
printf("in DEBUG with bit 0 being 1 to build history.\n");
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
Dumpf = fopen("history.log", "w");
|
|
||||||
if (!hwrap) {
|
if (!hwrap) {
|
||||||
start = 0;
|
start = 0;
|
||||||
end = hnext;
|
end = hnext;
|
||||||
|
@ -5957,7 +5955,7 @@ int32 Dump_History (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
strcpy(debmap, " ");
|
strcpy(debmap, " ");
|
||||||
debcar = 0;
|
debcar = 0;
|
||||||
if (hflags[ctr] & 0x80) {
|
if (hflags[ctr] & 0x80) {
|
||||||
fprintf(Dumpf, "--------- Interrupt %o (%o) to %6o ---------\n",
|
fprintf(st, "--------- Interrupt %o (%o) to %6o ---------\n",
|
||||||
hinst[ctr], hac0[ctr], hac1[ctr]);
|
hinst[ctr], hac0[ctr], hac1[ctr]);
|
||||||
} else {
|
} else {
|
||||||
if (hflags[ctr] & 0x01) debcar = 1;
|
if (hflags[ctr] & 0x01) debcar = 1;
|
||||||
|
@ -5966,20 +5964,18 @@ int32 Dump_History (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
if (hflags[ctr] & 0x08) strcpy(debmap, "B");
|
if (hflags[ctr] & 0x08) strcpy(debmap, "B");
|
||||||
if (hflags[ctr] & 0x10) strcpy(debmap, "C");
|
if (hflags[ctr] & 0x10) strcpy(debmap, "C");
|
||||||
if (hflags[ctr] & 0x20) strcpy(debmap, "D");
|
if (hflags[ctr] & 0x20) strcpy(debmap, "D");
|
||||||
fprintf(Dumpf, "%s%s%06o acs: %06o %06o %06o %06o %01o ",
|
fprintf(st, "%s%s%06o acs: %06o %06o %06o %06o %01o ",
|
||||||
debion, debmap, hpc[ctr], hac0[ctr], hac1[ctr], hac2[ctr],
|
debion, debmap, hpc[ctr], hac0[ctr], hac1[ctr], hac2[ctr],
|
||||||
hac3[ctr], debcar);
|
hac3[ctr], debcar);
|
||||||
simeval[0] = hinst[ctr];
|
simeval[0] = hinst[ctr];
|
||||||
simeval[1] = hinst2[ctr];
|
simeval[1] = hinst2[ctr];
|
||||||
fprint_sym (Dumpf, hpc[ctr], simeval, NULL, SWMASK('M'));
|
fprint_sym (st, hpc[ctr], simeval, NULL, SWMASK('M'));
|
||||||
fprintf(Dumpf, "\n");
|
fprintf(st, "\n");
|
||||||
}
|
}
|
||||||
ctr++;
|
ctr++;
|
||||||
if (ctr > hmax)
|
if (ctr > hmax)
|
||||||
ctr = 0;
|
ctr = 0;
|
||||||
}
|
}
|
||||||
fclose(Dumpf);
|
|
||||||
printf("\n%d records dumped to history.log\n", count);
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
To: Users
|
To: Users
|
||||||
From: Bob Supnik
|
From: Bob Supnik
|
||||||
Subj: Nova Simulator Usage
|
Subj: Nova Simulator Usage
|
||||||
Date: 15-Mar-2004
|
Date: 15-Nov-2004
|
||||||
|
|
||||||
COPYRIGHT NOTICE
|
COPYRIGHT NOTICE
|
||||||
|
|
||||||
|
@ -540,7 +540,7 @@ write locked, and to select the type of drive:
|
||||||
SET DPn 6103 set unit n to 6103
|
SET DPn 6103 set unit n to 6103
|
||||||
SET DPn 4231 set unit n to 4231
|
SET DPn 4231 set unit n to 4231
|
||||||
|
|
||||||
Units can also be set ONLINE or OFFLINE. The moving head disk controller
|
Units can also be set ENABLED or DISABLED. The moving head disk controller
|
||||||
supports the BOOT command.
|
supports the BOOT command.
|
||||||
|
|
||||||
All drives have 256 16b words per sector. The other disk parameters are:
|
All drives have 256 16b words per sector. The other disk parameters are:
|
||||||
|
@ -594,7 +594,7 @@ or write locked.
|
||||||
SET MTn LOCKED set unit n write locked
|
SET MTn LOCKED set unit n write locked
|
||||||
SET MTn WRITEENABLED set unit n write enabled
|
SET MTn WRITEENABLED set unit n write enabled
|
||||||
|
|
||||||
Units can also be set ONLINE or OFFLINE. The magnetic tape controller
|
Units can also be set ENABLED or DISABLED. The magnetic tape controller
|
||||||
supports the BOOT command.
|
supports the BOOT command.
|
||||||
|
|
||||||
The magnetic tape controller implements these registers:
|
The magnetic tape controller implements these registers:
|
||||||
|
|
102
PDP1/pdp1_cpu.c
102
PDP1/pdp1_cpu.c
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
cpu PDP-1 central processor
|
cpu PDP-1 central processor
|
||||||
|
|
||||||
|
09-Nov-04 RMS Added instruction history
|
||||||
07-Sep-03 RMS Added additional explanation on I/O simulation
|
07-Sep-03 RMS Added additional explanation on I/O simulation
|
||||||
01-Sep-03 RMS Added address switches for hardware readin
|
01-Sep-03 RMS Added address switches for hardware readin
|
||||||
23-Jul-03 RMS Revised to detect I/O wait hang
|
23-Jul-03 RMS Revised to detect I/O wait hang
|
||||||
|
@ -229,6 +230,18 @@
|
||||||
#define UNIT_MDV (1 << UNIT_V_MDV)
|
#define UNIT_MDV (1 << UNIT_V_MDV)
|
||||||
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
|
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
|
||||||
|
|
||||||
|
#define HIST_PC 0x40000000
|
||||||
|
#define HIST_V_SHF 18
|
||||||
|
#define HIST_MIN 64
|
||||||
|
#define HIST_MAX 65536
|
||||||
|
struct InstHistory {
|
||||||
|
uint32 pc;
|
||||||
|
uint32 ir;
|
||||||
|
uint32 ovac;
|
||||||
|
uint32 pfio;
|
||||||
|
uint32 ea;
|
||||||
|
uint32 opnd; };
|
||||||
|
|
||||||
int32 M[MAXMEMSIZE] = { 0 }; /* memory */
|
int32 M[MAXMEMSIZE] = { 0 }; /* memory */
|
||||||
int32 AC = 0; /* AC */
|
int32 AC = 0; /* AC */
|
||||||
int32 IO = 0; /* IO */
|
int32 IO = 0; /* IO */
|
||||||
|
@ -252,6 +265,9 @@ int32 ind_max = 16; /* nested ind limit */
|
||||||
uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
|
uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
|
||||||
int32 pcq_p = 0; /* PC queue ptr */
|
int32 pcq_p = 0; /* PC queue ptr */
|
||||||
REG *pcq_r = NULL; /* PC queue reg ptr */
|
REG *pcq_r = NULL; /* PC queue reg ptr */
|
||||||
|
int32 hst_p = 0; /* history pointer */
|
||||||
|
int32 hst_lnt = 0; /* history length */
|
||||||
|
struct InstHistory *hst = NULL; /* instruction history */
|
||||||
|
|
||||||
extern UNIT *sim_clock_queue;
|
extern UNIT *sim_clock_queue;
|
||||||
extern int32 sim_int_char;
|
extern int32 sim_int_char;
|
||||||
|
@ -261,6 +277,8 @@ t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
|
||||||
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
|
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
|
||||||
t_stat cpu_reset (DEVICE *dptr);
|
t_stat cpu_reset (DEVICE *dptr);
|
||||||
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
|
|
||||||
extern int32 ptr (int32 inst, int32 dev, int32 dat);
|
extern int32 ptr (int32 inst, int32 dev, int32 dat);
|
||||||
extern int32 ptp (int32 inst, int32 dev, int32 dat);
|
extern int32 ptp (int32 inst, int32 dev, int32 dat);
|
||||||
|
@ -355,6 +373,8 @@ MTAB cpu_mod[] = {
|
||||||
{ UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size },
|
{ UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size },
|
||||||
{ UNIT_MSIZE, 49152, NULL, "48K", &cpu_set_size },
|
{ UNIT_MSIZE, 49152, NULL, "48K", &cpu_set_size },
|
||||||
{ UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size },
|
{ UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size },
|
||||||
|
{ MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY",
|
||||||
|
&cpu_set_hist, &cpu_show_hist },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
|
||||||
DEVICE cpu_dev = {
|
DEVICE cpu_dev = {
|
||||||
|
@ -408,6 +428,13 @@ IR = M[MA]; /* fetch instruction */
|
||||||
PC = INCR_ADDR (PC); /* increment PC */
|
PC = INCR_ADDR (PC); /* increment PC */
|
||||||
xct_count = 0; /* track nested XCT's */
|
xct_count = 0; /* track nested XCT's */
|
||||||
sim_interval = sim_interval - 1;
|
sim_interval = sim_interval - 1;
|
||||||
|
if (hst_lnt) { /* history enabled? */
|
||||||
|
hst_p = (hst_p + 1); /* next entry */
|
||||||
|
if (hst_p >= hst_lnt) hst_p = 0;
|
||||||
|
hst[hst_p].pc = MA | HIST_PC; /* save PC, IR, LAC, MQ */
|
||||||
|
hst[hst_p].ir = IR;
|
||||||
|
hst[hst_p].ovac = (OV << HIST_V_SHF) | AC;
|
||||||
|
hst[hst_p].pfio = (PF << HIST_V_SHF) | IO; }
|
||||||
|
|
||||||
xct_instr: /* label for XCT */
|
xct_instr: /* label for XCT */
|
||||||
if ((IR == (OP_JMP+IA+1)) && ((MA & EPCMASK) == 0) && (sbs & SB_ON)) {
|
if ((IR == (OP_JMP+IA+1)) && ((MA & EPCMASK) == 0) && (sbs & SB_ON)) {
|
||||||
|
@ -430,7 +457,13 @@ if ((op < 032) && (op != 007)) { /* mem ref instr */
|
||||||
if ((t & IA) == 0) break; }
|
if ((t & IA) == 0) break; }
|
||||||
if (i >= ind_max) { /* indirect loop? */
|
if (i >= ind_max) { /* indirect loop? */
|
||||||
reason = STOP_IND;
|
reason = STOP_IND;
|
||||||
break; } } } }
|
break; } /* end if loop */
|
||||||
|
} /* end else !extm */
|
||||||
|
} /* end if indirect */
|
||||||
|
if (hst_p) { /* history enabled? */
|
||||||
|
hst[hst_p].ea = MA;
|
||||||
|
hst[hst_p].opnd = M[MA]; }
|
||||||
|
}
|
||||||
|
|
||||||
switch (op) { /* decode IR<0:4> */
|
switch (op) { /* decode IR<0:4> */
|
||||||
|
|
||||||
|
@ -852,3 +885,70 @@ MEMSIZE = val;
|
||||||
for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0;
|
for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set history */
|
||||||
|
|
||||||
|
t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
int32 i, lnt;
|
||||||
|
t_stat r;
|
||||||
|
|
||||||
|
if (cptr == NULL) {
|
||||||
|
for (i = 0; i < hst_lnt; i++) hst[i].pc = 0;
|
||||||
|
hst_p = 0;
|
||||||
|
return SCPE_OK; }
|
||||||
|
lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r);
|
||||||
|
if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG;
|
||||||
|
hst_p = 0;
|
||||||
|
if (hst_lnt) {
|
||||||
|
free (hst);
|
||||||
|
hst_lnt = 0;
|
||||||
|
hst = NULL; }
|
||||||
|
if (lnt) {
|
||||||
|
hst = calloc (sizeof (struct InstHistory), lnt);
|
||||||
|
if (hst == NULL) return SCPE_MEM;
|
||||||
|
hst_lnt = lnt; }
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Show history */
|
||||||
|
|
||||||
|
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
|
{
|
||||||
|
int32 ov, pf, op, k, di, lnt;
|
||||||
|
char *cptr = (char *) desc;
|
||||||
|
t_stat r;
|
||||||
|
t_value sim_eval;
|
||||||
|
struct InstHistory *h;
|
||||||
|
extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
|
||||||
|
UNIT *uptr, int32 sw);
|
||||||
|
|
||||||
|
if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */
|
||||||
|
if (cptr) {
|
||||||
|
lnt = (int32) get_uint (cptr, 10, hst_lnt, &r);
|
||||||
|
if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; }
|
||||||
|
else lnt = hst_lnt;
|
||||||
|
di = hst_p - lnt; /* work forward */
|
||||||
|
if (di < 0) di = di + hst_lnt;
|
||||||
|
fprintf (st, "PC OV AC IO PF EA IR\n\n");
|
||||||
|
for (k = 0; k < lnt; k++) { /* print specified */
|
||||||
|
h = &hst[(++di) % hst_lnt]; /* entry pointer */
|
||||||
|
if (h->pc & HIST_PC) { /* instruction? */
|
||||||
|
ov = (h->ovac >> HIST_V_SHF) & 1; /* overflow */
|
||||||
|
pf = (h->pfio >> HIST_V_SHF) & 077; /* prog flags */
|
||||||
|
op = ((h->ir >> 13) & 037); /* get opcode */
|
||||||
|
fprintf (st, "%06o %o %06o %06o %02o ",
|
||||||
|
h->pc & AMASK, ov, h->ovac & DMASK, h->pfio & DMASK, pf);
|
||||||
|
if ((op < 032) && (op != 007)) /* mem ref instr */
|
||||||
|
fprintf (st, "%06o ", h->ea);
|
||||||
|
else fprintf (st, " ");
|
||||||
|
sim_eval = h->ir;
|
||||||
|
if ((fprint_sym (st, h->pc & AMASK, &sim_eval, &cpu_unit, SWMASK ('M'))) > 0)
|
||||||
|
fprintf (st, "(undefined) %06o", h->ir);
|
||||||
|
else if ((op < 032) && (op != 007)) /* mem ref instr */
|
||||||
|
fprintf (st, " [%06o]", h->opnd);
|
||||||
|
fputc ('\n', st); /* end line */
|
||||||
|
} /* end else instruction */
|
||||||
|
} /* end for */
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
To: Users
|
To: Users
|
||||||
From: Bob Supnik
|
From: Bob Supnik
|
||||||
Subj: PDP-1 Simulator Usage
|
Subj: PDP-1 Simulator Usage
|
||||||
Date: 15-Feb-2004
|
Date: 15-Nov-2004
|
||||||
|
|
||||||
COPYRIGHT NOTICE
|
COPYRIGHT NOTICE
|
||||||
|
|
||||||
|
@ -150,6 +150,17 @@ control registers for the interrupt system.
|
||||||
IND_MAX 8 maximum nested indirect addresses
|
IND_MAX 8 maximum nested indirect addresses
|
||||||
WRU 8 interrupt character
|
WRU 8 interrupt character
|
||||||
|
|
||||||
|
The CPU can maintain a history of the most recently executed instructions.
|
||||||
|
This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands:
|
||||||
|
|
||||||
|
SET CPU HISTORY clear history buffer
|
||||||
|
SET CPU HISTORY=0 disable history
|
||||||
|
SET CPU HISTORY=n enable history, length = n
|
||||||
|
SHOW CPU HISTORY print CPU history
|
||||||
|
SHOW CPU HISTORY=n print first n entries of CPU history
|
||||||
|
|
||||||
|
The maximum length for the history is 65536 entries.
|
||||||
|
|
||||||
2.2 Programmed I/O Devices
|
2.2 Programmed I/O Devices
|
||||||
|
|
||||||
2.2.1 Paper Tape Reader (PTR)
|
2.2.1 Paper Tape Reader (PTR)
|
||||||
|
@ -280,7 +291,7 @@ locked.
|
||||||
SET DTn WRITEENABLED set unit n write enabled
|
SET DTn WRITEENABLED set unit n write enabled
|
||||||
SET DTn LOCKED set unit n write locked
|
SET DTn LOCKED set unit n write locked
|
||||||
|
|
||||||
Units can also be set ONLINE or OFFLINE.
|
Units can also be set ENABLED or DISABLED.
|
||||||
|
|
||||||
The DECtape controller can be disabled and enabled with the SET DT DISABLED
|
The DECtape controller can be disabled and enabled with the SET DT DISABLED
|
||||||
and SET DT ENABLED commands, respectively.
|
and SET DT ENABLED commands, respectively.
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
cpu KS10 central processor
|
cpu KS10 central processor
|
||||||
|
|
||||||
|
10-Nov-04 RMS Added instruction history
|
||||||
08-Oct-02 RMS Revised to build dib_tab dynamically
|
08-Oct-02 RMS Revised to build dib_tab dynamically
|
||||||
Added SHOW IOSPACE
|
Added SHOW IOSPACE
|
||||||
30-Dec-01 RMS Added old PC queue
|
30-Dec-01 RMS Added old PC queue
|
||||||
|
@ -136,6 +137,15 @@
|
||||||
#define UNIT_V_MSIZE (UNIT_V_T20V41 + 1) /* dummy mask */
|
#define UNIT_V_MSIZE (UNIT_V_T20V41 + 1) /* dummy mask */
|
||||||
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
|
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
|
||||||
|
|
||||||
|
#define HIST_PC 0x40000000
|
||||||
|
#define HIST_MIN 64
|
||||||
|
#define HIST_MAX 65536
|
||||||
|
struct InstHistory {
|
||||||
|
a10 pc;
|
||||||
|
a10 ea;
|
||||||
|
d10 ir;
|
||||||
|
d10 ac; };
|
||||||
|
|
||||||
d10 *M = NULL; /* memory */
|
d10 *M = NULL; /* memory */
|
||||||
d10 acs[AC_NBLK * AC_NUM] = { 0 }; /* AC blocks */
|
d10 acs[AC_NBLK * AC_NUM] = { 0 }; /* AC blocks */
|
||||||
d10 *ac_cur, *ac_prv; /* AC cur, prv (dyn) */
|
d10 *ac_cur, *ac_prv; /* AC cur, prv (dyn) */
|
||||||
|
@ -178,6 +188,9 @@ a10 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
|
||||||
int32 pcq_p = 0; /* PC queue ptr */
|
int32 pcq_p = 0; /* PC queue ptr */
|
||||||
REG *pcq_r = NULL; /* PC queue reg ptr */
|
REG *pcq_r = NULL; /* PC queue reg ptr */
|
||||||
jmp_buf save_env;
|
jmp_buf save_env;
|
||||||
|
int32 hst_p = 0; /* history pointer */
|
||||||
|
int32 hst_lnt = 0; /* history length */
|
||||||
|
struct InstHistory *hst = NULL; /* instruction history */
|
||||||
|
|
||||||
extern int32 sim_int_char;
|
extern int32 sim_int_char;
|
||||||
extern int32 sim_interval;
|
extern int32 sim_interval;
|
||||||
|
@ -189,6 +202,8 @@ extern UNIT tim_unit;
|
||||||
t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
|
t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
|
||||||
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
|
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
|
||||||
t_stat cpu_reset (DEVICE *dptr);
|
t_stat cpu_reset (DEVICE *dptr);
|
||||||
|
t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
d10 adjsp (d10 val, a10 ea);
|
d10 adjsp (d10 val, a10 ea);
|
||||||
void ibp (a10 ea, int32 pflgs);
|
void ibp (a10 ea, int32 pflgs);
|
||||||
d10 ldb (a10 ea, int32 pflgs);
|
d10 ldb (a10 ea, int32 pflgs);
|
||||||
|
@ -375,6 +390,8 @@ MTAB cpu_mod[] = {
|
||||||
{ UNIT_ITS+UNIT_T20V41, UNIT_ITS, "ITS microcode", "ITS", NULL },
|
{ UNIT_ITS+UNIT_T20V41, UNIT_ITS, "ITS microcode", "ITS", NULL },
|
||||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "IOSPACE", NULL,
|
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "IOSPACE", NULL,
|
||||||
NULL, &show_iospace },
|
NULL, &show_iospace },
|
||||||
|
{ MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY",
|
||||||
|
&cpu_set_hist, &cpu_show_hist },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
|
||||||
DEVICE cpu_dev = {
|
DEVICE cpu_dev = {
|
||||||
|
@ -743,6 +760,13 @@ for (indrct = inst, i = 0; i < ind_max; i++) { /* calc eff addr */
|
||||||
else break; }
|
else break; }
|
||||||
if (i >= ind_max)
|
if (i >= ind_max)
|
||||||
ABORT (STOP_IND); /* too many ind? stop */
|
ABORT (STOP_IND); /* too many ind? stop */
|
||||||
|
if (hst_lnt) { /* history enabled? */
|
||||||
|
hst_p = (hst_p + 1); /* next entry */
|
||||||
|
if (hst_p >= hst_lnt) hst_p = 0;
|
||||||
|
hst[hst_p].pc = pager_PC | HIST_PC;
|
||||||
|
hst[hst_p].ea = ea;
|
||||||
|
hst[hst_p].ir = inst;
|
||||||
|
hst[hst_p].ac = AC(ac); }
|
||||||
switch (op) { /* case on opcode */
|
switch (op) { /* case on opcode */
|
||||||
|
|
||||||
/* UUO's (0000 - 0077) - checked against KS10 ucode */
|
/* UUO's (0000 - 0077) - checked against KS10 ucode */
|
||||||
|
@ -2100,3 +2124,63 @@ if (rptr == NULL) return;
|
||||||
for (i = 0; i < AC_NUM; i++, rptr++) rptr->loc = (void *) (acbase + i);
|
for (i = 0; i < AC_NUM; i++, rptr++) rptr->loc = (void *) (acbase + i);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set history */
|
||||||
|
|
||||||
|
t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
int32 i, lnt;
|
||||||
|
t_stat r;
|
||||||
|
|
||||||
|
if (cptr == NULL) {
|
||||||
|
for (i = 0; i < hst_lnt; i++) hst[i].pc = 0;
|
||||||
|
hst_p = 0;
|
||||||
|
return SCPE_OK; }
|
||||||
|
lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r);
|
||||||
|
if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG;
|
||||||
|
hst_p = 0;
|
||||||
|
if (hst_lnt) {
|
||||||
|
free (hst);
|
||||||
|
hst_lnt = 0;
|
||||||
|
hst = NULL; }
|
||||||
|
if (lnt) {
|
||||||
|
hst = calloc (sizeof (struct InstHistory), lnt);
|
||||||
|
if (hst == NULL) return SCPE_MEM;
|
||||||
|
hst_lnt = lnt; }
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Show history */
|
||||||
|
|
||||||
|
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
|
{
|
||||||
|
int32 k, di, lnt;
|
||||||
|
char *cptr = (char *) desc;
|
||||||
|
t_stat r;
|
||||||
|
t_value sim_eval;
|
||||||
|
struct InstHistory *h;
|
||||||
|
extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
|
||||||
|
UNIT *uptr, int32 sw);
|
||||||
|
|
||||||
|
if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */
|
||||||
|
if (cptr) {
|
||||||
|
lnt = (int32) get_uint (cptr, 10, hst_lnt, &r);
|
||||||
|
if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; }
|
||||||
|
else lnt = hst_lnt;
|
||||||
|
di = hst_p - lnt; /* work forward */
|
||||||
|
if (di < 0) di = di + hst_lnt;
|
||||||
|
fprintf (st, "PC AC EA IR\n\n");
|
||||||
|
for (k = 0; k < lnt; k++) { /* print specified */
|
||||||
|
h = &hst[(++di) % hst_lnt]; /* entry pointer */
|
||||||
|
if (h->pc & HIST_PC) { /* instruction? */
|
||||||
|
fprintf (st, "%06o ", h->pc & AMASK);
|
||||||
|
fprintf (st, "%012o ", h->ac);
|
||||||
|
fprintf (st, "%06o ", h->ea);
|
||||||
|
sim_eval = h->ir;
|
||||||
|
if ((fprint_sym (st, h->pc & AMASK, &sim_eval, &cpu_unit, SWMASK ('M'))) > 0)
|
||||||
|
fprintf (st, "(undefined) %012o", h->ir);
|
||||||
|
fputc ('\n', st); /* end line */
|
||||||
|
} /* end else instruction */
|
||||||
|
} /* end for */
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
|
@ -619,9 +619,6 @@ typedef struct pdp_dib DIB;
|
||||||
|
|
||||||
#define UNIBUS TRUE /* 18b only */
|
#define UNIBUS TRUE /* 18b only */
|
||||||
|
|
||||||
#define FST 0 /* Unibus 1 */
|
|
||||||
#define MAP 1 /* Unibus 3 */
|
|
||||||
|
|
||||||
#define DEV_RDX 8 /* default device radix */
|
#define DEV_RDX 8 /* default device radix */
|
||||||
|
|
||||||
/* I/O page layout */
|
/* I/O page layout */
|
||||||
|
@ -739,10 +736,11 @@ typedef struct pdp_dib DIB;
|
||||||
|
|
||||||
/* Function prototypes */
|
/* Function prototypes */
|
||||||
|
|
||||||
int32 Map_ReadB (uint32 ba, int32 bc, uint8 *buf, t_bool ub);
|
int32 Map_ReadB (uint32 ba, int32 bc, uint8 *buf);
|
||||||
int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf, t_bool ub);
|
int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf);
|
||||||
int32 Map_WriteB (uint32 ba, int32 bc, uint8 *buf, t_bool ub);
|
int32 Map_WriteB (uint32 ba, int32 bc, uint8 *buf);
|
||||||
int32 Map_WriteW (uint32 ba, int32 bc, uint16 *buf, t_bool ub);
|
int32 Map_WriteW (uint32 ba, int32 bc, uint16 *buf);
|
||||||
|
|
||||||
t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
t_stat set_addr_flt (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat set_addr_flt (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc);
|
t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
To: Users
|
To: Users
|
||||||
From: Bob Supnik
|
From: Bob Supnik
|
||||||
Subj: PDP-10 Simulator Usage
|
Subj: PDP-10 Simulator Usage
|
||||||
Date: 15-Jun-2004
|
Date: 15-Nov-2004
|
||||||
|
|
||||||
COPYRIGHT NOTICE
|
COPYRIGHT NOTICE
|
||||||
|
|
||||||
|
@ -174,6 +174,17 @@ control registers for the interrupt system.
|
||||||
WRU 8 interrupt character
|
WRU 8 interrupt character
|
||||||
REG[0:127] 36 fast memory blocks
|
REG[0:127] 36 fast memory blocks
|
||||||
|
|
||||||
|
The CPU can maintain a history of the most recently executed instructions.
|
||||||
|
This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands:
|
||||||
|
|
||||||
|
SET CPU HISTORY clear history buffer
|
||||||
|
SET CPU HISTORY=0 disable history
|
||||||
|
SET CPU HISTORY=n enable history, length = n
|
||||||
|
SHOW CPU HISTORY print CPU history
|
||||||
|
SHOW CPU HISTORY=n print first n entries of CPU history
|
||||||
|
|
||||||
|
The maximum length for the history is 65536 entries.
|
||||||
|
|
||||||
2.2 Pager
|
2.2 Pager
|
||||||
|
|
||||||
The pager contains the page maps for executive and user mode. The
|
The pager contains the page maps for executive and user mode. The
|
||||||
|
@ -417,7 +428,7 @@ to set the drive type to one of six disk types, or autosize:
|
||||||
The type options can be used only when a unit is not attached to a file.
|
The type options can be used only when a unit is not attached to a file.
|
||||||
Note that TOPS-10 V7.03 supported only the RP06 and RM03; V7.04 added
|
Note that TOPS-10 V7.03 supported only the RP06 and RM03; V7.04 added
|
||||||
support for the RP07. TOPS-20 V4.1 also supported only the RP06 and
|
support for the RP07. TOPS-20 V4.1 also supported only the RP06 and
|
||||||
RM03. Units can be set ONLINE or OFFLINE.
|
RM03. Units can be set ENABLED or DISABLED.
|
||||||
|
|
||||||
The RP controller implements these registers:
|
The RP controller implements these registers:
|
||||||
|
|
||||||
|
@ -467,7 +478,7 @@ the ability to make units write enabled or locked.
|
||||||
SET TUn LOCKED set unit n write locked
|
SET TUn LOCKED set unit n write locked
|
||||||
SET TUn WRITEENABLED set unit n write enabled
|
SET TUn WRITEENABLED set unit n write enabled
|
||||||
|
|
||||||
Units can also be set ONLINE or OFFLINE.
|
Units can also be set ENABLED or DISABLED.
|
||||||
|
|
||||||
The magnetic tape controller implements these registers:
|
The magnetic tape controller implements these registers:
|
||||||
|
|
||||||
|
|
|
@ -394,7 +394,7 @@ for (i = 0; dibp = dib_tab[i]; i++ ) {
|
||||||
UBNXM_FAIL (pa, mode);
|
UBNXM_FAIL (pa, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mapped read and write routines - used by word-oriented Unibus devices */
|
/* Mapped read and write routines - used by standard Unibus devices on Unibus 1 */
|
||||||
|
|
||||||
a10 Map_Addr10 (a10 ba, int32 ub)
|
a10 Map_Addr10 (a10 ba, int32 ub)
|
||||||
{
|
{
|
||||||
|
@ -407,23 +407,23 @@ pa10 = (ubmap[ub][vpn] + PAG_GETOFF (ba >> 2)) & PAMASK;
|
||||||
return pa10;
|
return pa10;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 Map_ReadB (uint32 ba, int32 bc, uint8 *buf, t_bool ub)
|
int32 Map_ReadB (uint32 ba, int32 bc, uint8 *buf)
|
||||||
{
|
{
|
||||||
uint32 lim;
|
uint32 lim;
|
||||||
a10 pa10;
|
a10 pa10;
|
||||||
|
|
||||||
lim = ba + bc;
|
lim = ba + bc;
|
||||||
for ( ; ba < lim; ba++) { /* by bytes */
|
for ( ; ba < lim; ba++) { /* by bytes */
|
||||||
pa10 = Map_Addr10 (ba, ub); /* map addr */
|
pa10 = Map_Addr10 (ba, 1); /* map addr */
|
||||||
if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */
|
if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */
|
||||||
ubcs[ub] = ubcs[ub] | UBCS_TMO; /* UBA times out */
|
ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA times out */
|
||||||
return (lim - ba); } /* return bc */
|
return (lim - ba); } /* return bc */
|
||||||
*buf++ = (uint8) ((M[pa10] >> ubashf[ba & 3]) & 0377);
|
*buf++ = (uint8) ((M[pa10] >> ubashf[ba & 3]) & 0377);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf, t_bool ub)
|
int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf)
|
||||||
{
|
{
|
||||||
uint32 lim;
|
uint32 lim;
|
||||||
a10 pa10;
|
a10 pa10;
|
||||||
|
@ -431,16 +431,16 @@ a10 pa10;
|
||||||
ba = ba & ~01; /* align start */
|
ba = ba & ~01; /* align start */
|
||||||
lim = ba + (bc & ~01);
|
lim = ba + (bc & ~01);
|
||||||
for ( ; ba < lim; ba = ba + 2) { /* by words */
|
for ( ; ba < lim; ba = ba + 2) { /* by words */
|
||||||
pa10 = Map_Addr10 (ba, ub); /* map addr */
|
pa10 = Map_Addr10 (ba, 1); /* map addr */
|
||||||
if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */
|
if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */
|
||||||
ubcs[ub] = ubcs[ub] | UBCS_TMO; /* UBA times out */
|
ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA times out */
|
||||||
return (lim - ba); } /* return bc */
|
return (lim - ba); } /* return bc */
|
||||||
*buf++ = (uint16) ((M[pa10] >> ((ba & 2)? 0: 18)) & 0177777);
|
*buf++ = (uint16) ((M[pa10] >> ((ba & 2)? 0: 18)) & 0177777);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 Map_WriteB (uint32 ba, int32 bc, uint8 *buf, t_bool ub)
|
int32 Map_WriteB (uint32 ba, int32 bc, uint8 *buf)
|
||||||
{
|
{
|
||||||
uint32 lim;
|
uint32 lim;
|
||||||
a10 pa10;
|
a10 pa10;
|
||||||
|
@ -448,16 +448,16 @@ static d10 mask = 0377;
|
||||||
|
|
||||||
lim = ba + bc;
|
lim = ba + bc;
|
||||||
for ( ; ba < lim; ba++) { /* by bytes */
|
for ( ; ba < lim; ba++) { /* by bytes */
|
||||||
pa10 = Map_Addr10 (ba, ub); /* map addr */
|
pa10 = Map_Addr10 (ba, 1); /* map addr */
|
||||||
if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */
|
if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */
|
||||||
ubcs[ub] = ubcs[ub] | UBCS_TMO; /* UBA times out */
|
ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA times out */
|
||||||
return (lim - ba); } /* return bc */
|
return (lim - ba); } /* return bc */
|
||||||
M[pa10] = (M[pa10] & ~(mask << ubashf[ba & 3])) |
|
M[pa10] = (M[pa10] & ~(mask << ubashf[ba & 3])) |
|
||||||
(((d10) *buf++) << ubashf[ba & 3]); }
|
(((d10) *buf++) << ubashf[ba & 3]); }
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 Map_WriteW (uint32 ba, int32 bc, uint16 *buf, t_bool ub)
|
int32 Map_WriteW (uint32 ba, int32 bc, uint16 *buf)
|
||||||
{
|
{
|
||||||
uint32 lim;
|
uint32 lim;
|
||||||
a10 pa10;
|
a10 pa10;
|
||||||
|
@ -466,9 +466,9 @@ d10 val;
|
||||||
ba = ba & ~01; /* align start */
|
ba = ba & ~01; /* align start */
|
||||||
lim = ba + (bc & ~01);
|
lim = ba + (bc & ~01);
|
||||||
for ( ; ba < lim; ba++) { /* by bytes */
|
for ( ; ba < lim; ba++) { /* by bytes */
|
||||||
pa10 = Map_Addr10 (ba, ub); /* map addr */
|
pa10 = Map_Addr10 (ba, 1); /* map addr */
|
||||||
if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */
|
if ((pa10 < 0) || MEM_ADDR_NXM (pa10)) { /* inv map or NXM? */
|
||||||
ubcs[ub] = ubcs[ub] | UBCS_TMO; /* UBA times out */
|
ubcs[1] = ubcs[1] | UBCS_TMO; /* UBA times out */
|
||||||
return (lim - ba); } /* return bc */
|
return (lim - ba); } /* return bc */
|
||||||
val = *buf++; /* get data */
|
val = *buf++; /* get data */
|
||||||
if (ba & 2) M[pa10] = (M[pa10] & 0777777600000) | val;
|
if (ba & 2) M[pa10] = (M[pa10] & 0777777600000) | val;
|
||||||
|
|
|
@ -373,7 +373,7 @@ if ((fnc == FNC_PR) && (dvlnt == 0)) {
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
|
|
||||||
for (i = 0, cont = TRUE; (i < tbc) && cont; ba++, i++) {
|
for (i = 0, cont = TRUE; (i < tbc) && cont; ba++, i++) {
|
||||||
if (Map_ReadW (ba, 2, &wd10, MAP)) { /* get word, err? */
|
if (Map_ReadW (ba, 2, &wd10)) { /* get word, err? */
|
||||||
lpcsb = lpcsb | CSB_MTE; /* set NXM error */
|
lpcsb = lpcsb | CSB_MTE; /* set NXM error */
|
||||||
update_lpcs (CSA_ERR); /* set done */
|
update_lpcs (CSA_ERR); /* set done */
|
||||||
break; }
|
break; }
|
||||||
|
|
217
PDP10/pdp10_rp.c
217
PDP10/pdp10_rp.c
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
rp RH/RP/RM moving head disks
|
rp RH/RP/RM moving head disks
|
||||||
|
|
||||||
|
20-Sep-04 RMS Fixed bugs in replicated state, RP vs RM accuracy
|
||||||
04-Jan-04 RMS Changed sim_fsize calling sequence
|
04-Jan-04 RMS Changed sim_fsize calling sequence
|
||||||
23-Jul-03 RMS Fixed bug in read header stub
|
23-Jul-03 RMS Fixed bug in read header stub
|
||||||
25-Apr-03 RMS Revised for extended file support
|
25-Apr-03 RMS Revised for extended file support
|
||||||
|
@ -72,6 +73,8 @@
|
||||||
#define RP_MAXFR 32768 /* max transfer */
|
#define RP_MAXFR 32768 /* max transfer */
|
||||||
#define GET_SECTOR(x,d) ((int) fmod (sim_gtime() / ((double) (x)), \
|
#define GET_SECTOR(x,d) ((int) fmod (sim_gtime() / ((double) (x)), \
|
||||||
((double) drv_tab[d].sect)))
|
((double) drv_tab[d].sect)))
|
||||||
|
#define MBA_RP_CTRL 0 /* RP drive */
|
||||||
|
#define MBA_RM_CTRL 1 /* RM drive */
|
||||||
|
|
||||||
/* Flags in the unit flags word */
|
/* Flags in the unit flags word */
|
||||||
|
|
||||||
|
@ -255,6 +258,8 @@
|
||||||
In theory, each drive can be a different type. The size field in
|
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
|
each unit selects the drive capacity for each drive and thus the
|
||||||
drive type. DISKS MUST BE DECLARED IN ASCENDING SIZE.
|
drive type. DISKS MUST BE DECLARED IN ASCENDING SIZE.
|
||||||
|
|
||||||
|
The RP07, despite its name, uses an RM-style controller.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define RM03_DTYPE 0
|
#define RM03_DTYPE 0
|
||||||
|
@ -300,20 +305,21 @@
|
||||||
#define RP07_SIZE (RP07_SECT * RP07_SURF * RP07_CYL * RP_NUMWD)
|
#define RP07_SIZE (RP07_SECT * RP07_SURF * RP07_CYL * RP_NUMWD)
|
||||||
|
|
||||||
struct drvtyp {
|
struct drvtyp {
|
||||||
int sect; /* sectors */
|
int32 sect; /* sectors */
|
||||||
int surf; /* surfaces */
|
int32 surf; /* surfaces */
|
||||||
int cyl; /* cylinders */
|
int32 cyl; /* cylinders */
|
||||||
int size; /* #blocks */
|
int32 size; /* #blocks */
|
||||||
int devtype; /* device type */
|
int32 devtype; /* device type */
|
||||||
|
int32 ctrl; /* ctrl type */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct drvtyp drv_tab[] = {
|
struct drvtyp drv_tab[] = {
|
||||||
{ RM03_SECT, RM03_SURF, RM03_CYL, RM03_SIZE, RM03_DEV },
|
{ RM03_SECT, RM03_SURF, RM03_CYL, RM03_SIZE, RM03_DEV, MBA_RM_CTRL },
|
||||||
{ RP04_SECT, RP04_SURF, RP04_CYL, RP04_SIZE, RP04_DEV },
|
{ RP04_SECT, RP04_SURF, RP04_CYL, RP04_SIZE, RP04_DEV, MBA_RP_CTRL },
|
||||||
{ RM80_SECT, RM80_SURF, RM80_CYL, RM80_SIZE, RM80_DEV },
|
{ RM80_SECT, RM80_SURF, RM80_CYL, RM80_SIZE, RM80_DEV, MBA_RM_CTRL },
|
||||||
{ RP06_SECT, RP06_SURF, RP06_CYL, RP06_SIZE, RP06_DEV },
|
{ RP06_SECT, RP06_SURF, RP06_CYL, RP06_SIZE, RP06_DEV, MBA_RP_CTRL },
|
||||||
{ RM05_SECT, RM05_SURF, RM05_CYL, RM05_SIZE, RM05_DEV },
|
{ RM05_SECT, RM05_SURF, RM05_CYL, RM05_SIZE, RM05_DEV, MBA_RM_CTRL },
|
||||||
{ RP07_SECT, RP07_SURF, RP07_CYL, RP07_SIZE, RP07_DEV },
|
{ RP07_SECT, RP07_SURF, RP07_CYL, RP07_SIZE, RP07_DEV, MBA_RM_CTRL },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
|
||||||
extern d10 *M; /* memory */
|
extern d10 *M; /* memory */
|
||||||
|
@ -326,18 +332,20 @@ extern UNIT cpu_unit;
|
||||||
int32 rpcs1 = 0; /* control/status 1 */
|
int32 rpcs1 = 0; /* control/status 1 */
|
||||||
int32 rpwc = 0; /* word count */
|
int32 rpwc = 0; /* word count */
|
||||||
int32 rpba = 0; /* bus address */
|
int32 rpba = 0; /* bus address */
|
||||||
int32 rpda = 0; /* track/sector */
|
|
||||||
int32 rpcs2 = 0; /* control/status 2 */
|
int32 rpcs2 = 0; /* control/status 2 */
|
||||||
int32 rpds[RP_NUMDR] = { 0 }; /* drive status */
|
|
||||||
int32 rper1[RP_NUMDR] = { 0 }; /* error status 1 */
|
|
||||||
int32 rpdb = 0; /* data buffer */
|
int32 rpdb = 0; /* data buffer */
|
||||||
int32 rpmr = 0; /* maint register */
|
uint16 rpda[RP_NUMDR] = { 0 }; /* track/sector */
|
||||||
int32 rpof = 0; /* offset */
|
uint16 rpds[RP_NUMDR] = { 0 }; /* drive status */
|
||||||
int32 rpdc = 0; /* cylinder */
|
uint16 rper1[RP_NUMDR] = { 0 }; /* error status 1 */
|
||||||
int32 rper2 = 0; /* error status 2 */
|
uint16 rmhr[RP_NUMDR] = { 0 }; /* holding reg */
|
||||||
int32 rper3 = 0; /* error status 3 */
|
uint16 rpmr[RP_NUMDR] = { 0 }; /* maint reg */
|
||||||
int32 rpec1 = 0; /* ECC correction 1 */
|
uint16 rmmr2[RP_NUMDR] = { 0 }; /* maint reg 2 */
|
||||||
int32 rpec2 = 0; /* ECC correction 2 */
|
uint16 rpof[RP_NUMDR] = { 0 }; /* offset */
|
||||||
|
uint16 rpdc[RP_NUMDR] = { 0 }; /* cylinder */
|
||||||
|
uint16 rper2[RP_NUMDR] = { 0 }; /* error status 2 */
|
||||||
|
uint16 rper3[RP_NUMDR] = { 0 }; /* error status 3 */
|
||||||
|
uint16 rpec1[RP_NUMDR] = { 0 }; /* ECC correction 1 */
|
||||||
|
uint16 rpec2[RP_NUMDR] = { 0 }; /* ECC correction 2 */
|
||||||
int32 rpiff = 0; /* INTR flip/flop */
|
int32 rpiff = 0; /* INTR flip/flop */
|
||||||
int32 rp_stopioe = 1; /* stop on error */
|
int32 rp_stopioe = 1; /* stop on error */
|
||||||
int32 rp_swait = 10; /* seek time */
|
int32 rp_swait = 10; /* seek time */
|
||||||
|
@ -345,6 +353,7 @@ int32 rp_rwait = 10; /* rotate time */
|
||||||
static int32 reg_in_drive[32] = {
|
static int32 reg_in_drive[32] = {
|
||||||
0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1,
|
0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1,
|
||||||
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||||
|
static char *rp_mapnam[MBA_RM_CTRL + 1] = { "RP", "RM" };
|
||||||
|
|
||||||
t_stat rp_rd (int32 *data, int32 PA, int32 access);
|
t_stat rp_rd (int32 *data, int32 PA, int32 access);
|
||||||
t_stat rp_wr (int32 data, int32 PA, int32 access);
|
t_stat rp_wr (int32 data, int32 PA, int32 access);
|
||||||
|
@ -354,6 +363,7 @@ t_stat rp_reset (DEVICE *dptr);
|
||||||
t_stat rp_boot (int32 unitno, DEVICE *dptr);
|
t_stat rp_boot (int32 unitno, DEVICE *dptr);
|
||||||
t_stat rp_attach (UNIT *uptr, char *cptr);
|
t_stat rp_attach (UNIT *uptr, char *cptr);
|
||||||
t_stat rp_detach (UNIT *uptr);
|
t_stat rp_detach (UNIT *uptr);
|
||||||
|
void set_rper (int32 flag, int32 drv);
|
||||||
void update_rpcs (int32 flags, int32 drv);
|
void update_rpcs (int32 flags, int32 drv);
|
||||||
void rp_go (int32 drv, int32 fnc);
|
void rp_go (int32 drv, int32 fnc);
|
||||||
t_stat rp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat rp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
@ -391,18 +401,20 @@ REG rp_reg[] = {
|
||||||
{ ORDATA (RPCS1, rpcs1, 16) },
|
{ ORDATA (RPCS1, rpcs1, 16) },
|
||||||
{ ORDATA (RPWC, rpwc, 16) },
|
{ ORDATA (RPWC, rpwc, 16) },
|
||||||
{ ORDATA (RPBA, rpba, 16) },
|
{ ORDATA (RPBA, rpba, 16) },
|
||||||
{ ORDATA (RPDA, rpda, 16) },
|
|
||||||
{ ORDATA (RPCS2, rpcs2, 16) },
|
{ ORDATA (RPCS2, rpcs2, 16) },
|
||||||
|
{ ORDATA (RPDB, rpdb, 16) },
|
||||||
|
{ BRDATA (RPDA, rpda, 8, 16, RP_NUMDR) },
|
||||||
{ BRDATA (RPDS, rpds, 8, 16, RP_NUMDR) },
|
{ BRDATA (RPDS, rpds, 8, 16, RP_NUMDR) },
|
||||||
{ BRDATA (RPER1, rper1, 8, 16, RP_NUMDR) },
|
{ BRDATA (RPER1, rper1, 8, 16, RP_NUMDR) },
|
||||||
{ ORDATA (RPOF, rpof, 16) },
|
{ BRDATA (RPHR, rmhr, 8, 16, RP_NUMDR) },
|
||||||
{ ORDATA (RPDC, rpdc, 16) },
|
{ BRDATA (RPOF, rpof, 8, 16, RP_NUMDR) },
|
||||||
{ ORDATA (RPER2, rper2, 16) },
|
{ BRDATA (RPDC, rpdc, 8, 16, RP_NUMDR) },
|
||||||
{ ORDATA (RPER3, rper3, 16) },
|
{ BRDATA (RPER2, rper2, 8, 16, RP_NUMDR) },
|
||||||
{ ORDATA (RPEC1, rpec1, 16) },
|
{ BRDATA (RPER3, rper3, 8, 16, RP_NUMDR) },
|
||||||
{ ORDATA (RPEC2, rpec2, 16) },
|
{ BRDATA (RPEC1, rpec1, 8, 16, RP_NUMDR) },
|
||||||
{ ORDATA (RPMR, rpmr, 16) },
|
{ BRDATA (RPEC2, rpec2, 8, 16, RP_NUMDR) },
|
||||||
{ ORDATA (RPDB, rpdb, 16) },
|
{ BRDATA (RMMR, rpmr, 8, 16, RP_NUMDR) },
|
||||||
|
{ BRDATA (RMMR2, rmmr2, 8, 16, RP_NUMDR) },
|
||||||
{ FLDATA (IFF, rpiff, 0) },
|
{ FLDATA (IFF, rpiff, 0) },
|
||||||
{ FLDATA (INT, int_req, INT_V_RP) },
|
{ FLDATA (INT, int_req, INT_V_RP) },
|
||||||
{ FLDATA (SC, rpcs1, CSR_V_ERR) },
|
{ FLDATA (SC, rpcs1, CSR_V_ERR) },
|
||||||
|
@ -497,7 +509,7 @@ case 002: /* RPBA */
|
||||||
*data = rpba = rpba & ~BA_MBZ;
|
*data = rpba = rpba & ~BA_MBZ;
|
||||||
break;
|
break;
|
||||||
case 003: /* RPDA */
|
case 003: /* RPDA */
|
||||||
*data = rpda = rpda & ~DA_MBZ;
|
*data = rpda[drv] = rpda[drv] & ~DA_MBZ;
|
||||||
break;
|
break;
|
||||||
case 004: /* RPCS2 */
|
case 004: /* RPCS2 */
|
||||||
*data = rpcs2 = (rpcs2 & ~CS2_MBZ) | CS2_IR | CS2_OR;
|
*data = rpcs2 = (rpcs2 & ~CS2_MBZ) | CS2_IR | CS2_OR;
|
||||||
|
@ -520,7 +532,7 @@ case 011: /* RPDB */
|
||||||
*data = rpdb;
|
*data = rpdb;
|
||||||
break;
|
break;
|
||||||
case 012: /* RPMR */
|
case 012: /* RPMR */
|
||||||
*data = rpmr;
|
*data = rpmr[drv];
|
||||||
break;
|
break;
|
||||||
case 013: /* RPDT */
|
case 013: /* RPDT */
|
||||||
*data = drv_tab[dtype].devtype;
|
*data = drv_tab[dtype].devtype;
|
||||||
|
@ -529,28 +541,34 @@ case 014: /* RPSN */
|
||||||
*data = 020 | (drv + 1);
|
*data = 020 | (drv + 1);
|
||||||
break;
|
break;
|
||||||
case 015: /* RPOF */
|
case 015: /* RPOF */
|
||||||
*data = rpof = rpof & ~OF_MBZ;
|
*data = rpof[drv] = rpof[drv] & ~OF_MBZ;
|
||||||
break;
|
break;
|
||||||
case 016: /* RPDC */
|
case 016: /* RPDC */
|
||||||
*data = rpdc = rpdc & ~DC_MBZ;
|
*data = rpdc[drv] = rpdc[drv] & ~DC_MBZ;
|
||||||
break;
|
break;
|
||||||
case 017: /* RPCC, RMHR */
|
case 017: /* RPCC, RMHR */
|
||||||
|
if (drv_tab[dtype].ctrl == MBA_RP_CTRL) /* RP is CC */
|
||||||
*data = rp_unit[drv].CYL;
|
*data = rp_unit[drv].CYL;
|
||||||
|
else *data = rmhr[drv] ^ 0177777; /* RM is HR */
|
||||||
break;
|
break;
|
||||||
case 020: /* RPER2, RMMR2 */
|
case 020: /* RPER2, RMMR2 */
|
||||||
*data = rper2;
|
if (drv_tab[dtype].ctrl == MBA_RP_CTRL) /* RP is ER2 */
|
||||||
|
*data = rper2[drv];
|
||||||
|
else *data = rmmr2[drv]; /* RM is MR2 */
|
||||||
break;
|
break;
|
||||||
case 021: /* RPER3, RMER2 */
|
case 021: /* RPER3, RMER2 */
|
||||||
*data = rper3;
|
if (drv_tab[dtype].ctrl == MBA_RP_CTRL) /* RP is ER3 */
|
||||||
|
*data = rper3[drv];
|
||||||
|
else *data = rper2[drv]; /* RM is ER2 */
|
||||||
break;
|
break;
|
||||||
case 022: /* RPEC1 */
|
case 022: /* RPEC1 */
|
||||||
*data = rpec1;
|
*data = rpec1[drv];
|
||||||
break;
|
break;
|
||||||
case 023: /* RPEC2 */
|
case 023: /* RPEC2 */
|
||||||
*data = rpec2;
|
*data = rpec2[drv];
|
||||||
break;
|
break;
|
||||||
default: /* all others */
|
default: /* all others */
|
||||||
rper1[drv] = rper1[drv] | ER1_ILR;
|
set_rper (ER1_ILR, drv);
|
||||||
update_rpcs (0, drv);
|
update_rpcs (0, drv);
|
||||||
break; }
|
break; }
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -558,11 +576,12 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat rp_wr (int32 data, int32 PA, int32 access)
|
t_stat rp_wr (int32 data, int32 PA, int32 access)
|
||||||
{
|
{
|
||||||
int32 cs1f, drv, i, j;
|
int32 cs1f, drv, dtype, i, j;
|
||||||
UNIT *uptr;
|
UNIT *uptr;
|
||||||
|
|
||||||
cs1f = 0; /* no int on cs1 upd */
|
cs1f = 0; /* no int on cs1 upd */
|
||||||
drv = GET_UNIT (rpcs2); /* get current unit */
|
drv = GET_UNIT (rpcs2); /* get current unit */
|
||||||
|
dtype = GET_DTYPE (rp_unit[drv].flags); /* get drive type */
|
||||||
uptr = rp_dev.units + drv; /* get unit */
|
uptr = rp_dev.units + drv; /* get unit */
|
||||||
j = (PA >> 1) & 037; /* get reg offset */
|
j = (PA >> 1) & 037; /* get reg offset */
|
||||||
if (reg_in_drive[j] && (rp_unit[drv].flags & UNIT_DIS)) { /* nx disk */
|
if (reg_in_drive[j] && (rp_unit[drv].flags & UNIT_DIS)) { /* nx disk */
|
||||||
|
@ -570,9 +589,10 @@ if (reg_in_drive[j] && (rp_unit[drv].flags & UNIT_DIS)) { /* nx disk */
|
||||||
update_rpcs (CS1_SC, drv); /* request intr */
|
update_rpcs (CS1_SC, drv); /* request intr */
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
if (reg_in_drive[j] && sim_is_active (&rp_unit[drv])) { /* unit busy? */
|
if (reg_in_drive[j] && sim_is_active (&rp_unit[drv])) { /* unit busy? */
|
||||||
rper1[drv] = rper1[drv] | ER1_RMR; /* won't write */
|
set_rper (ER1_RMR, drv); /* won't write */
|
||||||
update_rpcs (0, drv);
|
update_rpcs (0, drv);
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
|
rmhr[drv] = data;
|
||||||
|
|
||||||
switch (j) { /* decode PA<5:1> */
|
switch (j) { /* decode PA<5:1> */
|
||||||
case 000: /* RPCS1 */
|
case 000: /* RPCS1 */
|
||||||
|
@ -591,7 +611,7 @@ case 000: /* RPCS1 */
|
||||||
rpcs2 = rpcs2 | CS2_NED; /* set error flag */
|
rpcs2 = rpcs2 | CS2_NED; /* set error flag */
|
||||||
cs1f = CS1_SC; } /* req interrupt */
|
cs1f = CS1_SC; } /* req interrupt */
|
||||||
else if (sim_is_active (uptr))
|
else if (sim_is_active (uptr))
|
||||||
rper1[drv] = rper1[drv] | ER1_RMR; /* won't write */
|
set_rper (ER1_RMR, drv); /* won't write */
|
||||||
else if (data & CS1_GO) { /* start op */
|
else if (data & CS1_GO) { /* start op */
|
||||||
uptr->FUNC = GET_FNC (data); /* set func */
|
uptr->FUNC = GET_FNC (data); /* set func */
|
||||||
if ((uptr->FUNC >= FNC_XFER) && /* data xfer and */
|
if ((uptr->FUNC >= FNC_XFER) && /* data xfer and */
|
||||||
|
@ -610,9 +630,8 @@ case 002: /* RPBA */
|
||||||
rpba = data & ~BA_MBZ;
|
rpba = data & ~BA_MBZ;
|
||||||
break;
|
break;
|
||||||
case 003: /* RPDA */
|
case 003: /* RPDA */
|
||||||
if (access == WRITEB) data = (PA & 1)?
|
if ((access == WRITEB) && (PA & 1)) data = data << 8;
|
||||||
(rpda & 0377) | (data << 8): (rpda & ~0377) | data;
|
rpda[drv] = data & ~DA_MBZ;
|
||||||
rpda = data & ~DA_MBZ;
|
|
||||||
break;
|
break;
|
||||||
case 004: /* RPCS2 */
|
case 004: /* RPCS2 */
|
||||||
if ((access == WRITEB) && (PA & 1)) data = data << 8;
|
if ((access == WRITEB) && (PA & 1)) data = data << 8;
|
||||||
|
@ -626,8 +645,8 @@ case 004: /* RPCS2 */
|
||||||
drv = GET_UNIT (rpcs2);
|
drv = GET_UNIT (rpcs2);
|
||||||
break;
|
break;
|
||||||
case 006: /* RPER1 */
|
case 006: /* RPER1 */
|
||||||
if (access == WRITEB) break;
|
if ((access == WRITEB) && (PA & 1)) data = data << 8;
|
||||||
rper1[drv] = rper1[drv] & data;
|
rper1[drv] = data;
|
||||||
break;
|
break;
|
||||||
case 007: /* RPAS */
|
case 007: /* RPAS */
|
||||||
if ((access == WRITEB) && (PA & 1)) break;
|
if ((access == WRITEB) && (PA & 1)) break;
|
||||||
|
@ -640,32 +659,28 @@ case 011: /* RPDB */
|
||||||
rpdb = data;
|
rpdb = data;
|
||||||
break;
|
break;
|
||||||
case 012: /* RPMR */
|
case 012: /* RPMR */
|
||||||
if (access == WRITEB) data = (PA & 1)?
|
if ((access == WRITEB) && (PA & 1)) data = data << 8;
|
||||||
(rpmr & 0377) | (data << 8): (rpmr & ~0377) | data;
|
rpmr[drv] = data;
|
||||||
rpmr = data;
|
|
||||||
break;
|
break;
|
||||||
case 015: /* RPOF */
|
case 015: /* RPOF */
|
||||||
if (access == WRITEB) data = (PA & 1)?
|
rpof[drv] = data & ~OF_MBZ;
|
||||||
(rpof & 0377) | (data << 8): (rpof & ~0377) | data;
|
|
||||||
rpof = data & ~OF_MBZ;
|
|
||||||
break;
|
break;
|
||||||
case 016: /* RPDC */
|
case 016: /* RPDC */
|
||||||
if (access == WRITEB) data = (PA & 1)?
|
if ((access == WRITEB) && (PA & 1)) data = data << 8;
|
||||||
(rpdc & 0377) | (data << 8): (rpdc & ~0377) | data;
|
rpdc[drv] = data & ~DC_MBZ;
|
||||||
rpdc = data & ~DC_MBZ;
|
|
||||||
break;
|
break;
|
||||||
case 005: /* RPDS */
|
case 005: /* RPDS */
|
||||||
case 010: /* RPLA */
|
case 010: /* RPLA */
|
||||||
case 013: /* RPDT */
|
case 013: /* RPDT */
|
||||||
case 014: /* RPSN */
|
case 014: /* RPSN */
|
||||||
case 017: /* RPDC, RMHR */
|
case 017: /* RPCC, RMHR */
|
||||||
case 020: /* RPER2, RMMN2 */
|
case 020: /* RPER2, RMMR2 */
|
||||||
case 021: /* RPER3, RMER2 */
|
case 021: /* RPER3, RMER2 */
|
||||||
case 022: /* RPEC1 */
|
case 022: /* RPEC1 */
|
||||||
case 023: /* RPEC2 */
|
case 023: /* RPEC2 */
|
||||||
break; /* read only */
|
break; /* read only */
|
||||||
default: /* all others */
|
default: /* all others */
|
||||||
rper1[drv] = rper1[drv] | ER1_ILR;
|
set_rper (ER1_ILR, drv);
|
||||||
break; } /* end switch */
|
break; } /* end switch */
|
||||||
update_rpcs (cs1f, drv); /* update status */
|
update_rpcs (cs1f, drv); /* update status */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -684,26 +699,25 @@ if (uptr->flags & UNIT_DIS) { /* nx unit? */
|
||||||
update_rpcs (CS1_SC, drv); /* request intr */
|
update_rpcs (CS1_SC, drv); /* request intr */
|
||||||
return; }
|
return; }
|
||||||
if ((fnc != FNC_DCLR) && (rpds[drv] & DS_ERR)) { /* err & ~clear? */
|
if ((fnc != FNC_DCLR) && (rpds[drv] & DS_ERR)) { /* err & ~clear? */
|
||||||
rper1[drv] = rper1[drv] | ER1_ILF; /* not allowed */
|
set_rper (ER1_ILF, drv); /* set err, ATN */
|
||||||
rpds[drv] = rpds[drv] | DS_ATA; /* set attention */
|
|
||||||
update_rpcs (CS1_SC, drv); /* request intr */
|
update_rpcs (CS1_SC, drv); /* request intr */
|
||||||
return; }
|
return; }
|
||||||
dtype = GET_DTYPE (uptr->flags); /* get drive type */
|
dtype = GET_DTYPE (uptr->flags); /* get drive type */
|
||||||
rpds[drv] = rpds[drv] & ~DS_ATA; /* clear attention */
|
rpds[drv] = rpds[drv] & ~DS_ATA; /* clear attention */
|
||||||
dc = rpdc; /* assume seek, sch */
|
dc = rpdc[drv]; /* assume seek, sch */
|
||||||
|
|
||||||
switch (fnc) { /* case on function */
|
switch (fnc) { /* case on function */
|
||||||
case FNC_DCLR: /* drive clear */
|
case FNC_DCLR: /* drive clear */
|
||||||
rpda = 0; /* clear disk addr */
|
rpda[drv] = 0; /* clear disk addr */
|
||||||
rper1[drv] = rper2 = rper3 = 0; /* clear errors */
|
rper1[drv] = rper2[drv] = rper3[drv] = 0; /* clear errors */
|
||||||
case FNC_NOP: /* no operation */
|
case FNC_NOP: /* no operation */
|
||||||
case FNC_RELEASE: /* port release */
|
case FNC_RELEASE: /* port release */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case FNC_PRESET: /* read-in preset */
|
case FNC_PRESET: /* read-in preset */
|
||||||
rpdc = 0; /* clear disk addr */
|
rpdc[drv] = 0; /* clear disk addr */
|
||||||
rpda = 0;
|
rpda[drv] = 0;
|
||||||
rpof = 0; /* clear offset */
|
rpof[drv] = 0; /* clear offset */
|
||||||
case FNC_PACK: /* pack acknowledge */
|
case FNC_PACK: /* pack acknowledge */
|
||||||
rpds[drv] = rpds[drv] | DS_VV; /* set volume valid */
|
rpds[drv] = rpds[drv] | DS_VV; /* set volume valid */
|
||||||
return;
|
return;
|
||||||
|
@ -711,7 +725,7 @@ case FNC_PACK: /* pack acknowledge */
|
||||||
case FNC_OFFSET: /* offset mode */
|
case FNC_OFFSET: /* offset mode */
|
||||||
case FNC_RETURN:
|
case FNC_RETURN:
|
||||||
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
|
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
|
||||||
rper1[drv] = rper1[drv] | ER1_UNS; /* unsafe */
|
set_rper (ER1_UNS, drv); /* unsafe */
|
||||||
break; }
|
break; }
|
||||||
rpds[drv] = (rpds[drv] & ~DS_RDY) | DS_PIP; /* set positioning */
|
rpds[drv] = (rpds[drv] & ~DS_RDY) | DS_PIP; /* set positioning */
|
||||||
sim_activate (uptr, rp_swait); /* time operation */
|
sim_activate (uptr, rp_swait); /* time operation */
|
||||||
|
@ -723,12 +737,12 @@ case FNC_RECAL: /* recalibrate */
|
||||||
case FNC_SEEK: /* seek */
|
case FNC_SEEK: /* seek */
|
||||||
case FNC_SEARCH: /* search */
|
case FNC_SEARCH: /* search */
|
||||||
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
|
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
|
||||||
rper1[drv] = rper1[drv] | ER1_UNS; /* unsafe */
|
set_rper (ER1_UNS, drv); /* unsafe */
|
||||||
break; }
|
break; }
|
||||||
if ((GET_CY (dc) >= drv_tab[dtype].cyl) || /* bad cylinder */
|
if ((GET_CY (dc) >= drv_tab[dtype].cyl) || /* bad cylinder */
|
||||||
(GET_SF (rpda) >= drv_tab[dtype].surf) || /* bad surface */
|
(GET_SF (rpda[drv]) >= drv_tab[dtype].surf) || /* bad surface */
|
||||||
(GET_SC (rpda) >= drv_tab[dtype].sect)) { /* or bad sector? */
|
(GET_SC (rpda[drv]) >= drv_tab[dtype].sect)) { /* or bad sector? */
|
||||||
rper1[drv] = rper1[drv] | ER1_IAE;
|
set_rper (ER1_IAE, drv);
|
||||||
break; }
|
break; }
|
||||||
rpds[drv] = (rpds[drv] & ~DS_RDY) | DS_PIP; /* set positioning */
|
rpds[drv] = (rpds[drv] & ~DS_RDY) | DS_PIP; /* set positioning */
|
||||||
t = abs (dc - uptr->CYL); /* cyl diff */
|
t = abs (dc - uptr->CYL); /* cyl diff */
|
||||||
|
@ -743,14 +757,14 @@ case FNC_WCHK: /* write check */
|
||||||
case FNC_READ: /* read */
|
case FNC_READ: /* read */
|
||||||
case FNC_READH: /* read headers */
|
case FNC_READH: /* read headers */
|
||||||
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
|
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
|
||||||
rper1[drv] = rper1[drv] | ER1_UNS; /* unsafe */
|
set_rper (ER1_UNS, drv); /* unsafe */
|
||||||
break; }
|
break; }
|
||||||
rpcs2 = rpcs2 & ~CS2_ERR; /* clear errors */
|
rpcs2 = rpcs2 & ~CS2_ERR; /* clear errors */
|
||||||
rpcs1 = rpcs1 & ~(CS1_TRE | CS1_MCPE | CS1_DONE);
|
rpcs1 = rpcs1 & ~(CS1_TRE | CS1_MCPE | CS1_DONE);
|
||||||
if ((GET_CY (dc) >= drv_tab[dtype].cyl) || /* bad cylinder */
|
if ((GET_CY (dc) >= drv_tab[dtype].cyl) || /* bad cylinder */
|
||||||
(GET_SF (rpda) >= drv_tab[dtype].surf) || /* bad surface */
|
(GET_SF (rpda[drv]) >= drv_tab[dtype].surf) || /* bad surface */
|
||||||
(GET_SC (rpda) >= drv_tab[dtype].sect)) { /* or bad sector? */
|
(GET_SC (rpda[drv]) >= drv_tab[dtype].sect)) { /* or bad sector? */
|
||||||
rper1[drv] = rper1[drv] | ER1_IAE;
|
set_rper (ER1_IAE, drv);
|
||||||
break; }
|
break; }
|
||||||
rpds[drv] = rpds[drv] & ~DS_RDY; /* clear drive rdy */
|
rpds[drv] = rpds[drv] & ~DS_RDY; /* clear drive rdy */
|
||||||
sim_activate (uptr, rp_rwait + (rp_swait * abs (dc - uptr->CYL)));
|
sim_activate (uptr, rp_rwait + (rp_swait * abs (dc - uptr->CYL)));
|
||||||
|
@ -758,9 +772,8 @@ case FNC_READH: /* read headers */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default: /* all others */
|
default: /* all others */
|
||||||
rper1[drv] = rper1[drv] | ER1_ILF; /* not supported */
|
set_rper (ER1_ILF, drv); /* not supported */
|
||||||
break; }
|
break; }
|
||||||
rpds[drv] = rpds[drv] | DS_ATA; /* error, set attn */
|
|
||||||
update_rpcs (CS1_SC, drv); /* req intr */
|
update_rpcs (CS1_SC, drv); /* req intr */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -815,7 +828,7 @@ case FNC_SEEK: /* seek */
|
||||||
|
|
||||||
case FNC_WRITE: /* write */
|
case FNC_WRITE: /* write */
|
||||||
if (uptr->flags & UNIT_WPRT) { /* write locked? */
|
if (uptr->flags & UNIT_WPRT) { /* write locked? */
|
||||||
rper1[drv] = rper1[drv] | ER1_WLE; /* set drive error */
|
set_rper (ER1_WLE, drv); /* set drive error */
|
||||||
update_rpcs (CS1_DONE | CS1_TRE, drv); /* set done, err */
|
update_rpcs (CS1_DONE | CS1_TRE, drv); /* set done, err */
|
||||||
break; }
|
break; }
|
||||||
case FNC_WCHK: /* write check */
|
case FNC_WCHK: /* write check */
|
||||||
|
@ -823,9 +836,9 @@ case FNC_READ: /* read */
|
||||||
case FNC_READH: /* read headers */
|
case FNC_READH: /* read headers */
|
||||||
ba = GET_UAE (rpcs1) | rpba; /* get byte addr */
|
ba = GET_UAE (rpcs1) | rpba; /* get byte addr */
|
||||||
wc10 = (0200000 - rpwc) >> 1; /* get PDP-10 wc */
|
wc10 = (0200000 - rpwc) >> 1; /* get PDP-10 wc */
|
||||||
da = GET_DA (rpdc, rpda, dtype) * RP_NUMWD; /* get disk addr */
|
da = GET_DA (rpdc[drv], rpda[drv], dtype) * RP_NUMWD; /* get disk addr */
|
||||||
if ((da + wc10) > drv_tab[dtype].size) { /* disk overrun? */
|
if ((da + wc10) > drv_tab[dtype].size) { /* disk overrun? */
|
||||||
rper1[drv] = rper1[drv] | ER1_AOE;
|
set_rper (ER1_AOE, drv);
|
||||||
if (wc10 > (drv_tab[dtype].size - da))
|
if (wc10 > (drv_tab[dtype].size - da))
|
||||||
wc10 = drv_tab[dtype].size - da; }
|
wc10 = drv_tab[dtype].size - da; }
|
||||||
|
|
||||||
|
@ -884,13 +897,13 @@ case FNC_READH: /* read headers */
|
||||||
da = da + twc10 + (RP_NUMWD - 1);
|
da = da + twc10 + (RP_NUMWD - 1);
|
||||||
if (da >= drv_tab[dtype].size) rpds[drv] = rpds[drv] | DS_LST;
|
if (da >= drv_tab[dtype].size) rpds[drv] = rpds[drv] | DS_LST;
|
||||||
da = da / RP_NUMWD;
|
da = da / RP_NUMWD;
|
||||||
rpda = da % drv_tab[dtype].sect;
|
rpda[drv] = da % drv_tab[dtype].sect;
|
||||||
da = da / drv_tab[dtype].sect;
|
da = da / drv_tab[dtype].sect;
|
||||||
rpda = rpda | ((da % drv_tab[dtype].surf) << DA_V_SF);
|
rpda[drv] = rpda[drv] | ((da % drv_tab[dtype].surf) << DA_V_SF);
|
||||||
rpdc = da / drv_tab[dtype].surf;
|
rpdc[drv] = da / drv_tab[dtype].surf;
|
||||||
|
|
||||||
if (err != 0) { /* error? */
|
if (err != 0) { /* error? */
|
||||||
rper1[drv] = rper1[drv] | ER1_PAR; /* set drive error */
|
set_rper (ER1_PAR, drv); /* set drive error */
|
||||||
update_rpcs (CS1_DONE | CS1_TRE, drv); /* set done, err */
|
update_rpcs (CS1_DONE | CS1_TRE, drv); /* set done, err */
|
||||||
perror ("RP I/O error");
|
perror ("RP I/O error");
|
||||||
clearerr (uptr->fileref);
|
clearerr (uptr->fileref);
|
||||||
|
@ -901,6 +914,16 @@ case FNC_WRITEH: /* write headers stub */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set drive error */
|
||||||
|
|
||||||
|
void set_rper (int32 flag, int32 drv)
|
||||||
|
{
|
||||||
|
rper1[drv] = rper1[drv] | flag;
|
||||||
|
rpds[drv] = rpds[drv] | DS_ATA;
|
||||||
|
rpcs1 = rpcs1 | CS1_SC;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Controller status update
|
/* Controller status update
|
||||||
|
|
||||||
Check for done transition
|
Check for done transition
|
||||||
|
@ -921,7 +944,8 @@ if (rp_unit[drv].flags & UNIT_DIS) rpds[drv] = rper1[drv] = 0;
|
||||||
else rpds[drv] = (rpds[drv] | DS_DPR) & ~DS_PGM;
|
else rpds[drv] = (rpds[drv] | DS_DPR) & ~DS_PGM;
|
||||||
if (rp_unit[drv].flags & UNIT_ATT) rpds[drv] = rpds[drv] | DS_MOL;
|
if (rp_unit[drv].flags & UNIT_ATT) rpds[drv] = rpds[drv] | DS_MOL;
|
||||||
else rpds[drv] = rpds[drv] & ~(DS_MOL | DS_VV | DS_RDY);
|
else rpds[drv] = rpds[drv] & ~(DS_MOL | DS_VV | DS_RDY);
|
||||||
if (rper1[drv] | rper2 | rper3) rpds[drv] = rpds[drv] | DS_ERR | DS_ATA;
|
if (rper1[drv] | rper2[drv] | rper3[drv])
|
||||||
|
rpds[drv] = rpds[drv] | DS_ERR;
|
||||||
else rpds[drv] = rpds[drv] & ~DS_ERR;
|
else rpds[drv] = rpds[drv] & ~DS_ERR;
|
||||||
|
|
||||||
rpcs1 = (rpcs1 & ~(CS1_SC | CS1_MCPE | CS1_MBZ | CS1_DRV)) | CS1_DVA | flag;
|
rpcs1 = (rpcs1 & ~(CS1_SC | CS1_MCPE | CS1_MBZ | CS1_DRV)) | CS1_DVA | flag;
|
||||||
|
@ -955,10 +979,7 @@ UNIT *uptr;
|
||||||
|
|
||||||
rpcs1 = CS1_DVA | CS1_DONE;
|
rpcs1 = CS1_DVA | CS1_DONE;
|
||||||
rpcs2 = CS2_IR | CS2_OR;
|
rpcs2 = CS2_IR | CS2_OR;
|
||||||
rpba = rpda = 0;
|
rpba = rpwc = 0;
|
||||||
rpof = rpdc = 0;
|
|
||||||
rper2 = rper3 = 0;
|
|
||||||
rpec1 = rpec2 = 0;
|
|
||||||
rpiff = 0; /* clear CSTB INTR */
|
rpiff = 0; /* clear CSTB INTR */
|
||||||
int_req = int_req & ~INT_RP; /* clear intr req */
|
int_req = int_req & ~INT_RP; /* clear intr req */
|
||||||
for (i = 0; i < RP_NUMDR; i++) {
|
for (i = 0; i < RP_NUMDR; i++) {
|
||||||
|
@ -969,7 +990,17 @@ for (i = 0; i < RP_NUMDR; i++) {
|
||||||
DS_DPR | DS_RDY | DS_MOL | ((uptr->flags & UNIT_WPRT)? DS_WRL: 0);
|
DS_DPR | DS_RDY | DS_MOL | ((uptr->flags & UNIT_WPRT)? DS_WRL: 0);
|
||||||
else if (uptr->flags & UNIT_DIS) rpds[i] = 0;
|
else if (uptr->flags & UNIT_DIS) rpds[i] = 0;
|
||||||
else rpds[i] = DS_DPR;
|
else rpds[i] = DS_DPR;
|
||||||
rper1[i] = 0; }
|
rper1[i] = 0;
|
||||||
|
rper2[i] = 0;
|
||||||
|
rper3[i] = 0;
|
||||||
|
rpda[i] = 0;
|
||||||
|
rpdc[i] = 0;
|
||||||
|
rpmr[i] = 0;
|
||||||
|
rpof[i] = 0;
|
||||||
|
rpec1[i] = 0;
|
||||||
|
rpec2[i] = 0;
|
||||||
|
rmmr2[i] = 0;
|
||||||
|
rmhr[i] = 0; }
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1021,8 +1052,10 @@ return detach_unit (uptr);
|
||||||
|
|
||||||
t_stat rp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
t_stat rp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
{
|
{
|
||||||
|
int32 dtype = GET_DTYPE (val);
|
||||||
|
|
||||||
if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
|
if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
|
||||||
uptr->capac = drv_tab[GET_DTYPE (val)].size;
|
uptr->capac = drv_tab[dtype].size;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
134
PDP10/pdp10_tu.c
134
PDP10/pdp10_tu.c
|
@ -25,6 +25,12 @@
|
||||||
|
|
||||||
tu RH11/TM03/TU45 magtape
|
tu RH11/TM03/TU45 magtape
|
||||||
|
|
||||||
|
23-Oct-04 RMS Fixed setting done on non data transfers
|
||||||
|
01-Oct-04 RMS Modified to set FCE on read short record, eof
|
||||||
|
Implemented write check
|
||||||
|
TM03 uses only den<2> for validity test
|
||||||
|
TMK is cleared by new motion command, not DCLR
|
||||||
|
14-Sep-04 RMS Fixed RIP value
|
||||||
25-Apr-03 RMS Revised for extended file support
|
25-Apr-03 RMS Revised for extended file support
|
||||||
28-Mar-03 RMS Added multiformat support
|
28-Mar-03 RMS Added multiformat support
|
||||||
28-Feb-03 RMS Revised for magtape library
|
28-Feb-03 RMS Revised for magtape library
|
||||||
|
@ -92,6 +98,7 @@
|
||||||
#define CS1_GO CSR_GO /* go */
|
#define CS1_GO CSR_GO /* go */
|
||||||
#define CS1_V_FNC 1 /* function pos */
|
#define CS1_V_FNC 1 /* function pos */
|
||||||
#define CS1_M_FNC 037 /* function mask */
|
#define CS1_M_FNC 037 /* function mask */
|
||||||
|
#define CS1_N_FNC (CS1_M_FNC + 1)
|
||||||
#define CS1_FNC (CS1_M_FNC << CS1_V_FNC)
|
#define CS1_FNC (CS1_M_FNC << CS1_V_FNC)
|
||||||
#define FNC_NOP 000 /* no operation */
|
#define FNC_NOP 000 /* no operation */
|
||||||
#define FNC_UNLOAD 001 /* unload */
|
#define FNC_UNLOAD 001 /* unload */
|
||||||
|
@ -146,7 +153,7 @@
|
||||||
#define CS2_NEM 0004000 /* nx mem err */
|
#define CS2_NEM 0004000 /* nx mem err */
|
||||||
#define CS2_NEF 0010000 /* nx fmter err */
|
#define CS2_NEF 0010000 /* nx fmter err */
|
||||||
#define CS2_PE 0020000 /* parity err NI */
|
#define CS2_PE 0020000 /* parity err NI */
|
||||||
#define CS2_WCE 0040000 /* write chk err NI */
|
#define CS2_WCE 0040000 /* write chk err */
|
||||||
#define CS2_DLT 0100000 /* data late NI */
|
#define CS2_DLT 0100000 /* data late NI */
|
||||||
#define CS2_MBZ (CS2_CLR | CS2_WCE)
|
#define CS2_MBZ (CS2_CLR | CS2_WCE)
|
||||||
#define CS2_RW (CS2_FMTR | CS2_UAI | CS2_PAT | CS2_MXF | CS2_PE)
|
#define CS2_RW (CS2_FMTR | CS2_UAI | CS2_PAT | CS2_MXF | CS2_PE)
|
||||||
|
@ -214,6 +221,7 @@
|
||||||
|
|
||||||
/* MTDT - 172466 - drive type */
|
/* MTDT - 172466 - drive type */
|
||||||
|
|
||||||
|
#define DT_NSA 0100000 /* not sect addr */
|
||||||
#define DT_TAPE 0040000 /* tape */
|
#define DT_TAPE 0040000 /* tape */
|
||||||
#define DT_PRES 0002000 /* slave present */
|
#define DT_PRES 0002000 /* slave present */
|
||||||
#define DT_TM03 0000040 /* TM03 formatter */
|
#define DT_TM03 0000040 /* TM03 formatter */
|
||||||
|
@ -243,6 +251,7 @@
|
||||||
#define TC_ACC 0100000 /* accelerating NI */
|
#define TC_ACC 0100000 /* accelerating NI */
|
||||||
#define TC_RW 0013777
|
#define TC_RW 0013777
|
||||||
#define TC_MBZ 0004000
|
#define TC_MBZ 0004000
|
||||||
|
#define TC_RIP ((TC_800 << TC_V_DEN) || (TC_10C << TC_V_FMT))
|
||||||
#define GET_DEN(x) (((x) >> TC_V_DEN) & TC_M_DEN)
|
#define GET_DEN(x) (((x) >> TC_V_DEN) & TC_M_DEN)
|
||||||
#define GET_FMT(x) (((x) >> TC_V_FMT) & TC_M_FMT)
|
#define GET_FMT(x) (((x) >> TC_V_FMT) & TC_M_FMT)
|
||||||
#define GET_DRV(x) (((x) >> TC_V_UNIT) & TC_M_UNIT)
|
#define GET_DRV(x) (((x) >> TC_V_UNIT) & TC_M_UNIT)
|
||||||
|
@ -280,6 +289,8 @@ extern int32 int_vec[32];
|
||||||
extern int32 ubmap[UBANUM][UMAP_MEMSIZE]; /* Unibus map */
|
extern int32 ubmap[UBANUM][UMAP_MEMSIZE]; /* Unibus map */
|
||||||
extern int32 ubcs[UBANUM];
|
extern int32 ubcs[UBANUM];
|
||||||
extern UNIT cpu_unit;
|
extern UNIT cpu_unit;
|
||||||
|
extern int32 sim_switches;
|
||||||
|
extern FILE *sim_deb;
|
||||||
|
|
||||||
int32 tucs1 = 0; /* control/status 1 */
|
int32 tucs1 = 0; /* control/status 1 */
|
||||||
int32 tuwc = 0; /* word count */
|
int32 tuwc = 0; /* word count */
|
||||||
|
@ -304,8 +315,11 @@ int32 reg_in_fmtr1[32] = { /* rmr if write + go */
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
|
||||||
int32 fmt_test[16] = { /* fmt bytes/10 wd */
|
int32 fmt_test[16] = { /* fmt bytes/10 wd */
|
||||||
5, 0, 5, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
5, 0, 5, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||||
int32 den_test[8] = { /* valid densities */
|
static char *tu_fname[CS1_N_FNC] = {
|
||||||
0, 0, 0, 1, 1, 0, 0, 0 };
|
"NOP", "UNLD", "2", "REW", "FCLR", "5", "6", "7",
|
||||||
|
"RIP", "11", "ERASE", "WREOF", "SPCF", "SPCR", "16", "17",
|
||||||
|
"20", "21", "22", "23", "WRCHKF", "25", "26", "WRCHKR",
|
||||||
|
"WRITE", "31", "32", "33", "READF", "35", "36" "READR" };
|
||||||
static uint8 *xbuf = NULL; /* xfer buffer */
|
static uint8 *xbuf = NULL; /* xfer buffer */
|
||||||
|
|
||||||
t_stat tu_rd (int32 *data, int32 PA, int32 access);
|
t_stat tu_rd (int32 *data, int32 PA, int32 access);
|
||||||
|
@ -317,6 +331,7 @@ t_stat tu_attach (UNIT *uptr, char *cptr);
|
||||||
t_stat tu_detach (UNIT *uptr);
|
t_stat tu_detach (UNIT *uptr);
|
||||||
t_stat tu_boot (int32 unitno, DEVICE *dptr);
|
t_stat tu_boot (int32 unitno, DEVICE *dptr);
|
||||||
void tu_go (int32 drv);
|
void tu_go (int32 drv);
|
||||||
|
void set_tuer (int32 flag);
|
||||||
void update_tucs (int32 flag, int32 drv);
|
void update_tucs (int32 flag, int32 drv);
|
||||||
t_stat tu_map_err (UNIT *uptr, t_stat st);
|
t_stat tu_map_err (UNIT *uptr, t_stat st);
|
||||||
|
|
||||||
|
@ -381,7 +396,7 @@ DEVICE tu_dev = {
|
||||||
TU_NUMDR, 10, 31, 1, 8, 8,
|
TU_NUMDR, 10, 31, 1, 8, 8,
|
||||||
NULL, NULL, &tu_reset,
|
NULL, NULL, &tu_reset,
|
||||||
&tu_boot, &tu_attach, &tu_detach,
|
&tu_boot, &tu_attach, &tu_detach,
|
||||||
&tu_dib, DEV_UBUS };
|
&tu_dib, DEV_UBUS | DEV_DEBUG };
|
||||||
|
|
||||||
/* I/O dispatch routine, I/O addresses 17772440 - 17772472 */
|
/* I/O dispatch routine, I/O addresses 17772440 - 17772472 */
|
||||||
|
|
||||||
|
@ -435,8 +450,8 @@ case 012: /* MTMR */
|
||||||
*data = tumr;
|
*data = tumr;
|
||||||
break;
|
break;
|
||||||
case 013: /* MTDT */
|
case 013: /* MTDT */
|
||||||
*data = DT_TAPE | DT_TM03 | ((tu_unit[drv].flags & UNIT_DIS)?
|
*data = DT_NSA | DT_TAPE | DT_TM03 |
|
||||||
DT_OFF: (DT_PRES | DT_TU45));
|
((tu_unit[drv].flags & UNIT_DIS)? DT_OFF: (DT_PRES | DT_TU45));
|
||||||
break;
|
break;
|
||||||
case 014: /* MTSN */
|
case 014: /* MTSN */
|
||||||
*data = (tu_unit[drv].flags & UNIT_DIS)? 0: 040 | (drv + 1);
|
*data = (tu_unit[drv].flags & UNIT_DIS)? 0: 040 | (drv + 1);
|
||||||
|
@ -445,7 +460,7 @@ case 015: /* MTTC */
|
||||||
*data = tutc = tutc & ~TC_MBZ;
|
*data = tutc = tutc & ~TC_MBZ;
|
||||||
break;
|
break;
|
||||||
default: /* all others */
|
default: /* all others */
|
||||||
tuer = tuer | ER_ILR;
|
set_tuer (ER_ILR);
|
||||||
update_tucs (0, drv);
|
update_tucs (0, drv);
|
||||||
break; }
|
break; }
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -464,7 +479,7 @@ if (reg_in_fmtr[j] && (fmtr != 0)) { /* nx formatter */
|
||||||
update_tucs (CS1_SC, drv); /* request intr */
|
update_tucs (CS1_SC, drv); /* request intr */
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
if (reg_in_fmtr1[j] && ((tucs1 & CS1_DONE) == 0)) { /* formatter busy? */
|
if (reg_in_fmtr1[j] && ((tucs1 & CS1_DONE) == 0)) { /* formatter busy? */
|
||||||
tuer = tuer | ER_RMR; /* won't write */
|
set_tuer (ER_RMR); /* won't write */
|
||||||
update_tucs (0, drv);
|
update_tucs (0, drv);
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
|
|
||||||
|
@ -485,7 +500,7 @@ case 000: /* MTCS1 */
|
||||||
tucs2 = tucs2 | CS2_NEF; /* set error flag */
|
tucs2 = tucs2 | CS2_NEF; /* set error flag */
|
||||||
cs1f = CS1_SC; } /* req interrupt */
|
cs1f = CS1_SC; } /* req interrupt */
|
||||||
else if (tucs1 & CS1_GO) { /* busy? */
|
else if (tucs1 & CS1_GO) { /* busy? */
|
||||||
if (tucs1 & CS1_DONE) tuer = tuer | ER_RMR;
|
if (tucs1 & CS1_DONE) set_tuer (ER_RMR);
|
||||||
else tucs2 = tucs2 | CS2_PGE; }
|
else tucs2 = tucs2 | CS2_PGE; }
|
||||||
else {
|
else {
|
||||||
tucs1 = (tucs1 & ~CS1_DRV) | (data & CS1_DRV);
|
tucs1 = (tucs1 & ~CS1_DRV) | (data & CS1_DRV);
|
||||||
|
@ -544,7 +559,7 @@ case 013: /* MTDT */
|
||||||
case 014: /* MTSN */
|
case 014: /* MTSN */
|
||||||
break; /* read only */
|
break; /* read only */
|
||||||
default: /* all others */
|
default: /* all others */
|
||||||
tuer = tuer | ER_ILR;
|
set_tuer (ER_ILR);
|
||||||
break; } /* end switch */
|
break; } /* end switch */
|
||||||
update_tucs (cs1f, drv); /* update status */
|
update_tucs (cs1f, drv); /* update status */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -560,10 +575,12 @@ UNIT *uptr;
|
||||||
fnc = GET_FNC (tucs1); /* get function */
|
fnc = GET_FNC (tucs1); /* get function */
|
||||||
den = GET_DEN (tutc); /* get density */
|
den = GET_DEN (tutc); /* get density */
|
||||||
uptr = tu_dev.units + drv; /* get unit */
|
uptr = tu_dev.units + drv; /* get unit */
|
||||||
|
if (DEBUG_PRS (tu_dev)) fprintf (sim_deb,
|
||||||
|
">>TU%d STRT: fnc=%s, cs1=%06o, cs2=%06o, ba=%06o, wc=%06o, fc=%06o, fs=%06o, er=%06o, pos=%d\n",
|
||||||
|
drv, tu_fname[fnc], tucs1, tucs2, tuba, tuwc, tufc, tufs, tuer, uptr->pos);
|
||||||
if ((fnc != FNC_FCLR) && /* not clear & err */
|
if ((fnc != FNC_FCLR) && /* not clear & err */
|
||||||
((tufs & FS_ERR) || sim_is_active (uptr))) { /* or in motion? */
|
((tufs & FS_ERR) || sim_is_active (uptr))) { /* or in motion? */
|
||||||
tuer = tuer | ER_ILF; /* set error flag */
|
set_tuer (ER_ILF); /* set err, ATN */
|
||||||
tufs = tufs | FS_ATA; /* exception */
|
|
||||||
tucs1 = tucs1 & ~CS1_GO; /* clear go */
|
tucs1 = tucs1 & ~CS1_GO; /* clear go */
|
||||||
update_tucs (CS1_SC, drv); /* request intr */
|
update_tucs (CS1_SC, drv); /* request intr */
|
||||||
return; }
|
return; }
|
||||||
|
@ -574,45 +591,48 @@ switch (fnc) { /* case on function */
|
||||||
case FNC_FCLR: /* drive clear */
|
case FNC_FCLR: /* drive clear */
|
||||||
tuer = 0; /* clear errors */
|
tuer = 0; /* clear errors */
|
||||||
tutc = tutc & ~TC_FCS; /* clear fc status */
|
tutc = tutc & ~TC_FCS; /* clear fc status */
|
||||||
tufs = tufs & ~(FS_SAT | FS_SSC | FS_ID | FS_TMK | FS_ERR);
|
tufs = tufs & ~(FS_SAT | FS_SSC | FS_ID | FS_ERR);
|
||||||
sim_cancel (uptr); /* reset drive */
|
sim_cancel (uptr); /* reset drive */
|
||||||
uptr->USTAT = 0;
|
uptr->USTAT = 0;
|
||||||
case FNC_NOP:
|
case FNC_NOP:
|
||||||
tucs1 = tucs1 & ~CS1_GO; /* no operation */
|
tucs1 = tucs1 & ~CS1_GO; /* no operation */
|
||||||
return;
|
return;
|
||||||
case FNC_RIP: /* read-in preset */
|
case FNC_RIP: /* read-in preset */
|
||||||
tutc = TC_800; /* density = 800 */
|
tutc = TC_RIP; /* density = 800 */
|
||||||
sim_tape_rewind (&tu_unit[0]); /* rewind unit 0 */
|
sim_tape_rewind (&tu_unit[0]); /* rewind unit 0 */
|
||||||
tu_unit[0].USTAT = 0;
|
tu_unit[0].USTAT = 0;
|
||||||
tucs1 = tucs1 & ~CS1_GO;
|
tucs1 = tucs1 & ~CS1_GO;
|
||||||
|
tufs = tufs & ~FS_TMK;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case FNC_UNLOAD: /* unload */
|
case FNC_UNLOAD: /* unload */
|
||||||
if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */
|
if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */
|
||||||
tuer = tuer | ER_UNS;
|
set_tuer (ER_UNS);
|
||||||
break; }
|
break; }
|
||||||
detach_unit (uptr);
|
detach_unit (uptr);
|
||||||
uptr->USTAT = FS_REW;
|
uptr->USTAT = FS_REW;
|
||||||
sim_activate (uptr, tu_time);
|
sim_activate (uptr, tu_time);
|
||||||
tucs1 = tucs1 & ~CS1_GO;
|
tucs1 = tucs1 & ~CS1_GO;
|
||||||
|
tufs = tufs & ~FS_TMK;
|
||||||
return;
|
return;
|
||||||
case FNC_REWIND:
|
case FNC_REWIND:
|
||||||
if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */
|
if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */
|
||||||
tuer = tuer | ER_UNS;
|
set_tuer (ER_UNS);
|
||||||
break; }
|
break; }
|
||||||
uptr->USTAT = FS_PIP | FS_REW;
|
uptr->USTAT = FS_PIP | FS_REW;
|
||||||
sim_activate (uptr, tu_time);
|
sim_activate (uptr, tu_time);
|
||||||
tucs1 = tucs1 & ~CS1_GO;
|
tucs1 = tucs1 & ~CS1_GO;
|
||||||
|
tufs = tufs & ~FS_TMK;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case FNC_SPACEF:
|
case FNC_SPACEF:
|
||||||
space_test = FS_EOT;
|
space_test = FS_EOT;
|
||||||
case FNC_SPACER:
|
case FNC_SPACER:
|
||||||
if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */
|
if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */
|
||||||
tuer = tuer | ER_UNS;
|
set_tuer (ER_UNS);
|
||||||
break; }
|
break; }
|
||||||
if ((tufs & space_test) || ((tutc & TC_FCS) == 0)) {
|
if ((tufs & space_test) || ((tutc & TC_FCS) == 0)) {
|
||||||
tuer = tuer | ER_NXF;
|
set_tuer (ER_NXF);
|
||||||
break; }
|
break; }
|
||||||
uptr->USTAT = FS_PIP;
|
uptr->USTAT = FS_PIP;
|
||||||
goto GO_XFER;
|
goto GO_XFER;
|
||||||
|
@ -620,36 +640,30 @@ case FNC_SPACER:
|
||||||
case FNC_WCHKR: /* wchk = read */
|
case FNC_WCHKR: /* wchk = read */
|
||||||
case FNC_READR: /* read rev */
|
case FNC_READR: /* read rev */
|
||||||
if (tufs & FS_BOT) { /* beginning of tape? */
|
if (tufs & FS_BOT) { /* beginning of tape? */
|
||||||
tuer = tuer | ER_NXF;
|
set_tuer (ER_NXF);
|
||||||
break; }
|
break; }
|
||||||
goto DATA_XFER;
|
goto DATA_XFER;
|
||||||
|
|
||||||
case FNC_WRITE: /* write */
|
case FNC_WRITE: /* write */
|
||||||
if (((tutc & TC_FCS) == 0) || /* frame cnt = 0? */
|
if (((tutc & TC_FCS) == 0) || /* frame cnt = 0? */
|
||||||
((den == TC_800) && (tufc > 0777765))) { /* NRZI, fc < 13? */
|
((den == TC_800) && (tufc > 0777765))) { /* NRZI, fc < 13? */
|
||||||
tuer = tuer | ER_NXF;
|
set_tuer (ER_NXF);
|
||||||
break; }
|
break; }
|
||||||
case FNC_WREOF: /* write tape mark */
|
case FNC_WREOF: /* write tape mark */
|
||||||
case FNC_ERASE: /* erase */
|
case FNC_ERASE: /* erase */
|
||||||
if (sim_tape_wrp (uptr)) { /* write locked? */
|
if (sim_tape_wrp (uptr)) { /* write locked? */
|
||||||
tuer = tuer | ER_NXF;
|
set_tuer (ER_NXF);
|
||||||
break; }
|
break; }
|
||||||
case FNC_WCHKF: /* wchk = read */
|
case FNC_WCHKF: /* wchk = read */
|
||||||
case FNC_READF: /* read */
|
case FNC_READF: /* read */
|
||||||
DATA_XFER:
|
DATA_XFER:
|
||||||
if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */
|
if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */
|
||||||
tuer = tuer | ER_UNS;
|
set_tuer (ER_UNS);
|
||||||
break; }
|
break; }
|
||||||
if (fmt_test[GET_FMT (tutc)] == 0) { /* invalid format? */
|
if (fmt_test[GET_FMT (tutc)] == 0) { /* invalid format? */
|
||||||
tuer = tuer | ER_FER;
|
set_tuer (ER_FER);
|
||||||
break; }
|
|
||||||
if (den_test[den] == 0) { /* invalid density? */
|
|
||||||
tuer = tuer | ER_NXF;
|
|
||||||
break; }
|
break; }
|
||||||
if (uptr->UDENS == UD_UNK) uptr->UDENS = den; /* set dens */
|
if (uptr->UDENS == UD_UNK) uptr->UDENS = den; /* set dens */
|
||||||
/* else if (uptr->UDENS != den) { /* density mismatch? */
|
|
||||||
/* tuer = tuer | ER_NXF;
|
|
||||||
/* break; } */
|
|
||||||
uptr->USTAT = 0;
|
uptr->USTAT = 0;
|
||||||
tucs1 = tucs1 & ~CS1_DONE; /* clear done */
|
tucs1 = tucs1 & ~CS1_DONE; /* clear done */
|
||||||
GO_XFER:
|
GO_XFER:
|
||||||
|
@ -660,10 +674,9 @@ GO_XFER:
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default: /* all others */
|
default: /* all others */
|
||||||
tuer = tuer | ER_ILF; /* not supported */
|
set_tuer (ER_ILF); /* not supported */
|
||||||
break; } /* end case function */
|
break; } /* end case function */
|
||||||
tucs1 = tucs1 & ~CS1_GO; /* clear go */
|
tucs1 = tucs1 & ~CS1_GO; /* clear go */
|
||||||
tufs = tufs | FS_ATA; /* set attn */
|
|
||||||
update_tucs (CS1_SC, drv); /* set intr */
|
update_tucs (CS1_SC, drv); /* set intr */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -677,7 +690,7 @@ return;
|
||||||
|
|
||||||
t_stat tu_svc (UNIT *uptr)
|
t_stat tu_svc (UNIT *uptr)
|
||||||
{
|
{
|
||||||
int32 f, fmt, i, j, k, wc10, ba10;
|
int32 fnc, fmt, i, j, k, wc10, ba10;
|
||||||
int32 ba, fc, wc, drv, mpa10, vpn;
|
int32 ba, fc, wc, drv, mpa10, vpn;
|
||||||
d10 val, v[4];
|
d10 val, v[4];
|
||||||
t_mtrlnt tbc;
|
t_mtrlnt tbc;
|
||||||
|
@ -691,7 +704,7 @@ if (uptr->USTAT & FS_REW) { /* rewind or unload? */
|
||||||
update_tucs (CS1_SC, drv); /* update status */
|
update_tucs (CS1_SC, drv); /* update status */
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
|
|
||||||
f = GET_FNC (tucs1); /* get command */
|
fnc = GET_FNC (tucs1); /* get command */
|
||||||
fmt = GET_FMT (tutc); /* get format */
|
fmt = GET_FMT (tutc); /* get format */
|
||||||
ba = GET_UAE (tucs1) | tuba; /* get bus address */
|
ba = GET_UAE (tucs1) | tuba; /* get bus address */
|
||||||
wc = 0200000 - tuwc; /* get word count */
|
wc = 0200000 - tuwc; /* get word count */
|
||||||
|
@ -700,7 +713,7 @@ wc10 = wc >> 1; /* 10 word count */
|
||||||
ba10 = ba >> 2; /* 10 word addr */
|
ba10 = ba >> 2; /* 10 word addr */
|
||||||
uptr->USTAT = 0; /* clear status */
|
uptr->USTAT = 0; /* clear status */
|
||||||
|
|
||||||
switch (f) { /* case on function */
|
switch (fnc) { /* case on function */
|
||||||
|
|
||||||
/* Unit service - non-data transfer commands - set ATA when done */
|
/* Unit service - non-data transfer commands - set ATA when done */
|
||||||
|
|
||||||
|
@ -712,7 +725,7 @@ case FNC_SPACEF: /* space forward */
|
||||||
break; }
|
break; }
|
||||||
}
|
}
|
||||||
while (tufc != 0);
|
while (tufc != 0);
|
||||||
if (tufc) tuer = tuer | ER_FCE;
|
if (tufc) set_tuer (ER_FCE);
|
||||||
else tutc = tutc & ~TC_FCS;
|
else tutc = tutc & ~TC_FCS;
|
||||||
tufs = tufs | FS_ATA;
|
tufs = tufs | FS_ATA;
|
||||||
break;
|
break;
|
||||||
|
@ -725,7 +738,7 @@ case FNC_SPACER: /* space reverse */
|
||||||
break; }
|
break; }
|
||||||
}
|
}
|
||||||
while (tufc != 0);
|
while (tufc != 0);
|
||||||
if (tufc) tuer = tuer | ER_FCE;
|
if (tufc) set_tuer (ER_FCE);
|
||||||
else tutc = tutc & ~TC_FCS;
|
else tutc = tutc & ~TC_FCS;
|
||||||
tufs = tufs | FS_ATA;
|
tufs = tufs | FS_ATA;
|
||||||
break;
|
break;
|
||||||
|
@ -770,11 +783,15 @@ case FNC_WCHKF: /* wcheck = read */
|
||||||
for (k = 0; k < 4; k++) v[k] = xbuf[j++];
|
for (k = 0; k < 4; k++) v[k] = xbuf[j++];
|
||||||
val = (v[0] << 28) | (v[1] << 20) | (v[2] << 12) | (v[3] << 4);
|
val = (v[0] << 28) | (v[1] << 20) | (v[2] << 12) | (v[3] << 4);
|
||||||
if (fmt == TC_10C) val = val | ((d10) xbuf[j++] & 017);
|
if (fmt == TC_10C) val = val | ((d10) xbuf[j++] & 017);
|
||||||
if (f == FNC_READF) M[mpa10] = val;
|
if (fnc == FNC_READF) M[mpa10] = val; /* read? store */
|
||||||
|
else if (M[mpa10] != val) { /* wchk, mismatch? */
|
||||||
|
tucs2 = tucs2 | CS2_WCE; /* flag, stop */
|
||||||
|
break; }
|
||||||
mpa10 = mpa10 + 1; } /* end for */
|
mpa10 = mpa10 + 1; } /* end for */
|
||||||
tufc = tbc & 0177777;
|
tufc = tbc & 0177777;
|
||||||
tuwc = (tuwc + (i << 1)) & 0177777;
|
tuwc = (tuwc + (i << 1)) & 0177777;
|
||||||
ba = ba + (i << 2);
|
ba = ba + (i << 2);
|
||||||
|
if (tuwc) set_tuer (ER_FCE); /* short record? */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FNC_WRITE: /* write */
|
case FNC_WRITE: /* write */
|
||||||
|
@ -813,20 +830,38 @@ case FNC_WCHKR: /* wcheck = read */
|
||||||
val = ((fmt == TC_10C)? (((d10) xbuf [--j]) & 017): 0);
|
val = ((fmt == TC_10C)? (((d10) xbuf [--j]) & 017): 0);
|
||||||
for (k = 0; k < 4; i++) v[k] = xbuf[--j];
|
for (k = 0; k < 4; i++) v[k] = xbuf[--j];
|
||||||
val = val | (v[0] << 4) | (v[1] << 12) | (v[2] << 20) | (v[3] << 28);
|
val = val | (v[0] << 4) | (v[1] << 12) | (v[2] << 20) | (v[3] << 28);
|
||||||
if (f == FNC_READR) M[mpa10] = val;
|
if (fnc == FNC_READR) M[mpa10] = val; /* read? store */
|
||||||
|
else if (M[mpa10] != val) { /* wchk, mismatch? */
|
||||||
|
tucs2 = tucs2 | CS2_WCE; /* flag, stop */
|
||||||
|
break; }
|
||||||
mpa10 = mpa10 - 1; } /* end for */
|
mpa10 = mpa10 - 1; } /* end for */
|
||||||
tufc = tbc & 0177777;
|
tufc = tbc & 0177777;
|
||||||
tuwc = (tuwc + (i << 1)) & 0177777;
|
tuwc = (tuwc + (i << 1)) & 0177777;
|
||||||
ba = ba - (i << 2);
|
ba = ba - (i << 2);
|
||||||
|
if (tuwc) set_tuer (ER_FCE); /* short record? */
|
||||||
break; } /* end case */
|
break; } /* end case */
|
||||||
|
|
||||||
tucs1 = (tucs1 & ~CS1_UAE) | ((ba >> (16 - CS1_V_UAE)) & CS1_UAE);
|
tucs1 = (tucs1 & ~CS1_UAE) | ((ba >> (16 - CS1_V_UAE)) & CS1_UAE);
|
||||||
tuba = ba & 0177777; /* update mem addr */
|
tuba = ba & 0177777; /* update mem addr */
|
||||||
tucs1 = tucs1 & ~CS1_GO; /* clear go */
|
tucs1 = tucs1 & ~CS1_GO; /* clear go */
|
||||||
update_tucs (CS1_DONE, drv);
|
if (fnc >= FNC_XFER) update_tucs (CS1_DONE, drv); /* data xfer? */
|
||||||
|
else update_tucs (CS1_SC, drv); /* no, set attn */
|
||||||
|
if (DEBUG_PRS (tu_dev)) fprintf (sim_deb,
|
||||||
|
">>TU%d DONE: fnc=%s, cs1=%06o, cs2=%06o, ba=%06o, wc=%06o, fc=%06o, fs=%06o, er=%06o, pos=%d\n",
|
||||||
|
drv, tu_fname[fnc], tucs1, tucs2, tuba, tuwc, tufc, tufs, tuer, uptr->pos);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Formatter error */
|
||||||
|
|
||||||
|
void set_tuer (int32 flag)
|
||||||
|
{
|
||||||
|
tuer = tuer | flag;
|
||||||
|
tufs = tufs | FS_ATA;
|
||||||
|
tucs1 = tucs1 | CS1_SC;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Controller status update
|
/* Controller status update
|
||||||
|
|
||||||
Check for done transition
|
Check for done transition
|
||||||
|
@ -877,29 +912,30 @@ t_stat tu_map_err (UNIT *uptr, t_stat st)
|
||||||
switch (st) {
|
switch (st) {
|
||||||
case MTSE_FMT: /* illegal fmt */
|
case MTSE_FMT: /* illegal fmt */
|
||||||
case MTSE_UNATT: /* not attached */
|
case MTSE_UNATT: /* not attached */
|
||||||
tuer = tuer | ER_NXF; /* can't execute */
|
set_tuer (ER_NXF); /* can't execute */
|
||||||
case MTSE_OK: /* no error */
|
case MTSE_OK: /* no error */
|
||||||
return SCPE_IERR;
|
return SCPE_IERR;
|
||||||
case MTSE_TMK: /* end of file */
|
case MTSE_TMK: /* end of file */
|
||||||
tufs = tufs | FS_TMK;
|
tufs = tufs | FS_TMK;
|
||||||
|
set_tuer (ER_FCE); /* also sets FCE */
|
||||||
break;
|
break;
|
||||||
case MTSE_IOERR: /* IO error */
|
case MTSE_IOERR: /* IO error */
|
||||||
tuer = tuer | ER_VPE; /* flag error */
|
set_tuer (ER_VPE); /* flag error */
|
||||||
if (tu_stopioe) return SCPE_IOERR;
|
if (tu_stopioe) return SCPE_IOERR;
|
||||||
break;
|
break;
|
||||||
case MTSE_INVRL: /* invalid rec lnt */
|
case MTSE_INVRL: /* invalid rec lnt */
|
||||||
tuer = tuer | ER_VPE; /* flag error */
|
set_tuer (ER_VPE); /* flag error */
|
||||||
return SCPE_MTRLNT;
|
return SCPE_MTRLNT;
|
||||||
case MTSE_RECE: /* record in error */
|
case MTSE_RECE: /* record in error */
|
||||||
tuer = tuer | ER_CRC; /* set crc err */
|
set_tuer (ER_CRC); /* set crc err */
|
||||||
break;
|
break;
|
||||||
case MTSE_EOM: /* end of medium */
|
case MTSE_EOM: /* end of medium */
|
||||||
tuer = tuer | ER_OPI; /* incomplete */
|
set_tuer (ER_OPI); /* incomplete */
|
||||||
break;
|
break;
|
||||||
case MTSE_BOT: /* reverse into BOT */
|
case MTSE_BOT: /* reverse into BOT */
|
||||||
break;
|
break;
|
||||||
case MTSE_WRP: /* write protect */
|
case MTSE_WRP: /* write protect */
|
||||||
tuer = tuer | ER_NXF; /* can't execute */
|
set_tuer (ER_NXF); /* can't execute */
|
||||||
break; }
|
break; }
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -913,9 +949,13 @@ UNIT *uptr;
|
||||||
|
|
||||||
tucs1 = CS1_DVA | CS1_DONE;
|
tucs1 = CS1_DVA | CS1_DONE;
|
||||||
tucs2 = CS2_IR | CS2_OR;
|
tucs2 = CS2_IR | CS2_OR;
|
||||||
tuba = tufc = 0;
|
tuba = 0;
|
||||||
tutc = tuer = 0;
|
tuwc = 0;
|
||||||
|
tufc = 0;
|
||||||
|
tuer = 0;
|
||||||
tufs = FS_FPR | FS_RDY;
|
tufs = FS_FPR | FS_RDY;
|
||||||
|
if (sim_switches & SWMASK ('P')) tutc = 0; /* powerup? clr TC */
|
||||||
|
else tutc = tutc & ~TC_FCS; /* no, clr <fcs> */
|
||||||
tuiff = 0; /* clear CSTB INTR */
|
tuiff = 0; /* clear CSTB INTR */
|
||||||
int_req = int_req & ~INT_TU; /* clear interrupt */
|
int_req = int_req & ~INT_TU; /* clear interrupt */
|
||||||
for (u = 0; u < TU_NUMDR; u++) { /* loop thru units */
|
for (u = 0; u < TU_NUMDR; u++) { /* loop thru units */
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
This module simulates the PDP-11 commercial instruction set (CIS).
|
This module simulates the PDP-11 commercial instruction set (CIS).
|
||||||
|
|
||||||
|
16-Sep-04 RMS Fixed bug in CMPP/N of negative strings
|
||||||
17-Oct-02 RMS Fixed compiler warning (found by Hans Pufal)
|
17-Oct-02 RMS Fixed compiler warning (found by Hans Pufal)
|
||||||
08-Oct-02 RMS Fixed macro definitions
|
08-Oct-02 RMS Fixed macro definitions
|
||||||
|
|
||||||
|
@ -154,8 +155,8 @@
|
||||||
#define MAXDVAL 429496730 /* 2^32 / 10 */
|
#define MAXDVAL 429496730 /* 2^32 / 10 */
|
||||||
|
|
||||||
struct dstr {
|
struct dstr {
|
||||||
unsigned int32 sign;
|
uint32 sign;
|
||||||
unsigned int32 val[DSTRLNT]; };
|
uint32 val[DSTRLNT]; };
|
||||||
|
|
||||||
typedef struct dstr DSTR;
|
typedef struct dstr DSTR;
|
||||||
|
|
||||||
|
@ -175,8 +176,8 @@ void SubDstr (DSTR *src1, DSTR *src2, DSTR *dst);
|
||||||
int32 CmpDstr (DSTR *src1, DSTR *src2);
|
int32 CmpDstr (DSTR *src1, DSTR *src2);
|
||||||
int32 TestDstr (DSTR *dsrc);
|
int32 TestDstr (DSTR *dsrc);
|
||||||
int32 LntDstr (DSTR *dsrc, int32 nz);
|
int32 LntDstr (DSTR *dsrc, int32 nz);
|
||||||
unsigned int32 NibbleLshift (DSTR *dsrc, int32 sc, unsigned int32 cin);
|
uint32 NibbleLshift (DSTR *dsrc, int32 sc, uint32 cin);
|
||||||
unsigned int32 NibbleRshift (DSTR *dsrc, int32 sc, unsigned int32 cin);
|
uint32 NibbleRshift (DSTR *dsrc, int32 sc, uint32 cin);
|
||||||
int32 WordLshift (DSTR *dsrc, int32 sc);
|
int32 WordLshift (DSTR *dsrc, int32 sc);
|
||||||
void WordRshift (DSTR *dsrc, int32 sc);
|
void WordRshift (DSTR *dsrc, int32 sc);
|
||||||
void CreateTable (DSTR *dsrc, DSTR mtable[10]);
|
void CreateTable (DSTR *dsrc, DSTR mtable[10]);
|
||||||
|
@ -738,8 +739,9 @@ case 052: case 072: case 0152: case 0172:
|
||||||
if (src1.sign != src2.sign) N = src1.sign;
|
if (src1.sign != src2.sign) N = src1.sign;
|
||||||
else {
|
else {
|
||||||
t = CmpDstr (&src1, &src2); /* compare strings */
|
t = CmpDstr (&src1, &src2); /* compare strings */
|
||||||
if (t < 0) N = 1;
|
if (t < 0) N = (src1.sign? 0: 1);
|
||||||
else if (t == 0) Z = 1; }
|
else if (t > 0) N = (src1.sign? 1: 0);
|
||||||
|
else Z = 1; }
|
||||||
if ((op & INLINE) == 0) /* if reg, clr reg */
|
if ((op & INLINE) == 0) /* if reg, clr reg */
|
||||||
R[0] = R[1] = R[2] = R[3] = 0;
|
R[0] = R[1] = R[2] = R[3] = 0;
|
||||||
return;
|
return;
|
||||||
|
@ -1073,7 +1075,7 @@ return;
|
||||||
int32 AddDstr (DSTR *s1, DSTR *s2, DSTR *ds, int32 cy)
|
int32 AddDstr (DSTR *s1, DSTR *s2, DSTR *ds, int32 cy)
|
||||||
{
|
{
|
||||||
int32 i;
|
int32 i;
|
||||||
unsigned int32 sm1, sm2, tm1, tm2, tm3, tm4;
|
uint32 sm1, sm2, tm1, tm2, tm3, tm4;
|
||||||
|
|
||||||
for (i = 0; i < DSTRLNT; i++) { /* loop low to high */
|
for (i = 0; i < DSTRLNT; i++) { /* loop low to high */
|
||||||
tm1 = s1->val[i] ^ (s2->val[i] + cy); /* xor operands */
|
tm1 = s1->val[i] ^ (s2->val[i] + cy); /* xor operands */
|
||||||
|
@ -1226,7 +1228,7 @@ return c;
|
||||||
cin = carry in
|
cin = carry in
|
||||||
*/
|
*/
|
||||||
|
|
||||||
unsigned int32 NibbleRshift (DSTR *dsrc, int32 sc, unsigned int32 cin)
|
uint32 NibbleRshift (DSTR *dsrc, int32 sc, uint32 cin)
|
||||||
{
|
{
|
||||||
int32 i, s, rs, nc;
|
int32 i, s, rs, nc;
|
||||||
|
|
||||||
|
@ -1249,7 +1251,7 @@ return 0;
|
||||||
cin = carry in
|
cin = carry in
|
||||||
*/
|
*/
|
||||||
|
|
||||||
unsigned int32 NibbleLshift (DSTR *dsrc, int32 sc, unsigned int32 cin)
|
uint32 NibbleLshift (DSTR *dsrc, int32 sc, uint32 cin)
|
||||||
{
|
{
|
||||||
int32 i, s, rs, nc;
|
int32 i, s, rs, nc;
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
977
PDP11/pdp11_cpumod.c
Normal file
977
PDP11/pdp11_cpumod.c
Normal file
|
@ -0,0 +1,977 @@
|
||||||
|
/* pdp11_cpumod.c: PDP-11 CPU model-specific features
|
||||||
|
|
||||||
|
Copyright (c) 2004, 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"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
system PDP-11 model-specific registers
|
||||||
|
|
||||||
|
This module includes CPU- and system-specific registers, such as the Unibus
|
||||||
|
map and control registers on 22b Unibus systems, the board registers for the
|
||||||
|
F11- and J11-based systems, and the system registers for the PDP-11/44,
|
||||||
|
PDP-11/45, PDP-11/60, and PDP-11/70. Most registers are implemented at
|
||||||
|
a minimum level: just enough to satisfy the machine identification code
|
||||||
|
in the various operating systems.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "pdp11_defs.h"
|
||||||
|
#include "pdp11_cpumod.h"
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
/* Byte write macros for system registers */
|
||||||
|
|
||||||
|
#define ODD_IGN(cur) \
|
||||||
|
if ((access == WRITEB) && (pa & 1)) return SCPE_OK
|
||||||
|
#define ODD_WO(cur) \
|
||||||
|
if ((access == WRITEB) && (pa & 1)) cur = cur << 8
|
||||||
|
#define ODD_MRG(prv,cur) \
|
||||||
|
if (access == WRITEB) cur = \
|
||||||
|
((pa & 1)? (((prv) & 0377) | ((cur) & 0177400)) : \
|
||||||
|
(((prv) & 0177400) | ((cur) & 0377)))
|
||||||
|
|
||||||
|
int32 SR = 0; /* switch register */
|
||||||
|
int32 DR = 0; /* display register */
|
||||||
|
int32 MBRK = 0; /* 11/70 microbreak */
|
||||||
|
int32 CPUERR = 0; /* CPU error reg */
|
||||||
|
int32 MEMERR = 0; /* memory error reg */
|
||||||
|
int32 CCR = 0; /* cache control reg */
|
||||||
|
int32 HITMISS = 0; /* hit/miss reg */
|
||||||
|
int32 MAINT = 0; /* maint reg */
|
||||||
|
int32 JCSR = 0; /* J11 control */
|
||||||
|
int32 JPCR = 0; /* J11 page ctrl */
|
||||||
|
int32 JASR = 0; /* J11 addtl status */
|
||||||
|
int32 UDCR = 0; /* UBA diag ctrl */
|
||||||
|
int32 UDDR = 0; /* UBA diag data */
|
||||||
|
int32 UCSR = 0; /* UBA control */
|
||||||
|
int32 uba_last = 0; /* UBA last mapped */
|
||||||
|
int32 ub_map[UBM_LNT_LW] = { 0 }; /* UBA map array */
|
||||||
|
int32 toy_state = 0;
|
||||||
|
uint8 toy_data[TOY_LNT] = { 0 };
|
||||||
|
static int32 clk_tps_map[4] = { 60, 60, 50, 800 };
|
||||||
|
|
||||||
|
extern uint16 *M;
|
||||||
|
extern int32 R[8];
|
||||||
|
extern DEVICE cpu_dev, *sim_devices[];
|
||||||
|
extern UNIT cpu_unit;
|
||||||
|
extern FILE *sim_log;
|
||||||
|
extern int32 STKLIM, PIRQ;
|
||||||
|
extern int32 cpu_model, cpu_type, cpu_opt;
|
||||||
|
extern int32 clk_fie, clk_fnxm, clk_tps, clk_default;
|
||||||
|
|
||||||
|
t_stat CPU24_rd (int32 *data, int32 addr, int32 access);
|
||||||
|
t_stat CPU24_wr (int32 data, int32 addr, int32 access);
|
||||||
|
t_stat CPU44_rd (int32 *data, int32 addr, int32 access);
|
||||||
|
t_stat CPU44_wr (int32 data, int32 addr, int32 access);
|
||||||
|
t_stat CPU45_rd (int32 *data, int32 addr, int32 access);
|
||||||
|
t_stat CPU45_wr (int32 data, int32 addr, int32 access);
|
||||||
|
t_stat CPU60_rd (int32 *data, int32 addr, int32 access);
|
||||||
|
t_stat CPU60_wr (int32 data, int32 addr, int32 access);
|
||||||
|
t_stat CPU70_rd (int32 *data, int32 addr, int32 access);
|
||||||
|
t_stat CPU70_wr (int32 data, int32 addr, int32 access);
|
||||||
|
t_stat CPUJ_rd (int32 *data, int32 addr, int32 access);
|
||||||
|
t_stat CPUJ_wr (int32 data, int32 addr, int32 access);
|
||||||
|
t_stat REG_rd (int32 *data, int32 addr, int32 access);
|
||||||
|
t_stat REG_wr (int32 data, int32 addr, int32 access);
|
||||||
|
t_stat SR_rd (int32 *data, int32 addr, int32 access);
|
||||||
|
t_stat DR_wr (int32 data, int32 addr, int32 access);
|
||||||
|
t_stat CTLFB_rd (int32 *data, int32 addr, int32 access);
|
||||||
|
t_stat CTLFB_wr (int32 data, int32 addr, int32 access);
|
||||||
|
t_stat CTLJB_rd (int32 *data, int32 addr, int32 access);
|
||||||
|
t_stat CTLJB_wr (int32 data, int32 addr, int32 access);
|
||||||
|
t_stat CTLJD_rd (int32 *data, int32 addr, int32 access);
|
||||||
|
t_stat CTLJD_wr (int32 data, int32 addr, int32 access);
|
||||||
|
t_stat CTLJE_rd (int32 *data, int32 addr, int32 access);
|
||||||
|
t_stat CTLJE_wr (int32 data, int32 addr, int32 access);
|
||||||
|
t_stat UBA24_rd (int32 *data, int32 addr, int32 access);
|
||||||
|
t_stat UBA24_wr (int32 data, int32 addr, int32 access);
|
||||||
|
t_stat UBAJ_rd (int32 *data, int32 addr, int32 access);
|
||||||
|
t_stat UBAJ_wr (int32 data, int32 addr, int32 access);
|
||||||
|
t_stat sys_reset (DEVICE *dptr);
|
||||||
|
int32 toy_read (void);
|
||||||
|
void toy_write (int32 bit);
|
||||||
|
uint8 toy_set (int32 val);
|
||||||
|
|
||||||
|
extern t_stat PSW_rd (int32 *data, int32 addr, int32 access);
|
||||||
|
extern t_stat PSW_wr (int32 data, int32 addr, int32 access);
|
||||||
|
extern t_stat APR_rd (int32 *data, int32 addr, int32 access);
|
||||||
|
extern t_stat APR_wr (int32 data, int32 addr, int32 access);
|
||||||
|
extern t_stat MMR012_rd (int32 *data, int32 addr, int32 access);
|
||||||
|
extern t_stat MMR012_wr (int32 data, int32 addr, int32 access);
|
||||||
|
extern t_stat MMR3_rd (int32 *data, int32 addr, int32 access);
|
||||||
|
extern t_stat MMR3_wr (int32 data, int32 addr, int32 access);
|
||||||
|
extern t_stat ubm_rd (int32 *data, int32 addr, int32 access);
|
||||||
|
extern t_stat ubm_wr (int32 data, int32 addr, int32 access);
|
||||||
|
extern void put_PIRQ (int32 val);
|
||||||
|
|
||||||
|
/* Fixed I/O address table entries */
|
||||||
|
|
||||||
|
DIB psw_dib = { IOBA_PSW, IOLN_PSW, &PSW_rd, &PSW_wr, 0 };
|
||||||
|
DIB cpuj_dib = { IOBA_CPU, IOLN_CPU, &CPUJ_rd, &CPUJ_wr, 0 };
|
||||||
|
DIB cpu24_dib = { IOBA_CPU, IOLN_CPU, &CPU24_rd, &CPU24_wr, 0 };
|
||||||
|
DIB cpu44_dib = { IOBA_CPU, IOLN_CPU, &CPU44_rd, &CPU44_wr, 0 };
|
||||||
|
DIB cpu45_dib = { IOBA_CPU, IOLN_CPU, &CPU45_rd, &CPU45_wr, 0 };
|
||||||
|
DIB cpu60_dib = { IOBA_CPU, IOLN_CPU, &CPU60_rd, &CPU60_wr, 0 };
|
||||||
|
DIB cpu70_dib = { IOBA_CPU, IOLN_CPU, &CPU70_rd, &CPU70_wr, 0 };
|
||||||
|
DIB reg_dib = { IOBA_GPR, IOLN_GPR, ®_rd, ®_wr, 0 };
|
||||||
|
DIB ctlfb_dib = { IOBA_CTL, IOLN_CTL, &CTLFB_rd, &CTLFB_wr };
|
||||||
|
DIB ctljb_dib = { IOBA_CTL, IOLN_CTL, &CTLJB_rd, &CTLJB_wr };
|
||||||
|
DIB ctljd_dib = { IOBA_CTL, IOLN_CTL, &CTLJD_rd, &CTLJD_wr };
|
||||||
|
DIB ctlje_dib = { IOBA_CTL, IOLN_CTL, &CTLJE_rd, &CTLJE_wr };
|
||||||
|
DIB uba24_dib = { IOBA_UCTL, IOLN_UCTL, &UBA24_rd, &UBA24_wr };
|
||||||
|
DIB ubaj_dib = {IOBA_UCTL, IOLN_UCTL, &UBAJ_rd, &UBAJ_wr };
|
||||||
|
DIB supv_dib = { IOBA_SUP, IOLN_SUP, &APR_rd, &APR_wr, 0 };
|
||||||
|
DIB kipdr_dib = { IOBA_KIPDR, IOLN_KIPDR, &APR_rd, &APR_wr, 0 };
|
||||||
|
DIB kdpdr_dib = { IOBA_KDPDR, IOLN_KDPDR, &APR_rd, &APR_wr, 0 };
|
||||||
|
DIB kipar_dib = { IOBA_KIPAR, IOLN_KIPAR, &APR_rd, &APR_wr, 0 };
|
||||||
|
DIB kdpar_dib = { IOBA_KDPAR, IOLN_KDPAR, &APR_rd, &APR_wr, 0 };
|
||||||
|
DIB uipdr_dib = { IOBA_UIPDR, IOLN_UIPDR, &APR_rd, &APR_wr, 0 };
|
||||||
|
DIB udpdr_dib = { IOBA_UDPDR, IOLN_UDPDR, &APR_rd, &APR_wr, 0 };
|
||||||
|
DIB uipar_dib = { IOBA_UIPAR, IOLN_UIPAR, &APR_rd, &APR_wr, 0 };
|
||||||
|
DIB udpar_dib = { IOBA_UDPAR, IOLN_UDPAR, &APR_rd, &APR_wr, 0 };
|
||||||
|
DIB sr_dib = { IOBA_SR, IOLN_SR, &SR_rd, NULL, 0 };
|
||||||
|
DIB dr_dib = { IOBA_SR, IOLN_SR, NULL, &DR_wr, 0 };
|
||||||
|
DIB mmr012_dib = { IOBA_MMR012, IOLN_MMR012, &MMR012_rd, &MMR012_wr, 0 };
|
||||||
|
DIB mmr3_dib = { IOBA_MMR3, IOLN_MMR3, &MMR3_rd, &MMR3_wr, 0 };
|
||||||
|
DIB ubm_dib = { IOBA_UBM, IOLN_UBM, &ubm_rd, &ubm_wr, 0 };
|
||||||
|
|
||||||
|
CPUTAB cpu_tab[MOD_MAX] = {
|
||||||
|
{ "11/03", SOP_1103, OPT_1103, MEMSIZE64K, PSW_1103,
|
||||||
|
0, 0, 0, 0, 0 },
|
||||||
|
{ "11/04", SOP_1104, OPT_1104, MEMSIZE64K, PSW_1104,
|
||||||
|
0, 0, 0, 0, 0 },
|
||||||
|
{ "11/05", SOP_1105, OPT_1105, MEMSIZE64K, PSW_1105,
|
||||||
|
0, 0, 0, 0, 0 },
|
||||||
|
{ "11/20", SOP_1120, OPT_1120, MEMSIZE64K, PSW_1120,
|
||||||
|
0, 0, 0, 0, 0 },
|
||||||
|
{ "11/23", SOP_1123, OPT_1123, MAXMEMSIZE, PSW_F,
|
||||||
|
MFPT_F, PAR_F, PDR_F, MM0_F, MM3_F },
|
||||||
|
{ "11/23+", SOP_1123P, OPT_1123P, MAXMEMSIZE, PSW_F,
|
||||||
|
MFPT_F, PAR_F, PDR_F, MM0_F, MM3_F },
|
||||||
|
{ "11/24", SOP_1124, OPT_1124, MAXMEMSIZE, PSW_F,
|
||||||
|
MFPT_F, PAR_F, PDR_F, MM0_F, MM3_F },
|
||||||
|
{ "11/34", SOP_1134, OPT_1134, UNIMEMSIZE, PSW_1134,
|
||||||
|
0, PAR_1134, PDR_1134, MM0_1134, 0 },
|
||||||
|
{ "11/40", SOP_1140, OPT_1140, UNIMEMSIZE, PSW_1140,
|
||||||
|
0, PAR_1140, PDR_1140, MM0_1140, 0 },
|
||||||
|
{ "11/44", SOP_1144, OPT_1144, MAXMEMSIZE, PSW_1144,
|
||||||
|
MFPT_44, PAR_1144, PDR_1144, MM0_1144, MM3_1144 },
|
||||||
|
{ "11/45", SOP_1145, OPT_1145, UNIMEMSIZE, PSW_1145,
|
||||||
|
0, PAR_1145, PDR_1145, MM0_1145, MM3_1145 },
|
||||||
|
{ "11/60", SOP_1160, OPT_1160, UNIMEMSIZE, PSW_1160,
|
||||||
|
0, PAR_1160, PDR_1160, MM0_1160, 0 },
|
||||||
|
{ "11/70", SOP_1170, OPT_1170, MAXMEMSIZE, PSW_1170,
|
||||||
|
0, PAR_1170, PDR_1170, MM0_1170, MM3_1170 },
|
||||||
|
{ "11/73", SOP_1173, OPT_1173, MAXMEMSIZE, PSW_J,
|
||||||
|
MFPT_J, PAR_J, PDR_J, MM0_J, MM3_J },
|
||||||
|
{ "11/53", SOP_1153, OPT_1153, MAXMEMSIZE, PSW_J,
|
||||||
|
MFPT_J, PAR_J, PDR_J, MM0_J, MM3_J },
|
||||||
|
{ "11/73B", SOP_1173B, OPT_1173B, MAXMEMSIZE, PSW_J,
|
||||||
|
MFPT_J, PAR_J, PDR_J, MM0_J, MM3_J },
|
||||||
|
{ "11/83", SOP_1183, OPT_1183, MAXMEMSIZE, PSW_J,
|
||||||
|
MFPT_J, PAR_J, PDR_J, MM0_J, MM3_J },
|
||||||
|
{ "11/84", SOP_1184, OPT_1184, MAXMEMSIZE, PSW_J,
|
||||||
|
MFPT_J, PAR_J, PDR_J, MM0_J, MM3_J },
|
||||||
|
{ "11/93", SOP_1193, OPT_1193, MAXMEMSIZE, PSW_J,
|
||||||
|
MFPT_J, PAR_J, PDR_J, MM0_J, MM3_J },
|
||||||
|
{ "11/94", SOP_1194, OPT_1194, MAXMEMSIZE, PSW_J,
|
||||||
|
MFPT_J, PAR_J, PDR_J, MM0_J, MM3_J } };
|
||||||
|
|
||||||
|
CNFTAB cnf_tab[] = {
|
||||||
|
{ HAS_PSW, 0, &psw_dib }, /* PSW */
|
||||||
|
{ CPUT_J, 0, &cpuj_dib }, /* CPU control */
|
||||||
|
{ CPUT_24, 0, &cpu24_dib },
|
||||||
|
{ CPUT_44, 0, &cpu44_dib },
|
||||||
|
{ CPUT_45, 0, &cpu45_dib },
|
||||||
|
{ CPUT_60, 0, &cpu60_dib },
|
||||||
|
{ CPUT_70, 0, &cpu70_dib },
|
||||||
|
{ HAS_IOSR, 0, ®_dib },
|
||||||
|
{ CPUT_23P, 0, &ctlfb_dib }, /* board ctls */
|
||||||
|
{ CPUT_JB, 0, &ctljb_dib },
|
||||||
|
{ CPUT_53, 0, &ctljd_dib },
|
||||||
|
{ CPUT_JE, 0, &ctlje_dib },
|
||||||
|
{ CPUT_24, 0, &uba24_dib }, /* UBA */
|
||||||
|
{ CPUT_JU, 0, &ubaj_dib },
|
||||||
|
{ 0, OPT_MMU, &kipdr_dib }, /* MMU */
|
||||||
|
{ 0, OPT_MMU, &kipar_dib },
|
||||||
|
{ 0, OPT_MMU, &uipdr_dib },
|
||||||
|
{ 0, OPT_MMU, &uipar_dib },
|
||||||
|
{ 0, OPT_MMU, &mmr012_dib }, /* MMR0-2 */
|
||||||
|
{ HAS_MMR3, 0, &mmr3_dib }, /* MMR3 */
|
||||||
|
{ 0, OPT_UBM, &ubm_dib }, /* Unibus map */
|
||||||
|
{ HAS_SID, 0, &kdpdr_dib }, /* supv, I/D */
|
||||||
|
{ HAS_SID, 0, &kdpar_dib },
|
||||||
|
{ HAS_SID, 0, &supv_dib },
|
||||||
|
{ HAS_SID, 0, &udpdr_dib },
|
||||||
|
{ HAS_SID, 0, &udpar_dib },
|
||||||
|
{ HAS_SR, 0, &sr_dib }, /* SR */
|
||||||
|
{ HAS_DR, 0, &dr_dib }, /* DR */
|
||||||
|
{ 0, 0, NULL } };
|
||||||
|
|
||||||
|
static const char *opt_name[] = {
|
||||||
|
"Unibus", "Qbus", "EIS", "NOEIS", "FIS", "NOFIS",
|
||||||
|
"FPP", "NOFPP", "CIS", "NOCIS", "MMU", "NOMMU",
|
||||||
|
"RH11", "RH70", "PARITY", "NOPARITY", "Unibus map", "No map", NULL };
|
||||||
|
|
||||||
|
/* SYSTEM data structures
|
||||||
|
|
||||||
|
sys_dev SYSTEM device descriptor
|
||||||
|
sys_unit SYSTEM unit descriptor
|
||||||
|
sys_reg SYSTEM register list
|
||||||
|
*/
|
||||||
|
|
||||||
|
UNIT sys_unit = { UDATA (NULL, 0, 0) };
|
||||||
|
|
||||||
|
REG sys_reg[] = {
|
||||||
|
{ ORDATA (SR, SR, 16) },
|
||||||
|
{ ORDATA (DR, DR, 16) },
|
||||||
|
{ ORDATA (MEMERR, MEMERR, 16) },
|
||||||
|
{ ORDATA (CCR, CCR, 16) },
|
||||||
|
{ ORDATA (MAINT, MAINT, 16) },
|
||||||
|
{ ORDATA (HITMISS, HITMISS, 16) },
|
||||||
|
{ ORDATA (CPUERR, CPUERR, 16) },
|
||||||
|
{ ORDATA (MBRK, MBRK, 16) },
|
||||||
|
{ ORDATA (JCSR, JCSR, 16) },
|
||||||
|
{ ORDATA (JPCR, JPCR, 16) },
|
||||||
|
{ ORDATA (JASR, JASR, 16) },
|
||||||
|
{ ORDATA (UDCR, UDCR, 16) },
|
||||||
|
{ ORDATA (UDDR, UDDR, 16) },
|
||||||
|
{ ORDATA (UCSR, UCSR, 16) },
|
||||||
|
{ ORDATA (ULAST, uba_last, 23) },
|
||||||
|
{ BRDATA (UBMAP, ub_map, 8, 22, UBM_LNT_LW) },
|
||||||
|
{ DRDATA (TOY_STATE, toy_state, 6), REG_HRO },
|
||||||
|
{ BRDATA (TOY_DATA, toy_data, 8, 8, TOY_LNT), REG_HRO },
|
||||||
|
{ NULL} };
|
||||||
|
|
||||||
|
DEVICE sys_dev = {
|
||||||
|
"SYSTEM", &sys_unit, sys_reg, NULL,
|
||||||
|
1, 0, 0, 0, 0, 0,
|
||||||
|
NULL, NULL, &sys_reset,
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
NULL, 0, 0,
|
||||||
|
NULL, NULL, NULL };
|
||||||
|
|
||||||
|
/* Switch and display registers - many */
|
||||||
|
|
||||||
|
t_stat SR_rd (int32 *data, int32 pa, int32 access)
|
||||||
|
{
|
||||||
|
*data = SR;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat DR_wr (int32 data, int32 pa, int32 access)
|
||||||
|
{
|
||||||
|
DR = data;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GPR's - 11/04, 11/05 */
|
||||||
|
|
||||||
|
t_stat REG_rd (int32 *data, int32 pa, int32 access)
|
||||||
|
{
|
||||||
|
*data = R[pa & 07];
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat REG_wr (int32 data, int32 pa, int32 access)
|
||||||
|
{
|
||||||
|
int32 reg = pa & 07;
|
||||||
|
|
||||||
|
if (access == WRITE) R[reg] = data;
|
||||||
|
else if (pa & 1) R[reg] = (R[reg] & 0377) | (data << 8);
|
||||||
|
else R[reg] = (R[reg] & ~0377) | data;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CPU control registers - 11/24 */
|
||||||
|
|
||||||
|
t_stat CPU24_rd (int32 *data, int32 pa, int32 access)
|
||||||
|
{
|
||||||
|
switch ((pa >> 1) & 017) { /* decode pa<4:1> */
|
||||||
|
case 013: /* CPUERR */
|
||||||
|
*data = 0;
|
||||||
|
return SCPE_OK; } /* end switch PA */
|
||||||
|
*data = 0;
|
||||||
|
return SCPE_NXM; /* unimplemented */
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat CPU24_wr (int32 data, int32 pa, int32 access)
|
||||||
|
{
|
||||||
|
switch ((pa >> 1) & 017) { /* decode pa<4:1> */
|
||||||
|
case 013: /* CPUERR */
|
||||||
|
return SCPE_OK; } /* end switch pa */
|
||||||
|
return SCPE_NXM; /* unimplemented */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CPU control registers - 11/44 */
|
||||||
|
|
||||||
|
t_stat CPU44_rd (int32 *data, int32 pa, int32 access)
|
||||||
|
{
|
||||||
|
switch ((pa >> 1) & 017) { /* decode pa<4:1> */
|
||||||
|
case 2: /* MEMERR */
|
||||||
|
*data = MEMERR;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 3: /* CCR */
|
||||||
|
*data = CCR & CCR44_RD;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 4: /* MAINT */
|
||||||
|
*data = MAINT & CMR44_RD;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 5: /* Hit/miss */
|
||||||
|
*data = HITMISS;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 6: /* CDR */
|
||||||
|
*data = 0;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 013: /* CPUERR */
|
||||||
|
if (CPUERR & CPUE_YEL) /* 11/44 stack err */
|
||||||
|
CPUERR = (CPUERR & ~CPUE_YEL) | CPUE_RED; /* in <2> not <3> */
|
||||||
|
if (CPUERR & (CPUE_ODD|CPUE_NXM|CPUE_TMO)) /* additional flag */
|
||||||
|
CPUERR = CPUERR | CPUE44_BUSE;
|
||||||
|
*data = CPUERR & CPUE_IMP;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 015: /* PIRQ */
|
||||||
|
*data = PIRQ;
|
||||||
|
return SCPE_OK; } /* end switch PA */
|
||||||
|
*data = 0;
|
||||||
|
return SCPE_NXM; /* unimplemented */
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat CPU44_wr (int32 data, int32 pa, int32 access)
|
||||||
|
{
|
||||||
|
switch ((pa >> 1) & 017) { /* decode pa<4:1> */
|
||||||
|
case 2: /* MEMERR */
|
||||||
|
MEMERR = 0;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 3: /* CCR */
|
||||||
|
ODD_MRG (CCR, data);
|
||||||
|
CCR = data & CCR44_WR;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 4: /* MAINT */
|
||||||
|
ODD_MRG (MAINT, data);
|
||||||
|
MAINT = data & CMR44_WR;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 5: /* Hit/miss */
|
||||||
|
return SCPE_OK;
|
||||||
|
case 013: /* CPUERR */
|
||||||
|
CPUERR = 0;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 015: /* PIRQ */
|
||||||
|
ODD_WO (data);
|
||||||
|
put_PIRQ (data);
|
||||||
|
return SCPE_OK; }
|
||||||
|
return SCPE_NXM; /* unimplemented */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CPU control registers - 11/45 */
|
||||||
|
|
||||||
|
t_stat CPU45_rd (int32 *data, int32 pa, int32 access)
|
||||||
|
{
|
||||||
|
switch ((pa >> 1) & 017) { /* decode pa<4:1> */
|
||||||
|
case 014: /* MBRK */
|
||||||
|
*data = MBRK;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 015: /* PIRQ */
|
||||||
|
*data = PIRQ;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 016: /* STKLIM */
|
||||||
|
*data = STKLIM & STKLIM_RW;
|
||||||
|
return SCPE_OK; } /* end switch PA */
|
||||||
|
*data = 0;
|
||||||
|
return SCPE_NXM; /* unimplemented */
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat CPU45_wr (int32 data, int32 pa, int32 access)
|
||||||
|
{
|
||||||
|
switch ((pa >> 1) & 017) { /* decode pa<4:1> */
|
||||||
|
case 015: /* PIRQ */
|
||||||
|
ODD_WO (data);
|
||||||
|
put_PIRQ (data);
|
||||||
|
return SCPE_OK;
|
||||||
|
case 016: /* STKLIM */
|
||||||
|
ODD_WO (data);
|
||||||
|
STKLIM = data & STKLIM_RW;
|
||||||
|
return SCPE_OK; } /* end switch pa */
|
||||||
|
return SCPE_NXM; /* unimplemented */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CPU control registers - 11/60 */
|
||||||
|
|
||||||
|
t_stat CPU60_rd (int32 *data, int32 pa, int32 access)
|
||||||
|
{
|
||||||
|
switch ((pa >> 1) & 017) { /* decode pa<4:1> */
|
||||||
|
case 2: /* MEMERR */
|
||||||
|
*data = MEMERR;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 3: /* CCR */
|
||||||
|
*data = CCR;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 5: /* Hit/miss */
|
||||||
|
*data = HITMISS;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 016: /* STKLIM */
|
||||||
|
*data = STKLIM & STKLIM_RW;
|
||||||
|
return SCPE_OK; } /* end switch PA */
|
||||||
|
*data = 0;
|
||||||
|
return SCPE_NXM; /* unimplemented */
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat CPU60_wr (int32 data, int32 pa, int32 access)
|
||||||
|
{
|
||||||
|
switch ((pa >> 1) & 017) { /* decode pa<4:1> */
|
||||||
|
case 2: /* MEMERR */
|
||||||
|
MEMERR = 0;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 3: /* CCR */
|
||||||
|
ODD_MRG (CCR, data);
|
||||||
|
CCR = data;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 5: /* Hit/miss */
|
||||||
|
return SCPE_OK;
|
||||||
|
case 016: /* STKLIM */
|
||||||
|
ODD_WO (data);
|
||||||
|
STKLIM = data & STKLIM_RW;
|
||||||
|
return SCPE_OK; } /* end switch pa */
|
||||||
|
return SCPE_NXM; /* unimplemented */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CPU control registers - 11/70 */
|
||||||
|
|
||||||
|
t_stat CPU70_rd (int32 *data, int32 pa, int32 access)
|
||||||
|
{
|
||||||
|
switch ((pa >> 1) & 017) { /* decode pa<4:1> */
|
||||||
|
case 0: case 1: case 011: /* LO,HI ERR, HI SIZE */
|
||||||
|
*data = 0;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 2: /* MEMERR */
|
||||||
|
*data = MEMERR;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 3: /* CCR */
|
||||||
|
*data = CCR;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 4: /* MAINT */
|
||||||
|
*data = 0;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 5: /* Hit/miss */
|
||||||
|
*data = HITMISS;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 010: /* lower size */
|
||||||
|
*data = (MEMSIZE >> 6) - 1;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 012: /* system ID */
|
||||||
|
*data = 0x1234;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 013: /* CPUERR */
|
||||||
|
*data = CPUERR & CPUE_IMP;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 014: /* MBRK */
|
||||||
|
*data = MBRK;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 015: /* PIRQ */
|
||||||
|
*data = PIRQ;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 016: /* STKLIM */
|
||||||
|
*data = STKLIM & STKLIM_RW;
|
||||||
|
return SCPE_OK; } /* end switch PA */
|
||||||
|
*data = 0;
|
||||||
|
return SCPE_NXM; /* unimplemented */
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat CPU70_wr (int32 data, int32 pa, int32 access)
|
||||||
|
{
|
||||||
|
switch ((pa >> 1) & 017) { /* decode pa<4:1> */
|
||||||
|
case 2: /* MEMERR */
|
||||||
|
ODD_WO (data);
|
||||||
|
MEMERR = MEMERR & ~data;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 3: /* CCR */
|
||||||
|
ODD_MRG (CCR, data);
|
||||||
|
CCR = data;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 4: /* MAINT */
|
||||||
|
return SCPE_OK;
|
||||||
|
case 5: /* Hit/miss */
|
||||||
|
return SCPE_OK;
|
||||||
|
case 013: /* CPUERR */
|
||||||
|
CPUERR = 0;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 015: /* PIRQ */
|
||||||
|
ODD_WO (data);
|
||||||
|
put_PIRQ (data);
|
||||||
|
return SCPE_OK;
|
||||||
|
case 016: /* STKLIM */
|
||||||
|
ODD_WO (data);
|
||||||
|
STKLIM = data & STKLIM_RW;
|
||||||
|
return SCPE_OK; } /* end switch pa */
|
||||||
|
return SCPE_NXM; /* unimplemented */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CPU control registers - J11 */
|
||||||
|
|
||||||
|
t_stat CPUJ_rd (int32 *data, int32 pa, int32 access)
|
||||||
|
{
|
||||||
|
switch ((pa >> 1) & 017) { /* decode pa<4:1> */
|
||||||
|
case 2: /* MEMERR */
|
||||||
|
*data = MEMERR;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 3: /* CCR */
|
||||||
|
*data = CCR;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 4: /* MAINT */
|
||||||
|
*data = MAINT | MAINT_NOFPA | MAINT_BPOK | (UNIBUS? MAINT_U: MAINT_Q);
|
||||||
|
if (CPUT (CPUT_53)) *data |= MAINT_KDJD | MAINT_POROM;
|
||||||
|
if (CPUT (CPUT_73)) *data |= MAINT_KDJA | MAINT_POODT;
|
||||||
|
if (CPUT (CPUT_73B|CPUT_83|CPUT_84)) *data |= MAINT_KDJB | MAINT_POROM;
|
||||||
|
if (CPUT (CPUT_93|CPUT_94)) *data |= MAINT_KDJE | MAINT_POROM;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 5: /* Hit/miss */
|
||||||
|
if (CPUT (CPUT_73B)) *data = 0; /* must be 0 for 73B */
|
||||||
|
else *data = HITMISS | 010; /* must be nz for 11/8X */
|
||||||
|
return SCPE_OK;
|
||||||
|
case 013: /* CPUERR */
|
||||||
|
*data = CPUERR & CPUE_IMP;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 015: /* PIRQ */
|
||||||
|
*data = PIRQ;
|
||||||
|
return SCPE_OK; } /* end switch PA */
|
||||||
|
*data = 0;
|
||||||
|
return SCPE_NXM; /* unimplemented */
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat CPUJ_wr (int32 data, int32 pa, int32 access)
|
||||||
|
{
|
||||||
|
switch ((pa >> 1) & 017) { /* decode pa<4:1> */
|
||||||
|
case 2: /* MEMERR */
|
||||||
|
MEMERR = 0;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 3: /* CCR */
|
||||||
|
ODD_MRG (CCR, data);
|
||||||
|
CCR = data;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 4: /* MAINT */
|
||||||
|
return SCPE_OK;
|
||||||
|
case 5: /* Hit/miss */
|
||||||
|
return SCPE_OK;
|
||||||
|
case 013: /* CPUERR */
|
||||||
|
CPUERR = 0;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 015: /* PIRQ */
|
||||||
|
ODD_WO (data);
|
||||||
|
put_PIRQ (data);
|
||||||
|
return SCPE_OK; } /* end switch pa */
|
||||||
|
return SCPE_NXM; /* unimplemented */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Board control registers - KDF11B */
|
||||||
|
|
||||||
|
t_stat CTLFB_rd (int32 *data, int32 pa, int32 access)
|
||||||
|
{
|
||||||
|
switch ((pa >> 1) & 03) { /* decode pa<2:1> */
|
||||||
|
case 0: /* PCR */
|
||||||
|
*data = JPCR & PCRFB_RW;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 1: /* MAINT */
|
||||||
|
*data = MAINT;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 2: /* CDR */
|
||||||
|
*data = SR & CDRFB_RD;
|
||||||
|
return SCPE_OK; }
|
||||||
|
*data = 0;
|
||||||
|
return SCPE_NXM;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat CTLFB_wr (int32 data, int32 pa, int32 access)
|
||||||
|
{
|
||||||
|
switch ((pa >> 1) & 03) { /* decode pa<2:1> */
|
||||||
|
case 0: /* PCR */
|
||||||
|
ODD_MRG (JPCR, data);
|
||||||
|
JPCR = data & PCRFB_RW;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 1: /* MAINT */
|
||||||
|
ODD_MRG (MAINT, data);
|
||||||
|
MAINT = data;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 2: /* CDR */
|
||||||
|
ODD_WO (data);
|
||||||
|
DR = data & CDRFB_WR;
|
||||||
|
return SCPE_OK; }
|
||||||
|
return SCPE_NXM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Board control registers - KDJ11B */
|
||||||
|
|
||||||
|
t_stat CTLJB_rd (int32 *data, int32 pa, int32 access)
|
||||||
|
{
|
||||||
|
switch ((pa >> 1) & 03) { /* decode pa<2:1> */
|
||||||
|
case 0: /* CSR */
|
||||||
|
*data = JCSR & CSRJB_RD;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 1: /* PCR */
|
||||||
|
*data = JPCR & PCRJB_RW;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 2: /* CDR */
|
||||||
|
*data = SR & CDRJB_RD;
|
||||||
|
return SCPE_OK; }
|
||||||
|
*data = 0;
|
||||||
|
return SCPE_NXM;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat CTLJB_wr (int32 data, int32 pa, int32 access)
|
||||||
|
{
|
||||||
|
int32 t;
|
||||||
|
|
||||||
|
switch ((pa >> 1) & 03) { /* decode pa<2:1> */
|
||||||
|
case 0: /* CSR */
|
||||||
|
ODD_MRG (JCSR, data);
|
||||||
|
JCSR = (JCSR & ~CSRJB_WR) | (data & CSRJB_WR);
|
||||||
|
if (JCSR & CSRJ_LTCI) clk_fie = 1; /* force LTC int enb? */
|
||||||
|
else clk_fie = 0;
|
||||||
|
if (JCSR & CSRJ_LTCD) clk_fnxm = 1; /* force LTC reg nxm? */
|
||||||
|
else clk_fnxm = 0;
|
||||||
|
t = CSRJ_LTCSEL (JCSR); /* get freq sel */
|
||||||
|
if (t) clk_tps = clk_tps_map[t];
|
||||||
|
else clk_tps = clk_default;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 1: /* PCR */
|
||||||
|
ODD_MRG (JPCR, data);
|
||||||
|
JPCR = data & PCRJB_RW;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 2: /* CDR */
|
||||||
|
ODD_WO (data);
|
||||||
|
DR = data & CDRJB_WR;
|
||||||
|
return SCPE_OK; }
|
||||||
|
return SCPE_NXM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Board control registers - KDJ11D */
|
||||||
|
|
||||||
|
t_stat CTLJD_rd (int32 *data, int32 pa, int32 access)
|
||||||
|
{
|
||||||
|
switch ((pa >> 1) & 03) { /* decode pa<2:1> */
|
||||||
|
case 0: /* CSR */
|
||||||
|
*data = JCSR & CSRJD_RD;
|
||||||
|
return SCPE_OK; }
|
||||||
|
*data = 0;
|
||||||
|
return SCPE_NXM;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat CTLJD_wr (int32 data, int32 pa, int32 access)
|
||||||
|
{
|
||||||
|
switch ((pa >> 1) & 03) { /* decode pa<2:1> */
|
||||||
|
case 0: /* CSR */
|
||||||
|
ODD_MRG (JCSR, data);
|
||||||
|
JCSR = (JCSR & ~CSRJD_WR) | (data & CSRJD_WR);
|
||||||
|
return SCPE_OK; }
|
||||||
|
return SCPE_NXM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Board control registers - KDJ11E */
|
||||||
|
|
||||||
|
t_stat CTLJE_rd (int32 *data, int32 pa, int32 access)
|
||||||
|
{
|
||||||
|
switch ((pa >> 1) & 03) { /* decode pa<2:1> */
|
||||||
|
case 0: /* CSR */
|
||||||
|
*data = JCSR & CSRJE_RD;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 1: /* PCR */
|
||||||
|
*data = JPCR & PCRJE_RW;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 2: /* CDR */
|
||||||
|
*data = SR & CDRJE_RD;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 3: /* ASR */
|
||||||
|
JASR = (JASR & ~ASRJE_TOY) | (toy_read () << ASRJE_V_TOY);
|
||||||
|
*data = JASR & ASRJE_RW;
|
||||||
|
return SCPE_OK; }
|
||||||
|
*data = 0;
|
||||||
|
return SCPE_NXM;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat CTLJE_wr (int32 data, int32 pa, int32 access)
|
||||||
|
{
|
||||||
|
int32 t;
|
||||||
|
|
||||||
|
switch ((pa >> 1) & 03) { /* decode pa<2:1> */
|
||||||
|
case 0: /* CSR */
|
||||||
|
ODD_MRG (JCSR, data);
|
||||||
|
JCSR = (JCSR & ~CSRJE_WR) | (data & CSRJE_WR);
|
||||||
|
if (JCSR & CSRJ_LTCI) clk_fie = 1; /* force LTC int enb? */
|
||||||
|
else clk_fie = 0;
|
||||||
|
if (JCSR & CSRJ_LTCD) clk_fnxm = 1; /* force LTC reg nxm? */
|
||||||
|
else clk_fnxm = 0;
|
||||||
|
t = CSRJ_LTCSEL (JCSR); /* get freq sel */
|
||||||
|
if (t) clk_tps = clk_tps_map[t];
|
||||||
|
else clk_tps = clk_default;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 1: /* PCR */
|
||||||
|
ODD_MRG (JPCR, data);
|
||||||
|
JPCR = data & PCRJE_RW;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 2: /* CDR */
|
||||||
|
ODD_WO (data);
|
||||||
|
DR = data & CDRJE_WR;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 3: /* ASR */
|
||||||
|
ODD_MRG (JASR, data);
|
||||||
|
JASR = data & ASRJE_RW;
|
||||||
|
toy_write (ASRJE_TOYBIT (JASR));
|
||||||
|
return SCPE_OK; }
|
||||||
|
return SCPE_NXM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unibus adapter registers - KT24 */
|
||||||
|
|
||||||
|
t_stat UBA24_rd (int32 *data, int32 pa, int32 access)
|
||||||
|
{
|
||||||
|
switch ((pa >> 1) & 03) { /* decode pa<2:1> */
|
||||||
|
case 2: /* LMAL */
|
||||||
|
*data = uba_last & LMAL_RD;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 3: /* LMAH */
|
||||||
|
*data = uba_last & LMAH_RD;
|
||||||
|
return SCPE_OK; }
|
||||||
|
*data = 0;
|
||||||
|
return SCPE_NXM;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat UBA24_wr (int32 data, int32 pa, int32 access)
|
||||||
|
{
|
||||||
|
switch ((pa >> 1) & 03) { /* decode pa<2:1> */
|
||||||
|
case 3: /* ASR */
|
||||||
|
ODD_IGN (data);
|
||||||
|
uba_last = (uba_last & ~LMAH_WR) | ((data & LMAH_WR) << 16);
|
||||||
|
return SCPE_OK; }
|
||||||
|
return SCPE_NXM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unibus registers - KTJ11B */
|
||||||
|
|
||||||
|
t_stat UBAJ_rd (int32 *data, int32 pa, int32 access)
|
||||||
|
{
|
||||||
|
switch ((pa >> 1) & 03) { /* decode pa<2:1> */
|
||||||
|
case 0: /* DCR */
|
||||||
|
*data = UDCR & DCRKTJ_RD;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 1: /* DDR */
|
||||||
|
*data = UDDR & DDRKTJ_RW;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 2: /* CSR */
|
||||||
|
*data = UCSR & MCRKTJ_RD;
|
||||||
|
return SCPE_OK; }
|
||||||
|
*data = 0;
|
||||||
|
return SCPE_NXM;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat UBAJ_wr (int32 data, int32 pa, int32 access)
|
||||||
|
{
|
||||||
|
switch ((pa >> 1) & 03) { /* decode pa<2:1> */
|
||||||
|
case 0: /* DCR */
|
||||||
|
ODD_MRG (UDCR, data);
|
||||||
|
UDCR = (UDCR & ~DCRKTJ_WR) | (data & DCRKTJ_WR);
|
||||||
|
return SCPE_OK;
|
||||||
|
case 1: /* DDR */
|
||||||
|
ODD_MRG (UDDR, data);
|
||||||
|
UDDR = data & DDRKTJ_RW;;
|
||||||
|
return SCPE_OK;
|
||||||
|
case 2: /* CSR */
|
||||||
|
ODD_MRG (UCSR, data);
|
||||||
|
UCSR = (UCSR & ~MCRKTJ_WR) | (data & MCRKTJ_WR);
|
||||||
|
return SCPE_OK; }
|
||||||
|
return SCPE_NXM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* KDJ11E TOY routines */
|
||||||
|
|
||||||
|
int32 toy_read (void)
|
||||||
|
{
|
||||||
|
time_t curr;
|
||||||
|
struct tm *ctm;
|
||||||
|
int32 bit;
|
||||||
|
|
||||||
|
if (toy_state == 0) {
|
||||||
|
curr = time (NULL); /* get curr time */
|
||||||
|
if (curr == (time_t) -1) return 0; /* error? */
|
||||||
|
ctm = localtime (&curr); /* decompose */
|
||||||
|
if (ctm == NULL) return 0; /* error? */
|
||||||
|
toy_data[TOY_HSEC] = 0x50;
|
||||||
|
toy_data[TOY_SEC] = toy_set (ctm->tm_sec);
|
||||||
|
toy_data[TOY_MIN] = toy_set (ctm->tm_min);
|
||||||
|
toy_data[TOY_HR] = toy_set (ctm->tm_hour);
|
||||||
|
toy_data[TOY_DOW] = toy_set (ctm->tm_wday);
|
||||||
|
toy_data[TOY_DOM] = toy_set (ctm->tm_mday);
|
||||||
|
toy_data[TOY_MON] = toy_set (ctm->tm_mon + 1);
|
||||||
|
toy_data[TOY_YR] = toy_set (ctm->tm_year % 100); }
|
||||||
|
bit = toy_data[toy_state >> 3] >> (toy_state & 07);
|
||||||
|
toy_state = (toy_state + 1) % (TOY_LNT * 8);
|
||||||
|
return (bit & 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void toy_write (int32 bit)
|
||||||
|
{
|
||||||
|
toy_state = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 toy_set (int32 val)
|
||||||
|
{
|
||||||
|
uint32 d1, d2;
|
||||||
|
|
||||||
|
d1 = val / 10;
|
||||||
|
d2 = val % 10;
|
||||||
|
return (uint8) ((d1 << 4) | d2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build I/O space entries for CPU */
|
||||||
|
|
||||||
|
t_stat cpu_build_dib (void)
|
||||||
|
{
|
||||||
|
int32 i;
|
||||||
|
t_stat r;
|
||||||
|
|
||||||
|
for (i = 0; cnf_tab[i].dib != NULL; i++) { /* loop thru config tab */
|
||||||
|
if (((cnf_tab[i].cpum == 0) || (cpu_type & cnf_tab[i].cpum)) &&
|
||||||
|
((cnf_tab[i].optm == 0) || (cpu_opt & cnf_tab[i].optm))) {
|
||||||
|
if (r = build_ubus_tab (&cpu_dev, cnf_tab[i].dib)) /* add to dispatch tab */
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set/show CPU model */
|
||||||
|
|
||||||
|
t_stat cpu_set_model (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
if (cptr != NULL) return SCPE_ARG;
|
||||||
|
if (val >= MOD_MAX) return SCPE_IERR;
|
||||||
|
if (val == (int32) cpu_model) return SCPE_OK;
|
||||||
|
if (MEMSIZE > cpu_tab[val].maxm)
|
||||||
|
cpu_set_size (uptr, cpu_tab[val].maxm, NULL, NULL);
|
||||||
|
if (MEMSIZE > cpu_tab[val].maxm) return SCPE_INCOMP;
|
||||||
|
cpu_model = val;
|
||||||
|
cpu_type = 1u << cpu_model;
|
||||||
|
cpu_opt = cpu_tab[cpu_model].std;
|
||||||
|
cpu_set_bus (cpu_opt);
|
||||||
|
reset_all (0); /* reset world */
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat cpu_show_model (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
|
{
|
||||||
|
uint32 i, std;
|
||||||
|
|
||||||
|
fprintf (st, "%s", cpu_tab[cpu_model].name);
|
||||||
|
std = cpu_tab[cpu_model].opt;
|
||||||
|
for (i = 0; std && opt_name[i]; i = i++) {
|
||||||
|
if ((std >> i) & 1) fprintf (st, ", %s",
|
||||||
|
((cpu_opt >> i) & 1)? opt_name[2 * i]: opt_name[(2 * i) + 1]);
|
||||||
|
}
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set/clear CPU option */
|
||||||
|
|
||||||
|
t_stat cpu_set_opt (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
if (cptr) return SCPE_ARG;
|
||||||
|
if ((val & cpu_tab[cpu_model].opt) == 0) return SCPE_ARG;
|
||||||
|
cpu_opt = cpu_opt | val;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat cpu_clr_opt (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
if (cptr) return SCPE_ARG;
|
||||||
|
if ((val & cpu_tab[cpu_model].opt) == 0) return SCPE_ARG;
|
||||||
|
cpu_opt = cpu_opt & ~val;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Memory allocation */
|
||||||
|
|
||||||
|
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
int32 mc = 0;
|
||||||
|
uint32 i, clim;
|
||||||
|
uint16 *nM;
|
||||||
|
|
||||||
|
if ((val <= 0) || (val > (int32) cpu_tab[cpu_model].maxm) ||
|
||||||
|
((val & 07777) != 0)) return SCPE_ARG;
|
||||||
|
for (i = val; i < MEMSIZE; i = i + 2) mc = mc | M[i >> 1];
|
||||||
|
if ((mc != 0) && !get_yn ("Really truncate memory [N]?", FALSE))
|
||||||
|
return SCPE_OK;
|
||||||
|
nM = calloc (val >> 1, sizeof (uint16));
|
||||||
|
if (nM == NULL) return SCPE_MEM;
|
||||||
|
clim = (((t_addr) val) < MEMSIZE)? val: MEMSIZE;
|
||||||
|
for (i = 0; i < clim; i = i + 2) nM[i >> 1] = M[i >> 1];
|
||||||
|
free (M);
|
||||||
|
M = nM;
|
||||||
|
MEMSIZE = val;
|
||||||
|
cpu_set_bus (cpu_opt);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bus configuration, disable Unibus or Qbus devices */
|
||||||
|
|
||||||
|
t_stat cpu_set_bus (int32 opt)
|
||||||
|
{
|
||||||
|
DEVICE *dptr;
|
||||||
|
uint32 i, mask;
|
||||||
|
|
||||||
|
if (opt & BUS_U) mask = DEV_UBUS; /* Unibus variant? */
|
||||||
|
else if (MEMSIZE <= UNIMEMSIZE) /* 18b Qbus devices? */
|
||||||
|
mask = DEV_QBUS | DEV_Q18;
|
||||||
|
else mask = DEV_QBUS; /* must be 22b */
|
||||||
|
for (i = 0; (dptr = sim_devices[i]) != NULL; i++) {
|
||||||
|
if ((dptr->flags & DEV_DISABLE) && /* disable-able? */
|
||||||
|
!(dptr->flags & DEV_DIS) && /* enabled? */
|
||||||
|
((dptr->flags & mask) == 0)) { /* not allowed? */
|
||||||
|
printf ("Disabling %s\n", sim_dname (dptr));
|
||||||
|
if (sim_log) fprintf (sim_log, "Disabling %s\n", sim_dname (dptr));
|
||||||
|
dptr->flags = dptr->flags | DEV_DIS; } }
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* System reset */
|
||||||
|
|
||||||
|
t_stat sys_reset (DEVICE *dptr)
|
||||||
|
{
|
||||||
|
int32 i;
|
||||||
|
|
||||||
|
CCR = 0;
|
||||||
|
HITMISS = 0;
|
||||||
|
CPUERR = 0;
|
||||||
|
MEMERR = 0;
|
||||||
|
if (!CPUT (CPUT_J)) MAINT = 0;
|
||||||
|
MBRK = 0;
|
||||||
|
JCSR = 0;
|
||||||
|
JPCR = 0;
|
||||||
|
JASR = 0;
|
||||||
|
UDCR = 0;
|
||||||
|
UDDR = 0;
|
||||||
|
UCSR = 0;
|
||||||
|
uba_last = 0;
|
||||||
|
DR = 0;
|
||||||
|
toy_state = 0;
|
||||||
|
for (i = 0; i < UBM_LNT_LW; i++) ub_map[i] = 0;
|
||||||
|
for (i = 0; i < TOY_LNT; i++) toy_data[i] = 0;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
280
PDP11/pdp11_cpumod.h
Normal file
280
PDP11/pdp11_cpumod.h
Normal file
|
@ -0,0 +1,280 @@
|
||||||
|
/* pdp11_cpumod.h: PDP-11 CPU model definitions
|
||||||
|
|
||||||
|
Copyright (c) 2004, 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"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _PDP11_CPUMOD_H_
|
||||||
|
#define _PDP11_CPUMOD_H_ 1
|
||||||
|
|
||||||
|
#define SOP_1103 (BUS_Q)
|
||||||
|
#define OPT_1103 (OPT_EIS|OPT_FIS)
|
||||||
|
#define PSW_1103 0000377
|
||||||
|
|
||||||
|
#define SOP_1104 (BUS_U)
|
||||||
|
#define OPT_1104 0
|
||||||
|
#define PSW_1104 0000377
|
||||||
|
|
||||||
|
#define SOP_1105 (BUS_U)
|
||||||
|
#define OPT_1105 0
|
||||||
|
#define PSW_1105 0000377
|
||||||
|
|
||||||
|
#define SOP_1120 (BUS_U)
|
||||||
|
#define OPT_1120 0
|
||||||
|
#define PSW_1120 0000377
|
||||||
|
|
||||||
|
#define SOP_1123 (BUS_Q|OPT_EIS|OPT_FPP|OPT_MMU)
|
||||||
|
#define OPT_1123 (OPT_FPP|OPT_CIS)
|
||||||
|
#define PSW_F 0170777
|
||||||
|
#define PAR_F 0177777
|
||||||
|
#define PDR_F 0077516
|
||||||
|
#define MM0_F 0160157
|
||||||
|
#define MM3_F 0000060
|
||||||
|
|
||||||
|
#define SOP_1123P (BUS_Q|OPT_EIS|OPT_FPP|OPT_MMU)
|
||||||
|
#define OPT_1123P (OPT_FPP|OPT_CIS)
|
||||||
|
|
||||||
|
#define SOP_1124 (BUS_U|OPT_EIS|OPT_FPP|OPT_MMU|OPT_UBM)
|
||||||
|
#define OPT_1124 (OPT_FPP|OPT_CIS)
|
||||||
|
|
||||||
|
#define SOP_1134 (BUS_U|OPT_EIS|OPT_MMU)
|
||||||
|
#define OPT_1134 (OPT_FPP)
|
||||||
|
#define PSW_1134 0170377
|
||||||
|
#define PAR_1134 0007777
|
||||||
|
#define PDR_1134 0077516
|
||||||
|
#define MM0_1134 0160557
|
||||||
|
|
||||||
|
#define SOP_1140 (BUS_U|OPT_EIS|OPT_MMU)
|
||||||
|
#define OPT_1140 (OPT_FIS)
|
||||||
|
#define PSW_1140 0170377
|
||||||
|
#define PAR_1140 0007777
|
||||||
|
#define PDR_1140 0077516
|
||||||
|
#define MM0_1140 0160557
|
||||||
|
|
||||||
|
#define SOP_1144 (BUS_U|OPT_EIS|OPT_FPP|OPT_MMU|OPT_UBM)
|
||||||
|
#define OPT_1144 (OPT_FPP|OPT_CIS)
|
||||||
|
#define PSW_1144 0170777
|
||||||
|
#define PAR_1144 0177777
|
||||||
|
#define PDR_1144 0177516
|
||||||
|
#define MM0_1144 0160557
|
||||||
|
#define MM3_1144 0000077
|
||||||
|
|
||||||
|
#define SOP_1145 (BUS_U|OPT_EIS|OPT_FPP|OPT_MMU|OPT_RH11)
|
||||||
|
#define OPT_1145 (OPT_FPP)
|
||||||
|
#define PSW_1145 0174377
|
||||||
|
#define PAR_1145 0007777
|
||||||
|
#define PDR_1145 0077717
|
||||||
|
#define MM0_1145 0171777
|
||||||
|
#define MM3_1145 0000007
|
||||||
|
|
||||||
|
#define SOP_1160 (BUS_U|OPT_EIS|OPT_FPP|OPT_MMU)
|
||||||
|
#define OPT_1160 0
|
||||||
|
#define PSW_1160 0170377
|
||||||
|
#define PAR_1160 0007777
|
||||||
|
#define PDR_1160 0077516
|
||||||
|
#define MM0_1160 0160557
|
||||||
|
|
||||||
|
#define SOP_1170 (BUS_U|OPT_EIS|OPT_FPP|OPT_MMU|OPT_UBM)
|
||||||
|
#define OPT_1170 (OPT_FPP|OPT_RH11)
|
||||||
|
#define PSW_1170 0174377
|
||||||
|
#define PAR_1170 0177777
|
||||||
|
#define PDR_1170 0077717
|
||||||
|
#define MM0_1170 0171777
|
||||||
|
#define MM3_1170 0000067
|
||||||
|
|
||||||
|
#define SOP_1173 (BUS_Q|OPT_EIS|OPT_FPP|OPT_MMU)
|
||||||
|
#define OPT_1173 (OPT_CIS)
|
||||||
|
#define PSW_J 0174777
|
||||||
|
#define PAR_J 0177777
|
||||||
|
#define PDR_J 0177516
|
||||||
|
#define MM0_J 0160177
|
||||||
|
#define MM3_J 0000077
|
||||||
|
|
||||||
|
#define SOP_1153 (BUS_Q|OPT_EIS|OPT_FPP|OPT_MMU)
|
||||||
|
#define OPT_1153 (OPT_CIS)
|
||||||
|
|
||||||
|
#define SOP_1173B (BUS_Q|OPT_EIS|OPT_FPP|OPT_MMU)
|
||||||
|
#define OPT_1173B (OPT_CIS)
|
||||||
|
|
||||||
|
#define SOP_1183 (BUS_Q|OPT_EIS|OPT_FPP|OPT_MMU)
|
||||||
|
#define OPT_1183 (OPT_CIS)
|
||||||
|
|
||||||
|
#define SOP_1184 (BUS_U|OPT_EIS|OPT_FPP|OPT_MMU|OPT_UBM|OPT_RH11)
|
||||||
|
#define OPT_1184 (OPT_CIS)
|
||||||
|
|
||||||
|
#define SOP_1193 (BUS_Q|OPT_EIS|OPT_FPP|OPT_MMU)
|
||||||
|
#define OPT_1193 (OPT_CIS)
|
||||||
|
|
||||||
|
#define SOP_1194 (BUS_U|OPT_EIS|OPT_FPP|OPT_MMU|OPT_UBM|OPT_RH11)
|
||||||
|
#define OPT_1194 (OPT_CIS)
|
||||||
|
|
||||||
|
#define MOD_MAX 20
|
||||||
|
|
||||||
|
/* MFPT codes */
|
||||||
|
|
||||||
|
#define MFPT_44 1
|
||||||
|
#define MFPT_F 3
|
||||||
|
#define MFPT_T 4
|
||||||
|
#define MFPT_J 5
|
||||||
|
|
||||||
|
/* KDF11B specific register */
|
||||||
|
|
||||||
|
#define PCRFB_RW 0037477 /* page ctrl reg */
|
||||||
|
|
||||||
|
#define CDRFB_RD 0000377 /* config reg */
|
||||||
|
#define CDRFB_WR 0000017
|
||||||
|
|
||||||
|
/* KT24 Unibus map specific registers */
|
||||||
|
|
||||||
|
#define LMAL_RD 0177777 /* last mapped low */
|
||||||
|
|
||||||
|
#define LMAH_RD 0000177 /* last mapped high */
|
||||||
|
#define LMAH_WR 0000100
|
||||||
|
|
||||||
|
/* 11/44 specific registers */
|
||||||
|
|
||||||
|
#define CCR44_RD 0033315 /* cache control */
|
||||||
|
#define CCR44_WR 0003315
|
||||||
|
|
||||||
|
#define CMR44_RD 0177437 /* cache maint */
|
||||||
|
#define CMR44_WR 0000037
|
||||||
|
|
||||||
|
#define CPUE44_BUSE 0004000
|
||||||
|
|
||||||
|
/* J11 specific registers */
|
||||||
|
|
||||||
|
/* Maintenance register */
|
||||||
|
|
||||||
|
#define MAINT_V_UQ 9 /* Q/U flag */
|
||||||
|
#define MAINT_Q (0 << MAINT_V_UQ) /* Qbus */
|
||||||
|
#define MAINT_U (1 << MAINT_V_UQ)
|
||||||
|
#define MAINT_V_FPA 8 /* FPA flag */
|
||||||
|
#define MAINT_NOFPA (0 << MAINT_V_FPA)
|
||||||
|
#define MAINT_FPA (1 << MAINT_V_FPA)
|
||||||
|
#define MAINT_V_TYP 4 /* system type */
|
||||||
|
#define MAINT_KDJA (1 << MAINT_V_TYP) /* KDJ11A */
|
||||||
|
#define MAINT_KDJB (2 << MAINT_V_TYP) /* KDJ11B */
|
||||||
|
#define MAINT_KDJD (4 << MAINT_V_TYP) /* KDJ11D */
|
||||||
|
#define MAINT_KDJE (5 << MAINT_V_TYP) /* KDJ11E */
|
||||||
|
#define MAINT_V_HTRAP 3 /* trap 4 on HALT */
|
||||||
|
#define MAINT_HTRAP (1 << MAINT_V_HTRAP)
|
||||||
|
#define MAINT_V_POM 1 /* power on option */
|
||||||
|
#define MAINT_POODT (0 << MAINT_V_POM) /* power up ODT */
|
||||||
|
#define MAINT_POROM (2 << MAINT_V_POM) /* power up ROM */
|
||||||
|
#define MAINT_V_BPOK 0 /* power OK */
|
||||||
|
#define MAINT_BPOK (1 << MAINT_V_BPOK)
|
||||||
|
|
||||||
|
/* KDJ11B control */
|
||||||
|
|
||||||
|
#define CSRJB_RD 0177767
|
||||||
|
#define CSRJB_WR 0037767
|
||||||
|
#define CSRJ_LTCI 0020000 /* force LTC int */
|
||||||
|
#define CSRJ_LTCD 0010000 /* disable LTC reg */
|
||||||
|
#define CSRJ_V_LTCSEL 10
|
||||||
|
#define CSRJ_M_LTCSEL 03
|
||||||
|
#define CSRJ_LTCSEL(x) (((x) >> CSRJ_V_LTCSEL) & CSRJ_M_LTCSEL)
|
||||||
|
#define CSRJ_HBREAK 0001000 /* halt on break */
|
||||||
|
|
||||||
|
#define PCRJB_RW 0077176 /* page ctrl reg */
|
||||||
|
|
||||||
|
#define CDRJB_RD 0000377 /* config register */
|
||||||
|
#define CDRJB_WR 0000377
|
||||||
|
|
||||||
|
/* KDJ11D control */
|
||||||
|
|
||||||
|
#define CSRJD_RD 0157777 /* native register */
|
||||||
|
#define CSRJD_WR 0000377
|
||||||
|
#define CSRJD_15M 0040000 /* 1.5M mem on board */
|
||||||
|
|
||||||
|
/* KDJ11E control */
|
||||||
|
|
||||||
|
#define CSRJE_RD 0137360 /* control reg */
|
||||||
|
#define CSRJE_WR 0037370
|
||||||
|
|
||||||
|
#define PCRJE_RW 0177376 /* page ctrl reg */
|
||||||
|
|
||||||
|
#define CDRJE_RD 0000377 /* config register */
|
||||||
|
#define CDRJE_WR 0000077
|
||||||
|
|
||||||
|
#define ASRJE_RW 0030462 /* additional status */
|
||||||
|
#define ASRJE_V_TOY 8
|
||||||
|
#define ASRJE_TOY (1u << ASRJE_V_TOY) /* TOY serial bit */
|
||||||
|
#define ASRJE_TOYBIT(x) (((x) >> ASRJE_V_TOY) & 1)
|
||||||
|
|
||||||
|
/* KDJ11E TOY clock */
|
||||||
|
|
||||||
|
#define TOY_HSEC 0
|
||||||
|
#define TOY_SEC 1
|
||||||
|
#define TOY_MIN 2
|
||||||
|
#define TOY_HR 3
|
||||||
|
#define TOY_DOW 4
|
||||||
|
#define TOY_DOM 5
|
||||||
|
#define TOY_MON 6
|
||||||
|
#define TOY_YR 7
|
||||||
|
#define TOY_LNT 8
|
||||||
|
|
||||||
|
/* KTJ11B Unibus map */
|
||||||
|
|
||||||
|
#define DCRKTJ_RD 0100616 /* diag control */
|
||||||
|
#define DCRKTJ_WR 0000416
|
||||||
|
|
||||||
|
#define DDRKTJ_RW 0177777 /* diag data */
|
||||||
|
|
||||||
|
#define MCRKTJ_RD 0000377 /* control register */
|
||||||
|
#define MCRKTJ_WR 0000177
|
||||||
|
|
||||||
|
/* Data tables */
|
||||||
|
|
||||||
|
struct cpu_table {
|
||||||
|
char *name; /* model name */
|
||||||
|
uint32 std; /* standard flags */
|
||||||
|
uint32 opt; /* set/clear flags */
|
||||||
|
uint32 maxm; /* max memory */
|
||||||
|
uint32 psw; /* PSW mask */
|
||||||
|
uint32 mfpt; /* MFPT code */
|
||||||
|
uint32 par; /* PAR mask */
|
||||||
|
uint32 pdr; /* PDR mask */
|
||||||
|
uint32 mm0; /* MMR0 mask */
|
||||||
|
uint32 mm3; /* MMR3 mask */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct cpu_table CPUTAB;
|
||||||
|
|
||||||
|
struct conf_table {
|
||||||
|
uint32 cpum;
|
||||||
|
uint32 optm;
|
||||||
|
DIB *dib;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct conf_table CNFTAB;
|
||||||
|
|
||||||
|
/* Prototypes */
|
||||||
|
|
||||||
|
t_stat cpu_set_model (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat cpu_show_model (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
|
t_stat cpu_set_opt (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat cpu_clr_opt (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat cpu_set_bus (int32 opt);
|
||||||
|
|
||||||
|
#endif
|
|
@ -26,6 +26,10 @@
|
||||||
The author gratefully acknowledges the help of Max Burnet, Megan Gentry,
|
The author gratefully acknowledges the help of Max Burnet, Megan Gentry,
|
||||||
and John Wilson in resolving questions about the PDP-11
|
and John Wilson in resolving questions about the PDP-11
|
||||||
|
|
||||||
|
30-Sep-04 RMS Added Massbus support
|
||||||
|
Removed Map_Addr prototype
|
||||||
|
Removed map argument from Unibus routines
|
||||||
|
Added framework for model selection
|
||||||
28-May-04 RMS Added DHQ support
|
28-May-04 RMS Added DHQ support
|
||||||
25-Jan-04 RMS Removed local debug logging support
|
25-Jan-04 RMS Removed local debug logging support
|
||||||
22-Dec-03 RMS Added second DEUNA/DELUA support
|
22-Dec-03 RMS Added second DEUNA/DELUA support
|
||||||
|
@ -68,9 +72,11 @@
|
||||||
|
|
||||||
/* Architectural constants */
|
/* Architectural constants */
|
||||||
|
|
||||||
#define STKLIM 0400 /* stack limit */
|
#define STKL_R 0340 /* stack limit */
|
||||||
|
#define STKL_Y 0400
|
||||||
#define VASIZE 0200000 /* 2**16 */
|
#define VASIZE 0200000 /* 2**16 */
|
||||||
#define VAMASK (VASIZE - 1) /* 2**16 - 1 */
|
#define VAMASK (VASIZE - 1) /* 2**16 - 1 */
|
||||||
|
#define MEMSIZE64K 0200000 /* 2**16 */
|
||||||
#define INIMEMSIZE 001000000 /* 2**18 */
|
#define INIMEMSIZE 001000000 /* 2**18 */
|
||||||
#define UNIMEMSIZE 001000000 /* 2**18 */
|
#define UNIMEMSIZE 001000000 /* 2**18 */
|
||||||
#define UNIMASK (UNIMEMSIZE - 1) /* 2**18 - 1 */
|
#define UNIMASK (UNIMEMSIZE - 1) /* 2**18 - 1 */
|
||||||
|
@ -83,6 +89,149 @@
|
||||||
#define ADDR_IS_MEM(x) (((t_addr) (x)) < MEMSIZE)
|
#define ADDR_IS_MEM(x) (((t_addr) (x)) < MEMSIZE)
|
||||||
#define DMASK 0177777
|
#define DMASK 0177777
|
||||||
|
|
||||||
|
/* CPU models */
|
||||||
|
|
||||||
|
#define MOD_1103 0
|
||||||
|
#define MOD_1104 1
|
||||||
|
#define MOD_1105 2
|
||||||
|
#define MOD_1120 3
|
||||||
|
#define MOD_1123 4
|
||||||
|
#define MOD_1123P 5
|
||||||
|
#define MOD_1124 6
|
||||||
|
#define MOD_1134 7
|
||||||
|
#define MOD_1140 8
|
||||||
|
#define MOD_1144 9
|
||||||
|
#define MOD_1145 10
|
||||||
|
#define MOD_1160 11
|
||||||
|
#define MOD_1170 12
|
||||||
|
#define MOD_1173 13
|
||||||
|
#define MOD_1153 14
|
||||||
|
#define MOD_1173B 15
|
||||||
|
#define MOD_1183 16
|
||||||
|
#define MOD_1184 17
|
||||||
|
#define MOD_1193 18
|
||||||
|
#define MOD_1194 19
|
||||||
|
#define MOD_T 20
|
||||||
|
|
||||||
|
#define CPUT_03 (1u << MOD_1103) /* LSI-11 */
|
||||||
|
#define CPUT_04 (1u << MOD_1104) /* 11/04 */
|
||||||
|
#define CPUT_05 (1u << MOD_1105) /* 11/05 */
|
||||||
|
#define CPUT_20 (1u << MOD_1120) /* 11/20 */
|
||||||
|
#define CPUT_23 (1u << MOD_1123) /* 11/23 */
|
||||||
|
#define CPUT_23P (1u << MOD_1123P) /* 11/23+ */
|
||||||
|
#define CPUT_24 (1u << MOD_1124) /* 11/24 */
|
||||||
|
#define CPUT_34 (1u << MOD_1134) /* 11/34 */
|
||||||
|
#define CPUT_40 (1u << MOD_1140) /* 11/40 */
|
||||||
|
#define CPUT_44 (1u << MOD_1144) /* 11/44 */
|
||||||
|
#define CPUT_45 (1u << MOD_1145) /* 11/45 */
|
||||||
|
#define CPUT_60 (1u << MOD_1160) /* 11/60 */
|
||||||
|
#define CPUT_70 (1u << MOD_1170) /* 11/70 */
|
||||||
|
#define CPUT_73 (1u << MOD_1173) /* 11/73 */
|
||||||
|
#define CPUT_53 (1u << MOD_1153) /* 11/53 */
|
||||||
|
#define CPUT_73B (1u << MOD_1173B) /* 11/73B */
|
||||||
|
#define CPUT_83 (1u << MOD_1183) /* 11/83 */
|
||||||
|
#define CPUT_84 (1u << MOD_1184) /* 11/84 */
|
||||||
|
#define CPUT_93 (1u << MOD_1193) /* 11/93 */
|
||||||
|
#define CPUT_94 (1u << MOD_1194) /* 11/94 */
|
||||||
|
#define CPUT_T (1u << MOD_T) /* T-11 */
|
||||||
|
|
||||||
|
#define CPUT_F (CPUT_23|CPUT_23P|CPUT_24) /* all F11's */
|
||||||
|
#define CPUT_J (CPUT_53|CPUT_73|CPUT_73B| \
|
||||||
|
CPUT_83|CPUT_84|CPUT_93|CPUT_94)
|
||||||
|
#define CPUT_JB (CPUT_73B|CPUT_83|CPUT_84) /* KDJ11B */
|
||||||
|
#define CPUT_JE (CPUT_93|CPUT_94) /* KDJ11E */
|
||||||
|
#define CPUT_JU (CPUT_84|CPUT_94) /* KTJ11B UBA */
|
||||||
|
#define CPUT_ALL 0xFFFFFFFF
|
||||||
|
|
||||||
|
/* CPU options */
|
||||||
|
|
||||||
|
#define BUS_U (1u << 0) /* Unibus */
|
||||||
|
#define BUS_Q (0) /* Qbus */
|
||||||
|
#define OPT_EIS (1u << 1) /* EIS */
|
||||||
|
#define OPT_FIS (1u << 2) /* FIS */
|
||||||
|
#define OPT_FPP (1u << 3) /* FPP */
|
||||||
|
#define OPT_CIS (1u << 4) /* CIS */
|
||||||
|
#define OPT_MMU (1u << 5) /* MMU */
|
||||||
|
#define OPT_RH11 (1u << 6) /* RH11 */
|
||||||
|
#define OPT_PAR (1u << 7) /* parity */
|
||||||
|
#define OPT_UBM (1u << 8) /* UBM */
|
||||||
|
|
||||||
|
#define CPUT(x) ((cpu_type & (x)) != 0)
|
||||||
|
#define CPUO(x) ((cpu_opt & (x)) != 0)
|
||||||
|
#define UNIBUS (cpu_opt & BUS_U)
|
||||||
|
|
||||||
|
/* Feature sets
|
||||||
|
|
||||||
|
SDSD source addr, source fetch, dest addr, dest fetch
|
||||||
|
SR switch register
|
||||||
|
DR display register
|
||||||
|
RTT RTT instruction
|
||||||
|
SXS SXT, XOR, SOB instructions
|
||||||
|
MARK MARK instruction
|
||||||
|
SPL SPL instruction
|
||||||
|
MXPY MTPI, MTPD, MFPI, MFPD instructions
|
||||||
|
MXPS MTPS, MFPS instructions
|
||||||
|
MFPT MFPT instruction
|
||||||
|
CSM CSM instruction
|
||||||
|
TSWLK TSTSET, WRLCK instructions
|
||||||
|
PSW PSW register
|
||||||
|
EXPT explicit PSW writes can alter T-bit
|
||||||
|
IOSR general registers readable from programs in IO space
|
||||||
|
2REG dual register set
|
||||||
|
MMR3 MMR3 register
|
||||||
|
MMTR mem mgt traps
|
||||||
|
STKLR STKLIM register
|
||||||
|
STKLF fixed stack limit
|
||||||
|
SID supervisor mode, I/D spaces
|
||||||
|
ODD odd address trap
|
||||||
|
HALT4 halt in kernel mode traps to 4
|
||||||
|
JREG4 JMP/JSR R traps to 4
|
||||||
|
STKA stop on stack abort
|
||||||
|
LTCR LTC CSR
|
||||||
|
LTCM LTC CSR<7>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define IS_SDSD (CPUT_20|CPUT_F|CPUT_40|CPUT_60|CPUT_J|CPUT_T)
|
||||||
|
#define HAS_SR (CPUT_04|CPUT_05|CPUT_20|CPUT_34|CPUT_40| \
|
||||||
|
CPUT_44|CPUT_45|CPUT_60|CPUT_70)
|
||||||
|
#define HAS_DR (CPUT_04|CPUT_05|CPUT_20|CPUT_24|CPUT_34| \
|
||||||
|
CPUT_40|CPUT_45|CPUT_60|CPUT_70)
|
||||||
|
#define HAS_RTT (CPUT_03|CPUT_04|CPUT_F|CPUT_34|CPUT_40| \
|
||||||
|
CPUT_44|CPUT_45|CPUT_60|CPUT_70|CPUT_J|CPUT_T)
|
||||||
|
#define HAS_SXS (CPUT_03|CPUT_F|CPUT_34|CPUT_40|CPUT_44| \
|
||||||
|
CPUT_45|CPUT_60|CPUT_70|CPUT_J|CPUT_T)
|
||||||
|
#define HAS_MARK (CPUT_03|CPUT_F|CPUT_34|CPUT_40|CPUT_44| \
|
||||||
|
CPUT_45|CPUT_60|CPUT_70|CPUT_J)
|
||||||
|
#define HAS_SPL (CPUT_44|CPUT_45|CPUT_70|CPUT_J)
|
||||||
|
#define HAS_MXPY (CPUT_F|CPUT_34|CPUT_40|CPUT_44|CPUT_45| \
|
||||||
|
CPUT_60|CPUT_70|CPUT_J)
|
||||||
|
#define HAS_MXPS (CPUT_03|CPUT_F|CPUT_34|CPUT_J|CPUT_T)
|
||||||
|
#define HAS_MFPT (CPUT_F|CPUT_44|CPUT_J|CPUT_T)
|
||||||
|
#define HAS_CSM (CPUT_44|CPUT_J)
|
||||||
|
#define HAS_TSWLK (CPUT_J)
|
||||||
|
#define HAS_PSW (CPUT_04|CPUT_05|CPUT_20|CPUT_F|CPUT_34|CPUT_40| \
|
||||||
|
CPUT_44|CPUT_45|CPUT_60|CPUT_70|CPUT_J)
|
||||||
|
#define HAS_EXPT (CPUT_04|CPUT_05|CPUT_20)
|
||||||
|
#define HAS_IOSR (CPUT_04|CPUT_05)
|
||||||
|
#define HAS_2REG (CPUT_45|CPUT_70|CPUT_J)
|
||||||
|
#define HAS_MMR3 (CPUT_F|CPUT_44|CPUT_45|CPUT_70|CPUT_J)
|
||||||
|
#define HAS_MMTR (CPUT_45|CPUT_70)
|
||||||
|
#define HAS_STKLR (CPUT_45|CPUT_60|CPUT_70)
|
||||||
|
#define HAS_STKLF (CPUT_04|CPUT_05|CPUT_20|CPUT_F|CPUT_34| \
|
||||||
|
CPUT_40|CPUT_44|CPUT_J)
|
||||||
|
#define HAS_SID (CPUT_44|CPUT_45|CPUT_70|CPUT_J)
|
||||||
|
#define HAS_ODD (CPUT_04|CPUT_05|CPUT_20|CPUT_34|CPUT_40| \
|
||||||
|
CPUT_44|CPUT_45|CPUT_60|CPUT_70|CPUT_J)
|
||||||
|
#define HAS_HALT4 (CPUT_44|CPUT_45|CPUT_70|CPUT_J)
|
||||||
|
#define HAS_JREG4 (CPUT_03|CPUT_04|CPUT_05|CPUT_20|CPUT_F| \
|
||||||
|
CPUT_34|CPUT_40|CPUT_60|CPUT_T)
|
||||||
|
#define STOP_STKA (CPUT_03|CPUT_04|CPUT_05|CPUT_20|CPUT_34|CPUT_44)
|
||||||
|
#define HAS_LTCR (CPUT_04|CPUT_05|CPUT_20|CPUT_23P|CPUT_24| \
|
||||||
|
CPUT_34|CPUT_40|CPUT_44|CPUT_45|CPUT_60| \
|
||||||
|
CPUT_70|CPUT_J)
|
||||||
|
#define HAS_LTCM (CPUT_04|CPUT_05|CPUT_20|CPUT_24|CPUT_34| \
|
||||||
|
CPUT_40|CPUT_44|CPUT_45|CPUT_60|CPUT_70|CPUT_J)
|
||||||
|
|
||||||
/* Protection modes */
|
/* Protection modes */
|
||||||
|
|
||||||
#define MD_KER 0
|
#define MD_KER 0
|
||||||
|
@ -106,10 +255,13 @@
|
||||||
#define PSW_V_N 3
|
#define PSW_V_N 3
|
||||||
#define PSW_V_TBIT 4 /* trace trap */
|
#define PSW_V_TBIT 4 /* trace trap */
|
||||||
#define PSW_V_IPL 5 /* int priority */
|
#define PSW_V_IPL 5 /* int priority */
|
||||||
|
#define PSW_V_FPD 8 /* first part done */
|
||||||
#define PSW_V_RS 11 /* register set */
|
#define PSW_V_RS 11 /* register set */
|
||||||
#define PSW_V_PM 12 /* previous mode */
|
#define PSW_V_PM 12 /* previous mode */
|
||||||
#define PSW_V_CM 14 /* current mode */
|
#define PSW_V_CM 14 /* current mode */
|
||||||
#define PSW_RW 0174357 /* read/write bits */
|
#define PSW_CC 017
|
||||||
|
#define PSW_TBIT (1 << PSW_V_TBIT)
|
||||||
|
#define PSW_PM (3 << PSW_V_PM)
|
||||||
|
|
||||||
/* FPS */
|
/* FPS */
|
||||||
|
|
||||||
|
@ -139,18 +291,25 @@
|
||||||
#define PIRQ_IMP 0177356 /* implemented bits */
|
#define PIRQ_IMP 0177356 /* implemented bits */
|
||||||
#define PIRQ_RW 0177000 /* read/write bits */
|
#define PIRQ_RW 0177000 /* read/write bits */
|
||||||
|
|
||||||
|
/* STKLIM */
|
||||||
|
|
||||||
|
#define STKLIM_RW 0177400
|
||||||
|
|
||||||
/* MMR0 */
|
/* MMR0 */
|
||||||
|
|
||||||
#define MMR0_MME 0000001 /* mem mgt enable */
|
#define MMR0_MME 0000001 /* mem mgt enable */
|
||||||
#define MMR0_V_PAGE 1 /* offset to pageno */
|
#define MMR0_V_PAGE 1 /* offset to pageno */
|
||||||
#define MMR0_M_PAGE 077 /* mask for pageno */
|
#define MMR0_M_PAGE 077 /* mask for pageno */
|
||||||
#define MMR0_PAGE (MMR0_M_PAGE << MMR0_V_PAGE)
|
#define MMR0_PAGE (MMR0_M_PAGE << MMR0_V_PAGE)
|
||||||
|
#define MMR0_IC 0000200 /* instr complete */
|
||||||
|
#define MMR0_MAINT 0000400 /* maintenance */
|
||||||
|
#define MMR0_TENB 0001000 /* trap enable */
|
||||||
|
#define MMR0_TRAP 0010000 /* mem mgt trap */
|
||||||
#define MMR0_RO 0020000 /* read only error */
|
#define MMR0_RO 0020000 /* read only error */
|
||||||
#define MMR0_PL 0040000 /* page lnt error */
|
#define MMR0_PL 0040000 /* page lnt error */
|
||||||
#define MMR0_NR 0100000 /* no access error */
|
#define MMR0_NR 0100000 /* no access error */
|
||||||
#define MMR0_FREEZE 0160000 /* if set, no update */
|
#define MMR0_FREEZE 0160000 /* if set, no update */
|
||||||
#define MMR0_IMP 0160177 /* implemented bits */
|
#define MMR0_WR 0171401 /* writeable bits */
|
||||||
#define MMR0_RW 0160001 /* read/write bits */
|
|
||||||
|
|
||||||
/* MMR3 */
|
/* MMR3 */
|
||||||
|
|
||||||
|
@ -160,18 +319,23 @@
|
||||||
#define MMR3_CSM 010 /* CSM enable */
|
#define MMR3_CSM 010 /* CSM enable */
|
||||||
#define MMR3_M22E 020 /* 22b mem mgt enbl */
|
#define MMR3_M22E 020 /* 22b mem mgt enbl */
|
||||||
#define MMR3_BME 040 /* DMA bus map enbl */
|
#define MMR3_BME 040 /* DMA bus map enbl */
|
||||||
#define MMR3_IMP 077 /* implemented bits */
|
|
||||||
#define MMR3_RW 077 /* read/write bits */
|
/* PAR */
|
||||||
|
|
||||||
|
#define PAR_18B 0007777 /* 18b addressing */
|
||||||
|
#define PAR_22B 0177777 /* 22b addressing */
|
||||||
|
|
||||||
/* PDR */
|
/* PDR */
|
||||||
|
|
||||||
#define PDR_PRD 0000002 /* page readable */
|
#define PDR_ACF 0000007 /* access control */
|
||||||
#define PDR_PWR 0000004 /* page writeable */
|
#define PDR_ACS 0000006 /* 2b access control */
|
||||||
#define PDR_ED 0000010 /* expansion dir */
|
#define PDR_ED 0000010 /* expansion dir */
|
||||||
#define PDR_W 0000100 /* written flag */
|
#define PDR_W 0000100 /* written flag */
|
||||||
|
#define PDR_A 0000200 /* access flag */
|
||||||
#define PDR_PLF 0077400 /* page lnt field */
|
#define PDR_PLF 0077400 /* page lnt field */
|
||||||
#define PDR_IMP 0177516 /* implemented bits */
|
#define PDR_NOC 0100000 /* don't cache */
|
||||||
#define PDR_RW 0177416 /* read/write bits */
|
|
||||||
|
#define PDR_PRD 0000003 /* page readable if 2 */
|
||||||
|
|
||||||
/* Virtual address */
|
/* Virtual address */
|
||||||
|
|
||||||
|
@ -189,6 +353,7 @@
|
||||||
#define UBM_M_PN 037
|
#define UBM_M_PN 037
|
||||||
#define UBM_V_OFF 0 /* offset */
|
#define UBM_V_OFF 0 /* offset */
|
||||||
#define UBM_M_OFF 017777
|
#define UBM_M_OFF 017777
|
||||||
|
#define UBM_PAGSIZE (UBM_M_OFF + 1) /* page size */
|
||||||
#define UBM_GETPN(x) (((x) >> UBM_V_PN) & UBM_M_PN)
|
#define UBM_GETPN(x) (((x) >> UBM_V_PN) & UBM_M_PN)
|
||||||
#define UBM_GETOFF(x) ((x) & UBM_M_OFF)
|
#define UBM_GETOFF(x) ((x) & UBM_M_OFF)
|
||||||
|
|
||||||
|
@ -202,26 +367,11 @@
|
||||||
#define CPUE_HALT 0200 /* HALT not kernel */
|
#define CPUE_HALT 0200 /* HALT not kernel */
|
||||||
#define CPUE_IMP 0374 /* implemented bits */
|
#define CPUE_IMP 0374 /* implemented bits */
|
||||||
|
|
||||||
/* Maintenance register */
|
|
||||||
|
|
||||||
#define MAINT_V_UQ 9 /* Q/U flag */
|
|
||||||
#define MAINT_Q (0 << MAINT_V_UQ) /* Qbus */
|
|
||||||
#define MAINT_U (1 << MAINT_V_UQ)
|
|
||||||
#define MAINT_V_FPA 8 /* FPA flag */
|
|
||||||
#define MAINT_NOFPA (0 << MAINT_V_FPA)
|
|
||||||
#define MAINT_FPA (1 << MAINT_V_FPA)
|
|
||||||
#define MAINT_V_TYP 4 /* system type */
|
|
||||||
#define MAINT_KDJ (1 << MAINT_V_TYP) /* KDJ11A */
|
|
||||||
#define MAINT_V_HTRAP 3 /* trap 4 on HALT */
|
|
||||||
#define MAINT_HTRAP (1 << MAINT_V_HTRAP)
|
|
||||||
#define MAINT_V_BPOK 0 /* power OK */
|
|
||||||
#define MAINT_BPOK (1 << MAINT_V_BPOK)
|
|
||||||
|
|
||||||
/* Floating point accumulators */
|
/* Floating point accumulators */
|
||||||
|
|
||||||
struct fpac {
|
struct fpac {
|
||||||
unsigned int32 l; /* low 32b */
|
uint32 l; /* low 32b */
|
||||||
unsigned int32 h; /* high 32b */
|
uint32 h; /* high 32b */
|
||||||
};
|
};
|
||||||
typedef struct fpac fpac_t;
|
typedef struct fpac fpac_t;
|
||||||
|
|
||||||
|
@ -322,15 +472,13 @@ typedef struct fpac fpac_t;
|
||||||
#define DEV_V_QBUS (DEV_V_UF + 1) /* Qbus */
|
#define DEV_V_QBUS (DEV_V_UF + 1) /* Qbus */
|
||||||
#define DEV_V_Q18 (DEV_V_UF + 2) /* Qbus with <= 256KB */
|
#define DEV_V_Q18 (DEV_V_UF + 2) /* Qbus with <= 256KB */
|
||||||
#define DEV_V_FLTA (DEV_V_UF + 3) /* flt addr */
|
#define DEV_V_FLTA (DEV_V_UF + 3) /* flt addr */
|
||||||
|
#define DEV_V_MBUS (DEV_V_UF + 4) /* Massbus */
|
||||||
|
#define DEV_V_FFUF (DEV_V_UF + 5) /* first free flag */
|
||||||
#define DEV_UBUS (1u << DEV_V_UBUS)
|
#define DEV_UBUS (1u << DEV_V_UBUS)
|
||||||
#define DEV_QBUS (1u << DEV_V_QBUS)
|
#define DEV_QBUS (1u << DEV_V_QBUS)
|
||||||
#define DEV_Q18 (1u << DEV_V_Q18)
|
#define DEV_Q18 (1u << DEV_V_Q18)
|
||||||
#define DEV_FLTA (1u << DEV_V_FLTA)
|
#define DEV_FLTA (1u << DEV_V_FLTA)
|
||||||
|
#define DEV_MBUS (1u << DEV_V_MBUS)
|
||||||
#define UNIBUS (cpu_18b || cpu_ubm) /* T if 18b */
|
|
||||||
|
|
||||||
#define MAP 1 /* mapped */
|
|
||||||
#define NOMAP 0 /* not mapped */
|
|
||||||
|
|
||||||
#define DEV_RDX 8 /* default device radix */
|
#define DEV_RDX 8 /* default device radix */
|
||||||
|
|
||||||
|
@ -369,8 +517,18 @@ typedef struct pdp_dib DIB;
|
||||||
#define IOLN_UBM (UBM_LNT_LW * sizeof (int32))
|
#define IOLN_UBM (UBM_LNT_LW * sizeof (int32))
|
||||||
#define IOBA_RQ (IOPAGEBASE + 012150) /* RQDX3 */
|
#define IOBA_RQ (IOPAGEBASE + 012150) /* RQDX3 */
|
||||||
#define IOLN_RQ 004
|
#define IOLN_RQ 004
|
||||||
#define IOBA_APR (IOPAGEBASE + 012200) /* APRs */
|
#define IOBA_SUP (IOPAGEBASE + 012200) /* supervisor APR's */
|
||||||
#define IOLN_APR 0200
|
#define IOLN_SUP 0100
|
||||||
|
#define IOBA_KIPDR (IOPAGEBASE + 012300) /* kernel APR's */
|
||||||
|
#define IOLN_KIPDR 020
|
||||||
|
#define IOBA_KDPDR (IOPAGEBASE + 012320)
|
||||||
|
#define IOLN_KDPDR 020
|
||||||
|
#define IOBA_KIPAR (IOPAGEBASE + 012340)
|
||||||
|
#define IOLN_KIPAR 020
|
||||||
|
#define IOBA_KDPAR (IOPAGEBASE + 012360)
|
||||||
|
#define IOLN_KDPAR 020
|
||||||
|
#define IOBA_TU (IOPAGEBASE + 012440) /* TU */
|
||||||
|
#define IOLN_TU 040
|
||||||
#define IOBA_MMR3 (IOPAGEBASE + 012516) /* MMR3 */
|
#define IOBA_MMR3 (IOPAGEBASE + 012516) /* MMR3 */
|
||||||
#define IOLN_MMR3 002
|
#define IOLN_MMR3 002
|
||||||
#define IOBA_TM (IOPAGEBASE + 012520) /* TM11 */
|
#define IOBA_TM (IOPAGEBASE + 012520) /* TM11 */
|
||||||
|
@ -403,6 +561,8 @@ typedef struct pdp_dib DIB;
|
||||||
#define IOLN_HK 040
|
#define IOLN_HK 040
|
||||||
#define IOBA_LPT (IOPAGEBASE + 017514) /* LP11 */
|
#define IOBA_LPT (IOPAGEBASE + 017514) /* LP11 */
|
||||||
#define IOLN_LPT 004
|
#define IOLN_LPT 004
|
||||||
|
#define IOBA_CTL (IOPAGEBASE + 017520) /* board ctrl */
|
||||||
|
#define IOLN_CTL 010
|
||||||
#define IOBA_CLK (IOPAGEBASE + 017546) /* KW11L */
|
#define IOBA_CLK (IOPAGEBASE + 017546) /* KW11L */
|
||||||
#define IOLN_CLK 002
|
#define IOLN_CLK 002
|
||||||
#define IOBA_PTR (IOPAGEBASE + 017550) /* PC11 reader */
|
#define IOBA_PTR (IOPAGEBASE + 017550) /* PC11 reader */
|
||||||
|
@ -413,12 +573,26 @@ typedef struct pdp_dib DIB;
|
||||||
#define IOLN_TTI 004
|
#define IOLN_TTI 004
|
||||||
#define IOBA_TTO (IOPAGEBASE + 017564) /* DL11 xmt */
|
#define IOBA_TTO (IOPAGEBASE + 017564) /* DL11 xmt */
|
||||||
#define IOLN_TTO 004
|
#define IOLN_TTO 004
|
||||||
#define IOBA_SRMM (IOPAGEBASE + 017570) /* SR, MMR0-2 */
|
#define IOBA_SR (IOPAGEBASE + 017570) /* SR */
|
||||||
#define IOLN_SRMM 010
|
#define IOLN_SR 002
|
||||||
#define IOBA_APR1 (IOPAGEBASE + 017600) /* APRs */
|
#define IOBA_MMR012 (IOPAGEBASE + 017572) /* MMR0-2 */
|
||||||
#define IOLN_APR1 0100
|
#define IOLN_MMR012 006
|
||||||
|
#define IOBA_UIPDR (IOPAGEBASE + 017600) /* user APR's */
|
||||||
|
#define IOLN_UIPDR 020
|
||||||
|
#define IOBA_UDPDR (IOPAGEBASE + 017620)
|
||||||
|
#define IOLN_UDPDR 020
|
||||||
|
#define IOBA_UIPAR (IOPAGEBASE + 017640)
|
||||||
|
#define IOLN_UIPAR 020
|
||||||
|
#define IOBA_UDPAR (IOPAGEBASE + 017660)
|
||||||
|
#define IOLN_UDPAR 020
|
||||||
|
#define IOBA_GPR (IOPAGEBASE + 017700) /* GPR's */
|
||||||
|
#define IOLN_GPR 010
|
||||||
|
#define IOBA_UCTL (IOPAGEBASE + 017730) /* UBA ctrl */
|
||||||
|
#define IOLN_UCTL 010
|
||||||
#define IOBA_CPU (IOPAGEBASE + 017740) /* CPU reg */
|
#define IOBA_CPU (IOPAGEBASE + 017740) /* CPU reg */
|
||||||
#define IOLN_CPU 040
|
#define IOLN_CPU 036
|
||||||
|
#define IOBA_PSW (IOPAGEBASE + 017776) /* PSW */
|
||||||
|
#define IOLN_PSW 002
|
||||||
|
|
||||||
/* Interrupt assignments; within each level, priority is right to left */
|
/* Interrupt assignments; within each level, priority is right to left */
|
||||||
|
|
||||||
|
@ -445,7 +619,8 @@ typedef struct pdp_dib DIB;
|
||||||
#define INT_V_RY 11
|
#define INT_V_RY 11
|
||||||
#define INT_V_XQ 12
|
#define INT_V_XQ 12
|
||||||
#define INT_V_XU 13
|
#define INT_V_XU 13
|
||||||
#define INT_V_PIR5 14
|
#define INT_V_TU 14
|
||||||
|
#define INT_V_PIR5 15
|
||||||
|
|
||||||
#define INT_V_TTI 0 /* BR4 */
|
#define INT_V_TTI 0 /* BR4 */
|
||||||
#define INT_V_TTO 1
|
#define INT_V_TTO 1
|
||||||
|
@ -479,6 +654,7 @@ typedef struct pdp_dib DIB;
|
||||||
#define INT_RY (1u << INT_V_RY)
|
#define INT_RY (1u << INT_V_RY)
|
||||||
#define INT_XQ (1u << INT_V_XQ)
|
#define INT_XQ (1u << INT_V_XQ)
|
||||||
#define INT_XU (1u << INT_V_XU)
|
#define INT_XU (1u << INT_V_XU)
|
||||||
|
#define INT_TU (1u << INT_V_TU)
|
||||||
#define INT_PIR5 (1u << INT_V_PIR5)
|
#define INT_PIR5 (1u << INT_V_PIR5)
|
||||||
#define INT_PTR (1u << INT_V_PTR)
|
#define INT_PTR (1u << INT_V_PTR)
|
||||||
#define INT_PTP (1u << INT_V_PTP)
|
#define INT_PTP (1u << INT_V_PTP)
|
||||||
|
@ -509,6 +685,7 @@ typedef struct pdp_dib DIB;
|
||||||
#define IPL_RY 5
|
#define IPL_RY 5
|
||||||
#define IPL_XQ 5
|
#define IPL_XQ 5
|
||||||
#define IPL_XU 5
|
#define IPL_XU 5
|
||||||
|
#define IPL_TU 5
|
||||||
#define IPL_PTR 4
|
#define IPL_PTR 4
|
||||||
#define IPL_PTP 4
|
#define IPL_PTP 4
|
||||||
#define IPL_TTI 4
|
#define IPL_TTI 4
|
||||||
|
@ -545,6 +722,7 @@ typedef struct pdp_dib DIB;
|
||||||
#define VEC_DTA 0214
|
#define VEC_DTA 0214
|
||||||
#define VEC_TM 0224
|
#define VEC_TM 0224
|
||||||
#define VEC_TS 0224
|
#define VEC_TS 0224
|
||||||
|
#define VEC_TU 0224
|
||||||
#define VEC_RP 0254
|
#define VEC_RP 0254
|
||||||
#define VEC_TQ 0260
|
#define VEC_TQ 0260
|
||||||
#define VEC_RX 0264
|
#define VEC_RX 0264
|
||||||
|
@ -571,6 +749,16 @@ typedef struct pdp_dib DIB;
|
||||||
#define SET_INT(dv) int_req[IPL_##dv] = int_req[IPL_##dv] | (INT_##dv)
|
#define SET_INT(dv) int_req[IPL_##dv] = int_req[IPL_##dv] | (INT_##dv)
|
||||||
#define CLR_INT(dv) int_req[IPL_##dv] = int_req[IPL_##dv] & ~(INT_##dv)
|
#define CLR_INT(dv) int_req[IPL_##dv] = int_req[IPL_##dv] & ~(INT_##dv)
|
||||||
|
|
||||||
|
/* Massbus definitions */
|
||||||
|
|
||||||
|
#define MBA_NUM 2 /* number of MBA's */
|
||||||
|
#define MBA_RP 0 /* MBA for RP */
|
||||||
|
#define MBA_TU 1 /* MBA for TU */
|
||||||
|
#define MBA_RMASK 037 /* max 32 reg */
|
||||||
|
#define MBE_NXD 1 /* nx drive */
|
||||||
|
#define MBE_NXR 2 /* nx reg */
|
||||||
|
#define MBE_GOE 3 /* err on GO */
|
||||||
|
|
||||||
/* CPU and FPU macros */
|
/* CPU and FPU macros */
|
||||||
|
|
||||||
#define update_MM ((MMR0 & MMR0_FREEZE) == 0)
|
#define update_MM ((MMR0 & MMR0_FREEZE) == 0)
|
||||||
|
@ -582,16 +770,27 @@ typedef struct pdp_dib DIB;
|
||||||
|
|
||||||
/* Function prototypes */
|
/* Function prototypes */
|
||||||
|
|
||||||
t_bool Map_Addr (uint32 qa, uint32 *ma);
|
int32 Map_ReadB (uint32 ba, int32 bc, uint8 *buf);
|
||||||
int32 Map_ReadB (uint32 ba, int32 bc, uint8 *buf, t_bool map);
|
int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf);
|
||||||
int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf, t_bool map);
|
int32 Map_WriteB (uint32 ba, int32 bc, uint8 *buf);
|
||||||
int32 Map_WriteB (uint32 ba, int32 bc, uint8 *buf, t_bool map);
|
int32 Map_WriteW (uint32 ba, int32 bc, uint16 *buf);
|
||||||
int32 Map_WriteW (uint32 ba, int32 bc, uint16 *buf, t_bool map);
|
|
||||||
t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc);
|
t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
t_stat set_addr_flt (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat set_addr_flt (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
t_stat set_vec (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat set_vec (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
t_stat show_vec (FILE *st, UNIT *uptr, int32 val, void *desc);
|
t_stat show_vec (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
t_stat auto_config (uint32 rank, uint32 num);
|
t_stat auto_config (uint32 rank, uint32 num);
|
||||||
|
t_stat build_ubus_tab (DEVICE *dptr, DIB *dibp);
|
||||||
|
|
||||||
|
int32 mba_rdbufW (uint32 mbus, int32 bc, uint16 *buf);
|
||||||
|
int32 mba_wrbufW (uint32 mbus, int32 bc, uint16 *buf);
|
||||||
|
int32 mba_chbufW (uint32 mbus, int32 bc, uint16 *buf);
|
||||||
|
int32 mba_get_bc (uint32 mbus);
|
||||||
|
int32 mba_get_csr (uint32 mbus);
|
||||||
|
void mba_upd_ata (uint32 mbus, uint32 val);
|
||||||
|
void mba_set_exc (uint32 mbus);
|
||||||
|
void mba_set_don (uint32 mbus);
|
||||||
|
t_stat mba_show_num (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
To: Users
|
To: Users
|
||||||
From: Bob Supnik
|
From: Bob Supnik
|
||||||
Subj: PDP-11 Simulator Usage
|
Subj: PDP-11 Simulator Usage
|
||||||
Date: 15-Jun-2004
|
Date: 15-Nov-2004
|
||||||
|
|
||||||
COPYRIGHT NOTICE
|
COPYRIGHT NOTICE
|
||||||
|
|
||||||
|
@ -59,12 +59,14 @@ sim/ scp.h
|
||||||
sim_timer.c
|
sim_timer.c
|
||||||
sim_tmxr.c
|
sim_tmxr.c
|
||||||
|
|
||||||
sim/pdp11/ pdp11_defs.h
|
sim/pdp11/ pdp11_cpumod.h
|
||||||
|
pdp11_defs.h
|
||||||
pdp11_mscp.h
|
pdp11_mscp.h
|
||||||
pdp11_uqssp.h
|
pdp11_uqssp.h
|
||||||
pdp11_xq.h
|
pdp11_xq.h
|
||||||
pdp11_xq_bootrom.h
|
pdp11_xq_bootrom.h
|
||||||
pdp11_cpu.c
|
pdp11_cpu.c
|
||||||
|
pdp11_cpumod.c
|
||||||
pdp11_dz.c
|
pdp11_dz.c
|
||||||
pdp11_fp.c
|
pdp11_fp.c
|
||||||
pdp11_hk.c
|
pdp11_hk.c
|
||||||
|
@ -72,18 +74,20 @@ sim/pdp11/ pdp11_defs.h
|
||||||
pdp11_lp.c
|
pdp11_lp.c
|
||||||
pdp11_pclk.c
|
pdp11_pclk.c
|
||||||
pdp11_pt.c
|
pdp11_pt.c
|
||||||
|
pdp11_rh.c
|
||||||
pdp11_rk.c
|
pdp11_rk.c
|
||||||
pdp11_rl.c
|
pdp11_rl.c
|
||||||
pdp11_rp.c
|
pdp11_rp.c
|
||||||
pdp11_rq.c
|
pdp11_rq.c
|
||||||
pdp11_tq.c
|
|
||||||
pdp11_rx.c
|
pdp11_rx.c
|
||||||
pdp11_ry.c
|
pdp11_ry.c
|
||||||
pdp11_stddev.c
|
pdp11_stddev.c
|
||||||
pdp11_sys.c
|
pdp11_sys.c
|
||||||
pdp11_tc.c
|
pdp11_tc.c
|
||||||
pdp11_tm.c
|
pdp11_tm.c
|
||||||
|
pdp11_tq.c
|
||||||
pdp11_ts.c
|
pdp11_ts.c
|
||||||
|
pdp11_tu.c
|
||||||
pdp11_vh.c
|
pdp11_vh.c
|
||||||
pdp11_xq.c
|
pdp11_xq.c
|
||||||
pdp11_xu.c
|
pdp11_xu.c
|
||||||
|
@ -95,31 +99,32 @@ The PDP-11 simulator is configured as follows:
|
||||||
device simulates
|
device simulates
|
||||||
name(s)
|
name(s)
|
||||||
|
|
||||||
CPU J-11 CPU with 256KB of memory
|
CPU PDP-11 CPU with 256KB of memory
|
||||||
- FP11 floating point unit (FPA)
|
|
||||||
- CIS11 commercial instruction set (CIS, off by default)
|
|
||||||
PTR,PTP PC11 paper tape reader/punch
|
PTR,PTP PC11 paper tape reader/punch
|
||||||
TTI,TTO DL11 console terminal
|
TTI,TTO DL11 console terminal
|
||||||
LPT LP11 line printer
|
LPT LP11 line printer
|
||||||
CLK line frequency clock
|
CLK line frequency clock
|
||||||
PCLK KW11P programmable clock
|
PCLK KW11P programmable clock
|
||||||
DZ DZ11 8-line terminal multiplexor (up to 4)
|
DZ DZ11 8-line terminal multiplexor (up to 4)
|
||||||
VH DHQ11 8-line terminal multiplexor (up to 4)
|
VH DHU11/DHQ11 8-line terminal multiplexor (up to 4)
|
||||||
RK RK11/RK05 cartridge disk controller with eight drives
|
RK RK11/RK05 cartridge disk controller with eight drives
|
||||||
HK RK611/RK06(7) cartridge disk controller with eight drives
|
HK RK611/RK06(7) cartridge disk controller with eight drives
|
||||||
RL RLV12/RL01(2) cartridge disk controller with four drives
|
RL RLV12/RL01(2) cartridge disk controller with four drives
|
||||||
RP RM02/03/05/80, RP04/05/06/07 Massbus style controller
|
RH RH11/RH70 Massbus adapter (up to 2)
|
||||||
|
RP RM02/03/05/80, RP04/05/06/07 Massbus disks
|
||||||
with eight drives
|
with eight drives
|
||||||
RQ RQDX3 MSCP controller with four drives
|
RQ RQDX3/UDA50 MSCP controller with four drives
|
||||||
RQB second RQDX3 MSCP controller with four drives
|
RQB second RQDX3/UDA50 MSCP controller with four drives
|
||||||
RQC third RQDX3 MSCP controller with four drives
|
RQC third RQDX3/UDA50 MSCP controller with four drives
|
||||||
RQD fourth RQDX3 MSCP controller with four drives
|
RQD fourth RQDX3/UDA50 MSCP controller with four drives
|
||||||
RX RX11/RX01 floppy disk controller with two drives
|
RX RX11/RX01 floppy disk controller with two drives
|
||||||
RY RX211/RX01 floppy disk controller with two drives
|
RY RX211/RX01 floppy disk controller with two drives
|
||||||
TC TC11/TU56 DECtape controller with eight drives
|
TC TC11/TU56 DECtape controller with eight drives
|
||||||
TM TM11/TU10 magnetic tape controller with eight drives
|
TM TM11/TU10 magnetic tape controller with eight drives
|
||||||
TS TS11/TSV05 magnetic tape controller with one drive
|
TS TS11/TSV05 magnetic tape controller with one drive
|
||||||
TQ TQK50 TMSCP magnetic tape controller with four drives
|
TQ TQK50/TU81 TMSCP magnetic tape controller with four drives
|
||||||
|
TU TM02/TM03 magnetic tape formatter with eight
|
||||||
|
TE16/TU45/TU77 drives
|
||||||
XQ DELQA/DEQNA Qbus Ethernet controller
|
XQ DELQA/DEQNA Qbus Ethernet controller
|
||||||
XQB second DELQA/DEQNA Qbus Ethernet controller
|
XQB second DELQA/DEQNA Qbus Ethernet controller
|
||||||
XU DEUNA/DELUA Unibus Ethernet controller
|
XU DEUNA/DELUA Unibus Ethernet controller
|
||||||
|
@ -140,19 +145,44 @@ The PDP-11 simulator implements several unique stop conditions:
|
||||||
The PDP-11 loader supports standard binary format tapes. The DUMP command
|
The PDP-11 loader supports standard binary format tapes. The DUMP command
|
||||||
is not implemented.
|
is not implemented.
|
||||||
|
|
||||||
2.1 CPU
|
2.1 CPU and System
|
||||||
|
|
||||||
The CPU options include CPU mapping configuration (18b Unibus, 22b Unibus
|
2.1.1 CPU
|
||||||
with RH70-style controllers, 22b Unibus with RH11 style controllers, and
|
|
||||||
22b Qbus), the CIS instruction set, and the size of main memory.
|
|
||||||
|
|
||||||
SET CPU U18 Unibus, no I/O map, 18b addressing
|
The CPU options include CPU type, CPU instruction set options for the
|
||||||
SET CPU URH11 Unibus, I/O map with 22b addressing,
|
specified type, and the size of main memory.
|
||||||
18b mapped RH11 controller
|
|
||||||
SET CPU URH70 Unibus, I/O map with 22b addressing,
|
SET CPU 11/03 set CPU type to 11/03
|
||||||
22b unmapped RH70 controller
|
SET CPU 11/04 set CPU type to 11/04
|
||||||
SET CPU Q22 Qbus, no I/O map, 22b addressing
|
SET CPU 11/05 set CPU type to 11/05
|
||||||
SET CPU NOCIS disable CIS instructions (default)
|
SET CPU 11/20 set CPU type to 11/20
|
||||||
|
SET CPU 11/23 set CPU type to 11/23
|
||||||
|
SET CPU 11/23+ set CPU type to 11/23+
|
||||||
|
SET CPU 11/24 set CPU type to 11/24
|
||||||
|
SET CPU 11/34 set CPU type to 11/34
|
||||||
|
SET CPU 11/40 set CPU type to 11/40
|
||||||
|
SET CPU 11/44 set CPU type to 11/44
|
||||||
|
SET CPU 11/45 set CPU type to 11/45
|
||||||
|
SET CPU 11/53 set CPU type to 11/53
|
||||||
|
SET CPU 11/60 set CPU type to 11/60
|
||||||
|
SET CPU 11/70 set CPU type to 11/70
|
||||||
|
SET CPU 11/73 set CPU type to 11/73
|
||||||
|
SET CPU 11/73B set CPU type to 11/73B
|
||||||
|
SET CPU 11/83 set CPU type to 11/83
|
||||||
|
SET CPU 11/84 set CPU type to 11/84
|
||||||
|
set CPU 11/93 set CPU type to 11/93
|
||||||
|
set CPU 11/94 set CPU type to 11/94
|
||||||
|
SET CPU U18 deprecated; same as 11/45
|
||||||
|
SET CPU URH11 deprecated; same as 11/84
|
||||||
|
SET CPU URH70 deprecated; same as 11/70
|
||||||
|
SET CPU Q22 deprecated; same as 11/73
|
||||||
|
SET CPU NOEIS disable EIS instructions
|
||||||
|
SET CPU EIS enable EIS instructions
|
||||||
|
SET CPU NOFIS disable FIS instructions
|
||||||
|
SET CPU FIS enable FIS instructions
|
||||||
|
SET CPU NOFPP disable FPP instructions
|
||||||
|
SET CPU FPP enable FPP instructions
|
||||||
|
SET CPU NOCIS disable CIS instructions
|
||||||
SET CPU CIS enable CIS instructions
|
SET CPU CIS enable CIS instructions
|
||||||
SET CPU 16K set memory size = 16KB
|
SET CPU 16K set memory size = 16KB
|
||||||
SET CPU 32K set memory size = 32KB
|
SET CPU 32K set memory size = 32KB
|
||||||
|
@ -170,9 +200,37 @@ with RH70-style controllers, 22b Unibus with RH11 style controllers, and
|
||||||
SET CPU 3072K (or 3M) set memory size = 3072KB
|
SET CPU 3072K (or 3M) set memory size = 3072KB
|
||||||
SET CPU 4096K (or 4M) set memory size = 4096KB
|
SET CPU 4096K (or 4M) set memory size = 4096KB
|
||||||
|
|
||||||
The CPU implements a show command to display the I/O address space map:
|
The CPU types and their capabilities are shown in the following table:
|
||||||
|
|
||||||
SHOW CPU IOSPACE show I/O space address map
|
type bus memory MMU? Umap? EIS? FIS? FPP? CIS?
|
||||||
|
|
||||||
|
11/03 Q 64K no no std opt no no
|
||||||
|
11/04 U 64K no no no no no no
|
||||||
|
11/05 U 64K no no no no no no
|
||||||
|
11/20 U 64K no no no no no no
|
||||||
|
11/23 Q 4M std no std no opt opt
|
||||||
|
11/23+ Q 4M std no std no opt opt
|
||||||
|
11/24 U 4M std std std no opt opt
|
||||||
|
11/34 U 256K std no std no opt no
|
||||||
|
11/40 U 256K std no std opt no no
|
||||||
|
11/44 U 4M std std std no opt opt
|
||||||
|
11/45 U 256K std no std no opt no
|
||||||
|
11/53 Q 4M std no std no std opt
|
||||||
|
11/60 U 256K std no std no std no
|
||||||
|
11/70 U 4M std std std no opt no
|
||||||
|
11/73 Q 4M std no std no std opt
|
||||||
|
11/73B Q 4M std no std no std opt
|
||||||
|
11/83 Q 4M std no std no std opt
|
||||||
|
11/84 U 4M std std std no std opt
|
||||||
|
11/93 Q 4M std no std no std opt
|
||||||
|
11/94 U 4M std std std no std opt
|
||||||
|
|
||||||
|
If a capability is standard, it cannot be disabled; if a capability is
|
||||||
|
not included, it cannot be enabled.
|
||||||
|
|
||||||
|
The CPU implements a show command to display the I/O address assignments:
|
||||||
|
|
||||||
|
SHOW CPU IOSPACE show I/O space address assignments
|
||||||
|
|
||||||
If memory size is being reduced, and the memory being truncated contains
|
If memory size is being reduced, and the memory being truncated contains
|
||||||
non-zero data, the simulator asks for confirmation. Data in the truncated
|
non-zero data, the simulator asks for confirmation. Data in the truncated
|
||||||
|
@ -181,31 +239,6 @@ is being increased to more than 256KB, or the bus structue is being changed,
|
||||||
the simulator asks whether it should disable peripherals that can't run
|
the simulator asks whether it should disable peripherals that can't run
|
||||||
in the current bus structure.
|
in the current bus structure.
|
||||||
|
|
||||||
DMA peripherals function differently, depending on whether the CPU is
|
|
||||||
configured for 18B, URH11, URH70, or 22B addressing and I/O:
|
|
||||||
|
|
||||||
peripheral 18B URH11 URH70 22B
|
|
||||||
|
|
||||||
RK 18b 18b 18b won't work, disabled
|
|
||||||
HK 18b 18b 18b SC02/C 22b, works
|
|
||||||
only with Ultrix-11
|
|
||||||
RL 18b 18b 18b 22b RLV12
|
|
||||||
RP 18b 18b 22b 22b third party
|
|
||||||
RQ 18b 18b 18b 22b RQDX3
|
|
||||||
RY 18b 18b 18b won't work, disabled
|
|
||||||
TC 18b 18b 18b won't work, disabled
|
|
||||||
TM 18b 18b 18b won't work, disabled
|
|
||||||
TS 18b 18b 18b 22b TSV05
|
|
||||||
TQ 18b 18b 18b 22b TQK50
|
|
||||||
XQ 18b won't work, 22b DELQA
|
|
||||||
disabled
|
|
||||||
XU 18b 18b 18b won't work, disabled
|
|
||||||
|
|
||||||
Non-DMA peripherals work the same in all configurations. Unibus-only
|
|
||||||
peripherals should be disabled in a Qbus (22B) configuration with more
|
|
||||||
than 256KB of memory, and Qbus-only peripherals should be disabled in
|
|
||||||
a Unibus (URH11 or URH70) configuration with more than 256KB of memory.
|
|
||||||
|
|
||||||
These switches are recognized when examining or depositing in CPU memory:
|
These switches are recognized when examining or depositing in CPU memory:
|
||||||
|
|
||||||
-v interpret address as virtual
|
-v interpret address as virtual
|
||||||
|
@ -215,8 +248,8 @@ These switches are recognized when examining or depositing in CPU memory:
|
||||||
-u if mem mgt enabled, force user mode
|
-u if mem mgt enabled, force user mode
|
||||||
-p if mem mgt enabled, force previous mode
|
-p if mem mgt enabled, force previous mode
|
||||||
|
|
||||||
CPU registers include the visible state of the processor as well as the
|
CPU registers include the architectural state of the PDP-11 processor
|
||||||
control registers for the interrupt system.
|
as well as the control registers for the interrupt system.
|
||||||
|
|
||||||
name size comments
|
name size comments
|
||||||
|
|
||||||
|
@ -238,14 +271,8 @@ control registers for the interrupt system.
|
||||||
Z 1 zero flag, PSW<2>
|
Z 1 zero flag, PSW<2>
|
||||||
V 1 overflow flag, PSW<1>
|
V 1 overflow flag, PSW<1>
|
||||||
C 1 carry flag, PSW<0>
|
C 1 carry flag, PSW<0>
|
||||||
SR 16 front panel switches
|
|
||||||
DR 16 front panel display
|
|
||||||
MEMERR 16 memory error register
|
|
||||||
CCR 16 cache control register
|
|
||||||
MAINT 16 maintenance register
|
|
||||||
HITMISS 16 hit/miss register
|
|
||||||
CPUERR 16 CPU error register
|
|
||||||
PIRQ 16 programmed interrupt requests
|
PIRQ 16 programmed interrupt requests
|
||||||
|
STKLIM 16 stack limit
|
||||||
FAC0H..FAC5H 32 FAC0..FAC5, high 32 bits
|
FAC0H..FAC5H 32 FAC0..FAC5, high 32 bits
|
||||||
FAC0L..FAC5L 32 FAC0..FAC5, low 32 bits
|
FAC0L..FAC5L 32 FAC0..FAC5, low 32 bits
|
||||||
FPS 16 floating point status
|
FPS 16 floating point status
|
||||||
|
@ -254,9 +281,8 @@ control registers for the interrupt system.
|
||||||
MMR0..3 16 memory management registers 0..3
|
MMR0..3 16 memory management registers 0..3
|
||||||
{K/S/U}{I/D}{PAR/PDR}{0..7}
|
{K/S/U}{I/D}{PAR/PDR}{0..7}
|
||||||
16 memory management registers
|
16 memory management registers
|
||||||
UBMAP[0:63] 16 Unibus map registers
|
IREQ[0:7] 32 interrupt pending flags, IPL 0-7
|
||||||
INT 32 interrupt pending flags
|
TRAPS 18 trap pending flags
|
||||||
TRAP 18 trap pending flags
|
|
||||||
WAIT 0 wait state flag
|
WAIT 0 wait state flag
|
||||||
WAIT_ENABLE 0 wait state enable flag
|
WAIT_ENABLE 0 wait state enable flag
|
||||||
STOP_TRAPS 18 stop on trap flags
|
STOP_TRAPS 18 stop on trap flags
|
||||||
|
@ -266,7 +292,87 @@ control registers for the interrupt system.
|
||||||
most recent PC change first
|
most recent PC change first
|
||||||
WRU 8 interrupt character
|
WRU 8 interrupt character
|
||||||
|
|
||||||
2.2 I/O Device Addressing
|
2.1.2 System Registers (SYSTEM)
|
||||||
|
|
||||||
|
The SYSTEM device implements registers that vary from system to system:
|
||||||
|
|
||||||
|
name models size comments
|
||||||
|
|
||||||
|
SR 11/04, 11/05, 11/20, 16 switch register or
|
||||||
|
11/23+, 11/34, 11/40, configuration register
|
||||||
|
11/44, 11/45, 11/60,
|
||||||
|
11/70, 11/73B, 11/83,
|
||||||
|
11/84, 11/93, 11/94
|
||||||
|
DR 11/04, 11/05, 11/20, 16 display register or
|
||||||
|
1123+, 11/24, 11/34, board LEDs
|
||||||
|
11/70, 11/73B, 11/83,
|
||||||
|
11/84, 11/93, 11/94
|
||||||
|
MEMERR 11/44, 11/60, 11/70, 16 memory error register
|
||||||
|
11/53, 11/73, 11/73B,
|
||||||
|
11/83, 11/84, 11/93,
|
||||||
|
11/94
|
||||||
|
CCR 11/44, 11/60, 11/70, 16 cache control register
|
||||||
|
11/53, 11/73, 11/73B,
|
||||||
|
11/83, 11/84, 11/93,
|
||||||
|
11/94
|
||||||
|
MAINT 11/23+, 11/44, 11/70, 16 maintenance register
|
||||||
|
11/53, 11/73, 11/73B,
|
||||||
|
11/83, 11/84, 11/93,
|
||||||
|
11/94
|
||||||
|
HITMISS 11/44, 11/60, 11/70, 16 hit/miss register
|
||||||
|
11/53, 11/73, 11/73B,
|
||||||
|
11/83, 11/84, 11/93,
|
||||||
|
11/94
|
||||||
|
CPUERR 11/24, 11/44, 11/70, 16 CPU error register
|
||||||
|
11/53, 11/73, 11/73B,
|
||||||
|
11/83, 11/84, 11/93,
|
||||||
|
11/94
|
||||||
|
MBRK 11/45, 11/70 16 microbreak register
|
||||||
|
JCSR 11/53, 11/73B, 11/83, 16 board control/status
|
||||||
|
11/84, 11/93, 11/94
|
||||||
|
JPCR 11/23+, 11/53, 11/73B, 16 page control register
|
||||||
|
11/83, 11/84, 11/93,
|
||||||
|
11/94
|
||||||
|
JASR 11/93, 11/94 16 additional status
|
||||||
|
UDCR 11/84, 11/94 16 Unibus map diag control
|
||||||
|
UDDR 11/84, 11/94 16 Unibus map diag data
|
||||||
|
UCSR 11/84, 11/94 16 Unibus map control/status
|
||||||
|
ULAST 11/24 23 last Unibus map result
|
||||||
|
|
||||||
|
2.2 I/O Devices
|
||||||
|
|
||||||
|
2.2.1 Unibus and Qbus DMA Devices
|
||||||
|
|
||||||
|
DMA peripherals function differently, depending on whether the CPU is
|
||||||
|
configured for Unibus or Qbus, and whether the Unibus system supports
|
||||||
|
22b direct memory access (11/70 with RH70 controllers):
|
||||||
|
|
||||||
|
peripheral 11/70 all Qbus
|
||||||
|
+RH70 other
|
||||||
|
Unibus
|
||||||
|
|
||||||
|
RK 18b 18b disabled
|
||||||
|
HK 18b 18b disabled
|
||||||
|
RL 18b 18b 22b RLV12
|
||||||
|
RP 22b 18b 22b third party
|
||||||
|
RQ 18b 18b 22b RQDX3
|
||||||
|
RY 18b 18b disabled
|
||||||
|
TC 18b 18b disabled
|
||||||
|
TM 18b 18b disabled
|
||||||
|
TS 18b 18b 22b TSV05
|
||||||
|
TQ 18b 18b 22b TQK50
|
||||||
|
TU 22b 18b 22b third party
|
||||||
|
VH 18b 18b 22b DHQ11
|
||||||
|
XQ disabled 22b DELQA
|
||||||
|
XU 18b 18b disabled
|
||||||
|
|
||||||
|
Non-DMA peripherals work the same in all configurations. Unibus-only
|
||||||
|
peripherals are disabled in a Qbusconfiguration, and Qbus-only
|
||||||
|
peripherals are disabled in a Unibus configuration. In addition,
|
||||||
|
Qbus DMA peripherals with only 18b addressing capability are
|
||||||
|
disabled in a Qbus configuration with more than 256KB memory.
|
||||||
|
|
||||||
|
2.2.2 I/O Device Addressing
|
||||||
|
|
||||||
PDP-11 I/O space is not large enough to allow all possible devices to be
|
PDP-11 I/O space is not large enough to allow all possible devices to be
|
||||||
configured simultaneously at fixed addresses. Instead, many devices have
|
configured simultaneously at fixed addresses. Instead, many devices have
|
||||||
|
@ -274,6 +380,7 @@ floating addresses; that is, the assigned device address depends on the
|
||||||
presense of other devices in the configuration:
|
presense of other devices in the configuration:
|
||||||
|
|
||||||
DZ11 all instances have floating addresses
|
DZ11 all instances have floating addresses
|
||||||
|
DHU11/DHQ11 all instances have floating addresses
|
||||||
RL11 first instance has fixed address, rest floating
|
RL11 first instance has fixed address, rest floating
|
||||||
RX11/RX211 first instance has fixed address, rest floating
|
RX11/RX211 first instance has fixed address, rest floating
|
||||||
DEUNA/DELUA first instance has fixed address, rest floating
|
DEUNA/DELUA first instance has fixed address, rest floating
|
||||||
|
@ -550,8 +657,8 @@ locked, single or double density, or autosized:
|
||||||
SET RYn DOUBLE set unit n double density (default)
|
SET RYn DOUBLE set unit n double density (default)
|
||||||
SET RYn AUTOSIZE set unit n autosized
|
SET RYn AUTOSIZE set unit n autosized
|
||||||
|
|
||||||
The RX211 supports the BOOT command. The RX211 will not function
|
The RX211 supports the BOOT command. The RX211 is disabled in a
|
||||||
properly in a Qbus (22B) system with more than 256KB of memory.
|
Qbus (Q22) system with more than 256KB of memory.
|
||||||
|
|
||||||
The RX211 implements these registers:
|
The RX211 implements these registers:
|
||||||
|
|
||||||
|
@ -597,9 +704,9 @@ locked:
|
||||||
SET RKn LOCKED set unit n write locked
|
SET RKn LOCKED set unit n write locked
|
||||||
SET RKn WRITEENABLED set unit n write enabled
|
SET RKn WRITEENABLED set unit n write enabled
|
||||||
|
|
||||||
Units can also be set ONLINE or OFFLINE. The RK11 supports the BOOT
|
Units can also be set ENABLED or DISABLED. The RK11 supports the BOOT
|
||||||
command. The RK11 will not function properly in a Qbus (22B) system
|
command. The RK11 is disabled in a Qbus (Q22) system with more than
|
||||||
with more than 256KB of memory.
|
256KB of memory.
|
||||||
|
|
||||||
The RK11 implements these registers:
|
The RK11 implements these registers:
|
||||||
|
|
||||||
|
@ -648,11 +755,8 @@ a DEC standard 044 compliant bad block table on the last track:
|
||||||
|
|
||||||
The size options can be used only when a unit is not attached to a file.
|
The size options can be used only when a unit is not attached to a file.
|
||||||
The bad block option can be used only when a unit is attached to a file.
|
The bad block option can be used only when a unit is attached to a file.
|
||||||
Units can be set ONLINE or OFFLINE. The RK611 supports the BOOT command.
|
Units can be set ENABLED or DISABLED. The RK611 supports the BOOT command.
|
||||||
The RK611 will not function properly in a Qbus (22B) system with more
|
The RK611 is disabled in a Qbus (Q22) system with more than 256KB of memory.
|
||||||
than 256KB of memory using standard DEC software. The simulator implements
|
|
||||||
a third-party extension of addressing capability to 22b; this is only
|
|
||||||
supported by Ultrix-11.
|
|
||||||
|
|
||||||
The RK611 implements these registers:
|
The RK611 implements these registers:
|
||||||
|
|
||||||
|
@ -704,10 +808,9 @@ a DEC standard 044 compliant bad block table on the last track:
|
||||||
|
|
||||||
The size options can be used only when a unit is not attached to a file.
|
The size options can be used only when a unit is not attached to a file.
|
||||||
The bad block option can be used only when a unit is attached to a file.
|
The bad block option can be used only when a unit is attached to a file.
|
||||||
Units can be set ONLINE or OFFLINE. The RL11 supports the BOOT command.
|
Units can be set ENABLED or DISABLED. The RL11 supports the BOOT command.
|
||||||
In an 18B or Unibus system, the RL behaves like an RL11 with 18b
|
In a Unibus system, the RL behaves like an RL11 with 18b addressing; in
|
||||||
addressing; in a Qbus (22B) system, the RL behaves like the RLV12 with
|
a Qbus (Q22) system, the RL behaves like the RLV12 with 22b addressing.
|
||||||
22b addressing.
|
|
||||||
|
|
||||||
The RL11 implements these registers:
|
The RL11 implements these registers:
|
||||||
|
|
||||||
|
@ -737,14 +840,34 @@ Error handling is as follows:
|
||||||
|
|
||||||
OS I/O error x report error and stop
|
OS I/O error x report error and stop
|
||||||
|
|
||||||
2.6 RM02/03/05/80, RP04/05/06/07 Disk Pack Drives (RP)
|
2.6 Massbus Subsystems
|
||||||
|
|
||||||
The RP controller implements a "Massbus style" 22b direct interface
|
2.6.1 RH70/RH11 Massbus Adapters (RHA, RHB)
|
||||||
for large disk drives. It is more abstract than other device simulators,
|
|
||||||
with just enough detail to run operating system drivers. In addition,
|
|
||||||
the RP controller conflates the details of the RM series controllers
|
|
||||||
with the RP series controllers, although there were detailed differences.
|
|
||||||
|
|
||||||
|
The RH70/RH11 Massbus adapters interface Massbus peripherals to the
|
||||||
|
memory bus or Unibus of the CPU. The simulator provides two Massbus
|
||||||
|
adapters. The first, RHA, is configured for the RP family of disk
|
||||||
|
drives. The second, RHB, is configured for the TU family of tape
|
||||||
|
controllers. By default, RHA is enabled and RHB is disabled.
|
||||||
|
|
||||||
|
Each RH adapter implements these registers:
|
||||||
|
|
||||||
|
CS1 16 control/status register 1
|
||||||
|
WC 16 word count
|
||||||
|
BA 16 bus address
|
||||||
|
CS2 16 control/status register 2
|
||||||
|
DB 16 data buffer
|
||||||
|
BAE 6 bus address extension
|
||||||
|
CS3 16 control/status register 3
|
||||||
|
IFF 1 transfer complete interrupt request flop
|
||||||
|
INT 1 interrupt pending flag
|
||||||
|
SC 1 special condition (CSR1<15>)
|
||||||
|
DONE 1 device done flag (CSR1<7>)
|
||||||
|
IE 1 interrupt enable flag (CSR1<6>)
|
||||||
|
|
||||||
|
2.6.2 RM02/03/05/80, RP04/05/06/07 Disk Pack Drives (RP)
|
||||||
|
|
||||||
|
The RP controller implements the Massbus family of large disk drives.
|
||||||
RP options include the ability to set units write enabled or write
|
RP options include the ability to set units write enabled or write
|
||||||
locked, to set the drive type to one of six disk types, or autosize,
|
locked, to set the drive type to one of six disk types, or autosize,
|
||||||
and to write a DEC standard 044 compliant bad block table on the last
|
and to write a DEC standard 044 compliant bad block table on the last
|
||||||
|
@ -763,37 +886,29 @@ track:
|
||||||
|
|
||||||
The type options can be used only when a unit is not attached to a file.
|
The type options can be used only when a unit is not attached to a file.
|
||||||
The bad block option can be used only when a unit is attached to a file.
|
The bad block option can be used only when a unit is attached to a file.
|
||||||
Units can be set ONLINE or OFFLINE. The RP controller supports the
|
Units can be set ENABLED or DISABLED. The RP controller supports the
|
||||||
BOOT command. In a Unibus system, the RP can implement either 18b
|
BOOT command. In a Unibus system, the RP can implement either 18b
|
||||||
(RH11) addressing or 22b (RH70) addressing. In a Qbus (22B) system,
|
(URH11) addressing or 22b (URH70) addressing. In a Qbus (Q22) system,
|
||||||
the RP always implements 22b addressing.
|
the RP always implements 22b addressing.
|
||||||
|
|
||||||
The RP controller implements these registers:
|
The RP controller implements the registers listed below. Registers
|
||||||
|
suffixed with [0:7] are replicated per drive.
|
||||||
|
|
||||||
name size comments
|
name size comments
|
||||||
|
|
||||||
RPCS1 16 control/status 1
|
CS1[0:7] 16 current operation
|
||||||
RPWC 16 word count
|
DA[0:7] 16 desired surface, sector
|
||||||
RPBA 16 bus address
|
DS[0:7] 16 drive status
|
||||||
RPDA 16 desired surface, sector
|
ER1[0:7] 16 drive errors
|
||||||
RPCS2 16 control/status 2
|
OF[0:7] 16 offset
|
||||||
RPDS[0:7] 16 drive status, drives 0-7
|
DC[0:7] 16 desired cylinder
|
||||||
RPER1[0:7] 16 drive errors, drives 0-7
|
ER2[0:7] 16 error status 2
|
||||||
RPOF 16 offset
|
ER3[0:7] 16 error status 3
|
||||||
RPDC 16 desired cylinder
|
EC1[0:7] 16 ECC syndrome 1
|
||||||
RPER2 16 error status 2
|
EC2[0:7] 16 ECC syndrome 2
|
||||||
RPER3 16 error status 3
|
MR[0:7] 16 maintenance register
|
||||||
RPEC1 16 ECC syndrome 1
|
MR2[0:7] 16 maintenance register 2 (RM only)
|
||||||
RPEC2 16 ECC syndrome 2
|
HR[0:7] 16 holding register (RM only)
|
||||||
RPMR 16 maintenance register
|
|
||||||
RPDB 16 data buffer
|
|
||||||
RPBAE 6 bus address extension
|
|
||||||
RPCS3 16 control/status 3
|
|
||||||
IFF 1 transfer complete interrupt request flop
|
|
||||||
INT 1 interrupt pending flag
|
|
||||||
SC 1 special condition (CSR1<15>)
|
|
||||||
DONE 1 device done flag (CSR1<7>)
|
|
||||||
IE 1 interrupt enable flag (CSR1<6>)
|
|
||||||
STIME 24 seek time, per cylinder
|
STIME 24 seek time, per cylinder
|
||||||
RTIME 24 rotational delay
|
RTIME 24 rotational delay
|
||||||
STOP_IOE 1 stop on I/O error
|
STOP_IOE 1 stop on I/O error
|
||||||
|
@ -809,7 +924,49 @@ Error handling is as follows:
|
||||||
|
|
||||||
OS I/O error x report error and stop
|
OS I/O error x report error and stop
|
||||||
|
|
||||||
2.7 RQDX3 MSCP Disk Controllers (RQ, RQB, RQC, RQD)
|
2.6.3 TM02/TM03/TE16/TU45/TU77 Magtapes (TU)
|
||||||
|
|
||||||
|
The TU controller implementes the Massbus family of 800/1600bpi tape
|
||||||
|
drives. TU options include the ability to select the formatter type
|
||||||
|
(TM02 or TM03), to set the drive type to one of three drives (TE16,
|
||||||
|
TU45, or TU77), and to set the drives write enabled or write locked.
|
||||||
|
|
||||||
|
SET TU TM02 set controller type to TM02
|
||||||
|
SET TU TM03 set controller type to TM03
|
||||||
|
set TUn TE16 set drive type to TE16
|
||||||
|
SET TUn TU45 set drive type to TU45
|
||||||
|
SET TUn TU77 set drive type to TU77
|
||||||
|
|
||||||
|
Units can be set ENABLED or DISABLED. The TU controller supports the
|
||||||
|
BOOT command. In a Unibus system, the TU can implement either 18b
|
||||||
|
(URH11) addressing or 22b (URH70) addressing. In a Qbus (Q22) system,
|
||||||
|
the TU always implements 22b addressing.
|
||||||
|
|
||||||
|
The TU controller implements the following registers:
|
||||||
|
|
||||||
|
name size comments
|
||||||
|
|
||||||
|
CS1 6 current operation
|
||||||
|
FC 16 frame count
|
||||||
|
FS 16 formatter status
|
||||||
|
ER 16 formatter errors
|
||||||
|
CC 16 check character
|
||||||
|
MR 16 maintenance register
|
||||||
|
TC 16 tape control register
|
||||||
|
TIME 24 operation execution time
|
||||||
|
STOP_IOE 1 stop of I/O error
|
||||||
|
|
||||||
|
Error handling is as follows:
|
||||||
|
|
||||||
|
error processed as
|
||||||
|
|
||||||
|
not attached tape not ready; if STOP_IOE, stop
|
||||||
|
|
||||||
|
end of file bad tape
|
||||||
|
|
||||||
|
OS I/O error parity error; if STOP_IOE, stop
|
||||||
|
|
||||||
|
2.7 RQDX3/UDA50 MSCP Disk Controllers (RQ, RQB, RQC, RQD)
|
||||||
|
|
||||||
The simulator implements four MSCP disk controllers, RQ, RQB, RQC, RQD.
|
The simulator implements four MSCP disk controllers, RQ, RQB, RQC, RQD.
|
||||||
Initially, RQB, RQC, and RQD are disabled. Each RQ controller simulates
|
Initially, RQB, RQC, and RQD are disabled. Each RQ controller simulates
|
||||||
|
@ -831,16 +988,18 @@ of many disk types:
|
||||||
SET RQn RA90 set type to RA90
|
SET RQn RA90 set type to RA90
|
||||||
SET RQn RA92 set type to RA92
|
SET RQn RA92 set type to RA92
|
||||||
SET RQn RRD40 set type to RRD40 (CD ROM)
|
SET RQn RRD40 set type to RRD40 (CD ROM)
|
||||||
SET RQn RAUSER{=n} set type to RA81 with n LBNs
|
SET RQn RAUSER{=n} set type to RA81 with n MB's
|
||||||
|
SET -L RQn RAUSER{=n} set type to RA81 with n LBN's
|
||||||
|
|
||||||
The type options can be used only when a unit is not attached to a file.
|
The type options can be used only when a unit is not attached to a file.
|
||||||
RAUSER is a "user specified" disk; the user can specify the size of the
|
RAUSER is a "user specified" disk; the user can specify the size of the
|
||||||
disk in logical block numbers (LBN's, 512 bytes each). The minimum size
|
disk in either MB (1000000 bytes) or logical block numbers (LBN's, 512
|
||||||
is 50MB; the maximum size is 2GB.
|
bytes each). The minimum size is 5MB; the maximum size is 2GB.
|
||||||
|
|
||||||
Units can also be set ONLINE or OFFLINE. Each RQ controller supports the
|
Units can also be set ENABLED or DISABLED. Each RQ controller supports the
|
||||||
BOOT command. In a Unibus system, an RQ supports 18b addressing. In
|
BOOT command. In a Unibus system, an RQ supports 18b addressing and
|
||||||
a Qbus (22B) system, an RQ supports 22b addressing.
|
identifies itself as a UDA50. In a Qbus (Q22) system, an RQ supports 22b
|
||||||
|
addressing and identifies itself as an RQDX3.
|
||||||
|
|
||||||
Each RQ controller implements the following special SHOW commands:
|
Each RQ controller implements the following special SHOW commands:
|
||||||
|
|
||||||
|
@ -907,9 +1066,8 @@ locked.
|
||||||
SET DTn LOCKED set unit n write locked
|
SET DTn LOCKED set unit n write locked
|
||||||
SET DTn WRITEENABLED set unit n write enabled
|
SET DTn WRITEENABLED set unit n write enabled
|
||||||
|
|
||||||
Units can be set ONLINE or OFFLINE. The TC11 supports the BOOT command.
|
Units can be set ENABLED or DISABLED. The TC11 supports the BOOT command.
|
||||||
The TC11 will not function properly in a 22B (Qbus) system with more
|
The TC11 is automatically disabled in a Qbus system.
|
||||||
than 256KB of memory.
|
|
||||||
|
|
||||||
The TC11 supports supports PDP-8 format, PDP-11 format, and 18b format
|
The TC11 supports supports PDP-8 format, PDP-11 format, and 18b format
|
||||||
DECtape images. ATTACH tries to determine the tape format from the DECtape
|
DECtape images. ATTACH tries to determine the tape format from the DECtape
|
||||||
|
@ -965,7 +1123,7 @@ locked.
|
||||||
SET TMn LOCKED set unit n write locked
|
SET TMn LOCKED set unit n write locked
|
||||||
SET TMn WRITEENABLED set unit n write enabled
|
SET TMn WRITEENABLED set unit n write enabled
|
||||||
|
|
||||||
Units can be set ONLINE or OFFLINE.
|
Units can be set ENABLED or DISABLED.
|
||||||
|
|
||||||
The TM11 supports the BOOT command. The bootstrap supports both original
|
The TM11 supports the BOOT command. The bootstrap supports both original
|
||||||
and DEC standard boot formats. Originally, a tape bootstrap read and
|
and DEC standard boot formats. Originally, a tape bootstrap read and
|
||||||
|
@ -974,8 +1132,8 @@ standard bootstrap skipped the first record and read and executed the
|
||||||
second. The DEC standard is the default; to bootstrap an original format
|
second. The DEC standard is the default; to bootstrap an original format
|
||||||
tape, use the -o switch.
|
tape, use the -o switch.
|
||||||
|
|
||||||
The TM11 will not function properly in a Qbus (22B) system with more
|
The TM11 is automatically disabled in a Qbus (Q22) system with more than
|
||||||
than 256KB of memory
|
256KB of memory.
|
||||||
|
|
||||||
The TM controller implements these registers:
|
The TM controller implements these registers:
|
||||||
|
|
||||||
|
@ -1017,7 +1175,7 @@ The TS11 supports the BOOT command. The bootstrap supports only DEC
|
||||||
standard boot formats. To allow for ANSI labels, the DEC standard
|
standard boot formats. To allow for ANSI labels, the DEC standard
|
||||||
bootstrap skipped the first record and read and executed the second.
|
bootstrap skipped the first record and read and executed the second.
|
||||||
In a Unibus system, the TS behaves like the TS11 and implements 18b
|
In a Unibus system, the TS behaves like the TS11 and implements 18b
|
||||||
addresses. In a Qbus (22B) system, the TS behaves like the TSV05
|
addresses. In a Qbus (Q22) system, the TS behaves like the TSV05
|
||||||
and implements 22b addresses.
|
and implements 22b addresses.
|
||||||
|
|
||||||
The TS controller implements these registers:
|
The TS controller implements these registers:
|
||||||
|
@ -1077,7 +1235,7 @@ specify the controller type and tape length:
|
||||||
User-specified capacity must be between 50 and 2000 MB.
|
User-specified capacity must be between 50 and 2000 MB.
|
||||||
|
|
||||||
The TQ controller supports the BOOT command. In a Unibus system, the
|
The TQ controller supports the BOOT command. In a Unibus system, the
|
||||||
TQ supports 18b addressing. In a Qbus (22B) system, the TQ supports
|
TQ supports 18b addressing. In a Qbus (Q22) system, the TQ supports
|
||||||
22b addressing.
|
22b addressing.
|
||||||
|
|
||||||
The TQ controller implements the following special SHOW commands:
|
The TQ controller implements the following special SHOW commands:
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
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.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
04-Oct-04 RMS Added FIS instructions
|
||||||
19-Jan-03 RMS Changed mode definitions for Apple Dev Kit conflict
|
19-Jan-03 RMS Changed mode definitions for Apple Dev Kit conflict
|
||||||
08-Oct-02 RMS Fixed macro definitions
|
08-Oct-02 RMS Fixed macro definitions
|
||||||
05-Jun-98 RMS Fixed implementation specific shift bugs
|
05-Jun-98 RMS Fixed implementation specific shift bugs
|
||||||
|
@ -194,10 +195,13 @@
|
||||||
#define GET_SIGN_W(ir) GET_BIT((ir), 15)
|
#define GET_SIGN_W(ir) GET_BIT((ir), 15)
|
||||||
|
|
||||||
extern jmp_buf save_env;
|
extern jmp_buf save_env;
|
||||||
|
extern int32 cpu_type;
|
||||||
extern int32 FEC, FEA, FPS;
|
extern int32 FEC, FEA, FPS;
|
||||||
extern int32 CPUERR, trap_req;
|
extern int32 CPUERR, trap_req;
|
||||||
extern int32 N, Z, V, C;
|
extern int32 N, Z, V, C;
|
||||||
extern int32 R[8];
|
extern int32 R[8];
|
||||||
|
extern int32 STKLIM;
|
||||||
|
extern int32 cm, isenable, dsenable, MMR0, MMR1;
|
||||||
extern fpac_t FR[6];
|
extern fpac_t FR[6];
|
||||||
|
|
||||||
fpac_t zero_fac = { 0, 0 };
|
fpac_t zero_fac = { 0, 0 };
|
||||||
|
@ -219,7 +223,7 @@ int32 backup_PC;
|
||||||
int32 fpnotrap (int32 code);
|
int32 fpnotrap (int32 code);
|
||||||
int32 GeteaFP (int32 spec, int32 len);
|
int32 GeteaFP (int32 spec, int32 len);
|
||||||
|
|
||||||
unsigned int32 ReadI (int32 addr, int32 spec, int32 len);
|
uint32 ReadI (int32 addr, int32 spec, int32 len);
|
||||||
void ReadFP (fpac_t *fac, int32 addr, int32 spec, int32 len);
|
void ReadFP (fpac_t *fac, int32 addr, int32 spec, int32 len);
|
||||||
void WriteI (int32 data, int32 addr, int32 spec, int32 len);
|
void WriteI (int32 data, int32 addr, int32 spec, int32 len);
|
||||||
void WriteFP (fpac_t *data, int32 addr, int32 spec, int32 len);
|
void WriteFP (fpac_t *data, int32 addr, int32 spec, int32 len);
|
||||||
|
@ -235,6 +239,7 @@ int32 round_and_pack (fpac_t *fac, int32 exp, fpac_t *frac, int r);
|
||||||
extern int32 GeteaW (int32 spec);
|
extern int32 GeteaW (int32 spec);
|
||||||
extern int32 ReadW (int32 addr);
|
extern int32 ReadW (int32 addr);
|
||||||
extern void WriteW (int32 data, int32 addr);
|
extern void WriteW (int32 data, int32 addr);
|
||||||
|
extern void set_stack_trap (int32 adr);
|
||||||
|
|
||||||
/* Set up for instruction decode and execution */
|
/* Set up for instruction decode and execution */
|
||||||
|
|
||||||
|
@ -244,7 +249,7 @@ int32 dst, ea, ac, dstspec;
|
||||||
int32 i, qdouble, lenf, leni;
|
int32 i, qdouble, lenf, leni;
|
||||||
int32 newV, exp, sign;
|
int32 newV, exp, sign;
|
||||||
fpac_t fac, fsrc, modfrac;
|
fpac_t fac, fsrc, modfrac;
|
||||||
static const unsigned int32 i_limit[2][2] =
|
static const uint32 i_limit[2][2] =
|
||||||
{ { 0x80000000, 0x80010000 }, { 0x80000000, 0x80000001 } };
|
{ { 0x80000000, 0x80010000 }, { 0x80000000, 0x80000001 } };
|
||||||
|
|
||||||
backup_PC = PC; /* save PC for FEA */
|
backup_PC = PC; /* save PC for FEA */
|
||||||
|
@ -471,6 +476,9 @@ case 6: /* SUBf */
|
||||||
case 011: /* DIVf */
|
case 011: /* DIVf */
|
||||||
ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf);
|
ReadFP (&fsrc, GeteaFP (dstspec, lenf), dstspec, lenf);
|
||||||
F_LOAD (qdouble, FR[ac], fac);
|
F_LOAD (qdouble, FR[ac], fac);
|
||||||
|
if (GET_EXP (fsrc.h) == 0) { /* divide by zero? */
|
||||||
|
fpnotrap (FEC_DZRO);
|
||||||
|
ABORT (TRAP_INT); }
|
||||||
newV = divfp11 (&fac, &fsrc);
|
newV = divfp11 (&fac, &fsrc);
|
||||||
F_STORE (qdouble, fac, FR[ac]);
|
F_STORE (qdouble, fac, FR[ac]);
|
||||||
FPS = setfcc (FPS, fac.h, newV);
|
FPS = setfcc (FPS, fac.h, newV);
|
||||||
|
@ -494,7 +502,6 @@ return;
|
||||||
int32 GeteaFP (int32 spec, int32 len)
|
int32 GeteaFP (int32 spec, int32 len)
|
||||||
{
|
{
|
||||||
int32 adr, reg, ds;
|
int32 adr, reg, ds;
|
||||||
extern int32 cm, isenable, dsenable, MMR0, MMR1;
|
|
||||||
|
|
||||||
reg = spec & 07; /* reg number */
|
reg = spec & 07; /* reg number */
|
||||||
ds = (reg == 7)? isenable: dsenable; /* dspace if not PC */
|
ds = (reg == 7)? isenable: dsenable; /* dspace if not PC */
|
||||||
|
@ -517,16 +524,14 @@ case 3: /* @(R)+ */
|
||||||
case 4: /* -(R) */
|
case 4: /* -(R) */
|
||||||
adr = R[reg] = (R[reg] - len) & 0177777;
|
adr = R[reg] = (R[reg] - len) & 0177777;
|
||||||
if (update_MM) MMR1 = (((-len) & 037) << 3) | reg;
|
if (update_MM) MMR1 = (((-len) & 037) << 3) | reg;
|
||||||
if ((adr < STKLIM) && (reg == 6) && (cm == MD_KER)) {
|
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
|
||||||
setTRAP (TRAP_YEL);
|
set_stack_trap (adr);
|
||||||
setCPUERR (CPUE_YEL); }
|
|
||||||
return (adr | ds);
|
return (adr | ds);
|
||||||
case 5: /* @-(R) */
|
case 5: /* @-(R) */
|
||||||
adr = R[reg] = (R[reg] - 2) & 0177777;
|
adr = R[reg] = (R[reg] - 2) & 0177777;
|
||||||
if (update_MM) MMR1 = 0360 | reg;
|
if (update_MM) MMR1 = 0360 | reg;
|
||||||
if ((adr < STKLIM) && (reg == 6) && (cm == MD_KER)) {
|
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
|
||||||
setTRAP (TRAP_YEL);
|
set_stack_trap (adr);
|
||||||
setCPUERR (CPUE_YEL); }
|
|
||||||
adr = ReadW (adr | ds);
|
adr = ReadW (adr | ds);
|
||||||
return (adr | dsenable);
|
return (adr | dsenable);
|
||||||
case 6: /* d(r) */
|
case 6: /* d(r) */
|
||||||
|
@ -551,7 +556,7 @@ return 0;
|
||||||
data = data read from memory or I/O space
|
data = data read from memory or I/O space
|
||||||
*/
|
*/
|
||||||
|
|
||||||
unsigned int32 ReadI (int32 VA, int32 spec, int32 len)
|
uint32 ReadI (int32 VA, int32 spec, int32 len)
|
||||||
{
|
{
|
||||||
if ((len == WORD) || (spec == 027)) return (ReadW (VA) << 16);
|
if ((len == WORD) || (spec == 027)) return (ReadW (VA) << 16);
|
||||||
return ((ReadW (VA) << 16) | ReadW ((VA & ~0177777) | ((VA + 2) & 0177777)));
|
return ((ReadW (VA) << 16) | ReadW ((VA & ~0177777) | ((VA + 2) & 0177777)));
|
||||||
|
@ -633,6 +638,66 @@ WriteW ((fptr->l >> FP_V_F3) & 0177777, exta | ((VA + 6) & 0177777));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIS instructions */
|
||||||
|
|
||||||
|
t_stat fis11 (int32 IR)
|
||||||
|
{
|
||||||
|
int32 reg, exta;
|
||||||
|
fpac_t fac, fsrc;
|
||||||
|
|
||||||
|
reg = IR & 07; /* isolate reg */
|
||||||
|
if (reg == 7) exta = isenable; /* choose I,D */
|
||||||
|
else exta = dsenable;
|
||||||
|
if (IR & 000740) { /* defined? */
|
||||||
|
if (CPUT (CPUT_03)) ReadW (exta | R[reg]); /* 11/03 reads word */
|
||||||
|
ABORT (TRAP_ILL); }
|
||||||
|
FEC = 0; /* no errors */
|
||||||
|
FPS = FPS_IU|FPS_IV; /* trap ovf,unf */
|
||||||
|
|
||||||
|
fsrc.h = (ReadW (exta | R[reg]) << FP_V_F0) |
|
||||||
|
(ReadW (exta | ((R[reg] + 2) & 0177777)) << FP_V_F1);
|
||||||
|
fsrc.l = 0;
|
||||||
|
fac.h = (ReadW (exta | ((R[reg] + 4) & 0177777)) << FP_V_F0) |
|
||||||
|
(ReadW (exta | ((R[reg] + 6) & 0177777)) << FP_V_F1);
|
||||||
|
fac.l = 0;
|
||||||
|
if (GET_SIGN (fsrc.h) && (GET_EXP (fsrc.h) == 0)) /* clean 0's */
|
||||||
|
fsrc.h = fsrc.l = 0;
|
||||||
|
if (GET_SIGN (fac.h) && (GET_EXP (fac.l) == 0))
|
||||||
|
fac.h = fac.l = 0;
|
||||||
|
|
||||||
|
N = Z = V = C = 0; /* clear cc's */
|
||||||
|
switch ((IR >> 3) & 3) { /* case IR<5:3> */
|
||||||
|
|
||||||
|
case 0: /* FAD */
|
||||||
|
addfp11 (&fac, &fsrc);
|
||||||
|
break;
|
||||||
|
case 1: /* FSUB */
|
||||||
|
if (fsrc.h != 0) fsrc.h = fsrc.h ^ FP_SIGN; /* invert sign */
|
||||||
|
addfp11 (&fac, &fsrc);
|
||||||
|
break;
|
||||||
|
case 2: /* FMUL */
|
||||||
|
mulfp11 (&fac, &fsrc);
|
||||||
|
break;
|
||||||
|
case 3: /* FDIV */
|
||||||
|
if (fsrc.h == 0) { /* div by 0? */
|
||||||
|
V = N = C = 1; /* set cc's */
|
||||||
|
setTRAP (TRAP_FPE); /* set trap */
|
||||||
|
return SCPE_OK; }
|
||||||
|
else divfp11 (&fac, &fsrc);
|
||||||
|
break; }
|
||||||
|
|
||||||
|
if (FEC == 0) { /* no err? */
|
||||||
|
WriteW ((fac.h >> FP_V_F0) & 0177777, exta | ((R[reg] + 4) & 0177777));
|
||||||
|
WriteW ((fac.h >> FP_V_F1) & 0177777, exta | ((R[reg] + 6) & 0177777));
|
||||||
|
R[reg] = (R[reg] + 4) & 0177777; /* pop stack */
|
||||||
|
N = (GET_SIGN (fac.h) != 0); /* set N,Z */
|
||||||
|
Z = (fac.h == 0); }
|
||||||
|
else if (FEC == FEC_OVFLO) V = 1; /* ovf? trap set */
|
||||||
|
else if (FEC == FEC_UNFLO) V = N = 1; /* unf? trap set */
|
||||||
|
else return SCPE_IERR; /* what??? */
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* Floating point add
|
/* Floating point add
|
||||||
|
|
||||||
Inputs:
|
Inputs:
|
||||||
|
@ -864,6 +929,8 @@ return;
|
||||||
fsrcp = pointer to divisor
|
fsrcp = pointer to divisor
|
||||||
Outputs:
|
Outputs:
|
||||||
ovflo = overflow indicator
|
ovflo = overflow indicator
|
||||||
|
|
||||||
|
Source operand must be checked for zero by caller!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int32 divfp11 (fpac_t *facp, fpac_t *fsrcp)
|
int32 divfp11 (fpac_t *facp, fpac_t *fsrcp)
|
||||||
|
@ -872,9 +939,6 @@ int32 facexp, fsrcexp, i, count, qd;
|
||||||
fpac_t facfrac, fsrcfrac, quo;
|
fpac_t facfrac, fsrcfrac, quo;
|
||||||
|
|
||||||
fsrcexp = GET_EXP (fsrcp->h); /* get divisor exp */
|
fsrcexp = GET_EXP (fsrcp->h); /* get divisor exp */
|
||||||
if (fsrcexp == 0) { /* divide by zero? */
|
|
||||||
fpnotrap (FEC_DZRO);
|
|
||||||
ABORT (TRAP_INT); }
|
|
||||||
facexp = GET_EXP (facp->h); /* get dividend exp */
|
facexp = GET_EXP (facp->h); /* get dividend exp */
|
||||||
if (facexp == 0) { /* test for zero */
|
if (facexp == 0) { /* test for zero */
|
||||||
*facp = zero_fac; /* result zero */
|
*facp = zero_fac; /* result zero */
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
hk RK611/RK06/RK07 disk
|
hk RK611/RK06/RK07 disk
|
||||||
|
|
||||||
|
03-Oct-04 RMS Revised Unibus interface
|
||||||
|
RMS Fixed state of output ready for M+
|
||||||
26-Mar-04 RMS Fixed warnings with -std=c99
|
26-Mar-04 RMS Fixed warnings with -std=c99
|
||||||
25-Jan-04 RMS Revised for device debug support
|
25-Jan-04 RMS Revised for device debug support
|
||||||
04-Jan-04 RMS Changed sim_fsize calling sequence
|
04-Jan-04 RMS Changed sim_fsize calling sequence
|
||||||
|
@ -43,11 +45,16 @@
|
||||||
This module includes ideas from a previous implementation by Fred Van Kempen.
|
This module includes ideas from a previous implementation by Fred Van Kempen.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pdp11_defs.h"
|
#if defined (VM_PDP10) /* PDP10 version */
|
||||||
|
#error "RK611 is not supported on the PDP-10!"
|
||||||
|
|
||||||
#define HK_RDX 8
|
#elif defined (VM_VAX) /* VAX version */
|
||||||
#define HK_WID 16
|
#include "vax_defs.h"
|
||||||
extern int32 cpu_18b, cpu_ubm;
|
|
||||||
|
#else /* PDP-11 version */
|
||||||
|
#include "pdp11_defs.h"
|
||||||
|
extern int32 cpu_opt;
|
||||||
|
#endif
|
||||||
|
|
||||||
extern uint16 *M;
|
extern uint16 *M;
|
||||||
|
|
||||||
|
@ -379,37 +386,37 @@ UNIT hk_unit[] = {
|
||||||
UNIT_ROABLE+UNIT_RK06, RK06_SIZE) } };
|
UNIT_ROABLE+UNIT_RK06, RK06_SIZE) } };
|
||||||
|
|
||||||
REG hk_reg[] = {
|
REG hk_reg[] = {
|
||||||
{ GRDATA (HKCS1, hkcs1, HK_RDX, 16, 0) },
|
{ GRDATA (HKCS1, hkcs1, DEV_RDX, 16, 0) },
|
||||||
{ GRDATA (HKWC, hkwc, HK_RDX, 16, 0) },
|
{ GRDATA (HKWC, hkwc, DEV_RDX, 16, 0) },
|
||||||
{ GRDATA (HKBA, hkba, HK_RDX, 16, 0) },
|
{ GRDATA (HKBA, hkba, DEV_RDX, 16, 0) },
|
||||||
{ GRDATA (HKDA, hkda, HK_RDX, 16, 0) },
|
{ GRDATA (HKDA, hkda, DEV_RDX, 16, 0) },
|
||||||
{ GRDATA (HKCS2, hkcs2, HK_RDX, 16, 0) },
|
{ GRDATA (HKCS2, hkcs2, DEV_RDX, 16, 0) },
|
||||||
{ BRDATA (HKDS, hkds, HK_RDX, 16, HK_NUMDR) },
|
{ BRDATA (HKDS, hkds, DEV_RDX, 16, HK_NUMDR) },
|
||||||
{ BRDATA (HKER, hker, HK_RDX, 16, HK_NUMDR) },
|
{ BRDATA (HKER, hker, DEV_RDX, 16, HK_NUMDR) },
|
||||||
{ BRDATA (HKDB, hkdb, HK_RDX, 16, 3) },
|
{ BRDATA (HKDB, hkdb, DEV_RDX, 16, 3) },
|
||||||
{ GRDATA (HKDC, hkdc, HK_RDX, 16, 0) },
|
{ GRDATA (HKDC, hkdc, DEV_RDX, 16, 0) },
|
||||||
{ GRDATA (HKOF, hkof, HK_RDX, 8, 0) },
|
{ GRDATA (HKOF, hkof, DEV_RDX, 8, 0) },
|
||||||
{ GRDATA (HKMR, hkmr, HK_RDX, 16, 0) },
|
{ GRDATA (HKMR, hkmr, DEV_RDX, 16, 0) },
|
||||||
{ GRDATA (HKMR2, hkmr2, HK_RDX, 16, 0), REG_RO },
|
{ GRDATA (HKMR2, hkmr2, DEV_RDX, 16, 0), REG_RO },
|
||||||
{ GRDATA (HKMR3, hkmr3, HK_RDX, 16, 0), REG_RO },
|
{ GRDATA (HKMR3, hkmr3, DEV_RDX, 16, 0), REG_RO },
|
||||||
{ GRDATA (HKSPR, hkspr, HK_RDX, 16, 0) },
|
{ GRDATA (HKSPR, hkspr, DEV_RDX, 16, 0) },
|
||||||
{ FLDATA (INT, IREQ (HK), INT_V_HK) },
|
{ FLDATA (INT, IREQ (HK), INT_V_HK) },
|
||||||
{ FLDATA (ERR, hkcs1, CSR_V_ERR) },
|
{ FLDATA (ERR, hkcs1, CSR_V_ERR) },
|
||||||
{ FLDATA (DONE, hkcs1, CSR_V_DONE) },
|
{ FLDATA (DONE, hkcs1, CSR_V_DONE) },
|
||||||
{ FLDATA (IE, hkcs1, CSR_V_IE) },
|
{ FLDATA (IE, hkcs1, CSR_V_IE) },
|
||||||
{ DRDATA (STIME, hk_swait, 24), REG_NZ + PV_LEFT },
|
{ DRDATA (STIME, hk_swait, 24), REG_NZ + PV_LEFT },
|
||||||
{ DRDATA (RTIME, hk_rwait, 24), REG_NZ + PV_LEFT },
|
{ DRDATA (RTIME, hk_rwait, 24), REG_NZ + PV_LEFT },
|
||||||
{ URDATA (FNC, hk_unit[0].FNC, HK_RDX, 5, 0,
|
{ URDATA (FNC, hk_unit[0].FNC, DEV_RDX, 5, 0,
|
||||||
HK_NUMDR, REG_HRO) },
|
HK_NUMDR, REG_HRO) },
|
||||||
{ URDATA (CYL, hk_unit[0].CYL, HK_RDX, 10, 0,
|
{ URDATA (CYL, hk_unit[0].CYL, DEV_RDX, 10, 0,
|
||||||
HK_NUMDR, REG_HRO) },
|
HK_NUMDR, REG_HRO) },
|
||||||
{ BRDATA (OFFSET, hk_off, HK_RDX, 16, HK_NUMDR), REG_HRO },
|
{ BRDATA (OFFSET, hk_off, DEV_RDX, 16, HK_NUMDR), REG_HRO },
|
||||||
{ BRDATA (CYLDIF, hk_dif, HK_RDX, 16, HK_NUMDR), REG_HRO },
|
{ BRDATA (CYLDIF, hk_dif, DEV_RDX, 16, HK_NUMDR), REG_HRO },
|
||||||
{ URDATA (CAPAC, hk_unit[0].capac, 10, T_ADDR_W, 0,
|
{ URDATA (CAPAC, hk_unit[0].capac, 10, T_ADDR_W, 0,
|
||||||
HK_NUMDR, PV_LEFT | REG_HRO) },
|
HK_NUMDR, PV_LEFT | REG_HRO) },
|
||||||
{ FLDATA (STOP_IOE, hk_stopioe, 0) },
|
{ FLDATA (STOP_IOE, hk_stopioe, 0) },
|
||||||
{ GRDATA (DEVADDR, hk_dib.ba, HK_RDX, 32, 0), REG_HRO },
|
{ GRDATA (DEVADDR, hk_dib.ba, DEV_RDX, 32, 0), REG_HRO },
|
||||||
{ GRDATA (DEVVEC, hk_dib.vec, HK_RDX, 16, 0), REG_HRO },
|
{ GRDATA (DEVVEC, hk_dib.vec, DEV_RDX, 16, 0), REG_HRO },
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
MTAB hk_mod[] = {
|
MTAB hk_mod[] = {
|
||||||
|
@ -438,7 +445,7 @@ MTAB hk_mod[] = {
|
||||||
|
|
||||||
DEVICE hk_dev = {
|
DEVICE hk_dev = {
|
||||||
"HK", hk_unit, hk_reg, hk_mod,
|
"HK", hk_unit, hk_reg, hk_mod,
|
||||||
HK_NUMDR, HK_RDX, 24, 1, HK_RDX, HK_WID,
|
HK_NUMDR, DEV_RDX, 24, 1, DEV_RDX, 16,
|
||||||
NULL, NULL, &hk_reset,
|
NULL, NULL, &hk_reset,
|
||||||
&hk_boot, &hk_attach, &hk_detach,
|
&hk_boot, &hk_attach, &hk_detach,
|
||||||
&hk_dib, DEV_DISABLE | DEV_UBUS | DEV_Q18 | DEV_DEBUG };
|
&hk_dib, DEV_DISABLE | DEV_UBUS | DEV_Q18 | DEV_DEBUG };
|
||||||
|
@ -472,7 +479,7 @@ case 003: /* HKDA */
|
||||||
*data = hkda = hkda & ~DA_MBZ;
|
*data = hkda = hkda & ~DA_MBZ;
|
||||||
break;
|
break;
|
||||||
case 004: /* HKCS2 */
|
case 004: /* HKCS2 */
|
||||||
*data = hkcs2 = (hkcs2 & ~CS2_MBZ) | CS2_IR | CS2_OR;
|
*data = hkcs2 = (hkcs2 & ~CS2_MBZ) | CS2_IR;
|
||||||
break;
|
break;
|
||||||
case 005: /* HKDS */
|
case 005: /* HKDS */
|
||||||
*data = hkds[drv];
|
*data = hkds[drv];
|
||||||
|
@ -532,7 +539,7 @@ switch (j) { /* decode PA<4:1> */
|
||||||
case 000: /* HKCS1 */
|
case 000: /* HKCS1 */
|
||||||
if (data & CS1_CCLR) { /* controller reset? */
|
if (data & CS1_CCLR) { /* controller reset? */
|
||||||
hkcs1 = CS1_DONE; /* CS1 = done */
|
hkcs1 = CS1_DONE; /* CS1 = done */
|
||||||
hkcs2 = CS2_IR | CS2_OR; /* CS2 = ready */
|
hkcs2 = CS2_IR; /* CS2 = ready */
|
||||||
hkmr = hkmr2 = hkmr3 = 0; /* maint = 0 */
|
hkmr = hkmr2 = hkmr3 = 0; /* maint = 0 */
|
||||||
hkda = hkdc = 0;
|
hkda = hkdc = 0;
|
||||||
hkba = hkwc = 0;
|
hkba = hkwc = 0;
|
||||||
|
@ -564,7 +571,7 @@ case 003: /* HKDA */
|
||||||
break;
|
break;
|
||||||
case 004: /* HKCS2 */
|
case 004: /* HKCS2 */
|
||||||
if (data & CS2_CLR) hk_reset (&hk_dev); /* init? */
|
if (data & CS2_CLR) hk_reset (&hk_dev); /* init? */
|
||||||
else hkcs2 = (hkcs2 & ~CS2_RW) | (data & CS2_RW) | CS2_IR | CS2_OR;
|
else hkcs2 = (hkcs2 & ~CS2_RW) | (data & CS2_RW) | CS2_IR;
|
||||||
drv = GET_UNIT (hkcs2);
|
drv = GET_UNIT (hkcs2);
|
||||||
break;
|
break;
|
||||||
case 007: /* HKAS */
|
case 007: /* HKAS */
|
||||||
|
@ -780,12 +787,12 @@ case FNC_READ: /* read */
|
||||||
err = fseek (uptr->fileref, da * sizeof (int16), SEEK_SET);
|
err = fseek (uptr->fileref, da * sizeof (int16), SEEK_SET);
|
||||||
if (uptr->FNC == FNC_WRITE) { /* write? */
|
if (uptr->FNC == FNC_WRITE) { /* write? */
|
||||||
if (hkcs2 & CS2_UAI) { /* no addr inc? */
|
if (hkcs2 & CS2_UAI) { /* no addr inc? */
|
||||||
if (t = Map_ReadW (ba, 2, &comp, MAP)) { /* get 1st wd */
|
if (t = Map_ReadW (ba, 2, &comp)) { /* get 1st wd */
|
||||||
wc = 0; /* NXM, no xfr */
|
wc = 0; /* NXM, no xfr */
|
||||||
hkcs2 = hkcs2 | CS2_NEM; } /* set nxm err */
|
hkcs2 = hkcs2 | CS2_NEM; } /* set nxm err */
|
||||||
for (i = 0; i < wc; i++) hkxb[i] = comp; }
|
for (i = 0; i < wc; i++) hkxb[i] = comp; }
|
||||||
else { /* normal */
|
else { /* normal */
|
||||||
if (t = Map_ReadW (ba, wc << 1, hkxb, MAP)) { /* get buf */
|
if (t = Map_ReadW (ba, wc << 1, hkxb)) { /* get buf */
|
||||||
wc = wc - (t >> 1); /* NXM, adj wc */
|
wc = wc - (t >> 1); /* NXM, adj wc */
|
||||||
hkcs2 = hkcs2 | CS2_NEM; } /* set nxm err */
|
hkcs2 = hkcs2 | CS2_NEM; } /* set nxm err */
|
||||||
ba = ba + (wc << 1); } /* adv ba */
|
ba = ba + (wc << 1); } /* adv ba */
|
||||||
|
@ -800,11 +807,11 @@ case FNC_READ: /* read */
|
||||||
err = ferror (uptr->fileref);
|
err = ferror (uptr->fileref);
|
||||||
for ( ; i < wc; i++) hkxb[i] = 0; /* fill buf */
|
for ( ; i < wc; i++) hkxb[i] = 0; /* fill buf */
|
||||||
if (hkcs2 & CS2_UAI) { /* no addr inc? */
|
if (hkcs2 & CS2_UAI) { /* no addr inc? */
|
||||||
if (t = Map_WriteW (ba, 2, &hkxb[wc - 1], MAP)) {
|
if (t = Map_WriteW (ba, 2, &hkxb[wc - 1])) {
|
||||||
wc = 0; /* NXM, no xfr */
|
wc = 0; /* NXM, no xfr */
|
||||||
hkcs2 = hkcs2 | CS2_NEM; } } /* set nxm err */
|
hkcs2 = hkcs2 | CS2_NEM; } } /* set nxm err */
|
||||||
else { /* normal */
|
else { /* normal */
|
||||||
if (t = Map_WriteW (ba, wc << 1, hkxb, MAP)) { /* put buf */
|
if (t = Map_WriteW (ba, wc << 1, hkxb)) { /* put buf */
|
||||||
wc = wc - (t >> 1); /* NXM, adj wc */
|
wc = wc - (t >> 1); /* NXM, adj wc */
|
||||||
hkcs2 = hkcs2 | CS2_NEM; } /* set nxm err */
|
hkcs2 = hkcs2 | CS2_NEM; } /* set nxm err */
|
||||||
ba = ba + (wc << 1); } /* adv ba */
|
ba = ba + (wc << 1); } /* adv ba */
|
||||||
|
@ -815,7 +822,7 @@ case FNC_READ: /* read */
|
||||||
for ( ; i < wc; i++) hkxb[i] = 0; /* fill buf */
|
for ( ; i < wc; i++) hkxb[i] = 0; /* fill buf */
|
||||||
awc = wc;
|
awc = wc;
|
||||||
for (wc = 0; wc < awc; wc++) { /* loop thru buf */
|
for (wc = 0; wc < awc; wc++) { /* loop thru buf */
|
||||||
if (Map_ReadW (ba, 2, &comp, MAP)) { /* read word */
|
if (Map_ReadW (ba, 2, &comp)) { /* read word */
|
||||||
hkcs2 = hkcs2 | CS2_NEM; /* set error */
|
hkcs2 = hkcs2 | CS2_NEM; /* set error */
|
||||||
break; }
|
break; }
|
||||||
if (comp != hkxb[wc]) { /* compare wd */
|
if (comp != hkxb[wc]) { /* compare wd */
|
||||||
|
@ -999,7 +1006,7 @@ int32 i;
|
||||||
UNIT *uptr;
|
UNIT *uptr;
|
||||||
|
|
||||||
hkcs1 = CS1_DONE; /* set done */
|
hkcs1 = CS1_DONE; /* set done */
|
||||||
hkcs2 = CS2_IR | CS2_OR; /* clear state */
|
hkcs2 = CS2_IR; /* clear state */
|
||||||
hkmr = hkmr2 = hkmr3 = 0;
|
hkmr = hkmr2 = hkmr3 = 0;
|
||||||
hkda = hkdc = 0;
|
hkda = hkdc = 0;
|
||||||
hkba = hkwc = 0;
|
hkba = hkwc = 0;
|
||||||
|
@ -1014,7 +1021,7 @@ for (i = 0; i < HK_NUMDR; i++) { /* stop operations */
|
||||||
hk_dif[i] = 0;
|
hk_dif[i] = 0;
|
||||||
hk_off[i] = 0;
|
hk_off[i] = 0;
|
||||||
hker[i] = 0; } /* clear errors */
|
hker[i] = 0; } /* clear errors */
|
||||||
if (hkxb == NULL) hkxb = calloc (HK_MAXFR, sizeof (unsigned int16));
|
if (hkxb == NULL) hkxb = calloc (HK_MAXFR, sizeof (uint16));
|
||||||
if (hkxb == NULL) return SCPE_MEM;
|
if (hkxb == NULL) return SCPE_MEM;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -1082,6 +1089,8 @@ t_stat hk_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
return pdp11_bad_block (uptr, HK_NUMSC, HK_NUMWD);
|
return pdp11_bad_block (uptr, HK_NUMSC, HK_NUMWD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined (VM_PDP11)
|
||||||
|
|
||||||
/* Device bootstrap - does not clear CSR when done */
|
/* Device bootstrap - does not clear CSR when done */
|
||||||
|
|
||||||
#define BOOT_START 02000 /* start */
|
#define BOOT_START 02000 /* start */
|
||||||
|
@ -1134,3 +1143,12 @@ M[BOOT_CSR >> 1] = hk_dib.ba & DMASK;
|
||||||
saved_PC = BOOT_ENTRY;
|
saved_PC = BOOT_ENTRY;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
t_stat hk_boot (int32 unitno, DEVICE *dptr)
|
||||||
|
{
|
||||||
|
return SCPE_NOFNC;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
198
PDP11/pdp11_io.c
198
PDP11/pdp11_io.c
|
@ -23,6 +23,7 @@
|
||||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
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.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
30-Sep-04 RMS Revised Unibus interface
|
||||||
28-May-04 RMS Revised I/O dispatching (from John Dundas)
|
28-May-04 RMS Revised I/O dispatching (from John Dundas)
|
||||||
25-Jan-04 RMS Removed local debug logging support
|
25-Jan-04 RMS Removed local debug logging support
|
||||||
21-Dec-03 RMS Fixed bug in autoconfigure vector assignment; added controls
|
21-Dec-03 RMS Fixed bug in autoconfigure vector assignment; added controls
|
||||||
|
@ -43,18 +44,20 @@
|
||||||
extern uint16 *M;
|
extern uint16 *M;
|
||||||
extern int32 int_req[IPL_HLVL];
|
extern int32 int_req[IPL_HLVL];
|
||||||
extern int32 ub_map[UBM_LNT_LW];
|
extern int32 ub_map[UBM_LNT_LW];
|
||||||
extern int32 cpu_bme, cpu_18b, cpu_ubm;
|
extern int32 cpu_opt, cpu_bme;
|
||||||
extern int32 trap_req, ipl;
|
extern int32 trap_req, ipl;
|
||||||
extern int32 cpu_log;
|
extern int32 cpu_log;
|
||||||
extern int32 autcon_enb;
|
extern int32 autcon_enb;
|
||||||
|
extern int32 uba_last;
|
||||||
extern FILE *sim_log;
|
extern FILE *sim_log;
|
||||||
extern DEVICE *sim_devices[], cpu_dev;
|
extern DEVICE *sim_devices[], cpu_dev;
|
||||||
extern UNIT cpu_unit;
|
extern UNIT cpu_unit;
|
||||||
|
|
||||||
int32 calc_ints (int32 nipl, int32 trq);
|
int32 calc_ints (int32 nipl, int32 trq);
|
||||||
|
|
||||||
extern DIB cpu0_dib, cpu1_dib, cpu2_dib;
|
extern t_stat cpu_build_dib (void);
|
||||||
extern DIB cpu3_dib, cpu4_dib, ubm_dib;
|
extern void init_mbus_tab (void);
|
||||||
|
extern t_stat build_mbus_tab (DEVICE *dptr, DIB *dibp);
|
||||||
|
|
||||||
/* I/O data structures */
|
/* I/O data structures */
|
||||||
|
|
||||||
|
@ -66,14 +69,6 @@ int32 int_vec[IPL_HLVL][32]; /* int req to vector */
|
||||||
|
|
||||||
int32 (*int_ack[IPL_HLVL][32])(void); /* int ack routines */
|
int32 (*int_ack[IPL_HLVL][32])(void); /* int ack routines */
|
||||||
|
|
||||||
static DIB *std_dib[] = { /* standard DIBs */
|
|
||||||
&cpu0_dib,
|
|
||||||
&cpu1_dib,
|
|
||||||
&cpu2_dib,
|
|
||||||
&cpu3_dib,
|
|
||||||
&cpu4_dib,
|
|
||||||
NULL };
|
|
||||||
|
|
||||||
static const int32 pirq_bit[7] = {
|
static const int32 pirq_bit[7] = {
|
||||||
INT_V_PIR1, INT_V_PIR2, INT_V_PIR3, INT_V_PIR4,
|
INT_V_PIR1, INT_V_PIR2, INT_V_PIR3, INT_V_PIR4,
|
||||||
INT_V_PIR5, INT_V_PIR6, INT_V_PIR7 };
|
INT_V_PIR5, INT_V_PIR6, INT_V_PIR7 };
|
||||||
|
@ -152,52 +147,48 @@ return 0;
|
||||||
even = low 16b, bit <0> clear
|
even = low 16b, bit <0> clear
|
||||||
odd = high 6b
|
odd = high 6b
|
||||||
|
|
||||||
The Unibus map is stored as an array of longwords
|
The Unibus map is stored as an array of longwords.
|
||||||
|
These routines are only reachable if a Unibus map is configured.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
t_stat ubm_rd (int32 *data, int32 addr, int32 access)
|
t_stat ubm_rd (int32 *data, int32 addr, int32 access)
|
||||||
{
|
{
|
||||||
if (cpu_ubm) {
|
int32 pg = (addr >> 2) & UBM_M_PN;
|
||||||
int32 pg = (addr >> 2) & UBM_M_PN;
|
|
||||||
*data = (addr & 2)? ((ub_map[pg] >> 16) & 077):
|
*data = (addr & 2)? ((ub_map[pg] >> 16) & 077):
|
||||||
(ub_map[pg] & 0177776);
|
(ub_map[pg] & 0177776);
|
||||||
return SCPE_OK; }
|
return SCPE_OK;
|
||||||
return SCPE_NXM;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
t_stat ubm_wr (int32 data, int32 addr, int32 access)
|
t_stat ubm_wr (int32 data, int32 addr, int32 access)
|
||||||
{
|
{
|
||||||
if (cpu_ubm) {
|
int32 sc, pg = (addr >> 2) & UBM_M_PN;
|
||||||
int32 sc, pg = (addr >> 2) & UBM_M_PN;
|
if (access == WRITEB) {
|
||||||
if (access == WRITEB) {
|
|
||||||
sc = (addr & 3) << 3;
|
sc = (addr & 3) << 3;
|
||||||
ub_map[pg] = (ub_map[pg] & ~(0377 << sc)) |
|
ub_map[pg] = (ub_map[pg] & ~(0377 << sc)) |
|
||||||
((data & 0377) << sc); }
|
((data & 0377) << sc); }
|
||||||
else {
|
else { sc = (addr & 2) << 3;
|
||||||
sc = (addr & 2) << 3;
|
|
||||||
ub_map[pg] = (ub_map[pg] & ~(0177777 << sc)) |
|
ub_map[pg] = (ub_map[pg] & ~(0177777 << sc)) |
|
||||||
((data & 0177777) << sc); }
|
((data & 0177777) << sc); }
|
||||||
ub_map[pg] = ub_map[pg] & 017777776;
|
ub_map[pg] = ub_map[pg] & 017777776;
|
||||||
return SCPE_OK; }
|
return SCPE_OK;
|
||||||
return SCPE_NXM;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mapped memory access routines for DMA devices */
|
/* Mapped memory access routines for DMA devices */
|
||||||
|
|
||||||
#define BUSMASK(m) ((cpu_18b || (cpu_ubm && (m)))? UNIMASK: PAMASK)
|
#define BUSMASK ((UNIBUS)? UNIMASK: PAMASK)
|
||||||
|
|
||||||
/* Map I/O address to memory address */
|
/* Map I/O address to memory address - caller checks cpu_bme */
|
||||||
|
|
||||||
t_bool Map_Addr (uint32 ba, uint32 *ma)
|
uint32 Map_Addr (uint32 ba)
|
||||||
{
|
{
|
||||||
if (cpu_bme) { /* bus map on? */
|
int32 pg = UBM_GETPN (ba); /* map entry */
|
||||||
int32 pg = UBM_GETPN (ba); /* map entry */
|
int32 off = UBM_GETOFF (ba); /* offset */
|
||||||
int32 off = UBM_GETOFF (ba); /* offset */
|
|
||||||
if (pg != UBM_M_PN) /* last page? */
|
if (pg != UBM_M_PN) /* last page? */
|
||||||
*ma = (ub_map[pg] + off) & PAMASK; /* no, use map */
|
uba_last = (ub_map[pg] + off) & PAMASK; /* no, use map */
|
||||||
else *ma = (IOPAGEBASE + off) & PAMASK; } /* yes, use fixed */
|
else uba_last = (IOPAGEBASE + off) & PAMASK; /* yes, use fixed */
|
||||||
else *ma = ba; /* else physical */
|
return uba_last;
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* I/O buffer routines, aligned access
|
/* I/O buffer routines, aligned access
|
||||||
|
@ -206,17 +197,29 @@ return TRUE;
|
||||||
Map_ReadW - fetch word buffer from memory
|
Map_ReadW - fetch word buffer from memory
|
||||||
Map_WriteB - store byte buffer into memory
|
Map_WriteB - store byte buffer into memory
|
||||||
Map_WriteW - store word buffer into memory
|
Map_WriteW - store word buffer into memory
|
||||||
|
|
||||||
|
These routines are used only for Unibus and Qbus devices.
|
||||||
|
Massbus devices have their own IO routines. As a result,
|
||||||
|
the historic 'map' parameter is no longer needed.
|
||||||
|
|
||||||
|
- In a U18 configuration, the map is always disabled.
|
||||||
|
Device addresses are trimmed to 18b.
|
||||||
|
- In a U22 configuration, the map is always configured
|
||||||
|
(although it may be disabled). Device addresses are
|
||||||
|
trimmed to 18b.
|
||||||
|
- In a Qbus configuration, the map is always disabled.
|
||||||
|
Device addresses are trimmed to 22b.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int32 Map_ReadB (uint32 ba, int32 bc, uint8 *buf, t_bool map)
|
int32 Map_ReadB (uint32 ba, int32 bc, uint8 *buf)
|
||||||
{
|
{
|
||||||
uint32 alim, lim, ma;
|
uint32 alim, lim, ma;
|
||||||
|
|
||||||
ba = ba & BUSMASK (map); /* trim address */
|
ba = ba & BUSMASK; /* trim address */
|
||||||
lim = ba + bc;
|
lim = ba + bc;
|
||||||
if (map && cpu_bme) { /* map req & on? */
|
if (cpu_bme) { /* map enabled? */
|
||||||
for ( ; ba < lim; ba++) { /* by bytes */
|
for ( ; ba < lim; ba++) { /* by bytes */
|
||||||
Map_Addr (ba, &ma); /* map addr */
|
ma = Map_Addr (ba); /* map addr */
|
||||||
if (!ADDR_IS_MEM (ma)) return (lim - ba); /* NXM? err */
|
if (!ADDR_IS_MEM (ma)) return (lim - ba); /* NXM? err */
|
||||||
if (ma & 1) *buf++ = (M[ma >> 1] >> 8) & 0377; /* get byte */
|
if (ma & 1) *buf++ = (M[ma >> 1] >> 8) & 0377; /* get byte */
|
||||||
else *buf++ = M[ma >> 1] & 0377; }
|
else *buf++ = M[ma >> 1] & 0377; }
|
||||||
|
@ -231,15 +234,15 @@ else { /* physical */
|
||||||
return (lim - alim); }
|
return (lim - alim); }
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf, t_bool map)
|
int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf)
|
||||||
{
|
{
|
||||||
uint32 alim, lim, ma;
|
uint32 alim, lim, ma;
|
||||||
|
|
||||||
ba = (ba & BUSMASK (map)) & ~01; /* trim, align addr */
|
ba = (ba & BUSMASK) & ~01; /* trim, align addr */
|
||||||
lim = ba + (bc & ~01);
|
lim = ba + (bc & ~01);
|
||||||
if (map && cpu_bme) { /* map req & on? */
|
if (cpu_bme) { /* map enabled? */
|
||||||
for (; ba < lim; ba = ba + 2) { /* by words */
|
for (; ba < lim; ba = ba + 2) { /* by words */
|
||||||
Map_Addr (ba, &ma); /* map addr */
|
ma = Map_Addr (ba); /* map addr */
|
||||||
if (!ADDR_IS_MEM (ma)) return (lim - ba); /* NXM? err */
|
if (!ADDR_IS_MEM (ma)) return (lim - ba); /* NXM? err */
|
||||||
*buf++ = M[ma >> 1]; }
|
*buf++ = M[ma >> 1]; }
|
||||||
return 0; }
|
return 0; }
|
||||||
|
@ -252,15 +255,15 @@ else { /* physical */
|
||||||
return (lim - alim); }
|
return (lim - alim); }
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 Map_WriteB (uint32 ba, int32 bc, uint8 *buf, t_bool map)
|
int32 Map_WriteB (uint32 ba, int32 bc, uint8 *buf)
|
||||||
{
|
{
|
||||||
uint32 alim, lim, ma;
|
uint32 alim, lim, ma;
|
||||||
|
|
||||||
ba = ba & BUSMASK (map); /* trim address */
|
ba = ba & BUSMASK; /* trim address */
|
||||||
lim = ba + bc;
|
lim = ba + bc;
|
||||||
if (map && cpu_bme) { /* map req & on? */
|
if (cpu_bme) { /* map enabled? */
|
||||||
for ( ; ba < lim; ba++) { /* by bytes */
|
for ( ; ba < lim; ba++) { /* by bytes */
|
||||||
Map_Addr (ba, &ma); /* map addr */
|
ma = Map_Addr (ba); /* map addr */
|
||||||
if (!ADDR_IS_MEM (ma)) return (lim - ba); /* NXM? err */
|
if (!ADDR_IS_MEM (ma)) return (lim - ba); /* NXM? err */
|
||||||
if (ma & 1) M[ma >> 1] = (M[ma >> 1] & 0377) |
|
if (ma & 1) M[ma >> 1] = (M[ma >> 1] & 0377) |
|
||||||
((uint16) *buf++ << 8);
|
((uint16) *buf++ << 8);
|
||||||
|
@ -277,15 +280,15 @@ else { /* physical */
|
||||||
return (lim - alim); }
|
return (lim - alim); }
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 Map_WriteW (uint32 ba, int32 bc, uint16 *buf, t_bool map)
|
int32 Map_WriteW (uint32 ba, int32 bc, uint16 *buf)
|
||||||
{
|
{
|
||||||
uint32 alim, lim, ma;
|
uint32 alim, lim, ma;
|
||||||
|
|
||||||
ba = (ba & BUSMASK (map)) & ~01; /* trim, align addr */
|
ba = (ba & BUSMASK) & ~01; /* trim, align addr */
|
||||||
lim = ba + (bc & ~01);
|
lim = ba + (bc & ~01);
|
||||||
if (map && cpu_bme) { /* map req & on? */
|
if (cpu_bme) { /* map enabled? */
|
||||||
for (; ba < lim; ba = ba + 2) { /* by words */
|
for (; ba < lim; ba = ba + 2) { /* by words */
|
||||||
Map_Addr (ba, &ma); /* map addr */
|
ma = Map_Addr (ba); /* map addr */
|
||||||
if (!ADDR_IS_MEM (ma)) return (lim - ba); /* NXM? err */
|
if (!ADDR_IS_MEM (ma)) return (lim - ba); /* NXM? err */
|
||||||
M[ma >> 1] = *buf++; } /* store word */
|
M[ma >> 1] = *buf++; } /* store word */
|
||||||
return 0; }
|
return 0; }
|
||||||
|
@ -311,8 +314,7 @@ return auto_config (0, 0);
|
||||||
|
|
||||||
t_stat show_autocon (FILE *st, UNIT *uptr, int32 val, void *desc)
|
t_stat show_autocon (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
{
|
{
|
||||||
fprintf (st, "autoconfiguration ");
|
fprintf (st, "autoconfiguration %s", (autcon_enb? "on": "off"));
|
||||||
fprintf (st, autcon_enb? "enabled": "disabled");
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -421,36 +423,26 @@ else { fprintf (st, "vector=%o", vec);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Build dispatch tables */
|
/* Init Unibus tables */
|
||||||
|
|
||||||
t_stat build_dsp_tab (DEVICE *dptr, DIB *dibp)
|
void init_ubus_tab (void)
|
||||||
{
|
{
|
||||||
uint32 i, idx;
|
int32 i, j;
|
||||||
|
|
||||||
if ((dptr == NULL) || (dibp == NULL)) return SCPE_IERR; /* validate args */
|
for (i = 0; i < IPL_HLVL; i++) { /* clear intr tab */
|
||||||
for (i = 0; i < dibp->lnt; i = i + 2) { /* create entries */
|
for (j = 0; j < 32; j++) {
|
||||||
idx = ((dibp->ba + i) & IOPAGEMASK) >> 1; /* index into disp */
|
int_vec[i][j] = 0;
|
||||||
if ((iodispR[idx] && dibp->rd && /* conflict? */
|
int_ack[i][j] = NULL; } }
|
||||||
(iodispR[idx] != dibp->rd)) ||
|
for (i = 0; i < (IOPAGESIZE >> 1); i++) { /* clear dispatch tab */
|
||||||
(iodispW[idx] && dibp->wr &&
|
iodispR[i] = NULL;
|
||||||
(iodispW[idx] != dibp->wr))) {
|
iodispW[i] = NULL;
|
||||||
printf ("Device %s address conflict at %08o\n",
|
iodibp[i] = NULL; }
|
||||||
sim_dname (dptr), dibp->ba);
|
return;
|
||||||
if (sim_log) fprintf (sim_log,
|
|
||||||
"Device %s address conflict at %08o\n",
|
|
||||||
sim_dname (dptr), dibp->ba);
|
|
||||||
return SCPE_STOP;
|
|
||||||
}
|
|
||||||
if (dibp->rd) iodispR[idx] = dibp->rd; /* set rd dispatch */
|
|
||||||
if (dibp->wr) iodispW[idx] = dibp->wr; /* set wr dispatch */
|
|
||||||
iodibp[idx] = dibp; /* remember DIB */
|
|
||||||
}
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Build interrupt tables */
|
/* Build Unibus tables */
|
||||||
|
|
||||||
t_stat build_int_vec (DEVICE *dptr, DIB *dibp)
|
t_stat build_ubus_tab (DEVICE *dptr, DIB *dibp)
|
||||||
{
|
{
|
||||||
int32 i, idx, vec, ilvl, ibit;
|
int32 i, idx, vec, ilvl, ibit;
|
||||||
|
|
||||||
|
@ -475,45 +467,53 @@ for (i = 0; i < dibp->vnum; i++) { /* loop thru vec */
|
||||||
if (dibp->ack[i]) int_ack[ilvl][ibit] = dibp->ack[i];
|
if (dibp->ack[i]) int_ack[ilvl][ibit] = dibp->ack[i];
|
||||||
else if (vec) int_vec[ilvl][ibit] = vec;
|
else if (vec) int_vec[ilvl][ibit] = vec;
|
||||||
}
|
}
|
||||||
|
for (i = 0; i < (int32) dibp->lnt; i = i + 2) { /* create entries */
|
||||||
|
idx = ((dibp->ba + i) & IOPAGEMASK) >> 1; /* index into disp */
|
||||||
|
if ((iodispR[idx] && dibp->rd && /* conflict? */
|
||||||
|
(iodispR[idx] != dibp->rd)) ||
|
||||||
|
(iodispW[idx] && dibp->wr &&
|
||||||
|
(iodispW[idx] != dibp->wr))) {
|
||||||
|
printf ("Device %s address conflict at %08o\n",
|
||||||
|
sim_dname (dptr), dibp->ba);
|
||||||
|
if (sim_log) fprintf (sim_log,
|
||||||
|
"Device %s address conflict at %08o\n",
|
||||||
|
sim_dname (dptr), dibp->ba);
|
||||||
|
return SCPE_STOP;
|
||||||
|
}
|
||||||
|
if (dibp->rd) iodispR[idx] = dibp->rd; /* set rd dispatch */
|
||||||
|
if (dibp->wr) iodispW[idx] = dibp->wr; /* set wr dispatch */
|
||||||
|
iodibp[idx] = dibp; /* remember DIB */
|
||||||
|
}
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Build tables from device list */
|
/* Build tables from device list */
|
||||||
|
|
||||||
t_stat build_dib_tab (int32 ubm)
|
t_stat build_dib_tab (void)
|
||||||
{
|
{
|
||||||
int32 i, j;
|
int32 i;
|
||||||
DEVICE *dptr;
|
DEVICE *dptr;
|
||||||
DIB *dibp;
|
DIB *dibp;
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
for (i = 0; i < IPL_HLVL; i++) { /* clear intr tab */
|
init_ubus_tab (); /* init Unibus tables */
|
||||||
for (j = 0; j < 32; j++) {
|
init_mbus_tab (); /* init Massbus tables */
|
||||||
int_vec[i][j] = 0;
|
|
||||||
int_ack[i][j] = NULL; } }
|
|
||||||
for (i = 0; i < (IOPAGESIZE >> 1); i++) { /* clear dispatch tab */
|
|
||||||
iodispR[i] = NULL;
|
|
||||||
iodispW[i] = NULL;
|
|
||||||
iodibp[i] = NULL; }
|
|
||||||
for (i = 0; i < 7; i++) /* seed PIRQ intr */
|
for (i = 0; i < 7; i++) /* seed PIRQ intr */
|
||||||
int_vec[i + 1][pirq_bit[i]] = VEC_PIRQ;
|
int_vec[i + 1][pirq_bit[i]] = VEC_PIRQ;
|
||||||
|
if (r = cpu_build_dib ()) return r; /* build CPU entries */
|
||||||
for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */
|
for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */
|
||||||
dibp = (DIB *) dptr->ctxt; /* get DIB */
|
dibp = (DIB *) dptr->ctxt; /* get DIB */
|
||||||
if (dibp && !(dptr->flags & DEV_DIS)) { /* defined, enabled? */
|
if (dibp && !(dptr->flags & DEV_DIS)) { /* defined, enabled? */
|
||||||
if (r = build_int_vec (dptr, dibp)) /* add to intr tab */
|
if (dptr->flags & DEV_MBUS) { /* Massbus? */
|
||||||
|
if (r = build_mbus_tab (dptr, dibp)) /* add to Mbus tab */
|
||||||
return r;
|
return r;
|
||||||
if (r = build_dsp_tab (dptr, dibp)) /* add to dispatch tab */
|
}
|
||||||
|
else { /* no, Unibus */
|
||||||
|
if (r = build_ubus_tab (dptr, dibp)) /* add to Unibus tab */
|
||||||
return r;
|
return r;
|
||||||
|
}
|
||||||
} /* end if enabled */
|
} /* end if enabled */
|
||||||
} /* end for */
|
} /* end for */
|
||||||
for (i = 0; std_dib[i] != NULL; i++) { /* loop thru std */
|
|
||||||
if (r = build_dsp_tab (&cpu_dev, std_dib[i])) /* add to dispatch tab */
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
if (ubm) { /* Unibus map? */
|
|
||||||
if (r = build_dsp_tab (&cpu_dev, &ubm_dib)) /* add to dispatch tab */
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -525,7 +525,7 @@ uint32 i, j;
|
||||||
DEVICE *dptr;
|
DEVICE *dptr;
|
||||||
DIB *dibp;
|
DIB *dibp;
|
||||||
|
|
||||||
if (build_dib_tab (cpu_ubm)) return SCPE_OK; /* build IO page */
|
if (build_dib_tab ()) return SCPE_OK; /* build IO page */
|
||||||
for (i = 0, dibp = NULL; i < (IOPAGESIZE >> 1); i++) { /* loop thru entries */
|
for (i = 0, dibp = NULL; i < (IOPAGESIZE >> 1); i++) { /* loop thru entries */
|
||||||
if (iodibp[i] && (iodibp[i] != dibp)) { /* new block? */
|
if (iodibp[i] && (iodibp[i] != dibp)) { /* new block? */
|
||||||
dibp = iodibp[i]; /* DIB for block */
|
dibp = iodibp[i]; /* DIB for block */
|
||||||
|
|
|
@ -41,13 +41,9 @@
|
||||||
|
|
||||||
#elif defined (VM_VAX) /* VAX version */
|
#elif defined (VM_VAX) /* VAX version */
|
||||||
#include "vax_defs.h"
|
#include "vax_defs.h"
|
||||||
extern int32 int_req[IPL_HLVL];
|
|
||||||
extern int32 int_vec[IPL_HLVL][32];
|
|
||||||
|
|
||||||
#else /* PDP-11 version */
|
#else /* PDP-11 version */
|
||||||
#include "pdp11_defs.h"
|
#include "pdp11_defs.h"
|
||||||
extern int32 int_req[IPL_HLVL];
|
|
||||||
extern int32 int_vec[IPL_HLVL][32];
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define LPTCSR_IMP (CSR_ERR + CSR_DONE + CSR_IE) /* implemented */
|
#define LPTCSR_IMP (CSR_ERR + CSR_DONE + CSR_IE) /* implemented */
|
||||||
|
|
779
PDP11/pdp11_rh.c
Normal file
779
PDP11/pdp11_rh.c
Normal file
|
@ -0,0 +1,779 @@
|
||||||
|
/* pdp11_rh.c: PDP-11 Massbus adapter simulator
|
||||||
|
|
||||||
|
Copyright (c) 2004, 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"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
rha, rhb RH11/RH70 Massbus adapter
|
||||||
|
|
||||||
|
WARNING: The interupt logic of the RH11/RH70 is unusual and must be
|
||||||
|
simulated with great precision. The RH11 has an internal interrupt
|
||||||
|
request flop, CSTB INTR, which is controlled as follows:
|
||||||
|
- Writing IE and DONE simultaneously sets CSTB INTR
|
||||||
|
- Controller clear, INIT, and interrupt acknowledge clear CSTB INTR
|
||||||
|
(and also clear IE)
|
||||||
|
- A transition of DONE from 0 to 1 sets CSTB INTR from IE
|
||||||
|
The output of CSTB INTR is OR'd with the AND of RPCS1<SC,DONE,IE> to
|
||||||
|
create the interrupt request signal. Thus,
|
||||||
|
- The DONE interrupt is edge sensitive, but the SC interrupt is
|
||||||
|
level sensitive.
|
||||||
|
- The DONE interrupt, once set, is not disabled if IE is cleared,
|
||||||
|
but the SC interrupt is.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined (VM_PDP10) /* PDP10 version */
|
||||||
|
#error "PDP-10 uses pdp10_rp.c and pdp10_tu.c!"
|
||||||
|
|
||||||
|
#elif defined (VM_VAX) /* VAX version */
|
||||||
|
#error "VAX uses vax780_mba.c!"
|
||||||
|
|
||||||
|
#else /* PDP-11 version */
|
||||||
|
#include "pdp11_defs.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* CS1 - base + 000 - control/status 1 */
|
||||||
|
|
||||||
|
#define CS1_OF 0
|
||||||
|
#define CS1_GO CSR_GO /* go */
|
||||||
|
#define CS1_V_FNC 1 /* function pos */
|
||||||
|
#define CS1_M_FNC 037 /* function mask */
|
||||||
|
#define CS1_FNC (CS1_M_FNC << CS1_V_FNC)
|
||||||
|
#define FNC_XFER 024 /* >=? data xfr */
|
||||||
|
#define CS1_IE CSR_IE /* int enable */
|
||||||
|
#define CS1_DONE CSR_DONE /* ready */
|
||||||
|
#define CS1_V_UAE 8 /* Unibus addr ext */
|
||||||
|
#define CS1_M_UAE 03
|
||||||
|
#define CS1_UAE (CS1_M_UAE << CS1_V_UAE)
|
||||||
|
#define CS1_DVA 0004000 /* drive avail NI */
|
||||||
|
#define CS1_MCPE 0020000 /* Mbus par err NI */
|
||||||
|
#define CS1_TRE 0040000 /* transfer err */
|
||||||
|
#define CS1_SC 0100000 /* special cond */
|
||||||
|
#define CS1_MBZ 0012000
|
||||||
|
#define CS1_DRV (CS1_FNC | CS1_GO)
|
||||||
|
#define GET_FNC(x) (((x) >> CS1_V_FNC) & CS1_M_FNC)
|
||||||
|
|
||||||
|
/* WC - base + 002 - word count */
|
||||||
|
|
||||||
|
#define WC_OF 1
|
||||||
|
|
||||||
|
/* BA - base + 004 - base address */
|
||||||
|
|
||||||
|
#define BA_OF 2
|
||||||
|
#define BA_MBZ 0000001 /* must be zero */
|
||||||
|
|
||||||
|
/* CS2 - base + 010 - control/status 2 */
|
||||||
|
|
||||||
|
#define CS2_OF 3
|
||||||
|
#define CS2_V_UNIT 0 /* unit pos */
|
||||||
|
#define CS2_M_UNIT 07 /* unit mask */
|
||||||
|
#define CS2_UNIT (CS2_M_UNIT << CS2_V_UNIT)
|
||||||
|
#define CS2_UAI 0000010 /* addr inhibit */
|
||||||
|
#define CS2_PAT 0000020 /* parity test NI */
|
||||||
|
#define CS2_CLR 0000040 /* controller clear */
|
||||||
|
#define CS2_IR 0000100 /* input ready */
|
||||||
|
#define CS2_OR 0000200 /* output ready */
|
||||||
|
#define CS2_MDPE 0000400 /* Mbus par err NI */
|
||||||
|
#define CS2_MXF 0001000 /* missed xfer NI */
|
||||||
|
#define CS2_PGE 0002000 /* program err */
|
||||||
|
#define CS2_NEM 0004000 /* nx mem err */
|
||||||
|
#define CS2_NED 0010000 /* nx drive err */
|
||||||
|
#define CS2_PE 0020000 /* parity err NI */
|
||||||
|
#define CS2_WCE 0040000 /* write check err */
|
||||||
|
#define CS2_DLT 0100000 /* data late NI */
|
||||||
|
#define CS2_MBZ (CS2_CLR)
|
||||||
|
#define CS2_RW (CS2_UNIT | CS2_UAI | CS2_PAT | CS2_MXF | CS2_PE)
|
||||||
|
#define CS2_ERR (CS2_MDPE | CS2_MXF | CS2_PGE | CS2_NEM | \
|
||||||
|
CS2_NED | CS2_PE | CS2_WCE | CS2_DLT )
|
||||||
|
#define GET_UNIT(x) (((x) >> CS2_V_UNIT) & CS2_M_UNIT)
|
||||||
|
|
||||||
|
/* DB - base + 022 - data buffer */
|
||||||
|
|
||||||
|
#define DB_OF 4
|
||||||
|
|
||||||
|
/* BAE - base + 050/34 - bus address extension */
|
||||||
|
|
||||||
|
#define BAE_OF 5
|
||||||
|
#define AE_M_MAE 0 /* addr ext pos */
|
||||||
|
#define AE_V_MAE 077 /* addr ext mask */
|
||||||
|
#define AE_MBZ 0177700
|
||||||
|
|
||||||
|
/* CS3 - base + 052/36 - control/status 3 */
|
||||||
|
|
||||||
|
#define CS3_OF 6
|
||||||
|
#define CS3_APE 0100000 /* addr perr - NI */
|
||||||
|
#define CS3_DPO 0040000 /* data perr odd - NI */
|
||||||
|
#define CS3_DPE 0020000 /* data perr even - NI */
|
||||||
|
#define CS3_WCO 0010000 /* wchk err odd */
|
||||||
|
#define CS3_WCE 0004000 /* wchk err even */
|
||||||
|
#define CS3_DBL 0002000 /* dbl word xfer - NI */
|
||||||
|
#define CS3_IPCK 0000017 /* wrong par - NI */
|
||||||
|
#define CS3_ERR (CS3_APE|CS3_DPO|CS3_DPE|CS3_WCO|CS3_WCE)
|
||||||
|
#define CS3_MBZ 0001660
|
||||||
|
#define CS3_RW (CS1_IE | CS3_IPCK)
|
||||||
|
|
||||||
|
#define MBA_OFSMASK 077 /* max 32 reg */
|
||||||
|
#define INT 0000 /* int reg flag */
|
||||||
|
#define EXT 0100 /* ext reg flag */
|
||||||
|
|
||||||
|
/* Declarations */
|
||||||
|
|
||||||
|
#define RH11 (cpu_opt & OPT_RH11)
|
||||||
|
|
||||||
|
struct mbctx {
|
||||||
|
uint32 cs1; /* ctrl/status 1 */
|
||||||
|
uint32 wc; /* word count */
|
||||||
|
uint32 ba; /* bus addr */
|
||||||
|
uint32 cs2; /* ctrl/status 2 */
|
||||||
|
uint32 db; /* data buffer */
|
||||||
|
uint32 bae; /* addr ext */
|
||||||
|
uint32 cs3; /* ctrl/status 3 */
|
||||||
|
uint32 iff; /* int flip flop */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct mbctx MBACTX;
|
||||||
|
MBACTX massbus[MBA_NUM];
|
||||||
|
|
||||||
|
extern int32 cpu_opt, cpu_bme;
|
||||||
|
extern uint16 *M;
|
||||||
|
extern int32 int_req[IPL_HLVL];
|
||||||
|
extern int32 int_vec[IPL_HLVL][32];
|
||||||
|
extern UNIT cpu_unit;
|
||||||
|
extern FILE *sim_deb;
|
||||||
|
extern FILE *sim_log;
|
||||||
|
extern int32 sim_switches;
|
||||||
|
|
||||||
|
t_stat mba_reset (DEVICE *dptr);
|
||||||
|
t_stat mba_rd (int32 *val, int32 pa, int32 access);
|
||||||
|
t_stat mba_wr (int32 val, int32 pa, int32 access);
|
||||||
|
t_stat mba_set_type (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat mba_show_type (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
|
int32 mba0_inta (void);
|
||||||
|
int32 mba1_inta (void);
|
||||||
|
void mba_set_int (uint32 mb);
|
||||||
|
void mba_clr_int (uint32 mb);
|
||||||
|
void mba_upd_cs1 (uint32 set, uint32 clr, uint32 mb);
|
||||||
|
void mba_set_cs2 (uint32 flg, uint32 mb);
|
||||||
|
uint32 mba_map_pa (int32 pa, int32 *ofs);
|
||||||
|
DEVICE mba0_dev, mba1_dev;
|
||||||
|
|
||||||
|
extern uint32 Map_Addr (uint32 ba);
|
||||||
|
|
||||||
|
/* Maps */
|
||||||
|
|
||||||
|
static MBACTX *ctxmap[MBA_NUM] = { &massbus[0], &massbus[1] };
|
||||||
|
static DEVICE *devmap[MBA_NUM] = { &mba0_dev, &mba1_dev };
|
||||||
|
|
||||||
|
/* Massbus register dispatches */
|
||||||
|
|
||||||
|
static t_stat (*mbregR[MBA_NUM])(int32 *dat, int32 ad, int32 md);
|
||||||
|
static t_stat (*mbregW[MBA_NUM])(int32 dat, int32 ad, int32 md);
|
||||||
|
static int32 (*mbabort[MBA_NUM])(void);
|
||||||
|
|
||||||
|
/* Unibus to register offset map */
|
||||||
|
|
||||||
|
static int32 mba_mapofs[(MBA_OFSMASK + 1) >> 1] =
|
||||||
|
{ INT|0, INT|1, INT|2, EXT|5, INT|3, EXT|1, EXT|2, EXT|4,
|
||||||
|
EXT|7, INT|4, EXT|3, EXT|6, EXT|8, EXT|9, EXT|10, EXT|11,
|
||||||
|
EXT|12, EXT|13, EXT|14, EXT|15, EXT|16, EXT|17, EXT|18, EXT|19,
|
||||||
|
EXT|20, EXT|21, EXT|22, EXT|23, EXT|24, EXT|25, EXT|26, EXT|27 };
|
||||||
|
|
||||||
|
/* Massbus adapter data structures
|
||||||
|
|
||||||
|
mbax_dev RHx device descriptor
|
||||||
|
mbax_unit RHx units
|
||||||
|
mbax_reg RHx register list
|
||||||
|
*/
|
||||||
|
|
||||||
|
DIB mba0_dib = { IOBA_RP, IOLN_RP, &mba_rd, &mba_wr,
|
||||||
|
1, IVCL (RP), VEC_RP, { &mba0_inta } };
|
||||||
|
|
||||||
|
UNIT mba0_unit = { UDATA (NULL, 0, 0) };
|
||||||
|
|
||||||
|
REG mba0_reg[] = {
|
||||||
|
{ ORDATA (CS1, massbus[0].cs1, 16) },
|
||||||
|
{ ORDATA (WC, massbus[0].wc, 16) },
|
||||||
|
{ ORDATA (BA, massbus[0].ba, 16) },
|
||||||
|
{ ORDATA (CS2, massbus[0].cs2, 16) },
|
||||||
|
{ ORDATA (DB, massbus[0].db, 16) },
|
||||||
|
{ ORDATA (BAE, massbus[0].bae, 6) },
|
||||||
|
{ ORDATA (CS3, massbus[0].cs3, 16) },
|
||||||
|
{ FLDATA (IFF, massbus[0].iff, 0) },
|
||||||
|
{ FLDATA (INT, IREQ (RP), INT_V_RP) },
|
||||||
|
{ FLDATA (SC, massbus[0].cs1, CSR_V_ERR) },
|
||||||
|
{ FLDATA (DONE, massbus[0].cs1, CSR_V_DONE) },
|
||||||
|
{ FLDATA (IE, massbus[0].cs1, CSR_V_IE) },
|
||||||
|
{ ORDATA (DEVADDR, mba0_dib.ba, 32), REG_HRO },
|
||||||
|
{ ORDATA (DEVVEC, mba0_dib.vec, 16), REG_HRO },
|
||||||
|
{ NULL } };
|
||||||
|
|
||||||
|
MTAB mba0_mod[] = {
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 0100, "ADDRESS", "ADDRESS",
|
||||||
|
&set_addr, &show_addr, NULL },
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR",
|
||||||
|
&set_vec, &show_vec, NULL },
|
||||||
|
{ 0 } };
|
||||||
|
|
||||||
|
DEVICE mba0_dev = {
|
||||||
|
"RHA", &mba0_unit, mba0_reg, mba0_mod,
|
||||||
|
1, 0, 0, 0, 0, 0,
|
||||||
|
NULL, NULL, &mba_reset,
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
&mba0_dib, DEV_DEBUG | DEV_DISABLE | DEV_UBUS | DEV_QBUS };
|
||||||
|
|
||||||
|
DIB mba1_dib = { IOBA_TU, IOLN_TU, &mba_rd, &mba_wr,
|
||||||
|
1, IVCL (TU), VEC_TU, { &mba1_inta } };
|
||||||
|
|
||||||
|
UNIT mba1_unit = { UDATA (NULL, 0, 0) };
|
||||||
|
|
||||||
|
REG mba1_reg[] = {
|
||||||
|
{ ORDATA (CS1, massbus[1].cs1, 16) },
|
||||||
|
{ ORDATA (WC, massbus[1].wc, 16) },
|
||||||
|
{ ORDATA (BA, massbus[1].ba, 16) },
|
||||||
|
{ ORDATA (CS2, massbus[1].cs2, 16) },
|
||||||
|
{ ORDATA (DB, massbus[1].db, 16) },
|
||||||
|
{ ORDATA (BAE, massbus[1].bae, 6) },
|
||||||
|
{ ORDATA (CS3, massbus[1].cs3, 16) },
|
||||||
|
{ FLDATA (IFF, massbus[1].iff, 0) },
|
||||||
|
{ FLDATA (INT, IREQ (TU), INT_V_TU) },
|
||||||
|
{ FLDATA (SC, massbus[1].cs1, CSR_V_ERR) },
|
||||||
|
{ FLDATA (DONE, massbus[1].cs1, CSR_V_DONE) },
|
||||||
|
{ FLDATA (IE, massbus[1].cs1, CSR_V_IE) },
|
||||||
|
{ ORDATA (DEVADDR, mba1_dib.ba, 32), REG_HRO },
|
||||||
|
{ ORDATA (DEVVEC, mba1_dib.vec, 16), REG_HRO },
|
||||||
|
{ NULL } };
|
||||||
|
|
||||||
|
MTAB mba1_mod[] = {
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 0040, "ADDRESS", "ADDRESS",
|
||||||
|
&set_addr, &show_addr, NULL },
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR",
|
||||||
|
&set_vec, &show_vec, NULL },
|
||||||
|
{ 0 } };
|
||||||
|
|
||||||
|
DEVICE mba1_dev = {
|
||||||
|
"RHB", &mba1_unit, mba1_reg, mba1_mod,
|
||||||
|
1, 0, 0, 0, 0, 0,
|
||||||
|
NULL, NULL, &mba_reset,
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
&mba1_dib, DEV_DEBUG | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS };
|
||||||
|
|
||||||
|
/* Read Massbus adapter register */
|
||||||
|
|
||||||
|
t_stat mba_rd (int32 *val, int32 pa, int32 mode)
|
||||||
|
{
|
||||||
|
int32 ofs, dat, mb, drv;
|
||||||
|
t_stat r;
|
||||||
|
MBACTX *mbp;
|
||||||
|
|
||||||
|
mb = mba_map_pa (pa, &ofs); /* get mb number */
|
||||||
|
if ((mb < 0) || (ofs < 0)) return SCPE_NXM; /* valid? */
|
||||||
|
mbp = ctxmap[mb]; /* get context */
|
||||||
|
drv = GET_UNIT (mbp->cs2); /* get drive */
|
||||||
|
mba_upd_cs1 (0, 0, mb); /* update CS1 */
|
||||||
|
|
||||||
|
if (ofs & EXT) { /* external? */
|
||||||
|
if (!mbregR[mb]) return SCPE_NXM; /* device there? */
|
||||||
|
r = mbregR[mb] (val, ofs & ~EXT, drv); /* call device */
|
||||||
|
if (r == MBE_NXD) mba_set_cs2 (CS2_NED, mb); /* nx drive? */
|
||||||
|
else if (r == MBE_NXR) return SCPE_NXM; /* nx reg? */
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (ofs) { /* case on reg */
|
||||||
|
case CS1_OF: /* CS1 */
|
||||||
|
if (!mbregR[mb]) return SCPE_NXM; /* nx device? */
|
||||||
|
r = mbregR[mb] (&dat, ofs, drv); /* get dev cs1 */
|
||||||
|
if (r == MBE_NXD) mba_set_cs2 (CS2_NED, mb); /* nx drive? */
|
||||||
|
*val = mbp->cs1 | dat;
|
||||||
|
break;
|
||||||
|
case WC_OF: /* WC */
|
||||||
|
*val = mbp->wc;
|
||||||
|
break;
|
||||||
|
case BA_OF: /* BA */
|
||||||
|
*val = mbp->ba & ~BA_MBZ;
|
||||||
|
break;
|
||||||
|
case CS2_OF: /* CS2 */
|
||||||
|
*val = mbp->cs2 = (mbp->cs2 & ~CS2_MBZ) | CS2_IR | CS2_OR;
|
||||||
|
break;
|
||||||
|
case DB_OF: /* DB */
|
||||||
|
*val = mbp->db;
|
||||||
|
break;
|
||||||
|
case BAE_OF: /* BAE */
|
||||||
|
*val = mbp->bae = mbp->bae & ~AE_MBZ;
|
||||||
|
break;
|
||||||
|
case CS3_OF: /* CS3 */
|
||||||
|
*val = mbp->cs3 = (mbp->cs3 & ~(CS1_IE | CS3_MBZ)) | (mbp->cs1 & CS1_IE);
|
||||||
|
break;
|
||||||
|
default: /* huh? */
|
||||||
|
return SCPE_NXM;
|
||||||
|
}
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat mba_wr (int32 val, int32 pa, int32 access)
|
||||||
|
{
|
||||||
|
int32 ofs, cs1f, drv, mb;
|
||||||
|
t_stat r;
|
||||||
|
t_bool cs1dt;
|
||||||
|
MBACTX *mbp;
|
||||||
|
|
||||||
|
mb = mba_map_pa (pa, &ofs); /* get mb number */
|
||||||
|
if ((mb < 0) || (ofs < 0)) return SCPE_NXM; /* valid? */
|
||||||
|
mbp = ctxmap[mb]; /* get context */
|
||||||
|
drv = GET_UNIT (mbp->cs2); /* get drive */
|
||||||
|
|
||||||
|
if (ofs & EXT) { /* external? */
|
||||||
|
if (!mbregW[mb]) return SCPE_NXM; /* device there? */
|
||||||
|
if ((access == WRITEB) && (pa & 1)) /* byte writes */
|
||||||
|
val = val << 8; /* don't work */
|
||||||
|
r = mbregW[mb] (val, ofs & ~EXT, drv); /* write dev reg */
|
||||||
|
if (r == MBE_NXD) mba_set_cs2 (CS2_NED, mb); /* nx drive? */
|
||||||
|
else if (r == MBE_NXR) return SCPE_NXM; /* nx reg? */
|
||||||
|
mba_upd_cs1 (0, 0, mb); /* update status */
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
cs1f = 0; /* no int on cs1 upd */
|
||||||
|
switch (ofs) { /* case on reg */
|
||||||
|
case CS1_OF: /* CS1 */
|
||||||
|
if (!mbregW[mb]) return SCPE_NXM; /* device exist? */
|
||||||
|
if ((access == WRITEB) && (pa & 1)) val = val << 8;
|
||||||
|
if (val & CS1_TRE) { /* error clear? */
|
||||||
|
mbp->cs1 = mbp->cs1 & ~CS1_TRE; /* clr CS1<TRE> */
|
||||||
|
mbp->cs2 = mbp->cs2 & ~CS2_ERR; /* clr CS2<15:8> */
|
||||||
|
mbp->cs3 = mbp->cs3 & ~CS3_ERR; /* clr CS3<15:11> */
|
||||||
|
}
|
||||||
|
if ((access == WRITE) || (pa & 1)) { /* hi byte write? */
|
||||||
|
if (mbp->cs1 & CS1_DONE) /* done set? */
|
||||||
|
mbp->cs1 = (mbp->cs1 & ~CS1_UAE) | (val & CS1_UAE); }
|
||||||
|
if ((access == WRITE) || !(pa & 1)) { /* lo byte write? */
|
||||||
|
if ((val & CS1_DONE) && (val & CS1_IE)) /* to DONE+IE? */
|
||||||
|
mbp->iff = 1; /* set CSTB INTR */
|
||||||
|
mbp->cs1 = (mbp->cs1 & ~CS1_IE) | (val & CS1_IE);
|
||||||
|
cs1dt = (val & CS1_GO) && (GET_FNC (val) >= FNC_XFER);
|
||||||
|
if (cs1dt && ((mbp->cs1 & CS1_DONE) == 0)) /* dt, done clr? */
|
||||||
|
mba_set_cs2 (CS2_PGE, mb); /* prgm error */
|
||||||
|
else {
|
||||||
|
r = mbregW[mb] (val & 077, ofs, drv); /* write dev CS1 */
|
||||||
|
if (r == MBE_NXD) mba_set_cs2 (CS2_NED, mb); /* nx drive? */
|
||||||
|
else if (r == MBE_NXR) return SCPE_NXM; /* nx reg? */
|
||||||
|
else if (cs1dt && (r == SCPE_OK)) { /* xfer, no err? */
|
||||||
|
mbp->cs1 &= ~(CS1_TRE | CS1_MCPE | CS1_DONE);
|
||||||
|
mbp->cs2 &= ~CS2_ERR; /* clear errors */
|
||||||
|
mbp->cs3 &= ~(CS3_ERR | CS3_DBL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mbp->cs3 = (mbp->cs3 & ~CS1_IE) | /* update CS3 */
|
||||||
|
(mbp->cs1 & CS1_IE);
|
||||||
|
mbp->bae = (mbp->bae & ~CS1_M_UAE) | /* update BAE */
|
||||||
|
((mbp->cs1 >> CS1_V_UAE) & CS1_M_UAE);
|
||||||
|
break;
|
||||||
|
case WC_OF: /* WC */
|
||||||
|
if (access == WRITEB) val = (pa & 1)?
|
||||||
|
(mbp->wc & 0377) | (val << 8): (mbp->wc & ~0377) | val;
|
||||||
|
mbp->wc = val;
|
||||||
|
break;
|
||||||
|
case BA_OF: /* BA */
|
||||||
|
if (access == WRITEB) val = (pa & 1)?
|
||||||
|
(mbp->ba & 0377) | (val << 8): (mbp->ba & ~0377) | val;
|
||||||
|
mbp->ba = val & ~BA_MBZ;
|
||||||
|
break;
|
||||||
|
case CS2_OF: /* CS2 */
|
||||||
|
if ((access == WRITEB) && (pa & 1)) val = val << 8;
|
||||||
|
if (val & CS2_CLR) mba_reset (devmap[mb]); /* init? */
|
||||||
|
else {
|
||||||
|
if ((val & ~mbp->cs2) & (CS2_PE | CS2_MXF))
|
||||||
|
cs1f = CS1_SC; /* diagn intr */
|
||||||
|
if (access == WRITEB) val = (mbp->cs2 & /* merge val */
|
||||||
|
((pa & 1)? 0377: 0177400)) | val;
|
||||||
|
mbp->cs2 = (mbp->cs2 & ~CS2_RW) |
|
||||||
|
(val & CS2_RW) | CS2_IR | CS2_OR; }
|
||||||
|
break;
|
||||||
|
case DB_OF: /* DB */
|
||||||
|
if (access == WRITEB) val = (pa & 1)?
|
||||||
|
(mbp->db & 0377) | (val << 8): (mbp->db & ~0377) | val;
|
||||||
|
mbp->db = val;
|
||||||
|
break;
|
||||||
|
case BAE_OF: /* BAE */
|
||||||
|
if ((access == WRITEB) && (pa & 1)) break;
|
||||||
|
mbp->bae = val & ~AE_MBZ;
|
||||||
|
mbp->cs1 = (mbp->cs1 & ~CS1_UAE) | /* update CS1 */
|
||||||
|
((mbp->bae << CS1_V_UAE) & CS1_UAE);
|
||||||
|
break;
|
||||||
|
case CS3_OF: /* CS3 */
|
||||||
|
if ((access == WRITEB) && (pa & 1)) break;
|
||||||
|
mbp->cs3 = (mbp->cs3 & ~CS3_RW) | (val & CS3_RW);
|
||||||
|
mbp->cs1 = (mbp->cs1 & ~CS1_IE) | /* update CS1 */
|
||||||
|
(mbp->cs3 & CS1_IE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return SCPE_NXM;
|
||||||
|
}
|
||||||
|
mba_upd_cs1 (cs1f, 0, mb); /* update status */
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Massbus I/O routines
|
||||||
|
|
||||||
|
mb_rdbufW - fetch word buffer from memory
|
||||||
|
mb_wrbufW - store word buffer into memory
|
||||||
|
mb_chbufW - compare word buffer with memory
|
||||||
|
|
||||||
|
Returns number of bytes successfully transferred/checked
|
||||||
|
*/
|
||||||
|
|
||||||
|
int32 mba_rdbufW (uint32 mb, int32 bc, uint16 *buf)
|
||||||
|
{
|
||||||
|
MBACTX *mbp;
|
||||||
|
int32 i, j, ba, mbc, pbc;
|
||||||
|
uint32 pa;
|
||||||
|
|
||||||
|
bc = bc & ~1; /* bc even */
|
||||||
|
if (mb >= MBA_NUM) return 0; /* valid MBA? */
|
||||||
|
mbp = ctxmap[mb]; /* get context */
|
||||||
|
ba = (mbp->bae << 16) | mbp->ba; /* get busaddr */
|
||||||
|
mbc = (0200000 - mbp->wc) << 1; /* MB byte count */
|
||||||
|
if (bc > mbc) bc = mbc; /* use smaller */
|
||||||
|
for (i = 0; i < bc; i = i + pbc) { /* loop by pages */
|
||||||
|
if (RH11 && cpu_bme) pa = Map_Addr (ba); /* map addr */
|
||||||
|
else pa = ba;
|
||||||
|
if (!ADDR_IS_MEM (pa)) { /* NXM? */
|
||||||
|
mba_set_cs2 (CS2_NEM, mb); /* set error */
|
||||||
|
break; }
|
||||||
|
pbc = UBM_PAGSIZE - UBM_GETOFF (pa); /* left in page */
|
||||||
|
if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */
|
||||||
|
for (j = 0; j < pbc; j = j + 2) { /* loop by words */
|
||||||
|
*buf++ = M[pa >> 1]; /* fetch word */
|
||||||
|
if (!(mbp->cs2 & CS2_UAI)) { /* if not inhb */
|
||||||
|
ba = ba + 2; /* incr ba, pa */
|
||||||
|
pa = pa + 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mbp->wc = (mbp->wc + (bc >> 1)) & DMASK; /* update wc */
|
||||||
|
mbp->ba = ba & DMASK; /* update ba */
|
||||||
|
mbp->bae = (ba >> 16) & ~AE_MBZ; /* upper 6b */
|
||||||
|
mbp->cs1 = (mbp->cs1 & ~ CS1_UAE) | /* update CS1 */
|
||||||
|
((mbp->bae << CS1_V_UAE) & CS1_UAE);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 mba_wrbufW (uint32 mb, int32 bc, uint16 *buf)
|
||||||
|
{
|
||||||
|
MBACTX *mbp;
|
||||||
|
int32 i, j, ba, mbc, pbc;
|
||||||
|
uint32 pa;
|
||||||
|
|
||||||
|
bc = bc & ~1; /* bc even */
|
||||||
|
if (mb >= MBA_NUM) return 0; /* valid MBA? */
|
||||||
|
mbp = ctxmap[mb]; /* get context */
|
||||||
|
ba = (mbp->bae << 16) | mbp->ba; /* get busaddr */
|
||||||
|
mbc = (0200000 - mbp->wc) << 1; /* MB byte count */
|
||||||
|
if (bc > mbc) bc = mbc; /* use smaller */
|
||||||
|
for (i = 0; i < bc; i = i + pbc) { /* loop by pages */
|
||||||
|
if (RH11 && cpu_bme) pa = Map_Addr (ba); /* map addr */
|
||||||
|
else pa = ba;
|
||||||
|
if (!ADDR_IS_MEM (pa)) { /* NXM? */
|
||||||
|
mba_set_cs2 (CS2_NEM, mb); /* set error */
|
||||||
|
break; }
|
||||||
|
pbc = UBM_PAGSIZE - UBM_GETOFF (pa); /* left in page */
|
||||||
|
if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */
|
||||||
|
for (j = 0; j < pbc; j = j + 2) { /* loop by words */
|
||||||
|
M[pa >> 1] = *buf++; /* put word */
|
||||||
|
if (!(mbp->cs2 & CS2_UAI)) { /* if not inhb */
|
||||||
|
ba = ba + 2; /* incr ba, pa */
|
||||||
|
pa = pa + 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mbp->wc = (mbp->wc + (bc >> 1)) & DMASK; /* update wc */
|
||||||
|
mbp->ba = ba & DMASK; /* update ba */
|
||||||
|
mbp->bae = (ba >> 16) & ~AE_MBZ; /* upper 6b */
|
||||||
|
mbp->cs1 = (mbp->cs1 & ~ CS1_UAE) | /* update CS1 */
|
||||||
|
((mbp->bae << CS1_V_UAE) & CS1_UAE);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 mba_chbufW (uint32 mb, int32 bc, uint16 *buf)
|
||||||
|
{
|
||||||
|
MBACTX *mbp;
|
||||||
|
int32 i, j, ba, mbc, pbc;
|
||||||
|
uint32 pa;
|
||||||
|
|
||||||
|
bc = bc & ~1; /* bc even */
|
||||||
|
if (mb >= MBA_NUM) return 0; /* valid MBA? */
|
||||||
|
mbp = ctxmap[mb]; /* get context */
|
||||||
|
ba = (mbp->bae << 16) | mbp->ba; /* get busaddr */
|
||||||
|
mbc = (0200000 - mbp->wc) << 1; /* MB byte count */
|
||||||
|
if (bc > mbc) bc = mbc; /* use smaller */
|
||||||
|
for (i = 0; i < bc; i = i + pbc) { /* loop by pages */
|
||||||
|
if (RH11 && cpu_bme) pa = Map_Addr (ba); /* map addr */
|
||||||
|
else pa = ba;
|
||||||
|
if (!ADDR_IS_MEM (pa)) { /* NXM? */
|
||||||
|
mba_set_cs2 (CS2_NEM, mb); /* set error */
|
||||||
|
break; }
|
||||||
|
pbc = UBM_PAGSIZE - UBM_GETOFF (pa); /* left in page */
|
||||||
|
if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */
|
||||||
|
for (j = 0; j < pbc; j = j + 2) { /* loop by words */
|
||||||
|
mbp->db = *buf++; /* get dev word */
|
||||||
|
if (M[pa >> 1] != mbp->db) { /* miscompare? */
|
||||||
|
mba_set_cs2 (CS2_WCE, mb); /* set error */
|
||||||
|
mbp->cs3 = mbp->cs3 | /* set even/odd */
|
||||||
|
((pa & 1)? CS3_WCO: CS3_WCE);
|
||||||
|
break; }
|
||||||
|
if (!(mbp->cs2 & CS2_UAI)) { /* if not inhb */
|
||||||
|
ba = ba + 2; /* incr ba, pa */
|
||||||
|
pa = pa + 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mbp->wc = (mbp->wc + (bc >> 1)) & DMASK; /* update wc */
|
||||||
|
mbp->ba = ba & DMASK; /* update ba */
|
||||||
|
mbp->bae = (ba >> 16) & ~AE_MBZ; /* upper 6b */
|
||||||
|
mbp->cs1 = (mbp->cs1 & ~ CS1_UAE) | /* update CS1 */
|
||||||
|
((mbp->bae << CS1_V_UAE) & CS1_UAE);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Device access, status, and interrupt routines */
|
||||||
|
|
||||||
|
void mba_set_don (uint32 mb)
|
||||||
|
{
|
||||||
|
mba_upd_cs1 (CS1_DONE, 0, mb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mba_upd_ata (uint32 mb, uint32 val)
|
||||||
|
{
|
||||||
|
if (val) mba_upd_cs1 (CS1_SC, 0, mb);
|
||||||
|
else mba_upd_cs1 (0, CS1_SC, mb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mba_set_exc (uint32 mb)
|
||||||
|
{
|
||||||
|
mba_upd_cs1 (CS1_TRE | CS1_DONE, 0, mb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 mba_get_bc (uint32 mb)
|
||||||
|
{
|
||||||
|
MBACTX *mbp;
|
||||||
|
|
||||||
|
if (mb >= MBA_NUM) return 0;
|
||||||
|
mbp = ctxmap[mb];
|
||||||
|
return ((0200000 - mbp->wc) << 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 mba_get_csr (uint32 mb)
|
||||||
|
{
|
||||||
|
DEVICE *dptr;
|
||||||
|
DIB *dibp;
|
||||||
|
|
||||||
|
if (mb >= MBA_NUM) return 0;
|
||||||
|
dptr = devmap[mb];
|
||||||
|
dibp = (DIB *) dptr->ctxt;
|
||||||
|
return dibp->ba;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mba_set_int (uint32 mb)
|
||||||
|
{
|
||||||
|
DEVICE *dptr;
|
||||||
|
DIB *dibp;
|
||||||
|
|
||||||
|
if (mb >= MBA_NUM) return;
|
||||||
|
dptr = devmap[mb];
|
||||||
|
dibp = (DIB *) dptr->ctxt;
|
||||||
|
int_req[dibp->vloc >> 5] |= (1 << (dibp->vloc & 037));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mba_clr_int (uint32 mb)
|
||||||
|
{
|
||||||
|
DEVICE *dptr;
|
||||||
|
DIB *dibp;
|
||||||
|
|
||||||
|
if (mb >= MBA_NUM) return;
|
||||||
|
dptr = devmap[mb];
|
||||||
|
dibp = (DIB *) dptr->ctxt;
|
||||||
|
int_req[dibp->vloc >> 5] &= ~(1 << (dibp->vloc & 037));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mba_upd_cs1 (uint32 set, uint32 clr, uint32 mb)
|
||||||
|
{
|
||||||
|
MBACTX *mbp;
|
||||||
|
|
||||||
|
if (mb >= MBA_NUM) return;
|
||||||
|
mbp = ctxmap[mb];
|
||||||
|
if ((set & ~mbp->cs1) & CS1_DONE) /* DONE 0 to 1? */
|
||||||
|
mbp->iff = (mbp->cs1 & CS1_IE)? 1: 0; /* CSTB INTR <- IE */
|
||||||
|
mbp->cs1 = (mbp->cs1 & ~(clr | CS1_MCPE | CS1_MBZ | CS1_DRV)) | CS1_DVA | set;
|
||||||
|
if (mbp->cs2 & CS2_ERR) mbp->cs1 = mbp->cs1 | CS1_TRE | CS1_SC;
|
||||||
|
else if (mbp->cs1 & CS1_TRE) mbp->cs1 = mbp->cs1 | CS1_SC;
|
||||||
|
if (mbp->iff || ((mbp->cs1 & CS1_SC) && (mbp->cs1 & CS1_DONE) && (mbp->cs1 & CS1_IE)))
|
||||||
|
mba_set_int (mb);
|
||||||
|
else mba_clr_int (mb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mba_set_cs2 (uint32 flag, uint32 mb)
|
||||||
|
{
|
||||||
|
MBACTX *mbp;
|
||||||
|
|
||||||
|
if (mb >= MBA_NUM) return;
|
||||||
|
mbp = ctxmap[mb];
|
||||||
|
mbp->cs2 = mbp->cs2 | flag;
|
||||||
|
mba_upd_cs1 (0, 0, mb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Interrupt acknowledge */
|
||||||
|
|
||||||
|
int32 mba0_inta (void)
|
||||||
|
{
|
||||||
|
massbus[0].cs1 &= ~CS1_IE; /* clear int enable */
|
||||||
|
massbus[0].cs3 &= ~CS1_IE; /* in both registers */
|
||||||
|
massbus[0].iff = 0; /* clear CSTB INTR */
|
||||||
|
return mba0_dib.vec; /* acknowledge */
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 mba1_inta (void)
|
||||||
|
{
|
||||||
|
massbus[1].cs1 &= ~CS1_IE; /* clear int enable */
|
||||||
|
massbus[1].cs3 &= ~CS1_IE; /* in both registers */
|
||||||
|
massbus[1].iff = 0; /* clear CSTB INTR */
|
||||||
|
return mba1_dib.vec; /* acknowledge */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Map physical address to Massbus number, offset */
|
||||||
|
|
||||||
|
uint32 mba_map_pa (int32 pa, int32 *ofs)
|
||||||
|
{
|
||||||
|
int32 i, uo, ba, lnt;
|
||||||
|
DEVICE *dptr;
|
||||||
|
DIB *dibp;
|
||||||
|
|
||||||
|
for (i = 0; i < MBA_NUM; i++) { /* loop thru ctrls */
|
||||||
|
dptr = devmap[i]; /* get device */
|
||||||
|
dibp = (DIB *) dptr->ctxt; /* get DIB */
|
||||||
|
ba = dibp->ba;
|
||||||
|
lnt = dibp->lnt;
|
||||||
|
if ((pa >= ba) && /* in range? */
|
||||||
|
(pa < (ba + lnt))) {
|
||||||
|
if (pa < (ba + (lnt - 4))) { /* not last two? */
|
||||||
|
uo = ((pa - ba) & MBA_OFSMASK) >> 1; /* get Unibus offset */
|
||||||
|
*ofs = mba_mapofs[uo]; /* map thru PROM */
|
||||||
|
return i; /* return ctrl idx */
|
||||||
|
}
|
||||||
|
else if (RH11) return -1; /* RH11? done */
|
||||||
|
else { /* RH70 */
|
||||||
|
uo = (pa - (ba + (lnt - 4))) >> 1; /* offset relative */
|
||||||
|
*ofs = BAE_OF + uo; /* to BAE */
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset Massbus adapter */
|
||||||
|
|
||||||
|
t_stat mba_reset (DEVICE *dptr)
|
||||||
|
{
|
||||||
|
int32 mb;
|
||||||
|
MBACTX *mbp;
|
||||||
|
|
||||||
|
for (mb = 0; mb < MBA_NUM; mb++) {
|
||||||
|
mbp = ctxmap[mb];
|
||||||
|
if (dptr == devmap[mb]) break;
|
||||||
|
}
|
||||||
|
if (mb >= MBA_NUM) return SCPE_NOFNC;
|
||||||
|
mbp->cs1 = CS1_DONE;
|
||||||
|
mbp->wc = 0;
|
||||||
|
mbp->ba = 0;
|
||||||
|
mbp->cs2 = 0;
|
||||||
|
mbp->db = 0;
|
||||||
|
mbp->bae= 0;
|
||||||
|
mbp->cs3 = 0;
|
||||||
|
mbp->iff = 0;
|
||||||
|
mba_clr_int (mb);
|
||||||
|
if (mbabort[mb]) mbabort[mb] ();
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Show Massbus adapter number */
|
||||||
|
|
||||||
|
t_stat mba_show_num (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
|
{
|
||||||
|
DEVICE *dptr = find_dev_from_unit (uptr);
|
||||||
|
DIB *dibp;
|
||||||
|
|
||||||
|
if (dptr == NULL) return SCPE_IERR;
|
||||||
|
dibp = (DIB *) dptr->ctxt;
|
||||||
|
if (dibp == NULL) return SCPE_IERR;
|
||||||
|
fprintf (st, "Massbus adapter %d", dibp->ba);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Init Mbus tables */
|
||||||
|
|
||||||
|
void init_mbus_tab (void)
|
||||||
|
{
|
||||||
|
uint32 i;
|
||||||
|
|
||||||
|
for (i = 0; i < MBA_NUM; i++) {
|
||||||
|
mbregR[i] = NULL;
|
||||||
|
mbregW[i] = NULL;
|
||||||
|
mbabort[i] = NULL;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build dispatch tables */
|
||||||
|
|
||||||
|
t_stat build_mbus_tab (DEVICE *dptr, DIB *dibp)
|
||||||
|
{
|
||||||
|
uint32 idx;
|
||||||
|
|
||||||
|
if ((dptr == NULL) || (dibp == NULL)) return SCPE_IERR; /* validate args */
|
||||||
|
idx = dibp->ba; /* Mbus # */
|
||||||
|
if (idx >= MBA_NUM) return SCPE_STOP;
|
||||||
|
if ((mbregR[idx] && dibp->rd && /* conflict? */
|
||||||
|
(mbregR[idx] != dibp->rd)) ||
|
||||||
|
(mbregW[idx] && dibp->wr &&
|
||||||
|
(mbregW[idx] != dibp->wr)) ||
|
||||||
|
(mbabort[idx] && dibp->ack[0] &&
|
||||||
|
(mbabort[idx] != dibp->ack[0]))) {
|
||||||
|
printf ("Massbus %s assignment conflict at %d\n",
|
||||||
|
sim_dname (dptr), dibp->ba);
|
||||||
|
if (sim_log) fprintf (sim_log,
|
||||||
|
"Massbus %s assignment conflict at %d\n",
|
||||||
|
sim_dname (dptr), dibp->ba);
|
||||||
|
return SCPE_STOP;
|
||||||
|
}
|
||||||
|
if (dibp->rd) mbregR[idx] = dibp->rd; /* set rd dispatch */
|
||||||
|
if (dibp->wr) mbregW[idx] = dibp->wr; /* set wr dispatch */
|
||||||
|
if (dibp->ack[0]) mbabort[idx] = dibp->ack[0]; /* set abort dispatch */
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
rk RK11/RKV11/RK05 cartridge disk
|
rk RK11/RKV11/RK05 cartridge disk
|
||||||
|
|
||||||
|
30-Sep-04 RMS Revised Unibus interface
|
||||||
24-Jan-04 RMS Added increment inhibit, overrun detection, formatting
|
24-Jan-04 RMS Added increment inhibit, overrun detection, formatting
|
||||||
29-Dec-03 RMS Added RKV11 support
|
29-Dec-03 RMS Added RKV11 support
|
||||||
29-Sep-02 RMS Added variable address support to bootstrap
|
29-Sep-02 RMS Added variable address support to bootstrap
|
||||||
|
@ -484,12 +485,12 @@ if (wc && (err == 0)) { /* seek ok? */
|
||||||
for ( ; i < wc; i++) rkxb[i] = 0; /* fill buf */
|
for ( ; i < wc; i++) rkxb[i] = 0; /* fill buf */
|
||||||
}
|
}
|
||||||
if (rkcs & RKCS_INH) { /* incr inhibit? */
|
if (rkcs & RKCS_INH) { /* incr inhibit? */
|
||||||
if (t = Map_WriteW (ma, 2, &rkxb[wc - 1], MAP)) { /* store last */
|
if (t = Map_WriteW (ma, 2, &rkxb[wc - 1])) { /* store last */
|
||||||
rker = rker | RKER_NXM; /* NXM? set flag */
|
rker = rker | RKER_NXM; /* NXM? set flag */
|
||||||
wc = 0; } /* no transfer */
|
wc = 0; } /* no transfer */
|
||||||
}
|
}
|
||||||
else { /* normal store */
|
else { /* normal store */
|
||||||
if (t = Map_WriteW (ma, wc << 1, rkxb, MAP)) { /* store buf */
|
if (t = Map_WriteW (ma, wc << 1, rkxb)) { /* store buf */
|
||||||
rker = rker | RKER_NXM; /* NXM? set flag */
|
rker = rker | RKER_NXM; /* NXM? set flag */
|
||||||
wc = wc - t; } /* adj wd cnt */
|
wc = wc - t; } /* adj wd cnt */
|
||||||
}
|
}
|
||||||
|
@ -497,13 +498,13 @@ if (wc && (err == 0)) { /* seek ok? */
|
||||||
|
|
||||||
case RKCS_WRITE: /* write */
|
case RKCS_WRITE: /* write */
|
||||||
if (rkcs & RKCS_INH) { /* incr inhibit? */
|
if (rkcs & RKCS_INH) { /* incr inhibit? */
|
||||||
if (t = Map_ReadW (ma, 2, &comp, MAP)) { /* get 1st word */
|
if (t = Map_ReadW (ma, 2, &comp)) { /* get 1st word */
|
||||||
rker = rker | RKER_NXM; /* NXM? set flag */
|
rker = rker | RKER_NXM; /* NXM? set flag */
|
||||||
wc = 0; } /* no transfer */
|
wc = 0; } /* no transfer */
|
||||||
for (i = 0; i < wc; i++) rkxb[i] = comp; /* all words same */
|
for (i = 0; i < wc; i++) rkxb[i] = comp; /* all words same */
|
||||||
}
|
}
|
||||||
else { /* normal fetch */
|
else { /* normal fetch */
|
||||||
if (t = Map_ReadW (ma, wc << 1, rkxb, MAP)) { /* get buf */
|
if (t = Map_ReadW (ma, wc << 1, rkxb)) { /* get buf */
|
||||||
rker = rker | RKER_NXM; /* NXM? set flg */
|
rker = rker | RKER_NXM; /* NXM? set flg */
|
||||||
wc = wc - t; } /* adj wd cnt */
|
wc = wc - t; } /* adj wd cnt */
|
||||||
}
|
}
|
||||||
|
@ -523,7 +524,7 @@ if (wc && (err == 0)) { /* seek ok? */
|
||||||
for ( ; i < wc; i++) rkxb[i] = 0; /* fill buf */
|
for ( ; i < wc; i++) rkxb[i] = 0; /* fill buf */
|
||||||
awc = wc; /* save wc */
|
awc = wc; /* save wc */
|
||||||
for (wc = 0, cma = ma; wc < awc; wc++) { /* loop thru buf */
|
for (wc = 0, cma = ma; wc < awc; wc++) { /* loop thru buf */
|
||||||
if (Map_ReadW (cma, 2, &comp, MAP)) { /* mem wd */
|
if (Map_ReadW (cma, 2, &comp)) { /* mem wd */
|
||||||
rker = rker | RKER_NXM; /* NXM? set flg */
|
rker = rker | RKER_NXM; /* NXM? set flg */
|
||||||
break; }
|
break; }
|
||||||
if (comp != rkxb[wc]) { /* match to disk? */
|
if (comp != rkxb[wc]) { /* match to disk? */
|
||||||
|
@ -618,7 +619,7 @@ for (i = 0; i < RK_NUMDR; i++) {
|
||||||
sim_cancel (uptr);
|
sim_cancel (uptr);
|
||||||
uptr->CYL = uptr->FUNC = 0;
|
uptr->CYL = uptr->FUNC = 0;
|
||||||
uptr->flags = uptr->flags & ~UNIT_SWLK; }
|
uptr->flags = uptr->flags & ~UNIT_SWLK; }
|
||||||
if (rkxb == NULL) rkxb = calloc (RK_MAXFR, sizeof (unsigned int16));
|
if (rkxb == NULL) rkxb = calloc (RK_MAXFR, sizeof (uint16));
|
||||||
if (rkxb == NULL) return SCPE_MEM;
|
if (rkxb == NULL) return SCPE_MEM;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
rl RL11(RLV12)/RL01/RL02 cartridge disk
|
rl RL11(RLV12)/RL01/RL02 cartridge disk
|
||||||
|
|
||||||
|
30-Sep-04 RMS Revised Unibus interface
|
||||||
04-Jan-04 RMS Changed sim_fsize calling sequence
|
04-Jan-04 RMS Changed sim_fsize calling sequence
|
||||||
19-May-03 RMS Revised for new conditional compilation scheme
|
19-May-03 RMS Revised for new conditional compilation scheme
|
||||||
25-Apr-03 RMS Revised for extended file support
|
25-Apr-03 RMS Revised for extended file support
|
||||||
|
@ -73,14 +74,10 @@
|
||||||
|
|
||||||
#elif defined (VM_VAX) /* VAX version */
|
#elif defined (VM_VAX) /* VAX version */
|
||||||
#include "vax_defs.h"
|
#include "vax_defs.h"
|
||||||
extern int32 int_req[IPL_HLVL];
|
|
||||||
extern int32 int_vec[IPL_HLVL][32];
|
|
||||||
|
|
||||||
#else /* PDP-11 version */
|
#else /* PDP-11 version */
|
||||||
#include "pdp11_defs.h"
|
#include "pdp11_defs.h"
|
||||||
extern int32 int_req[IPL_HLVL];
|
extern int32 cpu_opt;
|
||||||
extern int32 int_vec[IPL_HLVL][32];
|
|
||||||
extern int32 cpu_18b, cpu_ubm;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Constants */
|
/* Constants */
|
||||||
|
@ -191,7 +188,6 @@ extern int32 cpu_18b, cpu_ubm;
|
||||||
|
|
||||||
#define RLBAE_IMP 0000077 /* implemented */
|
#define RLBAE_IMP 0000077 /* implemented */
|
||||||
|
|
||||||
extern uint16 *M;
|
|
||||||
extern int32 int_req[IPL_HLVL];
|
extern int32 int_req[IPL_HLVL];
|
||||||
extern int32 int_vec[IPL_HLVL][32];
|
extern int32 int_vec[IPL_HLVL][32];
|
||||||
|
|
||||||
|
@ -462,13 +458,13 @@ if ((func >= RLCS_READ) && (err == 0)) { /* read (no hdr)? */
|
||||||
i = fxread (rlxb, sizeof (int16), wc, uptr->fileref);
|
i = fxread (rlxb, sizeof (int16), wc, uptr->fileref);
|
||||||
err = ferror (uptr->fileref);
|
err = ferror (uptr->fileref);
|
||||||
for ( ; i < wc; i++) rlxb[i] = 0; /* fill buffer */
|
for ( ; i < wc; i++) rlxb[i] = 0; /* fill buffer */
|
||||||
if (t = Map_WriteW (ma, wc << 1, rlxb, MAP)) { /* store buffer */
|
if (t = Map_WriteW (ma, wc << 1, rlxb)) { /* store buffer */
|
||||||
rlcs = rlcs | RLCS_ERR | RLCS_NXM; /* nxm */
|
rlcs = rlcs | RLCS_ERR | RLCS_NXM; /* nxm */
|
||||||
wc = wc - t; } /* adjust wc */
|
wc = wc - t; } /* adjust wc */
|
||||||
} /* end read */
|
} /* end read */
|
||||||
|
|
||||||
if ((func == RLCS_WRITE) && (err == 0)) { /* write? */
|
if ((func == RLCS_WRITE) && (err == 0)) { /* write? */
|
||||||
if (t = Map_ReadW (ma, wc << 1, rlxb, MAP)) { /* fetch buffer */
|
if (t = Map_ReadW (ma, wc << 1, rlxb)) { /* fetch buffer */
|
||||||
rlcs = rlcs | RLCS_ERR | RLCS_NXM; /* nxm */
|
rlcs = rlcs | RLCS_ERR | RLCS_NXM; /* nxm */
|
||||||
wc = wc - t; } /* adj xfer lnt */
|
wc = wc - t; } /* adj xfer lnt */
|
||||||
if (wc) { /* any xfer? */
|
if (wc) { /* any xfer? */
|
||||||
|
@ -484,7 +480,7 @@ if ((func == RLCS_WCHK) && (err == 0)) { /* write check? */
|
||||||
for ( ; i < wc; i++) rlxb[i] = 0; /* fill buffer */
|
for ( ; i < wc; i++) rlxb[i] = 0; /* fill buffer */
|
||||||
awc = wc; /* save wc */
|
awc = wc; /* save wc */
|
||||||
for (wc = 0; (err == 0) && (wc < awc); wc++) { /* loop thru buf */
|
for (wc = 0; (err == 0) && (wc < awc); wc++) { /* loop thru buf */
|
||||||
if (Map_ReadW (ma + (wc << 1), 2, &comp, MAP)) { /* mem wd */
|
if (Map_ReadW (ma + (wc << 1), 2, &comp)) { /* mem wd */
|
||||||
rlcs = rlcs | RLCS_ERR | RLCS_NXM; /* nxm */
|
rlcs = rlcs | RLCS_ERR | RLCS_NXM; /* nxm */
|
||||||
break; }
|
break; }
|
||||||
if (comp != rlxb[wc]) /* check to buf */
|
if (comp != rlxb[wc]) /* check to buf */
|
||||||
|
@ -535,7 +531,7 @@ for (i = 0; i < RL_NUMDR; i++) {
|
||||||
uptr = rl_dev.units + i;
|
uptr = rl_dev.units + i;
|
||||||
sim_cancel (uptr);
|
sim_cancel (uptr);
|
||||||
uptr->STAT = 0; }
|
uptr->STAT = 0; }
|
||||||
if (rlxb == NULL) rlxb = calloc (RL_MAXFR, sizeof (unsigned int16));
|
if (rlxb == NULL) rlxb = calloc (RL_MAXFR, sizeof (uint16));
|
||||||
if (rlxb == NULL) return SCPE_MEM;
|
if (rlxb == NULL) return SCPE_MEM;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -635,6 +631,7 @@ static const uint16 boot_rom[] = {
|
||||||
t_stat rl_boot (int32 unitno, DEVICE *dptr)
|
t_stat rl_boot (int32 unitno, DEVICE *dptr)
|
||||||
{
|
{
|
||||||
int32 i;
|
int32 i;
|
||||||
|
extern uint16 *M;
|
||||||
extern int32 saved_PC;
|
extern int32 saved_PC;
|
||||||
|
|
||||||
for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i];
|
for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i];
|
||||||
|
@ -650,4 +647,6 @@ t_stat rl_boot (int32 unitno, DEVICE *dptr)
|
||||||
{
|
{
|
||||||
return SCPE_NOFNC;
|
return SCPE_NOFNC;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
1014
PDP11/pdp11_rp.c
1014
PDP11/pdp11_rp.c
File diff suppressed because it is too large
Load diff
107
PDP11/pdp11_rq.c
107
PDP11/pdp11_rq.c
|
@ -26,6 +26,11 @@
|
||||||
|
|
||||||
rq RQDX3 disk controller
|
rq RQDX3 disk controller
|
||||||
|
|
||||||
|
31-Oct-04 RMS Added -L switch (LBNs) to RAUSER size specification
|
||||||
|
01-Oct-04 RMS Revised Unibus interface
|
||||||
|
Changed to identify as UDA50 in Unibus configurations
|
||||||
|
Changed width to be 16b in all configurations
|
||||||
|
Changed default timing for VAX
|
||||||
24-Jul-04 RMS VAX controllers luns start with 0 (from Andreas Cejna)
|
24-Jul-04 RMS VAX controllers luns start with 0 (from Andreas Cejna)
|
||||||
05-Feb-04 RMS Revised for file I/O library
|
05-Feb-04 RMS Revised for file I/O library
|
||||||
25-Jan-04 RMS Revised for device debug support
|
25-Jan-04 RMS Revised for device debug support
|
||||||
|
@ -64,18 +69,18 @@
|
||||||
|
|
||||||
#elif defined (VM_VAX) /* VAX version */
|
#elif defined (VM_VAX) /* VAX version */
|
||||||
#include "vax_defs.h"
|
#include "vax_defs.h"
|
||||||
#define RQ_AINC 4
|
#define RQ_QTIME 100
|
||||||
#define RQ_WID 32
|
#define RQ_XTIME 200
|
||||||
extern int32 int_req[IPL_HLVL];
|
#define OLDPC fault_PC
|
||||||
extern int32 int_vec[IPL_HLVL][32];
|
extern int32 fault_PC;
|
||||||
|
|
||||||
#else /* PDP-11 version */
|
#else /* PDP-11 version */
|
||||||
#include "pdp11_defs.h"
|
#include "pdp11_defs.h"
|
||||||
#define RQ_AINC 2
|
#define RQ_QTIME 200
|
||||||
#define RQ_WID 16
|
#define RQ_XTIME 500
|
||||||
extern int32 cpu_18b, cpu_ubm;
|
#define OLDPC MMR2
|
||||||
extern int32 int_req[IPL_HLVL];
|
extern int32 MMR2;
|
||||||
extern int32 int_vec[IPL_HLVL][32];
|
extern int32 cpu_opt;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined (RQ_NUMCT)
|
#if !defined (RQ_NUMCT)
|
||||||
|
@ -98,8 +103,12 @@ extern int32 int_vec[IPL_HLVL][32];
|
||||||
#define RQ_SH_UN 010 /* show unit q's */
|
#define RQ_SH_UN 010 /* show unit q's */
|
||||||
|
|
||||||
#define RQ_CLASS 1 /* RQ class */
|
#define RQ_CLASS 1 /* RQ class */
|
||||||
#define RQ_UQPM 19 /* UQ port model */
|
#define RQU_UQPM 6 /* UB port model */
|
||||||
#define RQ_MODEL 19 /* MSCP ctrl model */
|
#define RQQ_UQPM 19 /* QB port model */
|
||||||
|
#define RQ_UQPM (UNIBUS? RQU_UQPM: RQQ_UQPM)
|
||||||
|
#define RQU_MODEL 6 /* UB MSCP ctrl model */
|
||||||
|
#define RQQ_MODEL 19 /* QB MSCP ctrl model */
|
||||||
|
#define RQ_MODEL (UNIBUS? RQU_MODEL: RQQ_MODEL)
|
||||||
#define RQ_HVER 1 /* hardware version */
|
#define RQ_HVER 1 /* hardware version */
|
||||||
#define RQ_SVER 3 /* software version */
|
#define RQ_SVER 3 /* software version */
|
||||||
#define RQ_DHTMO 60 /* def host timeout */
|
#define RQ_DHTMO 60 /* def host timeout */
|
||||||
|
@ -169,7 +178,7 @@ struct rqpkt {
|
||||||
#define PUTP32(p,w,x) cp->pak[p].d[w] = (x) & 0xFFFF; \
|
#define PUTP32(p,w,x) cp->pak[p].d[w] = (x) & 0xFFFF; \
|
||||||
cp->pak[p].d[(w)+1] = ((x) >> 16) & 0xFFFF
|
cp->pak[p].d[(w)+1] = ((x) >> 16) & 0xFFFF
|
||||||
|
|
||||||
/* Disk formats. An RQDX3 consists of the following regions:
|
/* Disk formats. An RQDX3 disk consists of the following regions:
|
||||||
|
|
||||||
XBNs Extended blocks - contain information about disk format,
|
XBNs Extended blocks - contain information about disk format,
|
||||||
also holds track being reformatted during bad block repl.
|
also holds track being reformatted during bad block repl.
|
||||||
|
@ -417,23 +426,23 @@ struct rqpkt {
|
||||||
#define RA92_FLGS RQDF_SDI
|
#define RA92_FLGS RQDF_SDI
|
||||||
|
|
||||||
#define RA8U_DTYPE 12 /* user defined */
|
#define RA8U_DTYPE 12 /* user defined */
|
||||||
#define RA8U_SECT 57 /* +1 spare/track */
|
#define RA8U_SECT 57 /* from RA82 */
|
||||||
#define RA8U_SURF 15
|
#define RA8U_SURF 15
|
||||||
#define RA8U_CYL 1435 /* 0-1422 user */
|
#define RA8U_CYL 1435 /* from RA82 */
|
||||||
#define RA8U_TPG RA8U_SURF
|
#define RA8U_TPG RA8U_SURF
|
||||||
#define RA8U_GPC 1
|
#define RA8U_GPC 1
|
||||||
#define RA8U_XBN 3420 /* cyl 1427-1430 */
|
#define RA8U_XBN 0
|
||||||
#define RA8U_DBN 3420 /* cyl 1431-1434 */
|
#define RA8U_DBN 0
|
||||||
#define RA8U_LBN 1216665 /* 57*15*1423 */
|
#define RA8U_LBN 1216665 /* from RA82 */
|
||||||
#define RA8U_RCTS 400 /* cyl 1423-1426 */
|
#define RA8U_RCTS 400
|
||||||
#define RA8U_RCTC 8
|
#define RA8U_RCTC 8
|
||||||
#define RA8U_RBN 21345 /* 1 *15*1423 */
|
#define RA8U_RBN 21345
|
||||||
#define RA8U_MOD 11 /* RA82 */
|
#define RA8U_MOD 11 /* RA82 */
|
||||||
#define RA8U_MED 0x25641052 /* RA82 */
|
#define RA8U_MED 0x25641052 /* RA82 */
|
||||||
#define RA8U_FLGS RQDF_SDI
|
#define RA8U_FLGS RQDF_SDI
|
||||||
#define RA8U_MINC 5 /* min cap MB */
|
#define RA8U_MINC 10000 /* min cap LBNs */
|
||||||
#define RA8U_MAXC 2000 /* max cap MB */
|
#define RA8U_MAXC 4000000 /* max cap LBNs */
|
||||||
#define RA8U_EMAXC 1000000 /* ext max cap */
|
#define RA8U_EMAXC 2000000000 /* ext max cap */
|
||||||
|
|
||||||
struct drvtyp {
|
struct drvtyp {
|
||||||
int32 sect; /* sectors */
|
int32 sect; /* sectors */
|
||||||
|
@ -474,12 +483,13 @@ extern int32 tmr_poll, clk_tps;
|
||||||
extern UNIT cpu_unit;
|
extern UNIT cpu_unit;
|
||||||
extern FILE *sim_deb;
|
extern FILE *sim_deb;
|
||||||
extern uint32 sim_taddr_64;
|
extern uint32 sim_taddr_64;
|
||||||
|
extern int32 sim_switches;
|
||||||
|
|
||||||
uint16 *rqxb = NULL; /* xfer buffer */
|
uint16 *rqxb = NULL; /* xfer buffer */
|
||||||
int32 rq_itime = 200; /* init time, except */
|
int32 rq_itime = 200; /* init time, except */
|
||||||
int32 rq_itime4 = 10; /* stage 4 */
|
int32 rq_itime4 = 10; /* stage 4 */
|
||||||
int32 rq_qtime = 200; /* queue time */
|
int32 rq_qtime = RQ_QTIME; /* queue time */
|
||||||
int32 rq_xtime = 500; /* transfer time */
|
int32 rq_xtime = RQ_XTIME; /* transfer time */
|
||||||
|
|
||||||
struct mscp_con {
|
struct mscp_con {
|
||||||
uint32 cnum; /* ctrl number */
|
uint32 cnum; /* ctrl number */
|
||||||
|
@ -687,7 +697,7 @@ MTAB rq_mod[] = {
|
||||||
|
|
||||||
DEVICE rq_dev = {
|
DEVICE rq_dev = {
|
||||||
"RQ", rq_unit, rq_reg, rq_mod,
|
"RQ", rq_unit, rq_reg, rq_mod,
|
||||||
RQ_NUMDR + 2, DEV_RDX, 31, RQ_AINC, DEV_RDX, RQ_WID,
|
RQ_NUMDR + 2, DEV_RDX, 31, 2, DEV_RDX, 16,
|
||||||
NULL, NULL, &rq_reset,
|
NULL, NULL, &rq_reset,
|
||||||
&rq_boot, &rq_attach, &rq_detach,
|
&rq_boot, &rq_attach, &rq_detach,
|
||||||
&rq_dib, DEV_FLTA | DEV_DISABLE | DEV_UBUS | DEV_QBUS | DEV_DEBUG };
|
&rq_dib, DEV_FLTA | DEV_DISABLE | DEV_UBUS | DEV_QBUS | DEV_DEBUG };
|
||||||
|
@ -751,7 +761,7 @@ REG rqb_reg[] = {
|
||||||
|
|
||||||
DEVICE rqb_dev = {
|
DEVICE rqb_dev = {
|
||||||
"RQB", rqb_unit, rqb_reg, rq_mod,
|
"RQB", rqb_unit, rqb_reg, rq_mod,
|
||||||
RQ_NUMDR + 2, DEV_RDX, 31, RQ_AINC, DEV_RDX, RQ_WID,
|
RQ_NUMDR + 2, DEV_RDX, 31, 2, DEV_RDX, 16,
|
||||||
NULL, NULL, &rq_reset,
|
NULL, NULL, &rq_reset,
|
||||||
&rq_boot, &rq_attach, &rq_detach,
|
&rq_boot, &rq_attach, &rq_detach,
|
||||||
&rqb_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS | DEV_DEBUG };
|
&rqb_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS | DEV_DEBUG };
|
||||||
|
@ -815,7 +825,7 @@ REG rqc_reg[] = {
|
||||||
|
|
||||||
DEVICE rqc_dev = {
|
DEVICE rqc_dev = {
|
||||||
"RQC", rqc_unit, rqc_reg, rq_mod,
|
"RQC", rqc_unit, rqc_reg, rq_mod,
|
||||||
RQ_NUMDR + 2, DEV_RDX, 31, RQ_AINC, DEV_RDX, RQ_WID,
|
RQ_NUMDR + 2, DEV_RDX, 31, 2, DEV_RDX, 16,
|
||||||
NULL, NULL, &rq_reset,
|
NULL, NULL, &rq_reset,
|
||||||
&rq_boot, &rq_attach, &rq_detach,
|
&rq_boot, &rq_attach, &rq_detach,
|
||||||
&rqc_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS | DEV_DEBUG };
|
&rqc_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS | DEV_DEBUG };
|
||||||
|
@ -879,7 +889,7 @@ REG rqd_reg[] = {
|
||||||
|
|
||||||
DEVICE rqd_dev = {
|
DEVICE rqd_dev = {
|
||||||
"RQD", rqd_unit, rqd_reg, rq_mod,
|
"RQD", rqd_unit, rqd_reg, rq_mod,
|
||||||
RQ_NUMDR + 2, DEV_RDX, 31, RQ_AINC, DEV_RDX, RQ_WID,
|
RQ_NUMDR + 2, DEV_RDX, 31, 2, DEV_RDX, 16,
|
||||||
NULL, NULL, &rq_reset,
|
NULL, NULL, &rq_reset,
|
||||||
&rq_boot, &rq_attach, &rq_detach,
|
&rq_boot, &rq_attach, &rq_detach,
|
||||||
&rqd_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS | DEV_DEBUG };
|
&rqd_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS | DEV_DEBUG };
|
||||||
|
@ -908,6 +918,8 @@ case 0: /* IP */
|
||||||
*data = 0; /* reads zero */
|
*data = 0; /* reads zero */
|
||||||
if (cp->csta == CST_S3_PPB) rq_step4 (cp); /* waiting for poll? */
|
if (cp->csta == CST_S3_PPB) rq_step4 (cp); /* waiting for poll? */
|
||||||
else if (cp->csta == CST_UP) { /* if up */
|
else if (cp->csta == CST_UP) { /* if up */
|
||||||
|
if (DEBUG_PRD (dptr)) fprintf (sim_deb,
|
||||||
|
">>RQ%c: poll started, PC=%X\n", 'A' + cp->cnum, OLDPC);
|
||||||
cp->pip = 1; /* poll host */
|
cp->pip = 1; /* poll host */
|
||||||
sim_activate (dptr->units + RQ_QUEUE, rq_qtime); }
|
sim_activate (dptr->units + RQ_QUEUE, rq_qtime); }
|
||||||
break;
|
break;
|
||||||
|
@ -977,7 +989,7 @@ else base = cp->comm + SA_COMM_CI;
|
||||||
lnt = cp->comm + cp->cq.lnt + cp->rq.lnt - base; /* comm lnt */
|
lnt = cp->comm + cp->cq.lnt + cp->rq.lnt - base; /* comm lnt */
|
||||||
if (lnt > SA_COMM_MAX) lnt = SA_COMM_MAX; /* paranoia */
|
if (lnt > SA_COMM_MAX) lnt = SA_COMM_MAX; /* paranoia */
|
||||||
for (i = 0; i < (lnt >> 1); i++) zero[i] = 0; /* clr buffer */
|
for (i = 0; i < (lnt >> 1); i++) zero[i] = 0; /* clr buffer */
|
||||||
if (Map_WriteW (base, lnt, zero, MAP)) /* zero comm area */
|
if (Map_WriteW (base, lnt, zero)) /* zero comm area */
|
||||||
return rq_fatal (cp, PE_QWE); /* error? */
|
return rq_fatal (cp, PE_QWE); /* error? */
|
||||||
cp->sa = SA_S4 | (RQ_UQPM << SA_S4C_V_MOD) | /* send step 4 */
|
cp->sa = SA_S4 | (RQ_UQPM << SA_S4C_V_MOD) | /* send step 4 */
|
||||||
(RQ_SVER << SA_S4C_V_VER);
|
(RQ_SVER << SA_S4C_V_VER);
|
||||||
|
@ -1427,8 +1439,7 @@ int32 rq_rw_valid (MSC *cp, int32 pkt, UNIT *uptr, uint32 cmd)
|
||||||
uint32 dtyp = GET_DTYPE (uptr->flags); /* get drive type */
|
uint32 dtyp = GET_DTYPE (uptr->flags); /* get drive type */
|
||||||
uint32 lbn = GETP32 (pkt, RW_LBNL); /* get lbn */
|
uint32 lbn = GETP32 (pkt, RW_LBNL); /* get lbn */
|
||||||
uint32 bc = GETP32 (pkt, RW_BCL); /* get byte cnt */
|
uint32 bc = GETP32 (pkt, RW_BCL); /* get byte cnt */
|
||||||
uint32 maxlbn = uptr->capac / RQ_NUMBY; /* get max lbn */
|
uint32 maxlbn = (uint32) (uptr->capac / RQ_NUMBY); /* get max lbn */
|
||||||
/* uint32 maxlbn = drv_tab[dtyp].lbn; /* get max lbn */
|
|
||||||
|
|
||||||
if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */
|
if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */
|
||||||
return (ST_OFL | SB_OFL_NV); /* offl no vol */
|
return (ST_OFL | SB_OFL_NV); /* offl no vol */
|
||||||
|
@ -1497,7 +1508,7 @@ if (cmd == OP_ERS) { /* erase? */
|
||||||
err = ferror (uptr->fileref); } /* end if erase */
|
err = ferror (uptr->fileref); } /* end if erase */
|
||||||
|
|
||||||
else if (cmd == OP_WR) { /* write? */
|
else if (cmd == OP_WR) { /* write? */
|
||||||
t = Map_ReadW (ba, tbc, rqxb, MAP); /* fetch buffer */
|
t = Map_ReadW (ba, tbc, rqxb); /* fetch buffer */
|
||||||
if (abc = tbc - t) { /* any xfer? */
|
if (abc = tbc - t) { /* any xfer? */
|
||||||
wwc = ((abc + (RQ_NUMBY - 1)) & ~(RQ_NUMBY - 1)) >> 1;
|
wwc = ((abc + (RQ_NUMBY - 1)) & ~(RQ_NUMBY - 1)) >> 1;
|
||||||
for (i = (abc >> 1); i < wwc; i++) rqxb[i] = 0;
|
for (i = (abc >> 1); i < wwc; i++) rqxb[i] = 0;
|
||||||
|
@ -1517,7 +1528,7 @@ else { err = sim_fseek (uptr->fileref, da, SEEK_SET); /* set pos */
|
||||||
for ( ; i < (tbc >> 1); i++) rqxb[i] = 0; /* fill */
|
for ( ; i < (tbc >> 1); i++) rqxb[i] = 0; /* fill */
|
||||||
err = ferror (uptr->fileref); }
|
err = ferror (uptr->fileref); }
|
||||||
if ((cmd == OP_RD) && !err) { /* read? */
|
if ((cmd == OP_RD) && !err) { /* read? */
|
||||||
if (t = Map_WriteW (ba, tbc, rqxb, MAP)) { /* store, nxm? */
|
if (t = Map_WriteW (ba, tbc, rqxb)) { /* store, nxm? */
|
||||||
PUTP32 (pkt, RW_WBCL, bc - (tbc - t)); /* adj bc */
|
PUTP32 (pkt, RW_WBCL, bc - (tbc - t)); /* adj bc */
|
||||||
PUTP32 (pkt, RW_WBAL, ba + (tbc - t)); /* adj ba */
|
PUTP32 (pkt, RW_WBAL, ba + (tbc - t)); /* adj ba */
|
||||||
if (rq_hbe (cp, uptr)) /* post err log */
|
if (rq_hbe (cp, uptr)) /* post err log */
|
||||||
|
@ -1527,7 +1538,7 @@ else { err = sim_fseek (uptr->fileref, da, SEEK_SET); /* set pos */
|
||||||
else if ((cmd == OP_CMP) && !err) { /* compare? */
|
else if ((cmd == OP_CMP) && !err) { /* compare? */
|
||||||
uint8 dby, mby;
|
uint8 dby, mby;
|
||||||
for (i = 0; i < tbc; i++) { /* loop */
|
for (i = 0; i < tbc; i++) { /* loop */
|
||||||
if (Map_ReadB (ba + i, 1, &mby, MAP)) { /* fetch, nxm? */
|
if (Map_ReadB (ba + i, 1, &mby)) { /* fetch, nxm? */
|
||||||
PUTP32 (pkt, RW_WBCL, bc - i); /* adj bc */
|
PUTP32 (pkt, RW_WBCL, bc - i); /* adj bc */
|
||||||
PUTP32 (pkt, RW_WBAL, bc - i); /* adj ba */
|
PUTP32 (pkt, RW_WBAL, bc - i); /* adj ba */
|
||||||
if (rq_hbe (cp, uptr)) /* post err log */
|
if (rq_hbe (cp, uptr)) /* post err log */
|
||||||
|
@ -1762,7 +1773,7 @@ if ((desc & UQ_DESC_OWN) == 0) { /* none */
|
||||||
if (!rq_deqf (cp, pkt)) return ERR; /* get cmd pkt */
|
if (!rq_deqf (cp, pkt)) return ERR; /* get cmd pkt */
|
||||||
cp->hat = 0; /* dsbl hst timer */
|
cp->hat = 0; /* dsbl hst timer */
|
||||||
addr = desc & UQ_ADDR; /* get Q22 addr */
|
addr = desc & UQ_ADDR; /* get Q22 addr */
|
||||||
if (Map_ReadW (addr + UQ_HDR_OFF, RQ_PKT_SIZE, cp->pak[*pkt].d, MAP))
|
if (Map_ReadW (addr + UQ_HDR_OFF, RQ_PKT_SIZE, cp->pak[*pkt].d))
|
||||||
return rq_fatal (cp, PE_PRE); /* read pkt */
|
return rq_fatal (cp, PE_PRE); /* read pkt */
|
||||||
return rq_putdesc (cp, &cp->cq, desc); /* release desc */
|
return rq_putdesc (cp, &cp->cq, desc); /* release desc */
|
||||||
}
|
}
|
||||||
|
@ -1794,7 +1805,7 @@ if ((GETP (pkt, UQ_HCTC, TYP) == UQ_TYP_SEQ) && /* seq packet? */
|
||||||
cr = (cp->credits >= 14)? 14: cp->credits; /* max 14 credits */
|
cr = (cp->credits >= 14)? 14: cp->credits; /* max 14 credits */
|
||||||
cp->credits = cp->credits - cr; /* decr credits */
|
cp->credits = cp->credits - cr; /* decr credits */
|
||||||
cp->pak[pkt].d[UQ_HCTC] |= ((cr + 1) << UQ_HCTC_V_CR); }
|
cp->pak[pkt].d[UQ_HCTC] |= ((cr + 1) << UQ_HCTC_V_CR); }
|
||||||
if (Map_WriteW (addr + UQ_HDR_OFF, lnt, cp->pak[pkt].d, MAP))
|
if (Map_WriteW (addr + UQ_HDR_OFF, lnt, cp->pak[pkt].d))
|
||||||
return rq_fatal (cp, PE_PWE); /* write pkt */
|
return rq_fatal (cp, PE_PWE); /* write pkt */
|
||||||
rq_enqh (cp, &cp->freq, pkt); /* pkt is free */
|
rq_enqh (cp, &cp->freq, pkt); /* pkt is free */
|
||||||
cp->pbsy = cp->pbsy - 1; /* decr busy cnt */
|
cp->pbsy = cp->pbsy - 1; /* decr busy cnt */
|
||||||
|
@ -1809,7 +1820,7 @@ t_bool rq_getdesc (MSC *cp, struct uq_ring *ring, uint32 *desc)
|
||||||
uint32 addr = ring->ba + ring->idx;
|
uint32 addr = ring->ba + ring->idx;
|
||||||
uint16 d[2];
|
uint16 d[2];
|
||||||
|
|
||||||
if (Map_ReadW (addr, 4, d, MAP)) /* fetch desc */
|
if (Map_ReadW (addr, 4, d)) /* fetch desc */
|
||||||
return rq_fatal (cp, PE_QRE); /* err? dead */
|
return rq_fatal (cp, PE_QRE); /* err? dead */
|
||||||
*desc = ((uint32) d[0]) | (((uint32) d[1]) << 16);
|
*desc = ((uint32) d[0]) | (((uint32) d[1]) << 16);
|
||||||
return OK;
|
return OK;
|
||||||
|
@ -1829,13 +1840,13 @@ uint16 d[2];
|
||||||
|
|
||||||
d[0] = newd & 0xFFFF; /* 32b to 16b */
|
d[0] = newd & 0xFFFF; /* 32b to 16b */
|
||||||
d[1] = (newd >> 16) & 0xFFFF;
|
d[1] = (newd >> 16) & 0xFFFF;
|
||||||
if (Map_WriteW (addr, 4, d, MAP)) /* store desc */
|
if (Map_WriteW (addr, 4, d)) /* store desc */
|
||||||
return rq_fatal (cp, PE_QWE); /* err? dead */
|
return rq_fatal (cp, PE_QWE); /* err? dead */
|
||||||
if (desc & UQ_DESC_F) { /* was F set? */
|
if (desc & UQ_DESC_F) { /* was F set? */
|
||||||
if (ring->lnt <= 4) rq_ring_int (cp, ring); /* lnt = 1? intr */
|
if (ring->lnt <= 4) rq_ring_int (cp, ring); /* lnt = 1? intr */
|
||||||
else { /* prv desc */
|
else { /* prv desc */
|
||||||
prva = ring->ba + ((ring->idx - 4) & (ring->lnt - 1));
|
prva = ring->ba + ((ring->idx - 4) & (ring->lnt - 1));
|
||||||
if (Map_ReadW (prva, 4, d, MAP)) /* read prv */
|
if (Map_ReadW (prva, 4, d)) /* read prv */
|
||||||
return rq_fatal (cp, PE_QRE);
|
return rq_fatal (cp, PE_QRE);
|
||||||
prvd = ((uint32) d[0]) | (((uint32) d[1]) << 16);
|
prvd = ((uint32) d[0]) | (((uint32) d[1]) << 16);
|
||||||
if (prvd & UQ_DESC_OWN) rq_ring_int (cp, ring); } }
|
if (prvd & UQ_DESC_OWN) rq_ring_int (cp, ring); } }
|
||||||
|
@ -1873,7 +1884,7 @@ return;
|
||||||
void rq_putr_unit (MSC *cp, int32 pkt, UNIT *uptr, uint32 lu, t_bool all)
|
void rq_putr_unit (MSC *cp, int32 pkt, UNIT *uptr, uint32 lu, t_bool all)
|
||||||
{
|
{
|
||||||
uint32 dtyp = GET_DTYPE (uptr->flags); /* get drive type */
|
uint32 dtyp = GET_DTYPE (uptr->flags); /* get drive type */
|
||||||
uint32 maxlbn = uptr->capac / RQ_NUMBY; /* get max lbn */
|
uint32 maxlbn = (uint32) (uptr->capac / RQ_NUMBY); /* get max lbn */
|
||||||
|
|
||||||
cp->pak[pkt].d[ONL_MLUN] = lu; /* unit */
|
cp->pak[pkt].d[ONL_MLUN] = lu; /* unit */
|
||||||
cp->pak[pkt].d[ONL_UFL] = uptr->uf | UF_RPL | RQ_WPH (uptr) | RQ_RMV (uptr);
|
cp->pak[pkt].d[ONL_UFL] = uptr->uf | UF_RPL | RQ_WPH (uptr) | RQ_RMV (uptr);
|
||||||
|
@ -1922,7 +1933,7 @@ void rq_ring_int (MSC *cp, struct uq_ring *ring)
|
||||||
uint32 iadr = cp->comm + ring->ioff; /* addr intr wd */
|
uint32 iadr = cp->comm + ring->ioff; /* addr intr wd */
|
||||||
uint16 flag = 1;
|
uint16 flag = 1;
|
||||||
|
|
||||||
Map_WriteW (iadr, 2, &flag, MAP); /* write flag */
|
Map_WriteW (iadr, 2, &flag); /* write flag */
|
||||||
if (cp->s1dat & SA_S1H_VEC) rq_setint (cp); /* if enb, intr */
|
if (cp->s1dat & SA_S1H_VEC) rq_setint (cp); /* if enb, intr */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2021,9 +2032,10 @@ if ((val < 0) || (val > RA8U_DTYPE) || ((val != RA8U_DTYPE) && cptr))
|
||||||
return SCPE_ARG;
|
return SCPE_ARG;
|
||||||
if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
|
if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
|
||||||
if (cptr) {
|
if (cptr) {
|
||||||
cap = (int32) get_uint (cptr, 10, max, &r);
|
cap = (uint32) get_uint (cptr, 10, 0xFFFFFFFF, &r);
|
||||||
if ((r != SCPE_OK) || (cap < RA8U_MINC)) return SCPE_ARG;
|
if ((sim_switches & SWMASK ('L')) == 0) cap = cap * 1954;
|
||||||
drv_tab[val].lbn = cap * 1954; }
|
if ((r != SCPE_OK) || (cap < RA8U_MINC) || (cap >= max)) return SCPE_ARG;
|
||||||
|
drv_tab[val].lbn = cap; }
|
||||||
uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (val << UNIT_V_DTYPE);
|
uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (val << UNIT_V_DTYPE);
|
||||||
uptr->capac = ((t_addr) drv_tab[val].lbn) * RQ_NUMBY;
|
uptr->capac = ((t_addr) drv_tab[val].lbn) * RQ_NUMBY;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -2089,7 +2101,8 @@ cp->csta = CST_S1; /* init stage 1 */
|
||||||
cp->s1dat = 0; /* no S1 data */
|
cp->s1dat = 0; /* no S1 data */
|
||||||
dibp->vec = 0; /* no vector */
|
dibp->vec = 0; /* no vector */
|
||||||
cp->comm = 0; /* no comm region */
|
cp->comm = 0; /* no comm region */
|
||||||
cp->sa = SA_S1 | SA_S1C_Q22 | SA_S1C_DI | SA_S1C_MP; /* init SA val */
|
if (UNIBUS) cp->sa = SA_S1 | SA_S1C_DI | SA_S1C_MP; /* Unibus? */
|
||||||
|
else cp->sa = SA_S1 | SA_S1C_Q22 | SA_S1C_DI | SA_S1C_MP; /* init SA val */
|
||||||
cp->cflgs = CF_RPL; /* ctrl flgs off */
|
cp->cflgs = CF_RPL; /* ctrl flgs off */
|
||||||
cp->htmo = RQ_DHTMO; /* default timeout */
|
cp->htmo = RQ_DHTMO; /* default timeout */
|
||||||
cp->hat = cp->htmo; /* default timer */
|
cp->hat = cp->htmo; /* default timer */
|
||||||
|
@ -2112,7 +2125,7 @@ for (i = 0; i < (RQ_NUMDR + 2); i++) { /* init units */
|
||||||
uptr->flags = uptr->flags & ~(UNIT_ONL | UNIT_ATP);
|
uptr->flags = uptr->flags & ~(UNIT_ONL | UNIT_ATP);
|
||||||
uptr->uf = 0; /* clr unit flags */
|
uptr->uf = 0; /* clr unit flags */
|
||||||
uptr->cpkt = uptr->pktq = 0; } /* clr pkt q's */
|
uptr->cpkt = uptr->pktq = 0; } /* clr pkt q's */
|
||||||
if (rqxb == NULL) rqxb = calloc (RQ_MAXFR >> 1, sizeof (unsigned int16));
|
if (rqxb == NULL) rqxb = calloc (RQ_MAXFR >> 1, sizeof (uint16));
|
||||||
if (rqxb == NULL) return SCPE_MEM;
|
if (rqxb == NULL) return SCPE_MEM;
|
||||||
return auto_config (0, 0); /* run autoconfig */
|
return auto_config (0, 0); /* run autoconfig */
|
||||||
}
|
}
|
||||||
|
@ -2230,7 +2243,7 @@ fprintf (st, "ring, base = %x, index = %d, length = %d\n",
|
||||||
rp->ba, rp->idx >> 2, rp->lnt >> 2);
|
rp->ba, rp->idx >> 2, rp->lnt >> 2);
|
||||||
#endif
|
#endif
|
||||||
for (i = 0; i < (rp->lnt >> 2); i++) {
|
for (i = 0; i < (rp->lnt >> 2); i++) {
|
||||||
if (Map_ReadW (rp->ba + (i << 2), 4, d, MAP)) {
|
if (Map_ReadW (rp->ba + (i << 2), 4, d)) {
|
||||||
fprintf (st, " %3d: non-existent memory\n", i);
|
fprintf (st, " %3d: non-existent memory\n", i);
|
||||||
break; }
|
break; }
|
||||||
desc = ((uint32) d[0]) | (((uint32) d[1]) << 16);
|
desc = ((uint32) d[0]) | (((uint32) d[1]) << 16);
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
ry RX211/RXV21/RX02 floppy disk
|
ry RX211/RXV21/RX02 floppy disk
|
||||||
|
|
||||||
|
30-Sep-04 RMS Revised Unibus interface
|
||||||
21-Mar-04 RMS Added VAX support
|
21-Mar-04 RMS Added VAX support
|
||||||
29-Dec-03 RMS Added RXV21 support
|
29-Dec-03 RMS Added RXV21 support
|
||||||
19-May-03 RMS Revised for new conditional compilation scheme
|
19-May-03 RMS Revised for new conditional compilation scheme
|
||||||
|
@ -372,8 +373,8 @@ case FEXFR: /* transfer */
|
||||||
break; }
|
break; }
|
||||||
if (func == RYCS_FILL) { /* fill? read */
|
if (func == RYCS_FILL) { /* fill? read */
|
||||||
for (i = 0; i < RY_NUMBY; i++) rx2xb[i] = 0;
|
for (i = 0; i < RY_NUMBY; i++) rx2xb[i] = 0;
|
||||||
t = Map_ReadB (ba, ry_wc << 1, rx2xb, MAP); }
|
t = Map_ReadB (ba, ry_wc << 1, rx2xb); }
|
||||||
else t = Map_WriteB (ba, ry_wc << 1, rx2xb, MAP);
|
else t = Map_WriteB (ba, ry_wc << 1, rx2xb);
|
||||||
ry_wc = t >> 1; /* adjust wc */
|
ry_wc = t >> 1; /* adjust wc */
|
||||||
ry_done (t? RYES_NXM: 0, 0); /* done */
|
ry_done (t? RYES_NXM: 0, 0); /* done */
|
||||||
break;
|
break;
|
||||||
|
@ -428,7 +429,7 @@ case SDCNF: /* confirm set density */
|
||||||
break;
|
break;
|
||||||
case SDXFR: /* erase disk */
|
case SDXFR: /* erase disk */
|
||||||
for (i = 0; i < (int32) uptr->capac; i++) fbuf[i] = 0;
|
for (i = 0; i < (int32) uptr->capac; i++) fbuf[i] = 0;
|
||||||
uptr->hwmark = uptr->capac;
|
uptr->hwmark = (uint32) uptr->capac;
|
||||||
if (ry_csr & RYCS_DEN) uptr->flags = uptr->flags | UNIT_DEN;
|
if (ry_csr & RYCS_DEN) uptr->flags = uptr->flags | UNIT_DEN;
|
||||||
else uptr->flags = uptr->flags & ~UNIT_DEN;
|
else uptr->flags = uptr->flags & ~UNIT_DEN;
|
||||||
ry_done (0, 0);
|
ry_done (0, 0);
|
||||||
|
@ -452,7 +453,7 @@ case ESXFR:
|
||||||
((ry_unit[0].flags & UNIT_DEN)? 0020: 0) |
|
((ry_unit[0].flags & UNIT_DEN)? 0020: 0) |
|
||||||
((ry_csr & RYCS_DEN)? 0001: 0);
|
((ry_csr & RYCS_DEN)? 0001: 0);
|
||||||
estat[7] = uptr->TRACK;
|
estat[7] = uptr->TRACK;
|
||||||
t = Map_WriteB (ba, 8, estat, MAP); /* DMA to memory */
|
t = Map_WriteB (ba, 8, estat); /* DMA to memory */
|
||||||
ry_done (t? RYES_NXM: 0, 0); /* done */
|
ry_done (t? RYES_NXM: 0, 0); /* done */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,9 @@
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
tti,tto DL11 terminal input/output
|
tti,tto DL11 terminal input/output
|
||||||
clk KW11L line frequency clock
|
clk KW11L (and other) line frequency clock
|
||||||
|
|
||||||
|
11-Oct-04 RMS Added clock model dependencies
|
||||||
28-May-04 RMS Removed SET TTI CTRL-C
|
28-May-04 RMS Removed SET TTI CTRL-C
|
||||||
29-Dec-03 RMS Added console backpressure support
|
29-Dec-03 RMS Added console backpressure support
|
||||||
25-Apr-03 RMS Revised for extended file support
|
25-Apr-03 RMS Revised for extended file support
|
||||||
|
@ -65,11 +66,15 @@
|
||||||
|
|
||||||
extern int32 int_req[IPL_HLVL];
|
extern int32 int_req[IPL_HLVL];
|
||||||
extern int32 int_vec[IPL_HLVL][32];
|
extern int32 int_vec[IPL_HLVL][32];
|
||||||
|
extern int32 cpu_type;
|
||||||
|
|
||||||
int32 tti_csr = 0; /* control/status */
|
int32 tti_csr = 0; /* control/status */
|
||||||
int32 tto_csr = 0; /* control/status */
|
int32 tto_csr = 0; /* control/status */
|
||||||
int32 clk_csr = 0; /* control/status */
|
int32 clk_csr = 0; /* control/status */
|
||||||
int32 clk_tps = 60; /* ticks/second */
|
int32 clk_tps = 60; /* ticks/second */
|
||||||
|
int32 clk_default = 60; /* default ticks/second */
|
||||||
|
int32 clk_fie = 0; /* force IE = 1 */
|
||||||
|
int32 clk_fnxm = 0; /* force NXM on reg */
|
||||||
int32 tmxr_poll = CLK_DELAY; /* term mux poll */
|
int32 tmxr_poll = CLK_DELAY; /* term mux poll */
|
||||||
int32 tmr_poll = CLK_DELAY; /* timer poll */
|
int32 tmr_poll = CLK_DELAY; /* timer poll */
|
||||||
|
|
||||||
|
@ -85,6 +90,7 @@ t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
t_stat clk_rd (int32 *data, int32 PA, int32 access);
|
t_stat clk_rd (int32 *data, int32 PA, int32 access);
|
||||||
t_stat clk_wr (int32 data, int32 PA, int32 access);
|
t_stat clk_wr (int32 data, int32 PA, int32 access);
|
||||||
t_stat clk_svc (UNIT *uptr);
|
t_stat clk_svc (UNIT *uptr);
|
||||||
|
int32 clk_inta (void);
|
||||||
t_stat clk_reset (DEVICE *dptr);
|
t_stat clk_reset (DEVICE *dptr);
|
||||||
t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc);
|
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 clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
|
@ -175,7 +181,7 @@ DEVICE tto_dev = {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DIB clk_dib = { IOBA_CLK, IOLN_CLK, &clk_rd, &clk_wr,
|
DIB clk_dib = { IOBA_CLK, IOLN_CLK, &clk_rd, &clk_wr,
|
||||||
1, IVCL (CLK), VEC_CLK, { NULL } };
|
1, IVCL (CLK), VEC_CLK, { &clk_inta } };
|
||||||
|
|
||||||
UNIT clk_unit = { UDATA (&clk_svc, 0, 0), 8000 };
|
UNIT clk_unit = { UDATA (&clk_svc, 0, 0), 8000 };
|
||||||
|
|
||||||
|
@ -185,7 +191,10 @@ REG clk_reg[] = {
|
||||||
{ FLDATA (DONE, clk_csr, CSR_V_DONE) },
|
{ FLDATA (DONE, clk_csr, CSR_V_DONE) },
|
||||||
{ FLDATA (IE, clk_csr, CSR_V_IE) },
|
{ FLDATA (IE, clk_csr, CSR_V_IE) },
|
||||||
{ DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT },
|
{ DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT },
|
||||||
{ DRDATA (TPS, clk_tps, 8), PV_LEFT + REG_HRO },
|
{ DRDATA (TPS, clk_tps, 16), PV_LEFT + REG_HRO },
|
||||||
|
{ DRDATA (DEFTPS, clk_default, 16), PV_LEFT + REG_HRO },
|
||||||
|
{ FLDATA (FIE, clk_fie, 0), REG_HIDDEN },
|
||||||
|
{ FLDATA (FNXM, clk_fnxm, 0), REG_HIDDEN },
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
MTAB clk_mod[] = {
|
MTAB clk_mod[] = {
|
||||||
|
@ -334,20 +343,32 @@ tto_unit.flags = (tto_unit.flags & ~UNIT_8B) | val;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The line time clock has a few twists and turns through the history of 11's
|
||||||
|
|
||||||
|
LSI-11 no CSR
|
||||||
|
LSI-11/23 (KDF11A) no CSR
|
||||||
|
PDP-11/23+ (KDF11B) no monitor bit
|
||||||
|
PDP-11/24 (KDF11U) monitor bit clears on IAK
|
||||||
|
*/
|
||||||
|
|
||||||
/* Clock I/O address routines */
|
/* Clock I/O address routines */
|
||||||
|
|
||||||
t_stat clk_rd (int32 *data, int32 PA, int32 access)
|
t_stat clk_rd (int32 *data, int32 PA, int32 access)
|
||||||
{
|
{
|
||||||
*data = clk_csr & CLKCSR_IMP;
|
if (clk_fnxm) return SCPE_NXM; /* not there??? */
|
||||||
|
if (CPUT (HAS_LTCM)) *data = clk_csr & CLKCSR_IMP; /* monitor bit? */
|
||||||
|
else *data = clk_csr & (CLKCSR_IMP & ~CSR_DONE); /* no, just IE */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
t_stat clk_wr (int32 data, int32 PA, int32 access)
|
t_stat clk_wr (int32 data, int32 PA, int32 access)
|
||||||
{
|
{
|
||||||
|
if (clk_fnxm) return SCPE_NXM; /* not there??? */
|
||||||
if (PA & 1) return SCPE_OK;
|
if (PA & 1) return SCPE_OK;
|
||||||
clk_csr = (clk_csr & ~CLKCSR_RW) | (data & CLKCSR_RW);
|
clk_csr = (clk_csr & ~CLKCSR_RW) | (data & CLKCSR_RW);
|
||||||
if ((data & CSR_DONE) == 0) clk_csr = clk_csr & ~CSR_DONE;
|
if (CPUT (HAS_LTCM) && ((data & CSR_DONE) == 0)) /* monitor bit? */
|
||||||
if (((clk_csr & CSR_IE) == 0) || /* unless IE+DONE */
|
clk_csr = clk_csr & ~CSR_DONE; /* clr if zero */
|
||||||
|
if ((((clk_csr & CSR_IE) == 0) && !clk_fie) || /* unless IE+DONE */
|
||||||
((clk_csr & CSR_DONE) == 0)) CLR_INT (CLK); /* clr intr */
|
((clk_csr & CSR_DONE) == 0)) CLR_INT (CLK); /* clr intr */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -359,7 +380,7 @@ t_stat clk_svc (UNIT *uptr)
|
||||||
int32 t;
|
int32 t;
|
||||||
|
|
||||||
clk_csr = clk_csr | CSR_DONE; /* set done */
|
clk_csr = clk_csr | CSR_DONE; /* set done */
|
||||||
if (clk_csr & CSR_IE) SET_INT (CLK);
|
if ((clk_csr & CSR_IE) || clk_fie) SET_INT (CLK);
|
||||||
t = sim_rtcn_calb (clk_tps, TMR_CLK); /* calibrate clock */
|
t = sim_rtcn_calb (clk_tps, TMR_CLK); /* calibrate clock */
|
||||||
sim_activate (&clk_unit, t); /* reactivate unit */
|
sim_activate (&clk_unit, t); /* reactivate unit */
|
||||||
tmr_poll = t; /* set timer poll */
|
tmr_poll = t; /* set timer poll */
|
||||||
|
@ -367,10 +388,21 @@ tmxr_poll = t; /* set mux poll */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Clock interrupt acknowledge */
|
||||||
|
|
||||||
|
int32 clk_inta (void)
|
||||||
|
{
|
||||||
|
if (CPUT (CPUT_24)) clk_csr = clk_csr & ~CSR_DONE;
|
||||||
|
return clk_dib.vec;
|
||||||
|
}
|
||||||
|
|
||||||
/* Clock reset */
|
/* Clock reset */
|
||||||
|
|
||||||
t_stat clk_reset (DEVICE *dptr)
|
t_stat clk_reset (DEVICE *dptr)
|
||||||
{
|
{
|
||||||
|
if (CPUT (HAS_LTCR)) clk_fie = clk_fnxm = 0; /* reg there? */
|
||||||
|
else clk_fie = clk_fnxm = 1; /* no, BEVENT */
|
||||||
|
clk_tps = clk_default; /* set default tps */
|
||||||
clk_csr = CSR_DONE; /* set done */
|
clk_csr = CSR_DONE; /* set done */
|
||||||
CLR_INT (CLK);
|
CLR_INT (CLK);
|
||||||
sim_activate (&clk_unit, clk_unit.wait); /* activate unit */
|
sim_activate (&clk_unit, clk_unit.wait); /* activate unit */
|
||||||
|
@ -385,7 +417,7 @@ t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
{
|
{
|
||||||
if (cptr) return SCPE_ARG;
|
if (cptr) return SCPE_ARG;
|
||||||
if ((val != 50) && (val != 60)) return SCPE_IERR;
|
if ((val != 50) && (val != 60)) return SCPE_IERR;
|
||||||
clk_tps = val;
|
clk_tps = clk_default = val;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,6 +425,6 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc)
|
t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
{
|
{
|
||||||
fprintf (st, (clk_tps == 50)? "50Hz": "60Hz");
|
fprintf (st, "%dHz", clk_tps);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
#include "pdp11_defs.h"
|
#include "pdp11_defs.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
extern DEVICE cpu_dev;
|
extern DEVICE cpu_dev, sys_dev;
|
||||||
extern DEVICE ptr_dev, ptp_dev;
|
extern DEVICE ptr_dev, ptp_dev;
|
||||||
extern DEVICE tti_dev, tto_dev;
|
extern DEVICE tti_dev, tto_dev;
|
||||||
extern DEVICE lpt_dev;
|
extern DEVICE lpt_dev;
|
||||||
|
@ -61,7 +61,8 @@ extern DEVICE vh_dev;
|
||||||
extern DEVICE rk_dev, rl_dev;
|
extern DEVICE rk_dev, rl_dev;
|
||||||
extern DEVICE hk_dev;
|
extern DEVICE hk_dev;
|
||||||
extern DEVICE rx_dev, ry_dev;
|
extern DEVICE rx_dev, ry_dev;
|
||||||
extern DEVICE rp_dev;
|
extern DEVICE mba0_dev, mba1_dev;
|
||||||
|
extern DEVICE rp_dev, tu_dev;
|
||||||
extern DEVICE rq_dev, rqb_dev, rqc_dev, rqd_dev;
|
extern DEVICE rq_dev, rqb_dev, rqc_dev, rqd_dev;
|
||||||
extern DEVICE dt_dev;
|
extern DEVICE dt_dev;
|
||||||
extern DEVICE tm_dev, ts_dev;
|
extern DEVICE tm_dev, ts_dev;
|
||||||
|
@ -91,6 +92,9 @@ int32 sim_emax = 4;
|
||||||
|
|
||||||
DEVICE *sim_devices[] = {
|
DEVICE *sim_devices[] = {
|
||||||
&cpu_dev,
|
&cpu_dev,
|
||||||
|
&sys_dev,
|
||||||
|
&mba0_dev,
|
||||||
|
&mba1_dev,
|
||||||
&ptr_dev,
|
&ptr_dev,
|
||||||
&ptp_dev,
|
&ptp_dev,
|
||||||
&tti_dev,
|
&tti_dev,
|
||||||
|
@ -114,6 +118,7 @@ DEVICE *sim_devices[] = {
|
||||||
&tm_dev,
|
&tm_dev,
|
||||||
&ts_dev,
|
&ts_dev,
|
||||||
&tq_dev,
|
&tq_dev,
|
||||||
|
&tu_dev,
|
||||||
&xq_dev,
|
&xq_dev,
|
||||||
&xqb_dev,
|
&xqb_dev,
|
||||||
&xu_dev,
|
&xu_dev,
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
tc TC11/TU56 DECtape
|
tc TC11/TU56 DECtape
|
||||||
|
|
||||||
|
30-Sep-04 RMS Revised Unibus interface
|
||||||
25-Jan-04 RMS Revised for device debug support
|
25-Jan-04 RMS Revised for device debug support
|
||||||
09-Jan-04 RMS Changed sim_fsize calling sequence, added STOP_OFFR
|
09-Jan-04 RMS Changed sim_fsize calling sequence, added STOP_OFFR
|
||||||
29-Dec-03 RMS Changed initial status to disabled (in Qbus system)
|
29-Dec-03 RMS Changed initial status to disabled (in Qbus system)
|
||||||
|
@ -737,7 +738,8 @@ int32 dir = mot & DTS_DIR;
|
||||||
int32 fnc = DTS_GETFNC (uptr->STATE);
|
int32 fnc = DTS_GETFNC (uptr->STATE);
|
||||||
int32 *fbuf = uptr->filebuf;
|
int32 *fbuf = uptr->filebuf;
|
||||||
int32 blk, wrd, relpos, dat;
|
int32 blk, wrd, relpos, dat;
|
||||||
uint32 ba, ma, mma;
|
uint32 ba, ma;
|
||||||
|
uint16 wbuf;
|
||||||
|
|
||||||
/* Motion cases
|
/* Motion cases
|
||||||
|
|
||||||
|
@ -799,15 +801,12 @@ case DTS_OFR: /* off reel */
|
||||||
case FNC_READ: /* read */
|
case FNC_READ: /* read */
|
||||||
wrd = DT_LIN2WD (uptr->pos, uptr); /* get word # */
|
wrd = DT_LIN2WD (uptr->pos, uptr); /* get word # */
|
||||||
if (!dt_substate) { /* !wc ovf? */
|
if (!dt_substate) { /* !wc ovf? */
|
||||||
tcwc = tcwc & DMASK; /* incr MA, WC */
|
|
||||||
tcba = tcba & DMASK;
|
|
||||||
ma = (CSR_GETMEX (tccm) << 16) | tcba; /* form 18b addr */
|
ma = (CSR_GETMEX (tccm) << 16) | tcba; /* form 18b addr */
|
||||||
if (!Map_Addr (ma, &mma) || /* map addr */
|
ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */
|
||||||
!ADDR_IS_MEM (mma)) { /* nx mem? */
|
tcdt = wbuf = fbuf[ba] & DMASK; /* read word */
|
||||||
|
if (Map_WriteW (ma, 2, &wbuf)) { /* store, nxm? */
|
||||||
dt_seterr (uptr, STA_NXM);
|
dt_seterr (uptr, STA_NXM);
|
||||||
break; }
|
break; }
|
||||||
ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */
|
|
||||||
M[mma >> 1] = tcdt = fbuf[ba] & DMASK; /* read word */
|
|
||||||
tcwc = (tcwc + 1) & DMASK; /* incr MA, WC */
|
tcwc = (tcwc + 1) & DMASK; /* incr MA, WC */
|
||||||
tcba = (tcba + 2) & DMASK;
|
tcba = (tcba + 2) & DMASK;
|
||||||
if (tcba <= 1) tccm = CSR_INCMEX (tccm);
|
if (tcba <= 1) tccm = CSR_INCMEX (tccm);
|
||||||
|
@ -835,11 +834,10 @@ case FNC_WRIT: /* write */
|
||||||
if (dt_substate) tcdt = 0; /* wc ovf? fill */
|
if (dt_substate) tcdt = 0; /* wc ovf? fill */
|
||||||
else {
|
else {
|
||||||
ma = (CSR_GETMEX (tccm) << 16) | tcba; /* form 18b addr */
|
ma = (CSR_GETMEX (tccm) << 16) | tcba; /* form 18b addr */
|
||||||
if (!Map_Addr (ma, &mma) || /* map addr */
|
if (Map_ReadW (ma, 2, &wbuf)) { /* fetch word */
|
||||||
!ADDR_IS_MEM (mma)) { /* nx mem? */
|
|
||||||
dt_seterr (uptr, STA_NXM);
|
dt_seterr (uptr, STA_NXM);
|
||||||
break; }
|
break; }
|
||||||
else tcdt = M[mma >> 1]; /* get word */
|
tcdt = wbuf; /* get word */
|
||||||
tcwc = (tcwc + 1) & DMASK; /* incr MA, WC */
|
tcwc = (tcwc + 1) & DMASK; /* incr MA, WC */
|
||||||
tcba = (tcba + 2) & DMASK;
|
tcba = (tcba + 2) & DMASK;
|
||||||
if (tcba <= 1) tccm = CSR_INCMEX (tccm); }
|
if (tcba <= 1) tccm = CSR_INCMEX (tccm); }
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
tm TM11/TU10 magtape
|
tm TM11/TU10 magtape
|
||||||
|
|
||||||
|
30-Sep-04 RMS Revised Unibus interface
|
||||||
25-Jan-04 RMS Revised for device debug support
|
25-Jan-04 RMS Revised for device debug support
|
||||||
29-Dec-03 RMS Added 18b Qbus support
|
29-Dec-03 RMS Added 18b Qbus support
|
||||||
25-Apr-03 RMS Revised for extended file support
|
25-Apr-03 RMS Revised for extended file support
|
||||||
|
@ -398,7 +399,7 @@ case MTC_READ: /* read */
|
||||||
break; }
|
break; }
|
||||||
if (tbc > cbc) tm_sta = tm_sta | STA_RLE; /* wrong size? */
|
if (tbc > cbc) tm_sta = tm_sta | STA_RLE; /* wrong size? */
|
||||||
if (tbc < cbc) cbc = tbc; /* use smaller */
|
if (tbc < cbc) cbc = tbc; /* use smaller */
|
||||||
if (t = Map_WriteB (xma, cbc, tmxb, MAP)) { /* copy buf to mem */
|
if (t = Map_WriteB (xma, cbc, tmxb)) { /* copy buf to mem */
|
||||||
tm_sta = tm_sta | STA_NXM; /* NXM, set err */
|
tm_sta = tm_sta | STA_NXM; /* NXM, set err */
|
||||||
cbc = cbc - t; } /* adj byte cnt */
|
cbc = cbc - t; } /* adj byte cnt */
|
||||||
xma = (xma + cbc) & 0777777; /* inc bus addr */
|
xma = (xma + cbc) & 0777777; /* inc bus addr */
|
||||||
|
@ -407,7 +408,7 @@ case MTC_READ: /* read */
|
||||||
|
|
||||||
case MTC_WRITE: /* write */
|
case MTC_WRITE: /* write */
|
||||||
case MTC_WREXT: /* write ext gap */
|
case MTC_WREXT: /* write ext gap */
|
||||||
if (t = Map_ReadB (xma, cbc, tmxb, MAP)) { /* copy mem to buf */
|
if (t = Map_ReadB (xma, cbc, tmxb)) { /* copy mem to buf */
|
||||||
tm_sta = tm_sta | STA_NXM; /* NXM, set err */
|
tm_sta = tm_sta | STA_NXM; /* NXM, set err */
|
||||||
cbc = cbc - t; /* adj byte cnt */
|
cbc = cbc - t; /* adj byte cnt */
|
||||||
if (cbc == 0) break; } /* no xfr? done */
|
if (cbc == 0) break; } /* no xfr? done */
|
||||||
|
@ -530,7 +531,7 @@ for (u = 0; u < TM_NUMDR; u++) { /* loop thru units */
|
||||||
(sim_tape_bot (uptr)? STA_BOT: 0) |
|
(sim_tape_bot (uptr)? STA_BOT: 0) |
|
||||||
(sim_tape_wrp (uptr)? STA_WLK: 0);
|
(sim_tape_wrp (uptr)? STA_WLK: 0);
|
||||||
else uptr->USTAT = 0; }
|
else uptr->USTAT = 0; }
|
||||||
if (tmxb == NULL) tmxb = calloc (MT_MAXFR, sizeof (unsigned int8));
|
if (tmxb == NULL) tmxb = calloc (MT_MAXFR, sizeof (uint8));
|
||||||
if (tmxb == NULL) return SCPE_MEM;
|
if (tmxb == NULL) return SCPE_MEM;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
tq TQK50 tape controller
|
tq TQK50 tape controller
|
||||||
|
|
||||||
|
30-Sep-04 RMS Revised Unibus interface
|
||||||
12-Jun-04 RMS Fixed bug in reporting write protect (reported by Lyle Bickley)
|
12-Jun-04 RMS Fixed bug in reporting write protect (reported by Lyle Bickley)
|
||||||
18-Apr-04 RMS Fixed TQK70 media ID and model byte (found by Robert Schaffrath)
|
18-Apr-04 RMS Fixed TQK70 media ID and model byte (found by Robert Schaffrath)
|
||||||
26-Mar-04 RMS Fixed warnings with -std=c99
|
26-Mar-04 RMS Fixed warnings with -std=c99
|
||||||
|
@ -45,14 +46,16 @@
|
||||||
|
|
||||||
#elif defined (VM_VAX) /* VAX version */
|
#elif defined (VM_VAX) /* VAX version */
|
||||||
#include "vax_defs.h"
|
#include "vax_defs.h"
|
||||||
extern int32 int_req[IPL_HLVL];
|
#if (UNIBUS)
|
||||||
extern int32 int_vec[IPL_HLVL][32];
|
#define INIT_TYPE TQU_TYPE
|
||||||
|
#else
|
||||||
|
#define INIT_TYPE TQ5_TYPE
|
||||||
|
#endif
|
||||||
|
|
||||||
#else /* PDP-11 version */
|
#else /* PDP-11 version */
|
||||||
#include "pdp11_defs.h"
|
#include "pdp11_defs.h"
|
||||||
extern int32 int_req[IPL_HLVL];
|
#define INIT_TYPE TQ5_TYPE
|
||||||
extern int32 int_vec[IPL_HLVL][32];
|
extern int32 cpu_opt;
|
||||||
extern int32 cpu_18b, cpu_ubm;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "pdp11_uqssp.h"
|
#include "pdp11_uqssp.h"
|
||||||
|
@ -236,7 +239,7 @@ int32 tq_itime = 200; /* init time, except */
|
||||||
int32 tq_itime4 = 10; /* stage 4 */
|
int32 tq_itime4 = 10; /* stage 4 */
|
||||||
int32 tq_qtime = 200; /* queue time */
|
int32 tq_qtime = 200; /* queue time */
|
||||||
int32 tq_xtime = 500; /* transfer time */
|
int32 tq_xtime = 500; /* transfer time */
|
||||||
int32 tq_typ = TQ5_TYPE; /* device type */
|
int32 tq_typ = INIT_TYPE; /* device type */
|
||||||
|
|
||||||
/* Command table - legal modifiers (low 16b) and flags (high 16b) */
|
/* Command table - legal modifiers (low 16b) and flags (high 16b) */
|
||||||
|
|
||||||
|
@ -506,7 +509,7 @@ else base = tq_comm + SA_COMM_CI;
|
||||||
lnt = tq_comm + tq_cq.lnt + tq_rq.lnt - base; /* comm lnt */
|
lnt = tq_comm + tq_cq.lnt + tq_rq.lnt - base; /* comm lnt */
|
||||||
if (lnt > SA_COMM_MAX) lnt = SA_COMM_MAX; /* paranoia */
|
if (lnt > SA_COMM_MAX) lnt = SA_COMM_MAX; /* paranoia */
|
||||||
for (i = 0; i < (lnt >> 1); i++) zero[i] = 0; /* clr buffer */
|
for (i = 0; i < (lnt >> 1); i++) zero[i] = 0; /* clr buffer */
|
||||||
if (Map_WriteW (base, lnt, zero, MAP)) /* zero comm area */
|
if (Map_WriteW (base, lnt, zero)) /* zero comm area */
|
||||||
return tq_fatal (PE_QWE); /* error? */
|
return tq_fatal (PE_QWE); /* error? */
|
||||||
tq_sa = SA_S4 | (drv_tab[tq_typ].uqpm << SA_S4C_V_MOD) |/* send step 4 */
|
tq_sa = SA_S4 | (drv_tab[tq_typ].uqpm << SA_S4C_V_MOD) |/* send step 4 */
|
||||||
((drv_tab[tq_typ].cver & 0xFF) << SA_S4C_V_VER);
|
((drv_tab[tq_typ].cver & 0xFF) << SA_S4C_V_VER);
|
||||||
|
@ -1062,7 +1065,7 @@ case OP_RD:case OP_ACC:case OP_CMP: /* read-like op */
|
||||||
wbc = bc; } /* set working bc */
|
wbc = bc; } /* set working bc */
|
||||||
else wbc = tbc;
|
else wbc = tbc;
|
||||||
if (cmd == OP_RD) { /* read? */
|
if (cmd == OP_RD) { /* read? */
|
||||||
if (t = Map_WriteB (ba, wbc, tqxb, MAP)) { /* store, nxm? */
|
if (t = Map_WriteB (ba, wbc, tqxb)) { /* store, nxm? */
|
||||||
PUTP32 (pkt, RW_BCL, wbc - t); /* adj bc */
|
PUTP32 (pkt, RW_BCL, wbc - t); /* adj bc */
|
||||||
if (tq_hbe (uptr, ba + wbc - t)) /* post err log */
|
if (tq_hbe (uptr, ba + wbc - t)) /* post err log */
|
||||||
tq_mot_end (uptr, EF_LOG, ST_HST | SB_HST_NXM, tbc);
|
tq_mot_end (uptr, EF_LOG, ST_HST | SB_HST_NXM, tbc);
|
||||||
|
@ -1078,7 +1081,7 @@ case OP_RD:case OP_ACC:case OP_CMP: /* read-like op */
|
||||||
else {
|
else {
|
||||||
mba = ba + i;
|
mba = ba + i;
|
||||||
dby = tqxb[i]; }
|
dby = tqxb[i]; }
|
||||||
if (Map_ReadB (mba, 1, &mby, MAP)) { /* fetch, nxm? */
|
if (Map_ReadB (mba, 1, &mby)) { /* fetch, nxm? */
|
||||||
PUTP32 (pkt, RW_BCL, i); /* adj bc */
|
PUTP32 (pkt, RW_BCL, i); /* adj bc */
|
||||||
if (tq_hbe (uptr, mba)) /* post err log */
|
if (tq_hbe (uptr, mba)) /* post err log */
|
||||||
tq_mot_end (uptr, EF_LOG, ST_HST | SB_HST_NXM, tbc);
|
tq_mot_end (uptr, EF_LOG, ST_HST | SB_HST_NXM, tbc);
|
||||||
|
@ -1094,7 +1097,7 @@ case OP_RD:case OP_ACC:case OP_CMP: /* read-like op */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_WR: /* write */
|
case OP_WR: /* write */
|
||||||
if (t = Map_ReadB (ba, bc, tqxb, MAP)) { /* fetch buf, nxm? */
|
if (t = Map_ReadB (ba, bc, tqxb)) { /* fetch buf, nxm? */
|
||||||
PUTP32 (pkt, RW_BCL, 0); /* no bytes xfer'd */
|
PUTP32 (pkt, RW_BCL, 0); /* no bytes xfer'd */
|
||||||
if (tq_hbe (uptr, ba + bc - t)) /* post err log */
|
if (tq_hbe (uptr, ba + bc - t)) /* post err log */
|
||||||
tq_mot_end (uptr, EF_LOG, ST_HST | SB_HST_NXM, bc);
|
tq_mot_end (uptr, EF_LOG, ST_HST | SB_HST_NXM, bc);
|
||||||
|
@ -1481,7 +1484,7 @@ if ((desc & UQ_DESC_OWN) == 0) { /* none */
|
||||||
if (!tq_deqf (pkt)) return ERR; /* get cmd pkt */
|
if (!tq_deqf (pkt)) return ERR; /* get cmd pkt */
|
||||||
tq_hat = 0; /* dsbl hst timer */
|
tq_hat = 0; /* dsbl hst timer */
|
||||||
addr = desc & UQ_ADDR; /* get Q22 addr */
|
addr = desc & UQ_ADDR; /* get Q22 addr */
|
||||||
if (Map_ReadW (addr + UQ_HDR_OFF, TQ_PKT_SIZE, tq_pkt[*pkt].d, MAP))
|
if (Map_ReadW (addr + UQ_HDR_OFF, TQ_PKT_SIZE, tq_pkt[*pkt].d))
|
||||||
return tq_fatal (PE_PRE); /* read pkt */
|
return tq_fatal (PE_PRE); /* read pkt */
|
||||||
return tq_putdesc (&tq_cq, desc); /* release desc */
|
return tq_putdesc (&tq_cq, desc); /* release desc */
|
||||||
}
|
}
|
||||||
|
@ -1516,7 +1519,7 @@ if ((GETP (pkt, UQ_HCTC, TYP) == UQ_TYP_SEQ) && /* seq packet? */
|
||||||
cr = (tq_credits >= 14)? 14: tq_credits; /* max 14 credits */
|
cr = (tq_credits >= 14)? 14: tq_credits; /* max 14 credits */
|
||||||
tq_credits = tq_credits - cr; /* decr credits */
|
tq_credits = tq_credits - cr; /* decr credits */
|
||||||
tq_pkt[pkt].d[UQ_HCTC] |= ((cr + 1) << UQ_HCTC_V_CR); }
|
tq_pkt[pkt].d[UQ_HCTC] |= ((cr + 1) << UQ_HCTC_V_CR); }
|
||||||
if (Map_WriteW (addr + UQ_HDR_OFF, lnt, tq_pkt[pkt].d, MAP))
|
if (Map_WriteW (addr + UQ_HDR_OFF, lnt, tq_pkt[pkt].d))
|
||||||
return tq_fatal (PE_PWE); /* write pkt */
|
return tq_fatal (PE_PWE); /* write pkt */
|
||||||
tq_enqh (&tq_freq, pkt); /* pkt is free */
|
tq_enqh (&tq_freq, pkt); /* pkt is free */
|
||||||
tq_pbsy = tq_pbsy - 1; /* decr busy cnt */
|
tq_pbsy = tq_pbsy - 1; /* decr busy cnt */
|
||||||
|
@ -1531,7 +1534,7 @@ t_bool tq_getdesc (struct uq_ring *ring, uint32 *desc)
|
||||||
uint32 addr = ring->ba + ring->idx;
|
uint32 addr = ring->ba + ring->idx;
|
||||||
uint16 d[2];
|
uint16 d[2];
|
||||||
|
|
||||||
if (Map_ReadW (addr, 4, d, MAP)) /* fetch desc */
|
if (Map_ReadW (addr, 4, d)) /* fetch desc */
|
||||||
return tq_fatal (PE_QRE); /* err? dead */
|
return tq_fatal (PE_QRE); /* err? dead */
|
||||||
*desc = ((uint32) d[0]) | (((uint32) d[1]) << 16);
|
*desc = ((uint32) d[0]) | (((uint32) d[1]) << 16);
|
||||||
return OK;
|
return OK;
|
||||||
|
@ -1551,13 +1554,13 @@ uint16 d[2];
|
||||||
|
|
||||||
d[0] = newd & 0xFFFF; /* 32b to 16b */
|
d[0] = newd & 0xFFFF; /* 32b to 16b */
|
||||||
d[1] = (newd >> 16) & 0xFFFF;
|
d[1] = (newd >> 16) & 0xFFFF;
|
||||||
if (Map_WriteW (addr, 4, d, MAP)) /* store desc */
|
if (Map_WriteW (addr, 4, d)) /* store desc */
|
||||||
return tq_fatal (PE_QWE); /* err? dead */
|
return tq_fatal (PE_QWE); /* err? dead */
|
||||||
if (desc & UQ_DESC_F) { /* was F set? */
|
if (desc & UQ_DESC_F) { /* was F set? */
|
||||||
if (ring->lnt <= 4) tq_ring_int (ring); /* lnt = 1? intr */
|
if (ring->lnt <= 4) tq_ring_int (ring); /* lnt = 1? intr */
|
||||||
else { prva = ring->ba + /* prv desc */
|
else { prva = ring->ba + /* prv desc */
|
||||||
((ring->idx - 4) & (ring->lnt - 1));
|
((ring->idx - 4) & (ring->lnt - 1));
|
||||||
if (Map_ReadW (prva, 4, d, MAP)) /* read prv */
|
if (Map_ReadW (prva, 4, d)) /* read prv */
|
||||||
return tq_fatal (PE_QRE);
|
return tq_fatal (PE_QRE);
|
||||||
prvd = ((uint32) d[0]) | (((uint32) d[1]) << 16);
|
prvd = ((uint32) d[0]) | (((uint32) d[1]) << 16);
|
||||||
if (prvd & UQ_DESC_OWN) tq_ring_int (ring); } }
|
if (prvd & UQ_DESC_OWN) tq_ring_int (ring); } }
|
||||||
|
@ -1652,7 +1655,7 @@ void tq_ring_int (struct uq_ring *ring)
|
||||||
uint32 iadr = tq_comm + ring->ioff; /* addr intr wd */
|
uint32 iadr = tq_comm + ring->ioff; /* addr intr wd */
|
||||||
uint16 flag = 1;
|
uint16 flag = 1;
|
||||||
|
|
||||||
Map_WriteW (iadr, 2, &flag, MAP); /* write flag */
|
Map_WriteW (iadr, 2, &flag); /* write flag */
|
||||||
if (tq_dib.vec) SET_INT (TQ); /* if enb, intr */
|
if (tq_dib.vec) SET_INT (TQ); /* if enb, intr */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1712,7 +1715,8 @@ UNIT *uptr;
|
||||||
tq_csta = CST_S1; /* init stage 1 */
|
tq_csta = CST_S1; /* init stage 1 */
|
||||||
tq_s1dat = 0; /* no S1 data */
|
tq_s1dat = 0; /* no S1 data */
|
||||||
tq_dib.vec = 0; /* no vector */
|
tq_dib.vec = 0; /* no vector */
|
||||||
tq_sa = SA_S1 | SA_S1C_Q22 | SA_S1C_DI | SA_S1C_MP; /* init SA val */
|
if (UNIBUS) tq_sa = SA_S1 | SA_S1C_DI | SA_S1C_MP; /* Unibus? */
|
||||||
|
else tq_sa = SA_S1 | SA_S1C_Q22 | SA_S1C_DI | SA_S1C_MP; /* init SA val */
|
||||||
tq_cflgs = CF_RPL; /* ctrl flgs off */
|
tq_cflgs = CF_RPL; /* ctrl flgs off */
|
||||||
tq_htmo = TQ_DHTMO; /* default timeout */
|
tq_htmo = TQ_DHTMO; /* default timeout */
|
||||||
tq_hat = tq_htmo; /* default timer */
|
tq_hat = tq_htmo; /* default timer */
|
||||||
|
@ -1870,6 +1874,7 @@ t_stat tq_boot (int32 unitno, DEVICE *dptr)
|
||||||
{
|
{
|
||||||
return SCPE_NOFNC;
|
return SCPE_NOFNC;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Special show commands */
|
/* Special show commands */
|
||||||
|
@ -1887,7 +1892,7 @@ fprintf (st, "ring, base = %x, index = %d, length = %d\n",
|
||||||
rp->ba, rp->idx >> 2, rp->lnt >> 2);
|
rp->ba, rp->idx >> 2, rp->lnt >> 2);
|
||||||
#endif
|
#endif
|
||||||
for (i = 0; i < (rp->lnt >> 2); i++) {
|
for (i = 0; i < (rp->lnt >> 2); i++) {
|
||||||
if (Map_ReadW (rp->ba + (i << 2), 4, d, MAP)) {
|
if (Map_ReadW (rp->ba + (i << 2), 4, d)) {
|
||||||
fprintf (st, " %3d: non-existent memory\n", i);
|
fprintf (st, " %3d: non-existent memory\n", i);
|
||||||
break; }
|
break; }
|
||||||
desc = ((uint32) d[0]) | (((uint32) d[1]) << 16);
|
desc = ((uint32) d[0]) | (((uint32) d[1]) << 16);
|
||||||
|
|
125
PDP11/pdp11_ts.c
125
PDP11/pdp11_ts.c
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
ts TS11/TSV05 magtape
|
ts TS11/TSV05 magtape
|
||||||
|
|
||||||
|
30-Sep-04 RMS Revised Unibus interface
|
||||||
25-Jan-04 RMS Revised for device debug support
|
25-Jan-04 RMS Revised for device debug support
|
||||||
19-May-03 RMS Revised for new conditional compilation scheme
|
19-May-03 RMS Revised for new conditional compilation scheme
|
||||||
25-Apr-03 RMS Revised for extended file support
|
25-Apr-03 RMS Revised for extended file support
|
||||||
|
@ -82,30 +83,16 @@
|
||||||
#elif defined (VM_VAX) /* VAX version */
|
#elif defined (VM_VAX) /* VAX version */
|
||||||
#include "vax_defs.h"
|
#include "vax_defs.h"
|
||||||
#define TS_DIS 0 /* on by default */
|
#define TS_DIS 0 /* on by default */
|
||||||
#define ADDRTEST 0177700
|
|
||||||
#define DMASK 0xFFFF
|
#define DMASK 0xFFFF
|
||||||
extern int32 ReadB (uint32 pa);
|
|
||||||
extern void WriteB (uint32 pa, int32 val);
|
|
||||||
extern int32 ReadW (uint32 pa);
|
|
||||||
extern void WriteW (uint32 pa, int32 val);
|
|
||||||
extern int32 int_req[IPL_HLVL];
|
|
||||||
extern int32 int_vec[IPL_HLVL][32];
|
|
||||||
|
|
||||||
#else /* PDP-11 version */
|
#else /* PDP-11 version */
|
||||||
#include "pdp11_defs.h"
|
#include "pdp11_defs.h"
|
||||||
#define TS_DIS DEV_DIS /* off by default */
|
#define TS_DIS DEV_DIS /* off by default */
|
||||||
#define ADDRTEST (UNIBUS? 0177774: 0177700)
|
extern int32 cpu_opt;
|
||||||
extern uint16 *M;
|
|
||||||
extern int32 cpu_18b, cpu_ubm;
|
|
||||||
#define ReadB(p) ((M[(p) >> 1] >> (((p) & 1)? 8: 0)) & 0377)
|
|
||||||
#define WriteB(p,v) M[(p) >> 1] = ((p) & 1)? \
|
|
||||||
((M[(p) >> 1] & 0377) | ((v) << 8)): \
|
|
||||||
((M[(p) >> 1] & ~0377) | (v))
|
|
||||||
#define ReadW(p) M[(p) >> 1]
|
|
||||||
#define WriteW(p,v) M[(p) >> 1] = (v)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "sim_tape.h"
|
#include "sim_tape.h"
|
||||||
|
#define ADDRTEST (UNIBUS? 0177774: 0177700)
|
||||||
|
|
||||||
/* TSBA/TSDB - 17772520: base address/data buffer register
|
/* TSBA/TSDB - 17772520: base address/data buffer register
|
||||||
|
|
||||||
|
@ -268,6 +255,7 @@ extern int32 cpu_18b, cpu_ubm;
|
||||||
#define WCHX_HDS 0000040 /* high density */
|
#define WCHX_HDS 0000040 /* high density */
|
||||||
|
|
||||||
#define MAX(a,b) (((a) >= (b))? (a): (b))
|
#define MAX(a,b) (((a) >= (b))? (a): (b))
|
||||||
|
#define MAX_PLNT 8 /* max pkt length */
|
||||||
|
|
||||||
extern int32 int_req[IPL_HLVL];
|
extern int32 int_req[IPL_HLVL];
|
||||||
extern int32 int_vec[IPL_HLVL][32];
|
extern int32 int_vec[IPL_HLVL][32];
|
||||||
|
@ -286,6 +274,7 @@ int32 ts_ownm = 0; /* tape owns msg */
|
||||||
int32 ts_qatn = 0; /* queued attn */
|
int32 ts_qatn = 0; /* queued attn */
|
||||||
int32 ts_bcmd = 0; /* boot cmd */
|
int32 ts_bcmd = 0; /* boot cmd */
|
||||||
int32 ts_time = 10; /* record latency */
|
int32 ts_time = 10; /* record latency */
|
||||||
|
static uint16 cpy_buf[MAX_PLNT]; /* copy buffer */
|
||||||
|
|
||||||
DEVICE ts_dev;
|
DEVICE ts_dev;
|
||||||
t_stat ts_rd (int32 *data, int32 PA, int32 access);
|
t_stat ts_rd (int32 *data, int32 PA, int32 access);
|
||||||
|
@ -383,8 +372,7 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat ts_wr (int32 data, int32 PA, int32 access)
|
t_stat ts_wr (int32 data, int32 PA, int32 access)
|
||||||
{
|
{
|
||||||
int32 i;
|
int32 i, t;
|
||||||
uint32 pa;
|
|
||||||
|
|
||||||
switch ((PA >> 1) & 01) { /* decode PA<1> */
|
switch ((PA >> 1) & 01) { /* decode PA<1> */
|
||||||
case 0: /* TSDB */
|
case 0: /* TSDB */
|
||||||
|
@ -398,13 +386,13 @@ case 0: /* TSDB */
|
||||||
msgxs0 = ts_updxs0 (msgxs0 & ~XS0_ALLCLR); /* clr, upd xs0 */
|
msgxs0 = ts_updxs0 (msgxs0 & ~XS0_ALLCLR); /* clr, upd xs0 */
|
||||||
msgrfc = msgxs1 = msgxs2 = msgxs3 = msgxs4 = 0; /* clr status */
|
msgrfc = msgxs1 = msgxs2 = msgxs3 = msgxs4 = 0; /* clr status */
|
||||||
CLR_INT (TS); /* clr int req */
|
CLR_INT (TS); /* clr int req */
|
||||||
for (i = 0; i < CMD_PLNT; i++) { /* get cmd pkt */
|
t = Map_ReadW (tsba, CMD_PLNT << 1, cpy_buf); /* read cmd pkt */
|
||||||
if (Map_Addr (tsba, &pa) && ADDR_IS_MEM (pa))
|
tsba = tsba + ((CMD_PLNT << 1) - t); /* incr tsba */
|
||||||
tscmdp[i] = ReadW (pa);
|
if (t) { /* nxm? */
|
||||||
else {
|
|
||||||
ts_endcmd (TSSR_NXM + TC5, 0, MSG_ACK|MSG_MNEF|MSG_CFAIL);
|
ts_endcmd (TSSR_NXM + TC5, 0, MSG_ACK|MSG_MNEF|MSG_CFAIL);
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
tsba = tsba + 2; } /* incr tsba */
|
for (i = 0; i < CMD_PLNT; i++) /* copy packet */
|
||||||
|
tscmdp[i] = cpy_buf[i];
|
||||||
ts_ownc = ts_ownm = 1; /* tape owns all */
|
ts_ownc = ts_ownm = 1; /* tape owns all */
|
||||||
sim_activate (&ts_unit, ts_time); /* activate */
|
sim_activate (&ts_unit, ts_time); /* activate */
|
||||||
break;
|
break;
|
||||||
|
@ -536,8 +524,8 @@ return 0;
|
||||||
int32 ts_readf (UNIT *uptr, uint32 fc)
|
int32 ts_readf (UNIT *uptr, uint32 fc)
|
||||||
{
|
{
|
||||||
t_stat st;
|
t_stat st;
|
||||||
t_mtrlnt i, tbc, wbc;
|
t_mtrlnt i, t, tbc, wbc;
|
||||||
uint32 wa, pa;
|
int32 wa;
|
||||||
|
|
||||||
msgrfc = fc;
|
msgrfc = fc;
|
||||||
st = sim_tape_rdrecf (uptr, tsxb, &tbc, MT_MAXFR); /* read rec fwd */
|
st = sim_tape_rdrecf (uptr, tsxb, &tbc, MT_MAXFR); /* read rec fwd */
|
||||||
|
@ -546,15 +534,22 @@ if (fc == 0) fc = 0200000; /* byte count */
|
||||||
tsba = (cmdadh << 16) | cmdadl; /* buf addr */
|
tsba = (cmdadh << 16) | cmdadl; /* buf addr */
|
||||||
wbc = (tbc > fc)? fc: tbc; /* cap buf size */
|
wbc = (tbc > fc)? fc: tbc; /* cap buf size */
|
||||||
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
||||||
for (i = 0; i < wbc; i++) { /* copy buffer */
|
if (cmdhdr & CMD_SWP) { /* swapped? */
|
||||||
wa = (cmdhdr & CMD_SWP)? tsba ^ 1: tsba; /* apply OPP */
|
for (i = 0; i < wbc; i++) { /* copy buffer */
|
||||||
if (Map_Addr (wa, &pa) && ADDR_IS_MEM (pa)) /* map addr, nxm? */
|
wa = tsba ^ 1; /* apply OPP */
|
||||||
WriteB (pa, tsxb[i]); /* no, store */
|
if (Map_WriteB (tsba, 1, &tsxb[i])) { /* store byte, nxm? */
|
||||||
else {
|
|
||||||
tssr = ts_updtssr (tssr | TSSR_NXM); /* set error */
|
tssr = ts_updtssr (tssr | TSSR_NXM); /* set error */
|
||||||
return (XTC (XS0_RLS, TC4)); }
|
return (XTC (XS0_RLS, TC4)); }
|
||||||
tsba = tsba + 1;
|
tsba = tsba + 1;
|
||||||
msgrfc = (msgrfc - 1) & DMASK; }
|
msgrfc = (msgrfc - 1) & DMASK; }
|
||||||
|
}
|
||||||
|
else { t = Map_WriteB (tsba, wbc, tsxb); /* store record */
|
||||||
|
tsba = tsba + (wbc - t); /* update tsba */
|
||||||
|
if (t) { /* nxm? */
|
||||||
|
tssr = ts_updtssr (tssr | TSSR_NXM); /* set error */
|
||||||
|
return (XTC (XS0_RLS, TC4)); }
|
||||||
|
msgrfc = (msgrfc - (wbc - t)) & DMASK; /* update fc */
|
||||||
|
}
|
||||||
if (msgrfc) return (XTC (XS0_RLS, TC2)); /* buf too big? */
|
if (msgrfc) return (XTC (XS0_RLS, TC2)); /* buf too big? */
|
||||||
if (tbc > wbc) return (XTC (XS0_RLL, TC2)); /* rec too big? */
|
if (tbc > wbc) return (XTC (XS0_RLL, TC2)); /* rec too big? */
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -564,7 +559,7 @@ int32 ts_readr (UNIT *uptr, uint32 fc)
|
||||||
{
|
{
|
||||||
t_stat st;
|
t_stat st;
|
||||||
t_mtrlnt i, tbc, wbc;
|
t_mtrlnt i, tbc, wbc;
|
||||||
uint32 wa, pa;
|
int32 wa;
|
||||||
|
|
||||||
msgrfc = fc;
|
msgrfc = fc;
|
||||||
st = sim_tape_rdrecr (uptr, tsxb, &tbc, MT_MAXFR); /* read rec rev */
|
st = sim_tape_rdrecr (uptr, tsxb, &tbc, MT_MAXFR); /* read rec rev */
|
||||||
|
@ -576,9 +571,7 @@ msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
||||||
for (i = wbc; i > 0; i--) { /* copy buffer */
|
for (i = wbc; i > 0; i--) { /* copy buffer */
|
||||||
tsba = tsba - 1;
|
tsba = tsba - 1;
|
||||||
wa = (cmdhdr & CMD_SWP)? tsba ^ 1: tsba; /* apply OPP */
|
wa = (cmdhdr & CMD_SWP)? tsba ^ 1: tsba; /* apply OPP */
|
||||||
if (Map_Addr (wa, &pa) && ADDR_IS_MEM (pa)) /* map addr, nxm? */
|
if (Map_WriteB (wa, 1, &tsxb[i - 1])) { /* store byte, nxm? */
|
||||||
WriteB (pa, tsxb[i - 1]); /* no, store */
|
|
||||||
else {
|
|
||||||
tssr = ts_updtssr (tssr | TSSR_NXM);
|
tssr = ts_updtssr (tssr | TSSR_NXM);
|
||||||
return (XTC (XS0_RLS, TC4)); }
|
return (XTC (XS0_RLS, TC4)); }
|
||||||
msgrfc = (msgrfc - 1) & DMASK; }
|
msgrfc = (msgrfc - 1) & DMASK; }
|
||||||
|
@ -589,21 +582,27 @@ return 0;
|
||||||
|
|
||||||
int32 ts_write (UNIT *uptr, int32 fc)
|
int32 ts_write (UNIT *uptr, int32 fc)
|
||||||
{
|
{
|
||||||
int32 i;
|
int32 i, t;
|
||||||
uint32 wa, pa;
|
uint32 wa;
|
||||||
t_stat st;
|
t_stat st;
|
||||||
|
|
||||||
msgrfc = fc;
|
msgrfc = fc;
|
||||||
if (fc == 0) fc = 0200000; /* byte count */
|
if (fc == 0) fc = 0200000; /* byte count */
|
||||||
tsba = (cmdadh << 16) | cmdadl; /* buf addr */
|
tsba = (cmdadh << 16) | cmdadl; /* buf addr */
|
||||||
for (i = 0; i < fc; i++) { /* copy mem to buf */
|
if (cmdhdr & CMD_SWP) { /* swapped? */
|
||||||
wa = (cmdhdr & CMD_SWP)? tsba ^ 1: tsba; /* apply OPP */
|
for (i = 0; i < fc; i++) { /* copy mem to buf */
|
||||||
if (Map_Addr (wa, &pa) && ADDR_IS_MEM (pa)) /* map addr, nxm? */
|
wa = tsba ^ 1; /* apply OPP */
|
||||||
tsxb[i] = ReadB (pa); /* no, store */
|
if (Map_ReadB (wa, 1, &tsxb[i])) { /* fetch byte, nxm? */
|
||||||
else {
|
|
||||||
tssr = ts_updtssr (tssr | TSSR_NXM);
|
tssr = ts_updtssr (tssr | TSSR_NXM);
|
||||||
return TC5; }
|
return TC5; }
|
||||||
tsba = tsba + 1; }
|
tsba = tsba + 1; }
|
||||||
|
}
|
||||||
|
else { t = Map_ReadB (tsba, fc, tsxb); /* fetch record */
|
||||||
|
tsba = tsba + (fc - t); /* update tsba */
|
||||||
|
if (t) { /* nxm? */
|
||||||
|
tssr = ts_updtssr (tssr | TSSR_NXM);
|
||||||
|
return TC5; }
|
||||||
|
}
|
||||||
if (st = sim_tape_wrrecf (uptr, tsxb, fc)) /* write rec, err? */
|
if (st = sim_tape_wrrecf (uptr, tsxb, fc)) /* write rec, err? */
|
||||||
return ts_map_status (st); /* return status */
|
return ts_map_status (st); /* return status */
|
||||||
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
||||||
|
@ -625,8 +624,7 @@ return XTC (XS0_TMK, TC0);
|
||||||
|
|
||||||
t_stat ts_svc (UNIT *uptr)
|
t_stat ts_svc (UNIT *uptr)
|
||||||
{
|
{
|
||||||
int32 i, fnc, mod, st0, st1;
|
int32 i, t, bc, fnc, mod, st0, st1;
|
||||||
uint32 pa;
|
|
||||||
|
|
||||||
static const int32 fnc_mod[CMD_N_FNC] = { /* max mod+1 0 ill */
|
static const int32 fnc_mod[CMD_N_FNC] = { /* max mod+1 0 ill */
|
||||||
0, 4, 0, 0, 1, 2, 1, 0, /* 00 - 07 */
|
0, 4, 0, 0, 1, 2, 1, 0, /* 00 - 07 */
|
||||||
|
@ -638,6 +636,11 @@ static const int32 fnc_flg[CMD_N_FNC] = {
|
||||||
FLG_MO, FLG_MO+FLG_WR, FLG_MO, 0, 0, 0, 0, 0,
|
FLG_MO, FLG_MO+FLG_WR, FLG_MO, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 27 */
|
0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 27 */
|
||||||
0, 0, 0, 0, 0, 0, 0, 0 }; /* 30 - 37 */
|
0, 0, 0, 0, 0, 0, 0, 0 }; /* 30 - 37 */
|
||||||
|
static const char *fnc_name[CMD_N_FNC] = {
|
||||||
|
"0", "READ", "2", "3", "WCHR", "WRITE", "WSSM", "7",
|
||||||
|
"POS", "FMT", "CTL", "INIT", "14", "15", "16", "GSTA",
|
||||||
|
"20", "21", "22", "23", "24", "25", "26", "27",
|
||||||
|
"30", "31", "32", "33", "34", "35", "36", "37" };
|
||||||
|
|
||||||
if (ts_bcmd) { /* boot? */
|
if (ts_bcmd) { /* boot? */
|
||||||
ts_bcmd = 0; /* clear flag */
|
ts_bcmd = 0; /* clear flag */
|
||||||
|
@ -659,8 +662,8 @@ if (!(cmdhdr & CMD_ACK)) { /* no acknowledge? */
|
||||||
fnc = GET_FNC (cmdhdr); /* get fnc+mode */
|
fnc = GET_FNC (cmdhdr); /* get fnc+mode */
|
||||||
mod = GET_MOD (cmdhdr);
|
mod = GET_MOD (cmdhdr);
|
||||||
if (DEBUG_PRS (ts_dev))
|
if (DEBUG_PRS (ts_dev))
|
||||||
fprintf (sim_deb, ">>TS: cmd=%o, mod=%o, buf=%o, lnt=%d, pos=%d\n",
|
fprintf (sim_deb, ">>TS: cmd=%s, mod=%o, buf=%o, lnt=%d, pos=%d\n",
|
||||||
fnc, mod, cmdadl, cmdlnt, ts_unit.pos);
|
fnc_name[fnc], mod, cmdadl, cmdlnt, ts_unit.pos);
|
||||||
if ((fnc != FNC_WCHR) && (tssr & TSSR_NBA)) { /* ~wr chr & nba? */
|
if ((fnc != FNC_WCHR) && (tssr & TSSR_NBA)) { /* ~wr chr & nba? */
|
||||||
ts_endcmd (TC3, 0, 0); /* error */
|
ts_endcmd (TC3, 0, 0); /* error */
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
|
@ -705,13 +708,14 @@ case FNC_WCHR: /* write char */
|
||||||
ts_endcmd (TSSR_NBA | TC3, XS0_ILA, 0);
|
ts_endcmd (TSSR_NBA | TC3, XS0_ILA, 0);
|
||||||
break; }
|
break; }
|
||||||
tsba = (cmdadh << 16) | cmdadl;
|
tsba = (cmdadh << 16) | cmdadl;
|
||||||
for (i = 0; (i < WCH_PLNT) && (i < (cmdlnt / 2)); i++) {
|
bc = ((WCH_PLNT << 1) > cmdlnt)? cmdlnt: WCH_PLNT << 1;
|
||||||
if (Map_Addr (tsba, &pa) && ADDR_IS_MEM (pa))
|
t = Map_ReadW (tsba, bc, cpy_buf); /* fetch packet */
|
||||||
tswchp[i] = ReadW (pa);
|
tsba = tsba + (bc - t); /* inc tsba */
|
||||||
else {
|
if (t) { /* nxm? */
|
||||||
ts_endcmd (TSSR_NBA | TSSR_NXM | TC5, 0, 0);
|
ts_endcmd (TSSR_NBA | TSSR_NXM | TC5, 0, 0);
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
tsba = tsba + 2; }
|
for (i = 0; i < (bc / 2); i++) /* copy packet */
|
||||||
|
tswchp[i] = cpy_buf[i];
|
||||||
if ((wchlnt < ((MSG_PLNT - 1) * 2)) || (wchadh & 0177700) ||
|
if ((wchlnt < ((MSG_PLNT - 1) * 2)) || (wchadh & 0177700) ||
|
||||||
(wchadl & 1)) ts_endcmd (TSSR_NBA | TC3, 0, 0);
|
(wchadl & 1)) ts_endcmd (TSSR_NBA | TC3, 0, 0);
|
||||||
else {
|
else {
|
||||||
|
@ -859,8 +863,7 @@ return;
|
||||||
|
|
||||||
void ts_endcmd (int32 tc, int32 xs0, int32 msg)
|
void ts_endcmd (int32 tc, int32 xs0, int32 msg)
|
||||||
{
|
{
|
||||||
int32 i;
|
int32 i, t;
|
||||||
uint32 pa;
|
|
||||||
|
|
||||||
msgxs0 = ts_updxs0 (msgxs0 | xs0); /* update XS0 */
|
msgxs0 = ts_updxs0 (msgxs0 | xs0); /* update XS0 */
|
||||||
if (wchxopt & WCHX_HDS) msgxs4 = msgxs4 | XS4_HDS; /* update XS4 */
|
if (wchxopt & WCHX_HDS) msgxs4 = msgxs4 | XS4_HDS; /* update XS4 */
|
||||||
|
@ -868,14 +871,14 @@ if (msg && !(tssr & TSSR_NBA)) { /* send end pkt */
|
||||||
msghdr = msg;
|
msghdr = msg;
|
||||||
msglnt = wchlnt - 4; /* exclude hdr, bc */
|
msglnt = wchlnt - 4; /* exclude hdr, bc */
|
||||||
tsba = (wchadh << 16) | wchadl;
|
tsba = (wchadh << 16) | wchadl;
|
||||||
for (i = 0; (i < MSG_PLNT) && (i < (wchlnt / 2)); i++) {
|
for (i = 0; (i < MSG_PLNT) && (i < (wchlnt / 2)); i++)
|
||||||
if (Map_Addr (tsba, &pa) && ADDR_IS_MEM (pa))
|
cpy_buf[i] = (uint16) tsmsgp[i]; /* copy buffer */
|
||||||
WriteW (pa, tsmsgp[i]);
|
t = Map_WriteW (tsba, i << 1, cpy_buf); /* write to mem */
|
||||||
else {
|
tsba = tsba + ((i << 1) - t); /* incr tsba */
|
||||||
|
if (t) { /* nxm? */
|
||||||
tssr = tssr | TSSR_NXM;
|
tssr = tssr | TSSR_NXM;
|
||||||
tc = (tc & ~TSSR_TC) | TC4;
|
tc = (tc & ~TSSR_TC) | TC4; }
|
||||||
break; }
|
}
|
||||||
tsba = tsba + 2; } }
|
|
||||||
tssr = ts_updtssr (tssr | tc | TSSR_SSR | (tc? TSSR_SC: 0));
|
tssr = ts_updtssr (tssr | tc | TSSR_SSR | (tc? TSSR_SC: 0));
|
||||||
if (cmdhdr & CMD_IE) SET_INT (TS);
|
if (cmdhdr & CMD_IE) SET_INT (TS);
|
||||||
ts_ownm = 0; ts_ownc = 0;
|
ts_ownm = 0; ts_ownc = 0;
|
||||||
|
@ -902,7 +905,7 @@ for (i = 0; i < WCH_PLNT; i++) tswchp[i] = 0;
|
||||||
for (i = 0; i < MSG_PLNT; i++) tsmsgp[i] = 0;
|
for (i = 0; i < MSG_PLNT; i++) tsmsgp[i] = 0;
|
||||||
msgxs0 = ts_updxs0 (XS0_VCK);
|
msgxs0 = ts_updxs0 (XS0_VCK);
|
||||||
CLR_INT (TS);
|
CLR_INT (TS);
|
||||||
if (tsxb == NULL) tsxb = calloc (MT_MAXFR, sizeof (unsigned int8));
|
if (tsxb == NULL) tsxb = calloc (MT_MAXFR, sizeof (uint8));
|
||||||
if (tsxb == NULL) return SCPE_MEM;
|
if (tsxb == NULL) return SCPE_MEM;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -993,6 +996,7 @@ t_stat ts_boot (int32 unitno, DEVICE *dptr)
|
||||||
{
|
{
|
||||||
int32 i;
|
int32 i;
|
||||||
extern int32 saved_PC;
|
extern int32 saved_PC;
|
||||||
|
extern uint16 *M;
|
||||||
|
|
||||||
sim_tape_rewind (&ts_unit);
|
sim_tape_rewind (&ts_unit);
|
||||||
for (i = 0; i < BOOT_LEN; i++)
|
for (i = 0; i < BOOT_LEN; i++)
|
||||||
|
@ -1002,6 +1006,7 @@ M[BOOT_CSR1 >> 1] = (ts_dib.ba & DMASK) + 02;
|
||||||
saved_PC = BOOT_START;
|
saved_PC = BOOT_START;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
t_stat ts_boot (int32 unitno, DEVICE *dptr)
|
t_stat ts_boot (int32 unitno, DEVICE *dptr)
|
||||||
|
|
912
PDP11/pdp11_tu.c
Normal file
912
PDP11/pdp11_tu.c
Normal file
|
@ -0,0 +1,912 @@
|
||||||
|
/* pdp11_tu.c - PDP-11 TM02/TU16 TM03/TU45/TU77 Massbus magnetic tape controller
|
||||||
|
|
||||||
|
Copyright (c) 1993-2004, 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"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
tu TM02/TM03 magtape
|
||||||
|
|
||||||
|
10-Sep-04 RMS Cloned from pdp10_tu.c
|
||||||
|
|
||||||
|
Magnetic tapes are represented as a series of variable 8b records
|
||||||
|
of the form:
|
||||||
|
|
||||||
|
32b record length in bytes - exact number, sign = error
|
||||||
|
byte 0
|
||||||
|
byte 1
|
||||||
|
:
|
||||||
|
byte n-2
|
||||||
|
byte n-1
|
||||||
|
32b record length in bytes - exact number, sign = error
|
||||||
|
|
||||||
|
If the byte count is odd, the record is padded with an extra byte
|
||||||
|
of junk. File marks are represented by a single record length of 0.
|
||||||
|
End of tape is two consecutive end of file marks.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined (VM_PDP10)
|
||||||
|
#error "PDP-10 uses pdp10_tu.c!"
|
||||||
|
|
||||||
|
#elif defined (VM_PDP11)
|
||||||
|
#include "pdp11_defs.h"
|
||||||
|
#define DEV_DIS_INIT DEV_DIS
|
||||||
|
|
||||||
|
#elif defined (VM_VAX)
|
||||||
|
#include "vax_defs.h"
|
||||||
|
#define DEV_DIS_INIT 0
|
||||||
|
#if (!UNIBUS)
|
||||||
|
#error "Qbus not supported!"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#include "sim_tape.h"
|
||||||
|
|
||||||
|
#define TU_NUMFM 1 /* #formatters */
|
||||||
|
#define TU_NUMDR 8 /* #drives */
|
||||||
|
#define USTAT u3 /* unit status */
|
||||||
|
#define UDENS u4 /* unit density */
|
||||||
|
#define UD_UNK 0 /* unknown */
|
||||||
|
#define MT_MAXFR (1 << 16) /* max data buf */
|
||||||
|
#define DEV_V_TM03 (DEV_V_FFUF + 0) /* TM02/TM03 */
|
||||||
|
#define DEV_TM03 (1 << DEV_V_TM03)
|
||||||
|
#define UNIT_V_TYPE (MTUF_V_UF + 0)
|
||||||
|
#define UNIT_M_TYPE 03
|
||||||
|
#define UNIT_TYPE (UNIT_M_TYPE << UNIT_V_TYPE)
|
||||||
|
#define UNIT_TE16 (0 << UNIT_V_TYPE)
|
||||||
|
#define UNIT_TU45 (1 << UNIT_V_TYPE)
|
||||||
|
#define UNIT_TU77 (2 << UNIT_V_TYPE)
|
||||||
|
#define GET_TYPE(x) (((x) >> UNIT_V_TYPE) & UNIT_M_TYPE)
|
||||||
|
|
||||||
|
/* CS1 - offset 0 */
|
||||||
|
|
||||||
|
#define CS1_OF 0
|
||||||
|
#define CS1_GO CSR_GO /* go */
|
||||||
|
#define CS1_V_FNC 1 /* function pos */
|
||||||
|
#define CS1_M_FNC 037 /* function mask */
|
||||||
|
#define CS1_N_FNC (CS1_M_FNC + 1)
|
||||||
|
#define FNC_NOP 000 /* no operation */
|
||||||
|
#define FNC_UNLOAD 001 /* unload */
|
||||||
|
#define FNC_REWIND 003 /* rewind */
|
||||||
|
#define FNC_FCLR 004 /* formatter clear */
|
||||||
|
#define FNC_RIP 010 /* read in preset */
|
||||||
|
#define FNC_ERASE 012 /* erase tape */
|
||||||
|
#define FNC_WREOF 013 /* write tape mark */
|
||||||
|
#define FNC_SPACEF 014 /* space forward */
|
||||||
|
#define FNC_SPACER 015 /* space reverse */
|
||||||
|
#define FNC_XFER 024 /* >=? data xfr */
|
||||||
|
#define FNC_WCHKF 024 /* write check */
|
||||||
|
#define FNC_WCHKR 027 /* write check rev */
|
||||||
|
#define FNC_WRITE 030 /* write */
|
||||||
|
#define FNC_READF 034 /* read forward */
|
||||||
|
#define FNC_READR 037 /* read reverse */
|
||||||
|
#define CS1_RW 077
|
||||||
|
#define GET_FNC(x) (((x) >> CS1_V_FNC) & CS1_M_FNC)
|
||||||
|
|
||||||
|
/* TUFS - formatter status - offset 1
|
||||||
|
+ indicates kept in drive status
|
||||||
|
^ indicates calculated on the fly
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FS_OF 1
|
||||||
|
#define FS_SAT 0000001 /* slave attention */
|
||||||
|
#define FS_BOT 0000002 /* ^beginning of tape */
|
||||||
|
#define FS_TMK 0000004 /* end of file */
|
||||||
|
#define FS_ID 0000010 /* ID burst detected */
|
||||||
|
#define FS_SLOW 0000020 /* slowing down NI */
|
||||||
|
#define FS_PE 0000040 /* ^PE status */
|
||||||
|
#define FS_SSC 0000100 /* slave stat change */
|
||||||
|
#define FS_RDY 0000200 /* ^formatter ready */
|
||||||
|
#define FS_FPR 0000400 /* formatter present */
|
||||||
|
#define FS_EOT 0002000 /* +end of tape */
|
||||||
|
#define FS_WRL 0004000 /* ^write locked */
|
||||||
|
#define FS_MOL 0010000 /* ^medium online */
|
||||||
|
#define FS_PIP 0020000 /* +pos in progress */
|
||||||
|
#define FS_ERR 0040000 /* ^error */
|
||||||
|
#define FS_ATA 0100000 /* attention active */
|
||||||
|
#define FS_REW 0200000 /* +rewinding */
|
||||||
|
|
||||||
|
#define FS_DYN (FS_ERR | FS_PIP | FS_MOL | FS_WRL | FS_EOT | \
|
||||||
|
FS_RDY | FS_PE | FS_BOT)
|
||||||
|
|
||||||
|
/* TUER - error register - offset 2 */
|
||||||
|
|
||||||
|
#define ER_OF 2
|
||||||
|
#define ER_ILF 0000001 /* illegal func */
|
||||||
|
#define ER_ILR 0000002 /* illegal register */
|
||||||
|
#define ER_RMR 0000004 /* reg mod refused */
|
||||||
|
#define ER_MCP 0000010 /* Mbus cpar err NI */
|
||||||
|
#define ER_FER 0000020 /* format sel err */
|
||||||
|
#define ER_MDP 0000040 /* Mbus dpar err NI */
|
||||||
|
#define ER_VPE 0000100 /* vert parity err */
|
||||||
|
#define ER_CRC 0000200 /* CRC err NI */
|
||||||
|
#define ER_NSG 0000400 /* non std gap err NI */
|
||||||
|
#define ER_FCE 0001000 /* frame count err */
|
||||||
|
#define ER_ITM 0002000 /* inv tape mark NI */
|
||||||
|
#define ER_NXF 0004000 /* wlock or fnc err */
|
||||||
|
#define ER_DTE 0010000 /* time err NI */
|
||||||
|
#define ER_OPI 0020000 /* op incomplete */
|
||||||
|
#define ER_UNS 0040000 /* drive unsafe */
|
||||||
|
#define ER_DCK 0100000 /* data check NI */
|
||||||
|
|
||||||
|
/* TUMR - maintenance register - offset 03 */
|
||||||
|
|
||||||
|
#define MR_OF 3
|
||||||
|
#define MR_RW 0177637 /* read/write */
|
||||||
|
|
||||||
|
/* TUAS - attention summary - offset 4 */
|
||||||
|
|
||||||
|
#define AS_OF 4
|
||||||
|
#define AS_U0 0000001 /* unit 0 flag */
|
||||||
|
|
||||||
|
/* TUFC - offset 5 */
|
||||||
|
|
||||||
|
#define FC_OF 5
|
||||||
|
|
||||||
|
/* TUDT - drive type - offset 6 */
|
||||||
|
|
||||||
|
#define DT_OF 6
|
||||||
|
#define DT_NSA 0100000 /* not sect addr */
|
||||||
|
#define DT_TAPE 0040000 /* tape */
|
||||||
|
#define DT_PRES 0002000 /* slave present */
|
||||||
|
#define DT_TM03 0000040 /* TM03 formatter */
|
||||||
|
#define DT_OFF 0000010 /* drive off */
|
||||||
|
#define DT_TU16 0000011 /* TE16 */
|
||||||
|
#define DT_TU45 0000012 /* TU45 */
|
||||||
|
#define DT_TU77 0000014 /* TU77 */
|
||||||
|
|
||||||
|
/* TUCC - check character, read only - offset 7 */
|
||||||
|
|
||||||
|
#define CC_OF 7
|
||||||
|
#define CC_MBZ 0177000 /* must be zero */
|
||||||
|
|
||||||
|
/* TUSN - serial number - offset 8 */
|
||||||
|
|
||||||
|
#define SN_OF 8
|
||||||
|
|
||||||
|
/* TUTC - tape control register - offset 9 */
|
||||||
|
|
||||||
|
#define TC_OF 9
|
||||||
|
#define TC_V_UNIT 0 /* unit select */
|
||||||
|
#define TC_M_UNIT 07
|
||||||
|
#define TC_V_EVN 0000010 /* even parity */
|
||||||
|
#define TC_V_FMT 4 /* format select */
|
||||||
|
#define TC_M_FMT 017
|
||||||
|
#define TC_STD 014 /* standard */
|
||||||
|
#define TC_CDUMP 015 /* core dump */
|
||||||
|
#define TC_V_DEN 8 /* density select */
|
||||||
|
#define TC_M_DEN 07
|
||||||
|
#define TC_800 3 /* 800 bpi */
|
||||||
|
#define TC_1600 4 /* 1600 bpi */
|
||||||
|
#define TC_AER 0010000 /* abort on error */
|
||||||
|
#define TC_SAC 0020000 /* slave addr change */
|
||||||
|
#define TC_FCS 0040000 /* frame count status */
|
||||||
|
#define TC_ACC 0100000 /* accelerating NI */
|
||||||
|
#define TC_RW 0013777
|
||||||
|
#define TC_MBZ 0004000
|
||||||
|
#define TC_RIP ((TC_800 << TC_V_DEN) | (TC_STD << TC_V_FMT))
|
||||||
|
#define GET_DEN(x) (((x) >> TC_V_DEN) & TC_M_DEN)
|
||||||
|
#define GET_FMT(x) (((x) >> TC_V_FMT) & TC_M_FMT)
|
||||||
|
#define GET_DRV(x) (((x) >> TC_V_UNIT) & TC_M_UNIT)
|
||||||
|
|
||||||
|
int32 tucs1 = 0; /* control/status 1 */
|
||||||
|
int32 tufc = 0; /* frame count */
|
||||||
|
int32 tufs = 0; /* formatter status */
|
||||||
|
int32 tuer = 0; /* error status */
|
||||||
|
int32 tucc = 0; /* check character */
|
||||||
|
int32 tumr = 0; /* maint register */
|
||||||
|
int32 tutc = 0; /* tape control */
|
||||||
|
int32 tu_time = 10; /* record latency */
|
||||||
|
int32 tu_stopioe = 1; /* stop on error */
|
||||||
|
static uint8 *xbuf = NULL; /* xfer buffer */
|
||||||
|
static uint16 *wbuf = NULL;
|
||||||
|
static int32 den_test[8] = { /* valid densities */
|
||||||
|
1, 1, 1, 1, 1, 0, 0, 0 }; /* 0-3 = 800, 4 = 1600 */
|
||||||
|
static int32 fmt_test[16] = { /* fmt valid */
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0 };
|
||||||
|
static int32 dt_map[3] = { DT_TU16, DT_TU45, DT_TU77 };
|
||||||
|
static char *tu_fname[CS1_N_FNC] = {
|
||||||
|
"NOP", "UNLD", "2", "REW", "FCLR", "5", "6", "7",
|
||||||
|
"RIP", "11", "ERASE", "WREOF", "SPCF", "SPCR", "16", "17",
|
||||||
|
"20", "21", "22", "23", "WRCHKF", "25", "26", "WRCHKR",
|
||||||
|
"WRITE", "31", "32", "33", "READF", "35", "36" "READR" };
|
||||||
|
|
||||||
|
extern int32 sim_switches;
|
||||||
|
extern FILE *sim_deb;
|
||||||
|
|
||||||
|
t_stat tu_mbrd (int32 *data, int32 PA, int32 fmtr);
|
||||||
|
t_stat tu_mbwr (int32 data, int32 PA, int32 fmtr);
|
||||||
|
t_stat tu_svc (UNIT *uptr);
|
||||||
|
t_stat tu_reset (DEVICE *dptr);
|
||||||
|
t_stat tu_attach (UNIT *uptr, char *cptr);
|
||||||
|
t_stat tu_detach (UNIT *uptr);
|
||||||
|
t_stat tu_boot (int32 unitno, DEVICE *dptr);
|
||||||
|
t_stat tu_set_fmtr (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat tu_show_fmtr (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
|
t_stat tu_go (int32 drv);
|
||||||
|
int32 tu_abort (void);
|
||||||
|
void tu_set_er (int32 flg);
|
||||||
|
void tu_clr_as (int32 mask);
|
||||||
|
void tu_update_fs (int32 flg, int32 drv);
|
||||||
|
t_stat tu_map_err (int32 drv, t_stat st);
|
||||||
|
|
||||||
|
/* TU data structures
|
||||||
|
|
||||||
|
tu_dev TU device descriptor
|
||||||
|
tu_unit TU unit list
|
||||||
|
tu_reg TU register list
|
||||||
|
tu_mod TU modifier list
|
||||||
|
*/
|
||||||
|
|
||||||
|
DIB tu_dib = { MBA_TU, 0, &tu_mbrd, &tu_mbwr,0, 0, 0, { &tu_abort } };
|
||||||
|
|
||||||
|
UNIT tu_unit[] = {
|
||||||
|
{ UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||||
|
{ UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||||
|
{ UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||||
|
{ UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||||
|
{ UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||||
|
{ UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||||
|
{ UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
|
||||||
|
{ UDATA (&tu_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) } };
|
||||||
|
|
||||||
|
REG tu_reg[] = {
|
||||||
|
{ GRDATA (CS1, tucs1, DEV_RDX, 6, 0) },
|
||||||
|
{ GRDATA (FC, tufc, DEV_RDX, 16, 0) },
|
||||||
|
{ GRDATA (FS, tufs, DEV_RDX, 16, 0) },
|
||||||
|
{ GRDATA (ER, tuer, DEV_RDX, 16, 0) },
|
||||||
|
{ GRDATA (CC, tucc, DEV_RDX, 16, 0) },
|
||||||
|
{ GRDATA (MR, tumr, DEV_RDX, 16, 0) },
|
||||||
|
{ GRDATA (TC, tutc, DEV_RDX, 16, 0) },
|
||||||
|
{ FLDATA (STOP_IOE, tu_stopioe, 0) },
|
||||||
|
{ DRDATA (TIME, tu_time, 24), PV_LEFT },
|
||||||
|
{ URDATA (UST, tu_unit[0].USTAT, DEV_RDX, 17, 0, TU_NUMDR, 0) },
|
||||||
|
{ URDATA (POS, tu_unit[0].pos, 10, T_ADDR_W, 0,
|
||||||
|
TU_NUMDR, PV_LEFT | REG_RO) },
|
||||||
|
{ NULL } };
|
||||||
|
|
||||||
|
MTAB tu_mod[] = {
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 0, "MASSBUS", "MASSBUS", NULL, &mba_show_num },
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 0, "FORMATTER", "TM02",
|
||||||
|
&tu_set_fmtr, &tu_show_fmtr },
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 1, NULL, "TM03",
|
||||||
|
&tu_set_fmtr, NULL },
|
||||||
|
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||||
|
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
|
||||||
|
{ UNIT_TYPE, UNIT_TE16, "TE16", "TE16", NULL },
|
||||||
|
{ UNIT_TYPE, UNIT_TU45, "TU45", "TU45", NULL },
|
||||||
|
{ UNIT_TYPE, UNIT_TU77, "TU77", "TU77", NULL },
|
||||||
|
{ MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
|
||||||
|
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
|
||||||
|
{ 0 } };
|
||||||
|
|
||||||
|
DEVICE tu_dev = {
|
||||||
|
"TU", tu_unit, tu_reg, tu_mod,
|
||||||
|
TU_NUMDR, 10, 31, 1, DEV_RDX, 8,
|
||||||
|
NULL, NULL, &tu_reset,
|
||||||
|
&tu_boot, &tu_attach, &tu_detach,
|
||||||
|
&tu_dib, DEV_MBUS | DEV_UBUS | DEV_QBUS | DEV_DEBUG | DEV_DISABLE | DEV_DIS_INIT };
|
||||||
|
|
||||||
|
/* Massbus register read */
|
||||||
|
|
||||||
|
t_stat tu_mbrd (int32 *data, int32 ofs, int32 fmtr)
|
||||||
|
{
|
||||||
|
int32 drv;
|
||||||
|
|
||||||
|
if (fmtr != 0) { /* only one fmtr */
|
||||||
|
*data = 0;
|
||||||
|
return MBE_NXD;
|
||||||
|
}
|
||||||
|
drv = GET_DRV (tutc); /* get current unit */
|
||||||
|
tu_update_fs (0, drv); /* update status */
|
||||||
|
|
||||||
|
switch (ofs) { /* decode offset */
|
||||||
|
case CS1_OF: /* MTCS1 */
|
||||||
|
*data = tucs1 & CS1_RW;
|
||||||
|
break;
|
||||||
|
case FC_OF: /* MTFC */
|
||||||
|
*data = tufc;
|
||||||
|
break;
|
||||||
|
case FS_OF: /* MTFS */
|
||||||
|
*data = tufs & 0177777; /* mask off rewind */
|
||||||
|
break;
|
||||||
|
case ER_OF: /* MTER */
|
||||||
|
*data = tuer;
|
||||||
|
break;
|
||||||
|
case AS_OF: /* MTAS */
|
||||||
|
*data = (tufs & FS_ATA)? AS_U0: 0;
|
||||||
|
break;
|
||||||
|
case CC_OF: /* MTCC */
|
||||||
|
*data = tucc = tucc & ~CC_MBZ;
|
||||||
|
break;
|
||||||
|
case MR_OF: /* MTMR */
|
||||||
|
*data = tumr;
|
||||||
|
break;
|
||||||
|
case DT_OF: /* MTDT */
|
||||||
|
*data = DT_NSA | DT_TAPE | /* fmtr flags */
|
||||||
|
((tu_dev.flags & DEV_TM03)? DT_TM03: 0);
|
||||||
|
if (tu_unit[drv].flags & UNIT_DIS) *data |= DT_OFF;
|
||||||
|
else *data |= DT_PRES | dt_map[GET_TYPE (tu_unit[drv].flags)];
|
||||||
|
break;
|
||||||
|
case SN_OF: /* MTSN */
|
||||||
|
*data = (tu_unit[drv].flags & UNIT_DIS)? 0: 040 | (drv + 1);
|
||||||
|
break;
|
||||||
|
case TC_OF: /* MTTC */
|
||||||
|
*data = tutc = tutc & ~TC_MBZ;
|
||||||
|
break;
|
||||||
|
default: /* all others */
|
||||||
|
return MBE_NXR; }
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Massbus register write */
|
||||||
|
|
||||||
|
t_stat tu_mbwr (int32 data, int32 ofs, int32 fmtr)
|
||||||
|
{
|
||||||
|
int32 drv;
|
||||||
|
|
||||||
|
if (fmtr != 0) return MBE_NXD; /* only one fmtr */
|
||||||
|
drv = GET_DRV (tutc); /* get current unit */
|
||||||
|
|
||||||
|
switch (ofs) { /* decode PA<4:1> */
|
||||||
|
case CS1_OF: /* MTCS1 */
|
||||||
|
if (tucs1 & CS1_GO) tu_set_er (ER_RMR);
|
||||||
|
else {
|
||||||
|
tucs1 = data & CS1_RW;
|
||||||
|
if (tucs1 & CS1_GO) return tu_go (drv);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FC_OF: /* MTFC */
|
||||||
|
if (tucs1 & CS1_GO) tu_set_er (ER_RMR);
|
||||||
|
else {
|
||||||
|
tufc = data;
|
||||||
|
tutc = tutc | TC_FCS; /* set fc flag */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AS_OF: /* MTAS */
|
||||||
|
tu_clr_as (data);
|
||||||
|
break;
|
||||||
|
case MR_OF: /* MTMR */
|
||||||
|
tumr = (tumr & ~MR_RW) | (data & MR_RW);
|
||||||
|
break;
|
||||||
|
case TC_OF: /* MTTC */
|
||||||
|
if (tucs1 & CS1_GO) tu_set_er (ER_RMR);
|
||||||
|
else {
|
||||||
|
tutc = (tutc & ~TC_RW) | (data & TC_RW) | TC_SAC;
|
||||||
|
drv = GET_DRV (tutc); }
|
||||||
|
break;
|
||||||
|
case FS_OF: /* MTFS */
|
||||||
|
case ER_OF: /* MTER */
|
||||||
|
case CC_OF: /* MTCC */
|
||||||
|
case DT_OF: /* MTDT */
|
||||||
|
case SN_OF: /* MTSN */
|
||||||
|
if (tucs1 & CS1_GO) tu_set_er (ER_RMR);
|
||||||
|
break; /* read only */
|
||||||
|
default: /* all others */
|
||||||
|
return MBE_NXR; } /* end switch */
|
||||||
|
tu_update_fs (0, drv);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* New magtape command */
|
||||||
|
|
||||||
|
t_stat tu_go (int32 drv)
|
||||||
|
{
|
||||||
|
int32 fnc, den, space_test = FS_BOT;
|
||||||
|
UNIT *uptr;
|
||||||
|
|
||||||
|
fnc = GET_FNC (tucs1); /* get function */
|
||||||
|
den = GET_DEN (tutc); /* get density */
|
||||||
|
uptr = tu_dev.units + drv; /* get unit */
|
||||||
|
if (DEBUG_PRS (tu_dev)) fprintf (sim_deb,
|
||||||
|
">>TU%d STRT: fnc=%s, fc=%06o, fs=%06o, er=%06o, pos=%d\n",
|
||||||
|
drv, tu_fname[fnc], tufc, tufs, tuer, uptr->pos);
|
||||||
|
|
||||||
|
if ((fnc != FNC_FCLR) && /* not clear & err */
|
||||||
|
((tufs & FS_ERR) || sim_is_active (uptr))) { /* or in motion? */
|
||||||
|
tu_set_er (ER_ILF); /* set err */
|
||||||
|
tucs1 = tucs1 & ~CS1_GO; /* clear go */
|
||||||
|
tu_update_fs (FS_ATA, drv); /* set attn */
|
||||||
|
return MBE_GOE; }
|
||||||
|
tu_clr_as (AS_U0); /* clear ATA */
|
||||||
|
tutc = tutc & ~TC_SAC; /* clear addr change */
|
||||||
|
|
||||||
|
switch (fnc) { /* case on function */
|
||||||
|
case FNC_FCLR: /* drive clear */
|
||||||
|
tuer = 0; /* clear errors */
|
||||||
|
tutc = tutc & ~TC_FCS; /* clear fc status */
|
||||||
|
tufs = tufs & ~(FS_SAT | FS_SSC | FS_ID | FS_ERR);
|
||||||
|
sim_cancel (uptr); /* reset drive */
|
||||||
|
uptr->USTAT = 0;
|
||||||
|
case FNC_NOP:
|
||||||
|
tucs1 = tucs1 & ~CS1_GO; /* no operation */
|
||||||
|
return SCPE_OK;
|
||||||
|
|
||||||
|
case FNC_RIP: /* read-in preset */
|
||||||
|
tutc = TC_RIP; /* set tutc */
|
||||||
|
sim_tape_rewind (&tu_unit[0]); /* rewind unit 0 */
|
||||||
|
tu_unit[0].USTAT = 0;
|
||||||
|
tucs1 = tucs1 & ~CS1_GO;
|
||||||
|
tufs = tufs & ~FS_TMK;
|
||||||
|
return SCPE_OK;
|
||||||
|
|
||||||
|
case FNC_UNLOAD: /* unload */
|
||||||
|
if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */
|
||||||
|
tu_set_er (ER_UNS);
|
||||||
|
break; }
|
||||||
|
detach_unit (uptr);
|
||||||
|
uptr->USTAT = FS_REW;
|
||||||
|
sim_activate (uptr, tu_time);
|
||||||
|
tucs1 = tucs1 & ~CS1_GO;
|
||||||
|
tufs = tufs & ~FS_TMK;
|
||||||
|
return SCPE_OK;
|
||||||
|
|
||||||
|
case FNC_REWIND:
|
||||||
|
if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */
|
||||||
|
tu_set_er (ER_UNS);
|
||||||
|
break; }
|
||||||
|
uptr->USTAT = FS_PIP | FS_REW;
|
||||||
|
sim_activate (uptr, tu_time);
|
||||||
|
tucs1 = tucs1 & ~CS1_GO;
|
||||||
|
tufs = tufs & ~FS_TMK;
|
||||||
|
return SCPE_OK;
|
||||||
|
|
||||||
|
case FNC_SPACEF:
|
||||||
|
space_test = FS_EOT;
|
||||||
|
case FNC_SPACER:
|
||||||
|
if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */
|
||||||
|
tu_set_er (ER_UNS);
|
||||||
|
break; }
|
||||||
|
if ((tufs & space_test) || ((tutc & TC_FCS) == 0)) {
|
||||||
|
tu_set_er (ER_NXF);
|
||||||
|
break; }
|
||||||
|
uptr->USTAT = FS_PIP;
|
||||||
|
goto GO_XFER;
|
||||||
|
|
||||||
|
case FNC_WCHKR: /* wchk = read */
|
||||||
|
case FNC_READR: /* read rev */
|
||||||
|
if (tufs & FS_BOT) { /* beginning of tape? */
|
||||||
|
tu_set_er (ER_NXF);
|
||||||
|
break; }
|
||||||
|
goto DATA_XFER;
|
||||||
|
|
||||||
|
case FNC_WRITE: /* write */
|
||||||
|
if (((tutc & TC_FCS) == 0) || /* frame cnt = 0? */
|
||||||
|
((den == TC_800) && (tufc > 0777765))) { /* NRZI, fc < 13? */
|
||||||
|
tu_set_er (ER_NXF);
|
||||||
|
break; }
|
||||||
|
case FNC_WREOF: /* write tape mark */
|
||||||
|
case FNC_ERASE: /* erase */
|
||||||
|
if (sim_tape_wrp (uptr)) { /* write locked? */
|
||||||
|
tu_set_er (ER_NXF);
|
||||||
|
break; }
|
||||||
|
case FNC_WCHKF: /* wchk = read */
|
||||||
|
case FNC_READF: /* read */
|
||||||
|
DATA_XFER:
|
||||||
|
if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */
|
||||||
|
tu_set_er (ER_UNS);
|
||||||
|
break; }
|
||||||
|
if (fmt_test[GET_FMT (tutc)] == 0) { /* invalid format? */
|
||||||
|
tu_set_er (ER_FER);
|
||||||
|
break; }
|
||||||
|
if (uptr->UDENS == UD_UNK) uptr->UDENS = den; /* set dens */
|
||||||
|
uptr->USTAT = 0;
|
||||||
|
GO_XFER:
|
||||||
|
tufs = tufs & ~(FS_TMK | FS_ID); /* clear eof, id */
|
||||||
|
sim_activate (uptr, tu_time);
|
||||||
|
return SCPE_OK;
|
||||||
|
|
||||||
|
default: /* all others */
|
||||||
|
tu_set_er (ER_ILF); /* not supported */
|
||||||
|
break; } /* end case function */
|
||||||
|
tucs1 = tucs1 & ~CS1_GO; /* clear go */
|
||||||
|
tu_update_fs (FS_ATA, drv); /* set attn */
|
||||||
|
return MBE_GOE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Abort transfer */
|
||||||
|
|
||||||
|
t_stat tu_abort (void)
|
||||||
|
{
|
||||||
|
return tu_reset (&tu_dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unit service
|
||||||
|
|
||||||
|
Complete movement or data transfer command
|
||||||
|
Unit must exist - can't remove an active unit
|
||||||
|
Unit must be attached - detach cancels in progress operations
|
||||||
|
*/
|
||||||
|
|
||||||
|
t_stat tu_svc (UNIT *uptr)
|
||||||
|
{
|
||||||
|
int32 fnc, fmt, j, xbc;
|
||||||
|
int32 fc, drv;
|
||||||
|
t_mtrlnt i, tbc;
|
||||||
|
t_stat st, r = SCPE_OK;
|
||||||
|
|
||||||
|
drv = uptr - tu_dev.units; /* get drive # */
|
||||||
|
if (uptr->USTAT & FS_REW) { /* rewind or unload? */
|
||||||
|
sim_tape_rewind (uptr); /* rewind tape */
|
||||||
|
uptr->USTAT = 0; /* clear status */
|
||||||
|
tu_update_fs (FS_ATA | FS_SSC, drv);
|
||||||
|
return SCPE_OK; }
|
||||||
|
|
||||||
|
fnc = GET_FNC (tucs1); /* get command */
|
||||||
|
fmt = GET_FMT (tutc); /* get format */
|
||||||
|
fc = 0200000 - tufc; /* get frame count */
|
||||||
|
uptr->USTAT = 0; /* clear status */
|
||||||
|
|
||||||
|
if ((uptr->flags & UNIT_ATT) == 0) {
|
||||||
|
tu_set_er (ER_UNS); /* set formatter error */
|
||||||
|
if (fnc >= FNC_XFER) mba_set_don (tu_dib.ba);
|
||||||
|
tu_update_fs (FS_ATA, drv);
|
||||||
|
return (tu_stopioe? SCPE_UNATT: SCPE_OK);
|
||||||
|
}
|
||||||
|
switch (fnc) { /* case on function */
|
||||||
|
|
||||||
|
/* Non-data transfer commands - set ATA when done */
|
||||||
|
|
||||||
|
case FNC_SPACEF: /* space forward */
|
||||||
|
do {
|
||||||
|
tufc = (tufc + 1) & 0177777; /* incr fc */
|
||||||
|
if (st = sim_tape_sprecf (uptr, &tbc)) { /* space rec fwd, err? */
|
||||||
|
r = tu_map_err (drv, st); /* map error */
|
||||||
|
break; }
|
||||||
|
}
|
||||||
|
while (tufc != 0);
|
||||||
|
if (tufc) tu_set_er (ER_FCE);
|
||||||
|
else tutc = tutc & ~TC_FCS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FNC_SPACER: /* space reverse */
|
||||||
|
do {
|
||||||
|
tufc = (tufc + 1) & 0177777; /* incr wc */
|
||||||
|
if (st = sim_tape_sprecr (uptr, &tbc)) { /* space rec rev, err? */
|
||||||
|
r = tu_map_err (drv, st); /* map error */
|
||||||
|
break; }
|
||||||
|
}
|
||||||
|
while (tufc != 0);
|
||||||
|
if (tufc) tu_set_er (ER_FCE);
|
||||||
|
else tutc = tutc & ~TC_FCS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FNC_WREOF: /* write end of file */
|
||||||
|
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
|
||||||
|
r = tu_map_err (drv, st); /* map error */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FNC_ERASE:
|
||||||
|
if (sim_tape_wrp (uptr)) /* write protected? */
|
||||||
|
r = tu_map_err (drv, MTSE_WRP); /* map error */
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Unit service - data transfer commands */
|
||||||
|
|
||||||
|
case FNC_READF: /* read */
|
||||||
|
case FNC_WCHKF: /* wcheck = read */
|
||||||
|
tufc = 0; /* clear frame count */
|
||||||
|
if ((uptr->UDENS == TC_1600) && sim_tape_bot (uptr))
|
||||||
|
tufs = tufs | FS_ID; /* PE BOT? ID burst */
|
||||||
|
if (st = sim_tape_rdrecf (uptr, xbuf, &tbc, MT_MAXFR)) { /* read fwd */
|
||||||
|
r = tu_map_err (drv, st); /* map error */
|
||||||
|
break; } /* done */
|
||||||
|
for (i = tbc; i < tbc + 4; i++) xbuf[i] = 0; /* pad with 0's */
|
||||||
|
if (fmt == TC_CDUMP) { /* core dump? */
|
||||||
|
for (i = j = 0; i < tbc; i = i + 4) {
|
||||||
|
wbuf[j++] = ((uint16) xbuf[i] & 0xF) |
|
||||||
|
(((uint16) (xbuf[i + 1] & 0xF)) << 4) |
|
||||||
|
(((uint16) (xbuf[i + 2] & 0xF)) << 8) |
|
||||||
|
(((uint16) (xbuf[i + 3] & 0xf)) << 12);
|
||||||
|
}
|
||||||
|
xbc = (tbc + 1) >> 1;
|
||||||
|
}
|
||||||
|
else { /* standard */
|
||||||
|
for (i = j = 0; i < tbc; i = i + 2) {
|
||||||
|
wbuf[j++] = ((uint16) xbuf[i]) |
|
||||||
|
(((uint16) xbuf[i + 1]) << 8);
|
||||||
|
}
|
||||||
|
xbc = tbc;
|
||||||
|
}
|
||||||
|
if (mba_get_bc (tu_dib.ba) > xbc) /* record short? */
|
||||||
|
tu_set_er (ER_FCE); /* set FCE, ATN */
|
||||||
|
if (fnc == FNC_WCHKF) mba_chbufW (tu_dib.ba, xbc, wbuf);
|
||||||
|
else mba_wrbufW (tu_dib.ba, xbc, wbuf);
|
||||||
|
tufc = tbc & 0177777;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FNC_WRITE: /* write */
|
||||||
|
xbc = mba_rdbufW (tu_dib.ba, fc, wbuf); /* read buffer */
|
||||||
|
if (xbc == 0) break; /* anything?? */
|
||||||
|
if (fmt == TC_CDUMP) { /* core dump? */
|
||||||
|
for (i = j = 0; j < xbc; j = j + 1) {
|
||||||
|
xbuf[i++] = wbuf[j] & 0xF;
|
||||||
|
xbuf[i++] = (wbuf[j] >> 4) & 0xF;
|
||||||
|
xbuf[i++] = (wbuf[j] >> 8) & 0xF;
|
||||||
|
xbuf[i++] = (wbuf[j] >> 12) & 0xF;
|
||||||
|
}
|
||||||
|
tbc = (xbc + 1) >> 1;
|
||||||
|
}
|
||||||
|
else { /* standard */
|
||||||
|
for (i = j = 0; j < xbc; j = j + 1) {
|
||||||
|
xbuf[i++] = wbuf[j] & 0377;
|
||||||
|
xbuf[i++] = (wbuf[j] >> 8) & 0377; }
|
||||||
|
tbc = xbc;
|
||||||
|
}
|
||||||
|
if (st = sim_tape_wrrecf (uptr, xbuf, tbc)) /* write rec, err? */
|
||||||
|
r = tu_map_err (drv, st); /* map error */
|
||||||
|
else {
|
||||||
|
tufc = (tufc + tbc) & 0177777;
|
||||||
|
if (tufc == 0) tutc = tutc & ~TC_FCS;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FNC_READR: /* read reverse */
|
||||||
|
case FNC_WCHKR: /* wcheck = read */
|
||||||
|
tufc = 0; /* clear frame count */
|
||||||
|
if (st = sim_tape_rdrecr (uptr, xbuf + 4, &tbc, MT_MAXFR)) { /* read rev */
|
||||||
|
r = tu_map_err (drv, st); /* map error */
|
||||||
|
break; } /* done */
|
||||||
|
for (i = 0; i < 4; i++) xbuf[i] = 0; /* pad with 0's */
|
||||||
|
if (fmt == TC_CDUMP) { /* core dump? */
|
||||||
|
for (i = tbc + 3, j = 0; i > 3; i = i - 4) {
|
||||||
|
wbuf[j++] = ((uint16) xbuf[i] & 0xF) |
|
||||||
|
(((uint16) (xbuf[i - 1] & 0xF)) << 4) |
|
||||||
|
(((uint16) (xbuf[i - 2] & 0xF)) << 8) |
|
||||||
|
(((uint16) (xbuf[i - 3] & 0xf)) << 12);
|
||||||
|
}
|
||||||
|
xbc = (tbc + 1) >> 1;
|
||||||
|
}
|
||||||
|
else { /* standard */
|
||||||
|
for (i = tbc + 3, j = 0; i > 3; i = i - 2) {
|
||||||
|
wbuf[j++] = ((uint16) xbuf[i]) |
|
||||||
|
(((uint16) xbuf[i - 1]) << 8);
|
||||||
|
}
|
||||||
|
xbc = tbc;
|
||||||
|
}
|
||||||
|
if (mba_get_bc (tu_dib.ba) > xbc) /* record short? */
|
||||||
|
tu_set_er (ER_FCE); /* set FCE, ATN */
|
||||||
|
if (fnc == FNC_WCHKR) mba_chbufW (tu_dib.ba, xbc, wbuf);
|
||||||
|
else mba_wrbufW (tu_dib.ba, xbc, wbuf);
|
||||||
|
tufc = tbc & 0177777;
|
||||||
|
break;
|
||||||
|
} /* end case */
|
||||||
|
|
||||||
|
tucs1 = tucs1 & ~CS1_GO; /* clear go */
|
||||||
|
if (fnc >= FNC_XFER) { /* data xfer? */
|
||||||
|
mba_set_don (tu_dib.ba); /* set done */
|
||||||
|
tu_update_fs (0, drv); } /* update fs */
|
||||||
|
else tu_update_fs (FS_ATA, drv); /* no, set attn */
|
||||||
|
if (DEBUG_PRS (tu_dev)) fprintf (sim_deb,
|
||||||
|
">>TU%d DONE: fnc=%s, fc=%06o, fs=%06o, er=%06o, pos=%d\n",
|
||||||
|
drv, tu_fname[fnc], tufc, tufs, tuer, uptr->pos);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set formatter error */
|
||||||
|
|
||||||
|
void tu_set_er (int32 flg)
|
||||||
|
{
|
||||||
|
tuer = tuer | flg;
|
||||||
|
tufs = tufs | FS_ATA;
|
||||||
|
mba_upd_ata (tu_dib.ba, 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear attention */
|
||||||
|
|
||||||
|
void tu_clr_as (int32 mask)
|
||||||
|
{
|
||||||
|
if (mask & AS_U0) tufs = tufs & ~FS_ATA;
|
||||||
|
mba_upd_ata (tu_dib.ba, tufs & FS_ATA);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Formatter update status */
|
||||||
|
|
||||||
|
void tu_update_fs (int32 flg, int32 drv)
|
||||||
|
{
|
||||||
|
int32 act = sim_is_active (&tu_unit[drv]);
|
||||||
|
|
||||||
|
tufs = (tufs & ~FS_DYN) | FS_FPR | flg;
|
||||||
|
if (tu_unit[drv].flags & UNIT_ATT) {
|
||||||
|
tufs = tufs | FS_MOL | tu_unit[drv].USTAT;
|
||||||
|
if (tu_unit[drv].UDENS == TC_1600) tufs = tufs | FS_PE;
|
||||||
|
if (sim_tape_wrp (&tu_unit[drv])) tufs = tufs | FS_WRL;
|
||||||
|
if (sim_tape_bot (&tu_unit[drv]) && !act) tufs = tufs | FS_BOT; }
|
||||||
|
if (tuer) tufs = tufs | FS_ERR;
|
||||||
|
if (tufs && !act) tufs = tufs | FS_RDY;
|
||||||
|
if (flg & FS_ATA) mba_upd_ata (tu_dib.ba, 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Map tape error status */
|
||||||
|
|
||||||
|
t_stat tu_map_err (int32 drv, t_stat st)
|
||||||
|
{
|
||||||
|
switch (st) {
|
||||||
|
case MTSE_FMT: /* illegal fmt */
|
||||||
|
case MTSE_UNATT: /* not attached */
|
||||||
|
tu_set_er (ER_NXF); /* can't execute */
|
||||||
|
break;
|
||||||
|
case MTSE_TMK: /* end of file */
|
||||||
|
tufs = tufs | FS_TMK;
|
||||||
|
tu_set_er (ER_FCE); /* also sets FCE */
|
||||||
|
break;
|
||||||
|
case MTSE_IOERR: /* IO error */
|
||||||
|
tu_set_er (ER_VPE); /* flag error */
|
||||||
|
mba_set_exc (tu_dib.ba); /* set exception */
|
||||||
|
return (tu_stopioe? SCPE_IOERR: SCPE_OK);
|
||||||
|
case MTSE_INVRL: /* invalid rec lnt */
|
||||||
|
tu_set_er (ER_VPE); /* flag error */
|
||||||
|
return SCPE_MTRLNT;
|
||||||
|
case MTSE_RECE: /* record in error */
|
||||||
|
tu_set_er (ER_CRC); /* set crc err */
|
||||||
|
break;
|
||||||
|
case MTSE_EOM: /* end of medium */
|
||||||
|
tu_set_er (ER_OPI); /* incomplete */
|
||||||
|
break;
|
||||||
|
case MTSE_BOT: /* reverse into BOT */
|
||||||
|
return SCPE_OK;
|
||||||
|
case MTSE_WRP: /* write protect */
|
||||||
|
tu_set_er (ER_NXF); /* can't execute */
|
||||||
|
break;
|
||||||
|
default: /* unknown error */
|
||||||
|
return SCPE_IERR; }
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset routine */
|
||||||
|
|
||||||
|
t_stat tu_reset (DEVICE *dptr)
|
||||||
|
{
|
||||||
|
int32 u;
|
||||||
|
UNIT *uptr;
|
||||||
|
|
||||||
|
tucs1 = 0;
|
||||||
|
tufc = 0;
|
||||||
|
tuer = 0;
|
||||||
|
tufs = FS_FPR | FS_RDY;
|
||||||
|
if (sim_switches & SWMASK ('P')) tutc = 0; /* powerup? clr TC */
|
||||||
|
else tutc = tutc & ~TC_FCS; /* no, clr <fcs> */
|
||||||
|
for (u = 0; u < TU_NUMDR; u++) { /* loop thru units */
|
||||||
|
uptr = tu_dev.units + u;
|
||||||
|
sim_tape_reset (uptr); /* clear pos flag */
|
||||||
|
sim_cancel (uptr); /* cancel activity */
|
||||||
|
uptr->USTAT = 0; }
|
||||||
|
if (xbuf == NULL) xbuf = calloc (MT_MAXFR + 4, sizeof (uint8));
|
||||||
|
if (xbuf == NULL) return SCPE_MEM;
|
||||||
|
if (wbuf == NULL) wbuf = calloc ((MT_MAXFR + 4) >> 1, sizeof (uint16));
|
||||||
|
if (wbuf == NULL) return SCPE_MEM;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attach routine */
|
||||||
|
|
||||||
|
t_stat tu_attach (UNIT *uptr, char *cptr)
|
||||||
|
{
|
||||||
|
int32 drv = uptr - tu_dev.units, flg;
|
||||||
|
t_stat r;
|
||||||
|
|
||||||
|
r = sim_tape_attach (uptr, cptr);
|
||||||
|
if (r != SCPE_OK) return r;
|
||||||
|
uptr->USTAT = 0; /* clear unit status */
|
||||||
|
uptr->UDENS = UD_UNK; /* unknown density */
|
||||||
|
flg = FS_ATA | FS_SSC; /* set attention */
|
||||||
|
if (GET_DRV (tutc) == drv) flg = flg | FS_SAT; /* sel drv? set SAT */
|
||||||
|
tu_update_fs (flg, drv); /* update status */
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Detach routine */
|
||||||
|
|
||||||
|
t_stat tu_detach (UNIT* uptr)
|
||||||
|
{
|
||||||
|
int32 drv = uptr - tu_dev.units;
|
||||||
|
|
||||||
|
uptr->USTAT = 0; /* clear status flags */
|
||||||
|
tu_update_fs (FS_ATA | FS_SSC, drv); /* update status */
|
||||||
|
return sim_tape_detach (uptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set/show formatter type */
|
||||||
|
|
||||||
|
t_stat tu_set_fmtr (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
DEVICE *dptr = find_dev_from_unit (uptr);
|
||||||
|
|
||||||
|
if (cptr != NULL) return SCPE_ARG;
|
||||||
|
if (dptr == NULL) return SCPE_IERR;
|
||||||
|
if (val) dptr->flags = dptr->flags | DEV_TM03;
|
||||||
|
else dptr->flags = dptr->flags & ~DEV_TM03;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat tu_show_fmtr (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
|
{
|
||||||
|
DEVICE *dptr = find_dev_from_unit (uptr);
|
||||||
|
|
||||||
|
if (dptr == NULL) return SCPE_IERR;
|
||||||
|
fprintf (st, "TM0%d", (dptr->flags & DEV_TM03? 3: 2));
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Device bootstrap */
|
||||||
|
|
||||||
|
#if defined (PDP11)
|
||||||
|
|
||||||
|
#elif defined (VM_PDP11)
|
||||||
|
|
||||||
|
#define BOOT_START 016000 /* start */
|
||||||
|
#define BOOT_ENTRY (BOOT_START + 002) /* entry */
|
||||||
|
#define BOOT_UNIT (BOOT_START + 010) /* unit number */
|
||||||
|
#define BOOT_CSR (BOOT_START + 014) /* CSR */
|
||||||
|
#define BOOT_LEN (sizeof (boot_rom) / sizeof (uint16))
|
||||||
|
|
||||||
|
static const uint16 boot_rom[] = {
|
||||||
|
0046515, /* "MM" */
|
||||||
|
0012706, BOOT_START, /* mov #boot_start, sp */
|
||||||
|
0012700, 0000000, /* mov #unit, r0 */
|
||||||
|
0012701, 0172440, /* mov #TUCS1, r1 */
|
||||||
|
0012761, 0000040, 0000010, /* mov #CS2_CLR, 10(r1) ; reset */
|
||||||
|
0012711, 0000021, /* mov #RIP+GO, (r1) ; rip */
|
||||||
|
0010004, /* mov r0, r4 */
|
||||||
|
0052704, 0002300, /* bis #2300, r4 ; set den */
|
||||||
|
0010461, 0000032, /* mov r4, 32(r1) ; set unit */
|
||||||
|
0012761, 0177777, 0000006, /* mov #-1, 6(r1) ; set fc */
|
||||||
|
0012711, 0000031, /* mov #SPCF+GO, (r1) ; skip rec */
|
||||||
|
0105761, 0000012, /* tstb 12 (r1) ; fmtr rdy? */
|
||||||
|
0100375, /* bpl .-4 */
|
||||||
|
0012761, 0177000, 0000002, /* mov #-1000, 2(r1) ; set wc */
|
||||||
|
0005061, 0000004, /* clr 4(r1) ; clr ba */
|
||||||
|
0005061, 0000006, /* clr 6(r1) ; clr fc */
|
||||||
|
0012711, 0000071, /* mov #READ+GO, (r1) ; read */
|
||||||
|
0105711, /* tstb (r1) ; wait */
|
||||||
|
0100376, /* bpl .-2 */
|
||||||
|
0005002, /* clr R2 */
|
||||||
|
0005003, /* clr R3 */
|
||||||
|
0012704, BOOT_START+020, /* mov #start+020, r4 */
|
||||||
|
0005005, /* clr R5 */
|
||||||
|
0105011, /* clrb (r1) */
|
||||||
|
0005007 /* clr PC */
|
||||||
|
};
|
||||||
|
|
||||||
|
t_stat tu_boot (int32 unitno, DEVICE *dptr)
|
||||||
|
{
|
||||||
|
int32 i;
|
||||||
|
extern int32 saved_PC;
|
||||||
|
extern uint16 *M;
|
||||||
|
|
||||||
|
for (i = 0; i < BOOT_LEN; i++) M[(BOOT_START >> 1) + i] = boot_rom[i];
|
||||||
|
M[BOOT_UNIT >> 1] = unitno & (TU_NUMDR - 1);
|
||||||
|
M[BOOT_CSR >> 1] = mba_get_csr (tu_dib.ba) & DMASK;
|
||||||
|
saved_PC = BOOT_ENTRY;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
t_stat tu_boot (int32 unitno, DEVICE *dptr)
|
||||||
|
{
|
||||||
|
return SCPE_NOFNC;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -69,6 +69,7 @@ extern int32 int_vec[IPL_HLVL][32];
|
||||||
#include "pdp11_defs.h"
|
#include "pdp11_defs.h"
|
||||||
extern int32 int_req[IPL_HLVL];
|
extern int32 int_req[IPL_HLVL];
|
||||||
extern int32 int_vec[IPL_HLVL][32];
|
extern int32 int_vec[IPL_HLVL][32];
|
||||||
|
extern int32 cpu_opt;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "sim_sock.h"
|
#include "sim_sock.h"
|
||||||
|
@ -1054,8 +1055,8 @@ static void doDMA ( int32 vh,
|
||||||
pa |= (lp->tbuf2 & TB2_M_TBUFFAD) << 16;
|
pa |= (lp->tbuf2 & TB2_M_TBUFFAD) << 16;
|
||||||
status = chan << CSR_V_TX_LINE;
|
status = chan << CSR_V_TX_LINE;
|
||||||
while (lp->tbuffct) {
|
while (lp->tbuffct) {
|
||||||
char buf;
|
uint8 buf;
|
||||||
if (Map_ReadB (pa, 1, &buf, MAP)) {
|
if (Map_ReadB (pa, 1, &buf)) {
|
||||||
status |= CSR_TX_DMA_ERR;
|
status |= CSR_TX_DMA_ERR;
|
||||||
lp->tbuffct = 0;
|
lp->tbuffct = 0;
|
||||||
break;
|
break;
|
||||||
|
@ -1233,10 +1234,6 @@ static t_stat vh_clear ( int32 vh,
|
||||||
static t_stat vh_reset ( DEVICE *dptr )
|
static t_stat vh_reset ( DEVICE *dptr )
|
||||||
{
|
{
|
||||||
int32 i;
|
int32 i;
|
||||||
#if defined (VM_PDP11)
|
|
||||||
/* import from pdp11_cpu.c: */
|
|
||||||
extern int32 cpu_18b, cpu_ubm;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (i = 0; i < (VH_MUXES * VH_LINES); i++)
|
for (i = 0; i < (VH_MUXES * VH_LINES); i++)
|
||||||
vh_parm[i].tmln = &vh_ldsc[i];
|
vh_parm[i].tmln = &vh_ldsc[i];
|
||||||
|
|
|
@ -669,11 +669,11 @@ void xq_write_callback (CTLR* xq, int status)
|
||||||
xq->var->stats.xmit += 1;
|
xq->var->stats.xmit += 1;
|
||||||
/* update write status words */
|
/* update write status words */
|
||||||
if (status == 0) { /* success */
|
if (status == 0) { /* success */
|
||||||
wstatus = Map_WriteW(xq->var->xbdl_ba + 8, 4, write_success, NOMAP);
|
wstatus = Map_WriteW(xq->var->xbdl_ba + 8, 4, write_success);
|
||||||
} else { /* failure */
|
} else { /* failure */
|
||||||
sim_debug(DBG_WRN, xq->dev, "Packet Write Error!\n");
|
sim_debug(DBG_WRN, xq->dev, "Packet Write Error!\n");
|
||||||
xq->var->stats.fail += 1;
|
xq->var->stats.fail += 1;
|
||||||
wstatus = Map_WriteW(xq->var->xbdl_ba + 8, 4, write_failure, NOMAP);
|
wstatus = Map_WriteW(xq->var->xbdl_ba + 8, 4, write_failure);
|
||||||
}
|
}
|
||||||
if (wstatus) {
|
if (wstatus) {
|
||||||
xq_nxm_error(xq);
|
xq_nxm_error(xq);
|
||||||
|
@ -760,8 +760,8 @@ t_stat xq_process_rbdl(CTLR* xq)
|
||||||
|
|
||||||
/* get receive bdl from memory */
|
/* get receive bdl from memory */
|
||||||
xq->var->rbdl_buf[0] = 0xFFFF;
|
xq->var->rbdl_buf[0] = 0xFFFF;
|
||||||
wstatus = Map_WriteW(xq->var->rbdl_ba, 2, &xq->var->rbdl_buf[0], NOMAP);
|
wstatus = Map_WriteW(xq->var->rbdl_ba, 2, &xq->var->rbdl_buf[0]);
|
||||||
rstatus = Map_ReadW (xq->var->rbdl_ba + 2, 6, &xq->var->rbdl_buf[1], NOMAP);
|
rstatus = Map_ReadW (xq->var->rbdl_ba + 2, 6, &xq->var->rbdl_buf[1]);
|
||||||
if (rstatus || wstatus) return xq_nxm_error(xq);
|
if (rstatus || wstatus) return xq_nxm_error(xq);
|
||||||
|
|
||||||
/* invalid buffer? */
|
/* invalid buffer? */
|
||||||
|
@ -780,7 +780,7 @@ t_stat xq_process_rbdl(CTLR* xq)
|
||||||
if (!xq->var->ReadQ.count) break;
|
if (!xq->var->ReadQ.count) break;
|
||||||
|
|
||||||
/* get status words */
|
/* get status words */
|
||||||
rstatus = Map_ReadW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4], NOMAP);
|
rstatus = Map_ReadW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4]);
|
||||||
if (rstatus) return xq_nxm_error(xq);
|
if (rstatus) return xq_nxm_error(xq);
|
||||||
|
|
||||||
/* get host memory address */
|
/* get host memory address */
|
||||||
|
@ -828,7 +828,7 @@ t_stat xq_process_rbdl(CTLR* xq)
|
||||||
item->packet.used += rbl;
|
item->packet.used += rbl;
|
||||||
|
|
||||||
/* send data to host */
|
/* send data to host */
|
||||||
wstatus = Map_WriteB(address, rbl, rbuf, NOMAP);
|
wstatus = Map_WriteB(address, rbl, rbuf);
|
||||||
if (wstatus) return xq_nxm_error(xq);
|
if (wstatus) return xq_nxm_error(xq);
|
||||||
|
|
||||||
/* set receive size into RBL - RBL<10:8> maps into Status1<10:8>,
|
/* set receive size into RBL - RBL<10:8> maps into Status1<10:8>,
|
||||||
|
@ -860,7 +860,7 @@ t_stat xq_process_rbdl(CTLR* xq)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update read status words*/
|
/* update read status words*/
|
||||||
wstatus = Map_WriteW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4], NOMAP);
|
wstatus = Map_WriteW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4]);
|
||||||
if (wstatus) return xq_nxm_error(xq);
|
if (wstatus) return xq_nxm_error(xq);
|
||||||
|
|
||||||
/* remove packet from queue */
|
/* remove packet from queue */
|
||||||
|
@ -901,7 +901,7 @@ t_stat xq_process_mop(CTLR* xq)
|
||||||
case 0: /* MOP Termination */
|
case 0: /* MOP Termination */
|
||||||
break;
|
break;
|
||||||
case 1: /* MOP Read Ethernet Address */
|
case 1: /* MOP Read Ethernet Address */
|
||||||
wstatus = Map_WriteB(address, sizeof(ETH_MAC), (uint8*) &xq->var->setup.macs[0], NOMAP);
|
wstatus = Map_WriteB(address, sizeof(ETH_MAC), (uint8*) &xq->var->setup.macs[0]);
|
||||||
if (wstatus) return xq_nxm_error(xq);
|
if (wstatus) return xq_nxm_error(xq);
|
||||||
break;
|
break;
|
||||||
case 2: /* MOP Reset System ID */
|
case 2: /* MOP Reset System ID */
|
||||||
|
@ -1062,9 +1062,9 @@ t_stat xq_process_xbdl(CTLR* xq)
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
/* Get transmit bdl from memory */
|
/* Get transmit bdl from memory */
|
||||||
rstatus = Map_ReadW (xq->var->xbdl_ba, 12, &xq->var->xbdl_buf[0], NOMAP);
|
rstatus = Map_ReadW (xq->var->xbdl_ba, 12, &xq->var->xbdl_buf[0]);
|
||||||
xq->var->xbdl_buf[0] = 0xFFFF;
|
xq->var->xbdl_buf[0] = 0xFFFF;
|
||||||
wstatus = Map_WriteW(xq->var->xbdl_ba, 2, &xq->var->xbdl_buf[0], NOMAP);
|
wstatus = Map_WriteW(xq->var->xbdl_ba, 2, &xq->var->xbdl_buf[0]);
|
||||||
if (rstatus || wstatus) return xq_nxm_error(xq);
|
if (rstatus || wstatus) return xq_nxm_error(xq);
|
||||||
|
|
||||||
/* invalid buffer? */
|
/* invalid buffer? */
|
||||||
|
@ -1093,7 +1093,7 @@ t_stat xq_process_xbdl(CTLR* xq)
|
||||||
/* add to transmit buffer, making sure it's not too big */
|
/* add to transmit buffer, making sure it's not too big */
|
||||||
if ((xq->var->write_buffer.len + b_length) > sizeof(xq->var->write_buffer.msg))
|
if ((xq->var->write_buffer.len + b_length) > sizeof(xq->var->write_buffer.msg))
|
||||||
b_length = sizeof(xq->var->write_buffer.msg) - xq->var->write_buffer.len;
|
b_length = sizeof(xq->var->write_buffer.msg) - xq->var->write_buffer.len;
|
||||||
rstatus = Map_ReadB(address, b_length, &xq->var->write_buffer.msg[xq->var->write_buffer.len], NOMAP);
|
rstatus = Map_ReadB(address, b_length, &xq->var->write_buffer.msg[xq->var->write_buffer.len]);
|
||||||
if (rstatus) return xq_nxm_error(xq);
|
if (rstatus) return xq_nxm_error(xq);
|
||||||
xq->var->write_buffer.len += b_length;
|
xq->var->write_buffer.len += b_length;
|
||||||
|
|
||||||
|
@ -1112,7 +1112,7 @@ t_stat xq_process_xbdl(CTLR* xq)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update write status */
|
/* update write status */
|
||||||
wstatus = Map_WriteW(xq->var->xbdl_ba + 8, 4, (uint16*) write_success, NOMAP);
|
wstatus = Map_WriteW(xq->var->xbdl_ba + 8, 4, (uint16*) write_success);
|
||||||
if (wstatus) return xq_nxm_error(xq);
|
if (wstatus) return xq_nxm_error(xq);
|
||||||
|
|
||||||
/* clear write buffer */
|
/* clear write buffer */
|
||||||
|
@ -1145,7 +1145,7 @@ t_stat xq_process_xbdl(CTLR* xq)
|
||||||
|
|
||||||
sim_debug(DBG_WRN, xq->dev, "XBDL processing implicit chain buffer segment\n");
|
sim_debug(DBG_WRN, xq->dev, "XBDL processing implicit chain buffer segment\n");
|
||||||
/* update bdl status words */
|
/* update bdl status words */
|
||||||
wstatus = Map_WriteW(xq->var->xbdl_ba + 8, 4, (uint16*) implicit_chain_status, NOMAP);
|
wstatus = Map_WriteW(xq->var->xbdl_ba + 8, 4, (uint16*) implicit_chain_status);
|
||||||
if(wstatus) return xq_nxm_error(xq);
|
if(wstatus) return xq_nxm_error(xq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1175,8 +1175,8 @@ t_stat xq_dispatch_rbdl(CTLR* xq)
|
||||||
|
|
||||||
/* get first receive buffer */
|
/* get first receive buffer */
|
||||||
xq->var->rbdl_buf[0] = 0xFFFF;
|
xq->var->rbdl_buf[0] = 0xFFFF;
|
||||||
wstatus = Map_WriteW(xq->var->rbdl_ba, 2, &xq->var->rbdl_buf[0], NOMAP);
|
wstatus = Map_WriteW(xq->var->rbdl_ba, 2, &xq->var->rbdl_buf[0]);
|
||||||
rstatus = Map_ReadW (xq->var->rbdl_ba + 2, 6, &xq->var->rbdl_buf[1], NOMAP);
|
rstatus = Map_ReadW (xq->var->rbdl_ba + 2, 6, &xq->var->rbdl_buf[1]);
|
||||||
if (rstatus || wstatus) return xq_nxm_error(xq);
|
if (rstatus || wstatus) return xq_nxm_error(xq);
|
||||||
|
|
||||||
/* is buffer valid? */
|
/* is buffer valid? */
|
||||||
|
@ -1460,8 +1460,8 @@ t_stat xq_process_bootrom (CTLR* xq)
|
||||||
|
|
||||||
/* get receive bdl from memory */
|
/* get receive bdl from memory */
|
||||||
xq->var->rbdl_buf[0] = 0xFFFF;
|
xq->var->rbdl_buf[0] = 0xFFFF;
|
||||||
wstatus = Map_WriteW(xq->var->rbdl_ba, 2, &xq->var->rbdl_buf[0], NOMAP);
|
wstatus = Map_WriteW(xq->var->rbdl_ba, 2, &xq->var->rbdl_buf[0]);
|
||||||
rstatus = Map_ReadW (xq->var->rbdl_ba + 2, 6, &xq->var->rbdl_buf[1], NOMAP);
|
rstatus = Map_ReadW (xq->var->rbdl_ba + 2, 6, &xq->var->rbdl_buf[1]);
|
||||||
if (rstatus || wstatus) return xq_nxm_error(xq);
|
if (rstatus || wstatus) return xq_nxm_error(xq);
|
||||||
|
|
||||||
/* invalid buffer? */
|
/* invalid buffer? */
|
||||||
|
@ -1471,7 +1471,7 @@ t_stat xq_process_bootrom (CTLR* xq)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get status words */
|
/* get status words */
|
||||||
rstatus = Map_ReadW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4], NOMAP);
|
rstatus = Map_ReadW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4]);
|
||||||
if (rstatus) return xq_nxm_error(xq);
|
if (rstatus) return xq_nxm_error(xq);
|
||||||
|
|
||||||
/* get host memory address */
|
/* get host memory address */
|
||||||
|
@ -1487,7 +1487,7 @@ t_stat xq_process_bootrom (CTLR* xq)
|
||||||
assert(b_length >= sizeof(xq_bootrom)/2);
|
assert(b_length >= sizeof(xq_bootrom)/2);
|
||||||
|
|
||||||
/* send data to host */
|
/* send data to host */
|
||||||
wstatus = Map_WriteB(address, sizeof(xq_bootrom)/2, bootrom, NOMAP);
|
wstatus = Map_WriteB(address, sizeof(xq_bootrom)/2, bootrom);
|
||||||
if (wstatus) return xq_nxm_error(xq);
|
if (wstatus) return xq_nxm_error(xq);
|
||||||
|
|
||||||
/* update read status words */
|
/* update read status words */
|
||||||
|
@ -1495,7 +1495,7 @@ t_stat xq_process_bootrom (CTLR* xq)
|
||||||
xq->var->rbdl_buf[5] = 0;
|
xq->var->rbdl_buf[5] = 0;
|
||||||
|
|
||||||
/* update read status words*/
|
/* update read status words*/
|
||||||
wstatus = Map_WriteW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4], NOMAP);
|
wstatus = Map_WriteW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4]);
|
||||||
if (wstatus) return xq_nxm_error(xq);
|
if (wstatus) return xq_nxm_error(xq);
|
||||||
|
|
||||||
/* set to next bdl (implicit chain) */
|
/* set to next bdl (implicit chain) */
|
||||||
|
@ -1505,8 +1505,8 @@ t_stat xq_process_bootrom (CTLR* xq)
|
||||||
|
|
||||||
/* get receive bdl from memory */
|
/* get receive bdl from memory */
|
||||||
xq->var->rbdl_buf[0] = 0xFFFF;
|
xq->var->rbdl_buf[0] = 0xFFFF;
|
||||||
wstatus = Map_WriteW(xq->var->rbdl_ba, 2, &xq->var->rbdl_buf[0], NOMAP);
|
wstatus = Map_WriteW(xq->var->rbdl_ba, 2, &xq->var->rbdl_buf[0]);
|
||||||
rstatus = Map_ReadW (xq->var->rbdl_ba + 2, 6, &xq->var->rbdl_buf[1], NOMAP);
|
rstatus = Map_ReadW (xq->var->rbdl_ba + 2, 6, &xq->var->rbdl_buf[1]);
|
||||||
if (rstatus || wstatus) return xq_nxm_error(xq);
|
if (rstatus || wstatus) return xq_nxm_error(xq);
|
||||||
|
|
||||||
/* invalid buffer? */
|
/* invalid buffer? */
|
||||||
|
@ -1516,7 +1516,7 @@ t_stat xq_process_bootrom (CTLR* xq)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get status words */
|
/* get status words */
|
||||||
rstatus = Map_ReadW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4], NOMAP);
|
rstatus = Map_ReadW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4]);
|
||||||
if (rstatus) return xq_nxm_error(xq);
|
if (rstatus) return xq_nxm_error(xq);
|
||||||
|
|
||||||
/* get host memory address */
|
/* get host memory address */
|
||||||
|
@ -1532,7 +1532,7 @@ t_stat xq_process_bootrom (CTLR* xq)
|
||||||
assert(b_length >= sizeof(xq_bootrom)/2);
|
assert(b_length >= sizeof(xq_bootrom)/2);
|
||||||
|
|
||||||
/* send data to host */
|
/* send data to host */
|
||||||
wstatus = Map_WriteB(address, sizeof(xq_bootrom)/2, &bootrom[2048], NOMAP);
|
wstatus = Map_WriteB(address, sizeof(xq_bootrom)/2, &bootrom[2048]);
|
||||||
if (wstatus) return xq_nxm_error(xq);
|
if (wstatus) return xq_nxm_error(xq);
|
||||||
|
|
||||||
/* update read status words */
|
/* update read status words */
|
||||||
|
@ -1540,7 +1540,7 @@ t_stat xq_process_bootrom (CTLR* xq)
|
||||||
xq->var->rbdl_buf[5] = 0;
|
xq->var->rbdl_buf[5] = 0;
|
||||||
|
|
||||||
/* update read status words*/
|
/* update read status words*/
|
||||||
wstatus = Map_WriteW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4], NOMAP);
|
wstatus = Map_WriteW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4]);
|
||||||
if (wstatus) return xq_nxm_error(xq);
|
if (wstatus) return xq_nxm_error(xq);
|
||||||
|
|
||||||
/* set to next bdl (implicit chain) */
|
/* set to next bdl (implicit chain) */
|
||||||
|
@ -1553,8 +1553,8 @@ t_stat xq_process_bootrom (CTLR* xq)
|
||||||
|
|
||||||
/* get receive bdl from memory */
|
/* get receive bdl from memory */
|
||||||
xq->var->rbdl_buf[0] = 0xFFFF;
|
xq->var->rbdl_buf[0] = 0xFFFF;
|
||||||
wstatus = Map_WriteW(xq->var->rbdl_ba, 2, &xq->var->rbdl_buf[0], NOMAP);
|
wstatus = Map_WriteW(xq->var->rbdl_ba, 2, &xq->var->rbdl_buf[0]);
|
||||||
rstatus = Map_ReadW (xq->var->rbdl_ba + 2, 6, &xq->var->rbdl_buf[1], NOMAP);
|
rstatus = Map_ReadW (xq->var->rbdl_ba + 2, 6, &xq->var->rbdl_buf[1]);
|
||||||
if (rstatus || wstatus) return xq_nxm_error(xq);
|
if (rstatus || wstatus) return xq_nxm_error(xq);
|
||||||
|
|
||||||
/* invalid buffer? */
|
/* invalid buffer? */
|
||||||
|
@ -1564,7 +1564,7 @@ t_stat xq_process_bootrom (CTLR* xq)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get status words */
|
/* get status words */
|
||||||
rstatus = Map_ReadW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4], NOMAP);
|
rstatus = Map_ReadW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4]);
|
||||||
if (rstatus) return xq_nxm_error(xq);
|
if (rstatus) return xq_nxm_error(xq);
|
||||||
|
|
||||||
/* update read status words */
|
/* update read status words */
|
||||||
|
@ -1572,7 +1572,7 @@ t_stat xq_process_bootrom (CTLR* xq)
|
||||||
xq->var->rbdl_buf[5] = 0;
|
xq->var->rbdl_buf[5] = 0;
|
||||||
|
|
||||||
/* update read status words*/
|
/* update read status words*/
|
||||||
wstatus = Map_WriteW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4], NOMAP);
|
wstatus = Map_WriteW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4]);
|
||||||
if (wstatus) return xq_nxm_error(xq);
|
if (wstatus) return xq_nxm_error(xq);
|
||||||
|
|
||||||
/* set to next bdl (implicit chain) */
|
/* set to next bdl (implicit chain) */
|
||||||
|
|
|
@ -605,7 +605,7 @@ int32 xu_command(CTLR* xu)
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Grab the PCB from the host. */
|
/* Grab the PCB from the host. */
|
||||||
rstatus = Map_ReadW(xu->var->pcbb, 8, xu->var->pcb, MAP);
|
rstatus = Map_ReadW(xu->var->pcbb, 8, xu->var->pcb);
|
||||||
if (rstatus != SCPE_OK)
|
if (rstatus != SCPE_OK)
|
||||||
return PCSR0_PCEI + 1;
|
return PCSR0_PCEI + 1;
|
||||||
|
|
||||||
|
@ -621,19 +621,19 @@ int32 xu_command(CTLR* xu)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FC_RDPA: /* read default physical address */
|
case FC_RDPA: /* read default physical address */
|
||||||
wstatus = Map_WriteW(xu->var->pcbb + 2, 6, (uint16*)xu->var->mac, MAP);
|
wstatus = Map_WriteW(xu->var->pcbb + 2, 6, (uint16*)xu->var->mac);
|
||||||
if (wstatus != SCPE_OK)
|
if (wstatus != SCPE_OK)
|
||||||
return PCSR0_PCEI + 1;
|
return PCSR0_PCEI + 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FC_RPA: /* read current physical address */
|
case FC_RPA: /* read current physical address */
|
||||||
wstatus = Map_WriteW(xu->var->pcbb + 2, 6, (uint16*)&xu->var->setup.macs[0], MAP);
|
wstatus = Map_WriteW(xu->var->pcbb + 2, 6, (uint16*)&xu->var->setup.macs[0]);
|
||||||
if (wstatus != SCPE_OK)
|
if (wstatus != SCPE_OK)
|
||||||
return PCSR0_PCEI + 1;
|
return PCSR0_PCEI + 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FC_WPA: /* write current physical address */
|
case FC_WPA: /* write current physical address */
|
||||||
rstatus = Map_ReadW(xu->var->pcbb + 2, 6, (uint16*)&xu->var->setup.macs[0], MAP);
|
rstatus = Map_ReadW(xu->var->pcbb + 2, 6, (uint16*)&xu->var->setup.macs[0]);
|
||||||
if (xu->var->pcb[1] & 1) return PCSR0_PCEI;
|
if (xu->var->pcb[1] & 1) return PCSR0_PCEI;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -641,7 +641,7 @@ int32 xu_command(CTLR* xu)
|
||||||
mtlen = (xu->var->pcb[2] & 0xFF00) >> 8;
|
mtlen = (xu->var->pcb[2] & 0xFF00) >> 8;
|
||||||
if (mtlen > 10) return PCSR0_PCEI;
|
if (mtlen > 10) return PCSR0_PCEI;
|
||||||
udbb = xu->var->pcb[1] | ((xu->var->pcb[2] & 03) << 16);
|
udbb = xu->var->pcb[1] | ((xu->var->pcb[2] & 03) << 16);
|
||||||
rstatus = Map_ReadW(udbb, mtlen * 6, (uint16*) &xu->var->setup.macs[1], MAP);
|
rstatus = Map_ReadW(udbb, mtlen * 6, (uint16*) &xu->var->setup.macs[1]);
|
||||||
if (rstatus == SCPE_OK) {
|
if (rstatus == SCPE_OK) {
|
||||||
xu->var->setup.mac_count = mtlen + 1;
|
xu->var->setup.mac_count = mtlen + 1;
|
||||||
status = eth_filter (xu->var->etherface, xu->var->setup.mac_count,
|
status = eth_filter (xu->var->etherface, xu->var->setup.mac_count,
|
||||||
|
@ -664,7 +664,7 @@ int32 xu_command(CTLR* xu)
|
||||||
|
|
||||||
/* Write UDB to host memory. */
|
/* Write UDB to host memory. */
|
||||||
udbb = xu->var->pcb[1] + ((xu->var->pcb[2] & 3) << 16);
|
udbb = xu->var->pcb[1] + ((xu->var->pcb[2] & 3) << 16);
|
||||||
wstatus = Map_WriteW(udbb, 12, xu->var->pcb, MAP);
|
wstatus = Map_WriteW(udbb, 12, xu->var->pcb);
|
||||||
if (wstatus != SCPE_OK)
|
if (wstatus != SCPE_OK)
|
||||||
return PCSR0_PCEI+1;
|
return PCSR0_PCEI+1;
|
||||||
break;
|
break;
|
||||||
|
@ -677,7 +677,7 @@ int32 xu_command(CTLR* xu)
|
||||||
|
|
||||||
/* Read UDB into local memory. */
|
/* Read UDB into local memory. */
|
||||||
udbb = xu->var->pcb[1] + ((xu->var->pcb[2] & 3) << 16);
|
udbb = xu->var->pcb[1] + ((xu->var->pcb[2] & 3) << 16);
|
||||||
rstatus = Map_ReadW(udbb, 12, xu->var->udb, MAP);
|
rstatus = Map_ReadW(udbb, 12, xu->var->udb);
|
||||||
if (rstatus != SCPE_OK)
|
if (rstatus != SCPE_OK)
|
||||||
return PCSR0_PCEI+1;
|
return PCSR0_PCEI+1;
|
||||||
|
|
||||||
|
@ -740,7 +740,7 @@ int32 xu_command(CTLR* xu)
|
||||||
|
|
||||||
/* transfer udb to host */
|
/* transfer udb to host */
|
||||||
udbb = xu->var->pcb[1] + ((xu->var->pcb[2] & 3) << 16);
|
udbb = xu->var->pcb[1] + ((xu->var->pcb[2] & 3) << 16);
|
||||||
wstatus = Map_WriteW(udbb, 68, xu->var->udb, MAP);
|
wstatus = Map_WriteW(udbb, 68, xu->var->udb);
|
||||||
if (wstatus != SCPE_OK) {
|
if (wstatus != SCPE_OK) {
|
||||||
xu->var->pcsr0 |= PCSR0_PCEI;
|
xu->var->pcsr0 |= PCSR0_PCEI;
|
||||||
}
|
}
|
||||||
|
@ -752,7 +752,7 @@ int32 xu_command(CTLR* xu)
|
||||||
|
|
||||||
case FC_RMODE: /* read mode register */
|
case FC_RMODE: /* read mode register */
|
||||||
value = xu->var->mode;
|
value = xu->var->mode;
|
||||||
wstatus = Map_WriteW(xu->var->pcbb+2, 2, &value, MAP);
|
wstatus = Map_WriteW(xu->var->pcbb+2, 2, &value);
|
||||||
if (wstatus != SCPE_OK)
|
if (wstatus != SCPE_OK)
|
||||||
return PCSR0_PCEI + 1;
|
return PCSR0_PCEI + 1;
|
||||||
break;
|
break;
|
||||||
|
@ -775,11 +775,11 @@ int32 xu_command(CTLR* xu)
|
||||||
case FC_RSTAT: /* read extended status */
|
case FC_RSTAT: /* read extended status */
|
||||||
case FC_RCSTAT: /* read and clear extended status */
|
case FC_RCSTAT: /* read and clear extended status */
|
||||||
value = xu->var->stat;
|
value = xu->var->stat;
|
||||||
wstatus = Map_WriteW(xu->var->pcbb+2, 2, &value, MAP);
|
wstatus = Map_WriteW(xu->var->pcbb+2, 2, &value);
|
||||||
value = 10;
|
value = 10;
|
||||||
wstatus2 = Map_WriteW(xu->var->pcbb+4, 2, &value, MAP);
|
wstatus2 = Map_WriteW(xu->var->pcbb+4, 2, &value);
|
||||||
value = 32;
|
value = 32;
|
||||||
wstatus3 = Map_WriteW(xu->var->pcbb+6, 2, &value, MAP);
|
wstatus3 = Map_WriteW(xu->var->pcbb+6, 2, &value);
|
||||||
if ((wstatus != SCPE_OK) || (wstatus2 != SCPE_OK) || (wstatus3 != SCPE_OK))
|
if ((wstatus != SCPE_OK) || (wstatus2 != SCPE_OK) || (wstatus3 != SCPE_OK))
|
||||||
return PCSR0_PCEI + 1;
|
return PCSR0_PCEI + 1;
|
||||||
|
|
||||||
|
@ -824,7 +824,7 @@ void xu_process_receive(CTLR* xu)
|
||||||
|
|
||||||
/* get next receive buffer */
|
/* get next receive buffer */
|
||||||
ba = xu->var->rdrb + (xu->var->relen * 2) * xu->var->rxnext;
|
ba = xu->var->rdrb + (xu->var->relen * 2) * xu->var->rxnext;
|
||||||
rstatus = Map_ReadW (ba, 8, xu->var->rxhdr, MAP);
|
rstatus = Map_ReadW (ba, 8, xu->var->rxhdr);
|
||||||
if (rstatus) {
|
if (rstatus) {
|
||||||
/* tell host bus read failed */
|
/* tell host bus read failed */
|
||||||
xu->var->stat |= STAT_ERRS | STAT_MERR | STAT_TMOT | STAT_RRNG;
|
xu->var->stat |= STAT_ERRS | STAT_MERR | STAT_TMOT | STAT_RRNG;
|
||||||
|
@ -882,7 +882,7 @@ void xu_process_receive(CTLR* xu)
|
||||||
wlen = slen;
|
wlen = slen;
|
||||||
|
|
||||||
/* transfer chained packet to host buffer */
|
/* transfer chained packet to host buffer */
|
||||||
wstatus = Map_WriteB (segb, wlen, &item->packet.msg[off], MAP);
|
wstatus = Map_WriteB (segb, wlen, &item->packet.msg[off]);
|
||||||
if (wstatus) {
|
if (wstatus) {
|
||||||
/* error during write */
|
/* error during write */
|
||||||
xu->var->stat |= STAT_ERRS | STAT_MERR | STAT_TMOT | STAT_RRNG;
|
xu->var->stat |= STAT_ERRS | STAT_MERR | STAT_TMOT | STAT_RRNG;
|
||||||
|
@ -938,7 +938,7 @@ void xu_process_receive(CTLR* xu)
|
||||||
xu->var->rxhdr[2] &= ~RXR_OWN; /* clear ownership flag */
|
xu->var->rxhdr[2] &= ~RXR_OWN; /* clear ownership flag */
|
||||||
|
|
||||||
/* update the ring entry in host memory. */
|
/* update the ring entry in host memory. */
|
||||||
wstatus = Map_WriteW (ba, 8, xu->var->rxhdr, MAP);
|
wstatus = Map_WriteW (ba, 8, xu->var->rxhdr);
|
||||||
if (wstatus) {
|
if (wstatus) {
|
||||||
/* tell host bus write failed */
|
/* tell host bus write failed */
|
||||||
xu->var->stat |= STAT_ERRS | STAT_MERR | STAT_TMOT | STAT_RRNG;
|
xu->var->stat |= STAT_ERRS | STAT_MERR | STAT_TMOT | STAT_RRNG;
|
||||||
|
@ -978,7 +978,7 @@ void xu_process_transmit(CTLR* xu)
|
||||||
|
|
||||||
/* get next transmit buffer */
|
/* get next transmit buffer */
|
||||||
ba = xu->var->tdrb + (xu->var->telen * 2) * xu->var->txnext;
|
ba = xu->var->tdrb + (xu->var->telen * 2) * xu->var->txnext;
|
||||||
rstatus = Map_ReadW (ba, 8, xu->var->txhdr, MAP);
|
rstatus = Map_ReadW (ba, 8, xu->var->txhdr);
|
||||||
if (rstatus) {
|
if (rstatus) {
|
||||||
/* tell host bus read failed */
|
/* tell host bus read failed */
|
||||||
xu->var->stat |= STAT_ERRS | STAT_MERR | STAT_TMOT | STAT_TRNG;
|
xu->var->stat |= STAT_ERRS | STAT_MERR | STAT_TMOT | STAT_TRNG;
|
||||||
|
@ -1007,7 +1007,7 @@ void xu_process_transmit(CTLR* xu)
|
||||||
giant = 1;
|
giant = 1;
|
||||||
}
|
}
|
||||||
if (wlen > 0) {
|
if (wlen > 0) {
|
||||||
rstatus = Map_ReadB(segb, wlen, &xu->var->write_buffer.msg[off], MAP);
|
rstatus = Map_ReadB(segb, wlen, &xu->var->write_buffer.msg[off]);
|
||||||
if (rstatus) {
|
if (rstatus) {
|
||||||
/* tell host bus read failed */
|
/* tell host bus read failed */
|
||||||
xu->var->stat |= STAT_ERRS | STAT_MERR | STAT_TMOT | STAT_TRNG;
|
xu->var->stat |= STAT_ERRS | STAT_MERR | STAT_TMOT | STAT_TRNG;
|
||||||
|
@ -1078,7 +1078,7 @@ void xu_process_transmit(CTLR* xu)
|
||||||
xu->var->txhdr[2] &= ~TXR_OWN;
|
xu->var->txhdr[2] &= ~TXR_OWN;
|
||||||
|
|
||||||
/* update transmit buffer */
|
/* update transmit buffer */
|
||||||
wstatus = Map_WriteW (ba, 8, xu->var->txhdr, MAP);
|
wstatus = Map_WriteW (ba, 8, xu->var->txhdr);
|
||||||
if (wstatus) {
|
if (wstatus) {
|
||||||
/* tell host bus write failed */
|
/* tell host bus write failed */
|
||||||
xu->var->pcsr0 |= PCSR0_PCEI;
|
xu->var->pcsr0 |= PCSR0_PCEI;
|
||||||
|
|
|
@ -50,7 +50,11 @@ extern int32 int_req;
|
||||||
extern int32 int_vec[32];
|
extern int32 int_vec[32];
|
||||||
|
|
||||||
#elif defined (VM_VAX) /* VAX version */
|
#elif defined (VM_VAX) /* VAX version */
|
||||||
#error "DEUNA/DELUA not supported on VAX!"
|
#include "vax_defs.h"
|
||||||
|
#define XU_RDX 8
|
||||||
|
#define XU_WID 16
|
||||||
|
extern int32 int_req[IPL_HLVL];
|
||||||
|
extern int32 int_vec[IPL_HLVL][32];
|
||||||
|
|
||||||
#else /* PDP-11 version */
|
#else /* PDP-11 version */
|
||||||
#include "pdp11_defs.h"
|
#include "pdp11_defs.h"
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
cpu PDP-4/7/9/15 central processor
|
cpu PDP-4/7/9/15 central processor
|
||||||
|
|
||||||
|
06-Nov-04 RMS Added =n to SHOW HISTORY
|
||||||
26-Mar-04 RMS Fixed warning from -std=c99
|
26-Mar-04 RMS Fixed warning from -std=c99
|
||||||
14-Jan-04 RMS Fixed g_mode in XVM implementation
|
14-Jan-04 RMS Fixed g_mode in XVM implementation
|
||||||
PDP-15 index, autoincrement generate 18b addresses
|
PDP-15 index, autoincrement generate 18b addresses
|
||||||
|
@ -543,7 +544,7 @@ MTAB cpu_mod[] = {
|
||||||
{ UNIT_MSIZE, 114688, NULL, "112K", &cpu_set_size },
|
{ UNIT_MSIZE, 114688, NULL, "112K", &cpu_set_size },
|
||||||
{ UNIT_MSIZE, 131072, NULL, "128K", &cpu_set_size },
|
{ UNIT_MSIZE, 131072, NULL, "128K", &cpu_set_size },
|
||||||
#endif
|
#endif
|
||||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "HISTORY", "HISTORY",
|
{ MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY",
|
||||||
&cpu_set_hist, &cpu_show_hist },
|
&cpu_set_hist, &cpu_show_hist },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
|
||||||
|
@ -1966,16 +1967,23 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)
|
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
{
|
{
|
||||||
int32 l, j, k, di;
|
int32 l, j, k, di, lnt;
|
||||||
|
char *cptr = (char *) desc;
|
||||||
t_value sim_eval[2];
|
t_value sim_eval[2];
|
||||||
|
t_stat r;
|
||||||
struct InstHistory *h;
|
struct InstHistory *h;
|
||||||
extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
|
extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
|
||||||
UNIT *uptr, int32 sw);
|
UNIT *uptr, int32 sw);
|
||||||
|
|
||||||
if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */
|
if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */
|
||||||
|
if (cptr) {
|
||||||
|
lnt = (int32) get_uint (cptr, 10, hst_lnt, &r);
|
||||||
|
if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; }
|
||||||
|
else lnt = hst_lnt;
|
||||||
|
di = hst_p - lnt; /* work forward */
|
||||||
|
if (di < 0) di = di + hst_lnt;
|
||||||
fprintf (st, "PC L AC MQ IR\n\n");
|
fprintf (st, "PC L AC MQ IR\n\n");
|
||||||
di = hst_p; /* work forward */
|
for (k = 0; k < lnt; k++) { /* print specified */
|
||||||
for (k = 0; k < hst_lnt; k++) { /* print specified */
|
|
||||||
h = &hst[(di++) % hst_lnt]; /* entry pointer */
|
h = &hst[(di++) % hst_lnt]; /* entry pointer */
|
||||||
if (h->pc & HIST_PC) { /* instruction? */
|
if (h->pc & HIST_PC) { /* instruction? */
|
||||||
l = (h->lac >> 18) & 1; /* link */
|
l = (h->lac >> 18) & 1; /* link */
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
To: Users
|
To: Users
|
||||||
From: Bob Supnik
|
From: Bob Supnik
|
||||||
Subj: 18b PDP Simulator Usage
|
Subj: 18b PDP Simulator Usage
|
||||||
Date: 15-Jun-2004
|
Date: 15-Nov-2004
|
||||||
|
|
||||||
COPYRIGHT NOTICE
|
COPYRIGHT NOTICE
|
||||||
|
|
||||||
|
@ -280,8 +280,9 @@ This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands:
|
||||||
|
|
||||||
SET CPU HISTORY clear history buffer
|
SET CPU HISTORY clear history buffer
|
||||||
SET CPU HISTORY=0 disable history
|
SET CPU HISTORY=0 disable history
|
||||||
SET CPU HISTORY=n enable history, display length = n
|
SET CPU HISTORY=n enable history, length = n
|
||||||
SHOW CPU HISTORY print CPU history
|
SHOW CPU HISTORY print CPU history
|
||||||
|
SHOW CPU HISTORY=n print first n entries of CPU history
|
||||||
|
|
||||||
The maximum length for the history is 65536 entries.
|
The maximum length for the history is 65536 entries.
|
||||||
|
|
||||||
|
@ -596,7 +597,7 @@ RP15 options include the ability to make units write enabled or write locked:
|
||||||
SET RPn LOCKED set unit n write locked
|
SET RPn LOCKED set unit n write locked
|
||||||
SET RPn WRITEENABLED set unit n write enabled
|
SET RPn WRITEENABLED set unit n write enabled
|
||||||
|
|
||||||
Units can also be set ONLINE or OFFLINE.
|
Units can also be set ENABLED or DISABLED.
|
||||||
|
|
||||||
The RP15 implements these registers:
|
The RP15 implements these registers:
|
||||||
|
|
||||||
|
@ -745,7 +746,7 @@ locked.
|
||||||
SET DTn WRITEENABLED set unit n write enabled
|
SET DTn WRITEENABLED set unit n write enabled
|
||||||
SET DTn LOCKED set unit n write locked
|
SET DTn LOCKED set unit n write locked
|
||||||
|
|
||||||
Units can also be set ONLINE or OFFLINE.
|
Units can also be set ENABLED or DISABLED.
|
||||||
|
|
||||||
The Type 550, TC02, and TC15 support PDP-8 format, PDP-11 format, and
|
The Type 550, TC02, and TC15 support PDP-8 format, PDP-11 format, and
|
||||||
18b format DECtape images. ATTACH tries to determine the tape format
|
18b format DECtape images. ATTACH tries to determine the tape format
|
||||||
|
@ -800,7 +801,7 @@ or write locked.
|
||||||
SET MTn LOCKED set unit n write locked
|
SET MTn LOCKED set unit n write locked
|
||||||
SET MTn WRITEENABLED set unit n write enabled
|
SET MTn WRITEENABLED set unit n write enabled
|
||||||
|
|
||||||
Units can also be set ONLINE or OFFLINE.
|
Units can also be set ENABLED or DISABLED.
|
||||||
|
|
||||||
The magnetic tape controller implements these registers:
|
The magnetic tape controller implements these registers:
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
fpp PDP-15 floating point processor
|
fpp PDP-15 floating point processor
|
||||||
|
|
||||||
|
31-Oct-04 RMS Fixed URFST to mask low 9b of fraction
|
||||||
|
Fixed exception PC setting
|
||||||
10-Apr-04 RMS JEA is 15b not 18b
|
10-Apr-04 RMS JEA is 15b not 18b
|
||||||
|
|
||||||
The FP15 instruction format is:
|
The FP15 instruction format is:
|
||||||
|
@ -205,7 +207,7 @@ DEVICE fpp_dev = {
|
||||||
1, 8, 1, 1, 8, 18,
|
1, 8, 1, 1, 8, 18,
|
||||||
NULL, NULL, &fp15_reset,
|
NULL, NULL, &fp15_reset,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
NULL, DEV_DISABLE | DEV_DIS };
|
NULL, DEV_DISABLE };
|
||||||
|
|
||||||
/* Instruction decode for FP15
|
/* Instruction decode for FP15
|
||||||
|
|
||||||
|
@ -390,11 +392,11 @@ t_stat sta;
|
||||||
fguard = 0; /* clear guard */
|
fguard = 0; /* clear guard */
|
||||||
if (ir & FI_FP) { /* fp? */
|
if (ir & FI_FP) { /* fp? */
|
||||||
if (sta = fp15_norm (ir, a, NULL, 0)) return sta; /* normalize */
|
if (sta = fp15_norm (ir, a, NULL, 0)) return sta; /* normalize */
|
||||||
wd[1] = (a->sign << 17) | a->hi; /* hi frac */
|
|
||||||
if (ir & FI_DP) { /* dp? */
|
if (ir & FI_DP) { /* dp? */
|
||||||
numwd = 3; /* 3 words */
|
|
||||||
wd[0] = a->exp & DMASK; /* exponent */
|
wd[0] = a->exp & DMASK; /* exponent */
|
||||||
wd[2] = a->lo; } /* low frac */
|
wd[1] = (a->sign << 17) | a->hi; /* hi frac */
|
||||||
|
wd[2] = a->lo; /* low frac */
|
||||||
|
numwd = 3; } /* 3 words */
|
||||||
else { /* single */
|
else { /* single */
|
||||||
if (!(ir & FI_NORND) && (a->lo & UFP_FL_SRND)) { /* round? */
|
if (!(ir & FI_NORND) && (a->lo & UFP_FL_SRND)) { /* round? */
|
||||||
a->lo = (a->lo + UFP_FL_SRND) & UFP_FL_SMASK;
|
a->lo = (a->lo + UFP_FL_SRND) & UFP_FL_SMASK;
|
||||||
|
@ -404,24 +406,25 @@ if (ir & FI_FP) { /* fp? */
|
||||||
a->exp = a->exp + 1; } }
|
a->exp = a->exp + 1; } }
|
||||||
if (a->exp > 0377) return FP_OVF; /* sp ovf? */
|
if (a->exp > 0377) return FP_OVF; /* sp ovf? */
|
||||||
if (a->exp < -0400) return FP_UNF; /* sp unf? */
|
if (a->exp < -0400) return FP_UNF; /* sp unf? */
|
||||||
numwd = 2; /* 2 words */
|
wd[0] = (a->exp & 0777) | (a->lo & UFP_FL_SMASK); /* low frac'exp */
|
||||||
wd[0] = (a->exp & 0777) | a->lo; } /* low frac'exp */
|
wd[1] = (a->sign << 17) | a->hi; /* hi frac */
|
||||||
|
numwd = 2; } /* 2 words */
|
||||||
}
|
}
|
||||||
else { fmb.lo = (-a->lo) & UFP_FL_MASK; /* 2's complement */
|
else { fmb.lo = (-a->lo) & UFP_FL_MASK; /* 2's complement */
|
||||||
fmb.hi = (~a->hi + (fmb.lo == 0)) & UFP_FH_MASK;/* to FMB */
|
fmb.hi = (~a->hi + (fmb.lo == 0)) & UFP_FH_MASK;/* to FMB */
|
||||||
if (ir & FI_DP) { /* dp? */
|
if (ir & FI_DP) { /* dp? */
|
||||||
numwd = 2; /* 2 words */
|
|
||||||
if (a->sign) { /* negative? */
|
if (a->sign) { /* negative? */
|
||||||
wd[0] = fmb.hi | SIGN; /* store FMB */
|
wd[0] = fmb.hi | SIGN; /* store FMB */
|
||||||
wd[1] = fmb.lo; }
|
wd[1] = fmb.lo; }
|
||||||
else { /* pos, store FMA */
|
else { /* pos, store FMA */
|
||||||
wd[0] = a->hi;
|
wd[0] = a->hi;
|
||||||
wd[1] = a->lo; } }
|
wd[1] = a->lo; }
|
||||||
|
numwd = 2; } /* 2 words */
|
||||||
else { /* single */
|
else { /* single */
|
||||||
if (a->hi || (a->lo & SIGN)) return FP_OVF; /* check int ovf */
|
if (a->hi || (a->lo & SIGN)) return FP_OVF; /* check int ovf */
|
||||||
numwd = 1; /* 1 word */
|
|
||||||
if (a->sign) wd[0] = fmb.lo; /* neg? store FMB */
|
if (a->sign) wd[0] = fmb.lo; /* neg? store FMB */
|
||||||
else wd[0] = a->lo; } /* pos, store FMA */
|
else wd[0] = a->lo; /* pos, store FMA */
|
||||||
|
numwd = 1; } /* 1 word */
|
||||||
}
|
}
|
||||||
for (i = 0; i < numwd; i++) { /* store words */
|
for (i = 0; i < numwd; i++) { /* store words */
|
||||||
if (Write (addr, wd[i], WR)) return FP_MM;
|
if (Write (addr, wd[i], WR)) return FP_MM;
|
||||||
|
@ -483,7 +486,7 @@ while (((a->hi & UFP_FH_NORM) == 0) && /* normalize divd */
|
||||||
dp_lsh_1 (a, NULL); /* lsh divd, divr */
|
dp_lsh_1 (a, NULL); /* lsh divd, divr */
|
||||||
dp_lsh_1 (b, NULL); } /* can't carry out */
|
dp_lsh_1 (b, NULL); } /* can't carry out */
|
||||||
if (!(a->hi & UFP_FH_NORM) && (b->hi & UFP_FH_NORM)) { /* divr norm, divd not? */
|
if (!(a->hi & UFP_FH_NORM) && (b->hi & UFP_FH_NORM)) { /* divr norm, divd not? */
|
||||||
a->hi = a->lo = 0; /* result is 0 */
|
dp_swap (a, &fmq); /* quo = 0 (fmq), rem = a */
|
||||||
return FP_OK; }
|
return FP_OK; }
|
||||||
while ((b->hi & UFP_FH_NORM) == 0) { /* normalize divr */
|
while ((b->hi & UFP_FH_NORM) == 0) { /* normalize divr */
|
||||||
dp_lsh_1 (b, NULL); /* can't carry out */
|
dp_lsh_1 (b, NULL); /* can't carry out */
|
||||||
|
@ -562,7 +565,7 @@ if (a->hi | a->lo) { /* divd non-zero? */
|
||||||
for (i = 0; (fmq.hi & UFP_FH_NORM) == 0; i++) { /* until quo */
|
for (i = 0; (fmq.hi & UFP_FH_NORM) == 0; i++) { /* until quo */
|
||||||
dp_lsh_1 (&fmq, NULL); /* left shift quo */
|
dp_lsh_1 (&fmq, NULL); /* left shift quo */
|
||||||
if (dp_cmp (a, b) >= 0) { /* sub work? */
|
if (dp_cmp (a, b) >= 0) { /* sub work? */
|
||||||
dp_sub (a, b); /* a -= b */
|
dp_sub (a, b); /* a = a - b */
|
||||||
if (i == 0) a->exp = a->exp + 1;
|
if (i == 0) a->exp = a->exp + 1;
|
||||||
fmq.lo = fmq.lo | 1; } /* set quo bit */
|
fmq.lo = fmq.lo | 1; } /* set quo bit */
|
||||||
dp_lsh_1 (a, NULL); } /* left shift divd */
|
dp_lsh_1 (a, NULL); } /* left shift divd */
|
||||||
|
@ -768,7 +771,7 @@ PCQ_ENTRY; /* record branch */
|
||||||
PC = Incr_addr (PC); /* PC+1 for "JMS" */
|
PC = Incr_addr (PC); /* PC+1 for "JMS" */
|
||||||
mb = Jms_word (usmd); /* form JMS word */
|
mb = Jms_word (usmd); /* form JMS word */
|
||||||
if (Write (ma, mb, WR)) return SCPE_OK; /* store */
|
if (Write (ma, mb, WR)) return SCPE_OK; /* store */
|
||||||
PC = (jea + 1) & IAMASK; /* new PC */
|
PC = (ma + 1) & IAMASK; /* new PC */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
cpu central processor
|
cpu central processor
|
||||||
|
|
||||||
|
06-Nov-04 RMS Added =n to SHOW HISTORY
|
||||||
31-Dec-03 RMS Fixed bug in set_cpu_hist
|
31-Dec-03 RMS Fixed bug in set_cpu_hist
|
||||||
13-Oct-03 RMS Added instruction history
|
13-Oct-03 RMS Added instruction history
|
||||||
Added TSC8-75 support (from Bernhard Baehr)
|
Added TSC8-75 support (from Bernhard Baehr)
|
||||||
|
@ -298,7 +299,7 @@ MTAB cpu_mod[] = {
|
||||||
{ UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size },
|
{ UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size },
|
||||||
{ UNIT_MSIZE, 28672, NULL, "28K", &cpu_set_size },
|
{ UNIT_MSIZE, 28672, NULL, "28K", &cpu_set_size },
|
||||||
{ UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size },
|
{ UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size },
|
||||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "HISTORY", "HISTORY",
|
{ MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY",
|
||||||
&cpu_set_hist, &cpu_show_hist },
|
&cpu_set_hist, &cpu_show_hist },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
|
||||||
|
@ -1326,16 +1327,23 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)
|
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
{
|
{
|
||||||
int32 l, k, di;
|
int32 l, k, di, lnt;
|
||||||
|
char *cptr = (char *) desc;
|
||||||
|
t_stat r;
|
||||||
t_value sim_eval;
|
t_value sim_eval;
|
||||||
struct InstHistory *h;
|
struct InstHistory *h;
|
||||||
extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
|
extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
|
||||||
UNIT *uptr, int32 sw);
|
UNIT *uptr, int32 sw);
|
||||||
|
|
||||||
if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */
|
if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */
|
||||||
|
if (cptr) {
|
||||||
|
lnt = (int32) get_uint (cptr, 10, hst_lnt, &r);
|
||||||
|
if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; }
|
||||||
|
else lnt = hst_lnt;
|
||||||
|
di = hst_p - lnt; /* work forward */
|
||||||
|
if (di < 0) di = di + hst_lnt;
|
||||||
fprintf (st, "PC L AC MQ ea IR\n\n");
|
fprintf (st, "PC L AC MQ ea IR\n\n");
|
||||||
di = hst_p; /* work forward */
|
for (k = 0; k < lnt; k++) { /* print specified */
|
||||||
for (k = 0; k < hst_lnt; k++) { /* print specified */
|
|
||||||
h = &hst[(++di) % hst_lnt]; /* entry pointer */
|
h = &hst[(++di) % hst_lnt]; /* entry pointer */
|
||||||
if (h->pc & HIST_PC) { /* instruction? */
|
if (h->pc & HIST_PC) { /* instruction? */
|
||||||
l = (h->lac >> 12) & 1; /* link */
|
l = (h->lac >> 12) & 1; /* link */
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
To: Users
|
To: Users
|
||||||
From: Bob Supnik
|
From: Bob Supnik
|
||||||
Subj: PDP-8 Simulator Usage
|
Subj: PDP-8 Simulator Usage
|
||||||
Date: 15-Jun-2004
|
Date: 15-Nov-2004
|
||||||
|
|
||||||
COPYRIGHT NOTICE
|
COPYRIGHT NOTICE
|
||||||
|
|
||||||
|
@ -198,8 +198,9 @@ This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands:
|
||||||
|
|
||||||
SET CPU HISTORY clear history buffer
|
SET CPU HISTORY clear history buffer
|
||||||
SET CPU HISTORY=0 disable history
|
SET CPU HISTORY=0 disable history
|
||||||
SET CPU HISTORY=n enable history, display length = n
|
SET CPU HISTORY=n enable history, length = n
|
||||||
SHOW CPU HISTORY print CPU history
|
SHOW CPU HISTORY print CPU history
|
||||||
|
SHOW CPU HISTORY=n print first n entries of CPU history
|
||||||
|
|
||||||
The maximum length for the history is 65536 entries.
|
The maximum length for the history is 65536 entries.
|
||||||
|
|
||||||
|
@ -442,7 +443,7 @@ locked.
|
||||||
SET DTn LOCKED set unit n write locked
|
SET DTn LOCKED set unit n write locked
|
||||||
SET DTn WRITEENABLED set unit n write enabled
|
SET DTn WRITEENABLED set unit n write enabled
|
||||||
|
|
||||||
Units can also be set ONLINE or OFFLINE. The TD8E supports the BOOT command.
|
Units can also be set ENABLED or DISABLED. The TD8E supports the BOOT command.
|
||||||
|
|
||||||
The TD8E supports supports PDP-8 format, PDP-11 format, and 18b format
|
The TD8E supports supports PDP-8 format, PDP-11 format, and 18b format
|
||||||
DECtape images. ATTACH tries to determine the tape format from the DECtape
|
DECtape images. ATTACH tries to determine the tape format from the DECtape
|
||||||
|
@ -487,7 +488,7 @@ RK8E options include the ability to make units write enabled or write locked:
|
||||||
SET RKn LOCKED set unit n write locked
|
SET RKn LOCKED set unit n write locked
|
||||||
SET RKn WRITEENABLED set unit n write enabled
|
SET RKn WRITEENABLED set unit n write enabled
|
||||||
|
|
||||||
Units can also be set ONLINE or OFFLINE. The RK8E supports the BOOT command.
|
Units can also be set ENABLED or DISABLED. The RK8E supports the BOOT command.
|
||||||
|
|
||||||
The RK8E implements these registers:
|
The RK8E implements these registers:
|
||||||
|
|
||||||
|
@ -719,7 +720,7 @@ locked.
|
||||||
SET DTn LOCKED set unit n write locked
|
SET DTn LOCKED set unit n write locked
|
||||||
SET DTn WRITEENABLED set unit n write enabled
|
SET DTn WRITEENABLED set unit n write enabled
|
||||||
|
|
||||||
Units can also be set ONLINE or OFFLINE. The TC08 supports the BOOT command.
|
Units can also be set ENABLED or DISABLED. The TC08 supports the BOOT command.
|
||||||
|
|
||||||
The TC08 supports supports PDP-8 format, PDP-11 format, and 18b format
|
The TC08 supports supports PDP-8 format, PDP-11 format, and 18b format
|
||||||
DECtape images. ATTACH tries to determine the tape format from the DECtape
|
DECtape images. ATTACH tries to determine the tape format from the DECtape
|
||||||
|
@ -771,7 +772,7 @@ or write locked.
|
||||||
SET MTn LOCKED set unit n write locked
|
SET MTn LOCKED set unit n write locked
|
||||||
SET MTn WRITEENABLED set unit n write enabled
|
SET MTn WRITEENABLED set unit n write enabled
|
||||||
|
|
||||||
Units can also be set ONLINE or OFFLINE.
|
Units can also be set ENABLED or DISABLED.
|
||||||
|
|
||||||
The magnetic tape controller implements these registers:
|
The magnetic tape controller implements these registers:
|
||||||
|
|
||||||
|
|
|
@ -507,7 +507,7 @@ for (i = 0; i < RL_NUMDR; i++) {
|
||||||
uptr = rl_dev.units + i;
|
uptr = rl_dev.units + i;
|
||||||
sim_cancel (uptr);
|
sim_cancel (uptr);
|
||||||
uptr->STAT = 0; }
|
uptr->STAT = 0; }
|
||||||
if (rlxb == NULL) rlxb = calloc (RL_MAXFR, sizeof (unsigned int8));
|
if (rlxb == NULL) rlxb = calloc (RL_MAXFR, sizeof (uint8));
|
||||||
if (rlxb == NULL) return SCPE_MEM;
|
if (rlxb == NULL) return SCPE_MEM;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -396,7 +396,7 @@ extern int32 dsk1 (int32 op, int32 m, int32 n, int32 data);
|
||||||
extern int32 dsk2 (int32 op, int32 m, int32 n, int32 data);
|
extern int32 dsk2 (int32 op, int32 m, int32 n, int32 data);
|
||||||
extern int32 cpu (int32 op, int32 m, int32 n, int32 data);
|
extern int32 cpu (int32 op, int32 m, int32 n, int32 data);
|
||||||
extern t_stat sim_activate (UNIT *uptr, int32 delay);
|
extern t_stat sim_activate (UNIT *uptr, int32 delay);
|
||||||
extern int32 fprint_sym (FILE *of, int32 addr, unsigned int32 *val,
|
extern int32 fprint_sym (FILE *of, int32 addr, uint32 *val,
|
||||||
UNIT *uptr, int32 sw);
|
UNIT *uptr, int32 sw);
|
||||||
int32 nulldev (int32 opcode, int32 m, int32 n, int32 data);
|
int32 nulldev (int32 opcode, int32 m, int32 n, int32 data);
|
||||||
int add_zoned (int32 addr1, int32 len1, int32 addr2, int32 len2);
|
int add_zoned (int32 addr1, int32 len1, int32 addr2, int32 len2);
|
||||||
|
|
|
@ -44,7 +44,7 @@ extern int32 saved_PC, IAR[];
|
||||||
extern char ebcdic_to_ascii[256];
|
extern char ebcdic_to_ascii[256];
|
||||||
char *parse_addr(char *cptr, char *gbuf, int32 *addr, int32 *addrtype);
|
char *parse_addr(char *cptr, char *gbuf, int32 *addr, int32 *addrtype);
|
||||||
|
|
||||||
int32 printf_sym (FILE *of, char *strg, int32 addr, unsigned int32 *val,
|
int32 printf_sym (FILE *of, char *strg, int32 addr, uint32 *val,
|
||||||
UNIT *uptr, int32 sw);
|
UNIT *uptr, int32 sw);
|
||||||
|
|
||||||
/* SCP data structures
|
/* SCP data structures
|
||||||
|
@ -246,7 +246,7 @@ return (SCPE_OK);
|
||||||
status = error code
|
status = error code
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int32 fprint_sym (FILE *of, int32 addr, unsigned int32 *val,
|
int32 fprint_sym (FILE *of, int32 addr, uint32 *val,
|
||||||
UNIT *uptr, int32 sw)
|
UNIT *uptr, int32 sw)
|
||||||
{
|
{
|
||||||
int32 r;
|
int32 r;
|
||||||
|
@ -261,7 +261,7 @@ int32 fprint_sym (FILE *of, int32 addr, unsigned int32 *val,
|
||||||
return (r);
|
return (r);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 printf_sym (FILE *of, char *strg, int32 addr, unsigned int32 *val,
|
int32 printf_sym (FILE *of, char *strg, int32 addr, uint32 *val,
|
||||||
UNIT *uptr, int32 sw)
|
UNIT *uptr, int32 sw)
|
||||||
{
|
{
|
||||||
int32 cflag, c1, c2, group, len1, len2, inst, aaddr, baddr;
|
int32 cflag, c1, c2, group, len1, len2, inst, aaddr, baddr;
|
||||||
|
@ -496,7 +496,7 @@ return -(oplen - 1);
|
||||||
status = error status
|
status = error status
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int32 parse_sym (char *cptr, int32 addr, UNIT *uptr, unsigned int32 *val, int32 sw)
|
int32 parse_sym (char *cptr, int32 addr, UNIT *uptr, uint32 *val, int32 sw)
|
||||||
{
|
{
|
||||||
int32 cflag, i = 0, j, r, oplen, addtyp, saveaddr, vptr;
|
int32 cflag, i = 0, j, r, oplen, addtyp, saveaddr, vptr;
|
||||||
char gbuf[CBUFSIZE];
|
char gbuf[CBUFSIZE];
|
||||||
|
|
121
SDS/sds_cpu.c
121
SDS/sds_cpu.c
|
@ -23,6 +23,12 @@
|
||||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
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.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
cpu central processor
|
||||||
|
rtc real time clock
|
||||||
|
|
||||||
|
07-Nov-04 RMS Added instruction history
|
||||||
|
01-Mar-03 RMS Added SET/SHOW RTC FREQ support
|
||||||
|
|
||||||
The system state for the SDS 940 is:
|
The system state for the SDS 940 is:
|
||||||
|
|
||||||
A<0:23> A register
|
A<0:23> A register
|
||||||
|
@ -38,11 +44,6 @@
|
||||||
EM2<0:2> memory extension, block 2
|
EM2<0:2> memory extension, block 2
|
||||||
EM3<0:2> memory extension, block 3
|
EM3<0:2> memory extension, block 3
|
||||||
bpt breakpoint switches
|
bpt breakpoint switches
|
||||||
|
|
||||||
cpu central processor
|
|
||||||
rtc real time clock
|
|
||||||
|
|
||||||
01-Mar-03 RMS Added SET/SHOW RTC FREQ support
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* The SDS 940 has three instruction format -- memory reference, register change,
|
/* The SDS 940 has three instruction format -- memory reference, register change,
|
||||||
|
@ -137,6 +138,21 @@
|
||||||
#define UNIT_V_MSIZE (UNIT_V_GENIE + 1) /* dummy mask */
|
#define UNIT_V_MSIZE (UNIT_V_GENIE + 1) /* dummy mask */
|
||||||
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
|
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
|
||||||
|
|
||||||
|
#define HIST_XCT 1 /* instruction */
|
||||||
|
#define HIST_INT 2 /* interrupt cycle */
|
||||||
|
#define HIST_TRP 3 /* trap cycle */
|
||||||
|
#define HIST_MIN 64
|
||||||
|
#define HIST_MAX 65536
|
||||||
|
#define HIST_NOEA 0x40000000
|
||||||
|
struct InstHistory {
|
||||||
|
uint32 typ;
|
||||||
|
uint32 pc;
|
||||||
|
uint32 ir;
|
||||||
|
uint32 a;
|
||||||
|
uint32 b;
|
||||||
|
uint32 x;
|
||||||
|
uint32 ea; };
|
||||||
|
|
||||||
uint32 M[MAXMEMSIZE] = { 0 }; /* memory */
|
uint32 M[MAXMEMSIZE] = { 0 }; /* memory */
|
||||||
uint32 A, B, X; /* registers */
|
uint32 A, B, X; /* registers */
|
||||||
uint32 P; /* program counter */
|
uint32 P; /* program counter */
|
||||||
|
@ -169,6 +185,9 @@ int32 stop_inviop = 1; /* stop inv io op */
|
||||||
uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
|
uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
|
||||||
int32 pcq_p = 0; /* PC queue ptr */
|
int32 pcq_p = 0; /* PC queue ptr */
|
||||||
REG *pcq_r = NULL; /* PC queue reg ptr */
|
REG *pcq_r = NULL; /* PC queue reg ptr */
|
||||||
|
int32 hst_p = 0; /* history pointer */
|
||||||
|
int32 hst_lnt = 0; /* history length */
|
||||||
|
struct InstHistory *hst = NULL; /* instruction history */
|
||||||
int32 rtc_pie = 0; /* rtc pulse ie */
|
int32 rtc_pie = 0; /* rtc pulse ie */
|
||||||
int32 rtc_tps = 60; /* rtc ticks/sec */
|
int32 rtc_tps = 60; /* rtc ticks/sec */
|
||||||
|
|
||||||
|
@ -181,6 +200,8 @@ t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
|
||||||
t_stat cpu_reset (DEVICE *dptr);
|
t_stat cpu_reset (DEVICE *dptr);
|
||||||
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
t_stat cpu_set_type (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat cpu_set_type (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
t_stat Ea (uint32 wd, uint32 *va);
|
t_stat Ea (uint32 wd, uint32 *va);
|
||||||
t_stat EaSh (uint32 wd, uint32 *va);
|
t_stat EaSh (uint32 wd, uint32 *va);
|
||||||
t_stat Read (uint32 va, uint32 *dat);
|
t_stat Read (uint32 va, uint32 *dat);
|
||||||
|
@ -195,6 +216,7 @@ void Div48 (uint32 dvdh, uint32 dvdl, uint32 dvr);
|
||||||
void RotR48 (uint32 sc);
|
void RotR48 (uint32 sc);
|
||||||
void ShfR48 (uint32 sc, uint32 sgn);
|
void ShfR48 (uint32 sc, uint32 sgn);
|
||||||
t_stat one_inst (uint32 inst, uint32 pc, uint32 mode);
|
t_stat one_inst (uint32 inst, uint32 pc, uint32 mode);
|
||||||
|
void inst_hist (uint32 inst, uint32 pc, uint32 typ);
|
||||||
t_stat rtc_inst (uint32 inst);
|
t_stat rtc_inst (uint32 inst);
|
||||||
t_stat rtc_svc (UNIT *uptr);
|
t_stat rtc_svc (UNIT *uptr);
|
||||||
t_stat rtc_reset (DEVICE *dptr);
|
t_stat rtc_reset (DEVICE *dptr);
|
||||||
|
@ -262,6 +284,8 @@ MTAB cpu_mod[] = {
|
||||||
{ UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size },
|
{ UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size },
|
||||||
{ UNIT_MSIZE, 49152, NULL, "48K", &cpu_set_size },
|
{ UNIT_MSIZE, 49152, NULL, "48K", &cpu_set_size },
|
||||||
{ UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size },
|
{ UNIT_MSIZE, 65536, NULL, "64K", &cpu_set_size },
|
||||||
|
{ MTAB_XTD|MTAB_VDV|MTAB_NMO|MTAB_SHP, 0, "HISTORY", "HISTORY",
|
||||||
|
&cpu_set_hist, &cpu_show_hist },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
|
||||||
DEVICE cpu_dev = {
|
DEVICE cpu_dev = {
|
||||||
|
@ -371,6 +395,7 @@ if (ion && !ion_defer && int_reqhi) { /* int request? */
|
||||||
tinst = ReadP (pa); /* get inst */
|
tinst = ReadP (pa); /* get inst */
|
||||||
save_mode = usr_mode; /* save mode */
|
save_mode = usr_mode; /* save mode */
|
||||||
usr_mode = 0; /* switch to mon */
|
usr_mode = 0; /* switch to mon */
|
||||||
|
if (hst_lnt) inst_hist (tinst, P, HIST_INT); /* record inst */
|
||||||
if (pa != VEC_RTCP) { /* normal intr? */
|
if (pa != VEC_RTCP) { /* normal intr? */
|
||||||
tr = one_inst (tinst, P, save_mode); /* exec intr inst */
|
tr = one_inst (tinst, P, save_mode); /* exec intr inst */
|
||||||
if (tr) { /* stop code? */
|
if (tr) { /* stop code? */
|
||||||
|
@ -396,6 +421,7 @@ else { /* normal instr */
|
||||||
P = (P + 1) & VA_MASK; /* incr PC */
|
P = (P + 1) & VA_MASK; /* incr PC */
|
||||||
if (reason == SCPE_OK) { /* fetch ok? */
|
if (reason == SCPE_OK) { /* fetch ok? */
|
||||||
ion_defer = 0; /* clear ion */
|
ion_defer = 0; /* clear ion */
|
||||||
|
if (hst_lnt) inst_hist (inst, save_P, HIST_XCT);
|
||||||
reason = one_inst (inst, save_P, usr_mode); /* exec inst */
|
reason = one_inst (inst, save_P, usr_mode); /* exec inst */
|
||||||
if (reason > 0) { /* stop code? */
|
if (reason > 0) { /* stop code? */
|
||||||
if (reason != STOP_HALT) P = save_P;
|
if (reason != STOP_HALT) P = save_P;
|
||||||
|
@ -411,6 +437,7 @@ else { /* normal instr */
|
||||||
save_mode = usr_mode; /* save mode */
|
save_mode = usr_mode; /* save mode */
|
||||||
usr_mode = 0; /* switch to mon */
|
usr_mode = 0; /* switch to mon */
|
||||||
mon_usr_trap = 0;
|
mon_usr_trap = 0;
|
||||||
|
if (hst_lnt) inst_hist (tinst, save_P, HIST_TRP);
|
||||||
tr = one_inst (tinst, save_P, save_mode); /* trap inst */
|
tr = one_inst (tinst, save_P, save_mode); /* trap inst */
|
||||||
if (tr) { /* stop code? */
|
if (tr) { /* stop code? */
|
||||||
usr_mode = save_mode; /* restore mode */
|
usr_mode = save_mode; /* restore mode */
|
||||||
|
@ -838,7 +865,9 @@ t_stat r;
|
||||||
for (i = 0; i < ind_lim; i++) { /* count indirects */
|
for (i = 0; i < ind_lim; i++) { /* count indirects */
|
||||||
if (wd & I_IDX) va = (va & VA_USR) | ((va + X) & VA_MASK);
|
if (wd & I_IDX) va = (va & VA_USR) | ((va + X) & VA_MASK);
|
||||||
*addr = va;
|
*addr = va;
|
||||||
if ((wd & I_IND) == 0) return SCPE_OK; /* indirect? */
|
if ((wd & I_IND) == 0) { /* end of ind chain? */
|
||||||
|
if (hst_lnt) hst[hst_p].ea = *addr; /* record */
|
||||||
|
return SCPE_OK; }
|
||||||
if (r = Read (va, &wd)) return r; /* read ind; fails? */
|
if (r = Read (va, &wd)) return r; /* read ind; fails? */
|
||||||
va = (va & VA_USR) | (wd & XVA_MASK);
|
va = (va & VA_USR) | (wd & XVA_MASK);
|
||||||
}
|
}
|
||||||
|
@ -859,6 +888,7 @@ for (i = 0; i < ind_lim; i++) { /* count indirects */
|
||||||
if (wd & I_IDX) *addr = (va & (VA_MASK & ~I_SHFMSK)) |
|
if (wd & I_IDX) *addr = (va & (VA_MASK & ~I_SHFMSK)) |
|
||||||
((va + X) & I_SHFMSK); /* 9b indexing */
|
((va + X) & I_SHFMSK); /* 9b indexing */
|
||||||
else *addr = va & VA_MASK;
|
else *addr = va & VA_MASK;
|
||||||
|
if (hst_lnt) hst[hst_p].ea = *addr; /* record */
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
if (wd & I_IDX) va = (va & VA_USR) | ((va + X) & VA_MASK);
|
if (wd & I_IDX) va = (va & VA_USR) | ((va + X) & VA_MASK);
|
||||||
if (r = Read (va, &wd)) return r; /* read ind; fails? */
|
if (r = Read (va, &wd)) return r; /* read ind; fails? */
|
||||||
|
@ -1280,3 +1310,82 @@ t_stat rtc_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
fprintf (st, (rtc_tps == 50)? "50Hz": "60Hz");
|
fprintf (st, (rtc_tps == 50)? "50Hz": "60Hz");
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Record history */
|
||||||
|
|
||||||
|
void inst_hist (uint32 ir, uint32 pc, uint32 tp)
|
||||||
|
{
|
||||||
|
hst_p = (hst_p + 1); /* next entry */
|
||||||
|
if (hst_p >= hst_lnt) hst_p = 0;
|
||||||
|
hst[hst_p].typ = tp | (OV << 4);
|
||||||
|
hst[hst_p].pc = pc;
|
||||||
|
hst[hst_p].ir = ir;
|
||||||
|
hst[hst_p].a = A;
|
||||||
|
hst[hst_p].b = B;
|
||||||
|
hst[hst_p].x = X;
|
||||||
|
hst[hst_p].ea = HIST_NOEA;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set history */
|
||||||
|
|
||||||
|
t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
int32 i, lnt;
|
||||||
|
t_stat r;
|
||||||
|
|
||||||
|
if (cptr == NULL) {
|
||||||
|
for (i = 0; i < hst_lnt; i++) hst[i].typ = 0;
|
||||||
|
hst_p = 0;
|
||||||
|
return SCPE_OK; }
|
||||||
|
lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r);
|
||||||
|
if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG;
|
||||||
|
hst_p = 0;
|
||||||
|
if (hst_lnt) {
|
||||||
|
free (hst);
|
||||||
|
hst_lnt = 0;
|
||||||
|
hst = NULL; }
|
||||||
|
if (lnt) {
|
||||||
|
hst = calloc (sizeof (struct InstHistory), lnt);
|
||||||
|
if (hst == NULL) return SCPE_MEM;
|
||||||
|
hst_lnt = lnt; }
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Show history */
|
||||||
|
|
||||||
|
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
|
{
|
||||||
|
int32 ov, k, di, lnt;
|
||||||
|
char *cptr = (char *) desc;
|
||||||
|
t_stat r;
|
||||||
|
t_value sim_eval;
|
||||||
|
struct InstHistory *h;
|
||||||
|
extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
|
||||||
|
UNIT *uptr, int32 sw);
|
||||||
|
static char *cyc[] = { " ", " ", "INT", "TRP" };
|
||||||
|
|
||||||
|
if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */
|
||||||
|
if (cptr) {
|
||||||
|
lnt = (int32) get_uint (cptr, 10, hst_lnt, &r);
|
||||||
|
if ((r != SCPE_OK) || (lnt == 0)) return SCPE_ARG; }
|
||||||
|
else lnt = hst_lnt;
|
||||||
|
di = hst_p - lnt; /* work forward */
|
||||||
|
if (di < 0) di = di + hst_lnt;
|
||||||
|
fprintf (st, "CYC PC OV A B X EA IR\n\n");
|
||||||
|
for (k = 0; k < lnt; k++) { /* print specified */
|
||||||
|
h = &hst[(++di) % hst_lnt]; /* entry pointer */
|
||||||
|
if (h->typ) { /* instruction? */
|
||||||
|
ov = (h->typ >> 4) & 1; /* overflow */
|
||||||
|
fprintf (st, "%s %05o %o %08o %08o %08o ", cyc[h->typ & 3],
|
||||||
|
h->pc, ov, h->a, h->b, h->x);
|
||||||
|
if (h->ea & HIST_NOEA) fprintf (st, " ");
|
||||||
|
else fprintf (st, "%05o ", h->ea);
|
||||||
|
sim_eval = h->ir;
|
||||||
|
if ((fprint_sym (st, h->pc, &sim_eval, &cpu_unit, SWMASK ('M'))) > 0)
|
||||||
|
fprintf (st, "(undefined) %08o", h->ir);
|
||||||
|
fputc ('\n', st); /* end line */
|
||||||
|
} /* end else instruction */
|
||||||
|
} /* end for */
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
To: Users
|
To: Users
|
||||||
From: Bob Supnik
|
From: Bob Supnik
|
||||||
Subj: SDS 940 Simulator Usage
|
Subj: SDS 940 Simulator Usage
|
||||||
Date: 15-Feb-2004
|
Date: 15-Nov-2004
|
||||||
|
|
||||||
COPYRIGHT NOTICE
|
COPYRIGHT NOTICE
|
||||||
|
|
||||||
|
@ -142,6 +142,17 @@ control registers for the interrupt system.
|
||||||
most recent P change first
|
most recent P change first
|
||||||
WRU 8 interrupt character
|
WRU 8 interrupt character
|
||||||
|
|
||||||
|
The CPU can maintain a history of the most recently executed instructions.
|
||||||
|
This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands:
|
||||||
|
|
||||||
|
SET CPU HISTORY clear history buffer
|
||||||
|
SET CPU HISTORY=0 disable history
|
||||||
|
SET CPU HISTORY=n enable history, length = n
|
||||||
|
SHOW CPU HISTORY print CPU history
|
||||||
|
SHOW CPU HISTORY=n print first n entries of CPU history
|
||||||
|
|
||||||
|
The maximum length for the history is 65536 entries.
|
||||||
|
|
||||||
2.2 Channels (CHAN)
|
2.2 Channels (CHAN)
|
||||||
|
|
||||||
The SDS 940 has up to eight I/O channels, designated W, Y, C, D, E, F, G,
|
The SDS 940 has up to eight I/O channels, designated W, Y, C, D, E, F, G,
|
||||||
|
@ -481,7 +492,7 @@ MT options include the ability to make units write enabled or write locked.
|
||||||
SET MTn LOCKED set unit n write locked
|
SET MTn LOCKED set unit n write locked
|
||||||
SET MTn WRITEENABLED set unit n write enabled
|
SET MTn WRITEENABLED set unit n write enabled
|
||||||
|
|
||||||
Units can also be set ONLINE or OFFLINE.
|
Units can also be set ENABLED or DISABLED.
|
||||||
|
|
||||||
The magnetic tape implements these registers:
|
The magnetic tape implements these registers:
|
||||||
|
|
||||||
|
|
405
VAX/vax780_defs.h
Normal file
405
VAX/vax780_defs.h
Normal file
|
@ -0,0 +1,405 @@
|
||||||
|
/* vax780_defs.h: VAX 780 model-specific definitions file
|
||||||
|
|
||||||
|
Copyright (c) 2004, 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"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
This file covers the VAX 11/780, the first VAX.
|
||||||
|
|
||||||
|
System memory map
|
||||||
|
|
||||||
|
0000 0000 - 1FFF FFFF main memory
|
||||||
|
|
||||||
|
2000 0000 - 2001 FFFF nexus register space
|
||||||
|
2002 0000 - 200F FFFF reserved
|
||||||
|
2010 0000 - 2013 FFFF Unibus address space, Unibus 0
|
||||||
|
2014 0000 - 2017 FFFF Unibus address space, Unibus 1
|
||||||
|
2018 0000 - 201B FFFF Unibus address space, Unibus 2
|
||||||
|
201C 0000 - 201F FFFF Unibus address space, Unibus 3
|
||||||
|
2020 0000 - 3FFF FFFF reserved
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Microcode constructs */
|
||||||
|
|
||||||
|
#ifndef FULL_VAX
|
||||||
|
#define FULL_VAX 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _VAX_780_DEFS_H_
|
||||||
|
#define _VAX_780_DEFS_H_ 1
|
||||||
|
|
||||||
|
#define VAX780_SID (1 << 24) /* system ID */
|
||||||
|
#define VAX780_ECO (7 << 19) /* ucode revision */
|
||||||
|
#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 */
|
||||||
|
#define MCHK_IBUF 0x0D /* read istream */
|
||||||
|
|
||||||
|
/* Interrupts */
|
||||||
|
|
||||||
|
#define IPL_HMAX 0x17 /* highest hwre level */
|
||||||
|
#define IPL_HMIN 0x14 /* lowest hwre level */
|
||||||
|
#define IPL_HLVL (IPL_HMAX - IPL_HMIN + 1) /* # hardware levels */
|
||||||
|
#define IPL_SMAX 0xF /* highest swre level */
|
||||||
|
|
||||||
|
/* Nexus constants */
|
||||||
|
|
||||||
|
#define NEXUS_NUM 16 /* number of nexus */
|
||||||
|
#define MCTL_NUM 2 /* number of mem ctrl */
|
||||||
|
#define MBA_NUM 2 /* number of MBA's */
|
||||||
|
#define TR_MCTL0 1 /* nexus assignments */
|
||||||
|
#define TR_MCTL1 2
|
||||||
|
#define TR_UBA 3
|
||||||
|
#define TR_MBA0 8
|
||||||
|
#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 */
|
||||||
|
|
||||||
|
/* Internal I/O interrupts - relative except for clock and console */
|
||||||
|
|
||||||
|
#define IPL_CLKINT 0x18 /* clock IPL */
|
||||||
|
#define IPL_TTINT 0x14 /* console IPL */
|
||||||
|
|
||||||
|
#define IPL_MCTL0 (0x15 - IPL_HMIN)
|
||||||
|
#define IPL_MCTL1 (0x15 - IPL_HMIN)
|
||||||
|
#define IPL_UBA (0x15 - IPL_HMIN)
|
||||||
|
#define IPL_MBA0 (0x15 - IPL_HMIN)
|
||||||
|
#define IPL_MBA1 (0x15 - IPL_HMIN)
|
||||||
|
|
||||||
|
/* Nexus interrupt macros */
|
||||||
|
|
||||||
|
#define SET_NEXUS_INT(dv) nexus_req[IPL_##dv] |= (1 << TR_##dv)
|
||||||
|
#define CLR_NEXUS_INT(dv) nexus_req[IPL_##dv] &= ~(1 << TR_##dv)
|
||||||
|
|
||||||
|
/* Machine specific IPRs */
|
||||||
|
|
||||||
|
#define MT_ACCS 40 /* FPA control */
|
||||||
|
#define MT_ACCR 41 /* FPA maint */
|
||||||
|
#define MT_WCSA 44 /* WCS address */
|
||||||
|
#define MT_WCSD 45 /* WCS data */
|
||||||
|
#define MT_SBIFS 48 /* SBI fault status */
|
||||||
|
#define MT_SBIS 49 /* SBI silo */
|
||||||
|
#define MT_SBISC 50 /* SBI silo comparator */
|
||||||
|
#define MT_SBIMT 51 /* SBI maint */
|
||||||
|
#define MT_SBIER 52 /* SBI error */
|
||||||
|
#define MT_SBITA 53 /* SBI timeout addr */
|
||||||
|
#define MT_SBIQC 54 /* SBI timeout clear */
|
||||||
|
#define MT_MBRK 60 /* microbreak */
|
||||||
|
|
||||||
|
/* Memory */
|
||||||
|
|
||||||
|
#define MAXMEMWIDTH 23 /* max mem, MS780C */
|
||||||
|
#define MAXMEMSIZE (1 << MAXMEMWIDTH)
|
||||||
|
#define MAXMEMWIDTH_X 27 /* max mem, MS780E */
|
||||||
|
#define MAXMEMSIZE_X (1 << MAXMEMWIDTH_X)
|
||||||
|
#define INITMEMSIZE (1 << MAXMEMWIDTH) /* initial memory size */
|
||||||
|
#define MEMSIZE (cpu_unit.capac)
|
||||||
|
#define ADDR_IS_MEM(x) (((uint32) (x)) < MEMSIZE)
|
||||||
|
|
||||||
|
/* Unibus I/O registers */
|
||||||
|
|
||||||
|
#define UBADDRWIDTH 18 /* Unibus addr width */
|
||||||
|
#define UBADDRSIZE (1u << UBADDRWIDTH) /* Unibus addr length */
|
||||||
|
#define UBADDRMASK (UBADDRSIZE - 1) /* Unibus addr mask */
|
||||||
|
#define IOPAGEAWIDTH 13 /* IO addr width */
|
||||||
|
#define IOPAGESIZE (1u << IOPAGEAWIDTH) /* IO page length */
|
||||||
|
#define IOPAGEMASK (IOPAGESIZE - 1) /* IO addr mask */
|
||||||
|
#define UBADDRBASE 0x20100000 /* Unibus addr base */
|
||||||
|
#define IOPAGEBASE 0x2013E000 /* IO page base */
|
||||||
|
#define ADDR_IS_IO(x) ((((uint32) (x)) >= UBADDRBASE) && \
|
||||||
|
(((uint32) (x)) < (UBADDRBASE + UBADDRSIZE)))
|
||||||
|
#define ADDR_IS_IOP(x) (((uint32) (x)) >= IOPAGEBASE)
|
||||||
|
|
||||||
|
/* Nexus register space */
|
||||||
|
|
||||||
|
#define REGAWIDTH 17 /* REG addr width */
|
||||||
|
#define REG_V_NEXUS 13 /* nexus number */
|
||||||
|
#define REG_M_NEXUS 0xF
|
||||||
|
#define REG_V_OFS 2 /* register number */
|
||||||
|
#define REG_M_OFS 0x7FF
|
||||||
|
#define REGSIZE (1u << REGAWIDTH) /* REG length */
|
||||||
|
#define REGBASE 0x20000000 /* REG addr base */
|
||||||
|
#define ADDR_IS_REG(x) ((((uint32) (x)) >= REGBASE) && \
|
||||||
|
(((uint32) (x)) < (REGBASE + REGSIZE)))
|
||||||
|
#define NEXUS_GETNEX(x) (((x) >> REG_V_NEXUS) & REG_M_NEXUS)
|
||||||
|
#define NEXUS_GETOFS(x) (((x) >> REG_V_OFS) & REG_M_OFS)
|
||||||
|
|
||||||
|
/* ROM address space in memory controllers */
|
||||||
|
|
||||||
|
#define ROMAWIDTH 12 /* ROM addr width */
|
||||||
|
#define ROMSIZE (1u << ROMAWIDTH) /* ROM size */
|
||||||
|
#define ROM0BASE (REGBASE + (TR_MCTL0 << REG_V_NEXUS) + 0x1000)
|
||||||
|
#define ROM1BASE (REGBASE + (TR_MCTL1 << REG_V_NEXUS) + 0x1000)
|
||||||
|
#define ADDR_IS_ROM0(x) ((((uint32) (x)) >= ROM0BASE) && \
|
||||||
|
(((uint32) (x)) < (ROM0BASE + ROMSIZE)))
|
||||||
|
#define ADDR_IS_ROM1(x) ((((uint32) (x)) >= ROM1BASE) && \
|
||||||
|
(((uint32) (x)) < (ROM1BASE + ROMSIZE)))
|
||||||
|
#define ADDR_IS_ROM(x) (ADDR_IS_ROM0 (x) || ADDR_IS_ROM1 (x))
|
||||||
|
|
||||||
|
/* Other address spaces */
|
||||||
|
|
||||||
|
#define ADDR_IS_CDG(x) (0)
|
||||||
|
#define ADDR_IS_NVR(x) (0)
|
||||||
|
|
||||||
|
/* Unibus I/O modes */
|
||||||
|
|
||||||
|
#define READ 0 /* PDP-11 compatibility */
|
||||||
|
#define WRITE (L_WORD)
|
||||||
|
#define WRITEB (L_BYTE)
|
||||||
|
|
||||||
|
/* Common CSI flags */
|
||||||
|
|
||||||
|
#define CSR_V_GO 0 /* go */
|
||||||
|
#define CSR_V_IE 6 /* interrupt enable */
|
||||||
|
#define CSR_V_DONE 7 /* done */
|
||||||
|
#define CSR_V_BUSY 11 /* busy */
|
||||||
|
#define CSR_V_ERR 15 /* error */
|
||||||
|
#define CSR_GO (1u << CSR_V_GO)
|
||||||
|
#define CSR_IE (1u << CSR_V_IE)
|
||||||
|
#define CSR_DONE (1u << CSR_V_DONE)
|
||||||
|
#define CSR_BUSY (1u << CSR_V_BUSY)
|
||||||
|
#define CSR_ERR (1u << CSR_V_ERR)
|
||||||
|
|
||||||
|
/* Timers */
|
||||||
|
|
||||||
|
#define TMR_CLK 0 /* 100Hz clock */
|
||||||
|
|
||||||
|
/* I/O system definitions */
|
||||||
|
|
||||||
|
#define DZ_MUXES 4 /* max # of DZV muxes */
|
||||||
|
#define DZ_LINES 8 /* lines per DZV mux */
|
||||||
|
#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 */
|
||||||
|
#define DEV_V_NEXUS (DEV_V_UF + 2) /* Nexus */
|
||||||
|
#define DEV_V_FLTA (DEV_V_UF + 3) /* flt addr */
|
||||||
|
#define DEV_V_FFUF (DEV_V_UF + 4) /* first free flag */
|
||||||
|
#define DEV_UBUS (1u << DEV_V_UBUS)
|
||||||
|
#define DEV_MBUS (1u << DEV_V_MBUS)
|
||||||
|
#define DEV_NEXUS (1u << DEV_V_NEXUS)
|
||||||
|
#define DEV_FLTA (1u << DEV_V_FLTA)
|
||||||
|
#define DEV_QBUS (0)
|
||||||
|
#define DEV_Q18 (0)
|
||||||
|
|
||||||
|
#define UNIBUS TRUE /* Unibus only */
|
||||||
|
|
||||||
|
#define DEV_RDX 16 /* default device radix */
|
||||||
|
|
||||||
|
/* Device information block
|
||||||
|
|
||||||
|
For Massbus devices,
|
||||||
|
ba = Massbus number
|
||||||
|
lnt = Massbus ctrl type
|
||||||
|
ack[0] = abort routine
|
||||||
|
|
||||||
|
For Nexus devices,
|
||||||
|
ba = Nexus number
|
||||||
|
lnt = number of consecutive nexi */
|
||||||
|
|
||||||
|
#define VEC_DEVMAX 4 /* max device vec */
|
||||||
|
|
||||||
|
struct pdp_dib {
|
||||||
|
uint32 ba; /* base addr */
|
||||||
|
uint32 lnt; /* length */
|
||||||
|
t_stat (*rd)(int32 *dat, int32 ad, int32 md);
|
||||||
|
t_stat (*wr)(int32 dat, int32 ad, int32 md);
|
||||||
|
int32 vnum; /* vectors: number */
|
||||||
|
int32 vloc; /* locator */
|
||||||
|
int32 vec; /* value */
|
||||||
|
int32 (*ack[VEC_DEVMAX])(void); /* ack routine */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct pdp_dib DIB;
|
||||||
|
|
||||||
|
/* Unibus I/O page layout - XUB,RQB,RQC,RQD float based on number of DZ's
|
||||||
|
Massbus devices (RP, TU) do not appear in the Unibus IO page */
|
||||||
|
|
||||||
|
#define IOBA_DZ (IOPAGEBASE + 000100) /* DZ11 */
|
||||||
|
#define IOLN_DZ 010
|
||||||
|
#define IOBA_XUB (IOPAGEBASE + 000330 + (020 * (DZ_MUXES / 2)))
|
||||||
|
#define IOLN_XUB 010
|
||||||
|
#define IOBA_RQB (IOPAGEBASE + 000334 + (020 * (DZ_MUXES / 2)))
|
||||||
|
#define IOLN_RQB 004
|
||||||
|
#define IOBA_RQC (IOPAGEBASE + IOBA_RQB + IOLN_RQB)
|
||||||
|
#define IOLN_RQC 004
|
||||||
|
#define IOBA_RQD (IOPAGEBASE + IOBA_RQC + IOLN_RQC)
|
||||||
|
#define IOLN_RQD 004
|
||||||
|
#define IOBA_RQ (IOPAGEBASE + 012150) /* UDA50 */
|
||||||
|
#define IOLN_RQ 004
|
||||||
|
#define IOBA_TS (IOPAGEBASE + 012520) /* TS11 */
|
||||||
|
#define IOLN_TS 004
|
||||||
|
#define IOBA_RL (IOPAGEBASE + 014400) /* RL11 */
|
||||||
|
#define IOLN_RL 012
|
||||||
|
#define IOBA_TQ (IOPAGEBASE + 014500) /* TMSCP */
|
||||||
|
#define IOLN_TQ 004
|
||||||
|
#define IOBA_XU (IOPAGEBASE + 014510) /* DEUNA/DELUA */
|
||||||
|
#define IOLN_XU 010
|
||||||
|
#define IOBA_RX (IOPAGEBASE + 017170) /* RX11 */
|
||||||
|
#define IOLN_RX 004
|
||||||
|
#define IOBA_RY (IOPAGEBASE + 017170) /* RXV21 */
|
||||||
|
#define IOLN_RY 004
|
||||||
|
#define IOBA_HK (IOPAGEBASE + 017440) /* RK611 */
|
||||||
|
#define IOLN_HK 040
|
||||||
|
#define IOBA_LPT (IOPAGEBASE + 017514) /* LP11 */
|
||||||
|
#define IOLN_LPT 004
|
||||||
|
#define IOBA_PTR (IOPAGEBASE + 017550) /* PC11 reader */
|
||||||
|
#define IOLN_PTR 004
|
||||||
|
#define IOBA_PTP (IOPAGEBASE + 017554) /* PC11 punch */
|
||||||
|
#define IOLN_PTP 004
|
||||||
|
|
||||||
|
/* Interrupt assignments; within each level, priority is right to left */
|
||||||
|
|
||||||
|
#define INT_V_DZRX 0 /* BR5 */
|
||||||
|
#define INT_V_DZTX 1
|
||||||
|
#define INT_V_HK 2
|
||||||
|
#define INT_V_RL 3
|
||||||
|
#define INT_V_RQ 4
|
||||||
|
#define INT_V_TQ 5
|
||||||
|
#define INT_V_TS 6
|
||||||
|
#define INT_V_RY 7
|
||||||
|
#define INT_V_XU 8
|
||||||
|
|
||||||
|
#define INT_V_LPT 0 /* BR4 */
|
||||||
|
#define INT_V_PTR 1
|
||||||
|
#define INT_V_PTP 2
|
||||||
|
|
||||||
|
#define INT_DZRX (1u << INT_V_DZRX)
|
||||||
|
#define INT_DZTX (1u << INT_V_DZTX)
|
||||||
|
#define INT_HK (1u << INT_V_HK)
|
||||||
|
#define INT_RL (1u << INT_V_RL)
|
||||||
|
#define INT_RQ (1u << INT_V_RQ)
|
||||||
|
#define INT_TQ (1u << INT_V_TQ)
|
||||||
|
#define INT_TS (1u << INT_V_TS)
|
||||||
|
#define INT_RY (1u << INT_V_RY)
|
||||||
|
#define INT_XU (1u << INT_V_XU)
|
||||||
|
#define INT_PTR (1u << INT_V_PTR)
|
||||||
|
#define INT_PTP (1u << INT_V_PTP)
|
||||||
|
#define INT_LPT (1u << INT_V_LPT)
|
||||||
|
|
||||||
|
#define IPL_DZRX (0x15 - IPL_HMIN)
|
||||||
|
#define IPL_DZTX (0x15 - IPL_HMIN)
|
||||||
|
#define IPL_HK (0x15 - IPL_HMIN)
|
||||||
|
#define IPL_RL (0x15 - IPL_HMIN)
|
||||||
|
#define IPL_RQ (0x15 - IPL_HMIN)
|
||||||
|
#define IPL_TQ (0x15 - IPL_HMIN)
|
||||||
|
#define IPL_TS (0x15 - IPL_HMIN)
|
||||||
|
#define IPL_RY (0x15 - IPL_HMIN)
|
||||||
|
#define IPL_XU (0x15 - IPL_HMIN)
|
||||||
|
#define IPL_PTR (0x14 - IPL_HMIN)
|
||||||
|
#define IPL_PTP (0x14 - IPL_HMIN)
|
||||||
|
#define IPL_LPT (0x14 - IPL_HMIN)
|
||||||
|
|
||||||
|
/* Device vectors */
|
||||||
|
|
||||||
|
#define VEC_Q 0000
|
||||||
|
#define VEC_PTR 0070
|
||||||
|
#define VEC_PTP 0074
|
||||||
|
#define VEC_XU 0120
|
||||||
|
#define VEC_RQ 0154
|
||||||
|
#define VEC_RL 0160
|
||||||
|
#define VEC_LPT 0200
|
||||||
|
#define VEC_HK 0210
|
||||||
|
#define VEC_TS 0224
|
||||||
|
#define VEC_TQ 0260
|
||||||
|
#define VEC_RX 0264
|
||||||
|
#define VEC_RY 0264
|
||||||
|
#define VEC_DZRX 0300
|
||||||
|
#define VEC_DZTX 0304
|
||||||
|
|
||||||
|
/* Autoconfigure ranks */
|
||||||
|
|
||||||
|
#define RANK_DZ 8
|
||||||
|
#define RANK_RL 14
|
||||||
|
#define RANK_RX 18
|
||||||
|
#define RANK_XU 25
|
||||||
|
#define RANK_RQ 26
|
||||||
|
#define RANK_TQ 30
|
||||||
|
#define RANK_VH 32
|
||||||
|
|
||||||
|
/* Interrupt macros */
|
||||||
|
|
||||||
|
#define IVCL(dv) ((IPL_##dv * 32) + INT_V_##dv)
|
||||||
|
#define NVCL(dv) ((IPL_##dv * 32) + TR_##dv)
|
||||||
|
#define IREQ(dv) int_req[IPL_##dv]
|
||||||
|
#define SET_INT(dv) int_req[IPL_##dv] = int_req[IPL_##dv] | (INT_##dv)
|
||||||
|
#define CLR_INT(dv) int_req[IPL_##dv] = int_req[IPL_##dv] & ~(INT_##dv)
|
||||||
|
#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* cond error return */
|
||||||
|
|
||||||
|
/* Logging */
|
||||||
|
|
||||||
|
#define LOG_CPU_I 0x1 /* intexc */
|
||||||
|
#define LOG_CPU_R 0x2 /* REI */
|
||||||
|
#define LOG_CPU_P 0x4 /* context */
|
||||||
|
|
||||||
|
/* Massbus definitions */
|
||||||
|
|
||||||
|
#define MBA_RP (TR_MBA0 - TR_MBA0) /* MBA for RP */
|
||||||
|
#define MBA_TU (TR_MBA1 - TR_MBA0) /* MBA for TU */
|
||||||
|
#define MBA_RMASK 0x1F /* max 32 reg */
|
||||||
|
#define MBE_NXD 1 /* nx drive */
|
||||||
|
#define MBE_NXR 2 /* nx reg */
|
||||||
|
#define MBE_GOE 3 /* err on GO */
|
||||||
|
|
||||||
|
/* Boot definitions */
|
||||||
|
|
||||||
|
#define BOOT_MB 0 /* device codes */
|
||||||
|
#define BOOT_HK 1 /* for VMB */
|
||||||
|
#define BOOT_RL 2
|
||||||
|
#define BOOT_UDA 17
|
||||||
|
#define BOOT_TK 18
|
||||||
|
|
||||||
|
/* Function prototypes for I/O */
|
||||||
|
|
||||||
|
t_bool map_addr (uint32 qa, uint32 *ma);
|
||||||
|
int32 Map_ReadB (uint32 ba, int32 bc, uint8 *buf);
|
||||||
|
int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf);
|
||||||
|
int32 Map_WriteB (uint32 ba, int32 bc, uint8 *buf);
|
||||||
|
int32 Map_WriteW (uint32 ba, int32 bc, uint16 *buf);
|
||||||
|
|
||||||
|
t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat show_addr (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
|
t_stat set_addr_flt (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat set_vec (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat show_vec (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
|
t_stat auto_config (uint32 rank, uint32 num);
|
||||||
|
|
||||||
|
int32 mba_rdbufW (uint32 mbus, int32 bc, uint16 *buf);
|
||||||
|
int32 mba_wrbufW (uint32 mbus, int32 bc, uint16 *buf);
|
||||||
|
int32 mba_chbufW (uint32 mbus, int32 bc, uint16 *buf);
|
||||||
|
int32 mba_get_bc (uint32 mbus);
|
||||||
|
void mba_upd_ata (uint32 mbus, uint32 val);
|
||||||
|
void mba_set_exc (uint32 mbus);
|
||||||
|
void mba_set_don (uint32 mbus);
|
||||||
|
t_stat mba_show_num (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
|
|
||||||
|
t_stat show_nexus (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
|
|
||||||
|
#endif
|
1077
VAX/vax780_doc.txt
Normal file
1077
VAX/vax780_doc.txt
Normal file
File diff suppressed because it is too large
Load diff
699
VAX/vax780_mba.c
Normal file
699
VAX/vax780_mba.c
Normal file
|
@ -0,0 +1,699 @@
|
||||||
|
/* vax780_mba.c: VAX 11/780 Massbus adapter
|
||||||
|
|
||||||
|
Copyright (c) 2004, 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"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
mba0, mba1 RH780 Massbus adapter
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "vax_defs.h"
|
||||||
|
|
||||||
|
/* Massbus */
|
||||||
|
|
||||||
|
#define MBA_NMAPR 256 /* number of map reg */
|
||||||
|
#define MBA_V_RTYPE 10 /* nexus addr: reg type */
|
||||||
|
#define MBA_M_RTYPE 0x3
|
||||||
|
#define MBART_INT 0x0 /* internal */
|
||||||
|
#define MBART_EXT 0x1 /* external */
|
||||||
|
#define MBART_MAP 0x2 /* map */
|
||||||
|
#define MBA_V_INTOFS 2 /* int reg: reg ofs */
|
||||||
|
#define MBA_M_INTOFS 0xFF
|
||||||
|
#define MBA_V_DRV 7 /* ext reg: drive num */
|
||||||
|
#define MBA_M_DRV 0x7
|
||||||
|
#define MBA_V_DEVOFS 2 /* ext reg: reg ofs */
|
||||||
|
#define MBA_M_DEVOFS 0x1F
|
||||||
|
#define MBA_RTYPE(x) (((x) >> MBA_V_RTYPE) & MBA_M_RTYPE)
|
||||||
|
#define MBA_INTOFS(x) (((x) >> MBA_V_INTOFS) & MBA_M_INTOFS)
|
||||||
|
#define MBA_EXTDRV(x) (((x) >> MBA_V_DRV) & MBA_M_DRV)
|
||||||
|
#define MBA_EXTOFS(x) (((x) >> MBA_V_DEVOFS) & MBA_M_DEVOFS)
|
||||||
|
|
||||||
|
/* Massbus configuration register */
|
||||||
|
|
||||||
|
#define MBACNF_OF 0x0
|
||||||
|
#define MBACNF_ADPDN 0x00800000 /* adap pdn - ni */
|
||||||
|
#define MBACNF_ADPUP 0x00400000 /* adap pup - ni */
|
||||||
|
#define MBACNF_CODE 0x00000020
|
||||||
|
#define MBACNF_RD (SBI_FAULTS|MBACNF_W1C)
|
||||||
|
#define MBACNF_W1C 0x00C00000
|
||||||
|
|
||||||
|
/* Control register */
|
||||||
|
|
||||||
|
#define MBACR_OF 0x1
|
||||||
|
#define MBACR_MNT 0x00000008 /* maint */
|
||||||
|
#define MBACR_IE 0x00000004 /* int enable */
|
||||||
|
#define MBACR_ABORT 0x00000002 /* abort */
|
||||||
|
#define MBACR_INIT 0x00000001
|
||||||
|
#define MBACR_RD 0x0000000E
|
||||||
|
#define MBACR_WR 0x0000000E
|
||||||
|
|
||||||
|
/* Status register */
|
||||||
|
|
||||||
|
#define MBASR_OF 0x2
|
||||||
|
#define MBASR_DTBUSY 0x80000000 /* DT busy RO */
|
||||||
|
#define MBASR_NRCONF 0x40000000 /* no conf - ni W1C */
|
||||||
|
#define MBASR_CRD 0x20000000 /* CRD - ni W1C */
|
||||||
|
#define MBASR_CBH 0x00800000 /* CBHUNG - ni W1C */
|
||||||
|
#define MBASR_PGE 0x00080000 /* prog err - W1C int */
|
||||||
|
#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_DTCMP 0x00002000 /* xfr done - W1C int */
|
||||||
|
#define MBASR_DTABT 0x00001000 /* abort - W1C int */
|
||||||
|
#define MBASR_DLT 0x00000800 /* dat late - ni W1C abt */
|
||||||
|
#define MBASR_WCEU 0x00000400 /* wrchk upper - W1C abt */
|
||||||
|
#define MBASR_WCEL 0x00000200 /* wrchk lower - W1C abt */
|
||||||
|
#define MBASR_MXF 0x00000100 /* miss xfr - ni W1C abt */
|
||||||
|
#define MBASR_MBEXC 0x00000080 /* except - ni W1C abt */
|
||||||
|
#define MBASR_MBDPE 0x00000040 /* dat perr - ni W1C abt */
|
||||||
|
#define MBASR_MAPPE 0x00000020 /* map perr - ni W1C abt */
|
||||||
|
#define MBASR_INVM 0x00000010 /* inv map - W1C abt */
|
||||||
|
#define MBASR_ERCONF 0x00000008 /* err conf - ni W1C abt */
|
||||||
|
#define MBASR_RDS 0x00000004 /* RDS - ni W1C abt */
|
||||||
|
#define MBASR_ITMO 0x00000002 /* timeout - W1C abt */
|
||||||
|
#define MBASR_RTMO 0x00000001 /* rd timeout - W1C abt */
|
||||||
|
#define MBASR_RD 0xE08F7FFF
|
||||||
|
#define MBASR_W1C 0x608F7FFF
|
||||||
|
#define MBASR_ABORTS 0x00000FFF
|
||||||
|
#define MBASR_INTR 0x000F7000
|
||||||
|
|
||||||
|
/* Virtual address register */
|
||||||
|
|
||||||
|
#define MBAVA_OF 0x3
|
||||||
|
#define MBAVA_RD 0x0001FFFF
|
||||||
|
#define MBAVA_WR (MBAVA_RD)
|
||||||
|
|
||||||
|
/* Byte count */
|
||||||
|
|
||||||
|
#define MBABC_OF 0x4
|
||||||
|
#define MBABC_RD 0xFFFFFFFF
|
||||||
|
#define MBABC_WR 0x0000FFFF
|
||||||
|
#define MBABC_V_CNT 16 /* active count */
|
||||||
|
|
||||||
|
/* Diagnostic register */
|
||||||
|
|
||||||
|
#define MBADR_OF 0x5
|
||||||
|
#define MBADR_RD 0xFFFFFFFF
|
||||||
|
#define MBADR_WR 0xFFC00000
|
||||||
|
|
||||||
|
/* Selected map entry - read only */
|
||||||
|
|
||||||
|
#define MBASMR_OF 0x6
|
||||||
|
#define MBASMR_RD (MBAMAP_RD)
|
||||||
|
|
||||||
|
/* Command register (SBI) - read only */
|
||||||
|
|
||||||
|
#define MBACMD_OF 0x7
|
||||||
|
|
||||||
|
#define MBAMAX_OF 0x8
|
||||||
|
|
||||||
|
/* External registers */
|
||||||
|
|
||||||
|
#define MBA_CS1 0x00 /* device CSR1 */
|
||||||
|
#define MBA_CS1_WR 0x3F /* writeable bits */
|
||||||
|
#define MBA_CS1_DT 0x28 /* >= for data xfr */
|
||||||
|
|
||||||
|
/* Map registers */
|
||||||
|
|
||||||
|
#define MBAMAP_VLD 0x80000000 /* valid */
|
||||||
|
#define MBAMAP_PAG 0x001FFFFF
|
||||||
|
#define MBAMAP_RD (MBAMAP_VLD | MBAMAP_PAG)
|
||||||
|
#define MBAMAP_WR (MBAMAP_RD)
|
||||||
|
|
||||||
|
struct mbctx {
|
||||||
|
uint32 cnf; /* config reg */
|
||||||
|
uint32 cr; /* control reg */
|
||||||
|
uint32 sr; /* status reg */
|
||||||
|
uint32 va; /* virt addr */
|
||||||
|
uint32 bc; /* byte count */
|
||||||
|
uint32 dr; /* diag reg */
|
||||||
|
uint32 smr; /* sel map reg */
|
||||||
|
uint32 map[MBA_NMAPR]; /* map */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct mbctx MBACTX;
|
||||||
|
MBACTX massbus[MBA_NUM];
|
||||||
|
|
||||||
|
extern uint32 nexus_req[NEXUS_HLVL];
|
||||||
|
extern UNIT cpu_unit;
|
||||||
|
extern FILE *sim_log;
|
||||||
|
extern int32 sim_switches;
|
||||||
|
|
||||||
|
t_stat mba_reset (DEVICE *dptr);
|
||||||
|
t_stat mba_rdreg (int32 *val, int32 pa, int32 mode);
|
||||||
|
t_stat mba_wrreg (int32 val, int32 pa, int32 lnt);
|
||||||
|
t_bool mba_map_addr (uint32 va, uint32 *ma, uint32 mb);
|
||||||
|
void mba_set_int (uint32 mb);
|
||||||
|
void mba_clr_int (uint32 mb);
|
||||||
|
void mba_upd_sr (uint32 set, uint32 clr, uint32 mb);
|
||||||
|
DEVICE mba0_dev, mba1_dev;
|
||||||
|
DIB mba0_dib, mba1_dib;
|
||||||
|
|
||||||
|
extern int32 ReadB (uint32 pa);
|
||||||
|
extern int32 ReadW (uint32 pa);
|
||||||
|
extern int32 ReadL (uint32 pa);
|
||||||
|
extern void WriteB (uint32 pa, int32 val);
|
||||||
|
extern void WriteW (uint32 pa, int32 val);
|
||||||
|
extern void WriteL (uint32 pa, int32 val);
|
||||||
|
|
||||||
|
/* Maps */
|
||||||
|
|
||||||
|
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 */
|
||||||
|
|
||||||
|
static t_stat (*mbregR[MBA_NUM])(int32 *dat, int32 ad, int32 md);
|
||||||
|
static t_stat (*mbregW[MBA_NUM])(int32 dat, int32 ad, int32 md);
|
||||||
|
static int32 (*mbabort[MBA_NUM])(void);
|
||||||
|
|
||||||
|
/* Massbus adapter data structures
|
||||||
|
|
||||||
|
mba_dev UBA device descriptor
|
||||||
|
mba_unit UBA units
|
||||||
|
mba_reg UBA register list
|
||||||
|
*/
|
||||||
|
|
||||||
|
DIB mba0_dib = { TR_MBA0, 0, &mba_rdreg, &mba_wrreg, 0, NVCL (MBA0) };
|
||||||
|
|
||||||
|
UNIT mba0_unit = { UDATA (NULL, 0, 0) };
|
||||||
|
|
||||||
|
REG mba0_reg[] = {
|
||||||
|
{ HRDATA (CNFR, massbus[0].cnf, 32) },
|
||||||
|
{ HRDATA (CR, massbus[0].cr, 4) },
|
||||||
|
{ HRDATA (SR, massbus[0].sr, 32) },
|
||||||
|
{ HRDATA (VA, massbus[0].va, 17) },
|
||||||
|
{ HRDATA (BC, massbus[0].bc, 32) },
|
||||||
|
{ HRDATA (DR, massbus[0].dr, 32) },
|
||||||
|
{ HRDATA (SMR, massbus[0].dr, 32) },
|
||||||
|
{ BRDATA (MAP, massbus[0].map, 16, 32, MBA_NMAPR) },
|
||||||
|
{ FLDATA (NEXINT, nexus_req[IPL_MBA0], TR_MBA0) },
|
||||||
|
{ NULL } };
|
||||||
|
|
||||||
|
MTAB mba0_mod[] = {
|
||||||
|
{ MTAB_XTD|MTAB_VDV, TR_MBA0, "NEXUS", NULL,
|
||||||
|
NULL, &show_nexus },
|
||||||
|
{ 0 } };
|
||||||
|
|
||||||
|
DEVICE mba0_dev = {
|
||||||
|
"MBA0", &mba0_unit, mba0_reg, mba0_mod,
|
||||||
|
1, 0, 0, 0, 0, 0,
|
||||||
|
NULL, NULL, &mba_reset,
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
&mba0_dib, DEV_NEXUS };
|
||||||
|
|
||||||
|
DIB mba1_dib = { TR_MBA1, 0, &mba_rdreg, &mba_wrreg, 0, NVCL (MBA0) };
|
||||||
|
|
||||||
|
UNIT mba1_unit = { UDATA (NULL, 0, 0) };
|
||||||
|
|
||||||
|
MTAB mba1_mod[] = {
|
||||||
|
{ MTAB_XTD|MTAB_VDV, TR_MBA1, "NEXUS", NULL,
|
||||||
|
NULL, &show_nexus },
|
||||||
|
{ 0 } };
|
||||||
|
|
||||||
|
REG mba1_reg[] = {
|
||||||
|
{ HRDATA (CNFR, massbus[1].cnf, 32) },
|
||||||
|
{ HRDATA (CR, massbus[1].cr, 4) },
|
||||||
|
{ HRDATA (SR, massbus[1].sr, 32) },
|
||||||
|
{ HRDATA (VA, massbus[1].va, 17) },
|
||||||
|
{ HRDATA (BC, massbus[1].bc, 32) },
|
||||||
|
{ HRDATA (DR, massbus[1].dr, 32) },
|
||||||
|
{ HRDATA (SMR, massbus[1].dr, 32) },
|
||||||
|
{ BRDATA (MAP, massbus[1].map, 16, 32, MBA_NMAPR) },
|
||||||
|
{ FLDATA (NEXINT, nexus_req[IPL_MBA1], TR_MBA1) },
|
||||||
|
{ NULL } };
|
||||||
|
|
||||||
|
DEVICE mba1_dev = {
|
||||||
|
"MBA1", &mba1_unit, mba1_reg, mba1_mod,
|
||||||
|
1, 0, 0, 0, 0, 0,
|
||||||
|
NULL, NULL, &mba_reset,
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
&mba1_dib, DEV_NEXUS };
|
||||||
|
|
||||||
|
/* Read Massbus adapter register */
|
||||||
|
|
||||||
|
t_stat mba_rdreg (int32 *val, int32 pa, int32 mode)
|
||||||
|
{
|
||||||
|
int32 mb, ofs, drv, rtype;
|
||||||
|
t_stat r;
|
||||||
|
MBACTX *mbp;
|
||||||
|
|
||||||
|
mb = NEXUS_GETNEX (pa) - TR_MBA0; /* get MBA */
|
||||||
|
if (mb >= MBA_NUM) return SCPE_NXM; /* valid? */
|
||||||
|
mbp = ctxmap[mb]; /* get context */
|
||||||
|
rtype = MBA_RTYPE (pa); /* get reg type */
|
||||||
|
|
||||||
|
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;
|
||||||
|
break;
|
||||||
|
case MBACR_OF: /* CR */
|
||||||
|
*val = mbp->cr & MBACR_RD;
|
||||||
|
break;
|
||||||
|
case MBASR_OF: /* SR */
|
||||||
|
*val = mbp->sr & MBASR_RD;
|
||||||
|
break;
|
||||||
|
case MBAVA_OF: /* VA */
|
||||||
|
*val = mbp->va & MBAVA_RD;
|
||||||
|
break;
|
||||||
|
case MBABC_OF: /* BC */
|
||||||
|
*val = mbp->bc & MBABC_RD;
|
||||||
|
break;
|
||||||
|
case MBADR_OF: /* DR */
|
||||||
|
*val = mbp->dr & MBADR_RD;
|
||||||
|
break;
|
||||||
|
case MBASMR_OF: /* SMR */
|
||||||
|
*val = mbp->smr & MBASMR_RD;
|
||||||
|
break;
|
||||||
|
case MBACMD_OF: /* CMD */
|
||||||
|
*val = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return SCPE_NXM;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MBART_EXT: /* external */
|
||||||
|
if (!mbregR[mb]) return SCPE_NXM; /* device there? */
|
||||||
|
drv = MBA_EXTDRV (pa); /* get dev num */
|
||||||
|
ofs = MBA_EXTOFS (pa); /* get reg offs */
|
||||||
|
r = mbregR[mb] (val, ofs, drv); /* call device */
|
||||||
|
if (r == MBE_NXD) mba_upd_sr (MBASR_NFD, 0, mb);/* nx drive? */
|
||||||
|
else if (r == MBE_NXR) return SCPE_NXM; /* nx reg? */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MBART_MAP: /* map */
|
||||||
|
ofs = MBA_INTOFS (pa);
|
||||||
|
*val = mbp->map[ofs] & MBAMAP_RD;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return SCPE_NXM; }
|
||||||
|
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write Massbus adapter register */
|
||||||
|
|
||||||
|
t_stat mba_wrreg (int32 val, int32 pa, int32 lnt)
|
||||||
|
{
|
||||||
|
int32 mb, ofs, drv, rtype;
|
||||||
|
t_stat r;
|
||||||
|
t_bool cs1dt;
|
||||||
|
MBACTX *mbp;
|
||||||
|
|
||||||
|
mb = NEXUS_GETNEX (pa) - TR_MBA0; /* get MBA */
|
||||||
|
if (mb >= MBA_NUM) return SCPE_NXM; /* valid? */
|
||||||
|
mbp = ctxmap[mb]; /* get context */
|
||||||
|
rtype = MBA_RTYPE (pa); /* get reg type */
|
||||||
|
|
||||||
|
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);
|
||||||
|
break;
|
||||||
|
case MBACR_OF: /* CR */
|
||||||
|
if (val & MBACR_INIT) /* init? */
|
||||||
|
mba_reset (devmap[mb]); /* reset MBA */
|
||||||
|
if ((val & MBACR_ABORT) && (mbp->sr & MBASR_DTBUSY)) {
|
||||||
|
if (mbabort[mb]) mbabort[mb] (); /* abort? */
|
||||||
|
mba_upd_sr (MBASR_DTABT, 0, mb); }
|
||||||
|
if ((val & MBACR_MNT) && (mbp->sr & MBASR_DTBUSY)) {
|
||||||
|
mba_upd_sr (MBASR_PGE, 0, mb); /* mnt & xfer? */
|
||||||
|
val = val & ~MBACR_MNT; }
|
||||||
|
if ((val & MBACR_IE) == 0) mba_clr_int (mb);
|
||||||
|
mbp->cr = (mbp->cr & ~MBACR_WR) | (val & MBACR_WR);
|
||||||
|
break;
|
||||||
|
case MBASR_OF: /* SR */
|
||||||
|
mbp->sr = mbp->sr & ~(val & MBASR_W1C);
|
||||||
|
break;
|
||||||
|
case MBAVA_OF: /* VA */
|
||||||
|
if (mbp->sr & MBASR_DTBUSY) /* err if xfr */
|
||||||
|
mba_upd_sr (MBASR_PGE, 0, mb);
|
||||||
|
else mbp->va = val & MBAVA_WR;
|
||||||
|
break;
|
||||||
|
case MBABC_OF: /* BC */
|
||||||
|
if (mbp->sr & MBASR_DTBUSY) /* err if xfr */
|
||||||
|
mba_upd_sr (MBASR_PGE, 0, mb);
|
||||||
|
else {
|
||||||
|
val = val & MBABC_WR;
|
||||||
|
mbp->bc = (val << MBABC_V_CNT) | val;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MBADR_OF: /* DR */
|
||||||
|
mbp->dr = (mbp->dr & ~MBADR_WR) | (val & MBADR_WR);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return SCPE_NXM;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MBART_EXT: /* external */
|
||||||
|
if (!mbregW[mb]) return SCPE_NXM; /* device there? */
|
||||||
|
drv = MBA_EXTDRV (pa); /* get dev num */
|
||||||
|
ofs = MBA_EXTOFS (pa); /* get reg offs */
|
||||||
|
cs1dt = (ofs == MBA_CS1) && (val & CSR_GO) && /* starting xfr? */
|
||||||
|
((val & MBA_CS1_WR) >= MBA_CS1_DT);
|
||||||
|
if (cs1dt && (mbp->sr & MBASR_DTBUSY)) { /* xfr while busy? */
|
||||||
|
mba_upd_sr (MBASR_PGE, 0, mb); /* prog error */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
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? */
|
||||||
|
mbp->sr = (mbp->sr | MBASR_DTBUSY) & ~MBASR_W1C;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MBART_MAP: /* map */
|
||||||
|
ofs = MBA_INTOFS (pa);
|
||||||
|
mbp->map[ofs] = val & MBAMAP_WR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return SCPE_NXM; }
|
||||||
|
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Massbus I/O routine
|
||||||
|
|
||||||
|
mb_rdbufW - fetch word buffer from memory
|
||||||
|
mb_wrbufW - store word buffer into memory
|
||||||
|
mb_chbufW - compare word buffer with memory
|
||||||
|
|
||||||
|
Returns number of bytes successfully transferred/checked
|
||||||
|
*/
|
||||||
|
|
||||||
|
int32 mba_rdbufW (uint32 mb, int32 bc, uint16 *buf)
|
||||||
|
{
|
||||||
|
MBACTX *mbp;
|
||||||
|
int32 i, j, ba, mbc, pbc;
|
||||||
|
uint32 pa, dat;
|
||||||
|
|
||||||
|
if (mb >= MBA_NUM) return 0; /* valid MBA? */
|
||||||
|
mbp = ctxmap[mb]; /* get context */
|
||||||
|
ba = mbp->va; /* get virt addr */
|
||||||
|
mbc = ((MBABC_WR + 1) - (mbp->bc >> MBABC_V_CNT)) & MBABC_WR; /* get Mbus bc */
|
||||||
|
if (bc > mbc) bc = mbc; /* use smaller */
|
||||||
|
for (i = 0; i < bc; i = i + pbc) { /* loop by pages */
|
||||||
|
if (!mba_map_addr (ba + i, &pa, mb)) break; /* page inv? */
|
||||||
|
if (!ADDR_IS_MEM (pa)) { /* NXM? */
|
||||||
|
mba_upd_sr (MBASR_RTMO, 0, mb);
|
||||||
|
break; }
|
||||||
|
pbc = VA_PAGSIZE - VA_GETOFF (pa); /* left in page */
|
||||||
|
if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */
|
||||||
|
if ((pa | pbc) & 1) { /* aligned word? */
|
||||||
|
for (j = 0; j < pbc; pa++, j++) { /* no, bytes */
|
||||||
|
if ((i + j) & 1) { /* odd byte? */
|
||||||
|
*buf = (*buf & BMASK) | (ReadB (pa) << 8);
|
||||||
|
buf++;
|
||||||
|
}
|
||||||
|
else *buf = (*buf & ~BMASK) | ReadB (pa);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((pa | pbc) & 3) { /* aligned LW? */
|
||||||
|
for (j = 0; j < pbc; pa = pa + 2, j = j + 2) { /* no, words */
|
||||||
|
*buf++ = ReadW (pa); /* get word */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { /* yes, do by LW */
|
||||||
|
for (j = 0; j < pbc; pa = pa + 4, j = j + 4) {
|
||||||
|
dat = ReadL (pa); /* get lw */
|
||||||
|
*buf++ = dat & WMASK; /* low 16b */
|
||||||
|
*buf++ = (dat >> 16) & WMASK; /* high 16b */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 mba_wrbufW (uint32 mb, int32 bc, uint16 *buf)
|
||||||
|
{
|
||||||
|
MBACTX *mbp;
|
||||||
|
int32 i, j, ba, mbc, pbc;
|
||||||
|
uint32 pa, dat;
|
||||||
|
|
||||||
|
if (mb >= MBA_NUM) return 0; /* valid MBA? */
|
||||||
|
mbp = ctxmap[mb]; /* get context */
|
||||||
|
ba = mbp->va; /* get virt addr */
|
||||||
|
mbc = ((MBABC_WR + 1) - (mbp->bc >> MBABC_V_CNT)) & MBABC_WR; /* get Mbus bc */
|
||||||
|
if (bc > mbc) bc = mbc; /* use smaller */
|
||||||
|
for (i = 0; i < bc; i = i + pbc) { /* loop by pages */
|
||||||
|
if (!mba_map_addr (ba + i, &pa, mb)) break; /* page inv? */
|
||||||
|
if (!ADDR_IS_MEM (pa)) { /* NXM? */
|
||||||
|
mba_upd_sr (MBASR_RTMO, 0, mb);
|
||||||
|
break; }
|
||||||
|
pbc = VA_PAGSIZE - VA_GETOFF (pa); /* left in page */
|
||||||
|
if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */
|
||||||
|
if ((pa | pbc) & 1) { /* aligned word? */
|
||||||
|
for (j = 0; j < pbc; pa++, j++) { /* no, bytes */
|
||||||
|
if ((i + j) & 1) {
|
||||||
|
WriteB (pa, (*buf >> 8) & BMASK);
|
||||||
|
buf++; }
|
||||||
|
else WriteB (pa, *buf & BMASK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((pa | pbc) & 3) { /* aligned LW? */
|
||||||
|
for (j = 0; j < pbc; pa = pa + 2, j = j + 2) { /* no, words */
|
||||||
|
WriteW (pa, *buf); /* write word */
|
||||||
|
buf++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { /* yes, do by LW */
|
||||||
|
for (j = 0; j < pbc; pa = pa + 4, j = j + 4) {
|
||||||
|
dat = (uint32) *buf++; /* get low 16b */
|
||||||
|
dat = dat | (((uint32) *buf++) << 16); /* merge hi 16b */
|
||||||
|
WriteL (pa, dat); /* store LW */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 mba_chbufW (uint32 mb, int32 bc, uint16 *buf)
|
||||||
|
{
|
||||||
|
MBACTX *mbp;
|
||||||
|
int32 i, j, ba, mbc, pbc;
|
||||||
|
uint32 pa, dat, cmp;
|
||||||
|
|
||||||
|
if (mb >= MBA_NUM) return 0; /* valid MBA? */
|
||||||
|
mbp = ctxmap[mb]; /* get context */
|
||||||
|
ba = mbp->va; /* get virt addr */
|
||||||
|
mbc = ((MBABC_WR + 1) - (mbp->bc >> MBABC_V_CNT)) & MBABC_WR; /* get Mbus bc */
|
||||||
|
if (bc > mbc) bc = mbc; /* use smaller */
|
||||||
|
for (i = 0; i < bc; i = i + pbc) { /* loop by pages */
|
||||||
|
if (!mba_map_addr (ba + i, &pa, mb)) break; /* page inv? */
|
||||||
|
if (!ADDR_IS_MEM (pa)) { /* NXM? */
|
||||||
|
mba_upd_sr (MBASR_RTMO, 0, mb);
|
||||||
|
break; }
|
||||||
|
pbc = VA_PAGSIZE - VA_GETOFF (pa); /* left in page */
|
||||||
|
if (pbc > (bc - i)) pbc = bc - i; /* limit to rem xfr */
|
||||||
|
for (j = 0; j < pbc; j++, pa++) { /* byte by byte */
|
||||||
|
cmp = ReadB (pa);
|
||||||
|
if ((i + j) & 1) dat = (*buf++ >> 8) & BMASK;
|
||||||
|
else dat = *buf & BMASK;
|
||||||
|
if (cmp != dat) {
|
||||||
|
mba_upd_sr ((j & 1)? MBASR_WCEU: MBASR_WCEL, 0, mb);
|
||||||
|
break;
|
||||||
|
} /* end if */
|
||||||
|
} /* end for j */
|
||||||
|
} /* end for i */
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Map an address via the translation map */
|
||||||
|
|
||||||
|
t_bool mba_map_addr (uint32 va, uint32 *ma, uint32 mb)
|
||||||
|
{
|
||||||
|
MBACTX *mbp = ctxmap[mb];
|
||||||
|
uint32 vblk = (va >> VA_V_VPN); /* map index */
|
||||||
|
uint32 mmap = mbp->map[vblk]; /* get map */
|
||||||
|
|
||||||
|
mbp->smr = mmap; /* save map reg */
|
||||||
|
if (mmap & MBAMAP_VLD) { /* valid? */
|
||||||
|
*ma = ((mmap & MBAMAP_PAG) << VA_V_VPN) + VA_GETOFF (va);
|
||||||
|
return 1; } /* legit addr */
|
||||||
|
mba_upd_sr (MBASR_INVM, 0, mb); /* invalid map */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Device access, status, and interrupt routines */
|
||||||
|
|
||||||
|
void mba_set_don (uint32 mb)
|
||||||
|
{
|
||||||
|
mba_upd_sr (MBASR_DTCMP, 0, mb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mba_upd_ata (uint32 mb, uint32 val)
|
||||||
|
{
|
||||||
|
if (val) mba_upd_sr (MBASR_ATA, 0, mb);
|
||||||
|
else mba_upd_sr (0, MBASR_ATA, mb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mba_set_exc (uint32 mb)
|
||||||
|
{
|
||||||
|
mba_upd_sr (MBASR_MBEXC, 0, mb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 mba_get_bc (uint32 mb)
|
||||||
|
{
|
||||||
|
MBACTX *mbp;
|
||||||
|
|
||||||
|
if (mb >= MBA_NUM) return 0;
|
||||||
|
mbp = ctxmap[mb];
|
||||||
|
return ((0x10000 - (mbp->bc >> MBABC_V_CNT)) & MBABC_WR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mba_set_int (uint32 mb)
|
||||||
|
{
|
||||||
|
DEVICE *dptr;
|
||||||
|
DIB *dibp;
|
||||||
|
|
||||||
|
if (mb >= MBA_NUM) return;
|
||||||
|
dptr = devmap[mb];
|
||||||
|
dibp = (DIB *) dptr->ctxt;
|
||||||
|
nexus_req[dibp->vloc >> 5] |= (1u << (dibp->vloc & 0x1F));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mba_clr_int (uint32 mb)
|
||||||
|
{
|
||||||
|
DEVICE *dptr;
|
||||||
|
DIB *dibp;
|
||||||
|
|
||||||
|
if (mb >= MBA_NUM) return;
|
||||||
|
dptr = devmap[mb];
|
||||||
|
dibp = (DIB *) dptr->ctxt;
|
||||||
|
nexus_req[dibp->vloc >> 5] &= ~(1u << (dibp->vloc & 0x1F));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mba_upd_sr (uint32 set, uint32 clr, uint32 mb)
|
||||||
|
{
|
||||||
|
MBACTX *mbp;
|
||||||
|
|
||||||
|
if (mb >= MBA_NUM) return;
|
||||||
|
mbp = ctxmap[mb];
|
||||||
|
if (set & MBASR_ABORTS) set |= (MBASR_DTCMP|MBASR_DTABT);
|
||||||
|
if (set & (MBASR_DTCMP|MBASR_DTABT)) mbp->sr &= ~MBASR_DTBUSY;
|
||||||
|
mbp->sr = (mbp->sr | set) & ~clr;
|
||||||
|
if ((set & MBASR_INTR) && (mbp->cr & MBACR_IE))
|
||||||
|
mba_set_int (mb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset Massbus adapter */
|
||||||
|
|
||||||
|
t_stat mba_reset (DEVICE *dptr)
|
||||||
|
{
|
||||||
|
int32 i, mb;
|
||||||
|
MBACTX *mbp;
|
||||||
|
|
||||||
|
for (mb = 0; mb < MBA_NUM; mb++) {
|
||||||
|
mbp = ctxmap[mb];
|
||||||
|
if (dptr == devmap[mb]) break;
|
||||||
|
}
|
||||||
|
mbp->cnf = 0;
|
||||||
|
mbp->cr = mbp->cr & MBACR_MNT;
|
||||||
|
mbp->sr = 0;
|
||||||
|
mbp->bc = 0;
|
||||||
|
mbp->va = 0;
|
||||||
|
mbp->dr = 0;
|
||||||
|
mbp->smr = 0;
|
||||||
|
if (sim_switches & SWMASK ('P')) {
|
||||||
|
for (i = 0; i < MBA_NMAPR; i++) mbp->map[i] = 0;
|
||||||
|
}
|
||||||
|
if (mbabort[mb]) mbabort[mb] (); /* reset device */
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Show Massbus adapter number */
|
||||||
|
|
||||||
|
t_stat mba_show_num (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
|
{
|
||||||
|
DEVICE *dptr = find_dev_from_unit (uptr);
|
||||||
|
DIB *dibp;
|
||||||
|
|
||||||
|
if (dptr == NULL) return SCPE_IERR;
|
||||||
|
dibp = (DIB *) dptr->ctxt;
|
||||||
|
if (dibp == NULL) return SCPE_IERR;
|
||||||
|
fprintf (st, "Massbus adapter %d", dibp->ba);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Init Mbus tables */
|
||||||
|
|
||||||
|
void init_mbus_tab (void)
|
||||||
|
{
|
||||||
|
uint32 i;
|
||||||
|
|
||||||
|
for (i = 0; i < MBA_NUM; i++) {
|
||||||
|
mbregR[i] = NULL;
|
||||||
|
mbregW[i] = NULL;
|
||||||
|
mbabort[i] = NULL;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build dispatch tables */
|
||||||
|
|
||||||
|
t_stat build_mbus_tab (DEVICE *dptr, DIB *dibp)
|
||||||
|
{
|
||||||
|
uint32 idx;
|
||||||
|
|
||||||
|
if ((dptr == NULL) || (dibp == NULL)) return SCPE_IERR; /* validate args */
|
||||||
|
idx = dibp->ba; /* Mbus # */
|
||||||
|
if (idx >= MBA_NUM) return SCPE_STOP;
|
||||||
|
if ((mbregR[idx] && dibp->rd && /* conflict? */
|
||||||
|
(mbregR[idx] != dibp->rd)) ||
|
||||||
|
(mbregW[idx] && dibp->wr &&
|
||||||
|
(mbregW[idx] != dibp->wr)) ||
|
||||||
|
(mbabort[idx] && dibp->ack[0] &&
|
||||||
|
(mbabort[idx] != dibp->ack[0]))) {
|
||||||
|
printf ("Massbus %s assignment conflict at %d\n",
|
||||||
|
sim_dname (dptr), dibp->ba);
|
||||||
|
if (sim_log) fprintf (sim_log,
|
||||||
|
"Massbus %s assignment conflict at %d\n",
|
||||||
|
sim_dname (dptr), dibp->ba);
|
||||||
|
return SCPE_STOP;
|
||||||
|
}
|
||||||
|
if (dibp->rd) mbregR[idx] = dibp->rd; /* set rd dispatch */
|
||||||
|
if (dibp->wr) mbregW[idx] = dibp->wr; /* set wr dispatch */
|
||||||
|
if (dibp->ack[0]) mbabort[idx] = dibp->ack[0]; /* set abort dispatch */
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue