Notes For V2.10-2
1. New Features in 2.10-2 The build procedures have changed. There is only one UNIX makefile. To compile without Ethernet support, simply type gmake {target|all} To compile with Ethernet support, type gmake USE_NETWORK=1 {target|all} The Mingw batch files require Mingw release 2 and invoke the Unix makefile. There are still separate batch files for compilation with or without Ethernet support. 1.1 SCP and Libraries - The EVAL command will evaluate a symbolic type-in and display it in numeric form. - The ! command (with no arguments) will launch the host operating system command shell. The ! command (with an argument) executes the argument as a host operating system command. (Code from Mark Pizzolato) - Telnet sessions now recognize BREAK. How a BREAK is transmitted dependent on the particular Telnet client. (Code from Mark Pizzolato) - The sockets library includes code for active connections as well as listening connections. - The RESTORE command will restore saved memory size, if the simulator supports dynamic memory resizing. 1.2 PDP-1 - The PDP-1 supports the Type 24 serial drum (based on recently discovered documents). 1.3 18b PDP's - The PDP-4 supports the Type 24 serial drum (based on recently discovered documents). 1.4 PDP-11 - The PDP-11 implements a stub DEUNA/DELUA (XU). The real XU module will be included in a later release. 1.5 PDP-10 - The PDP-10 implements a stub DEUNA/DELUA (XU). The real XU module will be included in a later release. 1.6 HP 2100 - The IOP microinstruction set is supported for the 21MX as well as the 2100. - The HP2100 supports the Access Interprocessor Link (IPL). 1.7 VAX - If the VAX console is attached to a Telnet session, BREAK is interpreted as console halt. - The SET/SHOW HISTORY commands enable and display a history of the most recently executed instructions. (Code from Mark Pizzolato) 1.8 Terminals Multiplexors - BREAK detection was added to the HP, DEC, and Interdata terminal multiplexors. 1.9 Interdata 16b and 32b - First release. UNIX is not yet working. 1.10 SDS 940 - First release. 2. Bugs Fixed in 2.10-2 - PDP-11 console must default to 7b for early UNIX compatibility. - PDP-11/VAX TMSCP emulator was using the wrong packet length for read/write end packets. - Telnet IAC+IAC processing was fixed, both for input and output (found by Mark Pizzolato). - PDP-11/VAX Ethernet setting flag bits wrong for chained descriptors (found by Mark Pizzolato). 3. New Features in 2.10 vs prior releases 3.1 SCP and Libraries - The VT emulation package has been replaced by the capability to remote the console to a Telnet session. Telnet clients typically have more complete and robust VT100 emulation. - Simulated devices may now have statically allocated buffers, in addition to dynamically allocated buffers or disk-based data stores. - The DO command now takes substitutable arguments (max 9). In command files, %n represents substitutable argument n. - The initial command line is now interpreted as the command name and substitutable arguments for a DO command. This is backward compatible to prior versions. - The initial command line parses switches. -Q is interpreted as quiet mode; informational messages are suppressed. - The HELP command now takes an optional argument. HELP <cmd> types help on the specified command. - Hooks have been added for implementing GUI-based consoles, as well as simulator-specific command extensions. A few internal data structures and definitions have changed. - Two new routines (tmxr_open_master, tmxr_close_master) have been added to sim_tmxr.c. The calling sequence for sim_accept_conn has been changed in sim_sock.c. - The calling sequence for the VM boot routine has been modified to add an additional parameter. - SAVE now saves, and GET now restores, controller and unit flags. - Library sim_ether.c has been added for Ethernet support. 3.2 VAX - Non-volatile RAM (NVR) can behave either like a memory or like a disk-based peripheral. If unattached, it behaves like memory and is saved and restored by SAVE and RESTORE, respectively. If attached, its contents are loaded from disk by ATTACH and written back to disk at DETACH and EXIT. - SHOW <device> VECTOR displays the device's interrupt vector. A few devices allow the vector to be changed with SET <device> VECTOR=nnn. - SHOW CPU IOSPACE displays the I/O space address map. - The TK50 (TMSCP tape) has been added. - The DEQNA/DELQA (Qbus Ethernet controllers) have been added. - Autoconfiguration support has been added. - The paper tape reader has been removed from vax_stddev.c and now references a common implementation file, dec_pt.h. - Examine and deposit switches now work on all devices, not just the CPU. - Device address conflicts are not detected until simulation starts. 3.3 PDP-11 - SHOW <device> VECTOR displays the device's interrupt vector. Most devices allow the vector to be changed with SET <device> VECTOR=nnn. - SHOW CPU IOSPACE displays the I/O space address map. - The TK50 (TMSCP tape), RK611/RK06/RK07 (cartridge disk), RX211 (double density floppy), and KW11P programmable clock have been added. - The DEQNA/DELQA (Qbus Ethernet controllers) have been added. - Autoconfiguration support has been added. - The paper tape reader has been removed from pdp11_stddev.c and now references a common implementation file, dec_pt.h. - Device bootstraps now use the actual CSR specified by the SET ADDRESS command, rather than just the default CSR. Note that PDP-11 operating systems may NOT support booting with non-standard addresses. - Specifying more than 256KB of memory, or changing the bus configuration, causes all peripherals that are not compatible with the current bus configuration to be disabled. - Device address conflicts are not detected until simulation starts. 3.4 PDP-10 - SHOW <device> VECTOR displays the device's interrupt vector. A few devices allow the vector to be changed with SET <device> VECTOR=nnn. - SHOW CPU IOSPACE displays the I/O space address map. - The RX211 (double density floppy) has been added; it is off by default. - The paper tape now references a common implementation file, dec_pt.h. - Device address conflicts are not detected until simulation starts. 3.5 PDP-1 - DECtape (then known as MicroTape) support has been added. - The line printer and DECtape can be disabled and enabled. 3.6 PDP-8 - The RX28 (double density floppy) has been added as an option to the existing RX8E controller. - SHOW <device> DEVNO displays the device's device number. Most devices allow the device number to be changed with SET <device> DEVNO=nnn. - Device number conflicts are not detected until simulation starts. 3.7 IBM 1620 - The IBM 1620 simulator has been released. 3.8 AltairZ80 - A hard drive has been added for increased storage. - Several bugs have been fixed. 3.9 HP 2100 - The 12845A has been added and made the default line printer (LPT). The 12653A has been renamed LPS and is off by default. It also supports the diagnostic functions needed to run the DCPC and DMS diagnostics. - The 12557A/13210A disk defaults to the 13210A (7900/7901). - The 12559A magtape is off by default. - New CPU options (EAU/NOEAU) enable/disable the extended arithmetic instructions for the 2116. These instructions are standard on the 2100 and 21MX. - New CPU options (MPR/NOMPR) enable/disable memory protect for the 2100 and 21MX. - New CPU options (DMS/NODMS) enable/disable the dynamic mapping instructions for the 21MX. - The 12539 timebase generator autocalibrates. 3.10 Simulated Magtapes - Simulated magtapes recognize end of file and the marker 0xFFFFFFFF as end of medium. Only the TMSCP tape simulator can generate an end of medium marker. - The error handling in simulated magtapes was overhauled to be consistent through all simulators. 3.11 Simulated DECtapes - Added support for RT11 image file format (256 x 16b) to DECtapes. 4. Bugs Fixed in 2.10 vs prior releases - TS11/TSV05 was not simulating the XS0_MOT bit, causing failures under VMS. In addition, two of the CTL options were coded interchanged. - IBM 1401 tape was not setting a word mark under group mark for load mode reads. This caused the diagnostics to crash. - SCP bugs in ssh_break and set_logon were fixed (found by Dave Hittner). - Numerous bugs in the HP 2100 extended arithmetic, floating point, 21MX, DMS, and IOP instructions were fixed. Bugs were also fixed in the memory protect and DMS functions. The moving head disks (DP, DQ) were revised to simulate the hardware more accurately. Missing functions in DQ (address skip, read address) were added. - PDP-10 tape wouldn't boot, and then wouldn't read (reported by Michael Thompson and Harris Newman, respectively) - PDP-1 typewriter is half duplex, with only one shift state for both input and output (found by Derek Peschel) 5. General Notes WARNING: V2.10 has reorganized and renamed some of the definition files for the PDP-10, PDP-11, and VAX. Be sure to delete all previous source files before you unpack the Zip archive, or unpack it into a new directory structure. WARNING: V2.10 has a new, more comprehensive save file format. Restoring save files from previous releases will cause 'invalid register' errors and loss of CPU option flags, device enable/ disable flags, unit online/offline flags, and unit writelock flags. WARNING: If you are using Visual Studio .NET through the IDE, be sure to turn off the /Wp64 flag in the project settings, or dozens of spurious errors will be generated. WARNING: Compiling Ethernet support under Windows requires extra steps; see the Ethernet readme file. Ethernet support is currently available only for Windows, Linux, NetBSD, and OpenBSD.
This commit is contained in:
parent
4ea745b3ad
commit
2bcd1e7c4c
206 changed files with 30253 additions and 12114 deletions
154
0readme_210.txt
154
0readme_210.txt
|
@ -1,28 +1,97 @@
|
|||
Notes For V2.10-1
|
||||
Notes For V2.10-2
|
||||
|
||||
WARNING: V2.10 has reorganized and renamed some of the definition
|
||||
files for the PDP-10, PDP-11, and VAX. Be sure to delete all
|
||||
previous source files before you unpack the Zip archive, or
|
||||
unpack it into a new directory structure.
|
||||
1. New Features in 2.10-2
|
||||
|
||||
WARNING: V2.10 has a new, more comprehensive save file format.
|
||||
Restoring save files from previous releases will cause 'invalid
|
||||
register' errors and loss of CPU option flags, device enable/
|
||||
disable flags, unit online/offline flags, and unit writelock
|
||||
flags.
|
||||
The build procedures have changed. There is only one UNIX makefile.
|
||||
To compile without Ethernet support, simply type
|
||||
|
||||
WARNING: If you are using Visual Studio .NET through the IDE,
|
||||
be sure to turn off the /Wp64 flag in the project settings, or
|
||||
dozens of spurious errors will be generated.
|
||||
gmake {target|all}
|
||||
|
||||
WARNING: Compiling Ethernet support under Windows requires
|
||||
extra steps; see the Ethernet readme file. Ethernet support is
|
||||
currently available only for Windows, Linux, NetBSD, and OpenBSD.
|
||||
To compile with Ethernet support, type
|
||||
|
||||
1. New Features
|
||||
gmake USE_NETWORK=1 {target|all}
|
||||
|
||||
The Mingw batch files require Mingw release 2 and invoke the Unix
|
||||
makefile. There are still separate batch files for compilation
|
||||
with or without Ethernet support.
|
||||
|
||||
1.1 SCP and Libraries
|
||||
|
||||
- The EVAL command will evaluate a symbolic type-in and display
|
||||
it in numeric form.
|
||||
- The ! command (with no arguments) will launch the host operating
|
||||
system command shell. The ! command (with an argument) executes
|
||||
the argument as a host operating system command. (Code from
|
||||
Mark Pizzolato)
|
||||
- Telnet sessions now recognize BREAK. How a BREAK is transmitted
|
||||
dependent on the particular Telnet client. (Code from Mark
|
||||
Pizzolato)
|
||||
- The sockets library includes code for active connections as
|
||||
well as listening connections.
|
||||
- The RESTORE command will restore saved memory size, if the
|
||||
simulator supports dynamic memory resizing.
|
||||
|
||||
1.2 PDP-1
|
||||
|
||||
- The PDP-1 supports the Type 24 serial drum (based on recently
|
||||
discovered documents).
|
||||
|
||||
1.3 18b PDP's
|
||||
|
||||
- The PDP-4 supports the Type 24 serial drum (based on recently
|
||||
discovered documents).
|
||||
|
||||
1.4 PDP-11
|
||||
|
||||
- The PDP-11 implements a stub DEUNA/DELUA (XU). The real XU
|
||||
module will be included in a later release.
|
||||
|
||||
1.5 PDP-10
|
||||
|
||||
- The PDP-10 implements a stub DEUNA/DELUA (XU). The real XU
|
||||
module will be included in a later release.
|
||||
|
||||
1.6 HP 2100
|
||||
|
||||
- The IOP microinstruction set is supported for the 21MX as well
|
||||
as the 2100.
|
||||
- The HP2100 supports the Access Interprocessor Link (IPL).
|
||||
|
||||
1.7 VAX
|
||||
|
||||
- If the VAX console is attached to a Telnet session, BREAK is
|
||||
interpreted as console halt.
|
||||
- The SET/SHOW HISTORY commands enable and display a history of
|
||||
the most recently executed instructions. (Code from Mark
|
||||
Pizzolato)
|
||||
|
||||
1.8 Terminals Multiplexors
|
||||
|
||||
- BREAK detection was added to the HP, DEC, and Interdata terminal
|
||||
multiplexors.
|
||||
|
||||
1.9 Interdata 16b and 32b
|
||||
|
||||
- First release. UNIX is not yet working.
|
||||
|
||||
1.10 SDS 940
|
||||
|
||||
- First release.
|
||||
|
||||
2. Bugs Fixed in 2.10-2
|
||||
|
||||
- PDP-11 console must default to 7b for early UNIX compatibility.
|
||||
- PDP-11/VAX TMSCP emulator was using the wrong packet length for
|
||||
read/write end packets.
|
||||
- Telnet IAC+IAC processing was fixed, both for input and output
|
||||
(found by Mark Pizzolato).
|
||||
- PDP-11/VAX Ethernet setting flag bits wrong for chained
|
||||
descriptors (found by Mark Pizzolato).
|
||||
|
||||
3. New Features in 2.10 vs prior releases
|
||||
|
||||
3.1 SCP and Libraries
|
||||
|
||||
- The VT emulation package has been replaced by the capability
|
||||
to remote the console to a Telnet session. Telnet clients
|
||||
typically have more complete and robust VT100 emulation.
|
||||
|
@ -49,7 +118,7 @@ currently available only for Windows, Linux, NetBSD, and OpenBSD.
|
|||
- SAVE now saves, and GET now restores, controller and unit flags.
|
||||
- Library sim_ether.c has been added for Ethernet support.
|
||||
|
||||
1.2 VAX
|
||||
3.2 VAX
|
||||
|
||||
- Non-volatile RAM (NVR) can behave either like a memory or like
|
||||
a disk-based peripheral. If unattached, it behaves like memory
|
||||
|
@ -69,7 +138,7 @@ currently available only for Windows, Linux, NetBSD, and OpenBSD.
|
|||
the CPU.
|
||||
- Device address conflicts are not detected until simulation starts.
|
||||
|
||||
1.3 PDP-11
|
||||
3.3 PDP-11
|
||||
|
||||
- SHOW <device> VECTOR displays the device's interrupt vector.
|
||||
Most devices allow the vector to be changed with SET
|
||||
|
@ -91,7 +160,7 @@ currently available only for Windows, Linux, NetBSD, and OpenBSD.
|
|||
with the current bus configuration to be disabled.
|
||||
- Device address conflicts are not detected until simulation starts.
|
||||
|
||||
1.4 PDP-10
|
||||
3.4 PDP-10
|
||||
|
||||
- SHOW <device> VECTOR displays the device's interrupt vector.
|
||||
A few devices allow the vector to be changed with SET
|
||||
|
@ -103,12 +172,12 @@ currently available only for Windows, Linux, NetBSD, and OpenBSD.
|
|||
dec_pt.h.
|
||||
- Device address conflicts are not detected until simulation starts.
|
||||
|
||||
1.5 PDP-1
|
||||
3.5 PDP-1
|
||||
|
||||
- DECtape (then known as MicroTape) support has been added.
|
||||
- The line printer and DECtape can be disabled and enabled.
|
||||
|
||||
1.6 PDP-8
|
||||
3.6 PDP-8
|
||||
|
||||
- The RX28 (double density floppy) has been added as an option to
|
||||
the existing RX8E controller.
|
||||
|
@ -117,16 +186,16 @@ currently available only for Windows, Linux, NetBSD, and OpenBSD.
|
|||
DEVNO=nnn.
|
||||
- Device number conflicts are not detected until simulation starts.
|
||||
|
||||
1.7 IBM 1620
|
||||
3.7 IBM 1620
|
||||
|
||||
- The IBM 1620 simulator has been released.
|
||||
|
||||
1.8 AltairZ80
|
||||
3.8 AltairZ80
|
||||
|
||||
- A hard drive has been added for increased storage.
|
||||
- Several bugs have been fixed.
|
||||
|
||||
1.9 HP 2100
|
||||
3.9 HP 2100
|
||||
|
||||
- The 12845A has been added and made the default line printer (LPT).
|
||||
The 12653A has been renamed LPS and is off by default. It also
|
||||
|
@ -143,7 +212,7 @@ currently available only for Windows, Linux, NetBSD, and OpenBSD.
|
|||
instructions for the 21MX.
|
||||
- The 12539 timebase generator autocalibrates.
|
||||
|
||||
1.10 Simulated Magtapes
|
||||
3.10 Simulated Magtapes
|
||||
|
||||
- Simulated magtapes recognize end of file and the marker
|
||||
0xFFFFFFFF as end of medium. Only the TMSCP tape simulator
|
||||
|
@ -151,13 +220,11 @@ currently available only for Windows, Linux, NetBSD, and OpenBSD.
|
|||
- The error handling in simulated magtapes was overhauled to be
|
||||
consistent through all simulators.
|
||||
|
||||
1.11 Simulated DECtapes
|
||||
3.11 Simulated DECtapes
|
||||
|
||||
- Added support for RT11 image file format (256 x 16b) to DECtapes.
|
||||
|
||||
2. Release Notes
|
||||
|
||||
2.1 Bugs Fixed
|
||||
4. Bugs Fixed in 2.10 vs prior releases
|
||||
|
||||
- TS11/TSV05 was not simulating the XS0_MOT bit, causing failures
|
||||
under VMS. In addition, two of the CTL options were coded
|
||||
|
@ -176,18 +243,23 @@ currently available only for Windows, Linux, NetBSD, and OpenBSD.
|
|||
- PDP-1 typewriter is half duplex, with only one shift state for
|
||||
both input and output (found by Derek Peschel)
|
||||
|
||||
2.2 HP 2100 Debugging
|
||||
5. General Notes
|
||||
|
||||
- The HP 2100 CPU nows runs all of the CPU diagnostics.
|
||||
- The peripherals run most of the peripheral diagnostics. There
|
||||
is still a problem in overlapped seek operation on the disks.
|
||||
See the file hp2100_diag.txt for details.
|
||||
WARNING: V2.10 has reorganized and renamed some of the definition
|
||||
files for the PDP-10, PDP-11, and VAX. Be sure to delete all
|
||||
previous source files before you unpack the Zip archive, or
|
||||
unpack it into a new directory structure.
|
||||
|
||||
3. In Progress
|
||||
WARNING: V2.10 has a new, more comprehensive save file format.
|
||||
Restoring save files from previous releases will cause 'invalid
|
||||
register' errors and loss of CPU option flags, device enable/
|
||||
disable flags, unit online/offline flags, and unit writelock
|
||||
flags.
|
||||
|
||||
These simulators are not finished and are available in a separate
|
||||
Zip archive distribution.
|
||||
WARNING: If you are using Visual Studio .NET through the IDE,
|
||||
be sure to turn off the /Wp64 flag in the project settings, or
|
||||
dozens of spurious errors will be generated.
|
||||
|
||||
- Interdata 16b/32b: coded, partially tested. See the file
|
||||
id_diag.txt for details.
|
||||
- SDS 940: coded, partially tested.
|
||||
WARNING: Compiling Ethernet support under Windows requires
|
||||
extra steps; see the Ethernet readme file. Ethernet support is
|
||||
currently available only for Windows, Linux, NetBSD, and OpenBSD.
|
||||
|
|
|
@ -2,6 +2,16 @@ This file contains information about the XQ/SIM_ETHER package.
|
|||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
16-Jan-03 Release:
|
||||
1. Added VMScluster support (thanks to Mark Pizzolato)
|
||||
2. Verified VAX remote boot functionality (>>>B XQA0)
|
||||
3. Added major performance enhancements (thanks to Mark Pizzolato again)
|
||||
4. Changed _DEBUG tracers to XQ_DEBUG and ETH_DEBUG
|
||||
5. Added local packet processing
|
||||
6. Added system id broadcast
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
GOLD Changes: (08-Nov-02)
|
||||
1. Added USE_NETWORK conditional to Sim_Ether
|
||||
2. Fixed behaviour of SHOW XQ ETH if no devices exist
|
||||
|
@ -68,19 +78,18 @@ supports Windows, Linux, and NetBSD.
|
|||
|
||||
Currently, the Sim_Ether module sets the selected ethernet card into
|
||||
promiscuous mode to gather all packets, then filters out the packets that it
|
||||
doesn't want. This method is somewhat inefficient and will be looked at in
|
||||
future versions. Packets having the same source MAC address as the
|
||||
doesn't want. In Windows, Packets having the same source MAC address as the
|
||||
controller are ignored for WinPCAP compatibility (see Windows notes below).
|
||||
|
||||
If your ethernet card is plugged into a switch, the promiscuous mode setting
|
||||
should not cause much of a problem, since the switch will still filter out
|
||||
most of the undesirable traffic. You will only see "excessive" traffic if you
|
||||
are on a hub(repeater) or a direct lan (thickwire/thinwire) segment.
|
||||
are on a direct or hub(repeater) segment.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Windows notes:
|
||||
1. The Windows-specific code uses the WinPCAP 3.0 package from
|
||||
1. The Windows-specific code uses the WinPCAP 3.0 (or 2.3) package from
|
||||
http://winpcap.polito.it. This package for windows simulates the libpcap
|
||||
package that is freely available for unix systems.
|
||||
2. You must *install* WinPCAP.
|
||||
|
@ -91,8 +100,9 @@ Windows notes:
|
|||
but this defeats DECNET's duplicate node number detection scheme. A more
|
||||
correct fix for WinPCAP will be explored as time allows.
|
||||
5. The first time the WinPCAP driver is used, it will be dynamically loaded,
|
||||
and the user must be an Administrator on the machine to do so. See the
|
||||
WinPCAP documentation for a static load workaround if needed.
|
||||
and the user must be an Administrator on the machine to do so. If you need
|
||||
to run as an unprivileged user, you must set the service to autostart. See
|
||||
the WinPCAP documentation for details on the static load workaround.
|
||||
|
||||
Building on Windows:
|
||||
1. Install WinPCAP 3.0.
|
||||
|
@ -109,8 +119,10 @@ Building on Windows:
|
|||
Linux, NetBSD, and OpenBSD notes:
|
||||
|
||||
1. You must run SIMH(scp) as root so that the ethernet card can be set into
|
||||
promiscuous mode by the driver.
|
||||
promiscuous mode by the driver. Alternative suggestions will be welcomed.
|
||||
|
||||
Building on Linux, NetBSD, and OpenBSD:
|
||||
1. Define USE_NETWORK if you want the network functionality.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
@ -136,28 +148,25 @@ Regression test criteria:
|
|||
15. LAT loads sucessfully (passed)
|
||||
16. SET HOST/LAT <nodename> works from SIMH to real VAX LAT machine (passed)
|
||||
17. SET HOST/LAT <nodename> works from real VAX LAT machine to SIMH (passed)
|
||||
18. SIMH node joins VMSCluster (passed)
|
||||
19. SIMH node mounts other VMSCluster disks (passed)
|
||||
20. SIMH node MSCP serves disks to other nodes (passed)
|
||||
21. SIMH node remote boots into VMScluster (>>>B XQAO) (passed)
|
||||
|
||||
I have NOT tested the following, but have reports that the following work:
|
||||
1. Operation with the PDP-11 emulator (RSX)
|
||||
2. Remote booting of NetBSD (via >>> B XQA0)
|
||||
The following are known to NOT work:
|
||||
1. PDP-11 using RSTS/E v10.1 (fails to enable device - needs bootrom support)
|
||||
|
||||
I have tested the following, and they do NOT work correctly:
|
||||
1. VMS NI Clustering (LAVC)
|
||||
2. Remote VAX booting (>>>B XQA0) into a VMScluster;
|
||||
the remote boot works, but VMS BUGCHECKs when joining the cluster
|
||||
I have reports that the following work:
|
||||
1. PDP-11 using RSX
|
||||
2. VAX remote booting of NetBSD (via >>> B XQA0)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Things planned for future releases:
|
||||
1. Loopback packet processing
|
||||
2. Full MOP implementation
|
||||
3. Identity broadcast, which should occur every 8-10 minutes
|
||||
4. Full support for network boot (>> B XQA0)
|
||||
5. VMS NI Cluster (LAVC) support
|
||||
6. More efficient Sim_Ether module implementation for windows
|
||||
7. PDP-11 bootstrap
|
||||
8. DESQA support (if someone can get me the user manuals)
|
||||
9. DETQA support [DELQA-Turbo] (I have the manual)
|
||||
1. Full MOP implementation
|
||||
2. PDP-11 bootstrap/bootrom
|
||||
3. DESQA support (if someone can get me the user manuals)
|
||||
4. DETQA support [DELQA-Turbo] (I have the manual)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
@ -166,16 +175,13 @@ Things which I need help with:
|
|||
2. Information about Remote MOP processing
|
||||
3. PDP-11 bootstrap code.
|
||||
4. VAX hardware diagnotics image file and docs, to test XQ thoroughly.
|
||||
5. Feedback on the ethernet timing clock interval.
|
||||
6. Feedback on operation with other VAX OS's.
|
||||
7. Feedback on operation of PDP-11 OS's.
|
||||
5. Feedback on operation with other VAX OS's.
|
||||
6. Feedback on operation with PDP-11 OS's.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Please send all patches, questions, feedback, clarifications, and help to:
|
||||
dhittner AT northropgrumman DOT com
|
||||
|
||||
NOTE: I _have_ corrected my email address!! Sorry about the confusion!
|
||||
|
||||
Thanks, and Enjoy!!
|
||||
Dave
|
||||
|
|
|
@ -93,10 +93,10 @@ int32 sio0s (int32 port, int32 io, int32 data);
|
|||
int32 sio1d (int32 port, int32 io, int32 data);
|
||||
int32 sio1s (int32 port, int32 io, int32 data);
|
||||
void reset_sio_terminals(int32 useDefault);
|
||||
t_stat simh_dev_reset(void);
|
||||
t_stat simh_dev_reset(DEVICE *dptr);
|
||||
t_stat simh_svc(UNIT *uptr);
|
||||
t_stat simh_dev_set_timeron(void);
|
||||
t_stat simh_dev_set_timeroff(void);
|
||||
t_stat simh_dev_set_timeron(UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat simh_dev_set_timeroff(UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
int32 simh_in(void);
|
||||
int32 simh_out(int32 data);
|
||||
void attachCPM(UNIT *uptr);
|
||||
|
@ -641,7 +641,7 @@ struct tm *currentTime = NULL;
|
|||
uint32 markTime[splimit];
|
||||
char version[] = "SIMH002";
|
||||
|
||||
t_stat simh_dev_reset(void) {
|
||||
t_stat simh_dev_reset(DEVICE *dptr) {
|
||||
currentTime = NULL;
|
||||
ClockZSDOSDelta = 0;
|
||||
setClockZSDOSPos = 0;
|
||||
|
@ -658,12 +658,12 @@ t_stat simh_dev_reset(void) {
|
|||
lastCPMStatus = SCPE_OK;
|
||||
timerInterrupt = FALSE;
|
||||
if (simh_unit.flags & UNIT_SIMH_TIMERON) {
|
||||
simh_dev_set_timeron();
|
||||
simh_dev_set_timeron(NULL, 0, NULL, NULL);
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat simh_dev_set_timeron(void) {
|
||||
t_stat simh_dev_set_timeron(UNIT *uptr, int32 val, char *cptr, void *desc) {
|
||||
if (rtc_avail) {
|
||||
timeOfNextInterrupt = sim_os_msec() + timerDelta;
|
||||
return sim_activate(&simh_unit, simh_unit.wait); /* activate unit */
|
||||
|
@ -674,7 +674,7 @@ t_stat simh_dev_set_timeron(void) {
|
|||
}
|
||||
}
|
||||
|
||||
t_stat simh_dev_set_timeroff(void) {
|
||||
t_stat simh_dev_set_timeroff(UNIT *uptr, int32 val, char *cptr, void *desc) {
|
||||
timerInterrupt = FALSE;
|
||||
sim_cancel(&simh_unit);
|
||||
return SCPE_OK;
|
||||
|
@ -997,14 +997,14 @@ int32 simh_out(int32 data) {
|
|||
cpu_unit.flags &= ~UNIT_CHIP;
|
||||
break;
|
||||
case startTimerInterruptsCmd:
|
||||
if (simh_dev_set_timeron() == SCPE_OK) {
|
||||
if (simh_dev_set_timeron(NULL, 0, NULL, NULL) == SCPE_OK) {
|
||||
timerInterrupt = FALSE;
|
||||
simh_unit.flags |= UNIT_SIMH_TIMERON;
|
||||
}
|
||||
break;
|
||||
case stopTimerInterruptsCmd:
|
||||
simh_unit.flags &= ~UNIT_SIMH_TIMERON;
|
||||
simh_dev_set_timeroff();
|
||||
simh_dev_set_timeroff(NULL, 0, NULL, NULL);
|
||||
break;
|
||||
case setTimerDeltaCmd:
|
||||
setTimerDeltaPos = 0;
|
||||
|
|
|
@ -450,11 +450,11 @@ else if ((src != U_MEM) && (dst == U_TRP)) { /* cond jump */
|
|||
case 05: /* src >= 0 */
|
||||
jmp = (t < SIGN);
|
||||
break;
|
||||
case 06:
|
||||
jmp = (t == 0) || (t & SIGN); /* src <= 0 */
|
||||
case 06: /* src <= 0 */
|
||||
jmp = (t == 0) || (t & SIGN);
|
||||
break;
|
||||
case 07:
|
||||
jmp = (t != 0) && !(t & SIGN); /* src > 0 */
|
||||
case 07: /* src > 0 */
|
||||
jmp = (t != 0) && !(t & SIGN);
|
||||
break; }
|
||||
if (jmp) { /* jump taken? */
|
||||
SCQ_ENTRY; /* save SC */
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
hsp S42-006 high speed punch
|
||||
rtc real time clock
|
||||
|
||||
22-Dec-02 RMS Added break support
|
||||
01-Nov-02 RMS Added 7b/8B support to terminal
|
||||
*/
|
||||
|
||||
|
@ -228,7 +229,8 @@ int32 c;
|
|||
|
||||
sim_activate (&tti_unit, tti_unit.wait); /* continue poll */
|
||||
if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */
|
||||
if (tti_unit.flags & UNIT_KSR) { /* KSR? */
|
||||
if (c & SCPE_BREAK) tti_unit.buf = 0; /* break? */
|
||||
else if (tti_unit.flags & UNIT_KSR) { /* KSR? */
|
||||
c = c & 0177; /* force 7b */
|
||||
if (islower (c)) c = toupper (c); /* cvt to UC */
|
||||
tti_unit.buf = c | 0200; } /* add TTY bit */
|
||||
|
|
|
@ -349,7 +349,8 @@ for (i = 0; opcode[i] != NULL; i++) { /* loop thru ops */
|
|||
if (bop) fprintf (of, "%s %s,%s", opcode[i + 2],
|
||||
unsrc[src], opname[bop]);
|
||||
else fprintf (of, "%s %s", opcode[i + 2], unsrc[src]); }
|
||||
else { if (bop) fprintf (of, "%s %s,%s,%s", opcode[i],
|
||||
else {
|
||||
if (bop) fprintf (of, "%s %s,%s,%s", opcode[i],
|
||||
unsrc[src], opname[bop], undst[dst]);
|
||||
else fprintf (of, "%s %s,%s", opcode[i],
|
||||
unsrc[src], undst[dst]); }
|
||||
|
@ -419,7 +420,7 @@ while (*cptr) {
|
|||
for (i = 0; fname[i] != NULL; i++) { /* search table */
|
||||
if ((strcmp (gbuf, fname[i]) == 0) && /* match for inst? */
|
||||
((inst & fop[i].imask) == fop[i].inst)) {
|
||||
if (fop[i].oper & fncm) return NULL; /* already filled? */
|
||||
if (fop[i].oper & fncm) return NULL;/* already filled? */
|
||||
fncm = fncm | fop[i].omask;
|
||||
fncv = fncv | fop[i].oper;
|
||||
break; } }
|
||||
|
|
|
@ -608,7 +608,8 @@ case 020:
|
|||
switch (I_GETFNC (MB)) { /* case shift fnc */
|
||||
case 000: /* LRL */
|
||||
if (t1 > 32) ut = 0; /* >32? all 0 */
|
||||
else { ut = GETDBL_U (AR, BR); /* get A'B */
|
||||
else {
|
||||
ut = GETDBL_U (AR, BR); /* get A'B */
|
||||
C = (ut >> (t1 - 1)) & 1; /* C = last out */
|
||||
ut = ut >> t1; } /* log right */
|
||||
PUTDBL_U (ut); /* store A,B */
|
||||
|
@ -637,7 +638,8 @@ case 020:
|
|||
break;
|
||||
case 004: /* LGR */
|
||||
if (t1 > 16) AR = 0; /* > 16? all 0 */
|
||||
else { C = (AR >> (t1 - 1)) & 1; /* C = last out */
|
||||
else {
|
||||
C = (AR >> (t1 - 1)) & 1; /* C = last out */
|
||||
AR = (AR >> t1) & DMASK; } /* log right */
|
||||
break;
|
||||
case 005: /* ARS */
|
||||
|
@ -661,7 +663,8 @@ case 020:
|
|||
|
||||
case 010: /* LLL */
|
||||
if (t1 > 32) ut = 0; /* > 32? all 0 */
|
||||
else { ut = GETDBL_U (AR, BR); /* get A'B */
|
||||
else {
|
||||
ut = GETDBL_U (AR, BR); /* get A'B */
|
||||
C = (ut >> (32 - t1)) & 1; /* C = last out */
|
||||
ut = ut << t1; } /* log left */
|
||||
PUTDBL_U (ut); /* store A,B */
|
||||
|
@ -692,7 +695,8 @@ case 020:
|
|||
break;
|
||||
case 014: /* LGL */
|
||||
if (t1 > 16) AR = 0; /* > 16? all 0 */
|
||||
else { C = (AR >> (16 - t1)) & 1; /* C = last out */
|
||||
else {
|
||||
C = (AR >> (16 - t1)) & 1; /* C = last out */
|
||||
AR = (AR << t1) & DMASK; } /* log left */
|
||||
break;
|
||||
case 015: /* ALS */
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
tty 316/516-33 teleprinter
|
||||
clk/options 316/516-12 real time clocks/internal options
|
||||
|
||||
22-Dec-02 RMS Added break support
|
||||
01-Nov-02 RMS Added 7b/8b support to terminal
|
||||
30-May-02 RMS Widened POS to 32b
|
||||
03-Nov-01 RMS Implemented upper case for console output
|
||||
|
@ -349,7 +350,8 @@ switch (inst) { /* case on opcode */
|
|||
case ioOCP: /* OCP */
|
||||
if (fnc & 016) return IOBADFNC (dat); /* only fnc 0,1 */
|
||||
if (fnc && (tty_mode == 0)) { /* input to output? */
|
||||
if (!sim_is_active (&tty_unit[TTO])) SET_READY (INT_TTY);
|
||||
if (!sim_is_active (&tty_unit[TTO])) /* set ready */
|
||||
SET_READY (INT_TTY);
|
||||
tty_mode = 1; } /* mode is output */
|
||||
else if ((fnc == 0) && tty_mode) { /* output to input? */
|
||||
CLR_READY (INT_TTY); /* clear ready */
|
||||
|
@ -396,7 +398,8 @@ int32 out, c;
|
|||
sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* continue poll */
|
||||
if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */
|
||||
out = c & 0177; /* mask echo to 7b */
|
||||
if (tty_unit[TTI].flags & UNIT_KSR) { /* KSR? */
|
||||
if (c & SCPE_BREAK) c = 0; /* break? */
|
||||
else if (tty_unit[TTI].flags & UNIT_KSR) { /* KSR? */
|
||||
if (islower (out)) out = toupper (out); /* cvt to UC */
|
||||
c = out | 0200; } /* add TTY bit */
|
||||
else c = c & ((tty_unit[TTI].flags & UNIT_8B)? 0377: 0177);
|
||||
|
@ -404,7 +407,7 @@ if (tty_mode == 0) { /* input mode? */
|
|||
tty_buf = c; /* put char in buf */
|
||||
tty_unit[TTI].pos = tty_unit[TTI].pos + 1;
|
||||
SET_READY (INT_TTY); /* set flag */
|
||||
sim_putchar (out); } /* echo */
|
||||
if (out) sim_putchar (out); } /* echo */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -452,7 +455,8 @@ case ioOCP: /* OCP */
|
|||
if (fnc & 015) return IOBADFNC (dat); /* only fnc 0,2 */
|
||||
CLR_READY (INT_CLK); /* reset ready */
|
||||
if (fnc) sim_cancel (&clk_unit); /* fnc = 2? stop */
|
||||
else { if (!sim_is_active (&clk_unit)) /* fnc = 0? start */
|
||||
else { /* fnc = 0? */
|
||||
if (!sim_is_active (&clk_unit))
|
||||
sim_activate (&clk_unit, /* activate */
|
||||
sim_rtc_init (clk_unit.wait)); } /* init calibr */
|
||||
break;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
22-Nov-02 RMS Added 21MX IOP support
|
||||
24-Oct-02 RMS Fixed bugs in IOP and extended instructions
|
||||
Fixed bugs in memory protection and DMS
|
||||
Added clock calibration
|
||||
|
@ -283,8 +284,9 @@
|
|||
#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 + 5) /* DMS */
|
||||
#define UNIT_V_IOP (UNIT_V_UF + 6) /* IOP */
|
||||
#define UNIT_V_MSIZE (UNIT_V_UF + 7) /* dummy mask */
|
||||
#define UNIT_V_IOP (UNIT_V_UF + 6) /* 2100 IOP */
|
||||
#define UNIT_V_IOPX (UNIT_V_UF + 7) /* 21MX IOP */
|
||||
#define UNIT_V_MSIZE (UNIT_V_UF + 8) /* dummy mask */
|
||||
#define UNIT_2100 (1 << UNIT_V_2100)
|
||||
#define UNIT_21MX (1 << UNIT_V_21MX)
|
||||
#define UNIT_EAU (1 << UNIT_V_EAU)
|
||||
|
@ -292,6 +294,7 @@
|
|||
#define UNIT_MPR (1 << UNIT_V_MPR)
|
||||
#define UNIT_DMS (1 << UNIT_V_DMS)
|
||||
#define UNIT_IOP (1 << UNIT_V_IOP)
|
||||
#define UNIT_IOPX (1 << UNIT_V_IOPX)
|
||||
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
|
||||
|
||||
#define MOD_2116 1
|
||||
|
@ -330,6 +333,7 @@ uint32 dms_ump = 0; /* dms user map */
|
|||
uint32 dms_sr = 0; /* dms status reg */
|
||||
uint32 dms_vr = 0; /* dms violation reg */
|
||||
uint32 dms_map[MAP_NUM * MAP_LNT] = { 0 }; /* dms maps */
|
||||
uint32 iop_sp = 0; /* iop stack */
|
||||
uint32 ind_max = 16; /* iadr nest limit */
|
||||
uint32 stop_inst = 1; /* stop on ill inst */
|
||||
uint32 stop_dev = 0; /* stop on ill dev */
|
||||
|
@ -347,7 +351,7 @@ static struct opt_table opt_val[] = {
|
|||
{ UNIT_FP, MOD_2100 },
|
||||
{ UNIT_MPR, MOD_2100 | MOD_21MX },
|
||||
{ UNIT_DMS, MOD_21MX },
|
||||
{ UNIT_IOP, MOD_2100 },
|
||||
{ UNIT_IOP, MOD_2100 | MOD_21MX },
|
||||
{ 0, 0 } };
|
||||
|
||||
extern int32 sim_interval;
|
||||
|
@ -431,6 +435,7 @@ REG cpu_reg[] = {
|
|||
{ ORDATA (DMSSR, dms_sr, 16) },
|
||||
{ ORDATA (DMSVR, dms_vr, 16) },
|
||||
{ BRDATA (DMSMAP, dms_map, 8, PA_N_SIZE, MAP_NUM * MAP_LNT) },
|
||||
{ ORDATA (IOPSP, iop_sp, 16) },
|
||||
{ FLDATA (STOP_INST, stop_inst, 0) },
|
||||
{ FLDATA (STOP_DEV, stop_dev, 1) },
|
||||
{ DRDATA (INDMAX, ind_max, 16), REG_NZ + PV_LEFT },
|
||||
|
@ -448,34 +453,36 @@ REG cpu_reg[] = {
|
|||
{ NULL } };
|
||||
|
||||
MTAB cpu_mod[] = {
|
||||
{ UNIT_2100+UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_MPR+UNIT_DMS+UNIT_IOP,
|
||||
{ UNIT_2100+UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_MPR+UNIT_DMS+UNIT_IOP+UNIT_IOPX,
|
||||
0, NULL, "2116", NULL },
|
||||
{ UNIT_2100+UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_MPR+UNIT_DMS+UNIT_IOP,
|
||||
{ UNIT_2100+UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_MPR+UNIT_DMS+UNIT_IOP+UNIT_IOPX,
|
||||
UNIT_2100+UNIT_EAU, NULL, "2100", NULL },
|
||||
{ UNIT_2100+UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_MPR+UNIT_DMS+UNIT_IOP,
|
||||
{ UNIT_2100+UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_MPR+UNIT_DMS+UNIT_IOP+UNIT_IOPX,
|
||||
UNIT_21MX+UNIT_EAU+UNIT_FP+UNIT_MPR+UNIT_DMS, NULL, "21MX", NULL },
|
||||
{ UNIT_2100+UNIT_21MX, 0, "2116", NULL, NULL },
|
||||
{ UNIT_2100+UNIT_21MX, UNIT_2100, "2100", NULL, NULL },
|
||||
{ UNIT_2100+UNIT_21MX, UNIT_21MX, "21MX", NULL, NULL },
|
||||
{ UNIT_EAU, UNIT_EAU, "EAU", "EAU", &cpu_set_opt,
|
||||
NULL, (void *) UNIT_EAU },
|
||||
{ UNIT_EAU, 0, "NOEAU", "NOEAU", &cpu_set_opt,
|
||||
{ UNIT_EAU, 0, "no EAU", "NOEAU", &cpu_set_opt,
|
||||
NULL, (void *) UNIT_EAU },
|
||||
{ UNIT_FP, UNIT_FP, "FP", "FP", &cpu_set_opt,
|
||||
NULL, (void *) UNIT_FP },
|
||||
{ UNIT_FP, 0, "NOFP", "NOFP", &cpu_set_opt,
|
||||
{ UNIT_FP, 0, "no FP", "NOFP", &cpu_set_opt,
|
||||
NULL, (void *) UNIT_FP },
|
||||
{ UNIT_MPR, UNIT_MPR, "MPR", "MPR", &cpu_set_opt,
|
||||
NULL, (void *) UNIT_MPR },
|
||||
{ UNIT_MPR, 0, "NOMPR", "NOMPR", &cpu_set_opt,
|
||||
{ UNIT_MPR, 0, "no MPR", "NOMPR", &cpu_set_opt,
|
||||
NULL, (void *) UNIT_MPR },
|
||||
{ UNIT_DMS, UNIT_DMS, "DMS", "DMS", &cpu_set_opt,
|
||||
NULL, (void *) UNIT_DMS },
|
||||
{ UNIT_DMS, 0, "NODMS", "NODMS", &cpu_set_opt,
|
||||
{ UNIT_DMS, 0, "no DMS", "NODMS", &cpu_set_opt,
|
||||
NULL, (void *) UNIT_DMS },
|
||||
{ UNIT_IOP, UNIT_IOP, "IOP", "IOP", &cpu_set_opt,
|
||||
{ UNIT_MSIZE, 2, NULL, "IOP", &cpu_set_opt,
|
||||
NULL, (void *) UNIT_IOP },
|
||||
{ UNIT_IOP, 0, "NOIOP", "NOIOP", &cpu_set_opt,
|
||||
{ UNIT_IOP+UNIT_IOPX, UNIT_IOP, "IOP", NULL, NULL },
|
||||
{ UNIT_IOP+UNIT_IOPX, UNIT_IOPX, "IOP", NULL, NULL },
|
||||
{ UNIT_IOP+UNIT_IOPX, 0, "no IOP", "NOIOP", &cpu_set_opt,
|
||||
NULL, (void *) UNIT_IOP },
|
||||
{ UNIT_MSIZE, 4096, NULL, "4K", &cpu_set_size },
|
||||
{ UNIT_MSIZE, 8192, NULL, "8K", &cpu_set_size },
|
||||
|
@ -544,6 +551,7 @@ DEVICE dma1_dev = {
|
|||
#define E_21MX (UNIT_21MX >> (UNIT_V_UF - E_V_FL))
|
||||
#define E_DMS (UNIT_DMS >> (UNIT_V_UF - E_V_FL))
|
||||
#define E_IOP (UNIT_IOP >> (UNIT_V_UF - E_V_FL))
|
||||
#define E_IOPX (UNIT_IOPX >> (UNIT_V_UF - E_V_FL))
|
||||
#define E_V_TY 8 /* type */
|
||||
#define E_M_TY 0xF
|
||||
#define E_NO 0 /* no operands */
|
||||
|
@ -558,7 +566,7 @@ DEVICE dma1_dev = {
|
|||
#define ET_CN (E_CN << E_V_TY)
|
||||
#define ET_AC (E_AC << E_V_TY)
|
||||
#define ET_AZ (E_AZ << E_V_TY)
|
||||
#define E_V_TYI 12 /* type if IOP */
|
||||
#define E_V_TYI 12 /* type if 2100 IOP */
|
||||
#define E_GETFL(x) (((x) >> E_V_FL) & E_M_FL)
|
||||
#define E_GETTY(f,x) (((x) >> \
|
||||
((((f) & E_IOP) && (cpu_unit.flags & UNIT_IOP))? \
|
||||
|
@ -572,6 +580,9 @@ DEVICE dma1_dev = {
|
|||
#define D_NO E_DMS | ET_NO
|
||||
#define D_MR E_DMS | ET_AD
|
||||
#define D_AA E_DMS | ET_AA
|
||||
#define M_NO E_IOPX | ET_NO
|
||||
#define M_CN E_IOPX | ET_CN
|
||||
#define M_AC E_IOPX | ET_AC
|
||||
#define I_NO E_IOP | (ET_NO << (E_V_TYI - E_V_TY))
|
||||
#define I_CN E_IOP | (ET_CN << (E_V_TYI - E_V_TY))
|
||||
#define I_AC E_IOP | (ET_AC << (E_V_TYI - E_V_TY))
|
||||
|
@ -591,17 +602,20 @@ static const uint32 e_inst[512] = {
|
|||
0,0,0,0,0,0,0,0,I_CN,0,0,0,0,0,0,0, /* CRC */
|
||||
I_CN,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* TRSLT */
|
||||
I_AZ,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* WMOVE */
|
||||
I_NO,I_NO,I_NO,I_NO,0,0,0,0,0,0,0,0,0,0,0,0, /* READF,PFRIO,PFREI,PFRIO */
|
||||
I_NO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,I_NO, /* ENQ,ENPQ */
|
||||
I_NO,I_NO,I_NO,I_NO,0,0,0,0,0,0,0,0,0,0,0,0, /* READF,PFRIO,PFREI,PFREX */
|
||||
I_NO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,I_NO, /* ENQ,PENQ */
|
||||
I_NO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* DEQ */
|
||||
I_NO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* SBYTE */
|
||||
I_NO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* LBYTE */
|
||||
I_NO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* REST */
|
||||
0,0,I_NO,0,0,0,0,0,0,0,0,0,0,0,0,0, /* SAVE */
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0400 */
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0420 */
|
||||
M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO, /* LAI-/SAI- */
|
||||
M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,
|
||||
M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO, /* LAI+/SAI+ */
|
||||
M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0440 */
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0460 */
|
||||
M_CN,M_NO,M_NO,M_NO,M_NO,M_NO,M_NO,M_CN, /* CRC,REST,READF,INS,ENQ,PENQ,DEQ,TR */
|
||||
M_AC,M_NO,M_NO,M_NO,M_NO,0,0,0, /* ILIST,PFREI,PFREX,PFRIO,SAVE */
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0500 */
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0520 */
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0540 */
|
||||
|
@ -921,7 +935,7 @@ case 0014:case 0015:case 0016:case 0017:
|
|||
t = (t + 1) & DMASK;
|
||||
if (t == 0) E = 1;
|
||||
if (t == SIGN) O = 1; }
|
||||
if ((IR & 000002) && (t == 0)) skip = 1;/* SZx */
|
||||
if ((IR & 000002) && (t == 0)) skip = 1; /* SZx */
|
||||
} /* end if ~RSS */
|
||||
ABREG[absel] = t; /* store result */
|
||||
PC = (PC + skip) & VAMASK; /* add in skip */
|
||||
|
@ -1092,42 +1106,33 @@ case 0203:case 0213: /* MAC1 ext */
|
|||
/* Floating point instructions */
|
||||
|
||||
case 0000: /* IOP ILIST/FAD */
|
||||
if (cpu_unit.flags & UNIT_IOP) { /* ILIST (E_AC) */
|
||||
do { /* for count */
|
||||
WriteW (MA, AR); /* write AR to mem */
|
||||
AR = (AR + 1) & DMASK; /* incr AR */
|
||||
MA = (MA + 1) & VAMASK; /* incr MA */
|
||||
wc = (wc - 1) & DMASK; } /* decr count */
|
||||
while (wc != 0); }
|
||||
else { /* FAD (E_AD) */
|
||||
if (cpu_unit.flags & UNIT_IOP) /* ILIST (E_AC) */
|
||||
goto IOP_ILIST;
|
||||
fop = ReadF (MA); /* get fop */
|
||||
O = f_as (fop, 0); } /* add, upd ovflo */
|
||||
O = f_as (fop, 0); /* add, upd ovflo */
|
||||
break;
|
||||
case 0020: /* IOP LAI-/FSB */
|
||||
if (cpu_unit.flags & UNIT_IOP) /* LAI -20 (I_NO) */
|
||||
AR = ReadW ((BR - 020) & VAMASK); /* load AR */
|
||||
else { /* FSB (E_AD) */
|
||||
goto IOP_LAIM;
|
||||
fop = ReadF (MA); /* get fop */
|
||||
O = f_as (fop, 1); } /* sub, upd ovflo */
|
||||
O = f_as (fop, 1); /* sub, upd ovflo */
|
||||
break;
|
||||
case 0040: /* IOP LAI+/FMP */
|
||||
if (cpu_unit.flags & UNIT_IOP) /* LAI 0 (I_NO) */
|
||||
AR = ReadW (BR & VAMASK); /* load AR */
|
||||
else { /* FMP (E_AD) */
|
||||
goto IOP_LAIP;
|
||||
fop = ReadF (MA); /* get fop */
|
||||
O = f_mul (fop); } /* mul, upd ovflo */
|
||||
O = f_mul (fop); /* mul, upd ovflo */
|
||||
break;
|
||||
case 0060: /* IOP SAI-/FDV */
|
||||
if (cpu_unit.flags & UNIT_IOP) /* SAI -20 (I_NO) */
|
||||
WriteW ((BR - 020) & VAMASK, AR); /* store AR */
|
||||
else { /* FDV (E_AD) */
|
||||
goto IOP_SAIM;
|
||||
fop = ReadF (MA); /* get fop */
|
||||
O = f_div (fop); } /* div, upd ovflo */
|
||||
O = f_div (fop); /* div, upd ovflo */
|
||||
break;
|
||||
case 0100: /* IOP SAI+/FIX */
|
||||
if (cpu_unit.flags & UNIT_IOP) /* SAI 0 (I_NO) */
|
||||
WriteW (BR & VAMASK, AR); /* store AR */
|
||||
else O = f_fix (); /* FIX (E_NO) */
|
||||
goto IOP_SAIP;
|
||||
O = f_fix (); /* FIX (E_NO) */
|
||||
break;
|
||||
case 0120: /* IOP MBYTE/FLT */
|
||||
if (cpu_unit.flags & UNIT_IOP) /* MBYTE (I_AZ) */
|
||||
|
@ -1135,30 +1140,30 @@ case 0203:case 0213: /* MAC1 ext */
|
|||
O = f_flt (); /* FLT (E_NO) */
|
||||
break;
|
||||
|
||||
/* IOP instructions */
|
||||
/* 2100 (and 21MX) IOP instructions */
|
||||
|
||||
case 0021: case 0022: case 0023: /* IOP LAI- (I_NO) */
|
||||
IOP_LAIM: case 0021: case 0022: case 0023: /* IOP LAI- (I_NO) */
|
||||
case 0024: case 0025: case 0026: case 0027:
|
||||
case 0030: case 0031: case 0032: case 0033:
|
||||
case 0034: case 0035: case 0036: case 0037:
|
||||
MA = ((IR | 0177760) + BR) & VAMASK; /* IR<3:0> = -offset */
|
||||
AR = ReadW (MA); /* load AR */
|
||||
break;
|
||||
case 0041: case 0042: case 0043: /* IOP LAI+ (I_NO) */
|
||||
IOP_LAIP: case 0041: case 0042: case 0043: /* IOP LAI+ (I_NO) */
|
||||
case 0044: case 0045: case 0046: case 0047:
|
||||
case 0050: case 0051: case 0052: case 0053:
|
||||
case 0054: case 0055: case 0056: case 0057:
|
||||
MA = ((IR & 017) + BR) & VAMASK; /* IR<3:0> = +offset */
|
||||
AR = ReadW (MA); /* load AR */
|
||||
break;
|
||||
case 0061: case 0062: case 0063: /* IOP SAI- (I_NO) */
|
||||
IOP_SAIM: case 0061: case 0062: case 0063: /* IOP SAI- (I_NO) */
|
||||
case 0064: case 0065: case 0066: case 0067:
|
||||
case 0070: case 0071: case 0072: case 0073:
|
||||
case 0074: case 0075: case 0076: case 0077:
|
||||
MA = ((IR | 0177760) + BR) & VAMASK; /* IR<3:0> = -offset */
|
||||
WriteW (MA, AR); /* store AR */
|
||||
break;
|
||||
case 0101: case 0102: case 0103: /* IOP SAI+ (I_NO) */
|
||||
IOP_SAIP: case 0101: case 0102: case 0103: /* IOP SAI+ (I_NO) */
|
||||
case 0104: case 0105: case 0106: case 0107:
|
||||
case 0110: case 0111: case 0112: case 0113:
|
||||
case 0114: case 0115: case 0116: case 0117:
|
||||
|
@ -1166,6 +1171,7 @@ case 0203:case 0213: /* MAC1 ext */
|
|||
WriteW (MA, AR); /* store AR */
|
||||
break;
|
||||
case 0150: /* IOP CRC (I_CN) */
|
||||
case 0460: /* IOPX CRC (I_CN) */
|
||||
t = (AR & 0xFF) ^ wc; /* start CRC */
|
||||
for (i = 0; i < 8; i++) { /* apply polynomial */
|
||||
t = (t >> 1) | ((t & 1) << 15); /* rotate right */
|
||||
|
@ -1173,6 +1179,7 @@ case 0203:case 0213: /* MAC1 ext */
|
|||
WriteW (awc, t); /* rewrite CRC */
|
||||
break;
|
||||
case 0160: /* IOP TRSLT (I_CN) */
|
||||
case 0467: /* IOPX TRSLT (I_CN) */
|
||||
if (wc & SIGN) break; /* cnt < 0? */
|
||||
while (wc != 0) { /* loop */
|
||||
MA = (AR + AR + ReadB (BR)) & VAMASK;
|
||||
|
@ -1180,19 +1187,25 @@ case 0203:case 0213: /* MAC1 ext */
|
|||
WriteB (BR, t); /* store char */
|
||||
BR = (BR + 1) & DMASK; /* incr ptr */
|
||||
wc = (wc - 1) & DMASK; /* decr cnt */
|
||||
WriteW (awc, wc); }
|
||||
WriteW (awc, wc);
|
||||
if (wc && intrq) { /* more and intr? */
|
||||
PC = err_PC; /* stop for now */
|
||||
break; } }
|
||||
break;
|
||||
case 0220: /* IOP READF (I_NO) */
|
||||
AR = mp_fence; /* copy mp_fence */
|
||||
case 0462: /* IOPX READF (I_NO) */
|
||||
AR = iop_sp; /* copy stk ptr */
|
||||
break;
|
||||
case 0221: /* IOP PRFIO (I_NO) */
|
||||
case 0473: /* IOPX PFRIO (I_NO) */
|
||||
IR = ReadW (PC); /* get IO instr */
|
||||
PC = (PC + 1) & VAMASK;
|
||||
WriteW (PC, 1); /* set flag */
|
||||
PC = (PC + 1) & VAMASK;
|
||||
reason = iogrp (IR, 0); /* execute instr */
|
||||
break;
|
||||
case 0222: /* IOP PRFIE (I_NO) */
|
||||
case 0222: /* IOP PRFEI (I_NO) */
|
||||
case 0471: /* IOPX PFREI (I_NO) */
|
||||
IR = ReadW (PC); /* get IO instr */
|
||||
PC = (PC + 1) & VAMASK;
|
||||
WriteW (PC, 1); /* set flag */
|
||||
|
@ -1200,12 +1213,14 @@ case 0203:case 0213: /* MAC1 ext */
|
|||
reason = iogrp (IR, 0); /* execute instr */
|
||||
/* fall through */
|
||||
case 0223: /* IOP PRFEX (I_NO) */
|
||||
case 0472: /* IOPX PFREX (I_NO) */
|
||||
MA = ReadW (PC); /* exit addr */
|
||||
PCQ_ENTRY;
|
||||
PC = ReadW (MA) & VAMASK; /* jump indirect */
|
||||
WriteW (MA, 0); /* clear exit */
|
||||
break;
|
||||
case 0240: /* IOP ENQ (I_NO) */
|
||||
case 0464: /* IOPX ENQ (I_NO) */
|
||||
hp = ReadW (AR & VAMASK); /* addr of head */
|
||||
tp = ReadW ((AR + 1) & VAMASK); /* addr of tail */
|
||||
WriteW ((BR - 1) & VAMASK, 0); /* entry link */
|
||||
|
@ -1213,7 +1228,8 @@ case 0203:case 0213: /* MAC1 ext */
|
|||
WriteW ((AR + 1) & VAMASK, BR); /* queue tail */
|
||||
if (hp != 0) PC = (PC + 1) & VAMASK; /* q not empty? skip */
|
||||
break;
|
||||
case 0257: /* IOP ENQP (I_NO) */
|
||||
case 0257: /* IOP PENQ (I_NO) */
|
||||
case 0465: /* IOPX PENQ (I_NO) */
|
||||
hp = ReadW (AR & VAMASK); /* addr of head */
|
||||
WriteW ((BR - 1) & VAMASK, hp); /* becomes entry link */
|
||||
WriteW (AR & VAMASK, BR); /* queue head */
|
||||
|
@ -1222,6 +1238,7 @@ case 0203:case 0213: /* MAC1 ext */
|
|||
else PC = (PC + 1) & VAMASK; /* skip */
|
||||
break;
|
||||
case 0260: /* IOP DEQ (I_NO) */
|
||||
case 0466: /* IOPX DEQ (I_NO) */
|
||||
BR = ReadW (AR & VAMASK); /* addr of head */
|
||||
if (BR) { /* queue not empty? */
|
||||
hp = ReadW ((BR - 1) & VAMASK); /* read hd entry link */
|
||||
|
@ -1239,23 +1256,56 @@ case 0203:case 0213: /* MAC1 ext */
|
|||
BR = (BR + 1) & DMASK; /* incr ptr */
|
||||
break;
|
||||
case 0340: /* IOP REST (I_NO) */
|
||||
mp_fence = (mp_fence - 1) & VAMASK; /* pop E/~O,BR,AR */
|
||||
t = ReadW (mp_fence);
|
||||
case 0461: /* IOPX REST (I_NO) */
|
||||
iop_sp = (iop_sp - 1) & VAMASK; /* pop E/~O,BR,AR */
|
||||
t = ReadW (iop_sp);
|
||||
O = ((t >> 1) ^ 1) & 1;
|
||||
E = t & 1;
|
||||
mp_fence = (mp_fence - 1) & VAMASK;
|
||||
BR = ReadW (mp_fence);
|
||||
mp_fence = (mp_fence - 1) & VAMASK;
|
||||
AR = ReadW (mp_fence);
|
||||
iop_sp = (iop_sp - 1) & VAMASK;
|
||||
BR = ReadW (iop_sp);
|
||||
iop_sp = (iop_sp - 1) & VAMASK;
|
||||
AR = ReadW (iop_sp);
|
||||
if (cpu_unit.flags & UNIT_2100) mp_fence = iop_sp;
|
||||
break;
|
||||
case 0362: /* IOP SAVE (I_NO) */
|
||||
WriteW (mp_fence, AR); /* push AR,BR,E/~O */
|
||||
mp_fence = (mp_fence + 1) & VAMASK;
|
||||
WriteW (mp_fence, BR);
|
||||
mp_fence = (mp_fence + 1) & VAMASK;
|
||||
case 0474: /* IOPX SAVE (I_NO) */
|
||||
WriteW (iop_sp, AR); /* push AR,BR,E/~O */
|
||||
iop_sp = (iop_sp + 1) & VAMASK;
|
||||
WriteW (iop_sp, BR);
|
||||
iop_sp = (iop_sp + 1) & VAMASK;
|
||||
t = ((O ^ 1) << 1) | E;
|
||||
WriteW (mp_fence, t);
|
||||
mp_fence = (mp_fence + 1) & VAMASK;
|
||||
WriteW (iop_sp, t);
|
||||
iop_sp = (iop_sp + 1) & VAMASK;
|
||||
if (cpu_unit.flags & UNIT_2100) mp_fence = iop_sp;
|
||||
break;
|
||||
|
||||
case 0400: case 0401: case 0402: case 0403: /* IOPX LAI-/SAI- (I_NO) */
|
||||
case 0404: case 0405: case 0406: case 0407:
|
||||
case 0410: case 0411: case 0412: case 0413:
|
||||
case 0414: case 0415: case 0416: case 0417:
|
||||
MA = ((IR | 0177760) + BR) & VAMASK; /* IR<3:0> = -offset */
|
||||
if (IR & I_AB) AR = ReadW (MA); /* AB = 1? LAI */
|
||||
else WriteW (MA, AR); /* AB = 0? SAI */
|
||||
break;
|
||||
case 0420: case 0421: case 0422: case 0423: /* IOPX LAI+/SAI+ (I_NO) */
|
||||
case 0424: case 0425: case 0426: case 0427:
|
||||
case 0430: case 0431: case 0432: case 0433:
|
||||
case 0434: case 0435: case 0436: case 0437:
|
||||
MA = ((IR & 017) + BR) & VAMASK; /* IR<3:0> = +offset */
|
||||
if (IR & I_AB) AR = ReadW (MA); /* AB = 1? LAI */
|
||||
else WriteW (MA, AR); /* AB = 0? SAI */
|
||||
break;
|
||||
case 0463: /* IOPX INS (I_NO) */
|
||||
iop_sp = AR; /* init stk ptr */
|
||||
break;
|
||||
case 0470: /* IOPX ILIST (I_CN) */
|
||||
IOP_ILIST:
|
||||
do { /* for count */
|
||||
WriteW (MA, AR); /* write AR to mem */
|
||||
AR = (AR + 1) & DMASK; /* incr AR */
|
||||
MA = (MA + 1) & VAMASK; /* incr MA */
|
||||
wc = (wc - 1) & DMASK; } /* decr count */
|
||||
while (wc != 0);
|
||||
break;
|
||||
|
||||
/* DMS instructions, move alternate - interruptible
|
||||
|
@ -2220,6 +2270,7 @@ case ioLIX: /* load */
|
|||
break;
|
||||
case ioOTX: /* output */
|
||||
mp_fence = dat & VAMASK;
|
||||
if (cpu_unit.flags & UNIT_2100) iop_sp = mp_fence;
|
||||
break;
|
||||
case ioCTL: /* control clear/set */
|
||||
if ((IR & I_CTL) == 0) { /* STC */
|
||||
|
@ -2420,6 +2471,8 @@ else M[addr] = val & DMASK;
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Memory size validation */
|
||||
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
int32 mc = 0;
|
||||
|
@ -2515,11 +2568,14 @@ mod = MOD_2116;
|
|||
if (uptr->flags & UNIT_2100) mod = MOD_2100;
|
||||
else if (uptr->flags & UNIT_21MX) mod = MOD_21MX;
|
||||
for (i = 0; opt_val[i].optf != 0; i++) {
|
||||
if ((val == opt_val[i].optf) && (mod & opt_val[i].cpuf)) {
|
||||
if (mod == MOD_2100) {
|
||||
if (val == UNIT_FP) uptr->flags = uptr->flags & ~UNIT_IOP;
|
||||
if (val == UNIT_IOP) uptr->flags = uptr->flags & ~UNIT_FP; }
|
||||
if (val == UNIT_DMS) uptr->flags = uptr->flags | UNIT_MPR;
|
||||
if ((opt == opt_val[i].optf) && (mod & opt_val[i].cpuf)) {
|
||||
if ((mod == MOD_2100) && (val == UNIT_FP))
|
||||
uptr->flags = uptr->flags & ~UNIT_IOP;
|
||||
if ((opt == UNIT_IOP) && val) {
|
||||
if (mod == MOD_2100) uptr->flags =
|
||||
(uptr->flags & ~UNIT_FP) | UNIT_IOP | UNIT_MPR;
|
||||
if (mod == MOD_21MX) uptr->flags |= UNIT_IOPX | UNIT_MPR; }
|
||||
if (val == UNIT_DMS) uptr->flags |= UNIT_MPR;
|
||||
return SCPE_OK; } }
|
||||
return SCPE_NOFNC;
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#define STOP_IBKPT 4 /* breakpoint */
|
||||
#define STOP_IND 5 /* indirect loop */
|
||||
#define STOP_INDINT 6 /* indirect intr */
|
||||
#define STOP_NOCONN 7 /* no connection */
|
||||
|
||||
#define ABORT_PRO 1 /* protection abort */
|
||||
|
||||
|
@ -207,6 +208,8 @@ struct DMA { /* DMA channel */
|
|||
#define DRC 027 /* 12610A control */
|
||||
#define MSD 030 /* 13181A data */
|
||||
#define MSC 031 /* 13181A control */
|
||||
#define IPLI 032 /* 12556B link in */
|
||||
#define IPLO 033 /* 12556B link out */
|
||||
#define MUXL 040 /* 12920A lower data */
|
||||
#define MUXU 041 /* 12920A upper data */
|
||||
#define MUXC 042 /* 12920A control */
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
HP2100 Diagnostics
|
||||
|
||||
CPU status writeup sources
|
||||
|
||||
24315 Memory reference group passed in 21MX CE no
|
||||
|
@ -32,7 +34,27 @@ CPU status writeup sources
|
|||
- prints diagnostic name
|
||||
- prints END OF PASS 1 and halts
|
||||
|
||||
13206 IOP for 2100 group passed 13206 manual no
|
||||
13206 IOP for 2100 passed 13206 manual no
|
||||
- load diagnostic via configurator
|
||||
- D S 0
|
||||
- SET CPU 2100
|
||||
- SET CPU IOP
|
||||
- RUN 2000
|
||||
- prints diagnostic name
|
||||
- prints section names, PASS 000001, and halts
|
||||
- note: will not pass interruptibility tests
|
||||
|
||||
13207 IOP for 21MX passed 13207 manual no
|
||||
- load diagnostic via configurator
|
||||
- D S 13
|
||||
- SET CPU 21MX
|
||||
- SET CPU IOP
|
||||
- RUN 100
|
||||
- HLT 74, PC = 2425
|
||||
- D S 0
|
||||
- CON
|
||||
- prints diagnostic name
|
||||
- prints section names, PASS 000001, and halts
|
||||
|
||||
24320 Floating point passed in 21MX CE no
|
||||
- load diagnostic via configurator
|
||||
|
|
|
@ -51,6 +51,7 @@ sim/hp2100/ hp2100_defs.h
|
|||
hp2100_dp.c
|
||||
hp2100_dq.c
|
||||
hp2100_dr.c
|
||||
hp2100_ipl.c
|
||||
hp2100_lps.c
|
||||
hp2100_lpt.c
|
||||
hp2100_mt.c
|
||||
|
@ -85,6 +86,8 @@ DR 12606B fixed head disk controller with 2770/2771 disks
|
|||
MT 12559C magnetic tape controller with one 3030 drive
|
||||
MS 13181A magnetic tape controller with four 7970B drives
|
||||
13183A magnetic tape controller with four 7970E drives
|
||||
IPLI 12556B interprocessor link, input side
|
||||
IPLO 12556B interprocessor link, output side
|
||||
|
||||
The HP2100 simulator implements several unique stop conditions:
|
||||
|
||||
|
@ -107,8 +110,8 @@ CPU options include choice of instruction set and memory size.
|
|||
SET CPU NOEAU no EAU instructions (2116 only)
|
||||
SET CPU FP FP instructions (2100 only)
|
||||
SET CPU NOFP no FP instructions (2100 only)
|
||||
SET CPU IOP IOP instructions (2100 only)
|
||||
SET CPU NOIOP no IOP instructions (2100 only)
|
||||
SET CPU IOP IOP instructions (2100, 21MX only)
|
||||
SET CPU NOIOP no IOP instructions (2100, 21MX only)
|
||||
SET CPU DMS DMS instructions (21MX only)
|
||||
SET CPU NODMS no DMS instructions (21MX only)
|
||||
SET CPU 4K set memory size = 4K
|
||||
|
@ -505,6 +508,62 @@ The modem control (MUXM) implements these registers:
|
|||
The terminal multiplexor does not support save and restore. All open
|
||||
connections are lost when the simulator shuts down or MUXU is detached.
|
||||
|
||||
2.4.8 Interprocessor Link (IPLI, IPLO)
|
||||
|
||||
The interprocessor link is a pair of 12556B parallel interfaces that
|
||||
are cross coupled to provide interprocessor communications to a second
|
||||
copy of the HP2100 simulator. The IPL is intended to support simulation
|
||||
of a two system HP TimeShared Basic configuration. The links are actually
|
||||
bidirectional half-duplex; TimeShared Basic uses them unidirectionally.
|
||||
The IPL is disabled by default.
|
||||
|
||||
To operate, the IPL devices must be enabled and then connected to the IPL
|
||||
devices in another copy of the simulator. The IPLI device in the first
|
||||
simulator is connected to the IPLO device in the second, and vice versa.
|
||||
Connections are established with the ATTACH command. One copy of the
|
||||
simulator listens for connections on a specified port (ATTACH -L); the
|
||||
other establishes connections to an IP address and port (ATTACH -C).
|
||||
Either copy may perform either operation, but the operations must be
|
||||
done in matched pairs:
|
||||
|
||||
simulator #1 simulator #2
|
||||
|
||||
sim> set ipli ena sim> set ipli ena
|
||||
(also enables iplo) (also enables iplo)
|
||||
sim> att -lw ipli 4000
|
||||
Listening on port 4000
|
||||
Waiting for connection
|
||||
sim> att -c iplo 4000
|
||||
Connection established Connected to 127.0.0.1 port 4000
|
||||
sim> att -lw iplo 4000
|
||||
Listening on port 4001
|
||||
Waiting for connection
|
||||
sim> att -c ipli 4001
|
||||
Connection established Connected to 127.0.0.1 port 4000
|
||||
|
||||
Both forms of ATTACH take a modifier -W (wait); if specified, the command
|
||||
will wait up to 30 seconds for the connection process to complete. ATTACH
|
||||
-C can specify both an IP address and a port, in the form aa.bb.cc.dd:port;
|
||||
if the IP address is omitted, it defaults to 127.0.0.1 (local system).
|
||||
|
||||
Both IPLI and IPLO implement the BOOT command. BOOT loads the HP Access
|
||||
Basic Block Loader for the IOP into the top 64 words of memory and starts
|
||||
it running.
|
||||
|
||||
Both IPLI and IPLO implement these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 16 buffer
|
||||
HOLD 8 holding buffer
|
||||
CMD 1 device enable
|
||||
CTL 1 device/interrupt enable
|
||||
FLG 1 device ready
|
||||
FBF 1 device ready buffer
|
||||
TIME 24 polling interval for input
|
||||
STOP_IOE 1 stop on I/O error
|
||||
|
||||
|
||||
2.5 12557A Disk Controller (DPC, DPD) with 2781 Drives
|
||||
13210A Disk Controller (DPC, DPD) with 7900 Drives
|
||||
|
||||
|
|
|
@ -119,8 +119,8 @@
|
|||
#define STA_MBZ13 (STA_ATN + STA_RWU + STA_SKI) /* zero in 13210 */
|
||||
|
||||
extern uint16 *M;
|
||||
extern int32 PC, SR;
|
||||
extern int32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2];
|
||||
extern uint32 PC, SR;
|
||||
extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2];
|
||||
extern int32 sim_switches;
|
||||
extern UNIT cpu_unit;
|
||||
|
||||
|
@ -702,8 +702,8 @@ return SCPE_OK;
|
|||
|
||||
/* 7900/7901 bootstrap routine (HP 12992F ROM) */
|
||||
|
||||
#define LDR_BASE 077
|
||||
#define CHANGE_DEV (1 << 24)
|
||||
#define CHANGE_ADDR (1 << 23)
|
||||
|
||||
static const int32 dboot[IBL_LNT] = {
|
||||
0106700+CHANGE_DEV, /*ST CLC DC ; clr dch */
|
||||
|
@ -766,7 +766,7 @@ static const int32 dboot[IBL_LNT] = {
|
|||
0027700, /* JMP ST ; no, retry */
|
||||
0117751, /*XT JSB ADDR2,I ; start program */
|
||||
0120000+CHANGE_DEV, /*DMACW 120000+DC */
|
||||
CHANGE_ADDR }; /* -ST */
|
||||
0000000 }; /* -ST */
|
||||
|
||||
t_stat dpc_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
|
@ -778,11 +778,10 @@ PC = ((MEMSIZE - 1) & ~IBL_MASK) & VAMASK; /* start at mem top */
|
|||
SR = IBL_DP + (dev << IBL_V_DEV); /* set SR */
|
||||
if (sim_switches & SWMASK ('F')) SR = SR | IBL_FIX; /* boot from fixed? */
|
||||
for (i = 0; i < IBL_LNT; i++) { /* copy bootstrap */
|
||||
if (dboot[i] & CHANGE_ADDR) /* memory limit? */
|
||||
M[PC + i] = (-PC) & DMASK;
|
||||
else if (dboot[i] & CHANGE_DEV) /* IO instr? */
|
||||
if (dboot[i] & CHANGE_DEV) /* IO instr? */
|
||||
M[PC + i] = (dboot[i] + dev) & DMASK;
|
||||
else M[PC + i] = dboot[i]; }
|
||||
M[PC + LDR_BASE] = (~PC + 1) & DMASK;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -104,8 +104,8 @@
|
|||
#define STA_ALLERR (STA_NRDY + STA_EOC + STA_AER + STA_FLG + STA_DTE)
|
||||
|
||||
extern uint16 *M;
|
||||
extern int32 PC, SR;
|
||||
extern int32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2];
|
||||
extern uint32 PC, SR;
|
||||
extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2];
|
||||
extern int32 sim_switches;
|
||||
extern UNIT cpu_unit;
|
||||
|
||||
|
@ -654,8 +654,8 @@ return SCPE_OK;
|
|||
|
||||
/* 2883/2884 bootstrap routine (subset HP 12992A ROM) */
|
||||
|
||||
#define LDR_BASE 077
|
||||
#define CHANGE_DEV (1 << 24)
|
||||
#define CHANGE_ADDR (1 << 23)
|
||||
|
||||
static const int32 dboot[IBL_LNT] = {
|
||||
0106700+CHANGE_DEV, /*ST CLC DC ; clr dch */
|
||||
|
@ -698,7 +698,7 @@ static const int32 dboot[IBL_LNT] = {
|
|||
0164000, /*CNT -6144. */
|
||||
0117773, /*XT JSB ADDR2,I ; start program */
|
||||
0120000+CHANGE_DEV, /*DMACW 120000+DC */
|
||||
CHANGE_ADDR }; /* -ST */
|
||||
0000000 }; /* -ST */
|
||||
|
||||
t_stat dqc_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
|
@ -709,10 +709,9 @@ dev = dqd_dib.devno; /* get data chan dev */
|
|||
PC = ((MEMSIZE - 1) & ~IBL_MASK) & VAMASK; /* start at mem top */
|
||||
SR = IBL_DQ + (dev << IBL_V_DEV); /* set SR */
|
||||
for (i = 0; i < IBL_LNT; i++) { /* copy bootstrap */
|
||||
if (dboot[i] & CHANGE_ADDR) /* memory limit? */
|
||||
M[PC + i] = (-PC) & DMASK;
|
||||
else if (dboot[i] & CHANGE_DEV) /* IO instr? */
|
||||
if (dboot[i] & CHANGE_DEV) /* IO instr? */
|
||||
M[PC + i] = (dboot[i] + dev) & DMASK;
|
||||
else M[PC + i] = dboot[i]; }
|
||||
M[PC + LDR_BASE] = (~PC + 1) & DMASK;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
|
|
@ -94,8 +94,8 @@
|
|||
|
||||
extern UNIT cpu_unit;
|
||||
extern uint16 *M;
|
||||
extern int32 PC;
|
||||
extern int32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2];
|
||||
extern uint32 PC;
|
||||
extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2];
|
||||
|
||||
int32 drc_cw = 0; /* fnc, addr */
|
||||
int32 drc_sta = 0; /* status */
|
||||
|
|
465
HP2100/hp2100_ipl.c
Normal file
465
HP2100/hp2100_ipl.c
Normal file
|
@ -0,0 +1,465 @@
|
|||
/* hp2100_ipl.c: HP 2000 interprocessor link simulator
|
||||
|
||||
Copyright (c) 2002, 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.
|
||||
|
||||
ipli, iplo 12556B interprocessor link pair
|
||||
*/
|
||||
|
||||
#include "hp2100_defs.h"
|
||||
#include "sim_sock.h"
|
||||
#include "sim_tmxr.h"
|
||||
|
||||
#define UNIT_V_DIAG (UNIT_V_UF + 0) /* diagnostic mode */
|
||||
#define UNIT_V_ACTV (UNIT_V_UF + 1) /* making connection */
|
||||
#define UNIT_V_ESTB (UNIT_V_UF + 2) /* connection established */
|
||||
#define UNIT_DIAG (1 << UNIT_V_DIAG)
|
||||
#define UNIT_ACTV (1 << UNIT_V_ACTV)
|
||||
#define UNIT_ESTB (1 << UNIT_V_ESTB)
|
||||
#define DSOCKET u3 /* data socket */
|
||||
#define LSOCKET u4 /* listening socket */
|
||||
#define HOLD wait /* holding byte */
|
||||
#define IPL_HOLD 0100000
|
||||
|
||||
extern uint32 PC;
|
||||
extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2];
|
||||
extern FILE *sim_log;
|
||||
int32 ipl_ptime = 400; /* polling interval */
|
||||
int32 ipl_stopioe = 0; /* stop on error */
|
||||
|
||||
DEVICE ipli_dev, iplo_dev;
|
||||
int32 ipliio (int32 inst, int32 IR, int32 dat);
|
||||
int32 iploio (int32 inst, int32 IR, int32 dat);
|
||||
int32 iplio (UNIT *uptr, int32 inst, int32 IR, int32 dat);
|
||||
t_stat ipl_svc (UNIT *uptr);
|
||||
t_stat ipl_reset (DEVICE *dptr);
|
||||
t_stat ipl_attach (UNIT *uptr, char *cptr);
|
||||
t_stat ipl_detach (UNIT *uptr);
|
||||
t_stat ipl_boot (int32 unitno, DEVICE *dptr);
|
||||
t_stat ipl_dscln (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat ipl_setdiag (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_bool ipl_check_conn (UNIT *uptr);
|
||||
|
||||
/* IPLI data structures
|
||||
|
||||
ipli_dev IPLI device descriptor
|
||||
ipli_unit IPLI unit descriptor
|
||||
ipli_reg IPLI register list
|
||||
*/
|
||||
|
||||
DIB ipl_dib[] = {
|
||||
{ IPLI, 0, 0, 0, 0, &ipliio },
|
||||
{ IPLO, 0, 0, 0, 0, &iploio } };
|
||||
|
||||
#define ipli_dib ipl_dib[0]
|
||||
#define iplo_dib ipl_dib[1]
|
||||
|
||||
UNIT ipl_unit[] = {
|
||||
{ UDATA (&ipl_svc, UNIT_ATTABLE, 0) },
|
||||
{ UDATA (&ipl_svc, UNIT_ATTABLE, 0) } };
|
||||
|
||||
#define ipli_unit ipl_unit[0]
|
||||
#define iplo_unit ipl_unit[1]
|
||||
|
||||
REG ipli_reg[] = {
|
||||
{ ORDATA (BUF, ipli_unit.buf, 16) },
|
||||
{ FLDATA (CMD, ipli_dib.cmd, 0) },
|
||||
{ FLDATA (CTL, ipli_dib.ctl, 0) },
|
||||
{ FLDATA (FLG, ipli_dib.flg, 0) },
|
||||
{ FLDATA (FBF, ipli_dib.fbf, 0) },
|
||||
{ ORDATA (HOLD, ipli_unit.HOLD, 16) },
|
||||
{ DRDATA (TIME, ipl_ptime, 24), PV_LEFT },
|
||||
{ FLDATA (STOP_IOE, ipl_stopioe, 0) },
|
||||
{ ORDATA (DEVNO, ipli_dib.devno, 6), REG_HRO },
|
||||
{ NULL } };
|
||||
|
||||
MTAB ipl_mod[] = {
|
||||
{ UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", &ipl_setdiag },
|
||||
{ UNIT_DIAG, 0, "link mode", "LINK", &ipl_setdiag },
|
||||
{ MTAB_XTD | MTAB_VDV, 0, NULL, "DISCONNECT",
|
||||
&ipl_dscln, NULL, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO",
|
||||
&hp_setdev, &hp_showdev, &ipli_dev },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE ipli_dev = {
|
||||
"IPLI", &ipli_unit, ipli_reg, ipl_mod,
|
||||
1, 10, 31, 1, 16, 16,
|
||||
&tmxr_ex, &tmxr_dep, &ipl_reset,
|
||||
&ipl_boot, &ipl_attach, &ipl_detach,
|
||||
&ipli_dib, DEV_DISABLE | DEV_DIS };
|
||||
|
||||
/* IPLO data structures
|
||||
|
||||
iplo_dev IPLO device descriptor
|
||||
iplo_unit IPLO unit descriptor
|
||||
iplo_reg IPLO register list
|
||||
*/
|
||||
|
||||
REG iplo_reg[] = {
|
||||
{ ORDATA (BUF, iplo_unit.buf, 16) },
|
||||
{ FLDATA (CMD, iplo_dib.cmd, 0) },
|
||||
{ FLDATA (CTL, iplo_dib.ctl, 0) },
|
||||
{ FLDATA (FLG, iplo_dib.flg, 0) },
|
||||
{ FLDATA (FBF, iplo_dib.fbf, 0) },
|
||||
{ ORDATA (HOLD, iplo_unit.HOLD, 16) },
|
||||
{ DRDATA (TIME, ipl_ptime, 24), PV_LEFT },
|
||||
{ ORDATA (DEVNO, iplo_dib.devno, 6), REG_HRO },
|
||||
{ NULL } };
|
||||
|
||||
DEVICE iplo_dev = {
|
||||
"IPLO", &iplo_unit, iplo_reg, ipl_mod,
|
||||
1, 10, 31, 1, 16, 16,
|
||||
&tmxr_ex, &tmxr_dep, &ipl_reset,
|
||||
&ipl_boot, &ipl_attach, &ipl_detach,
|
||||
&iplo_dib, DEV_DISABLE | DEV_DIS };
|
||||
|
||||
/* Interprocessor link I/O routines */
|
||||
|
||||
int32 ipliio (int32 inst, int32 IR, int32 dat)
|
||||
{
|
||||
return iplio (&ipli_unit, inst, IR, dat);
|
||||
}
|
||||
|
||||
int32 iploio (int32 inst, int32 IR, int32 dat)
|
||||
{
|
||||
return iplio (&iplo_unit, inst, IR, dat);
|
||||
}
|
||||
|
||||
int32 iplio (UNIT *uptr, int32 inst, int32 IR, int32 dat)
|
||||
{
|
||||
uint32 u, dev, odev;
|
||||
int32 sta;
|
||||
int8 msg[2];
|
||||
|
||||
dev = IR & I_DEVMASK; /* get device no */
|
||||
switch (inst) { /* case on opcode */
|
||||
case ioFLG: /* flag clear/set */
|
||||
if ((IR & I_HC) == 0) { setFLG (dev); } /* STF */
|
||||
break;
|
||||
case ioSFC: /* skip flag clear */
|
||||
if (FLG (dev) == 0) PC = (PC + 1) & VAMASK;
|
||||
return dat;
|
||||
case ioSFS: /* skip flag set */
|
||||
if (FLG (dev) != 0) PC = (PC + 1) & VAMASK;
|
||||
return dat;
|
||||
case ioOTX: /* output */
|
||||
uptr->buf = dat;
|
||||
break;
|
||||
case ioLIX: /* load */
|
||||
dat = uptr->buf; /* return val */
|
||||
break;
|
||||
case ioMIX: /* merge */
|
||||
dat = dat | uptr->buf; /* get return data */
|
||||
break;
|
||||
case ioCTL: /* control clear/set */
|
||||
if (IR & I_CTL) { /* CLC */
|
||||
clrCMD (dev); /* clear ctl, cmd */
|
||||
clrCTL (dev); }
|
||||
else { /* STC */
|
||||
setCMD (dev); /* set ctl, cmd */
|
||||
setCTL (dev);
|
||||
if (uptr->flags & UNIT_ATT) { /* attached? */
|
||||
if ((uptr->flags & UNIT_ESTB) == 0) { /* established? */
|
||||
if (!ipl_check_conn (uptr)) /* not established? */
|
||||
return STOP_NOCONN; /* lose */
|
||||
uptr->flags = uptr->flags | UNIT_ESTB; }
|
||||
msg[0] = (uptr->buf >> 8) & 0377;
|
||||
msg[1] = uptr->buf & 0377;
|
||||
sta = sim_write_sock (uptr->DSOCKET, msg, 2);
|
||||
if (sta == SOCKET_ERROR) {
|
||||
printf ("IPL: socket write error\n");
|
||||
return SCPE_IOERR; }
|
||||
sim_os_sleep (0); }
|
||||
else if (uptr->flags & UNIT_DIAG) { /* diagnostic mode? */
|
||||
u = (uptr - ipl_unit) ^ 1; /* find other device */
|
||||
ipl_unit[u].buf = uptr->buf; /* output to other */
|
||||
odev = ipl_dib[u].devno; /* other device no */
|
||||
setFLG (odev); } /* set other flag */
|
||||
else return SCPE_UNATT; } /* lose */
|
||||
break;
|
||||
default:
|
||||
break; }
|
||||
if (IR & I_HC) { clrFLG (dev); } /* H/C option */
|
||||
return dat;
|
||||
}
|
||||
|
||||
/* Unit service - poll for input */
|
||||
|
||||
t_stat ipl_svc (UNIT *uptr)
|
||||
{
|
||||
int32 u, nb, dev;
|
||||
int8 msg[2];
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* not attached? */
|
||||
sim_activate (uptr, ipl_ptime); /* reactivate */
|
||||
if ((uptr->flags & UNIT_ESTB) == 0) { /* not established? */
|
||||
if (!ipl_check_conn (uptr)) return SCPE_OK; /* check for conn */
|
||||
uptr->flags = uptr->flags | UNIT_ESTB; }
|
||||
nb = sim_read_sock (uptr->DSOCKET, msg, uptr->HOLD? 1: 2);
|
||||
if (nb < 0) { /* connection closed? */
|
||||
printf ("IPL: socket read error\n");
|
||||
return SCPE_IOERR; }
|
||||
if (nb == 0) return SCPE_OK; /* no data? */
|
||||
if (uptr->HOLD) { /* holdover byte? */
|
||||
uptr->buf = ((uptr->HOLD & 0377) << 8) | (((int32) msg[0]) & 0377);
|
||||
uptr->HOLD = 0; }
|
||||
else if (nb == 1) uptr->HOLD = (((int32) msg[0]) & 0377) | IPL_HOLD;
|
||||
else uptr->buf = ((((int32) msg[0]) & 0377) << 8) |
|
||||
(((int32) msg[1]) & 0377);
|
||||
u = uptr - ipl_unit; /* get link number */
|
||||
dev = ipl_dib[u].devno; /* get device number */
|
||||
clrCMD (dev); /* clr cmd, set flag */
|
||||
setFLG (dev);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_bool ipl_check_conn (UNIT *uptr)
|
||||
{
|
||||
SOCKET sock;
|
||||
|
||||
if (uptr->flags & UNIT_ESTB) return TRUE; /* established? */
|
||||
if (uptr->flags & UNIT_ACTV) { /* active connect? */
|
||||
if (sim_check_conn (uptr->DSOCKET, 0) <= 0) return FALSE; }
|
||||
else { sock = sim_accept_conn (uptr->LSOCKET, NULL); /* poll connect */
|
||||
if (sock == INVALID_SOCKET) return FALSE; /* got a live one? */
|
||||
uptr->DSOCKET = sock; } /* save data socket */
|
||||
uptr->flags = uptr->flags | UNIT_ESTB; /* conn established */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat ipl_reset (DEVICE *dptr)
|
||||
{
|
||||
DIB *dibp = (DIB *) dptr->ctxt;
|
||||
UNIT *uptr = dptr->units;
|
||||
|
||||
hp_enbdis_pair (&ipli_dev, &iplo_dev); /* make pair cons */
|
||||
dibp->cmd = dibp->ctl = 0; /* clear cmd, ctl */
|
||||
dibp->flg = dibp->fbf = 1; /* set flg, fbf */
|
||||
uptr->buf = uptr->HOLD = 0;
|
||||
if (uptr->flags & UNIT_ATT) sim_activate (uptr, ipl_ptime);
|
||||
else sim_cancel (uptr); /* deactivate unit */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Attach routine
|
||||
|
||||
attach -l - listen for connection on port
|
||||
attach -c - connect to ip address and port
|
||||
*/
|
||||
|
||||
t_stat ipl_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
extern int32 sim_switches;
|
||||
SOCKET newsock;
|
||||
uint32 i, t, ipa, ipp, oldf;
|
||||
char *tptr;
|
||||
t_stat r;
|
||||
|
||||
r = get_ipaddr (cptr, &ipa, &ipp);
|
||||
if ((r != SCPE_OK) || (ipp == 0)) return SCPE_ARG;
|
||||
oldf = uptr->flags;
|
||||
if (oldf & UNIT_ATT) ipl_detach (uptr);
|
||||
if ((sim_switches & SWMASK ('C')) ||
|
||||
((sim_switches & SIM_SW_REST) && (oldf & UNIT_ACTV))) {
|
||||
if (ipa == 0) ipa = 0x7F000001;
|
||||
newsock = sim_connect_sock (ipa, ipp);
|
||||
if (newsock == INVALID_SOCKET) return SCPE_IOERR;
|
||||
printf ("Connecting to IP address %d.%d.%d.%d, port %d\n",
|
||||
(ipa >> 24) & 0xff, (ipa >> 16) & 0xff,
|
||||
(ipa >> 8) & 0xff, ipa & 0xff, ipp);
|
||||
if (sim_log) fprintf (sim_log,
|
||||
"Connecting to IP address %d.%d.%d.%d, port %d\n",
|
||||
(ipa >> 24) & 0xff, (ipa >> 16) & 0xff,
|
||||
(ipa >> 8) & 0xff, ipa & 0xff, ipp);
|
||||
uptr->flags = uptr->flags | UNIT_ACTV;
|
||||
uptr->LSOCKET = 0;
|
||||
uptr->DSOCKET = newsock; }
|
||||
else { if (ipa != 0) return SCPE_ARG;
|
||||
newsock = sim_master_sock (ipp);
|
||||
if (newsock == INVALID_SOCKET) return SCPE_IOERR;
|
||||
printf ("Listening on port %d\n", ipp);
|
||||
if (sim_log) fprintf (sim_log, "Listening on port %d\n", ipp);
|
||||
uptr->flags = uptr->flags & ~UNIT_ACTV;
|
||||
uptr->LSOCKET = newsock;
|
||||
uptr->DSOCKET = 0; }
|
||||
uptr->buf = uptr->HOLD = 0;
|
||||
uptr->flags = (uptr->flags | UNIT_ATT) & ~UNIT_ESTB; /* no more errors */
|
||||
tptr = malloc (strlen (cptr) + 1); /* get string buf */
|
||||
if (tptr == NULL) { /* no memory? */
|
||||
ipl_detach (uptr); /* close sockets */
|
||||
return SCPE_MEM; }
|
||||
strcpy (tptr, cptr); /* copy ipaddr:port */
|
||||
uptr->filename = tptr; /* save */
|
||||
sim_activate (uptr, ipl_ptime); /* activate poll */
|
||||
if (sim_switches & SWMASK ('W')) { /* wait? */
|
||||
for (i = 0; i < 30; i++) { /* check for 30 sec */
|
||||
if (t = ipl_check_conn (uptr)) break; /* established? */
|
||||
if ((i % 10) == 0) /* status every 10 sec */
|
||||
printf ("Waiting for connnection\n");
|
||||
sim_os_sleep (1); } /* sleep 1 sec */
|
||||
if (t) printf ("Connection established\n"); }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Detach routine */
|
||||
|
||||
t_stat ipl_detach (UNIT *uptr)
|
||||
{
|
||||
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */
|
||||
if (uptr->flags & UNIT_ACTV) sim_close_sock (uptr->DSOCKET, 1);
|
||||
else { if (uptr->flags & UNIT_ESTB) /* if established, */
|
||||
sim_close_sock (uptr->DSOCKET, 0); /* close data socket */
|
||||
sim_close_sock (uptr->LSOCKET, 1); } /* closen listen socket */
|
||||
free (uptr->filename); /* free string */
|
||||
uptr->filename = NULL;
|
||||
uptr->LSOCKET = 0;
|
||||
uptr->DSOCKET = 0;
|
||||
uptr->flags = uptr->flags & ~(UNIT_ATT | UNIT_ACTV | UNIT_ESTB);
|
||||
sim_cancel (uptr); /* don't poll */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Disconnect routine */
|
||||
|
||||
t_stat ipl_dscln (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if (cptr) return SCPE_ARG;
|
||||
if (((uptr->flags & UNIT_ATT) == 0) || (uptr->flags & UNIT_ACTV) ||
|
||||
((uptr->flags & UNIT_ESTB) == 0)) return SCPE_NOFNC;
|
||||
sim_close_sock (uptr->DSOCKET, 0);
|
||||
uptr->DSOCKET = 0;
|
||||
uptr->flags = uptr->flags & ~UNIT_ESTB;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Diagnostic/normal mode routine */
|
||||
|
||||
t_stat ipl_setdiag (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if (val) {
|
||||
ipli_unit.flags = ipli_unit.flags | UNIT_DIAG;
|
||||
iplo_unit.flags = iplo_unit.flags | UNIT_DIAG; }
|
||||
else { ipli_unit.flags = ipli_unit.flags & ~UNIT_DIAG;
|
||||
iplo_unit.flags = iplo_unit.flags & ~UNIT_DIAG; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Interprocessor link bootstrap routine (HP Access Manual) */
|
||||
|
||||
#define LDR_BASE 073
|
||||
#define IPL_PNTR 074
|
||||
#define PTR_PNTR 075
|
||||
#define IPL_DEVA 076
|
||||
#define PTR_DEVA 077
|
||||
|
||||
static const int32 pboot[IBL_LNT] = {
|
||||
0163774, /*BBL LDA ICK,I ; IPL sel code */
|
||||
0027751, /* JMP CFG ; go configure */
|
||||
0107700, /*ST CLC 0,C ; intr off */
|
||||
0002702, /* CLA,CCE,SZA ; skip in */
|
||||
0063772, /*CN LDA M26 ; feed frame */
|
||||
0002307, /*EOC CCE,INA,SZA,RSS ; end of file? */
|
||||
0027760, /* JMP EOT ; yes */
|
||||
0017736, /* JSB READ ; get #char */
|
||||
0007307, /* CMB,CCE,INB,SZB,RSS ; 2's comp; null? */
|
||||
0027705, /* JMP EOC ; read next */
|
||||
0077770, /* STB WC ; word in rec */
|
||||
0017736, /* JSB READ ; get feed frame */
|
||||
0017736, /* JSB READ ; get address */
|
||||
0074000, /* STB 0 ; init csum */
|
||||
0077771, /* STB AD ; save addr */
|
||||
0067771, /*CK LDB AD ; check addr */
|
||||
0047773, /* ADB MAXAD ; below loader */
|
||||
0002040, /* SEZ ; E =0 => OK */
|
||||
0102055, /* HLT 55 */
|
||||
0017736, /* JSB READ ; get word */
|
||||
0040001, /* ADA 1 ; cont checksum */
|
||||
0177771, /* STB AD,I ; store word */
|
||||
0037771, /* ISZ AD */
|
||||
0000040, /* CLE ; force wd read */
|
||||
0037770, /* ISZ WC ; block done? */
|
||||
0027717, /* JMP CK ; no */
|
||||
0017736, /* JSB READ ; get checksum */
|
||||
0054000, /* CPB 0 ; ok? */
|
||||
0027704, /* JMP CN ; next block */
|
||||
0102011, /* HLT 11 ; bad csum */
|
||||
0000000, /*RD 0 */
|
||||
0006600, /* CLB,CME ; E reg byte ptr */
|
||||
0103700, /*IO1 STC RDR,C ; start reader */
|
||||
0102300, /*IO2 SFS RDR ; wait */
|
||||
0027741, /* JMP *-1 */
|
||||
0106400, /*IO3 MIB RDR ; get byte */
|
||||
0002041, /* SEZ,RSS ; E set? */
|
||||
0127736, /* JMP RD,I ; no, done */
|
||||
0005767, /* BLF,CLE,BLF ; shift byte */
|
||||
0027740, /* JMP IO1 ; again */
|
||||
0163775, /* LDA PTR,I ; get ptr code */
|
||||
0043765, /*CFG ADA SFS ; config IO */
|
||||
0073741, /* STA IO2 */
|
||||
0043766, /* ADA STC */
|
||||
0073740, /* STA IO1 */
|
||||
0043767, /* ADA MIB */
|
||||
0073743, /* STA IO3 */
|
||||
0027702, /* JMP ST */
|
||||
0063777, /*EOT LDA PSC ; put select codes */
|
||||
0067776, /* LDB ISC ; where xloader wants */
|
||||
0102077, /* HLT 77 */
|
||||
0027702, /* JMP ST */
|
||||
0000000, /* NOP */
|
||||
0102300, /*SFS SFS 0 */
|
||||
0001400, /*STC 1400 */
|
||||
0002500, /*MIB 2500 */
|
||||
0000000, /*WC 0 */
|
||||
0000000, /*AD 0 */
|
||||
0177746, /*M26 -26 */
|
||||
0000000, /*MAX -BBL */
|
||||
0007776, /*ICK ISC */
|
||||
0007777, /*PTR IPT */
|
||||
0000000, /*ISC 0 */
|
||||
0000000 /*IPT 0 */
|
||||
};
|
||||
|
||||
t_stat ipl_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
int32 i, devi, devp;
|
||||
extern DIB ptr_dib;
|
||||
extern UNIT cpu_unit;
|
||||
extern uint32 SR;
|
||||
extern uint16 *M;
|
||||
|
||||
devi = ipli_dib.devno; /* get device no */
|
||||
devp = ptr_dib.devno;
|
||||
PC = ((MEMSIZE - 1) & ~IBL_MASK) & VAMASK; /* start at mem top */
|
||||
SR = (devi << IBL_V_DEV) | devp; /* set SR */
|
||||
for (i = 0; i < IBL_LNT; i++) M[PC + i] = pboot[i]; /* copy bootstrap */
|
||||
M[PC + LDR_BASE] = (~PC + 1) & DMASK; /* fix ups */
|
||||
M[PC + IPL_PNTR] = M[PC + IPL_PNTR] | PC;
|
||||
M[PC + PTR_PNTR] = M[PC + PTR_PNTR] | PC;
|
||||
M[PC + IPL_DEVA] = devi;
|
||||
M[PC + PTR_DEVA] = devp;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
|
@ -42,8 +42,8 @@
|
|||
#define UNIT_V_DIAG (UNIT_V_UF + 0) /* diagnostic mode */
|
||||
#define UNIT_DIAG (1 << UNIT_V_DIAG)
|
||||
|
||||
extern int32 PC;
|
||||
extern int32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2];
|
||||
extern uint32 PC;
|
||||
extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2];
|
||||
int32 lps_ctime = 1000; /* char time */
|
||||
int32 lps_stopioe = 0; /* stop on error */
|
||||
int32 lps_sta = 0;
|
||||
|
@ -80,8 +80,8 @@ REG lps_reg[] = {
|
|||
{ NULL } };
|
||||
|
||||
MTAB lps_mod[] = {
|
||||
{ UNIT_DIAG, UNIT_DIAG, "DIAG", "DIAG", NULL },
|
||||
{ UNIT_DIAG, 0, "PRINTER", "PRINTER", NULL },
|
||||
{ UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", NULL },
|
||||
{ UNIT_DIAG, 0, "printer mode", "PRINTER", NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&hp_setdev, &hp_showdev, &lps_dev },
|
||||
{ 0 } };
|
||||
|
@ -128,8 +128,9 @@ case ioCTL: /* control clear/set */
|
|||
if (IR & I_CTL) { /* CLC */
|
||||
clrCMD (dev); /* clear ctl, cmd */
|
||||
clrCTL (dev); }
|
||||
else { setCMD (dev); /* STC */
|
||||
setCTL (dev); /* set ctl, cmd */
|
||||
else { /* STC */
|
||||
setCMD (dev); /* set ctl, cmd */
|
||||
setCTL (dev);
|
||||
if (lps_unit.flags & UNIT_DIAG) /* diagnostic? */
|
||||
sim_activate (&lps_unit, 1); /* loop back */
|
||||
else sim_activate (&lps_unit, /* real lpt, sched */
|
||||
|
|
|
@ -41,8 +41,8 @@
|
|||
#define LPT_SKIPM 0000077 /* line count mask */
|
||||
#define LPT_CHANM 0000007 /* channel mask */
|
||||
|
||||
extern int32 PC;
|
||||
extern int32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2];
|
||||
extern uint32 PC;
|
||||
extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2];
|
||||
int32 lpt_ctime = 1000; /* char time */
|
||||
int32 lpt_stopioe = 0; /* stop on error */
|
||||
int32 lpt_lcnt = 0; /* line count */
|
||||
|
@ -126,8 +126,9 @@ case ioCTL: /* control clear/set */
|
|||
if (IR & I_CTL) { /* CLC */
|
||||
clrCMD (dev); /* clear ctl, cmd */
|
||||
clrCTL (dev); }
|
||||
else { setCMD (dev); /* STC */
|
||||
setCTL (dev); /* set ctl, cmd */
|
||||
else { /* STC */
|
||||
setCMD (dev); /* set ctl, cmd */
|
||||
setCTL (dev);
|
||||
sim_activate (&lpt_unit, /* schedule op */
|
||||
(lpt_unit.buf & LPT_CTL)? lpt_unit.wait: lpt_ctime); }
|
||||
break;
|
||||
|
|
|
@ -111,8 +111,8 @@
|
|||
#define STA_DYN (STA_PE|STA_SEL|STA_TBSY|STA_WLK|STA_LOCAL)
|
||||
|
||||
extern uint16 *M;
|
||||
extern int32 PC, SR;
|
||||
extern int32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2];
|
||||
extern uint32 PC, SR;
|
||||
extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2];
|
||||
extern int32 sim_switches;
|
||||
extern UNIT cpu_unit;
|
||||
|
||||
|
|
|
@ -88,8 +88,8 @@
|
|||
#define STA_PAR 0002 /* parity error */
|
||||
#define STA_BUSY 0001 /* busy (d) */
|
||||
|
||||
extern int32 PC;
|
||||
extern int32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2];
|
||||
extern uint32 PC;
|
||||
extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2];
|
||||
int32 mtc_fnc = 0; /* function */
|
||||
int32 mtc_sta = 0; /* status register */
|
||||
int32 mtc_dtf = 0; /* data xfer flop */
|
||||
|
|
|
@ -87,7 +87,7 @@
|
|||
|
||||
#define LIU_SEEK 0100000 /* seeking NI */
|
||||
#define LIU_DG 0000010 /* diagnose */
|
||||
#define LIU_BRK 0000004 /* break NI */
|
||||
#define LIU_BRK 0000004 /* break */
|
||||
#define LIU_LOST 0000002 /* char lost */
|
||||
#define LIU_TR 0000001 /* trans/rcv */
|
||||
|
||||
|
@ -129,8 +129,8 @@
|
|||
((muxc_ota[ch] & (OTC_ES2|OTC_ES1)) >> OTC_V_ES)) \
|
||||
<< LIC_V_I)
|
||||
|
||||
extern int32 PC;
|
||||
extern int32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2];
|
||||
extern uint32 PC;
|
||||
extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2];
|
||||
|
||||
uint16 mux_sta[MUX_LINES]; /* line status */
|
||||
uint16 mux_rpar[MUX_LINES + MUX_ILINES]; /* rcv param */
|
||||
|
@ -482,6 +482,10 @@ tmxr_poll_rx (&mux_desc); /* poll for input */
|
|||
for (ln = 0; ln < MUX_LINES; ln++) { /* loop thru lines */
|
||||
if (mux_ldsc[ln].conn) { /* connected? */
|
||||
if (c = tmxr_getc_ln (&mux_ldsc[ln])) { /* get char */
|
||||
if (c & SCPE_BREAK) { /* break? */
|
||||
mux_sta[ln] = mux_sta[ln] | LIU_BRK;
|
||||
mux_rbuf[ln] = 0; } /* no char */
|
||||
else { /* normal */
|
||||
if (mux_rchp[ln]) mux_sta[ln] = mux_sta[ln] | LIU_LOST;
|
||||
if (muxl_unit[ln].flags & UNIT_UC) { /* cvt to UC? */
|
||||
c = c & 0177;
|
||||
|
@ -491,10 +495,13 @@ for (ln = 0; ln < MUX_LINES; ln++) { /* loop thru lines */
|
|||
TMLN *lp = &mux_ldsc[ln]; /* get line */
|
||||
tmxr_putc_ln (lp, c); /* output char */
|
||||
tmxr_poll_tx (&mux_desc); } /* poll xmt */
|
||||
if (mux_rpar[ln] & OTL_DIAG) mux_diag (c); /* rcv diag? */
|
||||
mux_rbuf[ln] = c; /* save char */
|
||||
mux_rchp[ln] = 1; } } /* char pending */
|
||||
else muxc_lia[ln] = 0; } /* disconnected */ /* end for */
|
||||
mux_rchp[ln] = 1; } /* char pending */
|
||||
if (mux_rpar[ln] & OTL_DIAG) mux_diag (c); /* rcv diag? */
|
||||
} /* end if char */
|
||||
} /* end if connected */
|
||||
else muxc_lia[ln] = 0; /* disconnected */
|
||||
} /* end for */
|
||||
if (!FLG (muxl_dib.devno)) mux_data_int (); /* scan for data int */
|
||||
if (!FLG (muxc_dib.devno)) mux_ctrl_int (); /* scan modem */
|
||||
return SCPE_OK;
|
||||
|
@ -584,9 +591,13 @@ void mux_diag (int32 c)
|
|||
int32 i;
|
||||
|
||||
for (i = MUX_LINES; i < (MUX_LINES + MUX_ILINES); i++) {
|
||||
if (c & SCPE_BREAK) { /* break? */
|
||||
mux_sta[i] = mux_sta[i] | LIU_BRK;
|
||||
mux_rbuf[i] = 0; } /* no char */
|
||||
else {
|
||||
if (mux_rchp[i]) mux_sta[i] = mux_sta[i] | LIU_LOST;
|
||||
mux_rchp[i] = 1;
|
||||
mux_rbuf[i] = c; }
|
||||
mux_rbuf[i] = c; } }
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
tty 12531C buffered teleprinter interface
|
||||
clk 12539C time base generator
|
||||
|
||||
22-Dec-02 RMS Added break support
|
||||
01-Nov-02 RMS Revised BOOT command for IBL ROMs
|
||||
Fixed bug in TTY reset, TTY starts in input mode
|
||||
Fixed bug in TTY mode OTA, stores data as well
|
||||
|
@ -77,8 +78,8 @@
|
|||
#define CLK_ERROR (1 << CLK_V_ERROR)
|
||||
|
||||
extern uint16 *M;
|
||||
extern int32 PC, SR;
|
||||
extern int32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2];
|
||||
extern uint32 PC, SR;
|
||||
extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2];
|
||||
extern UNIT cpu_unit;
|
||||
|
||||
int32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */
|
||||
|
@ -263,8 +264,8 @@ REG clk_reg[] = {
|
|||
{ NULL } };
|
||||
|
||||
MTAB clk_mod[] = {
|
||||
{ UNIT_DIAG, UNIT_DIAG, "DIAG", "DIAG", NULL },
|
||||
{ UNIT_DIAG, 0, "CALIBRATED", "CALIBRATED", NULL },
|
||||
{ UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", NULL },
|
||||
{ UNIT_DIAG, 0, "calibrated", "CALIBRATED", NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&hp_setdev, &hp_showdev, &clk_dev },
|
||||
{ 0 } };
|
||||
|
@ -350,8 +351,8 @@ return SCPE_OK;
|
|||
|
||||
/* Paper tape reader bootstrap routine (HP 12992K ROM) */
|
||||
|
||||
#define LDR_BASE 077
|
||||
#define CHANGE_DEV (1 << 24)
|
||||
#define CHANGE_ADDR (1 << 23)
|
||||
|
||||
static const int32 pboot[IBL_LNT] = {
|
||||
0107700, /*ST CLC 0,C ; intr off */
|
||||
|
@ -403,7 +404,7 @@ static const int32 pboot[IBL_LNT] = {
|
|||
0177765, /*M11 -11 ; feed count */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, /* unused */
|
||||
0, 0, 0, 0, 0, 0, 0, /* unused */
|
||||
CHANGE_ADDR }; /*MAXAD -ST ; max addr */
|
||||
0000000 }; /*MAXAD -ST ; max addr */
|
||||
|
||||
t_stat ptr_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
|
@ -413,11 +414,10 @@ dev = ptr_dib.devno; /* get device no */
|
|||
PC = ((MEMSIZE - 1) & ~IBL_MASK) & VAMASK; /* start at mem top */
|
||||
SR = IBL_PTR + (dev << IBL_V_DEV); /* set SR */
|
||||
for (i = 0; i < IBL_LNT; i++) { /* copy bootstrap */
|
||||
if (pboot[i] & CHANGE_ADDR) /* memory limit? */
|
||||
M[PC + i] = (-PC) & DMASK;
|
||||
else if (pboot[i] & CHANGE_DEV) /* IO instr? */
|
||||
if (pboot[i] & CHANGE_DEV) /* IO instr? */
|
||||
M[PC + i] = (pboot[i] + dev) & DMASK;
|
||||
else M[PC + i] = pboot[i]; }
|
||||
M[PC + LDR_BASE] = (~PC + 1) & DMASK;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -564,7 +564,8 @@ int32 c, dev;
|
|||
dev = tty_dib.devno; /* get device no */
|
||||
sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* continue poll */
|
||||
if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */
|
||||
if (tty_unit[TTI].flags & UNIT_UC) { /* UC only? */
|
||||
if (c & SCPE_BREAK) c = 0; /* break? */
|
||||
else if (tty_unit[TTI].flags & UNIT_UC) { /* UC only? */
|
||||
c = c & 0177;
|
||||
if (islower (c)) c = toupper (c); }
|
||||
else c = c & ((tty_unit[TTI].flags & UNIT_8B)? 0377: 0177);
|
||||
|
@ -572,7 +573,7 @@ if (tty_mode & TM_KBD) { /* keyboard enabled? */
|
|||
tty_buf = c; /* put char in buf */
|
||||
tty_unit[TTI].pos = tty_unit[TTI].pos + 1;
|
||||
setFLG (dev); /* set flag */
|
||||
return tto_out (c); } /* echo or punch? */
|
||||
if (c) return tto_out (c); } /* echo or punch? */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ extern DEVICE dpd_dev, dpc_dev;
|
|||
extern DEVICE dqd_dev, dqc_dev;
|
||||
extern DEVICE drd_dev, drc_dev;
|
||||
extern DEVICE muxl_dev, muxu_dev, muxc_dev;
|
||||
extern DEVICE ipli_dev, iplo_dev;
|
||||
extern REG cpu_reg[];
|
||||
extern uint16 *M;
|
||||
|
||||
|
@ -86,6 +87,7 @@ DEVICE *sim_devices[] = {
|
|||
&mtd_dev, &mtc_dev,
|
||||
&msd_dev, &msc_dev,
|
||||
&muxl_dev, &muxu_dev, &muxc_dev,
|
||||
&ipli_dev, &iplo_dev,
|
||||
NULL };
|
||||
|
||||
const char *sim_stop_messages[] = {
|
||||
|
@ -95,7 +97,8 @@ const char *sim_stop_messages[] = {
|
|||
"HALT instruction",
|
||||
"Breakpoint",
|
||||
"Indirect address loop",
|
||||
"Indirect address interrupt (should not happen!)" };
|
||||
"Indirect address interrupt (should not happen!)",
|
||||
"No connection on interprocessor link" };
|
||||
|
||||
/* Binary loader
|
||||
|
||||
|
|
|
@ -544,8 +544,8 @@ if ((t = M[IS]) & WM) { /* WM? 6 char inst */
|
|||
BS = BS + one_table[t]; /* finish B addr */
|
||||
xa = (BS >> V_INDEX) & M_INDEX; /* get index reg */
|
||||
if (xa && (cpu_unit.flags & XSA)) { /* indexed? */
|
||||
BS = BS + hun_table[M[xa] & CHAR] + ten_table[M[xa + 1] & CHAR]
|
||||
+ one_table[M[xa + 2] & CHAR];
|
||||
BS = BS + hun_table[M[xa] & CHAR] + ten_table[M[xa + 1] & CHAR] +
|
||||
one_table[M[xa + 2] & CHAR];
|
||||
BS = (BS & INDEXMASK) % MAXMEMSIZE; }
|
||||
PP (IS);
|
||||
|
||||
|
@ -585,11 +585,13 @@ case OP_MCW: /* move char */
|
|||
if (ADDR_ERR (AS)) { /* check A addr */
|
||||
reason = STOP_INVA;
|
||||
break; }
|
||||
do { M[BS] = (M[BS] & WM) | (M[AS] & CHAR); /* move char */
|
||||
do {
|
||||
M[BS] = (M[BS] & WM) | (M[AS] & CHAR); /* move char */
|
||||
wm = M[AS] | M[BS];
|
||||
MM (AS); MM (BS); } /* decr pointers */
|
||||
while ((wm & WM) == 0); /* stop on A,B WM */
|
||||
break;
|
||||
|
||||
case OP_LCA: /* load char */
|
||||
if (ilnt >= 8) { /* I/O form? */
|
||||
reason = iodisp (dev, unit, MD_WM, D);
|
||||
|
@ -597,25 +599,31 @@ case OP_LCA: /* load char */
|
|||
if (ADDR_ERR (AS)) { /* check A addr */
|
||||
reason = STOP_INVA;
|
||||
break; }
|
||||
do { wm = M[BS] = M[AS]; /* move char + wmark */
|
||||
do {
|
||||
wm = M[BS] = M[AS]; /* move char + wmark */
|
||||
MM (AS); MM (BS); } /* decr pointers */
|
||||
while ((wm & WM) == 0); /* stop on A WM */
|
||||
break;
|
||||
|
||||
case OP_MCM: /* move to rec/group */
|
||||
do { M[BS] = (M[BS] & WM) | (M[AS] & CHAR); /* move char */
|
||||
do {
|
||||
M[BS] = (M[BS] & WM) | (M[AS] & CHAR); /* move char */
|
||||
t = M[AS];
|
||||
PP (AS); PP (BS); } /* incr pointers */
|
||||
while (((t & CHAR) != BCD_RECMRK) && (t != (BCD_GRPMRK + WM)));
|
||||
break;
|
||||
|
||||
case OP_MSZ: /* move suppress zero */
|
||||
bsave = BS; /* save B start */
|
||||
qzero = 1; /* set suppress */
|
||||
do { M[BS] = M[AS] & ((BS != bsave)? CHAR: DIGIT); /* copy char */
|
||||
do {
|
||||
M[BS] = M[AS] & ((BS != bsave)? CHAR: DIGIT); /* copy char */
|
||||
wm = M[AS];
|
||||
MM (AS); MM (BS); } /* decr pointers */
|
||||
while ((wm & WM) == 0); /* stop on A WM */
|
||||
if (reason) break; /* addr err? stop */
|
||||
do { PP (BS); /* adv B */
|
||||
do {
|
||||
PP (BS); /* adv B */
|
||||
t = M[BS]; /* get B, cant be WM */
|
||||
if ((t == BCD_ZERO) || (t == BCD_COMMA)) {
|
||||
if (qzero) M[BS] = 0; }
|
||||
|
@ -625,10 +633,12 @@ case OP_MSZ: /* move suppress zero */
|
|||
else qzero = 1; }
|
||||
while (BS <= bsave);
|
||||
break;
|
||||
|
||||
case OP_MN: /* move numeric */
|
||||
M[BS] = (M[BS] & ~DIGIT) | (M[AS] & DIGIT); /* move digit */
|
||||
MM (AS); MM (BS); /* decr pointers */
|
||||
break;
|
||||
|
||||
case OP_MZ: /* move zone */
|
||||
M[BS] = (M[BS] & ~ZONE) | (M[AS] & ZONE); /* move high bits */
|
||||
MM (AS); MM (BS); /* decr pointers */
|
||||
|
@ -643,7 +653,8 @@ case OP_C: /* compare */
|
|||
if (ilnt != 1) { /* if not chained */
|
||||
ind[IN_EQU] = 1; /* clear indicators */
|
||||
ind[IN_UNQ] = ind[IN_HGH] = ind[IN_LOW] = 0; }
|
||||
do { a = M[AS]; /* get characters */
|
||||
do {
|
||||
a = M[AS]; /* get characters */
|
||||
b = M[BS];
|
||||
wm = a | b; /* get word marks */
|
||||
if ((a & CHAR) != (b & CHAR)) { /* unequal? */
|
||||
|
@ -675,18 +686,21 @@ case OP_B: /* branch */
|
|||
else if (ilnt == 5) { /* branch on ind? */
|
||||
if (ind[D]) { BRANCH; } /* test indicator */
|
||||
if (ind_table[D]) ind[D] = 0; } /* reset if needed */
|
||||
else { if (ADDR_ERR (BS)) { /* branch char eq */
|
||||
else {
|
||||
if (ADDR_ERR (BS)) { /* branch char eq */
|
||||
reason = STOP_INVB; /* validate B addr */
|
||||
break; }
|
||||
if ((M[BS] & CHAR) == D) { BRANCH; } /* char equal? */
|
||||
else { MM (BS); } }
|
||||
break;
|
||||
|
||||
case OP_BWZ: /* branch wm or zone */
|
||||
if (((D & 1) && (M[BS] & WM)) || /* d1? test wm */
|
||||
((D & 2) && ((M[BS] & ZONE) == (D & ZONE)))) /* d2? test zone */
|
||||
{ BRANCH; }
|
||||
else { MM (BS); } /* decr pointer */
|
||||
break;
|
||||
|
||||
case OP_BBE: /* branch if bit eq */
|
||||
if (M[BS] & D & CHAR) { BRANCH; } /* any bits set? */
|
||||
else { MM (BS); } /* decr pointer */
|
||||
|
@ -704,8 +718,10 @@ case OP_BBE: /* branch if bit eq */
|
|||
|
||||
case OP_ZA: case OP_ZS: /* zero and add/sub */
|
||||
a = i = 0; /* clear flags */
|
||||
do { if (a & WM) wm = M[BS] = (M[BS] & WM) | BCD_ZERO;
|
||||
else { a = M[AS]; /* get A char */
|
||||
do {
|
||||
if (a & WM) wm = M[BS] = (M[BS] & WM) | BCD_ZERO;
|
||||
else {
|
||||
a = M[AS]; /* get A char */
|
||||
t = (a & CHAR)? bin_to_bcd[a & DIGIT]: 0;
|
||||
wm = M[BS] = (M[BS] & WM) | t; /* move digit */
|
||||
MM (AS); }
|
||||
|
@ -714,6 +730,7 @@ case OP_ZA: case OP_ZS: /* zero and add/sub */
|
|||
MM (BS); }
|
||||
while ((wm & WM) == 0); /* stop on B WM */
|
||||
break;
|
||||
|
||||
case OP_A: case OP_S: /* add/sub */
|
||||
bsave = BS; /* save sign pos */
|
||||
a = M[AS]; /* get A digit/sign */
|
||||
|
@ -731,8 +748,10 @@ case OP_A: case OP_S: /* add/sub */
|
|||
if (qsign && (carry == 0)) M[bsave] = /* compl, no carry? */
|
||||
WM + ((b & ZONE) ^ ABIT) + sum_table[10 - t];
|
||||
break; }
|
||||
do { if (a & WM) a = WM; /* A WM? char = 0 */
|
||||
else { a = M[AS]; /* else get A */
|
||||
do {
|
||||
if (a & WM) a = WM; /* A WM? char = 0 */
|
||||
else {
|
||||
a = M[AS]; /* else get A */
|
||||
MM (AS); }
|
||||
b = M[BS]; /* get B */
|
||||
t = bcd_to_bin[a & DIGIT]; /* get A binary */
|
||||
|
@ -776,18 +795,21 @@ case OP_R: /* read */
|
|||
BS = CDR_BUF + CDR_WIDTH;
|
||||
if (ilnt >= 4) { BRANCH; } /* check for branch */
|
||||
break;
|
||||
|
||||
case OP_W: /* write */
|
||||
if (reason = iomod (ilnt, D, w_mod)) break; /* valid modifier? */
|
||||
reason = write_line (ilnt, D); /* print line */
|
||||
BS = LPT_BUF + LPT_WIDTH;
|
||||
if (ilnt >= 4) { BRANCH; } /* check for branch */
|
||||
break;
|
||||
|
||||
case OP_P: /* punch */
|
||||
if (reason = iomod (ilnt, D, NULL)) break; /* valid modifier? */
|
||||
reason = punch_card (ilnt, D); /* punch card */
|
||||
BS = CDP_BUF + CDP_WIDTH;
|
||||
if (ilnt >= 4) { BRANCH; } /* check for branch */
|
||||
break;
|
||||
|
||||
case OP_WR: /* write and read */
|
||||
if (reason = iomod (ilnt, D, w_mod)) break; /* valid modifier? */
|
||||
reason = write_line (ilnt, D); /* print line */
|
||||
|
@ -796,6 +818,7 @@ case OP_WR: /* write and read */
|
|||
if (ilnt >= 4) { BRANCH; } /* check for branch */
|
||||
if (reason == SCPE_OK) reason = r1; /* merge errors */
|
||||
break;
|
||||
|
||||
case OP_WP: /* write and punch */
|
||||
if (reason = iomod (ilnt, D, w_mod)) break; /* valid modifier? */
|
||||
reason = write_line (ilnt, D); /* print line */
|
||||
|
@ -804,6 +827,7 @@ case OP_WP: /* write and punch */
|
|||
if (ilnt >= 4) { BRANCH; } /* check for branch */
|
||||
if (reason == SCPE_OK) reason = r1; /* merge errors */
|
||||
break;
|
||||
|
||||
case OP_RP: /* read and punch */
|
||||
if (reason = iomod (ilnt, D, NULL)) break; /* valid modifier? */
|
||||
reason = read_card (ilnt, D); /* read card */
|
||||
|
@ -812,6 +836,7 @@ case OP_RP: /* read and punch */
|
|||
if (ilnt >= 4) { BRANCH; } /* check for branch */
|
||||
if (reason == SCPE_OK) reason = r1; /* merge errors */
|
||||
break;
|
||||
|
||||
case OP_WRP: /* write, read, punch */
|
||||
if (reason = iomod (ilnt, D, w_mod)) break; /* valid modifier? */
|
||||
reason = write_line (ilnt, D); /* print line */
|
||||
|
@ -821,19 +846,23 @@ case OP_WRP: /* write, read, punch */
|
|||
if (ilnt >= 4) { BRANCH; } /* check for branch */
|
||||
if (reason == SCPE_OK) reason = (r1 == SCPE_OK)? r2: r1;
|
||||
break;
|
||||
|
||||
case OP_SS: /* select stacker */
|
||||
if (reason = iomod (ilnt, D, ss_mod)) break; /* valid modifier? */
|
||||
if (reason = select_stack (D)) break; /* sel stack, error? */
|
||||
if (ilnt >= 4) { BRANCH; } /* check for branch */
|
||||
break;
|
||||
|
||||
case OP_CC: /* carriage control */
|
||||
if (reason = carriage_control (D)) break; /* car ctrl, error? */
|
||||
if (ilnt >= 4) { BRANCH; } /* check for branch */
|
||||
break;
|
||||
|
||||
case OP_MTF: /* magtape function */
|
||||
if (reason = iomod (ilnt, D, mtf_mod)) break; /* valid modifier? */
|
||||
if (reason = mt_func (unit, D)) break; /* mt func, error? */
|
||||
break; /* can't branch */
|
||||
|
||||
case OP_RF: case OP_PF: /* read, punch feed */
|
||||
break; /* nop's */
|
||||
|
||||
|
@ -886,7 +915,8 @@ case OP_MCE: /* edit */
|
|||
& blank B
|
||||
*/
|
||||
|
||||
do { b = M[BS]; /* get B char */
|
||||
do {
|
||||
b = M[BS]; /* get B char */
|
||||
M[BS] = M[BS] & ~WM; /* clr WM */
|
||||
switch (b & CHAR) { /* case on B char */
|
||||
case BCD_ASTER: /* * */
|
||||
|
@ -912,7 +942,8 @@ case OP_MCE: /* edit */
|
|||
if (a & WM) { /* end of A field? */
|
||||
qbody = 0; /* end body */
|
||||
qawm = 1; }
|
||||
else { qbody = 1; /* in body */
|
||||
else {
|
||||
qbody = 1; /* in body */
|
||||
a = M[AS]; MM (AS); /* next A */
|
||||
t = a & CHAR; }
|
||||
break;
|
||||
|
@ -935,7 +966,8 @@ case OP_MCE: /* edit */
|
|||
|
||||
/* Edit pass 2 - from left to right, supressing zeroes */
|
||||
|
||||
do { b = M[++BS]; /* get B char */
|
||||
do {
|
||||
b = M[++BS]; /* get B char */
|
||||
switch (b & CHAR) { /* case on B char */
|
||||
case BCD_ONE: case BCD_TWO: case BCD_THREE:
|
||||
case BCD_FOUR: case BCD_FIVE: case BCD_SIX:
|
||||
|
@ -995,7 +1027,8 @@ case OP_MCE: /* edit */
|
|||
|
||||
case OP_MUL:
|
||||
asave = AS; bsave = lowprd = BS; /* save AS, BS */
|
||||
do { a = M[AS]; /* get mpcd char */
|
||||
do {
|
||||
a = M[AS]; /* get mpcd char */
|
||||
M[BS] = BCD_ZERO; /* zero prod */
|
||||
MM (AS); MM (BS); } /* decr pointers */
|
||||
while ((a & WM) == 0); /* until A WM */
|
||||
|
@ -1009,11 +1042,13 @@ case OP_MUL:
|
|||
AS and ps cannot produce an address error.
|
||||
*/
|
||||
|
||||
do { ps = bsave; /* ptr to prod */
|
||||
do {
|
||||
ps = bsave; /* ptr to prod */
|
||||
AS = asave; /* ptr to mpcd */
|
||||
carry = 0; /* init carry */
|
||||
b = M[BS]; /* get mpyr char */
|
||||
do { a = M[AS]; /* get mpcd char */
|
||||
do {
|
||||
a = M[AS]; /* get mpcd char */
|
||||
t = (bcd_to_bin[a & DIGIT] * /* mpyr * mpcd */
|
||||
bcd_to_bin[b & DIGIT]) + /* + c + partial prod */
|
||||
carry + bcd_to_bin[M[ps] & DIGIT];
|
||||
|
@ -1058,7 +1093,8 @@ case OP_MUL:
|
|||
|
||||
case OP_DIV:
|
||||
asave = AS; ahigh = -1;
|
||||
do { a = M[AS]; /* get dvr char */
|
||||
do {
|
||||
a = M[AS]; /* get dvr char */
|
||||
if ((a & CHAR) != BCD_ZERO) ahigh = AS; /* mark non-zero */
|
||||
MM (AS); }
|
||||
while ((a & WM) == 0);
|
||||
|
@ -1066,7 +1102,8 @@ case OP_DIV:
|
|||
if (ahigh < 0) { /* div? by zero */
|
||||
ind[IN_OVF] = 1; /* set ovf indic */
|
||||
qs = bsave = BS; /* quo, dividend */
|
||||
do { b = M[bsave]; /* find end divd */
|
||||
do {
|
||||
b = M[bsave]; /* find end divd */
|
||||
PP (bsave); } /* marked by zone */
|
||||
while ((b & ZONE) == 0);
|
||||
if (reason) break; /* address err? */
|
||||
|
@ -1087,12 +1124,14 @@ case OP_DIV:
|
|||
qs = current quotient digit
|
||||
*/
|
||||
|
||||
do { quo = 0; /* clear quo digit */
|
||||
do {
|
||||
quo = 0; /* clear quo digit */
|
||||
if (ADDR_ERR (qs) || ADDR_ERR (bsave)) {
|
||||
reason = STOP_WRAP; /* address wrap? */
|
||||
break; }
|
||||
b = M[bsave]; /* save low divd */
|
||||
do { t = div_sub (asave, bsave, ahigh); /* subtract */
|
||||
do {
|
||||
t = div_sub (asave, bsave, ahigh); /* subtract */
|
||||
quo++; } /* incr quo digit */
|
||||
while (t == 0); /* until borrow */
|
||||
div_add (asave, bsave, ahigh); quo--; /* restore */
|
||||
|
@ -1131,17 +1170,20 @@ case OP_SWM: /* set word mark */
|
|||
M[AS] = M[AS] | WM; /* set B field mark */
|
||||
MM (AS); MM (BS); /* decr pointers */
|
||||
break;
|
||||
|
||||
case OP_CWM: /* clear word mark */
|
||||
M[BS] = M[BS] & ~WM; /* clear A field mark */
|
||||
M[AS] = M[AS] & ~WM; /* clear B field mark */
|
||||
MM (AS); MM (BS); /* decr pointers */
|
||||
break;
|
||||
|
||||
case OP_CS: /* clear storage */
|
||||
t = (BS / 100) * 100; /* lower bound */
|
||||
while (BS >= t) M[BS--] = 0; /* clear region */
|
||||
if (BS < 0) BS = BS + MEMSIZE; /* wrap if needed */
|
||||
if (ilnt >= 7) { BRANCH; } /* branch variant? */
|
||||
break;
|
||||
|
||||
case OP_MA: /* modify address */
|
||||
a = one_table[M[AS] & CHAR]; MM (AS); /* get A address */
|
||||
a = a + ten_table[M[AS] & CHAR]; MM (AS);
|
||||
|
@ -1155,18 +1197,22 @@ case OP_MA: /* modify address */
|
|||
M[BS + 1] = (M[BS + 1] & WM) | store_addr_h (t);
|
||||
if (((a % 4000) + (b % 4000)) >= 4000) BS = BS + 2; /* carry? */
|
||||
break;
|
||||
|
||||
case OP_SAR: case OP_SBR: /* store A, B reg */
|
||||
M[AS] = (M[AS] & WM) | store_addr_u (BS); MM (AS);
|
||||
M[AS] = (M[AS] & WM) | store_addr_t (BS); MM (AS);
|
||||
M[AS] = (M[AS] & WM) | store_addr_h (BS); MM (AS);
|
||||
break;
|
||||
|
||||
case OP_NOP: /* nop */
|
||||
break;
|
||||
|
||||
case OP_H: /* halt */
|
||||
if (ilnt >= 4) { BRANCH; } /* branch if called */
|
||||
reason = STOP_HALT; /* stop simulator */
|
||||
saved_IS = IS; /* commit instruction */
|
||||
break;
|
||||
|
||||
default:
|
||||
reason = STOP_NXI; /* unimplemented */
|
||||
break; } /* end switch */
|
||||
|
|
|
@ -231,7 +231,8 @@ if (mod == BCD_W) { /* write? */
|
|||
if (fnc == FNC_CHECK) { /* write check? */
|
||||
qwc = 1; /* special read */
|
||||
fnc = dp_lastf; } /* use last func */
|
||||
else { dp_lastf = fnc; /* save func */
|
||||
else {
|
||||
dp_lastf = fnc; /* save func */
|
||||
fnc = fnc + FNC_WOFF; } } /* change to write */
|
||||
else if (mod == BCD_R) dp_lastf = fnc; /* read? save func */
|
||||
else return STOP_INVM; /* other? error */
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
inq 1407 inquiry terminal
|
||||
|
||||
22-Dec-02 RMS Added break support
|
||||
07-Sep-01 RMS Moved function prototypes
|
||||
14-Apr-99 RMS Changed t_addr to unsigned
|
||||
*/
|
||||
|
@ -82,8 +83,9 @@ case BCD_R: /* input */
|
|||
ind[IN_INR] = 0; /* clear req */
|
||||
puts_tty ("[Enter]\r\n"); /* prompt */
|
||||
for (i = 0; M[BS] != (BCD_GRPMRK + WM); i++) { /* until GM + WM */
|
||||
while ((t = sim_poll_kbd ()) == SCPE_OK)
|
||||
if (stop_cpu) return SCPE_STOP; /* interrupt? */
|
||||
while (((t = sim_poll_kbd ()) == SCPE_OK) ||
|
||||
(t & SCPE_BREAK)) {
|
||||
if (stop_cpu) return SCPE_STOP; } /* interrupt? */
|
||||
if (t < SCPE_KFLAG) return t; /* if not char, err */
|
||||
t = t & 0177;
|
||||
if ((t == '\r') || (t == '\n')) break;
|
||||
|
@ -95,7 +97,8 @@ case BCD_R: /* input */
|
|||
sim_putchar (t); /* echo */
|
||||
if (flag == MD_WM) { /* word mark mode? */
|
||||
if ((t == '~') && (wm_seen == 0)) wm_seen = WM;
|
||||
else { M[BS] = wm_seen | ascii_to_bcd[t];
|
||||
else {
|
||||
M[BS] = wm_seen | ascii_to_bcd[t];
|
||||
wm_seen = 0; } }
|
||||
else M[BS] = (M[BS] & WM) | ascii_to_bcd[t];
|
||||
if (!wm_seen) BS++;
|
||||
|
|
|
@ -203,7 +203,8 @@ if ((lpt_unit.flags & UNIT_ATT) == 0) return SCPE_UNATT;
|
|||
cctptr = (cctptr + count) % cctlnt; /* adv cct, mod lnt */
|
||||
if (sflag && CHP (0, cct[cctptr])) /* skip, top of form? */
|
||||
fputs ("\n\f", lpt_unit.fileref); /* nl, ff */
|
||||
else { for (i = 0; i < count; i++) fputc ('\n', lpt_unit.fileref); }
|
||||
else { for (i = 0; i < count; i++)
|
||||
fputc ('\n', lpt_unit.fileref); }
|
||||
lpt_unit.pos = ftell (lpt_unit.fileref); /* update position */
|
||||
ind[IN_CC9] = CHP (9, cct[cctptr]) != 0; /* set indicators */
|
||||
ind[IN_CC12] = CHP (12, cct[cctptr]) != 0;
|
||||
|
|
|
@ -148,8 +148,7 @@ case BCD_B: /* backspace */
|
|||
ind[IN_END] = 0; /* clear end of reel */
|
||||
if (pnu || (uptr->pos < sizeof (t_mtrlnt))) /* bot or pnu? */
|
||||
return SCPE_OK;
|
||||
fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt),
|
||||
SEEK_SET);
|
||||
fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET);
|
||||
fxread (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
if ((err = ferror (uptr->fileref)) || /* err or eof? */
|
||||
feof (uptr->fileref)) break;
|
||||
|
@ -244,7 +243,8 @@ case BCD_R: /* read */
|
|||
if ((flag != MD_BIN) && (t == BCD_ALT)) t = BCD_BLANK;
|
||||
if (flag == MD_WM) { /* word mk mode? */
|
||||
if ((t == BCD_WM) && (wm_seen == 0)) wm_seen = WM;
|
||||
else { M[BS] = wm_seen | (t & CHAR);
|
||||
else {
|
||||
M[BS] = wm_seen | (t & CHAR);
|
||||
wm_seen = 0; } }
|
||||
else M[BS] = (M[BS] & WM) | (t & CHAR);
|
||||
if (!wm_seen) BS++;
|
||||
|
|
|
@ -214,7 +214,8 @@ if (sw & SWMASK ('D')) { /* dump? */
|
|||
return -(i - 1); }
|
||||
if (sw & SWMASK ('S')) { /* string? */
|
||||
i = 0;
|
||||
do { t = val[i++];
|
||||
do {
|
||||
t = val[i++];
|
||||
fprintf (of, (t & WM)? "~%c": "%c", bcd_to_ascii[t & CHAR]); }
|
||||
while ((i < LINE_LNT) && ((val[i] & WM) == 0));
|
||||
return -(i - 1); }
|
||||
|
|
|
@ -1683,7 +1683,8 @@ do { sd = M[s] & DIGIT; /* src digit */
|
|||
MM (s); /* decr src addr */
|
||||
MM (tbl); /* skip 1st tbl dig */
|
||||
tblc = 0; /* count */
|
||||
do { tf = M[tbl] & FLAG; /* get next */
|
||||
do {
|
||||
tf = M[tbl] & FLAG; /* get next */
|
||||
MM (tbl); /* decr ptr */
|
||||
if (tblc++ > MEMSIZE) return STOP_FWRAP; }
|
||||
while (tf == 0); /* until flag */
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
tty console typewriter
|
||||
|
||||
22-Dec-02 RMS Added break test
|
||||
*/
|
||||
|
||||
#include "i1620_defs.h"
|
||||
|
@ -260,7 +262,7 @@ t_stat tti_read (int8 *c)
|
|||
int32 t;
|
||||
|
||||
do { t = sim_poll_kbd (); } /* get character */
|
||||
while (t == SCPE_OK);
|
||||
while ((t == SCPE_OK) || (t & SCPE_BREAK)); /* ignore break */
|
||||
if (t < SCPE_KFLAG) return t; /* error? */
|
||||
*c = t & 0177; /* store character */
|
||||
return SCPE_OK;
|
||||
|
|
|
@ -190,7 +190,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_reset (DEVICE *dptr);
|
||||
t_stat cpu_svc (UNIT *uptr);
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 value);
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 value, char *cptr, void *desc);
|
||||
void calc_ints (void);
|
||||
|
||||
extern t_stat ts_wr (int32 data, int32 addr, int32 access);
|
||||
|
@ -1182,7 +1182,7 @@ t_stat cpu_svc (UNIT *uptr)
|
|||
* Memory allocation
|
||||
* ------------------------------------------------------------------------ */
|
||||
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 value)
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 value, char *cptr, void *desc)
|
||||
{
|
||||
t_bool used;
|
||||
int32 i;
|
||||
|
|
|
@ -149,12 +149,12 @@ extern int32 sim_switches;
|
|||
|
||||
static t_stat cr_svc (UNIT *uptr);
|
||||
static t_stat cr_reset (DEVICE *dptr);
|
||||
static t_stat cr_set_code (UNIT *uptr, int32 match);
|
||||
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_detach (UNIT *uptr);
|
||||
|
||||
static t_stat cp_reset (DEVICE *dptr);
|
||||
static t_stat cp_set_code (UNIT *uptr, int32 match);
|
||||
static t_stat cp_set_code (UNIT *uptr, int32 match, char *cptr, void *desc);
|
||||
static t_stat cp_detach (UNIT *uptr);
|
||||
|
||||
static int16 cr_dsw = 0; /* device status word */
|
||||
|
@ -497,12 +497,12 @@ t_stat set_active_cr_code (int match)
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat cr_set_code (UNIT *uptr, int32 match)
|
||||
t_stat cr_set_code (UNIT *uptr, int32 match, char *cptr, void *desc)
|
||||
{
|
||||
return set_active_cr_code(match);
|
||||
}
|
||||
|
||||
t_stat cp_set_code (UNIT *uptr, int32 match)
|
||||
t_stat cp_set_code (UNIT *uptr, int32 match, char *cptr, void *desc)
|
||||
{
|
||||
CPCODE *code;
|
||||
int ncode;
|
||||
|
@ -550,7 +550,7 @@ t_stat load_cr_boot (int drvno)
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat cr_boot (int unitno)
|
||||
t_stat cr_boot (int unitno, DEVICE *dptr)
|
||||
{
|
||||
t_stat rval;
|
||||
short buf[80];
|
||||
|
@ -917,7 +917,7 @@ static t_bool nextdeck (void)
|
|||
|
||||
static t_stat cr_reset (DEVICE *dptr)
|
||||
{
|
||||
cr_set_code(&cr_unit, active_cr_code & UNIT_CODE); /* reset to specified code table */
|
||||
cr_set_code(&cr_unit, active_cr_code & UNIT_CODE, NULL, NULL); /* reset to specified code table */
|
||||
|
||||
readstate = STATION_EMPTY;
|
||||
|
||||
|
@ -948,7 +948,7 @@ static t_stat cr_reset (DEVICE *dptr)
|
|||
|
||||
static t_stat cp_reset (DEVICE *dptr)
|
||||
{
|
||||
cp_set_code(&cp_unit, cp_unit.flags & UNIT_CODE);
|
||||
cp_set_code(&cp_unit, cp_unit.flags & UNIT_CODE, NULL, NULL);
|
||||
punchstate = STATION_EMPTY;
|
||||
|
||||
cp_unit.COLUMN = -1;
|
||||
|
|
|
@ -259,7 +259,7 @@ void xio_error (char *msg);
|
|||
|
||||
void bail (char *msg);
|
||||
t_stat load_cr_boot (int drv);
|
||||
t_stat cr_boot (int unitno);
|
||||
t_stat cr_boot (int unitno, DEVICE *dptr);
|
||||
void calc_ints (void); /* recalculate interrupt bitmask */
|
||||
void trace_io (char *fmt, ...); /* debugging printout */
|
||||
void scp_panic (char *msg); /* bail out of simulator */
|
||||
|
|
|
@ -80,7 +80,7 @@ static t_stat dsk_svc (UNIT *uptr);
|
|||
static t_stat dsk_reset (DEVICE *dptr);
|
||||
static t_stat dsk_attach (UNIT *uptr, char *cptr);
|
||||
static t_stat dsk_detach (UNIT *uptr);
|
||||
static t_stat dsk_boot (int unitno);
|
||||
static t_stat dsk_boot (int unitno, DEVICE *dptr);
|
||||
|
||||
static void diskfail (UNIT *uptr, int errflag);
|
||||
|
||||
|
@ -511,7 +511,7 @@ static t_stat dsk_detach (UNIT *uptr)
|
|||
|
||||
// boot routine - if they type BOOT DSK, load the standard boot card.
|
||||
|
||||
static t_stat dsk_boot (int unitno)
|
||||
static t_stat dsk_boot (int unitno, DEVICE *dptr)
|
||||
{
|
||||
t_stat rval;
|
||||
|
||||
|
|
|
@ -984,7 +984,7 @@ void HandleCommand (HWND hWnd, WPARAM wParam, LPARAM lParam)
|
|||
if (! running) { /* if card reader is attached to a file, do cold start read of one card */
|
||||
IAR = 0; /* reset IAR */
|
||||
// stuff_cmd("boot cr");
|
||||
if (cr_boot(0) != SCPE_OK) /* load boot card */
|
||||
if (cr_boot(0, NULL) != SCPE_OK) /* load boot card */
|
||||
remark_cmd("IPL failed");
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
// ASM1130 - IBM 1130 Cross Assembler
|
||||
//
|
||||
// Version
|
||||
// 1.07 - 2003Jan05 - Filenames are now left in lower case. SYMBOLS.SYS stays all upper case
|
||||
// 1.06 - 2002May02 - Fixed bug in ebdic constants (data goes into low byte)
|
||||
// First stab at adding ISS level # info, this is iffy
|
||||
// 1.05 - 2002Apr24 - Made negative BSS size a warning not an error, as it
|
||||
|
@ -155,7 +156,7 @@
|
|||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#define VERSION "ASM1130 CROSS ASSEMBLER V1.06"
|
||||
#define VERSION "ASM1130 CROSS ASSEMBLER V1.07"
|
||||
|
||||
#define ISTV 0x33 // magic number from DMS R2V12 monitorm symbol @ISTV
|
||||
|
||||
|
@ -1880,9 +1881,10 @@ void proc (char *fname)
|
|||
else
|
||||
strcpy(curfn, fname); // otherwise use extension specified
|
||||
|
||||
#if (defined(WIN32) || defined(VMS))
|
||||
upcase(curfn); // only force uppercase of name on Windows and VMS
|
||||
#endif
|
||||
// let's leave filename case alone even if it doesn't matter
|
||||
//#if (defined(WIN32) || defined(VMS))
|
||||
// upcase(curfn); // only force uppercase of name on Windows and VMS
|
||||
//#endif
|
||||
|
||||
if (progname[0] == '\0') { // pick up primary filename
|
||||
if ((c = strrchr(curfn, '\\')) == NULL)
|
1718
Interdata/id16_cpu.c
Normal file
1718
Interdata/id16_cpu.c
Normal file
File diff suppressed because it is too large
Load diff
346
Interdata/id16_dboot.c
Normal file
346
Interdata/id16_dboot.c
Normal file
|
@ -0,0 +1,346 @@
|
|||
/* id16_dboot.c: Interdata 16b simulator disk bootstrap
|
||||
|
||||
Copyright (c) 2000-2002, 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.
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
|
||||
#define DBOOT_BEG 0x1000
|
||||
#define DBOOT_START 0x100e
|
||||
#define DBOOT_LEN (sizeof (dboot_rom) / sizeof (uint8))
|
||||
|
||||
/* Boot ROM: transcription of OS/16 MT2 ALO Direct Access Loader */
|
||||
|
||||
static uint8 dboot_rom[] = {
|
||||
0xca, 0xf0, 0x00, 0x30,
|
||||
0xc5, 0xf0, 0x00, 0x3a,
|
||||
0x02, 0x8e,
|
||||
0x26, 0xf7,
|
||||
0x03, 0x0e,
|
||||
0xd1, 0xc0, 0x00, 0x78,
|
||||
0xd0, 0xc0, 0x13, 0xf6,
|
||||
0x07, 0xdd,
|
||||
0xc8, 0x10, 0x10, 0x00,
|
||||
0xd3, 0xf0, 0x00, 0x7e,
|
||||
0xc4, 0xf0, 0x00, 0x0f,
|
||||
0x01, 0xe1,
|
||||
0xd2, 0xf0, 0x12, 0xe2,
|
||||
0xd3, 0xf0, 0x00, 0x7f,
|
||||
0x90, 0xf4,
|
||||
0x01, 0xe1,
|
||||
0xd2, 0xf0, 0x12, 0xe3,
|
||||
0xd3, 0xf0, 0x00, 0x7f,
|
||||
0xc4, 0xf0, 0x00, 0x0f,
|
||||
0x01, 0xe1,
|
||||
0xd2, 0xf0, 0x12, 0xe4,
|
||||
0xd3, 0x20, 0x00, 0x7d,
|
||||
0xd3, 0x30, 0x00, 0x7c,
|
||||
0xd3, 0x40, 0x00, 0x7a,
|
||||
0xd3, 0x50, 0x00, 0x7b,
|
||||
0xc8, 0x70, 0x12, 0xf6,
|
||||
0xc8, 0x80, 0x13, 0xf5,
|
||||
0x07, 0xaa,
|
||||
0x07, 0xcc,
|
||||
0x41, 0xe0, 0x11, 0x88,
|
||||
0x48, 0xa0, 0x12, 0xfe,
|
||||
0x48, 0xc0, 0x13, 0x00,
|
||||
0x43, 0x00, 0x10, 0x98,
|
||||
0xc8, 0x70, 0x12, 0xf6,
|
||||
0x41, 0xe0, 0x11, 0x88,
|
||||
0xc8, 0xe0, 0x12, 0xfa,
|
||||
0x24, 0x15,
|
||||
0xd3, 0x0e, 0x00, 0x24,
|
||||
0xc3, 0x00, 0x00, 0x10,
|
||||
0x21, 0x3f,
|
||||
0xca, 0xe0, 0x00, 0x30,
|
||||
0x27, 0x11,
|
||||
0x20, 0x38,
|
||||
0x48, 0xa0, 0x12, 0xf6,
|
||||
0x48, 0xc0, 0x12, 0xf8,
|
||||
0x42, 0x30, 0x10, 0x70,
|
||||
0x08, 0xaa,
|
||||
0x20, 0x33,
|
||||
0x43, 0x00, 0x12, 0xb2,
|
||||
0x90, 0x05,
|
||||
0x42, 0x30, 0x10, 0x88,
|
||||
0xc8, 0x60, 0x4f, 0x53,
|
||||
0x45, 0x63, 0x00, 0x00,
|
||||
0x20, 0x36,
|
||||
0xc8, 0x60, 0x31, 0x36,
|
||||
0x45, 0x6e, 0x00, 0x02,
|
||||
0x20, 0x3b,
|
||||
0x48, 0x6e, 0x00, 0x08,
|
||||
0x45, 0x60, 0x12, 0xe2,
|
||||
0x20, 0x35,
|
||||
0xd3, 0x6e, 0x00, 0x0a,
|
||||
0xd4, 0x60, 0x12, 0xe4,
|
||||
0x20, 0x3a,
|
||||
0x08, 0x0e,
|
||||
0x07, 0x66,
|
||||
0xca, 0x60, 0x20, 0x00,
|
||||
0x23, 0x36,
|
||||
0x40, 0x06, 0x00, 0x00,
|
||||
0x45, 0x06, 0x00, 0x00,
|
||||
0x22, 0x37,
|
||||
0x48, 0xae, 0x00, 0x0c,
|
||||
0x48, 0xce, 0x00, 0x0e,
|
||||
0x48, 0x0e, 0x00, 0x10,
|
||||
0x48, 0x1e, 0x00, 0x12,
|
||||
0x0b, 0x1c,
|
||||
0x0f, 0x0a, 0x07, 0xff,
|
||||
0x26, 0x11,
|
||||
0x0e, 0x0f,
|
||||
0xed, 0x00, 0x00, 0x08,
|
||||
0xcb, 0x60, 0x02, 0xbe,
|
||||
0x08, 0x00,
|
||||
0x23, 0x34,
|
||||
0x08, 0x86,
|
||||
0x08, 0x16,
|
||||
0x23, 0x04,
|
||||
0x05, 0x16,
|
||||
0x22, 0x84,
|
||||
0x08, 0x81,
|
||||
0x07, 0x77,
|
||||
0x27, 0x81,
|
||||
0xc8, 0xd1, 0xee, 0xc0,
|
||||
0xc8, 0xf0, 0x11, 0x40,
|
||||
0x48, 0x0f, 0x00, 0x00,
|
||||
0x40, 0x01, 0x00, 0x00,
|
||||
0x26, 0xf2,
|
||||
0x26, 0x12,
|
||||
0xc5, 0xf0, 0x13, 0xfe,
|
||||
0x20, 0x88,
|
||||
0x0a, 0xed,
|
||||
0x40, 0xed, 0x12, 0xf4,
|
||||
0x43, 0x0d, 0x11, 0x40,
|
||||
0x41, 0xed, 0x11, 0x88,
|
||||
0xd1, 0xed, 0x13, 0xf6,
|
||||
0xd0, 0xe0, 0x00, 0x78,
|
||||
0xd1, 0xed, 0x13, 0xfa,
|
||||
0xd0, 0xe0, 0x00, 0x7c,
|
||||
0x48, 0x10, 0x00, 0x62,
|
||||
0x48, 0x6d, 0x12, 0xf4,
|
||||
0xd1, 0xa6, 0x00, 0x00,
|
||||
0xd0, 0xa1, 0x00, 0x30,
|
||||
0xd1, 0xe6, 0x00, 0x0c,
|
||||
0xd0, 0xe1, 0x00, 0x28,
|
||||
0x43, 0x00, 0x00, 0x60,
|
||||
0x07, 0x00,
|
||||
0x07, 0xbb,
|
||||
0x0b, 0xcf,
|
||||
0x0f, 0xab,
|
||||
0x21, 0x13,
|
||||
0x26, 0x01,
|
||||
0x22, 0x04,
|
||||
0x0a, 0xcf,
|
||||
0x0e, 0xab,
|
||||
0x08, 0xac,
|
||||
0x08, 0xc0,
|
||||
0x03, 0x0e,
|
||||
0xde, 0x2d, 0x12, 0x1e,
|
||||
0xc5, 0x50, 0x00, 0x33,
|
||||
0x42, 0x2d, 0x11, 0xec,
|
||||
0xde, 0x3d, 0x12, 0x1e,
|
||||
0x9d, 0x3f,
|
||||
0x22, 0x21,
|
||||
0x9d, 0x4f,
|
||||
0x42, 0x1d, 0x12, 0xb8,
|
||||
0xc3, 0xf0, 0x00, 0x10,
|
||||
0x20, 0x35,
|
||||
0xd0, 0xad, 0x13, 0xea,
|
||||
0xc8, 0xf0, 0x00, 0x30,
|
||||
0x41, 0xed, 0x11, 0x70,
|
||||
0x08, 0x9c,
|
||||
0x08, 0xba,
|
||||
0x48, 0xad, 0x13, 0xea,
|
||||
0x48, 0xcd, 0x13, 0xee,
|
||||
0xd1, 0xed, 0x13, 0xf2,
|
||||
0xc5, 0xb0, 0x00, 0x18,
|
||||
0x21, 0x82,
|
||||
0x26, 0xb8,
|
||||
0x98, 0x49,
|
||||
0xde, 0x4d, 0x12, 0xe7,
|
||||
0x9d, 0x3f,
|
||||
0x22, 0x21,
|
||||
0x9d, 0x4f,
|
||||
0x42, 0x7d, 0x12, 0xb8,
|
||||
0x20, 0x83,
|
||||
0x98, 0x27,
|
||||
0x98, 0x28,
|
||||
0x98, 0x49,
|
||||
0x9a, 0x3b,
|
||||
0x41, 0x6d, 0x12, 0x7a,
|
||||
0x22, 0x0f,
|
||||
0x9d, 0x4f,
|
||||
0xc3, 0xf0, 0x00, 0x19,
|
||||
0x42, 0x3d, 0x12, 0xb8,
|
||||
0xd0, 0xad, 0x13, 0xea,
|
||||
0xc8, 0xf5, 0xff, 0xcc,
|
||||
0x0a, 0xff,
|
||||
0x48, 0xff, 0x12, 0xec,
|
||||
0x41, 0xed, 0x11, 0x70,
|
||||
0x08, 0x9c,
|
||||
0x08, 0xca,
|
||||
0x07, 0xaa,
|
||||
0xc8, 0xf5, 0xff, 0xcc,
|
||||
0xd3, 0xff, 0x12, 0xe8,
|
||||
0x41, 0xed, 0x11, 0x70,
|
||||
0x40, 0xcd, 0x12, 0xf2,
|
||||
0x08, 0xba,
|
||||
0x48, 0xad, 0x13, 0xea,
|
||||
0x48, 0xcd, 0x13, 0xee,
|
||||
0xd1, 0xed, 0x13, 0xf2,
|
||||
0xde, 0x4d, 0x12, 0x6e,
|
||||
0x9d, 0x3f,
|
||||
0x22, 0x21,
|
||||
0x98, 0x49,
|
||||
0xde, 0x4d, 0x12, 0xd0,
|
||||
0x9d, 0x3f,
|
||||
0x22, 0x21,
|
||||
0xde, 0x4d, 0x12, 0xa2,
|
||||
0x9d, 0x3f,
|
||||
0x22, 0x21,
|
||||
0xd8, 0x4d, 0x12, 0xf2,
|
||||
0xde, 0x4d, 0x12, 0xd1,
|
||||
0x9d, 0x3f,
|
||||
0x22, 0x21,
|
||||
0xde, 0x4d, 0x12, 0xe7,
|
||||
0x9d, 0x3f,
|
||||
0x22, 0x21,
|
||||
0x9d, 0x4f,
|
||||
0x20, 0x81,
|
||||
0xc3, 0xf0, 0x00, 0x53,
|
||||
0x42, 0x3d, 0x12, 0xb8,
|
||||
0x48, 0xfd, 0x12, 0xf2,
|
||||
0x91, 0xfa,
|
||||
0x06, 0xf9,
|
||||
0xc8, 0x6d, 0x12, 0x2c,
|
||||
0x98, 0x27,
|
||||
0x98, 0x28,
|
||||
0x9a, 0x3b,
|
||||
0x98, 0x3f,
|
||||
0xde, 0x3d, 0x12, 0xe6,
|
||||
0xde, 0x2d, 0x11, 0xaf,
|
||||
0x9d, 0x2f,
|
||||
0x20, 0x81,
|
||||
0xde, 0x2d, 0x12, 0x1e,
|
||||
0x99, 0x20,
|
||||
0xde, 0x2d, 0x12, 0x1e,
|
||||
0x9d, 0x3f,
|
||||
0x22, 0x21,
|
||||
0x42, 0x1d, 0x12, 0xbc,
|
||||
0xc3, 0xf0, 0x00, 0x10,
|
||||
0x03, 0x3e,
|
||||
0x0b, 0x07,
|
||||
0x26, 0x02,
|
||||
0xc4, 0x00, 0xff, 0x00,
|
||||
0x0a, 0x70,
|
||||
0x26, 0x91,
|
||||
0x07, 0xbb,
|
||||
0x40, 0xbd, 0x12, 0xf2,
|
||||
0x03, 0x06,
|
||||
0x24, 0xf1,
|
||||
0x24, 0x10,
|
||||
0x23, 0x04,
|
||||
0x08, 0x14,
|
||||
0x23, 0x02,
|
||||
0x08, 0x13,
|
||||
0x24, 0x01,
|
||||
0xde, 0x0d, 0x10, 0xdc,
|
||||
0x9a, 0x0f,
|
||||
0x9a, 0x01,
|
||||
0xde, 0x0d, 0x12, 0xe5,
|
||||
0xd1, 0xed, 0x13, 0xf6,
|
||||
0xd0, 0xe0, 0x00, 0x78,
|
||||
0xd1, 0xed, 0x13, 0xfa,
|
||||
0xd0, 0xe0, 0x00, 0x7c,
|
||||
0x91, 0x0f,
|
||||
0x95, 0x10,
|
||||
0x22, 0x01,
|
||||
0x00, 0x00, 0x00,
|
||||
0x80,
|
||||
0xc1,
|
||||
0xc2,
|
||||
0x14, 0x40, 0x40, 0x00,
|
||||
0x01, 0x90,
|
||||
0x01, 0x40,
|
||||
0x04, 0xc0,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00
|
||||
};
|
||||
|
||||
/* Lower memory setup
|
||||
|
||||
78 = binary input device address
|
||||
79 = binary device input command
|
||||
7A = disk device number
|
||||
7B = device code
|
||||
7C = disk controller address
|
||||
7D = selector channel address
|
||||
7E:7F = operating system extension (user specified)
|
||||
*/
|
||||
|
||||
struct dboot_id {
|
||||
char *name;
|
||||
uint32 cap;
|
||||
uint32 dtype;
|
||||
uint32 offset;
|
||||
};
|
||||
|
||||
static struct dboot_id dboot_tab[] = {
|
||||
{ "DP", 2, 0x31, o_DP0 },
|
||||
{ "DP", 9, 0x33, o_DP0 },
|
||||
{ "DM", 64, 0x35, o_ID0 },
|
||||
{ "DM", 244, 0x36, o_ID0 },
|
||||
{ NULL } };
|
||||
|
||||
t_stat id_dboot (int32 u, DEVICE *dptr)
|
||||
{
|
||||
extern DIB pt_dib, sch_dib;
|
||||
extern uint32 PC;
|
||||
uint32 i, typ, ctlno, off, cap, sch_dev;
|
||||
UNIT *uptr;
|
||||
|
||||
DIB *ddib = (DIB *) dptr->ctxt; /* get disk DIB */
|
||||
ctlno = ddib->dno; /* get ctrl devno */
|
||||
sch_dev = sch_dib.dno + ddib->sch; /* sch dev # */
|
||||
uptr = dptr->units + u; /* get capacity */
|
||||
cap = uptr->capac >> 20;
|
||||
for (i = typ = 0; dboot_tab[i].name != NULL; i++) {
|
||||
if ((strcmp (dboot_tab[i].name, dptr->name) == 0) &&
|
||||
(dboot_tab[i].cap == cap)) {
|
||||
typ = dboot_tab[i].dtype;
|
||||
off = dboot_tab[i].offset; } }
|
||||
if (typ == 0) return SCPE_NOFNC;
|
||||
|
||||
IOWriteBlk (DBOOT_BEG, DBOOT_LEN, dboot_rom); /* copy boot */
|
||||
IOWriteB (AL_DEV, pt_dib.dno); /* bin input dev */
|
||||
IOWriteB (AL_IOC, 0x99);
|
||||
IOWriteB (AL_DSKU, ctlno + ((u + 1) * off)); /* disk param */
|
||||
IOWriteB (AL_DSKT, typ);
|
||||
IOWriteB (AL_DSKC, ctlno);
|
||||
IOWriteB (AL_SCH, sch_dev);
|
||||
PC = DBOOT_START;
|
||||
return SCPE_OK;
|
||||
}
|
521
Interdata/id16_sys.c
Normal file
521
Interdata/id16_sys.c
Normal file
|
@ -0,0 +1,521 @@
|
|||
/* id16_sys.c: Interdata 16b simulator interface
|
||||
|
||||
Copyright (c) 2000-2003, 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.
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
#include <ctype.h>
|
||||
|
||||
#define MSK_SBF 0x0100
|
||||
|
||||
extern DEVICE cpu_dev;
|
||||
extern DEVICE sch_dev;
|
||||
extern DEVICE pt_dev;
|
||||
extern DEVICE tt_dev, ttp_dev;
|
||||
extern DEVICE pas_dev, pasl_dev;
|
||||
extern DEVICE lpt_dev;
|
||||
extern DEVICE pic_dev, lfc_dev;
|
||||
extern DEVICE dp_dev, idc_dev;
|
||||
extern DEVICE fd_dev, mt_dev;
|
||||
extern UNIT cpu_unit;
|
||||
extern REG cpu_reg[];
|
||||
extern uint16 *M;
|
||||
|
||||
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val);
|
||||
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val);
|
||||
extern t_stat lp_load (FILE *fileref, char *cptr, char *fnam);
|
||||
extern pt_dump (FILE *of, char *cptr, char *fnam);
|
||||
|
||||
/* SCP data structures and interface routines
|
||||
|
||||
sim_name simulator name string
|
||||
sim_PC pointer to saved PC register descriptor
|
||||
sim_emax number of words for examine
|
||||
sim_devices array of pointers to simulated devices
|
||||
sim_stop_messages array of pointers to stop messages
|
||||
sim_load binary loader
|
||||
*/
|
||||
|
||||
char sim_name[] = "Interdata 16b";
|
||||
|
||||
REG *sim_PC = &cpu_reg[0];
|
||||
|
||||
int32 sim_emax = 8;
|
||||
|
||||
DEVICE *sim_devices[] = {
|
||||
&cpu_dev,
|
||||
&sch_dev,
|
||||
&pt_dev,
|
||||
&tt_dev,
|
||||
&ttp_dev,
|
||||
&pas_dev,
|
||||
&pasl_dev,
|
||||
&pic_dev,
|
||||
&lfc_dev,
|
||||
&lpt_dev,
|
||||
&dp_dev,
|
||||
&idc_dev,
|
||||
&fd_dev,
|
||||
&mt_dev,
|
||||
NULL };
|
||||
|
||||
const char *sim_stop_messages[] = {
|
||||
"Unknown error",
|
||||
"Reserved instruction",
|
||||
"HALT instruction",
|
||||
"Breakpoint",
|
||||
"Wait state",
|
||||
"Runaway VFU" };
|
||||
|
||||
/* Binary loader -- load carriage control tape
|
||||
Binary dump -- paper tape dump */
|
||||
|
||||
t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
|
||||
{
|
||||
if (flag) return pt_dump (fileref, cptr, fnam);
|
||||
return lp_load (fileref, cptr, fnam);
|
||||
}
|
||||
|
||||
/* Symbol tables */
|
||||
|
||||
#define I_V_FL 16 /* class bits */
|
||||
#define I_M_FL 0xF /* class mask */
|
||||
#define I_V_MR 0x0 /* mask-register */
|
||||
#define I_V_RR 0x1 /* register-register */
|
||||
#define I_V_R 0x2 /* register */
|
||||
#define I_V_MX 0x3 /* mask-memory */
|
||||
#define I_V_RX 0x4 /* register-memory */
|
||||
#define I_V_X 0x5 /* memory */
|
||||
#define I_V_FF 0x6 /* float reg-reg */
|
||||
#define I_V_FX 0x7 /* float reg-mem */
|
||||
#define I_V_SI 0x8 /* short immed */
|
||||
#define I_V_SB 0x9 /* short branch */
|
||||
#define I_V_SX 0xA /* short ext branch */
|
||||
#define I_MR (I_V_MR << I_V_FL)
|
||||
#define I_RR (I_V_RR << I_V_FL)
|
||||
#define I_R (I_V_R << I_V_FL)
|
||||
#define I_MX (I_V_MX << I_V_FL)
|
||||
#define I_RX (I_V_RX << I_V_FL)
|
||||
#define I_X (I_V_X << I_V_FL)
|
||||
#define I_FF (I_V_FF << I_V_FL)
|
||||
#define I_FX (I_V_FX << I_V_FL)
|
||||
#define I_SI (I_V_SI << I_V_FL)
|
||||
#define I_SB (I_V_SB << I_V_FL)
|
||||
#define I_SX (I_V_SX << I_V_FL)
|
||||
|
||||
#define R_X 0 /* no reg */
|
||||
#define R_M 1 /* reg mask */
|
||||
#define R_R 2 /* reg int reg */
|
||||
#define R_F 3 /* reg flt reg */
|
||||
|
||||
static const int32 masks[] = {
|
||||
0xFF00, 0xFF00, 0xFFF0, 0xFF00,
|
||||
0xFF00, 0xFFF0, 0xFF00, 0xFF00,
|
||||
0xFF00, 0xFE00, 0xFEF0 };
|
||||
|
||||
static const uint32 r1_type[] = {
|
||||
R_M, R_R, R_X, R_M,
|
||||
R_R, R_X, R_F, R_F,
|
||||
R_R, R_M, R_X };
|
||||
|
||||
static const uint32 r2_type[] = {
|
||||
R_X, R_R, R_R, R_X,
|
||||
R_X, R_X, R_F, R_X,
|
||||
R_M, R_X, R_X };
|
||||
|
||||
static const char *opcode[] = {
|
||||
"BER", "BNER","BZR", "BNZR",
|
||||
"BPR", "BNPR","BLR", "BNLR",
|
||||
"BMR", "BNMR","BOR", "BNOR",
|
||||
"BCR", "BNCR","BR",
|
||||
"BES", "BNES","BZS", "BNZS",
|
||||
"BPS", "BNPS","BLS", "BNLS",
|
||||
"BMS", "BNMS","BOS", "BNOS",
|
||||
"BCS", "BNCS","BS",
|
||||
"BE", "BNE", "BZ", "BNZ",
|
||||
"BP", "BNP", "BL", "BNL",
|
||||
"BM", "BNM", "BO", "BNO",
|
||||
"BC", "BNC", "B",
|
||||
"BALR","BTCR","BFCR",
|
||||
"NHR", "CLHR","OHR", "XHR",
|
||||
"LHR", "CHR", "AHR", "SHR",
|
||||
"MHR", "DHR", "ACHR","SCHR",
|
||||
"SETMR",
|
||||
"BTBS","BTFS","BFBS","BFFS",
|
||||
"LIS", "LCS", "AIS", "SIS",
|
||||
"LER", "CER", "AER", "SER",
|
||||
"MER", "DER", "FXR", "FLR",
|
||||
"LPSR",
|
||||
"LDR", "CDR", "ADR", "SDR",
|
||||
"MDR", "DDR", "FXDR","FLDR",
|
||||
"STH", "BAL", "BTC", "BFC",
|
||||
"NH", "CLH", "OH", "XH",
|
||||
"LH", "CH", "AH", "SH",
|
||||
"MH", "DH", "ACH", "SCH",
|
||||
"SETM",
|
||||
"STE", "AHM",
|
||||
"ATL", "ABL", "RTL", "RBL",
|
||||
"LE", "CE", "AE", "SE",
|
||||
"ME", "DE",
|
||||
"STD", "STME","LME", "LPS",
|
||||
"LD", "CD", "AD", "SD",
|
||||
"MD", "DD", "STMD","LMD",
|
||||
"SRLS","SLLS","STBR","LBR",
|
||||
"EXBR","EPSR","WBR", "RBR",
|
||||
"WHR", "RHR", "WDR", "RDR",
|
||||
"MHUR","SSR", "OCR", "AIR",
|
||||
"BXH", "BXLE","LPSW","THI",
|
||||
"NHI", "CLHI","OHI", "XHI",
|
||||
"LHI", "CHI", "AHI", "SHI",
|
||||
"SRHL","SLHL","SRHA","SLHA",
|
||||
"STM", "LM", "STB", "LB",
|
||||
"CLB", "AL", "WB", "RB",
|
||||
"WH", "RH", "WD", "RD",
|
||||
"MHU", "SS", "OC", "AI",
|
||||
"SVC", "SINT",
|
||||
"RRL", "RLL",
|
||||
"SRL", "SLL", "SRA", "SLA",
|
||||
NULL };
|
||||
|
||||
static const uint32 opc_val[] = {
|
||||
0x0330+I_R, 0x0230+I_R, 0x0330+I_R, 0x0230+I_R,
|
||||
0x0220+I_R, 0x0320+I_R, 0x0280+I_R, 0x0380+I_R,
|
||||
0x0210+I_R, 0x0310+I_R, 0x0240+I_R, 0x0340+I_R,
|
||||
0x0280+I_R, 0x0380+I_R, 0x0300+I_R,
|
||||
0x2230+I_SX, 0x2030+I_SX, 0x2230+I_SX, 0x2030+I_SX,
|
||||
0x2020+I_SX, 0x2220+I_SX, 0x2080+I_SX, 0x2280+I_SX,
|
||||
0x2010+I_SX, 0x2210+I_SX, 0x2040+I_SX, 0x2240+I_SX,
|
||||
0x2080+I_SX, 0x2280+I_SX, 0x2200+I_SX,
|
||||
0x4330+I_X, 0x4230+I_X, 0x4330+I_X, 0x4230+I_X,
|
||||
0x4220+I_X, 0x4320+I_X, 0x4280+I_X, 0x4380+I_X,
|
||||
0x4210+I_X, 0x4310+I_X, 0x4240+I_X, 0x4340+I_X,
|
||||
0x4280+I_X, 0x4380+I_X, 0x4300+I_X,
|
||||
0x0100+I_RR, 0x0200+I_MR, 0x0300+I_MR,
|
||||
0x0400+I_RR, 0x0500+I_RR, 0x0600+I_RR, 0x0700+I_RR,
|
||||
0x0800+I_RR, 0x0900+I_RR, 0x0A00+I_RR, 0x0B00+I_RR,
|
||||
0x0C00+I_RR, 0x0D00+I_RR, 0x0E00+I_RR, 0x0F00+I_RR,
|
||||
0x1300+I_RR,
|
||||
0x2000+I_SB, 0x2100+I_SB, 0x2200+I_SB, 0x2300+I_SB,
|
||||
0x2400+I_SI, 0x2500+I_SI, 0x2600+I_SI, 0x2700+I_SI,
|
||||
0x2800+I_FF, 0x2900+I_FF, 0x2A00+I_FF, 0x2B00+I_FF,
|
||||
0x2C00+I_FF, 0x2D00+I_FF, 0x2E00+I_RR, 0x2F00+I_RR,
|
||||
0x3300+I_R,
|
||||
0x3800+I_FF, 0x3900+I_FF, 0x3A00+I_FF, 0x3B00+I_FF,
|
||||
0x3C00+I_FF, 0x3D00+I_FF, 0x3E00+I_RR, 0x3F00+I_RR,
|
||||
0x4000+I_RX, 0x4100+I_RX, 0x4200+I_MX, 0x4300+I_MX,
|
||||
0x4400+I_RX, 0x4500+I_RX, 0x4600+I_RX, 0x4700+I_RX,
|
||||
0x4800+I_RX, 0x4900+I_RX, 0x4A00+I_RX, 0x4B00+I_RX,
|
||||
0x4C00+I_RX, 0x4D00+I_RX, 0x4E00+I_RX, 0x4F00+I_RX,
|
||||
0x5300+I_RX,
|
||||
0x6000+I_RX, 0x6100+I_RX,
|
||||
0x6400+I_RX, 0x6500+I_RX, 0x6600+I_RX, 0x6700+I_RX,
|
||||
0x6800+I_FX, 0x6900+I_FX, 0x6A00+I_FX, 0x6B00+I_FX,
|
||||
0x6C00+I_FX, 0x6D00+I_FX,
|
||||
0x7000+I_FX, 0x7100+I_FX, 0x7200+I_FX, 0x7300+I_X,
|
||||
0x7800+I_FX, 0x7900+I_FX, 0x7A00+I_FX, 0x7B00+I_FX,
|
||||
0x7C00+I_FX, 0x7D00+I_FX, 0x7E00+I_FX, 0x7F00+I_FX,
|
||||
0x9000+I_SI, 0x9100+I_SI, 0x9200+I_RR, 0x9300+I_RR,
|
||||
0x9400+I_RR, 0x9500+I_RR, 0x9600+I_RR, 0x9700+I_RR,
|
||||
0x9800+I_RR, 0x9900+I_RR, 0x9A00+I_RR, 0x9B00+I_RR,
|
||||
0x9C00+I_RR, 0x9D00+I_RR, 0x9E00+I_RR, 0x9F00+I_RR,
|
||||
0xC000+I_RX, 0xC100+I_RX, 0xC200+I_X, 0xC300+I_RX,
|
||||
0xC400+I_RX, 0xC500+I_RX, 0xC600+I_RX, 0xC700+I_RX,
|
||||
0xC800+I_RX, 0xC900+I_RX, 0xCA00+I_RX, 0xCB00+I_RX,
|
||||
0xCC00+I_RX, 0xCD00+I_RX, 0xCE00+I_RX, 0xCF00+I_RX,
|
||||
0xD000+I_RX, 0xD100+I_RX, 0xD200+I_RX, 0xD300+I_RX,
|
||||
0xD400+I_RX, 0xD500+I_X, 0xD600+I_RX, 0xD700+I_RX,
|
||||
0xD800+I_RX, 0xD900+I_RX, 0xDA00+I_RX, 0xDB00+I_RX,
|
||||
0xDC00+I_RX, 0xDD00+I_RX, 0xDE00+I_RX, 0xDF00+I_RX,
|
||||
0xE100+I_RX, 0xE200+I_RX,
|
||||
0xEA00+I_RX, 0xEB00+I_RX,
|
||||
0xEC00+I_RX, 0xED00+I_RX, 0xEE00+I_RX, 0xEF00+I_RX,
|
||||
0xFFFF };
|
||||
|
||||
#define GETNUM(d,n) for (k = d = 0; k < n; k++) \
|
||||
d = (d << 8) | (((uint32) val[vp++]) & 0xFF)
|
||||
|
||||
/* Symbolic decode
|
||||
|
||||
Inputs:
|
||||
*of = output stream
|
||||
addr = current PC
|
||||
*val = values to decode
|
||||
*uptr = pointer to unit
|
||||
sw = switches
|
||||
Outputs:
|
||||
return = if >= 0, error code
|
||||
if < 0, number of extra bytes retired
|
||||
*/
|
||||
|
||||
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
|
||||
UNIT *uptr, int32 sw)
|
||||
{
|
||||
int32 c, k, num, rdx, vp, lnt;
|
||||
t_stat r;
|
||||
DEVICE *dptr;
|
||||
|
||||
if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */
|
||||
dptr = find_dev_from_unit (uptr); /* find dev */
|
||||
if (dptr == NULL) return SCPE_IERR;
|
||||
if (dptr->dwidth != 8) return SCPE_ARG; /* byte dev only */
|
||||
if (sw & SWMASK ('B')) lnt = 1; /* get length */
|
||||
else if (sw & SWMASK ('W')) lnt = 2;
|
||||
else if (sw & SWMASK ('F')) lnt = 4;
|
||||
else lnt = (uptr == &cpu_unit)? 2: 1;
|
||||
if (sw & SWMASK ('D')) rdx = 10; /* get radix */
|
||||
else if (sw & SWMASK ('O')) rdx = 8;
|
||||
else if (sw & SWMASK ('H')) rdx = 16;
|
||||
else rdx = dptr->dradix;
|
||||
vp = 0; /* init ptr */
|
||||
if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */
|
||||
if (sw & SWMASK ('C')) lnt = sim_emax; /* -c -> string */
|
||||
if ((val[0] & 0x7F) == 0) return SCPE_ARG;
|
||||
while (vp < lnt) { /* print string */
|
||||
if ((c = (uint32) val[vp++] & 0x7F) == 0) break;
|
||||
fprintf (of, (c < 0x20)? "<%02X>": "%c", c); }
|
||||
return -(vp - 1); } /* return # chars */
|
||||
|
||||
if (sw & SWMASK ('M')) { /* inst format? */
|
||||
r = fprint_sym_m (of, addr, val); /* decode inst */
|
||||
if (r <= 0) return r; }
|
||||
|
||||
GETNUM (num, lnt); /* get number */
|
||||
fprint_val (of, num, rdx, lnt * 8, PV_RZRO);
|
||||
return -(vp - 1);
|
||||
}
|
||||
|
||||
/* Symbolic decode for -m
|
||||
|
||||
Inputs:
|
||||
of = output stream
|
||||
addr = current PC
|
||||
*val = values to decode
|
||||
Outputs:
|
||||
return = if >= 0, error code
|
||||
if < 0, number of extra bytes retired
|
||||
*/
|
||||
|
||||
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val)
|
||||
{
|
||||
uint32 i, j, k, inst, r1, r2, ea, tgt, vp;
|
||||
|
||||
vp = 0;
|
||||
GETNUM (inst, 2); /* first 16b */
|
||||
GETNUM (ea, 2); /* second 16b */
|
||||
for (i = 0; opcode[i] != NULL; i++) { /* loop thru ops */
|
||||
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
|
||||
if ((opc_val[i] & 0xFFFF) == (inst & masks[j])) { /* match? */
|
||||
r1 = (inst >> 4) & 0xF;
|
||||
r2 = inst & 0xF;
|
||||
switch (j) { /* case on class */
|
||||
case I_V_MR: /* mask-register */
|
||||
fprintf (of, "%s %-X,R%d", opcode[i], r1, r2);
|
||||
return -1;
|
||||
case I_V_RR: /* register-register */
|
||||
case I_V_FF: /* floating-floating */
|
||||
fprintf (of, "%s R%d,R%d", opcode[i], r1, r2);
|
||||
return -1;
|
||||
case I_V_SI: /* short immediate */
|
||||
fprintf (of, "%s R%d,%-X", opcode[i], r1, r2);
|
||||
return -1;
|
||||
case I_V_SB: /* short branch */
|
||||
if (inst & MSK_SBF) tgt = addr + r2 + r2;
|
||||
else tgt = addr - r2 - r2;
|
||||
fprintf (of, "%s %-X,%-X", opcode[i], r1, tgt);
|
||||
return -1;
|
||||
case I_V_SX: /* ext short branch */
|
||||
if (inst & MSK_SBF) tgt = addr + r2 + r2;
|
||||
else tgt = addr - r2 - r2;
|
||||
fprintf (of, "%s %-X", opcode[i], tgt);
|
||||
return -1;
|
||||
case I_V_R: /* register */
|
||||
fprintf (of, "%s R%d", opcode[i], r2);
|
||||
return -1;
|
||||
case I_V_MX: /* mask-memory */
|
||||
fprintf (of, "%s %-X,%-X", opcode[i], r1, ea);
|
||||
break;
|
||||
case I_V_RX: /* register-memory */
|
||||
case I_V_FX: /* floating-memory */
|
||||
fprintf (of, "%s R%d,%-X", opcode[i], r1, ea);
|
||||
break;
|
||||
case I_V_X: /* memory */
|
||||
fprintf (of, "%s %-X", opcode[i], ea);
|
||||
break; } /* end case */
|
||||
if (r2) fprintf (of, "(R%d)", r2);
|
||||
return -3; } /* end if */
|
||||
} /* end for */
|
||||
return SCPE_ARG; /* no match */
|
||||
}
|
||||
|
||||
/* Register number
|
||||
|
||||
Inputs:
|
||||
*cptr = pointer to input string
|
||||
**optr = pointer to pointer to next char
|
||||
rtype = mask, integer, or float
|
||||
Outputs:
|
||||
rnum = output register number, -1 if error
|
||||
*/
|
||||
|
||||
int32 get_reg (char *cptr, char **optr, int32 rtype)
|
||||
{
|
||||
int32 reg;
|
||||
|
||||
if ((*cptr == 'R') || (*cptr == 'r')) { /* R? */
|
||||
cptr++; /* skip */
|
||||
if (rtype == R_M) return -1; } /* cant be mask */
|
||||
if ((*cptr >= '0') && (*cptr <= '9')) {
|
||||
reg = *cptr++ - '0';
|
||||
if ((*cptr >= '0') && (*cptr <= '9'))
|
||||
reg = (reg * 10) + (*cptr - '0');
|
||||
else --cptr;
|
||||
if (reg > 0xF) return -1; }
|
||||
else if ((*cptr >= 'a') && (*cptr <= 'f')) reg = (*cptr - 'a') + 10;
|
||||
else if ((*cptr >= 'A') && (*cptr <= 'F')) reg = (*cptr - 'A') + 10;
|
||||
else return -1;
|
||||
if ((rtype == R_F) && (reg & 1)) return -1;
|
||||
*optr = cptr + 1;
|
||||
return reg;
|
||||
}
|
||||
|
||||
#define PUTNUM(d,n) for (k = n; k > 0; k--) \
|
||||
val[vp++] = (d >> ((k - 1) * 8)) & 0xFF
|
||||
|
||||
/* Symbolic input */
|
||||
|
||||
t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
|
||||
{
|
||||
int32 k, rdx, lnt, num, vp;
|
||||
t_stat r;
|
||||
DEVICE *dptr;
|
||||
static const uint32 maxv[5] = { 0, 0xFF, 0xFFFF, 0, 0xFFFFFFFF };
|
||||
|
||||
if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */
|
||||
dptr = find_dev_from_unit (uptr); /* find dev */
|
||||
if (dptr == NULL) return SCPE_IERR;
|
||||
if (dptr->dwidth != 8) return SCPE_ARG; /* byte dev only */
|
||||
if (sw & SWMASK ('B')) lnt = 1; /* get length */
|
||||
else if (sw & SWMASK ('W')) lnt = 2;
|
||||
else if (sw & SWMASK ('F')) lnt = 4;
|
||||
else lnt = (uptr == &cpu_unit)? 2: 1;
|
||||
if (sw & SWMASK ('D')) rdx = 10; /* get radix */
|
||||
else if (sw & SWMASK ('O')) rdx = 8;
|
||||
else if (sw & SWMASK ('H')) rdx = 16;
|
||||
else rdx = dptr->dradix;
|
||||
vp = 0;
|
||||
if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */
|
||||
if (sw & SWMASK ('C')) lnt = sim_emax; /* -c -> string */
|
||||
if (*cptr == 0) return SCPE_ARG;
|
||||
while ((vp < lnt) && *cptr) { /* get chars */
|
||||
val[vp++] = *cptr++; }
|
||||
return -(vp - 1); } /* return # chars */
|
||||
|
||||
if (uptr == &cpu_unit) { /* cpu only */
|
||||
r = parse_sym_m (cptr, addr, val); /* try to parse inst */
|
||||
if (r <= 0) return r; }
|
||||
|
||||
num = (int32) get_uint (cptr, rdx, maxv[lnt], &r); /* get number */
|
||||
if (r != SCPE_OK) return r;
|
||||
PUTNUM (num, lnt); /* store */
|
||||
return -(lnt - 1);
|
||||
}
|
||||
|
||||
/* Symbolic input for -m
|
||||
|
||||
Inputs:
|
||||
*cptr = pointer to input string
|
||||
addr = current PC
|
||||
*val = pointer to output values
|
||||
Outputs:
|
||||
status = > 0 error code
|
||||
<= 0 -number of extra words
|
||||
*/
|
||||
|
||||
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val)
|
||||
{
|
||||
uint32 i, j, k, t, df, db, inst, ea, vp;
|
||||
int32 r1, r2;
|
||||
t_stat r;
|
||||
char *tptr, gbuf[CBUFSIZE];
|
||||
|
||||
vp = 0;
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get opcode */
|
||||
for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;
|
||||
if (opcode[i] == NULL) return SCPE_ARG;
|
||||
inst = opc_val[i] & 0xFFFF; /* get value */
|
||||
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
|
||||
if (r1_type[j]) { /* any R1 field? */
|
||||
cptr = get_glyph (cptr, gbuf, ','); /* get R1 field */
|
||||
if ((r1 = get_reg (gbuf, &tptr, r1_type[j])) < 0)
|
||||
return SCPE_ARG;
|
||||
if (*tptr != 0) return SCPE_ARG; /* all done? */
|
||||
inst = inst | (r1 << 4); } /* or in R1 */
|
||||
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get operand */
|
||||
if (*cptr) return SCPE_ARG; /* should be end */
|
||||
switch (j) { /* case on class */
|
||||
|
||||
case I_V_FF: case I_V_SI: /* flt-flt, sh imm */
|
||||
case I_V_MR: case I_V_RR: /* mask/reg-reg */
|
||||
case I_V_R: /* register */
|
||||
if ((r2 = get_reg (gbuf, &tptr, r2_type[j])) < 0)
|
||||
return SCPE_ARG;
|
||||
if (*tptr != 0) return SCPE_ARG; /* all done? */
|
||||
inst = inst | r2; /* or in R2 */
|
||||
break;
|
||||
|
||||
case I_V_FX: /* float-memory */
|
||||
case I_V_MX: case I_V_RX: /* mask/reg-mem */
|
||||
case I_V_X: /* memory */
|
||||
errno = 0;
|
||||
ea = strtoul (gbuf, &tptr, 16); /* get address */
|
||||
if (errno || (gbuf == tptr)) return SCPE_ARG; /* error? */
|
||||
if (*tptr == '(') { /* index? */
|
||||
if ((r2 = get_reg (tptr + 1, &tptr, R_R)) < 0)
|
||||
return SCPE_ARG;
|
||||
if (*tptr++ != ')') return SCPE_ARG;
|
||||
inst = inst | r2; } /* or in R2 */
|
||||
if (*tptr != 0) return SCPE_ARG;
|
||||
PUTNUM (inst, 2);
|
||||
PUTNUM (ea, 2);
|
||||
return -3;
|
||||
|
||||
case I_V_SB: case I_V_SX: /* short branches */
|
||||
t = get_uint (gbuf, 16, DMASK16, &r); /* get addr */
|
||||
if ((r != SCPE_OK) || (t & 1)) return r; /* error if odd */
|
||||
db = (addr - t) & 0x1F; /* back displ */
|
||||
df = (t - addr) & 0x1F; /* fwd displ */
|
||||
if ((t == ((addr - db) & VAMASK16)) && /* back work and */
|
||||
((j == I_V_SX) || !(inst & MSK_SBF))) { /* ext or back br? */
|
||||
inst = inst | (db >> 1); /* or in back displ */
|
||||
break; }
|
||||
if ((t == ((addr + df) & VAMASK16)) && /* fwd work and */
|
||||
((j == I_V_SX) || (inst & MSK_SBF))) { /* ext or fwd br? */
|
||||
inst = inst | (df >> 1) | MSK_SBF; /* or in fwd displ */
|
||||
break; }
|
||||
return SCPE_ARG; } /* end case */
|
||||
|
||||
PUTNUM (inst, 2);
|
||||
return -1;
|
||||
}
|
2025
Interdata/id32_cpu.c
Normal file
2025
Interdata/id32_cpu.c
Normal file
File diff suppressed because it is too large
Load diff
308
Interdata/id32_dboot.c
Normal file
308
Interdata/id32_dboot.c
Normal file
|
@ -0,0 +1,308 @@
|
|||
/* id32_dboot.c: Interdata 32b simulator disk bootstrap
|
||||
|
||||
Copyright (c) 2000-2002, 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.
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
|
||||
#define DBOOT_BEG 0x1000
|
||||
#define DBOOT_START 0x100E
|
||||
#define DBOOT_LEN (sizeof (dboot_rom) / sizeof (uint8))
|
||||
|
||||
/* Transcribed from 32b Bootstrap Loader, 03-074N81R03A13 */
|
||||
|
||||
static uint8 dboot_rom[] = {
|
||||
0xca, 0xf0, 0x00, 0x30,
|
||||
0xc5, 0xf0, 0x00, 0x3a,
|
||||
0x02, 0x8e,
|
||||
0x26, 0xf7,
|
||||
0x03, 0x0e,
|
||||
0xe6, 0xd0, 0x0f, 0x30,
|
||||
0xd1, 0xe0, 0x00, 0x78,
|
||||
0xd0, 0xed, 0x03, 0x40,
|
||||
0xd3, 0xf0, 0x00, 0x7e,
|
||||
0xc4, 0xf0, 0x00, 0x0f,
|
||||
0x41, 0xed, 0x00, 0xd0,
|
||||
0xd2, 0xfd, 0x03, 0x25,
|
||||
0xd3, 0xf0, 0x00, 0x7f,
|
||||
0x10, 0xf4,
|
||||
0x41, 0xed, 0x00, 0xd0,
|
||||
0xd2, 0xfd, 0x03, 0x26,
|
||||
0xd3, 0xf0, 0x00, 0x7f,
|
||||
0xc4, 0xf0, 0x00, 0x0f,
|
||||
0x41, 0xed, 0x00, 0xd0,
|
||||
0xd2, 0xfd, 0x03, 0x27,
|
||||
0xd3, 0x20, 0x00, 0x7d,
|
||||
0xd3, 0x30, 0x00, 0x7c,
|
||||
0xd3, 0x40, 0x00, 0x7a,
|
||||
0x24, 0x50,
|
||||
0xd3, 0xf0, 0x00, 0x7b,
|
||||
0xcb, 0xf0, 0x00, 0x33,
|
||||
0x23, 0x23,
|
||||
0x11, 0xf1,
|
||||
0x08, 0x5f,
|
||||
0xe6, 0x7d, 0x03, 0x50,
|
||||
0xe6, 0x8d, 0x04, 0x4f,
|
||||
0x07, 0xcc,
|
||||
0x41, 0xed, 0x01, 0xfc,
|
||||
0xd1, 0xed, 0x03, 0x5c,
|
||||
0xd0, 0xed, 0x03, 0x48,
|
||||
0x58, 0xcd, 0x03, 0x58,
|
||||
0x43, 0x3d, 0x01, 0x9c,
|
||||
0xe6, 0x7d, 0x03, 0x50,
|
||||
0x41, 0xed, 0x01, 0xfc,
|
||||
0xe6, 0xed, 0x03, 0x54,
|
||||
0x24, 0x15,
|
||||
0xf8, 0xf0, 0x4f, 0x53, 0x33, 0x32,
|
||||
0xd3, 0x7e, 0x00, 0x24,
|
||||
0xc3, 0x70, 0x00, 0x10,
|
||||
0x23, 0x3e,
|
||||
0xce, 0x70, 0x00, 0xe0,
|
||||
0x21, 0xeb,
|
||||
0x55, 0xfe, 0x00, 0x00,
|
||||
0x21, 0x38,
|
||||
0x58, 0x6e, 0x00, 0x08,
|
||||
0x10, 0x68,
|
||||
0x55, 0x6d, 0x03, 0x24,
|
||||
0x44, 0x3d, 0x01, 0xb2,
|
||||
0xca, 0xe0, 0x00, 0x30,
|
||||
0x27, 0x11,
|
||||
0x42, 0x3d, 0x01, 0x66,
|
||||
0x58, 0xcd, 0x03, 0x50,
|
||||
0x42, 0x3d, 0x01, 0x52,
|
||||
0x48, 0x10, 0x00, 0x7e,
|
||||
0x42, 0x3d, 0x02, 0xf0,
|
||||
0x58, 0xcd, 0x03, 0x48,
|
||||
0x43, 0x3d, 0x02, 0xf0,
|
||||
0x58, 0x8d, 0x03, 0x4c,
|
||||
0x23, 0x07,
|
||||
0x58, 0xce, 0x00, 0x0c,
|
||||
0x58, 0x8e, 0x00, 0x10,
|
||||
0x0b, 0x8c,
|
||||
0x26, 0xc1,
|
||||
0x11, 0x88,
|
||||
0x08, 0x18,
|
||||
0xe6, 0xf0, 0x11, 0x18,
|
||||
0x58, 0x0f, 0x00, 0x00,
|
||||
0x50, 0x01, 0x00, 0x00,
|
||||
0x59, 0x01, 0x00, 0x00,
|
||||
0x42, 0x3d, 0x03, 0x08,
|
||||
0x26, 0xf4,
|
||||
0x26, 0x14,
|
||||
0xc5, 0xf0, 0x12, 0x78,
|
||||
0x20, 0x8c,
|
||||
0x08, 0xd8,
|
||||
0xcb, 0xd0, 0x01, 0xe8,
|
||||
0x03, 0x08,
|
||||
0x27, 0x81,
|
||||
0x07, 0x77,
|
||||
0x41, 0xed, 0x01, 0xfc,
|
||||
0xd1, 0xed, 0x03, 0x40,
|
||||
0xd0, 0xe0, 0x00, 0x78,
|
||||
0x43, 0x00, 0x00, 0x60,
|
||||
0xde, 0x2d, 0x03, 0x28,
|
||||
0x08, 0x0c,
|
||||
0x4d, 0x0d, 0x45, 0x00, 0x03, 0x30,
|
||||
0x08, 0x91,
|
||||
0x4d, 0x0d, 0x45, 0x00, 0x03, 0x38,
|
||||
0x08, 0xa1,
|
||||
0x08, 0xb0,
|
||||
0x08, 0x55,
|
||||
0x42, 0x2d, 0x02, 0x4a,
|
||||
0xde, 0x3d, 0x03, 0x28,
|
||||
0x9d, 0x3f,
|
||||
0x22, 0x21,
|
||||
0x9d, 0x4f,
|
||||
0x42, 0x1d, 0x02, 0xf4,
|
||||
0xc3, 0xf0, 0x00, 0x10,
|
||||
0x20, 0x35,
|
||||
0x11, 0xa5,
|
||||
0x06, 0xba,
|
||||
0x98, 0x49,
|
||||
0xde, 0x4d, 0x03, 0x28,
|
||||
0x9d, 0x3f,
|
||||
0x22, 0x21,
|
||||
0x9d, 0x4f,
|
||||
0x42, 0x7d, 0x02, 0xf8,
|
||||
0x20, 0x83,
|
||||
0x41, 0x6d, 0x02, 0x96,
|
||||
0x22, 0x0b,
|
||||
0x9d, 0x4f,
|
||||
0xc3, 0xf0, 0x00, 0x19,
|
||||
0x42, 0x3d, 0x02, 0xfc,
|
||||
0xde, 0x4d, 0x03, 0x2c,
|
||||
0x9d, 0x3f,
|
||||
0x22, 0x21,
|
||||
0x98, 0x49,
|
||||
0xde, 0x4d, 0x03, 0x2e,
|
||||
0x9d, 0x3f,
|
||||
0x22, 0x21,
|
||||
0xde, 0x4d, 0x03, 0x2d,
|
||||
0x9d, 0x3f,
|
||||
0x22, 0x21,
|
||||
0x98, 0x4a,
|
||||
0xde, 0x4d, 0x03, 0x2f,
|
||||
0x0d, 0x3f,
|
||||
0x22, 0x21,
|
||||
0xde, 0x4d, 0x03, 0x2b,
|
||||
0x9d, 0x3f,
|
||||
0x22, 0x21,
|
||||
0x9d, 0x4f,
|
||||
0x20, 0x81,
|
||||
0xc3, 0xf0, 0x00, 0x53,
|
||||
0x42, 0x3d, 0x03, 0x00,
|
||||
0x08, 0xfa,
|
||||
0x11, 0xfa,
|
||||
0x06, 0xf9,
|
||||
0xe6, 0x6d, 0x02, 0x54,
|
||||
0x34, 0x77,
|
||||
0x9a, 0x27,
|
||||
0x34, 0x77,
|
||||
0x98, 0x27,
|
||||
0x34, 0x88,
|
||||
0x9a, 0x28,
|
||||
0x34, 0x88,
|
||||
0x98, 0x28,
|
||||
0x08, 0x55,
|
||||
0x21, 0x24,
|
||||
0x98, 0x49,
|
||||
0x9a, 0x3b,
|
||||
0x23, 0x03,
|
||||
0x9a, 0x3b,
|
||||
0x98, 0x3f,
|
||||
0xde, 0x3d, 0x03, 0x2a,
|
||||
0xde, 0x2d, 0x03, 0x29,
|
||||
0x9d, 0x2f,
|
||||
0x20, 0x81,
|
||||
0xde, 0x2d, 0x03, 0x28,
|
||||
0x9b, 0x20,
|
||||
0x99, 0x21,
|
||||
0x34, 0x00,
|
||||
0x06, 0x01,
|
||||
0xde, 0x2d, 0x03, 0x28,
|
||||
0x9d, 0x3f,
|
||||
0x22, 0x21,
|
||||
0x42, 0x1d, 0x03, 0x04,
|
||||
0xc3, 0xf0, 0x00, 0x10,
|
||||
0x03, 0x3e,
|
||||
0x0b, 0x07,
|
||||
0x26, 0x04,
|
||||
0xc4, 0x00, 0xff, 0x00,
|
||||
0x0a, 0x70,
|
||||
0x26, 0x91,
|
||||
0x07, 0xaa,
|
||||
0x07, 0xbb,
|
||||
0x03, 0x06,
|
||||
0x24, 0x11,
|
||||
0x23, 0x0c,
|
||||
0x24, 0x12,
|
||||
0x23, 0x0a,
|
||||
0x24, 0x13,
|
||||
0x23, 0x08,
|
||||
0x24, 0x14,
|
||||
0x23, 0x06,
|
||||
0x24, 0x15,
|
||||
0x23, 0x04,
|
||||
0x24, 0x16,
|
||||
0x23, 0x02,
|
||||
0x24, 0x17,
|
||||
0x24, 0x01,
|
||||
0xde, 0x0d, 0x03, 0x28,
|
||||
0x9a, 0x01,
|
||||
0xde, 0x0d, 0x03, 0x28,
|
||||
0xd1, 0xed, 0x03, 0x40,
|
||||
0xd0, 0xe0, 0x00, 0x78,
|
||||
0x11, 0x0f,
|
||||
0x95, 0x10,
|
||||
0x22, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x48, 0x30,
|
||||
0xc1, 0xc2,
|
||||
0xc8, 0xc4,
|
||||
0xd0, 0xe0,
|
||||
0x00, 0x30,
|
||||
0x01, 0x90,
|
||||
0x01, 0x40,
|
||||
0x04, 0xc0,
|
||||
0x00, 0x18,
|
||||
0x00, 0x14,
|
||||
0x00, 0x40,
|
||||
0x00, 0x40,
|
||||
0x00
|
||||
};
|
||||
|
||||
/* Lower memory setup
|
||||
|
||||
78 = binary input device address
|
||||
79 = binary device input command
|
||||
7A = disk device number
|
||||
7B = device code
|
||||
7C = disk controller address
|
||||
7D = selector channel address
|
||||
7E:7F = operating system extension (user specified)
|
||||
*/
|
||||
|
||||
struct dboot_id {
|
||||
char *name;
|
||||
uint32 cap;
|
||||
uint32 dtype;
|
||||
uint32 offset;
|
||||
};
|
||||
|
||||
static struct dboot_id dboot_tab[] = {
|
||||
{ "DP", 2, 0x31, o_DP0 },
|
||||
{ "DP", 9, 0x33, o_DP0 },
|
||||
{ "DM", 64, 0x35, o_ID0 },
|
||||
{ "DM", 244, 0x36, o_ID0 },
|
||||
{ NULL } };
|
||||
|
||||
t_stat id_dboot (int32 u, DEVICE *dptr)
|
||||
{
|
||||
extern DIB pt_dib, sch_dib;
|
||||
extern uint32 PC;
|
||||
uint32 i, typ, ctlno, off, cap, sch_dev;
|
||||
UNIT *uptr;
|
||||
|
||||
DIB *ddib = (DIB *) dptr->ctxt; /* get disk DIB */
|
||||
ctlno = ddib->dno; /* get ctrl devno */
|
||||
sch_dev = sch_dib.dno + ddib->sch; /* sch dev # */
|
||||
uptr = dptr->units + u; /* get capacity */
|
||||
cap = uptr->capac >> 20;
|
||||
for (i = typ = 0; dboot_tab[i].name != NULL; i++) {
|
||||
if ((strcmp (dboot_tab[i].name, dptr->name) == 0) &&
|
||||
(dboot_tab[i].cap == cap)) {
|
||||
typ = dboot_tab[i].dtype;
|
||||
off = dboot_tab[i].offset; } }
|
||||
if (typ == 0) return SCPE_NOFNC;
|
||||
|
||||
IOWriteBlk (DBOOT_BEG, DBOOT_LEN, dboot_rom); /* copy boot */
|
||||
IOWriteB (AL_DEV, pt_dib.dno); /* bin input dev */
|
||||
IOWriteB (AL_IOC, 0x99);
|
||||
IOWriteB (AL_DSKU, ctlno + ((u + 1) * off)); /* disk param */
|
||||
IOWriteB (AL_DSKT, typ);
|
||||
IOWriteB (AL_DSKC, ctlno);
|
||||
IOWriteB (AL_SCH, sch_dev);
|
||||
PC = DBOOT_START;
|
||||
return SCPE_OK;
|
||||
}
|
641
Interdata/id32_sys.c
Normal file
641
Interdata/id32_sys.c
Normal file
|
@ -0,0 +1,641 @@
|
|||
/* id32_sys.c: Interdata 32b simulator interface
|
||||
|
||||
Copyright (c) 2000-2003, 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.
|
||||
|
||||
23-Dec-01 RMS Cloned from ID4 sources
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
#include <ctype.h>
|
||||
|
||||
#define MSK_SBF 0x0100
|
||||
#define SEXT15(x) (((x) & 0x4000)? ((x) | 0xFFFF8000): ((x) & 0x7FFF))
|
||||
|
||||
extern DEVICE cpu_dev;
|
||||
extern DEVICE sch_dev;
|
||||
extern DEVICE pt_dev;
|
||||
extern DEVICE tt_dev, ttp_dev;
|
||||
extern DEVICE pas_dev, pasl_dev;
|
||||
extern DEVICE lpt_dev;
|
||||
extern DEVICE pic_dev, lfc_dev;
|
||||
extern DEVICE dp_dev, idc_dev;
|
||||
extern DEVICE fd_dev, mt_dev;
|
||||
extern UNIT cpu_unit;
|
||||
extern REG cpu_reg[];
|
||||
extern uint32 *M;
|
||||
|
||||
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val);
|
||||
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val);
|
||||
extern t_stat lp_load (FILE *fileref, char *cptr, char *fnam);
|
||||
extern pt_dump (FILE *of, char *cptr, char *fnam);
|
||||
|
||||
/* SCP data structures and interface routines
|
||||
|
||||
sim_name simulator name string
|
||||
sim_PC pointer to saved PC register descriptor
|
||||
sim_emax number of words for examine
|
||||
sim_devices array of pointers to simulated devices
|
||||
sim_stop_messages array of pointers to stop messages
|
||||
sim_load binary loader
|
||||
*/
|
||||
|
||||
char sim_name[] = "Interdata 32b";
|
||||
|
||||
REG *sim_PC = &cpu_reg[0];
|
||||
|
||||
int32 sim_emax = 6;
|
||||
|
||||
DEVICE *sim_devices[] = {
|
||||
&cpu_dev,
|
||||
&sch_dev,
|
||||
&pt_dev,
|
||||
&tt_dev,
|
||||
&ttp_dev,
|
||||
&pas_dev,
|
||||
&pasl_dev,
|
||||
&pic_dev,
|
||||
&lfc_dev,
|
||||
&lpt_dev,
|
||||
&dp_dev,
|
||||
&idc_dev,
|
||||
&fd_dev,
|
||||
&mt_dev,
|
||||
NULL };
|
||||
|
||||
const char *sim_stop_messages[] = {
|
||||
"Unknown error",
|
||||
"Reserved instruction",
|
||||
"HALT instruction",
|
||||
"Breakpoint",
|
||||
"Wait state",
|
||||
"Runaway VFU" };
|
||||
|
||||
/* Binary loader -- load carriage control tape
|
||||
Binary dump -- paper tape dump */
|
||||
|
||||
t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
|
||||
{
|
||||
if (flag) return pt_dump (fileref, cptr, fnam);
|
||||
return lp_load (fileref, cptr, fnam);
|
||||
}
|
||||
|
||||
/* Symbol tables */
|
||||
|
||||
#define I_V_FL 16 /* class bits */
|
||||
#define I_M_FL 0xF /* class mask */
|
||||
#define I_V_MR 0x0 /* mask-register */
|
||||
#define I_V_RR 0x1 /* register-register */
|
||||
#define I_V_R 0x2 /* register */
|
||||
#define I_V_MX 0x3 /* mask-memory */
|
||||
#define I_V_RX 0x4 /* register-memory */
|
||||
#define I_V_X 0x5 /* memory */
|
||||
#define I_V_FF 0x6 /* float reg-reg */
|
||||
#define I_V_FX 0x7 /* float reg-mem */
|
||||
#define I_V_SI 0x8 /* short immed */
|
||||
#define I_V_SB 0x9 /* short branch */
|
||||
#define I_V_SX 0xA /* short ext branch */
|
||||
#define I_V_RI 0xB /* halfword imm */
|
||||
#define I_V_RF 0xC /* fullword imm */
|
||||
#define I_MR (I_V_MR << I_V_FL)
|
||||
#define I_RR (I_V_RR << I_V_FL)
|
||||
#define I_R (I_V_R << I_V_FL)
|
||||
#define I_MX (I_V_MX << I_V_FL)
|
||||
#define I_RX (I_V_RX << I_V_FL)
|
||||
#define I_X (I_V_X << I_V_FL)
|
||||
#define I_FF (I_V_FF << I_V_FL)
|
||||
#define I_FX (I_V_FX << I_V_FL)
|
||||
#define I_SI (I_V_SI << I_V_FL)
|
||||
#define I_SB (I_V_SB << I_V_FL)
|
||||
#define I_SX (I_V_SX << I_V_FL)
|
||||
#define I_RI (I_V_RI << I_V_FL)
|
||||
#define I_RF (I_V_RF << I_V_FL)
|
||||
|
||||
#define R_X 0 /* no R1 */
|
||||
#define R_M 1 /* R1 mask */
|
||||
#define R_R 2 /* R1 int reg */
|
||||
#define R_F 3 /* R1 flt reg */
|
||||
|
||||
static const int32 masks[] = {
|
||||
0xFF00, 0xFF00, 0xFFF0, 0xFF00,
|
||||
0xFF00, 0xFFF0, 0xFF00, 0xFF00,
|
||||
0xFF00, 0xFE00, 0xFEF0, 0xFF00,
|
||||
0xFF00 };
|
||||
|
||||
static const uint32 r1_type[] = {
|
||||
R_M, R_R, R_X, R_M,
|
||||
R_R, R_X, R_F, R_F,
|
||||
R_R, R_M, R_X, R_R,
|
||||
R_R };
|
||||
|
||||
static const uint32 r2_type[] = {
|
||||
R_X, R_R, R_R, R_X,
|
||||
R_X, R_X, R_F, R_X,
|
||||
R_M, R_X, R_X, R_X,
|
||||
R_X };
|
||||
|
||||
static const char *opcode[] = {
|
||||
"BER", "BNER","BZR", "BNZR",
|
||||
"BPR", "BNPR","BLR", "BNLR",
|
||||
"BMR", "BNMR","BOR", "BNOR",
|
||||
"BCR", "BNCR","BR",
|
||||
"BES", "BNES","BZS", "BNZS",
|
||||
"BPS", "BNPS","BLS", "BNLS",
|
||||
"BMS", "BNMS","BOS", "BNOS",
|
||||
"BCS", "BNCS","BS",
|
||||
"BE", "BNE", "BZ", "BNZ",
|
||||
"BP", "BNP", "BL", "BNL",
|
||||
"BM", "BNM", "BO", "BNO",
|
||||
"BC", "BNC", "B",
|
||||
"BALR","BTCR","BFCR",
|
||||
"NR", "CLR", "OR", "XR",
|
||||
"LR", "CHR", "AR", "SR",
|
||||
"MHR", "DHR",
|
||||
"SRLS","SLLS","CHVR",
|
||||
"LPSWR",
|
||||
"MR", "DR",
|
||||
"BTBS","BTFS","BFBS","BFFS",
|
||||
"LIS", "LCS", "AIS", "SIS",
|
||||
"LER", "CER", "AER", "SER",
|
||||
"MER", "DER", "FXR", "FLR",
|
||||
"MPBSR", "PBR",
|
||||
"EXHR",
|
||||
"LDR", "CDR", "ADR", "SDR",
|
||||
"MDR", "DDR", "FXDR","FLDR",
|
||||
"STH", "BAL", "BTC", "BFC",
|
||||
"NH", "CLH", "OH", "XH",
|
||||
"LH", "CH", "AH", "SH",
|
||||
"MH", "DH",
|
||||
"ST", "AM",
|
||||
"N", "CL", "O", "X",
|
||||
"L", "C", "A", "S",
|
||||
"M", "D", "CRC12","CRC16",
|
||||
"STE", "AHM", "PB", "LRA",
|
||||
"ATL", "ABL", "RTL", "RBL",
|
||||
"LE", "CE", "AE", "SE",
|
||||
"ME", "DE",
|
||||
"STD", "STME","LME", "LHL",
|
||||
"TBT", "SBT", "RBT", "CBT",
|
||||
"LD", "CD", "AD", "SD",
|
||||
"MD", "DD", "STMD","LMD",
|
||||
"SRHLS","SLHLS","STBR","LBR",
|
||||
"EXBR","EPSR","WBR", "RBR",
|
||||
"WHR", "RHR", "WDR", "RDR",
|
||||
"SSR", "OCR",
|
||||
"BXH", "BXLE","LPSW","THI",
|
||||
"NHI", "CLHI","OHI", "XHI",
|
||||
"LHI", "CHI", "AHI", "SHI",
|
||||
"SRHL","SLHL","SRHA","SLHA",
|
||||
"STM", "LM", "STB", "LB",
|
||||
"CLB", "AL", "WB", "RB",
|
||||
"WH", "RH", "WD", "RD",
|
||||
"SS", "OC",
|
||||
"TS", "SVC", "SINT","SCP",
|
||||
"LA", "TLATE",
|
||||
"RRL", "RLL",
|
||||
"SRL", "SLL", "SRA", "SLA",
|
||||
"TI",
|
||||
"NI", "CLI", "OI", "XI",
|
||||
"LI", "CI", "AI", "SI",
|
||||
NULL };
|
||||
|
||||
static const uint32 opc_val[] = {
|
||||
0x0330+I_R, 0x0230+I_R, 0x0330+I_R, 0x0230+I_R,
|
||||
0x0220+I_R, 0x0320+I_R, 0x0280+I_R, 0x0380+I_R,
|
||||
0x0210+I_R, 0x0310+I_R, 0x0240+I_R, 0x0340+I_R,
|
||||
0x0280+I_R, 0x0380+I_R, 0x0300+I_R,
|
||||
0x2230+I_SX, 0x2030+I_SX, 0x2230+I_SX, 0x2030+I_SX,
|
||||
0x2020+I_SX, 0x2220+I_SX, 0x2080+I_SX, 0x2280+I_SX,
|
||||
0x2010+I_SX, 0x2210+I_SX, 0x2040+I_SX, 0x2240+I_SX,
|
||||
0x2080+I_SX, 0x2280+I_SX, 0x2200+I_SX,
|
||||
0x4330+I_X, 0x4230+I_X, 0x4330+I_X, 0x4230+I_X,
|
||||
0x4220+I_X, 0x4320+I_X, 0x4280+I_X, 0x4380+I_X,
|
||||
0x4210+I_X, 0x4310+I_X, 0x4240+I_X, 0x4340+I_X,
|
||||
0x4280+I_X, 0x4380+I_X, 0x4300+I_X,
|
||||
0x0100+I_RR, 0x0200+I_MR, 0x0300+I_MR,
|
||||
0x0400+I_RR, 0x0500+I_RR, 0x0600+I_RR, 0x0700+I_RR,
|
||||
0x0800+I_RR, 0x0900+I_RR, 0x0A00+I_RR, 0x0B00+I_RR,
|
||||
0x0C00+I_RR, 0x0D00+I_RR,
|
||||
0x1000+I_SI, 0x1100+I_SI, 0x1200+I_RR,
|
||||
0x1800+I_RR,
|
||||
0x1C00+I_RR, 0x1D00+I_RR,
|
||||
0x2000+I_SB, 0x2100+I_SB, 0x2200+I_SB, 0x2300+I_SB,
|
||||
0x2400+I_SI, 0x2500+I_SI, 0x2600+I_SI, 0x2700+I_SI,
|
||||
0x2800+I_FF, 0x2900+I_FF, 0x2A00+I_FF, 0x2B00+I_FF,
|
||||
0x2C00+I_FF, 0x2D00+I_FF, 0x2E00+I_RR, 0x2F00+I_RR,
|
||||
0x3000+I_RR, 0x3200+I_RR,
|
||||
0x3400+I_RR,
|
||||
0x3800+I_FF, 0x3900+I_FF, 0x3A00+I_FF, 0x3B00+I_FF,
|
||||
0x3C00+I_FF, 0x3D00+I_FF, 0x3E00+I_RR, 0x3F00+I_RR,
|
||||
0x4000+I_RX, 0x4100+I_RX, 0x4200+I_MX, 0x4300+I_MX,
|
||||
0x4400+I_RX, 0x4500+I_RX, 0x4600+I_RX, 0x4700+I_RX,
|
||||
0x4800+I_RX, 0x4900+I_RX, 0x4A00+I_RX, 0x4B00+I_RX,
|
||||
0x4C00+I_RX, 0x4D00+I_RX,
|
||||
0x5000+I_RX, 0x5100+I_RX,
|
||||
0x5400+I_RX, 0x5500+I_RX, 0x5600+I_RX, 0x5700+I_RX,
|
||||
0x5800+I_RX, 0x5900+I_RX, 0x5A00+I_RX, 0x5B00+I_RX,
|
||||
0x5C00+I_RX, 0x5D00+I_RX, 0x5E00+I_RX, 0x5F00+I_RX,
|
||||
0x6000+I_RX, 0x6100+I_RX, 0x6200+I_RX, 0x6300+I_RX,
|
||||
0x6400+I_RX, 0x6500+I_RX, 0x6600+I_RX, 0x6700+I_RX,
|
||||
0x6800+I_FX, 0x6900+I_FX, 0x6A00+I_FX, 0x6B00+I_FX,
|
||||
0x6C00+I_FX, 0x6D00+I_FX,
|
||||
0x7000+I_FX, 0x7100+I_FX, 0x7200+I_FX, 0x7300+I_RX,
|
||||
0x7400+I_RX, 0x7500+I_RX, 0x7600+I_RX, 0x7700+I_RX,
|
||||
0x7800+I_FX, 0x7900+I_FX, 0x7A00+I_FX, 0x7B00+I_FX,
|
||||
0x7C00+I_FX, 0x7D00+I_FX, 0x7E00+I_FX, 0x7F00+I_FX,
|
||||
0x9000+I_SI, 0x9100+I_SI, 0x9200+I_RR, 0x9300+I_RR,
|
||||
0x9400+I_RR, 0x9500+I_RR, 0x9600+I_RR, 0x9700+I_RR,
|
||||
0x9800+I_RR, 0x9900+I_RR, 0x9A00+I_RR, 0x9B00+I_RR,
|
||||
0x9D00+I_RR, 0x9E00+I_RR,
|
||||
0xC000+I_RX, 0xC100+I_RX, 0xC200+I_RX, 0xC300+I_RI,
|
||||
0xC400+I_RI, 0xC500+I_RI, 0xC600+I_RI, 0xC700+I_RI,
|
||||
0xC800+I_RI, 0xC900+I_RI, 0xCA00+I_RI, 0xCB00+I_RI,
|
||||
0xCC00+I_RI, 0xCD00+I_RI, 0xCE00+I_RI, 0xCF00+I_RI,
|
||||
0xD000+I_RX, 0xD100+I_RX, 0xD200+I_RX, 0xD300+I_RX,
|
||||
0xD400+I_RX, 0xD500+I_X, 0xD600+I_RX, 0xD700+I_RX,
|
||||
0xD800+I_RX, 0xD900+I_RX, 0xDA00+I_RX, 0xDB00+I_RX,
|
||||
0xDD00+I_RX, 0xDE00+I_RX,
|
||||
0xE000+I_RX, 0xE100+I_RX, 0xE200+I_RI, 0xE300+I_RX,
|
||||
0xE600+I_RX, 0xE700+I_RX,
|
||||
0xEA00+I_RI, 0xEB00+I_RI,
|
||||
0xEC00+I_RI, 0xED00+I_RI, 0xEE00+I_RI, 0xEF00+I_RI,
|
||||
0xF300+I_RF,
|
||||
0xF400+I_RF, 0xF500+I_RF, 0xF600+I_RF, 0xF700+I_RF,
|
||||
0xF800+I_RF, 0xF900+I_RF, 0xFA00+I_RF, 0xFB00+I_RF,
|
||||
0xFFFF };
|
||||
|
||||
/* Print an RX specifier */
|
||||
|
||||
t_stat fprint_addr (FILE *of, t_addr addr, uint32 rx, uint32 ea1, uint32 ea2)
|
||||
{
|
||||
uint32 rx2;
|
||||
|
||||
if ((ea1 & 0xC000) == 0) { /* RX1 */
|
||||
fprintf (of, "%-X", ea1);
|
||||
if (rx) fprintf (of, "(R%d)", rx);
|
||||
return -3; }
|
||||
if (ea1 & 0x8000) { /* RX2 */
|
||||
ea1 = addr + 4 + SEXT15 (ea1);
|
||||
fprintf (of, "%-X", ea1 & VAMASK32);
|
||||
if (rx) fprintf (of, "(R%d)", rx);
|
||||
return -3; }
|
||||
rx2 = (ea1 >> 8) & 0xF;
|
||||
fprintf (of, "%-X", ((ea1 << 16) | ea2) & VAMASK32);
|
||||
if (rx && !rx2) fprintf (of, "(R%d)", rx);
|
||||
if (rx2) fprintf (of, "(R%d,R%d)", rx, rx2);
|
||||
return -5;
|
||||
}
|
||||
|
||||
#define GETNUM(d,n) for (k = d = 0; k < n; k++) \
|
||||
d = (d << 8) | (((uint32) val[vp++]) & 0xFF)
|
||||
|
||||
/* Symbolic decode
|
||||
|
||||
Inputs:
|
||||
*of = output stream
|
||||
addr = current PC
|
||||
*val = values to decode
|
||||
*uptr = pointer to unit
|
||||
sw = switches
|
||||
Outputs:
|
||||
return = if >= 0, error code
|
||||
if < 0, number of extra bytes retired
|
||||
*/
|
||||
|
||||
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
|
||||
UNIT *uptr, int32 sw)
|
||||
{
|
||||
int32 c, k, num, rdx, vp, lnt;
|
||||
t_stat r;
|
||||
DEVICE *dptr;
|
||||
|
||||
if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */
|
||||
dptr = find_dev_from_unit (uptr); /* find dev */
|
||||
if (dptr == NULL) return SCPE_IERR;
|
||||
if (dptr->dwidth != 8) return SCPE_ARG; /* byte dev only */
|
||||
if (sw & SWMASK ('B')) lnt = 1; /* get length */
|
||||
else if (sw & SWMASK ('W')) lnt = 2;
|
||||
else if (sw & SWMASK ('F')) lnt = 4;
|
||||
else lnt = (uptr == &cpu_unit)? 4: 1;
|
||||
if (sw & SWMASK ('D')) rdx = 10; /* get radix */
|
||||
else if (sw & SWMASK ('O')) rdx = 8;
|
||||
else if (sw & SWMASK ('H')) rdx = 16;
|
||||
else rdx = dptr->dradix;
|
||||
vp = 0; /* init ptr */
|
||||
if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */
|
||||
if (sw & SWMASK ('C')) lnt = sim_emax; /* -c -> string */
|
||||
if ((val[0] & 0x7F) == 0) return SCPE_ARG;
|
||||
while (vp < lnt) { /* print string */
|
||||
if ((c = (uint32) val[vp++] & 0x7F) == 0) break;
|
||||
fprintf (of, (c < 0x20)? "<%02X>": "%c", c); }
|
||||
return -(vp - 1); } /* return # chars */
|
||||
|
||||
if (sw & SWMASK ('M')) { /* inst format? */
|
||||
r = fprint_sym_m (of, addr, val); /* decode inst */
|
||||
if (r <= 0) return r; /* success? */
|
||||
lnt = 2; } /* no, skip 16b */
|
||||
|
||||
GETNUM (num, lnt); /* get number */
|
||||
fprint_val (of, num, rdx, lnt * 8, PV_RZRO);
|
||||
return -(vp - 1);
|
||||
}
|
||||
|
||||
/* Symbolic decode for -m
|
||||
|
||||
Inputs:
|
||||
of = output stream
|
||||
addr = current PC
|
||||
*val = values to decode
|
||||
Outputs:
|
||||
return = if >= 0, error code
|
||||
if < 0, number of extra bytes retired
|
||||
*/
|
||||
|
||||
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val)
|
||||
{
|
||||
uint32 i, j, k, inst, r1, r2, ea1, ea2, tgt, vp;
|
||||
|
||||
vp = 0;
|
||||
GETNUM (inst,2); /* high 16b */
|
||||
GETNUM (ea1, 2); /* next 16b */
|
||||
GETNUM (ea2, 2); /* next 16b */
|
||||
for (i = 0; opc_val[i] != 0xFFFF; i++) { /* loop thru ops */
|
||||
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
|
||||
if ((opc_val[i] & 0xFFFF) == (inst & masks[j])) { /* match? */
|
||||
r1 = (inst >> 4) & 0xF;
|
||||
r2 = inst & 0xF;
|
||||
switch (j) { /* case on class */
|
||||
case I_V_MR: /* mask-register */
|
||||
fprintf (of, "%s %-X,R%d", opcode[i], r1, r2);
|
||||
return -1;
|
||||
case I_V_RR: /* register-register */
|
||||
case I_V_FF: /* floating-floating */
|
||||
fprintf (of, "%s R%d,R%d", opcode[i], r1, r2);
|
||||
return -1;
|
||||
case I_V_SI: /* short immediate */
|
||||
fprintf (of, "%s R%d,%-X", opcode[i], r1, r2);
|
||||
return -1;
|
||||
case I_V_SB: /* short branch */
|
||||
if (inst & MSK_SBF) tgt = addr + r2 + r2;
|
||||
else tgt = addr - r2 - r2;
|
||||
fprintf (of, "%s %-X,%-X", opcode[i], r1, tgt);
|
||||
return -1;
|
||||
case I_V_SX: /* ext short branch */
|
||||
if (inst & MSK_SBF) tgt = addr + r2 + r2;
|
||||
else tgt = addr - r2 - r2;
|
||||
fprintf (of, "%s %-X", opcode[i], tgt);
|
||||
return -1;
|
||||
case I_V_R: /* register */
|
||||
fprintf (of, "%s R%d", opcode[i], r2);
|
||||
return -1;
|
||||
case I_V_RI: /* reg-immed */
|
||||
fprintf (of, "%s R%d,%-X", opcode[i], r1, ea1);
|
||||
if (r2) fprintf (of, "(R%d)", r2);
|
||||
return -3;
|
||||
case I_V_RF: /* reg-full imm */
|
||||
fprintf (of, "%s R%d,%-X", opcode[i], r1,
|
||||
(ea1 << 16) | ea2);
|
||||
if (r2) fprintf (of, "(R%d)", r2);
|
||||
return -5;
|
||||
case I_V_MX: /* mask-memory */
|
||||
fprintf (of, "%s %-X,", opcode[i], r1);
|
||||
return fprint_addr (of, addr, r2, ea1, ea2);
|
||||
case I_V_RX: /* register-memory */
|
||||
case I_V_FX: /* floating-memory */
|
||||
fprintf (of, "%s R%d,", opcode[i], r1);
|
||||
return fprint_addr (of, addr, r2, ea1, ea2);
|
||||
case I_V_X: /* memory */
|
||||
fprintf (of, "%s ", opcode[i]);
|
||||
return fprint_addr (of, addr, r2, ea1, ea2); }
|
||||
return SCPE_IERR; } /* end if */
|
||||
} /* end for */
|
||||
return SCPE_ARG; /* no match */
|
||||
}
|
||||
|
||||
/* Register number
|
||||
|
||||
Inputs:
|
||||
*cptr = pointer to input string
|
||||
**optr = pointer to pointer to next char
|
||||
rtype = mask, integer, or float
|
||||
Outputs:
|
||||
rnum = output register number, -1 if error
|
||||
*/
|
||||
|
||||
int32 get_reg (char *cptr, char **optr, int32 rtype)
|
||||
{
|
||||
int32 reg;
|
||||
|
||||
if ((*cptr == 'R') || (*cptr == 'r')) { /* R? */
|
||||
cptr++; /* skip */
|
||||
if (rtype == R_M) return -1; } /* cant be mask */
|
||||
if ((*cptr >= '0') && (*cptr <= '9')) {
|
||||
reg = *cptr++ - '0';
|
||||
if ((*cptr >= '0') && (*cptr <= '9'))
|
||||
reg = (reg * 10) + (*cptr - '0');
|
||||
else --cptr;
|
||||
if (reg > 0xF) return -1; }
|
||||
else if ((*cptr >= 'a') && (*cptr <= 'f')) reg = (*cptr - 'a') + 10;
|
||||
else if ((*cptr >= 'A') && (*cptr <= 'F')) reg = (*cptr - 'A') + 10;
|
||||
else return -1;
|
||||
if ((rtype == R_F) && (reg & 1)) return -1;
|
||||
*optr = cptr + 1;
|
||||
return reg;
|
||||
}
|
||||
|
||||
/* Immediate
|
||||
|
||||
Inputs:
|
||||
*cptr = pointer to input string
|
||||
*imm = pointer to output value
|
||||
*inst = pointer to instruction
|
||||
max = max value
|
||||
Outputs:
|
||||
sta = status
|
||||
*/
|
||||
|
||||
t_stat get_imm (char *cptr, uint32 *imm, uint32 *inst, uint32 max)
|
||||
{
|
||||
char *tptr;
|
||||
uint32 idx;
|
||||
|
||||
errno = 0;
|
||||
*imm = strtoul (cptr, &tptr, 16); /* get immed */
|
||||
if (errno || (*imm > max) || (cptr == tptr)) return SCPE_ARG;
|
||||
if (*tptr == '(') { /* index? */
|
||||
if ((idx = get_reg (tptr + 1, &tptr, R_R)) < 0)
|
||||
return SCPE_ARG;
|
||||
if (*tptr++ != ')') return SCPE_ARG;
|
||||
*inst = *inst | idx; }
|
||||
if (*tptr != 0) return SCPE_ARG;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
#define PUTNUM(d,n) for (k = n; k > 0; k--) \
|
||||
val[vp++] = (d >> ((k - 1) * 8)) & 0xFF
|
||||
|
||||
/* Symbolic input */
|
||||
|
||||
t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
|
||||
{
|
||||
int32 k, rdx, lnt, num, vp;
|
||||
t_stat r;
|
||||
DEVICE *dptr;
|
||||
static const uint32 maxv[5] = { 0, 0xFF, 0xFFFF, 0, 0xFFFFFFFF };
|
||||
|
||||
if (uptr == NULL) uptr = &cpu_unit; /* anon = CPU */
|
||||
dptr = find_dev_from_unit (uptr); /* find dev */
|
||||
if (dptr == NULL) return SCPE_IERR;
|
||||
if (dptr->dwidth != 8) return SCPE_ARG; /* byte dev only */
|
||||
if (sw & SWMASK ('B')) lnt = 1; /* get length */
|
||||
else if (sw & SWMASK ('W')) lnt = 2;
|
||||
else if (sw & SWMASK ('F')) lnt = 4;
|
||||
else lnt = (uptr == &cpu_unit)? 4: 1;
|
||||
if (sw & SWMASK ('D')) rdx = 10; /* get radix */
|
||||
else if (sw & SWMASK ('O')) rdx = 8;
|
||||
else if (sw & SWMASK ('H')) rdx = 16;
|
||||
else rdx = dptr->dradix;
|
||||
vp = 0;
|
||||
if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */
|
||||
if (sw & SWMASK ('C')) lnt = sim_emax; /* -c -> string */
|
||||
if (*cptr == 0) return SCPE_ARG;
|
||||
while ((vp < lnt) && *cptr) { /* get chars */
|
||||
val[vp++] = *cptr++; }
|
||||
return -(vp - 1); } /* return # chars */
|
||||
|
||||
if (uptr == &cpu_unit) { /* cpu only */
|
||||
r = parse_sym_m (cptr, addr, val); /* try to parse inst */
|
||||
if (r <= 0) return r; }
|
||||
|
||||
num = (int32) get_uint (cptr, rdx, maxv[lnt], &r); /* get number */
|
||||
if (r != SCPE_OK) return r;
|
||||
PUTNUM (num, lnt); /* store */
|
||||
return -(lnt - 1);
|
||||
}
|
||||
|
||||
/* Symbolic input for -m
|
||||
|
||||
Inputs:
|
||||
*cptr = pointer to input string
|
||||
addr = current PC
|
||||
*val = pointer to output values
|
||||
Outputs:
|
||||
status = > 0 error code
|
||||
<= 0 -number of extra words
|
||||
*/
|
||||
|
||||
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val)
|
||||
{
|
||||
uint32 i, j, k, t, df, db, inst, ea, vp;
|
||||
int32 st, r1, r2, rx2;
|
||||
t_stat r;
|
||||
char *tptr, gbuf[CBUFSIZE];
|
||||
|
||||
vp = 0;
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get opcode */
|
||||
for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;
|
||||
if (opcode[i] == NULL) return SCPE_ARG;
|
||||
inst = opc_val[i] & 0xFFFF; /* get value */
|
||||
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
|
||||
if (r1_type[j]) { /* any R1 field? */
|
||||
cptr = get_glyph (cptr, gbuf, ','); /* get R1 field */
|
||||
if ((r1 = get_reg (gbuf, &tptr, r1_type[j])) < 0)
|
||||
return SCPE_ARG;
|
||||
if (*tptr != 0) return SCPE_ARG;
|
||||
inst = inst | (r1 << 4); } /* or in R1 */
|
||||
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get operand */
|
||||
if (*cptr) return SCPE_ARG; /* should be end */
|
||||
switch (j) { /* case on class */
|
||||
|
||||
case I_V_FF: case I_V_SI: /* flt-flt, sh imm */
|
||||
case I_V_MR: case I_V_RR: /* mask/reg-register */
|
||||
case I_V_R: /* register */
|
||||
if ((r2 = get_reg (gbuf, &tptr, r2_type[j])) < 0)
|
||||
return SCPE_ARG;
|
||||
if (*tptr != 0) return SCPE_ARG;
|
||||
inst = inst | r2; /* or in R2 */
|
||||
break;
|
||||
|
||||
case I_V_FX: /* float-memory */
|
||||
case I_V_MX: case I_V_RX: /* mask/reg-memory */
|
||||
case I_V_X: /* memory */
|
||||
errno = 0;
|
||||
ea = strtoul (gbuf, &tptr, 16); /* get address */
|
||||
if (errno || (gbuf == tptr)) return SCPE_ARG; /* error? */
|
||||
rx2 = 0; /* assume no 2nd */
|
||||
if (*tptr == '(') { /* index? */
|
||||
if ((r2 = get_reg (tptr + 1, &tptr, R_R)) < 0)
|
||||
return SCPE_ARG;
|
||||
inst = inst | r2; /* or in R2 */
|
||||
if (*tptr == ',') { /* 2nd index? */
|
||||
if ((rx2 = get_reg (tptr + 1, &tptr, R_R)) < 0)
|
||||
return SCPE_ARG; }
|
||||
if (*tptr++ != ')') return SCPE_ARG; } /* all done? */
|
||||
if (*tptr != 0) return SCPE_ARG;
|
||||
PUTNUM (inst, 2); /* store inst */
|
||||
if (rx2 == 0) { /* no 2nd? */
|
||||
if (ea < 0x4000) { /* RX1? */
|
||||
PUTNUM (ea, 2); /* store ea */
|
||||
return -3; }
|
||||
st = (ea - (addr + 4)); /* displ */
|
||||
if ((st <= 0x3FFF) && (st >= -0x4000)) { /* RX2? */
|
||||
t = (st & 0x7FFF) | 0x8000;
|
||||
PUTNUM (t, 2); /* store displ */
|
||||
return -3; } }
|
||||
ea = (ea & VAMASK32) | 0x40000000 | (rx2 << 24);
|
||||
PUTNUM (ea, 4); /* RX3 */
|
||||
return -5;
|
||||
|
||||
case I_V_RI: /* 16b immediate */
|
||||
r = get_imm (gbuf, &ea, &inst, DMASK16); /* process imm */
|
||||
if (r != SCPE_OK) return r;
|
||||
PUTNUM (inst, 2); /* store inst */
|
||||
PUTNUM (ea, 2); /* store 16b imm */
|
||||
return -3;
|
||||
|
||||
case I_V_RF:
|
||||
r = get_imm (gbuf, &ea, &inst, DMASK32); /* process imm */
|
||||
if (r != SCPE_OK) return r;
|
||||
PUTNUM (inst, 2); /* store inst */
|
||||
PUTNUM (ea, 4); /* store 32b imm */
|
||||
return -5;
|
||||
|
||||
case I_V_SB: case I_V_SX: /* short branches */
|
||||
t = get_uint (gbuf, 16, DMASK16, &r); /* get addr */
|
||||
if ((r != SCPE_OK) || (t & 1)) return r; /* error if odd */
|
||||
db = (addr - t) & 0x1F; /* back displ */
|
||||
df = (t - addr) & 0x1F; /* fwd displ */
|
||||
if ((t == ((addr - db) & VAMASK16)) && /* back work and */
|
||||
((j == I_V_SX) || !(inst & MSK_SBF))) { /* ext or back br? */
|
||||
inst = inst | (db >> 1); /* or in back displ */
|
||||
break; }
|
||||
if ((t == ((addr + df) & VAMASK16)) && /* fwd work and */
|
||||
((j == I_V_SX) || (inst & MSK_SBF))) { /* ext or fwd br? */
|
||||
inst = inst | (df >> 1) | MSK_SBF; /* or in fwd displ */
|
||||
break; }
|
||||
return SCPE_ARG; } /* end case */
|
||||
|
||||
PUTNUM (inst, 2);
|
||||
return -1;
|
||||
}
|
483
Interdata/id_defs.h
Normal file
483
Interdata/id_defs.h
Normal file
|
@ -0,0 +1,483 @@
|
|||
/* id_defs.h: Interdata 16b/32b simulator definitions
|
||||
|
||||
Copyright (c) 2000-2002, 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.
|
||||
|
||||
The author gratefully acknowledges the help of Carl Friend and Al Kossow,
|
||||
who provided key documents about the Interdata product line.
|
||||
*/
|
||||
|
||||
#include "sim_defs.h" /* simulator defns */
|
||||
|
||||
/* Simulator stop codes */
|
||||
|
||||
#define STOP_RSRV 1 /* undef instr */
|
||||
#define STOP_HALT 2 /* HALT */
|
||||
#define STOP_IBKPT 3 /* breakpoint */
|
||||
#define STOP_WAIT 4 /* wait */
|
||||
#define STOP_VFU 5 /* runaway VFU */
|
||||
|
||||
/* Memory */
|
||||
|
||||
#define PAWIDTH16 16
|
||||
#define PAWIDTH16E 18
|
||||
#define PAWIDTH32 20
|
||||
#define MAXMEMSIZE16 (1u << PAWIDTH16) /* max mem size, 16b */
|
||||
#define MAXMEMSIZE16E (1u << PAWIDTH16E) /* max mem size, 16b E */
|
||||
#define MAXMEMSIZE32 (1u << PAWIDTH32) /* max mem size, 32b */
|
||||
#define PAMASK16 (MAXMEMSIZE16 - 1) /* phys mem mask */
|
||||
#define PAMASK16E (MAXMEMSIZE16E - 1)
|
||||
#define PAMASK32 (MAXMEMSIZE32 - 1)
|
||||
|
||||
#define MEMSIZE (cpu_unit.capac) /* act memory size */
|
||||
#define MEM_ADDR_OK(x) (((t_addr) (x)) < MEMSIZE)
|
||||
|
||||
/* Single precision floating point registers */
|
||||
|
||||
#if defined (IFP_IN_MEM)
|
||||
#define ReadFReg(r) (fp_in_hwre? \
|
||||
F[(r) >> 1]: ReadF (((r) << 1) & ~3, P))
|
||||
#define WriteFReg(r,v) if (fp_in_hwre) F[(r) >> 1] = (v); \
|
||||
else WriteF (((r) << 1) & ~3, (v), P)
|
||||
#else
|
||||
#define ReadFReg(r) (F[(r) >> 1])
|
||||
#define WriteFReg(r,v) F[(r) >> 1] = (v)
|
||||
#endif
|
||||
|
||||
/* Double precision floating point registers */
|
||||
|
||||
struct dpr {
|
||||
unsigned int32 h; /* high 32b */
|
||||
unsigned int32 l; /* low 32b */
|
||||
};
|
||||
|
||||
typedef struct dpr dpr_t;
|
||||
|
||||
/* Architectural constants */
|
||||
|
||||
#define VAMASK16 (0xFFFF) /* 16b virt addr */
|
||||
#define VAMASK32 (0x000FFFFF) /* 32b virt addr */
|
||||
|
||||
#define SIGN8 0x80 /* 8b sign bit */
|
||||
#define DMASK8 0xFF /* 8b data mask */
|
||||
#define MMASK8 0x7F /* 8b magnitude mask */
|
||||
#define SIGN16 0x8000 /* 16b sign bit */
|
||||
#define DMASK16 0xFFFF /* 16b data mask */
|
||||
#define MMASK16 0x7FFF /* 16b magnitude mask */
|
||||
#define SIGN32 0x80000000 /* 32b sign bit */
|
||||
#define DMASK32 0xFFFFFFFF /* 32b data mask */
|
||||
#define MMASK32 0x7FFFFFFF /* 32b magn mask */
|
||||
|
||||
#define CC_C 0x8 /* carry */
|
||||
#define CC_V 0x4 /* overflow */
|
||||
#define CC_G 0x2 /* greater than */
|
||||
#define CC_L 0x1 /* less than */
|
||||
#define CC_MASK (CC_C | CC_V | CC_G | CC_L)
|
||||
|
||||
#define PSW_WAIT 0x8000 /* wait */
|
||||
#define PSW_EXI 0x4000 /* ext intr enable */
|
||||
#define PSW_MCI 0x2000 /* machine check enable */
|
||||
#define PSW_AFI 0x1000 /* arith fault enb */
|
||||
#define PSW_AIO 0x0800 /* auto I/O int enable */
|
||||
#define PSW_FPF 0x0400 /* flt fault enb, 16b */
|
||||
#define PSW_REL 0x0400 /* reloc enb, 32b */
|
||||
#define PSW_SQI 0x0200 /* sys q int enable */
|
||||
#define PSW_PRO 0x0100 /* protect mode */
|
||||
#define PSW_V_MAP 4 /* mem map, 16b */
|
||||
#define PSW_M_MAP 0xF
|
||||
#define PSW_MAP (PSW_M_MAP << PSW_V_MAP)
|
||||
#define PSW_V_REG 4 /* reg set, 32b */
|
||||
#define PSW_M_REG 0x1
|
||||
#define PSW_ID4 0xF40F /* I3, I4 PSW */
|
||||
#define PSW_x16 0xFF0F /* 7/16, 8/16 PSW */
|
||||
#define PSW_816E 0xFFFF /* 8/16E PSW */
|
||||
#define PSW_x32 0xFFFF /* 7/32, 8/32 PSW */
|
||||
#define PSW_GETMAP(x) (((x) >> PSW_V_MAP) & PSW_M_MAP)
|
||||
#define PSW_GETREG(x) (((x) >> PSW_V_REG) & PSW_M_REG)
|
||||
|
||||
#define MCKOPSW 0x20 /* mchk old PSW, 32b */
|
||||
#define FPFPSW 0x28 /* flt fault PSW, 16b */
|
||||
#define ILOPSW 0x30 /* ill op PSW */
|
||||
#define MCKPSW 0x38 /* mach chk PSW */
|
||||
#define EXIPSW 0x40 /* ext intr PSW, 16b */
|
||||
#define AFIPSW 0x48 /* arith flt PSW */
|
||||
#define SQP 0x80 /* system queue ptr */
|
||||
#define SQIPSW 0x82 /* sys q int PSW, 16b */
|
||||
#define SQOP 0x8A /* sys q ovf ptr, 16b */
|
||||
#define SQVPSW 0x8C /* sys q ovf PSW, 16b */
|
||||
#define SQTPSW 0x88 /* sys q int PSW, 32b */
|
||||
#define MPRPSW 0x90 /* mprot int PSW, 32b */
|
||||
#define SVCAP 0x94 /* svc arg ptr, 16b */
|
||||
#define SVOPS 0x96 /* svc old PS, 16b */
|
||||
#define SVOPC 0x98 /* svc old PC, 16b */
|
||||
#define SVNPS32 0x98 /* svc new PS, 32b */
|
||||
#define SVNPS 0x9A /* svc new PS, 16b */
|
||||
#define SVNPC 0x9C /* svc new PC */
|
||||
#define INTSVT 0xD0 /* int service table */
|
||||
|
||||
#define AL_DEV 0x78 /* autoload: dev */
|
||||
#define AL_IOC 0x79 /* command */
|
||||
#define AL_DSKU 0x7A /* disk unit */
|
||||
#define AL_DSKT 0x7B /* disk type */
|
||||
#define AL_DSKC 0x7C /* disk ctrl */
|
||||
#define AL_SCH 0x7D /* sel chan */
|
||||
#define AL_EXT 0x7E /* OS extension */
|
||||
#define AL_BUF 0x80 /* buffer start */
|
||||
|
||||
#define Q16_SLT 0 /* list: # slots */
|
||||
#define Q16_USD 1 /* # in use */
|
||||
#define Q16_TOP 2 /* current top */
|
||||
#define Q16_BOT 3 /* next bottom */
|
||||
#define Q16_BASE 4 /* base of q */
|
||||
#define Q16_SLNT 2 /* slot length */
|
||||
|
||||
#define Q32_SLT 0 /* list: # slots */
|
||||
#define Q32_USD 2 /* # in use */
|
||||
#define Q32_TOP 4 /* current top */
|
||||
#define Q32_BOT 6 /* next bottom */
|
||||
#define Q32_BASE 8 /* base of q */
|
||||
#define Q32_SLNT 4 /* slot length */
|
||||
|
||||
/* CPU event flags */
|
||||
|
||||
#define EV_MAC 0x01 /* MAC interrupt */
|
||||
#define EV_BLK 0x02 /* block I/O in prog */
|
||||
#define EV_INT 0x04 /* interrupt pending */
|
||||
#define EV_WAIT 0x08 /* wait state pending */
|
||||
|
||||
/* Block I/O state */
|
||||
|
||||
struct BlockIO {
|
||||
uint32 dfl; /* devno, flags */
|
||||
t_addr cur; /* current addr */
|
||||
t_addr end; /* end addr */
|
||||
};
|
||||
|
||||
#define BL_RD 0x8000 /* block read */
|
||||
#define BL_LZ 0x4000 /* skip 0's */
|
||||
|
||||
/* Instruction decode ROM, for all, 16b, 32b */
|
||||
|
||||
#define OP_UNDEF 0x0000 /* undefined */
|
||||
#define OP_NO 0x0001 /* all: short or fp rr */
|
||||
#define OP_RR 0x0002 /* all: reg-reg */
|
||||
#define OP_RS 0x0003 /* 16b: reg-storage */
|
||||
#define OP_RI1 0x0003 /* 32b: reg-imm 16b */
|
||||
#define OP_RX 0x0004 /* all: reg-mem */
|
||||
#define OP_RXH 0x0005 /* all: reg-mem, rd HW */
|
||||
#define OP_RXF 0x0006 /* 32b: reg-mem, rd FW */
|
||||
#define OP_RI2 0x0007 /* 32b: reg-imm 32b */
|
||||
#define OP_MASK 0x000F
|
||||
|
||||
#define OP_ID4 0x0010 /* 16b: ID4 */
|
||||
#define OP_716 0x0020 /* 16b: 7/16 */
|
||||
#define OP_816 0x0040 /* 16b: 8/16 */
|
||||
#define OP_816E 0x0080 /* 16b: 8/16E */
|
||||
|
||||
#define OP_DPF 0x4000 /* all: hwre FP */
|
||||
#define OP_PRV 0x8000 /* all: privileged */
|
||||
|
||||
#define OP_TYPE(x) (decrom[(x)] & OP_MASK)
|
||||
#define OP_DPFP(x) (decrom[(x)] & OP_DPF)
|
||||
|
||||
/* Device information block */
|
||||
|
||||
struct interdib {
|
||||
uint32 dno; /* device number */
|
||||
int32 sch; /* sch */
|
||||
uint32 irq; /* interrupt */
|
||||
uint8 *tplte; /* template */
|
||||
uint32 (*iot)(uint32 d, uint32 o, uint32 dat);
|
||||
void (*ini)(t_bool f); };
|
||||
|
||||
typedef struct interdib DIB;
|
||||
|
||||
#define TPL_END 0xFF /* template end */
|
||||
|
||||
/* Device select return codes */
|
||||
|
||||
#define BY 0 /* 8b only */
|
||||
#define HW 1 /* 8b/16b */
|
||||
|
||||
/* I/O operations */
|
||||
|
||||
#define IO_ADR 0x0 /* address select */
|
||||
#define IO_RD 0x1 /* read byte */
|
||||
#define IO_RH 0x2 /* read halfword */
|
||||
#define IO_WD 0x3 /* write byte */
|
||||
#define IO_WH 0x4 /* write halfword */
|
||||
#define IO_OC 0x5 /* output command */
|
||||
#define IO_SS 0x6 /* sense status */
|
||||
|
||||
/* Device command byte */
|
||||
|
||||
#define CMD_V_INT 6 /* interrupt control */
|
||||
#define CMD_M_INT 0x3
|
||||
#define CMD_IENB 1 /* enable */
|
||||
#define CMD_IDIS 2 /* disable */
|
||||
#define CMD_IDSA 3 /* disarm */
|
||||
#define CMD_GETINT(x) (((x) >> CMD_V_INT) & CMD_M_INT)
|
||||
|
||||
/* Device status byte */
|
||||
|
||||
#define STA_BSY 0x8 /* busy */
|
||||
#define STA_EX 0x4 /* examine status */
|
||||
#define STA_EOM 0x2 /* end of medium */
|
||||
#define STA_DU 0x1 /* device unavailable */
|
||||
|
||||
/* Default device numbers */
|
||||
|
||||
#define DEV_LOW 0x01 /* lowest intr dev */
|
||||
#define DEV_MAX 0xFF /* highest intr dev */
|
||||
#define DEVNO (DEV_MAX + 1) /* number of devices */
|
||||
#define d_DS 0x01 /* display, switches */
|
||||
#define d_TT 0x02 /* teletype */
|
||||
#define d_PT 0x03 /* reader */
|
||||
#define d_CD 0x04 /* card reader */
|
||||
#define d_TTP 0x10 /* PAS as console */
|
||||
#define d_PAS 0x10 /* first PAS */
|
||||
#define o_PASX 0x01 /* offset to xmt */
|
||||
#define d_LPT 0x62 /* line printer */
|
||||
#define d_PIC 0x6C /* interval timer */
|
||||
#define d_LFC 0x6D /* line freq clk */
|
||||
#define d_DPC 0xB6 /* disk controller */
|
||||
#define o_DP0 0x10
|
||||
#define o_DPF 0x01 /* offset to fixed */
|
||||
#define d_FD 0xC1 /* floppy disk */
|
||||
#define d_MT 0xC5 /* magtape */
|
||||
#define o_MT0 0x10
|
||||
#define d_SCH 0xF0 /* selector chan */
|
||||
#define d_IDC 0xFB /* MSM disk ctrl */
|
||||
#define o_ID0 0x01
|
||||
|
||||
/* Interrupts
|
||||
|
||||
To make interrupt flags independent of device numbers, each device is
|
||||
assigned an interrupt flag in one of four interrupt words
|
||||
|
||||
word 0 DMA devices
|
||||
word 1 programmed I/O devices
|
||||
word 2-3 PAS devices
|
||||
|
||||
Devices are identified by a level and a bit within a level. Priorities
|
||||
run low to high in the array, right to left within words
|
||||
*/
|
||||
|
||||
#define INTSZ 4 /* interrupt words */
|
||||
#define SCH_NUMCH 4 /* #channels */
|
||||
#define ID_NUMDR 4 /* # MSM drives */
|
||||
#define DP_NUMDR 4 /* # DPC drives */
|
||||
#define MT_NUMDR 4 /* # MT drives */
|
||||
|
||||
/* Word 0, DMA devices */
|
||||
|
||||
#define i_SCH 0 /* highest priority */
|
||||
#define i_IDC (i_SCH + SCH_NUMCH) /* MSM disk ctrl */
|
||||
#define i_DPC (i_IDC + ID_NUMDR + 1) /* cartridge disk ctrl */
|
||||
#define i_MT (i_DPC + DP_NUMDR + 1) /* magtape */
|
||||
|
||||
#define l_SCH 0
|
||||
#define l_IDC 0
|
||||
#define l_DPC 0
|
||||
#define l_MT 0
|
||||
|
||||
#define v_SCH (l_SCH * 32) + i_SCH
|
||||
#define v_IDC (l_IDC * 32) + i_IDC
|
||||
#define v_DPC (l_DPC * 32) + i_DPC
|
||||
#define v_MT (l_MT * 32) + i_MT
|
||||
|
||||
/* Word 1, programmed I/O devices */
|
||||
|
||||
#define i_PIC 0 /* precision clock */
|
||||
#define i_LFC 1 /* line clock */
|
||||
#define i_FD 2 /* floppy disk */
|
||||
#define i_CD 3 /* card reader */
|
||||
#define i_LPT 4 /* line printer */
|
||||
#define i_PT 5 /* paper tape */
|
||||
#define i_TT 6 /* teletype */
|
||||
#define i_DS 7 /* display */
|
||||
#define i_TTP 10 /* PAS console */
|
||||
|
||||
#define l_PIC 1
|
||||
#define l_LFC 1
|
||||
#define l_FD 1
|
||||
#define l_CD 1
|
||||
#define l_LPT 1
|
||||
#define l_PT 1
|
||||
#define l_TT 1
|
||||
#define l_DS 1
|
||||
#define l_TTP 1
|
||||
|
||||
#define v_PIC (l_PIC * 32) + i_PIC
|
||||
#define v_LFC (l_LFC * 32) + i_LFC
|
||||
#define v_FD (l_FD * 32) + i_FD
|
||||
#define v_CD (l_CD * 32) + i_CD
|
||||
#define v_LPT (l_LPT * 32) + i_LPT
|
||||
#define v_PT (l_PT * 32) + i_PT
|
||||
#define v_TT (l_TT * 32) + i_TT
|
||||
#define v_DS (l_DS * 32) + i_DS
|
||||
#define v_TTP (l_TTP * 32) + i_TTP
|
||||
|
||||
/* Word 2-3, PAS devices */
|
||||
|
||||
#define i_PAS 0
|
||||
#define l_PAS 2
|
||||
#define v_PAS (l_PAS * 32) + i_PAS
|
||||
#define v_PASX (v_PAS + 1) /* offset to xmt */
|
||||
|
||||
/* I/O macros */
|
||||
|
||||
#define SET_INT(v) int_req[(v) >> 5] = int_req[(v) >> 5] | (1u << ((v) & 0x1F))
|
||||
#define CLR_INT(v) int_req[(v) >> 5] = int_req[(v) >> 5] & ~(1u << ((v) & 0x1F))
|
||||
#define SET_ENB(v) int_enb[(v) >> 5] = int_enb[(v) >> 5] | (1u << ((v) & 0x1F))
|
||||
#define CLR_ENB(v) int_enb[(v) >> 5] = int_enb[(v) >> 5] & ~(1u << ((v) & 0x1F))
|
||||
|
||||
#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */
|
||||
|
||||
/* Device accessible macro */
|
||||
|
||||
#define DEV_ACC(d) (dev_tab[d] && !sch_blk (d))
|
||||
|
||||
/* Automatic I/O channel programs, 16b */
|
||||
|
||||
#define CCB16_CHN -4 /* chain */
|
||||
#define CCB16_DEV -2 /* dev no */
|
||||
#define CCB16_STS -1 /* status */
|
||||
#define CCB16_CCW 0 /* cmd wd */
|
||||
#define CCB16_STR 2 /* start */
|
||||
#define CCB16_END 4 /* end */
|
||||
#define CCB16_IOC 6 /* OC byte */
|
||||
#define CCB16_TRM 7 /* term byte */
|
||||
|
||||
#define CCW16_INIT 0x8000 /* init */
|
||||
#define CCW16_NOP 0x4000 /* nop */
|
||||
#define CCW16_V_FNC 12 /* function */
|
||||
#define CCW16_M_FNC 0x3
|
||||
#define CCW16_FNC(x) (((x) >> CCW16_V_FNC) & CCW16_M_FNC)
|
||||
#define CCW16_RD 0 /* read */
|
||||
#define CCW16_WR 1 /* write */
|
||||
#define CCW16_DMT 2 /* dec mem */
|
||||
#define CCW16_NUL 3 /* null */
|
||||
#define CCW16_TRM 0x0400 /* term char */
|
||||
#define CCW16_Q 0x0200 /* queue */
|
||||
#define CCW16_HI 0x0100 /* queue hi */
|
||||
#define CCW16_OC 0x0080 /* OC */
|
||||
#define CCW16_CHN 0x0020 /* chain */
|
||||
#define CCW16_CON 0x0010 /* continue */
|
||||
#define CCW16_V_BPI 0 /* bytes per int */
|
||||
#define CCW16_M_BPI 0xF
|
||||
#define CCW16_BPI(x) (((x) >> CCW16_V_BPI) & CCW16_M_BPI)
|
||||
|
||||
/* Automatic I/O channel programs, 32b */
|
||||
|
||||
#define CCB32_CCW 0 /* cmd wd */
|
||||
#define CCB32_B0C 2 /* buf 0 cnt */
|
||||
#define CCB32_B0E 4 /* buf 0 end */
|
||||
#define CCB32_CHK 8 /* check word */
|
||||
#define CCB32_B1C 10 /* buf 1 cnt */
|
||||
#define CCB32_B1E 12 /* buf 1 end */
|
||||
#define CCB32_TAB 16 /* trans table */
|
||||
#define CCB32_SUB 20 /* subroutine */
|
||||
|
||||
#define CCW32_V_STA 8 /* status */
|
||||
#define CCW32_M_STA 0xFF
|
||||
#define CCW32_STA(x) (((x) >> CCW32_V_STA) & CCW32_M_STA)
|
||||
#define CCW32_EXE 0x80 /* execute */
|
||||
#define CCW32_CRC 0x10
|
||||
#define CCW32_B1 0x08 /* buffer 1 */
|
||||
#define CCW32_WR 0x04 /* write */
|
||||
#define CCW32_TL 0x02 /* translate */
|
||||
#define CCW32_FST 0x01 /* fast mode */
|
||||
|
||||
/* MAC, 32b */
|
||||
|
||||
#define P 0 /* physical */
|
||||
#define VE 1 /* virtual inst */
|
||||
#define VR 2 /* virtual read */
|
||||
#define VW 3 /* virtual write */
|
||||
|
||||
#define MAC_BASE 0x300 /* MAC base */
|
||||
#define MAC_STA 0x340 /* MAC status */
|
||||
#define MAC_LNT 16
|
||||
#define VA_V_OFF 0 /* offset */
|
||||
#define VA_M_OFF 0xFFFF
|
||||
#define VA_GETOFF(x) (((x) >> VA_V_OFF) & VA_M_OFF)
|
||||
#define VA_V_SEG 16 /* segment */
|
||||
#define VA_M_SEG 0xF
|
||||
#define VA_GETSEG(x) (((x) >> VA_V_SEG) & VA_M_SEG)
|
||||
|
||||
#define SRF_MASK 0x000FFF00 /* base mask */
|
||||
#define SRL_MASK 0x0FF00000 /* limit mask */
|
||||
#define GET_SRL(x) ((((x) & SRL_MASK) >> 12) + 0x100)
|
||||
#define SR_EXP 0x80 /* execute prot */
|
||||
#define SR_WPI 0x40 /* wr prot int */
|
||||
#define SR_WRP 0x20 /* wr prot */
|
||||
#define SR_PRS 0x10 /* present */
|
||||
#define SR_MASK (SRF_MASK|SRL_MASK|SR_EXP|SR_WPI|SR_WRP|SR_PRS)
|
||||
|
||||
#define MACS_L 0x10 /* limit viol */
|
||||
#define MACS_NP 0x08 /* not present */
|
||||
#define MACS_WP 0x04 /* write prot */
|
||||
#define MACS_WI 0x02 /* write int */
|
||||
#define MACS_EX 0x01 /* exec prot */
|
||||
|
||||
/* Miscellaneous */
|
||||
|
||||
#define TMR_LFC 0 /* LFC = timer 0 */
|
||||
#define TMR_PIC 1 /* PIC = timer 1 */
|
||||
#define TMR_PAS 2 /* PAS = timer 2 */
|
||||
#define LPT_WIDTH 132
|
||||
#define VFU_LNT 132
|
||||
#define MIN(x,y) (((x) < (y))? (x): (y))
|
||||
#define MAX(x,y) (((x) > (y))? (x): (y))
|
||||
|
||||
/* Logging */
|
||||
|
||||
#define LOG_CPU_I 0x0001 /* instructions */
|
||||
#define LOG_CPU_C 0x0002 /* context change */
|
||||
#define LOG_DP 0x0010
|
||||
#define LOG_IDC 0x0020
|
||||
#define LOG_MT 0x0040
|
||||
#define LOG_FD 0x0080
|
||||
|
||||
#define DBG_LOG(x) (sim_log && (cpu_log & (x)))
|
||||
|
||||
/* Function prototypes */
|
||||
|
||||
int32 int_chg (uint32 irq, int32 dat, int32 arm);
|
||||
int32 io_2b (int32 val, int32 pos, int32 old);
|
||||
uint32 IOReadB (uint32 loc);
|
||||
void IOWriteB (uint32 loc, uint32 val);
|
||||
uint32 ReadF (uint32 loc, uint32 rel);
|
||||
void WriteF (uint32 loc, uint32 val, uint32 rel);
|
||||
uint32 IOReadBlk (uint32 loc, uint32 cnt, uint8 *buf);
|
||||
uint32 IOWriteBlk (uint32 loc, uint32 cnt, uint8 *buf);
|
||||
void sch_adr (uint32 ch, uint32 dev);
|
||||
t_bool sch_actv (uint32 sch, uint32 devno);
|
||||
void sch_stop (uint32 sch);
|
||||
uint32 sch_wrmem (uint32 sch, uint8 *buf, uint32 cnt);
|
||||
uint32 sch_rdmem (uint32 sch, uint8 *buf, uint32 cnt);
|
||||
t_stat set_sch (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat set_dev (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat show_sch (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
t_stat show_dev (FILE *st, UNIT *uptr, int32 val, void *desc);
|
908
Interdata/id_diag.txt
Normal file
908
Interdata/id_diag.txt
Normal file
|
@ -0,0 +1,908 @@
|
|||
Interdata Diagnostics
|
||||
|
||||
Summary
|
||||
|
||||
816E CPU diagnostic, part 1 passed 16b n/a
|
||||
816E CPU diagnostic, part 2 partial 16b n/a
|
||||
Series 16 CPU diagnostic, part 1 passed 16b n/a
|
||||
16b memory diagnostic, part 1 passed 16b n/a
|
||||
16b memory diagnostic, part 2 passed 16b n/a
|
||||
816e extended memory diagnostic passed 16b n/a
|
||||
Series 16 selector channel diagnostic passed 16b n/a
|
||||
32b CPU diagnostic, part 1 n/a passed 32b
|
||||
32b CPU diagnostic, part 2 n/a passed 32b
|
||||
32b CPU diagnostic, part 3 n/a passed 32b
|
||||
32b memory diagnostic, part 1 n/a passed 32b
|
||||
32b memory diagnostic, part 2 n/a passed 32b
|
||||
32b memory diagnostic, part 3 n/a passed 32b
|
||||
32b memory diagnostic 6a, part 1 n/a passed 32b
|
||||
32b memory diagnostic 6a, part 2 n/a passed 32b
|
||||
32b MAC diagnostic, part 1 n/a passed 32b
|
||||
32b MAC diagnostic, part 2 n/a passed 32b
|
||||
Common line printer diagnostic passed 16b passed 32b
|
||||
Common magtape diagnostic passed 16b passed 32b
|
||||
Common 2.5/10MB disk diagnostic passed 16b passed 32b
|
||||
32b MSM disk diagnostic passed 32b
|
||||
Common floppy disk diagnostic passed 16b passed 32b
|
||||
Common clock diagnostic passed 16b passed 32b
|
||||
|
||||
Not tested:
|
||||
- 16b floating point
|
||||
- 32b double precision floating point
|
||||
- IDC
|
||||
- PASLA
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Operating Instructions
|
||||
|
||||
816E CPU diagnostic, part 1
|
||||
|
||||
sim> set cpu 816e
|
||||
sim> att -e pt0 diag.bin
|
||||
sim> br c2
|
||||
sim> boot pt0
|
||||
|
||||
Breakpoint: PC: 00C2 (EXBR R8,R6)
|
||||
|
||||
sim> run 100
|
||||
|
||||
MODEL 8/16E PROCESSOR TEST PART 1 06-211R00
|
||||
CPU
|
||||
* 8D
|
||||
|
||||
ENTER 0 OR 1
|
||||
1
|
||||
NO ERROR
|
||||
|
||||
CPU
|
||||
*
|
||||
|
||||
---
|
||||
816E CPU diagnostic, part 2
|
||||
|
||||
sim> set cpu 816e
|
||||
sim> d tt ttime 1000 ; timing dependency
|
||||
sim> att -e pt0 diag.bin
|
||||
sim> br c2
|
||||
sim> boot pt0
|
||||
|
||||
Breakpoint: PC: 00C2 (EXBR R8,R6)
|
||||
|
||||
sim> run 100
|
||||
|
||||
MODEL 8/16E PROCESSOR TEST PART 2 06-212R00
|
||||
CPU
|
||||
* 8D
|
||||
|
||||
SUBTEST
|
||||
|
||||
* (type subtest number)
|
||||
|
||||
Subtests 0, 1, 2, 5, 7, 8, 9 run correctly
|
||||
Subtest 3, 4 cannot be run (initialization, power fail)
|
||||
Subtest 6 cannot be run (hexadecimal display)
|
||||
|
||||
---
|
||||
Series 16 CPU diagnostic, part 1
|
||||
(Central error routine is at 21F4)
|
||||
|
||||
sim> set cpu 816e
|
||||
sim> att -e pt0 diag.bin ; diagnostic
|
||||
sim> br c0
|
||||
sim> boot pt0
|
||||
|
||||
Breakpoint, PC: 00C0 (8800)
|
||||
|
||||
sim> d 234a 0202 ; patch to use
|
||||
sim> d 234c a4a8 ; TTY as console
|
||||
sim> d 17a b1e4
|
||||
sim> run 100
|
||||
|
||||
SERIES SIXTEEN PROCESSOR TEST PART 1 06-242F01R00
|
||||
CPU
|
||||
* 2D
|
||||
ENTER 0 OR 1
|
||||
1
|
||||
|
||||
1234567890
|
||||
|
||||
NO ERROR
|
||||
|
||||
000A 0000
|
||||
|
||||
CPU
|
||||
*
|
||||
|
||||
---
|
||||
16b memory diagnostic, part 1
|
||||
|
||||
sim> att -e pt0 diag.bin ; diagnostic
|
||||
sim> br c2
|
||||
sim> boot pt0
|
||||
|
||||
Breakpoint, PC: 00C2 (EPSR R7,R6)
|
||||
|
||||
sim> run 100
|
||||
|
||||
02-340 PART 1 06-162F01R01
|
||||
|
||||
NO ERRORS
|
||||
|
||||
---
|
||||
16b memory diagnostic, part 2
|
||||
|
||||
sim> att -e pt0 diag.bin ; diagnostic
|
||||
sim> br c2
|
||||
sim> boot pt0
|
||||
|
||||
Breakpoint, PC: 00C2 (EPSR R7,R6)
|
||||
|
||||
sim> run 1000
|
||||
|
||||
02-340 PART 2 06-162F02R01
|
||||
|
||||
NO ERRORS
|
||||
|
||||
---
|
||||
816e extended memory diagnostic, parts 1 and 2
|
||||
|
||||
sim> set cpu 816e
|
||||
sim> set cpu 256k
|
||||
sim> att -e pt0 diag.bin ; diagnostic
|
||||
sim> br b4
|
||||
sim> boot pt0
|
||||
|
||||
Breakpoint, PC: 00B4 (LPSW R0,B8)
|
||||
|
||||
sim> run 1000
|
||||
|
||||
8/16 E EXTENDED MEMORY TEST PART 1 06-221R00
|
||||
NO ERROR
|
||||
* (CR to repeat part 1)
|
||||
8/16 E EXTENDED MEMORY TEST PART 1 06-221R00
|
||||
NO ERROR
|
||||
* (LF to go on to part 2)
|
||||
|
||||
Breakpoint, PC: 00B4 (LPSW R0,B8)
|
||||
sim> run 100
|
||||
|
||||
8/16 E EXTENDED MEMORY TEST PART 2 06-221R00
|
||||
PROGRAM DETECTED MAXIMUM MEMORY 3FFFE
|
||||
*TEST ; standard tests
|
||||
*RUN
|
||||
|
||||
SUBTEST 0 NO ERROR
|
||||
SUBTEST 1 NO ERROR
|
||||
SUBTEST 2 NO ERROR
|
||||
SUBTEST 3 NO ERROR
|
||||
SUBTEST 4 NO ERROR
|
||||
SUBTEST 6 NO ERROR
|
||||
SUBTEST 7 NO ERROR
|
||||
SUBTEST 8 NO ERROR
|
||||
END OF TEST
|
||||
|
||||
*
|
||||
|
||||
---
|
||||
Series 16 selector channel diagnostic
|
||||
|
||||
sim> set cpu 816e
|
||||
sim> set cpu 256k
|
||||
sim> att -e pt0 diag.bin ; diagnostic
|
||||
sim> att mt0 foo.tap ; magtape to test
|
||||
sim> br c0
|
||||
sim> boot pt0
|
||||
|
||||
Breakpoint, PC: 00C0 (LPSW R0,C8)
|
||||
|
||||
sim> d 2e68 2 ; console is TTY
|
||||
sim> run A00
|
||||
|
||||
S16 SELCH TEST 06-222 R01
|
||||
|
||||
TOP OF MEMORY 3 FFFF
|
||||
* IODEV1 C5 ; magtape
|
||||
* DEV1 2
|
||||
* RUN ; bank 0 by default
|
||||
TEST 00
|
||||
|
||||
NO ERROR
|
||||
|
||||
TEST 01
|
||||
|
||||
NO ERROR
|
||||
|
||||
TEST 02
|
||||
|
||||
NO ERROR
|
||||
|
||||
TEST 03
|
||||
|
||||
NO ERROR
|
||||
|
||||
TEST 04
|
||||
|
||||
NO ERROR
|
||||
|
||||
|
||||
* MEMMOD 1 {2,3} ; repeat for banks 1,2,3
|
||||
* RUN
|
||||
TEST 00
|
||||
|
||||
NO ERROR
|
||||
|
||||
TEST 01
|
||||
|
||||
NO ERROR
|
||||
|
||||
TEST 02
|
||||
|
||||
NO ERROR
|
||||
|
||||
TEST 03
|
||||
|
||||
NO ERROR
|
||||
|
||||
TEST 04
|
||||
|
||||
NO ERROR
|
||||
|
||||
*
|
||||
---
|
||||
32b CPU diagnostic, part 1
|
||||
|
||||
sim> att -e mt0 mmd_r07.tap
|
||||
sim> d -b 7f 7 ; file 8 on MMD R07 tape
|
||||
sim> boot mt0
|
||||
|
||||
S32PT1 06-154 R03
|
||||
CPU
|
||||
|
||||
*7X
|
||||
NO ERROR
|
||||
000A 0000
|
||||
*
|
||||
|
||||
---
|
||||
32b CPU diagnostic, part 2
|
||||
|
||||
sim> set tt 7b ; test is parity sensitive
|
||||
sim> att -e mt0 mmd_r07.tap
|
||||
sim> d -b 7f 8 ; file 9 on MMD R07 tape
|
||||
sim> boot mt0
|
||||
|
||||
|
||||
S32PT2R02
|
||||
CPU
|
||||
*
|
||||
7X
|
||||
SUBTEST
|
||||
* (type subtest number)
|
||||
|
||||
Subtests 1, 3, 4, 5, 9 run correctly
|
||||
Subtest 2 cannot be run (7/32 with halfword mode only)
|
||||
Subtest 6 cannot be run (hexadecimal display)
|
||||
Subtests 7,8 cannot be run (initialization, power fail)
|
||||
|
||||
---
|
||||
32b CPU diagnostic, part 3
|
||||
|
||||
sim> att -e mt0 mmd_r07.tap
|
||||
sim> d -b 7f 9 ; file 10 on MMD R07 tape
|
||||
sim> boot mt0
|
||||
|
||||
S32PT3 R01
|
||||
CPU
|
||||
*
|
||||
8X ; 7X denotes 7/32 with halfword mode
|
||||
MAC RESPONSE AT 000300
|
||||
|
||||
SUBTEST
|
||||
*
|
||||
|
||||
Subtests 1, 2, 3 run correctly
|
||||
Subtest 4 cannot be run (parity option)
|
||||
|
||||
---
|
||||
32b memory diagnostic, part 1
|
||||
|
||||
sim> att -e mt0 mmd_r07.tap
|
||||
sim> d -b 7f 17 ; file 24 on MMD R07 tape
|
||||
sim> br 2000
|
||||
sim> boot mt0
|
||||
|
||||
Breakpoint, PC: 02000 (B 2060)
|
||||
sim> d -w 2010 0202 ; console is TTY
|
||||
sim> c
|
||||
|
||||
S32MT1 06-156F01R04
|
||||
MAC PRESENT ? (Y OR N)
|
||||
*
|
||||
Y
|
||||
01
|
||||
02
|
||||
03
|
||||
04
|
||||
05
|
||||
06
|
||||
NO ERROR
|
||||
*
|
||||
|
||||
---
|
||||
32b memory diagnostic, part 2
|
||||
|
||||
sim> att -e mt0 c:\temp\mmd_r07.tap
|
||||
sim> d -b 7f 18 ; file 25 on MMD R07 tape
|
||||
sim> br a00
|
||||
sim> boot mt0
|
||||
|
||||
Breakpoint, PC: 00A00 (B A60)
|
||||
sim> d -w a10 0202 ; console is TTY
|
||||
sim> c
|
||||
|
||||
S32MT2 06-156F02R04
|
||||
AVAILABLE MEMORY
|
||||
000000 - 0FFFFF
|
||||
SUBTEST *
|
||||
0 ; all standard tests
|
||||
01
|
||||
TEST STILL RUNNING ; repeated multiple times
|
||||
:
|
||||
NO ERROR
|
||||
02
|
||||
TEST STILL RUNNING ; repeated multiple times
|
||||
:
|
||||
NO ERROR
|
||||
03
|
||||
TEST STILL RUNNING ; repeated multiple times
|
||||
:
|
||||
NO ERROR
|
||||
04
|
||||
TEST STILL RUNNING ; repeated multiple times
|
||||
:
|
||||
NO ERROR
|
||||
05
|
||||
TEST STILL RUNNING ; repeated multiple times
|
||||
:
|
||||
NO ERROR
|
||||
06
|
||||
TEST STILL RUNNING ; repeated multiple times
|
||||
:
|
||||
NO ERROR
|
||||
07
|
||||
TEST STILL RUNNING ; repeated multiple times
|
||||
:
|
||||
NO ERROR
|
||||
SUBTEST *
|
||||
|
||||
---
|
||||
32b memory diagnostic, part 3
|
||||
|
||||
sim> att -e mt0 c:\temp\mmd_r07.tap
|
||||
sim> d -b 7f 19 ; file 26 on MMD R07 tape
|
||||
sim> br a00
|
||||
sim> boot mt0
|
||||
|
||||
Breakpoint, PC: 00A00 (B A60)
|
||||
sim> d -w a10 0202 ; console is TTY
|
||||
|
||||
sim> c
|
||||
S32MT3 06-156F03R04
|
||||
AVAILABLE MEMORY
|
||||
000000 - 0FFFFF
|
||||
*
|
||||
|
||||
TEST STILL RUNNING ; repeated multiple times
|
||||
:
|
||||
NO ERROR
|
||||
*
|
||||
|
||||
---
|
||||
32b memory diagnostic, 6a, part 1
|
||||
|
||||
sim> att -e mt0 c:\temp\mmd_r07.tap
|
||||
sim> d -b 7f 15 ; file 22 on MMD R07 tape
|
||||
sim> boot mt0
|
||||
|
||||
32 BIT S6A MEMORY TEST 06-157F01R01
|
||||
AVAILABLE MEMORY
|
||||
0000-3FFF
|
||||
|
||||
MAC ADDRESS = 300
|
||||
TYPE= 3 ; any value, 0-4
|
||||
SUBTEST
|
||||
* 0
|
||||
01
|
||||
NO ERROR
|
||||
02
|
||||
NO ERROR
|
||||
03
|
||||
NO ERROR
|
||||
04
|
||||
NO ERROR
|
||||
05
|
||||
NO ERROR
|
||||
06
|
||||
NO ERROR
|
||||
07
|
||||
NO ERROR
|
||||
08
|
||||
NO ERROR
|
||||
|
||||
SUBTEST
|
||||
*
|
||||
|
||||
---
|
||||
32b memory diagnostic, 6a, part 2
|
||||
|
||||
sim> att -e mt0 c:\temp\mmd_r07.tap
|
||||
sim> d -b 7f 16 ; file 23 on MMD R07 tape
|
||||
sim> boot mt0
|
||||
|
||||
32 BIT S6A MEMORY TEST 06-157F02R01
|
||||
AVAILABLE MEMORY
|
||||
0000f-FFFFF
|
||||
|
||||
TYPE= 2 ; any value, 0-4
|
||||
SUBTEST
|
||||
* 0
|
||||
01
|
||||
NO ERROR
|
||||
02
|
||||
NO ERROR
|
||||
03
|
||||
NO ERROR
|
||||
04
|
||||
NO ERROR
|
||||
05
|
||||
NO ERROR
|
||||
06
|
||||
NO ERROR
|
||||
07
|
||||
NO ERROR
|
||||
08
|
||||
NO ERROR
|
||||
|
||||
SUBTEST
|
||||
*
|
||||
|
||||
---
|
||||
32b MAC diagnostic, part 1
|
||||
|
||||
sim> att -e mt0 c:\temp\mmd_r07.tap
|
||||
sim> d -b 7f 24 ; file 37 on MMD R07 tape
|
||||
sim> boot mt0
|
||||
|
||||
MACT 06-160F01R03
|
||||
AVAILABLE MEMORY
|
||||
00000- FFFFF
|
||||
|
||||
* RUN
|
||||
TEST 00 NO ERROR
|
||||
TEST 01 NO ERROR
|
||||
TEST 02 NO ERROR
|
||||
TEST 03 NO ERROR
|
||||
TEST 04 NO ERROR
|
||||
TEST 05 NO ERROR
|
||||
TEST 06 NO ERROR
|
||||
TEST 07 NO ERROR
|
||||
TEST 08 NO ERROR
|
||||
TEST 09 NO ERROR
|
||||
TEST 0B NO ERROR
|
||||
*
|
||||
|
||||
---
|
||||
sim> att -e mt0 c:\temp\mmd_r07.tap
|
||||
sim> d -b 7f 25 ; file 38 on MMD R07 tape
|
||||
sim> br ffd0 ; start != load point
|
||||
sim> boot mt0
|
||||
|
||||
Breakpoint, PC: 0FFD0 (B 1093E)
|
||||
|
||||
sim> run 10010
|
||||
|
||||
MACT 06-160F02R03
|
||||
|
||||
* RUN
|
||||
TEST 00 NO ERROR
|
||||
TEST 01 NO ERROR
|
||||
TEST 02 NO ERROR
|
||||
TEST 03 NO ERROR
|
||||
TEST 04 NO ERROR
|
||||
TEST 05 NO ERROR
|
||||
TEST 06 NO ERROR
|
||||
TEST 07 NO ERROR
|
||||
TEST 08 NO ERROR
|
||||
*
|
||||
|
||||
---
|
||||
Common line printer diagnostic
|
||||
|
||||
sim> att -e pt0 diag.bin
|
||||
sim> br c2
|
||||
sim> boot pt0
|
||||
|
||||
Breakpoint: PC: 00C2 (EXBR R8,R6)
|
||||
|
||||
sim> run a00 ; 32b
|
||||
sim> run a04 ; 16b
|
||||
|
||||
COMMON LINE PRINTER TEST 06-170R02
|
||||
|
||||
*TEST 0,1,2,3
|
||||
*RUN
|
||||
|
||||
TEST 00
|
||||
NO ERROR
|
||||
TEST 01
|
||||
NO ERROR
|
||||
TEST 02
|
||||
NO ERROR
|
||||
TEST 03
|
||||
NO ERROR
|
||||
END OF TEST
|
||||
|
||||
*INTRPT 1
|
||||
*RUN
|
||||
|
||||
TEST 00
|
||||
NO ERROR
|
||||
TEST 01
|
||||
NO ERROR
|
||||
TEST 02
|
||||
NO ERROR
|
||||
TEST 03
|
||||
NO ERROR
|
||||
END OF TEST
|
||||
|
||||
*
|
||||
|
||||
---
|
||||
Common magtape diagnostic
|
||||
|
||||
sim> set mt dev=85 ; 800 bpi default
|
||||
sim> att -e pt0 diag.bin
|
||||
sim> br c4
|
||||
sim> boot pt0
|
||||
|
||||
Breakpoint, PC: 00C4 (EXBR R8,R6)
|
||||
|
||||
sim> run a00 ; 32b
|
||||
sim> run a04 ; 16b
|
||||
|
||||
COMMON MAGNETIC TAPE TEST PROGRAM 06-172R02
|
||||
|
||||
*TEST 0,1,2,3,4,5
|
||||
*MODE 0 ; prog i/o and selch
|
||||
*RUN
|
||||
|
||||
*MODE 0
|
||||
*RUN
|
||||
|
||||
TEST 00
|
||||
NO ERROR
|
||||
TEST 01
|
||||
NO ERROR
|
||||
TEST 02
|
||||
NO ERROR
|
||||
TEST 03
|
||||
NO ERROR
|
||||
TEST 04
|
||||
NO ERROR
|
||||
TEST 05
|
||||
NO ERROR
|
||||
END OF TEST
|
||||
|
||||
*
|
||||
|
||||
---
|
||||
Common 2.5/10MB disk diagnostic
|
||||
|
||||
sim> att -e pt0 diag.bin
|
||||
sim> br c2
|
||||
sim> boot pt0
|
||||
|
||||
Breakpoint, PC: 00C2 (EXBR R8,R6)
|
||||
|
||||
sim> set dp0 5440
|
||||
sim> set dp1 5440
|
||||
sim> att dp0 test0.dsk
|
||||
sim> att dp1 test1.dsk
|
||||
sim> run a00 ; 32b
|
||||
sim> run a04 ; 16b
|
||||
|
||||
COMMON DISC TEST 06-173R01F01
|
||||
|
||||
*FILE 2 ; FILE 1 to test fixed platter
|
||||
*LOCYL 0
|
||||
*HICYL 197
|
||||
*TIMCON 1C0
|
||||
*TEST 0,1,2,3,4,6,7,8,9,A,C ; test 5 requires format capability
|
||||
; test B requires manual intervention
|
||||
*RUN
|
||||
|
||||
TEST 00
|
||||
NO ERROR
|
||||
TEST 01
|
||||
NO ERROR
|
||||
TEST 02
|
||||
NO ERROR
|
||||
TEST 03
|
||||
NO ERROR
|
||||
TEST 04
|
||||
NO ERROR
|
||||
TEST 06
|
||||
NO ERROR
|
||||
TEST 07
|
||||
NO ERROR
|
||||
TEST 08
|
||||
NO ERROR
|
||||
TEST 09
|
||||
NO ERROR
|
||||
TEST 0A
|
||||
NO ERROR
|
||||
TEST 0C
|
||||
NO ERROR
|
||||
END OF TEST
|
||||
|
||||
*
|
||||
|
||||
---
|
||||
32b MSM disk diagnostic
|
||||
|
||||
sim> att -e mt0 c:\temp\mmd_r07.tap
|
||||
sim> d -b 7f 45 ; file 70 on MMD R07 tape
|
||||
sim> br a00
|
||||
sim> boot mt0
|
||||
|
||||
Breakpoint, PC: 00A00 (B A5E)
|
||||
|
||||
sim> d -w a10 0101 ; patch for TTY console
|
||||
sim> att dm0 foo.dsk
|
||||
sim> att dm1 foo1.dsk
|
||||
sim> c
|
||||
|
||||
MSM DISC TEST 06-200F02R04 (32-BIT)
|
||||
|
||||
*LOCYL 0
|
||||
*HICYL 336 ; tests 8,9,A will run a very long
|
||||
; time, use 40 to shorten test
|
||||
*DRIVE 0
|
||||
*PACTYP 0
|
||||
*TIMVAL 14D
|
||||
*XFILE 1
|
||||
*TEST 0,1,2,3,4,6,7,8,9,A,C ; test 5 requires format capability
|
||||
; test B requires manual intervention
|
||||
*RUN
|
||||
|
||||
TEST 00
|
||||
TEST 01
|
||||
TEST 02
|
||||
TEST 03
|
||||
TEST 04
|
||||
TEST 06
|
||||
TEST 07
|
||||
TEST 08
|
||||
TEST 09
|
||||
TEST 0A
|
||||
TEST 0C
|
||||
|
||||
---
|
||||
Common floppy disk diagnostic
|
||||
|
||||
sim> att -e pt0 diag.bin
|
||||
sim> att fd0 foo0.flp
|
||||
sim> att fd1 foo1.flp
|
||||
sim> br b8
|
||||
sim> boot pt0
|
||||
|
||||
Breakpoint, PC: 000B8 (BS B2)
|
||||
|
||||
sim> d 2a72 bal r15,320a ; patch for multidrive test
|
||||
sim> run a00 ; 32b
|
||||
sim> run a04 ; 16b
|
||||
|
||||
COMMON FLOPPY DISC TEST 06-198R00
|
||||
UNPROTECT DISKETTE
|
||||
|
||||
*DRIVE AB
|
||||
*RUN
|
||||
|
||||
DRIVE A UNDER TEST
|
||||
TEST 00
|
||||
NO ERROR
|
||||
TEST 01
|
||||
NO ERROR
|
||||
TEST 02
|
||||
NO ERROR
|
||||
TEST 03
|
||||
NO ERROR
|
||||
TEST 04
|
||||
NO ERROR
|
||||
TEST 05
|
||||
NO ERROR
|
||||
TEST 06
|
||||
NO ERROR
|
||||
TEST 07
|
||||
NO ERROR
|
||||
DRIVE B UNDER TEST
|
||||
TEST 00
|
||||
NO ERROR
|
||||
TEST 01
|
||||
NO ERROR
|
||||
TEST 02
|
||||
NO ERROR
|
||||
TEST 03
|
||||
NO ERROR
|
||||
TEST 04
|
||||
NO ERROR
|
||||
TEST 05
|
||||
NO ERROR
|
||||
TEST 06
|
||||
NO ERROR
|
||||
TEST 07
|
||||
NO ERROR
|
||||
END OF TEST
|
||||
|
||||
*TEST 9 ; test 8 requires formatting
|
||||
*RUN
|
||||
|
||||
TEST 09
|
||||
NO ERROR
|
||||
END OF TEST
|
||||
|
||||
*
|
||||
|
||||
---
|
||||
Common clock diagnostic
|
||||
|
||||
sim> att -e pt0 diag.bin
|
||||
sim> br c4
|
||||
sim> boot pt0
|
||||
|
||||
Breakpoint, PC: 00C4 (EXBR R8,R6)
|
||||
|
||||
sim> d -w e28 4300 ; R09 patches
|
||||
sim> d -w e2a 10f4
|
||||
sim> id -w 10f4:110a
|
||||
10f4: 4840
|
||||
10f6: 188a
|
||||
10f8: 4850
|
||||
10fa: 188c
|
||||
10fc: de40
|
||||
10fe: 1eaf
|
||||
1100: de50
|
||||
1102: 1eaf
|
||||
1104: 4810
|
||||
1106: 0a24
|
||||
1108: 4300
|
||||
1110: 0e2c
|
||||
sim> d 1b9c bs 1ba6
|
||||
sim> d -w 1102 1eaf
|
||||
|
||||
sim> run a00 ; 32b
|
||||
sim> run a04 ; 16b
|
||||
|
||||
COMMON UNIVERSAL CLOCK MODULE TEST 06-133R05
|
||||
|
||||
*TIMVAL 1A4 ; simulator is a fast CPU
|
||||
*RUN
|
||||
|
||||
TEST 00
|
||||
NO ERROR
|
||||
TEST 01
|
||||
NO ERROR
|
||||
TEST 02
|
||||
NO ERROR
|
||||
TEST 03
|
||||
NO ERROR
|
||||
TEST 04
|
||||
NO ERROR
|
||||
TEST 05
|
||||
NO ERROR
|
||||
TEST 06
|
||||
NO ERROR
|
||||
TEST 07
|
||||
NO ERROR
|
||||
END OF TEST
|
||||
|
||||
*
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Bugs found
|
||||
|
||||
1. CPU16: instruction decoding interpreting CPU models incorrectly
|
||||
2. CPU16: SINT should not be conditional on device existing
|
||||
3. CPU16: immediate interrupts do not do a PSW swap, new PC is block+6
|
||||
4. CPU16: SLA, SLHA setting C incorrectly
|
||||
5. CPU16: diagnostic requires 816E extended memory to run
|
||||
6. CPU16: CCW16_OC defined incorrectly
|
||||
7. CPU16, CPU32: autoload not fetching or outputing OC
|
||||
8. CPU16, CPU32: block I/O completion is off by 1
|
||||
9. CPU16, CPU32: ESPR broken, EPSR rx,rx should copy PSW to rx
|
||||
10. CPU16, CPU32: PCQ displays in octal instead of hexadecimal
|
||||
11. CPU16, CPU32: SH and variations overflow calculation wrong
|
||||
12. CPU16, CPU32: SCH overflow calculation wrong
|
||||
13. CPU16, CPU32: CH and CLH overflow calculation wrong
|
||||
14. CPU16, CPU32: CH or'ing into CC's instead of loading
|
||||
15. CPU16, CPU32: RD, RH, SS, AI store some data on non-existent device
|
||||
16. CPU16, CPU32: console interrupt not implemented
|
||||
17. CPU16, CPU32: SRHL(s) setting C incorrectly
|
||||
18. CPU16, CPU32: WDR, OCR not masking register data to 8b
|
||||
19. CPU32: WH not masking data to 8b or 16b as required
|
||||
20. CPU32: 32b register sets ordered incorrectly in memory
|
||||
21. CPU32: wrong slot length in queue instructions
|
||||
22. CPU32: display device missing its interrupt declaration
|
||||
23. CPU32: LPSW(R) must load PC before changing PSW
|
||||
24. CPU32: SLL setting C incorrectly
|
||||
25. CPU32: bit instructions use halfword memory access and offsets
|
||||
26. CPU32: CRC sign-extending rather than zero-extending operands
|
||||
27. CPU32: SCP incrementing counts before, not after, transfer
|
||||
28. CPU32: CHVR not implemented
|
||||
29. CPU32: M(R) algorithm wrong
|
||||
30. CPU32: M(R) using wrong register as first operand
|
||||
31. CPU32: memory accesses were fullword rather than halfword aligned
|
||||
32. CPU32: D(R) overflow calculation incorrect
|
||||
33. CPU32: on 7/32, exceptions use register set 0, regardless of new PSW
|
||||
34. CPU32: system queue PSW location misdefined
|
||||
35. CPU32: autodriver channel not shifting bytes left before use as
|
||||
translation table index
|
||||
36. CPU32: MAC, LRA using wrong value for limit test
|
||||
37. CPU32: LRA using wrong value for segment base
|
||||
38. CPU32: MAC registers are accessible only if protection is off
|
||||
39. CPU32: MAC status clears only on write, not read
|
||||
40. CPU32: MAC write protect abort and interrupts implemented incorrectly
|
||||
41. CPU32: ex/dep -v test used & instead of &&
|
||||
42. CPU32: fetch tests for MAC abort at end of fetch, not per halfword
|
||||
43. FP: unpack and pack detecting RR format incorrectly
|
||||
44. FP: need separate microcode/hardware algorithms for add/sub denormalization
|
||||
45. FP: multiply and divide have 'early out' detection of overflow/underflow
|
||||
46. FP: compare less than not setting C
|
||||
47. FP: fix overflow not setting V
|
||||
48. FP: fix shift needed to be hex digits not binary digits
|
||||
49. IO: interrupt evaluation routine never sets an interrupt
|
||||
50. SELCH: transfer count calculation off by 1
|
||||
51. SELCH: device data structure set up incorrectly (reset routine)
|
||||
52. SELCH: stop clears pending interrupts
|
||||
53. SELCH: register load algorithm incorrect for 6 byte loads
|
||||
54. PT, LPT, FD: OR'ing status mask instead of AND'ing
|
||||
55. PT, TT: SET_INT on status change not conditioned on interrupt armed
|
||||
56. TT: input char converted to UC incorrectly
|
||||
57. TT: need SET TT BREAK to run CPU test part 2
|
||||
58. LPT: not clearing spacing done
|
||||
59. MT: WREOF not setting EOF status
|
||||
60. MT: CMD register pointer to wrong place
|
||||
61. MT: write record byte count taken from wrong variable
|
||||
62. MT: overrun processing incorrect for selector channel mode
|
||||
63. PIC, LFC: write data and overflow detection incorrect
|
||||
64. PIC, LFC: interpolation algorithm for cic read incorrect
|
||||
65. PIC, LFC: ric reloaded from output buffer on count overflow
|
||||
66. PIC, LFC: added diagnostic mode, revised use of count vs timer
|
||||
67. DP: track increment algorithm incorrect
|
||||
68. DP,IDC: incorrectly setting overrun for less than full sector reads
|
||||
69. DP: should interrupt on detach (offline)
|
||||
70. FD: high water mark not updated on write
|
||||
71. FD: deleted data not implemented, required for diagnostic
|
||||
72. FD: header CRC not implemented, required for diagnostic
|
||||
73. FD: function code not stored for service routine
|
||||
74. FD: LRN to track and sector conversions incorrect
|
||||
75. FD: reset status incorrect (should be not busy, LRN = 1)
|
||||
76. FD: extended status track 0 calculation wrong
|
||||
77. FD: reset does not clear interrupts, requires delay
|
||||
78. FD: read/write sequencing incorrect
|
||||
79. FD: command without write data uses implicit LRN
|
||||
80. FD: extended status is per drive not per controller
|
||||
81. FD: command start clears only extended status bytes 0,1
|
||||
82. FD: IDLE sets after BUSY drops and generates a separate interrupt
|
||||
83. SYS16, SYS32: WH mistyped as WD in symbol table
|
||||
84. SYS32: MHR, DHR misdefined
|
||||
85. PAS: busy set instead of cleared initially
|
||||
86. IDC: busy set instead of cleared initially
|
||||
87. IDC, DP: busy not cleared at transfer command complete
|
||||
88. IDC: busy is not cleared at drive command complete
|
||||
89. IDC: for MSM compatibility, must absorb WH of head/cylinder
|
||||
90. IDC: drive command 0x30 is an instant NOP
|
||||
91. IDC: set cylinder with invalid cylinder sets SKI
|
||||
92. IDC: read with invalid head sets ACF, not DTE
|
||||
|
960
Interdata/id_doc.txt
Normal file
960
Interdata/id_doc.txt
Normal file
|
@ -0,0 +1,960 @@
|
|||
To: Users
|
||||
From: Bob Supnik
|
||||
Subj: Interdata 16b/32b Simulator Usage
|
||||
Date: 15-Jan-2003
|
||||
|
||||
COPYRIGHT NOTICE
|
||||
|
||||
The following copyright notice applies to both the SIMH source and binary:
|
||||
|
||||
Original code published in 1993-2002, written by Robert M Supnik
|
||||
Copyright (c) 1993-2003, 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 memorandum documents the Interdata 16b and 32b simulators.
|
||||
|
||||
|
||||
1. Simulator Files
|
||||
|
||||
sim/ sim_defs.h
|
||||
sim_rev.h
|
||||
sim_sock.h
|
||||
sim_tmxr.h
|
||||
scp.c
|
||||
scp_tty.c
|
||||
sim_sock.c
|
||||
sim_tmxr.c
|
||||
|
||||
sim/interdata/ id_defs.h
|
||||
id16_cpu.c [or id32_cpu.c]
|
||||
id16_dboot.c [or id32_dboot.c]
|
||||
id_dp.c
|
||||
id_fd.c
|
||||
id_fp.c
|
||||
id_idc.c
|
||||
id_io.c
|
||||
id_lp.c
|
||||
id_mt.c
|
||||
id_pas.c
|
||||
id_pt.c
|
||||
id_tt.c
|
||||
id_ttp.c
|
||||
id_uvc.c
|
||||
id16_sys.c [or id32_sys.c]
|
||||
|
||||
2. Interdata Features
|
||||
|
||||
The Interdata simulator includes simulators for a variety of 16b (I3, I4,
|
||||
I5, 70, 80, 7/16, 8/16, 8/16E) and 32b (7/32, 8/32) models. This is by
|
||||
no means a complete sampling of all the variations in the Interdata/Perkin-
|
||||
Elmer family. The 32b family included options for special communications
|
||||
instructions (7/32C, 8/32C), as well as a later extension for virtual
|
||||
memory (3200 series).
|
||||
|
||||
The Interdata simulator is configured as follows:
|
||||
|
||||
device simulates
|
||||
name(s)
|
||||
|
||||
CPU - 16b Interdata 3, 4, 5, 70, 80, 7/16, or 8/16 CPU with 64KB memory
|
||||
Interdata 8/16E CPU with 256KB memory
|
||||
CPU - 32b Interdata 7/32 or 8/32 CPU with 1MB memory
|
||||
SELCH selector channel (1-4)
|
||||
PT paper tape reader/punch
|
||||
TT console terminal, Teletype interface
|
||||
TTP console terminal, PASLA interface
|
||||
LFC line frequency clock
|
||||
PIC programmable interval clock
|
||||
LPT line printer
|
||||
FD floppy disk
|
||||
DP 2.5MB/10MB cartridge disk
|
||||
DM mass storage module (MSM)/intelligent (IDC) disk controller
|
||||
MT magnetic tape
|
||||
PAS programmable asynchronous line controller
|
||||
PASL programmable asyhchronous lines, up to 32
|
||||
|
||||
The Interdata simulator implements two unique stop conditions:
|
||||
|
||||
- decode of an undefined instruction, and STOP_INST is set
|
||||
- runaway carriage control tape in the line printer.
|
||||
|
||||
The LOAD command is used to load a carriage control tape for the line
|
||||
printer. The DUMP command is used to dump a contiguous portion of
|
||||
memory as a self-loading bootstrap paper tape. The syntax for the DUMP
|
||||
command is:
|
||||
|
||||
DUMP <filename> lowaddr-highaddr
|
||||
|
||||
The low address must be greater than or equal to X'D0'.
|
||||
|
||||
Devices are assigned their default device numbers, as documented in the
|
||||
Interdata literature. Device numbers can be changed by the command:
|
||||
|
||||
SET <device> DEVNO=num
|
||||
|
||||
Device number conflicts are not checked until simulation starts. If
|
||||
there is a device number conflict, simulation stops immediately with
|
||||
an error message.
|
||||
|
||||
Selector channel devices are assigned by default to selector channel 0.
|
||||
Selector channel assignments can be changed by the command:
|
||||
|
||||
SET <dev> SELCH=num
|
||||
|
||||
Selector channel assignments cannot introduce conflicts.
|
||||
|
||||
Most devices can be disabled and enabled, with the commands:
|
||||
|
||||
SET <dev> DISABLED
|
||||
SET <dev> ENABLED
|
||||
|
||||
All devices are enabled by default.
|
||||
|
||||
2.1 CPU (16b)
|
||||
|
||||
The CPU options include memory size and CPU type:
|
||||
|
||||
SET CPU I3 Interdata 3 (base instruction set)
|
||||
SET CPU I4 Interdata 4 (base plus single precision
|
||||
floating point)
|
||||
SET CPU 716 Interdata 7/16 (extended instruction set)
|
||||
(equivalent to Models 5, 70, and 80)
|
||||
SET CPU 816 Interdata 8/16 (extended plus double
|
||||
precision floating point)
|
||||
SET CPU 816E Interdata 8/16E (extended plus double
|
||||
precision plus expanded memory)
|
||||
SET CPU 8K set memory size = 8KB
|
||||
SET CPU 16K set memory size = 16KB
|
||||
SET CPU 24K set memory size = 24KB
|
||||
SET CPU 32K set memory size = 32KB
|
||||
SET CPU 48K set memory size = 48KB
|
||||
SET CPU 64K set memory size = 64KB
|
||||
SET CPU 128K set memory size = 128KB (8/16E only)
|
||||
SET CPU 256K set memory size = 256KB (8/16E only)
|
||||
SET CPU CONSINT assert console interrupt (7/16, 8/16,
|
||||
and 8/16E only)
|
||||
|
||||
If memory size is being reduced, and the memory being truncated contains
|
||||
non-zero data, the simulator asks for confirmation. Data in the truncated
|
||||
portion of memory is lost. Initial memory size is 64KB.
|
||||
|
||||
These switches are recognized when examining or depositing in CPU memory
|
||||
(or any other byte oriented device):
|
||||
|
||||
-b examine/deposit bytes
|
||||
-w examine/deposit halfwords (CPU default)
|
||||
-f examine/deposit fullwords
|
||||
-d data radix is decimal
|
||||
-o data radix is octal
|
||||
-h data radix is hexadecimal
|
||||
-v interpret address as virtual
|
||||
|
||||
CPU registers include the visible state of the processor as well as the
|
||||
control registers for the interrupt system.
|
||||
|
||||
name size comments
|
||||
|
||||
PC 16 program counter
|
||||
R0..R15 16 general registers
|
||||
FR0..F14 32 single precision floating point registers
|
||||
D0H..D14H 32 double precision floating point registers,
|
||||
high order
|
||||
D0L..D14L 32 double precision floating point registers,
|
||||
low order
|
||||
PSW 16 processor status word
|
||||
CC 4 condition codes, PSW<12:15>
|
||||
SR 16 switch register
|
||||
DR 32 display register low 16 bits
|
||||
DRX 8 display register extension (x/16 only)
|
||||
DRMOD 1 display mode
|
||||
DRPOS 2 display pointer position
|
||||
SRPOS 1 switch pointer position
|
||||
IRQ[0:3] 32 interrupt requests
|
||||
IEN[0:3] 32 interrupt enables
|
||||
STOP_INST 1 stop on undefined instruction
|
||||
STOP_WAIT 1 stop if wait state and no I/O events pending
|
||||
PCQ[0:63] 16 PC prior to last branch or interrupt;
|
||||
most recent PC change first
|
||||
WRU 8 interrupt character
|
||||
|
||||
2.2 CPU (32b)
|
||||
|
||||
The CPU options include memory size and CPU type:
|
||||
|
||||
SET CPU 732 Interdata 7/32, single precision floating point
|
||||
SET CPU DPFP Interdata 7/32, double precision floating point
|
||||
SET CPU 832 Interdata 8/32 (double precision floating point)
|
||||
SET CPU 64K set memory size = 64KB
|
||||
SET CPU 128K set memory size = 128KB
|
||||
SET CPU 256K set memory size = 256KB
|
||||
SET CPU 512K set memory size = 512KB
|
||||
SET CPU 1M set memory size = 1024KB
|
||||
SET CPU CONSINT assert console interrupt
|
||||
|
||||
If memory size is being reduced, and the memory being truncated contains
|
||||
non-zero data, the simulator asks for confirmation. Data in the truncated
|
||||
portion of memory is lost. Initial memory size is 1024KB.
|
||||
|
||||
These switches are recognized when examining or depositing in CPU memory
|
||||
(or any other byte oriented device):
|
||||
|
||||
-b examine/deposit bytes
|
||||
-w examine/deposit halfwords
|
||||
-f examine/deposit fullwords (CPU default)
|
||||
-d data radix is decimal
|
||||
-o data radix is octal
|
||||
-h data radix is hexadecimal
|
||||
-v interpret address as virtual
|
||||
|
||||
CPU registers include the visible state of the processor as well as the
|
||||
control registers for the interrupt system.
|
||||
|
||||
name size comments
|
||||
|
||||
PC 20 program counter
|
||||
R0..R15 32 active general register set
|
||||
GREG[32] 32 general register sets, 16 x 2
|
||||
FR0..FR14 32 single precision floating point registers
|
||||
if double precision floating point; for
|
||||
microcoded floating point, floating point
|
||||
registers are kept in memory locations 00 - 1F
|
||||
D0H..D14H 32 double precision floating point registers,
|
||||
high order
|
||||
D0L..D14L 32 double precision floating point registers,
|
||||
low order
|
||||
PSW 16 processor status word
|
||||
CC 4 condition codes, PSW<12:15>
|
||||
SR 16 switch register
|
||||
DR 32 display register low 16 bits
|
||||
DRX 8 display register extension (x/16 only)
|
||||
DRMOD 1 display mode
|
||||
DRPOS 2 display pointer position
|
||||
SRPOS 1 switch pointer position
|
||||
MACREG[0:15] 32 memory access controller segment registers
|
||||
MACSTA 5 memory access controller interrupt status
|
||||
IRQ[0:3] 32 interrupt requests
|
||||
IEN[0:3] 32 interrupt enables
|
||||
STOP_INST 1 stop on undefined instruction
|
||||
STOP_WAIT 1 stop if wait state and no I/O events pending
|
||||
PCQ[0:63] 20 PC prior to last branch or interrupt;
|
||||
most recent PC change first
|
||||
WRU 8 interrupt character
|
||||
|
||||
2.3 Selector Channel (SELCH)
|
||||
|
||||
An Interdata system can have 1 to 4 selector channels (SELCH0, SELCH1,
|
||||
SELCH2, SELCH3). The default number of channels is 2. The number of
|
||||
channels can be changed with the command:
|
||||
|
||||
SET SELCH CHANNELS=num
|
||||
|
||||
The selector channels implement these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
SA[0:3] 20 start address, channels 0 to 3
|
||||
EA[0:3] 20 end address, channels 0 to 3
|
||||
CMD[0:3] 8 command, channels 0 to 3
|
||||
DEV[0:3] 8 active device, channels 0 to 3
|
||||
RDP[0:3] 2 read byte pointer, channels 0 to 3
|
||||
WDC[0:3] 3 write data counter, channels 0 to 3
|
||||
IREQ 4 interrupt requests; right to left,
|
||||
channels 0 to 3
|
||||
IENB 4 interrupt enables
|
||||
|
||||
2.4 Programmed I/O Devices
|
||||
|
||||
2.4.1 Paper Tape Reader/Punch (PT)
|
||||
|
||||
The paper tape reader and punch (PT units 0 and 1) read data from or
|
||||
write data to disk files. The RPOS and PPOS registers specify the
|
||||
number of the next data item to be read and written, respectively.
|
||||
Thus, by changing RPOS or PPOS, the user can backspace or advance
|
||||
these devices.
|
||||
|
||||
The paper tape reader supports the BOOT command. BOOT PTR copies the
|
||||
so-called '50 loader' into memory and starts it running.
|
||||
|
||||
The paper tape controller implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
RBUF 8 reader buffer
|
||||
RPOS 32 reader position in the input file
|
||||
RTIME 24 time from reader start to interrupt
|
||||
RSTOP_IOE 1 reader stop on I/O error
|
||||
PBUF 8 punch buffer
|
||||
PPOS 32 punch position in the output file
|
||||
PTIME 24 time from punch start to interrupt
|
||||
PSTOP_IOE 1 punch stop on I/O error
|
||||
IREQ 1 paper tape interrupt request
|
||||
IENB 1 paper tape interrupt enable
|
||||
IARM 1 paper tape interrupt armed
|
||||
RD 1 paper tape read/write mode
|
||||
RUN 1 paper tape running
|
||||
SLEW 1 paper tape reader slew mode
|
||||
EOF 1 paper tape reader end of file
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
type error STOP_IOE processed as
|
||||
|
||||
in,out not attached 1 report error and stop
|
||||
0 out of tape
|
||||
|
||||
in end of file 1 report error and stop
|
||||
0 out of tape
|
||||
|
||||
in,out OS I/O error x report error and stop
|
||||
|
||||
2.4.2 Console, Teletype Interface (TT)
|
||||
|
||||
The Teletype keyboard (TT0) reads from the console keyboard; the
|
||||
Teletype printer (TT1) writes to the simulator console window.
|
||||
The Teletype units (TT0, TT1) can be set to one of three modes:
|
||||
KSR, 7B, or 8B. In KSR mode, lower case input and output characters
|
||||
are automatically converted to upper case, and the high order bit is
|
||||
forced to one on input. In 7B mode, input and output characters are
|
||||
masked to 7 bits. In 8B mode, characters are not modified. Changing
|
||||
the mode of either unit changes both. The default mode is KSR.
|
||||
|
||||
The Teletype has a BREAK key, which is not present on today's
|
||||
keyboards. To simulate pressing the break key, stop the simulator
|
||||
and use the command:
|
||||
|
||||
SET TT BREAK
|
||||
|
||||
Break status will be asserted, and will remain asserted for the
|
||||
interval specified by KTIME.
|
||||
|
||||
The Teletype interface implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
KBUF 8 input buffer
|
||||
KPOS 32 number of characters input
|
||||
KTIME 24 input polling interval
|
||||
TBUF 8 output buffer
|
||||
TPOS 32 number of characters output
|
||||
TTIME 24 time from output start to interrupt
|
||||
IREQ 1 interrupt request
|
||||
IENB 1 interrupt enable
|
||||
IARM 1 interrupt armed
|
||||
RD 1 read/write mode
|
||||
FDPX 1 half-duplex
|
||||
CHP 1 input character pending
|
||||
|
||||
2.4.3 Console, PASLA Interface (TTP)
|
||||
|
||||
Later Interdata system connect the system console via the first
|
||||
PASLA interface rather than the Teletype interface. The PASLA
|
||||
console can be simulated with a Telnet session on the first PAS line.
|
||||
Alternately, the PASLA console can be attached to the simulator
|
||||
console window, using the TTP device in place of TT.
|
||||
|
||||
To switch the simulator console window to TTP, use the command:
|
||||
|
||||
SET TTP ENABLED or
|
||||
SET TT DISABLED
|
||||
|
||||
Device TT is automatically disabled and device TTP is enabled.
|
||||
To switch the simulator console window back to TT, use the command:
|
||||
|
||||
SET TT ENABLED or
|
||||
SET TTP DISABLED
|
||||
|
||||
Device TTP is automatically disabled and device TT is enabled.
|
||||
If TTP is enabled at its default device settings, the base address
|
||||
for the PAS multiplexor must be changed:
|
||||
|
||||
SET PAS DEVNO=12
|
||||
|
||||
Otherwise, a device number conflict occurs.
|
||||
|
||||
The PASLA keyboard (TTP0) reads from the console keyboard; the
|
||||
PALSA printer (TTP1) writes to the simulator console window.
|
||||
The PASLA units (TTP0, TTP1) can be set to one of three modes:
|
||||
UC, 7B, or 8B. In UC mode, lower case input and output characters
|
||||
are automatically converted to upper case. In 7B mode, input and
|
||||
output characters are masked to 7 bits. In 8B mode, characters
|
||||
are not modified. Changing the mode of either unit changes both.
|
||||
The default mode is UC.
|
||||
|
||||
To simulate pressing the break key, stop the simulator and use
|
||||
the command:
|
||||
|
||||
SET TTP BREAK
|
||||
|
||||
Break status will be asserted, and will remain asserted for the
|
||||
interval specified by KTIME.
|
||||
|
||||
The PASLA console interface implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
KBUF 8 input buffer
|
||||
KPOS 32 number of characters input
|
||||
KTIME 24 input polling interval
|
||||
KIREQ 1 input interrupt request
|
||||
KIENB 1 input interrupt enabled
|
||||
KARM 1 input interrupt armed
|
||||
CHP 1 input character pending
|
||||
TBUF 8 output buffer
|
||||
TPOS 32 number of characters output
|
||||
TTIME 24 time from output start to interrupt
|
||||
TIREQ 1 output interrupt request
|
||||
TIENB 1 output interrupt enable
|
||||
TIARM 1 output interrupt armed
|
||||
|
||||
2.4.4 Line Printer (LPT)
|
||||
|
||||
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,
|
||||
by changing POS, the user can backspace or advance the printer.
|
||||
|
||||
In addition, the line printer can be programmed with a carriage control
|
||||
tape. The LOAD command loads a new carriage control tape:
|
||||
|
||||
LOAD <file> load carriage control tape file
|
||||
|
||||
The format of a carriage control tape consists of multiple lines. Each
|
||||
line contains an optional repeat count, enclosed in parentheses, optionally
|
||||
followed by a series of column numbers separated by commas. Column numbers
|
||||
must be between 0 and 7; column seven is by convention top of form. The
|
||||
following are all legal carriage control specifications:
|
||||
|
||||
<blank line> no punch
|
||||
(5) 5 lines with no punches
|
||||
1,5,7 columns 1, 5, 7 punched
|
||||
(10)2 10 lines with column 2 punched
|
||||
0 column 0 punched
|
||||
|
||||
The default form is 1 line long, with all columns punched.
|
||||
|
||||
The line printer implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 7 last data item processed
|
||||
BPTR 8 line buffer pointer
|
||||
LBUF[0:131] 7 line buffer
|
||||
VFUP 8 vertical forms unit pointer
|
||||
VFUL 8 vertical forms unit length
|
||||
VFUT[0:131] 8 vertical forms unit table
|
||||
IREQ 1 line printer interrupt request
|
||||
IENB 1 line printer interrupt enable
|
||||
IARM 1 line printer interrupt armed
|
||||
POS 32 position in the output file
|
||||
CTIME 24 character processing time
|
||||
STIME 24 spacing operation time
|
||||
STOP_IOE 1 stop on I/O error
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 out of paper
|
||||
|
||||
OS I/O error x report error and stop
|
||||
|
||||
2.4.5 Line Frequency Clock (LFC)
|
||||
|
||||
The line frequency clock (LFC) implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
IREQ 1 clock interrupt request
|
||||
IENB 1 clock interrupt enable
|
||||
IARM 1 clock interrupt armed
|
||||
TIME 24 clock frequency
|
||||
TPS 8 ticks per second (120 or 100)
|
||||
|
||||
The real-time clock autocalibrates; the clock interval is adjusted up or
|
||||
down so that the clock tracks actual elapsed time.
|
||||
|
||||
2.4.6 Programmable Interval Clock (PIC)
|
||||
|
||||
The programmable interval clock (PIC) implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 16 output buffer
|
||||
RIC 16 reset interval and rate
|
||||
CIC 12 current interval
|
||||
DECR 10 current decrement value
|
||||
RDP 1 read byte select
|
||||
OVF 1 interval overflow flag
|
||||
IREQ 1 clock interrupt request
|
||||
IENB 1 clock interrupt enable
|
||||
IARM 1 clock interrupt armed
|
||||
|
||||
If the interval requested is longer than 1 msec, the programmable clock
|
||||
auto-calibrates; if not, it simply counts instructions.
|
||||
|
||||
2.4.7 Floppy Disk Controller (FD)
|
||||
|
||||
Floppy disk options include the ability to make units write enabled or
|
||||
write locked.
|
||||
|
||||
SET FDn LOCKED set unit n write locked
|
||||
SET FDn WRITEENABLED set unit n write enabled
|
||||
|
||||
Units can also be set ONLINE or OFFLINE.
|
||||
|
||||
The floppy disk supports the BOOT command. BOOT FDn copies an autoload
|
||||
sequence into memory and starts it running.
|
||||
|
||||
The floppy disk controller implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
CMD 8 command
|
||||
STA 8 status
|
||||
BUF 8 buffer
|
||||
LRN 16 logical record number
|
||||
ESTA[0:5] 8 extended status bytes
|
||||
DBUF[0:127] 8 transfer buffer
|
||||
DBPTR 8 transfer buffer pointer
|
||||
IREQ 1 interrupt request
|
||||
IENB 1 interrupt enabled
|
||||
IARM 1 interrupt armed
|
||||
CTIME 24 command response time
|
||||
STIME 24 seek time, per cylinder
|
||||
XTIME 24 transfer time, per byte
|
||||
STOP_IOE 1 stop on I/O error
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 disk not ready
|
||||
|
||||
Floppy disk data is buffered in memory; therefore, end of file and OS
|
||||
I/O errors cannot occur.
|
||||
|
||||
2.4.8 Programmable Asynchronous Line Adapters (PAS, PASL)
|
||||
|
||||
The Programmable Asynchronous Line Adapters (PAS and PASL) represent,
|
||||
indistinguishably, individual PASLA interfaces, two lines asynchronous
|
||||
multiplexors, and 8 line asynchronous multiplexors, with a maximum
|
||||
of 32 lines. All the lines are modelled as a terminal multiplexor, with
|
||||
PAS as the multiplexor controller, and PASL as the indivdual lines. The
|
||||
PASLAs perform input and output through Telnet sessions connected to a
|
||||
user-specified port. The ATTACH command specifies the port to be used:
|
||||
|
||||
ATTACH PAS <port> set up listening port
|
||||
|
||||
where port is a decimal number between 1 and 65535 that is not being used
|
||||
for other TCP/IP activities.
|
||||
|
||||
Each line (each unit of PASL) can be set to one of three modes: UC, 7B,
|
||||
or 8B. In UC mode, lower case input and output characters are converted
|
||||
automatically to upper case. In 7B mode, input and output characters are
|
||||
masked to 7 bits. In 8B mode, characters are not modified. The default
|
||||
mode is UC. Each line (each unit of PASL) can also be set for modem
|
||||
control with the command SET PASLn DATASET. The defaults are UC mode
|
||||
and DATASET disabled.
|
||||
|
||||
Once PAS is attached and the simulator is running, the terminals listen
|
||||
for connections on the specified port. They assume that the incoming
|
||||
connections are Telnet connections. The connections remain open until
|
||||
disconnected either by the Telnet client, a SET PAS DISCONNECT command,
|
||||
or a DETACH PAS command.
|
||||
|
||||
The SHOW PAS CONNECTIONS command displays the current connections to the
|
||||
extra terminals. The SHOW PAS STATISTICS command displays statistics for
|
||||
active connections. The SET PAS DISCONNECT=linenumber disconnects the
|
||||
specified line.
|
||||
|
||||
The controller (PAS) implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
STA[0:31] 8 status, lines 0 to 31
|
||||
CMD[0:31] 16 command, lines 0 to 31
|
||||
RBUF[0:31] 8 receive buffer, lines 0 to 31
|
||||
XBUF[0:31] 8 transmit buffer, lines 0 to 31
|
||||
RIREQ 32 receive interrupt requests;
|
||||
right to left, lines 0 to 31
|
||||
RIENB 32 receive interrupt enables
|
||||
RARM[0:31] 1 receive interrupt armed
|
||||
XIREQ 32 transmit interrupt requests;
|
||||
right to left, lines 0 to 31
|
||||
XIENB 32 transmit interrupt enables
|
||||
XARM[0:31] 1 transmit interrupt armed
|
||||
RCHP[0:31] 1 receiver character present, lines 0 to 31
|
||||
|
||||
The lines (PASL) implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
TIME[0:31] 24 transmit time, lines 0 to 31
|
||||
|
||||
The additional terminals do not support save and restore. All open
|
||||
connections are lost when the simulator shuts down or PAS is detached.
|
||||
|
||||
2.5 Cartridge Disk Controller (DP)
|
||||
|
||||
Cartridge disk options include the ability to make units write enabled or
|
||||
write locked, and to select the type of drive:
|
||||
|
||||
SET DPn LOCKED set unit n write locked
|
||||
SET DPn WRITEENABLED set unit n write enabled
|
||||
SET DPn 2315 set unit n to 2315 (2.5MB)
|
||||
SET DPn 5440 set unit n to 5440 (10MB)
|
||||
|
||||
Units can also be set ONLINE or OFFLINE.
|
||||
|
||||
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
|
||||
7E:7F. The disk bootstrap looks for a valid OS16/32 volume descriptor in
|
||||
block 0, and uses that to locate the volume directory. It then searches
|
||||
the directory for a filename of the form OS16xxxx.hhh or OS32xxxx.hhh,
|
||||
where the xxxx is ignored and hhh is the ASCII form of the extension from
|
||||
locations 7E:7F. The 32b bootstrap can also boot Wollongong UNIX; locations
|
||||
7E:7F must be 0.
|
||||
|
||||
All drives have 256 8b bytes per sector. The other disk parameters are:
|
||||
|
||||
drive cylinders surfaces sectors
|
||||
|
||||
2315 203 2 24
|
||||
5440 408 4 12
|
||||
|
||||
The cartridge disk controller implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
CMD 3 current command
|
||||
STA 8 controller status
|
||||
BUF 8 controller buffer
|
||||
HDSC 8 current head/sector select
|
||||
CYL 8 current cylinder select
|
||||
DBUF[0:255] 8 transfer buffer
|
||||
DBPTR 16 transfer buffer point
|
||||
DBLNT 16 transfer buffer length
|
||||
FIRST 1 first DMA service flag
|
||||
IREQ 5 interrupt requests; right-to-left,
|
||||
controller, drives 0 to 3
|
||||
IENB 5 interrupt enables
|
||||
IARM[0:3] 1 interrupts armed, drives 0 to 3
|
||||
STIME 24 seek latency, per cylinder
|
||||
RTIME 24 rotational latency, per sector
|
||||
WTIME 24 inter-word latency
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error processed as
|
||||
|
||||
not attached disk not ready
|
||||
|
||||
end of file assume rest of disk is zero
|
||||
|
||||
OS I/O error report error and stop
|
||||
|
||||
2.6 Mass Storage Module/Intelligent Disk Controller (DM)
|
||||
|
||||
MSM/IDC disk controller options include the ability to make units
|
||||
write enabled or write locked, and to select the type of drive:
|
||||
|
||||
SET DMn LOCKED set unit n write locked
|
||||
SET DMn WRITEENABLED set unit n write enabled
|
||||
SET DMn MSM80 set unit n to storage module, 80MB
|
||||
(67MB formatted)
|
||||
SET DMn MSM300 set unit n to storage module, 300MB
|
||||
(262MB formatted)
|
||||
SET DMn MCCD16 set unit n to medium capacity, 16MB
|
||||
(13.5MB formatted)
|
||||
SET DMn MCCD48 set unit n to medium capacity, 48MB
|
||||
(40.5MB formatted)
|
||||
SET DMn MCCD80 set unit n to medium capacity, 80MB
|
||||
(67MB formatted)
|
||||
SET DMn MSM330F set unit n to storage module, 330MB
|
||||
(300MB formatted)
|
||||
|
||||
Note that the disk bootstraps can ONLY boot the MSM80 and MSM300.
|
||||
Units can be set ONLINE or OFFLINE.
|
||||
|
||||
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
|
||||
7E:7F. The disk bootstrap looks for a valid OS16/32 volume descriptor in
|
||||
block 0, and uses that to locate the volume directory. It then searches
|
||||
the directory for a filename of the form OS16xxxx.hhh or OS32xxxx.hhh,
|
||||
where the xxxx is ignored and hhh is the ASCII form of the extension from
|
||||
locations 7E:7F. The 32b bootstrap can also boot Wollongong UNIX; locations
|
||||
7E:7F must be 0. Note that only the MSM80 and MSM300 drives can be boot-
|
||||
strapped; the boot code does not recognize the other drives.
|
||||
|
||||
All drives have 256 8b bytes per sector. The other disk parameters are:
|
||||
|
||||
drive cylinders surfaces sectors
|
||||
|
||||
MSM80 823 5 64
|
||||
MSM300 823 19 64
|
||||
MCCD16 823 1 64
|
||||
MCCD48 823 3 64
|
||||
MCCD80 823 5 64
|
||||
MSM300F 1024 16 64
|
||||
|
||||
The MSM/IDC disk controller implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
STA 8 controller status
|
||||
BUF 8 controller buffer
|
||||
SEC 8 current sector select
|
||||
DBUF[0:767] 8 transfer buffer
|
||||
DBPTR 16 transfer buffer point
|
||||
DBLNT 16 transfer buffer length
|
||||
FIRST 1 first DMA service flag
|
||||
IREQ 5 interrupt requests; right-to-left,
|
||||
controller, drives 0 to 3
|
||||
IENB 5 interrupt enables
|
||||
SIREQ 5 saved interrupt requests
|
||||
ICARM 1 controller interrupt armed
|
||||
IDARM[0:3] 1 drive interrupts armed, drives 0 to 3
|
||||
STIME 24 seek latency, per cylinder
|
||||
RTIME 24 rotational latency, per sector
|
||||
WTIME 24 inter-word latency
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error processed as
|
||||
|
||||
not attached disk not ready
|
||||
|
||||
end of file assume rest of disk is zero
|
||||
|
||||
OS I/O error report error and stop
|
||||
|
||||
2.7 Magnetic Tape Controller (MT)
|
||||
|
||||
Magnetic tape options include the ability to make units write enabled or
|
||||
or write locked.
|
||||
|
||||
SET MTn LOCKED set unit n write locked
|
||||
SET MTn WRITEENABLED set unit n write enabled
|
||||
|
||||
Units can also be set ONLINE or OFFLINE.
|
||||
|
||||
The magnetic tape supports the BOOT command. BOOT MTn copies an autoload
|
||||
sequence into memory and starts it running.
|
||||
|
||||
The magnetic tape controller implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
CMD 8 command
|
||||
STA 8 status
|
||||
BUF 8 buffer
|
||||
DBUF[0:65535] 8 transfer buffer
|
||||
DBPTR 16 transfer buffer pointer
|
||||
DBLNT 16 transfer buffer length
|
||||
XFR 1 transfer in progress flag
|
||||
FIRST 1 first DMA service flag
|
||||
IREQ 4 interrupt requests; right to left,
|
||||
drives 0 to 3
|
||||
IENB 4 interrupt enables
|
||||
IARM[0:3] 1 interrupts armed, drives 0 to 3
|
||||
STOP_IOE 1 stop on I/O error
|
||||
WTIME 1 word transfer time
|
||||
RTIME 1 interrecord latency
|
||||
UST[0:3] 8 unit status, drives 0 to 3
|
||||
POS[0:3] 32 tape position, drives 0 to 3
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error processed as
|
||||
|
||||
not attached tape not ready; if STOP_IOE, stop
|
||||
|
||||
end of file set error flag
|
||||
|
||||
OS I/O error set error flag; if STOP_IOE, stop
|
||||
|
||||
2.8 Symbolic Display and Input
|
||||
|
||||
The Interdata simulator implements symbolic display and input. Display is
|
||||
controlled by command line switches:
|
||||
|
||||
-a display as ASCII character
|
||||
-c display as two character string
|
||||
-m display instruction mnemonics
|
||||
|
||||
Input parsing is controlled by the first character typed in or by command
|
||||
line switches:
|
||||
|
||||
' or -a ASCII character
|
||||
" or -c two character sixbit string
|
||||
alphabetic instruction mnemonic
|
||||
numeric octal number
|
||||
|
||||
2.7.1 16b Instruction Input
|
||||
|
||||
Instruction input uses standard Interdata assembler syntax. There are
|
||||
seven instruction classes: short branch, extended short branch, short
|
||||
immediate, register, register-register, memory, and register-memory.
|
||||
|
||||
Short branch instructions have the format
|
||||
|
||||
sbop mask,address
|
||||
|
||||
where the mask is a hex (decimal) number between 0 and F (15), and
|
||||
the address is within +32 (forward branch) or -32 (backward branch)
|
||||
of the current location.
|
||||
|
||||
Extended short branch instructions have the format
|
||||
|
||||
sbxop address
|
||||
|
||||
where the address is within +32 or -32 of the current location. For
|
||||
extended short branches, the simulator chooses the forward or backward
|
||||
direction automatically.
|
||||
|
||||
Short immediate instructions have the format
|
||||
|
||||
siop regnum,immed
|
||||
|
||||
where the register number is a hex (decimal) number, optionally
|
||||
preceded by R, between 0 and F (15), and the immediate is a hex digit
|
||||
between 0 and F.
|
||||
|
||||
Register instructions have the format
|
||||
|
||||
rop regnum
|
||||
|
||||
where the register number is a hex (decimal) number, optionally
|
||||
preceded by R, between 0 and F (15).
|
||||
|
||||
Register-register instructions have the format
|
||||
|
||||
rrop regnum,regnum
|
||||
|
||||
where the register numbers are hex (decimal) numbers, optionally
|
||||
preceded by R, between 0 and F (15).
|
||||
|
||||
Memory instructions have the format
|
||||
|
||||
mop address{(index)}
|
||||
|
||||
where address is a hex number between 0 and 0xFFFF, and the index
|
||||
register is a hex (decimal) number, optionally preceded by R,
|
||||
between 1 and F (15).
|
||||
|
||||
Register-memory instructions have the format
|
||||
|
||||
rmop regnum,address{(index)}
|
||||
|
||||
where the register number is a hex (decimal) number, optionally
|
||||
preceded by R, between 0 and F (15), the address is a hex number
|
||||
between 0 and 0xFFFF, and the index register is a hex (decimal)
|
||||
number, optionally preceded by R, between 1 and F (15).
|
||||
|
||||
2.7.2 32b Instruction Input
|
||||
|
||||
Instruction input uses standard Interdata assembler syntax. There are
|
||||
nine instruction classes: short branch, extended short branch, short
|
||||
immediate, 16b immediate, 32b immediate, register, register-register,
|
||||
memory, and register-memory.
|
||||
|
||||
Short branch instructions have the format
|
||||
|
||||
sbop mask,address
|
||||
|
||||
where the mask is a hex (decimal) number between 0 and F (15), and
|
||||
the address is within +32 (forward branch) or -32 (backward branch)
|
||||
of the current location.
|
||||
|
||||
Extended short branch instructions have the format
|
||||
|
||||
sbxop address
|
||||
|
||||
where the address is within +32 or -32 of the current location. For
|
||||
extended short branches, the simulator chooses the forward or backward
|
||||
direction automatically.
|
||||
|
||||
Short immediate instructions have the format
|
||||
|
||||
siop regnum,immed
|
||||
|
||||
where the register number is a hex (decimal) number, optionally
|
||||
preceded by R, between 0 and F (15), and the immediate is a hex digit
|
||||
between 0 and F.
|
||||
|
||||
16b immediate instructins have the format
|
||||
|
||||
i16op regnum,immed16{(index)}
|
||||
|
||||
where the register number is a hex (decimal) number, optionally
|
||||
preceded by R, between 0 and F (15), the immediate is a hex number
|
||||
between 0 and 0xFFFF, and the index register is a hex (decimal)
|
||||
number, optionally preceded by R, between 1 and F (15).
|
||||
|
||||
32b immediate instructions have the format
|
||||
|
||||
i32op regnum,immed32{(index)}
|
||||
|
||||
where the register number is a hex (decimal) number, optionally
|
||||
preceded by R, between 0 and F (15), the immediate is a hex number
|
||||
between 0 and 0xFFFFFFFF, and the index register is a hex (decimal)
|
||||
number, optionally preceded by R, between 1 and F (15).
|
||||
|
||||
Register instructions have the format
|
||||
|
||||
rop regnum
|
||||
|
||||
where the register number is a hex (decimal) number, optionally
|
||||
preceded by R, between 0 and F (15).
|
||||
|
||||
Register-register instructions have the format
|
||||
|
||||
rrop regnum,regnum
|
||||
|
||||
where the register numbers are hex (decimal) numbers, optionally
|
||||
preceded by R, between 0 and F (15).
|
||||
|
||||
Memory instructions have the format
|
||||
|
||||
mop address{(index)} or
|
||||
mop address{(index1,index2)}
|
||||
|
||||
where address is a hex number between 0 and 0xFFFF, and the index
|
||||
registers are hex (decimal) numbers, optionally preceded by R,
|
||||
between 1 and F (15).
|
||||
|
||||
Register-memory instructions have the format
|
||||
|
||||
rmop regnum,address{(index)} or
|
||||
rmop regnum,address{(index1,index2)}
|
||||
|
||||
where the register number is a hex (decimal) number, optionally
|
||||
preceded by R, between 0 and F (15), the address is a hex number
|
||||
between 0 and 0xFFFF, and the index registers are hex (decimal)
|
||||
numbers, optionally preceded by R, between 1 and F (15).
|
||||
|
||||
For memory operands, the simulator automatically chooses the format
|
||||
(RX1, RX2, RX3) that consumes the fewest bytes. If both RX1 and RX2
|
||||
are feasible, the simulator chooses RX1.
|
||||
|
547
Interdata/id_dp.c
Normal file
547
Interdata/id_dp.c
Normal file
|
@ -0,0 +1,547 @@
|
|||
/* id_dp.c: Interdata 2.5MB/10MB cartridge disk simulator
|
||||
|
||||
Copyright (c) 2001-2002, 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.
|
||||
|
||||
dp M46-421 2.5MB/10MB cartridge disk
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
#include <math.h>
|
||||
|
||||
#define DP_NUMBY 256 /* bytes/sector */
|
||||
#define DP_NUMSC 24 /* sectors/track */
|
||||
|
||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
||||
#define UNIT_V_DTYPE (UNIT_V_UF + 1) /* disk type */
|
||||
#define UNIT_M_DTYPE 0x1
|
||||
#define UNIT_V_AUTO (UNIT_V_UF + 2) /* autosize */
|
||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
||||
#define UNIT_DTYPE (UNIT_M_DTYPE << UNIT_V_DTYPE)
|
||||
#define UNIT_AUTO (1 << UNIT_V_AUTO)
|
||||
#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE)
|
||||
|
||||
#define CYL u3 /* current cylinder */
|
||||
#define STD u4 /* drive status */
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
|
||||
/* Controller status */
|
||||
|
||||
#define STC_OVR 0x80 /* overrun */
|
||||
#define STC_ACF 0x40 /* addr cmp fail */
|
||||
#define STC_DEF 0x20 /* def track NI */
|
||||
#define STC_CYO 0x10 /* cylinder ovflo */
|
||||
#define STC_IDL 0x02 /* ctrl idle */
|
||||
#define STC_DTE 0x01 /* xfer error */
|
||||
#define SETC_EX (STC_OVR|STC_ACF|STC_DEF|STC_CYO)
|
||||
#define STC_MASK (STC_OVR|STC_ACF|STC_DEF|STC_CYO|STA_BSY|STC_IDL|STC_DTE)
|
||||
|
||||
/* Controller command */
|
||||
|
||||
#define CMC_MASK 0xF
|
||||
#define CMC_CLR 0x8 /* reset */
|
||||
#define CMC_RD 0x1 /* read */
|
||||
#define CMC_WR 0x2 /* write */
|
||||
#define CMC_RCHK 0x3 /* read check */
|
||||
#define CMC_RFMT 0x5 /* read fmt NI */
|
||||
#define CMC_WFMT 0x6 /* write fmt NI */
|
||||
|
||||
/* Drive status, ^ = dynamic, * = in unit status */
|
||||
|
||||
#define STD_WRP 0x80 /* ^write prot */
|
||||
#define STD_WCK 0x40 /* write check NI */
|
||||
#define STD_ILA 0x20 /* *illegal addr */
|
||||
#define STD_ILK 0x10 /* ^addr interlock */
|
||||
#define STD_MOV 0x08 /* *heads in motion */
|
||||
#define STD_INC 0x02 /* seek incomplete NI */
|
||||
#define STD_NRDY 0x01 /* ^not ready */
|
||||
#define STD_UST (STD_ILA | STD_MOV) /* set from unit */
|
||||
#define SETD_EX (STD_WCK | STD_ILA | STD_ILK) /* set examine */
|
||||
|
||||
/* Drive command */
|
||||
|
||||
#define CMD_SK 0x02 /* seek */
|
||||
#define CMD_RST 0x01 /* restore */
|
||||
|
||||
/* Head/sector register */
|
||||
|
||||
#define HS_SMASK 0x1F /* sector mask */
|
||||
#define HS_V_SRF 5 /* surface */
|
||||
#define HS_HMASK 0x20 /* head mask */
|
||||
#define HS_MASK (HS_HMASK | HS_SMASK)
|
||||
#define GET_SEC(x) ((x) & HS_SMASK)
|
||||
#define GET_SRF(x) (((x) & HS_HMASK) >> HS_V_SRF)
|
||||
|
||||
#define GET_SA(p,cy,sf,sc,t) (((((((p)*drv_tab[t].cyl)+(cy))*drv_tab[t].surf)+(sf))* \
|
||||
DP_NUMSC)+(sc))
|
||||
#define GET_ROTATE(x) ((int) fmod (sim_gtime() / ((double) (x)), \
|
||||
((double) DP_NUMSC)))
|
||||
|
||||
/* This controller supports two different disk drive types:
|
||||
|
||||
type #sectors/ #surfaces/ #cylinders/
|
||||
surface cylinder drive
|
||||
|
||||
2315 24 2 203
|
||||
5440 24 4 408
|
||||
|
||||
In theory, each drive can be a different type. The size field in
|
||||
each unit selects the drive capacity for each drive and thus the
|
||||
drive type. DISKS MUST BE DECLARED IN ASCENDING SIZE AND MUST HAVE
|
||||
THE SAME SECTORS/TRACK.
|
||||
*/
|
||||
|
||||
#define TYPE_2315 0
|
||||
#define CYL_2315 203
|
||||
#define SURF_2315 2
|
||||
#define SIZE_2315 (DP_NUMSC * SURF_2315 * CYL_2315 * DP_NUMBY)
|
||||
|
||||
#define TYPE_5440 1
|
||||
#define CYL_5440 408
|
||||
#define SURF_5440 2
|
||||
#define SIZE_5440 (2 * DP_NUMSC * SURF_5440 * CYL_5440 * DP_NUMBY)
|
||||
|
||||
struct drvtyp {
|
||||
int32 cyl; /* cylinders */
|
||||
uint32 surf; /* surfaces */
|
||||
uint32 size; /* #blocks */
|
||||
};
|
||||
|
||||
static struct drvtyp drv_tab[] = {
|
||||
{ CYL_2315, SURF_2315, SIZE_2315 },
|
||||
{ CYL_5440, SURF_5440, SIZE_5440 },
|
||||
{ 0 } };
|
||||
|
||||
extern uint32 int_req[INTSZ], int_enb[INTSZ];
|
||||
|
||||
uint8 dpxb[DP_NUMBY]; /* xfer buffer */
|
||||
uint32 dp_bptr = 0; /* buffer ptr */
|
||||
uint32 dp_db = 0; /* ctrl buffer */
|
||||
uint32 dp_cyl = 0; /* drive buffer */
|
||||
uint32 dp_sta = 0; /* ctrl status */
|
||||
uint32 dp_cmd = 0; /* ctrl command */
|
||||
uint32 dp_plat = 0; /* platter */
|
||||
uint32 dp_hdsc = 0; /* head/sector */
|
||||
uint32 dp_svun = 0; /* most recent unit */
|
||||
uint32 dp_1st = 0; /* first byte */
|
||||
uint32 dpd_arm[DP_NUMDR] = { 0 }; /* drives armed */
|
||||
int32 dp_stime = 100; /* seek latency */
|
||||
int32 dp_rtime = 100; /* rotate latency */
|
||||
int32 dp_wtime = 1; /* word time */
|
||||
uint8 dp_tplte[(2 * DP_NUMDR) + 2]; /* fix/rmv + ctrl + end */
|
||||
|
||||
DEVICE dp_dev;
|
||||
uint32 dp (uint32 dev, uint32 op, uint32 dat);
|
||||
void dp_ini (t_bool dtpl);
|
||||
t_stat dp_svc (UNIT *uptr);
|
||||
t_stat dp_reset (DEVICE *dptr);
|
||||
t_stat dp_attach (UNIT *uptr, char *cptr);
|
||||
t_stat dp_detach (UNIT *uptr);
|
||||
t_stat dp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat dp_rds (UNIT *uptr);
|
||||
t_stat dp_wds (UNIT *uptr);
|
||||
t_bool dp_dter (UNIT *uptr, uint32 first);
|
||||
void dp_done (uint32 flg);
|
||||
|
||||
extern t_stat id_dboot (int32 u, DEVICE *dptr);
|
||||
|
||||
/* DP data structures
|
||||
|
||||
dp_dev DP device descriptor
|
||||
dp_unit DP unit list
|
||||
dp_reg DP register list
|
||||
dp_mod DP modifier list
|
||||
*/
|
||||
|
||||
DIB dp_dib = { d_DPC, 0, v_DPC, dp_tplte, &dp, &dp_ini };
|
||||
|
||||
UNIT dp_unit[] = {
|
||||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+(TYPE_5440 << UNIT_V_DTYPE), SIZE_5440) },
|
||||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+(TYPE_5440 << UNIT_V_DTYPE), SIZE_5440) },
|
||||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+(TYPE_5440 << UNIT_V_DTYPE), SIZE_5440) },
|
||||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+(TYPE_5440 << UNIT_V_DTYPE), SIZE_5440) } };
|
||||
|
||||
REG dp_reg[] = {
|
||||
{ HRDATA (CMD, dp_cmd, 3) },
|
||||
{ HRDATA (STA, dp_sta, 8) },
|
||||
{ HRDATA (BUF, dp_db, 8) },
|
||||
{ HRDATA (PLAT, dp_plat, 1) },
|
||||
{ HRDATA (HDSC, dp_hdsc, 6) },
|
||||
{ HRDATA (CYL, dp_cyl, 9) },
|
||||
{ HRDATA (SVUN, dp_svun, 8), REG_HIDDEN },
|
||||
{ BRDATA (DBUF, dpxb, 16, 8, DP_NUMBY) },
|
||||
{ HRDATA (DBPTR, dp_bptr, 9), REG_RO },
|
||||
{ FLDATA (FIRST, dp_1st, 0) },
|
||||
{ GRDATA (IREQ, int_req[l_DPC], 16, DP_NUMDR + 1, i_DPC) },
|
||||
{ GRDATA (IENB, int_enb[l_DPC], 16, DP_NUMDR + 1, i_DPC) },
|
||||
{ BRDATA (IARM, dpd_arm, 16, 1, DP_NUMDR) },
|
||||
{ DRDATA (RTIME, dp_rtime, 0), PV_LEFT | REG_NZ },
|
||||
{ DRDATA (STIME, dp_stime, 0), PV_LEFT | REG_NZ },
|
||||
{ DRDATA (WTIME, dp_wtime, 0), PV_LEFT | REG_NZ },
|
||||
{ URDATA (UCYL, dp_unit[0].CYL, 16, 9, 0,
|
||||
DP_NUMDR, REG_RO) },
|
||||
{ URDATA (UST, dp_unit[0].STD, 16, 8, 0,
|
||||
DP_NUMDR, REG_RO) },
|
||||
{ URDATA (CAPAC, dp_unit[0].capac, 10, 31, 0,
|
||||
DP_NUMDR, PV_LEFT | REG_HRO) },
|
||||
{ HRDATA (DEVNO, dp_dib.dno, 8), REG_HRO },
|
||||
{ HRDATA (SELCH, dp_dib.sch, 2), REG_HRO },
|
||||
{ NULL } };
|
||||
|
||||
MTAB dp_mod[] = {
|
||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
|
||||
{ (UNIT_DTYPE+UNIT_ATT), (TYPE_2315 << UNIT_V_DTYPE) + UNIT_ATT,
|
||||
"2315", NULL, NULL },
|
||||
{ (UNIT_DTYPE+UNIT_ATT), (TYPE_5440 << UNIT_V_DTYPE) + UNIT_ATT,
|
||||
"5440", NULL, NULL },
|
||||
{ (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_2315 << UNIT_V_DTYPE),
|
||||
"2315", NULL, NULL },
|
||||
{ (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_5440 << UNIT_V_DTYPE),
|
||||
"5440", NULL, NULL },
|
||||
{ (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL },
|
||||
{ UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL },
|
||||
{ (UNIT_AUTO+UNIT_DTYPE), (TYPE_2315 << UNIT_V_DTYPE),
|
||||
NULL, "2315", &dp_set_size },
|
||||
{ (UNIT_AUTO+UNIT_DTYPE), (TYPE_5440 << UNIT_V_DTYPE),
|
||||
NULL, "5440", &dp_set_size },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "SELCH", "SELCH",
|
||||
&set_sch, &show_sch, NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE dp_dev = {
|
||||
"DP", dp_unit, dp_reg, dp_mod,
|
||||
DP_NUMDR, 16, 24, 1, 16, 8,
|
||||
NULL, NULL, &dp_reset,
|
||||
&id_dboot, &dp_attach, &dp_detach,
|
||||
&dp_dib, DEV_DISABLE };
|
||||
|
||||
/* Controller: IO routine */
|
||||
|
||||
uint32 dpc (uint32 dev, uint32 op, uint32 dat)
|
||||
{
|
||||
uint32 f, t, u;
|
||||
UNIT *uptr;
|
||||
static uint8 good_cmd[8] = { 0, 1, 1, 1, 0, 0, 0, 0 };
|
||||
|
||||
switch (op) { /* case IO op */
|
||||
case IO_ADR: /* select */
|
||||
sch_adr (dp_dib.sch, dev); /* inform sel ch */
|
||||
return BY; /* byte only */
|
||||
case IO_RD: /* read data */
|
||||
if (dp_sta & STC_IDL) /* if idle */
|
||||
return GET_ROTATE (dp_rtime); /* return sector */
|
||||
else dp_sta = dp_sta | STA_BSY; /* xfr? set busy */
|
||||
return dp_db; /* return data */
|
||||
case IO_WD: /* write data */
|
||||
if (dp_sta & STC_IDL) dp_hdsc = dat & HS_MASK; /* idle? hdsc */
|
||||
else { /* data xfer */
|
||||
dp_sta = dp_sta | STA_BSY; /* set busy */
|
||||
dp_db = dat & 0xFF; } /* store data */
|
||||
break;
|
||||
case IO_SS: /* status */
|
||||
t = dp_sta & STC_MASK; /* get status */
|
||||
if (t & SETC_EX) t = t | STA_EX; /* test for EX */
|
||||
return t;
|
||||
case IO_OC: /* command */
|
||||
f = dat & CMC_MASK; /* get cmd */
|
||||
if (f & CMC_CLR) { /* clear? */
|
||||
dp_reset (&dp_dev); /* reset world */
|
||||
break; }
|
||||
u = (dp_svun - dp_dib.dno - o_DP0) / o_DP0; /* get unit */
|
||||
uptr = dp_dev.units + u; /* ignore if busy */
|
||||
if (!(dp_sta & STC_IDL) || sim_is_active (uptr)) break;
|
||||
dp_cmd = f; /* save cmd */
|
||||
if (dp_cmd == CMC_WR) dp_sta = 0; /* write: bsy=0 else */
|
||||
else dp_sta = STA_BSY; /* bsy=1,idl,err=0 */
|
||||
dp_1st = 1; /* xfr not started */
|
||||
dp_bptr = 0; /* buffer empty */
|
||||
if (dp_svun & o_DPF) dp_plat = 1; /* upper platter? */
|
||||
else dp_plat = 0; /* no, lower */
|
||||
if (good_cmd[f]) sim_activate (uptr, dp_rtime); /* legal? sched */
|
||||
break; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Drives: IO routine */
|
||||
|
||||
uint32 dp (uint32 dev, uint32 op, uint32 dat)
|
||||
{
|
||||
int32 diff;
|
||||
uint32 t, u;
|
||||
UNIT *uptr;
|
||||
|
||||
if (dev == dp_dib.dno) return dpc (dev, op, dat); /* controller? */
|
||||
u = (dev - dp_dib.dno - o_DP0) / o_DP0; /* get unit num */
|
||||
uptr = dp_dev.units + u; /* get unit ptr */
|
||||
switch (op) { /* case IO op */
|
||||
case IO_ADR: /* select */
|
||||
if (dp_sta & STC_IDL) dp_svun = dev; /* idle? save unit */
|
||||
return BY; /* byte only */
|
||||
case IO_WD: /* write data */
|
||||
if (GET_DTYPE (uptr->flags) == TYPE_2315) /* 2.5MB drive? */
|
||||
dp_cyl = dat & 0xFF; /* cyl is 8b */
|
||||
else dp_cyl = ((dp_cyl << 8) | dat) & DMASK16; /* insert byte */
|
||||
break;
|
||||
case IO_SS: /* status */
|
||||
if (uptr->flags & UNIT_ATT) t = /* onl? */
|
||||
((uptr->flags & UNIT_WPRT)? STD_WRP: 0) |
|
||||
((dp_sta & STC_IDL)? 0: STD_ILK) |
|
||||
(uptr->STD & STD_UST);
|
||||
else t = STD_MOV | STD_NRDY; /* off = X'09' */
|
||||
if (t & SETD_EX) t = t | STA_EX; /* test for ex */
|
||||
return t;
|
||||
case IO_OC: /* command */
|
||||
dpd_arm[u] = int_chg (v_DPC + u + 1, dat, dpd_arm[u]);
|
||||
if (dat & CMD_SK) t = dp_cyl; /* seek? get cyl */
|
||||
else if (dat & CMD_RST) t = 0; /* rest? cyl 0 */
|
||||
else break; /* no action */
|
||||
diff = t - uptr->CYL;
|
||||
if (diff < 0) diff = -diff; /* ABS cyl diff */
|
||||
else if (diff == 0) diff = 1; /* must be nz */
|
||||
uptr->STD = STD_MOV; /* stat = moving */
|
||||
uptr->CYL = t; /* put on cyl */
|
||||
sim_activate (uptr, diff * dp_stime); /* schedule */
|
||||
break; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Unit service
|
||||
|
||||
If seek done, on cylinder;
|
||||
if read check, signal completion;
|
||||
else, do read or write
|
||||
*/
|
||||
|
||||
t_stat dp_svc (UNIT *uptr)
|
||||
{
|
||||
uint32 u = uptr - dp_dev.units; /* get unit number */
|
||||
int32 cyl = uptr->CYL; /* get cylinder */
|
||||
uint32 dtype = GET_DTYPE (uptr->flags); /* get drive type */
|
||||
uint32 t;
|
||||
t_stat r;
|
||||
|
||||
if (uptr->STD & STD_MOV) { /* seek? */
|
||||
uptr->STD = 0; /* clr seek in prog */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* offl? hangs */
|
||||
if (cyl >= drv_tab[dtype].cyl) { /* bad cylinder? */
|
||||
uptr->STD = STD_ILA; /* error */
|
||||
uptr->CYL = drv_tab[dtype].cyl - 1; } /* put at edge */
|
||||
if (dpd_arm[u]) SET_INT (v_DPC + u + 1); /* req intr */
|
||||
return SCPE_OK; }
|
||||
|
||||
switch (dp_cmd & 0x7) { /* case on func */
|
||||
|
||||
case CMC_RCHK: /* read check */
|
||||
dp_dter (uptr, 1); /* check xfr err */
|
||||
break;
|
||||
|
||||
case CMC_RD: /* read */
|
||||
if (sch_actv (dp_dib.sch, dp_dib.dno)) { /* sch transfer? */
|
||||
if (dp_dter (uptr, dp_1st)) return SCPE_OK; /* check xfr err */
|
||||
if (r = dp_rds (uptr)) return r; /* read sec, err? */
|
||||
dp_1st = 0;
|
||||
t = sch_wrmem (dp_dib.sch, dpxb, DP_NUMBY); /* write to memory */
|
||||
if (sch_actv (dp_dib.sch, dp_dib.dno)) { /* more to do? */
|
||||
sim_activate (uptr, dp_rtime); /* reschedule */
|
||||
return SCPE_OK; }
|
||||
break; } /* no, set done */
|
||||
|
||||
dp_sta = dp_sta | STC_DTE; /* can't work */
|
||||
break;
|
||||
|
||||
case CMC_WR: /* write */
|
||||
if (sch_actv (dp_dib.sch, dp_dib.dno)) { /* sch transfer? */
|
||||
dp_bptr = sch_rdmem (dp_dib.sch, dpxb, DP_NUMBY); /* read from mem */
|
||||
dp_db = dpxb[dp_bptr - 1]; /* last byte */
|
||||
if (dp_dter (uptr, dp_1st)) return SCPE_OK; /* check xfr err */
|
||||
if (r = dp_wds (uptr)) return r; /* write sec, err? */
|
||||
dp_1st = 0;
|
||||
if (sch_actv (dp_dib.sch, dp_dib.dno)) { /* more to do? */
|
||||
sim_activate (uptr, dp_rtime); /* reschedule */
|
||||
return SCPE_OK; }
|
||||
break; } /* no, set done */
|
||||
|
||||
dp_sta = dp_sta | STC_DTE; /* can't work */
|
||||
break; }
|
||||
|
||||
dp_done (0); /* done */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Read data sector */
|
||||
|
||||
t_stat dp_rds (UNIT *uptr)
|
||||
{
|
||||
uint32 i;
|
||||
|
||||
i = fxread (dpxb, sizeof (uint8), DP_NUMBY, uptr->fileref);
|
||||
for ( ; i < DP_NUMBY; i++) dpxb[i] = 0; /* fill with 0's */
|
||||
if (ferror (uptr->fileref)) { /* error? */
|
||||
perror ("DP I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
dp_done (STC_DTE);
|
||||
return SCPE_IOERR; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Write data sector */
|
||||
|
||||
t_stat dp_wds (UNIT *uptr)
|
||||
{
|
||||
for ( ; dp_bptr < DP_NUMBY; dp_bptr++)
|
||||
dpxb[dp_bptr] = dp_db; /* fill with last */
|
||||
fxwrite (dpxb, sizeof (uint8), DP_NUMBY, uptr->fileref);
|
||||
if (ferror (uptr->fileref)) { /* error? */
|
||||
perror ("DP I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
dp_done (STC_DTE);
|
||||
return SCPE_IOERR; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Data transfer error test routine */
|
||||
|
||||
t_bool dp_dter (UNIT *uptr, uint32 first)
|
||||
{
|
||||
uint32 hd, sc, sa;
|
||||
uint32 dtype = GET_DTYPE (uptr->flags); /* get drive type */
|
||||
|
||||
if (((uptr->flags & UNIT_ATT) == 0) || /* not attached? */
|
||||
((uptr->flags & UNIT_WPRT) && (dp_cmd == CMC_WR))) {
|
||||
dp_done (STC_DTE); /* error, done */
|
||||
return TRUE; }
|
||||
hd = GET_SRF (dp_hdsc); /* get head */
|
||||
sc = GET_SEC (dp_hdsc); /* get sector */
|
||||
if (dp_cyl != (uint32) uptr->CYL) { /* wrong cylinder? */
|
||||
dp_done (STC_ACF); /* error, done */
|
||||
return TRUE; }
|
||||
if (sc >= DP_NUMSC) { /* bad sector? */
|
||||
dp_done (STC_OVR); /* error, done */
|
||||
return TRUE; }
|
||||
if (!first && (sc == 0) && (hd == 0)) { /* cyl overflow? */
|
||||
dp_done (STC_CYO); /* error, done */
|
||||
return TRUE; }
|
||||
sa = GET_SA (dp_plat, uptr->CYL, hd, sc, dtype); /* curr disk addr */
|
||||
fseek (uptr->fileref, sa * DP_NUMBY, SEEK_SET);
|
||||
if ((sc + 1) < DP_NUMSC) dp_hdsc = dp_hdsc + 1; /* end of track? */
|
||||
else dp_hdsc = (dp_hdsc ^ HS_HMASK) & HS_HMASK; /* sec 0, nxt srf */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Data transfer done routine */
|
||||
|
||||
void dp_done (uint32 flg)
|
||||
{
|
||||
dp_sta = (dp_sta | STC_IDL | flg) & ~STA_BSY; /* set flag, idle */
|
||||
SET_INT (v_DPC); /* unmaskable intr */
|
||||
if (flg) sch_stop (dp_dib.sch); /* if err, stop ch */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat dp_reset (DEVICE *dptr)
|
||||
{
|
||||
uint32 u;
|
||||
UNIT *uptr;
|
||||
|
||||
dp_cmd = 0; /* clear cmd */
|
||||
dp_sta = STA_BSY | STC_IDL; /* idle, busy */
|
||||
dp_1st = 0; /* clear flag */
|
||||
dp_svun = dp_db = 0; /* clear unit, buf */
|
||||
dp_plat = 0;
|
||||
dp_hdsc = 0; /* clear addr */
|
||||
CLR_INT (v_DPC); /* clear ctrl int */
|
||||
SET_ENB (v_DPC); /* always enabled */
|
||||
for (u = 0; u < DP_NUMDR; u++) { /* loop thru units */
|
||||
uptr = dp_dev.units + u;
|
||||
uptr->CYL = uptr->STD = 0;
|
||||
CLR_INT (v_DPC + u + 1); /* clear intr */
|
||||
CLR_ENB (v_DPC + u + 1); /* clear enable */
|
||||
dpd_arm[u] = 0; /* clear arm */
|
||||
sim_cancel (uptr); } /* cancel activity */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Attach routine (with optional autosizing) */
|
||||
|
||||
t_stat dp_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
uint32 i, p;
|
||||
t_stat r;
|
||||
|
||||
uptr->capac = drv_tab[GET_DTYPE (uptr->flags)].size;
|
||||
r = attach_unit (uptr, cptr);
|
||||
uptr->CYL = 0;
|
||||
if ((r != SCPE_OK) || ((uptr->flags & UNIT_AUTO) == 0)) return r;
|
||||
if (fseek (uptr->fileref, 0, SEEK_END)) return SCPE_OK;
|
||||
if ((p = ftell (uptr->fileref)) == 0) return SCPE_OK;
|
||||
for (i = 0; drv_tab[i].surf != 0; i++) {
|
||||
if (p <= drv_tab[i].size) {
|
||||
uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE);
|
||||
uptr->capac = drv_tab[i].size;
|
||||
return SCPE_OK; } }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Detach routine (generates an interrupt) */
|
||||
|
||||
t_stat dp_detach (UNIT *uptr)
|
||||
{
|
||||
uint32 u = uptr - dp_dev.units;
|
||||
|
||||
if (dpd_arm[u]) SET_INT (v_DPC + u + 1); /* if arm, intr */
|
||||
return detach_unit (uptr);
|
||||
}
|
||||
|
||||
/* Set size command validation routine */
|
||||
|
||||
t_stat dp_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
|
||||
uptr->capac = drv_tab[GET_DTYPE (val)].size;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Create device number (T) or interrupt (F) template */
|
||||
|
||||
void dp_ini (t_bool dtpl)
|
||||
{
|
||||
int32 u, j, dev;
|
||||
|
||||
dp_tplte[0] = 0; /* controller */
|
||||
for (u = 0, j = 1; u < DP_NUMDR; u++) { /* loop thru units */
|
||||
dev = (u + 1) * o_DP0; /* drive dev # */
|
||||
dp_tplte[j++] = dev;
|
||||
if (dtpl && (GET_DTYPE (dp_unit[u].flags) == TYPE_5440))
|
||||
dp_tplte[j++] = dev + o_DPF; } /* if fixed */
|
||||
dp_tplte[j] = TPL_END; /* end marker */
|
||||
return;
|
||||
}
|
480
Interdata/id_fd.c
Normal file
480
Interdata/id_fd.c
Normal file
|
@ -0,0 +1,480 @@
|
|||
/* id_fd.c: Interdata floppy disk simulator
|
||||
|
||||
Copyright (c) 2001-2002, 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.
|
||||
|
||||
fd M46-630 floppy disk
|
||||
|
||||
A diskette consists of 77 tracks, each with 26 sectors of 128B. The
|
||||
Interdata floppy uses a logical record numbering scheme from 1 to 2002.
|
||||
Physical tracks are numbered 0-76, physical sectors 1-26.
|
||||
|
||||
To allow for deleted data handling, a directory is appended to the end
|
||||
of the image, one byte per LRN. Zero (the default) is a normal record,
|
||||
non-zero a deleted record.
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
|
||||
#define FD_NUMTR 77 /* tracks/disk */
|
||||
#define FD_NUMSC 26 /* sectors/track */
|
||||
#define FD_NUMBY 128 /* bytes/sector */
|
||||
#define FD_NUMLRN (FD_NUMTR * FD_NUMSC) /* LRNs/disk */
|
||||
#define FD_SIZE (FD_NUMLRN * FD_NUMBY) /* bytes/disk */
|
||||
#define FD_NUMDR 4 /* drives/controller */
|
||||
#define UNIT_V_WLK (UNIT_V_UF) /* write locked */
|
||||
#define UNIT_WLK (1u << UNIT_V_UF)
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
#define LRN u3 /* last LRN */
|
||||
#define FNC u4 /* last function */
|
||||
#define GET_DA(x) (((x) - 1) * FD_NUMBY)
|
||||
#define GET_TRK(x) (((x) - 1) / FD_NUMSC)
|
||||
#define GET_SEC(x) ((((x) - 1) % FD_NUMSC) + 1)
|
||||
#define LRN_BOOT 5 /* boot block LRN */
|
||||
|
||||
/* Command byte */
|
||||
|
||||
#define CMD_V_UNIT 4 /* unit */
|
||||
#define CMD_M_UNIT 0x3
|
||||
#define GET_UNIT(x) (((x) >> CMD_V_UNIT) & CMD_M_UNIT)
|
||||
#define CMD_V_FNC 0 /* function */
|
||||
#define CMD_M_FNC 0xF
|
||||
#define GET_FNC(x) (((x) >> CMD_V_FNC) & CMD_M_FNC)
|
||||
#define FNC_RD 0x1 /* read */
|
||||
#define FNC_WR 0x2 /* write */
|
||||
#define FNC_RDID 0x3 /* read ID */
|
||||
#define FNC_RSTA 0x4 /* read status */
|
||||
#define FNC_DEL 0x5 /* write deleted */
|
||||
#define FNC_BOOT 0x6 /* boot */
|
||||
#define FNC_STOP 0x7 /* stop */
|
||||
#define FNC_RESET 0x8 /* reset */
|
||||
#define FNC_FMT 0x9 /* format NI */
|
||||
#define FNC_STOPPING 0x10 /* stopping */
|
||||
|
||||
/* Status byte, * = dynamic */
|
||||
|
||||
#define STA_WRP 0x80 /* *write prot */
|
||||
#define STA_DEF 0x40 /* def track NI */
|
||||
#define STA_DEL 0x20 /* del record */
|
||||
#define STA_ERR 0x10 /* error */
|
||||
#define STA_IDL 0x02 /* idle */
|
||||
#define STA_OFL 0x01 /* fault */
|
||||
#define STA_MASK (STA_DEF|STA_DEL|STA_ERR|STA_BSY|STA_IDL)
|
||||
#define SET_EX (STA_ERR) /* set EX */
|
||||
|
||||
/* Extended status, 6 bytes, * = dynamic */
|
||||
|
||||
#define ES_SIZE 6
|
||||
#define ES0_HCRC 0x80 /* ID CRC NI */
|
||||
#define ES0_DCRC 0x40 /* data CRC NI */
|
||||
#define ES0_LRN 0x20 /* illegal LRN */
|
||||
#define ES0_WRP 0x10 /* *write prot */
|
||||
#define ES0_ERR 0x08 /* error */
|
||||
#define ES0_DEF 0x04 /* def trk NI */
|
||||
#define ES0_DEL 0x02 /* del rec NI */
|
||||
#define ES0_FLT 0x01 /* fault */
|
||||
#define ES1_TK0 0x80 /* track 0 */
|
||||
#define ES1_NRDY 0x40 /* not ready */
|
||||
#define ES1_NOAM 0x20 /* no addr mk NI */
|
||||
#define ES1_CMD 0x10 /* illegal cmd */
|
||||
#define ES1_SKE 0x08 /* seek err NI */
|
||||
#define ES1_UNS 0x04 /* unsafe NI */
|
||||
#define ES1_UNIT 0x03 /* unit # */
|
||||
|
||||
/* Processing options for commands */
|
||||
|
||||
#define C_RD 0x1 /* cmd reads disk */
|
||||
#define C_WD 0x2 /* cmd writes disk */
|
||||
|
||||
extern uint32 int_req[INTSZ], int_enb[INTSZ];
|
||||
|
||||
uint32 fd_sta = 0; /* status */
|
||||
uint32 fd_cmd = 0; /* command */
|
||||
uint32 fd_db = 0; /* data buffer */
|
||||
uint32 fd_bptr = 0; /* buffer pointer */
|
||||
uint8 fdxb[FD_NUMBY] = { 0 }; /* sector buffer */
|
||||
uint8 fd_es[FD_NUMDR][ES_SIZE] = { 0 }; /* ext status */
|
||||
uint32 fd_lrn = 0; /* log rec # */
|
||||
uint32 fd_wdv = 0; /* wd valid */
|
||||
uint32 fd_stopioe = 1; /* stop on error */
|
||||
uint32 fd_arm = 0; /* intr arm */
|
||||
int32 fd_ctime = 100; /* command time */
|
||||
int32 fd_stime = 10; /* seek, per LRN */
|
||||
int32 fd_xtime = 1; /* tr set time */
|
||||
|
||||
static uint32 ctab[16] = {
|
||||
0, C_RD, C_WD, 0, /* 0, rd, wr, 0 */
|
||||
0, C_WD, C_RD, 0, /* 0, del, boot, 0 */
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0 };
|
||||
|
||||
DEVICE fd_dev;
|
||||
uint32 fd (uint32 dev, uint32 op, uint32 dat);
|
||||
t_stat fd_svc (UNIT *uptr);
|
||||
t_stat fd_reset (DEVICE *dptr);
|
||||
t_stat fd_clr (DEVICE *dptr);
|
||||
t_stat fd_boot (int32 unitno, DEVICE *dptr);
|
||||
t_bool fd_dte (UNIT *uptr, t_bool wr);
|
||||
uint32 fd_crc (uint32 crc, uint32 dat, uint32 cnt);
|
||||
void fd_done (uint32 u, uint32 nsta, uint32 nes0, uint32 nes1);
|
||||
void sched_seek (UNIT *uptr, int32 newlrn);
|
||||
|
||||
/* FD data structures
|
||||
|
||||
fd_dev FD device descriptor
|
||||
fd_unit FD unit list
|
||||
fd_reg FD register list
|
||||
fd_mod FD modifier list
|
||||
*/
|
||||
|
||||
DIB fd_dib = { d_FD, -1, v_FD, NULL, &fd, NULL };
|
||||
|
||||
UNIT fd_unit[] = {
|
||||
{ UDATA (&fd_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_BUFABLE+UNIT_MUSTBUF, FD_SIZE + FD_NUMLRN) },
|
||||
{ UDATA (&fd_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_BUFABLE+UNIT_MUSTBUF, FD_SIZE + FD_NUMLRN) },
|
||||
{ UDATA (&fd_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_BUFABLE+UNIT_MUSTBUF, FD_SIZE + FD_NUMLRN) },
|
||||
{ UDATA (&fd_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_BUFABLE+UNIT_MUSTBUF, FD_SIZE + FD_NUMLRN) } };
|
||||
|
||||
REG fd_reg[] = {
|
||||
{ HRDATA (CMD, fd_cmd, 8) },
|
||||
{ HRDATA (STA, fd_sta, 8) },
|
||||
{ HRDATA (BUF, fd_db, 8) },
|
||||
{ HRDATA (LRN, fd_lrn, 16) },
|
||||
{ BRDATA (ESTA, fd_es, 16, 8, ES_SIZE * FD_NUMDR) },
|
||||
{ BRDATA (DBUF, fdxb, 16, 8, FD_NUMBY) },
|
||||
{ HRDATA (DBPTR, fd_bptr, 8) },
|
||||
{ FLDATA (WDV, fd_wdv, 0) },
|
||||
{ FLDATA (IREQ, int_req[l_FD], i_FD) },
|
||||
{ FLDATA (IENB, int_enb[l_FD], i_FD) },
|
||||
{ FLDATA (IARM, fd_arm, 0) },
|
||||
{ DRDATA (CTIME, fd_ctime, 24), PV_LEFT },
|
||||
{ DRDATA (STIME, fd_stime, 24), PV_LEFT },
|
||||
{ DRDATA (XTIME, fd_xtime, 24), PV_LEFT },
|
||||
{ FLDATA (STOP_IOE, fd_stopioe, 0) },
|
||||
{ URDATA (ULRN, fd_unit[0].LRN, 16, 16, 0, FD_NUMDR, REG_HRO) },
|
||||
{ URDATA (UFNC, fd_unit[0].FNC, 16, 8, 0, FD_NUMDR, REG_HRO) },
|
||||
{ HRDATA (DEVNO, fd_dib.dno, 8), REG_HRO },
|
||||
{ NULL } };
|
||||
|
||||
MTAB fd_mod[] = {
|
||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE fd_dev = {
|
||||
"FD", fd_unit, fd_reg, fd_mod,
|
||||
FD_NUMDR, 16, 20, 1, 16, 8,
|
||||
NULL, NULL, &fd_reset,
|
||||
&fd_boot, NULL, NULL,
|
||||
&fd_dib, DEV_DISABLE };
|
||||
|
||||
/* Floppy disk: IO routine */
|
||||
|
||||
uint32 fd (uint32 dev, uint32 op, uint32 dat)
|
||||
{
|
||||
int32 u, t, fnc;
|
||||
UNIT *uptr;
|
||||
|
||||
fnc = GET_FNC (fd_cmd); /* get fnc */
|
||||
u = GET_UNIT (fd_cmd); /* get unit */
|
||||
uptr = fd_dev.units + u;
|
||||
switch (op) { /* case IO op */
|
||||
case IO_ADR: /* select */
|
||||
return BY; /* byte only */
|
||||
case IO_RD: /* read */
|
||||
if (fd_sta & (STA_IDL | STA_BSY)) return fd_db; /* idle, busy? */
|
||||
if (fd_bptr < FD_NUMBY) fd_db = fdxb[fd_bptr++];/* get byte */
|
||||
if (fd_bptr >= FD_NUMBY) { /* buf end? */
|
||||
if (ctab[fnc] & C_RD) { /* disk read? */
|
||||
sched_seek (uptr, uptr->LRN + 1); /* sched read */
|
||||
fd_sta = fd_sta | STA_BSY; } /* set busy */
|
||||
else fd_bptr = 0; } /* just wrap */
|
||||
if ((ctab[fnc] & C_RD) && fd_arm) /* if rd & arm, */
|
||||
SET_INT (v_FD); /* interrupt */
|
||||
return fd_db; /* return buf */
|
||||
case IO_WD: /* write */
|
||||
if (fd_sta & STA_IDL) { /* idle? */
|
||||
fd_lrn = ((fd_lrn << 8) | dat) & DMASK16; /* insert byte */
|
||||
fd_wdv = 1;
|
||||
break; }
|
||||
if (fd_bptr < FD_NUMBY) /* if room, */
|
||||
fdxb[fd_bptr++] = fd_db = dat; /* store byte */
|
||||
if (fd_bptr >= FD_NUMBY) { /* buf end? */
|
||||
if (ctab[fnc] & C_WD) { /* disk write? */
|
||||
sched_seek (uptr, uptr->LRN + 1); /* sched write */
|
||||
fd_sta = fd_sta | STA_BSY; } /* set busy */
|
||||
else fd_bptr = 0; } /* just wrap */
|
||||
if ((ctab[fnc] & C_WD) && fd_arm) /* if wr & arm, */
|
||||
SET_INT (v_FD); /* interrupt */
|
||||
break;
|
||||
case IO_SS: /* status */
|
||||
t = fd_sta & STA_MASK; /* get status */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) t = t | STA_DU;
|
||||
if (t & SET_EX) t = t | STA_EX; /* test for ex */
|
||||
return t;
|
||||
case IO_OC: /* command */
|
||||
fd_arm = int_chg (v_FD, dat, fd_arm); /* upd int ctrl */
|
||||
fnc = GET_FNC (dat); /* new fnc */
|
||||
fd_cmd = dat; /* save cmd */
|
||||
u = GET_UNIT (dat); /* get unit */
|
||||
uptr = fd_dev.units + u;
|
||||
if (fnc == FNC_STOP) { /* stop? */
|
||||
uptr->FNC = uptr->FNC | FNC_STOPPING; /* flag stop */
|
||||
if (sim_is_active (uptr)) break; /* busy? cont */
|
||||
if (ctab[GET_FNC (uptr->FNC)] & C_WD) { /* write? */
|
||||
sched_seek (uptr, uptr->LRN + 1); /* sched write */
|
||||
fd_sta = fd_sta | STA_BSY; } /* set busy */
|
||||
else fd_done (u, 0, 0, 0); /* nrml done */
|
||||
break; }
|
||||
else if (fd_sta & STA_IDL) { /* must be idle */
|
||||
if (fnc != FNC_RSTA) { /* !rd status */
|
||||
fd_sta = STA_BSY; /* busy, !idle */
|
||||
fd_es[u][0] = 0;
|
||||
fd_es[u][1] = u; } /* init ext sta */
|
||||
else fd_sta = (fd_sta & ~STA_IDL) | STA_BSY;
|
||||
if (fnc == FNC_BOOT) t = LRN_BOOT; /* boot? fixed sec */
|
||||
else if (fd_wdv) t = fd_lrn; /* valid data? use */
|
||||
else t = uptr->LRN; /* use prev */
|
||||
fd_wdv = 0; /* data invalid */
|
||||
fd_bptr = 0; /* init buffer */
|
||||
uptr->FNC = fnc; /* save function */
|
||||
uptr->LRN = t; /* save LRN */
|
||||
if (ctab[fnc] & C_RD) sched_seek (uptr, t); /* seek now? */
|
||||
else sim_activate (uptr, fd_ctime); } /* start cmd */
|
||||
break; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Unit service; the action to be taken depends on command */
|
||||
|
||||
t_stat fd_svc (UNIT *uptr)
|
||||
{
|
||||
uint32 i, u, tk, sc, crc, fnc;
|
||||
t_addr da;
|
||||
|
||||
u = uptr - fd_dev.units; /* get unit number */
|
||||
fnc = GET_FNC (uptr->FNC); /* get function */
|
||||
switch (fnc) { /* case on function */
|
||||
|
||||
case FNC_RESET: /* reset */
|
||||
fd_clr (&fd_dev); /* clear device */
|
||||
fd_done (u, 0, 0, 0); /* set idle */
|
||||
return SCPE_OK;
|
||||
|
||||
case FNC_STOP: /* stop */
|
||||
fd_done (u, 0, 0, 0); /* set idle */
|
||||
return SCPE_OK;
|
||||
|
||||
case FNC_BOOT: /* boot, buf empty */
|
||||
case FNC_RD: /* read, buf empty */
|
||||
if (uptr->FNC & FNC_STOPPING) break; /* stopped? */
|
||||
if (fd_dte (uptr, FALSE)) return SCPE_OK; /* xfr error? */
|
||||
da = GET_DA (uptr->LRN); /* get disk addr */
|
||||
for (i = 0; i < FD_NUMBY; i++) /* read sector */
|
||||
fdxb[i] = *(((uint8 *) uptr->filebuf) + da + i);
|
||||
if (*(((uint8 *) uptr->filebuf) + FD_SIZE + uptr->LRN - 1)) {
|
||||
fd_sta = fd_sta | STA_DEL; /* deleted? set err */
|
||||
fd_es[u][0] = fd_es[u][0] | ES0_DEL; }
|
||||
fd_es[u][2] = GET_SEC (uptr->LRN); /* set ext sec/trk */
|
||||
fd_es[u][3] = GET_TRK (uptr->LRN);
|
||||
fd_bptr = 0; /* init buf */
|
||||
uptr->LRN = uptr->LRN + 1; /* next block */
|
||||
break;
|
||||
|
||||
case FNC_WR: case FNC_DEL: /* write block */
|
||||
if (fd_dte (uptr, TRUE)) return SCPE_OK; /* xfr error? */
|
||||
if (fd_bptr) { /* any transfer? */
|
||||
da = GET_DA (uptr->LRN); /* get disk addr */
|
||||
for (i = fd_bptr; i < FD_NUMBY; i++) /* pad sector */
|
||||
fdxb[i] = fd_db;
|
||||
for (i = 0; i < FD_NUMBY; i++) /* write sector */
|
||||
*(((uint8 *) uptr->filebuf) + da + i) = fdxb[i];
|
||||
*(((uint8 *) uptr->filebuf) + FD_SIZE + uptr->LRN - 1) =
|
||||
(fnc == FNC_DEL)? 1: 0; /* write dir */
|
||||
uptr->hwmark = uptr->capac; /* rewrite all */
|
||||
fd_es[u][2] = GET_SEC (uptr->LRN); /* set ext sec/trk */
|
||||
fd_es[u][3] = GET_TRK (uptr->LRN);
|
||||
fd_bptr = 0; /* init buf */
|
||||
uptr->LRN = uptr->LRN + 1; } /* next block */
|
||||
break;
|
||||
|
||||
case FNC_RSTA: /* read status */
|
||||
if (uptr->flags & UNIT_WPRT) /* wr protected? */
|
||||
fd_es[u][0] = fd_es[u][0] | ES0_WRP;
|
||||
if (GET_TRK (uptr->LRN) == 0) /* on track 0? */
|
||||
fd_es[u][1] = fd_es[u][1] | ES1_TK0;
|
||||
if ((uptr->flags & UNIT_BUF) == 0) { /* not attached? */
|
||||
fd_es[u][0] = fd_es[u][0] | ES0_FLT; /* set err */
|
||||
fd_es[u][1] = fd_es[u][1] | ES1_NRDY; }
|
||||
for (i = 0; i < ES_SIZE; i++) fdxb[i] = fd_es[u][i]; /* copy to buf */
|
||||
for (i = ES_SIZE; i < FD_NUMBY; i++) fdxb[i] = 0;
|
||||
break;
|
||||
|
||||
case FNC_RDID: /* read ID */
|
||||
if ((uptr->flags & UNIT_BUF) == 0) { /* not attached? */
|
||||
fd_done (u, STA_ERR, ES0_ERR | ES0_FLT, ES1_NRDY);
|
||||
return SCPE_OK; }
|
||||
for (i = 0; i < FD_NUMBY; i++) fdxb[i] = 0; /* clr buf */
|
||||
tk = GET_TRK (uptr->LRN); /* get track */
|
||||
sc = GET_SEC (uptr->LRN); /* get sector */
|
||||
fdxb[0] = tk & 0xFF; /* store track */
|
||||
fdxb[2] = sc & 0xFF; /* store sector */
|
||||
crc = fd_crc (0xFFFF, 0xFE00, 8); /* CRC addr mark */
|
||||
crc = fd_crc (crc, tk << 8, 16); /* CRC track */
|
||||
crc = fd_crc (crc, sc << 8, 16); /* CRC sector */
|
||||
fdxb[4] = (crc >> 8) & 0xFF; /* store CRC */
|
||||
fdxb[5] = crc & 0xFF;
|
||||
break;
|
||||
|
||||
case FNC_FMT: /* format */
|
||||
default:
|
||||
fd_done (u, STA_ERR, ES0_ERR, ES1_CMD); /* ill cmd */
|
||||
uptr->LRN = 1; /* on track 0 */
|
||||
return SCPE_OK; }
|
||||
|
||||
if (uptr->FNC & FNC_STOPPING) { /* stopping? */
|
||||
uptr->FNC = FNC_STOP; /* fnc = STOP */
|
||||
sim_activate (uptr, fd_ctime); } /* schedule */
|
||||
fd_sta = fd_sta & ~STA_BSY; /* clear busy */
|
||||
if (fd_arm) SET_INT (v_FD); /* if armed, int */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Schedule seek */
|
||||
|
||||
void sched_seek (UNIT *uptr, int32 newlrn)
|
||||
{
|
||||
int32 diff = newlrn - uptr->LRN; /* LRN diff */
|
||||
|
||||
if (diff < 0) diff = -diff; /* ABS */
|
||||
if (diff < 10) diff = 10; /* MIN 10 */
|
||||
sim_activate (uptr, diff * fd_stime); /* schedule */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Command complete */
|
||||
|
||||
void fd_done (uint32 u, uint32 nsta, uint32 nes0, uint32 nes1)
|
||||
{
|
||||
fd_sta = (fd_sta | STA_IDL | nsta) & ~STA_BSY; /* set idle */
|
||||
if (fd_arm) SET_INT (v_FD); /* if armed, int */
|
||||
fd_es[u][0] = fd_es[u][0] | nes0; /* set ext state */
|
||||
fd_es[u][1] = fd_es[u][1] | nes1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Test for data transfer error */
|
||||
|
||||
t_bool fd_dte (UNIT *uptr, t_bool wr)
|
||||
{
|
||||
uint32 u = uptr - fd_dev.units;
|
||||
|
||||
if ((uptr->flags & UNIT_BUF) == 0) { /* not attached? */
|
||||
fd_done (u, STA_ERR, ES0_ERR | ES0_FLT, ES1_NRDY);
|
||||
return TRUE; }
|
||||
if (wr && (uptr->flags & UNIT_WPRT)) { /* wr protected? */
|
||||
fd_done (u, STA_ERR, ES0_ERR | ES0_WRP, 0);
|
||||
return TRUE; }
|
||||
if ((uptr->LRN == 0) || (uptr->LRN > FD_NUMLRN)) { /* bad LRN? */
|
||||
fd_done (u, STA_ERR, ES0_ERR | ES0_LRN, 0);
|
||||
return TRUE; }
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Header CRC calculation */
|
||||
|
||||
uint32 fd_crc (uint32 crc, uint32 dat, uint32 cnt)
|
||||
{
|
||||
uint32 i, wrk;
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
wrk = crc ^ dat;
|
||||
crc = (crc << 1) & DMASK16;
|
||||
if (wrk & SIGN16) crc = ((crc ^ 0x1020) + 1) & DMASK16;
|
||||
dat = (dat << 1) & DMASK16; }
|
||||
return crc;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat fd_clr (DEVICE *dptr)
|
||||
{
|
||||
int32 i, j;
|
||||
UNIT *uptr;
|
||||
|
||||
fd_sta = STA_IDL; /* idle */
|
||||
fd_cmd = 0; /* clear state */
|
||||
fd_db = 0;
|
||||
fd_bptr = 0;
|
||||
fd_lrn = 1;
|
||||
fd_wdv = 0;
|
||||
for (i = 0; i < FD_NUMBY; i++) fdxb[i] = 0; /* clr xfr buf */
|
||||
for (i = 0; i < FD_NUMDR; i++) { /* loop thru units */
|
||||
for (j = 0; j < ES_SIZE; j++) fd_es[i][j] = 0; /* clr ext sta */
|
||||
fd_es[i][2] = 1; /* sector 1 */
|
||||
uptr = fd_dev.units + i;
|
||||
sim_cancel (uptr); /* stop drive */
|
||||
uptr->LRN = 1; /* clear state */
|
||||
uptr->FNC = 0; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat fd_reset (DEVICE *dptr)
|
||||
{
|
||||
CLR_INT (v_FD); /* clear int */
|
||||
CLR_ENB (v_FD); /* disable int */
|
||||
fd_arm = 0; /* disarm int */
|
||||
return fd_clr (dptr);;
|
||||
}
|
||||
|
||||
/* Bootstrap routine */
|
||||
|
||||
#define BOOT_START 0x50
|
||||
#define BOOT_LEN (sizeof (boot_rom) / sizeof (uint8))
|
||||
|
||||
static uint8 boot_rom[] = {
|
||||
0xD5, 0x00, /* ST: AL CF */
|
||||
0x00, 0xCF,
|
||||
0x43, 0x00, /* BR 80 */
|
||||
0x00, 0x80
|
||||
};
|
||||
|
||||
t_stat fd_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
extern uint32 PC, dec_flgs;
|
||||
extern uint16 decrom[];
|
||||
|
||||
if (decrom[0xD5] & dec_flgs) return SCPE_NOFNC; /* AL defined? */
|
||||
IOWriteBlk (BOOT_START, BOOT_LEN, boot_rom); /* copy boot */
|
||||
IOWriteB (AL_DEV, fd_dib.dno); /* set dev no */
|
||||
IOWriteB (AL_IOC, 0x86 + (unitno << CMD_V_UNIT)); /* set dev cmd, unit num */
|
||||
IOWriteB (AL_SCH, 0); /* clr sch dev no */
|
||||
PC = BOOT_START;
|
||||
return SCPE_OK;
|
||||
}
|
471
Interdata/id_fp.c
Normal file
471
Interdata/id_fp.c
Normal file
|
@ -0,0 +1,471 @@
|
|||
/* id_fp.c: Interdata floating point instructions
|
||||
|
||||
Copyright (c) 2000-2002, 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.
|
||||
|
||||
The Interdata uses IBM 360 floating point format:
|
||||
|
||||
0 7 8 15 23 31
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|S| exponent | fraction | :single
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| fraction low | :double
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
where S = 0 for plus, 1 for minus
|
||||
exponent = 16**n, in excess 64 code
|
||||
fraction = .hhhhhh, seen as 6-14 hexadecimal digits
|
||||
|
||||
Numbers can be normalized or unnormalized but are always normalized
|
||||
when loaded.
|
||||
|
||||
Interdata has 8 floating point registers, F0, F2, ... , FE. In floating
|
||||
point instructions, the low order bit of the register number is ignored.
|
||||
|
||||
On floating point overflow, the exponent and fraction are set to 1's.
|
||||
On floating point underflow, the exponent and fraction are set to 0's.
|
||||
|
||||
Interdata has both 32b only and 32b/64b floating point implementations.
|
||||
In 32b only implementations, add and subtract are truncated, but multiply
|
||||
and divide are rounded, and the floating point registers are kept in
|
||||
memory. In 64b implementations, all single precision precision operations
|
||||
are rounded, double precision operations are truncated, and the floating
|
||||
point registers are kept in separate hardware arrays.
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
|
||||
struct ufp { /* unpacked fp */
|
||||
int32 sign; /* sign */
|
||||
int32 exp; /* unbiased exp */
|
||||
uint32 h; /* fr high */
|
||||
uint32 l; }; /* fr low */
|
||||
|
||||
#define FP_V_SIGN 31 /* sign */
|
||||
#define FP_M_SIGN 0x1
|
||||
#define FP_GETSIGN(x) (((x) >> FP_V_SIGN) & FP_M_SIGN)
|
||||
#define FP_V_EXP 24 /* exponent */
|
||||
#define FP_M_EXP 0x7F
|
||||
#define FP_GETEXP(x) (((x) >> FP_V_EXP) & FP_M_EXP)
|
||||
#define FP_V_FRH 0 /* fraction */
|
||||
#define FP_M_FRH 0xFFFFFF
|
||||
#define FP_GETFRH(x) (((x) >> FP_V_FRH) & FP_M_FRH)
|
||||
#define FP_GETFRL(x) (x)
|
||||
|
||||
#define FP_BIAS 0x40 /* exp bias */
|
||||
#define FP_CARRY (1 << FP_V_EXP ) /* carry out */
|
||||
#define FP_NORM (0xF << (FP_V_EXP - 4)) /* normalized */
|
||||
#define FP_ROUND 0x80000000
|
||||
|
||||
/* Double precision fraction add/subtract/compare */
|
||||
|
||||
#define FR_ADD(d,s) d.l = (d.l + s.l) & DMASK32; \
|
||||
d.h = (d.h + s.h + (d.l < s.l)) & DMASK32
|
||||
|
||||
#define FR_SUB(d,s) d.h = (d.h - s.h - (d.l < s.l)) & DMASK32; \
|
||||
d.l = (d.l - s.l) & DMASK32
|
||||
|
||||
#define FR_GE(s1,s2) ((s1.h > s2.h) || \
|
||||
((s1.h == s2.h) && (s1.l >= s2.l)))
|
||||
|
||||
/* Variable and constant shifts; for constants, 0 < k < 32 */
|
||||
|
||||
#define FR_RSH_V(v,s) if ((s) < 32) { \
|
||||
v.l = ((v.l >> (s)) | \
|
||||
(v.h << (32 - (s)))) & DMASK32; \
|
||||
v.h = (v.h >> (s)) & DMASK32; } \
|
||||
else { v.l = v.h >> ((s) - 32); \
|
||||
v.h = 0; }
|
||||
|
||||
#define FR_RSH_K(v,s) v.l = ((v.l >> (s)) | \
|
||||
(v.h << (32 - (s)))) & DMASK32; \
|
||||
v.h = (v.h >> (s)) & DMASK32
|
||||
|
||||
#define FR_LSH_K(v,s) v.h = ((v.h << (s)) | \
|
||||
(v.l >> (32 - (s)))) & DMASK32; \
|
||||
v.l = (v.l << (s)) & DMASK32
|
||||
|
||||
#define Q_RND(op) (OP_DPFP (op) == 0)
|
||||
#define Q_RND_AS(op) ((OP_DPFP (op) == 0) && fp_in_hwre)
|
||||
|
||||
extern uint32 *R;
|
||||
extern uint32 F[8];
|
||||
extern dpr_t D[8];
|
||||
extern uint16 decrom[];
|
||||
extern uint32 fp_in_hwre;
|
||||
extern uint32 ReadF (uint32 loc, uint32 rel);
|
||||
extern void WriteF (uint32 loc, uint32 dat, uint32 rel);
|
||||
void ReadFP2 (struct ufp *fop, uint32 op, uint32 r2, uint32 ea);
|
||||
void UnpackFPR (struct ufp *fop, uint32 op, uint32 r1);
|
||||
void NormUFP (struct ufp *fop);
|
||||
uint32 StoreFPR (struct ufp *fop, uint32 op, uint32 r1, uint32 rnd);
|
||||
uint32 StoreFPX (struct ufp *fop, uint32 op, uint32 r1);
|
||||
|
||||
/* Floating point load */
|
||||
|
||||
uint32 f_l (uint32 op, uint32 r1, uint32 r2, uint32 ea)
|
||||
{
|
||||
struct ufp fop2;
|
||||
|
||||
ReadFP2 (&fop2, op, r2, ea); /* get op, normalize */
|
||||
return StoreFPR (&fop2, op, r1, 0); /* store, chk unflo */
|
||||
}
|
||||
|
||||
/* Floating point compare */
|
||||
|
||||
uint32 f_c (uint32 op, uint32 r1, uint32 r2, uint32 ea)
|
||||
{
|
||||
struct ufp fop1, fop2;
|
||||
|
||||
ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */
|
||||
UnpackFPR (&fop1, op, r1); /* get op1, norm */
|
||||
if (fop1.sign ^ fop2.sign) /* signs differ? */
|
||||
return (fop2.sign? CC_G: (CC_C | CC_L));
|
||||
if (fop1.exp != fop2.exp) /* exps differ? */
|
||||
return (((fop1.exp > fop2.exp) ^ fop1.sign)? CC_G: (CC_C | CC_L));
|
||||
if (fop1.h != fop2.h) /* hi fracs differ? */
|
||||
return (((fop1.h > fop2.h) ^ fop1.sign)? CC_G: (CC_C | CC_L));
|
||||
if (OP_DPFP (op) && (fop1.l != fop2.l)) /* dp: low fracs diff? */
|
||||
return (((fop1.l > fop2.l) ^ fop1.sign)? CC_G: (CC_C | CC_L));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Floating to integer conversion */
|
||||
|
||||
uint32 f_fix (uint32 op, uint32 r1, uint32 r2) /* 16b */
|
||||
{
|
||||
struct ufp res;
|
||||
uint32 cc;
|
||||
|
||||
UnpackFPR (&res, op, r2); /* get op2, norm */
|
||||
if ((res.h == 0) || (res.exp < 0x41)) { /* result zero? */
|
||||
R[r1] = 0;
|
||||
return 0; }
|
||||
if ((res.exp > 0x44) || /* result too big? */
|
||||
((res.exp == 0x44) && (res.h >= 0x00800000))) {
|
||||
res.h = MMASK16;
|
||||
cc = CC_V; }
|
||||
else { res.h = res.h >> ((0x46 - res.exp) * 4); /* right align frac */
|
||||
cc = 0; }
|
||||
if (res.sign) {
|
||||
R[r1] = ((res.h ^ DMASK16) + 1) & DMASK16; /* negate result */
|
||||
return cc | CC_L; }
|
||||
R[r1] = res.h & DMASK16;
|
||||
return cc | CC_G;
|
||||
}
|
||||
|
||||
uint32 f_fix32 (uint32 op, uint32 r1, uint32 r2) /* 32b */
|
||||
{
|
||||
struct ufp res;
|
||||
uint32 cc;
|
||||
|
||||
UnpackFPR (&res, op, r2); /* get op2, norm */
|
||||
if ((res.h == 0) || (res.exp < 0x41)) { /* result zero? */
|
||||
R[r1] = 0;
|
||||
return 0; }
|
||||
if ((res.exp > 0x48) || /* result too big? */
|
||||
((res.exp == 0x48) && (res.h >= 0x00800000))) {
|
||||
res.h = MMASK32;
|
||||
cc = CC_V; }
|
||||
else { FR_LSH_K (res, 8); /* get all in 32b */
|
||||
res.h = res.h >> ((0x48 - res.exp) * 4); /* right align frac */
|
||||
cc = 0; }
|
||||
if (res.sign) {
|
||||
R[r1] = (res.h ^ DMASK32) + 1; /* negate result */
|
||||
return cc | CC_L; }
|
||||
R[r1] = res.h;
|
||||
return cc | CC_G;
|
||||
}
|
||||
|
||||
/* Integer to floating conversion */
|
||||
|
||||
uint32 f_flt (uint32 op, uint32 r1, uint32 r2) /* 16b */
|
||||
{
|
||||
struct ufp res = { 0, 0x44, 0, 0 }; /* +, 16**4 */
|
||||
uint32 cc;
|
||||
|
||||
if (R[r2] == 0) cc = 0; /* zero arg? */
|
||||
else if (R[r2] & SIGN16) { /* neg arg? */
|
||||
res.sign = FP_M_SIGN; /* set sign */
|
||||
res.h = ((~R[r2] + 1) & DMASK16) << 8; /* get magnitude */
|
||||
cc = CC_L; }
|
||||
else { res.h = R[r2] << 8; /* pos nz arg */
|
||||
cc = CC_G; }
|
||||
NormUFP (&res); /* normalize */
|
||||
StoreFPR (&res, op, r1, 0); /* store result */
|
||||
return cc;
|
||||
}
|
||||
|
||||
uint32 f_flt32 (uint32 op, uint32 r1, uint32 r2) /* 32b */
|
||||
{
|
||||
struct ufp res = { 0, 0x48, 0, 0 }; /* +, 16**8 */
|
||||
uint32 cc, t;
|
||||
|
||||
t = R[r2]; /* int op */
|
||||
if (t) { /* nonzero arg? */
|
||||
if (t & SIGN32) { /* neg arg? */
|
||||
res.sign = FP_M_SIGN; /* set sign */
|
||||
t = (~t + 1) & DMASK32; /* get magnitude */
|
||||
cc = CC_L; }
|
||||
else cc = CC_G; /* pos nz arg */
|
||||
res.h = t >> 8; /* hi frac */
|
||||
res.l = t << 24; } /* lo frac */
|
||||
else cc = 0; /* zero arg */
|
||||
NormUFP (&res); /* normalize */
|
||||
StoreFPR (&res, op, r1, 0); /* store result */
|
||||
return cc;
|
||||
}
|
||||
|
||||
/* Floating point add/subtract */
|
||||
|
||||
uint32 f_as (uint32 op, uint32 r1, uint32 r2, uint32 ea)
|
||||
{
|
||||
struct ufp fop1, fop2, t;
|
||||
int32 ediff;
|
||||
|
||||
ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */
|
||||
UnpackFPR (&fop1, op, r1); /* get op1, norm */
|
||||
if (op & 1) fop2.sign = fop2.sign ^ 1; /* if sub, inv sign2 */
|
||||
if (fop1.h == 0) fop1 = fop2; /* if op1 = 0, res = op2 */
|
||||
else if (fop2.h != 0) { /* if op2 = 0, no add */
|
||||
if ((fop1.exp < fop2.exp) || /* |op1| < |op2|? */
|
||||
((fop1.exp == fop2.exp) &&
|
||||
((fop1.h < fop2.h) ||
|
||||
((fop1.h == fop2.h) && (fop1.l < fop2.l))))) {
|
||||
t = fop2; /* swap operands */
|
||||
fop2 = fop1;
|
||||
fop1 = t; }
|
||||
ediff = fop1.exp - fop2.exp; /* exp difference */
|
||||
if (OP_DPFP (op) || fp_in_hwre) { /* dbl prec or hwre? */
|
||||
if (ediff >= 14) fop2.h = fop2.l = 0; /* diff too big? */
|
||||
else if (ediff) { /* any difference? */
|
||||
FR_RSH_V (fop2, ediff * 4); } } /* shift frac */
|
||||
else { /* sgl prec ucode */
|
||||
if (ediff >= 6) fop2.h = 0; /* diff too big? */
|
||||
else if (ediff) /* any difference? */
|
||||
fop2.h = fop2.h >> (ediff * 4); } /* shift frac */
|
||||
if (fop1.sign ^ fop2.sign) { /* eff subtract */
|
||||
FR_SUB (fop1, fop2); /* sub fractions */
|
||||
NormUFP (&fop1); } /* normalize result */
|
||||
else {
|
||||
FR_ADD (fop1, fop2); /* add fractions */
|
||||
if (fop1.h & FP_CARRY) { /* carry out? */
|
||||
FR_RSH_K (fop1, 4); /* renormalize */
|
||||
fop1.exp = fop1.exp + 1; } } /* incr exp */
|
||||
} /* end if fop2 */
|
||||
return StoreFPR (&fop1, op, r1, Q_RND_AS (op)); /* store result */
|
||||
}
|
||||
|
||||
/* Floating point multiply
|
||||
|
||||
Notes:
|
||||
- Exponent overflow/underflow is tested right after the exponent
|
||||
add, without regard to potential changes due to normalization
|
||||
- Exponent underflow is tested right after normalization, without
|
||||
regard to changes due to rounding
|
||||
- Single precision hardware multiply may generate up to 48b
|
||||
- Double precision multiply generates 56b with no guard bits
|
||||
*/
|
||||
|
||||
int32 f_m (uint32 op, uint32 r1, uint32 r2, uint32 ea)
|
||||
{
|
||||
struct ufp fop1, fop2;
|
||||
struct ufp res = { 0, 0, 0, 0 };
|
||||
uint32 i;
|
||||
|
||||
ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */
|
||||
UnpackFPR (&fop1, op, r1); /* get op1, norm */
|
||||
if (fop1.h && fop2.h) { /* if both != 0 */
|
||||
res.sign = fop1.sign ^ fop2.sign; /* sign = diff */
|
||||
res.exp = fop1.exp + fop2.exp - FP_BIAS; /* exp = sum */
|
||||
if ((res.exp < 0) || (res.exp > FP_M_EXP)) /* ovf/undf? */
|
||||
return StoreFPX (&res, op, r1); /* early out */
|
||||
if ((fop1.l | fop2.l) == 0) { /* 24b x 24b? */
|
||||
for (i = 0; i < 24; i++) { /* 24 iterations */
|
||||
if (fop2.h & 1) res.h = res.h + fop1.h; /* add hi only */
|
||||
FR_RSH_K (res, 1); /* shift dp res */
|
||||
fop2.h = fop2.h >> 1; }
|
||||
}
|
||||
else { /* some low 0's */
|
||||
if (fop2.l != 0) { /* 56b x 56b? */
|
||||
for (i = 0; i < 32; i++) { /* do low 32b */
|
||||
if (fop2.l & 1) { FR_ADD (res, fop1); }
|
||||
FR_RSH_K (res, 1);
|
||||
fop2.l = fop2.l >> 1; } }
|
||||
for (i = 0; i < 24; i++) { /* do hi 24b */
|
||||
if (fop2.h & 1) { FR_ADD (res, fop1); }
|
||||
FR_RSH_K (res, 1);
|
||||
fop2.h = fop2.h >> 1; }
|
||||
}
|
||||
NormUFP (&res); /* normalize */
|
||||
if (res.exp < 0) /* underflow? */
|
||||
return StoreFPX (&res, op, r1); /* early out */
|
||||
}
|
||||
return StoreFPR (&res, op, r1, Q_RND (op)); /* store */
|
||||
}
|
||||
|
||||
/* Floating point divide - see overflow/underflow notes for multiply */
|
||||
|
||||
int32 f_d (uint32 op, uint32 r1, uint32 r2, uint32 ea)
|
||||
{
|
||||
struct ufp fop1, fop2;
|
||||
struct ufp quo = { 0, 0, 0, 0 };
|
||||
int32 i;
|
||||
|
||||
ReadFP2 (&fop2, op, r2, ea); /* get op2, norm */
|
||||
UnpackFPR (&fop1, op, r1); /* get op1, norm */
|
||||
if (fop2.h == 0) return CC_C | CC_V; /* div by zero? */
|
||||
if (fop1.h) { /* dvd != 0? */
|
||||
quo.sign = fop1.sign ^ fop2.sign; /* sign = diff */
|
||||
quo.exp = fop1.exp - fop2.exp + FP_BIAS; /* exp = diff */
|
||||
if ((quo.exp < 0) || (quo.exp > FP_M_EXP)) /* ovf/undf? */
|
||||
return StoreFPX (&quo, op, r1); /* early out */
|
||||
if (!FR_GE (fop1, fop2)) {
|
||||
FR_LSH_K (fop1, 4); } /* ensure success */
|
||||
else { /* exp off by 1 */
|
||||
quo.exp = quo.exp + 1; /* incr exponent */
|
||||
if (quo.exp > FP_M_EXP) /* overflow? */
|
||||
return StoreFPX (&quo, op, r1); } /* early out */
|
||||
for (i = 0; i < (OP_DPFP (op)? 14: 6); i++) { /* 6/14 hex digits */
|
||||
FR_LSH_K (quo, 4); /* shift quotient */
|
||||
while (FR_GE (fop1, fop2)) { /* while sub works */
|
||||
FR_SUB (fop1, fop2); /* decrement */
|
||||
quo.l = quo.l + 1; } /* add quo bit */
|
||||
FR_LSH_K (fop1, 4); } /* shift divd */
|
||||
if (!OP_DPFP (op)) { /* single? */
|
||||
quo.h = quo.l; /* move quotient */
|
||||
if (fop1.h >= (fop2.h << 3)) quo.l = FP_ROUND;
|
||||
else quo.l = 0; }
|
||||
/* don't need to normalize */
|
||||
} /* end if fop1.h */
|
||||
return StoreFPR (&quo, op, r1, Q_RND (op)); /* store result */
|
||||
}
|
||||
|
||||
/* Utility routines */
|
||||
|
||||
/* Unpack floating point number */
|
||||
|
||||
void UnpackFPR (struct ufp *fop, uint32 op, uint32 r1)
|
||||
{
|
||||
uint32 hi;
|
||||
|
||||
if (OP_DPFP (op)) { /* double prec? */
|
||||
hi = D[r1 >> 1].h; /* get hi */
|
||||
fop->l = FP_GETFRL (D[r1 >> 1].l); } /* get lo */
|
||||
else { hi = ReadFReg (r1); /* single prec */
|
||||
fop->l = 0; } /* lo is zero */
|
||||
fop->h = FP_GETFRH (hi); /* get hi frac */
|
||||
if (fop->h || fop->l) { /* non-zero? */
|
||||
fop->sign = FP_GETSIGN (hi); /* get sign */
|
||||
fop->exp = FP_GETEXP (hi); /* get exp */
|
||||
NormUFP (fop); } /* normalize */
|
||||
else fop->sign = fop->exp = 0; /* clean zero */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Read memory operand */
|
||||
|
||||
void ReadFP2 (struct ufp *fop, uint32 op, uint32 r2, uint32 ea)
|
||||
{
|
||||
uint32 hi;
|
||||
|
||||
if (OP_TYPE (op) > OP_RR) { /* mem ref? */
|
||||
hi = ReadF (ea, VR); /* get hi */
|
||||
if (OP_DPFP (op)) fop->l = ReadF (ea + 4, VR); /* dp? get lo */
|
||||
else fop->l = 0; } /* sp, lo = 0 */
|
||||
else { if (OP_DPFP (op)) { /* RR */
|
||||
hi = D[r2 >> 1].h; /* dp? get dp reg */
|
||||
fop->l = D[r2 >> 1].l; }
|
||||
else {
|
||||
hi = ReadFReg (r2); /* get sp reg */
|
||||
fop->l = 0; } }
|
||||
fop->h = FP_GETFRH (hi); /* get hi frac */
|
||||
if (fop->h || fop->l) { /* non-zero? */
|
||||
fop->sign = FP_GETSIGN (hi); /* get sign */
|
||||
fop->exp = FP_GETEXP (hi); /* get exp */
|
||||
NormUFP (fop); } /* normalize */
|
||||
else fop->sign = fop->exp = 0; /* clean zero */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Normalize unpacked floating point number */
|
||||
|
||||
void NormUFP (struct ufp *fop)
|
||||
{
|
||||
if ((fop->h & FP_M_FRH) || fop->l) { /* any fraction? */
|
||||
while ((fop->h & FP_NORM) == 0) { /* until norm */
|
||||
fop->h = (fop->h << 4) | ((fop->l >> 28) & 0xF);
|
||||
fop->l = fop->l << 4;
|
||||
fop->exp = fop->exp - 1; } }
|
||||
else fop->sign = fop->exp = 0; /* clean 0 */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Round fp number, store, generate condition codes */
|
||||
|
||||
uint32 StoreFPR (struct ufp *fop, uint32 op, uint32 r1, uint32 rnd)
|
||||
{
|
||||
uint32 hi, cc;
|
||||
|
||||
if (rnd && (fop->l & FP_ROUND)) { /* round? */
|
||||
fop->h = fop->h + 1; /* add 1 to frac */
|
||||
if (fop->h & FP_CARRY) { /* carry out? */
|
||||
fop->h = fop->h >> 4; /* renormalize */
|
||||
fop->exp = fop->exp + 1; } } /* incr exp */
|
||||
if (fop->h == 0) { /* result 0? */
|
||||
hi = fop->l = 0; /* store clean 0 */
|
||||
cc = 0; }
|
||||
else if (fop->exp < 0) { /* underflow? */
|
||||
hi = fop->l = 0; /* store clean 0 */
|
||||
cc = CC_V; }
|
||||
else if (fop->exp > FP_M_EXP) { /* overflow? */
|
||||
hi = (fop->sign)? 0xFFFFFFFF: 0x7FFFFFFF;
|
||||
fop->l = 0xFFFFFFFF;
|
||||
cc = (CC_V | ((fop->sign)? CC_L: CC_G)); }
|
||||
else { hi = ((fop->sign & FP_M_SIGN) << FP_V_SIGN) | /* pack result */
|
||||
((fop->exp & FP_M_EXP) << FP_V_EXP) |
|
||||
((fop->h & FP_M_FRH) << FP_V_FRH);
|
||||
cc = (fop->sign)? CC_L: CC_G; } /* set cc's */
|
||||
if (OP_DPFP (op)) { /* double precision? */
|
||||
D[r1 >> 1].h = hi;
|
||||
D[r1 >> 1].l = fop->l; }
|
||||
else { WriteFReg (r1, hi); }
|
||||
return cc;
|
||||
}
|
||||
|
||||
/* Generate exception result */
|
||||
|
||||
uint32 StoreFPX (struct ufp *fop, uint32 op, uint32 r1)
|
||||
{
|
||||
uint32 cc = CC_V;
|
||||
|
||||
if (fop->exp < 0) fop->h = fop->l = 0; /* undf? clean 0 */
|
||||
else { fop->h = (fop->sign)? 0xFFFFFFFF: 0x7FFFFFFF; /* overflow */
|
||||
fop->l = 0xFFFFFFFF;
|
||||
cc = cc | ((fop->sign)? CC_L: CC_G); }
|
||||
if (OP_DPFP (op)) { /* double precision? */
|
||||
D[r1 >> 1].h = fop->h;
|
||||
D[r1 >> 1].l = fop->l; }
|
||||
else { WriteFReg (r1, fop->h); }
|
||||
return cc;
|
||||
}
|
690
Interdata/id_idc.c
Normal file
690
Interdata/id_idc.c
Normal file
|
@ -0,0 +1,690 @@
|
|||
/* id_idc.c: Interdata MSM/IDC disk controller simulator
|
||||
|
||||
Copyright (c) 2001-2002, 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.
|
||||
|
||||
idc MSM/IDC disk controller
|
||||
|
||||
Note: define flag ID_IDC to enable the extra functions of the intelligent
|
||||
disk controller
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
|
||||
#define IDC_NUMBY 256 /* bytes/sector */
|
||||
#define IDC_NUMSC 64 /* sectors/track */
|
||||
|
||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
||||
#define UNIT_V_DTYPE (UNIT_V_UF + 1) /* disk type */
|
||||
#define UNIT_M_DTYPE 0x7
|
||||
#define UNIT_V_AUTO (UNIT_V_UF + 4) /* autosize */
|
||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
||||
#define UNIT_DTYPE (UNIT_M_DTYPE << UNIT_V_DTYPE)
|
||||
#define UNIT_AUTO (1 << UNIT_V_AUTO)
|
||||
#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE)
|
||||
|
||||
#define CYL u3 /* current cylinder */
|
||||
#define HD u4 /* current head */
|
||||
#define STD buf /* drive status */
|
||||
#define FNC wait /* function */
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
|
||||
#define IDC_DRVMASK ((1 << ID_NUMDR) - 1) /* drive bit mask */
|
||||
#define IDC_DIRMASK (IDC_DRVMASK << (i_IDC + 1)) /* drive irq mask */
|
||||
|
||||
/* Controller status */
|
||||
|
||||
#define STC_WRP 0x80 /* write protected */
|
||||
#define STC_ACF 0x40 /* addr cmp fail */
|
||||
#define STC_DEF 0x20 /* def track NI */
|
||||
#define STC_CYO 0x10 /* cylinder ovflo */
|
||||
#define STC_IDL 0x02 /* ctrl idle */
|
||||
#define STC_DTE 0x01 /* xfer error */
|
||||
#define SETC_EX (STC_WRP|STC_ACF|STC_DEF|STC_CYO)
|
||||
#define STC_MASK (STC_WRP|STC_ACF|STC_DEF|STC_CYO|STA_BSY|STC_IDL|STC_DTE)
|
||||
|
||||
/* Controller command */
|
||||
|
||||
#define CMC_MASK 0x3F
|
||||
#define CMC_CLR 0x08 /* reset */
|
||||
#define CMC_RD 0x01 /* read */
|
||||
#define CMC_WR 0x02 /* write */
|
||||
#define CMC_RCHK 0x03 /* read check */
|
||||
#define CMC_FCHK 0x04 /* format check NI */
|
||||
#define CMC_RFMT 0x05 /* read fmt NI */
|
||||
#define CMC_WFMT 0x06 /* write fmt NI */
|
||||
#define CMC_WFTK 0x07 /* write fmt track NI */
|
||||
|
||||
/* IDC only functions */
|
||||
|
||||
#define CMC_RRAM 0x10 /* read RAM */
|
||||
#define CMC_WRAM 0x11 /* write RAM */
|
||||
#define CMC_EXP0 0x12 /* read page 0 NI */
|
||||
#define CMC_RUNC 0x21 /* read uncorr */
|
||||
#define CMC_STST 0x30 /* self test */
|
||||
#define CMC_WLNG 0x32 /* write long NI */
|
||||
#define CMC_LAMP 0x37 /* lamp test */
|
||||
|
||||
#define CMC_DRV 0x100 /* drive func */
|
||||
#define CMC_DRV1 0x200 /* drive func, part 2 */
|
||||
|
||||
/* Drive status, ^ = dynamic, * = in unit status */
|
||||
|
||||
#define STD_WRP 0x80 /* ^write prot */
|
||||
/* 0x40 /* unused */
|
||||
#define STD_ACH 0x20 /* alt chan busy NI */
|
||||
#define STD_UNS 0x10 /* *unsafe */
|
||||
#define STD_NRDY 0x08 /* ^not ready */
|
||||
#define STD_SKI 0x02 /* *seek incomplete */
|
||||
#define STD_OFFL 0x01 /* ^offline */
|
||||
#define STD_UST (STD_UNS | STD_SKI) /* set from unit */
|
||||
#define SETD_EX (STD_WRP | STD_UNS) /* set examine */
|
||||
|
||||
/* Drive command */
|
||||
|
||||
#define CMDF_SHD 0x20 /* set head */
|
||||
#define CMDF_SCY 0x10 /* set cylinder */
|
||||
#define CMD_SK 0x02 /* seek */
|
||||
#define CMD_RST 0x01 /* restore */
|
||||
|
||||
#define CMDX_MASK 0x30 /* ext cmd bits */
|
||||
#define CMDX_RLS 0x80 /* release */
|
||||
#define CMDX_CLF 0x40 /* clear fault */
|
||||
#define CMDX_SVP 0x08 /* servo + */
|
||||
#define CMDX_SVM 0x04 /* servo - */
|
||||
#define CMDX_DSP 0x02 /* strobe + */
|
||||
#define CMDX_DSM 0x01 /* strobe - */
|
||||
|
||||
/* Geometry masks */
|
||||
|
||||
#define CY_MASK 0xFFF /* cylinder */
|
||||
#define HD_MASK 0x1F /* head mask */
|
||||
#define SC_MASK 0x3F /* sector mask */
|
||||
#define HCYL_V_HD 10 /* head/cyl word */
|
||||
#define HCYL_V_CYL 0
|
||||
|
||||
#define GET_SA(cy,sf,sc,t) (((((cy)*drv_tab[t].surf)+(sf))* \
|
||||
IDC_NUMSC)+(sc))
|
||||
|
||||
/* The MSM (IDC) controller supports (two) six different disk drive types:
|
||||
|
||||
type #sectors/ #surfaces/ #cylinders/
|
||||
surface cylinder drive
|
||||
|
||||
MCCDD16 64 1 823 IDC
|
||||
MCCDD48 64 3 823 IDC
|
||||
MCCDD80 64 5 823 IDC
|
||||
MSM80 64 5 823 MSM
|
||||
MSM300 64 19 823 MSM
|
||||
MSM330F 64 16 1024 IDC
|
||||
|
||||
In theory, each drive can be a different type. The size field in
|
||||
each unit selects the drive capacity for each drive and thus the
|
||||
drive type. DISKS MUST BE DECLARED IN ASCENDING SIZE AND MUST HAVE
|
||||
THE SAME SECTORS/TRACK.
|
||||
*/
|
||||
|
||||
#define TYPE_MCCDD16 0
|
||||
#define SURF_MCCDD16 1
|
||||
#define CYL_MCCDD16 823
|
||||
#define SIZE_MCCDD16 (IDC_NUMSC * SURF_MCCDD16 * CYL_MCCDD16 * IDC_NUMBY)
|
||||
|
||||
#define TYPE_MCCDD48 1
|
||||
#define SURF_MCCDD48 3
|
||||
#define CYL_MCCDD48 823
|
||||
#define SIZE_MCCDD48 (IDC_NUMSC * SURF_MCCDD48 * CYL_MCCDD48 * IDC_NUMBY)
|
||||
|
||||
#define TYPE_MCCDD80 2
|
||||
#define SURF_MCCDD80 5
|
||||
#define CYL_MCCDD80 823
|
||||
#define SIZE_MCCDD80 (IDC_NUMSC * SURF_MCCDD80 * CYL_MCCDD80 * IDC_NUMBY)
|
||||
|
||||
#define TYPE_MSM80 3
|
||||
#define SURF_MSM80 5
|
||||
#define CYL_MSM80 823
|
||||
#define SIZE_MSM80 (IDC_NUMSC * SURF_MSM80 * CYL_MSM80 * IDC_NUMBY)
|
||||
|
||||
#define TYPE_MSM300 4
|
||||
#define SURF_MSM300 19
|
||||
#define CYL_MSM300 823
|
||||
#define SIZE_MSM300 (IDC_NUMSC * SURF_MSM300 * CYL_MSM300 * IDC_NUMBY)
|
||||
|
||||
#define TYPE_MSM330F 5
|
||||
#define SURF_MSM330F 16
|
||||
#define CYL_MSM330F 1024
|
||||
#define SIZE_MSM330F (IDC_NUMSC * SURF_MSM330F * CYL_MSM330F * IDC_NUMBY)
|
||||
|
||||
|
||||
struct drvtyp {
|
||||
uint32 surf; /* surfaces */
|
||||
uint32 cyl; /* cylinders */
|
||||
uint32 size; /* #blocks */
|
||||
uint32 msmf; /* MSM drive */
|
||||
};
|
||||
|
||||
static struct drvtyp drv_tab[] = {
|
||||
{ SURF_MCCDD16, CYL_MCCDD16, SIZE_MCCDD16, 0 },
|
||||
{ SURF_MCCDD48, CYL_MCCDD48, SIZE_MCCDD48, 0 },
|
||||
{ SURF_MCCDD80, CYL_MCCDD80, SIZE_MCCDD80, 0 },
|
||||
{ SURF_MSM80, CYL_MSM80, SIZE_MSM80, 1 },
|
||||
{ SURF_MSM300, CYL_MSM300, SIZE_MSM300, 1 },
|
||||
{ SURF_MSM330F, CYL_MSM330F, SIZE_MSM330F, 0 },
|
||||
{ 0 } };
|
||||
|
||||
extern uint32 int_req[INTSZ], int_enb[INTSZ];
|
||||
|
||||
uint8 idcxb[IDC_NUMBY * 3]; /* xfer buffer */
|
||||
uint32 idc_bptr = 0; /* buffer ptr */
|
||||
uint32 idc_db = 0; /* ctrl buffer */
|
||||
uint32 idd_db = 0; /* drive buffer */
|
||||
uint32 idc_sta = 0; /* ctrl status */
|
||||
uint32 idc_sec = 0; /* sector */
|
||||
uint32 idc_hcyl = 0; /* head/cyl */
|
||||
uint32 idc_svun = 0; /* most recent unit */
|
||||
uint32 idc_1st = 0; /* first byte */
|
||||
uint32 idc_arm = 0; /* ctrl armed */
|
||||
uint32 idd_arm[ID_NUMDR] = { 0 }; /* drives armed */
|
||||
uint16 idd_dcy[ID_NUMDR] = { 0 }; /* desired cyl */
|
||||
uint32 idd_sirq = 0; /* drive saved irq */
|
||||
int32 idc_stime = 100; /* seek latency */
|
||||
int32 idc_rtime = 100; /* rotate latency */
|
||||
int32 idc_ctime = 5; /* command latency */
|
||||
uint8 idc_tplte[] = { 0, 1, 2, 3, 4, TPL_END }; /* ctrl + drive */
|
||||
|
||||
DEVICE idc_dev;
|
||||
uint32 id (uint32 dev, uint32 op, uint32 dat);
|
||||
t_stat idc_svc (UNIT *uptr);
|
||||
t_stat idc_reset (DEVICE *dptr);
|
||||
t_stat idc_attach (UNIT *uptr, char *cptr);
|
||||
t_stat idc_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat idc_rds (UNIT *uptr);
|
||||
t_stat idc_wds (UNIT *uptr);
|
||||
t_bool idc_dter (UNIT *uptr, uint32 first);
|
||||
void idc_done (uint32 flg);
|
||||
|
||||
extern t_stat id_dboot (int32 u, DEVICE *dptr);
|
||||
|
||||
/* DP data structures
|
||||
|
||||
idc_dev DP device descriptor
|
||||
idc_unit DP unit list
|
||||
idc_reg DP register list
|
||||
idc_mod DP modifier list
|
||||
*/
|
||||
|
||||
DIB idc_dib = { d_IDC, 0, v_IDC, idc_tplte, &id, NULL };
|
||||
|
||||
UNIT idc_unit[] = {
|
||||
{ UDATA (&idc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+(TYPE_MSM80 << UNIT_V_DTYPE), SIZE_MSM80) },
|
||||
{ UDATA (&idc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+(TYPE_MSM80 << UNIT_V_DTYPE), SIZE_MSM80) },
|
||||
{ UDATA (&idc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+(TYPE_MSM80 << UNIT_V_DTYPE), SIZE_MSM80) },
|
||||
{ UDATA (&idc_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE+(TYPE_MSM80 << UNIT_V_DTYPE), SIZE_MSM80) } };
|
||||
|
||||
REG idc_reg[] = {
|
||||
{ HRDATA (STA, idc_sta, 8) },
|
||||
{ HRDATA (BUF, idc_db, 8) },
|
||||
{ HRDATA (SEC, idc_sec, 8) },
|
||||
{ HRDATA (HCYL, idc_hcyl, 16) },
|
||||
{ HRDATA (BUF, idd_db, 8) },
|
||||
{ HRDATA (SVUN, idc_svun, 2), REG_HIDDEN },
|
||||
{ BRDATA (DBUF, idcxb, 16, 8, IDC_NUMBY * 3) },
|
||||
{ HRDATA (DBPTR, idc_bptr, 10), REG_RO },
|
||||
{ FLDATA (FIRST, idc_1st, 0) },
|
||||
{ GRDATA (IREQ, int_req[l_IDC], 16, ID_NUMDR + 1, i_IDC) },
|
||||
{ GRDATA (IENB, int_enb[l_IDC], 16, ID_NUMDR + 1, i_IDC) },
|
||||
{ GRDATA (SIREQ, idd_sirq, 16, ID_NUMDR, i_IDC + 1), REG_RO },
|
||||
{ FLDATA (ICARM, idc_arm, 0) },
|
||||
{ BRDATA (IDARM, idd_arm, 16, 1, ID_NUMDR) },
|
||||
{ DRDATA (RTIME, idc_rtime, 24), PV_LEFT | REG_NZ },
|
||||
{ DRDATA (STIME, idc_stime, 24), PV_LEFT | REG_NZ },
|
||||
{ DRDATA (CTIME, idc_ctime, 24), PV_LEFT | REG_NZ },
|
||||
{ BRDATA (CYL, idd_dcy, 16, 16, ID_NUMDR) },
|
||||
{ URDATA (UCYL, idc_unit[0].CYL, 16, 12, 0,
|
||||
ID_NUMDR, REG_RO) },
|
||||
{ URDATA (UHD, idc_unit[0].HD, 16, 5, 0,
|
||||
ID_NUMDR, REG_RO) },
|
||||
{ URDATA (UFNC, idc_unit[0].FNC, 16, 10, 0,
|
||||
ID_NUMDR, REG_HRO) },
|
||||
{ URDATA (UST, idc_unit[0].STD, 16, 8, 0,
|
||||
ID_NUMDR, REG_RO) },
|
||||
{ URDATA (CAPAC, idc_unit[0].capac, 10, 31, 0,
|
||||
ID_NUMDR, PV_LEFT | REG_HRO) },
|
||||
{ HRDATA (DEVNO, idc_dib.dno, 8), REG_HRO },
|
||||
{ HRDATA (SELCH, idc_dib.sch, 2), REG_HRO },
|
||||
{ BRDATA (TPLTE, idc_tplte, 16, 8, ID_NUMDR + 1), REG_HRO },
|
||||
{ NULL } };
|
||||
|
||||
MTAB idc_mod[] = {
|
||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
|
||||
{ (UNIT_DTYPE+UNIT_ATT), (TYPE_MCCDD16 << UNIT_V_DTYPE) + UNIT_ATT,
|
||||
"MCCDD16", NULL, NULL },
|
||||
{ (UNIT_DTYPE+UNIT_ATT), (TYPE_MCCDD48 << UNIT_V_DTYPE) + UNIT_ATT,
|
||||
"MCCDD48", NULL, NULL },
|
||||
{ (UNIT_DTYPE+UNIT_ATT), (TYPE_MCCDD80 << UNIT_V_DTYPE) + UNIT_ATT,
|
||||
"MCCDD80", NULL, NULL },
|
||||
{ (UNIT_DTYPE+UNIT_ATT), (TYPE_MSM330F << UNIT_V_DTYPE) + UNIT_ATT,
|
||||
"MSM330F", NULL, NULL },
|
||||
{ (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_MCCDD16 << UNIT_V_DTYPE),
|
||||
"MCCDD16", NULL, NULL },
|
||||
{ (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_MCCDD48 << UNIT_V_DTYPE),
|
||||
"MCCDD48", NULL, NULL },
|
||||
{ (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_MCCDD80 << UNIT_V_DTYPE),
|
||||
"MCCDD80", NULL, NULL },
|
||||
{ (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_MSM330F << UNIT_V_DTYPE),
|
||||
"MSM330F", NULL, NULL },
|
||||
{ (UNIT_AUTO+UNIT_DTYPE), (TYPE_MCCDD16 << UNIT_V_DTYPE),
|
||||
NULL, "MCCDD16", &idc_set_size },
|
||||
{ (UNIT_AUTO+UNIT_DTYPE), (TYPE_MCCDD48 << UNIT_V_DTYPE),
|
||||
NULL, "MCCDD48", &idc_set_size },
|
||||
{ (UNIT_AUTO+UNIT_DTYPE), (TYPE_MCCDD80 << UNIT_V_DTYPE),
|
||||
NULL, "MCCDD80", &idc_set_size },
|
||||
{ (UNIT_AUTO+UNIT_DTYPE), (TYPE_MSM330F << UNIT_V_DTYPE),
|
||||
NULL, "MSM330F", &idc_set_size },
|
||||
{ (UNIT_DTYPE+UNIT_ATT), (TYPE_MSM80 << UNIT_V_DTYPE) + UNIT_ATT,
|
||||
"MSM80", NULL, NULL },
|
||||
{ (UNIT_DTYPE+UNIT_ATT), (TYPE_MSM300 << UNIT_V_DTYPE) + UNIT_ATT,
|
||||
"MSM300", NULL, NULL },
|
||||
{ (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_MSM80 << UNIT_V_DTYPE),
|
||||
"MSM80", NULL, NULL },
|
||||
{ (UNIT_AUTO+UNIT_DTYPE+UNIT_ATT), (TYPE_MSM300 << UNIT_V_DTYPE),
|
||||
"MSM300", NULL, NULL },
|
||||
{ (UNIT_AUTO+UNIT_DTYPE), (TYPE_MSM80 << UNIT_V_DTYPE),
|
||||
NULL, "MSM80", &idc_set_size },
|
||||
{ (UNIT_AUTO+UNIT_DTYPE), (TYPE_MSM300 << UNIT_V_DTYPE),
|
||||
NULL, "MSM300", &idc_set_size },
|
||||
{ (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL },
|
||||
{ UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "SELCH", "SELCH",
|
||||
&set_sch, &show_sch, NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE idc_dev = {
|
||||
"DM", idc_unit, idc_reg, idc_mod,
|
||||
ID_NUMDR, 16, 29, 1, 16, 8,
|
||||
NULL, NULL, &idc_reset,
|
||||
&id_dboot, &idc_attach, NULL,
|
||||
&idc_dib, DEV_DISABLE };
|
||||
|
||||
/* Controller: IO routine */
|
||||
|
||||
uint32 idc (uint32 dev, uint32 op, uint32 dat)
|
||||
{
|
||||
uint32 f, t;
|
||||
UNIT *uptr;
|
||||
|
||||
switch (op) { /* case IO op */
|
||||
case IO_ADR: /* select */
|
||||
sch_adr (idc_dib.sch, dev); /* inform sel ch */
|
||||
return HW; /* halfwords */
|
||||
case IO_RD: /* read data */
|
||||
case IO_RH: /* read halfword */
|
||||
return 0; /* return data */
|
||||
case IO_WD: /* write data */
|
||||
idc_sec = dat; /* sector */
|
||||
break;
|
||||
case IO_WH: /* write halfword */
|
||||
idc_hcyl = dat; /* head/cylinder */
|
||||
break;
|
||||
case IO_SS: /* status */
|
||||
t = idc_sta & STC_MASK; /* get status */
|
||||
if (t & SETC_EX) t = t | STA_EX; /* test for EX */
|
||||
return t;
|
||||
case IO_OC: /* command */
|
||||
idc_arm = int_chg (v_IDC, dat, idc_arm); /* upd int ctrl */
|
||||
f = dat & CMC_MASK; /* get cmd */
|
||||
uptr = idc_dev.units + idc_svun; /* get unit */
|
||||
if (f & CMC_CLR) { /* clear? */
|
||||
idc_reset (&idc_dev); /* reset world */
|
||||
break; }
|
||||
if (!(idc_sta & STC_IDL) || /* if !idle, */
|
||||
sim_is_active (uptr) || /* unit busy, */
|
||||
(f == CMC_EXP0)) break; /* expg, ignore */
|
||||
idc_sta = STA_BSY; /* bsy=1,idl,err=0 */
|
||||
idc_1st = 1; /* xfr not started */
|
||||
idc_bptr = 0; /* buffer empty */
|
||||
uptr->FNC = f; /* save cmd */
|
||||
sim_activate (uptr, idc_rtime); /* schedule */
|
||||
idd_sirq = int_req[l_IDC] & IDC_DIRMASK; /* save drv ints */
|
||||
int_req[l_IDC] = int_req[l_IDC] & ~IDC_DIRMASK; /* clr drv ints */
|
||||
break; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Drives: IO routine */
|
||||
|
||||
uint32 id (uint32 dev, uint32 op, uint32 dat)
|
||||
{
|
||||
uint32 t, u;
|
||||
UNIT *uptr;
|
||||
|
||||
if (dev == idc_dib.dno) return idc (dev, op, dat); /* controller? */
|
||||
u = (dev - idc_dib.dno - o_ID0) / o_ID0; /* get unit num */
|
||||
uptr = idc_dev.units + u; /* get unit ptr */
|
||||
switch (op) { /* case IO op */
|
||||
case IO_ADR: /* select */
|
||||
if (idc_sta & STC_IDL) idc_svun = u; /* idle? save unit */
|
||||
return HW; /* byte only */
|
||||
case IO_RD: /* read data */
|
||||
case IO_RH:
|
||||
return 0;
|
||||
case IO_WD: /* write data */
|
||||
case IO_WH: /* write halfword */
|
||||
idd_db = dat; /* save data */
|
||||
break;
|
||||
case IO_SS: /* status */
|
||||
if (uptr->flags & UNIT_ATT) t =
|
||||
((uptr->flags & UNIT_WPRT)? STD_WRP: 0) |
|
||||
(sim_is_active (uptr)? STD_NRDY: 0) |
|
||||
(uptr->STD & STD_UST);
|
||||
else t = STD_NRDY | STD_OFFL; /* off = X'09' */
|
||||
if (t & SETD_EX) t = t | STA_EX; /* test for ex */
|
||||
return t;
|
||||
case IO_OC: /* command */
|
||||
idd_arm[u] = int_chg (v_IDC + u + 1, dat, idd_arm[u]);
|
||||
if (idd_arm[u] == 0) /* disarmed? */
|
||||
idd_sirq &= ~(1 << (v_IDC + u + 1)); /* clr saved req */
|
||||
if (sim_is_active (uptr) || /* if busy or */
|
||||
!(idc_sta & STC_IDL)) break; /* !idle, ignore */
|
||||
if ((dat & CMC_MASK) == CMDX_MASK) break; /* ignore 0x30 */
|
||||
uptr->FNC = (dat & CMC_MASK) | CMC_DRV; /* save cmd */
|
||||
idc_sta = idc_sta & ~STC_IDL; /* clr idle */
|
||||
sim_activate (uptr, idc_ctime); /* schedule */
|
||||
break; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Unit service
|
||||
|
||||
If drive command, process; if an interrupt is needed (positioning
|
||||
command), schedule second part
|
||||
|
||||
If data transfer command, process; must use selector channel
|
||||
*/
|
||||
|
||||
t_stat idc_svc (UNIT *uptr)
|
||||
{
|
||||
int32 diff;
|
||||
uint32 f, u = uptr - idc_dev.units; /* get unit number */
|
||||
uint32 dtype = GET_DTYPE (uptr->flags); /* get drive type */
|
||||
uint32 t;
|
||||
t_stat r;
|
||||
|
||||
if (uptr->FNC & CMC_DRV) { /* drive cmd? */
|
||||
f = uptr->FNC & CMC_MASK; /* get cmd */
|
||||
if (uptr->FNC & CMC_DRV1) { /* part 2? */
|
||||
if (idd_arm[u]) { /* drv int armed? */
|
||||
if (idc_sta & STC_IDL) /* ctrl idle? */
|
||||
SET_INT (v_IDC + u + 1); /* req intr */
|
||||
else idd_sirq |= (1 << (v_IDC + u + 1)); } /* def intr */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK;
|
||||
if (((f & CMDX_MASK) == 0) && /* seek? */
|
||||
(f & (CMD_SK | CMD_RST))) {
|
||||
if (idd_dcy[u] >= drv_tab[dtype].cyl) /* bad cylinder? */
|
||||
uptr->STD = uptr->STD | STD_SKI; /* error */
|
||||
uptr->CYL = idd_dcy[u]; } /* put on cyl */
|
||||
} /* end if p2 */
|
||||
else { /* part 1 */
|
||||
idc_sta = idc_sta | STC_IDL; /* set idle */
|
||||
uptr->FNC = uptr->FNC | CMC_DRV1; /* set part 2 */
|
||||
if (f >= CMDX_MASK) { /* extended? */
|
||||
if (f & CMDX_CLF) /* clr fault? */
|
||||
uptr->STD = uptr->STD & ~STD_UNS; /* clr unsafe */
|
||||
if (f & (CMDX_RLS | CMDX_SVP | CMDX_SVM)) /* intr expected? */
|
||||
sim_activate (uptr, idc_ctime); }
|
||||
else if (f >= CMDF_SCY) { /* tag? */
|
||||
if (f & CMDF_SHD) uptr->HD = idd_db & HD_MASK;
|
||||
else if (f & CMDF_SCY) {
|
||||
if (idd_db >= drv_tab[dtype].cyl) /* bad cylinder? */
|
||||
uptr->STD = uptr->STD | STD_SKI; /* set seek inc */
|
||||
idd_dcy[u] = idd_db & CY_MASK; } }
|
||||
else if (f & (CMD_SK | CMD_RST)) { /* seek? */
|
||||
if (f == CMD_RST) idd_dcy[u] = 0; /* restore? */
|
||||
if (idd_dcy[u] >= drv_tab[dtype].cyl) { /* bad cylinder? */
|
||||
uptr->STD = uptr->STD | STD_SKI; /* set seek inc */
|
||||
idd_dcy[u] = uptr->CYL; /* no motion */
|
||||
sim_activate (uptr, 0); } /* finish asap */
|
||||
else { /* cylinder ok */
|
||||
uptr->STD = uptr->STD & ~STD_SKI; /* clr seek inc */
|
||||
diff = idd_dcy[u] - uptr->CYL;
|
||||
if (diff < 0) diff = -diff; /* ABS cyl diff */
|
||||
else if (diff == 0) diff = 1; /* must be nz */
|
||||
sim_activate (uptr, diff * idc_stime); } }
|
||||
} /* end else p1 */
|
||||
return SCPE_OK; } /* end if drv */
|
||||
|
||||
switch (uptr->FNC & CMC_MASK) { /* case on func */
|
||||
|
||||
case CMC_RCHK: /* read check */
|
||||
idc_dter (uptr, 1); /* check xfr err */
|
||||
break;
|
||||
|
||||
#if defined (ID_IDC)
|
||||
case CMC_RUNC: /* read uncorr */
|
||||
#endif
|
||||
case CMC_RD: /* read */
|
||||
if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* sch transfer? */
|
||||
if (idc_dter (uptr, idc_1st)) return SCPE_OK; /* dte? done */
|
||||
/* fseek done */
|
||||
if (r = idc_rds (uptr)) return r; /* read sec, err? */
|
||||
idc_1st = 0;
|
||||
t = sch_wrmem (idc_dib.sch, idcxb, IDC_NUMBY); /* write mem */
|
||||
if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* more to do? */
|
||||
sim_activate (uptr, idc_rtime); /* reschedule */
|
||||
return SCPE_OK; }
|
||||
break; } /* no, set done */
|
||||
idc_sta = idc_sta | STC_DTE; /* cant work */
|
||||
break;
|
||||
|
||||
case CMC_WR: /* write */
|
||||
if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* sch transfer? */
|
||||
idc_bptr = sch_rdmem (idc_dib.sch, idcxb, IDC_NUMBY); /* read mem */
|
||||
idc_db = idcxb[idc_bptr - 1]; /* last byte */
|
||||
if (idc_dter (uptr, idc_1st)) return SCPE_OK; /* dte? done */
|
||||
if (r = idc_wds (uptr)) return r; /* write sec, err? */
|
||||
idc_1st = 0;
|
||||
if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* more to do? */
|
||||
sim_activate (uptr, idc_rtime); /* reschedule */
|
||||
return SCPE_OK; }
|
||||
break; } /* no, set done */
|
||||
idc_sta = idc_sta | STC_DTE; /* cant work */
|
||||
break;
|
||||
|
||||
case CMC_FCHK: case CMC_RFMT: case CMC_WFMT: case CMC_WFTK:
|
||||
idc_dter (uptr, 1);
|
||||
idc_sta = idc_sta | STC_WRP;
|
||||
break;
|
||||
|
||||
#if defined (ID_IDC)
|
||||
case CMC_RRAM: /* read RAM */
|
||||
if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* sch transfer? */
|
||||
sch_wrmem (idc_dib.sch, idcxb, IDC_NUMBY * 3);
|
||||
if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* more to do? */
|
||||
sim_activate (uptr, idc_rtime); /* reschedule */
|
||||
return SCPE_OK; }
|
||||
break; } /* no, set done */
|
||||
idc_sta = idc_sta | STC_DTE; /* cant work */
|
||||
break;
|
||||
|
||||
case CMC_WRAM: /* write RAM */
|
||||
if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* sch transfer? */
|
||||
sch_rdmem (idc_dib.sch, idcxb, IDC_NUMBY * 3); /* read from mem */
|
||||
if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* more to do? */
|
||||
sim_activate (uptr, idc_rtime); /* reschedule */
|
||||
return SCPE_OK; }
|
||||
break; } /* no, set done */
|
||||
idc_sta = idc_sta | STC_DTE; /* cant work */
|
||||
break;
|
||||
|
||||
case CMC_STST: case CMC_LAMP: /* tests */
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
idc_sta = idc_sta | STC_DTE;
|
||||
break; }
|
||||
|
||||
idc_done (0); /* done */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Read data sector */
|
||||
|
||||
t_stat idc_rds (UNIT *uptr)
|
||||
{
|
||||
uint32 i;
|
||||
|
||||
i = fxread (idcxb, sizeof (uint8), IDC_NUMBY, uptr->fileref);
|
||||
if (ferror (uptr->fileref)) { /* error? */
|
||||
perror ("IDC I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
idc_done (STC_DTE);
|
||||
return SCPE_IOERR; }
|
||||
for ( ; i < IDC_NUMBY; i++) idcxb[i] = 0; /* fill with 0's */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Write data sector */
|
||||
|
||||
t_bool idc_wds (UNIT *uptr)
|
||||
{
|
||||
for ( ; idc_bptr < IDC_NUMBY; idc_bptr++)
|
||||
idcxb[idc_bptr] = idc_db; /* fill with last */
|
||||
fxwrite (idcxb, sizeof (uint8), IDC_NUMBY, uptr->fileref);
|
||||
if (ferror (uptr->fileref)) { /* error? */
|
||||
perror ("IDC I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
idc_done (STC_DTE);
|
||||
return SCPE_IOERR; }
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Data transfer error test routine */
|
||||
|
||||
t_bool idc_dter (UNIT *uptr, uint32 first)
|
||||
{
|
||||
uint32 cy;
|
||||
uint32 hd, sc, sa;
|
||||
uint32 dtype = GET_DTYPE (uptr->flags); /* get drive type */
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
|
||||
idc_done (STC_DTE); /* error, done */
|
||||
return TRUE; }
|
||||
if ((uptr->flags & UNIT_WPRT) && (uptr->FNC == CMC_WR)) {
|
||||
idc_done (STC_WRP); /* error, done */
|
||||
return TRUE; }
|
||||
cy = uptr->CYL; /* get cylinder */
|
||||
hd = uptr->HD; /* get head */
|
||||
sc = idc_sec & SC_MASK; /* get sector */
|
||||
if (cy >= drv_tab[dtype].cyl) { /* bad cylinder? */
|
||||
uptr->STD = uptr->STD | STD_SKI; /* error */
|
||||
idc_done (STC_DTE); /* error, done */
|
||||
return TRUE; }
|
||||
if (hd >= drv_tab[dtype].surf) { /* bad head? */
|
||||
if (first) { /* 1st xfer? */
|
||||
uptr->STD = uptr->STD | STD_UNS; /* drive unsafe */
|
||||
idc_done (STC_ACF); }
|
||||
else idc_done (STC_CYO); /* no, cyl ovf */
|
||||
return TRUE; }
|
||||
sa = GET_SA (cy, hd, sc, dtype); /* curr disk addr */
|
||||
fseek (uptr->fileref, sa * IDC_NUMBY, SEEK_SET); /* seek to pos */
|
||||
idc_sec = (idc_sec + 1) & SC_MASK; /* incr disk addr */
|
||||
if (idc_sec == 0) uptr->HD = uptr->HD + 1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Data transfer done routine */
|
||||
|
||||
void idc_done (uint32 flg)
|
||||
{
|
||||
idc_sta = (idc_sta | STC_IDL | flg) & ~STA_BSY; /* set flag, idle */
|
||||
if (idc_arm) SET_INT (v_IDC); /* if armed, intr */
|
||||
int_req[l_IDC] = int_req[l_IDC] | idd_sirq; /* restore drv ints */
|
||||
idd_sirq = 0; /* clear saved */
|
||||
if (flg) sch_stop (idc_dib.sch); /* if err, stop sch */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat idc_reset (DEVICE *dptr)
|
||||
{
|
||||
uint32 u;
|
||||
UNIT *uptr;
|
||||
|
||||
idc_sta = STC_IDL | STA_BSY; /* idle, busy */
|
||||
idc_1st = 0; /* clear flag */
|
||||
idc_svun = idc_db = 0; /* clear unit, buf */
|
||||
idc_sec = 0; /* clear addr */
|
||||
idc_hcyl = 0;
|
||||
CLR_INT (v_IDC); /* clear ctrl int */
|
||||
CLR_ENB (v_IDC); /* clear ctrl enb */
|
||||
idc_arm = 0; /* clear ctrl arm */
|
||||
idd_sirq = 0;
|
||||
for (u = 0; u < ID_NUMDR; u++) { /* loop thru units */
|
||||
uptr = idc_dev.units + u;
|
||||
uptr->CYL = uptr->STD = 0;
|
||||
uptr->HD = uptr->FNC = 0;
|
||||
idd_dcy[u] = 0;
|
||||
CLR_INT (v_IDC + u + 1); /* clear intr */
|
||||
CLR_ENB (v_IDC + u + 1); /* clear enable */
|
||||
idd_arm[u] = 0; /* clear arm */
|
||||
sim_cancel (uptr); } /* cancel activity */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Attach routine (with optional autosizing) */
|
||||
|
||||
t_stat idc_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
uint32 i, p;
|
||||
t_stat r;
|
||||
|
||||
uptr->capac = drv_tab[GET_DTYPE (uptr->flags)].size;
|
||||
r = attach_unit (uptr, cptr);
|
||||
uptr->CYL = 0;
|
||||
if ((r != SCPE_OK) || ((uptr->flags & UNIT_AUTO) == 0)) return r;
|
||||
if (fseek (uptr->fileref, 0, SEEK_END)) return SCPE_OK;
|
||||
if ((p = ftell (uptr->fileref)) == 0) return SCPE_OK;
|
||||
for (i = 0; drv_tab[i].surf != 0; i++) {
|
||||
if (p <= drv_tab[i].size) {
|
||||
uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (i << UNIT_V_DTYPE);
|
||||
uptr->capac = drv_tab[i].size;
|
||||
return SCPE_OK; } }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Set size command validation routine */
|
||||
|
||||
t_stat idc_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
|
||||
uptr->capac = drv_tab[GET_DTYPE (val)].size;
|
||||
return SCPE_OK;
|
||||
}
|
542
Interdata/id_io.c
Normal file
542
Interdata/id_io.c
Normal file
|
@ -0,0 +1,542 @@
|
|||
/* id_io.c: Interdata CPU-independent I/O routines
|
||||
|
||||
Copyright (c) 2001-2002, 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.
|
||||
|
||||
Interdata I/O devices are defined by a device information block:
|
||||
|
||||
dno base device number
|
||||
sch selector channel, -1 if none
|
||||
irq interrupt request flag
|
||||
tplte device number template, NULL if one device number
|
||||
iot I/O processing routine
|
||||
ini initialization routine
|
||||
|
||||
Interdata I/O uses the following interconnected tables:
|
||||
|
||||
dev_tab[dev] Indexed by device number, points to the I/O instruction
|
||||
processing routine for the device. Initialized in the
|
||||
device reset routine.
|
||||
|
||||
sch_tab[dev] Indexed by device number, if non-zero, the number + 1
|
||||
of the selector channel used by the device.
|
||||
|
||||
int_req[level] Indexed by interrupt level, device interrupt flags.
|
||||
|
||||
int_enb[level] Indexed by interrupt level, device interrupt enable flags.
|
||||
|
||||
int_tab[idx] Indexed by ((interrupt level * 32) + interrupt number),
|
||||
maps bit positions in int_req to device numbers.
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
|
||||
/* Selector channel */
|
||||
|
||||
#define SCHC_EXA 0x40 /* read ext addr */
|
||||
#define SCHC_RD 0x20 /* read */
|
||||
#define SCHC_GO 0x10 /* go */
|
||||
#define SCHC_STOP 0x08 /* stop */
|
||||
#define SCHC_SSTA 0x04 /* sel ch status */
|
||||
#define SCHC_EXM 0x03 /* ext mem */
|
||||
|
||||
extern uint32 int_req[INTSZ], int_enb[INTSZ];
|
||||
extern uint32 (*dev_tab[DEVNO])(uint32 dev, uint32 op, uint32 datout);
|
||||
extern uint32 pawidth;
|
||||
extern UNIT cpu_unit;
|
||||
extern FILE *sim_log;
|
||||
extern DEVICE *sim_devices[];
|
||||
|
||||
uint32 sch_max = 2; /* sch count */
|
||||
uint32 sch_sa[SCH_NUMCH] = { 0 }; /* start addr */
|
||||
uint32 sch_ea[SCH_NUMCH] = { 0 }; /* end addr */
|
||||
uint8 sch_sdv[SCH_NUMCH] = { 0 }; /* device */
|
||||
uint8 sch_cmd[SCH_NUMCH] = { 0 }; /* command */
|
||||
uint8 sch_rdp[SCH_NUMCH] = { 0 }; /* read ptr */
|
||||
uint8 sch_wdc[SCH_NUMCH] = { 0 }; /* write ctr */
|
||||
uint32 sch_tab[DEVNO] = { 0 }; /* dev to sch map */
|
||||
uint32 int_tab[INTSZ * 32] = { 0 }; /* int to dev map */
|
||||
uint8 sch_tplte[SCH_NUMCH + 1]; /* dnum template */
|
||||
|
||||
uint32 sch (uint32 dev, uint32 op, uint32 dat);
|
||||
void sch_ini (t_bool dtpl);
|
||||
t_stat sch_reset (DEVICE *dptr);
|
||||
t_stat sch_vchan (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
|
||||
/* Selector channel data structures
|
||||
|
||||
sch_dev channel device descriptor
|
||||
sch_unit channel unit descriptor
|
||||
sch_mod channel modifiers list
|
||||
sch_reg channel register list
|
||||
*/
|
||||
|
||||
DIB sch_dib = { d_SCH, -1, v_SCH, sch_tplte, &sch, &sch_ini };
|
||||
|
||||
UNIT sch_unit = { UDATA (NULL, 0, 0) };
|
||||
|
||||
REG sch_reg[] = {
|
||||
{ HRDATA (CHAN, sch_max, 3), REG_HRO },
|
||||
{ BRDATA (SA, sch_sa, 16, 20, SCH_NUMCH) },
|
||||
{ BRDATA (EA, sch_ea, 16, 20, SCH_NUMCH) },
|
||||
{ BRDATA (CMD, sch_cmd, 16, 8, SCH_NUMCH) },
|
||||
{ BRDATA (DEV, sch_sdv, 16, 8, SCH_NUMCH) },
|
||||
{ BRDATA (RDP, sch_rdp, 16, 2, SCH_NUMCH) },
|
||||
{ BRDATA (WDC, sch_wdc, 16, 3, SCH_NUMCH) },
|
||||
{ GRDATA (IREQ, int_req[l_SCH], 16, SCH_NUMCH, i_SCH) },
|
||||
{ GRDATA (IENB, int_enb[l_SCH], 16, SCH_NUMCH, i_SCH) },
|
||||
{ HRDATA (DEVNO, sch_dib.dno, 8), REG_HRO },
|
||||
{ NULL } };
|
||||
|
||||
MTAB sch_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_VAL, 0, "channels", "CHANNELS",
|
||||
&sch_vchan, NULL, &sch_reg[0] },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, &sch_dib },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE sch_dev = {
|
||||
"SELCH", &sch_unit, sch_reg, sch_mod,
|
||||
1, 16, 8, 1, 16, 8,
|
||||
NULL, NULL, &sch_reset,
|
||||
NULL, NULL, NULL,
|
||||
&sch_dib, 0 };
|
||||
|
||||
/* (Extended) selector channel
|
||||
|
||||
There are really three different selector channels:
|
||||
- 16b selector channel (max 4B of data)
|
||||
- 18b selector channel (max 4B of data)
|
||||
- 20b selector channel (max 6B of data)
|
||||
The algorithm for loading the start and end addresses is taken
|
||||
from the maintenance manual for the Extended Selector Channel.
|
||||
*/
|
||||
|
||||
#define SCH_EXR(ch) ((sch_cmd[ch] & SCHC_EXA) && (pawidth == PAWIDTH32))
|
||||
|
||||
uint32 sch (uint32 dev, uint32 op, uint32 dat)
|
||||
{
|
||||
uint32 t, bank, sdv, ch = dev - sch_dib.dno;
|
||||
|
||||
switch (op) { /* case IO op */
|
||||
case IO_ADR: /* select */
|
||||
return BY; /* byte only */
|
||||
case IO_RD: /* read data */
|
||||
t = (sch_sa[ch] >> (sch_rdp[ch] * 8)) & DMASK8; /* get sa byte */
|
||||
if (sch_rdp[ch] == 0) sch_rdp[ch] = /* wrap? */
|
||||
SCH_EXR (ch)? 2: 1;
|
||||
else sch_rdp[ch] = sch_rdp[ch] - 1; /* dec byte ptr */
|
||||
return t;
|
||||
case IO_WD: /* write data */
|
||||
if (pawidth != PAWIDTH32) { /* 16b? max 4 */
|
||||
if (sch_wdc[ch] >= 4) break; /* stop at 4 */
|
||||
sch_sa[ch] = ((sch_sa[ch] << 8) | /* ripple ea to sa */
|
||||
(sch_ea[ch] >> 8)) & DMASK16;
|
||||
sch_ea[ch] = ((sch_ea[ch] << 8) | /* ripple ea low */
|
||||
dat) & DMASK16; } /* insert byte */
|
||||
else { /* 32b? max 6 */
|
||||
if (sch_wdc[ch] >= 6) break; /* stop at 6 */
|
||||
if (sch_wdc[ch] != 5) { /* if not last */
|
||||
sch_sa[ch] = ((sch_sa[ch] << 8) | /* ripple ea<15:8> to sa */
|
||||
((sch_ea[ch] >> 8) & DMASK8)) & PAMASK32;
|
||||
sch_ea[ch] = /* ripple ea<7:0> */
|
||||
(((sch_ea[ch] & DMASK8) << 8) | dat) & PAMASK32; }
|
||||
else sch_ea[ch] = ((sch_ea[ch] << 8) | dat) & PAMASK32; }
|
||||
sch_wdc[ch] = sch_wdc[ch] + 1; /* adv sequencer */
|
||||
break;
|
||||
case IO_SS: /* status */
|
||||
if (sch_cmd[ch] & SCHC_GO) return STA_BSY; /* test busy */
|
||||
if (sch_cmd[ch] & SCHC_SSTA) return 0; /* test sch sta */
|
||||
else {
|
||||
sdv = sch_sdv[ch]; /* get dev */
|
||||
if (dev_tab[sdv] == 0) return CC_V; /* not there? */
|
||||
dev_tab[sdv] (sdv, IO_ADR, 0); /* select dev */
|
||||
t = dev_tab[sdv] (sdv, IO_SS, 0); /* get status */
|
||||
return t & ~STA_BSY; } /* clr busy */
|
||||
case IO_OC: /* command */
|
||||
bank = 0; /* assume no bank */
|
||||
if (pawidth != PAWIDTH32) { /* 16b/18b proc? */
|
||||
dat = dat & ~(SCHC_EXA | SCHC_SSTA); /* clr ext func */
|
||||
if (pawidth == PAWIDTH16E) /* 18b proc? */
|
||||
bank = (dat & SCHC_EXM) << 16; }
|
||||
if (dat & SCHC_STOP) { /* stop? */
|
||||
sch_cmd[ch] = dat & (SCHC_EXA | SCHC_SSTA); /* clr go */
|
||||
CLR_INT (v_SCH + ch); /* clr intr */
|
||||
sch_rdp[ch] = SCH_EXR (ch)? 2: 1; /* init sequencers */
|
||||
sch_wdc[ch] = 0; }
|
||||
else if (dat & SCHC_GO) { /* go? */
|
||||
sch_cmd[ch] = dat & (SCHC_GO | SCHC_RD);
|
||||
if (sch_wdc[ch] <= 4) { /* 4 bytes? */
|
||||
sch_sa[ch] = (sch_sa[ch] & PAMASK16) | bank; /* 16b addr */
|
||||
sch_ea[ch] = (sch_ea[ch] & PAMASK16) | bank; }
|
||||
sch_sa[ch] = sch_sa[ch] & ~1;
|
||||
if (sch_ea[ch] <= sch_sa[ch]) /* wrap? */
|
||||
sch_ea[ch] = sch_ea[ch] | /* modify end addr */
|
||||
((pawidth == PAWIDTH32)? PAMASK32: PAMASK16); }
|
||||
break; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* CPU call to test if channel blocks access to device */
|
||||
|
||||
t_bool sch_blk (uint32 dev)
|
||||
{
|
||||
uint32 ch = sch_tab[dev] - 1;
|
||||
|
||||
if ((ch < sch_max) && (sch_cmd[ch] & SCHC_GO)) return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Device call to 'remember' last dev on channel */
|
||||
|
||||
void sch_adr (uint32 ch, uint32 dev)
|
||||
{
|
||||
if (ch < sch_max) sch_sdv[ch] = dev;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Device call to see if selector channel is active for device */
|
||||
|
||||
t_bool sch_actv (uint32 ch, uint32 dev)
|
||||
{
|
||||
if ((ch < sch_max) && /* chan valid, */
|
||||
(sch_cmd[ch] & SCHC_GO) && /* on, and */
|
||||
(sch_sdv[ch] == dev)) return TRUE; /* set for dev? */
|
||||
return FALSE; /* no */
|
||||
}
|
||||
|
||||
/* Device call to read a block of memory */
|
||||
|
||||
uint32 sch_rdmem (uint32 ch, uint8 *buf, uint32 cnt)
|
||||
{
|
||||
uint32 addr, end, xfr, inc;
|
||||
|
||||
if ((ch >= sch_max) || ((sch_cmd[ch] & SCHC_GO) == 0)) return 0;
|
||||
addr = sch_sa[ch]; /* start */
|
||||
end = sch_ea[ch]; /* end */
|
||||
xfr = MIN (cnt, end - addr + 1); /* sch xfr cnt */
|
||||
inc = IOReadBlk (addr, xfr, buf); /* read mem */
|
||||
if ((addr + inc) > end) { /* end? */
|
||||
SET_INT (v_SCH + ch); /* interrupt */
|
||||
sch_cmd[ch] &= ~(SCHC_GO | SCHC_RD); /* clear GO */
|
||||
sch_sa[ch] = sch_sa[ch] + inc - 1; } /* end addr */
|
||||
else sch_sa[ch] = sch_sa[ch] + inc; /* next addr */
|
||||
return inc;
|
||||
}
|
||||
|
||||
/* Device call to write a block of memory */
|
||||
|
||||
uint32 sch_wrmem (uint32 ch, uint8 *buf, uint32 cnt)
|
||||
{
|
||||
uint32 addr, end, xfr, inc;
|
||||
|
||||
if ((ch >= sch_max) || ((sch_cmd[ch] & SCHC_GO) == 0)) return 0;
|
||||
addr = sch_sa[ch]; /* start */
|
||||
end = sch_ea[ch]; /* end */
|
||||
xfr = MIN (cnt, end - addr + 1); /* sch xfr cnt */
|
||||
inc = IOWriteBlk (addr, xfr, buf); /* write mem */
|
||||
if ((addr + inc) > end) { /* end? */
|
||||
SET_INT (v_SCH + ch); /* interrupt */
|
||||
sch_cmd[ch] &= ~(SCHC_GO | SCHC_RD); /* clear GO */
|
||||
sch_sa[ch] = sch_sa[ch] + inc - 1; } /* end addr */
|
||||
else sch_sa[ch] = sch_sa[ch] + inc; /* next addr */
|
||||
return inc;
|
||||
}
|
||||
|
||||
/* Device call to stop a selector channel */
|
||||
|
||||
void sch_stop (uint32 ch)
|
||||
{
|
||||
if (ch < sch_max) {
|
||||
SET_INT (v_SCH + ch); /* interrupt */
|
||||
sch_cmd[ch] &= ~(SCHC_GO | SCHC_RD); } /* clear GO */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reset */
|
||||
|
||||
void sch_reset_ch (uint32 rst_lim)
|
||||
{
|
||||
uint32 ch;
|
||||
|
||||
for (ch = 0; ch < SCH_NUMCH; ch++) {
|
||||
if (ch >= rst_lim) {
|
||||
CLR_INT (v_SCH + ch);
|
||||
SET_ENB (v_SCH + ch);
|
||||
sch_sa[ch] = sch_ea[ch] = 0;
|
||||
sch_cmd[ch] = sch_sdv[ch] = 0;
|
||||
sch_wdc[ch] = 0;
|
||||
sch_rdp[ch] = 1; } }
|
||||
return;
|
||||
}
|
||||
|
||||
t_stat sch_reset (DEVICE *dptr)
|
||||
{
|
||||
sch_reset_ch (0); /* reset all chan */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Set number of channels */
|
||||
|
||||
t_stat sch_vchan (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
DEVICE *dptr;
|
||||
DIB *dibp;
|
||||
uint32 i, newmax;
|
||||
t_stat r;
|
||||
|
||||
if (cptr == NULL) return SCPE_ARG;
|
||||
newmax = get_uint (cptr, 10, SCH_NUMCH, &r); /* get new max */
|
||||
if ((r != SCPE_OK) || (newmax == sch_max)) return r; /* err or no chg? */
|
||||
if (newmax == 0) return SCPE_ARG; /* must be > 0 */
|
||||
if (newmax < sch_max) { /* reducing? */
|
||||
for (i = 0; dptr = sim_devices[i]; i++) { /* loop thru dev */
|
||||
dibp = (DIB *) dptr->ctxt; /* get DIB */
|
||||
if (dibp && (dibp->sch >= (int32) newmax)) {/* dev using chan? */
|
||||
printf ("Device %02X uses channel %d\n",
|
||||
dibp->dno, dibp->sch);
|
||||
if (sim_log) fprintf (sim_log, "Device %02X uses channel %d\n",
|
||||
dibp->dno, dibp->sch);
|
||||
return SCPE_OK; } } }
|
||||
sch_max = newmax; /* set new max */
|
||||
sch_reset_ch (sch_max); /* reset chan */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Initialize template */
|
||||
|
||||
void sch_ini (t_bool dtpl)
|
||||
{
|
||||
uint32 i;
|
||||
|
||||
for (i = 0; i < sch_max; i++) sch_tplte[i] = i;
|
||||
sch_tplte[sch_max] = TPL_END;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Evaluate interrupt */
|
||||
|
||||
void int_eval (void)
|
||||
{
|
||||
int i;
|
||||
extern uint32 qevent;
|
||||
|
||||
for (i = 0; i < INTSZ; i++)
|
||||
if (int_req[i] & int_enb[i]) {
|
||||
qevent = qevent | EV_INT;
|
||||
return; }
|
||||
qevent = qevent & ~EV_INT;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Return interrupting device */
|
||||
|
||||
uint32 int_getdev (void)
|
||||
{
|
||||
int32 i, j, t;
|
||||
uint32 r;
|
||||
|
||||
for (i = t = 0; i < INTSZ; i++) { /* loop thru array */
|
||||
if (r = int_req[i] & int_enb[i]) { /* find nz int wd */
|
||||
for (j = 0; j < 32; t++, j++) {
|
||||
if (r & (1u << j)) {
|
||||
int_req[i] = int_req[i] & ~(1u << j); /* clr request */
|
||||
return int_tab[t]; } } }
|
||||
else t = t + 32; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Update device interrupt status */
|
||||
|
||||
int32 int_chg (uint32 irq, int32 dat, int32 arm)
|
||||
{
|
||||
int32 t = CMD_GETINT (dat); /* get int ctrl */
|
||||
|
||||
if (t == CMD_IENB) { /* enable? */
|
||||
SET_ENB (irq);
|
||||
return 1; }
|
||||
else if (t == CMD_IDIS) { /* disable? */
|
||||
CLR_ENB (irq);
|
||||
return 1; }
|
||||
if (t == CMD_IDSA) { /* disarm? */
|
||||
CLR_ENB (irq);
|
||||
CLR_INT (irq);
|
||||
return 0; }
|
||||
return arm;
|
||||
}
|
||||
|
||||
/* Process a 2b field and return unchanged, set, clear, complement */
|
||||
|
||||
int32 io_2b (int32 val, int32 pos, int32 old)
|
||||
{
|
||||
int32 t = (val >> pos) & 3;
|
||||
if (t == 0) return old;
|
||||
if (t == 1) return 1;
|
||||
if (t == 2) return 0;
|
||||
return old ^1;
|
||||
}
|
||||
|
||||
/* Block transfer routines */
|
||||
|
||||
uint32 IOReadBlk (uint32 loc, uint32 cnt, uint8 *buf)
|
||||
{
|
||||
uint32 i;
|
||||
|
||||
if (!MEM_ADDR_OK (loc) || (cnt == 0)) return 0;
|
||||
if (!MEM_ADDR_OK (loc + cnt - 1)) cnt = MEMSIZE - loc;
|
||||
for (i = 0; i < cnt; i++) buf[i] = IOReadB (loc + i);
|
||||
return cnt;
|
||||
}
|
||||
|
||||
uint32 IOWriteBlk (uint32 loc, uint32 cnt, uint8 *buf)
|
||||
{
|
||||
uint32 i;
|
||||
|
||||
if (!MEM_ADDR_OK (loc) || (cnt == 0)) return 0;
|
||||
if (!MEM_ADDR_OK (loc + cnt - 1)) cnt = MEMSIZE - loc;
|
||||
for (i = 0; i < cnt; i++) IOWriteB (loc + i, buf[i]);
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/* Change selector channel for a device */
|
||||
|
||||
t_stat set_sch (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
DEVICE *dptr;
|
||||
DIB *dibp;
|
||||
uint32 newch;
|
||||
t_stat r;
|
||||
|
||||
if (cptr == NULL) return SCPE_ARG;
|
||||
if (uptr == NULL) return SCPE_IERR;
|
||||
dptr = find_dev_from_unit (uptr);
|
||||
if (dptr == NULL) return SCPE_IERR;
|
||||
dibp = (DIB *) dptr->ctxt;
|
||||
if ((dibp == NULL) || (dibp->sch < 0)) return SCPE_IERR;
|
||||
newch = get_uint (cptr, 16, sch_max - 1, &r); /* get new */
|
||||
if (r != SCPE_OK) return r;
|
||||
dibp->sch = newch; /* store */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Show selector channel for a device */
|
||||
|
||||
t_stat show_sch (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
DEVICE *dptr;
|
||||
DIB *dibp;
|
||||
|
||||
if (uptr == NULL) return SCPE_IERR;
|
||||
dptr = find_dev_from_unit (uptr);
|
||||
if (dptr == NULL) return SCPE_IERR;
|
||||
dibp = (DIB *) dptr->ctxt;
|
||||
if ((dibp == NULL) || (dibp->sch < 0)) return SCPE_IERR;
|
||||
fprintf (st, "selch=%X", dibp->sch);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Change device number for a device */
|
||||
|
||||
t_stat set_dev (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
DEVICE *dptr;
|
||||
DIB *dibp;
|
||||
uint32 newdev;
|
||||
t_stat r;
|
||||
|
||||
if (cptr == NULL) return SCPE_ARG;
|
||||
if (uptr == NULL) return SCPE_IERR;
|
||||
dptr = find_dev_from_unit (uptr);
|
||||
if (dptr == NULL) return SCPE_IERR;
|
||||
dibp = (DIB *) dptr->ctxt;
|
||||
if (dibp == NULL) return SCPE_IERR;
|
||||
newdev = get_uint (cptr, 16, DEV_MAX, &r); /* get new */
|
||||
if ((r != SCPE_OK) || (newdev == dibp->dno)) return r;
|
||||
if (newdev == 0) return SCPE_ARG; /* must be > 0 */
|
||||
dibp->dno = newdev; /* store */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Show device number for a device */
|
||||
|
||||
t_stat show_dev (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
DEVICE *dptr;
|
||||
DIB *dibp;
|
||||
|
||||
if (uptr == NULL) return SCPE_IERR;
|
||||
dptr = find_dev_from_unit (uptr);
|
||||
if (dptr == NULL) return SCPE_IERR;
|
||||
dibp = (DIB *) dptr->ctxt;
|
||||
if ((dibp == NULL) || (dibp->dno == 0)) return SCPE_IERR;
|
||||
fprintf (st, "devno=%02X", dibp->dno);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Init device tables */
|
||||
|
||||
t_bool devtab_init (void)
|
||||
{
|
||||
DEVICE *dptr;
|
||||
DIB *dibp;
|
||||
uint32 i, j, dno, dmsk, doff, t, dmap[DEVNO / 32];
|
||||
uint8 *tplte, dflt_tplte[] = { 0, TPL_END };
|
||||
|
||||
/* Clear tables, device map */
|
||||
|
||||
for (i = 0; i < DEVNO; i++) {
|
||||
dev_tab[i] = NULL;
|
||||
sch_tab[i] = 0; }
|
||||
for (i = 0; i < (INTSZ * 32); i++) int_tab[i] = 0;
|
||||
for (i = 0; i < (DEVNO / 32); i++) dmap[i] = 0;
|
||||
|
||||
/* Test each device for conflict; add to map; init tables */
|
||||
|
||||
for (i = 0; dptr = sim_devices[i]; i++) { /* loop thru devices */
|
||||
dibp = (DIB *) dptr->ctxt; /* get DIB */
|
||||
if ((dibp == NULL) || (dptr->flags & DEV_DIS)) continue; /* exist, enabled? */
|
||||
dno = dibp->dno; /* get device num */
|
||||
if (dibp->ini) dibp->ini (TRUE); /* gen dno template */
|
||||
tplte = dibp->tplte; /* get template */
|
||||
if (tplte == NULL) tplte = dflt_tplte; /* none? use default */
|
||||
for ( ; *tplte != TPL_END; tplte++) { /* loop thru template */
|
||||
t = (dno + *tplte) & DEV_MAX; /* loop thru template */
|
||||
dmsk = 1u << (t & 0x1F); /* bit to test */
|
||||
doff = t / 32; /* word to test */
|
||||
if (dmap[doff] & dmsk) { /* in use? */
|
||||
printf ("Device number conflict, devno = %02X\n", t);
|
||||
if (sim_log) fprintf (sim_log,
|
||||
"Device number conflict, devno = %02X\n", t);
|
||||
return TRUE; }
|
||||
dmap[doff] = dmap[doff] | dmsk;
|
||||
if (dibp->sch >= 0) sch_tab[t] = dibp->sch + 1;
|
||||
dev_tab[t] = dibp->iot; }
|
||||
|
||||
if (dibp->ini) dibp->ini (FALSE); /* gen int template */
|
||||
tplte = dibp->tplte; /* get template */
|
||||
if (tplte == NULL) tplte = dflt_tplte; /* none? use default */
|
||||
for (j = dibp->irq; *tplte != TPL_END; j++, tplte++) {
|
||||
int_tab[j] = (dno + *tplte) & DEV_MAX; }
|
||||
} /* end for i */
|
||||
return FALSE;
|
||||
}
|
288
Interdata/id_lp.c
Normal file
288
Interdata/id_lp.c
Normal file
|
@ -0,0 +1,288 @@
|
|||
/* id_lp.c: Interdata line printer
|
||||
|
||||
Copyright (c) 2001-2002, 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.
|
||||
|
||||
lpt M46-206 line printer
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
#include <ctype.h>
|
||||
|
||||
/* Device definitions */
|
||||
|
||||
#define UNIT_V_UC (UNIT_V_UF + 0) /* UC only */
|
||||
#define UNIT_UC (1 << UNIT_V_UC)
|
||||
#define SPC_BASE 0x40 /* spacing base */
|
||||
#define VFU_BASE 0x78 /* VFU base */
|
||||
#define VFU_WIDTH 0x8 /* VFU width */
|
||||
#define LF 0xA
|
||||
#define VT 0xB
|
||||
#define VT_VFU 4 /* VFU chan for VT */
|
||||
#define FF 0xC
|
||||
#define FF_VFU 8 /* VFU chan for FF */
|
||||
#define CR 0xD
|
||||
#define VFUP(ch,val) ((val) & (1 << (ch))) /* VFU chan test */
|
||||
|
||||
/* Status byte, * = dynamic */
|
||||
|
||||
#define STA_PAPE 0x40 /* *paper empty */
|
||||
#define STA_MASK (STA_BSY) /* static status */
|
||||
|
||||
uint32 lpt_sta = STA_BSY; /* status */
|
||||
char lpxb[LPT_WIDTH + 1]; /* line buffer */
|
||||
uint32 lpt_bptr = 0; /* buf ptr */
|
||||
uint32 lpt_spnd = 0; /* space pending */
|
||||
uint32 lpt_vfup = 0; /* VFU ptr */
|
||||
uint32 lpt_vful = 1; /* VFU lnt */
|
||||
uint8 lpt_vfut[VFU_LNT] = { 0xFF }; /* VFU tape */
|
||||
uint32 lpt_arm = 0; /* int armed */
|
||||
int32 lpt_ctime = 10; /* char time */
|
||||
int32 lpt_stime = 1000; /* space time */
|
||||
int32 lpt_stopioe = 0; /* stop on err */
|
||||
|
||||
extern uint32 int_req[INTSZ], int_enb[INTSZ];
|
||||
|
||||
DEVICE lpt_dev;
|
||||
uint32 lpt (uint32 dev, uint32 op, uint32 dat);
|
||||
t_stat lpt_svc (UNIT *uptr);
|
||||
t_stat lpt_reset (DEVICE *dptr);
|
||||
t_stat lpt_attach (UNIT *uptr, char *cptr);
|
||||
t_stat lpt_bufout (UNIT *uptr);
|
||||
t_stat lpt_vfu (UNIT *uptr, int32 ch);
|
||||
t_stat lpt_spc (UNIT *uptr, int32 cnt);
|
||||
|
||||
/* LPT data structures
|
||||
|
||||
lpt_dev LPT device descriptor
|
||||
lpt_unit LPT unit descriptors
|
||||
lpt_reg LPT register list
|
||||
*/
|
||||
|
||||
DIB lpt_dib = { d_LPT, -1, v_LPT, NULL, &lpt, NULL };
|
||||
|
||||
UNIT lpt_unit = { UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_UC, 0) };
|
||||
|
||||
REG lpt_reg[] = {
|
||||
{ HRDATA (STA, lpt_sta, 8) },
|
||||
{ HRDATA (BUF, lpt_unit.buf, 7) },
|
||||
{ BRDATA (DBUF, lpxb, 16, 7, LPT_WIDTH) },
|
||||
{ HRDATA (DBPTR, lpt_bptr, 8) },
|
||||
{ HRDATA (VFUP, lpt_vfup, 8) },
|
||||
{ HRDATA (VFUL, lpt_vful, 8) },
|
||||
{ BRDATA (VFUT, lpt_vfut, 16, 8, VFU_LNT) },
|
||||
{ FLDATA (IREQ, int_req[l_LPT], i_LPT) },
|
||||
{ FLDATA (IENB, int_enb[l_LPT], i_LPT) },
|
||||
{ FLDATA (IARM, lpt_arm, 0) },
|
||||
{ DRDATA (POS, lpt_unit.pos, 32), PV_LEFT },
|
||||
{ DRDATA (CTIME, lpt_ctime, 24), PV_LEFT },
|
||||
{ DRDATA (STIME, lpt_stime, 24), PV_LEFT },
|
||||
{ FLDATA (STOP_IOE, lpt_stopioe, 0) },
|
||||
{ HRDATA (DEVNO, lpt_dib.dno, 8), REG_HRO },
|
||||
{ NULL } };
|
||||
|
||||
MTAB lpt_mod[] = {
|
||||
{ UNIT_UC, 0, "lower case", "LC", NULL },
|
||||
{ UNIT_UC, UNIT_UC, "upper case", "UC", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE lpt_dev = {
|
||||
"LPT", &lpt_unit, lpt_reg, lpt_mod,
|
||||
1, 10, 31, 1, 16, 7,
|
||||
NULL, NULL, &lpt_reset,
|
||||
NULL, &lpt_attach, NULL,
|
||||
&lpt_dib, DEV_DISABLE };
|
||||
|
||||
/* Line printer: IO routine */
|
||||
|
||||
uint32 lpt (uint32 dev, uint32 op, uint32 dat)
|
||||
{
|
||||
int32 t;
|
||||
|
||||
switch (op) { /* case IO op */
|
||||
case IO_ADR: /* select */
|
||||
return BY; /* byte only */
|
||||
case IO_OC: /* command */
|
||||
lpt_arm = int_chg (v_LPT, dat, lpt_arm); /* upd int ctrl */
|
||||
break;
|
||||
case IO_WD: /* write */
|
||||
t = lpt_unit.buf = dat & 0x7F; /* mask char */
|
||||
lpt_sta = STA_BSY; /* set busy */
|
||||
if (lpt_spnd || ((t >= LF) && (t <= CR))) /* space op? */
|
||||
sim_activate (&lpt_unit, lpt_stime);
|
||||
else sim_activate (&lpt_unit, lpt_ctime); /* normal char */
|
||||
break;
|
||||
case IO_SS: /* status */
|
||||
t = lpt_sta & STA_MASK; /* status byte */
|
||||
if ((lpt_unit.flags & UNIT_ATT) == 0) /* test paper out */
|
||||
t = t | STA_EX | STA_PAPE | STA_BSY;
|
||||
return t; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Unit service */
|
||||
|
||||
t_stat lpt_svc (UNIT *uptr)
|
||||
{
|
||||
int32 t;
|
||||
t_stat r = SCPE_OK;
|
||||
|
||||
lpt_sta = 0; /* clear busy */
|
||||
if (lpt_arm) SET_INT (v_LPT); /* armed? intr */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
|
||||
return IORETURN (lpt_stopioe, SCPE_UNATT);
|
||||
t = uptr->buf; /* get character */
|
||||
if (lpt_spnd || ((t >= LF) && (t < CR))) { /* spc pend or spc op? */
|
||||
lpt_spnd = 0;
|
||||
if (lpt_bufout (uptr) != SCPE_OK) return SCPE_IOERR; /* print */
|
||||
if ((t == 1) || (t == LF)) lpt_spc (uptr, 1); /* single space */
|
||||
else if (t == VT) r = lpt_vfu (uptr, VT_VFU - 1); /* VT->VFU */
|
||||
else if (t == 0xC) r = lpt_vfu (uptr, FF_VFU - 1); /* FF->VFU */
|
||||
else if ((t >= SPC_BASE) && (t < VFU_BASE))
|
||||
lpt_spc (uptr, t - SPC_BASE); /* space */
|
||||
else if ((t >= VFU_BASE) && (t < VFU_BASE + VFU_WIDTH))
|
||||
r = lpt_vfu (uptr, t - VFU_BASE); /* VFU */
|
||||
else fputs ("\r", uptr->fileref); /* overprint */
|
||||
uptr->pos = ftell (uptr->fileref); /* update position */
|
||||
if (ferror (lpt_unit.fileref)) {
|
||||
perror ("LPT I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
return SCPE_IOERR; } }
|
||||
else if (t == CR) { /* CR? */
|
||||
lpt_spnd = 1; /* set spc pend */
|
||||
return lpt_bufout (uptr); } /* print line */
|
||||
else if (t >= 0x40) { /* printable? */
|
||||
if ((uptr->flags & UNIT_UC) && islower (t)) /* UC only? */
|
||||
t = toupper (t);
|
||||
if (lpt_bptr < LPT_WIDTH) lpxb[lpt_bptr++] = t; }
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Printing and spacing routines */
|
||||
|
||||
t_stat lpt_bufout (UNIT *uptr)
|
||||
{
|
||||
int32 i;
|
||||
t_stat r = SCPE_OK;
|
||||
|
||||
if (lpt_bptr == 0) return SCPE_OK; /* any char in buf? */
|
||||
for (i = LPT_WIDTH - 1; (i >= 0) && (lpxb[i] == ' '); i--)
|
||||
lpxb[i] = 0; /* backscan line */
|
||||
if (lpxb[0]) { /* any char left? */
|
||||
fputs (lpxb, uptr->fileref); /* write line */
|
||||
lpt_unit.pos = ftell (uptr->fileref); /* update position */
|
||||
if (ferror (uptr->fileref)) {
|
||||
perror ("LPT I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
r = SCPE_IOERR; } }
|
||||
lpt_bptr = 0; /* reset buffer */
|
||||
for (i = 0; i < LPT_WIDTH; i++) lpxb[i] = ' ';
|
||||
lpxb[LPT_WIDTH] = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
t_stat lpt_vfu (UNIT *uptr, int32 ch)
|
||||
{
|
||||
uint32 i, j;
|
||||
|
||||
if ((ch == (FF_VFU - 1)) && VFUP (ch, lpt_vfut[0])) { /* top of form? */
|
||||
fputs ("\n\f", uptr->fileref); /* nl + ff */
|
||||
lpt_vfup = 0; /* top of page */
|
||||
return SCPE_OK; }
|
||||
for (i = 1; i < lpt_vful + 1; i++) { /* sweep thru cct */
|
||||
lpt_vfup = (lpt_vfup + 1) % lpt_vful; /* adv pointer */
|
||||
if (VFUP (ch, lpt_vfut[lpt_vfup])) { /* chan punched? */
|
||||
for (j = 0; j < i; j++) fputc ('\n', uptr->fileref);
|
||||
return SCPE_OK; } }
|
||||
return STOP_VFU; /* runaway channel */
|
||||
}
|
||||
|
||||
t_stat lpt_spc (UNIT *uptr, int32 cnt)
|
||||
{
|
||||
int32 i;
|
||||
|
||||
if (cnt == 0) fputc ('\r', uptr->fileref);
|
||||
else { for (i = 0; i < cnt; i++) fputc ('\n', uptr->fileref);
|
||||
lpt_vfup = (lpt_vfup + cnt) % lpt_vful; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat lpt_reset (DEVICE *dptr)
|
||||
{
|
||||
int32 i;
|
||||
|
||||
sim_cancel (&lpt_unit); /* deactivate */
|
||||
lpt_sta = 0; /* clr busy */
|
||||
lpt_bptr = 0; /* clr buf ptr */
|
||||
for (i = 0; i < LPT_WIDTH; i++) lpxb[i] = ' '; /* clr buf */
|
||||
lpxb[LPT_WIDTH] = 0;
|
||||
CLR_INT (v_LPT); /* clearr int */
|
||||
CLR_ENB (v_LPT); /* disable int */
|
||||
lpt_arm = 0; /* disarm int */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Attach routine */
|
||||
|
||||
t_stat lpt_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
lpt_vfup = 0; /* top of form */
|
||||
return attach_unit (uptr, cptr);
|
||||
}
|
||||
|
||||
/* Carriage control load routine */
|
||||
|
||||
t_stat lp_load (FILE *fileref, char *cptr, char *fnam)
|
||||
{
|
||||
int32 col, ptr, mask, vfubuf[VFU_LNT];
|
||||
uint32 rpt;
|
||||
t_stat r;
|
||||
char cbuf[CBUFSIZE], gbuf[CBUFSIZE];
|
||||
|
||||
if (*cptr != 0) return SCPE_ARG;
|
||||
ptr = 0;
|
||||
for ( ; (cptr = fgets (cbuf, CBUFSIZE, fileref)) != NULL; ) { /* until eof */
|
||||
mask = 0;
|
||||
if (*cptr == '(') { /* repeat count? */
|
||||
cptr = get_glyph (cptr + 1, gbuf, ')'); /* get 1st field */
|
||||
rpt = get_uint (gbuf, 10, VFU_LNT, &r); /* repeat count */
|
||||
if (r != SCPE_OK) return SCPE_FMT; }
|
||||
else rpt = 1;
|
||||
while (*cptr != 0) { /* get col no's */
|
||||
cptr = get_glyph (cptr, gbuf, ','); /* get next field */
|
||||
col = get_uint (gbuf, 10, 7, &r); /* column number */
|
||||
if (r != SCPE_OK) return SCPE_FMT;
|
||||
mask = mask | (1 << col); } /* set bit */
|
||||
for ( ; rpt > 0; rpt--) { /* store vals */
|
||||
if (ptr >= VFU_LNT) return SCPE_FMT;
|
||||
vfubuf[ptr++] = mask; } }
|
||||
if (ptr == 0) return SCPE_FMT;
|
||||
lpt_vful = ptr;
|
||||
lpt_vfup = 0;
|
||||
for (rpt = 0; rpt < lpt_vful; rpt++) lpt_vfut[rpt] = vfubuf[rpt];
|
||||
return SCPE_OK;
|
||||
}
|
529
Interdata/id_mt.c
Normal file
529
Interdata/id_mt.c
Normal file
|
@ -0,0 +1,529 @@
|
|||
/* id_mt.c: Interdata magnetic tape simulator
|
||||
|
||||
Copyright (c) 2001-2002, 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.
|
||||
|
||||
mt M46-494 dual density 9-track magtape controller
|
||||
|
||||
Magnetic tapes are represented as a series of variable 8b records
|
||||
of the form:
|
||||
|
||||
32b record length in bytes - exact number
|
||||
byte 0
|
||||
byte 1
|
||||
:
|
||||
byte n-2
|
||||
byte n-1
|
||||
32b record length in bytes - exact number
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
|
||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
||||
#define UNIT_V_PNU (UNIT_V_UF + 1) /* pos not updated */
|
||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
||||
#define UNIT_PNU (1 << UNIT_V_PNU)
|
||||
#define UST u3 /* unit status */
|
||||
#define UCMD u4 /* unit command */
|
||||
#define MT_MAXFR (1 << 16) /* max transfer */
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
|
||||
/* Command - in UCMD */
|
||||
|
||||
#define MTC_SPCR 0x11 /* backspace */
|
||||
#define MTC_SKFR 0x13 /* space file rev */
|
||||
#define MTC_CLR 0x20 /* clear */
|
||||
#define MTC_RD 0x21 /* read */
|
||||
#define MTC_WR 0x22 /* write */
|
||||
#define MTC_SKFF 0x23 /* space file fwd */
|
||||
#define MTC_WEOF 0x30 /* write eof */
|
||||
#define MTC_REW 0x38 /* rewind */
|
||||
#define MTC_MASK 0x3F
|
||||
#define MTC_STOP1 0x40 /* stop, set EOM */
|
||||
#define MTC_STOP2 0x80 /* stop, set NMTN */
|
||||
|
||||
/* Status byte, * = in UST */
|
||||
|
||||
#define STA_ERR 0x80 /* error */
|
||||
#define STA_EOF 0x40 /* end of file */
|
||||
#define STA_EOT 0x20 /* *end of tape */
|
||||
#define STA_NMTN 0x10 /* *no motion */
|
||||
#define STA_UFLGS (STA_EOT|STA_NMTN) /* unit flags */
|
||||
#define STA_MASK (STA_ERR|STA_EOF|STA_BSY|STA_EOM)
|
||||
#define SET_EX (STA_ERR|STA_EOF|STA_NMTN)
|
||||
|
||||
extern uint32 int_req[INTSZ], int_enb[INTSZ];
|
||||
|
||||
uint8 mtxb[MT_MAXFR]; /* xfer buffer */
|
||||
uint32 mt_bptr = 0; /* pointer */
|
||||
uint32 mt_blnt = 0; /* length */
|
||||
uint32 mt_sta = 0; /* status byte */
|
||||
uint32 mt_db = 0; /* data buffer */
|
||||
uint32 mt_xfr = 0; /* data xfr in prog */
|
||||
uint32 mt_arm[MT_NUMDR] = { 0 }; /* intr armed */
|
||||
int32 mt_wtime = 10; /* byte latency */
|
||||
int32 mt_rtime = 1000; /* record latency */
|
||||
int32 mt_stopioe = 1; /* stop on error */
|
||||
uint8 mt_tplte[] = { 0, o_MT0, o_MT0*2, o_MT0*3, TPL_END };
|
||||
|
||||
static const uint8 bad_cmd[64] = {
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 };
|
||||
|
||||
DEVICE mt_dev;
|
||||
uint32 mt (uint32 dev, uint32 op, uint32 dat);
|
||||
t_bool mt_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
||||
t_bool mt_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
||||
t_bool mt_forwsp (UNIT *uptr, int32 *err);
|
||||
t_bool mt_backsp (UNIT *uptr, int32 *err);
|
||||
t_stat mt_svc (UNIT *uptr);
|
||||
t_stat mt_reset (DEVICE *dptr);
|
||||
t_stat mt_attach (UNIT *uptr, char *cptr);
|
||||
t_stat mt_detach (UNIT *uptr);
|
||||
t_stat mt_boot (int32 unitno, DEVICE *dptr);
|
||||
|
||||
/* MT data structures
|
||||
|
||||
mt_dev MT device descriptor
|
||||
mt_unit MT unit list
|
||||
mt_reg MT register list
|
||||
mt_mod MT modifier list
|
||||
*/
|
||||
|
||||
DIB mt_dib = { d_MT, 0, v_MT, mt_tplte, &mt, NULL };
|
||||
|
||||
UNIT mt_unit[] = {
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_DISABLE, 0) } };
|
||||
|
||||
REG mt_reg[] = {
|
||||
{ HRDATA (STA, mt_sta, 8) },
|
||||
{ HRDATA (BUF, mt_db, 8) },
|
||||
{ BRDATA (DBUF, mtxb, 16, 8, MT_MAXFR) },
|
||||
{ HRDATA (DBPTR, mt_bptr, 16) },
|
||||
{ HRDATA (DBLNT, mt_blnt, 17), REG_RO },
|
||||
{ FLDATA (XFR, mt_xfr, 0) },
|
||||
{ GRDATA (IREQ, int_req[l_MT], 16, MT_NUMDR, i_MT) },
|
||||
{ GRDATA (IENB, int_enb[l_MT], 16, MT_NUMDR, i_MT) },
|
||||
{ BRDATA (IARM, mt_arm, 16, 1, MT_NUMDR) },
|
||||
{ FLDATA (STOP_IOE, mt_stopioe, 0) },
|
||||
{ DRDATA (WTIME, mt_wtime, 24), PV_LEFT + REG_NZ },
|
||||
{ DRDATA (RTIME, mt_rtime, 24), PV_LEFT + REG_NZ },
|
||||
{ URDATA (UST, mt_unit[0].UST, 16, 8, 0, MT_NUMDR, 0) },
|
||||
{ URDATA (CMD, mt_unit[0].UCMD, 16, 8, 0, MT_NUMDR, 0) },
|
||||
{ URDATA (POS, mt_unit[0].pos, 10, 32, 0,
|
||||
MT_NUMDR, PV_LEFT | REG_RO) },
|
||||
{ HRDATA (DEVNO, mt_dib.dno, 8), REG_HRO },
|
||||
{ HRDATA (SELCH, mt_dib.sch, 1), REG_HRO },
|
||||
{ NULL } };
|
||||
|
||||
MTAB mt_mod[] = {
|
||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "SELCH", "SELCH",
|
||||
&set_sch, &show_sch, NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE mt_dev = {
|
||||
"MT", mt_unit, mt_reg, mt_mod,
|
||||
MT_NUMDR, 10, 31, 1, 16, 8,
|
||||
NULL, NULL, &mt_reset,
|
||||
&mt_boot, &mt_attach, &mt_detach,
|
||||
&mt_dib, DEV_DISABLE };
|
||||
|
||||
/* Magtape: IO routine */
|
||||
|
||||
uint32 mt (uint32 dev, uint32 op, uint32 dat)
|
||||
{
|
||||
uint32 i, f, t;
|
||||
uint32 u = (dev - mt_dib.dno) / o_MT0;
|
||||
UNIT *uptr = mt_dev.units + u;
|
||||
|
||||
switch (op) { /* case IO op */
|
||||
case IO_ADR: /* select */
|
||||
sch_adr (mt_dib.sch, dev); /* inform sel ch */
|
||||
return BY; /* byte only */
|
||||
case IO_RD: /* read data */
|
||||
if (mt_xfr) mt_sta = mt_sta | STA_BSY; /* xfr? set busy */
|
||||
return mt_db; /* return data */
|
||||
case IO_WD: /* write data */
|
||||
if (mt_xfr) { /* transfer? */
|
||||
mt_sta = mt_sta | STA_BSY; /* set busy */
|
||||
if ((uptr->UCMD & (MTC_STOP1 | MTC_STOP2)) &&
|
||||
((uptr->UCMD & MTC_MASK) == MTC_WR)) /* while stopping? */
|
||||
mt_sta = mt_sta | STA_ERR; } /* write overrun */
|
||||
mt_db = dat & DMASK8; /* store data */
|
||||
break;
|
||||
case IO_SS: /* status */
|
||||
mt_sta = mt_sta & STA_MASK; /* ctrl status */
|
||||
if (uptr->flags & UNIT_ATT) /* attached? */
|
||||
t = mt_sta | (uptr->UST & STA_UFLGS); /* yes, unit status */
|
||||
else t = mt_sta | STA_DU; /* no, dev unavail */
|
||||
if (t & SET_EX) t = t | STA_EX; /* test for ex */
|
||||
return t;
|
||||
case IO_OC: /* command */
|
||||
mt_arm[u] = int_chg (v_MT + u, dat, mt_arm[u]);
|
||||
f = dat & MTC_MASK; /* get cmd */
|
||||
if (f == MTC_CLR) { /* clear? */
|
||||
mt_reset (&mt_dev); /* reset world */
|
||||
break; }
|
||||
if (((uptr->flags & UNIT_ATT) == 0) || /* ignore if unatt */
|
||||
bad_cmd[f] || /* or bad cmd */
|
||||
(((f == MTC_WR) || (f == MTC_WEOF)) && /* or write */
|
||||
(uptr->flags & UNIT_WPRT))) break; /* and protected */
|
||||
for (i = 0; i < MT_NUMDR; i++) { /* check other drvs */
|
||||
if (sim_is_active (&mt_unit[i]) && /* active? */
|
||||
(mt_unit[i].UCMD != MTC_REW)) { /* not rewind? */
|
||||
sim_cancel (&mt_unit[i]); /* stop */
|
||||
mt_unit[i].UCMD = 0; }
|
||||
if (sim_is_active (uptr) && /* unit active? */
|
||||
!(uptr->UCMD & (MTC_STOP1 | MTC_STOP2))) /* not stopping? */
|
||||
break; /* ignore */
|
||||
if ((f == MTC_WR) || (f == MTC_REW)) mt_sta = 0;/* write, rew: bsy=0 */
|
||||
else mt_sta = STA_BSY; /* bsy=1,nmtn,eom,err=0 */
|
||||
mt_bptr = mt_blnt = 0; /* not yet started */
|
||||
if ((f == MTC_RD) || (f == MTC_WR)) /* data xfr? */
|
||||
mt_xfr = 1; /* set xfr flag */
|
||||
else mt_xfr = 0; }
|
||||
uptr->UCMD = f; /* save cmd */
|
||||
uptr->UST = 0; /* clr tape stat */
|
||||
sim_activate (uptr, mt_rtime); /* start op */
|
||||
break; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Unit service
|
||||
|
||||
A given operation can generate up to three interrupts
|
||||
|
||||
- EOF generates an interrupt when set (read, space, wreof)
|
||||
BUSY will still be set, EOM and NMTN will be clear
|
||||
- After operation complete + delay, EOM generates an interrupt
|
||||
BUSY will be clear, EOM will be set, NMTN will be clear
|
||||
- After a further delay, NMTN generates an interrupt
|
||||
BUSY will be clear, EOM and NMTN will be set
|
||||
|
||||
Rewind generates an interrupt when NMTN sets
|
||||
*/
|
||||
|
||||
t_stat mt_svc (UNIT *uptr)
|
||||
{
|
||||
uint32 i, pnu;
|
||||
int32 err;
|
||||
int32 u = uptr - mt_dev.units;
|
||||
uint32 dev = mt_dib.dno + (u * o_MT0);
|
||||
t_mtrlnt tbc;
|
||||
static t_mtrlnt bceof = { 0 };
|
||||
|
||||
err = 0;
|
||||
pnu = MT_TST_PNU (uptr); /* get pos not upd */
|
||||
MT_CLR_PNU (uptr); /* and clear */
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
|
||||
uptr->UCMD = 0; /* clr cmd */
|
||||
uptr->UST = 0; /* set status */
|
||||
mt_xfr = 0; /* clr op flags */
|
||||
mt_sta = STA_ERR | STA_EOM; /* set status */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* interrupt */
|
||||
return IORETURN (mt_stopioe, SCPE_UNATT); }
|
||||
|
||||
if (uptr->UCMD & MTC_STOP2) { /* stop, gen NMTN? */
|
||||
uptr->UCMD = 0; /* clr cmd */
|
||||
uptr->UST = STA_NMTN; /* set nmtn, not eot */
|
||||
mt_xfr = 0; /* clr xfr */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */
|
||||
return SCPE_OK; }
|
||||
|
||||
if (uptr->UCMD & MTC_STOP1) { /* stop, gen EOM? */
|
||||
uptr->UCMD = uptr->UCMD | MTC_STOP2; /* clr cmd */
|
||||
mt_sta = (mt_sta & ~STA_BSY) | STA_EOM; /* clr busy, set eom */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */
|
||||
sim_activate (uptr, mt_rtime); /* schedule */
|
||||
return SCPE_OK; } /* end case */
|
||||
|
||||
switch (uptr->UCMD) { /* case on function */
|
||||
|
||||
case MTC_REW: /* rewind */
|
||||
uptr->UCMD = 0; /* clr cmd */
|
||||
uptr->pos = 0; /* update position */
|
||||
uptr->UST = STA_NMTN | STA_EOT; /* update status */
|
||||
mt_sta = mt_sta & ~STA_BSY; /* don't set EOM */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* interrupt */
|
||||
return SCPE_OK;
|
||||
|
||||
/* Unit service, continued
|
||||
|
||||
For read, busy = 1 => buffer empty
|
||||
For write, busy = 1 => buffer full
|
||||
For read, data transfers continue for the full length of the
|
||||
record, or the maximum size of the transfer buffer
|
||||
For write, data transfers continue until a write is attempted
|
||||
and the buffer is empty
|
||||
*/
|
||||
|
||||
case MTC_RD: /* read */
|
||||
if (mt_blnt == 0) { /* first time? */
|
||||
if (mt_rdlntf (uptr, &tbc, &err)) break; /* read rec lnt, err? */
|
||||
mt_blnt = tbc; /* set buf lnt */
|
||||
if (tbc > MT_MAXFR) return SCPE_MTRLNT; /* record too long? */
|
||||
i = fxread (mtxb, sizeof (uint8), mt_blnt, uptr->fileref);
|
||||
if (err = ferror (uptr->fileref)) { /* error? */
|
||||
MT_SET_PNU (uptr); /* pos not upd */
|
||||
break; }
|
||||
for ( ; i < mt_blnt; i++) mtxb[i] = 0; /* fill with 0's */
|
||||
uptr->pos = uptr->pos + ((tbc + 1) & ~1) /* upd pos */
|
||||
+ (2 * sizeof (t_mtrlnt)); }
|
||||
|
||||
if (sch_actv (mt_dib.sch, dev)) { /* sch active? */
|
||||
i = sch_wrmem (mt_dib.sch, mtxb, mt_blnt); /* store rec in mem */
|
||||
if (sch_actv (mt_dib.sch, dev)) /* sch still active? */
|
||||
sch_stop (mt_dib.sch); /* stop chan, long rd */
|
||||
else if (i < mt_blnt) /* process entire rec? */
|
||||
mt_sta = mt_sta | STA_ERR; } /* no, overrun error */
|
||||
else if (mt_bptr < mt_blnt) { /* no, if !eor */
|
||||
if (!(mt_sta & STA_BSY)) /* busy still clr? */
|
||||
mt_sta = mt_sta | STA_ERR; /* read overrun */
|
||||
mt_db = mtxb[mt_bptr++]; /* get next byte */
|
||||
mt_sta = mt_sta & ~STA_BSY; /* !busy = buf full */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */
|
||||
sim_activate (uptr, mt_wtime); /* reschedule */
|
||||
return SCPE_OK; }
|
||||
break; /* record done */
|
||||
|
||||
case MTC_WR: /* write */
|
||||
if (sch_actv (mt_dib.sch, dev)) { /* sch active? */
|
||||
mt_bptr = sch_rdmem (mt_dib.sch, mtxb, MT_MAXFR); /* get rec */
|
||||
if (sch_actv (mt_dib.sch, dev)) /* not done? */
|
||||
sch_stop (mt_dib.sch); } /* stop chan */
|
||||
else if (mt_sta & STA_BSY) { /* no, if !eor */
|
||||
if (mt_bptr < MT_MAXFR) /* if room */
|
||||
mtxb[mt_bptr++] = mt_db; /* store in buf */
|
||||
mt_sta = mt_sta & ~STA_BSY; /* !busy = buf emp */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */
|
||||
sim_activate (uptr, mt_wtime); /* reschedule */
|
||||
return SCPE_OK; }
|
||||
|
||||
if (mt_bptr) { /* any chars? */
|
||||
int32 ebc = (mt_bptr + 1) & ~1; /* force even */
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
||||
fxwrite (&mt_bptr, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
fxwrite (mtxb, sizeof (uint8), ebc, uptr->fileref);
|
||||
fxwrite (&mt_bptr, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr);
|
||||
else uptr->pos = uptr->pos + ebc + (2 * sizeof (t_mtrlnt)); }
|
||||
break; /* record done */
|
||||
|
||||
/* Unit service, continued */
|
||||
|
||||
case MTC_WEOF: /* write eof */
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set pos */
|
||||
fxwrite (&bceof, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr);
|
||||
else uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* update pos */
|
||||
mt_sta = mt_sta | STA_EOF; /* set eof */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* interrupt */
|
||||
break;
|
||||
|
||||
case MTC_SKFF: /* skip file fwd */
|
||||
while (mt_forwsp (uptr, &err)) ; /* spc until EOF/EOT */
|
||||
break;
|
||||
|
||||
case MTC_SKFR: /* skip file rev */
|
||||
while (mt_backsp (uptr, &err)) ; /* spc until EOF/BOT */
|
||||
break;
|
||||
|
||||
case MTC_SPCR: /* backspace */
|
||||
if (!pnu) mt_backsp (uptr, &err); /* if pos not upd */
|
||||
break; } /* end case */
|
||||
|
||||
if (err != 0) { /* I/O error */
|
||||
mt_sta = mt_sta | STA_ERR;
|
||||
perror ("MT I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
if (mt_stopioe) return SCPE_IOERR; }
|
||||
uptr->UCMD = uptr->UCMD | MTC_STOP1; /* set stop stage 1 */
|
||||
sim_activate (uptr, mt_rtime); /* schedule */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Tape motion routines */
|
||||
|
||||
t_bool mt_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
||||
{
|
||||
int32 u = uptr - mt_dev.units;
|
||||
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* position */
|
||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref); /* get bc */
|
||||
if ((*err = ferror (uptr->fileref)) || /* err or eom? */
|
||||
feof (uptr->fileref) || (*tbc == MTR_EOM)) {
|
||||
mt_sta = mt_sta | STA_ERR; /* set err */
|
||||
MT_SET_PNU (uptr); /* pos not upd */
|
||||
return TRUE; }
|
||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
||||
mt_sta = mt_sta | STA_EOF; /* set eof */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */
|
||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* update pos */
|
||||
return TRUE; }
|
||||
*tbc = MTRL (*tbc);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
t_bool mt_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
||||
{
|
||||
int32 u = uptr - mt_dev.units;
|
||||
|
||||
if (uptr->pos < sizeof (t_mtrlnt)) { /* at bot? */
|
||||
uptr->UST = uptr->UST | STA_EOT; /* set err */
|
||||
return TRUE; }
|
||||
fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET);
|
||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref); /* get bc */
|
||||
if ((*err = ferror (uptr->fileref)) || /* err or eof? */
|
||||
feof (uptr->fileref)) {
|
||||
mt_sta = mt_sta | STA_ERR; /* set err */
|
||||
return TRUE; }
|
||||
if (*tbc == MTR_EOM) { /* eom? */
|
||||
mt_sta = mt_sta | STA_ERR; /* set err */
|
||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* update pos */
|
||||
return TRUE; }
|
||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
||||
mt_sta = mt_sta | STA_EOF; /* set eof */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */
|
||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* update pos */
|
||||
return TRUE; }
|
||||
*tbc = MTRL (*tbc);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
t_bool mt_forwsp (UNIT *uptr, int32 *err)
|
||||
{
|
||||
t_mtrlnt tbc;
|
||||
|
||||
if (mt_rdlntf (uptr, &tbc, err)) return FALSE; /* read rec lnt, err? */
|
||||
uptr->pos = uptr->pos + ((tbc + 1) & ~1) + /* space to next rec */
|
||||
(2 * sizeof (t_mtrlnt));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
t_bool mt_backsp (UNIT *uptr, int32 *err)
|
||||
{
|
||||
t_mtrlnt tbc;
|
||||
|
||||
if (mt_rdlntr (uptr, &tbc, err)) return FALSE; /* read rec lnt, err? */
|
||||
uptr->pos = uptr->pos - ((tbc + 1) & ~1) - /* space to prv rec */
|
||||
(2 * sizeof (t_mtrlnt));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat mt_reset (DEVICE *dptr)
|
||||
{
|
||||
uint32 u;
|
||||
UNIT *uptr;
|
||||
|
||||
mt_bptr = mt_blnt = 0; /* clr buf */
|
||||
mt_sta = STA_BSY; /* clr flags */
|
||||
mt_xfr = 0; /* clr controls */
|
||||
for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */
|
||||
CLR_INT (v_MT + u); /* clear int */
|
||||
CLR_ENB (v_MT + u); /* disable int */
|
||||
mt_arm[u] = 0; /* disarm int */
|
||||
uptr = mt_dev.units + u;
|
||||
MT_CLR_PNU (uptr); /* clear pos flag */
|
||||
sim_cancel (uptr); /* cancel activity */
|
||||
uptr->UST = (uptr->UST & STA_UFLGS) | STA_NMTN; /* init status */
|
||||
uptr->UCMD = 0; } /* init cmd */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Attach routine */
|
||||
|
||||
t_stat mt_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
int32 u = uptr - mt_dev.units;
|
||||
t_stat r;
|
||||
|
||||
r = attach_unit (uptr, cptr);
|
||||
if (r != SCPE_OK) return r;
|
||||
uptr->pos = 0;
|
||||
MT_CLR_PNU (uptr);
|
||||
uptr->UST = STA_EOT;
|
||||
if (mt_arm[u]) SET_INT (v_MT + u);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Detach routine */
|
||||
|
||||
t_stat mt_detach (UNIT* uptr)
|
||||
{
|
||||
int32 u = uptr - mt_dev.units;
|
||||
t_stat r;
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK;
|
||||
r = detach_unit (uptr);
|
||||
if (r != SCPE_OK) return r;
|
||||
if (mt_arm[u]) SET_INT (v_MT + u);
|
||||
MT_CLR_PNU (uptr);
|
||||
uptr->UST = 0;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Bootstrap routine */
|
||||
|
||||
#define BOOT_START 0x50
|
||||
#define BOOT_LEN (sizeof (boot_rom) / sizeof (uint8))
|
||||
|
||||
static uint8 boot_rom[] = {
|
||||
0xD5, 0x00, /* ST: AL CF */
|
||||
0x00, 0xCF,
|
||||
0x43, 0x00, /* BR 80 */
|
||||
0x00, 0x80
|
||||
};
|
||||
|
||||
t_stat mt_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
extern uint32 PC, dec_flgs;
|
||||
extern uint16 decrom[];
|
||||
extern DIB sch_dib;
|
||||
uint32 sch_dev;
|
||||
|
||||
if (decrom[0xD5] & dec_flgs) return SCPE_NOFNC; /* AL defined? */
|
||||
mt_unit[unitno].pos = 0; /* rewind */
|
||||
sch_dev = sch_dib.dno + mt_dib.sch; /* sch dev # */
|
||||
IOWriteBlk (BOOT_START, BOOT_LEN, boot_rom); /* copy boot */
|
||||
IOWriteB (AL_DEV, mt_dib.dno + (unitno * o_MT0)); /* set dev no for unit */
|
||||
IOWriteB (AL_IOC, 0xA1); /* set dev cmd */
|
||||
IOWriteB (AL_SCH, sch_dev); /* set dev no for chan */
|
||||
PC = BOOT_START;
|
||||
return SCPE_OK;
|
||||
}
|
546
Interdata/id_pas.c
Normal file
546
Interdata/id_pas.c
Normal file
|
@ -0,0 +1,546 @@
|
|||
/* id_pas.c: Interdata programmable async line adapter simulator
|
||||
|
||||
Copyright (c) 2001-2003, 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.
|
||||
|
||||
pas Programmable asynchronous line adapter(s)
|
||||
|
||||
This module implements up to 32 individual serial interfaces, representing
|
||||
either individual PASLA modules or combinations of the 2-line and 8-line
|
||||
multiplexors, which are functionally very similar. These interfaces are mapped
|
||||
to Telnet based connections as the lines of a terminal multiplexor. The
|
||||
connection polling mechanism and the character input polling for all lines
|
||||
are done through a single polling job.
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
#include "sim_sock.h"
|
||||
#include "sim_tmxr.h"
|
||||
#include <ctype.h>
|
||||
|
||||
#define PAS_LINES 32
|
||||
|
||||
#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */
|
||||
#define UNIT_V_UC (UNIT_V_UF + 1) /* UC only */
|
||||
#define UNIT_V_MDM (UNIT_V_UF + 2) /* modem control */
|
||||
#define UNIT_8B (1 << UNIT_V_8B)
|
||||
#define UNIT_UC (1 << UNIT_V_UC)
|
||||
#define UNIT_MDM (1 << UNIT_V_MDM)
|
||||
|
||||
#define PAS_INIT_POLL 8000
|
||||
#define PASL_WAIT 500
|
||||
|
||||
/* Status byte */
|
||||
|
||||
#define STA_OVR 0x80 /* overrun RO */
|
||||
#define STA_PF 0x40 /* parity err RONI */
|
||||
#define STA_NCL2S 0x40 /* not clr to snd XO */
|
||||
#define STA_FR 0x20 /* framing err RO */
|
||||
#define STA_RCR 0x10 /* rv chan rcv NI */
|
||||
#define STA_CROF 0x02 /* carrier off RO */
|
||||
#define STA_RING 0x01 /* ring RO */
|
||||
#define STA_RCV (STA_OVR|STA_PF|STA_FR|STA_RCR|STA_CROF|STA_RING)
|
||||
#define SET_EX (STA_OVR|STA_PF|STA_FR)
|
||||
#define STA_XMT (STA_BSY)
|
||||
|
||||
/* Command bytes 1,0 */
|
||||
|
||||
#define CMD_DTR (0x20 << 8) /* DTR */
|
||||
#define CMD_ECHO (0x10 << 8) /* echoplex */
|
||||
#define CMD_RCT (0x08 << 8) /* RCT/DTB NI */
|
||||
#define CMD_XMTB (0x04 << 8) /* xmt break NI */
|
||||
#define CMD_WRT (0x02 << 8) /* write/read */
|
||||
#define CMD_V_CLK 6 /* baud rate */
|
||||
#define CMD_M_CLK 0x3
|
||||
#define CMD_V_DB 4 /* data bits */
|
||||
#define CMD_M_DB 0x3
|
||||
#define CMD_STOP 0x80 /* stop bit */
|
||||
#define CMD_V_PAR 1 /* parity */
|
||||
#define CMD_M_PAR 0x3
|
||||
#define GET_PAR(x) (((x) >> CMD_V_PAR) & CMD_M_PAR)
|
||||
#define PAR_NONE 0
|
||||
#define PAR_RAW 1
|
||||
#define PAR_ODD 2
|
||||
#define PAR_EVEN 3
|
||||
|
||||
#define CMD_TYP 0x01 /* command type */
|
||||
|
||||
extern uint32 int_req[INTSZ], int_enb[INTSZ];
|
||||
|
||||
uint8 pas_sta[PAS_LINES]; /* status */
|
||||
uint16 pas_cmd[PAS_LINES]; /* command */
|
||||
uint8 pas_rbuf[PAS_LINES]; /* rcv buf */
|
||||
uint8 pas_xbuf[PAS_LINES]; /* xmt buf */
|
||||
uint8 pas_rarm[PAS_LINES]; /* rcvr int armed */
|
||||
uint8 pas_xarm[PAS_LINES]; /* xmt int armed */
|
||||
uint8 pas_rchp[PAS_LINES]; /* rcvr chr pend */
|
||||
uint32 pas_tps = 50; /* polls/second */
|
||||
uint8 pas_tplte[PAS_LINES * 2 + 1]; /* template */
|
||||
|
||||
TMLN pas_ldsc[PAS_LINES] = { 0 }; /* line descriptors */
|
||||
TMXR pas_desc = { 8, 0, 0, &pas_ldsc[0], NULL }; /* mux descriptor */
|
||||
#define PAS_ENAB pas_desc.lines
|
||||
|
||||
uint32 pas (uint32 dev, uint32 op, uint32 dat);
|
||||
void pas_ini (t_bool dtpl);
|
||||
t_stat pasi_svc (UNIT *uptr);
|
||||
t_stat paso_svc (UNIT *uptr);
|
||||
t_stat pas_reset (DEVICE *dptr);
|
||||
t_stat pas_attach (UNIT *uptr, char *cptr);
|
||||
t_stat pas_detach (UNIT *uptr);
|
||||
t_stat pas_summ (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
t_stat pas_show (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
int32 pas_par (int32 cmd, int32 c);
|
||||
t_stat pas_vlines (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
void pas_reset_ln (int32 i);
|
||||
|
||||
/* PAS data structures
|
||||
|
||||
pas_dev PAS device descriptor
|
||||
pas_unit PAS unit descriptor
|
||||
pas_reg PAS register list
|
||||
pas_mod PAS modifiers list
|
||||
*/
|
||||
|
||||
DIB pas_dib = { d_PAS, -1, v_PAS, pas_tplte, &pas, &pas_ini };
|
||||
|
||||
UNIT pas_unit = { UDATA (&pasi_svc, UNIT_ATTABLE, 0), PAS_INIT_POLL };
|
||||
|
||||
REG pas_nlreg = { DRDATA (NLINES, PAS_ENAB, 6), PV_LEFT };
|
||||
|
||||
REG pas_reg[] = {
|
||||
{ BRDATA (STA, pas_sta, 16, 8, PAS_LINES) },
|
||||
{ BRDATA (CMD, pas_cmd, 16, 16, PAS_LINES) },
|
||||
{ BRDATA (RBUF, pas_rbuf, 16, 8, PAS_LINES) },
|
||||
{ BRDATA (XBUF, pas_xbuf, 16, 8, PAS_LINES) },
|
||||
{ BRDATA (IREQ, &int_req[l_PAS], 16, 32, PAS_LINES / 16) },
|
||||
{ BRDATA (IENB, &int_enb[l_PAS], 16, 32, PAS_LINES / 16) },
|
||||
{ BRDATA (RARM, pas_rarm, 16, 1, PAS_LINES) },
|
||||
{ BRDATA (XARM, pas_xarm, 16, 1, PAS_LINES) },
|
||||
{ BRDATA (RCHP, pas_rchp, 16, 1, PAS_LINES) },
|
||||
{ HRDATA (DEVNO, pas_dib.dno, 8), REG_HRO },
|
||||
{ NULL } };
|
||||
|
||||
MTAB pas_mod[] = {
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_VAL, 0, "lines", "LINES",
|
||||
&pas_vlines, NULL, &pas_nlreg },
|
||||
{ MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT",
|
||||
&tmxr_dscln, NULL, &pas_desc },
|
||||
{ UNIT_ATT, UNIT_ATT, "connections", NULL, NULL, &pas_summ },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL,
|
||||
NULL, &pas_show, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL,
|
||||
NULL, &pas_show, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE pas_dev = {
|
||||
"PAS", &pas_unit, pas_reg, pas_mod,
|
||||
1, 10, 31, 1, 16, 8,
|
||||
&tmxr_ex, &tmxr_dep, &pas_reset,
|
||||
NULL, &pas_attach, &pas_detach,
|
||||
&pas_dib, DEV_DISABLE };
|
||||
|
||||
/* PASL data structures
|
||||
|
||||
pasl_dev PASL device descriptor
|
||||
pasl_unit PASL unit descriptor
|
||||
pasl_reg PASL register list
|
||||
pasl_mod PASL modifiers list
|
||||
*/
|
||||
|
||||
UNIT pasl_unit[] = {
|
||||
{ UDATA (&paso_svc, 0, 0), PASL_WAIT }, /* all but 8 dis */
|
||||
{ UDATA (&paso_svc, 0, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, 0, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, 0, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, 0, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, 0, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, 0, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, 0, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT },
|
||||
{ UDATA (&paso_svc, UNIT_DIS, 0), PASL_WAIT } };
|
||||
|
||||
MTAB pasl_mod[] = {
|
||||
{ UNIT_UC+UNIT_8B, UNIT_UC, "UC", "UC", NULL },
|
||||
{ UNIT_UC+UNIT_8B, 0 , "7b", "7B", NULL },
|
||||
{ UNIT_UC+UNIT_8B, UNIT_8B, "8b", "8B", NULL },
|
||||
{ UNIT_MDM, 0, "no dataset", "NODATASET", NULL },
|
||||
{ UNIT_MDM, UNIT_MDM, "dataset", "DATASET", NULL },
|
||||
{ 0 } };
|
||||
|
||||
REG pasl_reg[] = {
|
||||
{ URDATA (TIME, pasl_unit[0].wait, 16, 24, 0,
|
||||
PAS_LINES, REG_NZ + PV_LEFT) },
|
||||
{ NULL } };
|
||||
|
||||
DEVICE pasl_dev = {
|
||||
"PASL", pasl_unit, pasl_reg, pasl_mod,
|
||||
PAS_LINES, 10, 31, 1, 16, 8,
|
||||
NULL, NULL, &pas_reset,
|
||||
NULL, NULL, NULL,
|
||||
NULL, 0 };
|
||||
|
||||
/* PAS: IO routine */
|
||||
|
||||
uint32 pas (uint32 dev, uint32 op, uint32 dat)
|
||||
{
|
||||
int32 ln = (dev - pas_dib.dno) >> 1;
|
||||
int32 xmt = (dev - pas_dib.dno) & 1;
|
||||
int32 t, old_cmd;
|
||||
|
||||
switch (op) { /* case IO op */
|
||||
case IO_ADR: /* select */
|
||||
return BY; /* byte only */
|
||||
case IO_RD: /* read */
|
||||
pas_rchp[ln] = 0; /* clr chr pend */
|
||||
pas_sta[ln] = pas_sta[ln] & ~STA_OVR; /* clr overrun */
|
||||
return pas_rbuf[ln]; /* return buf */
|
||||
case IO_WD: /* write */
|
||||
pas_xbuf[ln] = dat & 0xFF; /* store char */
|
||||
pas_sta[ln] = pas_sta[ln] | STA_BSY; /* set busy */
|
||||
sim_activate (&pasl_unit[ln], pasl_unit[ln].wait);
|
||||
break;
|
||||
case IO_SS: /* status */
|
||||
if (xmt) { /* xmt side? */
|
||||
if (pas_ldsc[ln].conn == 0) /* not conn? */
|
||||
t = STA_NCL2S | STA_BSY; /* busy, not clr */
|
||||
else t = pas_sta[ln] & STA_XMT; } /* else just busy */
|
||||
else {
|
||||
t = pas_sta[ln] & STA_RCV; /* get static */
|
||||
if (!pas_rchp[ln]) t = t | STA_BSY; /* no char? busy */
|
||||
if (pas_ldsc[ln].conn == 0) /* not connected? */
|
||||
t = t | STA_BSY | STA_EX; /* = !dsr */
|
||||
if (t & SET_EX) t = t | STA_EX; } /* test for ex */
|
||||
return t;
|
||||
case IO_OC: /* command */
|
||||
old_cmd = pas_cmd[ln]; /* old cmd */
|
||||
if (dat & CMD_TYP) { /* type 1? */
|
||||
pas_cmd[ln] = (pas_cmd[ln] & 0xFF) | (dat << 8);
|
||||
if (pas_cmd[ln] & CMD_WRT) /* write? */
|
||||
pas_xarm[ln] = int_chg (v_PASX + ln + ln, dat, pas_xarm[ln]);
|
||||
else pas_rarm[ln] = int_chg (v_PAS + ln + ln, dat, pas_rarm[ln]); }
|
||||
else pas_cmd[ln] = (pas_cmd[ln] & ~0xFF) | dat;
|
||||
if (pasl_unit[ln].flags & UNIT_MDM) { /* modem ctrl? */
|
||||
if ((pas_cmd[ln] & CMD_DTR) && (pas_sta[ln] & STA_RING))
|
||||
pas_sta[ln] = pas_sta[ln] & ~(STA_CROF | STA_RING);
|
||||
if (old_cmd & ~pas_cmd[ln] & CMD_DTR) {
|
||||
tmxr_msg (pas_ldsc[ln].conn, "\r\nLine hangup\r\n");
|
||||
tmxr_reset_ln (&pas_ldsc[ln]); /* reset line */
|
||||
pas_sta[ln] = pas_sta[ln] | STA_CROF; /* no carrier */
|
||||
if (pas_rarm[ln]) SET_INT (v_PAS + ln + ln); } }
|
||||
break; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Unit service - receive side
|
||||
|
||||
Poll all active lines for input
|
||||
Poll for new connections
|
||||
*/
|
||||
|
||||
t_stat pasi_svc (UNIT *uptr)
|
||||
{
|
||||
int32 ln, c, out, t;
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */
|
||||
t = sim_rtcn_calb (pas_tps, TMR_PAS); /* calibrate */
|
||||
sim_activate (uptr, t); /* continue poll */
|
||||
ln = tmxr_poll_conn (&pas_desc); /* look for connect */
|
||||
if (ln >= 0) { /* got one? */
|
||||
if ((pasl_unit[ln].flags & UNIT_MDM) && /* modem control */
|
||||
((pas_cmd[ln] & CMD_DTR) == 0)) /* & !dtr? */
|
||||
pas_sta[ln] = pas_sta[ln] | STA_RING | STA_CROF; /* set ring, no cd */
|
||||
else pas_sta[ln] = pas_sta[ln] & ~STA_CROF; /* just answer */
|
||||
if (pas_rarm[ln]) SET_INT (v_PAS + ln + ln); /* interrupt */
|
||||
pas_ldsc[ln].rcve = 1; } /* rcv enabled */
|
||||
tmxr_poll_rx (&pas_desc); /* poll for input */
|
||||
for (ln = 0; ln < PAS_ENAB; ln++) { /* loop thru lines */
|
||||
if (pas_ldsc[ln].conn) { /* connected? */
|
||||
if (c = tmxr_getc_ln (&pas_ldsc[ln])) { /* any char? */
|
||||
pas_sta[ln] = pas_sta[ln] & ~(STA_FR | STA_PF);
|
||||
if (pas_rchp[ln]) pas_sta[ln] = pas_sta[ln] | STA_OVR;
|
||||
if (pas_rarm[ln]) SET_INT (v_PAS + ln + ln);
|
||||
if (c & SCPE_BREAK) { /* break? */
|
||||
pas_sta[ln] = pas_sta[ln] | STA_FR; /* framing error */
|
||||
pas_rbuf[ln] = 0; } /* no character */
|
||||
else { /* normal */
|
||||
out = c & 0x7F; /* echo is 7b */
|
||||
if (pasl_unit[ln].flags & UNIT_8B) /* 8b? */
|
||||
c = c & 0xFF;
|
||||
else { /* UC or 7b */
|
||||
if ((pasl_unit[ln].flags & UNIT_UC) && islower (out))
|
||||
out = toupper (out); /* cvt to UC */
|
||||
c = pas_par (pas_cmd[ln], out); } /* apply parity */
|
||||
pas_rbuf[ln] = c; /* save char */
|
||||
pas_rchp[ln] = 1; /* char pending */
|
||||
if ((pas_cmd[ln] & CMD_ECHO) && pas_ldsc[ln].xmte) {
|
||||
TMLN *lp = &pas_ldsc[ln]; /* get line */
|
||||
tmxr_putc_ln (lp, out); /* output char */
|
||||
tmxr_poll_tx (&pas_desc); } /* poll xmt */
|
||||
} /* end else normal */
|
||||
} /* end if char */
|
||||
} /* end if conn */
|
||||
else if ((pas_sta[ln] & STA_CROF) == 0) { /* not conn, was conn? */
|
||||
pas_sta[ln] = pas_sta[ln] | STA_CROF; /* no carrier */
|
||||
if (pas_rarm[ln]) SET_INT (v_PAS + ln + ln); } /* intr */
|
||||
} /* end for */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Unit service - transmit side */
|
||||
|
||||
t_stat paso_svc (UNIT *uptr)
|
||||
{
|
||||
int32 c;
|
||||
uint32 ln = uptr - pasl_unit; /* line # */
|
||||
|
||||
if (pas_ldsc[ln].conn) { /* connected? */
|
||||
if (pas_ldsc[ln].xmte) { /* xmt enabled? */
|
||||
TMLN *lp = &pas_ldsc[ln]; /* get line */
|
||||
if (pasl_unit[ln].flags & UNIT_8B) /* 8b? */
|
||||
c = pas_par (pas_cmd[ln], pas_xbuf[ln]);/* apply parity */
|
||||
else { /* UC or 7b */
|
||||
c = pas_xbuf[ln] & 0x7F; /* mask char */
|
||||
if ((pasl_unit[ln].flags & UNIT_UC) && islower (c))
|
||||
c = toupper (c); } /* cvt to UC */
|
||||
tmxr_putc_ln (lp, c); /* output char */
|
||||
tmxr_poll_tx (&pas_desc); } /* poll xmt */
|
||||
else { /* buf full */
|
||||
tmxr_poll_tx (&pas_desc); /* poll xmt */
|
||||
sim_activate (uptr, pasl_unit[ln].wait); /* wait */
|
||||
return SCPE_OK; } }
|
||||
pas_sta[ln] = pas_sta[ln] & ~STA_BSY; /* not busy */
|
||||
if (pas_xarm[ln]) SET_INT (v_PASX + ln + ln); /* set intr */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
int32 pas_par (int32 cmd, int32 c)
|
||||
{
|
||||
int32 pf = GET_PAR (cmd);
|
||||
static const uint8 odd_par[] = {
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 00 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 10 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 20 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 30 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 40 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 50 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 60 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 70 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* 80 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* 90 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* A0 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* B0 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* C0 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* D0 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80, /* E0 */
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0,
|
||||
0x80, 0, 0, 0x80, 0, 0x80, 0x80, 0, /* F0 */
|
||||
0, 0x80, 0x80, 0, 0x80, 0, 0, 0x80 };
|
||||
|
||||
switch (pf) { /* case on parity */
|
||||
case PAR_ODD:
|
||||
return (odd_par[c & 0x7F]) | (c & 0x7F);
|
||||
case PAR_EVEN:
|
||||
return (odd_par[c & 0x7F] ^ 0x80) | (c & 0x7F);
|
||||
case PAR_NONE:
|
||||
case PAR_RAW:
|
||||
break; }
|
||||
return c & 0xFF;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat pas_reset (DEVICE *dptr)
|
||||
{
|
||||
int32 i, t;
|
||||
|
||||
if (dptr->flags & DEV_DIS) { /* disabled? */
|
||||
pas_dev.flags = pas_dev.flags | DEV_DIS; /* disable lines */
|
||||
pasl_dev.flags = pasl_dev.flags | DEV_DIS; }
|
||||
else { pas_dev.flags = pas_dev.flags & ~DEV_DIS; /* enable lines */
|
||||
pasl_dev.flags = pasl_dev.flags & ~DEV_DIS; }
|
||||
if (pas_unit.flags & UNIT_ATT) { /* master att? */
|
||||
if (!sim_is_active (&pas_unit)) {
|
||||
t = sim_rtcn_init (pas_unit.wait, TMR_PAS);
|
||||
sim_activate (&pas_unit, t); } } /* activate */
|
||||
else sim_cancel (&pas_unit); /* else stop */
|
||||
for (i = 0; i < PAS_LINES; i++) {
|
||||
pas_desc.ldsc[i] = &pas_ldsc[i];
|
||||
pas_reset_ln (i); }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Attach master unit */
|
||||
|
||||
t_stat pas_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
t_stat r;
|
||||
|
||||
r = tmxr_attach (&pas_desc, uptr, cptr); /* attach */
|
||||
if (r != SCPE_OK) return r; /* error */
|
||||
sim_rtcn_init (pas_unit.wait, TMR_PAS);
|
||||
sim_activate (uptr, 100); /* quick poll */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Detach master unit */
|
||||
|
||||
t_stat pas_detach (UNIT *uptr)
|
||||
{
|
||||
int32 i;
|
||||
t_stat r;
|
||||
|
||||
r = tmxr_detach (&pas_desc, uptr); /* detach */
|
||||
for (i = 0; i < PAS_LINES; i++) pas_ldsc[i].rcve = 0; /* disable rcv */
|
||||
sim_cancel (uptr); /* stop poll */
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Show summary processor */
|
||||
|
||||
t_stat pas_summ (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
int32 i, t;
|
||||
|
||||
for (i = t = 0; i < PAS_LINES; i++) t = t + (pas_ldsc[i].conn != 0);
|
||||
if (t == 1) fprintf (st, "1 connection");
|
||||
else fprintf (st, "%d connections", t);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* SHOW CONN/STAT processor */
|
||||
|
||||
t_stat pas_show (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
int32 i;
|
||||
|
||||
for (i = 0; (i < PAS_LINES) && (pas_ldsc[i].conn == 0); i++) ;
|
||||
if (i < PAS_LINES) {
|
||||
for (i = 0; i < PAS_LINES; i++) {
|
||||
if (pas_ldsc[i].conn)
|
||||
if (val) tmxr_fconns (st, &pas_ldsc[i], i);
|
||||
else tmxr_fstats (st, &pas_ldsc[i], i); } }
|
||||
else fprintf (st, "all disconnected\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Change number of lines */
|
||||
|
||||
t_stat pas_vlines (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
int32 newln, i, t;
|
||||
t_stat r;
|
||||
|
||||
if (cptr == NULL) return SCPE_ARG;
|
||||
newln = get_uint (cptr, 10, PAS_LINES, &r);
|
||||
if ((r != SCPE_OK) || (newln == PAS_ENAB)) return r;
|
||||
if (newln == 0) return SCPE_ARG;
|
||||
if (newln < PAS_ENAB) {
|
||||
for (i = newln, t = 0; i < PAS_ENAB; i++) t = t | pas_ldsc[i].conn;
|
||||
if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE))
|
||||
return SCPE_OK;
|
||||
for (i = newln; i < PAS_ENAB; i++) {
|
||||
if (pas_ldsc[i].conn) {
|
||||
tmxr_msg (pas_ldsc[i].conn, "\r\nOperator disconnected line\r\n");
|
||||
tmxr_reset_ln (&pas_ldsc[i]); } /* reset line */
|
||||
pasl_unit[i].flags = pasl_unit[i].flags | UNIT_DIS;
|
||||
pas_reset_ln (i); }
|
||||
}
|
||||
else { for (i = PAS_ENAB; i < newln; i++) {
|
||||
pasl_unit[i].flags = pasl_unit[i].flags & ~UNIT_DIS;
|
||||
pas_reset_ln (i); }
|
||||
}
|
||||
PAS_ENAB = newln;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Reset an individual line */
|
||||
|
||||
void pas_reset_ln (int32 i)
|
||||
{
|
||||
CLR_INT (v_PAS + i + i); /* clear int */
|
||||
CLR_ENB (v_PAS + i + i);
|
||||
CLR_INT (v_PASX + i + i); /* disable int */
|
||||
CLR_ENB (v_PASX + i + i);
|
||||
pas_rarm[i] = pas_xarm[i] = 0; /* disarm int */
|
||||
pas_rbuf[i] = pas_xbuf[i] = 0; /* clear state */
|
||||
pas_cmd[i] = 0;
|
||||
pas_rchp[i] = 0;
|
||||
pas_sta[i] = 0;
|
||||
if (pas_ldsc[i].conn == 0) /* clear carrier */
|
||||
pas_sta[i] = pas_sta[i] | STA_CROF;
|
||||
sim_cancel (&pasl_unit[i]);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Init template */
|
||||
|
||||
void pas_ini (t_bool dtpl)
|
||||
{
|
||||
int32 i, j;
|
||||
|
||||
for (i = j = 0; i < PAS_ENAB; i++) {
|
||||
pas_tplte[j] = j;
|
||||
pas_tplte[j + 1] = j + o_PASX;
|
||||
j = j + 2; }
|
||||
pas_tplte[j] = TPL_END;
|
||||
return;
|
||||
}
|
350
Interdata/id_pt.c
Normal file
350
Interdata/id_pt.c
Normal file
|
@ -0,0 +1,350 @@
|
|||
/* id_pt.c: Interdata paper tape reader
|
||||
|
||||
Copyright (c) 2000-2001, 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.
|
||||
|
||||
pt paper tape reader and punch
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
#include <ctype.h>
|
||||
|
||||
/* Device definitions */
|
||||
|
||||
#define PTR 0 /* unit subscripts */
|
||||
#define PTP 1
|
||||
|
||||
#define STA_OVR 0x80 /* overrun */
|
||||
#define STA_NMTN 0x10 /* no motion */
|
||||
#define STA_MASK (STA_BSY | STA_OVR | STA_DU) /* static bits */
|
||||
#define SET_EX (STA_OVR | STA_NMTN) /* set EX */
|
||||
|
||||
#define CMD_V_RUN 4 /* run/stop */
|
||||
#define CMD_V_SLEW 2 /* slew/step */
|
||||
#define CMD_V_RD 0 /* read/write */
|
||||
|
||||
extern uint32 int_req[INTSZ], int_enb[INTSZ];
|
||||
|
||||
uint32 pt_run = 0, pt_slew = 0; /* ptr modes */
|
||||
uint32 pt_rd = 1, pt_chp = 0; /* pt state */
|
||||
uint32 pt_arm = 0; /* int arm */
|
||||
uint32 pt_sta = STA_BSY; /* status */
|
||||
uint32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */
|
||||
|
||||
DEVICE pt_dev;
|
||||
uint32 pt (uint32 dev, uint32 op, uint32 dat);
|
||||
t_stat ptr_svc (UNIT *uptr);
|
||||
t_stat ptp_svc (UNIT *uptr);
|
||||
t_stat pt_boot (int32 unitno, DEVICE *dptr);
|
||||
t_stat pt_reset (DEVICE *dptr);
|
||||
|
||||
/* PT data structures
|
||||
|
||||
pt_dev PT device descriptor
|
||||
pt_unit PT unit descriptors
|
||||
pt_reg PT register list
|
||||
*/
|
||||
|
||||
DIB pt_dib = { d_PT, -1, v_PT, NULL, &pt, NULL };
|
||||
|
||||
UNIT pt_unit[] = {
|
||||
{ UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0),
|
||||
SERIAL_IN_WAIT },
|
||||
{ UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0),
|
||||
SERIAL_OUT_WAIT } };
|
||||
|
||||
REG pt_reg[] = {
|
||||
{ HRDATA (STA, pt_sta, 8) },
|
||||
{ HRDATA (RBUF, pt_unit[PTR].buf, 8) },
|
||||
{ DRDATA (RPOS, pt_unit[PTR].pos, 32), PV_LEFT },
|
||||
{ DRDATA (RTIME, pt_unit[PTR].wait, 24), PV_LEFT },
|
||||
{ FLDATA (RSTOP_IOE, ptr_stopioe, 0) },
|
||||
{ HRDATA (PBUF, pt_unit[PTP].buf, 8) },
|
||||
{ DRDATA (PPOS, pt_unit[PTP].pos, 32), PV_LEFT },
|
||||
{ DRDATA (PTIME, pt_unit[PTP].wait, 24), PV_LEFT },
|
||||
{ FLDATA (PSTOP_IOE, ptp_stopioe, 0) },
|
||||
{ FLDATA (IREQ, int_req[l_PT], i_PT) },
|
||||
{ FLDATA (IENB, int_enb[l_PT], i_PT) },
|
||||
{ FLDATA (IARM, pt_arm, 0) },
|
||||
{ FLDATA (RD, pt_rd, 0) },
|
||||
{ FLDATA (RUN, pt_run, 0) },
|
||||
{ FLDATA (SLEW, pt_slew, 0) },
|
||||
{ FLDATA (CHP, pt_chp, 0) },
|
||||
{ HRDATA (DEVNO, pt_dib.dno, 8), REG_HRO },
|
||||
{ NULL } };
|
||||
|
||||
MTAB pt_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "devno", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE pt_dev = {
|
||||
"PT", pt_unit, pt_reg, pt_mod,
|
||||
2, 10, 31, 1, 16, 8,
|
||||
NULL, NULL, &pt_reset,
|
||||
&pt_boot, NULL, NULL,
|
||||
&pt_dib, DEV_DISABLE };
|
||||
|
||||
/* Paper tape: IO routine */
|
||||
|
||||
uint32 pt (uint32 dev, uint32 op, uint32 dat)
|
||||
{
|
||||
uint32 t, old_rd, old_run;
|
||||
|
||||
switch (op) { /* case IO op */
|
||||
case IO_ADR: /* select */
|
||||
return BY; /* byte only */
|
||||
case IO_OC: /* command */
|
||||
old_rd = pt_rd; /* save curr rw */
|
||||
old_run = pt_run; /* save curr run */
|
||||
pt_arm = int_chg (v_PT, dat, pt_arm); /* upd int ctrl */
|
||||
pt_rd = io_2b (dat, CMD_V_RD, pt_rd); /* upd read/wr */
|
||||
if (old_rd != pt_rd) { /* rw change? */
|
||||
pt_sta = pt_sta & ~STA_OVR; /* clr overrun */
|
||||
if (sim_is_active (&pt_unit[pt_rd? PTR: PTP])) {
|
||||
pt_sta = pt_sta | STA_BSY; /* busy = 1 */
|
||||
CLR_INT (v_PT); } /* clear int */
|
||||
else { /* not active */
|
||||
pt_sta = pt_sta & ~STA_BSY; /* busy = 0 */
|
||||
if (pt_arm) SET_INT (v_PT); } } /* no, set int */
|
||||
if (pt_rd) { /* reader? */
|
||||
pt_run = io_2b (dat, CMD_V_RUN, pt_run); /* upd run/stop */
|
||||
pt_slew = io_2b (dat, CMD_V_SLEW, pt_slew); /* upd slew/inc */
|
||||
if (pt_run) { /* run set? */
|
||||
if (old_run == 0) { /* run 0 -> 1? */
|
||||
sim_activate (&pt_unit[PTR], pt_unit[PTR].wait);
|
||||
pt_sta = pt_sta & ~STA_DU; } } /* clear eof */
|
||||
else sim_cancel (&pt_unit[PTR]); } /* clr, stop rdr */
|
||||
else pt_sta = pt_sta & ~STA_DU; /* punch, clr eof */
|
||||
break;
|
||||
case IO_RD: /* read */
|
||||
if (pt_run && !pt_slew) { /* incremental? */
|
||||
sim_activate (&pt_unit[PTR], pt_unit[PTR].wait);
|
||||
pt_sta = pt_sta & ~STA_DU; } /* clr eof */
|
||||
pt_chp = 0; /* clr char pend */
|
||||
if (pt_rd) pt_sta = pt_sta | STA_BSY; /* set busy */
|
||||
return (pt_unit[PTR].buf & 0xFF); /* return char */
|
||||
case IO_WD: /* write */
|
||||
pt_unit[PTP].buf = dat & DMASK8; /* save char */
|
||||
if (!pt_rd) pt_sta = pt_sta | STA_BSY; /* set busy */
|
||||
sim_activate (&pt_unit[PTP], pt_unit[PTP].wait);
|
||||
break;
|
||||
case IO_SS: /* status */
|
||||
t = pt_sta & STA_MASK; /* get status */
|
||||
if (pt_rd && !pt_run && !sim_is_active (&pt_unit[PTR]))
|
||||
t = t | STA_NMTN; /* stopped? */
|
||||
if ((pt_unit[pt_rd? PTR: PTP].flags & UNIT_ATT) == 0)
|
||||
t = t | STA_DU; /* offline? */
|
||||
if (t & SET_EX) t = t | STA_EX; /* test for EX */
|
||||
return t; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Unit service */
|
||||
|
||||
t_stat ptr_svc (UNIT *uptr)
|
||||
{
|
||||
uint32 temp;
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
|
||||
return IORETURN (ptr_stopioe, SCPE_UNATT);
|
||||
if (pt_rd) { /* read mode? */
|
||||
pt_sta = pt_sta & ~STA_BSY; /* clear busy */
|
||||
if (pt_arm) SET_INT (v_PT); /* if armed, intr */
|
||||
if (pt_chp) pt_sta = pt_sta | STA_OVR; } /* overrun? */
|
||||
pt_chp = 1; /* char pending */
|
||||
if ((temp = getc (uptr->fileref)) == EOF) { /* error? */
|
||||
if (feof (uptr->fileref)) { /* eof? */
|
||||
pt_sta = pt_sta | STA_DU; /* set DU */
|
||||
if (ptr_stopioe) printf ("PTR end of file\n");
|
||||
else return SCPE_OK; }
|
||||
else perror ("PTR I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
return SCPE_IOERR; }
|
||||
uptr->buf = temp & DMASK8; /* store char */
|
||||
uptr->pos = uptr->pos + 1; /* incr pos */
|
||||
if (pt_slew) sim_activate (uptr, uptr->wait); /* slew? continue */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat ptp_svc (UNIT *uptr)
|
||||
{
|
||||
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
|
||||
return IORETURN (ptp_stopioe, SCPE_UNATT);
|
||||
if (!pt_rd) { /* write mode? */
|
||||
pt_sta = pt_sta & ~STA_BSY; /* clear busy */
|
||||
if (pt_arm) SET_INT (v_PT); } /* if armed, intr */
|
||||
if (putc (uptr->buf, uptr -> fileref) == EOF) { /* write char */
|
||||
perror ("PTP I/O error");
|
||||
clearerr (uptr -> fileref);
|
||||
return SCPE_IOERR; }
|
||||
uptr -> pos = uptr -> pos + 1; /* incr pos */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat pt_reset (DEVICE *dptr)
|
||||
{
|
||||
sim_cancel (&pt_unit[PTR]); /* deactivate units */
|
||||
sim_cancel (&pt_unit[PTP]);
|
||||
pt_rd = 1; /* read */
|
||||
pt_chp = pt_run = pt_slew = 0; /* stop, inc, disarm */
|
||||
pt_sta = STA_BSY; /* buf empty */
|
||||
CLR_INT (v_PT); /* clear int */
|
||||
CLR_ENB (v_PT); /* disable int */
|
||||
pt_arm = 0; /* disarm int */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Bootstrap routine */
|
||||
|
||||
#define BOOT_START 0x50
|
||||
#define BOOT_LEN (sizeof (boot_rom) / sizeof (uint8))
|
||||
#define BOOT3_START 0x3E
|
||||
#define BOOT3_LEN (sizeof (boot_rom) / sizeof (uint8))
|
||||
|
||||
static uint8 boot_rom[] = {
|
||||
0xD5, 0x00, /* ST AL CF */
|
||||
0x00, 0xCF,
|
||||
0x43, 0x00, /* BR 80 */
|
||||
0x00, 0x80
|
||||
};
|
||||
|
||||
static uint8 boot3_rom[] = {
|
||||
0xC8, 0x20, /* ST LHI 2,80 */
|
||||
0x00, 0x80,
|
||||
0xC8, 0x30, /* LHI 3,1 */
|
||||
0x00, 0x01,
|
||||
0xC8, 0x40, /* LHI 4,CF */
|
||||
0x00, 0xCF,
|
||||
0xD3, 0xA0, /* LB A,78 */
|
||||
0x00, 0x78,
|
||||
0xDE, 0xA0, /* OC A,79 */
|
||||
0x00, 0x79,
|
||||
0x9D, 0xAE, /* LP SSR A,E */
|
||||
0x42, 0xF0, /* BTC F,LP */
|
||||
0x00, 0x52,
|
||||
0x9B, 0xAE, /* RDR A,E */
|
||||
0x08, 0xEE, /* LHR E,E */
|
||||
0x43, 0x30, /* BZ LP */
|
||||
0x00, 0x52,
|
||||
0x43, 0x00, /* BR STO */
|
||||
0x00, 0x6C,
|
||||
0x9D, 0xAE, /* LP1 SSR A,E */
|
||||
0x42, 0xF0, /* BTC F,LP1 */
|
||||
0x00, 0x64,
|
||||
0x9B, 0xAE, /* RDR A,E */
|
||||
0xD2, 0xE2, /* STO STB E,0(2) */
|
||||
0x00, 0x00,
|
||||
0xC1, 0x20, /* BXLE 2,LP1 */
|
||||
0x00, 0x64,
|
||||
0x43, 0x00, /* BR 80 */
|
||||
0x00, 0x80
|
||||
};
|
||||
|
||||
t_stat pt_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
extern uint32 PC, dec_flgs;
|
||||
extern uint16 decrom[];
|
||||
|
||||
if (decrom[0xD5] & dec_flgs) /* AL defined? */
|
||||
IOWriteBlk (BOOT3_START, BOOT3_LEN, boot3_rom); /* no, 50 seq */
|
||||
else IOWriteBlk (BOOT_START, BOOT_LEN, boot_rom); /* copy AL boot */
|
||||
IOWriteB (AL_DEV, pt_dib.dno); /* set dev no */
|
||||
IOWriteB (AL_IOC, 0x99); /* set dev cmd */
|
||||
IOWriteB (AL_SCH, 0); /* clr sch dev no */
|
||||
PC = BOOT_START;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Dump routine */
|
||||
|
||||
#define LOAD_START 0x80
|
||||
#define LOAD_LO 0x8A
|
||||
#define LOAD_HI 0x8E
|
||||
#define LOAD_CS 0x93
|
||||
#define LOAD_LEN (sizeof (load_rom) / sizeof (uint8))
|
||||
#define LOAD_LDR 50
|
||||
|
||||
static uint8 load_rom[] = {
|
||||
0x24, 0x21, /* BOOT LIS R2,1 */
|
||||
0x23, 0x03, /* BS BOOT */
|
||||
0x00, 0x00, /* 32b psw pointer */
|
||||
0x00, 0x00, /* 32b reg pointer */
|
||||
0xC8, 0x10, /* ST LHI R1,lo */
|
||||
0x00, 0x00,
|
||||
0xC8, 0x30, /* LHI R3,hi */
|
||||
0x00, 0x00,
|
||||
0xC8, 0x60, /* LHI R3,cs */
|
||||
0x00, 0x00,
|
||||
0xD3, 0x40, /* LB R4,X'78' */
|
||||
0x00, 0x78,
|
||||
0xDE, 0x40, /* OC R4,X'79' */
|
||||
0x00, 0x79,
|
||||
0x9D, 0x45, /* LDR SSR R4,R5 */
|
||||
0x20, 0x91, /* BTBS 9,.-2 */
|
||||
0x9B, 0x45, /* RDR R4,R5 */
|
||||
0x08, 0x55, /* L(H)R R5,R5 */
|
||||
0x22, 0x34, /* BZS LDR */
|
||||
0xD2, 0x51, /* LOOP STB R5,0(R1) */
|
||||
0x00, 0x00,
|
||||
0x07, 0x65, /* X(H)R R6,R5 */
|
||||
0x9A, 0x26, /* WDR R2,R6 */
|
||||
0x9D, 0x45, /* SSR R4,R5 */
|
||||
0x20, 0x91, /* BTBS 9,.-2 */
|
||||
0x9B, 0x45, /* RDR R4,R5 */
|
||||
0xC1, 0x10, /* BXLE R1,LOOP */
|
||||
0x00, 0xA6,
|
||||
0x24, 0x78, /* LIS R7,8 */
|
||||
0x91, 0x7C, /* SLLS R7,12 */
|
||||
0x95, 0x57, /* EPSR R5,R7 */
|
||||
0x22, 0x03 /* BS .-6 */
|
||||
};
|
||||
|
||||
t_stat pt_dump (FILE *of, char *cptr, char *fnam)
|
||||
{
|
||||
t_addr i, lo, hi;
|
||||
uint32 cs;
|
||||
char *tptr;
|
||||
extern DEVICE cpu_dev;
|
||||
|
||||
if ((cptr == NULL) || (*cptr == 0)) return SCPE_2FARG;
|
||||
tptr = get_range (cptr, &lo, &hi, cpu_dev.aradix, 0xFFFF, 0);
|
||||
if ((tptr == NULL) || (lo < INTSVT)) return SCPE_ARG;
|
||||
if (*tptr != 0) return SCPE_2MARG;
|
||||
for (i = lo, cs = 0; i <= hi; i++) cs = cs ^ IOReadB (i);
|
||||
IOWriteBlk (LOAD_START, LOAD_LEN, load_rom);
|
||||
IOWriteB (LOAD_LO, (lo >> 8) & 0xFF);
|
||||
IOWriteB (LOAD_LO + 1, lo & 0xFF);
|
||||
IOWriteB (LOAD_HI, (hi >> 8) & 0xFF);
|
||||
IOWriteB (LOAD_HI + 1, hi & 0xFF);
|
||||
IOWriteB (LOAD_CS, cs & 0xFF);
|
||||
for (i = 0; i < LOAD_LDR; i++) fputc (0, of);
|
||||
for (i = LOAD_START; i < (LOAD_START + LOAD_LEN); i++)
|
||||
fputc (IOReadB (i), of);
|
||||
for (i = 0; i < LOAD_LDR; i++) fputc (0, of);
|
||||
for (i = lo; i <= hi; i++) fputc (IOReadB (i), of);
|
||||
for (i = 0; i < LOAD_LDR; i++) fputc (0, of);
|
||||
return SCPE_OK;
|
||||
}
|
259
Interdata/id_tt.c
Normal file
259
Interdata/id_tt.c
Normal file
|
@ -0,0 +1,259 @@
|
|||
/* id_tt.c: Interdata teletype
|
||||
|
||||
Copyright (c) 2000-2003, 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.
|
||||
|
||||
tt console
|
||||
|
||||
11-Jan-03 RMS Added TTP support
|
||||
22-Dec-02 RMS Added break support
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
#include <ctype.h>
|
||||
|
||||
#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */
|
||||
#define UNIT_V_KSR (UNIT_V_UF + 1) /* KSR33 */
|
||||
#define UNIT_8B (1 << UNIT_V_8B)
|
||||
#define UNIT_KSR (1 << UNIT_V_KSR)
|
||||
|
||||
/* Device definitions */
|
||||
|
||||
#define TTI 0
|
||||
#define TTO 1
|
||||
|
||||
#define STA_OVR 0x80 /* overrun */
|
||||
#define STA_BRK 0x20 /* break */
|
||||
#define STA_MASK (STA_OVR | STA_BRK | STA_BSY) /* status mask */
|
||||
#define SET_EX (STA_OVR | STA_BRK) /* set EX */
|
||||
|
||||
#define CMD_V_FDPX 4 /* full/half duplex */
|
||||
#define CMD_V_RD 2 /* read/write */
|
||||
|
||||
extern uint32 int_req[INTSZ], int_enb[INTSZ];
|
||||
|
||||
uint32 tt_sta = STA_BSY; /* status */
|
||||
uint32 tt_fdpx = 1; /* tt mode */
|
||||
uint32 tt_rd = 1, tt_chp = 0; /* tt state */
|
||||
uint32 tt_arm = 0; /* int arm */
|
||||
|
||||
uint32 tt (uint32 dev, uint32 op, uint32 dat);
|
||||
t_stat tti_svc (UNIT *uptr);
|
||||
t_stat tto_svc (UNIT *uptr);
|
||||
t_stat tt_reset (DEVICE *dptr);
|
||||
t_stat tt_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat tt_set_break (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat tt_set_enbdis (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
|
||||
/* TT data structures
|
||||
|
||||
tt_dev TT device descriptor
|
||||
tt_unit TT unit descriptors
|
||||
tt_reg TT register list
|
||||
tt_mod TT modifiers list
|
||||
*/
|
||||
|
||||
DIB tt_dib = { d_TT, -1, v_TT, NULL, &tt, NULL };
|
||||
|
||||
UNIT tt_unit[] = {
|
||||
{ UDATA (&tti_svc, UNIT_KSR, 0), KBD_POLL_WAIT },
|
||||
{ UDATA (&tto_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT }
|
||||
};
|
||||
|
||||
REG tt_reg[] = {
|
||||
{ HRDATA (STA, tt_sta, 8) },
|
||||
{ HRDATA (KBUF, tt_unit[TTI].buf, 8) },
|
||||
{ DRDATA (KPOS, tt_unit[TTI].pos, 32), PV_LEFT },
|
||||
{ DRDATA (KTIME, tt_unit[TTI].wait, 24), REG_NZ + PV_LEFT },
|
||||
{ HRDATA (TBUF, tt_unit[TTO].buf, 8) },
|
||||
{ DRDATA (TPOS, tt_unit[TTO].pos, 32), PV_LEFT },
|
||||
{ DRDATA (TTIME, tt_unit[TTO].wait, 24), REG_NZ + PV_LEFT },
|
||||
{ FLDATA (IREQ, int_req[l_TT], i_TT) },
|
||||
{ FLDATA (IENB, int_enb[l_TT], i_TT) },
|
||||
{ FLDATA (IARM, tt_arm, 0) },
|
||||
{ FLDATA (RD, tt_rd, 0) },
|
||||
{ FLDATA (FDPX, tt_fdpx, 0) },
|
||||
{ FLDATA (CHP, tt_chp, 0) },
|
||||
{ HRDATA (DEVNO, tt_dib.dno, 8), REG_HRO },
|
||||
{ NULL } };
|
||||
|
||||
MTAB tt_mod[] = {
|
||||
{ UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tt_set_mode },
|
||||
{ UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tt_set_mode },
|
||||
{ UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tt_set_mode },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "ENABLED",
|
||||
&tt_set_enbdis, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, DEV_DIS, NULL, "DISABLED",
|
||||
&tt_set_enbdis, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "BREAK",
|
||||
&tt_set_break, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, &tt_dib },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE tt_dev = {
|
||||
"TT", tt_unit, tt_reg, tt_mod,
|
||||
2, 10, 31, 1, 16, 8,
|
||||
NULL, NULL, &tt_reset,
|
||||
NULL, NULL, NULL,
|
||||
&tt_dib, 0 };
|
||||
|
||||
/* Terminal: IO routine */
|
||||
|
||||
uint32 tt (uint32 dev, uint32 op, uint32 dat)
|
||||
{
|
||||
uint32 old_rd, t;
|
||||
|
||||
switch (op) { /* case IO op */
|
||||
case IO_ADR: /* select */
|
||||
return BY; /* byte only */
|
||||
case IO_OC: /* command */
|
||||
old_rd = tt_rd;
|
||||
tt_arm = int_chg (v_TT, dat, tt_arm); /* upd int ctrl */
|
||||
tt_fdpx = io_2b (dat, CMD_V_FDPX, tt_fdpx); /* upd full/half */
|
||||
tt_rd = io_2b (dat, CMD_V_RD, tt_rd); /* upd rd/write */
|
||||
if (tt_rd != old_rd) { /* rw change? */
|
||||
if (tt_rd? tt_chp: !sim_is_active (&tt_unit[TTO])) {
|
||||
tt_sta = 0; /* busy = 0 */
|
||||
if (tt_arm) SET_INT (v_TT); } /* req intr */
|
||||
else {
|
||||
tt_sta = STA_BSY; /* busy = 1 */
|
||||
CLR_INT (v_TT); } } /* clr int */
|
||||
else tt_sta = tt_sta & ~STA_OVR; /* clr ovflo */
|
||||
break;
|
||||
case IO_RD: /* read */
|
||||
tt_chp = 0; /* clear pend */
|
||||
if (tt_rd) tt_sta = (tt_sta | STA_BSY) & ~STA_OVR;
|
||||
return (tt_unit[TTI].buf & 0xFF);
|
||||
case IO_WD: /* write */
|
||||
tt_unit[TTO].buf = dat & 0xFF; /* save char */
|
||||
if (!tt_rd) tt_sta = tt_sta | STA_BSY; /* set busy */
|
||||
sim_activate (&tt_unit[TTO], tt_unit[TTO].wait);
|
||||
break;
|
||||
case IO_SS: /* status */
|
||||
t = tt_sta & STA_MASK; /* get status */
|
||||
if (t & SET_EX) t = t | STA_EX; /* test for EX */
|
||||
return t; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Unit service routines */
|
||||
|
||||
t_stat tti_svc (UNIT *uptr)
|
||||
{
|
||||
int32 out, temp;
|
||||
|
||||
sim_activate (uptr, uptr->wait); /* continue poll */
|
||||
tt_sta = tt_sta & ~STA_BRK; /* clear break */
|
||||
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */
|
||||
if (tt_rd) { /* read mode? */
|
||||
tt_sta = tt_sta & ~STA_BSY; /* clear busy */
|
||||
if (tt_arm) SET_INT (v_TT); /* if armed, intr */
|
||||
if (tt_chp) tt_sta = tt_sta | STA_OVR; } /* got char? overrun */
|
||||
tt_chp = 1; /* char pending */
|
||||
out = temp & 0x7F; /* echo is 7B */
|
||||
if (temp & SCPE_BREAK) { /* break? */
|
||||
tt_sta = tt_sta | STA_BRK; /* set status */
|
||||
uptr->buf = 0; } /* no character */
|
||||
else if (uptr->flags & UNIT_KSR) { /* KSR mode? */
|
||||
if (islower (out)) out = toupper (out); /* cvt to UC */
|
||||
uptr->buf = out | 0x80; } /* set high bit */
|
||||
else uptr->buf = temp & ((tt_unit[TTI].flags & UNIT_8B)? 0xFF: 0x7F);
|
||||
uptr->pos = uptr->pos + 1; /* incr count */
|
||||
if (!tt_fdpx) { /* half duplex? */
|
||||
if (out) sim_putchar (out); /* write char */
|
||||
tt_unit[TTO].pos = tt_unit[TTO].pos + 1; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat tto_svc (UNIT *uptr)
|
||||
{
|
||||
int32 ch;
|
||||
t_stat r;
|
||||
|
||||
if (!tt_rd) { /* write mode? */
|
||||
tt_sta = tt_sta & ~STA_BSY; /* clear busy */
|
||||
if (tt_arm) SET_INT (v_TT); } /* if armed, intr */
|
||||
if (uptr->flags & UNIT_KSR) { /* KSR mode? */
|
||||
ch = uptr->buf & 0x7F; /* mask to 7b */
|
||||
if (islower (ch)) ch = toupper (ch); } /* cvt to UC */
|
||||
else ch = uptr->buf & ((tt_unit[TTO].flags & UNIT_8B)? 0xFF: 0x7F);
|
||||
if (!(uptr->flags & UNIT_8B) && /* KSR or 7b? */
|
||||
((ch == 0) || (ch == 0x7F))) return SCPE_OK; /* supr NULL, DEL */
|
||||
if ((r = sim_putchar (ch)) != SCPE_OK) return r; /* output */
|
||||
uptr->pos = uptr->pos + 1; /* incr count */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat tt_reset (DEVICE *dptr)
|
||||
{
|
||||
if (dptr->flags & DEV_DIS) sim_cancel (&tt_unit[TTI]); /* dis? cancel poll */
|
||||
else sim_activate (&tt_unit[TTI], tt_unit[TTI].wait); /* activate input */
|
||||
sim_cancel (&tt_unit[TTO]); /* cancel output */
|
||||
tt_rd = tt_fdpx = 1; /* read, full duplex */
|
||||
tt_chp = 0; /* no char */
|
||||
tt_sta = STA_BSY; /* buffer empty */
|
||||
CLR_INT (v_TT); /* clear int */
|
||||
CLR_ENB (v_TT); /* disable int */
|
||||
tt_arm = 0; /* disarm int */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Make mode flags uniform */
|
||||
|
||||
t_stat tt_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
tt_unit[TTI].flags = (tt_unit[TTI].flags & ~(UNIT_KSR | UNIT_8B)) | val;
|
||||
tt_unit[TTO].flags = (tt_unit[TTO].flags & ~(UNIT_KSR | UNIT_8B)) | val;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Set input break */
|
||||
|
||||
t_stat tt_set_break (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if (tt_dev.flags & DEV_DIS) return SCPE_NOFNC;
|
||||
tt_sta = tt_sta | STA_BRK;
|
||||
if (tt_rd) { /* read mode? */
|
||||
tt_sta = tt_sta & ~STA_BSY; /* clear busy */
|
||||
if (tt_arm) SET_INT (v_TT); } /* if armed, intr */
|
||||
sim_cancel (&tt_unit[TTI]); /* restart TT poll */
|
||||
sim_activate (&tt_unit[TTI], tt_unit[TTI].wait); /* so brk is seen */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Set enabled/disabled */
|
||||
|
||||
t_stat tt_set_enbdis (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
extern DEVICE ttp_dev;
|
||||
extern t_stat ttp_reset (DEVICE *dptr);
|
||||
|
||||
tt_dev.flags = (tt_dev.flags & ~DEV_DIS) | val;
|
||||
ttp_dev.flags = (ttp_dev.flags & ~DEV_DIS) | (val ^ DEV_DIS);
|
||||
tt_reset (&tt_dev);
|
||||
ttp_reset (&ttp_dev);
|
||||
return SCPE_OK;
|
||||
}
|
263
Interdata/id_ttp.c
Normal file
263
Interdata/id_ttp.c
Normal file
|
@ -0,0 +1,263 @@
|
|||
/* id_ttp.c: Interdata PASLA console interface
|
||||
|
||||
Copyright (c) 2000-2003, 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.
|
||||
|
||||
ttp console (on PAS)
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
#include <ctype.h>
|
||||
|
||||
#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */
|
||||
#define UNIT_V_UC (UNIT_V_UF + 1) /* UC only */
|
||||
#define UNIT_8B (1 << UNIT_V_8B)
|
||||
#define UNIT_UC (1 << UNIT_V_UC)
|
||||
|
||||
#define TTI 0
|
||||
#define TTO 1
|
||||
|
||||
/* Status byte */
|
||||
|
||||
#define STA_OVR 0x80 /* overrun RO */
|
||||
#define STA_PF 0x40 /* parity err RO */
|
||||
#define STA_FR 0x20 /* framing err RO */
|
||||
#define STA_RCV (STA_OVR|STA_PF|STA_FR)
|
||||
#define SET_EX (STA_OVR|STA_PF|STA_FR)
|
||||
#define STA_XMT (STA_BSY)
|
||||
|
||||
/* Command bytes 1,0 */
|
||||
|
||||
#define CMD_ECHO (0x10 << 8) /* echoplex */
|
||||
#define CMD_WRT (0x02 << 8) /* write/read */
|
||||
#define CMD_TYP 0x01 /* command type */
|
||||
|
||||
extern uint32 int_req[INTSZ], int_enb[INTSZ];
|
||||
|
||||
uint32 ttp_sta = 0; /* status */
|
||||
uint32 ttp_cmd = 0; /* command */
|
||||
uint32 ttp_kchp = 0; /* rcvr chr pend */
|
||||
uint32 ttp_karm = 0; /* rcvr int armed */
|
||||
uint32 ttp_tarm = 0; /* xmt int armed */
|
||||
uint8 ttp_tplte[] = { 0, 1, TPL_END };
|
||||
|
||||
uint32 ttp (uint32 dev, uint32 op, uint32 dat);
|
||||
t_stat ttpi_svc (UNIT *uptr);
|
||||
t_stat ttpo_svc (UNIT *uptr);
|
||||
t_stat ttp_reset (DEVICE *dptr);
|
||||
t_stat ttp_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat ttp_set_break (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat ttp_set_enbdis (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
|
||||
extern int32 pas_par (int32 cmd, int32 c);
|
||||
|
||||
/* TTP data structures */
|
||||
|
||||
DIB ttp_dib = { d_TTP, -1, v_TTP, ttp_tplte, &ttp, NULL };
|
||||
|
||||
UNIT ttp_unit[] = {
|
||||
{ UDATA (&ttpi_svc, UNIT_UC, 0), KBD_POLL_WAIT },
|
||||
{ UDATA (&ttpo_svc, UNIT_UC, 0), SERIAL_OUT_WAIT }
|
||||
};
|
||||
|
||||
REG ttp_reg[] = {
|
||||
{ HRDATA (CMD, ttp_cmd, 16) },
|
||||
{ HRDATA (KBUF, ttp_unit[TTI].buf, 8) },
|
||||
{ DRDATA (KPOS, ttp_unit[TTI].pos, 32), PV_LEFT },
|
||||
{ DRDATA (KTIME, ttp_unit[TTI].wait, 24), REG_NZ + PV_LEFT },
|
||||
{ FLDATA (KIREQ, int_req[l_TTP], i_TTP) },
|
||||
{ FLDATA (KIENB, int_enb[l_TTP], i_TTP) },
|
||||
{ FLDATA (KARM, ttp_karm, 0) },
|
||||
{ FLDATA (CHP, ttp_kchp, 0) },
|
||||
{ HRDATA (TBUF, ttp_unit[TTO].buf, 8) },
|
||||
{ DRDATA (TPOS, ttp_unit[TTO].pos, 32), PV_LEFT },
|
||||
{ DRDATA (TTIME, ttp_unit[TTO].wait, 24), REG_NZ + PV_LEFT },
|
||||
{ FLDATA (TIREQ, int_req[l_TTP], i_TTP + 1) },
|
||||
{ FLDATA (TIENB, int_enb[l_TTP], i_TTP + 1) },
|
||||
{ FLDATA (TARM, ttp_tarm, 0) },
|
||||
{ HRDATA (DEVNO, ttp_dib.dno, 8), REG_HRO },
|
||||
{ NULL } };
|
||||
|
||||
MTAB ttp_mod[] = {
|
||||
{ UNIT_UC+UNIT_8B, UNIT_UC, "UC", "UC", &ttp_set_mode },
|
||||
{ UNIT_UC+UNIT_8B, 0 , "7b", "7B", &ttp_set_mode },
|
||||
{ UNIT_UC+UNIT_8B, UNIT_8B, "8b", "8B", &ttp_set_mode },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "ENABLED",
|
||||
&ttp_set_enbdis, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, DEV_DIS, NULL, "DISABLED",
|
||||
&ttp_set_enbdis, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "BREAK",
|
||||
&ttp_set_break, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE ttp_dev = {
|
||||
"TTP", ttp_unit, ttp_reg, ttp_mod,
|
||||
2, 10, 31, 1, 16, 8,
|
||||
NULL, NULL, &ttp_reset,
|
||||
NULL, NULL, NULL,
|
||||
&ttp_dib, DEV_DIS };
|
||||
|
||||
|
||||
/* Terminal: I/O routine */
|
||||
|
||||
uint32 ttp (uint32 dev, uint32 op, uint32 dat)
|
||||
{
|
||||
int32 xmt = dev & 1;
|
||||
int32 t, old_cmd;
|
||||
|
||||
switch (op) { /* case IO op */
|
||||
case IO_ADR: /* select */
|
||||
return BY; /* byte only */
|
||||
case IO_RD: /* read */
|
||||
ttp_kchp = 0; /* clr chr pend */
|
||||
ttp_sta = ttp_sta & ~STA_OVR; /* clr overrun */
|
||||
return ttp_unit[TTI].buf; /* return buf */
|
||||
case IO_WD: /* write */
|
||||
ttp_unit[TTO].buf = dat & 0xFF; /* store char */
|
||||
ttp_sta = ttp_sta | STA_BSY; /* set busy */
|
||||
sim_activate (&ttp_unit[TTO], ttp_unit[TTO].wait);
|
||||
break;
|
||||
case IO_SS: /* status */
|
||||
if (xmt) t = ttp_sta & STA_XMT; /* xmt? Just busy */
|
||||
else { /* rcv */
|
||||
t = ttp_sta & STA_RCV; /* get static */
|
||||
if (!ttp_kchp) t = t | STA_BSY; /* no char? busy */
|
||||
if (t & SET_EX) t = t | STA_EX; } /* test for ex */
|
||||
return t;
|
||||
case IO_OC: /* command */
|
||||
old_cmd = ttp_cmd; /* old cmd */
|
||||
if (dat & CMD_TYP) { /* type 1? */
|
||||
ttp_cmd = (ttp_cmd & 0xFF) | (dat << 8);
|
||||
if (ttp_cmd & CMD_WRT) /* write? */
|
||||
ttp_tarm = int_chg (v_TTP + 1, dat, ttp_tarm);
|
||||
else ttp_karm = int_chg (v_TTP, dat, ttp_karm); }
|
||||
else ttp_cmd = (ttp_cmd & ~0xFF) | dat;
|
||||
break; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Unit service */
|
||||
|
||||
t_stat ttpi_svc (UNIT *uptr)
|
||||
{
|
||||
int32 c, out;
|
||||
|
||||
sim_activate (uptr, uptr->wait); /* continue poll */
|
||||
ttp_sta = ttp_sta & ~STA_FR; /* clear break */
|
||||
if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */
|
||||
ttp_sta = ttp_sta & ~STA_PF; /* clear parity err */
|
||||
if (ttp_kchp) ttp_sta = ttp_sta | STA_OVR; /* overrun? */
|
||||
if (ttp_karm) SET_INT (v_TTP);
|
||||
if (c & SCPE_BREAK) { /* break? */
|
||||
ttp_sta = ttp_sta | STA_FR; /* framing error */
|
||||
uptr->buf = 0; } /* no character */
|
||||
else { c = c & 0xFF; /* char is 8b */
|
||||
out = c & 0x7F; /* echo is 7b */
|
||||
if (!(uptr->flags & UNIT_8B)) { /* not 8b? */
|
||||
if ((uptr->flags & UNIT_UC) && islower (out))
|
||||
out = toupper (out); /* cvt to UC */
|
||||
c = pas_par (ttp_cmd, out); } /* apply parity */
|
||||
uptr->buf = c; /* save char */
|
||||
uptr->pos = uptr->pos + 1; /* incr count */
|
||||
ttp_kchp = 1; /* char pending */
|
||||
if (ttp_cmd & CMD_ECHO) {
|
||||
sim_putchar (out);
|
||||
ttp_unit[TTO].pos = ttp_unit[TTO].pos + 1; } }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat ttpo_svc (UNIT *uptr)
|
||||
{
|
||||
int32 c;
|
||||
t_stat r;
|
||||
|
||||
ttp_sta = ttp_sta & ~STA_BSY; /* not busy */
|
||||
if (ttp_tarm) SET_INT (v_TTP + 1); /* set intr */
|
||||
if (uptr->flags & UNIT_8B) /* 8b? */
|
||||
c = pas_par (ttp_cmd, uptr->buf); /* apply parity */
|
||||
else { c = uptr->buf & 0x7F; /* mask char */
|
||||
if ((uptr->flags & UNIT_UC) && islower (c))
|
||||
c = toupper (c); } /* cvt to UC */
|
||||
if (!(uptr->flags & UNIT_8B) && /* UC or 7b? */
|
||||
((c == 0) || (c == 0x7F))) return SCPE_OK; /* supr NULL, DEL */
|
||||
if ((r = sim_putchar (c)) != SCPE_OK) return r; /* output */
|
||||
uptr->pos = uptr->pos + 1; /* incr count */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat ttp_reset (DEVICE *dptr)
|
||||
{
|
||||
extern DEVICE tt_dev;
|
||||
|
||||
if (dptr->flags & DEV_DIS) sim_cancel (&ttp_unit[TTI]);
|
||||
else sim_activate (&ttp_unit[TTI], ttp_unit[TTI].wait);
|
||||
sim_cancel (&ttp_unit[TTO]);
|
||||
CLR_INT (v_TTP); /* clear int */
|
||||
CLR_ENB (v_TTP);
|
||||
CLR_INT (v_TTP + 1); /* disable int */
|
||||
CLR_ENB (v_TTP + 1);
|
||||
ttp_karm = ttp_tarm = 0; /* disarm int */
|
||||
ttp_cmd = 0;
|
||||
ttp_sta = 0;
|
||||
ttp_kchp = 0;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Make mode flags uniform */
|
||||
|
||||
t_stat ttp_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
ttp_unit[TTI].flags = (ttp_unit[TTI].flags & ~(UNIT_UC | UNIT_8B)) | val;
|
||||
ttp_unit[TTO].flags = (ttp_unit[TTO].flags & ~(UNIT_UC | UNIT_8B)) | val;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Set input break */
|
||||
|
||||
t_stat ttp_set_break (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if (ttp_dev.flags & DEV_DIS) return SCPE_NOFNC;
|
||||
ttp_sta = ttp_sta | STA_FR;
|
||||
if (ttp_karm) SET_INT (v_TTP); /* if armed, intr */
|
||||
sim_cancel (&ttp_unit[TTI]); /* restart TT poll */
|
||||
sim_activate (&ttp_unit[TTI], ttp_unit[TTI].wait);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Set enabled/disabled */
|
||||
|
||||
t_stat ttp_set_enbdis (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
extern DEVICE tt_dev;
|
||||
extern t_stat tt_reset (DEVICE *dptr);
|
||||
|
||||
ttp_dev.flags = (ttp_dev.flags & ~DEV_DIS) | val;
|
||||
tt_dev.flags = (tt_dev.flags & ~DEV_DIS) | (val ^ DEV_DIS);
|
||||
ttp_reset (&ttp_dev);
|
||||
tt_reset (&tt_dev);
|
||||
return SCPE_OK;
|
||||
}
|
311
Interdata/id_uvc.c
Normal file
311
Interdata/id_uvc.c
Normal file
|
@ -0,0 +1,311 @@
|
|||
/* id_uvc.c: Interdata universal clock
|
||||
|
||||
Copyright (c) 2001-2002, 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.
|
||||
|
||||
pic precision incremental clock
|
||||
lfc line frequency clock
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
#include <ctype.h>
|
||||
|
||||
/* Device definitions */
|
||||
|
||||
#define UNIT_V_DIAG (UNIT_V_UF + 0) /* diag mode */
|
||||
#define UNIT_DIAG (1 << UNIT_V_DIAG)
|
||||
|
||||
#define STA_OVF 0x08 /* PIC overflow */
|
||||
#define CMD_STRT 0x20 /* start */
|
||||
#define PIC_V_RATE 12 /* rate */
|
||||
#define PIC_M_RATE 0xF
|
||||
#define PIC_RATE (PIC_M_RATE << PIC_V_RATE)
|
||||
#define PIC_CTR 0x0FFF /* PIC counters */
|
||||
#define GET_RATE(x) (((x) >> PIC_V_RATE) & PIC_M_RATE)
|
||||
#define GET_CTR(x) ((x) & PIC_CTR)
|
||||
#define PIC_TPS 1000
|
||||
|
||||
extern uint32 int_req[INTSZ], int_enb[INTSZ];
|
||||
|
||||
int32 pic_db = 0; /* output buf */
|
||||
int32 pic_ric = 0; /* reset count */
|
||||
int32 pic_cic = 0; /* current count */
|
||||
uint32 pic_save = 0; /* saved time */
|
||||
uint32 pic_ovf = 0; /* overflow */
|
||||
uint32 pic_rdp = 0;
|
||||
uint32 pic_wdp = 0;
|
||||
uint32 pic_cnti = 0; /* instr/timer */
|
||||
uint32 pic_arm = 0; /* int arm */
|
||||
uint16 pic_time[4] = { 1, 10, 100, 1000 }; /* delays */
|
||||
static int32 pic_map[16] = { /* map rate to delay */
|
||||
0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 };
|
||||
|
||||
DEVICE pic_dev;
|
||||
uint32 pic (uint32 dev, uint32 op, uint32 dat);
|
||||
t_stat pic_svc (UNIT *uptr);
|
||||
t_stat pic_reset (DEVICE *dptr);
|
||||
void pic_sched (t_bool strt);
|
||||
uint32 pic_rd_cic (void);
|
||||
|
||||
int32 lfc_tps = 120; /* ticks per */
|
||||
uint32 lfc_arm = 0; /* int arm */
|
||||
|
||||
DEVICE lfc_dev;
|
||||
uint32 lfc (uint32 dev, uint32 op, uint32 dat);
|
||||
t_stat lfc_svc (UNIT *uptr);
|
||||
t_stat lfc_reset (DEVICE *dptr);
|
||||
|
||||
/* PIC data structures
|
||||
|
||||
pic_dev PIC device descriptor
|
||||
pic_unit PIC unit descriptor
|
||||
pic_reg PIC register list
|
||||
*/
|
||||
|
||||
DIB pic_dib = { d_PIC, -1, v_PIC, NULL, &pic, NULL };
|
||||
|
||||
UNIT pic_unit = { UDATA (&pic_svc, 0, 0), 1000 };
|
||||
|
||||
REG pic_reg[] = {
|
||||
{ HRDATA (BUF, pic_db, 16) },
|
||||
{ HRDATA (RIC, pic_ric, 16) },
|
||||
{ HRDATA (CIC, pic_cic, 12) },
|
||||
{ DRDATA (SAVE, pic_save, 32), REG_HRO + PV_LEFT },
|
||||
{ FLDATA (RDP, pic_rdp, 0) },
|
||||
{ FLDATA (WDP, pic_wdp, 0) },
|
||||
{ FLDATA (OVF, pic_ovf, 0) },
|
||||
{ FLDATA (IREQ, int_req[l_PIC], i_PIC) },
|
||||
{ FLDATA (IENB, int_enb[l_PIC], i_PIC) },
|
||||
{ FLDATA (IARM, pic_arm, 0) },
|
||||
{ BRDATA (TIME, pic_time, 10, 16, 4), REG_NZ + PV_LEFT },
|
||||
{ HRDATA (DEVNO, pic_dib.dno, 8), REG_HRO },
|
||||
{ NULL } };
|
||||
|
||||
MTAB pic_mod[] = {
|
||||
{ UNIT_DIAG, UNIT_DIAG, "diagnostic mode", "DIAG", NULL },
|
||||
{ UNIT_DIAG, 0, NULL, "NORMAL", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE pic_dev = {
|
||||
"PIC", &pic_unit, pic_reg, pic_mod,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
NULL, NULL, &pic_reset,
|
||||
NULL, NULL, NULL,
|
||||
&pic_dib, DEV_DISABLE };
|
||||
|
||||
/* LFC data structures
|
||||
|
||||
lfc_dev LFC device descriptor
|
||||
lfc_unit LFC unit descriptor
|
||||
lfc_reg LFC register list
|
||||
*/
|
||||
|
||||
DIB lfc_dib = { d_LFC, -1, v_LFC, NULL, &lfc, NULL };
|
||||
|
||||
UNIT lfc_unit = { UDATA (&lfc_svc, 0, 0), 8333 };
|
||||
|
||||
REG lfc_reg[] = {
|
||||
{ FLDATA (IREQ, int_req[l_LFC], i_LFC) },
|
||||
{ FLDATA (IENB, int_enb[l_LFC], i_LFC) },
|
||||
{ FLDATA (IARM, lfc_arm, 0) },
|
||||
{ DRDATA (TIME, lfc_unit.wait, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TPS, lfc_tps, 8), REG_NZ + PV_LEFT },
|
||||
{ HRDATA (DEVNO, lfc_dib.dno, 8), REG_HRO },
|
||||
{ NULL } };
|
||||
|
||||
MTAB lfc_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE lfc_dev = {
|
||||
"LFC", &lfc_unit, lfc_reg, lfc_mod,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
NULL, NULL, &lfc_reset,
|
||||
NULL, NULL, NULL,
|
||||
&lfc_dib, DEV_DISABLE };
|
||||
|
||||
/* Precision clock: IO routine */
|
||||
|
||||
uint32 pic (uint32 dev, uint32 op, uint32 dat)
|
||||
{
|
||||
int32 t;
|
||||
|
||||
switch (op) { /* case IO op */
|
||||
case IO_ADR: /* select */
|
||||
return HW; /* HW capable */
|
||||
case IO_RH: /* read halfword */
|
||||
pic_rdp = 0; /* clr ptr */
|
||||
return pic_rd_cic ();
|
||||
case IO_RD: /* read */
|
||||
t = pic_rd_cic (); /* get cic */
|
||||
if (pic_rdp) t = t & DMASK8; /* 2nd? get lo */
|
||||
else t = (t >> 8) & DMASK8; /* 1st? get hi */
|
||||
pic_rdp = pic_rdp ^ 1; /* flip byte ptr */
|
||||
return t;
|
||||
case IO_WH: /* write halfword */
|
||||
pic_wdp = 0; /* clr ptr */
|
||||
pic_db = dat;
|
||||
break;
|
||||
case IO_WD: /* write */
|
||||
if (pic_wdp) pic_db = (pic_db & 0xFF00) | dat;
|
||||
else pic_db = (pic_db & 0xFF) | (dat << 8);
|
||||
pic_wdp = pic_wdp ^ 1; /* flip byte ptr */
|
||||
break;
|
||||
case IO_SS: /* sense status */
|
||||
if (pic_ovf) { /* overflow? */
|
||||
pic_ovf = 0; /* clear flag */
|
||||
CLR_INT (v_PIC); /* clear intr */
|
||||
return STA_OVF; }
|
||||
return 0;
|
||||
case IO_OC: /* output cmd */
|
||||
pic_arm = int_chg (v_PIC, dat, pic_arm); /* upd int ctrl */
|
||||
if (dat & CMD_STRT) { /* start? */
|
||||
pic_ric = pic_db; /* new ric */
|
||||
pic_cic = GET_CTR (pic_ric); /* new cic */
|
||||
pic_ovf = 0; /* clear flag */
|
||||
sim_cancel (&pic_unit); /* stop clock */
|
||||
pic_rdp = pic_wdp = 0; /* init ptrs */
|
||||
if (pic_ric & PIC_RATE) pic_sched (TRUE); /* any rate? */
|
||||
} /* end if start */
|
||||
break; } /* end case */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Unit service */
|
||||
|
||||
t_stat pic_svc (UNIT *uptr)
|
||||
{
|
||||
t_bool rate_chg = FALSE;
|
||||
|
||||
if (pic_cnti) pic_cic = -1; /* one shot? */
|
||||
pic_cic = pic_cic - 1; /* decrement */
|
||||
if (pic_cic < 0) { /* overflow? */
|
||||
if (pic_wdp) pic_ovf = 1; /* broken wr? set flag */
|
||||
if (pic_arm) SET_INT (v_PIC); /* if armed, intr */
|
||||
if (GET_RATE (pic_ric) != GET_RATE (pic_db)) /* rate change? */
|
||||
rate_chg = TRUE;
|
||||
pic_ric = pic_db; /* new ric */
|
||||
pic_cic = GET_CTR (pic_ric); /* new cic */
|
||||
if ((pic_ric & PIC_RATE) == 0) return SCPE_OK; }
|
||||
pic_sched (rate_chg);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Schedule next interval
|
||||
|
||||
If rate < 1ms, or diagnostic mode, count instructions
|
||||
If rate = 1ms, and not diagnostic mode, use timer
|
||||
*/
|
||||
|
||||
void pic_sched (t_bool strt)
|
||||
{
|
||||
int32 r, t;
|
||||
|
||||
pic_save = sim_grtime (); /* save start */
|
||||
r = pic_map[GET_RATE (pic_ric)]; /* get mapped rate */
|
||||
t = pic_time[r]; /* get delay */
|
||||
if ((r == 3) && !(pic_unit.flags & UNIT_DIAG)) { /* timer? */
|
||||
pic_cnti = 0; /* clr mode */
|
||||
if (strt) t = sim_rtcn_init (t, TMR_PIC); /* init or */
|
||||
else t = sim_rtcn_calb (PIC_TPS, TMR_PIC); } /* calibrate */
|
||||
else { pic_cnti = 1; /* set mode */
|
||||
t = t * (pic_cic + 1); /* interval */
|
||||
if (t == 1) t++; } /* for diagn */
|
||||
sim_activate (&pic_unit, t); /* activate */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Read (interpolated) current interval */
|
||||
|
||||
uint32 pic_rd_cic (void)
|
||||
{
|
||||
if (sim_is_active (&pic_unit) && pic_cnti) { /* running, one shot? */
|
||||
uint32 delta = sim_grtime () - pic_save; /* interval */
|
||||
uint32 tm = pic_time[pic_map[GET_RATE (pic_ric)]]; /* ticks/intv */
|
||||
delta = delta / tm; /* ticks elapsed */
|
||||
if (delta >= ((uint32) pic_cic)) return 0; /* cap value */
|
||||
return pic_cic - delta; }
|
||||
return pic_cic;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat pic_reset (DEVICE *dptr)
|
||||
{
|
||||
sim_cancel (&pic_unit); /* cancel unit */
|
||||
pic_ric = pic_cic = 0;
|
||||
pic_db = 0;
|
||||
pic_ovf = 0; /* clear state */
|
||||
pic_cnti = 0;
|
||||
pic_rdp = pic_wdp = 0;
|
||||
CLR_INT (v_PIC); /* clear int */
|
||||
CLR_ENB (v_PIC); /* disable int */
|
||||
pic_arm = 0; /* disarm int */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Line clock: IO routine */
|
||||
|
||||
uint32 lfc (uint32 dev, uint32 op, uint32 dat)
|
||||
{
|
||||
int32 t;
|
||||
|
||||
switch (op) { /* case IO op */
|
||||
case IO_ADR: /* select */
|
||||
return BY; /* byte only */
|
||||
case IO_OC: /* command */
|
||||
lfc_arm = int_chg (v_LFC, dat, lfc_arm); /* upd int ctrl */
|
||||
if (lfc_arm && !sim_is_active (&lfc_unit)) { /* starting? */
|
||||
t = sim_rtcn_init (lfc_unit.wait, TMR_LFC);
|
||||
sim_activate (&lfc_unit, t); } /* init clock */
|
||||
break; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Unit service */
|
||||
|
||||
t_stat lfc_svc (UNIT *uptr)
|
||||
{
|
||||
int32 t;
|
||||
|
||||
if (lfc_arm) { /* armed? */
|
||||
SET_INT (v_LFC); /* req intr */
|
||||
if (pic_unit.flags & UNIT_DIAG) t = uptr->wait; /* diag? fixed delay */
|
||||
else t = sim_rtcn_calb (lfc_tps, TMR_LFC); /* else calibrate */
|
||||
sim_activate (uptr, t); } /* reactivate */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat lfc_reset (DEVICE *dptr)
|
||||
{
|
||||
sim_cancel (&lfc_unit); /* cancel unit */
|
||||
CLR_INT (v_LFC); /* clear int */
|
||||
CLR_ENB (v_LFC); /* disable int */
|
||||
lfc_arm = 0; /* disarm int */
|
||||
return SCPE_OK;
|
||||
}
|
|
@ -26,7 +26,7 @@ t_stat tti_svc (UNIT *uptr);
|
|||
t_stat tto_svc (UNIT *uptr);
|
||||
t_stat tti_reset (DEVICE *dptr);
|
||||
t_stat tto_reset (DEVICE *dptr);
|
||||
t_stat ttx_setmod (UNIT *uptr, int32 value);
|
||||
t_stat ttx_setmod (UNIT *uptr, int32 value, char *cptr, void *desc);
|
||||
void translate_in();
|
||||
int32 translate_out(int32 c);
|
||||
int32 putseq(char *seq);
|
||||
|
@ -386,7 +386,7 @@ sim_cancel (&tto_unit); /* deactivate unit */
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat ttx_setmod (UNIT *uptr, int32 value)
|
||||
t_stat ttx_setmod (UNIT *uptr, int32 value, char *cptr, void *desc)
|
||||
{
|
||||
tti_unit.flags = (tti_unit.flags & ~UNIT_DASHER) | value;
|
||||
tto_unit.flags = (tto_unit.flags & ~UNIT_DASHER) | value;
|
||||
|
|
|
@ -681,22 +681,22 @@ else { /* IOT */
|
|||
AC[0] = (mddata >> 16) & DMASK;
|
||||
AC[1] = mddata & DMASK; }
|
||||
if (pulse == iopS) { /* div */
|
||||
if ((uAC0 >= uAC2) || (uAC2 == 0))
|
||||
C = CBIT;
|
||||
else { C = 0;
|
||||
if ((uAC0 >= uAC2) || (uAC2 == 0)) C = CBIT;
|
||||
else {
|
||||
C = 0;
|
||||
mddata = (uAC0 << 16) | uAC1;
|
||||
AC[1] = mddata / uAC2;
|
||||
AC[0] = mddata % uAC2; } } }
|
||||
if ((dstAC == 3) && (cpu_unit.flags & UNIT_BYT)) {
|
||||
int32 mddata;
|
||||
if (pulse == iopC) { /* muls */
|
||||
mddata = (SEXT (AC[1]) * SEXT (AC[2])) +
|
||||
SEXT (AC[0]);
|
||||
mddata = (SEXT (AC[1]) * SEXT (AC[2])) + SEXT (AC[0]);
|
||||
AC[0] = (mddata >> 16) & DMASK;
|
||||
AC[1] = mddata & DMASK; }
|
||||
if (pulse == iopN) { /* divs */
|
||||
if (AC[2] == 0) C = CBIT;
|
||||
else { mddata = (SEXT (AC[0]) << 16) | AC[1];
|
||||
else {
|
||||
mddata = (SEXT (AC[0]) << 16) | AC[1];
|
||||
AC[1] = mddata / SEXT (AC[2]);
|
||||
AC[0] = mddata % SEXT (AC[2]);
|
||||
if ((AC[1] > 077777) || (AC[1] < -0100000))
|
||||
|
@ -715,8 +715,7 @@ else { /* IOT */
|
|||
break;
|
||||
case ioDIB: /* int ack */
|
||||
AC[dstAC] = 0;
|
||||
int_req = (int_req & ~INT_DEV) |
|
||||
(dev_done & ~dev_disable);
|
||||
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
|
||||
iodata = int_req & (-int_req);
|
||||
for (i = DEV_LOW; i <= DEV_HIGH; i++) {
|
||||
if (iodata & dev_table[i].mask) {
|
||||
|
|
|
@ -441,12 +441,12 @@ All drives have 256 16b words per sector. The other disk parameters are:
|
|||
D44 408 4 12 5.014 4234, 6045
|
||||
C111 203 10 6 3.118 4048
|
||||
C114 203 20 12 12.472 4057, 2314
|
||||
6225 20 2 245 2.508
|
||||
6099 32 4 192 6.291
|
||||
6227 20 6 245 7.526
|
||||
6070 24 4 408 10.027
|
||||
6103 32 8 192 12.583
|
||||
4231 23 19 411 45.979
|
||||
6225 245 2 20 2.508
|
||||
6099 192 4 32 6.291
|
||||
6227 245 6 20 7.526
|
||||
6070 408 4 24 10.027
|
||||
6103 192 8 32 12.583
|
||||
4231 411 19 23 45.979
|
||||
|
||||
The moving head disk controller implements these registers:
|
||||
|
||||
|
|
|
@ -270,12 +270,14 @@ case iopS: /* start */
|
|||
~(STA_BOT | STA_EOF | STA_EOT | STA_RDY)) | STA_REW);
|
||||
sim_activate (uptr, mta_rwait); /* start IO */
|
||||
if (c == CU_UNLOAD) detach_unit (uptr); }
|
||||
else { mta_sta = 0; /* clear errors */
|
||||
else {
|
||||
mta_sta = 0; /* clear errors */
|
||||
dev_busy = dev_busy | INT_MTA; /* set busy */
|
||||
dev_done = dev_done & ~INT_MTA; /* clear done */
|
||||
int_req = int_req & ~INT_MTA; /* clear int */
|
||||
if (ctype[c]) sim_activate (uptr, mta_cwait);
|
||||
else { mta_upddsta (uptr, uptr->USTAT &
|
||||
else {
|
||||
mta_upddsta (uptr, uptr->USTAT &
|
||||
~(STA_BOT | STA_EOF | STA_EOT | STA_RDY));
|
||||
sim_activate (uptr, mta_rwait); } }
|
||||
mta_updcsta (uptr); /* update status */
|
||||
|
@ -350,7 +352,8 @@ case CU_READNS: /* read non-stop */
|
|||
cbc = wc * 2; /* expected bc */
|
||||
if (tbc & 1) mta_sta = mta_sta | STA_ODD; /* odd byte count? */
|
||||
if (tbc > cbc) mta_sta = mta_sta | STA_WCO; /* too big? */
|
||||
else { cbc = tbc; /* no, use it */
|
||||
else {
|
||||
cbc = tbc; /* no, use it */
|
||||
wc = (cbc + 1) / 2; } /* adjust wc */
|
||||
i = fxread (dbuf, sizeof (int8), cbc, uptr->fileref);
|
||||
for ( ; i < cbc; i++) dbuf[i] = 0;
|
||||
|
@ -382,7 +385,8 @@ case CU_WRITE: /* write */
|
|||
fxwrite (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY);
|
||||
if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr); /* error? */
|
||||
else { mta_wc = 0;
|
||||
else {
|
||||
mta_wc = 0;
|
||||
uptr->pos = uptr->pos + tbc + (2 * sizeof (t_mtrlnt)); }
|
||||
break;
|
||||
|
||||
|
@ -401,7 +405,8 @@ case CU_ERASE: /* erase */
|
|||
break;
|
||||
|
||||
case CU_SPACEF: /* space forward */
|
||||
do { mta_wc = (mta_wc + 1) & DMASK; /* incr wc */
|
||||
do {
|
||||
mta_wc = (mta_wc + 1) & DMASK; /* incr wc */
|
||||
if (mta_rdlntf (uptr, &tbc, &err)) break; /* read rec lnt, err? */
|
||||
uptr->pos = uptr->pos + ((tbc + 1) & ~1) +
|
||||
(2 * sizeof (t_mtrlnt)); }
|
||||
|
@ -410,9 +415,11 @@ case CU_SPACEF: /* space forward */
|
|||
break;
|
||||
|
||||
case CU_SPACER: /* space reverse */
|
||||
do { mta_wc = (mta_wc + 1) & DMASK; /* incr wc */
|
||||
do {
|
||||
mta_wc = (mta_wc + 1) & DMASK; /* incr wc */
|
||||
if (pnu) pnu = 0; /* pos not upd? */
|
||||
else { if (mta_rdlntr (uptr, &tbc, &err)) break;
|
||||
else {
|
||||
if (mta_rdlntr (uptr, &tbc, &err)) break;
|
||||
uptr->pos = uptr->pos - ((tbc + 1) & ~1) -
|
||||
(2 * sizeof (t_mtrlnt)); } }
|
||||
while (mta_wc != 0);
|
||||
|
|
|
@ -544,7 +544,8 @@ case 1: /* PC rel */
|
|||
if (disp & dsign) {
|
||||
if (cflag) fprintf (of, "%-o", (addr - (dmax - disp)) & AMASK);
|
||||
else fprintf (of, ".-%-o", dmax - disp); }
|
||||
else { if (cflag) fprintf (of, "%-o", (addr + disp) & AMASK);
|
||||
else {
|
||||
if (cflag) fprintf (of, "%-o", (addr + disp) & AMASK);
|
||||
else fprintf (of, ".+%-o", disp); }
|
||||
break;
|
||||
case 2: /* AC2 rel */
|
||||
|
@ -847,10 +848,11 @@ case I_V_RD: /* IOT reg,dev */
|
|||
val[0] = val[0] | (d << I_V_DST); /* put in place */
|
||||
case I_V_D: /* IOT dev */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get device */
|
||||
for (i = 0; (device[i] != NULL) && (strcmp (device[i], gbuf) != 0);
|
||||
i++);
|
||||
for (i = 0; (device[i] != NULL) &&
|
||||
(strcmp (device[i], gbuf) != 0); i++);
|
||||
if (device[i] != NULL) val[0] = val[0] | dev_val[i];
|
||||
else { d = get_uint (gbuf, 8, I_M_DEV, &r);
|
||||
else {
|
||||
d = get_uint (gbuf, 8, I_M_DEV, &r);
|
||||
if (r != SCPE_OK) return SCPE_ARG;
|
||||
val[0] = val[0] | (d << I_V_DEV); }
|
||||
break;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* nova_tt.c: NOVA console terminal simulator
|
||||
|
||||
Copyright (c) 1993-2002, Robert M. Supnik
|
||||
Copyright (c) 1993-2003, 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"),
|
||||
|
@ -26,6 +26,7 @@
|
|||
tti terminal input
|
||||
tto terminal output
|
||||
|
||||
05-Jan-02 RMS Fixed calling sequence for setmod
|
||||
03-Oct-02 RMS Added DIBs
|
||||
30-May-02 RMS Widened POS to 32b
|
||||
30-Nov-01 RMS Added extended SET/SHOW support
|
||||
|
@ -46,7 +47,7 @@ t_stat tti_svc (UNIT *uptr);
|
|||
t_stat tto_svc (UNIT *uptr);
|
||||
t_stat tti_reset (DEVICE *dptr);
|
||||
t_stat tto_reset (DEVICE *dptr);
|
||||
t_stat ttx_setmod (UNIT *uptr, int32 val, char *cptr);
|
||||
t_stat ttx_setmod (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
|
||||
/* TTI data structures
|
||||
|
||||
|
@ -210,7 +211,7 @@ sim_cancel (&tto_unit); /* deactivate unit */
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat ttx_setmod (UNIT *uptr, int32 val, char *cptr)
|
||||
t_stat ttx_setmod (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
tti_unit.flags = (tti_unit.flags & ~UNIT_DASHER) | val;
|
||||
tto_unit.flags = (tto_unit.flags & ~UNIT_DASHER) | val;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* nova_tt1.c: NOVA second terminal simulator
|
||||
|
||||
Copyright (c) 1993-2002, Robert M. Supnik
|
||||
Copyright (c) 1993-2003, Robert M. Supnik
|
||||
Written by Bruce Ray and used with his gracious permission.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
|
@ -27,6 +27,7 @@
|
|||
tti1 second terminal input
|
||||
tto1 second terminal output
|
||||
|
||||
05-Jan-03 RMS Fixed calling sequence for setmod
|
||||
03-Oct-02 RMS Added DIBs
|
||||
22-Aug-02 RMS Updated for changes in sim_tmxr
|
||||
30-May-02 RMS Widened POS to 32b
|
||||
|
@ -58,7 +59,7 @@ t_stat tti1_svc (UNIT *uptr);
|
|||
t_stat tto1_svc (UNIT *uptr);
|
||||
t_stat tti1_reset (DEVICE *dptr);
|
||||
t_stat tto1_reset (DEVICE *dptr);
|
||||
t_stat ttx1_setmod (UNIT *uptr, int32 val, char *cptr);
|
||||
t_stat ttx1_setmod (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat tti1_attach (UNIT *uptr, char *cptr);
|
||||
t_stat tti1_detach (UNIT *uptr);
|
||||
t_stat tti1_summ (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
|
@ -259,7 +260,7 @@ sim_cancel (&tto1_unit); /* deactivate unit */
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat ttx1_setmod (UNIT *uptr, int32 val, char *cptr)
|
||||
t_stat ttx1_setmod (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
tti1_unit.flags = (tti1_unit.flags & ~UNIT_DASHER) | val;
|
||||
tto1_unit.flags = (tto1_unit.flags & ~UNIT_DASHER) | val;
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
cpu PDP-1 central processor
|
||||
|
||||
05-Dec-02 RMS Added drum support
|
||||
06-Oct-02 RMS Revised for V2.10
|
||||
20-Aug-02 RMS Added DECtape support
|
||||
30-Dec-01 RMS Added old PC queue
|
||||
|
@ -262,6 +263,7 @@ extern int32 tti (int32 inst, int32 dev, int32 IO);
|
|||
extern int32 tto (int32 inst, int32 dev, int32 IO);
|
||||
extern int32 lpt (int32 inst, int32 dev, int32 IO);
|
||||
extern int32 dt (int32 inst, int32 dev, int32 IO);
|
||||
extern int32 drm (int32 inst, int32 dev, int32 IO);
|
||||
|
||||
int32 sc_map[512] = {
|
||||
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, /* 00000xxxx */
|
||||
|
@ -414,7 +416,8 @@ if ((op < 032) && (op != 007)) { /* mem ref instr */
|
|||
MA = (MA & EPCMASK) | (IR & DAMASK); /* direct address */
|
||||
if (IR & IA) { /* indirect addr? */
|
||||
if (extm) MA = M[MA] & AMASK; /* if ext, one level */
|
||||
else { for (i = 0; i < ind_max; i++) { /* count indirects */
|
||||
else { /* multi-level */
|
||||
for (i = 0; i < ind_max; i++) { /* count indirects */
|
||||
t = M[MA]; /* get indirect word */
|
||||
MA = (MA & EPCMASK) | (t & DAMASK);
|
||||
if ((t & IA) == 0) break; }
|
||||
|
@ -550,7 +553,8 @@ case 026: /* MUL */
|
|||
if ((sign & 0400000) && (AC | IO)) { /* negative, > 0? */
|
||||
AC = AC ^ 0777777;
|
||||
IO = IO ^ 0777777; } }
|
||||
else { if (IO & 1) AC = AC + M[MA]; /* multiply step */
|
||||
else { /* multiply step */
|
||||
if (IO & 1) AC = AC + M[MA];
|
||||
if (AC > 0777777) AC = (AC + 1) & 0777777;
|
||||
if (AC == 0777777) AC = 0;
|
||||
IO = (IO >> 1) | ((AC & 1) << 17);
|
||||
|
@ -577,7 +581,8 @@ case 027: /* DIV */
|
|||
AC = ((sign & 0400000) && IO)? IO ^ 0777777: IO;
|
||||
IO = t;
|
||||
PC = INCR_ADDR (PC); } /* skip */
|
||||
else { t = AC >> 17; /* divide step */
|
||||
else { /* divide step */
|
||||
t = AC >> 17;
|
||||
AC = ((AC << 1) | (IO >> 17)) & 0777777;
|
||||
IO = ((IO << 1) | (t ^ 1)) & 0777777;
|
||||
if (IO & 1) AC = AC + (M[MA] ^ 0777777);
|
||||
|
@ -685,7 +690,8 @@ case 035:
|
|||
if (IR & IO_WAIT) { /* wait? */
|
||||
if (ioh) { /* I/O halt? */
|
||||
if (ioc) ioh = 0; /* comp pulse? done */
|
||||
else { sim_interval = 0; /* force event */
|
||||
else { /* wait more */
|
||||
sim_interval = 0; /* force event */
|
||||
PC = DECR_ADDR (PC); } /* re-execute */
|
||||
break; } /* skip iot */
|
||||
ioh = 1; /* turn on halt */
|
||||
|
@ -726,6 +732,9 @@ case 035:
|
|||
case 056: /* clear seq brk */
|
||||
sbs = sbs & ~SB_IP;
|
||||
break;
|
||||
case 061: case 062: case 063: case 064: /* drum */
|
||||
io_data = drm (IR, dev, IO);
|
||||
break;
|
||||
case 074: /* extend mode */
|
||||
extm = (IR >> 11) & 1; /* set from IR<6> */
|
||||
break;
|
||||
|
@ -733,6 +742,7 @@ case 035:
|
|||
reason = stop_inst;
|
||||
break; } /* end switch dev */
|
||||
IO = io_data & 0777777;
|
||||
if (io_data & IOT_SKP) PC = INCR_ADDR (PC); /* skip? */
|
||||
if (io_data >= IOT_REASON) reason = io_data >> IOT_V_REASON;
|
||||
break;
|
||||
default: /* undefined */
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
05-Dec-02 RMS Added IOT skip support (required by drum)
|
||||
14-Apr-99 RMS Changed t_addr to unsigned
|
||||
|
||||
The PDP-1 was Digital's first computer. The system design evolved during
|
||||
|
@ -67,7 +68,9 @@
|
|||
|
||||
/* IOT subroutine return codes */
|
||||
|
||||
#define IOT_V_REASON 18 /* reason */
|
||||
#define IOT_V_SKP 18 /* skip */
|
||||
#define IOT_SKP (1 << IOT_V_SKP)
|
||||
#define IOT_V_REASON (IOT_V_SKP + 1) /* reason */
|
||||
#define IOT_REASON (1 << IOT_V_REASON)
|
||||
#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
To: Users
|
||||
From: Bob Supnik
|
||||
Subj: PDP-1 Simulator Usage
|
||||
Date: 15-Nov-2002
|
||||
Date: 15-Dec-2002
|
||||
|
||||
COPYRIGHT NOTICE
|
||||
|
||||
|
@ -47,6 +47,7 @@ sim/ sim_defs.h
|
|||
|
||||
sim/pdp1/ pdp1_defs.h
|
||||
pdp1_cpu.c
|
||||
pdp1_drm.c
|
||||
pdp1_dt.c
|
||||
pdp1_lp.c
|
||||
pdp1_stddev.c
|
||||
|
@ -63,6 +64,7 @@ CPU PDP-1 CPU with up to 64KW of memory
|
|||
PTR,PTP integral paper tape reader/punch
|
||||
TTY console typewriter
|
||||
LPT Type 62 line printer
|
||||
DRM Type 24 serial drum
|
||||
DT Type 550 Microtape (DECtape)
|
||||
|
||||
The PDP-1 simulator implements the following unique stop conditions:
|
||||
|
@ -299,7 +301,32 @@ operate correctly.
|
|||
- ACTIME must be less than DCTIME, and both need to be at
|
||||
least 100 times LTIME
|
||||
|
||||
2.4 Symbolic Display and Input
|
||||
2.4 Type 24 Serial Drum (DRM)
|
||||
|
||||
The serial drum (DRM) implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
DA 9 drum address (sector number)
|
||||
MA 16 current memory address
|
||||
INT 1 interrupt pending flag
|
||||
DONE 1 device done flag
|
||||
ERR 1 error flag
|
||||
WLK 32 write lock switches
|
||||
TIME 24 rotational latency, per word
|
||||
STOP_IOE 1 stop on I/O error
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 disk not ready
|
||||
|
||||
Drum data files are buffered in memory; therefore, end of file and OS
|
||||
I/O errors cannot occur.
|
||||
|
||||
2.5 Symbolic Display and Input
|
||||
|
||||
The PDP-1 simulator implements symbolic display and input. Display is
|
||||
controlled by command line switches:
|
||||
|
@ -359,7 +386,7 @@ Finally, the LAW instruction has the format
|
|||
|
||||
where immediate is in the range 0 to 07777.
|
||||
|
||||
2.5 Character Sets
|
||||
2.6 Character Sets
|
||||
|
||||
The PDP-1's console was a Frieden Flexowriter; its character encoding
|
||||
was known as FIODEC. The PDP-1's line printer used a modified Hollerith
|
||||
|
|
169
PDP1/pdp1_drm.c
Normal file
169
PDP1/pdp1_drm.c
Normal file
|
@ -0,0 +1,169 @@
|
|||
/* pdp1_drm.c: drum/fixed head disk simulator
|
||||
|
||||
Copyright (c) 1993-2002, 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.
|
||||
|
||||
drm Type 24 serial drum
|
||||
|
||||
05-Dec-02 RMS Cloned from pdp18b_drm.c
|
||||
*/
|
||||
|
||||
#include "pdp1_defs.h"
|
||||
#include <math.h>
|
||||
|
||||
/* Constants */
|
||||
|
||||
#define DRM_NUMWDS 256 /* words/sector */
|
||||
#define DRM_NUMSC 2 /* sectors/track */
|
||||
#define DRM_NUMTR 256 /* tracks/drum */
|
||||
#define DRM_NUMDK 1 /* drum/controller */
|
||||
#define DRM_NUMWDT (DRM_NUMWDS * DRM_NUMSC) /* words/track */
|
||||
#define DRM_SIZE (DRM_NUMDK * DRM_NUMTR * DRM_NUMWDT) /* words/drum */
|
||||
#define DRM_SMASK ((DRM_NUMTR * DRM_NUMSC) - 1) /* sector mask */
|
||||
|
||||
/* Parameters in the unit descriptor */
|
||||
|
||||
#define FUNC u4 /* function */
|
||||
#define DRM_READ 000 /* read */
|
||||
#define DRM_WRITE 010 /* write */
|
||||
|
||||
#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \
|
||||
((double) DRM_NUMWDT)))
|
||||
|
||||
extern int32 M[];
|
||||
extern int32 iosta, sbs;
|
||||
extern int32 stop_inst;
|
||||
extern UNIT cpu_unit;
|
||||
|
||||
int32 drm_da = 0; /* track address */
|
||||
int32 drm_ma = 0; /* memory address */
|
||||
int32 drm_err = 0; /* error flag */
|
||||
int32 drm_wlk = 0; /* write lock */
|
||||
int32 drm_time = 10; /* inter-word time */
|
||||
int32 drm_stopioe = 1; /* stop on error */
|
||||
|
||||
t_stat drm_svc (UNIT *uptr);
|
||||
t_stat drm_reset (DEVICE *dptr);
|
||||
|
||||
/* DRM data structures
|
||||
|
||||
drm_dev DRM device descriptor
|
||||
drm_unit DRM unit descriptor
|
||||
drm_reg DRM register list
|
||||
*/
|
||||
|
||||
UNIT drm_unit =
|
||||
{ UDATA (&drm_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF,
|
||||
DRM_SIZE) };
|
||||
|
||||
REG drm_reg[] = {
|
||||
{ ORDATA (DA, drm_da, 9) },
|
||||
{ ORDATA (MA, drm_ma, 16) },
|
||||
{ FLDATA (DONE, iosta, IOS_V_DRM) },
|
||||
{ FLDATA (ERR, drm_err, 0) },
|
||||
{ ORDATA (WLK, drm_wlk, 32) },
|
||||
{ DRDATA (TIME, drm_time, 24), REG_NZ + PV_LEFT },
|
||||
{ FLDATA (STOP_IOE, drm_stopioe, 0) },
|
||||
{ NULL } };
|
||||
|
||||
DEVICE drm_dev = {
|
||||
"DRM", &drm_unit, drm_reg, NULL,
|
||||
1, 8, 20, 1, 8, 18,
|
||||
NULL, NULL, &drm_reset,
|
||||
NULL, NULL, NULL,
|
||||
NULL, DEV_DISABLE };
|
||||
|
||||
/* IOT routines */
|
||||
|
||||
int32 drm (int32 IR, int32 dev, int32 IO)
|
||||
{
|
||||
int32 t;
|
||||
int32 pulse = (IR >> 6) & 037;
|
||||
|
||||
if (drm_dev.flags & DEV_DIS) /* disabled? */
|
||||
return (stop_inst << IOT_V_REASON) | IO; /* stop if requested */
|
||||
if ((pulse != 001) & (pulse != 011)) /* invalid pulse? */
|
||||
return (stop_inst << IOT_V_REASON) | IO; /* stop if requested */
|
||||
switch (dev) { /* switch on device */
|
||||
case 061: /* DWR, DRD */
|
||||
drm_ma = IO & 0177777; /* load mem addr */
|
||||
drm_unit.FUNC = pulse & DRM_WRITE; /* save function */
|
||||
break;
|
||||
case 062: /* DBL, DCN */
|
||||
if (pulse & 010) drm_da = IO & DRM_SMASK; /* load sector # */
|
||||
iosta = iosta & ~IOS_DRM; /* clear flags */
|
||||
drm_err = 0;
|
||||
t = ((drm_da % DRM_NUMSC) * DRM_NUMWDS) - GET_POS (drm_time);
|
||||
if (t <= 0) t = t + DRM_NUMWDT; /* wrap around? */
|
||||
break;
|
||||
case 063: /* DTD */
|
||||
if (iosta & IOS_DRM) return (IO | IOT_SKP); /* skip if done */
|
||||
case 064: /* DSE, DSP */
|
||||
if ((drm_err == 0) || (pulse & 010)) /* no error, par test? */
|
||||
return (IO | IOT_SKP);
|
||||
}
|
||||
return IO;
|
||||
}
|
||||
|
||||
/* Unit service
|
||||
|
||||
This code assumes the entire drum is buffered.
|
||||
*/
|
||||
|
||||
t_stat drm_svc (UNIT *uptr)
|
||||
{
|
||||
int32 i;
|
||||
t_addr da;
|
||||
|
||||
if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
|
||||
drm_err = 1; /* set error */
|
||||
iosta = iosta | IOS_DRM; /* set done */
|
||||
sbs = sbs | SB_RQ; /* req intr */
|
||||
return IORETURN (drm_stopioe, SCPE_UNATT); }
|
||||
|
||||
da = drm_da * DRM_NUMWDS; /* compute dev addr */
|
||||
for (i = 0; i < DRM_NUMWDS; i++, da++) { /* do transfer */
|
||||
if (uptr->FUNC == DRM_READ) {
|
||||
if (MEM_ADDR_OK (drm_ma)) /* read, check nxm */
|
||||
M[drm_ma] = *(((int32 *) uptr->filebuf) + da); }
|
||||
else {
|
||||
if ((drm_wlk >> (drm_da >> 4)) & 1) drm_err = 1;
|
||||
else {
|
||||
*(((int32 *) uptr->filebuf) + da) = M[drm_ma];
|
||||
if (da >= uptr->hwmark) uptr->hwmark = da + 1; } }
|
||||
drm_ma = (drm_ma + 1) & 0177777; } /* incr mem addr */
|
||||
drm_da = (drm_da + 1) & DRM_SMASK; /* incr dev addr */
|
||||
iosta = iosta | IOS_DRM; /* set done */
|
||||
sbs = sbs | SB_RQ; /* req intr */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat drm_reset (DEVICE *dptr)
|
||||
{
|
||||
drm_da = drm_ma = drm_err = 0;
|
||||
iosta = iosta & ~IOS_DRM;
|
||||
sim_cancel (&drm_unit);
|
||||
return SCPE_OK;
|
||||
}
|
|
@ -535,7 +535,8 @@ case FNC_WALL: /* write all */
|
|||
if (DT_QEZ (uptr)) { /* in "ok" end zone? */
|
||||
if (dir) newpos = DTU_FWDEZ (uptr) - DT_WSIZE;
|
||||
else newpos = DT_EZLIN + (DT_WSIZE - 1); }
|
||||
else { newpos = ((uptr->pos) / DT_WSIZE) * DT_WSIZE;
|
||||
else {
|
||||
newpos = ((uptr->pos) / DT_WSIZE) * DT_WSIZE;
|
||||
if (!dir) newpos = newpos + (DT_WSIZE - 1); }
|
||||
if ((dt_log & LOG_RA) || ((dt_log & LOG_BL) && (blk == dt_logblk)))
|
||||
printf ("[DT%d: read all block %d %s%s\n",
|
||||
|
@ -692,7 +693,8 @@ case FNC_READ: case FNC_RALL:
|
|||
ba = (blk * DTU_BSIZE (uptr)) + wrd;
|
||||
dtdb = bptr[ba]; /* get tape word */
|
||||
dtsb = dtsb | DTB_DTF; } /* set flag */
|
||||
else { ma = (2 * DT_HTWRD) + DTU_BSIZE (uptr) - DT_CSMWD - 1;
|
||||
else {
|
||||
ma = (2 * DT_HTWRD) + DTU_BSIZE (uptr) - DT_CSMWD - 1;
|
||||
wrd = relpos / DT_WSIZE; /* hdr start = wd 0 */
|
||||
if ((wrd == 0) || /* skip 1st, last */
|
||||
(wrd == ((2 * DT_HTWRD) + DTU_BSIZE (uptr) - 1))) break;
|
||||
|
@ -724,7 +726,8 @@ case FNC_WRIT: case FNC_WALL:
|
|||
if (wrd == (dir? 0: DTU_BSIZE (uptr) - 1))
|
||||
dtsb = dtsb | DTB_BEF; /* end block */
|
||||
else dtsb = dtsb | DTB_DTF; } /* else next word */
|
||||
else { wrd = relpos / DT_WSIZE; /* hdr start = wd 0 */
|
||||
else {
|
||||
wrd = relpos / DT_WSIZE; /* hdr start = wd 0 */
|
||||
if ((wrd == 0) || /* skip 1st, last */
|
||||
(wrd == ((2 * DT_HTWRD) + DTU_BSIZE (uptr) - 1))) break;
|
||||
if ((fnc == FNC_WRIT) && /* wr, skip if !csm */
|
||||
|
@ -830,7 +833,8 @@ for (i = 0; i < DT_NUMDR; i++) { /* stop all drives */
|
|||
sim_activate (uptr, dt_dctime); /* sched decel */
|
||||
DTS_SETSTA (DTS_DECF | (prev_mot & DTS_DIR), 0);
|
||||
} }
|
||||
else { sim_cancel (uptr); /* sim reset */
|
||||
else {
|
||||
sim_cancel (uptr); /* sim reset */
|
||||
uptr->STATE = 0;
|
||||
uptr->LASTT = sim_grtime (); } }
|
||||
dtsa = dtsb = 0; /* clear status */
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
tti keyboard
|
||||
tto teleprinter
|
||||
|
||||
22-Dec-02 RMS Added break support
|
||||
29-Nov-02 RMS Fixed output flag initialization (found by Derek Peschel)
|
||||
21-Nov-02 RMS Changed typewriter to half duplex (found by Derek Peschel)
|
||||
06-Oct-02 RMS Revised for V2.10
|
||||
30-May-02 RMS Widened POS to 32b
|
||||
|
@ -346,6 +348,7 @@ if (tti_hold & CW) { /* char waiting? */
|
|||
tty_buf = tti_hold & TT_WIDTH; /* return char */
|
||||
tti_hold = 0; } /* not waiting */
|
||||
else { if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp;
|
||||
if (temp & SCPE_BREAK) return SCPE_OK; /* ignore break */
|
||||
temp = temp & 0177;
|
||||
if (temp == 0177) temp = '\b'; /* rubout? bs */
|
||||
sim_putchar (temp); /* echo */
|
||||
|
@ -354,7 +357,8 @@ else { if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp;
|
|||
if (in == 0) return SCPE_OK; /* no xlation? */
|
||||
if ((in & BOTH) || ((in & UC) == (tty_uc & UC)))
|
||||
tty_buf = in & TT_WIDTH;
|
||||
else { tty_uc = in & UC; /* shift case */
|
||||
else { /* must shift */
|
||||
tty_uc = in & UC; /* new case */
|
||||
tty_buf = tty_uc? FIODEC_UC: FIODEC_LC;
|
||||
tti_hold = in | CW; } } /* set 2nd waiting */
|
||||
iosta = iosta | IOS_TTI; /* set flag */
|
||||
|
@ -395,7 +399,7 @@ tty_buf = 0; /* clear buffer */
|
|||
tty_uc = 0; /* clear case */
|
||||
tti_hold = 0; /* clear hold buf */
|
||||
tto_rpls = 0; /* clear reset pulse */
|
||||
iosta = iosta & ~(IOS_TTI | IOS_TTO); /* clear flag */
|
||||
iosta = (iosta & ~IOS_TTI) | IOS_TTO; /* clear flag */
|
||||
sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* activate keyboard */
|
||||
sim_cancel (&tty_unit[TTO]); /* stop printer */
|
||||
return SCPE_OK;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
05-Dec-02 RMS Added drum support
|
||||
21-Nov-02 RMS Changed typewriter to half duplex
|
||||
20-Aug-02 RMS Added DECtape support
|
||||
17-Sep-01 RMS Removed multiconsole support
|
||||
|
@ -39,9 +40,12 @@
|
|||
#include <ctype.h>
|
||||
|
||||
extern DEVICE cpu_dev;
|
||||
extern DEVICE ptr_dev, ptp_dev;
|
||||
extern DEVICE ptr_dev;
|
||||
extern DEVICE ptp_dev;
|
||||
extern DEVICE tty_dev;
|
||||
extern DEVICE lpt_dev, dt_dev;
|
||||
extern DEVICE lpt_dev;
|
||||
extern DEVICE dt_dev;
|
||||
extern DEVICE drm_dev;
|
||||
extern UNIT cpu_unit;
|
||||
extern REG cpu_reg[];
|
||||
extern int32 M[];
|
||||
|
@ -72,6 +76,7 @@ DEVICE *sim_devices[] = {
|
|||
&tty_dev,
|
||||
&lpt_dev,
|
||||
&dt_dev,
|
||||
&drm_dev,
|
||||
NULL };
|
||||
|
||||
const char *sim_stop_messages[] = {
|
||||
|
@ -441,13 +446,14 @@ case I_V_NPN: case I_V_IOT: case I_V_OPR: case I_V_SKP:
|
|||
for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0;
|
||||
cptr = get_glyph (cptr, gbuf, 0)) {
|
||||
for (i = 0; (opcode[i] != NULL) &&
|
||||
(strcmp (opcode[i], gbuf) != 0) ; i++) ;
|
||||
(strcmp (opcode[i], gbuf) != 0); i++) ;
|
||||
if (opcode[i] != NULL) {
|
||||
k = opc_val[i] & 0777777;
|
||||
if ((k != IA) && (((k ^ val[0]) & 0760000) != 0))
|
||||
return SCPE_ARG;
|
||||
val[0] = val[0] | k; }
|
||||
else { d = get_sint (gbuf, &sign, &r);
|
||||
else {
|
||||
d = get_sint (gbuf, &sign, &r);
|
||||
if (r != SCPE_OK) return SCPE_ARG;
|
||||
if (sign == 0) val[0] = val[0] + d;
|
||||
else if (sign < 0) val[0] = val[0] - d;
|
||||
|
|
|
@ -623,11 +623,12 @@ else if (abortval == PAGE_FAIL) { /* page fail */
|
|||
rlog = 0; /* clear log */
|
||||
if (pager_tc) flags = pager_flags; /* trap? get flags */
|
||||
if (T20) { /* TOPS-20 */
|
||||
WriteP (upta + UPT_T20_PFL, pager_word);/* write page fail wd */
|
||||
WriteP (upta + UPT_T20_PFL, pager_word); /* write page fail wd */
|
||||
WriteP (upta + UPT_T20_OFL, XWD (flags, 0));
|
||||
WriteP (upta + UPT_T20_OPC, pager_PC);
|
||||
mb = ReadP (upta + UPT_T20_NPC); }
|
||||
else { a10 ea; /* TOPS-10 or ITS */
|
||||
else {
|
||||
a10 ea; /* TOPS-10 or ITS */
|
||||
if (ITS) { /* ITS? */
|
||||
ea = epta + EPT_ITS_PAG + (pi_m2lvl[pi_act] * 3);
|
||||
if (its_1pr) flags = flags | F_1PR; /* store 1-proc */
|
||||
|
@ -670,8 +671,7 @@ if (qintr) {
|
|||
mb = ReadP (epta + EPT_UBIT + uba); /* get dispatch table */
|
||||
if (mb == 0) ABORT (STOP_ZERINT); /* invalid? stop */
|
||||
inst = ReadE ((((a10) mb) + (vec / 4)) & AMASK);
|
||||
if (inst == 0)
|
||||
ABORT (STOP_ZERINT); }
|
||||
if (inst == 0) ABORT (STOP_ZERINT); }
|
||||
else inst = ReadP (epta + EPT_PIIT + (2 * qintr));
|
||||
op = GET_OP (inst); /* get opcode */
|
||||
ac = GET_AC (inst); /* get ac */
|
||||
|
@ -1269,7 +1269,8 @@ MUUO: its_2pr = 0; /* clear trap */
|
|||
WriteP (upta + UPT_MUPC, PC); /* store PC */
|
||||
WriteP (upta + UPT_T20_UEA, ea); /* store eff addr */
|
||||
WriteP (upta + UPT_T20_CTX, UBRWORD); } /* store context */
|
||||
else { WriteP (upta + UPT_MUUO, UUOWORD); /* store instr word */
|
||||
else { /* TOPS10/ITS */
|
||||
WriteP (upta + UPT_MUUO, UUOWORD); /* store instr word */
|
||||
WriteP (upta + UPT_MUPC, XWD ( /* store flags,,PC */
|
||||
flags & ~(F_T2 | F_T1), PC)); /* traps clear */
|
||||
WriteP (upta + UPT_T10_CTX, UBRWORD); } /* store context */
|
||||
|
@ -1492,12 +1493,14 @@ else if (ea & RSIGN) {
|
|||
if (sc >= 36) {
|
||||
AC(p1) = AC(ac) >> (sc - 36);
|
||||
AC(ac) = 0; }
|
||||
else { AC(p1) = ((AC(p1) >> sc) | (AC(ac) << (36 - sc))) & DMASK;
|
||||
else {
|
||||
AC(p1) = ((AC(p1) >> sc) | (AC(ac) << (36 - sc))) & DMASK;
|
||||
AC(ac) = AC(ac) >> sc; } }
|
||||
else { if (sc >= 36) {
|
||||
AC(ac) = (AC(p1) << (sc - 36)) & DMASK;
|
||||
AC(p1) = 0; }
|
||||
else { AC(ac) = ((AC(ac) << sc) | (AC(p1) >> (36 - sc))) & DMASK;
|
||||
else {
|
||||
AC(ac) = ((AC(ac) << sc) | (AC(p1) >> (36 - sc))) & DMASK;
|
||||
AC(p1) = (AC(p1) << sc) & DMASK; } }
|
||||
return;
|
||||
}
|
||||
|
@ -1554,7 +1557,8 @@ if (ea & RSIGN) {
|
|||
if (sc >= 35) { /* right 36..70 */
|
||||
AC(p1) = ((AC(ac) >> (sc - 35)) | (fill << (70 - sc))) & DMASK;
|
||||
AC(ac) = fill; }
|
||||
else { AC(p1) = sign | /* right 1..35 */
|
||||
else {
|
||||
AC(p1) = sign | /* right 1..35 */
|
||||
(((AC(p1) >> sc) | (AC(ac) << (35 - sc))) & MMASK);
|
||||
AC(ac) = ((AC(ac) >> sc) | (fill << (35 - sc))) & DMASK; } }
|
||||
else { if (sc >= 35) { /* left 36..70 */
|
||||
|
@ -1563,7 +1567,8 @@ else { if (sc >= 35) { /* left 36..70 */
|
|||
(so != (sign? bytemask[sc - 35]: 0))) SETF (F_AOV | F_T1);
|
||||
AC(ac) = sign | ((AC(p1) << (sc - 35)) & MMASK);
|
||||
AC(p1) = sign; }
|
||||
else { so = AC(ac) >> (35 - sc); /* bits lost left */
|
||||
else {
|
||||
so = AC(ac) >> (35 - sc); /* bits lost left */
|
||||
if (so != (sign? bytemask[sc]: 0)) SETF (F_AOV | F_T1);
|
||||
AC(ac) = sign |
|
||||
(((AC(ac) << sc) | (AC(p1) >> (35 - sc))) & MMASK);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp10_defs.h: PDP-10 simulator definitions
|
||||
|
||||
Copyright (c) 1993-2002, Robert M Supnik
|
||||
Copyright (c) 1993-2003, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,7 @@
|
|||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
09-Jan-03 RMS Added DEUNA/DELUA support
|
||||
29-Sep-02 RMS Added variable vector, RX211 support
|
||||
22-Apr-02 RMS Removed magtape record length error
|
||||
20-Jan-02 RMS Added multiboard DZ11 support
|
||||
|
@ -637,6 +638,8 @@ typedef struct pdp_dib DIB;
|
|||
#define IOLN_UBCS3 001
|
||||
#define IOBA_UBMNT3 (IO_UBA3 + 0763101) /* Unibus 3 maint reg */
|
||||
#define IOLN_UBMNT3 001
|
||||
#define IOBA_XU (IO_UBA3 + 0774510) /* DEUNA/DELUA */
|
||||
#define IOLN_XU 010
|
||||
#define IOBA_RY (IO_UBA3 + 0777170) /* RX211 */
|
||||
#define IOLN_RY 004
|
||||
#define IOBA_TU (IO_UBA3 + 0772440) /* RH11/tape */
|
||||
|
@ -672,6 +675,7 @@ typedef struct pdp_dib DIB;
|
|||
|
||||
#define INT_V_RP 6 /* RH11/RP,RM drives */
|
||||
#define INT_V_TU 7 /* RH11/TM03/TU45 */
|
||||
#define INT_V_XU 15 /* DEUNA/DELUA */
|
||||
#define INT_V_DZRX 16 /* DZ11 */
|
||||
#define INT_V_DZTX 17
|
||||
#define INT_V_RY 18 /* RX211 */
|
||||
|
@ -681,6 +685,7 @@ typedef struct pdp_dib DIB;
|
|||
|
||||
#define INT_RP (1u << INT_V_RP)
|
||||
#define INT_TU (1u << INT_V_TU)
|
||||
#define INT_XU (1u << INT_V_XU)
|
||||
#define INT_DZRX (1u << INT_V_DZRX)
|
||||
#define INT_DZTX (1u << INT_V_DZTX)
|
||||
#define INT_RY (1u << INT_V_RY)
|
||||
|
@ -690,6 +695,7 @@ typedef struct pdp_dib DIB;
|
|||
|
||||
#define IPL_RP 6 /* int levels */
|
||||
#define IPL_TU 6
|
||||
#define IPL_XU 5
|
||||
#define IPL_DZRX 5
|
||||
#define IPL_DZTX 5
|
||||
#define IPL_RY 5
|
||||
|
@ -708,6 +714,7 @@ typedef struct pdp_dib DIB;
|
|||
#define VEC_Q 0000 /* vector base */
|
||||
#define VEC_PTR 0070 /* interrupt vectors */
|
||||
#define VEC_PTP 0074
|
||||
#define VEC_XU 0120
|
||||
#define VEC_TU 0224
|
||||
#define VEC_RP 0254
|
||||
#define VEC_RY 0264
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
To: Users
|
||||
From: Bob Supnik
|
||||
Subj: PDP-10 Simulator Usage
|
||||
Date: 15-Nov-2002
|
||||
Date: 15-Jan-2003
|
||||
|
||||
COPYRIGHT NOTICE
|
||||
|
||||
The following copyright notice applies to both the SIMH source and binary:
|
||||
|
||||
Original code published in 1993-2002, written by Robert M Supnik
|
||||
Copyright (c) 1993-2002, Robert M Supnik
|
||||
Original code published in 1993-2003, written by Robert M Supnik
|
||||
Copyright (c) 1993-2003, 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"),
|
||||
|
@ -45,10 +45,12 @@ sim/ dec_dz.h
|
|||
sim_rev.h
|
||||
sim_sock.h
|
||||
sim_tmxr.h
|
||||
sim_ether.h
|
||||
scp.c
|
||||
scp_tty.c
|
||||
sim_sock.c
|
||||
sim_tmxr.c
|
||||
sim_ether.c
|
||||
|
||||
sim/pdp10/ pdp10_defs.h
|
||||
pdp10_cpu.c
|
||||
|
@ -65,6 +67,7 @@ sim/pdp10/ pdp10_defs.h
|
|||
pdp10_xtnd.c
|
||||
|
||||
sim/pdp11/ pdp11_ry.c
|
||||
pdp11_xu.c
|
||||
|
||||
2. PDP-10 Features
|
||||
|
||||
|
@ -85,6 +88,7 @@ LP20 LP20 line printer
|
|||
RP RH11/RP04/RP05/RP06/RP07/RM03/RM05/RM80 controller with
|
||||
eight drives
|
||||
TU RH11/TM02/TU45 controller with eight drives
|
||||
XU DEUNA/DELUA Ethernet controller
|
||||
|
||||
The PTR, PTP, and RX211 are initially set DISABLED. The DZ11 and LP20 can
|
||||
also be set DISABLED. Some devices support the SET ADDRESS command, which
|
||||
|
@ -563,7 +567,12 @@ Error handling is as follows:
|
|||
RX02 data files are buffered in memory; therefore, end of file and OS
|
||||
I/O errors cannot occur.
|
||||
|
||||
2.13 Symbolic Display and Input
|
||||
2.13 DEUNA/DELUA Ethernet Controller (XU)
|
||||
|
||||
XU simulates the DEUNA/DELUA Ethernet controller. The current implementation
|
||||
is a stub and is permanently disabled.
|
||||
|
||||
2.14 Symbolic Display and Input
|
||||
|
||||
The PDP-10 simulator implements symbolic display and input. Display is
|
||||
controlled by command line switches:
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
fe KS10 console front end
|
||||
|
||||
22-Dec-02 RMS Added break support
|
||||
30-May-02 RMS Widened COUNT to 32b
|
||||
30-Nov-01 RMS Added extended SET/SHOW support
|
||||
23-Oct-01 RMS New IO page address constants
|
||||
|
@ -128,6 +129,7 @@ int32 temp;
|
|||
|
||||
sim_activate (&fei_unit, fei_unit.wait); /* continue poll */
|
||||
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */
|
||||
if (temp & SCPE_BREAK) return SCPE_OK; /* ignore break */
|
||||
fei_unit.buf = temp & 0177;
|
||||
fei_unit.pos = fei_unit.pos + 1;
|
||||
M[FE_CTYIN] = fei_unit.buf | FE_CVALID; /* put char in mem */
|
||||
|
|
|
@ -313,7 +313,8 @@ case 05: /* LPRDAT */
|
|||
case 06: /* LPCOLC/LPCBUF */
|
||||
if ((access == WRITEB) && (pa & 1)) /* odd byte */
|
||||
lpcolc = data & 0377;
|
||||
else { lpcbuf = data & 0377; /* even byte, word */
|
||||
else {
|
||||
lpcbuf = data & 0377; /* even byte, word */
|
||||
if (access == WRITE) lpcolc = (data >> 8) & 0377; }
|
||||
break;
|
||||
case 07: /* LPCSUM/LPPDAT */
|
||||
|
@ -492,7 +493,8 @@ if (davfu[dvptr] & (1 << DV_TOF)) { /* at top of form? */
|
|||
if (lppagc = (lppagc - 1) & PAGC_MASK) { /* decr page cntr */
|
||||
lpcsa = lpcsa & ~CSA_PZRO; /* update status */
|
||||
return TRUE; }
|
||||
else { lpcsa = lpcsa | CSA_PZRO; /* stop if zero */
|
||||
else {
|
||||
lpcsa = lpcsa | CSA_PZRO; /* stop if zero */
|
||||
return FALSE; } }
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -513,7 +515,8 @@ for (i = 0; i < dvlnt; i++) { /* search DAVFU */
|
|||
if (lppagc = (lppagc - 1) & PAGC_MASK) { /* decr page cntr */
|
||||
lpcsa = lpcsa & ~CSA_PZRO; /* update status */
|
||||
return TRUE; }
|
||||
else { lpcsa = lpcsa | CSA_PZRO; /* stop if zero */
|
||||
else {
|
||||
lpcsa = lpcsa | CSA_PZRO; /* stop if zero */
|
||||
return FALSE; } }
|
||||
} /* end for */
|
||||
dvlnt = 0; /* DAVFU error */
|
||||
|
|
|
@ -381,7 +381,8 @@ else { funpack (op1, 0, &a, SFRC); /* unpack operands */
|
|||
a.fhi = UNEG (a.fhi); /* complement result */
|
||||
a.sign = 1; } /* result is - */
|
||||
else a.sign = 0; } /* result is + */
|
||||
else { if (a.sign) a.fhi = UNEG (a.fhi); /* add, src -? comp */
|
||||
else {
|
||||
if (a.sign) a.fhi = UNEG (a.fhi); /* add, src -? comp */
|
||||
if (a.fhi & FP_UCRY) { /* check for carry */
|
||||
a.fhi = a.fhi >> 1; /* flo won't be used */
|
||||
a.exp = a.exp + 1; } } }
|
||||
|
@ -533,7 +534,8 @@ else {
|
|||
DUNEG (a); /* complement result */
|
||||
a.sign = 1; } /* result is - */
|
||||
else a.sign = 0; } /* result is + */
|
||||
else { if (a.sign) { DUNEG (a); }; /* add, src -? comp */
|
||||
else {
|
||||
if (a.sign) { DUNEG (a); }; /* add, src -? comp */
|
||||
if (a.fhi & FP_UCRY) { /* check for carry */
|
||||
a.fhi = a.fhi >> 1; /* flo won't be used */
|
||||
a.exp = a.exp + 1; } } }
|
||||
|
@ -629,8 +631,10 @@ r->flo = 0;
|
|||
if (r->sign) {
|
||||
r->exp = r->exp ^ FP_M_EXP;
|
||||
if (sgn) r->fhi = r->fhi | FP_UCRY; /* ext sign */
|
||||
else { if (r->fhi) r->fhi = UNEG (r->fhi) & FP_UFRAC;
|
||||
else { r->exp = r->exp + 1;
|
||||
else {
|
||||
if (r->fhi) r->fhi = UNEG (r->fhi) & FP_UFRAC;
|
||||
else {
|
||||
r->exp = r->exp + 1;
|
||||
r->fhi = FP_UNORM; } } }
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -510,7 +510,8 @@ if (PAGING) {
|
|||
ac_cur = &acs[UBR_GETCURAC (ubr) * AC_NUM];
|
||||
ac_prv = &acs[UBR_GETPRVAC (ubr) * AC_NUM];
|
||||
if (TSTF (F_USR)) ptbl_cur = ptbl_prv = &uptbl[0];
|
||||
else { ptbl_cur = &eptbl[0];
|
||||
else {
|
||||
ptbl_cur = &eptbl[0];
|
||||
ptbl_prv = TSTF (F_UIO)? &uptbl[0]: &eptbl[0]; } }
|
||||
else { ac_cur = ac_prv = &acs[0];
|
||||
ptbl_cur = ptbl_prv = &physptbl[0]; }
|
||||
|
|
|
@ -614,7 +614,8 @@ case 003: /* RPDA */
|
|||
case 004: /* RPCS2 */
|
||||
if ((access == WRITEB) && (PA & 1)) data = data << 8;
|
||||
if (data & CS2_CLR) rp_reset (&rp_dev); /* init? */
|
||||
else { if ((data & ~rpcs2) & (CS2_PE | CS2_MXF))
|
||||
else {
|
||||
if ((data & ~rpcs2) & (CS2_PE | CS2_MXF))
|
||||
cs1f = CS1_SC; /* diagn intr */
|
||||
if (access == WRITEB) data = (rpcs2 & /* merge data */
|
||||
((PA & 1)? 0377: 0177400)) | data;
|
||||
|
@ -650,7 +651,6 @@ case 016: /* RPDC */
|
|||
(rpdc & 0377) | (data << 8): (rpdc & ~0377) | data;
|
||||
rpdc = data & ~DC_MBZ;
|
||||
break;
|
||||
break;
|
||||
case 005: /* RPDS */
|
||||
case 010: /* RPLA */
|
||||
case 013: /* RPDT */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp10_sys.c: PDP-10 simulator interface
|
||||
|
||||
Copyright (c) 1993-2002, Robert M Supnik
|
||||
Copyright (c) 1993-2003, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,7 @@
|
|||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
09-Jan-03 RMS Added DEUNA/DELUA support
|
||||
12-Sep-02 RMS Added RX211 support
|
||||
22-Apr-02 RMS Removed magtape record length error
|
||||
17-Sep-01 RMS Removed multiconsole support
|
||||
|
@ -44,6 +45,7 @@ extern DEVICE ptr_dev, ptp_dev;
|
|||
extern DEVICE rp_dev, tu_dev;
|
||||
extern DEVICE dz_dev, ry_dev;
|
||||
extern DEVICE lp20_dev;
|
||||
extern DEVICE xu_dev;
|
||||
extern UNIT cpu_unit;
|
||||
extern REG cpu_reg[];
|
||||
extern d10 *M;
|
||||
|
@ -78,6 +80,7 @@ DEVICE *sim_devices[] = {
|
|||
&rp_dev,
|
||||
&tu_dev,
|
||||
&dz_dev,
|
||||
&xu_dev,
|
||||
NULL };
|
||||
|
||||
const char *sim_stop_messages[] = {
|
||||
|
@ -152,9 +155,10 @@ for ( ;; ) { /* loop until JRST */
|
|||
M[pa] = data; } /* end for */
|
||||
data = getrimw (fileref); /* get cksm */
|
||||
if (data < 0) return SCPE_FMT;
|
||||
if ((cksm + data) & DMASK) return SCPE_CSUM; /* test cksm */
|
||||
if ((cksm + data) & DMASK) return SCPE_CSUM;/* test cksm */
|
||||
} /* end if count */
|
||||
else { op = GET_OP (count); /* not IOWD */
|
||||
else {
|
||||
op = GET_OP (count); /* not IOWD */
|
||||
if (op != OP_JRST) return SCPE_FMT; /* JRST? */
|
||||
saved_PC = (a10) count & AMASK; /* set PC */
|
||||
return SCPE_OK; } /* end else */
|
||||
|
@ -191,7 +195,8 @@ for ( ;; ) { /* loop */
|
|||
pa = ((a10) count + 1) & AMASK; /* store data */
|
||||
M[pa] = data; } /* end for */
|
||||
} /* end if count*/
|
||||
else { op = GET_OP (count); /* not IOWD */
|
||||
else {
|
||||
op = GET_OP (count); /* not IOWD */
|
||||
if (op != OP_JRST) return SCPE_FMT; /* JRST? */
|
||||
saved_PC = (a10) count & AMASK; /* set PC */
|
||||
return SCPE_OK; } /* end else */
|
||||
|
|
|
@ -486,7 +486,8 @@ case 000: /* MTCS1 */
|
|||
else if (tucs1 & CS1_GO) { /* busy? */
|
||||
if (tucs1 & CS1_DONE) tuer = tuer | ER_RMR;
|
||||
else tucs2 = tucs2 | CS2_PGE; }
|
||||
else { tucs1 = (tucs1 & ~CS1_DRV) | (data & CS1_DRV);
|
||||
else {
|
||||
tucs1 = (tucs1 & ~CS1_DRV) | (data & CS1_DRV);
|
||||
if (tucs1 & CS1_GO) tu_go (drv); } }
|
||||
break;
|
||||
case 001: /* MTWC */
|
||||
|
@ -508,7 +509,8 @@ case 003: /* MTFC */
|
|||
case 004: /* MTCS2 */
|
||||
if ((access == WRITEB) && (PA & 1)) data = data << 8;
|
||||
if (data & CS2_CLR) tu_reset (&tu_dev); /* init? */
|
||||
else { if ((data & ~tucs2) & (CS2_PE | CS2_MXF))
|
||||
else {
|
||||
if ((data & ~tucs2) & (CS2_PE | CS2_MXF))
|
||||
cs1f = CS1_SC; /* diagn intr */
|
||||
if (access == WRITEB) data = (tucs2 & /* merge data */
|
||||
((PA & 1)? 0377: 0177400)) | data;
|
||||
|
@ -706,8 +708,9 @@ switch (f) { /* case on function */
|
|||
/* Unit service - non-data transfer commands - set ATA when done */
|
||||
|
||||
case FNC_SPACEF: /* space forward */
|
||||
do { tufc = (tufc + 1) & 0177777; /* incr fc */
|
||||
if (tu_rdlntf (uptr, &tbc, &err)) break;/* read rec lnt, err? */
|
||||
do {
|
||||
tufc = (tufc + 1) & 0177777; /* incr fc */
|
||||
if (tu_rdlntf (uptr, &tbc, &err)) break; /* read rec lnt, err? */
|
||||
uptr->pos = uptr->pos + ((MTRL (tbc) + 1) & ~1) +
|
||||
(2 * sizeof (t_mtrlnt)); }
|
||||
while (tufc != 0);
|
||||
|
@ -717,9 +720,11 @@ case FNC_SPACEF: /* space forward */
|
|||
break;
|
||||
|
||||
case FNC_SPACER: /* space reverse */
|
||||
do { tufc = (tufc + 1) & 0177777; /* incr wc */
|
||||
do {
|
||||
tufc = (tufc + 1) & 0177777; /* incr wc */
|
||||
if (pnu) pnu = 0; /* pos not upd? */
|
||||
else { if (tu_rdlntr (uptr, &tbc, &err)) break;
|
||||
else {
|
||||
if (tu_rdlntr (uptr, &tbc, &err)) break;
|
||||
uptr->pos = uptr->pos - ((MTRL (tbc) + 1) & ~1) -
|
||||
(2 * sizeof (t_mtrlnt)); } }
|
||||
while (tufc != 0);
|
||||
|
@ -803,7 +808,8 @@ case FNC_WRITE: /* write */
|
|||
fxwrite (xbuf, sizeof (int8), (fc + 1) & ~1, uptr->fileref);
|
||||
fxwrite (&fc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr);
|
||||
else { uptr->pos = uptr->pos + ((fc + 1) & ~1) +
|
||||
else {
|
||||
uptr->pos = uptr->pos + ((fc + 1) & ~1) +
|
||||
(2 * sizeof (t_mtrlnt));
|
||||
tufc = (tufc + fc) & 0177777;
|
||||
if (tufc == 0) tutc = tutc & ~TC_FCS;
|
||||
|
|
|
@ -274,7 +274,8 @@ case XT_CVTBDT: /* CVTBDT */
|
|||
rs[0] = rs[0] - pwrs10[i][0] - (rs[1] < pwrs10[i][1]);
|
||||
rs[1] = (rs[1] - pwrs10[i][1]) & MMASK; }
|
||||
if (xop == XT_CVTBDO) digit = (digit + xoff) & DMASK;
|
||||
else { f1 = Read (e1 + (int32) digit, MM_OPND);
|
||||
else {
|
||||
f1 = Read (e1 + (int32) digit, MM_OPND);
|
||||
if ((i == 1) && (AC(p3) & XT_LFLG)) f1 = f1 >> 18;
|
||||
digit = f1 & RMASK; }
|
||||
incstorebp (digit, p4, pflgs); /* store digit */
|
||||
|
@ -306,7 +307,8 @@ case XT_CVTDBO: /* CVTDBO */
|
|||
rlog = 0; /* clear log */
|
||||
b1 = incloadbp (p1, pflgs); /* get byte */
|
||||
if (xop == XT_CVTDBO) b1 = (b1 + xoff) & DMASK;
|
||||
else { b1 = xlate (b1, e1, &xflgs, MM_OPND);
|
||||
else {
|
||||
b1 = xlate (b1, e1, &xflgs, MM_OPND);
|
||||
if (b1 < 0) { /* terminated? */
|
||||
AC(ac) = xflgs | ((AC(ac) - 1) & XLNTMASK);
|
||||
if (TSTS (AC(p3))) AC(p4) = SETS (AC(p4));
|
||||
|
@ -425,7 +427,8 @@ case XT_EDIT: /* EDIT */
|
|||
switch (i) {
|
||||
case 00: case 02: case 03:
|
||||
if (xflgs & XT_SFLG) f1 = f1 & XT_BYMASK;
|
||||
else { f1 = Read (INCA (ea), MM_OPND);
|
||||
else {
|
||||
f1 = Read (INCA (ea), MM_OPND);
|
||||
if (f1 == 0) break; }
|
||||
incstorebp (f1, p4, pflgs);
|
||||
break;
|
||||
|
@ -465,7 +468,8 @@ case XT_EDIT: /* EDIT */
|
|||
case (0100 + (ED_MESSAG >> ED_V_POPC)): /* message */
|
||||
if (xflgs & XT_SFLG)
|
||||
f1 = Read (ea + (pat & ED_M_NUM) + 1, MM_OPND);
|
||||
else { f1 = Read (ea + 1, MM_OPND);
|
||||
else {
|
||||
f1 = Read (ea + 1, MM_OPND);
|
||||
if (f1 == 0) break; }
|
||||
incstorebp (f1, p4, pflgs);
|
||||
break;
|
||||
|
|
|
@ -621,7 +621,8 @@ case 0150: case 0151: case 0170: case 0171:
|
|||
if (CmpDstr (&src1, &src2) < 0) { /* src1 < src2? */
|
||||
SubDstr (&src1, &src2, &dst); /* src2 - src1 */
|
||||
dst.sign = src2.sign; } /* sign = src2 */
|
||||
else { SubDstr (&src2, &src1, &dst); /* src1 - src2 */
|
||||
else {
|
||||
SubDstr (&src2, &src1, &dst); /* src1 - src2 */
|
||||
dst.sign = src1.sign; } /* sign = src1 */
|
||||
V = 0; } /* can't carry */
|
||||
else { /* addition */
|
||||
|
@ -735,7 +736,8 @@ case 052: case 072: case 0152: case 0172:
|
|||
ReadDstr (A2, &src2, op); /* get source2 */
|
||||
N = Z = V = C = 0;
|
||||
if (src1.sign != src2.sign) N = src1.sign;
|
||||
else { t = CmpDstr (&src1, &src2); /* compare strings */
|
||||
else {
|
||||
t = CmpDstr (&src1, &src2); /* compare strings */
|
||||
if (t < 0) N = 1;
|
||||
else if (t == 0) Z = 1; }
|
||||
if ((op & INLINE) == 0) /* if reg, clr reg */
|
||||
|
@ -856,7 +858,8 @@ case 053: case 073: case 0153: case 0173:
|
|||
WriteW (result & 0177777, A2LNT | dsenable);
|
||||
WriteW ((result >> 16) & 0177777,
|
||||
((A2LNT + 2) & 0177777) | dsenable); }
|
||||
else { R[0] = R[1] = 0;
|
||||
else {
|
||||
R[0] = R[1] = 0;
|
||||
R[2] = (result >> 16) & 0177777;
|
||||
R[3] = result & 0177777; }
|
||||
return;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp11_cpu.c: PDP-11 CPU simulator
|
||||
|
||||
Copyright (c) 1993-2002, Robert M Supnik
|
||||
Copyright (c) 1993-2003, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -25,6 +25,7 @@
|
|||
|
||||
cpu PDP-11 CPU (J-11 microprocessor)
|
||||
|
||||
05-Jan-03 RMS Added memory size restore support
|
||||
17-Oct-02 RMS Fixed bug in examine/deposit (found by Hans Pufal)
|
||||
08-Oct-02 RMS Revised to build dib_tab dynamically
|
||||
Added SHOW IOSPACE
|
||||
|
@ -559,7 +560,8 @@ DEVICE cpu_dev = {
|
|||
"CPU", &cpu_unit, cpu_reg, cpu_mod,
|
||||
1, 8, 22, 2, 8, 16,
|
||||
&cpu_ex, &cpu_dep, &cpu_reset,
|
||||
NULL, NULL, NULL };
|
||||
NULL, NULL, NULL,
|
||||
NULL, DEV_DYNM, &cpu_set_size };
|
||||
|
||||
t_stat sim_instr (void)
|
||||
{
|
||||
|
@ -672,7 +674,8 @@ if (trap_req) { /* check traps, ints */
|
|||
} /* end if t & 1 */
|
||||
} /* end for */
|
||||
} /* end if t */
|
||||
else { trapea = get_vector (ipl); /* get int vector */
|
||||
else {
|
||||
trapea = get_vector (ipl); /* get int vector */
|
||||
trapnum = TRAP_V_MAX; /* defang stk trap */
|
||||
} /* end else t*/
|
||||
if (trapea == 0) { /* nothing to do? */
|
||||
|
@ -765,7 +768,8 @@ case 000:
|
|||
case 0: /* HALT */
|
||||
if ((cm == KERNEL) && ((MAINT & MAINT_HTRAP) == 0))
|
||||
reason = STOP_HALT;
|
||||
else { setTRAP (TRAP_PRV);
|
||||
else {
|
||||
setTRAP (TRAP_PRV);
|
||||
setCPUERR (CPUE_HALT); }
|
||||
break;
|
||||
case 1: /* WAIT */
|
||||
|
@ -781,8 +785,7 @@ case 000:
|
|||
if (cm == KERNEL) {
|
||||
reset_all (1);
|
||||
PIRQ = 0;
|
||||
for (i = 0; i < IPL_HLVL; i++)
|
||||
int_req[i] = 0;
|
||||
for (i = 0; i < IPL_HLVL; i++) int_req[i] = 0;
|
||||
MMR0 = MMR0 & ~(MMR0_MME | MMR0_FREEZE);
|
||||
MMR3 = 0;
|
||||
trap_req = trap_req & ~TRAP_INT;
|
||||
|
@ -802,7 +805,8 @@ case 000:
|
|||
pm = (src2 >> PSW_V_PM) & 03;
|
||||
rs = (src2 >> PSW_V_RS) & 01;
|
||||
ipl = (src2 >> PSW_V_IPL) & 07; }
|
||||
else { cm = cm | ((src2 >> PSW_V_CM) & 03);
|
||||
else {
|
||||
cm = cm | ((src2 >> PSW_V_CM) & 03);
|
||||
pm = pm | ((src2 >> PSW_V_PM) & 03);
|
||||
rs = rs | ((src2 >> PSW_V_RS) & 01); }
|
||||
tbit = (src2 >> PSW_V_TBIT) & 01;
|
||||
|
@ -830,7 +834,8 @@ case 000:
|
|||
|
||||
case 001: /* JMP */
|
||||
if (dstreg) setTRAP (TRAP_ILL);
|
||||
else { JMP_PC (GeteaW (dstspec) & 0177777); }
|
||||
else {
|
||||
JMP_PC (GeteaW (dstspec) & 0177777); }
|
||||
break; /* end JMP */
|
||||
case 002: /* RTS et al*/
|
||||
if (IR < 000210) { /* RTS */
|
||||
|
@ -914,7 +919,8 @@ case 000:
|
|||
case 040: case 041: case 042: case 043: /* JSR */
|
||||
case 044: case 045: case 046: case 047:
|
||||
if (dstreg) setTRAP (TRAP_ILL);
|
||||
else { srcspec = srcspec & 07;
|
||||
else {
|
||||
srcspec = srcspec & 07;
|
||||
dst = GeteaW (dstspec);
|
||||
SP = (SP - 2) & 0177777;
|
||||
if (update_MM) MMR1 = calc_MMR1 (0366);
|
||||
|
@ -1059,8 +1065,8 @@ case 000:
|
|||
if (dstreg) {
|
||||
if ((dstspec == 6) && (cm != pm)) dst = STACKFILE[pm];
|
||||
else dst = R[dstspec]; }
|
||||
else { i = ((cm == pm) && (cm == USER))?
|
||||
calc_ds (pm): calc_is (pm);
|
||||
else {
|
||||
i = ((cm == pm) && (cm == USER))? calc_ds (pm): calc_is (pm);
|
||||
dst = ReadW ((GeteaW (dstspec) & 0177777) | i); }
|
||||
N = GET_SIGN_W (dst);
|
||||
Z = GET_Z (dst);
|
||||
|
@ -1097,7 +1103,8 @@ case 000:
|
|||
case 070: /* CSM */
|
||||
if (((MMR3 & MMR3_CSM) == 0) || (cm == KERNEL))
|
||||
setTRAP (TRAP_ILL);
|
||||
else { dst = dstreg? R[dstspec]: ReadW (GeteaW (dstspec));
|
||||
else {
|
||||
dst = dstreg? R[dstspec]: ReadW (GeteaW (dstspec));
|
||||
PSW = (cm << PSW_V_CM) | (pm << PSW_V_PM) |
|
||||
(rs << PSW_V_RS) | (ipl << PSW_V_IPL) |
|
||||
(tbit << PSW_V_TBIT);
|
||||
|
@ -1115,7 +1122,8 @@ case 000:
|
|||
break;
|
||||
case 072: /* TSTSET */
|
||||
if (dstreg) setTRAP (TRAP_ILL);
|
||||
else { dst = ReadMW (GeteaW (dstspec));
|
||||
else {
|
||||
dst = ReadMW (GeteaW (dstspec));
|
||||
N = GET_SIGN_W (dst);
|
||||
Z = GET_Z (dst);
|
||||
V = 0;
|
||||
|
@ -1125,7 +1133,8 @@ case 000:
|
|||
break;
|
||||
case 073: /* WRTLCK */
|
||||
if (dstreg) setTRAP (TRAP_ILL);
|
||||
else { N = GET_SIGN_W (R[0]);
|
||||
else {
|
||||
N = GET_SIGN_W (R[0]);
|
||||
Z = GET_Z (R[0]);
|
||||
V = 0;
|
||||
WriteW (R[0], GeteaW (dstspec)); }
|
||||
|
@ -1150,7 +1159,8 @@ case 001: /* MOV */
|
|||
if (srcreg && !dstreg) { /* R,not R */
|
||||
ea = GeteaW (dstspec);
|
||||
dst = R[srcspec]; }
|
||||
else { dst = srcreg? R[srcspec]: ReadW (GeteaW (srcspec));
|
||||
else {
|
||||
dst = srcreg? R[srcspec]: ReadW (GeteaW (srcspec));
|
||||
if (!dstreg) ea = GeteaW (dstspec); }
|
||||
N = GET_SIGN_W (dst);
|
||||
Z = GET_Z (dst);
|
||||
|
@ -1162,7 +1172,8 @@ case 002: /* CMP */
|
|||
if (srcreg && !dstreg) { /* R,not R */
|
||||
src2 = ReadW (GeteaW (dstspec));
|
||||
src = R[srcspec]; }
|
||||
else { src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec));
|
||||
else {
|
||||
src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec));
|
||||
src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec)); }
|
||||
dst = (src - src2) & 0177777;
|
||||
N = GET_SIGN_W (dst);
|
||||
|
@ -1174,7 +1185,8 @@ case 003: /* BIT */
|
|||
if (srcreg && !dstreg) { /* R,not R */
|
||||
src2 = ReadW (GeteaW (dstspec));
|
||||
src = R[srcspec]; }
|
||||
else { src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec));
|
||||
else {
|
||||
src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec));
|
||||
src2 = dstreg? R[dstspec]: ReadW (GeteaW (dstspec)); }
|
||||
dst = src2 & src;
|
||||
N = GET_SIGN_W (dst);
|
||||
|
@ -1185,7 +1197,8 @@ case 004: /* BIC */
|
|||
if (srcreg && !dstreg) { /* R,not R */
|
||||
src2 = ReadMW (GeteaW (dstspec));
|
||||
src = R[srcspec]; }
|
||||
else { src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec));
|
||||
else {
|
||||
src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec));
|
||||
src2 = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); }
|
||||
dst = src2 & ~src;
|
||||
N = GET_SIGN_W (dst);
|
||||
|
@ -1198,7 +1211,8 @@ case 005: /* BIS */
|
|||
if (srcreg && !dstreg) { /* R,not R */
|
||||
src2 = ReadMW (GeteaW (dstspec));
|
||||
src = R[srcspec]; }
|
||||
else { src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec));
|
||||
else {
|
||||
src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec));
|
||||
src2 = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); }
|
||||
dst = src2 | src;
|
||||
N = GET_SIGN_W (dst);
|
||||
|
@ -1211,7 +1225,8 @@ case 006: /* ADD */
|
|||
if (srcreg && !dstreg) { /* R,not R */
|
||||
src2 = ReadMW (GeteaW (dstspec));
|
||||
src = R[srcspec]; }
|
||||
else { src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec));
|
||||
else {
|
||||
src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec));
|
||||
src2 = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); }
|
||||
dst = (src2 + src) & 0177777;
|
||||
N = GET_SIGN_W (dst);
|
||||
|
@ -1607,7 +1622,8 @@ case 011: /* MOVB */
|
|||
if (srcreg && !dstreg) { /* R,not R */
|
||||
ea = GeteaB (dstspec);
|
||||
dst = R[srcspec] & 0377; }
|
||||
else { dst = srcreg? R[srcspec] & 0377: ReadB (GeteaB (srcspec));
|
||||
else {
|
||||
dst = srcreg? R[srcspec] & 0377: ReadB (GeteaB (srcspec));
|
||||
if (!dstreg) ea = GeteaB (dstspec); }
|
||||
N = GET_SIGN_B (dst);
|
||||
Z = GET_Z (dst);
|
||||
|
@ -1619,7 +1635,8 @@ case 012: /* CMPB */
|
|||
if (srcreg && !dstreg) { /* R,not R */
|
||||
src2 = ReadB (GeteaB (dstspec));
|
||||
src = R[srcspec] & 0377; }
|
||||
else { src = srcreg? R[srcspec] & 0377: ReadB (GeteaB (srcspec));
|
||||
else {
|
||||
src = srcreg? R[srcspec] & 0377: ReadB (GeteaB (srcspec));
|
||||
src2 = dstreg? R[dstspec] & 0377: ReadB (GeteaB (dstspec)); }
|
||||
dst = (src - src2) & 0377;
|
||||
N = GET_SIGN_B (dst);
|
||||
|
@ -1631,7 +1648,8 @@ case 013: /* BITB */
|
|||
if (srcreg && !dstreg) { /* R,not R */
|
||||
src2 = ReadB (GeteaB (dstspec));
|
||||
src = R[srcspec] & 0377; }
|
||||
else { src = srcreg? R[srcspec] & 0377: ReadB (GeteaB (srcspec));
|
||||
else {
|
||||
src = srcreg? R[srcspec] & 0377: ReadB (GeteaB (srcspec));
|
||||
src2 = dstreg? R[dstspec] & 0377: ReadB (GeteaB (dstspec)); }
|
||||
dst = (src2 & src) & 0377;
|
||||
N = GET_SIGN_B (dst);
|
||||
|
@ -1642,7 +1660,8 @@ case 014: /* BICB */
|
|||
if (srcreg && !dstreg) { /* R,not R */
|
||||
src2 = ReadMB (GeteaB (dstspec));
|
||||
src = R[srcspec]; }
|
||||
else { src = srcreg? R[srcspec]: ReadB (GeteaB (srcspec));
|
||||
else {
|
||||
src = srcreg? R[srcspec]: ReadB (GeteaB (srcspec));
|
||||
src2 = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); }
|
||||
dst = (src2 & ~src) & 0377;
|
||||
N = GET_SIGN_B (dst);
|
||||
|
@ -1655,7 +1674,8 @@ case 015: /* BISB */
|
|||
if (srcreg && !dstreg) { /* R,not R */
|
||||
src2 = ReadMB (GeteaB (dstspec));
|
||||
src = R[srcspec]; }
|
||||
else { src = srcreg? R[srcspec]: ReadB (GeteaB (srcspec));
|
||||
else {
|
||||
src = srcreg? R[srcspec]: ReadB (GeteaB (srcspec));
|
||||
src2 = dstreg? R[dstspec]: ReadMB (GeteaB (dstspec)); }
|
||||
dst = (src2 | src) & 0377;
|
||||
N = GET_SIGN_B (dst);
|
||||
|
@ -1668,7 +1688,8 @@ case 016: /* SUB */
|
|||
if (srcreg && !dstreg) { /* R,not R */
|
||||
src2 = ReadMW (GeteaW (dstspec));
|
||||
src = R[srcspec]; }
|
||||
else { src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec));
|
||||
else {
|
||||
src = srcreg? R[srcspec]: ReadW (GeteaW (srcspec));
|
||||
src2 = dstreg? R[dstspec]: ReadMW (GeteaW (dstspec)); }
|
||||
dst = (src2 - src) & 0177777;
|
||||
N = GET_SIGN_W (dst);
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
To: Users
|
||||
From: Bob Supnik
|
||||
Subj: PDP-11 Simulator Usage
|
||||
Date: 15-Nov-2002
|
||||
Date: 15-Jan-2003
|
||||
|
||||
COPYRIGHT NOTICE
|
||||
|
||||
The following copyright notice applies to both the SIMH source and binary:
|
||||
|
||||
Original code published in 1993-2002, written by Robert M Supnik
|
||||
Copyright (c) 1993-2002, Robert M Supnik
|
||||
Original code published in 1993-2003, written by Robert M Supnik
|
||||
Copyright (c) 1993-2003, 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"),
|
||||
|
@ -73,7 +73,8 @@ sim/pdp11/ pdp11_defs.h
|
|||
pdp11_tc.c
|
||||
pdp11_tm.c
|
||||
pdp11_ts.c
|
||||
pdp11_xp.c
|
||||
pdp11_xq.c
|
||||
pdp11_xu.c
|
||||
|
||||
2. PDP-11 Features
|
||||
|
||||
|
@ -106,10 +107,12 @@ TC TC11/TU56 DECtape controller with eight drives
|
|||
TM TM11/TU10 magnetic tape controller with eight drives
|
||||
TS TS11/TSV05 magnetic tape controller with one drive
|
||||
TQ TQK50 TMSCP magnetic tape controller with four drives
|
||||
XQ DELQA/DEQNA Ethernet controller
|
||||
XQ DELQA/DEQNA Qbus Ethernet controller
|
||||
XU DEUNA/DELUA Unibus Ethernet controller
|
||||
|
||||
The DZ, RK, HK, RL, RP, RQ, RQB, RQC, RQD, RX, RY, TC, TM, TS, TQ, and XQ
|
||||
devices can be set DISABLED. RQB, RQC, RQD, RY, and TS are disabled by default.
|
||||
The DZ, RK, HK, RL, RP, RQ, RQB, RQC, RQD, RX, RY, TC, TM, TS, TQ, XQ, and XU
|
||||
devices can be set DISABLED. RQB, RQC, RQD, RY, TS, and XU are disabled by
|
||||
default.
|
||||
|
||||
The PDP-11 simulator implements several unique stop conditions:
|
||||
|
||||
|
@ -1140,9 +1143,9 @@ Error handling is as follows:
|
|||
|
||||
OS I/O error fatal tape error
|
||||
|
||||
2.10 DELQA/DEQNA Ethernet Controller (XQ)
|
||||
2.10 DELQA/DEQNA Qbus Ethernet Controller (XQ)
|
||||
|
||||
XQ simulates the DELQA/DEQNA 10Mbps Ethernet controller. Options allow
|
||||
XQ simulates the DELQA/DEQNA Qbus Ethernet controller. Options allow
|
||||
control of the MAC address, the controller mode, and the sanity timer.
|
||||
|
||||
SET XQ MAC=<mac-address> ex. 08-00-2B-AA-BB-CC
|
||||
|
@ -1209,7 +1212,12 @@ not limited to the ~1.5Mbit/sec of the real DEQNA/DELQA controllers,
|
|||
nor the 10Mbit/sec of a standard Ethernet. Attach it to a Fast Ethernet
|
||||
(100 Mbit/sec) card, and "Feel the Power!" :-)
|
||||
|
||||
2.11 Symbolic Display and Input
|
||||
2.11 DEUNA/DELUA Unibus Ethernet Controller (XU)
|
||||
|
||||
XU simulates the DEUNA/DELUA Unibus Ethernet controller. THe current
|
||||
implementation is a stub and is permanently disabled.
|
||||
|
||||
2.12 Symbolic Display and Input
|
||||
|
||||
The PDP-11 simulator implements symbolic display and input. Display is
|
||||
controlled by command line switches:
|
||||
|
|
|
@ -367,7 +367,8 @@ case 015: /* LDEXP */
|
|||
if (dst < 0100000) {
|
||||
if (fpnotrap (FEC_OVFLO)) fac = zero_fac;
|
||||
newV = FPS_V; }
|
||||
else { if (fpnotrap (FEC_UNFLO)) fac = zero_fac; } }
|
||||
else {
|
||||
if (fpnotrap (FEC_UNFLO)) fac = zero_fac; } }
|
||||
F_STORE (qdouble, fac, FR[ac]);
|
||||
FPS = setfcc (FPS, fac.h, newV);
|
||||
break;
|
||||
|
@ -407,19 +408,22 @@ case 013: /* STCfi */
|
|||
if (FPS & FPS_L) {
|
||||
leni = LONG;
|
||||
i = FP_BIAS + 32; }
|
||||
else { leni = WORD;
|
||||
else {
|
||||
leni = WORD;
|
||||
i = FP_BIAS + 16; }
|
||||
C = 0;
|
||||
if (exp <= FP_BIAS) dst = 0;
|
||||
else if (exp > i) {
|
||||
dst = 0;
|
||||
C = 1; }
|
||||
else { F_RSH_V (fac, FP_V_HB + 1 + i - exp, fsrc);
|
||||
else {
|
||||
F_RSH_V (fac, FP_V_HB + 1 + i - exp, fsrc);
|
||||
if (leni == WORD) fsrc.l = fsrc.l & ~0177777;
|
||||
if (fsrc.l >= i_limit[leni == LONG][sign]) {
|
||||
dst = 0;
|
||||
C = 1; }
|
||||
else { dst = fsrc.l;
|
||||
else {
|
||||
dst = fsrc.l;
|
||||
if (sign) dst = -dst; } }
|
||||
N = GET_SIGN_L (dst);
|
||||
Z = (dst == 0);
|
||||
|
@ -779,7 +783,8 @@ if (GET_BIT (facfrac.h, FP_V_HB + FP_GUARD) == 0) {
|
|||
fsrcfrac.l = facfrac.l & fmask.l; /* extract fraction */
|
||||
fsrcfrac.h = facfrac.h & fmask.h;
|
||||
if ((fsrcfrac.h | fsrcfrac.l) == 0) *fracp = zero_fac;
|
||||
else { F_LSH_V (fsrcfrac, facexp - FP_BIAS, fsrcfrac);
|
||||
else {
|
||||
F_LSH_V (fsrcfrac, facexp - FP_BIAS, fsrcfrac);
|
||||
fsrcexp = FP_BIAS;
|
||||
if ((fsrcfrac.h & (0x00FFFFFF << FP_GUARD)) == 0) {
|
||||
F_LSH_K (fsrcfrac, 24, fsrcfrac);
|
||||
|
|
|
@ -720,7 +720,8 @@ case FNC_OFFSET: /* offset */
|
|||
if (uptr->FNC & FNC_2ND) { /* 2nd int? */
|
||||
hkds[drv] = (hkds[drv] & ~DS_PIP) | DS_ATA; /* upd sta */
|
||||
update_hkcs (CS1_DI, drv); } /* drive intr */
|
||||
else { uptr->FNC = uptr->FNC | FNC_2ND; /* second state */
|
||||
else {
|
||||
uptr->FNC = uptr->FNC | FNC_2ND; /* second state */
|
||||
hk_off[drv] = hkof & AS_OF; /* save offset */
|
||||
sim_activate (uptr, hk_swait * 10); /* wait for compl */
|
||||
update_hkcs (CS1_DONE, drv); } /* done */
|
||||
|
@ -731,7 +732,8 @@ case FNC_SEEK: /* seek */
|
|||
if (uptr->FNC & FNC_2ND) { /* 2nd int? */
|
||||
hkds[drv] = (hkds[drv] & ~DS_PIP) | DS_ATA; /* upd sta */
|
||||
update_hkcs (CS1_DI, drv); } /* drive intr */
|
||||
else { uptr->FNC = uptr->FNC | FNC_2ND; /* second state */
|
||||
else {
|
||||
uptr->FNC = uptr->FNC | FNC_2ND; /* second state */
|
||||
hk_off[drv] = 0; /* clr offset */
|
||||
dc = (fnc == FNC_SEEK)? hkdc: 0; /* get cyl */
|
||||
hk_dif[drv] = dc - uptr->CYL; /* cyl diff */
|
||||
|
|
|
@ -171,7 +171,8 @@ if (cpu_ubm) {
|
|||
sc = (addr & 3) << 3;
|
||||
ub_map[pg] = (ub_map[pg] & ~(0377 << sc)) |
|
||||
((data & 0377) << sc); }
|
||||
else { sc = (addr & 2) << 3;
|
||||
else {
|
||||
sc = (addr & 2) << 3;
|
||||
ub_map[pg] = (ub_map[pg] & ~(0177777 << sc)) |
|
||||
((data & 0177777) << sc); }
|
||||
ub_map[pg] = ub_map[pg] & 017777776;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue