Notes For V3.1-0
RESTRICTION: The FP15 and XVM features of the PDP-15 are only partially debugged. Do NOT enable these features for normal operations. 1. New Features in 3.1-0 1.1 SCP and libraries - Added simulated Ethernet support for VMS, FreeBSD, Mac OS/X. - Added status return to tmxr_putc_ln. - Added sim_putchar_s to handle possible output stalls. 1.2 All DECtapes - Added "DECtape off reel" error stop. 1.3 All Asynchronous Consoles - Added support for output congestion stall if using a Telnet connection. 1.4 PDP-1 - Added Type 23 parallel drum support. 1.5 PDP-8 - Added instruction history. - Added TSC8-75 option support for ETOS. - Added TD8E DECtape support. 1.6 PDP-18b - Added instruction history. - Changed PDP-9, PDP-15 API default to enabled. 1.7 PDP-11 - Added support for 18b only Qbus devices. - Formalized bus and addressing definitions. - Added control to enable/disable autoconfiguration. - Added stub support for second Unibus Ethernet controller. 1.7 Interdata 32b - Added instruction history. 1.8 Eclipse - Added floating point support. - Added programmable interval timer support. 1.9 H316 - Added DMA/DMC support. - Added fixed head disk support. - Added moving head disk support. - Added magtape support. 1.10 IBM 1130 (Brian Knittel) - Added support for physical card reader, using the Cardread interface (www.ibm1130.org/sim/downloads). - Added support for physical printer (flushes output buffer after each line). 2. Bugs Fixed in 3.1-0 2.1 SCP and libraries - Fixed numerous bugs in Ethernet library. 2.2 All DECtapes - Fixed reverse checksum value in 'read all' mode. - Simplified (and sped up) timing. 2.3 PDP-8 - Fixed bug in RX28 read status (found by Charles Dickman). - Fixed RX28 double density write. 2.4 PDP-18b - Fixed autoincrement bug in PDP-4, PDP-7, PDP-9. 2.5 PDP-11/VAX - Revised RQ MB->LBN conversion for greater accuracy. - Fixed bug in IO configuration (found by David Hittner). - Fixed bug with multiple RQ RAUSER drives. - Fixed bug in second Qbus Ethernet controller interrupts. 2.6 Nova/Eclipse - Fixed bugs in DKP flag clear, map setup, map usage (Charles Owen). - Fixed bug in MT, reset completes despite I/O reset (Charles Owen). - Fixed bug in MT, space operations return word count (Charles Owen). 2.7 IBM 1130 (Brian Knittel) - Fixed bug in setting carry bit in subtract and subtract double. - Fixed timing problem in console printer simulation. 2.8 1620 - Fixed bug in branch digit (found by Dave Babcock). 3. New Features in 3.0 vs prior releases 3.1 SCP and Libraries - Added ASSIGN/DEASSIGN (logical name) commands. - Changed RESTORE to unconditionally detach files. - Added E11 and TPC format support to magtape library. - Fixed bug in SHOW CONNECTIONS. - Added USE_ADDR64 support. 3.2 All magtapes - Magtapes support SIMH format, E11 format, and TPC format (read only). - SET <tape_unit> FORMAT=format sets the specified tape unit's format. - SHOW <tape_unit> FORMAT displays the specified tape unit's format. - Tape format can also be set as part of the ATTACH command, using the -F switch. 3.3 VAX - VAX can be compiled without USE_INT64. - If compiled with USE_INT64 and USE_ADDR64, RQ and TQ controllers support files > 2GB. - VAX ROM has speed control (SET ROM DELAY/NODELAY). 3.4 PDP-1 - Added block loader format support to LOAD. - Changed BOOT PTR to allow loading of all of the first bank of memory. - The LOAD command takes an optional argument specifying the memory field to be loaded. - The PTR BOOT command takes its starting memory field from the TA (address switch) register. 3.5 PDP-18b Family - Added PDP-4 EAE support. - Added PDP-15 FP15 support. - Added PDP-15 XVM support. - Added PDP-15 "re-entrancy ECO". - Added PDP-7, PDP-9, PDP-15 hardware RIM loader support in BOOT PTR. 4. Bugs Fixed in 3.0 vs prior releases 4.1 SCP and Libraries - Fixed end of file problem in dep, idep. - Fixed handling of trailing spaces in dep, idep. 4.2 VAX - Fixed CVTfi bug: integer overflow not set if exponent out of range - Fixed EMODx bugs: o First and second operands reversed o Separated fraction received wrong exponent o Overflow calculation on separated integer incorrect o Fraction not set to zero if exponent out of range - Fixed interval timer and ROM access to pass power-up self-test even on very fast host processors (fixes from Mark Pizzolato). - Fixed bug in user disk size (found by Chaskiel M Grundman). 4.3 1401 - Fixed mnemonic, instruction lengths, and reverse scan length check bug for MCS. - Fixed MCE bug, BS off by 1 if zero suppress. - Fixed chaining bug, D lost if return to SCP. - Fixed H branch, branch occurs after continue. - Added check for invalid 8 character MCW, LCA. - Fixed magtape load-mode end of record response. - Revised fetch to model hardware more closely. - Fixed tape read end-of-record handling based on real 1401. - Added diagnostic read (space forward). 4.4 Nova - Fixed DSK variable size interaction with restore. - Fixed bug in DSK set size routine. 4.5 PDP-1 - Fixed DT variable size interaction with restore. - Updated CPU, line printer, standard devices to detect indefinite I/O wait. - Fixed incorrect logical, missing activate, break in drum simulator. - Fixed bugs in instruction decoding, overprinting for line printer. - Fixed system hang if continue after PTR error. - Fixed PTR to start/stop on successive rpa instructions. 4.6 PDP-11 - Fixed DT variable size interaction with restore. - Fixed bug in MMR1 update (found by Tim Stark). - Added XQ features and fixed bugs: o Corrected XQ interrupts on IE state transition (code by Tom Evans). o Added XQ interrupt clear on soft reset. o Removed XQ interrupt when setting XL or RL (multiple people). o Added SET/SHOW XQ STATS. o Added SHOW XQ FILTERS. o Added ability to split received packet into multiple buffers. o Added explicit runt and giant packet processing. - Fixed bug in user disk size (found by Chaskiel M Grundman). 4.7 PDP-18B - Fixed DT, RF variable size interaction with restore. - Fixed MT bug in MTTR. - Fixed bug in PDP-4 line printer overprinting. - Fixed bug in PDP-15 memory protect/skip interaction. - Fixed bug in RF set size routine. - Increased PTP TIME for PDP-15 operating systems. - Fixed priorities in PDP-15 API (differs from PDP-9). - Fixed sign handling in PDP-15 EAE unsigned mul/div (differs from PDP-9). - Fixed bug in CAF, clears API subsystem. 4.8 PDP-8 - Fixed DT, DF, RF, RX variable size interaction with restore. - Fixed MT bug in SKTR. - Fixed bug in DF, RF set size routine. 4.9 HP2100 - Fixed bug in DP (13210A controller only), DQ read status. - Fixed bug in DP, DQ seek complete. - Fixed DR drum sizes. - Fixed DR variable capacity interaction with SAVE/RESTORE. 4.10 GRI - Fixed bug in SC queue pointer management. 4.11 PDP-10 - Fixed bug in RP read header. 4.12 Ibm1130 - Fixed bugs found by APL 1130. 4.13 Altairz80 - Fixed bug in real-time clock on Windows host. 4.14 1620 - Fixed bug in immediate index add (found by Michael Short).
|
@ -1,43 +1,110 @@
|
|||
Notes For V3.0-2
|
||||
Notes For V3.1-0
|
||||
|
||||
RESTRICTION: The FP15 and XVM features of the PDP-15 are only partially
|
||||
debugged. Do NOT enable these features for normal operations.
|
||||
|
||||
1. New Features in 3.0-2
|
||||
1. New Features in 3.1-0
|
||||
|
||||
1.1 PDP-1
|
||||
1.1 SCP and libraries
|
||||
|
||||
- The LOAD command takes an optional argument specifying the memory field
|
||||
to be loaded.
|
||||
- The PTR BOOT command takes its starting memory field from the TA (address
|
||||
switch) register.
|
||||
- Added simulated Ethernet support for VMS, FreeBSD, Mac OS/X.
|
||||
- Added status return to tmxr_putc_ln.
|
||||
- Added sim_putchar_s to handle possible output stalls.
|
||||
|
||||
2. Bugs Fixed in 3.0-2
|
||||
1.2 All DECtapes
|
||||
|
||||
- Added "DECtape off reel" error stop.
|
||||
|
||||
1.3 All Asynchronous Consoles
|
||||
|
||||
- Added support for output congestion stall if using a Telnet connection.
|
||||
|
||||
1.4 PDP-1
|
||||
|
||||
- Added Type 23 parallel drum support.
|
||||
|
||||
1.5 PDP-8
|
||||
|
||||
- Added instruction history.
|
||||
- Added TSC8-75 option support for ETOS.
|
||||
- Added TD8E DECtape support.
|
||||
|
||||
1.6 PDP-18b
|
||||
|
||||
- Added instruction history.
|
||||
- Changed PDP-9, PDP-15 API default to enabled.
|
||||
|
||||
1.7 PDP-11
|
||||
|
||||
- Added support for 18b only Qbus devices.
|
||||
- Formalized bus and addressing definitions.
|
||||
- Added control to enable/disable autoconfiguration.
|
||||
- Added stub support for second Unibus Ethernet controller.
|
||||
|
||||
1.7 Interdata 32b
|
||||
|
||||
- Added instruction history.
|
||||
|
||||
1.8 Eclipse
|
||||
|
||||
- Added floating point support.
|
||||
- Added programmable interval timer support.
|
||||
|
||||
1.9 H316
|
||||
|
||||
- Added DMA/DMC support.
|
||||
- Added fixed head disk support.
|
||||
- Added moving head disk support.
|
||||
- Added magtape support.
|
||||
|
||||
1.10 IBM 1130 (Brian Knittel)
|
||||
|
||||
- Added support for physical card reader, using the Cardread
|
||||
interface (www.ibm1130.org/sim/downloads).
|
||||
- Added support for physical printer (flushes output buffer after
|
||||
each line).
|
||||
|
||||
2. Bugs Fixed in 3.1-0
|
||||
|
||||
2.1 SCP and libraries
|
||||
|
||||
- Fixed end of file problem in dep, idep.
|
||||
- Fixed handling of trailing spaces in dep, idep.
|
||||
- Fixed numerous bugs in Ethernet library.
|
||||
|
||||
2.2 PDP-1
|
||||
2.2 All DECtapes
|
||||
|
||||
- Fixed system hang if continue after PTR error.
|
||||
- Fixed PTR to start/stop on successive rpa instructions.
|
||||
- Fixed reverse checksum value in 'read all' mode.
|
||||
- Simplified (and sped up) timing.
|
||||
|
||||
2.3 PDP 18b family
|
||||
2.3 PDP-8
|
||||
|
||||
- Fixed priorities in PDP-15 API (differs from PDP-9).
|
||||
- Fixed sign handling in PDP-15 EAE unsigned mul/div (differs from PDP-9).
|
||||
- Fixed bug in CAF, clears API subsystem.
|
||||
- Fixed bug in RX28 read status (found by Charles Dickman).
|
||||
- Fixed RX28 double density write.
|
||||
|
||||
2.4 1401
|
||||
2.4 PDP-18b
|
||||
|
||||
- Fixed tape read end-of-record handling based on real 1401.
|
||||
- Added diagnostic read (space forward).
|
||||
- Fixed autoincrement bug in PDP-4, PDP-7, PDP-9.
|
||||
|
||||
2.5 1620
|
||||
2.5 PDP-11/VAX
|
||||
|
||||
- Fixed bug in immediate index add (found by Michael Short).
|
||||
- Revised RQ MB->LBN conversion for greater accuracy.
|
||||
- Fixed bug in IO configuration (found by David Hittner).
|
||||
- Fixed bug with multiple RQ RAUSER drives.
|
||||
- Fixed bug in second Qbus Ethernet controller interrupts.
|
||||
|
||||
2.6 Nova/Eclipse
|
||||
|
||||
- Fixed bugs in DKP flag clear, map setup, map usage (Charles Owen).
|
||||
- Fixed bug in MT, reset completes despite I/O reset (Charles Owen).
|
||||
- Fixed bug in MT, space operations return word count (Charles Owen).
|
||||
|
||||
2.7 IBM 1130 (Brian Knittel)
|
||||
|
||||
- Fixed bug in setting carry bit in subtract and subtract double.
|
||||
- Fixed timing problem in console printer simulation.
|
||||
|
||||
2.8 1620
|
||||
|
||||
- Fixed bug in branch digit (found by Dave Babcock).
|
||||
|
||||
3. New Features in 3.0 vs prior releases
|
||||
|
||||
|
@ -47,7 +114,7 @@ debugged. Do NOT enable these features for normal operations.
|
|||
- Changed RESTORE to unconditionally detach files.
|
||||
- Added E11 and TPC format support to magtape library.
|
||||
- Fixed bug in SHOW CONNECTIONS.
|
||||
- Added USE_ADDR64 support
|
||||
- Added USE_ADDR64 support.
|
||||
|
||||
3.2 All magtapes
|
||||
|
||||
|
@ -68,6 +135,10 @@ debugged. Do NOT enable these features for normal operations.
|
|||
|
||||
- Added block loader format support to LOAD.
|
||||
- Changed BOOT PTR to allow loading of all of the first bank of memory.
|
||||
- The LOAD command takes an optional argument specifying the memory field
|
||||
to be loaded.
|
||||
- The PTR BOOT command takes its starting memory field from the TA (address
|
||||
switch) register.
|
||||
|
||||
3.5 PDP-18b Family
|
||||
|
||||
|
@ -79,7 +150,12 @@ debugged. Do NOT enable these features for normal operations.
|
|||
|
||||
4. Bugs Fixed in 3.0 vs prior releases
|
||||
|
||||
4.1 VAX
|
||||
4.1 SCP and Libraries
|
||||
|
||||
- Fixed end of file problem in dep, idep.
|
||||
- Fixed handling of trailing spaces in dep, idep.
|
||||
|
||||
4.2 VAX
|
||||
|
||||
- Fixed CVTfi bug: integer overflow not set if exponent out of range
|
||||
- Fixed EMODx bugs:
|
||||
|
@ -91,7 +167,7 @@ debugged. Do NOT enable these features for normal operations.
|
|||
fast host processors (fixes from Mark Pizzolato).
|
||||
- Fixed bug in user disk size (found by Chaskiel M Grundman).
|
||||
|
||||
4.2 1401
|
||||
4.3 1401
|
||||
|
||||
- Fixed mnemonic, instruction lengths, and reverse scan length check bug for MCS.
|
||||
- Fixed MCE bug, BS off by 1 if zero suppress.
|
||||
|
@ -100,20 +176,24 @@ debugged. Do NOT enable these features for normal operations.
|
|||
- Added check for invalid 8 character MCW, LCA.
|
||||
- Fixed magtape load-mode end of record response.
|
||||
- Revised fetch to model hardware more closely.
|
||||
- Fixed tape read end-of-record handling based on real 1401.
|
||||
- Added diagnostic read (space forward).
|
||||
|
||||
4.3 Nova
|
||||
4.4 Nova
|
||||
|
||||
- Fixed DSK variable size interaction with restore.
|
||||
- Fixed bug in DSK set size routine.
|
||||
|
||||
4.4 PDP-1
|
||||
4.5 PDP-1
|
||||
|
||||
- Fixed DT variable size interaction with restore.
|
||||
- Updated CPU, line printer, standard devices to detect indefinite I/O wait.
|
||||
- Fixed incorrect logical, missing activate, break in drum simulator.
|
||||
- Fixed bugs in instruction decoding, overprinting for line printer.
|
||||
- Fixed system hang if continue after PTR error.
|
||||
- Fixed PTR to start/stop on successive rpa instructions.
|
||||
|
||||
4.5 PDP-11
|
||||
4.6 PDP-11
|
||||
|
||||
- Fixed DT variable size interaction with restore.
|
||||
- Fixed bug in MMR1 update (found by Tim Stark).
|
||||
|
@ -127,7 +207,7 @@ debugged. Do NOT enable these features for normal operations.
|
|||
o Added explicit runt and giant packet processing.
|
||||
- Fixed bug in user disk size (found by Chaskiel M Grundman).
|
||||
|
||||
4.6 PDP-18B
|
||||
4.7 PDP-18B
|
||||
|
||||
- Fixed DT, RF variable size interaction with restore.
|
||||
- Fixed MT bug in MTTR.
|
||||
|
@ -135,32 +215,40 @@ debugged. Do NOT enable these features for normal operations.
|
|||
- Fixed bug in PDP-15 memory protect/skip interaction.
|
||||
- Fixed bug in RF set size routine.
|
||||
- Increased PTP TIME for PDP-15 operating systems.
|
||||
- Fixed priorities in PDP-15 API (differs from PDP-9).
|
||||
- Fixed sign handling in PDP-15 EAE unsigned mul/div (differs from PDP-9).
|
||||
- Fixed bug in CAF, clears API subsystem.
|
||||
|
||||
4.7 PDP-8
|
||||
4.8 PDP-8
|
||||
|
||||
- Fixed DT, DF, RF, RX variable size interaction with restore.
|
||||
- Fixed MT bug in SKTR.
|
||||
- Fixed bug in DF, RF set size routine.
|
||||
|
||||
4.8 HP2100
|
||||
4.9 HP2100
|
||||
|
||||
- Fixed bug in DP (13210A controller only), DQ read status.
|
||||
- Fixed bug in DP, DQ seek complete.
|
||||
- Fixed DR drum sizes.
|
||||
- Fixed DR variable capacity interaction with SAVE/RESTORE.
|
||||
|
||||
4.9 GRI
|
||||
4.10 GRI
|
||||
|
||||
- Fixed bug in SC queue pointer management.
|
||||
|
||||
4.10 PDP-10
|
||||
4.11 PDP-10
|
||||
|
||||
- Fixed bug in RP read header.
|
||||
|
||||
4.11 Ibm1130
|
||||
4.12 Ibm1130
|
||||
|
||||
- Fixed bugs found by APL 1130.
|
||||
|
||||
4.12 Altairz80
|
||||
4.13 Altairz80
|
||||
|
||||
- Fixed bug in real-time clock on Windows host.
|
||||
|
||||
4.14 1620
|
||||
|
||||
- Fixed bug in immediate index add (found by Michael Short).
|
||||
|
|
@ -8,7 +8,7 @@ DELQA (M7516) and DEQNA (M7504) Q-bus ethernet cards for the SIMH emulator.
|
|||
The XQ emulator uses the Sim_Ether module to execute host-specific ethernet
|
||||
packet reads and writes, since all operating systems talk to real ethernet
|
||||
cards/controllers differently. The host-dependant Sim_Ether module currently
|
||||
supports Windows, Linux, NetBSD, and OpenBSD.
|
||||
supports Windows, Linux, NetBSD, OpenBSD, FreeBSD, OS/X, and Alpha VMS.
|
||||
|
||||
Currently, the Sim_Ether module sets the selected ethernet card into
|
||||
promiscuous mode to gather all packets, then filters out the packets that it
|
||||
|
@ -20,53 +20,138 @@ 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 direct or hub(repeater) segment.
|
||||
|
||||
Using the libpcap/WinPcap interface, the simulated computer cannot "talk" to
|
||||
the host computer via the selected interface, since the packets are not
|
||||
reflected back to the host. The workaround for this is to use a second NIC in
|
||||
the host and connect them both into the same network; then the host and the
|
||||
simulator can communicate over the physical LAN.
|
||||
|
||||
Universal TUN/TAP support provides another solution for the above dual-NIC
|
||||
problem for systems that support Universal TUN/TAP. Since the TUN/TAP interface
|
||||
is at a different network level, the host can create a TAP device for the
|
||||
simulator and then bridge or route packets between the TAP device and the real
|
||||
network interface. Note that the TAP device and any bridging or routing must be
|
||||
established before running the simulator; SIMH does not create, bridge, or
|
||||
route TAP devices for you.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Windows notes:
|
||||
1. The Windows-specific code uses the WinPCAP 3.0 package from
|
||||
http://winpcap.polito.it. This package for windows simulates the libpcap
|
||||
package that is freely available for unix systems.
|
||||
package that is freely available for un*x systems.
|
||||
|
||||
2. You must *install* the WinPCAP runtime package.
|
||||
|
||||
3. 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. 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.
|
||||
4. WinPCAP loops packet writes back into the read queue. This causes problems
|
||||
since the XQ controller is not expecting to read it's own packet. A fix
|
||||
to the packet read filter was added to reject packets from the current MAC,
|
||||
but this defeats DECNET's duplicate node number detection scheme. A more
|
||||
correct fix for WinPCAP will be explored as time allows.
|
||||
the WinPCAP documentation for details on the static loading workaround.
|
||||
|
||||
4. If you want to use TAP devices, they must be created before running SIMH.
|
||||
(TAP component from the OpenVPN project; http://openvpn.sourceforge.net)
|
||||
|
||||
5. Compaq PATHWORKS 32 v7.2 also enabled bridging for the ethernet adapters
|
||||
when the DECNET and LAT drivers were installed; TAP was not needed.
|
||||
|
||||
|
||||
Building on Windows:
|
||||
1. Install WinPCAP 3.0.
|
||||
1. Install WinPCAP 3.0 runtime and the WinPCAP Developer's kit.
|
||||
|
||||
2. Put the required .h files (bittypes,devioctl,ip6_misc,packet32,pcap,
|
||||
pcap-stdinc).h from the WinPCAP 3.0 developer's kit in the compiler's path
|
||||
|
||||
3. Put the required .lib files (packet,wpcap).lib from the WinPCAP 3.0
|
||||
developer's kit in the linker's path
|
||||
|
||||
4. If you're using Borland C++, use COFF2OMF to convert the .lib files into
|
||||
a format that can be used by the compiler.
|
||||
|
||||
5. Define USE_NETWORK if you want the network functionality.
|
||||
|
||||
6. Build it!
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Linux, NetBSD, and OpenBSD notes:
|
||||
Linux, {Free|Net|Open}BSD, OS/X, and Un*x notes:
|
||||
1. You must run SIMH(scp) as root so that the ethernet card can be set into
|
||||
promiscuous mode by the driver. Alternative methods for avoiding the
|
||||
'run as root' requirement will be welcomed.
|
||||
|
||||
Building on Linux, NetBSD, and OpenBSD:
|
||||
1. Get/install the libpcap package for your unix version. http://rpmfind.net
|
||||
might be a useful site for finding the linux variants.
|
||||
2. Use Make USE_NETWORK=1 if you want the network functionality.
|
||||
2. If you want to use TAP devices, they must be created before running SIMH.
|
||||
|
||||
Linux, {Free|Net|Open}BSD, OS/X, Un*x notes:
|
||||
1. Get/make/install the libpcap package for your operating system. Sources:
|
||||
Linux : search for your variant on http://rpmfind.net
|
||||
OS/X : Apple Developer's site?
|
||||
Others : http://sourceforge.net/projects/libpcap/
|
||||
|
||||
2. Use 'make USE_NETWORK=1' if you want the network functionality.
|
||||
|
||||
3. Build it!
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
OpenVMS Alpha notes:
|
||||
1. Ethernet support will only work on Alpha VMS 7.3-1 or later, which is
|
||||
when required VCI promiscuous mode support was added. Hobbyists can
|
||||
get the required version of VMS from the OpenVMS Alpha Hobbyist Kit 3.0.
|
||||
|
||||
Running a simulator built with ethernet support on a version of VMS prior
|
||||
to 7.3-1 will behave as if there is no ethernet support built in due to
|
||||
the inability of the software to set the PCAPVCM into promiscuous mode.
|
||||
|
||||
An example display of fully functional ethernet support:
|
||||
sim> SHOW XQ ETH
|
||||
ETH devices:
|
||||
0 we0 (VMS Device: _EWA0:)
|
||||
1 we1 (VMS Device: _EWB0:)
|
||||
|
||||
An example display when the simulator was built without ethernet support
|
||||
or is not running the required version of VMS:
|
||||
sim> SHOW XQ ETH
|
||||
ETH devices:
|
||||
no network devices are available
|
||||
|
||||
2. You must place the PCAPVCM.EXE execlet in SYS$LOADABLE_IMAGES before
|
||||
running a simulator with ethernet support.
|
||||
|
||||
3. You must have CMKRNL privilege to SHOW or ATTACH an ethernet device;
|
||||
alternatively, you can INSTALL the simulator with CMKRNL privilege.
|
||||
|
||||
4. If you use a second adapter to communicate to the host, SOME protocol
|
||||
that creates an I/O structure (SCS, DECNET, TCP) must be running on the
|
||||
adapter prior trying to connect with SIMH, or the host may crash.
|
||||
The execlet is not written to create an I/O structure for the device.
|
||||
|
||||
Building on OpenVMS Alpha:
|
||||
1. Build the PCAP library and execlet. They are in the [.PCAP-VMS]
|
||||
directory in the simh source distribution. The following builds
|
||||
both the pcap library and the pcap execlet:
|
||||
$ set def [.pcap-vms]
|
||||
$ @build_all
|
||||
Building VCI version of pcap...
|
||||
Building the PCAP VCM execlet...
|
||||
In order to use it, place PCAPVCM.EXE in the
|
||||
SYS$LOADABLE_IMAGES directory.
|
||||
%DCL-I-SUPERSEDE, previous value of PCAPVCM$OBJ has been superseded
|
||||
|
||||
To use the PCAPVCM.EXE execlet you must copy it to
|
||||
the SYS$LOADABLE_IMAGES directory.
|
||||
|
||||
Build done...
|
||||
|
||||
2. To build the simulators with ethernet support, you
|
||||
need to build them with MMS or MMK as follows:
|
||||
$ MMx/MACRO=("__ALPHA__=1", "__PCAP__=1")
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
VAX simulator support:
|
||||
|
||||
An OpenVMS VAX v7.2 system with DECNET Phase IV, MultiNet 4.4a, and LAT 5.3 has
|
||||
been successfully run. Other testers have reported success booting NetBSD also.
|
||||
been successfully run. Other testers have reported success booting NetBSD and
|
||||
OpenVMS VAX 5.5-2 also.
|
||||
|
||||
|
||||
PDP11 simulator support:
|
||||
|
@ -88,15 +173,14 @@ Things planned for future releases:
|
|||
-------------------------------------------------------------------------------
|
||||
|
||||
Things which I need help with:
|
||||
1. Porting Sim_Ether packet driver to other host platforms, especially VMS.
|
||||
2. Information about Remote MOP processing
|
||||
3. VAX/PDP-11 hardware diagnotics image files and docs, to test XQ thoroughly.
|
||||
4. Feedback on operation with other VAX/PDP-11 OS's.
|
||||
1. Information about Remote MOP processing
|
||||
2. VAX/PDP-11 hardware diagnotics image files and docs, to test XQ thoroughly.
|
||||
3. Feedback on operation with other VAX/PDP-11 OS's.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Please send all patches, questions, feedback, clarifications, and help to:
|
||||
dhittner AT northropgrumman DOT com
|
||||
david DOT hittner AT ngc DOT com
|
||||
|
||||
Thanks, and Enjoy!!
|
||||
Dave
|
||||
|
@ -106,33 +190,46 @@ Dave
|
|||
Change Log
|
||||
===============================================================================
|
||||
|
||||
26-Nov-03 Release:
|
||||
1. Added VMS support to Sim_Ether; created pcap-vms port (Anders Ahgren)
|
||||
2. Added DECNET duplicate detection for Windows (Mark Pizzolato)
|
||||
3. Added BPF filtering to increase efficiency (Mark Pizzolato)
|
||||
4. Corrected XQ Runt processing (Mark Pizzolato)
|
||||
5. Corrected XQ Software Reset (Mark Pizzolato)
|
||||
6. Corrected XQ Multicast/Promiscuous mode setting/resetting (Mark Pizzolato)
|
||||
7. Added Universal TUN/TAP support (Mark Pizzolato)
|
||||
8. Added FreeBSD support (Edward Brocklesby)
|
||||
9. Corrected interrupts on XQB device (David Hittner)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
05-Jun-03 Release:
|
||||
1. Added SET/SHOW XQ STATS
|
||||
2. Added SHOW XQ FILTERS
|
||||
3. Added ability to split received packet into multiple buffers
|
||||
4. Added explicit runt & giant packet processing
|
||||
1. Added SET/SHOW XQ STATS (David Hittner)
|
||||
2. Added SHOW XQ FILTERS (David Hittner)
|
||||
3. Added ability to split rcv packets into multiple buffers (David Hittner)
|
||||
4. Added explicit runt & giant packet processing (David Hittner)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
30-May-03 Release:
|
||||
1. Corrected bug in xq_setmac introduced in v3.0 (multiple people)
|
||||
2. Made XQ receive buffer allocation dynamic to reduce scp executable size
|
||||
2. Made XQ rcv buffer allocation dynamic to reduce scp size (David Hittner)
|
||||
3. Optimized some structs, removed legacy variables (Mark Pizzolato)
|
||||
4. Changed #ifdef WIN32 to _WIN32 for consistancy
|
||||
4. Changed #ifdef WIN32 to _WIN32 for consistancy (Mark Pizzolato)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
06-May-03 Release:
|
||||
1. Added second XQ controller
|
||||
2. Added SIMH v3.0 compatibility
|
||||
3. Removed SET ADDRESS functionality
|
||||
1. Added second XQ controller (David Hittner)
|
||||
2. Added SIMH v3.0 compatibility (David Hittner)
|
||||
3. Removed SET ADDRESS functionality (David Hittner)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
10-Apr-03 Release:
|
||||
1. Added preliminary support for RSTS/E
|
||||
2. Added PDP-11 bootrom load via CSR flags
|
||||
3. Support for SPARC linux (thanks to Mark Pizzolato)
|
||||
1. Added preliminary support for RSTS/E (David Hittner)
|
||||
2. Added PDP-11 bootrom load via CSR flags (David Hittner)
|
||||
3. Support for SPARC linux (Mark Pizzolato)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -29,6 +29,10 @@
|
|||
|
||||
#include "altairz80_defs.h"
|
||||
|
||||
#if !defined (_WIN32)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#define PCQ_SIZE 64 /* must be 2**n */
|
||||
#define PCQ_SIZE_LOG2 6 /* log2 of PCQ_SIZE */
|
||||
#define PCQ_MASK (PCQ_SIZE - 1)
|
||||
|
@ -1686,14 +1690,18 @@ int32 sim_instr (void) {
|
|||
register uint32 SP;
|
||||
register uint32 IX;
|
||||
register uint32 IY;
|
||||
register uint32 temp, acu, sum, cbits;
|
||||
register uint32 op, adr;
|
||||
register uint32 temp = 0;
|
||||
register uint32 acu = 0;
|
||||
register uint32 sum;
|
||||
register uint32 cbits;
|
||||
register uint32 op;
|
||||
register uint32 adr;
|
||||
/* tStates contains the number of t-states executed. One t-state is executed
|
||||
in one microsecond on a 1MHz CPU. tStates is used real-time simulation */
|
||||
register uint32 tStates;
|
||||
uint32 tStatesInSlice; /* number of t-states in 10 mSec time-slice */
|
||||
uint32 startTime;
|
||||
int32 br1, br2, tStateModifier;
|
||||
int32 br1, br2, tStateModifier = FALSE;
|
||||
|
||||
pc = saved_PC & ADDRMASK; /* load local PC */
|
||||
af[af_sel] = AF_S;
|
||||
|
@ -1744,7 +1752,16 @@ int32 sim_instr (void) {
|
|||
/* clockFrequency != 0 implies that real time clock is available */
|
||||
startTime += sliceLength;
|
||||
tStates -= tStatesInSlice;
|
||||
#if defined (_WIN32)
|
||||
while (sim_os_msec() <= startTime) {} /* poor man's sleep */
|
||||
#else
|
||||
{
|
||||
uint32 now;
|
||||
if (startTime > (now = sim_os_msec())) {
|
||||
usleep(1000 * (startTime - now));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (timerInterrupt && (IFF & 1)) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* gri_stddev.c: GRI-909 standard devices
|
||||
|
||||
Copyright (c) 2001-2003, Robert M Supnik
|
||||
Copyright (c) 2001-2004, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -29,6 +29,7 @@
|
|||
hsp S42-006 high speed punch
|
||||
rtc real time clock
|
||||
|
||||
29-Dec-03 RMS Added support for console backpressure
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
22-Dec-02 RMS Added break support
|
||||
01-Nov-02 RMS Added 7b/8B support to terminal
|
||||
|
@ -246,12 +247,14 @@ t_stat tto_svc (UNIT *uptr)
|
|||
int32 c;
|
||||
t_stat r;
|
||||
|
||||
dev_done = dev_done | INT_TTO; /* set ready */
|
||||
if (tto_unit.flags & UNIT_KSR) { /* KSR? */
|
||||
c = tto_unit.buf & 0177; /* force 7b */
|
||||
if (islower (c)) c = toupper (c); } /* cvt to UC */
|
||||
else c = tto_unit.buf & ((tto_unit.flags & UNIT_8B)? 0377: 0177);
|
||||
if ((r = sim_putchar (c)) != SCPE_OK) return r; /* output */
|
||||
if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */
|
||||
sim_activate (uptr, uptr->wait); /* try again */
|
||||
return ((r == SCPE_STALL)? SCPE_OK: r); } /* !stall? report */
|
||||
dev_done = dev_done | INT_TTO; /* set ready */
|
||||
tto_unit.pos = tto_unit.pos + 1;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
|
495
H316/h316_cpu.c
|
@ -1,6 +1,6 @@
|
|||
/* h316_cpu.c: Honeywell 316/516 CPU simulator
|
||||
|
||||
Copyright (c) 1999-2003, Robert M. Supnik
|
||||
Copyright (c) 1999-2004, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -25,6 +25,8 @@
|
|||
|
||||
cpu H316/H516 CPU
|
||||
|
||||
31-Dec-03 RMS Fixed bug in cpu_set_hist
|
||||
24-Oct-03 RMS Added DMA/DMC support, instruction history
|
||||
30-Dec-01 RMS Added old PC queue
|
||||
03-Nov-01 RMS Fixed NOHSA modifier
|
||||
30-Nov-01 RMS Added extended SET/SHOW support
|
||||
|
@ -167,10 +169,10 @@
|
|||
|
||||
2. Interrupts. Interrupts are maintained by two parallel variables:
|
||||
|
||||
dev_ready device ready flags
|
||||
dev_enable device interrupt enable flags
|
||||
dev_int device interrupt flags
|
||||
dev_enb device interrupt enable flags
|
||||
|
||||
In addition, dev_ready contains the interrupt enable and interrupt no
|
||||
In addition, dev_int contains the interrupt enable and interrupt no
|
||||
defer flags. If interrupt enable and interrupt no defer are set, and
|
||||
at least one interrupt request is pending, then an interrupt occurs.
|
||||
The order of flags in these variables corresponds to the order
|
||||
|
@ -194,8 +196,6 @@
|
|||
#define PCQ_MASK (PCQ_SIZE - 1)
|
||||
#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = PC
|
||||
#define PCQ_TOP pcq[pcq_p]
|
||||
#define UNIT_V_MSIZE (UNIT_V_UF) /* dummy mask */
|
||||
#define UNIT_MSIZE (1u << UNIT_V_MSIZE)
|
||||
#define m7 0001000 /* for generics */
|
||||
#define m8 0000400
|
||||
#define m9 0000200
|
||||
|
@ -207,6 +207,20 @@
|
|||
#define m15 0000002
|
||||
#define m16 0000001
|
||||
|
||||
#define HIST_PC 0x40000000
|
||||
#define HIST_C 0x20000000
|
||||
#define HIST_EA 0x10000000
|
||||
#define HIST_MIN 64
|
||||
#define HIST_MAX 65536
|
||||
struct InstHistory {
|
||||
int32 pc;
|
||||
int32 ir;
|
||||
int32 ar;
|
||||
int32 br;
|
||||
int32 xr;
|
||||
int32 ea;
|
||||
int32 opnd; };
|
||||
|
||||
uint16 M[MAXMEMSIZE] = { 0 }; /* memory */
|
||||
int32 saved_AR = 0; /* A register */
|
||||
int32 saved_BR = 0; /* B register */
|
||||
|
@ -219,27 +233,44 @@ int32 extoff_pending = 0; /* extend off pending */
|
|||
int32 dp = 0; /* double mode */
|
||||
int32 sc = 0; /* shift count */
|
||||
int32 ss[4]; /* sense switches */
|
||||
int32 dev_ready = 0; /* dev ready */
|
||||
int32 dev_enable = 0; /* dev enable */
|
||||
int32 dev_int = 0; /* dev ready */
|
||||
int32 dev_enb = 0; /* dev enable */
|
||||
int32 ind_max = 8; /* iadr nest limit */
|
||||
int32 stop_inst = 1; /* stop on ill inst */
|
||||
int32 stop_dev = 2; /* stop on ill dev */
|
||||
uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
|
||||
int32 pcq_p = 0; /* PC queue ptr */
|
||||
REG *pcq_r = NULL; /* PC queue reg ptr */
|
||||
int32 dlog = 0; /* debug log */
|
||||
int32 turnoff = 0;
|
||||
uint32 dma_nch = DMA_MAX; /* number of chan */
|
||||
uint32 dma_ad[DMA_MAX] = { 0 }; /* DMA addresses */
|
||||
uint32 dma_wc[DMA_MAX] = { 0 }; /* DMA word count */
|
||||
uint32 dma_eor[DMA_MAX] = { 0 }; /* DMA end of range */
|
||||
uint32 chan_req = 0; /* channel requests */
|
||||
uint32 chan_map[DMA_MAX + DMC_MAX] = { 0 }; /* chan->dev map */
|
||||
int32 (*iotab[DEV_MAX])(int32 inst, int32 fnc, int32 dat, int32 dev) = { NULL };
|
||||
int32 hst_p = 0; /* history pointer */
|
||||
int32 hst_lnt = 0; /* history length */
|
||||
struct InstHistory *hst = NULL; /* instruction history */
|
||||
|
||||
extern int32 sim_int_char;
|
||||
extern int32 sim_interval;
|
||||
extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
|
||||
extern FILE *sim_log;
|
||||
extern DEVICE *sim_devices[];
|
||||
|
||||
t_bool devtab_init (void);
|
||||
int32 dmaio (int32 inst, int32 fnc, int32 dat, int32 dev);
|
||||
int32 undio (int32 inst, int32 fnc, int32 dat, int32 dev);
|
||||
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_set_noext (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
t_stat cpu_show_dma (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
t_stat cpu_set_nchan (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat cpu_show_nchan (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
|
||||
extern t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
|
||||
UNIT *uptr, int32 sw);
|
||||
|
@ -252,7 +283,9 @@ extern t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
|
|||
cpu_mod CPU modifiers list
|
||||
*/
|
||||
|
||||
UNIT cpu_unit = { UDATA (NULL, UNIT_FIX + UNIT_BINK + UNIT_EXT,
|
||||
DIB cpu_dib = { DMA, IOBUS, 1, &dmaio };
|
||||
|
||||
UNIT cpu_unit = { UDATA (NULL, UNIT_FIX+UNIT_BINK+UNIT_EXT+UNIT_HSA+UNIT_DMC,
|
||||
MAXMEMSIZE) };
|
||||
|
||||
REG cpu_reg[] = {
|
||||
|
@ -270,19 +303,23 @@ REG cpu_reg[] = {
|
|||
{ FLDATA (SS2, ss[1], 0) },
|
||||
{ FLDATA (SS3, ss[2], 0) },
|
||||
{ FLDATA (SS4, ss[3], 0) },
|
||||
{ FLDATA (ION, dev_ready, INT_V_ON) },
|
||||
{ FLDATA (INODEF, dev_ready, INT_V_NODEF) },
|
||||
{ ORDATA (DEVRDY, dev_ready, 16), REG_RO },
|
||||
{ ORDATA (DEVENB, dev_enable, 16), REG_RO },
|
||||
{ FLDATA (MPERDY, dev_ready, INT_V_MPE) },
|
||||
{ FLDATA (MPEENB, dev_enable, INT_V_MPE) },
|
||||
{ FLDATA (ION, dev_int, INT_V_ON) },
|
||||
{ FLDATA (INODEF, dev_int, INT_V_NODEF) },
|
||||
{ ORDATA (DEVINT, dev_int, 16), REG_RO },
|
||||
{ ORDATA (DEVENB, dev_enb, 16), REG_RO },
|
||||
{ ORDATA (CHREQ, chan_req, DMA_MAX + DMC_MAX) },
|
||||
{ BRDATA (DMAAD, dma_ad, 8, 16, DMA_MAX) },
|
||||
{ BRDATA (DMAWC, dma_wc, 8, 16, DMA_MAX) },
|
||||
{ BRDATA (DMAEOR, dma_eor, 8, 1, DMA_MAX) },
|
||||
{ ORDATA (DMANCH, dma_nch, 3), REG_HRO },
|
||||
{ FLDATA (MPERDY, dev_int, INT_V_MPE) },
|
||||
{ FLDATA (MPEENB, dev_enb, INT_V_MPE) },
|
||||
{ FLDATA (STOP_INST, stop_inst, 0) },
|
||||
{ FLDATA (STOP_DEV, stop_dev, 1) },
|
||||
{ DRDATA (INDMAX, ind_max, 8), REG_NZ + PV_LEFT },
|
||||
{ BRDATA (PCQ, pcq, 8, 15, PCQ_SIZE), REG_RO + REG_CIRC },
|
||||
{ ORDATA (PCQP, pcq_p, 6), REG_HRO },
|
||||
{ ORDATA (WRU, sim_int_char, 8) },
|
||||
{ FLDATA (DLOG, dlog, 0), REG_HIDDEN },
|
||||
{ NULL } };
|
||||
|
||||
MTAB cpu_mod[] = {
|
||||
|
@ -296,47 +333,42 @@ MTAB cpu_mod[] = {
|
|||
{ UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size },
|
||||
{ UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size },
|
||||
{ UNIT_MSIZE, 32768, NULL, "32K", &cpu_set_size },
|
||||
{ MTAB_XTD | MTAB_VDV, 0, "channels", "CHANNELS",
|
||||
&cpu_set_nchan, &cpu_show_nchan, NULL },
|
||||
{ UNIT_DMC, 0, "no DMC", "NODMC", NULL },
|
||||
{ UNIT_DMC, UNIT_DMC, "DMC", "DMC", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "HISTORY", "HISTORY",
|
||||
&cpu_set_hist, &cpu_show_hist },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "DMA1", NULL,
|
||||
NULL, &cpu_show_dma, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "DMA2", NULL,
|
||||
NULL, &cpu_show_dma, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 2, "DMA3", NULL,
|
||||
NULL, &cpu_show_dma, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 3, "DMA4", NULL,
|
||||
NULL, &cpu_show_dma, NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE cpu_dev = {
|
||||
"CPU", &cpu_unit, cpu_reg, cpu_mod,
|
||||
1, 8, 15, 1, 8, 16,
|
||||
&cpu_ex, &cpu_dep, &cpu_reset,
|
||||
NULL, NULL, NULL };
|
||||
|
||||
/* I/O dispatch */
|
||||
|
||||
int32 undio (int32 op, int32 func, int32 AR);
|
||||
extern int32 ptrio (int32 op, int32 func, int32 AR);
|
||||
extern int32 ptpio (int32 op, int32 func, int32 AR);
|
||||
extern int32 lptio (int32 op, int32 func, int32 AR);
|
||||
extern int32 ttyio (int32 op, int32 func, int32 AR);
|
||||
extern int32 clkio (int32 op, int32 func, int32 AR);
|
||||
|
||||
int32 (*iotab[64])() = {
|
||||
&undio, &ptrio, &ptpio, &lptio, &ttyio, &undio, &undio, &undio,
|
||||
&undio, &undio, &undio, &undio, &undio, &undio, &undio, &undio,
|
||||
&clkio, &undio, &undio, &undio, &undio, &undio, &undio, &undio,
|
||||
&undio, &undio, &undio, &undio, &undio, &undio, &undio, &undio,
|
||||
&undio, &undio, &undio, &undio, &undio, &undio, &undio, &undio,
|
||||
&undio, &undio, &undio, &undio, &undio, &undio, &undio, &undio,
|
||||
&undio, &undio, &undio, &undio, &undio, &undio, &undio, &undio,
|
||||
&undio, &undio, &undio, &undio, &undio, &undio, &undio, &undio };
|
||||
|
||||
NULL, NULL, NULL,
|
||||
&cpu_dib, 0 };
|
||||
|
||||
t_stat sim_instr (void)
|
||||
{
|
||||
extern UNIT clk_unit;
|
||||
int32 AR, BR, MB, Y, t1, t2, t3, skip;
|
||||
int32 AR, BR, MB, Y, t1, t2, t3, skip, dev;
|
||||
uint32 ut;
|
||||
t_stat reason;
|
||||
t_stat Ea (int32 inst, int32 *addr);
|
||||
void Write (int32 val, int32 addr);
|
||||
void Write (int32 addr, int32 val);
|
||||
int32 Add16 (int32 val1, int32 val2);
|
||||
int32 Add31 (int32 val1, int32 val2);
|
||||
int32 Operate (int32 MB, int32 AR);
|
||||
|
||||
#define Read(x) M[(x)]
|
||||
#define Read(ad) M[(ad)]
|
||||
#define GETDBL_S(h,l) (((h) << 15) | ((l) & MMASK))
|
||||
#define GETDBL_U(h,l) (((h) << 16) | (l))
|
||||
#define PUTDBL_S(x) AR = ((x) >> 15) & DMASK; \
|
||||
|
@ -349,12 +381,12 @@ int32 Operate (int32 MB, int32 AR);
|
|||
|
||||
/* Restore register state */
|
||||
|
||||
if (devtab_init ()) return SCPE_STOP; /* init tables */
|
||||
AR = saved_AR & DMASK; /* restore reg */
|
||||
BR = saved_BR & DMASK;
|
||||
XR = saved_XR & DMASK;
|
||||
PC = PC & ((cpu_unit.flags & UNIT_EXT)? X_AMASK: NX_AMASK); /* mask PC */
|
||||
reason = 0;
|
||||
turnoff = 0;
|
||||
sim_rtc_init (clk_unit.wait); /* init calibration */
|
||||
|
||||
/* Main instruction fetch/decode loop */
|
||||
|
@ -363,14 +395,59 @@ while (reason == 0) { /* loop until halted */
|
|||
if (sim_interval <= 0) { /* check clock queue */
|
||||
if (reason = sim_process_event ()) break; }
|
||||
|
||||
if ((dev_ready & (INT_PENDING | dev_enable)) > INT_PENDING) { /* int req? */
|
||||
/* Channel breaks (DMA and DMC) */
|
||||
|
||||
if (chan_req) { /* channel request? */
|
||||
int32 i, t, ch, dev, st, end, ad, dmcad;
|
||||
t_stat r;
|
||||
for (i = 0, ch = chan_req; ch != 0; i++, ch = ch >> 1) {
|
||||
if (ch & 1) { /* req on chan i? */
|
||||
dev = chan_map[i]; /* get dev for chan */
|
||||
if (iotab[dev] == &undio) return SCPE_IERR;
|
||||
chan_req = chan_req & ~(1 << i); /* clear req */
|
||||
if (Q_DMA (i)) st = dma_ad[i]; /* DMA? */
|
||||
else { /* DMC */
|
||||
dmcad = DMC_BASE + ((i - DMC_V_DMC1) << 1);
|
||||
st = Read (dmcad); } /* DMC ctrl word */
|
||||
ad = st & X_AMASK; /* get curr addr */
|
||||
if (st & DMA_IN) { /* input? */
|
||||
t = iotab[dev] (ioINA, 0, 0, dev); /* input word */
|
||||
if ((t & IOT_SKIP) == 0) return STOP_DMAER;
|
||||
if (r = (t >> IOT_V_REASON)) return r;
|
||||
Write (ad, t & DMASK); } /* write to mem */
|
||||
else { /* no, output */
|
||||
t = iotab[dev] (ioOTA, 0, Read (ad), dev); /* output word */
|
||||
if ((t & IOT_SKIP) == 0) return STOP_DMAER;
|
||||
if (r = (t >> IOT_V_REASON)) return r; }
|
||||
if (Q_DMA (i)) { /* DMA? */
|
||||
dma_ad[i] = (dma_ad[i] & DMA_IN) | ((ad + 1) & X_AMASK);
|
||||
dma_wc[i] = (dma_wc[i] + 1) & 077777; /* update wc */
|
||||
if (dma_wc[i] == 0) { /* done? */
|
||||
dma_eor[i] = 1; /* set end of range */
|
||||
t = iotab[dev] (ioEND, 0, 0, dev); /* send end range */
|
||||
if (r = (t >> IOT_V_REASON)) return r; } }
|
||||
else { /* DMC */
|
||||
st = (st & DMA_IN) | ((ad + 1) & X_AMASK);
|
||||
Write (dmcad, st); /* update start */
|
||||
end = Read (dmcad + 1); /* get end */
|
||||
if (((ad ^ end) & X_AMASK) == 0) { /* start == end? */
|
||||
t = iotab[dev] (ioEND, 0, 0, dev); /* send end range */
|
||||
if (r = (t >> IOT_V_REASON)) return r; } }
|
||||
} /* end if chan i */
|
||||
} /* end for */
|
||||
} /* end if chan_req */
|
||||
|
||||
|
||||
/* Interrupts */
|
||||
|
||||
if ((dev_int & (INT_PENDING | dev_enb)) > INT_PENDING) { /* int req? */
|
||||
pme = ext; /* save extend */
|
||||
if (cpu_unit.flags & UNIT_EXT) ext = 1; /* ext opt? extend on */
|
||||
dev_ready = dev_ready & ~INT_ON; /* intr off */
|
||||
turnoff = 0;
|
||||
if (dlog && sim_log) fprintf (sim_log, "Interrupt\n");
|
||||
dev_int = dev_int & ~INT_ON; /* intr off */
|
||||
MB = 0120000 | M_INT; } /* inst = JST* 63 */
|
||||
|
||||
/* Instruction fetch */
|
||||
|
||||
else { if (sim_brk_summ &&
|
||||
sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
|
||||
reason = STOP_IBKPT; /* stop simulation */
|
||||
|
@ -378,16 +455,17 @@ else { if (sim_brk_summ &&
|
|||
Y = PC; /* set mem addr */
|
||||
MB = Read (Y); /* fetch instr */
|
||||
PC = NEWA (Y, Y + 1); /* incr PC */
|
||||
dev_ready = dev_ready | INT_NODEF; }
|
||||
dev_int = dev_int | INT_NODEF; }
|
||||
|
||||
sim_interval = sim_interval - 1;
|
||||
if (dlog && sim_log && !turnoff) { /* cycle log? */
|
||||
int32 op = I_GETOP (MB) & 017; /* core opcode */
|
||||
t_value val = MB;
|
||||
fprintf (sim_log, "A= %06o C= %1o P= %05o (", AR, C, PC);
|
||||
fprint_sym (sim_log, Y, &val, &cpu_unit, SWMASK ('M'));
|
||||
fprintf (sim_log, ")");
|
||||
if ((op == 0) || (op == 014)) fprintf (sim_log, "\n"); }
|
||||
if (hst_lnt) { /* instr hist? */
|
||||
hst_p = (hst_p + 1); /* next entry */
|
||||
if (hst_p >= hst_lnt) hst_p = 0;
|
||||
hst[hst_p].pc = Y | HIST_PC | (C? HIST_C: 0); /* fill slots */
|
||||
hst[hst_p].ir = MB;
|
||||
hst[hst_p].ar = AR;
|
||||
hst[hst_p].br = BR;
|
||||
hst[hst_p].xr = XR; }
|
||||
|
||||
/* Memory reference instructions */
|
||||
|
||||
|
@ -397,12 +475,6 @@ case 001: case 021: case 041: case 061: /* JMP */
|
|||
if (reason = Ea (MB, &Y)) break; /* eff addr */
|
||||
PCQ_ENTRY; /* save PC */
|
||||
PC = NEWA (PC, Y); /* set new PC */
|
||||
if (dlog && sim_log) { /* logging? */
|
||||
int32 op = I_GETOP (M[PC]) & 017; /* get target */
|
||||
if ((op == 014) && (PC == (PCQ_TOP - 2))) { /* jmp .-1 to IO? */
|
||||
turnoff = 1; /* yes, stop */
|
||||
fprintf (sim_log, "Idle loop detected\n"); }
|
||||
else turnoff = 0; } /* no, log */
|
||||
if (extoff_pending) ext = extoff_pending = 0; /* cond ext off */
|
||||
break;
|
||||
|
||||
|
@ -423,10 +495,10 @@ case 003: case 023: case 043: case 063: /* ANA */
|
|||
case 004: case 024: case 044: case 064: /* STA */
|
||||
if (reason = Ea (MB, &Y)) break; /* eff addr */
|
||||
if (dp) { /* double prec? */
|
||||
if ((Y & 1) == 0) Write (AR, Y); /* if even, store A */
|
||||
Write (BR, Y | 1); /* store B */
|
||||
if ((Y & 1) == 0) Write (Y, AR); /* if even, store A */
|
||||
Write (Y | 1, BR); /* store B */
|
||||
sc = 0; }
|
||||
else Write (AR, Y); /* no, store word */
|
||||
else Write (Y, AR); /* no, store word */
|
||||
break;
|
||||
|
||||
case 005: case 025: case 045: case 065: /* ERA */
|
||||
|
@ -461,7 +533,7 @@ case 007: case 027: case 047: case 067: /* SUB */
|
|||
case 010: case 030: case 050: case 070: /* JST */
|
||||
if (reason = Ea (MB, &Y)) break; /* eff addr */
|
||||
MB = NEWA (Read (Y), PC); /* merge old PC */
|
||||
Write (MB, Y);
|
||||
Write (Y, MB);
|
||||
PCQ_ENTRY;
|
||||
PC = NEWA (PC, Y + 1); /* set new PC */
|
||||
break;
|
||||
|
@ -476,20 +548,20 @@ case 011: case 031: case 051: case 071: /* CAS */
|
|||
case 012: case 032: case 052: case 072: /* IRS */
|
||||
if (reason = Ea (MB, &Y)) break; /* eff addr */
|
||||
MB = (Read (Y) + 1) & DMASK; /* incr, rewrite */
|
||||
Write (MB, Y);
|
||||
Write (Y, MB);
|
||||
if (MB == 0) PC = NEWA (PC, PC + 1); /* skip if zero */
|
||||
break;
|
||||
|
||||
case 013: case 033: case 053: case 073: /* IMA */
|
||||
if (reason = Ea (MB, &Y)) break; /* eff addr */
|
||||
MB = Read (Y);
|
||||
Write (AR, Y); /* A to mem */
|
||||
Write (Y, AR); /* A to mem */
|
||||
AR = MB; /* mem to A */
|
||||
break;
|
||||
|
||||
case 015: case 055: /* STX */
|
||||
if (reason = Ea (MB & ~IDX, &Y)) break; /* eff addr */
|
||||
Write (XR, Y); /* store XR */
|
||||
Write (Y, XR); /* store XR */
|
||||
break;
|
||||
|
||||
case 035: case 075: /* LDX */
|
||||
|
@ -525,35 +597,32 @@ case 017: case 037: case 057: case 077: /* DIV */
|
|||
/* I/O instructions */
|
||||
|
||||
case 014: /* OCP */
|
||||
t2 = iotab[MB & DEVMASK] (ioOCP, I_GETFNC (MB), AR);
|
||||
dev = MB & DEVMASK;
|
||||
t2 = iotab[dev] (ioOCP, I_GETFNC (MB), AR, dev);
|
||||
reason = t2 >> IOT_V_REASON;
|
||||
turnoff = 0;
|
||||
break;
|
||||
|
||||
case 034: /* SKS */
|
||||
t2 = iotab[MB & DEVMASK] (ioSKS, I_GETFNC (MB), AR);
|
||||
dev = MB & DEVMASK;
|
||||
t2 = iotab[dev] (ioSKS, I_GETFNC (MB), AR, dev);
|
||||
reason = t2 >> IOT_V_REASON;
|
||||
if (t2 & IOT_SKIP) { /* skip? */
|
||||
PC = NEWA (PC, PC + 1);
|
||||
turnoff = 0; }
|
||||
if (t2 & IOT_SKIP) PC = NEWA (PC, PC + 1); /* skip? */
|
||||
break;
|
||||
|
||||
case 054: /* INA */
|
||||
dev = MB & DEVMASK;
|
||||
if (MB & INCLRA) AR = 0;
|
||||
t2 = iotab[MB & DEVMASK] (ioINA, I_GETFNC (MB), AR);
|
||||
t2 = iotab[dev] (ioINA, I_GETFNC (MB & ~INCLRA), AR, dev);
|
||||
reason = t2 >> IOT_V_REASON;
|
||||
if (t2 & IOT_SKIP) { /* skip? */
|
||||
PC = NEWA (PC, PC + 1);
|
||||
turnoff = 0; }
|
||||
if (t2 & IOT_SKIP) PC = NEWA (PC, PC + 1); /* skip? */
|
||||
AR = t2 & DMASK; /* data */
|
||||
break;
|
||||
|
||||
case 074: /* OTA */
|
||||
t2 = iotab[MB & DEVMASK] (ioOTA, I_GETFNC (MB), AR);
|
||||
dev = MB & DEVMASK;
|
||||
t2 = iotab[dev] (ioOTA, I_GETFNC (MB), AR, dev);
|
||||
reason = t2 >> IOT_V_REASON;
|
||||
if (t2 & IOT_SKIP) { /* skip? */
|
||||
PC = NEWA (PC, PC + 1);
|
||||
turnoff = 0; }
|
||||
if (t2 & IOT_SKIP) PC = NEWA (PC, PC + 1); /* skip? */
|
||||
break;
|
||||
|
||||
/* Control */
|
||||
|
@ -571,8 +640,7 @@ case 000:
|
|||
ext = 1;
|
||||
extoff_pending = 0; } /* DXA */
|
||||
else extoff_pending = 1; }
|
||||
if (MB & m12) /* RMP */
|
||||
dev_ready = dev_ready & ~INT_MPE;
|
||||
if (MB & m12) CLR_INT (INT_MPE); /* RMP */
|
||||
if (MB & m11) { /* SCA, INK */
|
||||
if (MB & m15) /* INK */
|
||||
AR = (C << 15) | (dp << 14) | (pme << 13) | (sc & 037);
|
||||
|
@ -594,9 +662,9 @@ case 000:
|
|||
BR = AR;
|
||||
AR = sc; }
|
||||
if (MB & m8) /* ENB */
|
||||
dev_ready = (dev_ready | INT_ON) & ~INT_NODEF;
|
||||
dev_int = (dev_int | INT_ON) & ~INT_NODEF;
|
||||
if (MB & m7) /* INH */
|
||||
dev_ready = dev_ready & ~INT_ON;
|
||||
dev_int = dev_int & ~INT_ON;
|
||||
break;
|
||||
|
||||
/* Shift
|
||||
|
@ -841,15 +909,17 @@ else { /* non-extend */
|
|||
Y = NEWA (Y, IR + ((IR & IDX)? XR: 0)); } /* post-index */
|
||||
} /* end else */
|
||||
*addr = Y = Y & X_AMASK; /* return addr */
|
||||
if (dlog && sim_log && !turnoff) /* cycle log? */
|
||||
fprintf (sim_log, " EA= %06o [%06o]\n", Y, M[Y]);
|
||||
if (hst_lnt) { /* history? */
|
||||
hst[hst_p].pc = hst[hst_p].pc | HIST_EA;
|
||||
hst[hst_p].ea = Y;
|
||||
hst[hst_p].opnd = Read (Y); }
|
||||
if (i >= ind_max) return STOP_IND; /* too many ind? */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Write memory */
|
||||
|
||||
void Write (int32 val, int32 addr)
|
||||
void Write (int32 addr, int32 val)
|
||||
{
|
||||
if (((addr == 0) || (addr >= 020)) && MEM_ADDR_OK (addr))
|
||||
M[addr] = val;
|
||||
|
@ -878,10 +948,34 @@ return r;
|
|||
|
||||
/* Unimplemented I/O device */
|
||||
|
||||
int32 undio (int32 op, int32 fnc, int32 val)
|
||||
int32 undio (int32 op, int32 fnc, int32 val, int32 dev)
|
||||
{
|
||||
return ((stop_dev << IOT_V_REASON) | val);
|
||||
}
|
||||
|
||||
/* DMA control */
|
||||
|
||||
int32 dmaio (int32 inst, int32 fnc, int32 dat, int32 dev)
|
||||
{
|
||||
int32 ch = (fnc - 1) & 03;
|
||||
|
||||
switch (inst) { /* case on opcode */
|
||||
case ioOCP: /* OCP */
|
||||
if ((fnc >= 001) && (fnc <= 004)) { /* load addr ctr */
|
||||
dma_ad[ch] = dat;
|
||||
dma_wc[ch] = 0;
|
||||
dma_eor[ch] = 0; }
|
||||
else if ((fnc >= 011) && (fnc <= 014)) /* load range ctr */
|
||||
dma_wc[ch] = (dma_wc[ch] | dat) & 077777;
|
||||
else return IOBADFNC (dat); /* undefined */
|
||||
break;
|
||||
case ioINA: /* INA */
|
||||
if ((fnc >= 011) && (fnc <= 014)) {
|
||||
if (dma_eor[ch]) return dat; /* end range? nop */
|
||||
return IOSKIP (0100000 | dma_wc[ch]); } /* return range */
|
||||
else return IOBADFNC (dat); }
|
||||
return dat;
|
||||
}
|
||||
|
||||
/* Undefined operate instruction. This code is reached when the
|
||||
opcode does not correspond to a standard operate instruction.
|
||||
|
@ -1027,12 +1121,16 @@ return ARx;
|
|||
|
||||
t_stat cpu_reset (DEVICE *dptr)
|
||||
{
|
||||
int32 i;
|
||||
|
||||
saved_AR = saved_BR = saved_XR = 0;
|
||||
C = 0;
|
||||
dp = 0;
|
||||
ext = pme = extoff_pending = 0;
|
||||
dev_ready = dev_ready & ~INT_PENDING;
|
||||
dev_enable = 0;
|
||||
dev_int = dev_int & ~INT_PENDING;
|
||||
dev_enb = 0;
|
||||
for (i = 0; i < DMA_MAX; i++) dma_ad[i] = dma_wc[i] = dma_eor[i] = 0;
|
||||
chan_req = 0;
|
||||
pcq_r = find_reg ("PCQ", NULL, dptr);
|
||||
if (pcq_r) pcq_r->qptr = 0;
|
||||
else return SCPE_IERR;
|
||||
|
@ -1086,3 +1184,216 @@ MEMSIZE = val;
|
|||
for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat cpu_set_nchan (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
uint32 i, newmax;
|
||||
t_stat r;
|
||||
|
||||
if (cptr == NULL) return SCPE_ARG;
|
||||
newmax = get_uint (cptr, 10, DMA_MAX, &r); /* get new max */
|
||||
if ((r != SCPE_OK) || (newmax == dma_nch)) return r; /* err or no chg? */
|
||||
dma_nch = newmax; /* set new max */
|
||||
for (i = newmax; i <DMA_MAX; i++) { /* reset chan */
|
||||
dma_ad[i] = dma_wc[i] = dma_eor[i] = 0;
|
||||
chan_req = chan_req & ~(1 << i); }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Show DMA channels */
|
||||
|
||||
t_stat cpu_show_nchan (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
if (dma_nch) fprintf (st, "DMA channels = %d", dma_nch);
|
||||
else fprintf (st, "no DMA channels");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Show channel state */
|
||||
|
||||
t_stat cpu_show_dma (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
if ((val < 0) || (val >= DMA_MAX)) return SCPE_IERR;
|
||||
fputs ((dma_ad[val] & DMA_IN)? "Input": "Output", st);
|
||||
fprintf (st, ", addr = %06o, count = %06o, ", dma_ad[val] & X_AMASK, dma_wc[val]);
|
||||
fprintf (st, "end of range %s\n", (dma_eor[val]? "set": "clear"));
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Set I/O device to IOBUS / DMA channel / DMC channel */
|
||||
|
||||
t_stat io_set_iobus (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
DEVICE *dptr;
|
||||
DIB *dibp;
|
||||
|
||||
if (val || cptr || (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;
|
||||
dibp->chan = 0;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat io_set_dma (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
DEVICE *dptr;
|
||||
DIB *dibp;
|
||||
uint32 newc;
|
||||
t_stat r;
|
||||
|
||||
if ((cptr == NULL) || (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;
|
||||
if (dma_nch == 0) return SCPE_NOFNC;
|
||||
newc = get_uint (cptr, 10, DMA_MAX, &r); /* get new */
|
||||
if ((r != SCPE_OK) || (newc == 0) || (newc > dma_nch)) return SCPE_ARG;
|
||||
dibp->chan = (newc - DMA_MIN) + DMA_V_DMA1 + 1; /* store */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat io_set_dmc (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
DEVICE *dptr;
|
||||
DIB *dibp;
|
||||
uint32 newc;
|
||||
t_stat r;
|
||||
|
||||
if ((cptr == NULL) || (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;
|
||||
if (!(cpu_unit.flags & UNIT_DMC)) return SCPE_NOFNC;
|
||||
newc = get_uint (cptr, 10, DMC_MAX, &r); /* get new */
|
||||
if ((r != SCPE_OK) || (newc == 0)) return SCPE_ARG;
|
||||
dibp->chan = (newc - DMC_MIN) + DMC_V_DMC1 + 1; /* store */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Show channel configuration */
|
||||
|
||||
t_stat io_show_chan (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) return SCPE_IERR;
|
||||
if (dibp->chan == 0) fprintf (st, "IO bus");
|
||||
else if (dibp->chan < (DMC_V_DMC1 + 1))
|
||||
fprintf (st, "DMA channel %d", dibp->chan);
|
||||
else fprintf (st, "DMC channel %d", dibp->chan - DMC_V_DMC1);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Set up I/O dispatch and channel maps */
|
||||
|
||||
t_bool devtab_init (void)
|
||||
{
|
||||
DEVICE *dptr;
|
||||
DIB *dibp;
|
||||
uint32 i, j, dno, chan;
|
||||
|
||||
for (i = 0; i < DEV_MAX; i++) iotab[i] = NULL;
|
||||
for (i = 0; i < (DMA_MAX + DMC_MAX); i++) chan_map[i] = 0;
|
||||
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->dev; /* device number */
|
||||
for (j = 0; j < dibp->num; j++) { /* repeat for slots */
|
||||
if (iotab[dno + j]) { /* conflict? */
|
||||
printf ("%s device number conflict, devno = %02o\n", sim_dname (dptr), dno + j);
|
||||
if (sim_log) fprintf (sim_log,
|
||||
"%s device number conflict, devno = %02o\n", sim_dname (dptr), dno + j);
|
||||
return TRUE; }
|
||||
iotab[dno + j] = dibp->io; /* set I/O routine */
|
||||
} /* end for */
|
||||
if (dibp->chan) { /* DMA/DMC? */
|
||||
chan = dibp->chan - 1;
|
||||
if ((chan >= 0) && (chan < DMC_V_DMC1) && (chan >= dma_nch)) {
|
||||
printf ("%s configured for DMA channel %d\n", sim_dname (dptr), chan + 1);
|
||||
if (sim_log) fprintf (sim_log,
|
||||
"%s configured for DMA channel %d\n", sim_dname (dptr), chan + 1);
|
||||
return TRUE; }
|
||||
if ((chan >= DMC_V_DMC1) && !(cpu_unit.flags & UNIT_DMC)) {
|
||||
printf ("%s configured for DMC, option disabled\n", sim_dname (dptr));
|
||||
if (sim_log) fprintf (sim_log,
|
||||
"%s configured for DMC, option disabled\n", sim_dname (dptr));
|
||||
return TRUE; }
|
||||
if (chan_map[chan]) { /* channel conflict? */
|
||||
printf ("%s DMA/DMC channel conflict, devno = %02o\n", sim_dname (dptr), dno);
|
||||
if (sim_log) fprintf (sim_log,
|
||||
"%s DMA/DMC channel conflict, devno = %02o\n", sim_dname (dptr), dno);
|
||||
return TRUE; }
|
||||
chan_map[chan] = dno; } /* channel back map */
|
||||
} /* end for */
|
||||
for (i = 0; i < DEV_MAX; i++) { /* fill in blanks */
|
||||
if (iotab[i] == NULL) iotab[i] = &undio; }
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Set history */
|
||||
|
||||
t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
int32 i, lnt;
|
||||
t_stat r;
|
||||
|
||||
if (cptr == NULL) {
|
||||
for (i = 0; i < hst_lnt; i++) hst[i].pc = 0;
|
||||
hst_p = 0;
|
||||
return SCPE_OK; }
|
||||
lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r);
|
||||
if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG;
|
||||
hst_p = 0;
|
||||
if (hst_lnt) {
|
||||
free (hst);
|
||||
hst_lnt = 0;
|
||||
hst = NULL; }
|
||||
if (lnt) {
|
||||
hst = calloc (sizeof (struct InstHistory), lnt);
|
||||
if (hst == NULL) return SCPE_MEM;
|
||||
hst_lnt = lnt; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Show history */
|
||||
|
||||
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
int32 cr, k, di, op;
|
||||
t_value sim_eval;
|
||||
struct InstHistory *h;
|
||||
extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
|
||||
UNIT *uptr, int32 sw);
|
||||
static uint8 has_opnd[16] = {
|
||||
0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1 };
|
||||
|
||||
if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */
|
||||
fprintf (st, "PC C A B X ea IR\n\n");
|
||||
di = hst_p; /* work forward */
|
||||
for (k = 0; k < hst_lnt; k++) { /* print specified */
|
||||
h = &hst[(++di) % hst_lnt]; /* entry pointer */
|
||||
if (h->pc & HIST_PC) { /* instruction? */
|
||||
cr = (h->pc & HIST_C)? 1: 0; /* carry */
|
||||
fprintf (st, "%05o %o %06o %06o %06o ",
|
||||
h->pc & X_AMASK, cr, h->ar, h->br, h->xr);
|
||||
if (h->pc & HIST_EA) fprintf (st, "%05o ", h->ea);
|
||||
else fprintf (st, " ");
|
||||
sim_eval = h->ir;
|
||||
if ((fprint_sym (st, h->pc & X_AMASK, &sim_eval, &cpu_unit, SWMASK ('M'))) > 0)
|
||||
fprintf (st, "(undefined) %06o", h->ir);
|
||||
op = I_GETOP (h->ir) & 017; /* base op */
|
||||
if (has_opnd[op]) fprintf (st, " [%06o]", h->opnd);
|
||||
fputc ('\n', st); /* end line */
|
||||
} /* end else instruction */
|
||||
} /* end for */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
|
|
@ -23,9 +23,13 @@
|
|||
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.
|
||||
|
||||
24-Oct-03 RMS Added DMA/DMC support
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
*/
|
||||
|
||||
#ifndef _H316_DEFS_H_
|
||||
#define _H316_DEFS_H_ 0
|
||||
|
||||
#include "sim_defs.h" /* simulator defns */
|
||||
|
||||
/* Simulator stop codes */
|
||||
|
@ -35,6 +39,10 @@
|
|||
#define STOP_HALT 3 /* HALT */
|
||||
#define STOP_IBKPT 4 /* breakpoint */
|
||||
#define STOP_IND 5 /* indirect loop */
|
||||
#define STOP_DMAER 6 /* DMA error */
|
||||
#define STOP_MTWRP 7 /* MT write protected */
|
||||
#define STOP_DPOVR 8 /* DP write overrun */
|
||||
#define STOP_DPFMT 9 /* DP invalid format */
|
||||
|
||||
/* Memory */
|
||||
|
||||
|
@ -56,10 +64,14 @@
|
|||
|
||||
/* CPU options */
|
||||
|
||||
#define UNIT_V_MSIZE (UNIT_V_UF + 0) /* dummy mask */
|
||||
#define UNIT_V_EXT (UNIT_V_UF + 1) /* extended mem */
|
||||
#define UNIT_V_HSA (UNIT_V_UF + 2) /* high speed arith */
|
||||
#define UNIT_V_DMC (UNIT_V_UF + 3) /* DMC */
|
||||
#define UNIT_MSIZE (1u << UNIT_V_MSIZE)
|
||||
#define UNIT_EXT (1u << UNIT_V_EXT)
|
||||
#define UNIT_HSA (1u << UNIT_V_HSA)
|
||||
#define UNIT_DMC (1u << UNIT_V_DMC)
|
||||
|
||||
/* Instruction format */
|
||||
|
||||
|
@ -84,8 +96,42 @@
|
|||
#define ioSKS 1 /* skip if set */
|
||||
#define ioINA 2 /* input to A */
|
||||
#define ioOTA 3 /* output from A */
|
||||
#define ioEND 4 /* channel end */
|
||||
|
||||
/* I/O devices */
|
||||
/* Device information block */
|
||||
|
||||
struct h316_dib {
|
||||
uint32 dev; /* device number */
|
||||
uint32 chan; /* dma/dmc channel */
|
||||
uint32 num; /* number of slots */
|
||||
int32 (*io) (int32 inst, int32 fnc, int32 dat, int32 dev); };
|
||||
|
||||
typedef struct h316_dib DIB;
|
||||
|
||||
/* DMA/DMC channel numbers */
|
||||
|
||||
#define IOBUS 0 /* IO bus */
|
||||
#define DMA_MIN 1 /* 4 DMA channels */
|
||||
#define DMA_MAX 4
|
||||
#define DMC_MIN 1 /* 16 DMC channels */
|
||||
#define DMC_MAX 16
|
||||
|
||||
#define DMA1 (DMA_MIN)
|
||||
#define DMC1 (DMA_MAX+DMC_MIN)
|
||||
|
||||
/* DMA/DMC bit assignments in channel request word */
|
||||
|
||||
#define DMA_V_DMA1 0 /* DMA channels */
|
||||
#define DMC_V_DMC1 4 /* DMC channels */
|
||||
#define SET_CH_REQ(x) chan_req = chan_req | (1 << (x))
|
||||
#define Q_DMA(x) (((x) >= 0) && ((x) < DMC_V_DMC1))
|
||||
|
||||
/* DMA/DMC definitions */
|
||||
|
||||
#define DMA_IN 0100000 /* input flag */
|
||||
#define DMC_BASE 020 /* DMC memory base */
|
||||
|
||||
/* I/O device codes */
|
||||
|
||||
#define PTR 001 /* paper tape reader */
|
||||
#define PTP 002 /* paper tape punch */
|
||||
|
@ -93,11 +139,11 @@
|
|||
#define TTY 004 /* console */
|
||||
#define CDR 005 /* card reader */
|
||||
#define MT 010 /* mag tape data */
|
||||
#define KEYS 020 /* keys (CPU) */
|
||||
#define CLK_KEYS 020 /* clock/keys (CPU) */
|
||||
#define FHD 022 /* fixed head disk */
|
||||
#define DMA 024 /* DMA control */
|
||||
#define DP 025 /* moving head disk */
|
||||
#define OPT 034 /* SKS/OCP option */
|
||||
#define DEV_MAX 64
|
||||
|
||||
/* Interrupt flags, definitions correspond to SMK bits */
|
||||
|
||||
|
@ -119,7 +165,7 @@
|
|||
#define IOT_V_REASON 17
|
||||
#define IOT_V_SKIP 16
|
||||
#define IOT_SKIP (1u << IOT_V_SKIP)
|
||||
#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */
|
||||
#define IORETURN(f,v) (((f)? (v): SCPE_OK) << IOT_V_REASON)
|
||||
#define IOBADFNC(x) (((stop_inst) << IOT_V_REASON) | (x))
|
||||
#define IOSKIP(x) (IOT_SKIP | (x))
|
||||
|
||||
|
@ -137,8 +183,17 @@
|
|||
#define INT_ON (1u << INT_V_ON)
|
||||
#define INT_PENDING (INT_ON | INT_NODEF)
|
||||
|
||||
#define SET_READY(x) dev_ready = dev_ready | (x)
|
||||
#define CLR_READY(x) dev_ready = dev_ready & ~(x)
|
||||
#define TST_READY(x) ((dev_ready & (x)) != 0)
|
||||
#define CLR_ENABLE(x) dev_enable = dev_enable & ~(x)
|
||||
#define TST_INTREQ(x) ((dev_ready & dev_enable & (x)) != 0)
|
||||
#define SET_INT(x) dev_int = dev_int | (x)
|
||||
#define CLR_INT(x) dev_int = dev_int & ~(x)
|
||||
#define TST_INT(x) ((dev_int & (x)) != 0)
|
||||
#define CLR_ENB(x) dev_enb = dev_enb & ~(x)
|
||||
#define TST_INTREQ(x) ((dev_int & dev_enb & (x)) != 0)
|
||||
|
||||
/* Prototypes */
|
||||
|
||||
t_stat io_set_iobus (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat io_set_dma (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat io_set_dmc (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat io_show_chan (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
To: Users
|
||||
From: Bob Supnik
|
||||
Subj: H316 Simulator Usage
|
||||
Date: 15-Jul-2003
|
||||
Date: 15-Nov-2003
|
||||
|
||||
COPYRIGHT NOTICE
|
||||
|
||||
|
@ -41,15 +41,20 @@ The H316 requires the following files:
|
|||
sim/ sim_defs.h
|
||||
sim_rev.h
|
||||
sim_sock.h
|
||||
sim_tape.h
|
||||
sim_tmxr.h
|
||||
scp.c
|
||||
scp_tty.c
|
||||
sim_sock.c
|
||||
sim_tape.c
|
||||
sim_tmxr.c
|
||||
|
||||
sim/h316/ h316_defs.h
|
||||
h316_cpu.c
|
||||
h316_fhd.c
|
||||
h316_lp.c
|
||||
h316_mt.c
|
||||
h316_dp.c
|
||||
h316_stddev.c
|
||||
h316_sys.c
|
||||
|
||||
|
@ -66,6 +71,9 @@ PTP 316/516-52 paper tape punch
|
|||
TTY 316/516-33 console terminal
|
||||
CLK 316/516-12 real time clock
|
||||
LPT 316/516 line printer
|
||||
FHD 4400 fixed head disk
|
||||
DP 4623/4653/4720 disk pack controller with eight drives
|
||||
MT 4100 seven track magtape with four drives
|
||||
|
||||
The H316/H516 simulator implements several unique stop conditions:
|
||||
|
||||
|
@ -73,12 +81,19 @@ The H316/H516 simulator implements several unique stop conditions:
|
|||
- reference to an undefined I/O device, and STOP_DEV is set
|
||||
- more than INDMAX indirect references are detected during
|
||||
memory reference address decoding
|
||||
- DMA/DMC direction does not agree with I/O device operation
|
||||
- a write operation is initiated on a write locked magtape
|
||||
unit (hangs the real system)
|
||||
- a disk write overruns the specified record size (destroys
|
||||
the rest of the track on the real system)
|
||||
- a disk track has an illegal format
|
||||
|
||||
The H316/H516 loader is not implemented.
|
||||
|
||||
2.1 CPU
|
||||
|
||||
CPU options include choice of instruction set and memory size.
|
||||
CPU options include choice of instruction set, memory size, DMC option,
|
||||
and number of DMA channels.
|
||||
|
||||
SET CPU HSA high speed arithmetic instructions
|
||||
SET CPU NOHSA no high speed arithmetic instructions
|
||||
|
@ -88,10 +103,19 @@ CPU options include choice of instruction set and memory size.
|
|||
SET CPU 16K set memory size = 16K
|
||||
SET CPU 24K set memory size = 24K
|
||||
SET CPU 32K set memory size = 32K
|
||||
SET CPU DMC enable DMC option
|
||||
SET CPU NODMC disable DMC option
|
||||
SET CPU DMA=n set number of DMA channels to n (0-4)
|
||||
|
||||
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 32K.
|
||||
portion of memory is lost. Initial memory size is 32K. The HSA and DMC
|
||||
options are enabled, and four DMA channels are configured.
|
||||
|
||||
The CPU includes special show commands to display the state of the DMA
|
||||
channels:
|
||||
|
||||
SHOW CPU DMAn show DMA channel n
|
||||
|
||||
CPU registers include the visible state of the processor as well as the
|
||||
control registers for the interrupt system.
|
||||
|
@ -114,6 +138,10 @@ control registers for the interrupt system.
|
|||
INTREQ 16 interrupt requests
|
||||
DEVRDY 16 device ready flags (read only)
|
||||
DEVENB 16 device interrupt enable flags (read only)
|
||||
CHREQ 20 DMA/DMC channel requests
|
||||
DMAAD[0:3] 16 DMA channel current address, channels 1-4
|
||||
DMAWC[0:3] 15 DMA channel word count, channels 1-4
|
||||
DMAEOR[0:3] 1 DMA end of range flag, channels 1-4
|
||||
STOP_INST 1 stop on undefined instruction
|
||||
STOP_DEV 1 stop on undefined device
|
||||
INDMAX 1 indirect address limit
|
||||
|
@ -230,12 +258,21 @@ The clock implements these registers:
|
|||
The real-time clock autocalibrates; the clock interval is adjusted up or
|
||||
down so that the clock tracks actual elapsed time.
|
||||
|
||||
2.2.5 316/516 Line Printer (LPT)
|
||||
2.3 316/516 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.
|
||||
|
||||
The line printer can be connected to the IO bus, a DMC channel, or
|
||||
a DMA channel:
|
||||
|
||||
SET LPT IOBUS connect to IO bus
|
||||
SET LPT DMC=n connect to DMC channel n (1-16)
|
||||
SET LPT DMA=n connect to DMA channel n (1-4)
|
||||
|
||||
By default, the line printer is connected to the IO bus.
|
||||
|
||||
The line printer implements these registers:
|
||||
|
||||
name size comments
|
||||
|
@ -243,8 +280,10 @@ The line printer implements these registers:
|
|||
WDPOS 6 word position in current scan
|
||||
DRPOS 6 drum position
|
||||
CRPOS 1 carriage position
|
||||
XFER 1 transfer ready flag
|
||||
PRDN 1 print done flag
|
||||
RDY 1 ready flag
|
||||
EOR 1 (DMA/DMC) end of range flag
|
||||
DMA 1 transfer using DMA/DMC
|
||||
INTREQ 1 device interrupt request
|
||||
ENABLE 1 device interrupt enable
|
||||
SVCST 2 service state
|
||||
|
@ -265,7 +304,207 @@ Error handling is as follows:
|
|||
|
||||
OS I/O error x report error and stop
|
||||
|
||||
2.3 Symbolic Display and Input
|
||||
2.4 4400 Fixed Head Disk (FHD)
|
||||
|
||||
Fixed head disk options include the ability to set the number of
|
||||
surfaces to a fixed value between 1 and 16, or to autosize the number
|
||||
of surfaces from the attached file:
|
||||
|
||||
SET FHD 1S one surface (98K)
|
||||
SET FHD 2S two platters (196K)
|
||||
:
|
||||
SET FHD 16S sixteen surfaces (1568K)
|
||||
SET FHD AUTOSIZE autosized on attach
|
||||
|
||||
The default is one surface.
|
||||
|
||||
The fixed head disk can be connected to the IO bus, a DMC channel, or
|
||||
a DMA channel:
|
||||
|
||||
SET FHD IOBUS connect to IO bus
|
||||
SET FHD DMC=n connect to DMC channel n (1-16)
|
||||
SET FHD DMA=n connect to DMA channel n (1-4)
|
||||
|
||||
By default, the fixed head disk is connected to the IO bus.
|
||||
|
||||
|
||||
The fixed head disk implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
CW1 16 control word 1 (read write, surface, track)
|
||||
CW2 16 control word 2 (character address)
|
||||
BUF 16 data buffer
|
||||
BUSY 1 controller busy flag
|
||||
RDY 1 transfer ready flag
|
||||
DTE 1 data transfer error flag
|
||||
ACE 1 access error flag
|
||||
EOR 1 (DMA/DMC) end of range
|
||||
DMA 1 transfer using DMA/DMC
|
||||
CSUM 1 transfer parity checksum
|
||||
INTREQ 1 device interrupt request
|
||||
ENABLE 1 device interrupt enable
|
||||
TIME 24 delay between words
|
||||
STOP_IOE 1 stop on I/O error
|
||||
|
||||
The fixed head disk does not support the BOOT command.
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error STOP_IOE processed as
|
||||
|
||||
not attached 1 report error and stop
|
||||
0 disk not ready
|
||||
|
||||
Fixed head disk data files are buffered in memory; therefore, end of file
|
||||
and OS I/O errors cannot occur.
|
||||
|
||||
2.5 4100 7-track Magnetic Tape (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 be set ONLINE or OFFLINE, and WRITEENABLED or write LOCKED.
|
||||
|
||||
The magtape controller can be connected to the IO bus, a DMC channel, or
|
||||
a DMA channel:
|
||||
|
||||
SET MT IOBUS connect to IO bus
|
||||
SET MT DMC=n connect to DMC channel n (1-16)
|
||||
SET MT DMA=n connect to DMA channel n (1-4)
|
||||
|
||||
By default, the magtape controller is connected to the IO bus.
|
||||
|
||||
The magnetic tape controller implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
BUF 16 data buffer
|
||||
USEL 2 unit select
|
||||
BUSY 1 controller busy flag
|
||||
RDY 1 transfer ready flag
|
||||
ERR 1 error flag
|
||||
EOF 1 end of file flag
|
||||
EOR 1 (DMA/DMC) end of range
|
||||
DMA 1 transfer using DMA/DMC
|
||||
MDIRQ 1 motion done interrupt request
|
||||
INTREQ 1 device interrupt request
|
||||
ENABLE 1 device interrupt enable
|
||||
DBUF[0:65535] 8 transfer buffer
|
||||
BPTR 17 transfer buffer pointer
|
||||
BMAX 17 transfer size (reads)
|
||||
CTIME 24 start/stop time
|
||||
XTIME 24 delay between words
|
||||
POS[0:3] 32 position, units 0-3
|
||||
STOP_IOE 1 stop on I/O error
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error processed as
|
||||
|
||||
not attached tape not ready; if STOP_IOE, stop
|
||||
|
||||
end of file bad tape
|
||||
|
||||
OS I/O error parity error; if STOP_IOE, stop
|
||||
|
||||
2.6 4623/4651/4720 Disk Packs (DP)
|
||||
|
||||
The disk controller can be configured as a 4623, supporting 10 surface
|
||||
disk packs; a 4651, supporting 2 surface disk packs; or a 4720, supporting
|
||||
20 surface disk packs:
|
||||
|
||||
SET DP 4623 controller is 4623
|
||||
SET DP 4651 controller is 4651
|
||||
SET DP 4720 controller is 4720
|
||||
|
||||
The default is 4651. All disk packs on the controller must be of the
|
||||
same type. Units can be set ONLINE or OFFLINE, and WRITEENABLED or
|
||||
write LOCKED.
|
||||
|
||||
The disk pack controller can be connected to a DMC channel or a DMA
|
||||
channel; it cannot be connected to the IO bus:
|
||||
|
||||
SET DP DMC=n connect to DMC channel n (1-16)
|
||||
SET DP DMA=n connect to DMA channel n (1-4)
|
||||
|
||||
The disk pack controller supports variable track formatting. Each track
|
||||
can contain between 1 and 103 records, with a minimum size of 1 word and
|
||||
a maximum size of 1893 words. Record addresses are unconstrained. The
|
||||
simulator provides a command to perform a simple, fixed record size format
|
||||
of a new disk:
|
||||
|
||||
SET DPn FORMAT=k format unit n with k words per record
|
||||
SET -R DPn FORMAT=k format unit n with k records per track
|
||||
|
||||
Record addresses can either be geometric (cylinder/track/sector) or simple
|
||||
sequential starting from 0:
|
||||
|
||||
SET DPn FORMAT=k format with geometric record addresses
|
||||
SET -S DPn FORMAT=k format with sequential record addresses
|
||||
|
||||
Geometric address have the cylinder number in bits<1:8>, the head number in
|
||||
bits<9:13>, and the sector number in bits <14:16>.
|
||||
|
||||
A summary of the current format, and its validity, can be obtained with
|
||||
the command:
|
||||
|
||||
SHOW DPn FORMAT display format of unit n
|
||||
|
||||
To accomodate the variable formatting, each track is allocated 2048 words
|
||||
in the data file. A record consists of a three word header, the data, and
|
||||
a five word trailer:
|
||||
|
||||
word 0 record length in words, not including header/trailer
|
||||
word 1 record address
|
||||
word 2 number of extension words used (0-4)
|
||||
word 3 start of data record
|
||||
word 3+n-1 end of data record
|
||||
word 3+n..7+n record trailer: up to four extension words,
|
||||
plus checksum
|
||||
|
||||
A record can "grow" by up to four words without disrupting the track formatting;
|
||||
writing more than four extra words destroys the formatting of the rest of the
|
||||
track and causes a simulator error.
|
||||
|
||||
The disk pack controller implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
STA 16 status
|
||||
BUF 16 data buffer
|
||||
FNC 4 controller function
|
||||
CW1 16 command word 1
|
||||
CW2 16 command word 2
|
||||
CSUM 16 record checksum
|
||||
BUSY 1 controller busy
|
||||
RDY 1 transfer ready
|
||||
EOR 1 (DMA/DMC) end of range
|
||||
DEFINT 1 seek deferred interrupt pending
|
||||
INTREQ 1 interrupt request
|
||||
ENABLE 1 interrupt enable
|
||||
TBUF[0:2047] 16 track buffer
|
||||
RPTR 11 pointer to start of record in track buffer
|
||||
WPTR 11 pointer to current word in record
|
||||
BCTR 15 bit counter for formatting
|
||||
STIME 24 seek time, per cylinder
|
||||
XTIME 24 transfer time, per word
|
||||
BTIME 24 controller busy time
|
||||
|
||||
Error handling is as follows:
|
||||
|
||||
error processed as
|
||||
|
||||
not attached pack off line; if STOP_IOE, stop
|
||||
|
||||
end of file ignored
|
||||
|
||||
OS I/O error data error; if STOP_IOE, stop
|
||||
|
||||
2.7 Symbolic Display and Input
|
||||
|
||||
The H316/H516 simulator implements symbolic display and input. Display is
|
||||
controlled by command line switches:
|
||||
|
|
975
H316/h316_dp.c
Normal file
|
@ -0,0 +1,975 @@
|
|||
/* h316_dp.c: Honeywell 4623, 4651, 4720 disk simulator
|
||||
|
||||
Copyright (c) 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.
|
||||
|
||||
dp 4623 disk subsystem
|
||||
4651 disk subsystem
|
||||
4720 disk subsystem
|
||||
|
||||
The Honeywell disks have the unique characteristic of supporting variable
|
||||
formatting, on a per track basis. To accomodate this, each track is
|
||||
simulated as 2048 words, divided into records. (2048 words accomodates
|
||||
the largest record of 1891 + 8 overhead words.) A record is structured
|
||||
as follows:
|
||||
|
||||
word 0 record length n (0 = end of track)
|
||||
word 1 record address (16b, uninterpreted by the simulator)
|
||||
word 2 record extension (0 to 4 words of permitted 'overwrite')
|
||||
word 3 first data word
|
||||
:
|
||||
word 3+n-1 last data word
|
||||
word 3+n checksum word
|
||||
word 4+n first extension word
|
||||
:
|
||||
word 7+n fourth extension word
|
||||
word 8+n start of next record
|
||||
|
||||
Formatting is done in two ways. The SET DPn FORMAT=k command formats
|
||||
unit n with k records per track, each record having the maximum allowable
|
||||
record size and a standard record address; or with k words per record.
|
||||
Alternately, the simulator allows programmatic formating. When a track
|
||||
is formated, the program supplies record parameters as follows:
|
||||
|
||||
word 0 record address
|
||||
words 1-n data words
|
||||
word n+1 gap size in bits
|
||||
|
||||
To make this work, the simulator tracks the consumption of bits in the
|
||||
track, against the track capacity in bits. Bit consumption is:
|
||||
|
||||
16.5 * 16 for overhead (including address and checksum)
|
||||
n * 16 for data
|
||||
'gap' for gap, which must be at least 5% of the record length
|
||||
*/
|
||||
|
||||
#include "h316_defs.h"
|
||||
#include <math.h>
|
||||
|
||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
||||
#define FNC u3 /* saved function */
|
||||
#define CYL u4 /* actual cylinder */
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write prot */
|
||||
#define DP_TRKLEN 2048 /* track length, words */
|
||||
#define DP_NUMDRV 8 /* max # drives */
|
||||
#define DP_NUMTYP 3 /* # controller types */
|
||||
|
||||
/* Record format */
|
||||
|
||||
#define REC_LNT 0 /* length (unextended) */
|
||||
#define REC_ADDR 1 /* address */
|
||||
#define REC_EXT 2 /* extension (0-4) */
|
||||
#define REC_DATA 3 /* start of data */
|
||||
#define REC_OVHD 8 /* overhead words */
|
||||
#define REC_MAXEXT 4 /* maximum extension */
|
||||
#define REC_OVHD_WRDS 16.5 /* 16.5 words */
|
||||
#define REC_OVHD_BITS ((16 * 16) + 8)
|
||||
|
||||
/* Status word, ^ = dynamic */
|
||||
|
||||
#define STA_BUSY 0100000 /* busy */
|
||||
#define STA_RDY 0040000 /* ready */
|
||||
#define STA_ADRER 0020000 /* address error */
|
||||
#define STA_FMTER 0010000 /* format error */
|
||||
#define STA_HNLER 0004000 /* heads not loaded (NI) */
|
||||
#define STA_OFLER 0002000 /* offline */
|
||||
#define STA_SEKER 0001000 /* seek error */
|
||||
#define STA_MBZ 0000700
|
||||
#define STA_WPRER 0000040 /* write prot error */
|
||||
#define STA_UNSER 0000020 /* unsafe */
|
||||
#define STA_CSMER 0000010 /* checksum error */
|
||||
#define STA_DTRER 0000004 /* transfer rate error */
|
||||
#define STA_ANYER 0000002 /* any error^ */
|
||||
#define STA_EOR 0000001 /* end of record */
|
||||
#define STA_ALLERR (STA_ADRER|STA_FMTER|STA_HNLER|STA_OFLER|STA_SEKER|\
|
||||
STA_WPRER|STA_UNSER|STA_DTRER)
|
||||
|
||||
/* Functions */
|
||||
|
||||
#define FNC_SK0 0000 /* recalibrate */
|
||||
#define FNC_SEEK 0001 /* seek */
|
||||
#define FNC_RCA 0002 /* read current */
|
||||
#define FNC_UNL 0004 /* unload */
|
||||
#define FNC_FMT 0005 /* format */
|
||||
#define FNC_RW 0006 /* read/write */
|
||||
#define FNC_STOP 0010 /* stop format */
|
||||
#define FNC_RDS 0011 /* read status */
|
||||
#define FNC_DMA 0013 /* DMA/DMC */
|
||||
#define FNC_AKI 0014 /* acknowledge intr */
|
||||
#define FNC_IOBUS 0017 /* IO bus */
|
||||
#define FNC_2ND 0020 /* second state */
|
||||
#define FNC_3RD 0040 /* third state */
|
||||
#define FNC_4TH 0060 /* fourth state */
|
||||
#define FNC_5TH 0100 /* fifth state */
|
||||
|
||||
/* Command word 1 */
|
||||
|
||||
#define CW1_RW 0100000 /* read/write */
|
||||
#define CW1_DIR 0000400 /* seek direction */
|
||||
#define CW1_V_UNIT 11 /* unit select */
|
||||
#define CW1_V_HEAD 6 /* head select */
|
||||
#define CW1_V_OFFS 0 /* seek offset */
|
||||
#define CW1_GETUNIT(x) (((x) >> CW1_V_UNIT) & dp_tab[dp_ctype].umsk)
|
||||
#define CW1_GETHEAD(x) (((x) >> CW1_V_HEAD) & dp_tab[dp_ctype].hmsk)
|
||||
#define CW1_GETOFFS(x) (((x) >> CW1_V_OFFS) & dp_tab[dp_ctype].cmsk)
|
||||
|
||||
/* OTA states */
|
||||
|
||||
#define OTA_NOP 0 /* normal */
|
||||
#define OTA_CW1 1 /* expecting CW1 */
|
||||
#define OTA_CW2 2 /* expecting CW2 */
|
||||
|
||||
/* Transfer state */
|
||||
|
||||
#define XIP_UMSK 007 /* unit mask */
|
||||
#define XIP_SCHED 010 /* scheduled */
|
||||
#define XIP_WRT 020 /* write */
|
||||
#define XIP_FMT 040 /* format */
|
||||
|
||||
/* The H316/516 disk emulator supports three disk controllers:
|
||||
|
||||
controller units cylinders surfaces data words per track
|
||||
|
||||
4651 4 203 2 1908.25
|
||||
4623 8 203 10 1816.5
|
||||
4720 8 203 20 1908.25
|
||||
|
||||
Disk types may not be intermixed on the same controller.
|
||||
*/
|
||||
|
||||
#define TYPE_4651 0
|
||||
#define UNIT_4651 4
|
||||
#define CYL_4651 203
|
||||
#define SURF_4651 2
|
||||
#define WRDS_4651 1908.25
|
||||
#define UMSK_4651 0003
|
||||
#define HMSK_4651 0001
|
||||
#define CMSK_4651 0377
|
||||
#define CAP_4651 (CYL_4651*SURF_4651*DP_TRKLEN)
|
||||
|
||||
#define TYPE_4623 1
|
||||
#define UNIT_4623 8
|
||||
#define CYL_4623 203
|
||||
#define SURF_4623 10
|
||||
#define WRDS_4623 1816.5
|
||||
#define UMSK_4623 0007
|
||||
#define HMSK_4623 0017
|
||||
#define CMSK_4623 0377
|
||||
#define CAP_4623 (CYL_4623*SURF_4623*DP_TRKLEN)
|
||||
|
||||
#define TYPE_4720 2
|
||||
#define UNIT_4720 8
|
||||
#define CYL_4720 203
|
||||
#define SURF_4720 20
|
||||
#define WRDS_4720 1908.25
|
||||
#define UMSK_4720 0007
|
||||
#define HMSK_4720 0037
|
||||
#define CMSK_4720 0377
|
||||
#define CAP_4720 (CYL_4720*SURF_4720*DP_TRKLEN)
|
||||
|
||||
struct drvtyp {
|
||||
char *name;
|
||||
uint32 numu;
|
||||
uint32 cyl;
|
||||
uint32 surf;
|
||||
uint32 cap;
|
||||
uint32 umsk;
|
||||
uint32 hmsk;
|
||||
uint32 cmsk;
|
||||
float wrds; };
|
||||
|
||||
#define DP_DRV(d) \
|
||||
#d, \
|
||||
UNIT_##d, CYL_##d, SURF_##d, CAP_##d, \
|
||||
UMSK_##d, HMSK_##d, CMSK_##d, WRDS_##d
|
||||
|
||||
static struct drvtyp dp_tab[] = {
|
||||
{ DP_DRV (4651) },
|
||||
{ DP_DRV (4623) },
|
||||
{ DP_DRV (4720) } };
|
||||
|
||||
extern int32 dev_int, dev_enb, chan_req;
|
||||
extern int32 stop_inst;
|
||||
extern uint32 dma_ad[DMA_MAX];
|
||||
extern int32 sim_switches;
|
||||
|
||||
uint32 dp_cw1 = 0; /* cmd word 1 */
|
||||
uint32 dp_cw2 = 0; /* cmd word 2 */
|
||||
uint32 dp_fnc = 0; /* saved function */
|
||||
uint32 dp_buf = 0; /* buffer */
|
||||
uint32 dp_otas = 0; /* state */
|
||||
uint32 dp_sta = 0; /* status */
|
||||
uint32 dp_defint = 0; /* deferred seek int */
|
||||
uint32 dp_ctype = TYPE_4651; /* controller type */
|
||||
uint32 dp_dma = 0; /* DMA/DMC */
|
||||
uint32 dp_eor = 0; /* end of range */
|
||||
uint32 dp_xip = 0; /* transfer in prog */
|
||||
uint32 dp_csum = 0; /* parity checksum */
|
||||
uint32 dp_rptr = 0; /* start of record */
|
||||
uint32 dp_wptr = 0; /* word ptr in record */
|
||||
uint32 dp_bctr = 0; /* format bit cntr */
|
||||
uint32 dp_gap = 0; /* format gap size */
|
||||
uint32 dp_stopioe = 1; /* stop on error */
|
||||
int32 dp_stime = 1000; /* seek per cylinder */
|
||||
int32 dp_xtime = 10; /* xfer per word */
|
||||
int32 dp_btime = 30; /* busy time */
|
||||
uint16 dpxb[DP_TRKLEN]; /* track buffer */
|
||||
|
||||
int32 dpio (int32 inst, int32 fnc, int32 dat, int32 dev);
|
||||
t_stat dp_svc (UNIT *uptr);
|
||||
t_stat dp_reset (DEVICE *dptr);
|
||||
t_stat dp_attach (UNIT *uptr, char *cptr);
|
||||
t_stat dp_settype (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat dp_showtype (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
t_stat dp_go (uint32 dma);
|
||||
t_stat dp_go1 (uint32 dat);
|
||||
t_stat dp_go2 (uint32 dat);
|
||||
t_stat dp_rdtrk (UNIT *uptr, uint16 *buf, uint32 cyl, uint32 hd);
|
||||
t_stat dp_wrtrk (UNIT *uptr, uint16 *buf, uint32 cyl, uint32 hd);
|
||||
t_bool dp_findrec (uint32 addr);
|
||||
t_stat dp_wrwd (UNIT *uptr, uint32 dat);
|
||||
t_stat dp_wrdone (UNIT *uptr, uint32 flg);
|
||||
t_stat dp_done (uint32 req, uint32 f);
|
||||
t_stat dp_setformat (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat dp_showformat (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
|
||||
/* 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 = { DP, DMC1, 1, &dpio };
|
||||
|
||||
UNIT dp_unit[] = {
|
||||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, CAP_4651) },
|
||||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, CAP_4651) },
|
||||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, CAP_4651) },
|
||||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, CAP_4651) },
|
||||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, CAP_4651) },
|
||||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, CAP_4651) },
|
||||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, CAP_4651) },
|
||||
{ UDATA (&dp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+
|
||||
UNIT_ROABLE, CAP_4651) } };
|
||||
|
||||
REG dp_reg[] = {
|
||||
{ ORDATA (STA, dp_sta, 16) },
|
||||
{ ORDATA (BUF, dp_buf, 16) },
|
||||
{ ORDATA (FNC, dp_fnc, 4) },
|
||||
{ ORDATA (CW1, dp_cw1, 16) },
|
||||
{ ORDATA (CW2, dp_cw2, 16) },
|
||||
{ ORDATA (CSUM, dp_csum, 16) },
|
||||
{ FLDATA (BUSY, dp_sta, 15) },
|
||||
{ FLDATA (RDY, dp_sta, 14) },
|
||||
{ FLDATA (EOR, dp_eor, 0) },
|
||||
{ FLDATA (DEFINT, dp_defint, 0) },
|
||||
{ FLDATA (INTREQ, dev_int, INT_V_DP) },
|
||||
{ FLDATA (ENABLE, dev_enb, INT_V_DP) },
|
||||
{ BRDATA (TBUF, dpxb, 8, 16, DP_TRKLEN) },
|
||||
{ ORDATA (RPTR, dp_rptr, 11), REG_RO },
|
||||
{ ORDATA (WPTR, dp_wptr, 11), REG_RO },
|
||||
{ ORDATA (BCTR, dp_bctr, 15), REG_RO },
|
||||
{ ORDATA (GAP, dp_gap, 16), REG_RO },
|
||||
{ DRDATA (STIME, dp_stime, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (XTIME, dp_xtime, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (BTIME, dp_btime, 24), REG_NZ + PV_LEFT },
|
||||
{ FLDATA (CTYPE, dp_ctype, 0), REG_HRO },
|
||||
{ URDATA (UCYL, dp_unit[0].CYL, 10, 8, 0,
|
||||
DP_NUMDRV, PV_LEFT | REG_HRO) },
|
||||
{ URDATA (UFNC, dp_unit[0].FNC, 8, 7, 0,
|
||||
DP_NUMDRV, REG_HRO) },
|
||||
{ URDATA (CAPAC, dp_unit[0].capac, 10, T_ADDR_W, 0,
|
||||
DP_NUMDRV, PV_LEFT | REG_HRO) },
|
||||
{ ORDATA (OTAS, dp_otas, 2), REG_HRO },
|
||||
{ ORDATA (XIP, dp_xip, 6), REG_HRO },
|
||||
{ ORDATA (CHAN, dp_dib.chan, 5), REG_HRO },
|
||||
{ FLDATA (STOP_IOE, dp_stopioe, 0) },
|
||||
{ NULL } };
|
||||
|
||||
MTAB dp_mod[] = {
|
||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, TYPE_4623, NULL, "4623",
|
||||
&dp_settype, NULL, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, TYPE_4651, NULL, "4651",
|
||||
&dp_settype, NULL, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, TYPE_4720, NULL, "4720",
|
||||
&dp_settype, NULL, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 0, "TYPE", NULL,
|
||||
NULL, &dp_showtype, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, NULL, "DMC",
|
||||
&io_set_dmc, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, NULL, "DMA",
|
||||
&io_set_dma, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "CHANNEL", NULL,
|
||||
NULL, &io_show_chan, NULL },
|
||||
{ MTAB_XTD|MTAB_VUN|MTAB_NMO, 0, "FORMAT", "FORMAT",
|
||||
&dp_setformat, &dp_showformat, NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE dp_dev = {
|
||||
"DP", dp_unit, dp_reg, dp_mod,
|
||||
DP_NUMDRV, 8, 24, 1, 8, 16,
|
||||
NULL, NULL, &dp_reset,
|
||||
NULL, &dp_attach, NULL,
|
||||
&dp_dib, DEV_DISABLE };
|
||||
|
||||
/* IOT routines */
|
||||
|
||||
int32 dpio (int32 inst, int32 fnc, int32 dat, int32 dev)
|
||||
{
|
||||
int32 ch = dp_dib.chan - 1; /* DMA/DMC chan */
|
||||
int32 u;
|
||||
UNIT *uptr;
|
||||
|
||||
switch (inst) { /* case on opcode */
|
||||
case ioOCP: /* OCP */
|
||||
switch (fnc) { /* case on function */
|
||||
case FNC_SK0: case FNC_SEEK: case FNC_RCA: /* data transfer */
|
||||
case FNC_UNL: case FNC_FMT: case FNC_RW:
|
||||
dp_go (fnc); /* if !busy, start */
|
||||
break;
|
||||
case FNC_STOP: /* stop transfer */
|
||||
if (dp_xip) { /* transfer in prog? */
|
||||
uptr = dp_dev.units + (dp_xip & XIP_UMSK); /* get unit */
|
||||
sim_cancel (uptr); /* stop operation */
|
||||
if (dp_xip & (XIP_WRT|XIP_FMT)) /* write or format? */
|
||||
dp_wrdone (uptr, /* write track */
|
||||
((dp_xip & XIP_FMT) && /* check fmt state */
|
||||
(uptr->FNC != (FNC_FMT|FNC_2ND)))?
|
||||
STA_DTRER: 0);
|
||||
else dp_done (1, dp_csum? STA_CSMER: 0);/* no, just clr busy */
|
||||
dp_xip = 0; } /* clear flag */
|
||||
dp_otas = OTA_NOP; /* clear state */
|
||||
dp_sta = dp_sta & ~STA_BUSY; /* clear busy */
|
||||
break;
|
||||
case FNC_RDS: /* read status */
|
||||
if (dp_sta & STA_BUSY) return dat; /* ignore if busy */
|
||||
dp_sta = (dp_sta | STA_RDY) & ~(STA_MBZ | STA_ANYER);
|
||||
if (dp_sta & STA_ALLERR) dp_sta = dp_sta | STA_ANYER;
|
||||
dp_buf = dp_sta;
|
||||
if (dp_dma && Q_DMA (ch)) SET_CH_REQ (ch); /* DMA? set chan req */
|
||||
break;
|
||||
case FNC_DMA: /* set DMA/DMC */
|
||||
dp_dma = 1;
|
||||
break;
|
||||
case FNC_IOBUS: /* set IO bus */
|
||||
dp_dma = 0;
|
||||
break;
|
||||
case FNC_AKI: /* ack intr */
|
||||
CLR_INT (INT_DP);
|
||||
break;
|
||||
default: /* undefined */
|
||||
return IOBADFNC (dat); }
|
||||
break;
|
||||
|
||||
|
||||
case ioINA: /* INA */
|
||||
if (fnc) return IOBADFNC (dat); /* fnc 0 only */
|
||||
if (dp_sta & STA_RDY) { /* ready? */
|
||||
dp_sta = dp_sta & ~STA_RDY; /* clear ready */
|
||||
return IOSKIP (dat | dp_buf); } /* ret buf, skip */
|
||||
break;
|
||||
|
||||
case ioOTA: /* OTA */
|
||||
if (fnc) return IOBADFNC (dat); /* fnc 0 only */
|
||||
if (dp_sta & STA_RDY) { /* ready? */
|
||||
dp_sta = dp_sta & ~STA_RDY; /* clear ready */
|
||||
dp_buf = dat; /* store buf */
|
||||
if (dp_otas == OTA_CW1) dp_go1 (dat); /* expecting CW1? */
|
||||
else if (dp_otas == OTA_CW2) dp_go2 (dat); /* expecting CW2? */
|
||||
return IOSKIP (dat); }
|
||||
break;
|
||||
case ioSKS: /* SKS */
|
||||
u = 7; /* assume unit 7 */
|
||||
switch (fnc) {
|
||||
case 000: /* ready */
|
||||
if (dp_sta & STA_RDY) return IOSKIP (dat);
|
||||
break;
|
||||
case 001: /* !interrupting */
|
||||
if (!TST_INTREQ (INT_DP)) return IOSKIP (dat);
|
||||
break;
|
||||
case 002: /* operational */
|
||||
if (!(dp_sta & (STA_BUSY | STA_ALLERR))) return IOSKIP (dat);
|
||||
break;
|
||||
case 003: /* !error */
|
||||
if (!(dp_sta & STA_ALLERR)) return IOSKIP (dat);
|
||||
break;
|
||||
case 004: /* !busy */
|
||||
if (!(dp_sta & STA_BUSY)) return IOSKIP (dat);
|
||||
break;
|
||||
case 011: case 012: case 013: /* !not seeking 0-6 */
|
||||
case 014: case 015: case 016: case 017:
|
||||
u = fnc - 011;
|
||||
case 007: /* !not seeking 7 */
|
||||
if (!sim_is_active (&dp_unit[u]) || /* quiescent? */
|
||||
(dp_unit[u].FNC & 017) != FNC_SEEK) return IOSKIP (dat);
|
||||
break; }
|
||||
break;
|
||||
case ioEND: /* end of range */
|
||||
dp_eor = 1; /* transfer done */
|
||||
break; }
|
||||
return dat;
|
||||
}
|
||||
|
||||
|
||||
/* Start new operation - recal, seek, read address, format, read/write */
|
||||
|
||||
t_stat dp_go (uint32 fnc)
|
||||
{
|
||||
int32 ch = dp_dib.chan - 1; /* DMA/DMC chan */
|
||||
|
||||
if (dp_sta & STA_BUSY) return SCPE_OK; /* ignore if busy */
|
||||
dp_fnc = fnc; /* save function */
|
||||
dp_xip = 0; /* transfer not started */
|
||||
dp_eor = 0; /* not end of range */
|
||||
dp_csum = 0; /* init checksum */
|
||||
dp_otas = OTA_CW1; /* expect CW1 */
|
||||
dp_sta = (dp_sta | STA_BUSY | STA_RDY) & ~(STA_ALLERR | STA_EOR);
|
||||
if (dp_dma && Q_DMA (ch)) { /* DMA and DMA channel? */
|
||||
SET_CH_REQ (ch); /* set channel request */
|
||||
dma_ad[ch] = dma_ad[ch] & ~DMA_IN; } /* force output */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Process command word 1 - recal, seek, read address, format, read/write */
|
||||
|
||||
t_stat dp_go1 (uint32 dat)
|
||||
{
|
||||
int32 ch = dp_dib.chan - 1; /* DMA/DMC chan */
|
||||
uint32 u = CW1_GETUNIT (dat);
|
||||
UNIT *uptr = dp_dev.units + u;
|
||||
|
||||
dp_cw1 = dat; /* store CW1 */
|
||||
dp_otas = OTA_NOP; /* assume no CW2 */
|
||||
uptr->FNC = dp_fnc;
|
||||
if (sim_is_active (uptr)) /* still seeking? */
|
||||
return dp_done (1, STA_UNSER); /* unsafe */
|
||||
if (!(uptr->flags & UNIT_ATT)) /* not attached? */
|
||||
return dp_done (1, STA_OFLER); /* offline */
|
||||
switch (dp_fnc) { /* case on function */
|
||||
case FNC_SEEK: /* seek */
|
||||
case FNC_SK0: /* recalibrate */
|
||||
case FNC_UNL: /* unload */
|
||||
sim_activate (uptr, dp_btime); /* quick timeout */
|
||||
break;
|
||||
case FNC_FMT: /* format */
|
||||
if (uptr->flags & UNIT_WPRT) /* write protect? */
|
||||
return dp_done (1, STA_WPRER); /* stop now */
|
||||
case FNC_RCA: /* read current addr */
|
||||
dp_xip = u | XIP_SCHED; /* operation started */
|
||||
sim_activate (uptr, dp_xtime * 10); /* rotation timeout */
|
||||
break;
|
||||
case FNC_RW: /* read/write */
|
||||
dp_otas = OTA_CW2; /* expect CW2 */
|
||||
dp_sta = dp_sta | STA_RDY; /* set ready */
|
||||
if (dp_dma && Q_DMA (ch)) SET_CH_REQ (ch); /* DMA? set chan request */
|
||||
break; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Process command word 2 - read/write only */
|
||||
|
||||
t_stat dp_go2 (uint32 dat)
|
||||
{
|
||||
uint32 u = CW1_GETUNIT (dp_cw1);
|
||||
UNIT *uptr = dp_dev.units + u;
|
||||
|
||||
dp_cw2 = dat; /* store CW2 */
|
||||
dp_otas = OTA_NOP; /* normal state */
|
||||
sim_activate (uptr, dp_xtime * 10); /* rotation timeout */
|
||||
dp_xip = u | XIP_SCHED; /* operation started */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Unit service */
|
||||
|
||||
t_stat dp_svc (UNIT *uptr)
|
||||
{
|
||||
int32 dcyl = 0; /* assume recalibrate */
|
||||
int32 ch = dp_dib.chan - 1; /* DMA/DMC chan */
|
||||
uint32 h = CW1_GETHEAD (dp_cw1); /* head */
|
||||
int32 st;
|
||||
uint32 i, offs, lnt, ming, tpos;
|
||||
t_stat r;
|
||||
|
||||
if (!(uptr->flags & UNIT_ATT)) { /* not attached? */
|
||||
dp_done (1, STA_OFLER); /* offline */
|
||||
IORETURN (dp_stopioe, SCPE_UNATT); }
|
||||
|
||||
switch (uptr->FNC) { /* case on function */
|
||||
case FNC_SEEK: /* seek, need cyl */
|
||||
offs = CW1_GETOFFS (dp_cw1); /* get offset */
|
||||
if (dp_cw1 & CW1_DIR) dcyl = uptr->CYL - offs; /* get desired cyl */
|
||||
else dcyl = uptr->CYL + offs;
|
||||
if ((offs == 0) || (dcyl < 0) ||
|
||||
(dcyl >= (int32) dp_tab[dp_ctype].cyl))
|
||||
return dp_done (1, STA_SEKER); /* bad seek? */
|
||||
case FNC_SK0: /* recalibrate */
|
||||
dp_sta = dp_sta & ~STA_BUSY; /* clear busy */
|
||||
uptr->FNC = FNC_SEEK | FNC_2ND; /* next state */
|
||||
st = (abs (dcyl - uptr->CYL)) * dp_stime; /* schedule seek */
|
||||
if (st == 0) st = dp_stime;
|
||||
uptr->CYL = dcyl; /* put on cylinder */
|
||||
sim_activate (uptr, st);
|
||||
return SCPE_OK;
|
||||
|
||||
case FNC_SEEK | FNC_2ND: /* seek, 2nd state */
|
||||
if (dp_sta & STA_BUSY) dp_defint = 1; /* busy? queue intr */
|
||||
else SET_INT (INT_DP); /* no, req intr */
|
||||
return SCPE_OK;
|
||||
|
||||
case FNC_UNL: /* unload */
|
||||
detach_unit (uptr); /* detach unit */
|
||||
return dp_done (0, 0); /* clear busy, no intr */
|
||||
|
||||
case FNC_RCA: /* read current addr */
|
||||
if (h >= dp_tab[dp_ctype].surf) /* invalid head? */
|
||||
return dp_done (1, STA_ADRER); /* error */
|
||||
if (r = dp_rdtrk (uptr, dpxb, uptr->CYL, h)) /* get track; error? */
|
||||
return r;
|
||||
dp_rptr = 0; /* init rec ptr */
|
||||
if (dpxb[dp_rptr + REC_LNT] == 0) /* unformated? */
|
||||
return dp_done (1, STA_ADRER); /* error */
|
||||
tpos = (uint32) (fmod (sim_gtime () / (double) dp_xtime, DP_TRKLEN));
|
||||
do { /* scan down track */
|
||||
dp_buf = dpxb[dp_rptr + REC_ADDR]; /* get rec addr */
|
||||
dp_rptr = dp_rptr + dpxb[dp_rptr + REC_LNT] + REC_OVHD; }
|
||||
while ((dp_rptr < tpos) && (dpxb[dp_rptr + REC_LNT] != 0));
|
||||
if (dp_dma) { /* DMA/DMC? */
|
||||
if (Q_DMA (ch)) /* DMA? */
|
||||
dma_ad[ch] = dma_ad[ch] | DMA_IN; /* force input */
|
||||
SET_CH_REQ (ch); } /* request chan */
|
||||
return dp_done (1, STA_RDY); /* clr busy, set rdy */
|
||||
|
||||
/* Formating takes place in five states:
|
||||
|
||||
init - clear track buffer, start at first record
|
||||
address - store address word
|
||||
data - store data word(s) until end of range
|
||||
pause - wait for gap word or stop command
|
||||
gap - validate gap word, advance to next record
|
||||
|
||||
Note that formating is stopped externally by an OCP command; the
|
||||
track buffer is flushed at that point. If the stop does not occur
|
||||
in the proper state (gap word received), a format error occurs.
|
||||
*/
|
||||
|
||||
case FNC_FMT: /* format */
|
||||
for (i = 0; i < DP_TRKLEN; i++) dpxb[i] = 0; /* clear track */
|
||||
dp_xip = dp_xip | XIP_FMT; /* format in progress */
|
||||
dp_rptr = 0; /* init record ptr */
|
||||
dp_gap = 0; /* no gap before first */
|
||||
dp_bctr = (uint32) (16.0 * dp_tab[dp_ctype].wrds); /* init bit cntr */
|
||||
uptr->FNC = uptr->FNC | FNC_2ND; /* address state */
|
||||
break; /* set up next word */
|
||||
|
||||
case FNC_FMT | FNC_2ND: /* format, address word */
|
||||
dp_wptr = 0; /* clear word ptr */
|
||||
if (dp_bctr < (dp_gap + REC_OVHD_BITS + 16)) /* room for gap, record? */
|
||||
return dp_wrdone (uptr, STA_FMTER); /* no, format error */
|
||||
dp_bctr = dp_bctr - dp_gap - REC_OVHD_BITS; /* charge for gap, ovhd */
|
||||
dpxb[dp_rptr + REC_ADDR] = dp_buf; /* store address */
|
||||
uptr->FNC = FNC_FMT | FNC_3RD; /* data state */
|
||||
if (dp_eor) { /* record done? */
|
||||
dp_eor = 0; /* clear for restart */
|
||||
if (dp_dma) SET_INT (INT_DP); } /* DMA/DMC? intr */
|
||||
break; /* set up next word */
|
||||
|
||||
case FNC_FMT | FNC_3RD: /* format, data word */
|
||||
if (dp_sta & STA_RDY) /* timing failure? */
|
||||
return dp_wrdone (uptr, STA_DTRER); /* write trk, err */
|
||||
else { /* no, have word */
|
||||
if (dp_bctr < 16) /* room for it? */
|
||||
return dp_wrdone (uptr, STA_FMTER); /* no, error */
|
||||
dp_bctr = dp_bctr - 16; /* charge for word */
|
||||
dp_csum = dp_csum ^ dp_buf; /* update checksum */
|
||||
dpxb[dp_rptr + REC_DATA + dp_wptr] = dp_buf;/* store word */
|
||||
dpxb[dp_rptr + REC_LNT]++; /* incr rec lnt */
|
||||
dp_wptr++; } /* incr word ptr */
|
||||
if (dp_eor) { /* record done? */
|
||||
dp_eor = 0; /* clear for restart */
|
||||
if (dp_dma) SET_INT (INT_DP); /* DMA/DMC? intr */
|
||||
dpxb[dp_rptr + REC_DATA + dp_wptr] = dp_csum; /* store checksum */
|
||||
uptr->FNC = uptr->FNC | FNC_4TH; /* pause state */
|
||||
sim_activate (uptr, 5 * dp_xtime); /* schedule pause */
|
||||
return SCPE_OK; } /* don't request word */
|
||||
break; /* set up next word */
|
||||
|
||||
case FNC_FMT | FNC_4TH: /* format, pause */
|
||||
uptr->FNC = FNC_FMT | FNC_5TH; /* gap state */
|
||||
break; /* request word */
|
||||
|
||||
case FNC_FMT | FNC_5TH: /* format, gap word */
|
||||
ming = ((16 * dp_wptr) + REC_OVHD_BITS) / 20; /* min 5% gap */
|
||||
if (dp_buf < ming) /* too small? */
|
||||
return dp_wrdone (uptr, STA_FMTER); /* yes, format error */
|
||||
dp_rptr = dp_rptr + dp_wptr + REC_OVHD; /* next record */
|
||||
uptr->FNC = FNC_FMT | FNC_2ND; /* address state */
|
||||
if (dp_eor) { /* record done? */
|
||||
dp_eor = 0; /* clear for restart */
|
||||
if (dp_dma) SET_INT (INT_DP); } /* DMA/DMC? intr */
|
||||
dp_gap = dp_buf; /* save gap */
|
||||
dp_csum = 0; /* clear checksum */
|
||||
break; /* set up next word */
|
||||
|
||||
/* Read and write take place in two states:
|
||||
|
||||
init - read track into buffer, find record, validate parameters
|
||||
data - (read) fetch data from buffer, stop on end of range
|
||||
- (write) write data into buffer, flush on end of range
|
||||
*/
|
||||
|
||||
case FNC_RW: /* read/write */
|
||||
if (h >= dp_tab[dp_ctype].surf) /* invalid head? */
|
||||
return dp_done (1, STA_ADRER); /* error */
|
||||
if (r = dp_rdtrk (uptr, dpxb, uptr->CYL, h)) /* get track; error? */
|
||||
return r;
|
||||
if (!dp_findrec (dp_cw2)) /* find rec; error? */
|
||||
return dp_done (1, STA_ADRER); /* address error */
|
||||
if ((dpxb[dp_rptr + REC_LNT] >= (DP_TRKLEN - dp_rptr - REC_OVHD)) ||
|
||||
(dpxb[dp_rptr + REC_EXT] >= REC_MAXEXT)) { /* bad lnt or ext? */
|
||||
dp_done (1, STA_UNSER); /* stop simulation */
|
||||
return STOP_DPFMT; } /* bad format */
|
||||
uptr->FNC = uptr->FNC | FNC_2ND; /* next state */
|
||||
if (dp_cw1 & CW1_RW) { /* write? */
|
||||
if (uptr->flags & UNIT_WPRT) /* write protect? */
|
||||
return dp_done (1, STA_WPRER); /* error */
|
||||
dp_xip = dp_xip | XIP_WRT; /* write in progress */
|
||||
dp_sta = dp_sta | STA_RDY; /* set ready */
|
||||
if (dp_dma) SET_CH_REQ (ch); } /* if DMA/DMC, req chan */
|
||||
else if (Q_DMA (ch)) /* read; DMA? */
|
||||
dma_ad[ch] = dma_ad[ch] | DMA_IN; /* force input */
|
||||
sim_activate (uptr, dp_xtime); /* schedule word */
|
||||
dp_wptr = 0; /* init word pointer */
|
||||
return SCPE_OK;
|
||||
|
||||
case FNC_RW | FNC_2ND: /* read/write, word */
|
||||
if (dp_cw1 & CW1_RW) { /* write? */
|
||||
if (dp_sta & STA_RDY) /* timing failure? */
|
||||
return dp_wrdone (uptr, STA_DTRER); /* yes, error */
|
||||
if (r = dp_wrwd (uptr, dp_buf)) return r; /* wr word, error? */
|
||||
if (dp_eor) { /* transfer done? */
|
||||
dpxb[dp_rptr + REC_DATA + dp_wptr] = dp_csum;
|
||||
return dp_wrdone (uptr, 0); } } /* clear busy, intr req */
|
||||
else { /* read? */
|
||||
lnt = dpxb[dp_rptr + REC_LNT] + dpxb[dp_rptr + REC_EXT];
|
||||
dp_buf = dpxb[dp_rptr + REC_DATA + dp_wptr];/* current word */
|
||||
dp_csum = dp_csum ^ dp_buf; /* xor to csum */
|
||||
if ((dp_wptr > lnt) || dp_eor) /* transfer done? */
|
||||
return dp_done (1,
|
||||
(dp_csum? STA_CSMER: 0) |
|
||||
((dp_wptr >= lnt)? STA_EOR: 0));
|
||||
if (dp_sta & STA_RDY) /* data buf full? */
|
||||
return dp_done (1, STA_DTRER); /* no, underrun */
|
||||
dp_wptr++; } /* next word */
|
||||
break;
|
||||
|
||||
default:
|
||||
return SCPE_IERR; } /* end case */
|
||||
|
||||
dp_sta = dp_sta | STA_RDY; /* set ready */
|
||||
if (dp_dma) SET_CH_REQ (ch); /* if DMA/DMC, req chan */
|
||||
sim_activate (uptr, dp_xtime); /* schedule word */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Read track */
|
||||
|
||||
t_stat dp_rdtrk (UNIT *uptr, uint16 *buf, uint32 c, uint32 h)
|
||||
{
|
||||
uint32 da = ((c * dp_tab[dp_ctype].surf) + h) * DP_TRKLEN;
|
||||
int32 l;
|
||||
|
||||
fseek (uptr->fileref, da * sizeof (uint16), SEEK_SET);
|
||||
l = fxread (buf, sizeof (uint16), DP_TRKLEN, uptr->fileref);
|
||||
for ( ; l < DP_TRKLEN; l++) buf[l] = 0;
|
||||
if (ferror (uptr->fileref)) {
|
||||
perror ("DP I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
dp_done (1, STA_UNSER);
|
||||
return SCPE_IOERR; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Write track */
|
||||
|
||||
t_stat dp_wrtrk (UNIT *uptr, uint16 *buf, uint32 c, uint32 h)
|
||||
{
|
||||
uint32 da = ((c * dp_tab[dp_ctype].surf) + h) * DP_TRKLEN;
|
||||
|
||||
fseek (uptr->fileref, da * sizeof (uint16), SEEK_SET);
|
||||
fxwrite (buf, sizeof (uint16), DP_TRKLEN, uptr->fileref);
|
||||
if (ferror (uptr->fileref)) {
|
||||
perror ("DP I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
dp_done (1, STA_UNSER);
|
||||
return SCPE_IOERR; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Find record; true if found, false if not found */
|
||||
|
||||
t_bool dp_findrec (uint32 addr)
|
||||
{
|
||||
dp_rptr = 0;
|
||||
|
||||
do { if (dpxb[dp_rptr + REC_LNT] == 0) return FALSE;
|
||||
if (dpxb[dp_rptr + REC_LNT] >= DP_TRKLEN) return TRUE;
|
||||
if (dpxb[dp_rptr + REC_ADDR] == addr) return TRUE;
|
||||
dp_rptr = dp_rptr + dpxb[dp_rptr + REC_LNT] + REC_OVHD; }
|
||||
while (dp_rptr < DP_TRKLEN);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Write next word to track buffer; return TRUE if ok, FALSE if next record trashed */
|
||||
|
||||
t_stat dp_wrwd (UNIT *uptr, uint32 dat)
|
||||
{
|
||||
uint32 lnt = dpxb[dp_rptr + REC_LNT];
|
||||
t_stat r;
|
||||
|
||||
dp_csum = dp_csum ^ dat;
|
||||
if (dp_wptr < lnt) {
|
||||
dpxb[dp_rptr + REC_DATA + dp_wptr++] = dat;
|
||||
return SCPE_OK; }
|
||||
if (dp_wptr < (lnt + REC_MAXEXT)) {
|
||||
dpxb[dp_rptr + REC_EXT]++;
|
||||
dpxb[dp_rptr + REC_DATA + dp_wptr++] = dat;
|
||||
return SCPE_OK; }
|
||||
dpxb[dp_rptr + REC_DATA + dp_wptr] = dp_csum; /* write csum */
|
||||
dpxb[dp_rptr + lnt + REC_OVHD] = 0; /* zap rest of track */
|
||||
if (r = dp_wrdone (uptr, STA_UNSER)) return r; /* dump track */
|
||||
return STOP_DPOVR;
|
||||
}
|
||||
|
||||
/* Write done, dump track, clear busy */
|
||||
|
||||
t_stat dp_wrdone (UNIT *uptr, uint32 flg)
|
||||
{
|
||||
dp_done (1, flg);
|
||||
return dp_wrtrk (uptr, dpxb, uptr->CYL, CW1_GETHEAD (dp_cw1));
|
||||
}
|
||||
|
||||
/* Clear busy, set errors, request interrupt if required */
|
||||
|
||||
t_stat dp_done (uint32 req, uint32 flg)
|
||||
{
|
||||
dp_xip = 0; /* clear xfr in prog */
|
||||
dp_sta = (dp_sta | flg) & ~(STA_BUSY | STA_MBZ); /* clear busy */
|
||||
if (req || dp_defint) SET_INT (INT_DP); /* if req, set intr */
|
||||
dp_defint = 0; /* clr def intr */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat dp_reset (DEVICE *dptr)
|
||||
{
|
||||
int32 i;
|
||||
|
||||
dp_fnc = 0;
|
||||
dp_cw1 = 0;
|
||||
dp_cw2 = 0;
|
||||
dp_sta = 0;
|
||||
dp_buf = 0;
|
||||
dp_xip = 0;
|
||||
dp_eor = 0;
|
||||
dp_dma = 0;
|
||||
dp_csum = 0;
|
||||
dp_rptr = 0;
|
||||
dp_wptr = 0;
|
||||
dp_bctr = 0;
|
||||
dp_gap = 0;
|
||||
dp_defint = 0;
|
||||
for (i = 0; i < DP_NUMDRV; i++) { /* loop thru drives */
|
||||
sim_cancel (&dp_unit[i]); /* cancel activity */
|
||||
dp_unit[i].FNC = 0; /* clear function */
|
||||
dp_unit[i].CYL = 0; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Attach routine, test formating */
|
||||
|
||||
t_stat dp_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
t_stat r;
|
||||
r = attach_unit (uptr, cptr);
|
||||
if (r != SCPE_OK) return r;
|
||||
return dp_showformat (stdin, uptr, 0, NULL);
|
||||
}
|
||||
|
||||
/* Set controller type */
|
||||
|
||||
t_stat dp_settype (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
int32 i;
|
||||
|
||||
if ((val < 0) || (val >= DP_NUMTYP) || (cptr != NULL)) return SCPE_ARG;
|
||||
for (i = 0; i < DP_NUMDRV; i++) {
|
||||
if (dp_unit[i].flags & UNIT_ATT) return SCPE_ALATT; }
|
||||
for (i = 0; i < DP_NUMDRV; i++)
|
||||
dp_unit[i].capac = dp_tab[val].cap;
|
||||
dp_ctype = val;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Show controller type */
|
||||
|
||||
t_stat dp_showtype (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
if (dp_ctype >= DP_NUMTYP) return SCPE_IERR;
|
||||
fprintf (st, "%s", dp_tab[dp_ctype].name);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Set drive format
|
||||
|
||||
There is no standard format for record addresses. This routine
|
||||
provides two schemes:
|
||||
|
||||
-S sequential addressing (starting from 0)
|
||||
default geometric addressing (8b: cylinder, 5b: head, 3b: sector)
|
||||
|
||||
This routine also supports formatting by record count or word count:
|
||||
|
||||
-R argument is records per track
|
||||
default argument is words per record
|
||||
|
||||
The relationship between words per record (W), bits per track (B),
|
||||
and records per track (R), is as follows:
|
||||
|
||||
W = (B / (R + ((R - 1) / 20))) - 16.5
|
||||
|
||||
where (R - 1) / 20 is the "5% gap" and 16.5 is the overhead, in words,
|
||||
per record.
|
||||
*/
|
||||
|
||||
t_stat dp_setformat (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
uint32 h, c, cntr, rptr;
|
||||
int32 i, nr, nw, inp;
|
||||
uint16 tbuf[DP_TRKLEN];
|
||||
float finp;
|
||||
t_stat r;
|
||||
|
||||
if (uptr == NULL) return SCPE_IERR;
|
||||
if (cptr == NULL) return SCPE_ARG;
|
||||
if (!(uptr->flags & UNIT_ATT)) return SCPE_UNATT;
|
||||
inp = (int32) get_uint (cptr, 10, 2048, &r);
|
||||
if (r != SCPE_OK) return r;
|
||||
if (inp == 0) return SCPE_ARG;
|
||||
finp = (float) inp;
|
||||
if (sim_switches & SWMASK ('R')) { /* format records? */
|
||||
nr = inp;
|
||||
nw = (int32) ((dp_tab[dp_ctype].wrds / (finp + ((finp - 1.0) / 20.0))) - REC_OVHD_WRDS);
|
||||
if (nw <= 0) return SCPE_ARG; }
|
||||
else { nw = inp; /* format words */
|
||||
nr = (int32) ((((20.0 * dp_tab[dp_ctype].wrds) / (finp + REC_OVHD_WRDS)) + 1.0) / 21.0);
|
||||
if (nr <= 0) return SCPE_ARG; }
|
||||
printf ("Proposed format: records/track = %d, record size = %d\n", nr, nw);
|
||||
if (!get_yn ("Formatting will destroy all data on this disk; proceed? [N]", FALSE))
|
||||
return SCPE_OK;
|
||||
for (c = cntr = 0; c < dp_tab[dp_ctype].cyl; c++) {
|
||||
for (h = 0; h < dp_tab[dp_ctype].surf; h++) {
|
||||
for (i = 0; i < DP_TRKLEN; i++) tbuf[i] = 0;
|
||||
rptr = 0;
|
||||
for (i = 0; i < nr; i++) {
|
||||
tbuf[rptr + REC_LNT] = nw & DMASK;
|
||||
if (sim_switches & SWMASK ('S'))
|
||||
tbuf[rptr + REC_ADDR] = cntr++;
|
||||
else tbuf[rptr + REC_ADDR] = (c << 8) + (h << 3) + i;
|
||||
rptr = rptr + nw + REC_OVHD; }
|
||||
if (r = dp_wrtrk (uptr, tbuf, c, h)) return r;
|
||||
}
|
||||
}
|
||||
printf ("Formatting complete\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Show format */
|
||||
|
||||
t_stat dp_showformat (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
uint32 c, h, rptr, rlnt, sec;
|
||||
uint32 minrec = DP_TRKLEN;
|
||||
uint32 maxrec = 0;
|
||||
uint32 minsec = DP_TRKLEN;
|
||||
uint32 maxsec = 0;
|
||||
uint16 tbuf[DP_TRKLEN];
|
||||
t_stat r;
|
||||
|
||||
if (uptr == NULL) return SCPE_IERR;
|
||||
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT;
|
||||
for (c = 0; c < dp_tab[dp_ctype].cyl; c++) {
|
||||
for (h = 0; h < dp_tab[dp_ctype].surf; h++) {
|
||||
if (r = dp_rdtrk (uptr, tbuf, c, h)) return r;
|
||||
rptr = 0;
|
||||
rlnt = tbuf[rptr + REC_LNT];
|
||||
if (rlnt == 0) {
|
||||
if (c || h) fprintf (st,
|
||||
"Unformatted track, cyl = %d, head = %d\n", c, h);
|
||||
else fprintf (st, "Disk is unformatted\n");
|
||||
return SCPE_OK; }
|
||||
for (sec = 0; rlnt != 0; sec++) {
|
||||
if ((rptr + rlnt + REC_OVHD) >= DP_TRKLEN) {
|
||||
fprintf (st, "Invalid record length %d, cyl = %d, head = %d, sect = %d\n",
|
||||
rlnt, c, h, sec);
|
||||
return SCPE_OK; }
|
||||
if (tbuf[rptr + REC_EXT] >= REC_MAXEXT) {
|
||||
fprintf (st, "Invalid record extension %d, cyl = %d, head = %d, sect = %d\n",
|
||||
tbuf[rptr + REC_EXT], c, h, sec);
|
||||
return SCPE_OK; }
|
||||
if (rlnt > maxrec) maxrec = rlnt;
|
||||
if (rlnt < minrec) minrec = rlnt;
|
||||
rptr = rptr + rlnt + REC_OVHD;
|
||||
rlnt = tbuf[rptr + REC_LNT];
|
||||
}
|
||||
if (sec > maxsec) maxsec = sec;
|
||||
if (sec < minsec) minsec = sec;
|
||||
}
|
||||
}
|
||||
if ((minrec == maxrec) && (minsec == maxsec)) fprintf (st,
|
||||
"Valid fixed format, records/track = %d, record size = %d\n",
|
||||
minsec, minrec);
|
||||
else if (minrec == maxrec) fprintf (st,
|
||||
"Valid variable format, records/track = %d-%d, record size = %d\n",
|
||||
minsec, maxsec, minrec);
|
||||
else if (minsec == maxsec) fprintf (st,
|
||||
"Valid variable format, records/track = %d, record sizes = %d-%d\n",
|
||||
minsec, minrec, maxrec);
|
||||
else fprintf (st,
|
||||
"Valid variable format, records/track = %d-%d, record sizes = %d-%d\n",
|
||||
minsec, maxsec, minrec, maxrec);
|
||||
return SCPE_OK;
|
||||
}
|
423
H316/h316_fhd.c
Normal file
|
@ -0,0 +1,423 @@
|
|||
/* h316_fhd.c: H316/516 fixed head simulator
|
||||
|
||||
Copyright (c) 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.
|
||||
|
||||
fhd 516-4400 fixed head disk
|
||||
|
||||
These head-per-track devices are buffered in memory, to minimize overhead.
|
||||
*/
|
||||
|
||||
#include "h316_defs.h"
|
||||
#include <math.h>
|
||||
|
||||
/* Constants */
|
||||
|
||||
#define FH_NUMWD 1536 /* words/track */
|
||||
#define FH_NUMTK 64 /* tracks/surface */
|
||||
#define FH_WDPSF (FH_NUMWD * FH_NUMTK) /* words/surface */
|
||||
#define FH_NUMSF 16 /* surfaces/ctlr */
|
||||
#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */
|
||||
#define UNIT_V_SF (UNIT_V_UF + 1) /* #surfaces - 1 */
|
||||
#define UNIT_M_SF 017
|
||||
#define UNIT_AUTO (1 << UNIT_V_AUTO)
|
||||
#define UNIT_SF (UNIT_M_SF << UNIT_V_SF)
|
||||
#define UNIT_GETSF(x) ((((x) >> UNIT_V_SF) & UNIT_M_SF) + 1)
|
||||
|
||||
/* Command word 1 */
|
||||
|
||||
#define CW1_RW 0100000 /* read vs write */
|
||||
#define CW1_V_SF 10 /* surface */
|
||||
#define CW1_M_SF 017
|
||||
#define CW1_GETSF(x) (((x) >> CW1_V_SF) & CW1_M_SF)
|
||||
#define CW1_V_TK 4 /* track */
|
||||
#define CW1_M_TK 077
|
||||
#define CW1_GETTK(x) (((x) >> CW1_V_TK) & CW1_M_TK)
|
||||
|
||||
/* Command word 2 */
|
||||
|
||||
#define CW2_V_CA 0 /* character addr */
|
||||
#define CW2_M_CA 07777
|
||||
#define CW2_GETCA(x) (((x) >> CW2_V_CA) & CW2_M_CA)
|
||||
|
||||
#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \
|
||||
((double) FH_NUMWD)))
|
||||
|
||||
/* OTA states */
|
||||
|
||||
#define OTA_NOP 0 /* normal */
|
||||
#define OTA_CW1 1 /* expecting CW1 */
|
||||
#define OTA_CW2 2 /* expecting CW2 */
|
||||
|
||||
extern int32 dev_int, dev_enb, chan_req;
|
||||
extern int32 stop_inst;
|
||||
extern uint32 dma_ad[DMA_MAX];
|
||||
|
||||
uint32 fhd_cw1 = 0; /* cmd word 1 */
|
||||
uint32 fhd_cw2 = 0; /* cmd word 2 */
|
||||
uint32 fhd_buf = 0; /* buffer */
|
||||
uint32 fhd_otas = 0; /* state */
|
||||
uint32 fhd_busy = 0; /* busy */
|
||||
uint32 fhd_rdy = 0; /* word ready */
|
||||
uint32 fhd_dte = 0; /* data err */
|
||||
uint32 fhd_ace = 0; /* access error */
|
||||
uint32 fhd_dma = 0; /* DMA/DMC */
|
||||
uint32 fhd_eor = 0; /* end of range */
|
||||
uint32 fhd_csum = 0; /* parity checksum */
|
||||
uint32 fhd_stopioe = 1; /* stop on error */
|
||||
int32 fhd_time = 10; /* time per word */
|
||||
|
||||
int32 fhdio (int32 inst, int32 fnc, int32 dat, int32 dev);
|
||||
t_stat fhd_svc (UNIT *uptr);
|
||||
t_stat fhd_reset (DEVICE *dptr);
|
||||
t_stat fhd_attach (UNIT *uptr, char *cptr);
|
||||
t_stat fhd_boot (int32 unitno, DEVICE *dptr);
|
||||
t_stat fhd_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
void fhd_go (uint32 dma);
|
||||
void fhd_go1 (uint32 dat);
|
||||
void fhd_go2 (uint32 dat);
|
||||
t_bool fhd_getc (UNIT *uptr, uint32 *ch);
|
||||
t_bool fhd_putc (UNIT *uptr, uint32 ch);
|
||||
t_bool fhd_bad_wa (uint32 wa);
|
||||
uint32 fhd_csword (uint32 cs, uint32 ch);
|
||||
|
||||
/* FHD data structures
|
||||
|
||||
fhd_dev device descriptor
|
||||
fhd_unit unit descriptor
|
||||
fhd_mod unit modifiers
|
||||
fhd_reg register list
|
||||
*/
|
||||
|
||||
DIB fhd_dib = { FHD, IOBUS, 1, &fhdio };
|
||||
|
||||
UNIT fhd_unit =
|
||||
{ UDATA (&fhd_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+
|
||||
UNIT_MUSTBUF, FH_WDPSF) };
|
||||
|
||||
REG fhd_reg[] = {
|
||||
{ ORDATA (CW1, fhd_cw1, 16) },
|
||||
{ ORDATA (CW2, fhd_cw2, 16) },
|
||||
{ ORDATA (BUF, fhd_buf, 16) },
|
||||
{ FLDATA (BUSY, fhd_busy, 0) },
|
||||
{ FLDATA (RDY, fhd_rdy, 0) },
|
||||
{ FLDATA (DTE, fhd_dte, 0) },
|
||||
{ FLDATA (ACE, fhd_ace, 0) },
|
||||
{ FLDATA (EOR, fhd_eor, 0) },
|
||||
{ FLDATA (DMA, fhd_dma, 0) },
|
||||
{ FLDATA (CSUM, fhd_csum, 7) },
|
||||
{ FLDATA (INTREQ, dev_int, INT_V_MT) },
|
||||
{ FLDATA (ENABLE, dev_enb, INT_V_MT) },
|
||||
{ DRDATA (TIME, fhd_time, 31), REG_NZ + PV_LEFT },
|
||||
{ ORDATA (OTAS, fhd_otas, 2), REG_HRO },
|
||||
{ ORDATA (CHAN, fhd_dib.chan, 5), REG_HRO },
|
||||
{ FLDATA (STOP_IOE, fhd_stopioe, 0) },
|
||||
{ NULL } };
|
||||
|
||||
MTAB fhd_mod[] = {
|
||||
{ UNIT_SF, (0 << UNIT_V_SF), NULL, "1S", &fhd_set_size },
|
||||
{ UNIT_SF, (1 << UNIT_V_SF), NULL, "2S", &fhd_set_size },
|
||||
{ UNIT_SF, (2 << UNIT_V_SF), NULL, "3S", &fhd_set_size },
|
||||
{ UNIT_SF, (3 << UNIT_V_SF), NULL, "4S", &fhd_set_size },
|
||||
{ UNIT_SF, (4 << UNIT_V_SF), NULL, "5S", &fhd_set_size },
|
||||
{ UNIT_SF, (5 << UNIT_V_SF), NULL, "6S", &fhd_set_size },
|
||||
{ UNIT_SF, (6 << UNIT_V_SF), NULL, "7S", &fhd_set_size },
|
||||
{ UNIT_SF, (7 << UNIT_V_SF), NULL, "8S", &fhd_set_size },
|
||||
{ UNIT_SF, (8 << UNIT_V_SF), NULL, "9S", &fhd_set_size },
|
||||
{ UNIT_SF, (9 << UNIT_V_SF), NULL, "10S", &fhd_set_size },
|
||||
{ UNIT_SF, (10 << UNIT_V_SF), NULL, "11S", &fhd_set_size },
|
||||
{ UNIT_SF, (11 << UNIT_V_SF), NULL, "12S", &fhd_set_size },
|
||||
{ UNIT_SF, (12 << UNIT_V_SF), NULL, "13S", &fhd_set_size },
|
||||
{ UNIT_SF, (13 << UNIT_V_SF), NULL, "14S", &fhd_set_size },
|
||||
{ UNIT_SF, (14 << UNIT_V_SF), NULL, "15S", &fhd_set_size },
|
||||
{ UNIT_SF, (15 << UNIT_V_SF), NULL, "16S", &fhd_set_size },
|
||||
{ UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, NULL, "IOBUS",
|
||||
&io_set_iobus, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, NULL, "DMC",
|
||||
&io_set_dmc, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, NULL, "DMA",
|
||||
&io_set_dma, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "CHANNEL", NULL,
|
||||
NULL, &io_show_chan, NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE fhd_dev = {
|
||||
"FHD", &fhd_unit, fhd_reg, fhd_mod,
|
||||
1, 8, 22, 1, 8, 16,
|
||||
NULL, NULL, &fhd_reset,
|
||||
NULL, &fhd_attach, NULL,
|
||||
&fhd_dib, DEV_DISABLE };
|
||||
|
||||
/* IO routines */
|
||||
|
||||
int32 fhdio (int32 inst, int32 fnc, int32 dat, int32 dev)
|
||||
{
|
||||
switch (inst) { /* case on opcode */
|
||||
case ioOCP: /* control */
|
||||
if (fnc == 04) { /* terminate output? */
|
||||
fhd_eor = 1; /* stop */
|
||||
CLR_INT (INT_FHD); } /* clear int req */
|
||||
else if (fnc == 003) fhd_go (1); /* start, DMA */
|
||||
else if (fnc == 007) fhd_go (0); /* start, IO bus */
|
||||
else return IOBADFNC (dat);
|
||||
break;
|
||||
case ioOTA: /* output */
|
||||
if (fnc) return IOBADFNC (dat); /* only fnc 0 */
|
||||
if (fhd_rdy) { /* ready? */
|
||||
fhd_buf = dat; /* store data */
|
||||
if (fhd_otas == OTA_CW1) fhd_go1 (dat); /* expecting CW1? */
|
||||
else if (fhd_otas == OTA_CW2) fhd_go2 (dat);/* expecting CW2? */
|
||||
else fhd_rdy = 0; /* normal, clr ready */
|
||||
return IOSKIP (dat); }
|
||||
break;
|
||||
case ioINA: /* input */
|
||||
if (fnc) return IOBADFNC (dat); /* only fnc 0 */
|
||||
if (fhd_rdy) { /* ready? */
|
||||
fhd_rdy = 0; /* clear ready */
|
||||
return IOSKIP (dat | fhd_buf); } /* return data */
|
||||
break;
|
||||
case ioSKS: /* sense */
|
||||
if (((fnc == 000) && fhd_rdy) || /* 0 = skip if ready */
|
||||
((fnc == 001) && !fhd_busy) || /* 1 = skip if !busy */
|
||||
((fnc == 002) && !fhd_dte) || /* 2 = skip if !data err */
|
||||
((fnc == 003) && !fhd_ace) || /* 3 = skip if !access err */
|
||||
((fnc == 004) && !TST_INTREQ (INT_FHD))) /* 4 = skip if !interrupt */
|
||||
return IOSKIP (dat);
|
||||
break;
|
||||
case ioEND:
|
||||
fhd_eor = 1;
|
||||
break; }
|
||||
return dat;
|
||||
}
|
||||
|
||||
/* Start new operation */
|
||||
|
||||
void fhd_go (uint32 dma)
|
||||
{
|
||||
int32 ch = fhd_dib.chan - 1; /* DMA/DMC chan */
|
||||
|
||||
if (fhd_busy) return; /* ignore if busy */
|
||||
fhd_busy = 1; /* ctlr is busy */
|
||||
fhd_eor = 0; /* transfer not done */
|
||||
fhd_csum = 0; /* init checksum */
|
||||
fhd_dte = 0; /* clear errors */
|
||||
fhd_ace = 0;
|
||||
if (ch >= 0) fhd_dma = dma; /* DMA allowed? */
|
||||
else fhd_dma = 0; /* no, force IO bus */
|
||||
fhd_otas = OTA_CW1; /* expect CW1 */
|
||||
fhd_rdy = 1; /* set ready */
|
||||
if (fhd_dma && Q_DMA (ch)) { /* DMA and DMA channel? */
|
||||
SET_CH_REQ (ch); /* set channel request */
|
||||
dma_ad[ch] = dma_ad[ch] & ~DMA_IN; } /* force output */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Process command word 1 */
|
||||
|
||||
void fhd_go1 (uint32 dat)
|
||||
{
|
||||
int32 ch = fhd_dib.chan - 1; /* DMA/DMC chan */
|
||||
|
||||
fhd_cw1 = dat; /* store CW1 */
|
||||
fhd_otas = OTA_CW2; /* expect CW2 */
|
||||
fhd_rdy = 1; /* set ready */
|
||||
if (fhd_dma && Q_DMA (ch)) SET_CH_REQ (ch); /* DMA? set chan request */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Process command word 2 - initiate seek */
|
||||
|
||||
void fhd_go2 (uint32 dat)
|
||||
{
|
||||
int32 ch = fhd_dib.chan - 1; /* DMA/DMC chan */
|
||||
uint32 sf = CW1_GETSF (fhd_cw1); /* surface */
|
||||
int32 t, wa;
|
||||
|
||||
fhd_cw2 = dat; /* store CW2 */
|
||||
fhd_otas = OTA_NOP; /* next state */
|
||||
wa = CW2_GETCA (fhd_cw2) >> 1; /* word addr */
|
||||
if ((wa >= FH_NUMWD) || /* if bad char addr */
|
||||
((fhd_unit.flags & UNIT_ATT) == 0) || /* or unattached */
|
||||
(sf >= UNIT_GETSF (fhd_unit.flags))) { /* or bad surface */
|
||||
fhd_ace = 1; /* access error */
|
||||
fhd_busy = 0; /* abort operation */
|
||||
SET_INT (INT_FHD);
|
||||
return; }
|
||||
if (fhd_cw1 & CW1_RW) { /* write? */
|
||||
fhd_rdy = 1; /* set ready */
|
||||
if (fhd_dma) SET_CH_REQ (ch); } /* if DMA/DMC, req chan */
|
||||
else { fhd_rdy = 0; /* read, clear ready */
|
||||
if (fhd_dma && (ch < DMC_V_DMC1)) /* read and DMA chan? */
|
||||
dma_ad[ch] = dma_ad[ch] | DMA_IN; } /* force input */
|
||||
t = wa - GET_POS (fhd_time); /* delta to new loc */
|
||||
if (t < 0) t = t + FH_NUMWD; /* wrap around? */
|
||||
sim_activate (&fhd_unit, t * fhd_time); /* schedule op */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Unit service */
|
||||
|
||||
t_stat fhd_svc (UNIT *uptr)
|
||||
{
|
||||
int32 ch = fhd_dib.chan - 1; /* DMA/DMC chan (-1 if IO bus) */
|
||||
uint32 c1, c2;
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */
|
||||
fhd_ace = 1; /* access error */
|
||||
fhd_busy = 0; /* abort operation */
|
||||
SET_INT (INT_FHD);
|
||||
return IORETURN (fhd_stopioe, SCPE_UNATT); }
|
||||
|
||||
if (fhd_eor || fhd_rdy) { /* done or ready set? */
|
||||
if (fhd_rdy) fhd_dte = 1; /* if ready set, data err */
|
||||
if (fhd_cw1 & CW1_RW) { /* write? */
|
||||
if (!fhd_rdy) { /* buffer full? */
|
||||
fhd_putc (uptr, fhd_buf >> 8); /* store last word */
|
||||
fhd_putc (uptr, fhd_buf); }
|
||||
fhd_putc (uptr, fhd_csum); } /* store csum */
|
||||
else { /* read */
|
||||
fhd_getc (uptr, &c1); /* get csum */
|
||||
if (fhd_csum) fhd_dte = 1; } /* if csum != 0, err */
|
||||
fhd_busy = 0; /* operation complete */
|
||||
SET_INT (INT_FHD);
|
||||
return SCPE_OK; }
|
||||
|
||||
if (fhd_cw1 & CW1_RW) { /* write? */
|
||||
if (fhd_putc (uptr, fhd_buf >> 8)) return SCPE_OK;
|
||||
if (fhd_putc (uptr, fhd_buf)) return SCPE_OK; }
|
||||
else { if (fhd_getc (uptr, &c1)) return SCPE_OK; /* read */
|
||||
if (fhd_getc (uptr, &c2)) return SCPE_OK;
|
||||
fhd_buf = (c1 << 8) | c2; }
|
||||
sim_activate (uptr, fhd_time); /* next word */
|
||||
fhd_rdy = 1; /* set ready */
|
||||
if (fhd_dma) SET_CH_REQ (ch); /* if DMA/DMC, req chan */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Read character from disk */
|
||||
|
||||
t_bool fhd_getc (UNIT *uptr, uint32 *ch)
|
||||
{
|
||||
uint32 sf = CW1_GETSF (fhd_cw1); /* surface */
|
||||
uint32 tk = CW1_GETTK (fhd_cw1); /* track */
|
||||
uint32 ca = CW2_GETCA (fhd_cw2); /* char addr */
|
||||
uint32 wa = ca >> 1; /* word addr */
|
||||
uint32 ba = (((sf * FH_NUMTK) + tk) * FH_NUMWD) + wa; /* buffer offset */
|
||||
uint16 *fbuf = uptr->filebuf; /* buffer base */
|
||||
uint32 wd;
|
||||
|
||||
if (fhd_bad_wa (wa)) return TRUE; /* addr bad? */
|
||||
fhd_cw2 = fhd_cw2 + 1; /* incr char addr */
|
||||
if (ca & 1) wd = fbuf[ba] & 0377; /* select char */
|
||||
else wd = (fbuf[ba] >> 8) & 0377;
|
||||
fhd_csum = fhd_csword (fhd_csum, wd); /* put in csum */
|
||||
*ch = wd; /* return */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Write character to disk */
|
||||
|
||||
t_bool fhd_putc (UNIT *uptr, uint32 ch)
|
||||
{
|
||||
uint32 sf = CW1_GETSF (fhd_cw1); /* surface */
|
||||
uint32 tk = CW1_GETTK (fhd_cw1); /* track */
|
||||
uint32 ca = CW2_GETCA (fhd_cw2); /* char addr */
|
||||
uint32 wa = ca >> 1; /* word addr */
|
||||
uint32 ba = (((sf * FH_NUMTK) + tk) * FH_NUMWD) + wa; /* buffer offset */
|
||||
uint16 *fbuf = uptr->filebuf; /* buffer base */
|
||||
|
||||
ch = ch & 0377; /* mask char */
|
||||
if (fhd_bad_wa (wa)) return TRUE; /* addr bad? */
|
||||
fhd_cw2 = fhd_cw2 + 1; /* incr char addr */
|
||||
if (ca & 1) fbuf[ba] = (fbuf[ba] & ~0377) | ch; /* odd? low char */
|
||||
else fbuf[ba] = (fbuf[ba] & 0377) | (ch << 8); /* even, hi char */
|
||||
fhd_csum = fhd_csword (fhd_csum, ch); /* put in csum */
|
||||
if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; /* update hwmark */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Check word address */
|
||||
|
||||
t_bool fhd_bad_wa (uint32 wa)
|
||||
{
|
||||
if (wa >= FH_NUMWD) { /* bad address? */
|
||||
fhd_ace = 1; /* access error */
|
||||
fhd_busy = 0; /* abort operation */
|
||||
SET_INT (INT_FHD);
|
||||
return TRUE; }
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Add character to checksum (parity) */
|
||||
|
||||
uint32 fhd_csword (uint32 cs, uint32 ch)
|
||||
{
|
||||
while (ch) { /* count bits */
|
||||
ch = ch & ~(ch & (-(int32) ch));
|
||||
cs = cs ^ 0200; } /* invert cs for each 1 */
|
||||
return cs;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat fhd_reset (DEVICE *dptr)
|
||||
{
|
||||
fhd_busy = 0; /* reset state */
|
||||
fhd_rdy = 0;
|
||||
fhd_ace = 0;
|
||||
fhd_dte = 0;
|
||||
fhd_eor = 0;
|
||||
fhd_otas = OTA_NOP;
|
||||
fhd_cw1 = fhd_cw2 = fhd_buf = 0;
|
||||
CLR_INT (INT_FHD); /* clear int, enb */
|
||||
CLR_ENB (INT_FHD);
|
||||
sim_cancel (&fhd_unit); /* cancel operation */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Attach routine */
|
||||
|
||||
t_stat fhd_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
uint32 sz, sf;
|
||||
uint32 ds_bytes = FH_WDPSF * sizeof (int16);
|
||||
|
||||
if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (cptr))) {
|
||||
sf = (sz + ds_bytes - 1) / ds_bytes;
|
||||
if (sf >= FH_NUMSF) sf = FH_NUMSF - 1;
|
||||
uptr->flags = (uptr->flags & ~UNIT_SF) |
|
||||
(sf << UNIT_V_SF); }
|
||||
uptr->capac = UNIT_GETSF (uptr->flags) * FH_WDPSF;
|
||||
return attach_unit (uptr, cptr);
|
||||
}
|
||||
|
||||
/* Set size routine */
|
||||
|
||||
t_stat fhd_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if (val < 0) return SCPE_IERR;
|
||||
if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
|
||||
uptr->capac = UNIT_GETSF (val) * FH_WDPSF;
|
||||
return SCPE_OK;
|
||||
}
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
lpt line printer
|
||||
|
||||
24-Oct-03 RMS Added DMA/DMC support
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
30-May-02 RMS Widened POS to 32b
|
||||
|
||||
|
@ -55,8 +56,10 @@
|
|||
lpt_crpos carriage position (0-1)
|
||||
lpt_svcst service state (shuttle, paper advance)
|
||||
lpt_svcch channel for paper advance (0 = no adv)
|
||||
lpt_xfer transfer ready flag
|
||||
lpt_rdy transfer ready flag
|
||||
lpt_prdn printing done flag
|
||||
lpt_dma use DMA/DMC
|
||||
lpt_eor DMA/DMC end of range
|
||||
*/
|
||||
|
||||
#include "h316_defs.h"
|
||||
|
@ -67,22 +70,26 @@
|
|||
#define LPT_SVCSH 01 /* shuttle */
|
||||
#define LPT_SVCPA 02 /* paper advance */
|
||||
|
||||
extern int32 dev_ready, dev_enable;
|
||||
extern int32 dev_int, dev_enb;
|
||||
extern int32 stop_inst;
|
||||
extern uint32 chan_req;
|
||||
|
||||
int32 lpt_wdpos = 0; /* word position */
|
||||
int32 lpt_drpos = 0; /* drum position */
|
||||
int32 lpt_crpos = 0; /* carriage position */
|
||||
int32 lpt_svcst = 0; /* service state */
|
||||
int32 lpt_svcch = 0; /* service channel */
|
||||
int32 lpt_xfer = 0; /* transfer flag */
|
||||
int32 lpt_rdy = 0; /* transfer flag */
|
||||
int32 lpt_prdn = 1; /* printing done */
|
||||
int32 lpt_dma = 0; /* use DMA/DMC */
|
||||
int32 lpt_eor = 0; /* DMA/DMC end range */
|
||||
char lpt_buf[LPT_WIDTH + 1] = { 0 }; /* line buffer */
|
||||
int32 lpt_xtime = 5; /* transfer time */
|
||||
int32 lpt_etime = 50; /* end of scan time */
|
||||
int32 lpt_ptime = 5000; /* paper adv time */
|
||||
int32 lpt_stopioe = 0; /* stop on error */
|
||||
|
||||
int32 lptio (int32 inst, int32 fnc, int32 dat, int32 dev);
|
||||
t_stat lpt_svc (UNIT *uptr);
|
||||
t_stat lpt_reset (DEVICE *dptr);
|
||||
|
||||
|
@ -94,16 +101,20 @@ t_stat lpt_reset (DEVICE *dptr);
|
|||
lpt_reg LPT register list
|
||||
*/
|
||||
|
||||
DIB lpt_dib = { LPT, IOBUS, 1, &lptio };
|
||||
|
||||
UNIT lpt_unit = { UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0) };
|
||||
|
||||
REG lpt_reg[] = {
|
||||
{ DRDATA (WDPOS, lpt_wdpos, 6) },
|
||||
{ DRDATA (DRPOS, lpt_drpos, 6) },
|
||||
{ FLDATA (CRPOS, lpt_crpos, 0) },
|
||||
{ FLDATA (XFER, lpt_xfer, 0) },
|
||||
{ FLDATA (RDY, lpt_rdy, 0) },
|
||||
{ FLDATA (EOR, lpt_eor, 0) },
|
||||
{ FLDATA (DMA, lpt_dma, 0) },
|
||||
{ FLDATA (PRDN, lpt_prdn, 0) },
|
||||
{ FLDATA (INTREQ, dev_ready, INT_V_LPT) },
|
||||
{ FLDATA (ENABLE, dev_enable, INT_V_LPT) },
|
||||
{ FLDATA (INTREQ, dev_int, INT_V_LPT) },
|
||||
{ FLDATA (ENABLE, dev_enb, INT_V_LPT) },
|
||||
{ ORDATA (SVCST, lpt_svcst, 2) },
|
||||
{ ORDATA (SVCCH, lpt_svcch, 2) },
|
||||
{ BRDATA (BUF, lpt_buf, 8, 8, 120) },
|
||||
|
@ -118,12 +129,14 @@ DEVICE lpt_dev = {
|
|||
"LPT", &lpt_unit, lpt_reg, NULL,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &lpt_reset,
|
||||
NULL, NULL, NULL };
|
||||
NULL, NULL, NULL,
|
||||
&lpt_dib, DEV_DISABLE };
|
||||
|
||||
/* IO routine */
|
||||
|
||||
int32 lptio (int32 inst, int32 fnc, int32 dat)
|
||||
int32 lptio (int32 inst, int32 fnc, int32 dat, int32 dev)
|
||||
{
|
||||
int32 ch = lpt_dib.chan - 1; /* DMA/DMC chan */
|
||||
int32 chr;
|
||||
|
||||
switch (inst) { /* case on opcode */
|
||||
|
@ -133,13 +146,26 @@ case ioOCP: /* OCP */
|
|||
lpt_svcst = lpt_svcst | LPT_SVCPA; /* set state */
|
||||
lpt_svcch = fnc >> 1; /* save channel */
|
||||
sim_activate (&lpt_unit, lpt_ptime);
|
||||
CLR_READY (INT_LPT); /* clear int */
|
||||
CLR_INT (INT_LPT); /* clear int */
|
||||
break;
|
||||
case 007: /* init scan */
|
||||
case 003: /* init scan DMA/DMC */
|
||||
lpt_prdn = 0; /* clear pr done */
|
||||
lpt_wdpos = 0; /* init scan pos */
|
||||
if (!sim_is_active (&lpt_unit)) lpt_xfer = 1;
|
||||
CLR_READY (INT_LPT); /* clear int */
|
||||
lpt_eor = 0;
|
||||
if (ch >= 0) lpt_dma = 1; /* try for DMA/DMC */
|
||||
lpt_dma = 0;
|
||||
if (!sim_is_active (&lpt_unit)) {
|
||||
lpt_rdy = 1;
|
||||
if (lpt_dma) SET_CH_REQ (ch); }
|
||||
CLR_INT (INT_LPT); /* clear int */
|
||||
break;
|
||||
case 007: /* init scan IO bus*/
|
||||
lpt_prdn = 0; /* clear pr done */
|
||||
lpt_wdpos = 0; /* init scan pos */
|
||||
lpt_eor = 0;
|
||||
lpt_dma = 0; /* IO bus */
|
||||
if (!sim_is_active (&lpt_unit)) lpt_rdy = 1;
|
||||
CLR_INT (INT_LPT); /* clear int */
|
||||
break;
|
||||
default:
|
||||
return IOBADFNC (dat); }
|
||||
|
@ -148,7 +174,7 @@ case ioOCP: /* OCP */
|
|||
case ioSKS: /* SKS */
|
||||
switch (fnc) { /* case on fnc */
|
||||
case 000: /* if xfer rdy */
|
||||
if (lpt_xfer) return IOSKIP (dat);
|
||||
if (lpt_rdy) return IOSKIP (dat);
|
||||
break;
|
||||
case 002: /* if !alarm */
|
||||
if (lpt_unit.flags & UNIT_ATT) return IOSKIP (dat);
|
||||
|
@ -187,8 +213,8 @@ case ioSKS: /* SKS */
|
|||
|
||||
case ioOTA: /* OTA */
|
||||
if (fnc) return IOBADFNC (dat); /* only fnc 0 */
|
||||
if (lpt_xfer) { /* xfer ready? */
|
||||
lpt_xfer = 0; /* clear xfer */
|
||||
if (lpt_rdy) { /* xfer ready? */
|
||||
lpt_rdy = 0; /* clear xfer */
|
||||
chr = (dat >> (lpt_crpos? 0: 8)) & 077; /* get 6b char */
|
||||
if (chr == lpt_drpos) { /* match drum pos? */
|
||||
if (chr < 040) chr = chr | 0100;
|
||||
|
@ -207,6 +233,10 @@ case ioOTA: /* OTA */
|
|||
} /* end if endscan */
|
||||
else sim_activate (&lpt_unit, lpt_xtime);
|
||||
return IOSKIP (dat); } /* skip return */
|
||||
break;
|
||||
|
||||
case ioEND: /* end DMA/DMC */
|
||||
lpt_eor = 1; /* set end range */
|
||||
break; } /* end case op */
|
||||
return dat;
|
||||
}
|
||||
|
@ -216,6 +246,7 @@ return dat;
|
|||
t_stat lpt_svc (UNIT *uptr)
|
||||
{
|
||||
int32 i;
|
||||
int32 ch = lpt_dib.chan - 1; /* DMA/DMC chan */
|
||||
static const char *lpt_cc[] = {
|
||||
"\r",
|
||||
"\n",
|
||||
|
@ -224,12 +255,18 @@ static const char *lpt_cc[] = {
|
|||
|
||||
if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */
|
||||
return IORETURN (lpt_stopioe, SCPE_UNATT);
|
||||
lpt_xfer = 1;
|
||||
if (lpt_dma) { /* DMA/DMC? */
|
||||
if (lpt_eor) SET_INT (INT_LPT); /* end range? intr */
|
||||
else {
|
||||
lpt_rdy = 1; /* set ready */
|
||||
SET_CH_REQ (ch); } } /* get more data */
|
||||
else lpt_rdy = 1; /* IO, continue scan */
|
||||
if (lpt_dma && lpt_eor) SET_INT (INT_LPT); /* end of range? */
|
||||
if (lpt_svcst & LPT_SVCSH) { /* shuttling */
|
||||
SET_READY (INT_LPT); /* interrupt */
|
||||
SET_INT (INT_LPT); /* interrupt */
|
||||
if (lpt_crpos == 0) lpt_prdn = 1; }
|
||||
if (lpt_svcst & LPT_SVCPA) { /* paper advance */
|
||||
SET_READY (INT_LPT); /* interrupt */
|
||||
SET_INT (INT_LPT); /* interrupt */
|
||||
for (i = LPT_WIDTH - 1; i >= 0; i++) {
|
||||
if (lpt_buf[i] != ' ') break; }
|
||||
lpt_buf[i + 1] = 0;
|
||||
|
@ -250,12 +287,14 @@ int32 i;
|
|||
|
||||
lpt_wdpos = lpt_drpos = lpt_crpos = 0; /* clear positions */
|
||||
lpt_svcst = lpt_svcch = 0; /* idle state */
|
||||
lpt_xfer = 0; /* not rdy to xfer */
|
||||
lpt_rdy = 0; /* not rdy to xfer */
|
||||
lpt_prdn = 1; /* printing done */
|
||||
lpt_eor = 0;
|
||||
lpt_dma = 0;
|
||||
for (i = 0; i < LPT_WIDTH; i++) lpt_buf[i] = ' '; /* clear buffer */
|
||||
lpt_buf[LPT_WIDTH] = 0;
|
||||
CLR_READY (INT_LPT); /* clear int, enb */
|
||||
CLR_ENABLE (INT_LPT);
|
||||
CLR_INT (INT_LPT); /* clear int, enb */
|
||||
CLR_ENB (INT_LPT);
|
||||
sim_cancel (&lpt_unit); /* deactivate unit */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
|
520
H316/h316_mt.c
Normal file
|
@ -0,0 +1,520 @@
|
|||
/* h316_mt.c: H316/516 magnetic tape simulator
|
||||
|
||||
Copyright (c) 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.
|
||||
|
||||
mt 516-4100 seven track magnetic tape
|
||||
|
||||
Magnetic tapes are represented as a series of variable records
|
||||
of the form:
|
||||
|
||||
32b byte count
|
||||
byte 0
|
||||
byte 1
|
||||
:
|
||||
byte n-2
|
||||
byte n-1
|
||||
32b byte count
|
||||
|
||||
If the byte count is odd, the record is padded with an extra byte
|
||||
of junk. File marks are represented by a byte count of 0.
|
||||
*/
|
||||
|
||||
#include "h316_defs.h"
|
||||
#include "sim_tape.h"
|
||||
|
||||
#define MT_NUMDR 4 /* number of drives */
|
||||
#define DB_N_SIZE 16 /* max data buf */
|
||||
#define DBSIZE (1 << DB_N_SIZE) /* max data cmd */
|
||||
#define FNC u3 /* function */
|
||||
#define UST u4 /* unit status */
|
||||
#define UNIT_WPRT (MTUF_WLK | UNIT_RO) /* write prot */
|
||||
|
||||
/* Function codes */
|
||||
|
||||
#define FNC_RBCD2 000
|
||||
#define FNC_RBIN2 001
|
||||
#define FNC_RBIN3 002
|
||||
#define FNC_DMANM 003
|
||||
#define FNC_WBCD2 004
|
||||
#define FNC_WBIN2 005
|
||||
#define FNC_WEOF 006
|
||||
#define FNC_IOBUS 007
|
||||
#define FNC_WBIN3 010
|
||||
#define FNC_FSR 011
|
||||
#define FNC_FSF 012
|
||||
#define FNC_DMAAU 013
|
||||
#define FNC_REW 014
|
||||
#define FNC_BSR 015
|
||||
#define FNC_BSF 016
|
||||
#define FNC_STOPW 017
|
||||
#define FNC_2ND 020 /* second state */
|
||||
#define FNC_NOP (FNC_STOPW|FNC_2ND)
|
||||
#define FNC_EOM 040 /* end of motion */
|
||||
|
||||
/* Status - unit.UST */
|
||||
|
||||
#define STA_BOT 0000002 /* beg of tape */
|
||||
#define STA_EOT 0000001 /* end of tape */
|
||||
|
||||
extern int32 dev_int, dev_enb, chan_req;
|
||||
extern int32 stop_inst;
|
||||
|
||||
uint32 mt_buf = 0; /* data buffer */
|
||||
uint32 mt_usel = 0; /* unit select */
|
||||
uint32 mt_busy = 0; /* ctlr busy */
|
||||
uint32 mt_mdirq = 0; /* motion done int req */
|
||||
uint32 mt_rdy = 0; /* transfer ready (int) */
|
||||
uint32 mt_err = 0; /* error */
|
||||
uint32 mt_eof = 0; /* end of file */
|
||||
uint32 mt_eor = 0; /* transfer done */
|
||||
uint32 mt_dma = 0; /* DMA/DMC */
|
||||
uint32 mt_xtime = 16; /* transfer time */
|
||||
uint32 mt_ctime = 3000; /* start/stop time */
|
||||
uint32 mt_stopioe = 1; /* stop on I/O error */
|
||||
uint8 mtxb[DBSIZE] = { 0 }; /* data buffer */
|
||||
t_mtrlnt mt_ptr = 0, mt_max = 0; /* buffer ptrs */
|
||||
|
||||
int32 mtio (int32 inst, int32 fnc, int32 dat, int32 dev);
|
||||
void mt_updint (uint32 rdy, uint32 mdone);
|
||||
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_map_err (UNIT *uptr, t_stat st);
|
||||
void mt_wrwd (UNIT *uptr, uint32 dat);
|
||||
|
||||
/* 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 = { MT, IOBUS, MT_NUMDR, &mtio };
|
||||
|
||||
UNIT mt_unit[] = {
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) } };
|
||||
|
||||
REG mt_reg[] = {
|
||||
{ ORDATA (BUF, mt_buf, 16) },
|
||||
{ ORDATA (USEL, mt_usel, 2) },
|
||||
{ FLDATA (BUSY, mt_busy, 0) },
|
||||
{ FLDATA (RDY, mt_rdy, 0) },
|
||||
{ FLDATA (ERR, mt_err, 0) },
|
||||
{ FLDATA (EOF, mt_eof, 0) },
|
||||
{ FLDATA (EOR, mt_eor, 0) },
|
||||
{ FLDATA (MDIRQ, mt_mdirq, 0) },
|
||||
{ FLDATA (DMA, mt_dma, 0) },
|
||||
{ FLDATA (INTREQ, dev_int, INT_V_MT) },
|
||||
{ FLDATA (ENABLE, dev_enb, INT_V_MT) },
|
||||
{ BRDATA (DBUF, mtxb, 8, 8, DBSIZE) },
|
||||
{ DRDATA (BPTR, mt_ptr, DB_N_SIZE + 1) },
|
||||
{ DRDATA (BMAX, mt_max, DB_N_SIZE + 1) },
|
||||
{ DRDATA (CTIME, mt_ctime, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (XTIME, mt_xtime, 24), REG_NZ + PV_LEFT },
|
||||
{ URDATA (POS, mt_unit[0].pos, 10, T_ADDR_W, 0, MT_NUMDR, PV_LEFT) },
|
||||
{ URDATA (FNC, mt_unit[0].FNC, 8, 8, 0, MT_NUMDR, REG_HRO) },
|
||||
{ URDATA (UST, mt_unit[0].UST, 8, 2, 0, MT_NUMDR, REG_HRO) },
|
||||
{ ORDATA (CHAN, mt_dib.chan, 5), REG_HRO },
|
||||
{ FLDATA (STOP_IOE, mt_stopioe, 0) },
|
||||
{ NULL } };
|
||||
|
||||
MTAB mt_mod[] = {
|
||||
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
|
||||
{ MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
|
||||
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, NULL, "IOBUS",
|
||||
&io_set_iobus, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, NULL, "DMC",
|
||||
&io_set_dmc, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, NULL, "DMA",
|
||||
&io_set_dma, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "CHANNEL", NULL,
|
||||
NULL, &io_show_chan, NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE mt_dev = {
|
||||
"MT", mt_unit, mt_reg, mt_mod,
|
||||
MT_NUMDR, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &mt_reset,
|
||||
NULL, &mt_attach, &mt_detach,
|
||||
&mt_dib, DEV_DISABLE };
|
||||
|
||||
/* IO routine */
|
||||
|
||||
int32 mtio (int32 inst, int32 fnc, int32 dat, int32 dev)
|
||||
{
|
||||
uint32 u = dev & 03;
|
||||
UNIT *uptr = mt_dev.units + u;
|
||||
static uint8 wrt_fnc[16] = { /* >0 = wr, 1 = chan op */
|
||||
0, 0, 0, 0, 1, 1, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
switch (inst) { /* case on opcode */
|
||||
case ioOCP:
|
||||
mt_updint (mt_rdy, 0); /* clear motion intr */
|
||||
mt_eof = 0; /* clear eof */
|
||||
switch (fnc) { /* case on function */
|
||||
case FNC_DMANM: /* set DMA/DMC */
|
||||
case FNC_DMAAU:
|
||||
mt_usel = u; /* save unit select */
|
||||
if (mt_dib.chan) mt_dma = 1; /* if configured */
|
||||
break;
|
||||
case FNC_IOBUS: /* set IOBUS */
|
||||
mt_usel = u; /* save unit select */
|
||||
mt_dma = 0;
|
||||
break;
|
||||
case FNC_STOPW: /* stop write */
|
||||
mt_usel = u; /* save unit select */
|
||||
mt_updint (0, mt_mdirq); /* clear ready */
|
||||
if (wrt_fnc[uptr->FNC & 017] == 1) /* writing? */
|
||||
mt_eor = 1; /* set transfer done */
|
||||
break;
|
||||
default: /* motion command */
|
||||
if (mt_busy) return dat; /* nop if ctlr busy */
|
||||
mt_eor = 0; /* clr transfer done */
|
||||
mt_err = 0; /* clr error */
|
||||
mt_usel = u; /* save unit select */
|
||||
if (((uptr->flags & UNIT_ATT) == 0) || /* nop if not att */
|
||||
sim_is_active (uptr)) /* or busy */
|
||||
(IORETURN (mt_stopioe, SCPE_UNATT) | dat);
|
||||
if (wrt_fnc[fnc] && (uptr->flags & UNIT_WPRT))
|
||||
return (STOP_MTWRP << IOT_V_REASON);
|
||||
uptr->FNC = fnc;
|
||||
uptr->UST = 0;
|
||||
mt_busy = 1;
|
||||
sim_activate (uptr, mt_ctime); /* schedule */
|
||||
break; }
|
||||
break;
|
||||
case ioINA: /* INA */
|
||||
if (fnc) return IOBADFNC (dat); /* fnc 0 only */
|
||||
if (mt_rdy) { /* ready? */
|
||||
mt_rdy = 0; /* clear ready */
|
||||
return IOSKIP (dat | mt_buf); } /* ret buf, skip */
|
||||
break;
|
||||
case ioOTA: /* OTA */
|
||||
if (fnc) return IOBADFNC (dat); /* fnc 0 only */
|
||||
if (mt_rdy) { /* ready? */
|
||||
mt_rdy = 0; /* clear ready */
|
||||
mt_buf = dat; /* store buf */
|
||||
return IOSKIP (dat); } /* skip */
|
||||
break;
|
||||
case ioSKS:
|
||||
uptr = mt_dev.units + mt_usel; /* use saved unit sel */
|
||||
switch (fnc) {
|
||||
case 000: /* ready */
|
||||
if (mt_rdy) return IOSKIP (dat);
|
||||
break;
|
||||
case 001: /* !busy */
|
||||
if (!mt_busy) return IOSKIP (dat);
|
||||
break;
|
||||
case 002: /* !error */
|
||||
if (!mt_err) return IOSKIP (dat);
|
||||
break;
|
||||
case 003: /* !BOT */
|
||||
if (!(uptr->UST & STA_BOT)) return IOSKIP (dat);
|
||||
break;
|
||||
case 004: /* !interrupting */
|
||||
if (!TST_INTREQ (INT_MT)) return IOSKIP (dat);
|
||||
break;
|
||||
case 005: /* !EOT */
|
||||
if (!(uptr->UST & STA_EOT)) return IOSKIP (dat);
|
||||
break;
|
||||
case 006: /* !EOF */
|
||||
if (!mt_eof) return IOSKIP (dat);
|
||||
break;
|
||||
case 007: /* !write prot */
|
||||
if (!(uptr->flags & UNIT_WPRT)) return IOSKIP (dat);
|
||||
break;
|
||||
case 011: /* operational */
|
||||
if ((uptr->flags & UNIT_ATT) &&
|
||||
((uptr->FNC & 017) != FNC_REW)) return IOSKIP (dat);
|
||||
break;
|
||||
case 012: /* skip if !chan 2 */
|
||||
return IOSKIP (dat);
|
||||
case 013: /* skip if !auto */
|
||||
return IOSKIP (dat);
|
||||
case 014: /* !rewinding */
|
||||
uptr = mt_dev.units + (dev & 03); /* use specified unit */
|
||||
if ((uptr->FNC & 017) != FNC_REW) return IOSKIP (dat);
|
||||
break; }
|
||||
break;
|
||||
case ioEND: /* end of range */
|
||||
mt_eor = 1; /* transfer done */
|
||||
break; }
|
||||
return dat;
|
||||
}
|
||||
|
||||
/* Unit service
|
||||
|
||||
If rewind done, reposition to start of tape, set status
|
||||
else, do operation, set done, interrupt
|
||||
|
||||
Can't be write locked, can only write lock detached unit
|
||||
*/
|
||||
|
||||
t_stat mt_svc (UNIT *uptr)
|
||||
{
|
||||
int32 ch = mt_dib.chan - 1; /* DMA/DMC ch */
|
||||
uint32 i, c1, c2, c3;
|
||||
t_mtrlnt tbc;
|
||||
t_stat st, r = SCPE_OK;
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* offline? */
|
||||
mt_err = 1;
|
||||
mt_busy = 0;
|
||||
mt_updint (0, 1); /* cmd done */
|
||||
return IORETURN (mt_stopioe, SCPE_UNATT); }
|
||||
|
||||
switch (uptr->FNC) { /* case on function */
|
||||
case FNC_REW: /* rewind (initial) */
|
||||
mt_busy = 0; /* ctlr not busy */
|
||||
uptr->FNC = uptr->FNC | FNC_2ND;
|
||||
sim_activate (uptr, mt_ctime);
|
||||
return SCPE_OK; /* continue */
|
||||
|
||||
case FNC_REW | FNC_2ND: /* rewind done */
|
||||
uptr->pos = 0; /* reposition file */
|
||||
uptr->UST = STA_BOT; /* set BOT */
|
||||
uptr->FNC = FNC_NOP; /* nop function */
|
||||
for (i = 0; i < MT_NUMDR; i++) { /* last rewind? */
|
||||
if ((mt_unit[i].FNC & 017) == FNC_REW) return SCPE_OK; }
|
||||
mt_updint (mt_rdy, 1); /* yes, motion done */
|
||||
return SCPE_OK;
|
||||
|
||||
case FNC_WEOF: /* write file mark */
|
||||
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
break; /* sched end motion */
|
||||
|
||||
case FNC_FSR: /* space fwd rec */
|
||||
if (st = sim_tape_sprecf (uptr, &tbc)) /* space fwd, err? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
break; /* sched end motion */
|
||||
|
||||
case FNC_BSR: /* space rev rec */
|
||||
if (st = sim_tape_sprecr (uptr, &tbc)) /* space rev, err? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
break; /* sched end motion */
|
||||
|
||||
case FNC_FSF: /* space fwd file */
|
||||
while ((st = sim_tape_sprecf (uptr, &tbc)) == MTSE_OK) ;
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
break; /* sched end motion */
|
||||
|
||||
case FNC_BSF: /* space rev file */
|
||||
while ((st = sim_tape_sprecr (uptr, &tbc)) == MTSE_OK) ;
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
break; /* sched end motion */
|
||||
|
||||
case FNC_EOM: /* end of motion */
|
||||
uptr->FNC = FNC_NOP; /* nop function */
|
||||
mt_busy = 0; /* not busy */
|
||||
mt_updint (mt_rdy, 1); /* end of motion */
|
||||
return SCPE_OK; /* done! */
|
||||
|
||||
/* Unit service, continued */
|
||||
|
||||
case FNC_RBCD2: case FNC_RBIN2: case FNC_RBIN3: /* read first */
|
||||
mt_ptr = 0; /* clr buf ptr */
|
||||
st = sim_tape_rdrecf (uptr, mtxb, &mt_max, DBSIZE); /* read rec */
|
||||
if (st != MTSE_OK) { /* error? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
break; } /* sched end motion */
|
||||
uptr->FNC = uptr->FNC | FNC_2ND; /* next state */
|
||||
sim_activate (uptr, mt_xtime); /* sched xfer */
|
||||
return SCPE_OK;
|
||||
|
||||
case FNC_RBCD2 | FNC_2ND: /* read, word */
|
||||
case FNC_RBIN2 | FNC_2ND:
|
||||
case FNC_RBIN3 | FNC_2ND:
|
||||
if (mt_ptr >= mt_max) break; /* record done? */
|
||||
c1 = mtxb[mt_ptr++] & 077; /* get 2 chars */
|
||||
c2 = mtxb[mt_ptr++] & 077;
|
||||
if (uptr->FNC == (FNC_RBCD2 | FNC_2ND)) { /* BCD? */
|
||||
if (c1 == 012) c1 = 0; /* change 12 to 0 */
|
||||
if (c2 == 012) c2 = 0; }
|
||||
if (uptr->FNC == (FNC_RBIN3 | FNC_2ND)) { /* read 3? */
|
||||
if (mt_ptr >= mt_max) break; /* lose wd if not enuf */
|
||||
c3 = mtxb[mt_ptr++] & 017; } /* get 3rd char */
|
||||
else c3 = 0;
|
||||
sim_activate (uptr, mt_xtime); /* no, sched word */
|
||||
if (mt_eor) return SCPE_OK; /* xfer done? */
|
||||
mt_buf = (c1 << 10) | (c2 << 4) | c3; /* pack chars */
|
||||
if (mt_rdy) mt_err = 1; /* buf full? err */
|
||||
mt_updint (1, mt_mdirq); /* set ready */
|
||||
if (mt_dma) SET_CH_REQ (ch); /* DMC/DMA? req chan */
|
||||
return SCPE_OK; /* continue */
|
||||
|
||||
case FNC_WBCD2: case FNC_WBIN2: case FNC_WBIN3: /* write first */
|
||||
mt_ptr = 0; /* clear buf ptr */
|
||||
mt_updint (1, mt_mdirq); /* set ready */
|
||||
if (mt_dma) SET_CH_REQ (ch); /* DMC/DMA? req chan */
|
||||
uptr->FNC = uptr->FNC | FNC_2ND; /* next state */
|
||||
sim_activate (uptr, mt_xtime); /* sched xfer */
|
||||
return SCPE_OK; /* continue */
|
||||
|
||||
case FNC_WBCD2 | FNC_2ND: /* write, word */
|
||||
case FNC_WBIN2 | FNC_2ND:
|
||||
case FNC_WBIN3 | FNC_2ND:
|
||||
if (mt_eor || mt_rdy) { /* done or no data? */
|
||||
if (!mt_rdy) mt_wrwd (uptr, mt_buf); /* write last word */
|
||||
if (mt_ptr) { /* any data? */
|
||||
if (st = sim_tape_wrrecf (uptr, mtxb, mt_ptr)) /* write, err? */
|
||||
r = mt_map_err (uptr, st); } /* map error */
|
||||
break; } /* sched end motion */
|
||||
mt_wrwd (uptr, mt_buf); /* write word */
|
||||
sim_activate (uptr, mt_xtime); /* no, sched word */
|
||||
mt_updint (1, mt_mdirq); /* set ready */
|
||||
if (mt_dma) SET_CH_REQ (ch); /* DMC/DMA? req chan */
|
||||
return SCPE_OK; /* continue */
|
||||
|
||||
default: /* unknown */
|
||||
break; }
|
||||
|
||||
/* End of command, process error or schedule end of motion */
|
||||
|
||||
if (r != SCPE_OK) {
|
||||
uptr->FNC = FNC_NOP; /* nop function */
|
||||
mt_busy = 0; /* not busy */
|
||||
mt_updint (mt_rdy, 1); /* end of motion */
|
||||
return r; }
|
||||
uptr->FNC = FNC_EOM; /* sched end motion */
|
||||
sim_activate (uptr, mt_ctime);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Write word to buffer */
|
||||
|
||||
void mt_wrwd (UNIT *uptr, uint32 dat)
|
||||
{
|
||||
uint32 c1, c2;
|
||||
|
||||
c1 = (dat >> 10) & 077; /* get 2 chars */
|
||||
c2 = (dat >> 4) & 077;
|
||||
if (uptr->FNC == (FNC_WBCD2 | FNC_2ND)) { /* BCD? */
|
||||
if (c1 == 0) c1 = 012; /* change 0 to 12 */
|
||||
if (c2 == 0) c2 = 012; }
|
||||
if (mt_ptr < DBSIZE) mtxb[mt_ptr++] = c1; /* store 2 char */
|
||||
if (mt_ptr < DBSIZE) mtxb[mt_ptr++] = c2;
|
||||
if ((uptr->FNC == (FNC_WBIN3 | FNC_2ND)) && /* write 3? */
|
||||
(mt_ptr < DBSIZE)) mtxb[mt_ptr++] = mt_buf & 017;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Map tape error status */
|
||||
|
||||
t_stat mt_map_err (UNIT *uptr, t_stat st)
|
||||
{
|
||||
switch (st) {
|
||||
case MTSE_FMT: /* illegal fmt */
|
||||
case MTSE_UNATT: /* unattached */
|
||||
mt_err = 1; /* reject */
|
||||
case MTSE_OK: /* no error */
|
||||
return SCPE_IERR; /* never get here! */
|
||||
case MTSE_TMK: /* end of file */
|
||||
mt_eof = 1; /* eof */
|
||||
break;
|
||||
case MTSE_INVRL: /* invalid rec lnt */
|
||||
mt_err = 1;
|
||||
return SCPE_MTRLNT;
|
||||
case MTSE_IOERR: /* IO error */
|
||||
mt_err = 1; /* error */
|
||||
if (mt_stopioe) return SCPE_IOERR;
|
||||
break;
|
||||
case MTSE_RECE: /* record in error */
|
||||
case MTSE_EOM: /* end of medium */
|
||||
mt_err = 1; /* error */
|
||||
break;
|
||||
case MTSE_BOT: /* reverse into BOT */
|
||||
uptr->UST = STA_BOT; /* set status */
|
||||
break;
|
||||
case MTSE_WRP: /* write protect */
|
||||
mt_err = 1; /* error */
|
||||
return STOP_MTWRP; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Update interrupts */
|
||||
|
||||
void mt_updint (uint32 rdy, uint32 mdirq)
|
||||
{
|
||||
mt_rdy = rdy; /* store new ready */
|
||||
mt_mdirq = mdirq; /* store new motion irq */
|
||||
if ((mt_rdy && !mt_dma) || mt_mdirq) SET_INT (INT_MT); /* update int request */
|
||||
else CLR_INT (INT_MT);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat mt_reset (DEVICE *dptr)
|
||||
{
|
||||
int32 i;
|
||||
UNIT *uptr;
|
||||
|
||||
mt_buf = 0; /* clear state */
|
||||
mt_usel = 0;
|
||||
mt_mdirq = 0;
|
||||
mt_eor = 0;
|
||||
mt_busy = 0;
|
||||
mt_rdy = 0;
|
||||
mt_eof = 0;
|
||||
mt_err = 0;
|
||||
mt_dma = 0;
|
||||
CLR_INT (INT_MT); /* clear int, enb */
|
||||
CLR_ENB (INT_MT);
|
||||
for (i = 0; i < MT_NUMDR; i++) { /* loop thru units */
|
||||
uptr = mt_dev.units + i;
|
||||
sim_tape_reset (uptr); /* reset tape */
|
||||
sim_cancel (uptr); /* cancel op */
|
||||
uptr->UST = uptr->pos? 0: STA_BOT; /* update status */
|
||||
uptr->FNC = FNC_NOP; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Attach routine */
|
||||
|
||||
t_stat mt_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
t_stat r;
|
||||
|
||||
r = sim_tape_attach (uptr, cptr); /* attach unit */
|
||||
if (r != SCPE_OK) return r; /* update status */
|
||||
uptr->UST = STA_BOT;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Detach routine */
|
||||
|
||||
t_stat mt_detach (UNIT* uptr)
|
||||
{
|
||||
uptr->UST = 0; /* update status */
|
||||
uptr->FNC = FNC_NOP; /* nop function */
|
||||
return sim_tape_detach (uptr); /* detach unit */
|
||||
}
|
|
@ -28,6 +28,7 @@
|
|||
tty 316/516-33 teleprinter
|
||||
clk/options 316/516-12 real time clocks/internal options
|
||||
|
||||
24-Oct-03 RMS Added DMA/DMC support
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
01-Mar-03 RMS Added SET/SHOW CLK FREQ support
|
||||
22-Dec-02 RMS Added break support
|
||||
|
@ -50,7 +51,7 @@ extern uint16 M[];
|
|||
extern int32 PC;
|
||||
extern int32 stop_inst;
|
||||
extern int32 C, dp, ext, extoff_pending, sc;
|
||||
extern int32 dev_ready, dev_enable;
|
||||
extern int32 dev_int, dev_enb;
|
||||
extern UNIT cpu_unit;
|
||||
|
||||
int32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */
|
||||
|
@ -58,15 +59,19 @@ int32 ptp_power = 0, ptp_ptime; /* punch power, time */
|
|||
int32 tty_mode = 0, tty_buf = 0; /* tty mode, buf */
|
||||
int32 clk_tps = 60; /* ticks per second */
|
||||
|
||||
int32 ptrio (int32 inst, int32 fnc, int32 dat, int32 dev);
|
||||
t_stat ptr_svc (UNIT *uptr);
|
||||
t_stat ptr_reset (DEVICE *dptr);
|
||||
t_stat ptr_boot (int32 unitno, DEVICE *dptr);
|
||||
int32 ptpio (int32 inst, int32 fnc, int32 dat, int32 dev);
|
||||
t_stat ptp_svc (UNIT *uptr);
|
||||
t_stat ptp_reset (DEVICE *dptr);
|
||||
int32 ttyio (int32 inst, int32 fnc, int32 dat, int32 dev);
|
||||
t_stat tti_svc (UNIT *uptr);
|
||||
t_stat tto_svc (UNIT *uptr);
|
||||
t_stat tty_reset (DEVICE *dptr);
|
||||
t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
int32 clkio (int32 inst, int32 fnc, int32 dat, int32 dev);
|
||||
t_stat clk_svc (UNIT *uptr);
|
||||
t_stat clk_reset (DEVICE *dptr);
|
||||
t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
|
@ -80,14 +85,16 @@ t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc);
|
|||
ptr_reg PTR register list
|
||||
*/
|
||||
|
||||
DIB ptr_dib = { PTR, IOBUS, 1, &ptrio };
|
||||
|
||||
UNIT ptr_unit = {
|
||||
UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0),
|
||||
SERIAL_IN_WAIT };
|
||||
|
||||
REG ptr_reg[] = {
|
||||
{ ORDATA (BUF, ptr_unit.buf, 8) },
|
||||
{ FLDATA (READY, dev_ready, INT_V_PTR) },
|
||||
{ FLDATA (ENABLE, dev_enable, INT_V_PTR) },
|
||||
{ FLDATA (READY, dev_int, INT_V_PTR) },
|
||||
{ FLDATA (ENABLE, dev_enb, INT_V_PTR) },
|
||||
{ DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT },
|
||||
{ FLDATA (STOP_IOE, ptr_stopioe, 0) },
|
||||
|
@ -97,7 +104,8 @@ DEVICE ptr_dev = {
|
|||
"PTR", &ptr_unit, ptr_reg, NULL,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &ptr_reset,
|
||||
&ptr_boot, NULL, NULL };
|
||||
&ptr_boot, NULL, NULL,
|
||||
&ptr_dib, 0 };
|
||||
|
||||
/* PTP data structures
|
||||
|
||||
|
@ -107,13 +115,15 @@ DEVICE ptr_dev = {
|
|||
ptp_reg PTP register list
|
||||
*/
|
||||
|
||||
DIB ptp_dib = { PTP, IOBUS, 1, &ptpio };
|
||||
|
||||
UNIT ptp_unit = {
|
||||
UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT };
|
||||
|
||||
REG ptp_reg[] = {
|
||||
{ ORDATA (BUF, ptp_unit.buf, 8) },
|
||||
{ FLDATA (READY, dev_ready, INT_V_PTP) },
|
||||
{ FLDATA (ENABLE, dev_enable, INT_V_PTP) },
|
||||
{ FLDATA (READY, dev_int, INT_V_PTP) },
|
||||
{ FLDATA (ENABLE, dev_enb, INT_V_PTP) },
|
||||
{ FLDATA (POWER, ptp_power, 0) },
|
||||
{ DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT },
|
||||
|
@ -121,12 +131,12 @@ REG ptp_reg[] = {
|
|||
{ FLDATA (STOP_IOE, ptp_stopioe, 0) },
|
||||
{ NULL } };
|
||||
|
||||
|
||||
DEVICE ptp_dev = {
|
||||
"PTP", &ptp_unit, ptp_reg, NULL,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &ptp_reset,
|
||||
NULL, NULL, NULL };
|
||||
NULL, NULL, NULL,
|
||||
&ptp_dib, 0 };
|
||||
|
||||
/* TTY data structures
|
||||
|
||||
|
@ -139,6 +149,8 @@ DEVICE ptp_dev = {
|
|||
#define TTI 0
|
||||
#define TTO 1
|
||||
|
||||
DIB tty_dib = { TTY, IOBUS, 1, &ttyio };
|
||||
|
||||
UNIT tty_unit[] = {
|
||||
{ UDATA (&tti_svc, UNIT_KSR, 0), KBD_POLL_WAIT },
|
||||
{ UDATA (&tto_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT } };
|
||||
|
@ -146,8 +158,8 @@ UNIT tty_unit[] = {
|
|||
REG tty_reg[] = {
|
||||
{ ORDATA (BUF, tty_buf, 8) },
|
||||
{ FLDATA (MODE, tty_mode, 0) },
|
||||
{ FLDATA (READY, dev_ready, INT_V_TTY) },
|
||||
{ FLDATA (ENABLE, dev_enable, INT_V_TTY) },
|
||||
{ FLDATA (READY, dev_int, INT_V_TTY) },
|
||||
{ FLDATA (ENABLE, dev_enb, INT_V_TTY) },
|
||||
{ DRDATA (KPOS, tty_unit[TTI].pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (KTIME, tty_unit[TTI].wait, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TPOS, tty_unit[TTO].pos, T_ADDR_W), PV_LEFT },
|
||||
|
@ -164,7 +176,8 @@ DEVICE tty_dev = {
|
|||
"TTY", tty_unit, tty_reg, tty_mod,
|
||||
2, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &tty_reset,
|
||||
NULL, NULL, NULL };
|
||||
NULL, NULL, NULL,
|
||||
&tty_dib, 0 };
|
||||
|
||||
/* CLK data structures
|
||||
|
||||
|
@ -174,12 +187,14 @@ DEVICE tty_dev = {
|
|||
clk_reg CLK register list
|
||||
*/
|
||||
|
||||
DIB clk_dib = { CLK_KEYS, IOBUS, 1, &clkio };
|
||||
|
||||
UNIT clk_unit = {
|
||||
UDATA (&clk_svc, 0, 0), 16000 };
|
||||
|
||||
REG clk_reg[] = {
|
||||
{ FLDATA (READY, dev_ready, INT_V_CLK) },
|
||||
{ FLDATA (ENABLE, dev_enable, INT_V_CLK) },
|
||||
{ FLDATA (READY, dev_int, INT_V_CLK) },
|
||||
{ FLDATA (ENABLE, dev_enb, INT_V_CLK) },
|
||||
{ DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TPS, clk_tps, 8), PV_LEFT + REG_HRO },
|
||||
{ NULL } };
|
||||
|
@ -197,11 +212,12 @@ DEVICE clk_dev = {
|
|||
"CLK", &clk_unit, clk_reg, clk_mod,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
NULL, NULL, &clk_reset,
|
||||
NULL, NULL, NULL };
|
||||
NULL, NULL, NULL,
|
||||
&clk_dib, 0 };
|
||||
|
||||
/* Paper tape reader: IO routine */
|
||||
|
||||
int32 ptrio (int32 inst, int32 fnc, int32 dat)
|
||||
int32 ptrio (int32 inst, int32 fnc, int32 dat, int32 dev)
|
||||
{
|
||||
switch (inst) { /* case on opcode */
|
||||
case ioOCP: /* OCP */
|
||||
|
@ -211,14 +227,14 @@ case ioOCP: /* OCP */
|
|||
break;
|
||||
case ioSKS: /* SKS */
|
||||
if (fnc & 013) return IOBADFNC (dat); /* only fnc 0,4 */
|
||||
if (((fnc == 0) && TST_READY (INT_PTR)) || /* fnc 0? skip rdy */
|
||||
if (((fnc == 0) && TST_INT (INT_PTR)) || /* fnc 0? skip rdy */
|
||||
((fnc == 4) && !TST_INTREQ (INT_PTR))) /* fnc 4? skip !int */
|
||||
return IOSKIP (dat);
|
||||
break;
|
||||
case ioINA: /* INA */
|
||||
if (fnc & 007) return IOBADFNC (dat); /* only fnc 0,10 */
|
||||
if (TST_READY (INT_PTR)) { /* ready? */
|
||||
CLR_READY (INT_PTR); /* clear ready */
|
||||
if (fnc) return IOBADFNC (dat); /* only fnc 0 */
|
||||
if (TST_INT (INT_PTR)) { /* ready? */
|
||||
CLR_INT (INT_PTR); /* clear ready */
|
||||
return IOSKIP (ptr_unit.buf | dat); } /* ret buf, skip */
|
||||
break; } /* end case op */
|
||||
return dat;
|
||||
|
@ -239,7 +255,7 @@ if ((temp = getc (ptr_unit.fileref)) == EOF) { /* read byte */
|
|||
else perror ("PTR I/O error");
|
||||
clearerr (ptr_unit.fileref);
|
||||
return SCPE_IOERR; }
|
||||
SET_READY (INT_PTR); /* set ready flag */
|
||||
SET_INT (INT_PTR); /* set ready flag */
|
||||
ptr_unit.buf = temp & 0377; /* get byte */
|
||||
ptr_unit.pos = ftell (ptr_unit.fileref); /* update pos */
|
||||
sim_activate (&ptr_unit, ptr_unit.wait); /* reactivate */
|
||||
|
@ -250,8 +266,8 @@ return SCPE_OK;
|
|||
|
||||
t_stat ptr_reset (DEVICE *dptr)
|
||||
{
|
||||
CLR_READY (INT_PTR); /* clear ready, enb */
|
||||
CLR_ENABLE (INT_PTR);
|
||||
CLR_INT (INT_PTR); /* clear ready, enb */
|
||||
CLR_ENB (INT_PTR);
|
||||
ptr_unit.buf = 0; /* clear buffer */
|
||||
sim_cancel (&ptr_unit); /* deactivate unit */
|
||||
return SCPE_OK;
|
||||
|
@ -292,13 +308,13 @@ return SCPE_OK;
|
|||
|
||||
/* Paper tape punch: IO routine */
|
||||
|
||||
int32 ptpio (int32 inst, int32 fnc, int32 dat)
|
||||
int32 ptpio (int32 inst, int32 fnc, int32 dat, int32 dev)
|
||||
{
|
||||
switch (inst) { /* case on opcode */
|
||||
case ioOCP: /* OCP */
|
||||
if (fnc & 016) return IOBADFNC (dat); /* only fnc 0,1 */
|
||||
if (fnc) { /* fnc 1? pwr off */
|
||||
CLR_READY (INT_PTP); /* not ready */
|
||||
CLR_INT (INT_PTP); /* not ready */
|
||||
ptp_power = 0; /* turn off power */
|
||||
sim_cancel (&ptp_unit); } /* stop punch */
|
||||
else if (ptp_power == 0) /* fnc 0? start */
|
||||
|
@ -307,7 +323,7 @@ case ioOCP: /* OCP */
|
|||
case ioSKS: /* SKS */
|
||||
if ((fnc & 012) || (fnc == 005)) /* only 0, 1, 4 */
|
||||
return IOBADFNC (dat);
|
||||
if (((fnc == 00) && TST_READY (INT_PTP)) || /* fnc 0? skip rdy */
|
||||
if (((fnc == 00) && TST_INT (INT_PTP)) || /* fnc 0? skip rdy */
|
||||
((fnc == 01) /* fnc 1? skip ptp on */
|
||||
&& (ptp_power || sim_is_active (&ptp_unit))) ||
|
||||
((fnc == 04) && !TST_INTREQ (INT_PTP))) /* fnc 4? skip !int */
|
||||
|
@ -315,8 +331,8 @@ case ioSKS: /* SKS */
|
|||
break;
|
||||
case ioOTA: /* OTA */
|
||||
if (fnc) return IOBADFNC (dat); /* only fnc 0 */
|
||||
if (TST_READY (INT_PTP)) { /* if ptp ready */
|
||||
CLR_READY (INT_PTP); /* clear ready */
|
||||
if (TST_INT (INT_PTP)) { /* if ptp ready */
|
||||
CLR_INT (INT_PTP); /* clear ready */
|
||||
ptp_unit.buf = dat & 0377; /* store byte */
|
||||
sim_activate (&ptp_unit, ptp_unit.wait);
|
||||
return IOSKIP (dat); } /* skip return */
|
||||
|
@ -329,7 +345,7 @@ return dat;
|
|||
t_stat ptp_svc (UNIT *uptr)
|
||||
{
|
||||
|
||||
SET_READY (INT_PTP); /* set flag */
|
||||
SET_INT (INT_PTP); /* set flag */
|
||||
if (ptp_power == 0) { /* power on? */
|
||||
ptp_power = 1; /* ptp is ready */
|
||||
return SCPE_OK; }
|
||||
|
@ -347,8 +363,8 @@ return SCPE_OK;
|
|||
|
||||
t_stat ptp_reset (DEVICE *dptr)
|
||||
{
|
||||
CLR_READY (INT_PTP); /* clear ready, enb */
|
||||
CLR_ENABLE (INT_PTP);
|
||||
CLR_INT (INT_PTP); /* clear ready, enb */
|
||||
CLR_ENB (INT_PTP);
|
||||
ptp_power = 0; /* power off */
|
||||
ptp_unit.buf = 0; /* clear buffer */
|
||||
sim_cancel (&ptp_unit); /* deactivate unit */
|
||||
|
@ -357,22 +373,22 @@ return SCPE_OK;
|
|||
|
||||
/* Terminal: IO routine */
|
||||
|
||||
int32 ttyio (int32 inst, int32 fnc, int32 dat)
|
||||
int32 ttyio (int32 inst, int32 fnc, int32 dat, int32 dev)
|
||||
{
|
||||
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 */
|
||||
SET_READY (INT_TTY);
|
||||
SET_INT (INT_TTY);
|
||||
tty_mode = 1; } /* mode is output */
|
||||
else if ((fnc == 0) && tty_mode) { /* output to input? */
|
||||
CLR_READY (INT_TTY); /* clear ready */
|
||||
CLR_INT (INT_TTY); /* clear ready */
|
||||
tty_mode = 0; } /* mode is input */
|
||||
break;
|
||||
case ioSKS: /* SKS */
|
||||
if (fnc & 012) return IOBADFNC (dat); /* fnc 0,1,4,5 */
|
||||
if (((fnc == 0) && TST_READY (INT_TTY)) || /* fnc 0? skip rdy */
|
||||
if (((fnc == 0) && TST_INT (INT_TTY)) || /* fnc 0? skip rdy */
|
||||
((fnc == 1) && /* fnc 1? skip !busy */
|
||||
tty_mode && !sim_is_active (&tty_unit[TTO])) ||
|
||||
((fnc == 4) && !TST_INTREQ (INT_TTY)) || /* fnc 4? skip !int */
|
||||
|
@ -381,22 +397,22 @@ case ioSKS: /* SKS */
|
|||
return IOSKIP (dat);
|
||||
break;
|
||||
case ioINA: /* INA */
|
||||
if (fnc & 005) return IOBADFNC (dat); /* only 0,2,10,12 */
|
||||
if (TST_READY (INT_TTY)) { /* ready? */
|
||||
if (tty_mode == 0) CLR_READY (INT_TTY); /* inp? clear rdy */
|
||||
if (fnc & 005) return IOBADFNC (dat); /* only 0,2 */
|
||||
if (TST_INT (INT_TTY)) { /* ready? */
|
||||
if (tty_mode == 0) CLR_INT (INT_TTY); /* inp? clear rdy */
|
||||
return IOSKIP (dat |
|
||||
(tty_buf & ((fnc & 002)? 077: 0377))); }
|
||||
break;
|
||||
case ioOTA:
|
||||
if (fnc & 015) return IOBADFNC (dat); /* only 0,2 */
|
||||
if (TST_READY (INT_TTY)) { /* ready? */
|
||||
if (TST_INT (INT_TTY)) { /* ready? */
|
||||
tty_buf = dat & 0377; /* store char */
|
||||
if (fnc & 002) { /* binary mode? */
|
||||
tty_buf = tty_buf | 0100; /* set ch 7 */
|
||||
if (tty_buf & 040) tty_buf = tty_buf & 0277; }
|
||||
if (tty_mode) {
|
||||
sim_activate (&tty_unit[TTO], tty_unit[TTO].wait);
|
||||
CLR_READY (INT_TTY); }
|
||||
CLR_INT (INT_TTY); }
|
||||
return IOSKIP (dat); }
|
||||
break; } /* end case op */
|
||||
return dat;
|
||||
|
@ -419,7 +435,7 @@ else c = c & ((tty_unit[TTI].flags & UNIT_8B)? 0377: 0177);
|
|||
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 */
|
||||
SET_INT (INT_TTY); /* set flag */
|
||||
if (out) sim_putchar (out); } /* echo */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -429,12 +445,14 @@ t_stat tto_svc (UNIT *uptr)
|
|||
int32 c;
|
||||
t_stat r;
|
||||
|
||||
SET_READY (INT_TTY); /* set done flag */
|
||||
if (tty_unit[TTO].flags & UNIT_KSR) { /* UC only? */
|
||||
c = tty_buf & 0177; /* mask to 7b */
|
||||
if (islower (c)) c = toupper (c); } /* cvt to UC */
|
||||
else c = tty_buf & ((tty_unit[TTO].flags & UNIT_8B)? 0377: 0177);
|
||||
if ((r = sim_putchar (c)) != SCPE_OK) return r; /* output char */
|
||||
if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */
|
||||
sim_activate (uptr, uptr->wait); /* try again */
|
||||
return ((r == SCPE_STALL)? SCPE_OK: r); } /* !stall? report */
|
||||
SET_INT (INT_TTY); /* set done flag */
|
||||
tty_unit[TTO].pos = tty_unit[TTO].pos + 1;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -443,8 +461,8 @@ return SCPE_OK;
|
|||
|
||||
t_stat tty_reset (DEVICE *dptr)
|
||||
{
|
||||
CLR_READY (INT_TTY); /* clear ready, enb */
|
||||
CLR_ENABLE (INT_TTY);
|
||||
CLR_INT (INT_TTY); /* clear ready, enb */
|
||||
CLR_ENB (INT_TTY);
|
||||
tty_mode = 0; /* mode = input */
|
||||
tty_buf = 0;
|
||||
sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* activate poll */
|
||||
|
@ -461,12 +479,12 @@ return SCPE_OK;
|
|||
|
||||
/* Clock/options: IO routine */
|
||||
|
||||
int32 clkio (int32 inst, int32 fnc, int32 dat)
|
||||
int32 clkio (int32 inst, int32 fnc, int32 dat, int32 dev)
|
||||
{
|
||||
switch (inst) { /* case on opcode */
|
||||
case ioOCP: /* OCP */
|
||||
if (fnc & 015) return IOBADFNC (dat); /* only fnc 0,2 */
|
||||
CLR_READY (INT_CLK); /* reset ready */
|
||||
CLR_INT (INT_CLK); /* reset ready */
|
||||
if (fnc) sim_cancel (&clk_unit); /* fnc = 2? stop */
|
||||
else { /* fnc = 0? */
|
||||
if (!sim_is_active (&clk_unit))
|
||||
|
@ -477,13 +495,13 @@ case ioSKS: /* SKS */
|
|||
if (fnc == 0) { /* clock skip !int */
|
||||
if (!TST_INTREQ (INT_CLK)) return IOSKIP (dat); }
|
||||
else if ((fnc & 007) == 002) { /* mem parity? */
|
||||
if (((fnc == 002) && !TST_READY (INT_MPE)) ||
|
||||
((fnc == 012) && TST_READY (INT_MPE)))
|
||||
if (((fnc == 002) && !TST_INT (INT_MPE)) ||
|
||||
((fnc == 012) && TST_INT (INT_MPE)))
|
||||
return IOSKIP (dat); }
|
||||
else return IOBADFNC (dat); /* invalid fnc */
|
||||
break;
|
||||
case ioOTA: /* OTA */
|
||||
if (fnc == 000) dev_enable = dat; /* SMK */
|
||||
if (fnc == 000) dev_enb = dat; /* SMK */
|
||||
else if (fnc == 010) { /* OTK */
|
||||
C = (dat >> 15) & 1; /* set C */
|
||||
if (cpu_unit.flags & UNIT_HSA) /* HSA included? */
|
||||
|
@ -505,7 +523,7 @@ t_stat clk_svc (UNIT *uptr)
|
|||
{
|
||||
|
||||
M[M_CLK] = M[M_CLK + 1] & DMASK; /* increment mem ctr */
|
||||
if (M[M_CLK] == 0) SET_READY (INT_CLK); /* = 0? set flag */
|
||||
if (M[M_CLK] == 0) SET_INT (INT_CLK); /* = 0? set flag */
|
||||
sim_activate (&clk_unit, sim_rtc_calb (clk_tps)); /* reactivate */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -514,8 +532,8 @@ return SCPE_OK;
|
|||
|
||||
t_stat clk_reset (DEVICE *dptr)
|
||||
{
|
||||
CLR_READY (INT_CLK); /* clear ready, enb */
|
||||
CLR_ENABLE (INT_CLK);
|
||||
CLR_INT (INT_CLK); /* clear ready, enb */
|
||||
CLR_ENB (INT_CLK);
|
||||
sim_cancel (&clk_unit); /* deactivate unit */
|
||||
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.
|
||||
|
||||
24-Oct-03 RMS Added DMA/DMC support
|
||||
17-Sep-01 RMS Removed multiconsole support
|
||||
*/
|
||||
|
||||
|
@ -31,9 +32,14 @@
|
|||
|
||||
extern DEVICE cpu_dev;
|
||||
extern UNIT cpu_unit;
|
||||
extern DEVICE ptr_dev, ptp_dev;
|
||||
extern DEVICE tty_dev, lpt_dev;
|
||||
extern DEVICE ptr_dev;
|
||||
extern DEVICE ptp_dev;
|
||||
extern DEVICE tty_dev;
|
||||
extern DEVICE lpt_dev;
|
||||
extern DEVICE clk_dev;
|
||||
extern DEVICE dp_dev;
|
||||
extern DEVICE fhd_dev;
|
||||
extern DEVICE mt_dev;
|
||||
extern REG cpu_reg[];
|
||||
extern uint16 M[];
|
||||
extern int32 sim_switches;
|
||||
|
@ -54,10 +60,16 @@ REG *sim_PC = &cpu_reg[0];
|
|||
|
||||
int32 sim_emax = 1;
|
||||
|
||||
DEVICE *sim_devices[] = { &cpu_dev,
|
||||
&ptr_dev, &ptp_dev,
|
||||
&tty_dev, &lpt_dev,
|
||||
DEVICE *sim_devices[] = {
|
||||
&cpu_dev,
|
||||
&ptr_dev,
|
||||
&ptp_dev,
|
||||
&tty_dev,
|
||||
&lpt_dev,
|
||||
&clk_dev,
|
||||
&dp_dev,
|
||||
&fhd_dev,
|
||||
&mt_dev,
|
||||
NULL };
|
||||
|
||||
const char *sim_stop_messages[] = {
|
||||
|
@ -66,7 +78,11 @@ const char *sim_stop_messages[] = {
|
|||
"Unimplemented I/O device",
|
||||
"HALT instruction",
|
||||
"Breakpoint",
|
||||
"Indirect address loop" };
|
||||
"Indirect address loop",
|
||||
"DMA error",
|
||||
"MT write protected",
|
||||
"DP write overrun, track destroyed",
|
||||
"DP track format invalid" };
|
||||
|
||||
/* Binary loader
|
||||
|
||||
|
|
|
@ -291,6 +291,7 @@ t_stat drc_svc (UNIT *uptr)
|
|||
{
|
||||
int32 devd, trk, sec;
|
||||
uint32 da;
|
||||
uint16 *bptr = uptr->filebuf;
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) {
|
||||
drc_sta = DRS_ABO;
|
||||
|
@ -304,7 +305,7 @@ da = ((trk * DR_NUMSC) + sec) * DR_NUMWD;
|
|||
|
||||
if (drc_cw & CW_WR) { /* write? */
|
||||
if ((da < uptr->capac) && (sec < DR_NUMSC)) {
|
||||
*(((uint16 *) uptr->filebuf) + da + drd_ptr) = drd_obuf;
|
||||
bptr[da + drd_ptr] = drd_obuf;
|
||||
if (((uint32) (da + drd_ptr)) >= uptr->hwmark)
|
||||
uptr->hwmark = da + drd_ptr + 1; }
|
||||
drd_ptr = dr_incda (trk, sec, drd_ptr); /* inc disk addr */
|
||||
|
@ -313,12 +314,12 @@ if (drc_cw & CW_WR) { /* write? */
|
|||
sim_activate (uptr, dr_time); } /* sched next word */
|
||||
else if (drd_ptr) { /* done, need to fill? */
|
||||
for ( ; drd_ptr < DR_NUMWD; drd_ptr++)
|
||||
*(((uint16 *) uptr->filebuf) + da + drd_ptr) = 0; }
|
||||
bptr[da + drd_ptr] = 0; }
|
||||
} /* end write */
|
||||
else { /* read */
|
||||
if (CMD (devd)) { /* dch active? */
|
||||
if ((da >= uptr->capac) || (sec >= DR_NUMSC)) drd_ibuf = 0;
|
||||
else drd_ibuf = *(((uint16 *) uptr->filebuf) + da + drd_ptr);
|
||||
else drd_ibuf = bptr[da + drd_ptr];
|
||||
drd_ptr = dr_incda (trk, sec, drd_ptr);
|
||||
setFLG (devd); /* set dch flg */
|
||||
sim_activate (uptr, dr_time); } /* sched next word */
|
||||
|
@ -367,6 +368,7 @@ if (sz == 0) return SCPE_IERR;
|
|||
uptr->capac = sz;
|
||||
return attach_unit (uptr, cptr);
|
||||
}
|
||||
|
||||
/* Set size routine */
|
||||
|
||||
t_stat dr_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
ipli, iplo 12556B interprocessor link pair
|
||||
|
||||
21-Dec-03 RMS Adjusted ipl_ptime for TSB (from Mike Gemeny)
|
||||
09-May-03 RMS Added network device flag
|
||||
31-Jan-03 RMS Links are full duplex (found by Mike Gemeny)
|
||||
*/
|
||||
|
@ -49,7 +50,7 @@
|
|||
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_ptime = 31; /* polling interval */
|
||||
int32 ipl_stopioe = 0; /* stop on error */
|
||||
int32 ipl_hold[2] = { 0 }; /* holding character */
|
||||
|
||||
|
@ -339,7 +340,7 @@ return SCPE_OK;
|
|||
|
||||
t_stat ipl_detach (UNIT *uptr)
|
||||
{
|
||||
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */
|
||||
if (!(uptr->flags & UNIT_ATT)) 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 */
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
mt 12559A 3030 nine track magnetic tape
|
||||
|
||||
21-Dec-03 RMS Adjusted msc_ctime for TSB (from Mike Gemeny)
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
28-Mar-03 RMS Added multiformat support
|
||||
28-Feb-03 RMS Revised for magtape library
|
||||
|
@ -92,7 +93,7 @@ int32 mtc_fnc = 0; /* function */
|
|||
int32 mtc_sta = 0; /* status register */
|
||||
int32 mtc_dtf = 0; /* data xfer flop */
|
||||
int32 mtc_1st = 0; /* first svc flop */
|
||||
int32 mtc_ctime = 1000; /* command wait */
|
||||
int32 mtc_ctime = 40; /* command wait */
|
||||
int32 mtc_gtime = 1000; /* gap stop time */
|
||||
int32 mtc_xtime = 15; /* data xfer time */
|
||||
int32 mtc_stopioe = 1; /* stop on error */
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
mux,muxl,muxc 12920A terminal multiplexor
|
||||
|
||||
21-Dec-03 RMS Added invalid character screening for TSB (from Mike Gemeny)
|
||||
09-May-03 RMS Added network device flag
|
||||
01-Nov-02 RMS Added 7B/8B support
|
||||
22-Aug-02 RMS Updated for changes to sim_tmxr
|
||||
|
@ -526,6 +527,9 @@ if (mux_ldsc[ln].conn) { /* connected? */
|
|||
if (mux_xpar[ln] & OTL_DIAG) /* xmt diag? */
|
||||
mux_diag (mux_xbuf[ln]); /* before munge */
|
||||
mux_xdon[ln] = 1; /* set done */
|
||||
if (!(muxl_unit[ln].flags & UNIT_8B) && /* not transparent? */
|
||||
(c != 0x7f) && (c != 0x13) && /* not del, ^S? */
|
||||
(c != 0x11) && (c != 0x5)) /* not ^Q, ^E? */
|
||||
tmxr_putc_ln (lp, c); /* output char */
|
||||
tmxr_poll_tx (&mux_desc); } } /* poll xmt */
|
||||
else { /* buf full */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* hp2100_stddev.c: HP2100 standard devices simulator
|
||||
|
||||
Copyright (c) 1993-2003, Robert M. Supnik
|
||||
Copyright (c) 1993-2004, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -28,6 +28,7 @@
|
|||
tty 12531C buffered teleprinter interface
|
||||
clk 12539C time base generator
|
||||
|
||||
29-Mar-03 RMS Added support for console backpressure
|
||||
25-Apr-03 RMS Added extended file support
|
||||
22-Dec-02 RMS Added break support
|
||||
01-Nov-02 RMS Revised BOOT command for IBL ROMs
|
||||
|
@ -538,15 +539,20 @@ return dat;
|
|||
|
||||
t_stat tto_out (int32 c)
|
||||
{
|
||||
t_stat ret = SCPE_OK;
|
||||
t_stat r;
|
||||
|
||||
if (tty_mode & TM_PRI) { /* printing? */
|
||||
if (tty_unit[TTO].flags & UNIT_UC) { /* UC only? */
|
||||
c = c & 0177;
|
||||
if (islower (c)) c = toupper (c); }
|
||||
else c = c & ((tty_unit[TTO].flags & UNIT_8B)? 0377: 0177);
|
||||
ret = sim_putchar (c); /* output char */
|
||||
if (r = sim_putchar_s (c)) return r; /* output char */
|
||||
tty_unit[TTO].pos = tty_unit[TTO].pos + 1; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat ttp_out (int32 c)
|
||||
{
|
||||
if (tty_mode & TM_PUN) { /* punching? */
|
||||
if ((tty_unit[TTP].flags & UNIT_ATT) == 0) /* attached? */
|
||||
return IORETURN (ttp_stopioe, SCPE_UNATT);
|
||||
|
@ -555,7 +561,7 @@ if (tty_mode & TM_PUN) { /* punching? */
|
|||
clearerr (tty_unit[TTP].fileref);
|
||||
return SCPE_IOERR; }
|
||||
tty_unit[TTP].pos = ftell (tty_unit[TTP].fileref); }
|
||||
return ret;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat tti_svc (UNIT *uptr)
|
||||
|
@ -574,19 +580,25 @@ 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 */
|
||||
if (c) return tto_out (c); } /* echo or punch? */
|
||||
if (c) {
|
||||
tto_out (c); /* echo? */
|
||||
return ttp_out (c); } } /* punch? */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat tto_svc (UNIT *uptr)
|
||||
{
|
||||
int32 c, dev;
|
||||
t_stat r;
|
||||
|
||||
c = tty_buf; /* get char */
|
||||
tty_buf = 0377; /* defang buf */
|
||||
if ((r = tto_out (c)) != SCPE_OK) { /* output; error? */
|
||||
sim_activate (uptr, uptr->wait); /* retry */
|
||||
return ((r == SCPE_STALL)? SCPE_OK: r); } /* !stall? report */
|
||||
dev = tty_dib.devno; /* get device no */
|
||||
setFLG (dev); /* set done flag */
|
||||
c = tty_buf;
|
||||
tty_buf = 0377; /* defang buf */
|
||||
return tto_out (c); /* print and/or punch */
|
||||
return ttp_out (c); /* punch if enabled */
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
This CPU module incorporates code and comments from the 1620 simulator by
|
||||
Geoff Kuenning, with his permission.
|
||||
|
||||
02-Nov-03 RMS Fixed bug in branch digit (found by Dave Babcock)
|
||||
21-Aug-03 RMS Fixed bug in immediate index add (found by Michael Short)
|
||||
25-Apr-03 RMS Changed t_addr to uint32 throughout
|
||||
18-Oct-02 RMS Fixed bugs in invalid result testing (found by Hans Pufal)
|
||||
|
@ -567,10 +568,10 @@ case OP_BB:
|
|||
else reason = STOP_INVRTN; /* MAR check */
|
||||
break;
|
||||
|
||||
/* Branch on digit (zero) - P,Q are valid */
|
||||
/* Branch on digit (not zero) - P,Q are valid */
|
||||
|
||||
case OP_BD:
|
||||
if ((M[QAR] & DIGIT) == 0) { /* digit == 0? */
|
||||
if ((M[QAR] & DIGIT) != 0) { /* digit != 0? */
|
||||
BRANCH (PAR); } /* branch */
|
||||
break;
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
lpt 1443 line printer
|
||||
|
||||
29-Dec-03 RMS Fixed bug in scheduling
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
*/
|
||||
|
||||
|
@ -217,7 +218,7 @@ if ((lpt_unit.flags & UNIT_ATT) == 0) { /* not attached? */
|
|||
return SCPE_UNATT; }
|
||||
|
||||
ind[IN_PRBSY] = 1; /* print busy */
|
||||
sim_activate (&lpt_unit, lpt_unit.time); /* start timer */
|
||||
sim_activate (&lpt_unit, lpt_unit.wait); /* start timer */
|
||||
|
||||
for (i = LPT_WIDTH; i <= LPT_BSIZE; i++) /* clear unprintable */
|
||||
lpt_buf[i] = ' ';
|
||||
|
|
Before Width: | Height: | Size: 867 KiB After Width: | Height: | Size: 372 KiB |
BIN
Ibm1130/1132empty.bmp
Normal file
After Width: | Height: | Size: 6.1 KiB |
BIN
Ibm1130/1132full.bmp
Normal file
After Width: | Height: | Size: 6.1 KiB |
BIN
Ibm1130/1442empty.bmp
Normal file
After Width: | Height: | Size: 6.1 KiB |
BIN
Ibm1130/1442eof.bmp
Normal file
After Width: | Height: | Size: 6.1 KiB |
BIN
Ibm1130/1442full.bmp
Normal file
After Width: | Height: | Size: 6.1 KiB |
BIN
Ibm1130/1442middle.bmp
Normal file
After Width: | Height: | Size: 6.1 KiB |
|
@ -82,9 +82,9 @@ $(OUTDIR)/ibm1130.bsc : $(OUTDIR) $(BSC32_SBRS)
|
|||
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib wsock32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib wsock32.lib shell32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386
|
||||
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib\
|
||||
wsock32.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no\
|
||||
wsock32.lib shell32.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no\
|
||||
/PDB:$(OUTDIR)/"ibm1130.pdb" /MACHINE:I386 /OUT:$(OUTDIR)/"ibm1130.exe"
|
||||
DEF_FILE=
|
||||
LINK32_OBJS= \
|
||||
|
@ -161,9 +161,10 @@ $(OUTDIR)/ibm1130.bsc : $(OUTDIR) $(BSC32_SBRS)
|
|||
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib wsock32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib wsock32.lib shell32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386
|
||||
# SUBTRACT LINK32 /MAP
|
||||
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib comdlg32.lib advapi32.lib\
|
||||
wsock32.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes\
|
||||
wsock32.lib shell32.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes\
|
||||
/PDB:$(OUTDIR)/"ibm1130.pdb" /DEBUG /MACHINE:I386 /OUT:$(OUTDIR)/"ibm1130.exe"
|
||||
DEF_FILE=
|
||||
LINK32_OBJS= \
|
||||
|
|
|
@ -45,9 +45,21 @@ END
|
|||
// Bitmap
|
||||
//
|
||||
|
||||
IDB_CONSOLE BITMAP DISCARDABLE "1130consoleblank.bmp"
|
||||
IDB_CONSOLE BITMAP "1130consoleblank.bmp"
|
||||
FULL_1442 BITMAP "1442full.bmp"
|
||||
EOF_1442 BITMAP "1442eof.bmp"
|
||||
EMPTY_1442 BITMAP "1442empty.bmp"
|
||||
MIDDLE_1442 BITMAP "1442middle.bmp"
|
||||
FULL_1132 BITMAP "1132full.bmp"
|
||||
EMPTY_1132 BITMAP "1132empty.bmp"
|
||||
|
||||
IDC_HAND CURSOR DISCARDABLE "HAND.CUR"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Cursor
|
||||
//
|
||||
|
||||
IDC_HAND CURSOR "HAND.CUR"
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
16-Aug-02 BLK Fixed bug in multiply instruction; didn't work with negative values
|
||||
18-Mar-03 BLK Fixed bug in divide instruction; didn't work with negative values
|
||||
23-Jul-03 BLK Prevented tti polling in CGI mode
|
||||
24-Nov-03 BLK Fixed carry bit error in subtract and subtract double, found by Bob Flanders
|
||||
|
||||
The register state for the IBM 1130 CPU is:
|
||||
|
||||
|
@ -556,6 +557,8 @@ t_stat sim_instr (void)
|
|||
if (cpu_unit.flags & UNIT_ATT)
|
||||
trace_io("* XIO %s %s mod %02x addr %04x", xio_funcs[iocc_func], xio_devs[iocc_dev], iocc_mod, iocc_addr);
|
||||
|
||||
// fprintf(stderr, "* XIO %s %s mod %02x addr %04x\n", xio_funcs[iocc_func], xio_devs[iocc_dev], iocc_mod, iocc_addr);
|
||||
|
||||
ACC = 0; /* ACC is destroyed, and default XIO_SENSE_DEV result is 0 */
|
||||
|
||||
switch (iocc_func) {
|
||||
|
@ -895,7 +898,7 @@ t_stat sim_instr (void)
|
|||
src2 = ReadW(eaddr);
|
||||
ACC = (ACC-src2) & 0xFFFF;
|
||||
|
||||
C = src2 < src;
|
||||
C = src < src2;
|
||||
if (! V)
|
||||
V = SIGN_BIT((src ^ src2) & (src ^ ACC));
|
||||
break;
|
||||
|
@ -907,7 +910,7 @@ t_stat sim_instr (void)
|
|||
ACC = (dst >> 16) & 0xFFFF;
|
||||
EXT = dst & 0xFFFF;
|
||||
|
||||
C = (unsigned int32) src2 < (unsigned int32) src;
|
||||
C = (unsigned int32) src < (unsigned int32) src2;
|
||||
if (! V)
|
||||
V = DWSIGN_BIT((src ^ src2) & (src ^ dst));
|
||||
break;
|
||||
|
@ -1527,7 +1530,7 @@ static t_stat cpu_attach (UNIT *uptr, char *cptr)
|
|||
fclose(fd);
|
||||
}
|
||||
|
||||
return attach_unit(uptr, cptr);
|
||||
return attach_unit(uptr, quotefix(cptr)); /* fix quotes in filenames & attach */
|
||||
}
|
||||
|
||||
static void trace_instruction (void)
|
||||
|
@ -1795,6 +1798,7 @@ static void cgi_stop(t_stat reason)
|
|||
ORIGIN orig;
|
||||
char *msg;
|
||||
} pretstop[] = {
|
||||
0x8000, O_FORTRAN, "I/O attempted on invalid unit # or uninstalled device (just a guess)",
|
||||
0xF000, O_FORTRAN, "No *IOCS was specified but I/O was attempted",
|
||||
0xF001, O_FORTRAN, "Local unit defined incorrectly, or no *IOCS for specified device",
|
||||
0xF002, O_FORTRAN, "Requested record exceeds buffer size",
|
||||
|
|
|
@ -260,6 +260,8 @@ void xio_error (char *msg);
|
|||
void bail (char *msg);
|
||||
t_stat load_cr_boot (int drv, int switches);
|
||||
t_stat cr_boot (int unitno, DEVICE *dptr);
|
||||
t_stat cr_rewind (void);
|
||||
t_stat cr_detach (UNIT *uptr);
|
||||
void calc_ints (void); /* recalculate interrupt bitmask */
|
||||
void trace_io (char *fmt, ...); /* debugging printout */
|
||||
void scp_panic (char *msg); /* bail out of simulator */
|
||||
|
@ -269,9 +271,12 @@ char hollerith_to_ascii (uint16 hol); /* for debugging use only */
|
|||
t_bool gdu_active (void);
|
||||
void remark_cmd (char *remark);
|
||||
void stuff_cmd (char *cmd);
|
||||
t_bool stuff_and_wait (char *cmd, int timeout, int delay);
|
||||
void update_gui (t_bool force);
|
||||
void sim_init (void);
|
||||
t_stat register_cmd (char *name, t_stat (*action)(int32 flag, char *ptr), int arg, char *help);
|
||||
t_stat basic_attach (UNIT *uptr, char *cptr);
|
||||
char * quotefix (char * cptr);
|
||||
|
||||
/* GUI interface routines */
|
||||
t_bool keyboard_is_busy (void);
|
||||
|
|
|
@ -513,7 +513,7 @@ static t_stat dsk_attach (UNIT *uptr, char *cptr)
|
|||
SETBIT(uptr->flags, UNIT_ROABLE|UNIT_MUSTBUF); // but don't set the UNIT_RONLY flag so DMS can write to the buffered image
|
||||
}
|
||||
|
||||
if ((rval = attach_unit(uptr, cptr)) != SCPE_OK) { // mount new disk
|
||||
if ((rval = attach_unit(uptr, quotefix(cptr))) != SCPE_OK) { // mount new disk
|
||||
SETBIT(dsk_dsw[drv], DSK_DSW_NOT_READY);
|
||||
return rval;
|
||||
}
|
||||
|
|
|
@ -57,10 +57,10 @@
|
|||
// -------------------------------------------------------------------------------------------
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include "ibm1130_fmt.h"
|
||||
|
||||
#define MAXLINE 81 // maximum output line size
|
||||
|
|
|
@ -662,7 +662,7 @@ static HBITMAP hBmp = NULL;
|
|||
static int curwid = 0;
|
||||
static int curht = 0;
|
||||
static BOOL wcInited = FALSE;
|
||||
static int GDUPumpID = 0;
|
||||
static DWORD GDUPumpID = 0;
|
||||
static HANDLE hGDUPump = INVALID_HANDLE_VALUE;
|
||||
static HPEN hGreenPen = NULL;
|
||||
static HBRUSH hRedBrush = NULL;
|
||||
|
|
|
@ -11,6 +11,10 @@
|
|||
* This is not a supported product, but I welcome bug reports and fixes.
|
||||
* Mail to simh@ibm1130.org
|
||||
*
|
||||
* 02-Dec-02 BLK Changed display, added printer and card reader icons
|
||||
* Added drag and drop support for scripts and card decks
|
||||
* Added support for physical card reader and printer (hides icons)
|
||||
*
|
||||
* 17-May-02 BLK Pulled out of ibm1130_cpu.c
|
||||
*/
|
||||
|
||||
|
@ -32,6 +36,14 @@
|
|||
# define UPDATE_INTERVAL 5000 // GUI: set to 100000/f where f = desired updates/second of 1130 time
|
||||
#endif
|
||||
|
||||
#define UNIT_V_CR_EMPTY (UNIT_V_UF + 5) /* NOTE: THESE MUST MATCH THE DEFINITION IN ibm1130_cr.c */
|
||||
#define UNIT_CR_EMPTY (1u << UNIT_V_CR_EMPTY)
|
||||
#define UNIT_V_PHYSICAL (UNIT_V_UF + 9)
|
||||
#define UNIT_PHYSICAL (1u << UNIT_V_PHYSICAL)
|
||||
|
||||
#define UNIT_V_PHYSICAL_PTR (UNIT_V_UF + 10) /* NOTE: THESE MUST MATCH THE DEFINITION IN ibm1130_prt.c */
|
||||
#define UNIT_PHYSICAL_PTR (1u << UNIT_V_PHYSICAL_PTR)
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
* Function declarations
|
||||
* ------------------------------------------------------------------------ */
|
||||
|
@ -71,6 +83,10 @@ DEVICE console_dev = {
|
|||
|
||||
extern char *read_line (char *cptr, int size, FILE *stream);
|
||||
extern FILE *sim_log;
|
||||
extern DEVICE *find_unit (char *cptr, UNIT **uptr);
|
||||
|
||||
extern UNIT cr_unit; /* pointers to 1442 and 1132 (1403) printers */
|
||||
extern UNIT prt_unit;
|
||||
|
||||
#ifndef GUI_SUPPORT
|
||||
void update_gui (int force) {} /* stubs for non-GUI builds */
|
||||
|
@ -86,6 +102,7 @@ extern FILE *sim_log;
|
|||
|
||||
t_stat console_reset (DEVICE *dptr) {return SCPE_OK;}
|
||||
void stuff_cmd (char *cmd) {}
|
||||
t_bool stuff_and_wait (char *cmd, int timeout, int delay) {return FALSE;}
|
||||
char *read_cmdline (char *ptr, int size, FILE *stream) {return read_line(ptr, size, stream);}
|
||||
void remark_cmd (char *remark) {printf("%s\n", remark); if (sim_log) fprintf(sim_log, "%s\n", remark);}
|
||||
#else
|
||||
|
@ -134,15 +151,29 @@ void scp_panic (char *msg)
|
|||
#define IDC_RESET 14
|
||||
#define IDC_PROGRAM_LOAD 15
|
||||
|
||||
#define IDC_TEAR 16 // standard button
|
||||
#define IDC_1442 17 // device images
|
||||
#define IDC_1132 18
|
||||
|
||||
#define LAMPTIME 500 // 500 msec delay on updating
|
||||
#define FLASH_TIMER_ID 1
|
||||
#define UPDATE_TIMER_ID 2
|
||||
|
||||
#define RUNSWITCH_X 689 // center of the run mode switch dial
|
||||
#define RUNSWITCH_Y 107
|
||||
#define TOGGLES_X 122 // left edge of series of toggle switches
|
||||
|
||||
#define TXTBOX_X 200 // text labels showing attached devices
|
||||
#define TXTBOX_Y 300
|
||||
#define TXTBOX_WIDTH 195
|
||||
#define TXTBOX_HEIGHT 12
|
||||
|
||||
static BOOL class_defined = FALSE;
|
||||
static HWND hConsoleWnd = NULL;
|
||||
static HBITMAP hBitmap = NULL;
|
||||
static HFONT hFont = NULL;
|
||||
static HFONT hBtnFont = NULL;
|
||||
static HFONT hTinyFont = NULL;
|
||||
static HBRUSH hbLampOut = NULL;
|
||||
static HBRUSH hbWhite = NULL;
|
||||
static HBRUSH hbBlack = NULL;
|
||||
|
@ -164,41 +195,80 @@ static char szConsoleClassName[] = "1130CONSOLE";
|
|||
static DWORD PumpID = 0;
|
||||
static HANDLE hPump = INVALID_HANDLE_VALUE;
|
||||
static int bmwid, bmht;
|
||||
static HANDLE hbm1442_full, hbm1442_empty, hbm1442_eof, hbm1442_middle;
|
||||
static HANDLE hbm1132_full, hbm1132_empty;
|
||||
|
||||
static struct tag_btn {
|
||||
int x, y;
|
||||
int x, y, wx, wy;
|
||||
char *txt;
|
||||
BOOL pushable, state;
|
||||
COLORREF clr;
|
||||
HBRUSH hbrLit, hbrDark;
|
||||
HWND hBtn;
|
||||
BOOL subclassed;
|
||||
|
||||
} btn[] = {
|
||||
0, 0, "KEYBOARD\nSELECT", FALSE, FALSE, RGB(255,255,180), NULL, NULL, NULL,
|
||||
0, 1, "DISK\nUNLOCK", FALSE, TRUE, RGB(255,255,180), NULL, NULL, NULL,
|
||||
0, 2, "RUN", FALSE, FALSE, RGB(0,255,0), NULL, NULL, NULL,
|
||||
0, 3, "PARITY\nCHECK", FALSE, FALSE, RGB(255,0,0), NULL, NULL, NULL,
|
||||
0, 0, BUTTON_WIDTH, BUTTON_HEIGHT, "KEYBOARD\nSELECT", FALSE, FALSE, RGB(255,255,180), NULL, NULL, NULL, TRUE,
|
||||
0, 1, BUTTON_WIDTH, BUTTON_HEIGHT, "DISK\nUNLOCK", FALSE, TRUE, RGB(255,255,180), NULL, NULL, NULL, TRUE,
|
||||
0, 2, BUTTON_WIDTH, BUTTON_HEIGHT, "RUN", FALSE, FALSE, RGB(0,255,0), NULL, NULL, NULL, TRUE,
|
||||
0, 3, BUTTON_WIDTH, BUTTON_HEIGHT, "PARITY\nCHECK", FALSE, FALSE, RGB(255,0,0), NULL, NULL, NULL, TRUE,
|
||||
|
||||
1, 0, "", FALSE, FALSE, RGB(255,255,180), NULL, NULL, NULL,
|
||||
1, 1, "FILE\nREADY", FALSE, FALSE, RGB(0,255,0), NULL, NULL, NULL,
|
||||
1, 2, "FORMS\nCHECK", FALSE, FALSE, RGB(255,255,0), NULL, NULL, NULL,
|
||||
1, 3, "POWER\nON", FALSE, TRUE, RGB(255,255,180), NULL, NULL, NULL,
|
||||
1, 0, BUTTON_WIDTH, BUTTON_HEIGHT, "", FALSE, FALSE, RGB(255,255,180), NULL, NULL, NULL, TRUE,
|
||||
1, 1, BUTTON_WIDTH, BUTTON_HEIGHT, "FILE\nREADY", FALSE, FALSE, RGB(0,255,0), NULL, NULL, NULL, TRUE,
|
||||
1, 2, BUTTON_WIDTH, BUTTON_HEIGHT, "FORMS\nCHECK", FALSE, FALSE, RGB(255,255,0), NULL, NULL, NULL, TRUE,
|
||||
1, 3, BUTTON_WIDTH, BUTTON_HEIGHT, "POWER\nON", FALSE, TRUE, RGB(255,255,180), NULL, NULL, NULL, TRUE,
|
||||
|
||||
2, 0, "POWER", TRUE, FALSE, RGB(255,255,180), NULL, NULL, NULL,
|
||||
2, 1, "PROGRAM\nSTART", TRUE, FALSE, RGB(0,255,0), NULL, NULL, NULL,
|
||||
2, 2, "PROGRAM\nSTOP", TRUE, FALSE, RGB(255,0,0), NULL, NULL, NULL,
|
||||
2, 3, "LOAD\nIAR", TRUE, FALSE, RGB(0,0,255), NULL, NULL, NULL,
|
||||
2, 0, BUTTON_WIDTH, BUTTON_HEIGHT, "POWER", TRUE, FALSE, RGB(255,255,180), NULL, NULL, NULL, TRUE,
|
||||
2, 1, BUTTON_WIDTH, BUTTON_HEIGHT, "PROGRAM\nSTART", TRUE, FALSE, RGB(0,255,0), NULL, NULL, NULL, TRUE,
|
||||
2, 2, BUTTON_WIDTH, BUTTON_HEIGHT, "PROGRAM\nSTOP", TRUE, FALSE, RGB(255,0,0), NULL, NULL, NULL, TRUE,
|
||||
2, 3, BUTTON_WIDTH, BUTTON_HEIGHT, "LOAD\nIAR", TRUE, FALSE, RGB(0,0,255), NULL, NULL, NULL, TRUE,
|
||||
|
||||
3, 0, "KEYBOARD", TRUE, FALSE, RGB(255,255,180), NULL, NULL, NULL,
|
||||
3, 1, "IMM\nSTOP", TRUE, FALSE, RGB(255,0,0), NULL, NULL, NULL,
|
||||
3, 2, "CHECK\nRESET", TRUE, FALSE, RGB(0,0,255), NULL, NULL, NULL,
|
||||
3, 3, "PROGRAM\nLOAD", TRUE, FALSE, RGB(0,0,255), NULL, NULL, NULL,
|
||||
3, 0, BUTTON_WIDTH, BUTTON_HEIGHT, "KEYBOARD", TRUE, FALSE, RGB(255,255,180), NULL, NULL, NULL, TRUE,
|
||||
3, 1, BUTTON_WIDTH, BUTTON_HEIGHT, "IMM\nSTOP", TRUE, FALSE, RGB(255,0,0), NULL, NULL, NULL, TRUE,
|
||||
3, 2, BUTTON_WIDTH, BUTTON_HEIGHT, "CHECK\nRESET", TRUE, FALSE, RGB(0,0,255), NULL, NULL, NULL, TRUE,
|
||||
3, 3, BUTTON_WIDTH, BUTTON_HEIGHT, "PROGRAM\nLOAD", TRUE, FALSE, RGB(0,0,255), NULL, NULL, NULL, TRUE,
|
||||
|
||||
TXTBOX_X+40, TXTBOX_Y+25, 35, 12, "Tear", TRUE, FALSE, 0, NULL, NULL, NULL, FALSE,
|
||||
635, 238, 110, 110, "EMPTY_1442", TRUE, FALSE, 0, NULL, NULL, NULL, FALSE,
|
||||
635, 366, 110, 110, "EMPTY_1132", TRUE, FALSE, 0, NULL, NULL, NULL, FALSE,
|
||||
// 635, 366, 110, 110, "EMPTY_1132", TRUE, FALSE, 0, NULL, NULL, NULL, FALSE,
|
||||
};
|
||||
#define NBUTTONS (sizeof(btn) / sizeof(btn[0]))
|
||||
|
||||
#define STATE_1442_EMPTY 0 // no cards (no file attached)
|
||||
#define STATE_1442_FULL 1 // cards in hopper (file attached at BOF)
|
||||
#define STATE_1442_MIDDLE 2 // cards in hopper and stacker (file attached, neither EOF nor BOF)
|
||||
#define STATE_1442_EOF 3 // cards in stacker (file attached, at EOF)
|
||||
#define STATE_1442_HIDDEN 4 // simulator is attached to physical card reader
|
||||
|
||||
#define STATE_1132_EMPTY 0 // no paper hanging out of printer
|
||||
#define STATE_1132_FULL 1 // paper hanging out of printer
|
||||
#define STATE_1132_HIDDEN 2 // printer is attached to physical printer
|
||||
|
||||
static struct tag_txtbox {
|
||||
int x, y;
|
||||
char *txt;
|
||||
char *unitname;
|
||||
int idctrl;
|
||||
} txtbox[] = {
|
||||
TXTBOX_X, TXTBOX_Y, "Card Reader", "CR", -1,
|
||||
TXTBOX_X, TXTBOX_Y+ 25, "Printer", "PRT", IDC_1132,
|
||||
TXTBOX_X, TXTBOX_Y+ 50, "Disk 1", "DSK0", -1,
|
||||
TXTBOX_X, TXTBOX_Y+ 75, "Disk 2", "DSK1", -1,
|
||||
TXTBOX_X, TXTBOX_Y+100, "Disk 3", "DSK2", -1,
|
||||
TXTBOX_X, TXTBOX_Y+125, "Disk 4", "DSK3", -1,
|
||||
TXTBOX_X, TXTBOX_Y+150, "Disk 5", "DSK4", -1,
|
||||
};
|
||||
#define NTXTBOXES (sizeof(txtbox) / sizeof(txtbox[0]))
|
||||
|
||||
#define TXTBOX_BOTTOM (TXTBOX_Y+150)
|
||||
|
||||
static void init_console_window (void);
|
||||
static void destroy_console_window (void);
|
||||
LRESULT CALLBACK ConsoleWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
static DWORD WINAPI Pump (LPVOID arg);
|
||||
static void accept_dropped_file (HANDLE hDrop);
|
||||
static void tear_printer (void);
|
||||
|
||||
#define NIXOBJECT(hObj) if (hObj != NULL) {DeleteObject(hObj); hObj = NULL;}
|
||||
|
||||
|
@ -249,6 +319,7 @@ static void destroy_console_window (void)
|
|||
NIXOBJECT(hbLampOut)
|
||||
NIXOBJECT(hFont)
|
||||
NIXOBJECT(hBtnFont);
|
||||
NIXOBJECT(hTinyFont);
|
||||
NIXOBJECT(hcHand)
|
||||
NIXOBJECT(hSwitchPen)
|
||||
NIXOBJECT(hLtGreyPen)
|
||||
|
@ -322,6 +393,7 @@ void update_gui (BOOL force)
|
|||
BOOL state;
|
||||
static int in_here = FALSE;
|
||||
static int32 displayed = 0;
|
||||
RECT xin;
|
||||
|
||||
if ((int32)(console_unit.flags & UNIT_DISPLAY) != displayed) { // setting has changed
|
||||
displayed = console_unit.flags & UNIT_DISPLAY;
|
||||
|
@ -380,9 +452,9 @@ void update_gui (BOOL force)
|
|||
if ((wait_state|wait_lamp) != shown_wait)
|
||||
{shown_wait= (wait_state|wait_lamp); RedrawRegion(hConsoleWnd, 380, 77, 414, 97);}
|
||||
if (CES != shown_ces)
|
||||
{shown_ces = CES; RepaintRegion(hConsoleWnd, 115, 230, 478, 275);} /* console entry sw: do erase bkgnd */
|
||||
{shown_ces = CES; RepaintRegion(hConsoleWnd, TOGGLES_X-7, 230, TOGGLES_X+360, 275);} /* console entry sw: do erase bkgnd */
|
||||
if (RUNMODE != shown_runmode)
|
||||
{shown_runmode = RUNMODE;RepaintRegion(hConsoleWnd, 270, 359, 330, 418);}
|
||||
{shown_runmode = RUNMODE;RepaintRegion(hConsoleWnd, RUNSWITCH_X-50, RUNSWITCH_Y-50, RUNSWITCH_X+50, RUNSWITCH_Y+50);}
|
||||
|
||||
int_lamps = 0;
|
||||
|
||||
|
@ -415,6 +487,55 @@ void update_gui (BOOL force)
|
|||
}
|
||||
}
|
||||
|
||||
if (force) { // if force flag is set, update text region
|
||||
SetRect(&xin, TXTBOX_X, TXTBOX_Y, TXTBOX_X+TXTBOX_WIDTH, TXTBOX_BOTTOM+2*TXTBOX_HEIGHT);
|
||||
InvalidateRect(hConsoleWnd, &xin, TRUE);
|
||||
}
|
||||
|
||||
state = ((cr_unit.flags & UNIT_ATT) == 0) ? STATE_1442_EMPTY :
|
||||
(cr_unit.flags & UNIT_PHYSICAL) ? STATE_1442_HIDDEN :
|
||||
(cr_unit.flags & UNIT_CR_EMPTY) ? STATE_1442_EOF :
|
||||
cr_unit.pos ? STATE_1442_MIDDLE :
|
||||
STATE_1442_FULL;
|
||||
|
||||
if (state != btn[IDC_1442].state) {
|
||||
if (state == STATE_1442_HIDDEN)
|
||||
ShowWindow(btn[IDC_1442].hBtn, SW_HIDE);
|
||||
else {
|
||||
if (btn[IDC_1442].state == STATE_1442_HIDDEN)
|
||||
ShowWindow(btn[IDC_1442].hBtn, SW_SHOWNA);
|
||||
|
||||
SendMessage(btn[IDC_1442].hBtn, STM_SETIMAGE, IMAGE_BITMAP,
|
||||
(LPARAM) (
|
||||
(state == STATE_1442_FULL) ? hbm1442_full :
|
||||
(state == STATE_1442_MIDDLE) ? hbm1442_middle :
|
||||
(state == STATE_1442_EOF) ? hbm1442_eof :
|
||||
hbm1442_empty));
|
||||
}
|
||||
|
||||
btn[IDC_1442].state = state;
|
||||
}
|
||||
|
||||
state = ((prt_unit.flags & UNIT_ATT) == 0) ? STATE_1132_EMPTY :
|
||||
(prt_unit.flags & UNIT_PHYSICAL_PTR) ? STATE_1132_HIDDEN :
|
||||
prt_unit.pos ? STATE_1132_FULL :
|
||||
STATE_1132_EMPTY;
|
||||
|
||||
if (state != btn[IDC_1132].state) {
|
||||
if (state == STATE_1132_HIDDEN)
|
||||
ShowWindow(btn[IDC_1132].hBtn, SW_HIDE);
|
||||
else {
|
||||
if (btn[IDC_1132].state == STATE_1132_HIDDEN)
|
||||
ShowWindow(btn[IDC_1132].hBtn, SW_SHOWNA);
|
||||
|
||||
SendMessage(btn[IDC_1132].hBtn, STM_SETIMAGE, IMAGE_BITMAP,
|
||||
(LPARAM) (
|
||||
(state == STATE_1132_FULL) ? hbm1132_full : hbm1132_empty));
|
||||
}
|
||||
|
||||
btn[IDC_1132].state = state;
|
||||
}
|
||||
|
||||
in_here = FALSE;
|
||||
}
|
||||
|
||||
|
@ -474,6 +595,9 @@ void PaintButton (LPDRAWITEMSTRUCT dis)
|
|||
if (! BETWEEN(i, 0, NBUTTONS-1))
|
||||
return;
|
||||
|
||||
if (! btn[i].subclassed)
|
||||
return;
|
||||
|
||||
FillRect(dis->hDC, &dis->rcItem, ((btn[i].pushable || power) && IsWindowEnabled(btn[i].hBtn)) ? btn[i].hbrLit : btn[i].hbrDark);
|
||||
|
||||
if (! btn[i].pushable) {
|
||||
|
@ -565,7 +689,7 @@ HWND CreateSubclassedButton (HWND hwParent, int i)
|
|||
int r, g, b;
|
||||
|
||||
y = bmht - (4*BUTTON_HEIGHT) + BUTTON_HEIGHT * btn[i].y;
|
||||
x = (btn[i].x < 2) ? (btn[i].x*BUTTON_WIDTH) : (bmwid - (4-btn[i].x)*BUTTON_WIDTH);
|
||||
x = (btn[i].x < 2) ? (btn[i].x*BUTTON_WIDTH) : (598 - (4-btn[i].x)*BUTTON_WIDTH);
|
||||
|
||||
if ((hBtn = CreateWindow("BUTTON", btn[i].txt, WS_CHILD|WS_VISIBLE|BS_CENTER|BS_MULTILINE|BS_OWNERDRAW,
|
||||
x, y, BUTTON_WIDTH, BUTTON_HEIGHT, hwParent, (HMENU) i, hInstance, NULL)) == NULL)
|
||||
|
@ -654,12 +778,16 @@ static DWORD WINAPI Pump (LPVOID arg)
|
|||
hFont = CreateFont(-10, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, FIXED_PITCH, FF_SWISS, "Arial");
|
||||
if (hBtnFont == NULL)
|
||||
hBtnFont = CreateFont(-12, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, FIXED_PITCH, FF_SWISS, "Arial");
|
||||
if (hTinyFont == NULL)
|
||||
hTinyFont = CreateFont(-10, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, FIXED_PITCH, FF_SWISS, "Arial");
|
||||
|
||||
if (hConsoleWnd == NULL) { /* create window */
|
||||
if ((hConsoleWnd = CreateWindow(szConsoleClassName, "IBM 1130", WS_OVERLAPPED, 0, 0, 200, 200, NULL, NULL, hInstance, NULL)) == NULL) {
|
||||
if ((hConsoleWnd = CreateWindow(szConsoleClassName, "IBM 1130", WS_OVERLAPPED|WS_CLIPCHILDREN, 0, 0, 200, 200, NULL, NULL, hInstance, NULL)) == NULL) {
|
||||
PumpID = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
DragAcceptFiles(hConsoleWnd, TRUE); /* let it accept dragged files (scripts) */
|
||||
}
|
||||
|
||||
GetObject(hBitmap, sizeof(bm), &bm); /* get bitmap size */
|
||||
|
@ -667,12 +795,52 @@ static DWORD WINAPI Pump (LPVOID arg)
|
|||
bmht = bm.bmHeight;
|
||||
|
||||
for (i = 0; i < NBUTTONS; i++) {
|
||||
CreateSubclassedButton(hConsoleWnd, i);
|
||||
if (! btn[i].subclassed)
|
||||
continue;
|
||||
|
||||
CreateSubclassedButton(hConsoleWnd, i);
|
||||
if (! btn[i].pushable)
|
||||
EnableWindow(btn[i].hBtn, btn[i].state);
|
||||
}
|
||||
|
||||
// This isn't needed anymore, now that we have the big printer icon -- it acts like a button now
|
||||
// i = IDC_TEAR;
|
||||
// btn[i].hBtn = CreateWindow("BUTTON", btn[i].txt, WS_CHILD|WS_VISIBLE|BS_CENTER,
|
||||
// btn[i].x, btn[i].y, btn[i].wx, btn[i].wy, hConsoleWnd, (HMENU) i, hInstance, NULL);
|
||||
//
|
||||
// SendMessage(btn[i].hBtn, WM_SETFONT, (WPARAM) hTinyFont, TRUE);
|
||||
|
||||
hbm1442_full = LoadBitmap(hInstance, "FULL_1442");
|
||||
hbm1442_empty = LoadBitmap(hInstance, "EMPTY_1442");
|
||||
hbm1442_eof = LoadBitmap(hInstance, "EOF_1442");
|
||||
hbm1442_middle = LoadBitmap(hInstance, "MIDDLE_1442");
|
||||
hbm1132_full = LoadBitmap(hInstance, "FULL_1132");
|
||||
hbm1132_empty = LoadBitmap(hInstance, "EMPTY_1132");
|
||||
|
||||
i = IDC_1442;
|
||||
|
||||
btn[i].hBtn = CreateWindow("STATIC", btn[i].txt, WS_CHILD|WS_VISIBLE|SS_BITMAP|SS_SUNKEN|WS_BORDER|SS_REALSIZEIMAGE|SS_NOTIFY,
|
||||
btn[i].x, btn[i].y, btn[i].wx, btn[i].wy, hConsoleWnd, (HMENU) i, hInstance, NULL);
|
||||
btn[i].state = STATE_1442_EMPTY;
|
||||
|
||||
// wx = SendMessage(btn[i].hBtn, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hbm1442_full);
|
||||
wx = SendMessage(btn[i].hBtn, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hbm1442_empty);
|
||||
|
||||
i = IDC_1132;
|
||||
|
||||
btn[i].hBtn = CreateWindow("STATIC", btn[i].txt, WS_CHILD|WS_VISIBLE|SS_BITMAP|SS_SUNKEN|WS_BORDER|SS_REALSIZEIMAGE|SS_NOTIFY,
|
||||
btn[i].x, btn[i].y, btn[i].wx, btn[i].wy, hConsoleWnd, (HMENU) i, hInstance, NULL);
|
||||
btn[i].state = FALSE;
|
||||
|
||||
wx = SendMessage(btn[i].hBtn, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hbm1132_empty);
|
||||
|
||||
// for (i = 0; i < NTXTBOXES; i++) {
|
||||
// txtbox[i].hBox = CreateWindow("EDIT", txtbox[i].txt,
|
||||
// WS_CHILD|WS_VISIBLE|ES_LEFT|ES_READONLY,
|
||||
// txtbox[i].x, txtbox[i].y, TXTBOX_WIDTH, TXTBOX_HEIGHT, hConsoleWnd, (HMENU) (i+100), hInstance, NULL);
|
||||
// SendMessage(txtbox[i].hBox, WM_SETFONT, (WPARAM) hTinyFont, TRUE);
|
||||
// }
|
||||
|
||||
GetWindowRect(hConsoleWnd, &r); /* get window size as created */
|
||||
wx = r.right - r.left + 1;
|
||||
wy = r.bottom - r.top + 1;
|
||||
|
@ -712,6 +880,7 @@ static DWORD WINAPI Pump (LPVOID arg)
|
|||
}
|
||||
|
||||
if (hConsoleWnd != NULL) {
|
||||
DragAcceptFiles(hConsoleWnd, FALSE); /* unregister as drag/drop target */
|
||||
DestroyWindow(hConsoleWnd); /* but if a quit message got posted, clean up */
|
||||
hConsoleWnd = NULL;
|
||||
}
|
||||
|
@ -753,11 +922,12 @@ static void DrawBits (HDC hDC, int x, int y, int bits, int nbits, int mask, char
|
|||
* DrawToggles - display the console sense switches
|
||||
* ------------------------------------------------------------------------ */
|
||||
|
||||
|
||||
static void DrawToggles (HDC hDC, int bits)
|
||||
{
|
||||
int b, x;
|
||||
|
||||
for (b = 0x8000, x = 122; b != 0; b >>= 1) {
|
||||
for (b = 0x8000, x = TOGGLES_X; b != 0; b >>= 1) {
|
||||
if (shown_ces & b) { /* up */
|
||||
SelectObject(hDC, hbWhite);
|
||||
Rectangle(hDC, x, 232, x+9, 240);
|
||||
|
@ -789,10 +959,10 @@ void DrawRunmode (HDC hDC, int mode)
|
|||
ca = cos(angle);
|
||||
sa = sin(angle);
|
||||
|
||||
x0 = 301 + (int) (20.*ca + 0.5); /* inner radius */
|
||||
y0 = 389 - (int) (20.*sa + 0.5);
|
||||
x1 = 301 + (int) (25.*ca + 0.5); /* outer radius */
|
||||
y1 = 389 - (int) (25.*sa + 0.5);
|
||||
x0 = RUNSWITCH_X + (int) (20.*ca + 0.5); /* inner radius */
|
||||
y0 = RUNSWITCH_Y - (int) (20.*sa + 0.5);
|
||||
x1 = RUNSWITCH_X + (int) (25.*ca + 0.5); /* outer radius */
|
||||
y1 = RUNSWITCH_Y - (int) (25.*sa + 0.5);
|
||||
|
||||
hOldPen = SelectObject(hDC, hSwitchPen);
|
||||
|
||||
|
@ -812,7 +982,7 @@ static BOOL HandleClick (HWND hWnd, int xh, int yh, BOOL actual)
|
|||
{
|
||||
int b, x, r, ang, i;
|
||||
|
||||
for (b = 0x8000, x = 122; b != 0; b >>= 1) {
|
||||
for (b = 0x8000, x = TOGGLES_X; b != 0; b >>= 1) {
|
||||
if (BETWEEN(xh, x-3, x+8+3) && BETWEEN(yh, 230, 275)) {
|
||||
if (actual) {
|
||||
CES ^= b; /* a hit. Invert the bit and redisplay */
|
||||
|
@ -823,9 +993,9 @@ static BOOL HandleClick (HWND hWnd, int xh, int yh, BOOL actual)
|
|||
x += (b & 0x1111) ? 31 : 21;
|
||||
}
|
||||
|
||||
if (BETWEEN(xh, 245, 355) && BETWEEN(yh, 345, 425)) { /* hit near rotary switch */
|
||||
ang = (int) (atan2(301.-xh, 389.-yh)*180./3.1415926); /* this does implicit 90 deg rotation by the way */
|
||||
r = (int) sqrt((xh-301)*(xh-301)+(yh-389)*(yh-389));
|
||||
if (BETWEEN(xh, RUNSWITCH_X-50, RUNSWITCH_X+50) && BETWEEN(yh, RUNSWITCH_Y-50, RUNSWITCH_Y+50)) { /* hit near rotary switch */
|
||||
ang = (int) (atan2(RUNSWITCH_X-xh, RUNSWITCH_Y-yh)*180./3.1415926); /* this does implicit 90 deg rotation by the way */
|
||||
r = (int) sqrt((xh-RUNSWITCH_X)*(xh-RUNSWITCH_X)+(yh-RUNSWITCH_Y)*(yh-RUNSWITCH_Y));
|
||||
if (r > 12) {
|
||||
for (i = MODE_LOAD; i <= MODE_INT_RUN; i++) {
|
||||
if (BETWEEN(ang, i*45-12, i*45+12)) {
|
||||
|
@ -852,13 +1022,19 @@ static BOOL HandleClick (HWND hWnd, int xh, int yh, BOOL actual)
|
|||
* RepaintRegion-> repaint with background redraw. Used for toggles which change position.
|
||||
* ------------------------------------------------------------------------ */
|
||||
|
||||
static void DrawConsole (HDC hDC)
|
||||
static void DrawConsole (HDC hDC, PAINTSTRUCT *ps)
|
||||
{
|
||||
static char digits[] = " 0 1 2 3 4 5 6 7 8 9101112131415";
|
||||
static char cccs[] = "3216 8 4 2 1";
|
||||
static char cnds[] = " C V";
|
||||
static char waits[] = " W";
|
||||
HFONT hOldFont, hOldBrush;
|
||||
RECT xout, xin;
|
||||
int i, n;
|
||||
DEVICE *dptr;
|
||||
UNIT *uptr;
|
||||
t_bool enab;
|
||||
char nametemp[50], *dispname;
|
||||
|
||||
hOldFont = SelectObject(hDC, hFont); /* use that tiny font */
|
||||
hOldBrush = SelectObject(hDC, hbWhite);
|
||||
|
@ -885,6 +1061,47 @@ static void DrawConsole (HDC hDC)
|
|||
|
||||
SelectObject(hDC, hOldFont);
|
||||
SelectObject(hDC, hOldBrush);
|
||||
|
||||
SetBkColor(hDC, RGB(0,0,0));
|
||||
|
||||
SetRect(&xin, TXTBOX_X, TXTBOX_Y, TXTBOX_X+TXTBOX_WIDTH, TXTBOX_BOTTOM+TXTBOX_HEIGHT);
|
||||
if (IntersectRect(&xout, &xin, &ps->rcPaint)) {
|
||||
hOldFont = SelectObject(hDC, hTinyFont);
|
||||
|
||||
for (i = 0; i < NTXTBOXES; i++) {
|
||||
enab = FALSE;
|
||||
|
||||
dptr = find_unit(txtbox[i].unitname, &uptr);
|
||||
if (dptr != NULL && uptr != NULL) {
|
||||
if (uptr->flags & UNIT_DIS) {
|
||||
SetTextColor(hDC, RGB(128,0,0));
|
||||
}
|
||||
else if (uptr->flags & UNIT_ATT) {
|
||||
SetTextColor(hDC, RGB(0,0,255));
|
||||
if ((n = strlen(uptr->filename)) > 30) {
|
||||
strcpy(nametemp, "...");
|
||||
strcpy(nametemp+3, uptr->filename+n-30);
|
||||
dispname = nametemp;
|
||||
}
|
||||
else
|
||||
dispname = uptr->filename;
|
||||
|
||||
TextOut(hDC, txtbox[i].x+25, txtbox[i].y+TXTBOX_HEIGHT, dispname, strlen(dispname));
|
||||
SetTextColor(hDC, RGB(255,255,255));
|
||||
enab = TRUE;
|
||||
}
|
||||
else {
|
||||
SetTextColor(hDC, RGB(128,128,128));
|
||||
}
|
||||
TextOut(hDC, txtbox[i].x, txtbox[i].y, txtbox[i].txt, strlen(txtbox[i].txt));
|
||||
}
|
||||
|
||||
if (txtbox[i].idctrl >= 0)
|
||||
EnableWindow(btn[txtbox[i].idctrl].hBtn, enab);
|
||||
}
|
||||
|
||||
SelectObject(hDC, hOldFont);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
|
@ -914,11 +1131,11 @@ void gui_run (int running)
|
|||
flash_run(); /* keep run lamp active for a while after we stop running */
|
||||
}
|
||||
|
||||
void HandleCommand (HWND hWnd, WPARAM wParam, LPARAM lParam)
|
||||
void HandleCommand (HWND hWnd, WORD wNotify, WORD idCtl, HWND hwCtl)
|
||||
{
|
||||
int i;
|
||||
|
||||
switch (wParam) {
|
||||
switch (idCtl) {
|
||||
case IDC_POWER: /* toggle system power */
|
||||
power = ! power;
|
||||
reset_all(0);
|
||||
|
@ -1009,6 +1226,21 @@ void HandleCommand (HWND hWnd, WPARAM wParam, LPARAM lParam)
|
|||
remark_cmd("IPL failed");
|
||||
}
|
||||
break;
|
||||
|
||||
case IDC_TEAR: /* "tear off printer output" */
|
||||
case IDC_1132: /* do same if they click on the printer icon */
|
||||
if (btn[IDC_1132].state && (wNotify == STN_CLICKED || wNotify == STN_DBLCLK))
|
||||
tear_printer();
|
||||
break;
|
||||
|
||||
case IDC_1442:
|
||||
if (btn[IDC_1442].state == STATE_1442_FULL || wNotify == STN_DBLCLK)
|
||||
stuff_cmd("detach cr");
|
||||
else if (btn[IDC_1442].state != STATE_1442_EMPTY && wNotify == STN_CLICKED) {
|
||||
cr_rewind();
|
||||
update_gui(TRUE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
update_gui(FALSE);
|
||||
|
@ -1050,12 +1282,17 @@ LRESULT CALLBACK ConsoleWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa
|
|||
|
||||
case WM_PAINT:
|
||||
hDC = BeginPaint(hWnd, &ps);
|
||||
DrawConsole(hDC);
|
||||
DrawConsole(hDC, &ps);
|
||||
EndPaint(hWnd, &ps);
|
||||
break;
|
||||
|
||||
case WM_COMMAND: /* button click */
|
||||
HandleCommand(hWnd, wParam, lParam);
|
||||
HandleCommand(hWnd, HIWORD(wParam), LOWORD(wParam), (HWND) lParam);
|
||||
break;
|
||||
|
||||
case WM_CTLCOLOREDIT: /* text color for edit controls */
|
||||
SetBkColor((HDC) wParam, RGB(0,0,0));
|
||||
SetTextColor((HDC) wParam, RGB(255,255,255));
|
||||
break;
|
||||
|
||||
case WM_DRAWITEM:
|
||||
|
@ -1085,6 +1322,10 @@ LRESULT CALLBACK ConsoleWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa
|
|||
update_gui(FALSE);
|
||||
break;
|
||||
|
||||
case WM_DROPFILES:
|
||||
accept_dropped_file((HANDLE) wParam); // console window - dragged file is a script or card deck
|
||||
break;
|
||||
|
||||
default:
|
||||
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
@ -1160,6 +1401,81 @@ void disk_unlocked (int unlocked)
|
|||
EnableWindow(btn[IDC_DISK_UNLOCK].hBtn, unlocked);
|
||||
}
|
||||
|
||||
static void accept_dropped_file (HANDLE hDrop)
|
||||
{
|
||||
int nfiles;
|
||||
char fname[MAX_PATH], cmd[MAX_PATH+50], *deckfile;
|
||||
BOOL cardreader;
|
||||
POINT pt;
|
||||
HWND hWndDrop;
|
||||
|
||||
nfiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0); // get file count,
|
||||
DragQueryFile(hDrop, 0, fname, sizeof(fname)); // get first filename
|
||||
DragQueryPoint(hDrop, &pt); // get location of drop
|
||||
DragFinish(hDrop);
|
||||
|
||||
if (nfiles <= 0) // hmm, this seems unlikely to occur, but better check
|
||||
return;
|
||||
|
||||
if (running) { // can only accept a drop while processor is stopped
|
||||
MessageBeep(0);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((hWndDrop = ChildWindowFromPoint(hConsoleWnd, pt)) == btn[IDC_1442].hBtn)
|
||||
cardreader = TRUE; // file was dropped onto 1442 card reader
|
||||
else if (hWndDrop == NULL || hWndDrop == hConsoleWnd)
|
||||
cardreader = FALSE; // file was dropped onto console window, not a button
|
||||
else {
|
||||
MessageBeep(0); // file was dropped onto another button
|
||||
return;
|
||||
}
|
||||
|
||||
if (nfiles > 1) { // oops, we wouldn't know what order to read them in
|
||||
MessageBox(hConsoleWnd, "You may only drop one file at a time", "", MB_OK);
|
||||
return;
|
||||
}
|
||||
|
||||
// if shift key is down, prepend @ to name (make it a deck file)
|
||||
deckfile = ((GetKeyState(VK_SHIFT) & 0x8000) && cardreader) ? "@" : "";
|
||||
|
||||
sprintf(cmd, "%s \"%s%s\"", cardreader ? "attach cr" : "do", deckfile, fname);
|
||||
stuff_cmd(cmd);
|
||||
}
|
||||
|
||||
static void tear_printer (void)
|
||||
{
|
||||
char cmd[MAX_PATH+100], filename[MAX_PATH];
|
||||
|
||||
if ((prt_unit.flags & UNIT_ATT) == 0)
|
||||
return;
|
||||
|
||||
strcpy(filename, prt_unit.filename); // save current attached filename
|
||||
|
||||
if (! stuff_and_wait("detach prt", 1000, 0)) // detach it
|
||||
return;
|
||||
|
||||
sprintf(cmd, "view \"%s\"", filename); // spawn notepad to view it
|
||||
if (! stuff_and_wait(cmd, 3000, 500))
|
||||
return;
|
||||
|
||||
// no, now we have them click the card reader icon twice to unload the deck. more flexible that way
|
||||
// if (! stuff_and_wait("detach cr", 1000, 0)) // detach the card reader so they can edit the deck file
|
||||
// return;
|
||||
|
||||
unlink(filename); // delete the file
|
||||
|
||||
sprintf(cmd, "attach prt \"%s\"", filename); // reattach
|
||||
stuff_cmd(cmd);
|
||||
}
|
||||
|
||||
#ifdef XXX
|
||||
if ((hBtn = CreateWindow("BUTTON", btn[i].txt, WS_CHILD|WS_VISIBLE|BS_CENTER|BS_MULTILINE|BS_OWNERDRAW,
|
||||
x, y, BUTTON_WIDTH, BUTTON_HEIGHT, hwParent, (HMENU) i, hInstance, NULL)) == NULL)
|
||||
return NULL;
|
||||
|
||||
#endif
|
||||
|
||||
CRITICAL_SECTION critsect;
|
||||
|
||||
void begin_critical_section (void)
|
||||
|
@ -1201,6 +1517,7 @@ static DWORD WINAPI CmdThread (LPVOID arg)
|
|||
WaitForSingleObject(hCmdReadEvent, INFINITE); /* wait for request */
|
||||
read_line(cmdbuffer, sizeof(cmdbuffer), stdin); /* read one line */
|
||||
scp_stuffed = FALSE; /* say how we got it */
|
||||
scp_reading = FALSE;
|
||||
SetEvent(hCmdReadyEvent); /* notify main thread a line is ready */
|
||||
}
|
||||
return 0;
|
||||
|
@ -1225,9 +1542,6 @@ char *read_cmdline (char *ptr, int size, FILE *stream)
|
|||
|
||||
SetEvent(hCmdReadEvent); /* let read thread get one line */
|
||||
WaitForSingleObject(hCmdReadyEvent, INFINITE); /* wait for read thread or GUI to respond */
|
||||
|
||||
scp_reading = FALSE;
|
||||
|
||||
strncpy(ptr, cmdbuffer, MIN(size, sizeof(cmdbuffer))); /* copy line to caller's buffer */
|
||||
|
||||
for (cptr = ptr; isspace(*cptr); cptr++) /* absorb spaces */
|
||||
|
@ -1247,9 +1561,58 @@ void stuff_cmd (char *cmd)
|
|||
{
|
||||
strcpy(cmdbuffer, cmd); /* save the string */
|
||||
scp_stuffed = TRUE; /* note where it came from */
|
||||
scp_reading = FALSE;
|
||||
ResetEvent(hCmdReadEvent); /* clear read request event */
|
||||
SetEvent(hCmdReadyEvent); /* notify main thread a line is ready */
|
||||
}
|
||||
|
||||
// my_yield - process GUI messages. It's not apparent why stuff_and_wait would block,
|
||||
// since it sleeps in the GUI thread while scp runs in the main thread. However,
|
||||
// at the end of every command scp calls update_gui, which can result in messages
|
||||
// being sent to the GUI thread. So, the GUI thread has to process messages while
|
||||
// stuff_and_wait is waiting.
|
||||
|
||||
static void my_yield (void)
|
||||
{
|
||||
MSG msg;
|
||||
// multitask
|
||||
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
// stuff_and_wait -- stuff a command and wait for the emulator to process the command
|
||||
// and come back to prompt for another
|
||||
|
||||
t_bool stuff_and_wait (char *cmd, int timeout, int delay)
|
||||
{
|
||||
scp_reading = FALSE;
|
||||
|
||||
stuff_cmd(cmd);
|
||||
|
||||
while (! scp_reading) {
|
||||
if (timeout < 0)
|
||||
return FALSE;
|
||||
|
||||
my_yield();
|
||||
if (scp_reading)
|
||||
break;
|
||||
|
||||
Sleep(50);
|
||||
if (timeout)
|
||||
if ((timeout -= 50) <= 0)
|
||||
timeout = -1;
|
||||
|
||||
my_yield();
|
||||
}
|
||||
|
||||
if (delay)
|
||||
Sleep(delay);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* remark_cmd - print a remark from inside a command processor. This routine takes
|
||||
* into account the possiblity that the command might have been stuffed, in which
|
||||
* case the sim> prompt needs to be reprinted.
|
||||
|
@ -1257,8 +1620,14 @@ void stuff_cmd (char *cmd)
|
|||
|
||||
void remark_cmd (char *remark)
|
||||
{
|
||||
if (scp_reading) {
|
||||
putchar('\n');
|
||||
if (sim_log) putc('\n', sim_log);
|
||||
}
|
||||
|
||||
printf("%s\n", remark);
|
||||
if (sim_log) fprintf(sim_log, "%s\n", remark);
|
||||
|
||||
if (scp_reading) {
|
||||
printf("sim> ");
|
||||
if (sim_log) fprintf(sim_log, "sim> ");
|
||||
|
|
|
@ -4,6 +4,15 @@
|
|||
|
||||
Brian Knittel
|
||||
Revision History
|
||||
|
||||
2003.12.02 - Added -p option for physical line printer output (flushes
|
||||
output buffer after each line). When using a physical printer on
|
||||
Windows, be sure to set printer to "send output directly to printer"
|
||||
to disable spooling, otherwise nothing appears until printer is
|
||||
detatched.
|
||||
|
||||
2003.11.25 - Changed magic filename for standard output to "(stdout)".
|
||||
|
||||
2002.09.13 - Added 1403 support. New file, taken from part of ibm1130_stddev.c
|
||||
|
||||
Note: The 1403 is much faster, even in emulation, because it takes much
|
||||
|
@ -88,6 +97,7 @@ static int32 prt_twait = 50; /* transfer wait, for 1403 operations */
|
|||
#define UNIT_V_PARITYCHECK (UNIT_V_UF + 7) /* error flags for 1403 */
|
||||
#define UNIT_V_RINGCHECK (UNIT_V_UF + 8)
|
||||
#define UNIT_V_SYNCCHECK (UNIT_V_UF + 9)
|
||||
#define UNIT_V_PHYSICAL_PTR (UNIT_V_UF + 10) /* this appears in ibm1130_gui as well */
|
||||
|
||||
#define UNIT_FORMCHECK (1u << UNIT_V_FORMCHECK)
|
||||
#define UNIT_DATACHECK (1u << UNIT_V_DATACHECK)
|
||||
|
@ -99,6 +109,7 @@ static int32 prt_twait = 50; /* transfer wait, for 1403 operations */
|
|||
#define UNIT_PARITYCHECK (1u << UNIT_V_PARITYCHECK)
|
||||
#define UNIT_RINGCHECK (1u << UNIT_V_RINGCHECK)
|
||||
#define UNIT_SYNCCHECK (1u << UNIT_V_SYNCCHECK)
|
||||
#define UNIT_PHYSICAL_PTR (1u << UNIT_V_PHYSICAL_PTR)
|
||||
|
||||
UNIT prt_unit[] = {
|
||||
{ UDATA (&prt_svc, UNIT_ATTABLE, 0) },
|
||||
|
@ -106,6 +117,7 @@ UNIT prt_unit[] = {
|
|||
|
||||
#define IS_1403(uptr) (uptr->flags & UNIT_1403) /* model test */
|
||||
#define IS_1132(uptr) ((uptr->flags & UNIT_1403) == 0) /* model test */
|
||||
#define IS_PHYSICAL(uptr) (uptr->flags & UNIT_PHYSICAL_PTR)
|
||||
|
||||
/* Parameter in the unit descriptor (1132 printer) */
|
||||
|
||||
|
@ -118,8 +130,8 @@ REG prt_reg[] = {
|
|||
{ HRDATA (PRTDSW, PRT_DSW, 16) }, /* device status word */
|
||||
{ DRDATA (STIME, prt_swait, 24), PV_LEFT }, /* line skip wait */
|
||||
{ DRDATA (CTIME, prt_cwait, 24), PV_LEFT }, /* character rotation wait */
|
||||
{ DRDATA (CTIME, prt_fwait, 24), PV_LEFT }, /* 1403 fast wait */
|
||||
{ DRDATA (CTIME, prt_twait, 24), PV_LEFT }, /* 1403 transfer wait */
|
||||
{ DRDATA (FTIME, prt_fwait, 24), PV_LEFT }, /* 1403 fast wait */
|
||||
{ DRDATA (TTIME, prt_twait, 24), PV_LEFT }, /* 1403 transfer wait */
|
||||
{ NULL } };
|
||||
|
||||
MTAB prt_mod[] = {
|
||||
|
@ -175,6 +187,8 @@ cccgi[] = {
|
|||
|
||||
#include "ibm1130_prtwheel.h"
|
||||
|
||||
extern int32 sim_switches;
|
||||
|
||||
// cc_format_1132 and cc_format_1403 - turn cctape bits into proper format for DSW or status read
|
||||
|
||||
static int cc_format_1132 (int bits)
|
||||
|
@ -239,7 +253,7 @@ static void newpage (FILE *fd)
|
|||
putc('\f', fd); // formfeed
|
||||
}
|
||||
|
||||
static void flush_prt_line (FILE *fd, int spacemode)
|
||||
static void flush_prt_line (FILE *fd, int spacemode, t_bool phys_flush)
|
||||
{
|
||||
int r;
|
||||
|
||||
|
@ -262,6 +276,7 @@ static void flush_prt_line (FILE *fd, int spacemode)
|
|||
else
|
||||
prt_nnl++;
|
||||
|
||||
prt_unit->pos++; // note something written
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -296,7 +311,11 @@ static void flush_prt_line (FILE *fd, int spacemode)
|
|||
|
||||
reset_prt_line();
|
||||
|
||||
prt_unit->pos++; // note something written
|
||||
prt_nnl++; // queue a newline
|
||||
|
||||
if (phys_flush) // if physical printer, send buffered output to device
|
||||
fflush(fd);
|
||||
}
|
||||
|
||||
// 1132 printer commands
|
||||
|
@ -412,7 +431,7 @@ static t_stat prt1132_svc (UNIT *uptr)
|
|||
}
|
||||
|
||||
if (uptr->flags & UNIT_SPACING) {
|
||||
flush_prt_line(uptr->fileref, UNIT_SPACING);
|
||||
flush_prt_line(uptr->fileref, UNIT_SPACING, IS_PHYSICAL(uptr));
|
||||
|
||||
CLRBIT(PRT_DSW, PRT1132_DSW_CHANNEL_MASK|PRT1132_DSW_PRINTER_BUSY|PRT1132_DSW_CARRIAGE_BUSY);
|
||||
SETBIT(PRT_DSW, cc_format_1132(cctape[prt_row]) | PRT1132_DSW_SPACE_RESPONSE);
|
||||
|
@ -423,7 +442,7 @@ static t_stat prt1132_svc (UNIT *uptr)
|
|||
|
||||
if (uptr->flags & UNIT_SKIPPING) {
|
||||
do {
|
||||
flush_prt_line(uptr->fileref, UNIT_SKIPPING);
|
||||
flush_prt_line(uptr->fileref, UNIT_SKIPPING, IS_PHYSICAL(uptr));
|
||||
CLRBIT(PRT_DSW, PRT1132_DSW_CHANNEL_MASK);
|
||||
SETBIT(PRT_DSW, cc_format_1132(cctape[prt_row]));
|
||||
} while ((cctape[prt_row] & CC_1132_BITS) == 0); // slew directly to a cc tape punch
|
||||
|
@ -569,7 +588,7 @@ static t_stat prt1403_svc(UNIT *uptr)
|
|||
}
|
||||
else if (uptr->flags & UNIT_SKIPPING) {
|
||||
do { // find line with exact match of tape punches
|
||||
flush_prt_line(uptr->fileref, UNIT_SKIPPING);
|
||||
flush_prt_line(uptr->fileref, UNIT_SKIPPING, IS_PHYSICAL(uptr));
|
||||
} while (cctape[prt_row] != SKIPTARGET); // slew directly to requested cc tape punch
|
||||
|
||||
CLRBIT(uptr->flags, UNIT_SKIPPING); // done with this
|
||||
|
@ -579,7 +598,7 @@ static t_stat prt1403_svc(UNIT *uptr)
|
|||
SETBIT(ILSW[4], ILSW_4_1403_PRINTER);
|
||||
}
|
||||
else if (uptr->flags & UNIT_SPACING) {
|
||||
flush_prt_line(uptr->fileref, UNIT_SPACING);
|
||||
flush_prt_line(uptr->fileref, UNIT_SPACING, IS_PHYSICAL(uptr));
|
||||
|
||||
CLRBIT(uptr->flags, UNIT_SPACING); // done with this
|
||||
CLRBIT(PRT_DSW, PRT1403_DSW_CARRIAGE_BUSY);
|
||||
|
@ -685,9 +704,14 @@ static t_stat prt_attach (UNIT *uptr, char *cptr)
|
|||
}
|
||||
}
|
||||
|
||||
if (sim_switches & SWMASK('P')) /* set physical (unbuffered) printer flag */
|
||||
SETBIT(uptr->flags, UNIT_PHYSICAL_PTR);
|
||||
else
|
||||
CLRBIT(uptr->flags, UNIT_PHYSICAL_PTR);
|
||||
|
||||
sim_cancel(uptr);
|
||||
|
||||
if (strcmp(cptr, "-") == 0) { /* connect printer to stdout */
|
||||
if (strcmp(cptr, "(stdout)") == 0) { /* connect printer to stdout */
|
||||
if (uptr -> flags & UNIT_DIS) return SCPE_UDIS; /* disabled? */
|
||||
uptr->filename = calloc(CBUFSIZE, sizeof(char));
|
||||
strcpy(uptr->filename, "(stdout)");
|
||||
|
@ -695,11 +719,13 @@ static t_stat prt_attach (UNIT *uptr, char *cptr)
|
|||
SETBIT(uptr->flags, UNIT_ATT);
|
||||
uptr->pos = 0;
|
||||
}
|
||||
else if ((rval = attach_unit(uptr, cptr)) != SCPE_OK) {
|
||||
else {
|
||||
if ((rval = attach_unit(uptr, quotefix(cptr))) != SCPE_OK)
|
||||
return rval;
|
||||
}
|
||||
|
||||
fseek(uptr->fileref, 0, SEEK_END); /* if we opened an existing file, append to it */
|
||||
uptr->pos = ftell(uptr->fileref);
|
||||
|
||||
if (IS_1132(uptr)) {
|
||||
CLRBIT(ILSW[1], ILSW_1_1132_PRINTER);
|
||||
|
@ -743,7 +769,7 @@ static t_stat prt_detach (UNIT *uptr)
|
|||
{
|
||||
t_stat rval;
|
||||
|
||||
flush_prt_line(uptr->fileref, TRUE);
|
||||
flush_prt_line(uptr->fileref, TRUE, TRUE);
|
||||
|
||||
if (uptr->fileref == stdout) {
|
||||
CLRBIT(uptr->flags, UNIT_ATT);
|
||||
|
|
|
@ -5,6 +5,10 @@
|
|||
Brian Knittel
|
||||
|
||||
Revision History:
|
||||
|
||||
2003.11.23 - Fixed bug in new routine "quotefix" that made sim crash
|
||||
for all non-Windows builds :(
|
||||
|
||||
2003.06.15 - added output translation code to accomodate APL font
|
||||
added input translation feature to assist emulation of 1130 console keyboard for APL
|
||||
changes to console input and output IO emulation, fixed bugs exposed by APL interpreter
|
||||
|
@ -197,7 +201,7 @@ DEVICE tti_dev = {
|
|||
"KEYBOARD", &tti_unit, tti_reg, tti_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &tti_reset,
|
||||
NULL, NULL, NULL };
|
||||
NULL, basic_attach, NULL };
|
||||
|
||||
/* TTO data structures
|
||||
|
||||
|
@ -206,7 +210,11 @@ DEVICE tti_dev = {
|
|||
tto_reg TTO register list
|
||||
*/
|
||||
|
||||
UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT };
|
||||
// 14-Nov-03 -- the wait time was SERIAL_OUT_WAIT, but recent versions of SIMH reduced
|
||||
// this to 100, and wouldn't you know it, APL\1130 has about 120 instructions between the XIO WRITE
|
||||
// to the console and the associated WAIT.
|
||||
|
||||
UNIT tto_unit = { UDATA (&tto_svc, 0, 0), 200 };
|
||||
|
||||
REG tto_reg[] = {
|
||||
{ ORDATA (BUF, tto_unit.buf, 16) },
|
||||
|
@ -227,7 +235,7 @@ DEVICE tto_dev = {
|
|||
"TTO", &tto_unit, tto_reg, tto_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &tto_reset,
|
||||
NULL, NULL, NULL };
|
||||
NULL, basic_attach, NULL };
|
||||
|
||||
/* Terminal input routines
|
||||
|
||||
|
@ -270,6 +278,8 @@ void xio_1131_console (int32 iocc_addr, int32 func, int32 modify)
|
|||
ch = (ReadW(iocc_addr) >> 8) & 0xFF; /* get character to write */
|
||||
tto_unit.buf = emit_conout_character(ch); /* output character and save write status */
|
||||
|
||||
// fprintf(stderr, "[CONOUT] %02x\n", ch);
|
||||
|
||||
SETBIT(tto_dsw, TT_DSW_PRINTER_BUSY);
|
||||
sim_activate(&tto_unit, tto_unit.wait); /* schedule interrupt */
|
||||
break;
|
||||
|
@ -288,6 +298,8 @@ void xio_1131_console (int32 iocc_addr, int32 func, int32 modify)
|
|||
sprintf(msg, "Invalid console XIO function %x", func);
|
||||
xio_error(msg);
|
||||
}
|
||||
|
||||
// fprintf(stderr, "After XIO %04x %04x\n", tti_dsw, tto_dsw);
|
||||
}
|
||||
|
||||
// emit_conout_character - write character with 1130 console code 'ch'
|
||||
|
@ -345,6 +357,8 @@ static t_stat tti_svc (UNIT *uptr)
|
|||
/* otherwise, so ^E can interrupt the simulator, */
|
||||
sim_activate(&tti_unit, tti_unit.wait); /* always continue polling keyboard */
|
||||
|
||||
assert(sim_clock_queue != NULL);
|
||||
|
||||
temp = sim_poll_kbd();
|
||||
|
||||
if (temp < SCPE_KFLAG)
|
||||
|
@ -411,6 +425,8 @@ static t_stat tti_svc (UNIT *uptr)
|
|||
SETBIT(ILSW[4], ILSW_4_CONSOLE);
|
||||
calc_ints();
|
||||
|
||||
// fprintf(stderr, "TTI interrupt svc SET %04x %04x\n", tti_dsw, tto_dsw);
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -433,6 +449,35 @@ static t_stat tti_reset (DEVICE *dptr)
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
// basic_attach - fix quotes in filename, then call standard unit attach routine
|
||||
|
||||
t_stat basic_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
return attach_unit(uptr, quotefix(cptr)); /* fix quotes in filenames & attach */
|
||||
}
|
||||
|
||||
// quotefix - strip off quotes around filename, if present
|
||||
|
||||
char * quotefix (char * cptr)
|
||||
{
|
||||
#ifdef WIN32 /* do this only for Windows builds, for the time being */
|
||||
char *c;
|
||||
int quote;
|
||||
|
||||
if (*cptr == '"' || *cptr == '\'') {
|
||||
quote = *cptr++; /* remember quote and skip over it */
|
||||
|
||||
for (c = cptr; *c && *c != quote; c++)
|
||||
; /* find closing quote, or end of string */
|
||||
|
||||
if (*c) /* terminate string at closing quote */
|
||||
*c = '\0';
|
||||
}
|
||||
|
||||
#endif
|
||||
return cptr; /* return pointer to cleaned-up name */
|
||||
}
|
||||
|
||||
t_bool keyboard_is_busy (void) /* return TRUE if keyboard is not expecting a character */
|
||||
{
|
||||
return (tti_dsw & TT_DSW_KEYBOARD_BUSY);
|
||||
|
@ -446,6 +491,8 @@ static t_stat tto_svc (UNIT *uptr)
|
|||
SETBIT(ILSW[4], ILSW_4_CONSOLE);
|
||||
calc_ints();
|
||||
|
||||
// fprintf(stderr, "TTO interrupt svc SET %04x %04x\n", tti_dsw, tto_dsw);
|
||||
|
||||
return (t_stat) tto_unit.buf; /* return status saved during output conversion */
|
||||
}
|
||||
|
||||
|
@ -824,6 +871,9 @@ static t_stat map_conout_character (int ch)
|
|||
curcol--;
|
||||
}
|
||||
else if (n_os_mappings && ch != (unsigned char) IGNR_) {
|
||||
if (curcol >= MAX_OUTPUT_COLUMNS)
|
||||
map_conout_character('\x81'); // precede with automatic carriage return/line feed, I guess
|
||||
|
||||
if (curcol > maxcol) { // first time in this column, no overstrike possible yet
|
||||
os_buf[curcol].nin = 0;
|
||||
maxcol = curcol;
|
||||
|
@ -853,7 +903,7 @@ static t_stat map_conout_character (int ch)
|
|||
}
|
||||
}
|
||||
|
||||
if (curcol < MAX_OUTPUT_COLUMNS)
|
||||
if (curcol < MAX_OUTPUT_COLUMNS) // this should now never happen, as we automatically return
|
||||
curcol++;
|
||||
}
|
||||
|
||||
|
@ -897,18 +947,15 @@ static t_stat font_cmd (int32 flag, char *cptr)
|
|||
if (! *cptr) return SCPE_2FARG; /* argument missing */
|
||||
|
||||
fname = cptr; /* save start */
|
||||
while (*cptr && (*cptr > ' ')) {
|
||||
if (*cptr == '\'' || *cptr == '"') { /* quoted string */
|
||||
quote = *cptr; /* remember quote character */
|
||||
strcpy(cptr, cptr+1); /* slide string down over the quote */
|
||||
quote = *cptr++; /* remember quote character */
|
||||
fname++; /* skip the quote */
|
||||
|
||||
while (*cptr && *cptr != quote) /* find closing quote */
|
||||
while (*cptr && (*cptr != quote)) /* find closing quote */
|
||||
cptr++;
|
||||
|
||||
if (*cptr == quote) /* if closer was found, slide down over it */
|
||||
strcpy(cptr, cptr+1);
|
||||
}
|
||||
else /* skip over regular character */
|
||||
else {
|
||||
while (*cptr && (*cptr > ' ')) /* find terminating blank */
|
||||
cptr++;
|
||||
}
|
||||
*cptr = '\0'; /* terminate name */
|
||||
|
|
|
@ -46,7 +46,6 @@ extern int32 saved_PC;
|
|||
*/
|
||||
|
||||
char sim_name[] = "IBM 1130";
|
||||
char sim_version[] = "V0.30";
|
||||
|
||||
REG *sim_PC = &cpu_reg[0];
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
// Microsoft Visual C++ generated include file.
|
||||
// Used by ibm1130.rc
|
||||
//
|
||||
|
||||
#define IDB_CONSOLE 101
|
||||
#define IDC_HAND 102
|
||||
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
# (This makefile is for operating systems other than Windows,
|
||||
# or compilers other than Microsoft's. For MS builds, use the
|
||||
# .mak files found in this directory and the utils directory).
|
||||
#
|
||||
# If you are building the emulator and utilities as part of
|
||||
# the SIMH package, please:
|
||||
#
|
||||
# Be sure that you there are NO copies of scp.c, scp_tty.c,
|
||||
# sim_sock.c, sim_tmxr.c, sim_rev.h, sim_defs.h, sim_sock.h and
|
||||
# sim_tmxr.h in the ibm1130 subdirectory. Delete them if there
|
||||
# are.
|
||||
#
|
||||
# Do not use this makefile with "make all" or "make ibm1130".
|
||||
# Use the SIMH build files instead.
|
||||
#
|
||||
# If and when you download updates for this simulator from
|
||||
# www.ibm1130.org, get ibm1130code.zip and ibm1130software.zip
|
||||
# separately.
|
||||
#
|
||||
# If you have downloaded the emulator independently of SIMH (e.g, from
|
||||
# www.ibm1130.org), please:
|
||||
#
|
||||
# Be sure that you DO have copies of scp.c, scp_tty.c, sim_sock.c,
|
||||
# sim_tmxr.c, sim_rev.h, sim_defs.h, sim_sock.h and sim_tmxr.h
|
||||
# in this folder.
|
||||
#
|
||||
# Use this file to make the emulator.
|
||||
#
|
||||
# If and when you download updates for this simulator from
|
||||
# www.ibm1130.org, get ibm1130.zip. When you expand it,
|
||||
# also expand ibm1130sofware.zip, which is inside.
|
||||
#
|
||||
# In either case, if you want to build DMS or work with assembly
|
||||
# language programs outside of DMS, you'll want to make the utilities
|
||||
# by cd'ing to the utils directory and running make there.
|
||||
|
||||
# CC Command
|
||||
#
|
||||
# Note: -O2 is sometimes broken in GCC when setjump/longjump is being
|
||||
# used. Try -O2 only with released simulators.
|
||||
#
|
||||
CC = gcc -O0 -lm -I .
|
||||
#CC = gcc -O2 -g -lm -I .
|
||||
|
||||
|
||||
#
|
||||
# Common Libraries
|
||||
#
|
||||
BIN =
|
||||
SIM = scp.c scp_tty.c sim_sock.c sim_tmxr.c
|
||||
SIM_INC = sim_defs.h sim_rev.h sim_sock.h sim_tmxr.h
|
||||
|
||||
#
|
||||
# Emulator source files and compile time options
|
||||
#
|
||||
|
||||
ibm1130D = ./
|
||||
ibm1130 = ${ibm1130D}ibm1130_sys.c ${ibm1130D}ibm1130_cpu.c \
|
||||
${ibm1130D}ibm1130_cr.c ${ibm1130D}ibm1130_disk.c \
|
||||
${ibm1130D}ibm1130_stddev.c ${ibm1130D}ibm1130_gdu.c \
|
||||
${ibm1130D}ibm1130_gui.c ${ibm1130D}ibm1130_prt.c \
|
||||
${ibm1130D}ibm1130_fmt.c
|
||||
|
||||
ibm1130_INC = ibm1130res.h ibm1130_conin.h ibm1130_conout.h \
|
||||
ibm1130_defs.h ibm1130_prtwheel.h ibm1130_fmt.h \
|
||||
dmsr2v12phases.h dmsr2v12slet.h
|
||||
|
||||
#
|
||||
# Build the emulator
|
||||
#
|
||||
|
||||
${BIN}ibm1130 : ${ibm1130} ${SIM} ${ibm1130_INC} ${SIM_INC}
|
||||
${CC} ${ibm1130} ${SIM} -o $@
|
||||
|
|
@ -2,6 +2,18 @@ Version: 10 July 2003
|
|||
|
||||
History (partial):
|
||||
|
||||
2003-11-15 Changed default value of TTO STIME to 200. It was
|
||||
defined using a constant from sim_defs.h which was
|
||||
changed from 10 to 100 at some point. APL\1130 has a
|
||||
sychronization bug & hangs if the console output complete
|
||||
interrupt occurs between the XIO SENSE and WAIT instructions.
|
||||
This bug is hit frequently if the delay time is set to
|
||||
100 instructions. 10 worked reliably, but is really not realistic,
|
||||
and 200 may not be adequate in all cases, but we'll try 200 for now.
|
||||
|
||||
2003-11-00 Updated GUI to allow drag and drop to simulated card
|
||||
reader, tear-off from simulated printer
|
||||
|
||||
2003-07-10 Fixed disk and console terminal bugs uncovered by
|
||||
APL\1130. Added APL keyboard and output font support
|
||||
to enable use of APL\1130. APL will be released soon.
|
||||
|
|
|
@ -1,161 +0,0 @@
|
|||
# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
!IF "$(CFG)" == ""
|
||||
CFG=Win32 Debug
|
||||
!MESSAGE No configuration specified. Defaulting to Win32 Debug.
|
||||
!ENDIF
|
||||
|
||||
!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug"
|
||||
!MESSAGE Invalid configuration "$(CFG)" specified.
|
||||
!MESSAGE You can specify a configuration when running NMAKE on this makefile
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "asm1130.mak" CFG="Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
!ERROR An invalid configuration is specified.
|
||||
!ENDIF
|
||||
|
||||
################################################################################
|
||||
# Begin Project
|
||||
# PROP Target_Last_Scanned "Win32 Debug"
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "WinRel"
|
||||
# PROP BASE Intermediate_Dir "WinRel"
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "WinRel"
|
||||
# PROP Intermediate_Dir "WinRel"
|
||||
OUTDIR=.\WinRel
|
||||
INTDIR=.\WinRel
|
||||
|
||||
ALL : $(OUTDIR)/asm1130.exe $(OUTDIR)/asm1130.bsc
|
||||
|
||||
$(OUTDIR) :
|
||||
if not exist $(OUTDIR)/nul mkdir $(OUTDIR)
|
||||
|
||||
# ADD BASE CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c
|
||||
# ADD CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c
|
||||
CPP_PROJ=/nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\
|
||||
/FR$(INTDIR)/ /Fp$(OUTDIR)/"asm1130.pch" /Fo$(INTDIR)/ /c
|
||||
CPP_OBJS=.\WinRel/
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
BSC32_FLAGS=/nologo /o$(OUTDIR)/"asm1130.bsc"
|
||||
BSC32_SBRS= \
|
||||
$(INTDIR)/asm1130.sbr
|
||||
|
||||
$(OUTDIR)/asm1130.bsc : $(OUTDIR) $(BSC32_SBRS)
|
||||
$(BSC32) @<<
|
||||
$(BSC32_FLAGS) $(BSC32_SBRS)
|
||||
<<
|
||||
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386
|
||||
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console\
|
||||
/INCREMENTAL:no /PDB:$(OUTDIR)/"asm1130.pdb" /MACHINE:I386\
|
||||
/OUT:$(OUTDIR)/"asm1130.exe"
|
||||
DEF_FILE=
|
||||
LINK32_OBJS= \
|
||||
$(INTDIR)/asm1130.obj
|
||||
|
||||
$(OUTDIR)/asm1130.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS)
|
||||
$(LINK32) @<<
|
||||
$(LINK32_FLAGS) $(LINK32_OBJS)
|
||||
<<
|
||||
|
||||
!ELSEIF "$(CFG)" == "Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "WinDebug"
|
||||
# PROP BASE Intermediate_Dir "WinDebug"
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "WinDebug"
|
||||
# PROP Intermediate_Dir "WinDebug"
|
||||
OUTDIR=.\WinDebug
|
||||
INTDIR=.\WinDebug
|
||||
|
||||
ALL : $(OUTDIR)/asm1130.exe $(OUTDIR)/asm1130.bsc
|
||||
|
||||
$(OUTDIR) :
|
||||
if not exist $(OUTDIR)/nul mkdir $(OUTDIR)
|
||||
|
||||
# ADD BASE CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c
|
||||
# ADD CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c
|
||||
CPP_PROJ=/nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\
|
||||
/FR$(INTDIR)/ /Fp$(OUTDIR)/"asm1130.pch" /Fo$(INTDIR)/\
|
||||
/Fd$(OUTDIR)/"asm1130.pdb" /c
|
||||
CPP_OBJS=.\WinDebug/
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
BSC32_FLAGS=/nologo /o$(OUTDIR)/"asm1130.bsc"
|
||||
BSC32_SBRS= \
|
||||
$(INTDIR)/asm1130.sbr
|
||||
|
||||
$(OUTDIR)/asm1130.bsc : $(OUTDIR) $(BSC32_SBRS)
|
||||
$(BSC32) @<<
|
||||
$(BSC32_FLAGS) $(BSC32_SBRS)
|
||||
<<
|
||||
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386
|
||||
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console\
|
||||
/INCREMENTAL:yes /PDB:$(OUTDIR)/"asm1130.pdb" /DEBUG /MACHINE:I386\
|
||||
/OUT:$(OUTDIR)/"asm1130.exe"
|
||||
DEF_FILE=
|
||||
LINK32_OBJS= \
|
||||
$(INTDIR)/asm1130.obj
|
||||
|
||||
$(OUTDIR)/asm1130.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS)
|
||||
$(LINK32) @<<
|
||||
$(LINK32_FLAGS) $(LINK32_OBJS)
|
||||
<<
|
||||
|
||||
!ENDIF
|
||||
|
||||
.c{$(CPP_OBJS)}.obj:
|
||||
$(CPP) $(CPP_PROJ) $<
|
||||
|
||||
.cpp{$(CPP_OBJS)}.obj:
|
||||
$(CPP) $(CPP_PROJ) $<
|
||||
|
||||
.cxx{$(CPP_OBJS)}.obj:
|
||||
$(CPP) $(CPP_PROJ) $<
|
||||
|
||||
################################################################################
|
||||
# Begin Group "Source Files"
|
||||
|
||||
################################################################################
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\asm1130.c
|
||||
|
||||
$(INTDIR)/asm1130.obj : $(SOURCE) $(INTDIR)
|
||||
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Project
|
||||
################################################################################
|
|
@ -1,752 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright 2002, Brian Knittel.
|
||||
* You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN
|
||||
* RISK basis, there is no warranty of fitness for any purpose, and the rest of the
|
||||
* usual yada-yada. Please keep this notice and the copyright in any distributions
|
||||
* or modifications.
|
||||
*
|
||||
* This is not a supported product, but I welcome bug reports and fixes.
|
||||
* Mail to sim@ibm1130.org
|
||||
*/
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
// BINDUMP - dumps card deck files in assembler object format
|
||||
//
|
||||
// Usage:
|
||||
/// bindump deckfile lists object header info & sector break cards
|
||||
// bindump -v deckfile lists object data records as well
|
||||
// bindump -p deckfile for system program, lists phase IDs in the deck
|
||||
// bindump -s deckfile >outfile for system program, sorts the phases & writes to stdout
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef WIN32
|
||||
# include <windows.h>
|
||||
# include <io.h>
|
||||
# include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define BOOL int
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
typedef enum {R_ABSOLUTE = 0, R_RELATIVE = 1, R_LIBF = 2, R_CALL = 3} RELOC;
|
||||
|
||||
BOOL verbose = FALSE;
|
||||
BOOL phid = FALSE;
|
||||
BOOL sort = FALSE;
|
||||
unsigned short card[80], buf[54], cardtype;
|
||||
|
||||
// bindump - dump a binary (card format) deck to verify sbrks, etc
|
||||
|
||||
void bail (char *msg);
|
||||
void dump (char *fname);
|
||||
void dump_data (char *fname);
|
||||
void dump_phids (char *fname);
|
||||
char *getname (unsigned short *ptr);
|
||||
char *getseq (void);
|
||||
int hollerith_to_ascii (unsigned short h);
|
||||
void process (char *fname);
|
||||
void show_raw (char *name);
|
||||
void show_data (void);
|
||||
void show_core (void);
|
||||
void show_endc (void);
|
||||
void show_81 (void);
|
||||
void show_main (void);
|
||||
void show_sub (void);
|
||||
void show_ils (void);
|
||||
void show_iss (void);
|
||||
void show_end (void);
|
||||
void sort_phases (char *fname);
|
||||
void trim (char *s);
|
||||
void unpack (unsigned short *card, unsigned short *buf);
|
||||
void verify_checksum(unsigned short *buf);
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
char *arg;
|
||||
static char usestr[] = "Usage: bindump [-psv] filename...";
|
||||
int i;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
arg = argv[i];
|
||||
if (*arg == '-') {
|
||||
arg++;
|
||||
while (*arg) {
|
||||
switch (*arg++) {
|
||||
case 'v':
|
||||
verbose = TRUE;
|
||||
break;
|
||||
case 'p':
|
||||
phid = TRUE; // print only phase ID's
|
||||
break;
|
||||
case 's':
|
||||
sort = TRUE; // sort deck by phases, writing to stdout
|
||||
break;
|
||||
default:
|
||||
bail(usestr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
arg = argv[i];
|
||||
if (*arg != '-')
|
||||
process(arg);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void process (char *nm)
|
||||
{
|
||||
#ifdef WIN32
|
||||
WIN32_FIND_DATA fd;
|
||||
HANDLE hFind;
|
||||
char *c, buf[256];
|
||||
|
||||
if (strchr(nm, '*') == NULL && strchr(nm, '?') == NULL)
|
||||
dump(nm);
|
||||
|
||||
else if ((hFind = FindFirstFile(nm, &fd)) == INVALID_HANDLE_VALUE)
|
||||
fprintf(stderr, "No files matching '%s'\n", nm);
|
||||
|
||||
else {
|
||||
if ((c = strrchr(nm, '\\')) == NULL)
|
||||
c = strrchr(nm, ':');
|
||||
|
||||
do {
|
||||
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
continue;
|
||||
|
||||
if (c == NULL)
|
||||
dump(fd.cFileName);
|
||||
else {
|
||||
strcpy(buf, nm);
|
||||
strcpy(buf + (c-nm+1), fd.cFileName);
|
||||
dump(buf);
|
||||
}
|
||||
|
||||
} while (FindNextFile(hFind, &fd));
|
||||
|
||||
FindClose(hFind);
|
||||
}
|
||||
#else
|
||||
dump(nm); // on unices, sh globs for us
|
||||
#endif
|
||||
}
|
||||
|
||||
void dump (char *fname)
|
||||
{
|
||||
if (sort)
|
||||
sort_phases(fname);
|
||||
else if (phid)
|
||||
dump_phids(fname);
|
||||
else
|
||||
dump_data(fname);
|
||||
}
|
||||
|
||||
struct tag_card {
|
||||
int phid, seq;
|
||||
unsigned short card[80];
|
||||
};
|
||||
|
||||
int cardcomp (const void *a, const void *b)
|
||||
{
|
||||
short diff;
|
||||
|
||||
diff = ((struct tag_card *) a)->phid - ((struct tag_card *) b)->phid;
|
||||
|
||||
return diff ? diff : (((struct tag_card *) a)->seq - ((struct tag_card *) b)->seq);
|
||||
}
|
||||
|
||||
void sort_phases (char *fname)
|
||||
{
|
||||
int i, ncards, cardtype, len, seq = 0, phid;
|
||||
struct tag_card *deck;
|
||||
FILE *fd;
|
||||
BOOL saw_sbrk = TRUE;
|
||||
|
||||
if ((fd = fopen(fname, "rb")) == NULL) {
|
||||
perror(fname);
|
||||
return;
|
||||
}
|
||||
|
||||
fseek(fd, 0, SEEK_END);
|
||||
len = ftell(fd); // get length of file
|
||||
fseek(fd, 0, SEEK_SET);
|
||||
|
||||
if (len <= 0 || (len % 160) != 0) {
|
||||
fprintf(stderr, "%s is not a binard deck image\n");
|
||||
fclose(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
ncards = len / 160;
|
||||
|
||||
if ((deck = (struct tag_card *) malloc(ncards*sizeof(struct tag_card))) == NULL) {
|
||||
fprintf(stderr, "%s: can't sort, insufficient memory\n");
|
||||
fclose(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
phid = 0;
|
||||
for (i = 0; i < ncards; i++) {
|
||||
if (fread(deck[i].card, sizeof(card[0]), 80, fd) != 80) {
|
||||
free(deck);
|
||||
fprintf(stderr, "%s: error reading deck\n");
|
||||
fclose(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
unpack(deck[i].card, buf);
|
||||
deck[i].seq = seq++;
|
||||
deck[i].phid = phid;
|
||||
|
||||
verify_checksum(buf);
|
||||
|
||||
cardtype = (buf[2] >> 8) & 0xFF;
|
||||
|
||||
if (cardtype == 1 || cardtype == 2) { // start of deck is same as sector break
|
||||
saw_sbrk = TRUE;
|
||||
}
|
||||
else if (cardtype == 0) {
|
||||
fprintf(stderr, "%s is a core image deck\n");
|
||||
free(deck);
|
||||
fclose(fd);
|
||||
return;
|
||||
}
|
||||
else if (cardtype == 0x0A && saw_sbrk) {
|
||||
phid = (int) (signed short) buf[10];
|
||||
if (phid < 0)
|
||||
phid = -phid;
|
||||
|
||||
deck[i].phid = phid; // this belongs to the new phase
|
||||
deck[i-1].phid = phid; // as does previous card
|
||||
saw_sbrk = FALSE;
|
||||
}
|
||||
}
|
||||
fclose(fd);
|
||||
|
||||
qsort(deck, ncards, sizeof(struct tag_card), cardcomp); // sort the deck
|
||||
|
||||
#ifdef WIN32
|
||||
_setmode(_fileno(stdout), _O_BINARY); // set standard output to binary mode
|
||||
#endif
|
||||
|
||||
for (i = 0; i < ncards; i++) // write to stdout
|
||||
fwrite(deck[i].card, sizeof(card[0]), 80, stdout);
|
||||
|
||||
free(deck);
|
||||
}
|
||||
|
||||
void dump_phids (char *fname)
|
||||
{
|
||||
FILE *fp;
|
||||
BOOL first = TRUE;
|
||||
BOOL saw_sbrk = TRUE, neg;
|
||||
short id;
|
||||
|
||||
if ((fp = fopen(fname, "rb")) == NULL) {
|
||||
perror(fname);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("\n%s:\n", fname);
|
||||
|
||||
while (fread(card, sizeof(card[0]), 80, fp) > 0) {
|
||||
unpack(card, buf);
|
||||
verify_checksum(buf);
|
||||
|
||||
cardtype = (buf[2] >> 8) & 0xFF;
|
||||
|
||||
if (cardtype == 1 && ! first) { // sector break
|
||||
saw_sbrk = TRUE;
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
switch (cardtype) {
|
||||
case 0x00:
|
||||
printf(" This is a core image deck\n");
|
||||
goto done;
|
||||
break;
|
||||
case 0x01:
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
case 0x04:
|
||||
case 0x05:
|
||||
case 0x06:
|
||||
case 0x07:
|
||||
case 0x0F:
|
||||
break;
|
||||
|
||||
case 0x0A:
|
||||
if (saw_sbrk) {
|
||||
id = buf[10];
|
||||
if (id < 0)
|
||||
id = -id, neg = TRUE;
|
||||
else
|
||||
neg = FALSE;
|
||||
printf(" : %3d / %02x%s\n", id, id, neg ? " (neg)" : "");
|
||||
saw_sbrk = FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
show_raw("??? ");
|
||||
}
|
||||
}
|
||||
done:
|
||||
first = FALSE;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void dump_data (char *fname)
|
||||
{
|
||||
FILE *fp;
|
||||
BOOL first = TRUE;
|
||||
char str[80];
|
||||
int i;
|
||||
|
||||
if ((fp = fopen(fname, "rb")) == NULL) {
|
||||
perror(fname);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("\n%s:\n", fname);
|
||||
|
||||
while (fread(card, sizeof(card[0]), 80, fp) > 0) {
|
||||
unpack(card, buf);
|
||||
verify_checksum(buf);
|
||||
|
||||
cardtype = (buf[2] >> 8) & 0xFF;
|
||||
|
||||
if (cardtype == 1 && ! first) { // sector break
|
||||
for (i = 4; i < 72; i++)
|
||||
str[i] = hollerith_to_ascii(card[i]);
|
||||
|
||||
str[i] = '\0';
|
||||
trim(str+4);
|
||||
printf("*SBRK %s\n", str+4);
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
switch (cardtype) {
|
||||
case 0x00:
|
||||
if (first)
|
||||
show_raw("CORE");
|
||||
if (verbose)
|
||||
show_core();
|
||||
break;
|
||||
|
||||
case 0x01:
|
||||
show_raw("ABS ");
|
||||
show_main();
|
||||
break;
|
||||
case 0x02:
|
||||
show_raw("REL ");
|
||||
show_main();
|
||||
break;
|
||||
case 0x03:
|
||||
show_raw("LIB ");
|
||||
show_sub();
|
||||
break;
|
||||
case 0x04:
|
||||
show_raw("SUB ");
|
||||
show_sub();
|
||||
break;
|
||||
case 0x05:
|
||||
show_raw("ISSL");
|
||||
show_iss();
|
||||
break;
|
||||
case 0x06:
|
||||
show_raw("ISSC");
|
||||
show_iss();
|
||||
break;
|
||||
case 0x07:
|
||||
show_raw("ILS ");
|
||||
show_ils();
|
||||
break;
|
||||
case 0x0F:
|
||||
show_raw("END ");
|
||||
show_end();
|
||||
break;
|
||||
case 0x80:
|
||||
show_raw("ENDC");
|
||||
show_endc();
|
||||
break;
|
||||
case 0x81:
|
||||
show_raw("81 ");
|
||||
show_81();
|
||||
break;
|
||||
case 0x0A:
|
||||
if (verbose)
|
||||
show_data();
|
||||
break;
|
||||
default:
|
||||
show_raw("??? ");
|
||||
}
|
||||
}
|
||||
|
||||
first = FALSE;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void show_data (void)
|
||||
{
|
||||
int i, n, jrel, rflag, nout, ch, reloc;
|
||||
BOOL first = TRUE;
|
||||
|
||||
n = buf[2] & 0x00FF;
|
||||
|
||||
printf("%04x: ", buf[0]);
|
||||
|
||||
jrel = 3;
|
||||
nout = 0;
|
||||
rflag = buf[jrel++];
|
||||
for (i = 0; i < n; i++) {
|
||||
if (nout >= 8) {
|
||||
rflag = buf[jrel++];
|
||||
if (first) {
|
||||
printf(" %s", getseq());
|
||||
first = FALSE;
|
||||
}
|
||||
printf("\n ");
|
||||
nout = 0;
|
||||
}
|
||||
reloc = (rflag >> 14) & 0x03;
|
||||
ch = (reloc == R_ABSOLUTE) ? ' ' :
|
||||
(reloc == R_RELATIVE) ? 'R' :
|
||||
(reloc == R_LIBF) ? 'L' : '@';
|
||||
|
||||
printf("%04x%c ", buf[9+i], ch);
|
||||
rflag <<= 2;
|
||||
nout++;
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
void show_core (void)
|
||||
{
|
||||
int i, n, nout;
|
||||
BOOL first = TRUE;
|
||||
|
||||
n = buf[2] & 0x00FF;
|
||||
|
||||
printf("%04x: ", buf[0]);
|
||||
|
||||
nout = 0;
|
||||
for (i = 0; i < n; i++) {
|
||||
if (nout >= 8) {
|
||||
if (first) {
|
||||
printf(" %s", getseq());
|
||||
first = FALSE;
|
||||
}
|
||||
printf("\n ");
|
||||
nout = 0;
|
||||
}
|
||||
printf("%04x ", buf[9+i]);
|
||||
nout++;
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
void info (int i, char *nm, char type)
|
||||
{
|
||||
if (nm)
|
||||
printf("%s ", nm);
|
||||
|
||||
switch (type) {
|
||||
case 'd':
|
||||
printf("%d ", buf[i]);
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
printf("%04x ", buf[i]);
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
printf("%02x ", buf[i] & 0xFF);
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
printf("%s ", getname(buf+i));
|
||||
break;
|
||||
|
||||
default:
|
||||
bail("BAD TYPE");
|
||||
}
|
||||
}
|
||||
|
||||
void show_main (void)
|
||||
{
|
||||
printf(" ");
|
||||
info(2, "prec", 'b');
|
||||
info(4, "common", 'd');
|
||||
info(6, "work", 'd');
|
||||
info(8, "files", 'd');
|
||||
info(9, "name", 'n');
|
||||
info(11, "pta", 'x');
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
void show_sub (void)
|
||||
{
|
||||
int i, n;
|
||||
|
||||
printf(" ");
|
||||
info( 2, "prec", 'b');
|
||||
|
||||
n = buf[5] / 3;
|
||||
for (i = 0; i < n; i++) {
|
||||
info( 9+3*i, "ent", 'n');
|
||||
info(11+3*i, NULL, 'x');
|
||||
}
|
||||
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
void show_iss (void)
|
||||
{
|
||||
printf(" ");
|
||||
info(12, "level", 'd');
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
void show_ils (void)
|
||||
{
|
||||
printf(" ");
|
||||
info( 2, "prec", 'b');
|
||||
info( 5, "nint6", 'd');
|
||||
info( 9, "ent", 'n');
|
||||
info(11, NULL, 'x');
|
||||
info(14, "nint", 'd');
|
||||
info(15, "il1", 'd');
|
||||
info(16, "il2", 'd');
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
void show_end (void)
|
||||
{
|
||||
printf(" ");
|
||||
info(0, "size", 'd');
|
||||
info(3, "pta", 'x');
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
void show_endc(void)
|
||||
{
|
||||
printf(" ");
|
||||
info(52, "IX3", 'x');
|
||||
info(53, "pta", 'x');
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
void show_81(void)
|
||||
{
|
||||
}
|
||||
|
||||
void show_raw (char *name)
|
||||
{
|
||||
int i;
|
||||
printf("*%s", name);
|
||||
|
||||
for (i = 0; i < 12; i++)
|
||||
printf(" %04x", buf[i]);
|
||||
|
||||
printf(" %s\n", getseq());
|
||||
}
|
||||
|
||||
char * getseq (void)
|
||||
{
|
||||
static char seq[10];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
seq[i] = hollerith_to_ascii(card[72+i]);
|
||||
|
||||
seq[i] = '\0';
|
||||
return seq;
|
||||
}
|
||||
|
||||
|
||||
void bail (char *msg)
|
||||
{
|
||||
fprintf(stderr, "%s\n", msg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void unpack (unsigned short *icard, unsigned short *obuf)
|
||||
{
|
||||
int i, j;
|
||||
unsigned short wd1, wd2, wd3, wd4;
|
||||
|
||||
for (i = j = 0; i < 54; i += 3, j += 4) {
|
||||
wd1 = icard[j];
|
||||
wd2 = icard[j+1];
|
||||
wd3 = icard[j+2];
|
||||
wd4 = icard[j+3];
|
||||
|
||||
obuf[i ] = (wd1 & 0xFFF0) | ((wd2 >> 12) & 0x000F);
|
||||
obuf[i+1] = ((wd2 << 4) & 0xFF00) | ((wd3 >> 8) & 0x00FF);
|
||||
obuf[i+2] = ((wd3 << 8) & 0xF000) | ((wd4 >> 4) & 0x0FFF);
|
||||
}
|
||||
}
|
||||
|
||||
void verify_checksum (unsigned short *obuf)
|
||||
{
|
||||
// unsigned short sum;
|
||||
|
||||
if (obuf[1] == 0) // no checksum
|
||||
return;
|
||||
|
||||
// if (sum != card[1])
|
||||
// printf("Checksum %04x doesn't match card %04x\n", sum, card[1]);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
unsigned short hollerith;
|
||||
char ascii;
|
||||
} CPCODE;
|
||||
|
||||
static CPCODE cardcode_029[] =
|
||||
{
|
||||
0x0000, ' ',
|
||||
0x8000, '&', // + in 026 Fortran
|
||||
0x4000, '-',
|
||||
0x2000, '0',
|
||||
0x1000, '1',
|
||||
0x0800, '2',
|
||||
0x0400, '3',
|
||||
0x0200, '4',
|
||||
0x0100, '5',
|
||||
0x0080, '6',
|
||||
0x0040, '7',
|
||||
0x0020, '8',
|
||||
0x0010, '9',
|
||||
0x9000, 'A',
|
||||
0x8800, 'B',
|
||||
0x8400, 'C',
|
||||
0x8200, 'D',
|
||||
0x8100, 'E',
|
||||
0x8080, 'F',
|
||||
0x8040, 'G',
|
||||
0x8020, 'H',
|
||||
0x8010, 'I',
|
||||
0x5000, 'J',
|
||||
0x4800, 'K',
|
||||
0x4400, 'L',
|
||||
0x4200, 'M',
|
||||
0x4100, 'N',
|
||||
0x4080, 'O',
|
||||
0x4040, 'P',
|
||||
0x4020, 'Q',
|
||||
0x4010, 'R',
|
||||
0x3000, '/',
|
||||
0x2800, 'S',
|
||||
0x2400, 'T',
|
||||
0x2200, 'U',
|
||||
0x2100, 'V',
|
||||
0x2080, 'W',
|
||||
0x2040, 'X',
|
||||
0x2020, 'Y',
|
||||
0x2010, 'Z',
|
||||
0x0820, ':',
|
||||
0x0420, '#', // = in 026 Fortran
|
||||
0x0220, '@', // ' in 026 Fortran
|
||||
0x0120, '\'',
|
||||
0x00A0, '=',
|
||||
0x0060, '"',
|
||||
0x8820, 'c', // cent
|
||||
0x8420, '.',
|
||||
0x8220, '<', // ) in 026 Fortran
|
||||
0x8120, '(',
|
||||
0x80A0, '+',
|
||||
0x8060, '|',
|
||||
0x4820, '!',
|
||||
0x4420, '$',
|
||||
0x4220, '*',
|
||||
0x4120, ')',
|
||||
0x40A0, ';',
|
||||
0x4060, 'n', // not
|
||||
0x2820, 'x', // what?
|
||||
0x2420, ',',
|
||||
0x2220, '%', // ( in 026 Fortran
|
||||
0x2120, '_',
|
||||
0x20A0, '>',
|
||||
0x2060, '>',
|
||||
};
|
||||
|
||||
int hollerith_to_ascii (unsigned short h)
|
||||
{
|
||||
int i;
|
||||
|
||||
h &= 0xFFF0;
|
||||
|
||||
for (i = 0; i < sizeof(cardcode_029) / sizeof(CPCODE); i++)
|
||||
if (cardcode_029[i].hollerith == h)
|
||||
return cardcode_029[i].ascii;
|
||||
|
||||
return '?';
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
// trim - remove trailing whitespace from string s
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
||||
void trim (char *s)
|
||||
{
|
||||
char *nb;
|
||||
|
||||
for (nb = s-1; *s; s++)
|
||||
if (*s > ' ')
|
||||
nb = s;
|
||||
|
||||
nb[1] = '\0';
|
||||
}
|
||||
|
||||
int ascii_to_ebcdic_table[128] =
|
||||
{
|
||||
0x00,0x01,0x02,0x03,0x37,0x2d,0x2e,0x2f, 0x16,0x05,0x25,0x0b,0x0c,0x0d,0x0e,0x0f,
|
||||
0x10,0x11,0x12,0x13,0x3c,0x3d,0x32,0x26, 0x18,0x19,0x3f,0x27,0x1c,0x1d,0x1e,0x1f,
|
||||
0x40,0x5a,0x7f,0x7b,0x5b,0x6c,0x50,0x7d, 0x4d,0x5d,0x5c,0x4e,0x6b,0x60,0x4b,0x61,
|
||||
0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0x7a,0x5e,0x4c,0x7e,0x6e,0x6f,
|
||||
|
||||
0x7c,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, 0xc8,0xc9,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,
|
||||
0xd7,0xd8,0xd9,0xe2,0xe3,0xe4,0xe5,0xe6, 0xe7,0xe8,0xe9,0xba,0xe0,0xbb,0xb0,0x6d,
|
||||
0x79,0x81,0x82,0x83,0x84,0x85,0x86,0x87, 0x88,0x89,0x91,0x92,0x93,0x94,0x95,0x96,
|
||||
0x97,0x98,0x99,0xa2,0xa3,0xa4,0xa5,0xa6, 0xa7,0xa8,0xa9,0xc0,0x4f,0xd0,0xa1,0x07,
|
||||
};
|
||||
|
||||
char *getname (unsigned short *ptr)
|
||||
{
|
||||
static char str[6];
|
||||
int i, j, ch;
|
||||
long v;
|
||||
|
||||
v = (ptr[0] << 16L) | ptr[1];
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
ch = ((v >> 24) & 0x3F) | 0xC0; // recover those lost two bits
|
||||
v <<= 6;
|
||||
|
||||
str[i] = ' ';
|
||||
|
||||
for (j = 0; j < (sizeof(ascii_to_ebcdic_table)/sizeof(ascii_to_ebcdic_table[0])); j++) {
|
||||
if (ascii_to_ebcdic_table[j] == ch) {
|
||||
str[i] = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
str[5] = '\0';
|
||||
return str;
|
||||
}
|
||||
|
|
@ -1,161 +0,0 @@
|
|||
# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
!IF "$(CFG)" == ""
|
||||
CFG=Win32 Debug
|
||||
!MESSAGE No configuration specified. Defaulting to Win32 Debug.
|
||||
!ENDIF
|
||||
|
||||
!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug"
|
||||
!MESSAGE Invalid configuration "$(CFG)" specified.
|
||||
!MESSAGE You can specify a configuration when running NMAKE on this makefile
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "bindump.mak" CFG="Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
!ERROR An invalid configuration is specified.
|
||||
!ENDIF
|
||||
|
||||
################################################################################
|
||||
# Begin Project
|
||||
# PROP Target_Last_Scanned "Win32 Debug"
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "WinRel"
|
||||
# PROP BASE Intermediate_Dir "WinRel"
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "WinRel"
|
||||
# PROP Intermediate_Dir "WinRel"
|
||||
OUTDIR=.\WinRel
|
||||
INTDIR=.\WinRel
|
||||
|
||||
ALL : $(OUTDIR)/bindump.exe $(OUTDIR)/bindump.bsc
|
||||
|
||||
$(OUTDIR) :
|
||||
if not exist $(OUTDIR)/nul mkdir $(OUTDIR)
|
||||
|
||||
# ADD BASE CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c
|
||||
# ADD CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c
|
||||
CPP_PROJ=/nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\
|
||||
/FR$(INTDIR)/ /Fp$(OUTDIR)/"bindump.pch" /Fo$(INTDIR)/ /c
|
||||
CPP_OBJS=.\WinRel/
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
BSC32_FLAGS=/nologo /o$(OUTDIR)/"bindump.bsc"
|
||||
BSC32_SBRS= \
|
||||
$(INTDIR)/bindump.sbr
|
||||
|
||||
$(OUTDIR)/bindump.bsc : $(OUTDIR) $(BSC32_SBRS)
|
||||
$(BSC32) @<<
|
||||
$(BSC32_FLAGS) $(BSC32_SBRS)
|
||||
<<
|
||||
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386
|
||||
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
|
||||
/NOLOGO /SUBSYSTEM:console /INCREMENTAL:no /PDB:$(OUTDIR)/"bindump.pdb"\
|
||||
/MACHINE:I386 /OUT:$(OUTDIR)/"bindump.exe"
|
||||
DEF_FILE=
|
||||
LINK32_OBJS= \
|
||||
$(INTDIR)/bindump.obj
|
||||
|
||||
$(OUTDIR)/bindump.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS)
|
||||
$(LINK32) @<<
|
||||
$(LINK32_FLAGS) $(LINK32_OBJS)
|
||||
<<
|
||||
|
||||
!ELSEIF "$(CFG)" == "Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "WinDebug"
|
||||
# PROP BASE Intermediate_Dir "WinDebug"
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "WinDebug"
|
||||
# PROP Intermediate_Dir "WinDebug"
|
||||
OUTDIR=.\WinDebug
|
||||
INTDIR=.\WinDebug
|
||||
|
||||
ALL : $(OUTDIR)/bindump.exe $(OUTDIR)/bindump.bsc
|
||||
|
||||
$(OUTDIR) :
|
||||
if not exist $(OUTDIR)/nul mkdir $(OUTDIR)
|
||||
|
||||
# ADD BASE CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c
|
||||
# ADD CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c
|
||||
CPP_PROJ=/nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\
|
||||
/FR$(INTDIR)/ /Fp$(OUTDIR)/"bindump.pch" /Fo$(INTDIR)/\
|
||||
/Fd$(OUTDIR)/"bindump.pdb" /c
|
||||
CPP_OBJS=.\WinDebug/
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
BSC32_FLAGS=/nologo /o$(OUTDIR)/"bindump.bsc"
|
||||
BSC32_SBRS= \
|
||||
$(INTDIR)/bindump.sbr
|
||||
|
||||
$(OUTDIR)/bindump.bsc : $(OUTDIR) $(BSC32_SBRS)
|
||||
$(BSC32) @<<
|
||||
$(BSC32_FLAGS) $(BSC32_SBRS)
|
||||
<<
|
||||
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386
|
||||
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
|
||||
/NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes /PDB:$(OUTDIR)/"bindump.pdb" /DEBUG\
|
||||
/MACHINE:I386 /OUT:$(OUTDIR)/"bindump.exe"
|
||||
DEF_FILE=
|
||||
LINK32_OBJS= \
|
||||
$(INTDIR)/bindump.obj
|
||||
|
||||
$(OUTDIR)/bindump.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS)
|
||||
$(LINK32) @<<
|
||||
$(LINK32_FLAGS) $(LINK32_OBJS)
|
||||
<<
|
||||
|
||||
!ENDIF
|
||||
|
||||
.c{$(CPP_OBJS)}.obj:
|
||||
$(CPP) $(CPP_PROJ) $<
|
||||
|
||||
.cpp{$(CPP_OBJS)}.obj:
|
||||
$(CPP) $(CPP_PROJ) $<
|
||||
|
||||
.cxx{$(CPP_OBJS)}.obj:
|
||||
$(CPP) $(CPP_PROJ) $<
|
||||
|
||||
################################################################################
|
||||
# Begin Group "Source Files"
|
||||
|
||||
################################################################################
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\bindump.c
|
||||
|
||||
$(INTDIR)/bindump.obj : $(SOURCE) $(INTDIR)
|
||||
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Project
|
||||
################################################################################
|
|
@ -1,264 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright 2002, Brian Knittel.
|
||||
* You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN
|
||||
* RISK basis, there is no warranty of fitness for any purpose, and the rest of the
|
||||
* usual yada-yada. Please keep this notice and the copyright in any distributions
|
||||
* or modifications.
|
||||
*
|
||||
* This is not a supported product, but I welcome bug reports and fixes.
|
||||
* Mail to sim@ibm1130.org
|
||||
*/
|
||||
|
||||
// checkdisk - validates and optionally dumps an IBM1130 DMS2 disk image file
|
||||
//
|
||||
// Usage:
|
||||
// checkdisk [-f] [-d cyl.sec|abssec] [-n count] filename
|
||||
//
|
||||
// Examples:
|
||||
// checkdisk file.dsk
|
||||
// report any misnumbered sectors in file.dsk
|
||||
//
|
||||
// checkdisk -f file.dsk
|
||||
// report and fix any misnumbered sectors
|
||||
//
|
||||
// checkdisk -d 198.0 file.dsk
|
||||
// dump cylinder 198 sector 0
|
||||
//
|
||||
// checkdisk -d 0 file.dsk
|
||||
// dump absolute sector 0
|
||||
//
|
||||
// checkdisk -d 198.0 -n 4 file.dsk
|
||||
// dump 4 sectors starting at m.n
|
||||
// -----------------------------------------------------------------------------------------
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "util_io.h"
|
||||
|
||||
#ifdef WIN32
|
||||
# include <io.h>
|
||||
#else
|
||||
long filelength (int fno);
|
||||
# include <sys/types.h>
|
||||
# include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
# define BOOL int
|
||||
# define TRUE 1
|
||||
# define FALSE 0
|
||||
#endif
|
||||
|
||||
#define DSK_NUMWD 321 /* words/sector */
|
||||
#define DSK_NUMSC 4 /* sectors/surface */
|
||||
#define DSK_NUMSF 2 /* surfaces/cylinder */
|
||||
#define DSK_NUMCY 203 /* cylinders/drive */
|
||||
#define DSK_NUMDR 5 /* drives/controller */
|
||||
#define DSK_SIZE (DSK_NUMCY * DSK_NUMSF * DSK_NUMSC * DSK_NUMWD) /* words/drive */
|
||||
|
||||
char *usestr = "Usage: checkdisk [-f] [-d cyl.sec|abssec] [-n count] diskfile";
|
||||
char *baddisk = "Cannot fix this";
|
||||
|
||||
void bail (char *msg);
|
||||
char *lowcase (char *str);
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
FILE *fp;
|
||||
char *fname = NULL, *arg, *argval;
|
||||
int i, j, cyl, sec, pos, asec, retry, nbad = 0, nfixed = 0, nline;
|
||||
BOOL fixit = FALSE, dump = FALSE;
|
||||
int dsec, nsec = 1;
|
||||
unsigned short wd, buf[DSK_NUMWD];
|
||||
|
||||
util_io_init();
|
||||
|
||||
for (i = 1; i < argc;) {
|
||||
arg = argv[i++];
|
||||
if (*arg == '-') {
|
||||
arg++;
|
||||
lowcase(arg);
|
||||
while (*arg) {
|
||||
switch (*arg++) {
|
||||
case 'f':
|
||||
fixit = TRUE;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
dump = TRUE;
|
||||
|
||||
if (i >= argc)
|
||||
bail(usestr);
|
||||
|
||||
argval = argv[i++];
|
||||
if (strchr(argval, '.') != NULL) {
|
||||
if (sscanf(argval, "%d.%d", &cyl, &sec) != 2)
|
||||
bail(usestr);
|
||||
|
||||
dsec = cyl*(DSK_NUMSF*DSK_NUMSC) + sec;
|
||||
}
|
||||
else if (sscanf(argval, "%d", &dsec) != 1)
|
||||
bail(usestr);
|
||||
|
||||
if (dsec < 0 || dsec >= (DSK_NUMCY*DSK_NUMSF*DSK_NUMSC))
|
||||
bail("No such sector");
|
||||
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
if (i >= argc)
|
||||
bail(usestr);
|
||||
|
||||
argval = argv[i++];
|
||||
if (sscanf(argval, "%d", &nsec) != 1)
|
||||
bail(usestr);
|
||||
|
||||
if (nsec <= 0)
|
||||
bail(usestr);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
bail(usestr);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (fname == NULL)
|
||||
fname = arg;
|
||||
else
|
||||
bail(usestr);
|
||||
}
|
||||
|
||||
if (fname == NULL)
|
||||
bail(usestr);
|
||||
|
||||
if ((fp = fopen(fname, "rb+")) == NULL) {
|
||||
perror(fname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (filelength(fileno(fp)) != 2*DSK_SIZE) {
|
||||
fprintf(stderr, "File is wrong length, expected %d\n", DSK_SIZE);
|
||||
bail(baddisk);
|
||||
}
|
||||
|
||||
for (cyl = 0; cyl < DSK_NUMCY; cyl++) {
|
||||
for (sec = 0; sec < (DSK_NUMSF*DSK_NUMSC); sec++) {
|
||||
retry = 1;
|
||||
again:
|
||||
asec = cyl*(DSK_NUMSF*DSK_NUMSC) + sec;
|
||||
pos = asec*2*DSK_NUMWD;
|
||||
|
||||
if (fseek(fp, pos, SEEK_SET) != 0) {
|
||||
fprintf(stderr, "Error seeking to pos %x\n", pos);
|
||||
bail(baddisk);
|
||||
}
|
||||
|
||||
if (fxread(&wd, sizeof(wd), 1, fp) != 1) {
|
||||
fprintf(stderr, "Error reading word at abs sec %x, cyl %x, sec %x at offset %x\n", asec, cyl, sec, pos);
|
||||
bail(baddisk);
|
||||
}
|
||||
|
||||
if (wd != asec) {
|
||||
fprintf(stderr, "Bad sector #%x at abs sec %x, cyl %x, sec %x at offset %x\n", wd, asec, cyl, sec, pos);
|
||||
nbad++;
|
||||
|
||||
if (fixit) {
|
||||
if (fseek(fp, pos, SEEK_SET) != 0) {
|
||||
fprintf(stderr, "Error seeking to pos %x\n", pos);
|
||||
bail(baddisk);
|
||||
}
|
||||
|
||||
if (fxwrite(&asec, sizeof(wd), 1, fp) != 1) {
|
||||
fprintf(stderr, "Error writing sector # to abs sec %x, cyl %x, sec %x at offset %x\n", asec, cyl, sec, pos);
|
||||
bail(baddisk);
|
||||
}
|
||||
|
||||
if (retry) {
|
||||
retry = 0;
|
||||
nfixed++;
|
||||
goto again;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Failed after retry\n");
|
||||
bail(baddisk);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nbad)
|
||||
printf("%d bad sector mark%s %s\n", nbad, (nbad == 1) ? "" : "s", fixit ? "fixed" : "found");
|
||||
else if (! dump)
|
||||
printf("All sector marks OK\n");
|
||||
|
||||
if (! dump)
|
||||
return 0;
|
||||
|
||||
pos = dsec*2*DSK_NUMWD;
|
||||
if (fseek(fp, pos, SEEK_SET) != 0) {
|
||||
fprintf(stderr, "Error seeking to pos %x\n", pos);
|
||||
bail(baddisk);
|
||||
}
|
||||
|
||||
for (i = 0; i < nsec; i++) {
|
||||
cyl = dsec / (DSK_NUMSF*DSK_NUMSC);
|
||||
sec = dsec - cyl*(DSK_NUMSF*DSK_NUMSC);
|
||||
|
||||
if (fxread(&buf, sizeof(buf[0]), DSK_NUMWD, fp) != DSK_NUMWD) {
|
||||
fprintf(stderr, "Error reading abs sec %x, cyl %x, sec %x at offset %x\n", dsec, cyl, sec, pos);
|
||||
bail(baddisk);
|
||||
}
|
||||
|
||||
printf("\nSector %d.%d - %d - /%04x label %04x\n", cyl, sec, dsec, dsec, buf[0]);
|
||||
for (nline = 0, j = 1; j < DSK_NUMWD; j++) {
|
||||
printf("%04x", buf[j]);
|
||||
if (++nline == 16) {
|
||||
putchar('\n');
|
||||
nline = 0;
|
||||
}
|
||||
else
|
||||
putchar(' ');
|
||||
}
|
||||
|
||||
dsec++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void bail (char *msg)
|
||||
{
|
||||
fprintf(stderr, "%s\n", msg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
* lowcase - force a string to lower case (ASCII)
|
||||
* ------------------------------------------------------------------------ */
|
||||
|
||||
char *lowcase (char *str)
|
||||
{
|
||||
char *s;
|
||||
|
||||
for (s = str; *s; s++) {
|
||||
if (*s >= 'A' && *s <= 'Z')
|
||||
*s += 32;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
|
||||
long filelength (int fno)
|
||||
{
|
||||
struct stat sb;
|
||||
|
||||
if (fstat(fno, &sb) != 0)
|
||||
return 0;
|
||||
|
||||
return (long) sb.st_size;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,177 +0,0 @@
|
|||
# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
!IF "$(CFG)" == ""
|
||||
CFG=Win32 Debug
|
||||
!MESSAGE No configuration specified. Defaulting to Win32 Debug.
|
||||
!ENDIF
|
||||
|
||||
!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug"
|
||||
!MESSAGE Invalid configuration "$(CFG)" specified.
|
||||
!MESSAGE You can specify a configuration when running NMAKE on this makefile
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "checkdisk.mak" CFG="Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
!ERROR An invalid configuration is specified.
|
||||
!ENDIF
|
||||
|
||||
################################################################################
|
||||
# Begin Project
|
||||
# PROP Target_Last_Scanned "Win32 Release"
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "WinRel"
|
||||
# PROP BASE Intermediate_Dir "WinRel"
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "WinRel"
|
||||
# PROP Intermediate_Dir "WinRel"
|
||||
OUTDIR=.\WinRel
|
||||
INTDIR=.\WinRel
|
||||
|
||||
ALL : $(OUTDIR)/checkdisk.exe $(OUTDIR)/checkdisk.bsc
|
||||
|
||||
$(OUTDIR) :
|
||||
if not exist $(OUTDIR)/nul mkdir $(OUTDIR)
|
||||
|
||||
# ADD BASE CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c
|
||||
# ADD CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c
|
||||
CPP_PROJ=/nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\
|
||||
/FR$(INTDIR)/ /Fp$(OUTDIR)/"checkdisk.pch" /Fo$(INTDIR)/ /c
|
||||
CPP_OBJS=.\WinRel/
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
BSC32_FLAGS=/nologo /o$(OUTDIR)/"checkdisk.bsc"
|
||||
BSC32_SBRS= \
|
||||
$(INTDIR)/checkdisk.sbr \
|
||||
$(INTDIR)/util_io.sbr
|
||||
|
||||
$(OUTDIR)/checkdisk.bsc : $(OUTDIR) $(BSC32_SBRS)
|
||||
$(BSC32) @<<
|
||||
$(BSC32_FLAGS) $(BSC32_SBRS)
|
||||
<<
|
||||
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386
|
||||
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib /NOLOGO\
|
||||
/SUBSYSTEM:console /INCREMENTAL:no /PDB:$(OUTDIR)/"checkdisk.pdb" /MACHINE:I386\
|
||||
/OUT:$(OUTDIR)/"checkdisk.exe"
|
||||
DEF_FILE=
|
||||
LINK32_OBJS= \
|
||||
$(INTDIR)/checkdisk.obj \
|
||||
$(INTDIR)/util_io.obj
|
||||
|
||||
$(OUTDIR)/checkdisk.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS)
|
||||
$(LINK32) @<<
|
||||
$(LINK32_FLAGS) $(LINK32_OBJS)
|
||||
<<
|
||||
|
||||
!ELSEIF "$(CFG)" == "Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "WinDebug"
|
||||
# PROP BASE Intermediate_Dir "WinDebug"
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "WinDebug"
|
||||
# PROP Intermediate_Dir "WinDebug"
|
||||
OUTDIR=.\WinDebug
|
||||
INTDIR=.\WinDebug
|
||||
|
||||
ALL : $(OUTDIR)/checkdisk.exe $(OUTDIR)/checkdisk.bsc
|
||||
|
||||
$(OUTDIR) :
|
||||
if not exist $(OUTDIR)/nul mkdir $(OUTDIR)
|
||||
|
||||
# ADD BASE CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c
|
||||
# ADD CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c
|
||||
CPP_PROJ=/nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\
|
||||
/FR$(INTDIR)/ /Fp$(OUTDIR)/"checkdisk.pch" /Fo$(INTDIR)/\
|
||||
/Fd$(OUTDIR)/"checkdisk.pdb" /c
|
||||
CPP_OBJS=.\WinDebug/
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
BSC32_FLAGS=/nologo /o$(OUTDIR)/"checkdisk.bsc"
|
||||
BSC32_SBRS= \
|
||||
$(INTDIR)/checkdisk.sbr \
|
||||
$(INTDIR)/util_io.sbr
|
||||
|
||||
$(OUTDIR)/checkdisk.bsc : $(OUTDIR) $(BSC32_SBRS)
|
||||
$(BSC32) @<<
|
||||
$(BSC32_FLAGS) $(BSC32_SBRS)
|
||||
<<
|
||||
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386
|
||||
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib /NOLOGO\
|
||||
/SUBSYSTEM:console /INCREMENTAL:yes /PDB:$(OUTDIR)/"checkdisk.pdb" /DEBUG\
|
||||
/MACHINE:I386 /OUT:$(OUTDIR)/"checkdisk.exe"
|
||||
DEF_FILE=
|
||||
LINK32_OBJS= \
|
||||
$(INTDIR)/checkdisk.obj \
|
||||
$(INTDIR)/util_io.obj
|
||||
|
||||
$(OUTDIR)/checkdisk.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS)
|
||||
$(LINK32) @<<
|
||||
$(LINK32_FLAGS) $(LINK32_OBJS)
|
||||
<<
|
||||
|
||||
!ENDIF
|
||||
|
||||
.c{$(CPP_OBJS)}.obj:
|
||||
$(CPP) $(CPP_PROJ) $<
|
||||
|
||||
.cpp{$(CPP_OBJS)}.obj:
|
||||
$(CPP) $(CPP_PROJ) $<
|
||||
|
||||
.cxx{$(CPP_OBJS)}.obj:
|
||||
$(CPP) $(CPP_PROJ) $<
|
||||
|
||||
################################################################################
|
||||
# Begin Group "Source Files"
|
||||
|
||||
################################################################################
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\checkdisk.c
|
||||
DEP_CHECK=\
|
||||
.\util_io.h\
|
||||
\MSVC20\INCLUDE\sys\types.h\
|
||||
\MSVC20\INCLUDE\sys\stat.h
|
||||
|
||||
$(INTDIR)/checkdisk.obj : $(SOURCE) $(DEP_CHECK) $(INTDIR)
|
||||
|
||||
# End Source File
|
||||
################################################################################
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\util_io.c
|
||||
|
||||
$(INTDIR)/util_io.obj : $(SOURCE) $(INTDIR)
|
||||
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Project
|
||||
################################################################################
|
|
@ -1,614 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright 2002, Brian Knittel.
|
||||
* You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN
|
||||
* RISK basis, there is no warranty of fitness for any purpose, and the rest of the
|
||||
* usual yada-yada. Please keep this notice and the copyright in any distributions
|
||||
* or modifications.
|
||||
*
|
||||
* This is not a supported product, but I welcome bug reports and fixes.
|
||||
* Mail to sim@ibm1130.org
|
||||
*/
|
||||
|
||||
// DISKVIEW - lists contents of an 1130 system disk image file. Not finished yet.
|
||||
// needs LET/SLET listing routine.
|
||||
//
|
||||
// usage:
|
||||
// diskview -v diskfile
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include "util_io.h"
|
||||
|
||||
#define BETWEEN(v,a,b) (((v) >= (a)) && ((v) <= (b)))
|
||||
#define MIN(a,b) (((a) <= (b)) ? (a) : (b))
|
||||
#define MAX(a,b) (((a) >= (b)) ? (a) : (b))
|
||||
|
||||
#ifndef TRUE
|
||||
# define TRUE 1
|
||||
# define FALSE 0
|
||||
# define BOOL int
|
||||
#endif
|
||||
|
||||
#define NOT_DEF 0x0658 // defective cylinder table entry means no defect
|
||||
|
||||
#define DSK_NUMWD 321 /* words/sector */
|
||||
#define DSK_NUMCY 203 /* cylinders/drive */
|
||||
#define DSK_SECCYL 8 /* sectors per cylinder */
|
||||
#define SECLEN 320 /* data words per sector */
|
||||
#define SLETLEN ((3*SECLEN)/4) /* length of slet in records */
|
||||
|
||||
typedef unsigned short WORD;
|
||||
|
||||
FILE *fp;
|
||||
WORD buf[DSK_NUMWD];
|
||||
WORD dcom[DSK_NUMWD];
|
||||
|
||||
#pragma pack(2)
|
||||
struct tag_slet {
|
||||
WORD phid;
|
||||
WORD addr;
|
||||
WORD nwords;
|
||||
WORD sector;
|
||||
} slet[SLETLEN];
|
||||
|
||||
#pragma pack()
|
||||
|
||||
WORD dcyl[3];
|
||||
BOOL verbose = FALSE;
|
||||
|
||||
void checksectors (void);
|
||||
void dump_id (void);
|
||||
void dump_dcom (void);
|
||||
void dump_resmon (void);
|
||||
void dump_slet (void);
|
||||
void dump_hdng (void);
|
||||
void dump_scra (void);
|
||||
void dump_let (void);
|
||||
void dump_flet (void);
|
||||
void dump_cib (void);
|
||||
void getsector (int sec, WORD *sbuf);
|
||||
void getdcyl (void);
|
||||
char *lowcase (char *str);
|
||||
|
||||
void bail(char *fmt, ...);
|
||||
char *trim (char *s);
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
char *fname = NULL, *arg;
|
||||
static char usestr[] = "Usage: diskview [-v] filename";
|
||||
int i;
|
||||
|
||||
util_io_init();
|
||||
|
||||
for (i = 1; i < argc;) {
|
||||
arg = argv[i++];
|
||||
if (*arg == '-') {
|
||||
arg++;
|
||||
lowcase(arg);
|
||||
while (*arg) {
|
||||
switch (*arg++) {
|
||||
case 'v':
|
||||
verbose = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
bail(usestr);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (fname == NULL)
|
||||
fname = arg;
|
||||
else
|
||||
bail(usestr);
|
||||
}
|
||||
|
||||
if (fname == NULL)
|
||||
bail(usestr);
|
||||
|
||||
if ((fp = fopen(fname, "rb")) == NULL) {
|
||||
perror(fname);
|
||||
return 2;
|
||||
}
|
||||
|
||||
printf("%s:\n", fname);
|
||||
|
||||
checksectors();
|
||||
getdcyl();
|
||||
|
||||
dump_id(); // ID & coldstart
|
||||
dump_dcom(); // DCOM
|
||||
dump_resmon(); // resident image
|
||||
dump_slet(); // SLET
|
||||
dump_hdng(); // heading sector
|
||||
dump_scra();
|
||||
dump_flet();
|
||||
dump_cib();
|
||||
dump_let();
|
||||
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// checksectors - verify that all sectors are properly numbered
|
||||
|
||||
void checksectors ()
|
||||
{
|
||||
WORD sec = 0;
|
||||
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
|
||||
for (sec = 0; sec < DSK_NUMCY*DSK_SECCYL; sec++) {
|
||||
if (fxread(buf, sizeof(WORD), DSK_NUMWD, fp) != DSK_NUMWD)
|
||||
bail("File read error or not a disk image file");
|
||||
|
||||
if (buf[0] != sec)
|
||||
bail("Sector /%x is misnumbered, run checkdisk [-f]", sec);
|
||||
}
|
||||
}
|
||||
|
||||
// get defective cylinder list
|
||||
|
||||
void getdcyl (void)
|
||||
{
|
||||
fseek(fp, sizeof(WORD), SEEK_SET); // skip sector count
|
||||
if (fxread(dcyl, sizeof(WORD), 3, fp) != 3)
|
||||
bail("Unable to read defective cylinder table");
|
||||
}
|
||||
|
||||
// getsector - read specified absolute sector
|
||||
|
||||
void getsector (int sec, WORD *sbuf)
|
||||
{
|
||||
int i, cyl, ssec;
|
||||
|
||||
sec &= 0x7FF; // mask of drive bits, if any
|
||||
|
||||
cyl = sec / DSK_SECCYL; // get cylinder
|
||||
ssec = sec & ~(DSK_SECCYL-1); // mask to get starting sector of cylinder
|
||||
for (i = 0; i < 3; i++) { // map through defective cylinder table
|
||||
if (dcyl[i] == ssec) {
|
||||
sec &= (DSK_SECCYL-1); // mask to get base sector
|
||||
cyl = DSK_NUMCY-3+i; // replacements are last three on disk
|
||||
sec += cyl*DSK_SECCYL; // add new cylinder offset
|
||||
break;
|
||||
}
|
||||
}
|
||||
// read the sector
|
||||
if (fseek(fp, (sec*DSK_NUMWD+1)*sizeof(WORD), SEEK_SET) != 0)
|
||||
bail("File seek failed");
|
||||
|
||||
if (fxread(sbuf, sizeof(WORD), DSK_NUMWD, fp) != DSK_NUMWD)
|
||||
bail("File read error or not a disk image file");
|
||||
}
|
||||
|
||||
void dump (int nwords)
|
||||
{
|
||||
int i, nline = 0;
|
||||
|
||||
for (i = 0; i < nwords; i++) {
|
||||
if (nline == 16) {
|
||||
putchar('\n');
|
||||
nline = 0;
|
||||
}
|
||||
|
||||
printf("%04x", buf[i]);
|
||||
nline++;
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
void showmajor (char *label)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("\n--- %s ", label);
|
||||
|
||||
for (i = strlen(label); i < 40; i++)
|
||||
putchar('-');
|
||||
|
||||
putchar('\n');
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
void name (char *label)
|
||||
{
|
||||
printf("%-32.32s ", label);
|
||||
}
|
||||
|
||||
void pbf (char *label, WORD *buf, int nwords)
|
||||
{
|
||||
int i, nout;
|
||||
|
||||
name(label);
|
||||
|
||||
for (i = nout = 0; i < nwords; i++, nout++) {
|
||||
if (nout == 8) {
|
||||
putchar('\n');
|
||||
name("");
|
||||
nout = 0;
|
||||
}
|
||||
printf(" %04x", buf[i]);
|
||||
}
|
||||
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
void prt (char *label, char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
name(label);
|
||||
|
||||
putchar(' ');
|
||||
va_start(args, fmt);
|
||||
vprintf(fmt, args);
|
||||
va_end(args);
|
||||
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
void dump_id (void)
|
||||
{
|
||||
showmajor("Sector 0 - ID & coldstart");
|
||||
getsector(0, buf);
|
||||
|
||||
pbf("DCYL def cyl table", buf+ 0, 3);
|
||||
pbf("CIDN cart id", buf+ 3, 1);
|
||||
pbf(" copy code", buf+ 4, 1);
|
||||
pbf("DTYP disk type", buf+ 7, 1);
|
||||
pbf(" diskz copy", buf+ 30, 8);
|
||||
pbf(" cold start pgm",buf+270, 8);
|
||||
}
|
||||
|
||||
// EQUIVALENCES FOR DCOM PARAMETERS
|
||||
#define NAME 4 // NAME OF PROGRAM/CORE LOAD
|
||||
#define DBCT 6 // BLOCK CT OF PROGRAM/CORE LOAD
|
||||
#define FCNT 7 // FILES SWITCH
|
||||
#define SYSC 8 // SYSTEM/NON-SYSTEM CARTRIDGE INDR
|
||||
#define JBSW 9 // JOBT SWITCH
|
||||
#define CBSW 10 // CLB-RETURN SWITCH
|
||||
#define LCNT 11 // NO. OF LOCALS
|
||||
#define MPSW 12 // CORE MAP SWITCH
|
||||
#define MDF1 13 // NO. DUP CTRL RECORDS (MODIF)
|
||||
#define MDF2 14 // ADDR OF MODIF BUFFER
|
||||
#define NCNT 15 // NO. OF NOCALS
|
||||
#define ENTY 16 // RLTV ENTRY ADDR OF PROGRAM
|
||||
#define RP67 17 // 1442-5 SWITCH
|
||||
#define TODR 18 // OBJECT WORK STORAGE DRIVE CODE
|
||||
#define FHOL 20 // ADDR LARGEST HOLE IN FIXED AREA
|
||||
#define FSZE 21 // BLK CNT LARGEST HOLE IN FXA
|
||||
#define UHOL 22 // ADDR LAST HOLE IN USER AREA 2-10
|
||||
#define USZE 23 // BLK CNT LAST HOLE IN UA 2-10
|
||||
#define DCSW 24 // DUP CALL SWITCH
|
||||
#define PIOD 25 // PRINCIPAL I/O DEVICE INDICATOR
|
||||
#define PPTR 26 // PRINCIPAL PRINT DEVICE INDICATOR
|
||||
#define CIAD 27 // RLTV ADDR IN @STRT OF CIL ADDR
|
||||
#define ACIN 28 // AVAILABLE CARTRIDGE INDICATOR
|
||||
#define GRPH 29 // 2250 INDICATOR 2G2
|
||||
#define GCNT 30 // NO. G2250 RECORDS 2G2
|
||||
#define LOSW 31 // LOCAL-CALLS-LOCAL SWITCH 2-2
|
||||
#define X3SW 32 // SPECIAL ILS SWITCH 2-2
|
||||
#define ECNT 33 // NO. OF *EQUAT RCDS 2-4
|
||||
#define ANDU 35 // 1+BLK ADDR END OF UA (ADJUSTED)
|
||||
#define BNDU 40 // 1+BLK ADDR END OF UA (BASE)
|
||||
#define FPAD 45 // FILE PROTECT ADDR
|
||||
#define PCID 50 // CARTRIDGE ID, PHYSICAL DRIVE
|
||||
#define CIDN 55 // CARTRIDGE ID, LOGICAL DRIVE
|
||||
#define CIBA 60 // SCTR ADDR OF CIB
|
||||
#define SCRA 65 // SCTR ADDR OF SCRA
|
||||
#define FMAT 70 // FORMAT OF PROG IN WORKING STG
|
||||
#define FLET 75 // SCTR ADDR 1ST SCTR OF FLET
|
||||
#define ULET 80 // SCTR ADDR 1ST SCTR OF LET
|
||||
#define WSCT 85 // BLK CNT OF PROG IN WORKING STG
|
||||
#define CSHN 90 // NO. SCTRS IN CUSHION AREA
|
||||
|
||||
struct tag_dcominfo {
|
||||
char *nm;
|
||||
int offset;
|
||||
char *descr;
|
||||
} dcominfo[] = {
|
||||
"NAME", 4, "NAME OF PROGRAM/CORE LOAD",
|
||||
"DBCT", 6, "BLOCK CT OF PROGRAM/CORE LOAD",
|
||||
"FCNT", 7, "FILES SWITCH",
|
||||
"SYSC", 8, "SYSTEM/NON-SYSTEM CARTRIDGE INDR",
|
||||
"JBSW", 9, "JOBT SWITCH",
|
||||
"CBSW", 10, "CLB-RETURN SWITCH",
|
||||
"LCNT", 11, "NO. OF LOCALS",
|
||||
"MPSW", 12, "CORE MAP SWITCH",
|
||||
"MDF1", 13, "NO. DUP CTRL RECORDS (MODIF)",
|
||||
"MDF2", 14, "ADDR OF MODIF BUFFER",
|
||||
"NCNT", 15, "NO. OF NOCALS",
|
||||
"ENTY", 16, "RLTV ENTRY ADDR OF PROGRAM",
|
||||
"RP67", 17, "1442-5 SWITCH",
|
||||
"TODR", 18, "OBJECT WORK STORAGE DRIVE CODE",
|
||||
"FHOL", 20, "ADDR LARGEST HOLE IN FIXED AREA",
|
||||
"FSZE", 21, "BLK CNT LARGEST HOLE IN FXA",
|
||||
"UHOL", 22, "ADDR LAST HOLE IN USER AREA",
|
||||
"USZE", 23, "BLK CNT LAST HOLE IN UA",
|
||||
"DCSW", 24, "DUP CALL SWITCH",
|
||||
"PIOD", 25, "PRINCIPAL I/O DEVICE INDICATOR",
|
||||
"PPTR", 26, "PRINCIPAL PRINT DEVICE INDICATOR",
|
||||
"CIAD", 27, "RLTV ADDR IN @STRT OF CIL ADDR",
|
||||
"ACIN", 28, "AVAILABLE CARTRIDGE INDICATOR",
|
||||
"GRPH", 29, "2250 INDICATOR",
|
||||
"GCNT", 30, "NO. G2250 RECORDS",
|
||||
"LOSW", 31, "LOCAL-CALLS-LOCAL SWITCH",
|
||||
"X3SW", 32, "SPECIAL ILS SWITCH",
|
||||
"ECNT", 33, "NO. OF *EQUAT RCDS",
|
||||
"ANDU", 35, "1+BLK ADDR END OF UA (ADJUSTED)",
|
||||
"BNDU", 40, "1+BLK ADDR END OF UA (BASE)",
|
||||
"FPAD", 45, "FILE PROTECT ADDR",
|
||||
"PCID", 50, "CARTRIDGE ID, PHYSICAL DRIVE",
|
||||
"CIDN", 55, "CARTRIDGE ID, LOGICAL DRIVE",
|
||||
"CIBA", 60, "SCTR ADDR OF CIB",
|
||||
"SCRA", 65, "SCTR ADDR OF SCRA",
|
||||
"FMAT", 70, "FORMAT OF PROG IN WORKING STG",
|
||||
"FLET", 75, "SCTR ADDR 1ST SCTR OF FLET",
|
||||
"ULET", 80, "SCTR ADDR 1ST SCTR OF LET",
|
||||
"WSCT", 85, "BLK CNT OF PROG IN WORKING STG",
|
||||
"CSHN", 90, "NO. SCTRS IN CUSHION AREA",
|
||||
NULL
|
||||
};
|
||||
|
||||
void dump_dcom (void)
|
||||
{
|
||||
struct tag_dcominfo *d;
|
||||
char txt[50];
|
||||
|
||||
showmajor("Sector 1 - DCOM");
|
||||
getsector(1, dcom);
|
||||
|
||||
for (d = dcominfo; d->nm != NULL; d++) {
|
||||
sprintf(txt, "%-4.4s %s", d->nm, d->descr);
|
||||
pbf(txt, dcom+d->offset, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void dump_resmon (void)
|
||||
{
|
||||
showmajor("Sector 2 - Resident Image");
|
||||
getsector(2, buf);
|
||||
dump(verbose ? SECLEN : 32);
|
||||
}
|
||||
|
||||
struct {
|
||||
int pfrom, pto;
|
||||
int printed;
|
||||
char *name;
|
||||
} sletinfo[] = {
|
||||
0x01, 0x12, FALSE, "DUP",
|
||||
0x1F, 0x39, FALSE, "Fortran",
|
||||
0x51, 0x5C, FALSE, "Cobol",
|
||||
0x6E, 0x74, FALSE, "Supervisor",
|
||||
0x78, 0x84, FALSE, "Core Load Builder",
|
||||
0x8C, 0x8C, FALSE, "Sys 1403 prt",
|
||||
0x8D, 0x8D, FALSE, "Sys 1132 prt",
|
||||
0x8E, 0x8E, FALSE, "Sys console prt",
|
||||
0x8F, 0x8F, FALSE, "Sys 2501 rdr",
|
||||
0x90, 0x90, FALSE, "Sys 1442 rdr/pun",
|
||||
0x91, 0x91, FALSE, "Sys 1134 paper tape",
|
||||
0x92, 0x92, FALSE, "Sys kbd",
|
||||
0x93, 0x93, FALSE, "Sys 2501/1442 conv",
|
||||
0x94, 0x94, FALSE, "Sys 1134 conv",
|
||||
0x95, 0x95, FALSE, "Sys kbd conv",
|
||||
0x96, 0x96, FALSE, "Sys diskz",
|
||||
0x97, 0x97, FALSE, "Sys disk1",
|
||||
0x98, 0x98, FALSE, "Sys diskn",
|
||||
0x99, 0x99, FALSE, "(primary print)",
|
||||
0x9A, 0x9A, FALSE, "(primary input)",
|
||||
0x9B, 0x9B, FALSE, "(primary input excl kbd)",
|
||||
0x9C, 0x9C, FALSE, "(primary sys conv)",
|
||||
0x9D, 0x9D, FALSE, "(primary conv excl kbd)",
|
||||
0xA0, 0xA1, FALSE, "Core Image Loader",
|
||||
0xB0, 0xCC, FALSE, "RPG",
|
||||
0xCD, 0xCE, FALSE, "Dup Part 2",
|
||||
0xCF, 0xF6, FALSE, "Macro Assembler",
|
||||
0
|
||||
};
|
||||
|
||||
void dump_slet (void)
|
||||
{
|
||||
int i, j, iphase, nsecs, sec, max_sec = 0;
|
||||
char sstr[16], *smark;
|
||||
|
||||
showmajor("Sectors 3-5 - SLET");
|
||||
for (i = 0; i < 3; i++) {
|
||||
getsector(3+i, buf);
|
||||
memmove(((WORD *) slet)+SECLEN*i, buf, SECLEN*sizeof(WORD));
|
||||
}
|
||||
|
||||
printf("# PHID Addr Len Sector Secs\n");
|
||||
printf("------------------------------------------\n");
|
||||
for (i = 0; i < SLETLEN; i++) {
|
||||
if (slet[i].phid == 0)
|
||||
break;
|
||||
|
||||
sec = slet[i].sector;
|
||||
iphase = (int) (signed short) slet[i].phid;
|
||||
nsecs = (slet[i].nwords + SECLEN-1)/SECLEN;
|
||||
|
||||
if (sec & 0xF800) {
|
||||
smark = "*";
|
||||
sec &= 0x7FF;
|
||||
}
|
||||
else
|
||||
smark = " ";
|
||||
|
||||
for (j = 0; sletinfo[j].pfrom != 0; j++)
|
||||
if (sletinfo[j].pfrom <= iphase && sletinfo[j].pto >= iphase)
|
||||
break;
|
||||
|
||||
sprintf(sstr, "(%d.%d)", sec / DSK_SECCYL, slet[i].sector % DSK_SECCYL);
|
||||
|
||||
printf("%3d %04x %4d %04x %04x %04x %s %-7s %3x",
|
||||
i, slet[i].phid, iphase, slet[i].addr, slet[i].nwords, slet[i].sector, smark, sstr, nsecs);
|
||||
|
||||
if (iphase < 0)
|
||||
iphase = -iphase;
|
||||
|
||||
if (sletinfo[j].pfrom == 0)
|
||||
printf(" ???");
|
||||
else if (! sletinfo[j].printed) {
|
||||
printf(" %s", sletinfo[j].name);
|
||||
sletinfo[j].printed = TRUE;
|
||||
}
|
||||
|
||||
for (j = 0; j < i; j++) {
|
||||
if (sec == (slet[j].sector & 0x7FF)) {
|
||||
printf(" (same as %04x)", slet[j].phid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
max_sec = MAX(max_sec, sec+nsecs-1); // find last sector used
|
||||
|
||||
putchar('\n');
|
||||
|
||||
if (i >= 15 && ! verbose) {
|
||||
printf("...\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ascii_to_ebcdic_table[128] =
|
||||
{
|
||||
0x00,0x01,0x02,0x03,0x37,0x2d,0x2e,0x2f, 0x16,0x05,0x25,0x0b,0x0c,0x0d,0x0e,0x0f,
|
||||
0x10,0x11,0x12,0x13,0x3c,0x3d,0x32,0x26, 0x18,0x19,0x3f,0x27,0x1c,0x1d,0x1e,0x1f,
|
||||
0x40,0x5a,0x7f,0x7b,0x5b,0x6c,0x50,0x7d, 0x4d,0x5d,0x5c,0x4e,0x6b,0x60,0x4b,0x61,
|
||||
0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0x7a,0x5e,0x4c,0x7e,0x6e,0x6f,
|
||||
|
||||
0x7c,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, 0xc8,0xc9,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,
|
||||
0xd7,0xd8,0xd9,0xe2,0xe3,0xe4,0xe5,0xe6, 0xe7,0xe8,0xe9,0xba,0xe0,0xbb,0xb0,0x6d,
|
||||
0x79,0x81,0x82,0x83,0x84,0x85,0x86,0x87, 0x88,0x89,0x91,0x92,0x93,0x94,0x95,0x96,
|
||||
0x97,0x98,0x99,0xa2,0xa3,0xa4,0xa5,0xa6, 0xa7,0xa8,0xa9,0xc0,0x4f,0xd0,0xa1,0x07,
|
||||
};
|
||||
|
||||
int ebcdic_to_ascii (int ch)
|
||||
{
|
||||
int j;
|
||||
|
||||
for (j = 32; j < 128; j++)
|
||||
if (ascii_to_ebcdic_table[j] == ch)
|
||||
return j;
|
||||
|
||||
return '?';
|
||||
}
|
||||
|
||||
#define HDR_LEN 120
|
||||
|
||||
void dump_hdng(void)
|
||||
{
|
||||
int i;
|
||||
char str[HDR_LEN+1], *p = str;
|
||||
|
||||
showmajor("Sector 7 - Heading");
|
||||
getsector(7, buf);
|
||||
|
||||
for (i = 0; i < (HDR_LEN/2); i++) {
|
||||
*p++ = ebcdic_to_ascii((buf[i] >> 8) & 0xFF);
|
||||
*p++ = ebcdic_to_ascii( buf[i] & 0xFF);
|
||||
}
|
||||
|
||||
*p = '\0';
|
||||
trim(str);
|
||||
printf("%s\n", str);
|
||||
}
|
||||
|
||||
BOOL mget (int offset, char *name)
|
||||
{
|
||||
char title[80];
|
||||
|
||||
if (dcom[offset] == 0)
|
||||
return FALSE;
|
||||
|
||||
getsector(dcom[offset], buf);
|
||||
sprintf(title, "Sector %x - %s", dcom[offset], name);
|
||||
showmajor(title);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void dump_scra (void)
|
||||
{
|
||||
if (! mget(SCRA, "SCRA"))
|
||||
return;
|
||||
|
||||
dump(verbose ? SECLEN : 32);
|
||||
}
|
||||
|
||||
void dump_let (void)
|
||||
{
|
||||
if (! mget(ULET, "LET"))
|
||||
return;
|
||||
}
|
||||
|
||||
void dump_flet (void)
|
||||
{
|
||||
if (! mget(FLET, "FLET"))
|
||||
return;
|
||||
}
|
||||
|
||||
void dump_cib (void)
|
||||
{
|
||||
if (! mget(CIBA, "CIB"))
|
||||
return;
|
||||
|
||||
dump(verbose ? SECLEN : 32);
|
||||
}
|
||||
|
||||
#define LFHD 5 // WORD COUNT OF LET/FLET HEADER PMN09970
|
||||
#define LFEN 3 // NO OF WDS PER LET/FLET ENTRY PMN09980
|
||||
#define SCTN 0 // RLTY ADDR OF LET/FLET SCTR NO. PMN09990
|
||||
#define UAFX 1 // RLTV ADDR OF SCTR ADDR OF UA/FXA PMN10000
|
||||
#define WDSA 3 // RLTV ADDR OF WDS AVAIL IN SCTR PMN10010
|
||||
#define NEXT 4 // RLTV ADDR OF ADDR NEXT SCTR PMN10020
|
||||
#define LFNM 0 // RLTV ADDR OF LET/FLET ENTRY NAME PMN10030
|
||||
#define BLCT 2 // RLTV ADDR OF LET/FLET ENTRY DBCT PMN10040
|
||||
|
||||
void bail (char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
fprintf(stderr, fmt, args);
|
||||
va_end(args);
|
||||
putchar('\n');
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
// trim - remove trailing whitespace from string s
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
||||
char *trim (char *s)
|
||||
{
|
||||
char *os = s, *nb;
|
||||
|
||||
for (nb = s-1; *s; s++)
|
||||
if (*s > ' ')
|
||||
nb = s;
|
||||
|
||||
nb[1] = '\0';
|
||||
return os;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
* lowcase - force a string to lowercase (ASCII)
|
||||
* ------------------------------------------------------------------------ */
|
||||
|
||||
char *lowcase (char *str)
|
||||
{
|
||||
char *s;
|
||||
|
||||
for (s = str; *s; s++) {
|
||||
if (*s >= 'A' && *s <= 'Z')
|
||||
*s += 32;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
|
@ -1,175 +0,0 @@
|
|||
# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
!IF "$(CFG)" == ""
|
||||
CFG=Win32 Debug
|
||||
!MESSAGE No configuration specified. Defaulting to Win32 Debug.
|
||||
!ENDIF
|
||||
|
||||
!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug"
|
||||
!MESSAGE Invalid configuration "$(CFG)" specified.
|
||||
!MESSAGE You can specify a configuration when running NMAKE on this makefile
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "diskview.mak" CFG="Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
!ERROR An invalid configuration is specified.
|
||||
!ENDIF
|
||||
|
||||
################################################################################
|
||||
# Begin Project
|
||||
# PROP Target_Last_Scanned "Win32 Debug"
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "WinRel"
|
||||
# PROP BASE Intermediate_Dir "WinRel"
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "WinRel"
|
||||
# PROP Intermediate_Dir "WinRel"
|
||||
OUTDIR=.\WinRel
|
||||
INTDIR=.\WinRel
|
||||
|
||||
ALL : $(OUTDIR)/diskview.exe $(OUTDIR)/diskview.bsc
|
||||
|
||||
$(OUTDIR) :
|
||||
if not exist $(OUTDIR)/nul mkdir $(OUTDIR)
|
||||
|
||||
# ADD BASE CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c
|
||||
# ADD CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c
|
||||
CPP_PROJ=/nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\
|
||||
/FR$(INTDIR)/ /Fp$(OUTDIR)/"diskview.pch" /Fo$(INTDIR)/ /c
|
||||
CPP_OBJS=.\WinRel/
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
BSC32_FLAGS=/nologo /o$(OUTDIR)/"diskview.bsc"
|
||||
BSC32_SBRS= \
|
||||
$(INTDIR)/diskview.sbr \
|
||||
$(INTDIR)/util_io.sbr
|
||||
|
||||
$(OUTDIR)/diskview.bsc : $(OUTDIR) $(BSC32_SBRS)
|
||||
$(BSC32) @<<
|
||||
$(BSC32_FLAGS) $(BSC32_SBRS)
|
||||
<<
|
||||
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386
|
||||
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console\
|
||||
/INCREMENTAL:no /PDB:$(OUTDIR)/"diskview.pdb" /MACHINE:I386\
|
||||
/OUT:$(OUTDIR)/"diskview.exe"
|
||||
DEF_FILE=
|
||||
LINK32_OBJS= \
|
||||
$(INTDIR)/diskview.obj \
|
||||
$(INTDIR)/util_io.obj
|
||||
|
||||
$(OUTDIR)/diskview.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS)
|
||||
$(LINK32) @<<
|
||||
$(LINK32_FLAGS) $(LINK32_OBJS)
|
||||
<<
|
||||
|
||||
!ELSEIF "$(CFG)" == "Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "WinDebug"
|
||||
# PROP BASE Intermediate_Dir "WinDebug"
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "WinDebug"
|
||||
# PROP Intermediate_Dir "WinDebug"
|
||||
OUTDIR=.\WinDebug
|
||||
INTDIR=.\WinDebug
|
||||
|
||||
ALL : $(OUTDIR)/diskview.exe $(OUTDIR)/diskview.bsc
|
||||
|
||||
$(OUTDIR) :
|
||||
if not exist $(OUTDIR)/nul mkdir $(OUTDIR)
|
||||
|
||||
# ADD BASE CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c
|
||||
# ADD CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c
|
||||
CPP_PROJ=/nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\
|
||||
/FR$(INTDIR)/ /Fp$(OUTDIR)/"diskview.pch" /Fo$(INTDIR)/\
|
||||
/Fd$(OUTDIR)/"diskview.pdb" /c
|
||||
CPP_OBJS=.\WinDebug/
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
BSC32_FLAGS=/nologo /o$(OUTDIR)/"diskview.bsc"
|
||||
BSC32_SBRS= \
|
||||
$(INTDIR)/diskview.sbr \
|
||||
$(INTDIR)/util_io.sbr
|
||||
|
||||
$(OUTDIR)/diskview.bsc : $(OUTDIR) $(BSC32_SBRS)
|
||||
$(BSC32) @<<
|
||||
$(BSC32_FLAGS) $(BSC32_SBRS)
|
||||
<<
|
||||
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386
|
||||
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console\
|
||||
/INCREMENTAL:yes /PDB:$(OUTDIR)/"diskview.pdb" /DEBUG /MACHINE:I386\
|
||||
/OUT:$(OUTDIR)/"diskview.exe"
|
||||
DEF_FILE=
|
||||
LINK32_OBJS= \
|
||||
$(INTDIR)/diskview.obj \
|
||||
$(INTDIR)/util_io.obj
|
||||
|
||||
$(OUTDIR)/diskview.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS)
|
||||
$(LINK32) @<<
|
||||
$(LINK32_FLAGS) $(LINK32_OBJS)
|
||||
<<
|
||||
|
||||
!ENDIF
|
||||
|
||||
.c{$(CPP_OBJS)}.obj:
|
||||
$(CPP) $(CPP_PROJ) $<
|
||||
|
||||
.cpp{$(CPP_OBJS)}.obj:
|
||||
$(CPP) $(CPP_PROJ) $<
|
||||
|
||||
.cxx{$(CPP_OBJS)}.obj:
|
||||
$(CPP) $(CPP_PROJ) $<
|
||||
|
||||
################################################################################
|
||||
# Begin Group "Source Files"
|
||||
|
||||
################################################################################
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\diskview.c
|
||||
|
||||
$(INTDIR)/diskview.obj : $(SOURCE) $(INTDIR)
|
||||
|
||||
# End Source File
|
||||
################################################################################
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\util_io.c
|
||||
DEP_UTIL_=\
|
||||
.\util_io.h
|
||||
|
||||
$(INTDIR)/util_io.obj : $(SOURCE) $(DEP_UTIL_) $(INTDIR)
|
||||
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Project
|
||||
################################################################################
|
|
@ -1,705 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright 2002, Brian Knittel.
|
||||
* You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN
|
||||
* RISK basis, there is no warranty of fitness for any purpose, and the rest of the
|
||||
* usual yada-yada. Please keep this notice and the copyright in any distributions
|
||||
* or modifications.
|
||||
*
|
||||
* This is not a supported product, but I welcome bug reports and fixes.
|
||||
* Mail to sim@ibm1130.org
|
||||
*/
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
// MKBOOT - reads card loader format cards and produces an absolute core image that
|
||||
// can then be dumped out in 1130 IPL, 1800 IPL or Core Image loader formats.
|
||||
//
|
||||
// Usage: mkboot [-v] binfile outfile [1130|1800|core [loaddr [hiaddr [ident]]]]"
|
||||
//
|
||||
// Arguments:
|
||||
// binfile - name of assembler output file (card loader format, absolute output)
|
||||
// outfile - name of output file to create
|
||||
// mode - output mode, default is 1130 IPL format
|
||||
// loaddr - low address to dump. Default is lowest address loaded from binfile
|
||||
// hiaddr - high address to dump. Defult is highest address loaded from binfile
|
||||
// ident - ident string to write in last 8 columns. Omit when when writing an
|
||||
// 1130 IPL card that requires all 80 columns of data.
|
||||
//
|
||||
// Examples:
|
||||
// mkboot somefile.bin somefile.ipl 1130
|
||||
//
|
||||
// loads somefile.bin, writes object in 1130 IPL format to somefile.ipl
|
||||
// Up to 80 columns will be written depending on what the object actually uses
|
||||
//
|
||||
// mkboot somefile.bin somefile.ipl 1130 0 48 SOMEF
|
||||
//
|
||||
// loads somefile.bin. Writes 72 columns (hex 48), with ident columns 73-80 = SOMEF001
|
||||
//
|
||||
// mkboot somefile.bin somefile.dat core 0 0 SOMEF001
|
||||
//
|
||||
// loads somefile.bin and writes a core image format deck with ident SOMEF001, SOMEF002, etc
|
||||
//
|
||||
// For other examples of usage, see MKDMS.BAT
|
||||
//
|
||||
// 1.00 - 2002Apr18 - first release. Tested only under Win32. The core image
|
||||
// loader format is almost certainly wrong. Cannot handle
|
||||
// relocatable input decks, but it works well enough to
|
||||
// load DSYSLDR1 which is what we are after here.
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifndef TRUE
|
||||
#define BOOL int
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#ifndef WIN32
|
||||
int strnicmp (char *a, char *b, int n);
|
||||
int strcmpi (char *a, char *b);
|
||||
#endif
|
||||
|
||||
#define BETWEEN(v,a,b) (((v) >= (a)) && ((v) <= (b)))
|
||||
#define MIN(a,b) (((a) <= (b)) ? (a) : (b))
|
||||
#define MAX(a,b) (((a) >= (b)) ? (a) : (b))
|
||||
|
||||
#define MAXADDR 4096
|
||||
|
||||
typedef enum {R_ABSOLUTE = 0, R_RELATIVE = 1, R_LIBF = 2, R_CALL = 3} RELOC;
|
||||
|
||||
typedef enum {B_1130, B_1800, B_CORE} BOOTMODE;
|
||||
|
||||
BOOL verbose = FALSE;
|
||||
char *infile = NULL, *outfile = NULL;
|
||||
BOOTMODE mode = B_1130;
|
||||
int addr_from = 0, addr_to = 79;
|
||||
int outcols = 0; // columns written in using card output
|
||||
int maxiplcols = 80;
|
||||
char cardid[9]; // characters used for IPL card ID
|
||||
int pta = 0;
|
||||
int load_low = 0x7FFFFFF;
|
||||
int load_high = 0;
|
||||
unsigned short mem[MAXADDR]; // small core!
|
||||
|
||||
// mkboot - load a binary object deck into core and dump requested bytes as a boot card
|
||||
|
||||
void bail (char *msg);
|
||||
void verify_checksum(unsigned short *card);
|
||||
char *upcase (char *str);
|
||||
void unpack (unsigned short *card, unsigned short *buf);
|
||||
void dump (char *fname);
|
||||
void loaddata (char *fname);
|
||||
void write_1130 (void);
|
||||
void write_1800 (void);
|
||||
void write_core (void);
|
||||
void flushcard(void);
|
||||
int ascii_to_hollerith (int ch);
|
||||
void corecard_init (void);
|
||||
void corecard_writecard (char *sbrk_text);
|
||||
void corecard_writedata (void);
|
||||
void corecard_flush (void);
|
||||
void corecard_setorg (int neworg);
|
||||
void corecard_writew (int word, RELOC relative);
|
||||
void corecard_endcard (void);
|
||||
|
||||
char *fname = NULL;
|
||||
FILE *fout;
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
char *arg;
|
||||
static char usestr[] = "Usage: mkboot [-v] binfile outfile [1130|1800|core [loaddr [hiaddr [ident]]]]";
|
||||
int i, ano = 0, ok;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
arg = argv[i];
|
||||
if (*arg == '-') {
|
||||
arg++;
|
||||
while (*arg) {
|
||||
switch (*arg++) {
|
||||
case 'v':
|
||||
verbose = TRUE;
|
||||
break;
|
||||
default:
|
||||
bail(usestr);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (ano++) {
|
||||
case 0:
|
||||
infile = arg;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
outfile = arg;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (strcmp(arg, "1130") == 0) mode = B_1130;
|
||||
else if (strcmp(arg, "1800") == 0) mode = B_1800;
|
||||
else if (strcmpi(arg, "core") == 0) mode = B_CORE;
|
||||
else bail(usestr);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (strnicmp(arg, "0x", 2) == 0) ok = sscanf(arg+2, "%x", &addr_from);
|
||||
else if (arg[0] == '/') ok = sscanf(arg+1, "%x", &addr_from);
|
||||
else ok = sscanf(arg, "%d", &addr_from);
|
||||
if (ok != 1) bail(usestr);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
if (strnicmp(arg, "0x", 2) == 0) ok = sscanf(arg+2, "%x", &addr_to);
|
||||
else if (arg[0] == '/') ok = sscanf(arg+1, "%x", &addr_to);
|
||||
else ok = sscanf(arg, "%d", &addr_to);
|
||||
if (ok != 1) bail(usestr);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
strncpy(cardid, arg, 9);
|
||||
cardid[8] = '\0';
|
||||
upcase(cardid);
|
||||
break;
|
||||
|
||||
default:
|
||||
bail(usestr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (*cardid == '\0')
|
||||
maxiplcols = (mode == B_1130) ? 80 : 72;
|
||||
else {
|
||||
while (strlen(cardid) < 8)
|
||||
strcat(cardid, "0");
|
||||
maxiplcols = 72;
|
||||
}
|
||||
|
||||
loaddata(infile);
|
||||
|
||||
if (mode == B_1800)
|
||||
write_1800();
|
||||
else if (mode == B_CORE)
|
||||
write_core();
|
||||
else
|
||||
write_1130();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void write_1130 (void)
|
||||
{
|
||||
int addr;
|
||||
unsigned short word;
|
||||
|
||||
if ((fout = fopen(outfile, "wb")) == NULL) {
|
||||
perror(outfile);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (addr = addr_from; addr <= addr_to; addr++) {
|
||||
if (outcols >= maxiplcols)
|
||||
flushcard();
|
||||
|
||||
word = mem[addr];
|
||||
|
||||
// if F or L bits are set, or if high 2 bits of displacement are unequal, it's bad
|
||||
if ((word & 0x0700) || ! (((word & 0x00C0) == 0) || ((word & 0x00C0) == 0x00C0)))
|
||||
printf("Warning: word %04x @ %04x may not IPL properly\n", word & 0xFFFF, addr);
|
||||
|
||||
word = ((word & 0xF800) >> 4) | (word & 0x7F); // convert to 1130 IPL format
|
||||
|
||||
putc((word & 0x000F) << 4, fout); // write the 12 bits in little-endian binary AABBCC00 as CC00 AABB
|
||||
putc((word & 0x0FF0) >> 4, fout);
|
||||
outcols++;
|
||||
}
|
||||
flushcard();
|
||||
fclose(fout);
|
||||
}
|
||||
|
||||
void write_1800 (void)
|
||||
{
|
||||
int addr;
|
||||
unsigned short word;
|
||||
|
||||
if ((fout = fopen(outfile, "wb")) == NULL) {
|
||||
perror(outfile);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (addr = addr_from; addr <= addr_to; addr++) {
|
||||
word = mem[addr];
|
||||
|
||||
if (outcols >= maxiplcols)
|
||||
flushcard();
|
||||
|
||||
putc(0, fout);
|
||||
putc(word & 0xFF, fout); // write the low 8 bits in little-endian binary
|
||||
outcols++;
|
||||
|
||||
putc(0, fout);
|
||||
putc((word >> 8) & 0xFF, fout); // write the high 8 bits in little-endian binary
|
||||
outcols++;
|
||||
}
|
||||
flushcard();
|
||||
fclose(fout);
|
||||
}
|
||||
|
||||
void write_core (void)
|
||||
{
|
||||
int addr;
|
||||
|
||||
if ((fout = fopen(outfile, "wb")) == NULL) {
|
||||
perror(outfile);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
addr_from = load_low;
|
||||
addr_to = load_high;
|
||||
|
||||
maxiplcols = 72;
|
||||
corecard_init();
|
||||
corecard_setorg(addr_from);
|
||||
|
||||
for (addr = addr_from; addr <= addr_to; addr++) {
|
||||
corecard_writew(mem[addr], 0);
|
||||
}
|
||||
|
||||
corecard_flush();
|
||||
corecard_endcard();
|
||||
fclose(fout);
|
||||
}
|
||||
|
||||
void flushcard (void)
|
||||
{
|
||||
int i, hol, ndig;
|
||||
char fmt[20], newdig[20];
|
||||
|
||||
if (outcols <= 0)
|
||||
return; // nothing to flush
|
||||
|
||||
while (outcols < maxiplcols) { // pad to required number of columns with blanks (no punches)
|
||||
putc(0, fout);
|
||||
putc(0, fout);
|
||||
outcols++;
|
||||
}
|
||||
|
||||
if (*cardid) { // add label
|
||||
for (i = 0; i < 8; i++) { // write label as specified
|
||||
hol = ascii_to_hollerith(cardid[i] & 0x7F);
|
||||
putc(hol & 0xFF, fout);
|
||||
putc((hol >> 8) & 0xFF, fout);
|
||||
}
|
||||
|
||||
ndig = 0; // count trailing digits in the label
|
||||
for (i = 8; --i >= 0; ndig++)
|
||||
if (! isdigit(cardid[i]))
|
||||
break;
|
||||
|
||||
i++; // index of first digit in trailing sequence
|
||||
|
||||
if (ndig > 0) { // if any, increment them
|
||||
sprintf(fmt, "%%0%dd", ndig); // make, e.g. %03d
|
||||
sprintf(newdig, fmt, atoi(cardid+i)+1);
|
||||
newdig[ndig] = '\0'; // clip if necessary
|
||||
strcpy(cardid+i, newdig); // replace for next card's sequence number
|
||||
}
|
||||
}
|
||||
|
||||
outcols = 0;
|
||||
}
|
||||
|
||||
void show_data (unsigned short *buf)
|
||||
{
|
||||
int i, n, jrel, rflag, nout, ch, reloc;
|
||||
|
||||
n = buf[2] & 0x00FF;
|
||||
|
||||
printf("%04x: ", buf[0]);
|
||||
|
||||
jrel = 3;
|
||||
nout = 0;
|
||||
rflag = buf[jrel++];
|
||||
for (i = 0; i < n; i++) {
|
||||
if (nout >= 8) {
|
||||
rflag = buf[jrel++];
|
||||
putchar('\n');
|
||||
printf(" ");
|
||||
nout = 0;
|
||||
}
|
||||
reloc = (rflag >> 14) & 0x03;
|
||||
ch = (reloc == R_ABSOLUTE) ? ' ' :
|
||||
(reloc == R_RELATIVE) ? 'R' :
|
||||
(reloc == R_LIBF) ? 'L' : '@';
|
||||
|
||||
printf("%04x%c ", buf[9+i], ch);
|
||||
rflag <<= 2;
|
||||
nout++;
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
void loadcard (unsigned short *buf)
|
||||
{
|
||||
int addr, n, i;
|
||||
|
||||
addr = buf[0];
|
||||
n = buf[2] & 0x00FF;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
if (addr >= MAXADDR)
|
||||
bail("Program doesn't fit into 4K");
|
||||
mem[addr] = buf[9+i];
|
||||
|
||||
load_low = MIN(addr, load_low);
|
||||
load_high = MAX(addr, load_high);
|
||||
addr++;
|
||||
}
|
||||
}
|
||||
|
||||
void loaddata (char *fname)
|
||||
{
|
||||
FILE *fp;
|
||||
BOOL first = TRUE;
|
||||
unsigned short card[80], buf[54], cardtype;
|
||||
|
||||
if ((fp = fopen(fname, "rb")) == NULL) {
|
||||
perror(fname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
printf("\n%s:\n", fname);
|
||||
|
||||
while (fread(card, sizeof(card[0]), 80, fp) > 0) {
|
||||
unpack(card, buf);
|
||||
verify_checksum(card);
|
||||
|
||||
cardtype = (buf[2] >> 8) & 0xFF;
|
||||
|
||||
if (cardtype == 1 && ! first) { // sector break
|
||||
if (verbose)
|
||||
printf("*SBRK\n");
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
switch (cardtype) {
|
||||
case 0x01:
|
||||
if (verbose)
|
||||
printf("*ABS\n");
|
||||
break;
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
case 0x04:
|
||||
case 0x05:
|
||||
case 0x06:
|
||||
case 0x07:
|
||||
bail("Data must be in absolute format");
|
||||
break;
|
||||
|
||||
case 0x0F:
|
||||
pta = buf[3]; // save program transfer address
|
||||
if (verbose)
|
||||
printf("*END\n");
|
||||
break;
|
||||
|
||||
case 0x0A:
|
||||
if (verbose)
|
||||
show_data(buf);
|
||||
loadcard(buf);
|
||||
break;
|
||||
default:
|
||||
bail("Unexpected card type");
|
||||
}
|
||||
}
|
||||
first = FALSE;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void bail (char *msg)
|
||||
{
|
||||
fprintf(stderr, "%s\n", msg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void unpack (unsigned short *card, unsigned short *buf)
|
||||
{
|
||||
int i, j;
|
||||
unsigned short wd1, wd2, wd3, wd4;
|
||||
|
||||
for (i = j = 0; i < 54; i += 3, j += 4) {
|
||||
wd1 = card[j];
|
||||
wd2 = card[j+1];
|
||||
wd3 = card[j+2];
|
||||
wd4 = card[j+3];
|
||||
|
||||
buf[i ] = (wd1 & 0xFFF0) | ((wd2 >> 12) & 0x000F);
|
||||
buf[i+1] = ((wd2 << 4) & 0xFF00) | ((wd3 >> 8) & 0x00FF);
|
||||
buf[i+2] = ((wd3 << 8) & 0xF000) | ((wd4 >> 4) & 0x0FFF);
|
||||
}
|
||||
}
|
||||
|
||||
void verify_checksum (unsigned short *card)
|
||||
{
|
||||
// unsigned short sum;
|
||||
|
||||
if (card[1] == 0) // no checksum
|
||||
return;
|
||||
|
||||
// if (sum != card[1])
|
||||
// printf("Checksum %04x doesn't match card %04x\n", sum, card[1]);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int hollerith;
|
||||
char ascii;
|
||||
} CPCODE;
|
||||
|
||||
static CPCODE cardcode_029[] =
|
||||
{
|
||||
0x0000, ' ',
|
||||
0x8000, '&', // + in 026 Fortran
|
||||
0x4000, '-',
|
||||
0x2000, '0',
|
||||
0x1000, '1',
|
||||
0x0800, '2',
|
||||
0x0400, '3',
|
||||
0x0200, '4',
|
||||
0x0100, '5',
|
||||
0x0080, '6',
|
||||
0x0040, '7',
|
||||
0x0020, '8',
|
||||
0x0010, '9',
|
||||
0x9000, 'A',
|
||||
0x8800, 'B',
|
||||
0x8400, 'C',
|
||||
0x8200, 'D',
|
||||
0x8100, 'E',
|
||||
0x8080, 'F',
|
||||
0x8040, 'G',
|
||||
0x8020, 'H',
|
||||
0x8010, 'I',
|
||||
0x5000, 'J',
|
||||
0x4800, 'K',
|
||||
0x4400, 'L',
|
||||
0x4200, 'M',
|
||||
0x4100, 'N',
|
||||
0x4080, 'O',
|
||||
0x4040, 'P',
|
||||
0x4020, 'Q',
|
||||
0x4010, 'R',
|
||||
0x3000, '/',
|
||||
0x2800, 'S',
|
||||
0x2400, 'T',
|
||||
0x2200, 'U',
|
||||
0x2100, 'V',
|
||||
0x2080, 'W',
|
||||
0x2040, 'X',
|
||||
0x2020, 'Y',
|
||||
0x2010, 'Z',
|
||||
0x0820, ':',
|
||||
0x0420, '#', // = in 026 Fortran
|
||||
0x0220, '@', // ' in 026 Fortran
|
||||
0x0120, '\'',
|
||||
0x00A0, '=',
|
||||
0x0060, '"',
|
||||
0x8820, 'c', // cent
|
||||
0x8420, '.',
|
||||
0x8220, '<', // ) in 026 Fortran
|
||||
0x8120, '(',
|
||||
0x80A0, '+',
|
||||
0x8060, '|',
|
||||
0x4820, '!',
|
||||
0x4420, '$',
|
||||
0x4220, '*',
|
||||
0x4120, ')',
|
||||
0x40A0, ';',
|
||||
0x4060, 'n', // not
|
||||
0x2820, 'x', // what?
|
||||
0x2420, ',',
|
||||
0x2220, '%', // ( in 026 Fortran
|
||||
0x2120, '_',
|
||||
0x20A0, '>',
|
||||
0x2060, '>',
|
||||
};
|
||||
|
||||
int ascii_to_hollerith (int ch)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(cardcode_029) / sizeof(CPCODE); i++)
|
||||
if (cardcode_029[i].ascii == ch)
|
||||
return cardcode_029[i].hollerith;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
// corecard - routines to write IBM 1130 Card object format
|
||||
// ---------------------------------------------------------------------------------
|
||||
|
||||
unsigned short corecard[54]; // the 54 data words that can fit on a binary format card
|
||||
int corecard_n = 0; // number of object words stored in corecard (0-45)
|
||||
int corecard_seq = 1; // card output sequence number
|
||||
int corecard_org = 0; // origin of current card-full
|
||||
int corecard_maxaddr = 0;
|
||||
BOOL corecard_first = TRUE; // TRUE when we're to write the program type card
|
||||
|
||||
// corecard_init - prepare a new object data output card
|
||||
|
||||
void corecard_init (void)
|
||||
{
|
||||
memset(corecard, 0, sizeof(corecard)); // clear card data
|
||||
corecard_n = 0; // no data
|
||||
corecard[0] = corecard_org; // store load address
|
||||
corecard_maxaddr = MAX(corecard_maxaddr, corecard_org-1); // save highest address written-to (this may be a BSS)
|
||||
}
|
||||
|
||||
// binard_writecard - emit a card. sbrk_text = NULL for normal data cards, points to comment text for sbrk card
|
||||
|
||||
void corecard_writecard (char *sbrk_text)
|
||||
{
|
||||
unsigned short binout[80];
|
||||
int i, j;
|
||||
|
||||
for (i = j = 0; i < 54; i += 3, j += 4) {
|
||||
binout[j ] = ( corecard[i] & 0xFFF0);
|
||||
binout[j+1] = ((corecard[i] << 12) & 0xF000) | ((corecard[i+1] >> 4) & 0x0FF0);
|
||||
binout[j+2] = ((corecard[i+1] << 8) & 0xFF00) | ((corecard[i+2] >> 8) & 0x00F0);
|
||||
binout[j+3] = ((corecard[i+2] << 4) & 0xFFF0);
|
||||
}
|
||||
|
||||
for (i = 0; i < 72; i++) {
|
||||
putc(binout[i] & 0xFF, fout);
|
||||
putc((binout[i] >> 8) & 0xFF, fout);
|
||||
}
|
||||
|
||||
outcols = 72; // add the ident
|
||||
flushcard();
|
||||
}
|
||||
|
||||
// binard_writedata - emit an object data card
|
||||
|
||||
void corecard_writedata (void)
|
||||
{
|
||||
corecard[1] = 0; // checksum
|
||||
corecard[2] = 0x0000 | corecard_n; // data card type + word count
|
||||
corecard_writecard(FALSE); // emit the card
|
||||
}
|
||||
|
||||
// corecard_flush - flush any pending binary data
|
||||
|
||||
void corecard_flush (void)
|
||||
{
|
||||
if (corecard_n > 0)
|
||||
corecard_writedata();
|
||||
|
||||
corecard_init();
|
||||
}
|
||||
|
||||
// corecard_setorg - set the origin
|
||||
|
||||
void corecard_setorg (int neworg)
|
||||
{
|
||||
corecard_org = neworg; // set origin for next card
|
||||
corecard_flush(); // flush any current data & store origin
|
||||
}
|
||||
|
||||
// corecard_writew - write a word to the current output card.
|
||||
|
||||
void corecard_writew (int word, RELOC relative)
|
||||
{
|
||||
if (corecard_n >= 50) // flush full card buffer (must be even)
|
||||
corecard_flush();
|
||||
|
||||
corecard[3+corecard_n++] = word;
|
||||
corecard_org++;
|
||||
}
|
||||
|
||||
// corecard_endcard - write end of program card
|
||||
|
||||
void corecard_endcard (void)
|
||||
{
|
||||
corecard_flush();
|
||||
|
||||
corecard[0] = 0; // effective length: add 1 to max origin, then 1 more to round up
|
||||
corecard[1] = 0;
|
||||
corecard[2] = 0x8000; // they look for negative bit but all else must be zero
|
||||
corecard[52] = 0xabcd; // index register 3 value, this is for fun
|
||||
corecard[53] = pta; // hmmm
|
||||
|
||||
corecard_writecard(NULL);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
* upcase - force a string to uppercase (ASCII)
|
||||
* ------------------------------------------------------------------------ */
|
||||
|
||||
char *upcase (char *str)
|
||||
{
|
||||
char *s;
|
||||
|
||||
for (s = str; *s; s++) {
|
||||
if (*s >= 'a' && *s <= 'z')
|
||||
*s -= 32;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
|
||||
int strnicmp (char *a, char *b, int n)
|
||||
{
|
||||
int ca, cb;
|
||||
|
||||
for (;;) {
|
||||
if (--n < 0) // still equal after n characters? quit now
|
||||
return 0;
|
||||
|
||||
if ((ca = *a) == 0) // get character, stop on null terminator
|
||||
return *b ? -1 : 0;
|
||||
|
||||
if (ca >= 'a' && ca <= 'z') // fold lowercase to uppercase
|
||||
ca -= 32;
|
||||
|
||||
cb = *b;
|
||||
if (cb >= 'a' && cb <= 'z')
|
||||
cb -= 32;
|
||||
|
||||
if ((ca -= cb) != 0) // if different, return comparison
|
||||
return ca;
|
||||
|
||||
a++, b++;
|
||||
}
|
||||
}
|
||||
|
||||
int strcmpi (char *a, char *b)
|
||||
{
|
||||
int ca, cb;
|
||||
|
||||
for (;;) {
|
||||
if ((ca = *a) == 0) // get character, stop on null terminator
|
||||
return *b ? -1 : 0;
|
||||
|
||||
if (ca >= 'a' && ca <= 'z') // fold lowercase to uppercase
|
||||
ca -= 32;
|
||||
|
||||
cb = *b;
|
||||
if (cb >= 'a' && cb <= 'z')
|
||||
cb -= 32;
|
||||
|
||||
if ((ca -= cb) != 0) // if different, return comparison
|
||||
return ca;
|
||||
|
||||
a++, b++;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,161 +0,0 @@
|
|||
# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
!IF "$(CFG)" == ""
|
||||
CFG=Win32 Debug
|
||||
!MESSAGE No configuration specified. Defaulting to Win32 Debug.
|
||||
!ENDIF
|
||||
|
||||
!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug"
|
||||
!MESSAGE Invalid configuration "$(CFG)" specified.
|
||||
!MESSAGE You can specify a configuration when running NMAKE on this makefile
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "mkboot.mak" CFG="Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
!ERROR An invalid configuration is specified.
|
||||
!ENDIF
|
||||
|
||||
################################################################################
|
||||
# Begin Project
|
||||
# PROP Target_Last_Scanned "Win32 Debug"
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "WinRel"
|
||||
# PROP BASE Intermediate_Dir "WinRel"
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "WinRel"
|
||||
# PROP Intermediate_Dir "WinRel"
|
||||
OUTDIR=.\WinRel
|
||||
INTDIR=.\WinRel
|
||||
|
||||
ALL : $(OUTDIR)/mkboot.exe $(OUTDIR)/mkboot.bsc
|
||||
|
||||
$(OUTDIR) :
|
||||
if not exist $(OUTDIR)/nul mkdir $(OUTDIR)
|
||||
|
||||
# ADD BASE CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c
|
||||
# ADD CPP /nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c
|
||||
CPP_PROJ=/nologo /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\
|
||||
/FR$(INTDIR)/ /Fp$(OUTDIR)/"mkboot.pch" /Fo$(INTDIR)/ /c
|
||||
CPP_OBJS=.\WinRel/
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
BSC32_FLAGS=/nologo /o$(OUTDIR)/"mkboot.bsc"
|
||||
BSC32_SBRS= \
|
||||
$(INTDIR)/mkboot.sbr
|
||||
|
||||
$(OUTDIR)/mkboot.bsc : $(OUTDIR) $(BSC32_SBRS)
|
||||
$(BSC32) @<<
|
||||
$(BSC32_FLAGS) $(BSC32_SBRS)
|
||||
<<
|
||||
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386
|
||||
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console\
|
||||
/INCREMENTAL:no /PDB:$(OUTDIR)/"mkboot.pdb" /MACHINE:I386\
|
||||
/OUT:$(OUTDIR)/"mkboot.exe"
|
||||
DEF_FILE=
|
||||
LINK32_OBJS= \
|
||||
$(INTDIR)/mkboot.obj
|
||||
|
||||
$(OUTDIR)/mkboot.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS)
|
||||
$(LINK32) @<<
|
||||
$(LINK32_FLAGS) $(LINK32_OBJS)
|
||||
<<
|
||||
|
||||
!ELSEIF "$(CFG)" == "Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "WinDebug"
|
||||
# PROP BASE Intermediate_Dir "WinDebug"
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "WinDebug"
|
||||
# PROP Intermediate_Dir "WinDebug"
|
||||
OUTDIR=.\WinDebug
|
||||
INTDIR=.\WinDebug
|
||||
|
||||
ALL : $(OUTDIR)/mkboot.exe $(OUTDIR)/mkboot.bsc
|
||||
|
||||
$(OUTDIR) :
|
||||
if not exist $(OUTDIR)/nul mkdir $(OUTDIR)
|
||||
|
||||
# ADD BASE CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c
|
||||
# ADD CPP /nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c
|
||||
CPP_PROJ=/nologo /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\
|
||||
/FR$(INTDIR)/ /Fp$(OUTDIR)/"mkboot.pch" /Fo$(INTDIR)/ /Fd$(OUTDIR)/"mkboot.pdb"\
|
||||
/c
|
||||
CPP_OBJS=.\WinDebug/
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
BSC32_FLAGS=/nologo /o$(OUTDIR)/"mkboot.bsc"
|
||||
BSC32_SBRS= \
|
||||
$(INTDIR)/mkboot.sbr
|
||||
|
||||
$(OUTDIR)/mkboot.bsc : $(OUTDIR) $(BSC32_SBRS)
|
||||
$(BSC32) @<<
|
||||
$(BSC32_FLAGS) $(BSC32_SBRS)
|
||||
<<
|
||||
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386
|
||||
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib /NOLOGO /SUBSYSTEM:console\
|
||||
/INCREMENTAL:yes /PDB:$(OUTDIR)/"mkboot.pdb" /DEBUG /MACHINE:I386\
|
||||
/OUT:$(OUTDIR)/"mkboot.exe"
|
||||
DEF_FILE=
|
||||
LINK32_OBJS= \
|
||||
$(INTDIR)/mkboot.obj
|
||||
|
||||
$(OUTDIR)/mkboot.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS)
|
||||
$(LINK32) @<<
|
||||
$(LINK32_FLAGS) $(LINK32_OBJS)
|
||||
<<
|
||||
|
||||
!ENDIF
|
||||
|
||||
.c{$(CPP_OBJS)}.obj:
|
||||
$(CPP) $(CPP_PROJ) $<
|
||||
|
||||
.cpp{$(CPP_OBJS)}.obj:
|
||||
$(CPP) $(CPP_PROJ) $<
|
||||
|
||||
.cxx{$(CPP_OBJS)}.obj:
|
||||
$(CPP) $(CPP_PROJ) $<
|
||||
|
||||
################################################################################
|
||||
# Begin Group "Source Files"
|
||||
|
||||
################################################################################
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\mkboot.c
|
||||
|
||||
$(INTDIR)/mkboot.obj : $(SOURCE) $(INTDIR)
|
||||
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Project
|
||||
################################################################################
|
|
@ -1,242 +0,0 @@
|
|||
/* Simple program to display a binary card-image file in ASCII.
|
||||
* We assume the deck was written with one card per 16-bit word, left-justified,
|
||||
* and written in PC little-endian order
|
||||
*
|
||||
* (C) Copyright 2002, Brian Knittel.
|
||||
* You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN
|
||||
* RISK basis, there is no warranty of fitness for any purpose, and the rest of the
|
||||
* usual yada-yada. Please keep this notice and the copyright in any distributions
|
||||
* or modifications.
|
||||
*
|
||||
* This is not a supported product, but I welcome bug reports and fixes.
|
||||
* Mail to sim@ibm1130.org
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
typedef int BOOL;
|
||||
|
||||
int hollerith_to_ascii (unsigned short h);
|
||||
void bail (char *msg);
|
||||
void format_coldstart (unsigned short *buf);
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
FILE *fd;
|
||||
char *fname = NULL, line[82], *arg;
|
||||
BOOL coldstart = FALSE;
|
||||
unsigned short buf[80];
|
||||
int i, lastnb;
|
||||
static char usestr[] =
|
||||
"Usage: viewdeck [-c] deckfile\n"
|
||||
"\n"
|
||||
"-c: convert cold start card to 16-bit format as a C array initializer\n";
|
||||
|
||||
for (i = 1; i < argc; i++) { // process command line arguments
|
||||
arg = argv[i];
|
||||
|
||||
if (*arg == '-') {
|
||||
arg++;
|
||||
while (*arg) {
|
||||
switch (*arg++) {
|
||||
case 'c':
|
||||
coldstart = TRUE;
|
||||
break;
|
||||
default:
|
||||
bail(usestr);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (fname == NULL) // first non-switch arg is file name
|
||||
fname = arg;
|
||||
else
|
||||
bail(usestr); // there can be only one name
|
||||
}
|
||||
|
||||
if (fname == NULL) // there must be a name
|
||||
bail(usestr);
|
||||
|
||||
if ((fd = fopen(fname, "rb")) == NULL) {
|
||||
perror(fname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (fread(buf, sizeof(short), 80, fd) == 80) {
|
||||
if (coldstart) {
|
||||
format_coldstart(buf);
|
||||
break;
|
||||
}
|
||||
|
||||
lastnb = -1;
|
||||
for (i = 0; i < 80; i++) {
|
||||
line[i] = hollerith_to_ascii(buf[i]);
|
||||
if (line[i] > ' ')
|
||||
lastnb = i;
|
||||
}
|
||||
line[++lastnb] = '\n';
|
||||
line[++lastnb] = '\0';
|
||||
fputs(line, stdout);
|
||||
}
|
||||
|
||||
if (coldstart) {
|
||||
if (fread(buf, sizeof(short), 1, fd) == 1)
|
||||
bail("Coldstart deck has more than one card");
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void format_coldstart (unsigned short *buf)
|
||||
{
|
||||
int i, nout = 0;
|
||||
unsigned short word;
|
||||
|
||||
for (i = 0; i < 80; i++) {
|
||||
word = buf[i]; // expand 12-bit card data to 16-bit instruction
|
||||
word = (word & 0xF800) | ((word & 0x0400) ? 0x00C0 : 0x0000) | ((word & 0x03F0) >> 4);
|
||||
|
||||
if (nout >= 8) {
|
||||
fputs(",\n", stdout);
|
||||
nout = 0;
|
||||
}
|
||||
else if (i > 0)
|
||||
fputs(", ", stdout);
|
||||
|
||||
printf("0x%04x", word);
|
||||
nout++;
|
||||
}
|
||||
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
unsigned short hollerith;
|
||||
char ascii;
|
||||
} CPCODE;
|
||||
|
||||
static CPCODE cardcode_029[] =
|
||||
{
|
||||
0x0000, ' ',
|
||||
0x8000, '&', // + in 026 Fortran
|
||||
0x4000, '-',
|
||||
0x2000, '0',
|
||||
0x1000, '1',
|
||||
0x0800, '2',
|
||||
0x0400, '3',
|
||||
0x0200, '4',
|
||||
0x0100, '5',
|
||||
0x0080, '6',
|
||||
0x0040, '7',
|
||||
0x0020, '8',
|
||||
0x0010, '9',
|
||||
0x9000, 'A',
|
||||
0x8800, 'B',
|
||||
0x8400, 'C',
|
||||
0x8200, 'D',
|
||||
0x8100, 'E',
|
||||
0x8080, 'F',
|
||||
0x8040, 'G',
|
||||
0x8020, 'H',
|
||||
0x8010, 'I',
|
||||
0x5000, 'J',
|
||||
0x4800, 'K',
|
||||
0x4400, 'L',
|
||||
0x4200, 'M',
|
||||
0x4100, 'N',
|
||||
0x4080, 'O',
|
||||
0x4040, 'P',
|
||||
0x4020, 'Q',
|
||||
0x4010, 'R',
|
||||
0x3000, '/',
|
||||
0x2800, 'S',
|
||||
0x2400, 'T',
|
||||
0x2200, 'U',
|
||||
0x2100, 'V',
|
||||
0x2080, 'W',
|
||||
0x2040, 'X',
|
||||
0x2020, 'Y',
|
||||
0x2010, 'Z',
|
||||
0x0820, ':',
|
||||
0x0420, '#', // = in 026 Fortran
|
||||
0x0220, '@', // ' in 026 Fortran
|
||||
0x0120, '\'',
|
||||
0x00A0, '=',
|
||||
0x0060, '"',
|
||||
0x8820, '\xA2', // cent, in MS-DOS encoding
|
||||
0x8420, '.',
|
||||
0x8220, '<', // ) in 026 Fortran
|
||||
0x8120, '(',
|
||||
0x80A0, '+',
|
||||
0x8060, '|',
|
||||
0x4820, '!',
|
||||
0x4420, '$',
|
||||
0x4220, '*',
|
||||
0x4120, ')',
|
||||
0x40A0, ';',
|
||||
0x4060, '\xAC', // not, in MS-DOS encoding
|
||||
0x2420, ',',
|
||||
0x2220, '%', // ( in 026 Fortran
|
||||
0x2120, '_',
|
||||
0x20A0, '>',
|
||||
0xB000, 'a',
|
||||
0xA800, 'b',
|
||||
0xA400, 'c',
|
||||
0xA200, 'd',
|
||||
0xA100, 'e',
|
||||
0xA080, 'f',
|
||||
0xA040, 'g',
|
||||
0xA020, 'h',
|
||||
0xA010, 'i',
|
||||
0xD000, 'j',
|
||||
0xC800, 'k',
|
||||
0xC400, 'l',
|
||||
0xC200, 'm',
|
||||
0xC100, 'n',
|
||||
0xC080, 'o',
|
||||
0xC040, 'p',
|
||||
0xC020, 'q',
|
||||
0xC010, 'r',
|
||||
0x6800, 's',
|
||||
0x6400, 't',
|
||||
0x6200, 'u',
|
||||
0x6100, 'v',
|
||||
0x6080, 'w',
|
||||
0x6040, 'x',
|
||||
0x6020, 'y',
|
||||
0x6010, 'z', // these odd punch codes are used by APL:
|
||||
0x1010, '\001', // no corresponding ASCII using ^A
|
||||
0x0810, '\002', // SYN using ^B
|
||||
0x0410, '\003', // no corresponding ASCII using ^C
|
||||
0x0210, '\004', // PUNCH ON using ^D
|
||||
0x0110, '\005', // READER STOP using ^E
|
||||
0x0090, '\006', // UPPER CASE using ^F
|
||||
0x0050, '\013', // EOT using ^K
|
||||
0x0030, '\016', // no corresponding ASCII using ^N
|
||||
0x1030, '\017', // no corresponding ASCII using ^O
|
||||
0x0830, '\020', // no corresponding ASCII using ^P
|
||||
};
|
||||
|
||||
int hollerith_to_ascii (unsigned short h)
|
||||
{
|
||||
int i;
|
||||
|
||||
h &= 0xFFF0;
|
||||
|
||||
for (i = 0; i < sizeof(cardcode_029) / sizeof(CPCODE); i++)
|
||||
if (cardcode_029[i].hollerith == h)
|
||||
return cardcode_029[i].ascii;
|
||||
|
||||
return '?';
|
||||
}
|
||||
|
||||
void bail (char *msg)
|
||||
{
|
||||
fprintf(stderr, "%s\n", msg);
|
||||
exit(1);
|
||||
}
|
||||
|
|
@ -1,161 +0,0 @@
|
|||
# Microsoft Visual C++ Generated NMAKE File, Format Version 2.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Console Application" 0x0103
|
||||
|
||||
!IF "$(CFG)" == ""
|
||||
CFG=Win32 Debug
|
||||
!MESSAGE No configuration specified. Defaulting to Win32 Debug.
|
||||
!ENDIF
|
||||
|
||||
!IF "$(CFG)" != "Win32 Release" && "$(CFG)" != "Win32 Debug"
|
||||
!MESSAGE Invalid configuration "$(CFG)" specified.
|
||||
!MESSAGE You can specify a configuration when running NMAKE on this makefile
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "viewdeck.mak" CFG="Win32 Debug"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "Win32 Release" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE "Win32 Debug" (based on "Win32 (x86) Console Application")
|
||||
!MESSAGE
|
||||
!ERROR An invalid configuration is specified.
|
||||
!ENDIF
|
||||
|
||||
################################################################################
|
||||
# Begin Project
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "Win32 Release"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "WinRel"
|
||||
# PROP BASE Intermediate_Dir "WinRel"
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "WinRel"
|
||||
# PROP Intermediate_Dir "WinRel"
|
||||
OUTDIR=.\WinRel
|
||||
INTDIR=.\WinRel
|
||||
|
||||
ALL : $(OUTDIR)/viewdeck.exe $(OUTDIR)/viewdeck.bsc
|
||||
|
||||
$(OUTDIR) :
|
||||
if not exist $(OUTDIR)/nul mkdir $(OUTDIR)
|
||||
|
||||
# ADD BASE CPP /nologo /ML /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c
|
||||
# ADD CPP /nologo /ML /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /FR /c
|
||||
CPP_PROJ=/nologo /ML /W3 /GX /YX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE"\
|
||||
/FR$(INTDIR)/ /Fp$(OUTDIR)/"viewdeck.pch" /Fo$(INTDIR)/ /c
|
||||
CPP_OBJS=.\WinRel/
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
BSC32_FLAGS=/nologo /o$(OUTDIR)/"viewdeck.bsc"
|
||||
BSC32_SBRS= \
|
||||
$(INTDIR)/viewdeck.sbr
|
||||
|
||||
$(OUTDIR)/viewdeck.bsc : $(OUTDIR) $(BSC32_SBRS)
|
||||
$(BSC32) @<<
|
||||
$(BSC32_FLAGS) $(BSC32_SBRS)
|
||||
<<
|
||||
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib /NOLOGO /SUBSYSTEM:console /MACHINE:I386
|
||||
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
|
||||
advapi32.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:no\
|
||||
/PDB:$(OUTDIR)/"viewdeck.pdb" /MACHINE:I386 /OUT:$(OUTDIR)/"viewdeck.exe"
|
||||
DEF_FILE=
|
||||
LINK32_OBJS= \
|
||||
$(INTDIR)/viewdeck.obj
|
||||
|
||||
$(OUTDIR)/viewdeck.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS)
|
||||
$(LINK32) @<<
|
||||
$(LINK32_FLAGS) $(LINK32_OBJS)
|
||||
<<
|
||||
|
||||
!ELSEIF "$(CFG)" == "Win32 Debug"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "WinDebug"
|
||||
# PROP BASE Intermediate_Dir "WinDebug"
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "WinDebug"
|
||||
# PROP Intermediate_Dir "WinDebug"
|
||||
OUTDIR=.\WinDebug
|
||||
INTDIR=.\WinDebug
|
||||
|
||||
ALL : $(OUTDIR)/viewdeck.exe $(OUTDIR)/viewdeck.bsc
|
||||
|
||||
$(OUTDIR) :
|
||||
if not exist $(OUTDIR)/nul mkdir $(OUTDIR)
|
||||
|
||||
# ADD BASE CPP /nologo /ML /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c
|
||||
# ADD CPP /nologo /ML /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FR /c
|
||||
CPP_PROJ=/nologo /ML /W3 /GX /Zi /YX /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE"\
|
||||
/FR$(INTDIR)/ /Fp$(OUTDIR)/"viewdeck.pch" /Fo$(INTDIR)/\
|
||||
/Fd$(OUTDIR)/"viewdeck.pdb" /c
|
||||
CPP_OBJS=.\WinDebug/
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
BSC32_FLAGS=/nologo /o$(OUTDIR)/"viewdeck.bsc"
|
||||
BSC32_SBRS= \
|
||||
$(INTDIR)/viewdeck.sbr
|
||||
|
||||
$(OUTDIR)/viewdeck.bsc : $(OUTDIR) $(BSC32_SBRS)
|
||||
$(BSC32) @<<
|
||||
$(BSC32_FLAGS) $(BSC32_SBRS)
|
||||
<<
|
||||
|
||||
LINK32=link.exe
|
||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386
|
||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib /NOLOGO /SUBSYSTEM:console /DEBUG /MACHINE:I386
|
||||
LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
|
||||
advapi32.lib /NOLOGO /SUBSYSTEM:console /INCREMENTAL:yes\
|
||||
/PDB:$(OUTDIR)/"viewdeck.pdb" /DEBUG /MACHINE:I386\
|
||||
/OUT:$(OUTDIR)/"viewdeck.exe"
|
||||
DEF_FILE=
|
||||
LINK32_OBJS= \
|
||||
$(INTDIR)/viewdeck.obj
|
||||
|
||||
$(OUTDIR)/viewdeck.exe : $(OUTDIR) $(DEF_FILE) $(LINK32_OBJS)
|
||||
$(LINK32) @<<
|
||||
$(LINK32_FLAGS) $(LINK32_OBJS)
|
||||
<<
|
||||
|
||||
!ENDIF
|
||||
|
||||
.c{$(CPP_OBJS)}.obj:
|
||||
$(CPP) $(CPP_PROJ) $<
|
||||
|
||||
.cpp{$(CPP_OBJS)}.obj:
|
||||
$(CPP) $(CPP_PROJ) $<
|
||||
|
||||
.cxx{$(CPP_OBJS)}.obj:
|
||||
$(CPP) $(CPP_PROJ) $<
|
||||
|
||||
################################################################################
|
||||
# Begin Group "Source Files"
|
||||
|
||||
################################################################################
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\viewdeck.c
|
||||
|
||||
$(INTDIR)/viewdeck.obj : $(SOURCE) $(INTDIR)
|
||||
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Project
|
||||
################################################################################
|
|
@ -23,6 +23,9 @@
|
|||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
cpu Interdata 16b CPU
|
||||
|
||||
22-Sep-03 RMS Added additional instruction decode types
|
||||
07-Feb-03 RMS Fixed bug in SETM, SETMR (found by Mark Pizzolato)
|
||||
|
||||
The register state for the Interdata 16b CPU is:
|
||||
|
@ -266,7 +269,7 @@ const uint16 decrom[256] = {
|
|||
OP_NO | OP_816, /* FXR */
|
||||
OP_NO | OP_816, /* FLR */
|
||||
0, 0, 0, /* 30:32 */
|
||||
OP_RR | OP_816E | OP_PRV, /* LPSR */
|
||||
OP_NO | OP_816E | OP_PRV, /* LPSR */
|
||||
0, 0, 0, 0, /* 34:37 */
|
||||
OP_NO | OP_816 | OP_DPF, /* LDR */
|
||||
OP_NO | OP_816 | OP_DPF, /* CDR */
|
||||
|
@ -328,8 +331,8 @@ const uint16 decrom[256] = {
|
|||
OP_NO | OP_716, /* SRLS */
|
||||
OP_NO | OP_716, /* SLLS */
|
||||
OP_NO, /* STBR */
|
||||
OP_NO, /* LDBR */
|
||||
OP_NO | OP_716, /* EXBR */
|
||||
OP_RR, /* LDBR */
|
||||
OP_RR | OP_716, /* EXBR */
|
||||
OP_NO | OP_716 | OP_PRV, /* EPSR */
|
||||
OP_RR | OP_PRV, /* WBR */
|
||||
OP_RR | OP_PRV, /* RBR */
|
||||
|
@ -364,8 +367,8 @@ const uint16 decrom[256] = {
|
|||
OP_RX | OP_ID4, /* STM */
|
||||
OP_RX | OP_ID4, /* LM */
|
||||
OP_RX, /* STB */
|
||||
OP_RX, /* LDB */
|
||||
OP_RX | OP_716, /* CLB */
|
||||
OP_RXB, /* LDB */
|
||||
OP_RXB | OP_716, /* CLB */
|
||||
OP_RX | OP_ID4 | OP_PRV, /* AL */
|
||||
OP_RXH | OP_PRV, /* WB */
|
||||
OP_RXH | OP_PRV, /* RB */
|
||||
|
@ -552,6 +555,7 @@ while (reason == 0) { /* loop until halted */
|
|||
uint32 dev, drom, inc, lim, opnd;
|
||||
uint32 op, r1, r1p1, r2, ea, oPC;
|
||||
uint32 rslt, t, map;
|
||||
uint32 ir1, ir2, ityp;
|
||||
int32 sr, st;
|
||||
|
||||
if (sim_interval <= 0) { /* check clock queue */
|
||||
|
@ -606,11 +610,13 @@ if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
|
|||
|
||||
sim_interval = sim_interval - 1;
|
||||
|
||||
t = ReadH (oPC = PC); /* fetch instr */
|
||||
op = (t >> 8) & 0xFF; /* isolate op, R1, R2 */
|
||||
r1 = (t >> 4) & 0xF;
|
||||
r2 = t & 0xF;
|
||||
ir1 = ReadH (oPC = PC); /* fetch instr */
|
||||
op = (ir1 >> 8) & 0xFF; /* isolate op, R1, R2 */
|
||||
r1 = (ir1 >> 4) & 0xF;
|
||||
r2 = ir1 & 0xF;
|
||||
drom = decrom[op];
|
||||
ityp = drom & OP_MASK;
|
||||
|
||||
if ((drom == 0) || (drom & dec_flgs)) { /* not in model? */
|
||||
if (stop_inst) reason = STOP_RSRV; /* stop or */
|
||||
else cc = swap_psw (ILOPSW, cc); /* swap PSW */
|
||||
|
@ -618,26 +624,41 @@ if ((drom == 0) || (drom & dec_flgs)) { /* not in model? */
|
|||
if ((drom & OP_PRV) && (PSW & PSW_PRO)) { /* priv & protected? */
|
||||
cc = swap_psw (ILOPSW, cc); /* swap PSW */
|
||||
continue; }
|
||||
switch (drom & OP_MASK) { /* decode instruction */
|
||||
|
||||
switch (ityp) { /* decode instruction */
|
||||
case OP_NO: /* no operand */
|
||||
opnd = r2; /* assume short */
|
||||
break;
|
||||
|
||||
case OP_RR: /* reg-reg */
|
||||
opnd = R[r2]; /* operand is R2 */
|
||||
break;
|
||||
|
||||
case OP_RS: /* reg-storage */
|
||||
case OP_RX: /* reg-mem */
|
||||
PC = (PC + 2) & VAMASK; /* increment PC */
|
||||
ea = ReadH (PC); /* fetch address */
|
||||
if (r2) ea = (ea + R[r2]) & VAMASK; /* index calculation */
|
||||
ir2 = ea = ReadH (PC); /* fetch address */
|
||||
if (r2) ea = (ir2 + R[r2]) & VAMASK; /* index calculation */
|
||||
opnd = ea; /* operand is ea */
|
||||
break;
|
||||
case OP_RXH: /* reg-mem read */
|
||||
|
||||
case OP_RXB: /* reg-mem byte */
|
||||
PC = (PC + 2) & VAMASK; /* increment PC */
|
||||
ea = ReadH (PC); /* fetch address */
|
||||
ir2 = ea = ReadH (PC); /* fetch address */
|
||||
if (r2) ea = (ea + R[r2]) & VAMASK; /* index calculation */
|
||||
opnd = ReadB (ea); /* fetch operand */
|
||||
break;
|
||||
|
||||
case OP_RXH: /* reg-mem halfword */
|
||||
PC = (PC + 2) & VAMASK; /* increment PC */
|
||||
ir2 = ea = ReadH (PC); /* fetch address */
|
||||
if (r2) ea = (ea + R[r2]) & VAMASK; /* index calculation */
|
||||
opnd = ReadH (ea); /* fetch operand */
|
||||
break; }
|
||||
break;
|
||||
|
||||
default:
|
||||
return SCPE_IERR; }
|
||||
|
||||
PC = (PC + 2) & VAMASK; /* increment PC */
|
||||
switch (op) { /* case on opcode */
|
||||
|
||||
|
@ -672,11 +693,9 @@ case 0xD0: /* STM - RX */
|
|||
ea = (ea + 2) & VAMASK; } /* incr mem addr */
|
||||
break;
|
||||
|
||||
case 0x93: /* LDBR - NO */
|
||||
R[r1] = R[r2] & DMASK8; /* load byte */
|
||||
break;
|
||||
case 0xD3: /* LDB - RX */
|
||||
R[r1] = ReadB (ea); /* load byte */
|
||||
case 0x93: /* LDBR - RR */
|
||||
case 0xD3: /* LDB - RXB */
|
||||
R[r1] = opnd & DMASK8; /* load byte */
|
||||
break;
|
||||
|
||||
case 0x92: /* STBR - NO */
|
||||
|
@ -686,8 +705,8 @@ case 0xD2: /* STB - RX */
|
|||
WriteB (ea, R[r1] & DMASK8); /* store byte */
|
||||
break;
|
||||
|
||||
case 0x94: /* EXBR - NO */
|
||||
R[r1] = (R[r2] >> 8) | ((R[r2] & DMASK8) << 8);
|
||||
case 0x94: /* EXBR - RR */
|
||||
R[r1] = (opnd >> 8) | ((opnd & DMASK8) << 8);
|
||||
break;
|
||||
|
||||
/* Control instructions */
|
||||
|
@ -792,8 +811,7 @@ case 0xC5: /* CLHI - RS */
|
|||
if (((R[r1] ^ opnd) & (~opnd ^ rslt)) & SIGN16) cc = cc | CC_V;
|
||||
break;
|
||||
|
||||
case 0xD4: /* CLB - RX */
|
||||
opnd = ReadB (ea); /* get operand */
|
||||
case 0xD4: /* CLB - RXB */
|
||||
t = R[r1] & DMASK8;
|
||||
rslt = (t - opnd) & DMASK16; /* result */
|
||||
CC_GL_16 (rslt); /* set G,L */
|
||||
|
@ -1118,7 +1136,7 @@ case 0xC2: /* LPSW - RX */
|
|||
if (PSW & PSW_SQI) cc = testsysq (cc); /* test for q */
|
||||
break;
|
||||
|
||||
case 0x95: /* EPSR - RR */
|
||||
case 0x95: /* EPSR - NO */
|
||||
R[r1] = BUILD_PSW (cc); /* save PSW */
|
||||
case 0x33: /* LPSR - NO */
|
||||
cc = newPSW (R[r2]); /* load new PSW */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* id32_cpu.c: Interdata 32b CPU simulator
|
||||
|
||||
Copyright (c) 2000-2003, Robert M. Supnik
|
||||
Copyright (c) 2000-2004, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,12 @@
|
|||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
cpu Interdata 32b CPU
|
||||
|
||||
31-Dec-03 RMS Fixed bug in cpu_set_hist
|
||||
22-Sep-03 RMS Added additional instruction decode types
|
||||
Added instruction history
|
||||
|
||||
The register state for an Interdata 32b CPU is:
|
||||
|
||||
REG[0:F][2]<0:31> general register sets
|
||||
|
@ -156,6 +162,18 @@
|
|||
#define UNIT_832 (1 << UNIT_V_832)
|
||||
#define UNIT_TYPE (UNIT_DPFP | UNIT_832)
|
||||
|
||||
#define HIST_PC 0x40000000
|
||||
#define HIST_MIN 64
|
||||
#define HIST_MAX 65536
|
||||
struct InstHistory {
|
||||
uint32 pc;
|
||||
uint32 ir1;
|
||||
uint32 ir2;
|
||||
uint32 ir3;
|
||||
uint32 r1;
|
||||
uint32 ea;
|
||||
uint32 opnd; };
|
||||
|
||||
#define SEXT32(x) (((x) & SIGN32)? ((int32) ((x) | ~0x7FFFFFFF)): \
|
||||
((int32) ((x) & 0x7FFFFFFF)))
|
||||
#define SEXT16(x) (((x) & SIGN16)? ((int32) ((x) | ~0x7FFF)): \
|
||||
|
@ -202,6 +220,9 @@ uint32 dec_flgs = 0; /* decode flags */
|
|||
uint32 fp_in_hwre = 0; /* ucode vs hwre fp */
|
||||
uint32 pawidth = PAWIDTH32; /* addr mask */
|
||||
uint32 cpu_log = 0; /* debug logging */
|
||||
uint32 hst_p = 0; /* history pointer */
|
||||
uint32 hst_lnt = 0; /* history length */
|
||||
struct InstHistory *hst = NULL; /* instruction history */
|
||||
jmp_buf save_env; /* abort handler */
|
||||
struct BlockIO blk_io; /* block I/O status */
|
||||
uint32 (*dev_tab[DEVNO])(uint32 dev, uint32 op, uint32 datout) = { NULL };
|
||||
|
@ -229,6 +250,8 @@ t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
|
|||
t_stat cpu_reset (DEVICE *dptr);
|
||||
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat cpu_set_consint (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
void set_r_display (uint32 *rbase);
|
||||
|
||||
extern t_bool devtab_init (void);
|
||||
|
@ -329,8 +352,8 @@ const uint16 decrom[256] = {
|
|||
OP_RXF, /* S */
|
||||
OP_RXF, /* M */
|
||||
OP_RXF, /* D */
|
||||
OP_RX, /* CRC12 */
|
||||
OP_RX, /* CRC16 */
|
||||
OP_RXH, /* CRC12 */
|
||||
OP_RXH, /* CRC16 */
|
||||
OP_RX, /* STE */
|
||||
OP_RXH, /* AHM */
|
||||
0, /* PB - 8/32C */
|
||||
|
@ -349,7 +372,7 @@ const uint16 decrom[256] = {
|
|||
OP_RX | OP_DPF, /* STD */
|
||||
OP_RX, /* SME */
|
||||
OP_RX, /* LME */
|
||||
OP_RX, /* LHL */
|
||||
OP_RXH, /* LHL */
|
||||
OP_RX, /* TBT */
|
||||
OP_RX, /* SBT */
|
||||
OP_RX, /* RBT */
|
||||
|
@ -367,8 +390,8 @@ const uint16 decrom[256] = {
|
|||
OP_NO, /* SRHLS */
|
||||
OP_NO, /* SLHLS */
|
||||
OP_NO, /* STBR */
|
||||
OP_NO, /* LDBR */
|
||||
OP_NO, /* EXBR */
|
||||
OP_RR, /* LDBR */
|
||||
OP_RR, /* EXBR */
|
||||
OP_NO | OP_PRV, /* EPSR */
|
||||
OP_RR | OP_PRV, /* WBR */
|
||||
OP_RR | OP_PRV, /* RBR */
|
||||
|
@ -403,8 +426,8 @@ const uint16 decrom[256] = {
|
|||
OP_RX, /* STM */
|
||||
OP_RX, /* LM */
|
||||
OP_RX, /* STB */
|
||||
OP_RX, /* LDB */
|
||||
OP_RX, /* CLB */
|
||||
OP_RXB, /* LDB */
|
||||
OP_RXB, /* CLB */
|
||||
OP_RX | OP_PRV, /* AL */
|
||||
OP_RXF | OP_PRV, /* WB */
|
||||
OP_RXF | OP_PRV, /* RB */
|
||||
|
@ -419,7 +442,7 @@ const uint16 decrom[256] = {
|
|||
OP_RXH, /* TS */
|
||||
OP_RX, /* SVC */
|
||||
OP_RI1 | OP_PRV, /* SINT */
|
||||
OP_RX | OP_PRV, /* SCP */
|
||||
OP_RXH | OP_PRV, /* SCP */
|
||||
0, 0, /* E4:E5 */
|
||||
OP_RX, /* LA */
|
||||
OP_RXF, /* TLATE */
|
||||
|
@ -534,6 +557,8 @@ MTAB cpu_mod[] = {
|
|||
{ UNIT_TYPE, UNIT_DPFP | UNIT_832, "8/32", "832", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "CONSINT",
|
||||
&cpu_set_consint, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "HISTORY", "HISTORY",
|
||||
&cpu_set_hist, &cpu_show_hist },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE cpu_dev = {
|
||||
|
@ -586,6 +611,7 @@ uint32 dev, drom, opnd, inc, lim, bufa;
|
|||
uint32 op, r1, r1p1, r2, rx2, ea;
|
||||
uint32 mpy, mpc, dvr;
|
||||
uint32 i, rslt, rlo, t;
|
||||
uint32 ir1, ir2, ir3, ityp;
|
||||
int32 sr, st;
|
||||
|
||||
if (sim_interval <= 0) { /* check clock queue */
|
||||
|
@ -644,11 +670,13 @@ if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
|
|||
|
||||
sim_interval = sim_interval - 1;
|
||||
|
||||
t = ReadH (oPC = PC, VE); /* fetch instr */
|
||||
op = (t >> 8) & 0xFF; /* extract op,R1,R2 */
|
||||
r1 = (t >> 4) & 0xF;
|
||||
r2 = t & 0xF;
|
||||
ir1 = ReadH (oPC = PC, VE); /* fetch instr */
|
||||
op = (ir1 >> 8) & 0xFF; /* extract op,R1,R2 */
|
||||
r1 = (ir1 >> 4) & 0xF;
|
||||
r2 = ir1 & 0xF;
|
||||
drom = decrom[op]; /* get decode flags */
|
||||
ityp = drom & OP_MASK; /* instruction type */
|
||||
|
||||
if ((drom == 0) || (drom & dec_flgs)) { /* not in model? */
|
||||
if (stop_inst) reason = STOP_RSRV; /* stop or */
|
||||
else cc = exception (ILOPSW, cc, 0); /* exception */
|
||||
|
@ -657,55 +685,70 @@ if ((drom & OP_PRV) && (PSW & PSW_PRO)) { /* priv & protected? */
|
|||
cc = exception (ILOPSW, cc, 0); /* exception */
|
||||
continue; }
|
||||
|
||||
switch (drom & OP_MASK) { /* decode instruction */
|
||||
switch (ityp) { /* decode instruction */
|
||||
case OP_NO: /* no operand */
|
||||
opnd = r2; /* assume short */
|
||||
PC = (PC + 2) & VAMASK; /* increment PC */
|
||||
break;
|
||||
|
||||
case OP_RR: /* reg-reg */
|
||||
ea = opnd = R[r2]; /* operand is R2 */
|
||||
opnd = R[r2]; /* ea/operand is R2 */
|
||||
PC = (PC + 2) & VAMASK; /* increment PC */
|
||||
break;
|
||||
|
||||
case OP_RI1: /* reg-imm 1 */
|
||||
t = ReadH ((PC + 2) & VAMASK, VE); /* fetch immed */
|
||||
opnd = SEXT16 (t); /* sign extend */
|
||||
ir2 = ReadH ((PC + 2) & VAMASK, VE); /* fetch immed */
|
||||
opnd = SEXT16 (ir2); /* sign extend */
|
||||
if (r2) opnd = (opnd + R[r2]) & DMASK32; /* index calculation */
|
||||
PC = (PC + 4) & VAMASK; /* increment PC */
|
||||
break;
|
||||
|
||||
case OP_RI2: /* reg-imm 2 */
|
||||
t = ReadH ((PC + 2) & VAMASK, VE); /* fetch imm hi */
|
||||
opnd = t << 16; /* shift to place */
|
||||
t = ReadH ((PC + 4) & VAMASK, VE); /* fetch imm lo */
|
||||
opnd = opnd | t; /* complete imm */
|
||||
ir2 = ReadH ((PC + 2) & VAMASK, VE); /* fetch imm hi */
|
||||
ir3 = ReadH ((PC + 4) & VAMASK, VE); /* fetch imm lo */
|
||||
opnd = (ir2 << 16) | ir3; /* 32b immediate */
|
||||
if (r2) opnd = (opnd + R[r2]) & DMASK32; /* index calculation */
|
||||
PC = (PC + 6) & VAMASK; /* increment PC */
|
||||
break;
|
||||
case OP_RX: case OP_RXH: case OP_RXF: /* reg-mem */
|
||||
t = ReadH ((PC + 2) & VAMASK, VE); /* fetch addr */
|
||||
if ((t & 0xC000) == 0) { /* displacement? */
|
||||
|
||||
case OP_RX: case OP_RXB: case OP_RXH: case OP_RXF: /* reg-mem */
|
||||
ir2 = ReadH ((PC + 2) & VAMASK, VE); /* fetch addr */
|
||||
if ((ir2 & 0xC000) == 0) { /* displacement? */
|
||||
PC = (PC + 4) & VAMASK; /* increment PC */
|
||||
ea = t; } /* abs 14b displ */
|
||||
else if (t & 0x8000) { /* relative? */
|
||||
ea = ir2; } /* abs 14b displ */
|
||||
else if (ir2 & 0x8000) { /* relative? */
|
||||
PC = (PC + 4) & VAMASK; /* increment PC */
|
||||
ea = PC + SEXT15 (t); } /* add to incr PC */
|
||||
ea = PC + SEXT15 (ir2); } /* add to incr PC */
|
||||
else { /* absolute */
|
||||
rx2 = (t >> 8) & 0xF; /* get second index */
|
||||
ea = (t & 0xFF) << 16; /* shift to place */
|
||||
t = ReadH ((PC + 4) & VAMASK, VE); /* fetch addr lo */
|
||||
ea = ea | t; /* finish addr */
|
||||
rx2 = (ir2 >> 8) & 0xF; /* get second index */
|
||||
ea = (ir2 & 0xFF) << 16; /* shift to place */
|
||||
ir3 = ReadH ((PC + 4) & VAMASK, VE); /* fetch addr lo */
|
||||
ea = ea | ir3; /* finish addr */
|
||||
if (rx2) ea = ea + R[rx2]; /* index calc 2 */
|
||||
PC = (PC + 6) & VAMASK; } /* increment PC */
|
||||
if (r2) ea = ea + R[r2]; /* index calculation */
|
||||
ea = ea & VAMASK;
|
||||
if ((drom & OP_MASK) == OP_RXF) /* get fw operand? */
|
||||
opnd = ReadF (ea, VR); /* read fullword */
|
||||
else if ((drom & OP_MASK) == OP_RXH) { /* get hw operand? */
|
||||
if (ityp == OP_RXF) opnd = ReadF (ea, VR); /* get fw operand? */
|
||||
else if (ityp == OP_RXH) { /* get hw operand? */
|
||||
t = ReadH (ea, VR); /* read halfword */
|
||||
opnd = SEXT16 (t); } /* sign extend */
|
||||
else opnd = ea; /* for sloppy code */
|
||||
else if (ityp == OP_RXB) opnd = ReadB (ea, VR); /* get byte opnd? */
|
||||
else opnd = ea; /* just address */
|
||||
break;
|
||||
case OP_UNDEF:
|
||||
|
||||
default:
|
||||
return SCPE_IERR; }
|
||||
|
||||
if (hst_lnt) { /* instruction history? */
|
||||
hst[hst_p].pc = oPC | HIST_PC; /* save decode state */
|
||||
hst[hst_p].ir1 = ir1;
|
||||
hst[hst_p].ir2 = ir2;
|
||||
hst[hst_p].ir3 = ir3;
|
||||
hst[hst_p].r1 = R[r1];
|
||||
hst[hst_p].ea = ea;
|
||||
hst[hst_p].opnd = opnd;
|
||||
hst_p = hst_p + 1;
|
||||
if (hst_p >= hst_lnt) hst_p = 0; }
|
||||
if (qevent & EV_MAC) continue; /* MAC abort on fetch? */
|
||||
switch (op) { /* case on opcode */
|
||||
|
||||
|
@ -721,8 +764,8 @@ case 0xF8: /* LI - RI2 */
|
|||
CC_GL_32 (R[r1]); /* set G,L */
|
||||
break;
|
||||
|
||||
case 0x73: /* LHL - RX */
|
||||
R[r1] = ReadH (ea, VR); /* get op, zero ext */
|
||||
case 0x73: /* LHL - RXH */
|
||||
R[r1] = opnd & DMASK16; /* get op, zero ext */
|
||||
CC_GL_32 (R[r1]); /* set G, L */
|
||||
break;
|
||||
|
||||
|
@ -764,11 +807,9 @@ case 0xE0: /* TS - RXH */
|
|||
WriteH (ea, opnd | SIGN16, VW); /* set MSB */
|
||||
break;
|
||||
|
||||
case 0x93: /* LDBR - NO */
|
||||
R[r1] = R[r2] & DMASK8; /* load byte */
|
||||
break;
|
||||
case 0xD3: /* LDB - RX */
|
||||
R[r1] = ReadB (ea, VR); /* load byte */
|
||||
case 0x93: /* LDBR - RR */
|
||||
case 0xD3: /* LDB - RXB */
|
||||
R[r1] = opnd & DMASK8; /* load byte */
|
||||
break;
|
||||
|
||||
case 0x92: /* STBR - NO */
|
||||
|
@ -778,13 +819,13 @@ case 0xD2: /* STB - RX */
|
|||
WriteB (ea, R[r1], VW); /* store byte */
|
||||
break;
|
||||
|
||||
case 0x34: /* EXHR - NO */
|
||||
R[r1] = ((R[r2] >> 16) & DMASK16) | ((R[r2] & DMASK16) << 16);
|
||||
case 0x34: /* EXHR - RR */
|
||||
R[r1] = ((opnd >> 16) & DMASK16) | ((opnd & DMASK16) << 16);
|
||||
break;
|
||||
|
||||
case 0x94: /* EXBR - NO */
|
||||
case 0x94: /* EXBR - RR */
|
||||
R[r1] = (R[r1] & ~DMASK16) |
|
||||
((R[r2] >> 8) & DMASK8) | ((R[r2] & DMASK8) << 8);
|
||||
((opnd >> 8) & DMASK8) | ((opnd & DMASK8) << 8);
|
||||
break;
|
||||
|
||||
/* Control instructions */
|
||||
|
@ -793,14 +834,14 @@ case 0x01: /* BALR - RR */
|
|||
case 0x41: /* BAL - RX */
|
||||
PCQ_ENTRY; /* save old PC */
|
||||
R[r1] = PC; /* save cur PC */
|
||||
PC = ea; /* branch */
|
||||
PC = opnd; /* branch */
|
||||
break;
|
||||
|
||||
case 0x02: /* BTCR - RR */
|
||||
case 0x42: /* BTC - RX */
|
||||
if (cc & r1) { /* test CC's */
|
||||
PCQ_ENTRY; /* branch if true */
|
||||
PC = ea; }
|
||||
PC = opnd; }
|
||||
break;
|
||||
|
||||
case 0x20: /* BTBS - NO */
|
||||
|
@ -819,7 +860,7 @@ case 0x03: /* BFCR - RR */
|
|||
case 0x43: /* BFC - RX */
|
||||
if ((cc & r1) == 0) { /* test CC's */
|
||||
PCQ_ENTRY; /* branch if false */
|
||||
PC = ea; }
|
||||
PC = opnd; }
|
||||
break;
|
||||
|
||||
case 0x22: /* BFBS - NO */
|
||||
|
@ -840,16 +881,16 @@ case 0xC0: /* BXH - RX */
|
|||
R[r1] = (R[r1] + inc) & DMASK32; /* R1 = R1 + inc */
|
||||
if (R[r1] > lim) { /* if R1 > lim */
|
||||
PCQ_ENTRY; /* branch */
|
||||
PC = ea; }
|
||||
PC = opnd; }
|
||||
break;
|
||||
|
||||
case 0xC1: /* BXLE - RS */
|
||||
case 0xC1: /* BXLE - RX */
|
||||
inc = R[(r1 + 1) & 0xF]; /* inc = R1 + 1 */
|
||||
lim = R[(r1 + 2) & 0xF]; /* lim = R1 + 2 */
|
||||
R[r1] = (R[r1] + inc) & DMASK32; /* R1 = R1 + inc */
|
||||
if (R[r1] <= lim) { /* if R1 <= lim */
|
||||
PCQ_ENTRY; /* branch */
|
||||
PC = ea; }
|
||||
PC = opnd; }
|
||||
break;
|
||||
|
||||
/* Logical instructions */
|
||||
|
@ -898,8 +939,7 @@ case 0xF5: /* CI - RI2 */
|
|||
if (((R[r1] ^ opnd) & (~opnd ^ rslt)) & SIGN32) cc = cc | CC_V;
|
||||
break;
|
||||
|
||||
case 0xD4: /* CLB - RX */
|
||||
opnd = ReadB (ea, VR); /* get operand */
|
||||
case 0xD4: /* CLB - RXB */
|
||||
t = R[r1] & DMASK8;
|
||||
rslt = (t - opnd) & DMASK16; /* result */
|
||||
CC_GL_16 (rslt); /* set G,L 16b */
|
||||
|
@ -1278,8 +1318,8 @@ case 0xE2: /* SINT - RI1 */
|
|||
int_eval ();
|
||||
break;
|
||||
|
||||
case 0xE3: /* SCP - RX */
|
||||
opnd = ReadH (ea, VR); /* zero ext operand */
|
||||
case 0xE3: /* SCP - RXH */
|
||||
opnd = opnd & DMASK16; /* zero ext operand */
|
||||
if (opnd & CCW32_B1) t = ea + CCB32_B1C; /* point to buf */
|
||||
else t = ea + CCB32_B0C;
|
||||
sr = ReadH (t & VAMASK, VR); /* get count */
|
||||
|
@ -1335,7 +1375,7 @@ case 0x67: /* RBL - RX */
|
|||
break;
|
||||
|
||||
case 0x5E: /* CRC12 - RXH */
|
||||
opnd = ReadH (ea, VR); /* zero ext opnd */
|
||||
opnd = opnd & DMASK16; /* zero ext opnd */
|
||||
t = (R[r1] & 0x3F) ^ opnd;
|
||||
for (i = 0; i < 6; i++) {
|
||||
if (t & 1) t = (t >> 1) ^ 0x0F01;
|
||||
|
@ -1344,7 +1384,7 @@ case 0x5E: /* CRC12 - RXH */
|
|||
break;
|
||||
|
||||
case 0x5F: /* CRC16 - RXH */
|
||||
opnd = ReadH (ea, VR); /* zero ext opnd */
|
||||
opnd = opnd & DMASK16; /* zero ext opnd */
|
||||
t = (R[r1] & 0xFF) ^ opnd;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (t & 1) t = (t >> 1) ^ 0xA001;
|
||||
|
@ -1417,7 +1457,7 @@ case 0xDB: /* RD - RX */
|
|||
break;
|
||||
|
||||
case 0x99: /* RHR - RR */
|
||||
case 0xD9: /* RH - RS */
|
||||
case 0xD9: /* RH - RX */
|
||||
dev = R[r1] & DEV_MAX;
|
||||
if (DEV_ACC (dev)) { /* dev exist? */
|
||||
if (dev_tab[dev] (dev, IO_ADR, 0)) /* select, hw ok? */
|
||||
|
@ -1436,7 +1476,7 @@ case 0xD9: /* RH - RS */
|
|||
break;
|
||||
|
||||
case 0x9D: /* SSR - RR */
|
||||
case 0xDD: /* SS - RS */
|
||||
case 0xDD: /* SS - RX */
|
||||
dev = R[r1] & DEV_MAX;
|
||||
if (DEV_ACC (dev)) { /* dev exist? */
|
||||
dev_tab[dev] (dev, IO_ADR, 0); /* select */
|
||||
|
@ -2026,3 +2066,61 @@ t_stat cpu_set_consint (UNIT *uptr, int32 val, char *cptr, void *desc)
|
|||
if (PSW & PSW_EXI) SET_INT (v_DS);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Set history */
|
||||
|
||||
t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
uint32 i, lnt;
|
||||
t_stat r;
|
||||
|
||||
if (cptr == NULL) {
|
||||
for (i = 0; i < hst_lnt; i++) hst[i].pc = 0;
|
||||
hst_p = 0;
|
||||
return SCPE_OK; }
|
||||
lnt = (uint32) get_uint (cptr, 10, HIST_MAX, &r);
|
||||
if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG;
|
||||
hst_p = 0;
|
||||
if (hst_lnt) {
|
||||
free (hst);
|
||||
hst_lnt = 0;
|
||||
hst = NULL; }
|
||||
if (lnt) {
|
||||
hst = calloc (sizeof (struct InstHistory), lnt);
|
||||
if (hst == NULL) return SCPE_MEM;
|
||||
hst_lnt = lnt; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Show history */
|
||||
|
||||
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
uint32 op, k, di;
|
||||
t_value sim_eval[6];
|
||||
struct InstHistory *h;
|
||||
extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
|
||||
UNIT *uptr, int32 sw);
|
||||
|
||||
if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */
|
||||
fprintf (st, "PC r1 operand ea IR\n\n");
|
||||
di = hst_p; /* work forward */
|
||||
for (k = 0; k < hst_lnt; k++) { /* print specified */
|
||||
h = &hst[(di++) % hst_lnt]; /* entry pointer */
|
||||
if (h->pc & HIST_PC) { /* instruction? */
|
||||
fprintf (st, "%06X %08X %08X ", h->pc & VAMASK32, h->r1, h->opnd);
|
||||
sim_eval[0] = op = (h->ir1 >> 8) & 0xFF;
|
||||
sim_eval[1] = h->ir1 & 0xFF;
|
||||
sim_eval[2] = (h->ir2 >> 8) & 0xFF;
|
||||
sim_eval[3] = h->ir2 & 0xFF;
|
||||
sim_eval[4] = (h->ir3 >> 8) & 0xFF;
|
||||
sim_eval[5] = h->ir3 & 0xFF;
|
||||
if (OP_TYPE (op) >= OP_RX) fprintf (st, "%06X ", h->ea);
|
||||
else fprintf (st, " ");
|
||||
if ((fprint_sym (st, h->pc & VAMASK32, sim_eval, &cpu_unit, SWMASK ('M'))) > 0)
|
||||
fprintf (st, "(undefined) %04X", h->ir1);
|
||||
fputc ('\n', st); /* end line */
|
||||
} /* end if instruction */
|
||||
} /* end for */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
The author gratefully acknowledges the help of Carl Friend and Al Kossow,
|
||||
who provided key documents about the Interdata product line.
|
||||
|
||||
22-Sep-03 RMS Added additional instruction decode types
|
||||
21-Jun-03 RMS Changed subroutine argument for ARM compiler conflict
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
28-Feb-03 RMS Changed magtape device default to 0x85
|
||||
|
@ -188,9 +189,10 @@ struct BlockIO {
|
|||
#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_RXB 0x0005 /* all: reg-mem, rd BY */
|
||||
#define OP_RXH 0x0006 /* all: reg-mem, rd HW */
|
||||
#define OP_RXF 0x0007 /* 32b: reg-mem, rd FW */
|
||||
#define OP_RI2 0x0008 /* 32b: reg-imm 32b */
|
||||
#define OP_MASK 0x000F
|
||||
|
||||
#define OP_ID4 0x0010 /* 16b: ID4 */
|
||||
|
|
|
@ -69,7 +69,7 @@ sim> boot pt0
|
|||
|
||||
Breakpoint: PC: 00C2 (EXBR R8,R6)
|
||||
|
||||
sim> run 100
|
||||
sim> run 2d0
|
||||
|
||||
MODEL 8/16E PROCESSOR TEST PART 2 06-212R00
|
||||
CPU
|
||||
|
@ -96,7 +96,7 @@ Breakpoint, PC: 00C0 (8800)
|
|||
|
||||
sim> d 234a 0202 ; patch to use
|
||||
sim> d 234c a4a8 ; TTY as console
|
||||
sim> d 17a b1e4
|
||||
sim> d 17a b 1e4
|
||||
sim> run 100
|
||||
|
||||
SERIES SIXTEEN PROCESSOR TEST PART 1 06-242F01R00
|
||||
|
|
|
@ -259,6 +259,16 @@ control registers for the interrupt system.
|
|||
most recent PC change first
|
||||
WRU 8 interrupt character
|
||||
|
||||
The CPU can maintain a history of the most recently executed instructions.
|
||||
This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands:
|
||||
|
||||
SET CPU HISTORY clear history buffer
|
||||
SET CPU HISTORY=0 disable history
|
||||
SET CPU HISTORY=n enable history, display length = n
|
||||
SHOW CPU HISTORY print CPU history
|
||||
|
||||
The maximum length for the history is 65536 entries.
|
||||
|
||||
2.3 Selector Channel (SELCH)
|
||||
|
||||
An Interdata system can have 1 to 4 selector channels (SELCH0, SELCH1,
|
||||
|
|
|
@ -276,6 +276,7 @@ return 0;
|
|||
t_stat fd_svc (UNIT *uptr)
|
||||
{
|
||||
uint32 i, u, tk, sc, crc, fnc, da;
|
||||
uint8 *fbuf = uptr->filebuf;
|
||||
|
||||
u = uptr - fd_dev.units; /* get unit number */
|
||||
fnc = GET_FNC (uptr->FNC); /* get function */
|
||||
|
@ -296,9 +297,9 @@ case FNC_RD: /* read, buf empty */
|
|||
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 */
|
||||
fdxb[i] = fbuf[da + i];
|
||||
if (fbuf[FD_SIZE + uptr->LRN - 1]) { /* deleted? set err */
|
||||
fd_sta = fd_sta | STA_DEL;
|
||||
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);
|
||||
|
@ -313,9 +314,8 @@ case FNC_WR: case FNC_DEL: /* write block */
|
|||
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 */
|
||||
fbuf[da + i] = fdxb[i]; /* then dir */
|
||||
fbuf[FD_SIZE + uptr->LRN - 1] = ((fnc == FNC_DEL)? 1: 0);
|
||||
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);
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
tt console
|
||||
|
||||
29-Dec-03 RMS Added support for console backpressure
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
11-Jan-03 RMS Added TTP support
|
||||
22-Dec-02 RMS Added break support
|
||||
|
@ -192,16 +193,18 @@ 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 */
|
||||
if ((uptr->flags & UNIT_8B) || /* KSR or 7b? */
|
||||
((ch != 0) && (ch != 0x7F))) { /* supr NULL, DEL */
|
||||
if ((r = sim_putchar_s (ch)) != SCPE_OK) { /* output; error? */
|
||||
sim_activate (uptr, uptr->wait); /* try again */
|
||||
return ((r == SCPE_STALL)? SCPE_OK: r); } }
|
||||
if (!tt_rd) { /* write mode? */
|
||||
tt_sta = tt_sta & ~STA_BSY; /* clear busy */
|
||||
if (tt_arm) SET_INT (v_TT); } /* if armed, intr */
|
||||
uptr->pos = uptr->pos + 1; /* incr count */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* id_ttp.c: Interdata PASLA console interface
|
||||
|
||||
Copyright (c) 2000-2003, Robert M. Supnik
|
||||
Copyright (c) 2000-2004, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -25,6 +25,7 @@
|
|||
|
||||
ttp console (on PAS)
|
||||
|
||||
29-Dec-03 RMS Added support for console backpressure
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
*/
|
||||
|
||||
|
@ -195,16 +196,18 @@ 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 */
|
||||
if ((uptr->flags & UNIT_8B) || /* UC or 7b? */
|
||||
((c != 0) && (c != 0x7F))){ /* supr NULL, DEL */
|
||||
if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */
|
||||
sim_activate (uptr, uptr->wait); /* try again */
|
||||
return ((r == SCPE_STALL)? SCPE_OK: r); } }
|
||||
ttp_sta = ttp_sta & ~STA_BSY; /* not busy */
|
||||
if (ttp_tarm) SET_INT (v_TTP + 1); /* set intr */
|
||||
uptr->pos = uptr->pos + 1; /* incr count */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
|
3715
NOVA/eclipse_cpu.c
|
@ -23,6 +23,7 @@
|
|||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
22-Nov-03 CEO Added support for PIT device
|
||||
19-Jan-03 RMS Changed CMASK to CDMASK for Apple Dev kit conflict
|
||||
03-Oct-02 RMS Added device information structure
|
||||
22-Dec-00 RMS Added Bruce Ray's second terminal support
|
||||
|
@ -174,6 +175,7 @@
|
|||
#define DEV_ADCV 030 /* A/D converter */
|
||||
#define DEV_DKP 033 /* disk pack */
|
||||
#define DEV_CAS 034 /* cassette */
|
||||
#define DEV_PIT 043 /* programmable interval timer */
|
||||
#define DEV_TTI1 050 /* second console input */
|
||||
#define DEV_TTO1 051 /* second console output */
|
||||
#define DEV_CPU 077 /* CPU control */
|
||||
|
@ -211,6 +213,7 @@ typedef struct nova_dib DIB;
|
|||
Priority (for INTA) runs from low numbers to high
|
||||
*/
|
||||
|
||||
#define INT_V_PIT 2 /* PIT */
|
||||
#define INT_V_DKP 3 /* moving head disk */
|
||||
#define INT_V_DSK 4 /* fixed head disk */
|
||||
#define INT_V_MTA 5 /* magnetic tape */
|
||||
|
@ -227,6 +230,7 @@ typedef struct nova_dib DIB;
|
|||
#define INT_V_NO_ION_PENDING 16 /* ion delay */
|
||||
#define INT_V_ION 17 /* interrupts on */
|
||||
|
||||
#define INT_PIT (1 << INT_V_PIT)
|
||||
#define INT_DKP (1 << INT_V_DKP)
|
||||
#define INT_DSK (1 << INT_V_DSK)
|
||||
#define INT_MTA (1 << INT_V_MTA)
|
||||
|
@ -247,6 +251,7 @@ typedef struct nova_dib DIB;
|
|||
|
||||
/* PI disable bits */
|
||||
|
||||
#define PI_PIT 0001000
|
||||
#define PI_DKP 0000400
|
||||
#define PI_DSK 0000100
|
||||
#define PI_MTA 0000040
|
||||
|
|
|
@ -25,6 +25,9 @@
|
|||
|
||||
dkp moving head disk
|
||||
|
||||
28-Nov-03 CEO Boot from DP now puts device address in SR
|
||||
24-Nov-03 CEO Added support for disk sizing on 6099/6103
|
||||
19-Nov-03 CEO Corrected major DMA Mapping bug
|
||||
25-Apr-03 RMS Revised autosizing
|
||||
08-Oct-02 RMS Added DIB
|
||||
06-Jan-02 RMS Revised enable/disable support
|
||||
|
@ -278,11 +281,13 @@ extern UNIT cpu_unit;
|
|||
extern int32 int_req, dev_busy, dev_done, dev_disable;
|
||||
|
||||
int32 dkp_ma = 0; /* memory address */
|
||||
int32 dkp_map = 0; /* DCH map 0=A 3=B */
|
||||
int32 dkp_ussc = 0; /* unit/sf/sc/cnt */
|
||||
int32 dkp_fccy = 0; /* flags/cylinder */
|
||||
int32 dkp_sta = 0; /* status register */
|
||||
int32 dkp_swait = 100; /* seek latency */
|
||||
int32 dkp_rwait = 100; /* rotate latency */
|
||||
int32 dkp_diagmode = 0; /* diagnostic mode */
|
||||
|
||||
DEVICE dkp_dev;
|
||||
int32 dkp (int32 pulse, int32 code, int32 AC);
|
||||
|
@ -322,6 +327,8 @@ REG dkp_reg[] = {
|
|||
{ FLDATA (BUSY, dev_busy, INT_V_DKP) },
|
||||
{ FLDATA (DONE, dev_done, INT_V_DKP) },
|
||||
{ FLDATA (DISABLE, dev_disable, INT_V_DKP) },
|
||||
{ FLDATA (DIAG, dkp_diagmode, 0) },
|
||||
{ ORDATA (MAP, dkp_map, 2) },
|
||||
{ DRDATA (STIME, dkp_swait, 24), PV_LEFT },
|
||||
{ DRDATA (RTIME, dkp_rwait, 24), PV_LEFT },
|
||||
{ URDATA (CAPAC, dkp_unit[0].capac, 10, T_ADDR_W, 0,
|
||||
|
@ -452,22 +459,32 @@ case ioDIA: /* DIA */
|
|||
rval = dkp_sta;
|
||||
break;
|
||||
case ioDOA: /* DOA */
|
||||
if (AC & 0100000) /* clear rw done? */
|
||||
dkp_sta = dkp_sta & ~(STA_CYL|STA_XCY|STA_UNS|STA_CRC);
|
||||
if ((dev_busy & INT_DKP) == 0) {
|
||||
dkp_fccy = AC; /* save cmd, cyl */
|
||||
dkp_sta = dkp_sta & ~(AC & FCCY_FLAGS); }
|
||||
if ((dkp_sta & STA_DFLGS) == 0) /* done flags = 0? */
|
||||
dev_done = dev_done & ~INT_DKP; /* clear intr */
|
||||
break;
|
||||
case ioDIB: /* DIB */
|
||||
rval = dkp_ma; /* return buf addr */
|
||||
break;
|
||||
case ioDOB: /* DOB */
|
||||
if ((dev_busy & INT_DKP) == 0) dkp_ma =
|
||||
AC & (drv_tab[dtype].newf? DMASK: AMASK);
|
||||
if ((dev_busy & INT_DKP) == 0) {
|
||||
dkp_ma = AC & (drv_tab[dtype].newf? DMASK: AMASK);
|
||||
if (AC & 0100000) dkp_map = 3; /* high bit is map */
|
||||
else dkp_map = 0;
|
||||
}
|
||||
break;
|
||||
case ioDIC: /* DIC */
|
||||
rval = dkp_ussc; /* return unit, sect */
|
||||
break;
|
||||
case ioDOC: /* DOC */
|
||||
if ((dev_busy & INT_DKP) == 0) dkp_ussc = AC; /* save unit, sect */
|
||||
if (((dtype == TYPE_6099) || /* for 6099 and 6103 */
|
||||
(dtype == TYPE_6103)) && /* if data<0> set, */
|
||||
AC & 010000) dkp_diagmode = 1; /* set diagnostic mode */
|
||||
break; } /* end switch code */
|
||||
|
||||
/* IOT, continued */
|
||||
|
@ -478,7 +495,14 @@ case iopS: /* start */
|
|||
dev_busy = dev_busy | INT_DKP; /* set busy */
|
||||
dev_done = dev_done & ~INT_DKP; /* clear done */
|
||||
int_req = int_req & ~INT_DKP; /* clear int */
|
||||
if (dkp_diagmode) { /* in diagnostic mode? */
|
||||
dkp_diagmode = 0; /* reset it */
|
||||
if (dtype == TYPE_6099) dkp_ussc = 010002; /* return size bits */
|
||||
if (dtype == TYPE_6103) dkp_ussc = 010003; /* for certain types */
|
||||
}
|
||||
else { /* normal mode ... */
|
||||
if (dkp_go ()) break; /* new cmd, error? */
|
||||
}
|
||||
dev_busy = dev_busy & ~INT_DKP; /* clear busy */
|
||||
dev_done = dev_done | INT_DKP; /* set done */
|
||||
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
|
||||
|
@ -558,6 +582,13 @@ static uint16 tbuf[DKP_NUMWD]; /* transfer buffer */
|
|||
|
||||
rval = SCPE_OK;
|
||||
dtype = GET_DTYPE (uptr->flags); /* get drive type */
|
||||
if (dkp_diagmode) { /* diagnostic mode? */
|
||||
dkp_sta = (dkp_sta | STA_DONE); /* Set error bit only */
|
||||
dev_busy = dev_busy & ~INT_DKP; /* clear busy */
|
||||
dev_done = dev_done | INT_DKP; /* set done */
|
||||
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
|
||||
return SCPE_OK; /* do not do function */
|
||||
}
|
||||
if (uptr->FUNC == FCCY_SEEK) { /* seek? */
|
||||
if (uptr->CYL >= drv_tab[dtype].cyl) /* bad cylinder? */
|
||||
dkp_sta = dkp_sta | STA_ERR | STA_CYL;
|
||||
|
@ -597,14 +628,14 @@ else { sc = 16 - GET_COUNT (dkp_ussc); /* get sector count */
|
|||
for ( ; awc < DKP_NUMWD; awc++) tbuf[awc] = 0;
|
||||
if (err = ferror (uptr->fileref)) break;
|
||||
for (dx = 0; dx < DKP_NUMWD; dx++) { /* loop thru buffer */
|
||||
pa = MapAddr (0, dkp_ma);
|
||||
pa = MapAddr (dkp_map, (dkp_ma & AMASK));
|
||||
if (MEM_ADDR_OK (pa)) M[pa] = tbuf[dx];
|
||||
dkp_ma = (dkp_ma + 1) & AMASK; } } }
|
||||
|
||||
if (uptr->FUNC == FCCY_WRITE) { /* write? */
|
||||
for (sx = 0; sx < sc; sx++) { /* loop thru sectors */
|
||||
for (dx = 0; dx < DKP_NUMWD; dx++) { /* loop into buffer */
|
||||
pa = MapAddr (0, dkp_ma);
|
||||
pa = MapAddr (dkp_map, (dkp_ma & AMASK));
|
||||
tbuf[dx] = M[pa];
|
||||
dkp_ma = (dkp_ma + 1) & AMASK; }
|
||||
fxwrite (tbuf, sizeof(int16), DKP_NUMWD, uptr->fileref);
|
||||
|
@ -641,6 +672,8 @@ dev_busy = dev_busy & ~INT_DKP; /* clear busy */
|
|||
dev_done = dev_done & ~INT_DKP; /* clear done, int */
|
||||
int_req = int_req & ~INT_DKP;
|
||||
dkp_fccy = dkp_ussc = dkp_ma = dkp_sta = 0; /* clear registers */
|
||||
dkp_diagmode = 0; /* clear diagnostic mode */
|
||||
dkp_map = 0;
|
||||
for (u = 0; u < DKP_NUMDR; u++) { /* loop thru units */
|
||||
uptr = dkp_dev.units + u;
|
||||
sim_cancel (uptr); /* cancel activity */
|
||||
|
@ -685,33 +718,33 @@ return SCPE_OK;
|
|||
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int))
|
||||
|
||||
static const int32 boot_rom[] = {
|
||||
060233, /* NIOC 0,DKP ; clear disk */
|
||||
020420, /* LDA 0,USSC ; unit, sfc, sec, cnt */
|
||||
063033, /* DOC 0,DKP ; select disk */
|
||||
020417, /* LDA 0,SEKCMD ; command, cylinder */
|
||||
061333, /* DOAP 0,DKP ; start seek */
|
||||
024415, /* LDA 1,SEKDN */
|
||||
060433, /* DIA 0,DKP ; get status */
|
||||
0060233, /* NIOC 0,DKP ; clear disk */
|
||||
0020420, /* LDA 0,USSC ; unit, sfc, sec, cnt */
|
||||
0063033, /* DOC 0,DKP ; select disk */
|
||||
0020417, /* LDA 0,SEKCMD ; command, cylinder */
|
||||
0061333, /* DOAP 0,DKP ; start seek */
|
||||
0024415, /* LDA 1,SEKDN */
|
||||
0060433, /* DIA 0,DKP ; get status */
|
||||
0123415, /* AND# 1,0,SZR ; skip if done */
|
||||
000776, /* JMP .-2 */
|
||||
0000776, /* JMP .-2 */
|
||||
0102400, /* SUB 0,0 ; mem addr = 0 */
|
||||
062033, /* DOB 0,DKP */
|
||||
020411, /* LDA 0,REDCMD ; command, cylinder */
|
||||
061133, /* DOAS 0,DKP ; start read */
|
||||
060433, /* DIA 0, DKP ; get status */
|
||||
0062033, /* DOB 0,DKP */
|
||||
0020411, /* LDA 0,REDCMD ; command, cylinder */
|
||||
0061133, /* DOAS 0,DKP ; start read */
|
||||
0060433, /* DIA 0, DKP ; get status */
|
||||
0101113, /* MOVL# 0,0,SNC ; skip if done */
|
||||
000776, /* JMP .-2 */
|
||||
000377, /* JMP 377 */
|
||||
000016, /* USSC: 0.B1+0.B7+0.B11+16 */
|
||||
0000776, /* JMP .-2 */
|
||||
0000377, /* JMP 377 */
|
||||
0000016, /* USSC: 0.B1+0.B7+0.B11+16 */
|
||||
0175000, /* SEKCMD: 175000 */
|
||||
074000, /* SEKDN: 074000 */
|
||||
0074000, /* SEKDN: 074000 */
|
||||
0174000 /* REDCMD: 174000 */
|
||||
};
|
||||
|
||||
t_stat dkp_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
int32 i, dtype;
|
||||
extern int32 saved_PC;
|
||||
extern int32 saved_PC, SR;
|
||||
|
||||
for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i];
|
||||
unitno = unitno & USSC_M_UNIT;
|
||||
|
@ -719,5 +752,6 @@ dtype = GET_DTYPE (dkp_unit[unitno].flags);
|
|||
M[BOOT_UNIT] = M[BOOT_UNIT] | (unitno << USSC_V_UNIT);
|
||||
if (drv_tab[dtype].newf) M[BOOT_SEEK] = 0176000;
|
||||
saved_PC = BOOT_START;
|
||||
SR = 0100000 + DEV_DKP;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
|
|
@ -485,6 +485,8 @@ The moving head disk controller implements these registers:
|
|||
DONE 1 device done flag
|
||||
DISABLE 1 interrupt disable flag
|
||||
INT 1 interrupt pending flag
|
||||
DIAG 1 diagnostic mode flag
|
||||
MAP 2 map select
|
||||
STIME 24 seek time, per cylinder
|
||||
RTIME 24 rotational delay
|
||||
|
||||
|
|
|
@ -205,6 +205,7 @@ return rval;
|
|||
t_stat dsk_svc (UNIT *uptr)
|
||||
{
|
||||
int32 i, da, pa;
|
||||
int16 *fbuf = uptr->filebuf;
|
||||
|
||||
dev_busy = dev_busy & ~INT_DSK; /* clear busy */
|
||||
dev_done = dev_done | INT_DSK; /* set done */
|
||||
|
@ -218,13 +219,12 @@ da = dsk_da * DSK_NUMWD; /* calc disk addr */
|
|||
if (uptr->FUNC == iopS) { /* read? */
|
||||
for (i = 0; i < DSK_NUMWD; i++) { /* copy sector */
|
||||
pa = MapAddr (0, (dsk_ma + i) & AMASK); /* map address */
|
||||
if (MEM_ADDR_OK (pa)) M[pa] =
|
||||
*(((int16 *) uptr->filebuf) + da + i); }
|
||||
if (MEM_ADDR_OK (pa)) M[pa] = fbuf[da + i]; }
|
||||
dsk_ma = (dsk_ma + DSK_NUMWD) & AMASK; }
|
||||
if (uptr->FUNC == iopP) { /* write? */
|
||||
for (i = 0; i < DSK_NUMWD; i++) { /* copy sector */
|
||||
pa = MapAddr (0, (dsk_ma + i) & AMASK); /* map address */
|
||||
*(((int16 *) uptr->filebuf) + da + i) = M[pa]; }
|
||||
fbuf[da + i] = M[pa]; }
|
||||
if (((uint32) (da + i)) >= uptr->hwmark) /* past end? */
|
||||
uptr->hwmark = da + i + 1; /* upd hwmark */
|
||||
dsk_ma = (dsk_ma + DSK_NUMWD + 3) & AMASK; }
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
mta magnetic tape
|
||||
|
||||
22-Nov-03 CEO DIB returns # records skipped after space fwd
|
||||
22-Nov-03 CEO Removed cancel of tape events in IORST
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
28-Mar-03 RMS Added multiformat support
|
||||
28-Feb-03 RMS Revised for magtape library
|
||||
|
@ -397,6 +399,7 @@ case CU_SPACEF: /* space forward */
|
|||
}
|
||||
while (mta_wc != 0);
|
||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY);
|
||||
mta_ma = mta_wc; /* Word count = # records */
|
||||
break;
|
||||
|
||||
case CU_SPACER: /* space reverse */
|
||||
|
@ -408,6 +411,7 @@ case CU_SPACER: /* space reverse */
|
|||
}
|
||||
while (mta_wc != 0);
|
||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY);
|
||||
mta_ma = mta_wc; /* Word count = # records */
|
||||
break;
|
||||
|
||||
default: /* reserved */
|
||||
|
@ -503,8 +507,15 @@ dev_done = dev_done & ~INT_MTA; /* clear done, int */
|
|||
int_req = int_req & ~INT_MTA;
|
||||
mta_cu = mta_wc = mta_ma = mta_sta = 0; /* clear registers */
|
||||
mta_ep = 0;
|
||||
|
||||
/* AOS Installer does an IORST after a tape rewind command but before it can
|
||||
be serviced, yet expects the tape to have been rewound */
|
||||
|
||||
for (u = 0; u < MTA_NUMDR; u++) { /* loop thru units */
|
||||
uptr = mta_dev.units + u;
|
||||
if (sim_is_active (uptr) && /* active and */
|
||||
(uptr->flags & STA_REW)) /* rewinding? */
|
||||
sim_tape_rewind (uptr); /* update tape */
|
||||
sim_tape_reset (uptr); /* clear pos flag */
|
||||
sim_cancel (uptr); /* cancel activity */
|
||||
if (uptr->flags & UNIT_ATT) uptr->USTAT = STA_RDY |
|
||||
|
@ -556,34 +567,35 @@ return SCPE_OK;
|
|||
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int))
|
||||
|
||||
static const int32 boot_rom[] = {
|
||||
060222, /* NIOC 0,MTA ; clear disk */
|
||||
020417, /* LDA 0,UNIT ; unit */
|
||||
024417, /* LDA 1,REWIND ; cmd */
|
||||
0060222, /* NIOC 0,MTA ; clear disk */
|
||||
0020417, /* LDA 0,UNIT ; unit */
|
||||
0024417, /* LDA 1,REWIND ; cmd */
|
||||
0107000, /* ADD 0,1 ; cmd + unit */
|
||||
065122, /* DOAS 1,MTA ; start rewind */
|
||||
070422, /* DIA 2,MTA ; get status */
|
||||
0065122, /* DOAS 1,MTA ; start rewind */
|
||||
0070422, /* DIA 2,MTA ; get status */
|
||||
0151213, /* MOVR# 2,2,SNC ; skip if done */
|
||||
000776, /* JMP .-2 */
|
||||
0000776, /* JMP .-2 */
|
||||
0126400, /* SUB 1,1 ; ma, wc = 0 */
|
||||
066022, /* DOB 1,MTA */
|
||||
067022, /* DOC 1,MTA */
|
||||
061122, /* DOAS 0,MTA ; start read */
|
||||
070422, /* DIA 2,MTA ; get status */
|
||||
0066022, /* DOB 1,MTA */
|
||||
0067022, /* DOC 1,MTA */
|
||||
0061122, /* DOAS 0,MTA ; start read */
|
||||
0070422, /* DIA 2,MTA ; get status */
|
||||
0151213, /* MOVR# 2,2,SNC ; skip if done */
|
||||
000776, /* JMP .-2 */
|
||||
000377, /* JMP 377 */
|
||||
000000, /* UNIT: */
|
||||
000010 /* REWIND: 10 */
|
||||
0000776, /* JMP .-2 */
|
||||
0000377, /* JMP 377 */
|
||||
0000000, /* UNIT: */
|
||||
0000010 /* REWIND: 10 */
|
||||
};
|
||||
|
||||
t_stat mta_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
int32 i;
|
||||
extern int32 saved_PC;
|
||||
extern int32 saved_PC, SR;
|
||||
|
||||
sim_tape_rewind (&mta_unit[unitno]);
|
||||
for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i];
|
||||
M[BOOT_UNIT] = (unitno & CU_M_UNIT) << CU_V_UNIT;
|
||||
saved_PC = BOOT_START;
|
||||
SR = 0100000 + DEV_MTA;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
|
106
NOVA/nova_sys.c
|
@ -23,6 +23,7 @@
|
|||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
24-Nov-03 CEO Added symbolic support for LEF instruction
|
||||
17-Sep-01 RMS Removed multiconsole support
|
||||
31-May-01 RMS Added multiconsole support
|
||||
14-Mar-01 RMS Revised load/dump interface (again)
|
||||
|
@ -43,16 +44,23 @@ extern DEVICE cpu_dev;
|
|||
extern UNIT cpu_unit;
|
||||
#if defined (ECLIPSE)
|
||||
extern DEVICE map_dev;
|
||||
extern DEVICE fpu_dev;
|
||||
extern DEVICE pit_dev;
|
||||
extern int32 Usermap;
|
||||
extern int32 MapStat;
|
||||
#endif
|
||||
extern DEVICE ptr_dev, ptp_dev;
|
||||
extern DEVICE ptr_dev;
|
||||
extern DEVICE ptp_dev;
|
||||
extern DEVICE plt_dev;
|
||||
extern DEVICE tti_dev, tto_dev;
|
||||
extern DEVICE tti1_dev, tto1_dev;
|
||||
extern DEVICE clk_dev, lpt_dev;
|
||||
extern DEVICE dkp_dev, dsk_dev;
|
||||
extern DEVICE tti_dev;
|
||||
extern DEVICE tto_dev;
|
||||
extern DEVICE tti1_dev;
|
||||
extern DEVICE tto1_dev;
|
||||
extern DEVICE clk_dev;
|
||||
extern DEVICE lpt_dev;
|
||||
extern DEVICE dkp_dev;
|
||||
extern DEVICE dsk_dev;
|
||||
extern DEVICE mta_dev;
|
||||
extern UNIT tti_unit, tto_unit;
|
||||
extern UNIT tti1_unit, tto1_unit;
|
||||
extern REG cpu_reg[];
|
||||
extern uint16 M[];
|
||||
extern int32 saved_PC;
|
||||
|
@ -81,13 +89,21 @@ DEVICE *sim_devices[] = {
|
|||
&cpu_dev,
|
||||
#if defined (ECLIPSE)
|
||||
&map_dev,
|
||||
&fpu_dev,
|
||||
&pit_dev,
|
||||
#endif
|
||||
&ptr_dev, &ptp_dev,
|
||||
&tti_dev, &tto_dev,
|
||||
&tti1_dev, &tto1_dev,
|
||||
&clk_dev, &plt_dev,
|
||||
&lpt_dev, &dsk_dev,
|
||||
&dkp_dev, &mta_dev,
|
||||
&ptr_dev,
|
||||
&ptp_dev,
|
||||
&tti_dev,
|
||||
&tto_dev,
|
||||
&tti1_dev,
|
||||
&tto1_dev,
|
||||
&clk_dev,
|
||||
&plt_dev,
|
||||
&lpt_dev,
|
||||
&dsk_dev,
|
||||
&dkp_dev,
|
||||
&mta_dev,
|
||||
NULL };
|
||||
|
||||
const char *sim_stop_messages[] = {
|
||||
|
@ -256,7 +272,7 @@ static const char *opcode[] = {
|
|||
"BTO", "BTZ", "SBZ", "SZBO",
|
||||
"LOB", "LRB", "COB", "LDB",
|
||||
"STB", "PSH", "POP",
|
||||
"LMP", "SYSC",
|
||||
"LMP", "SYC",
|
||||
"PSHR", "POPB", "BAM", "POPJ",
|
||||
"RTN", "BLM", "DIVX",
|
||||
"MUL", "MULS", "DIV", "DIVS",
|
||||
|
@ -366,6 +382,9 @@ static const char *opcode[] = {
|
|||
"DIC", "DICS", "DICC", "DICP",
|
||||
"DOC", "DOCS", "DOCC", "DOCP",
|
||||
"SKPBN", "SKPBZ", "SKPDN", "SKPDZ",
|
||||
#if defined (ECLIPSE)
|
||||
"LEF", "LEF", "LEF", "LEF",
|
||||
#endif
|
||||
NULL };
|
||||
|
||||
static const opc_val[] = {
|
||||
|
@ -379,7 +398,7 @@ static const opc_val[] = {
|
|||
0102010+I_2AC, 0102110+I_2AC, 0102210+I_2AC, 0102310+I_2AC,
|
||||
0102410+I_2AC, 0102510+I_2AC, 0102610+I_2AC, 0102710+I_2AC,
|
||||
0103010+I_2AC, 0103110+I_2AC, 0103210+I_2AC,
|
||||
0113410+I_NPN, 0103510+I_RSI,
|
||||
0113410+I_NPN, 0103510+I_2AC,
|
||||
0103710+I_NPN, 0107710+I_NPN, 0113710+I_NPN, 0117710+I_NPN,
|
||||
0127710+I_NPN, 0133710+I_NPN, 0137710+I_NPN,
|
||||
0143710+I_NPN, 0147710+I_NPN, 0153710+I_NPN, 0157710+I_NPN,
|
||||
|
@ -489,6 +508,9 @@ static const opc_val[] = {
|
|||
0062400+I_RD, 0062500+I_RD, 0062600+I_RD, 0062700+I_RD,
|
||||
0063000+I_RD, 0063100+I_RD, 0063200+I_RD, 0063300+I_RD,
|
||||
0063400+I_D, 0063500+I_D, 0063600+I_D, 0063700+I_D,
|
||||
#if defined (ECLIPSE)
|
||||
0064000+I_D, 0070000+I_D, 0074000+I_D, 0076000+I_D,
|
||||
#endif
|
||||
-1 };
|
||||
|
||||
static const char *skip[] = {
|
||||
|
@ -579,8 +601,8 @@ int32 ind, mode, disp, dev;
|
|||
int32 byac, extind, extdisp, xop;
|
||||
|
||||
cflag = (uptr == NULL) || (uptr == &cpu_unit);
|
||||
c1 = (val[0] >> 8) & 0177;
|
||||
c2 = val[0] & 0177;
|
||||
c1 = ((int32) val[0] >> 8) & 0177;
|
||||
c2 = (int32) val[0] & 0177;
|
||||
if (sw & SWMASK ('A')) { /* ASCII? */
|
||||
fprintf (of, (c2 < 040)? "<%03o>": "%c", c2);
|
||||
return SCPE_OK; }
|
||||
|
@ -592,7 +614,7 @@ if (!(sw & SWMASK ('M'))) return SCPE_ARG; /* mnemonic? */
|
|||
|
||||
/* Instruction decode */
|
||||
|
||||
inst = val[0];
|
||||
inst = (int32) val[0];
|
||||
for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
|
||||
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
|
||||
if ((opc_val[i] & 0177777) == (inst & masks[j])) { /* match? */
|
||||
|
@ -605,8 +627,8 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
|
|||
dev = I_GETDEV (inst); /* IOT fields */
|
||||
byac = I_GETPULSE (inst); /* byte fields */
|
||||
xop = I_GETXOP (inst); /* XOP fields */
|
||||
extind = val[1] & A_IND; /* extended fields */
|
||||
extdisp = val[1] & AMASK;
|
||||
extind = (int32) val[1] & A_IND; /* extended fields */
|
||||
extdisp = (int32) val[1] & AMASK;
|
||||
for (dv = 0; (dev_val[dv] >= 0) && (dev_val[dv] != dev); dv++) ;
|
||||
|
||||
switch (j) { /* switch on class */
|
||||
|
@ -617,6 +639,13 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
|
|||
fprintf (of, "%s %-o", opcode[i], dst);
|
||||
break;
|
||||
case I_V_D: /* dev only */
|
||||
#if defined (ECLIPSE)
|
||||
if (Usermap && (MapStat & 0100)) { /* the evil LEF mode */
|
||||
fprintf (of, "LEF %-o,", dst);
|
||||
fprint_addr (of, addr, ind, mode, disp, FALSE, cflag);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
if (dev_val[dv] >= 0)
|
||||
fprintf (of, "%s %s", opcode[i], device[dv]);
|
||||
else fprintf (of, "%s %-o", opcode[i], dev);
|
||||
|
@ -671,7 +700,10 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
|
|||
return -1;
|
||||
case I_V_XP: /* XOP */
|
||||
fprintf (of, "%s %-o,%-o,%-o", opcode[i], src, dst, xop);
|
||||
break; } /* end case */
|
||||
break; /* end case */
|
||||
default:
|
||||
fprintf (of, "??? [%-o]", inst);
|
||||
break; }
|
||||
return SCPE_OK; } /* end if */
|
||||
} /* end for */
|
||||
return SCPE_ARG;
|
||||
|
@ -726,12 +758,12 @@ else if (*cptr == '-') { /* - sign? */
|
|||
cptr++; }
|
||||
if (*cptr != 0) { /* number? */
|
||||
cptr = get_glyph (cptr, gbuf, ','); /* get glyph */
|
||||
d = get_uint (gbuf, 8, AMASK, &r);
|
||||
d = (int32) get_uint (gbuf, 8, AMASK, &r);
|
||||
if (r != SCPE_OK) return NULL;
|
||||
pflag = pflag | A_NUM; }
|
||||
if (*cptr != 0) { /* index? */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get glyph */
|
||||
x = get_uint (gbuf, 8, I_M_DST, &r);
|
||||
x = (int32) get_uint (gbuf, 8, I_M_DST, &r);
|
||||
if ((r != SCPE_OK) || (x < 2)) return NULL;
|
||||
pflag = pflag | A_NX; }
|
||||
|
||||
|
@ -786,10 +818,10 @@ char gbuf[CBUFSIZE];
|
|||
t_stat r;
|
||||
|
||||
cptr = get_glyph (cptr, gbuf, ','); /* get register */
|
||||
val[0] = get_uint (gbuf, 8, I_M_SRC, &r);
|
||||
val[0] = (int32) get_uint (gbuf, 8, I_M_SRC, &r);
|
||||
if (r != SCPE_OK) return NULL;
|
||||
cptr = get_glyph (cptr, gbuf, term); /* get register */
|
||||
val[1] = get_uint (gbuf, 8, I_M_DST, &r);
|
||||
val[1] = (int32) get_uint (gbuf, 8, I_M_DST, &r);
|
||||
if (r != SCPE_OK) return NULL;
|
||||
return cptr;
|
||||
}
|
||||
|
@ -837,13 +869,13 @@ case I_V_NPN: /* no operand */
|
|||
break;
|
||||
case I_V_R: /* IOT reg */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get register */
|
||||
d = get_uint (gbuf, 8, I_M_DST, &r);
|
||||
d = (int32) get_uint (gbuf, 8, I_M_DST, &r);
|
||||
if (r != SCPE_OK) return SCPE_ARG;
|
||||
val[0] = val[0] | (d << I_V_DST); /* put in place */
|
||||
break;
|
||||
case I_V_RD: /* IOT reg,dev */
|
||||
cptr = get_glyph (cptr, gbuf, ','); /* get register */
|
||||
d = get_uint (gbuf, 8, I_M_DST, &r);
|
||||
d = (int32) get_uint (gbuf, 8, I_M_DST, &r);
|
||||
if (r != SCPE_OK) return SCPE_ARG;
|
||||
val[0] = val[0] | (d << I_V_DST); /* put in place */
|
||||
case I_V_D: /* IOT dev */
|
||||
|
@ -852,13 +884,13 @@ case I_V_D: /* IOT dev */
|
|||
(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);
|
||||
d = (int32) get_uint (gbuf, 8, I_M_DEV, &r);
|
||||
if (r != SCPE_OK) return SCPE_ARG;
|
||||
val[0] = val[0] | (d << I_V_DEV); }
|
||||
break;
|
||||
case I_V_RM: /* reg, addr */
|
||||
cptr = get_glyph (cptr, gbuf, ','); /* get register */
|
||||
d = get_uint (gbuf, 8, I_M_DST, &r);
|
||||
d = (int32) get_uint (gbuf, 8, I_M_DST, &r);
|
||||
if (r != SCPE_OK) return SCPE_ARG;
|
||||
val[0] = val[0] | (d << I_V_DST); /* put in place */
|
||||
case I_V_M: /* addr */
|
||||
|
@ -889,33 +921,33 @@ case I_V_2AC: /* reg, reg */
|
|||
break;
|
||||
case I_V_RSI: /* reg, short imm */
|
||||
cptr = get_glyph (cptr, gbuf, ','); /* get immediate */
|
||||
d = get_uint (gbuf, 8, I_M_SRC + 1, &r);
|
||||
d = (int32) get_uint (gbuf, 8, I_M_SRC + 1, &r);
|
||||
if ((d == 0) || (r != SCPE_OK)) return SCPE_ARG;
|
||||
val[0] = val[0] | ((d - 1) << I_V_SRC); /* put in place */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get register */
|
||||
d = get_uint (gbuf, 8, I_M_DST, &r);
|
||||
d = (int32) get_uint (gbuf, 8, I_M_DST, &r);
|
||||
if (r != SCPE_OK) return SCPE_ARG;
|
||||
val[0] = val[0] | (d << I_V_DST); /* put in place */
|
||||
break;
|
||||
case I_V_RLI: /* reg, long imm */
|
||||
cptr = get_glyph (cptr, gbuf, ','); /* get immediate */
|
||||
val[1] = get_uint (gbuf, 8, DMASK, &r);
|
||||
val[1] = (int32) get_uint (gbuf, 8, DMASK, &r);
|
||||
if (r != SCPE_OK) return SCPE_ARG;
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get register */
|
||||
d = get_uint (gbuf, 8, I_M_DST, &r);
|
||||
d = (int32) get_uint (gbuf, 8, I_M_DST, &r);
|
||||
if (r != SCPE_OK) return SCPE_ARG;
|
||||
val[0] = val[0] | (d << I_V_DST); /* put in place */
|
||||
rtn = -1;
|
||||
break;
|
||||
case I_V_LI: /* long imm */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get immediate */
|
||||
val[1] = get_uint (gbuf, 8, DMASK, &r);
|
||||
val[1] = (int32) get_uint (gbuf, 8, DMASK, &r);
|
||||
if (r != SCPE_OK) return SCPE_ARG;
|
||||
rtn = -1;
|
||||
break;
|
||||
case I_V_RLM: /* reg, long mem */
|
||||
cptr = get_glyph (cptr, gbuf, ','); /* get register */
|
||||
d = get_uint (gbuf, 8, I_M_DST, &r);
|
||||
d = (int32) get_uint (gbuf, 8, I_M_DST, &r);
|
||||
if (r != SCPE_OK) return SCPE_ARG;
|
||||
val[0] = val[0] | (d << I_V_DST); /* put in place */
|
||||
case I_V_LM: /* long mem */
|
||||
|
@ -927,7 +959,7 @@ case I_V_LM: /* long mem */
|
|||
break;
|
||||
case I_V_FRM: /* flt reg, long mem */
|
||||
cptr = get_glyph (cptr, gbuf, ','); /* get register */
|
||||
d = get_uint (gbuf, 8, I_M_DST, &r);
|
||||
d = (int32) get_uint (gbuf, 8, I_M_DST, &r);
|
||||
if (r != SCPE_OK) return SCPE_ARG;
|
||||
val[0] = val[0] | (d << I_V_DST); /* put in place */
|
||||
cptr = get_addr (cptr, addr, TRUE, cflag, amd);
|
||||
|
@ -948,7 +980,7 @@ case I_V_XP: /* XOP */
|
|||
if (cptr == NULL) return SCPE_ARG;
|
||||
val[0] = val[0] | (amd[0] << I_V_SRC) | (amd[1] << I_V_DST);
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get argument */
|
||||
d = get_uint (gbuf, 8, I_M_XOP, &r);
|
||||
d = (int32) get_uint (gbuf, 8, I_M_XOP, &r);
|
||||
if (r != SCPE_OK) return SCPE_ARG;
|
||||
val[0] = val[0] | (d << I_V_XOP);
|
||||
break; } /* end case */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* nova_tt.c: NOVA console terminal simulator
|
||||
|
||||
Copyright (c) 1993-2003, Robert M. Supnik
|
||||
Copyright (c) 1993-2004, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -26,6 +26,7 @@
|
|||
tti terminal input
|
||||
tto terminal output
|
||||
|
||||
29-Dec-03 RMS Added console backpressure support
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
05-Jan-02 RMS Fixed calling sequence for setmod
|
||||
03-Oct-02 RMS Added DIBs
|
||||
|
@ -188,14 +189,17 @@ return 0;
|
|||
|
||||
t_stat tto_svc (UNIT *uptr)
|
||||
{
|
||||
int32 c, temp;
|
||||
int32 c;
|
||||
t_stat r;
|
||||
|
||||
c = tto_unit.buf & 0177;
|
||||
if ((tto_unit.flags & UNIT_DASHER) && (c == 031)) c = '\b';
|
||||
if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */
|
||||
sim_activate (uptr, uptr->wait); /* try again */
|
||||
return ((r == SCPE_STALL)? SCPE_OK: r); } /* !stall? report */
|
||||
dev_busy = dev_busy & ~INT_TTO; /* clear busy */
|
||||
dev_done = dev_done | INT_TTO; /* set done */
|
||||
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
|
||||
c = tto_unit.buf & 0177;
|
||||
if ((tto_unit.flags & UNIT_DASHER) && (c == 031)) c = '\b';
|
||||
if ((temp = sim_putchar (c)) != SCPE_OK) return temp;
|
||||
tto_unit.pos = tto_unit.pos + 1;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
08-Dec-03 RMS Added support for parallel drum
|
||||
18-Oct-03 RMS Added DECtape off reel message
|
||||
22-Jul-03 RMS Updated for "hardware" RIM loader
|
||||
Revised to detect I/O wait hang
|
||||
05-Dec-02 RMS Added IOT skip support (required by drum)
|
||||
|
@ -36,6 +38,7 @@
|
|||
|
||||
Automatic multiply/divide Type 10
|
||||
Memory extension control Type 15
|
||||
Parallel drum Type 23
|
||||
Serial drum Type 24
|
||||
Line printer control Type 62
|
||||
Microtape (DECtape) control Type 550
|
||||
|
@ -51,6 +54,7 @@
|
|||
#define STOP_XCT 4 /* nested XCT's */
|
||||
#define STOP_IND 5 /* nested indirects */
|
||||
#define STOP_WAIT 6 /* IO wait hang */
|
||||
#define STOP_DTOFF 7 /* DECtape off reel */
|
||||
|
||||
/* Memory */
|
||||
|
||||
|
@ -92,6 +96,7 @@
|
|||
#define IOS_V_SQB 11 /* sequence break */
|
||||
#define IOS_V_PNT 2 /* print done */
|
||||
#define IOS_V_SPC 1 /* space done */
|
||||
#define IOS_V_DRP 0 /* parallel drum busy */
|
||||
|
||||
#define IOS_LPN (1 << IOS_V_LPN)
|
||||
#define IOS_PTR (1 << IOS_V_PTR)
|
||||
|
@ -102,6 +107,7 @@
|
|||
#define IOS_SQB (1 << IOS_V_SQB)
|
||||
#define IOS_PNT (1 << IOS_V_PNT)
|
||||
#define IOS_SPC (1 << IOS_V_SPC)
|
||||
#define IOS_DRP (1 << IOS_V_DRP)
|
||||
|
||||
/* Completion pulses */
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
To: Users
|
||||
From: Bob Supnik
|
||||
Subj: PDP-1 Simulator Usage
|
||||
Date: 15-Sep-2003
|
||||
Date: 15-Dec-2003
|
||||
|
||||
COPYRIGHT NOTICE
|
||||
|
||||
|
@ -65,6 +65,7 @@ PTR,PTP integral paper tape reader/punch
|
|||
TTY console typewriter
|
||||
LPT Type 62 line printer
|
||||
DRM Type 24 serial drum
|
||||
DRP Type 23 parallel drum
|
||||
DT Type 550 Microtape (DECtape)
|
||||
|
||||
The PDP-1 simulator implements the following unique stop conditions:
|
||||
|
@ -77,6 +78,7 @@ The PDP-1 simulator implements the following unique stop conditions:
|
|||
instruction execution
|
||||
- I/O wait, and no I/O operations outstanding (i.e, no I/O
|
||||
completion will ever occur)
|
||||
- a simulated DECtape runs off the end of its reel
|
||||
|
||||
The PDP-1 loader supports RIM format tapes and BLK format tapes. If
|
||||
the file to be loaded has an extension of .BIN, or switch -B is specified,
|
||||
|
@ -302,7 +304,6 @@ The DECtape controller implements these registers:
|
|||
BEF 1 block end flag
|
||||
ERF 1 error flag
|
||||
LTIME 31 time between lines
|
||||
ACTIME 31 time to accelerate to full speed
|
||||
DCTIME 31 time to decelerate to a full stop
|
||||
SUBSTATE 2 read/write command substate
|
||||
POS[0:7] 32 position, in lines, units 0-7
|
||||
|
@ -313,10 +314,19 @@ among the DECtape parameters, or the DECtape simulator will fail to
|
|||
operate correctly.
|
||||
|
||||
- LTIME must be at least 6
|
||||
- ACTIME must be less than DCTIME, and both need to be at
|
||||
least 100 times LTIME
|
||||
- DCTIME needs to be at least 100 times LTIME
|
||||
|
||||
2.4 Type 24 Serial Drum (DRM)
|
||||
Acceleration time is set to 75% of deceleration time.
|
||||
|
||||
2.4 Drums
|
||||
|
||||
The PDP-1 supported two drums: the Type 23 parallel drum (DRP) and
|
||||
the Type 24 serial drum (DRM). Both use device addresses 061-064;
|
||||
accordingly, only one can be enabled at a time. By default, the
|
||||
Type 24 serial drum is enabled, and the Type 23 parallel drum is
|
||||
disabled.
|
||||
|
||||
2.4.1 Type 24 Serial Drum (DRM)
|
||||
|
||||
The serial drum (DRM) implements these registers:
|
||||
|
||||
|
@ -324,7 +334,6 @@ The serial drum (DRM) implements these registers:
|
|||
|
||||
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
|
||||
|
@ -341,6 +350,35 @@ Error handling is as follows:
|
|||
Drum data files are buffered in memory; therefore, end of file and OS
|
||||
I/O errors cannot occur.
|
||||
|
||||
2.4.2 Type 23 Parallel Drum (DRP)
|
||||
|
||||
The parallel drum (DRP) implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
TA 12 track address
|
||||
RDF 5 read field
|
||||
RDE 1 read enable flag
|
||||
WRF 5 write field
|
||||
WRF 1 write enable flag
|
||||
MA 16 current memory address
|
||||
WC 12 word count
|
||||
BUSY 1 device busy flag
|
||||
ERR 1 error flag
|
||||
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
|
||||
|
|
213
PDP1/pdp1_drm.c
|
@ -23,8 +23,12 @@
|
|||
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.
|
||||
|
||||
drp Type 23 parallel drum
|
||||
drm Type 24 serial drum
|
||||
|
||||
08-Dec-03 RMS Added parallel drum support
|
||||
Fixed bug in DBL/DCN decoding
|
||||
26-Oct-03 RMS Cleaned up buffer copy code
|
||||
23-Jul-03 RMS Fixed incorrect logical, missing activate
|
||||
05-Dec-02 RMS Cloned from pdp18b_drm.c
|
||||
*/
|
||||
|
@ -32,21 +36,36 @@
|
|||
#include "pdp1_defs.h"
|
||||
#include <math.h>
|
||||
|
||||
/* Constants */
|
||||
/* Serial drum 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_SIZE (DRM_NUMTR * DRM_NUMWDT) /* words/drum */
|
||||
#define DRM_SMASK ((DRM_NUMTR * DRM_NUMSC) - 1) /* sector mask */
|
||||
|
||||
/* Parallel drum constants */
|
||||
|
||||
#define DRP_NUMWDT 4096 /* words/track */
|
||||
#define DRP_NUMTK 32 /* tracks/drum */
|
||||
#define DRP_SIZE (DRP_NUMWDT * DRP_NUMTK) /* words/drum */
|
||||
#define DRP_V_RWE 17 /* read/write enable */
|
||||
#define DRP_V_FLD 12 /* drum field */
|
||||
#define DRP_M_FLD 037
|
||||
#define DRP_TAMASK 07777 /* track address */
|
||||
#define DRP_WCMASK 07777 /* word count */
|
||||
#define DRP_MAINCM 07777 /* mem addr incr */
|
||||
#define DRP_GETRWE(x) (((x) >> DRP_V_RWE) & 1)
|
||||
#define DRP_GETRWF(x) (((x) >> DRP_V_FLD) & DRP_M_FLD)
|
||||
|
||||
/* Parameters in the unit descriptor */
|
||||
|
||||
#define FUNC u4 /* function */
|
||||
#define DRM_READ 000 /* read */
|
||||
#define DRM_WRITE 010 /* write */
|
||||
#define DRP_RW 000 /* read/write */
|
||||
#define DRP_BRK 001 /* break on address */
|
||||
|
||||
#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \
|
||||
((double) DRM_NUMWDT)))
|
||||
|
@ -56,15 +75,34 @@ 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 */
|
||||
/* Serial drum variables */
|
||||
|
||||
uint32 drm_da = 0; /* track address */
|
||||
uint32 drm_ma = 0; /* memory address */
|
||||
uint32 drm_err = 0; /* error flag */
|
||||
uint32 drm_wlk = 0; /* write lock */
|
||||
int32 drm_time = 4; /* inter-word time */
|
||||
int32 drm_stopioe = 1; /* stop on error */
|
||||
|
||||
/* Parallel drum variables */
|
||||
|
||||
uint32 drp_rde = 0; /* read enable */
|
||||
uint32 drp_wre = 0; /* write enable */
|
||||
uint32 drp_rdf = 0; /* read field */
|
||||
uint32 drp_wrf = 0; /* write field */
|
||||
uint32 drp_ta = 0; /* track address */
|
||||
uint32 drp_wc = 0; /* word count */
|
||||
uint32 drp_ma = 0; /* memory address */
|
||||
uint32 drp_err = 0; /* error */
|
||||
int32 drp_time = 2; /* inter-word time */
|
||||
int32 drp_stopioe = 1; /* stop on error */
|
||||
|
||||
/* Forward declarations */
|
||||
|
||||
t_stat drm_svc (UNIT *uptr);
|
||||
t_stat drm_reset (DEVICE *dptr);
|
||||
t_stat drp_svc (UNIT *uptr);
|
||||
t_stat drp_reset (DEVICE *dptr);
|
||||
|
||||
/* DRM data structures
|
||||
|
||||
|
@ -93,6 +131,38 @@ DEVICE drm_dev = {
|
|||
NULL, NULL, &drm_reset,
|
||||
NULL, NULL, NULL,
|
||||
NULL, DEV_DISABLE };
|
||||
|
||||
/* DRP data structures
|
||||
|
||||
drp_dev DRP device descriptor
|
||||
drp_unit DRP unit descriptor
|
||||
drp_reg DRP register list
|
||||
*/
|
||||
|
||||
UNIT drp_unit =
|
||||
{ UDATA (&drp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF,
|
||||
DRM_SIZE) };
|
||||
|
||||
REG drp_reg[] = {
|
||||
{ ORDATA (TA, drp_ta, 12) },
|
||||
{ ORDATA (RDF, drp_rdf, 5) },
|
||||
{ FLDATA (RDE, drp_rde, 0) },
|
||||
{ FLDATA (WRF, drp_wrf, 5) },
|
||||
{ FLDATA (WRE, drp_wre, 0) },
|
||||
{ ORDATA (MA, drp_ma, 16) },
|
||||
{ ORDATA (WC, drp_wc, 12) },
|
||||
{ FLDATA (BUSY, iosta, IOS_V_DRP) },
|
||||
{ FLDATA (ERR, drp_err, 0) },
|
||||
{ DRDATA (TIME, drp_time, 24), REG_NZ + PV_LEFT },
|
||||
{ FLDATA (STOP_IOE, drp_stopioe, 0) },
|
||||
{ NULL } };
|
||||
|
||||
DEVICE drp_dev = {
|
||||
"DRP", &drp_unit, drp_reg, NULL,
|
||||
1, 8, 20, 1, 8, 18,
|
||||
NULL, NULL, &drp_reset,
|
||||
NULL, NULL, NULL,
|
||||
NULL, DEV_DISABLE | DEV_DIS };
|
||||
|
||||
/* IOT routines */
|
||||
|
||||
|
@ -101,39 +171,77 @@ int32 drm (int32 IR, int32 dev, int32 dat)
|
|||
int32 t;
|
||||
int32 pulse = (IR >> 6) & 037;
|
||||
|
||||
if (drm_dev.flags & DEV_DIS) /* disabled? */
|
||||
if ((drm_dev.flags & DEV_DIS) == 0) { /* serial enabled? */
|
||||
if ((pulse != 001) && (pulse != 011)) /* invalid pulse? */
|
||||
return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */
|
||||
if ((pulse != 001) && (pulse != 011)) /* invalid pulse? */
|
||||
return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */
|
||||
switch (dev) { /* switch on device */
|
||||
case 061: /* DWR, DRD */
|
||||
drm_ma = dat & 0177777; /* load mem addr */
|
||||
switch (dev) { /* switch on device */
|
||||
case 061: /* DWR, DRD */
|
||||
drm_ma = dat & AMASK; /* load mem addr */
|
||||
drm_unit.FUNC = pulse & DRM_WRITE; /* save function */
|
||||
break;
|
||||
case 062: /* DBL, DCN */
|
||||
if (pulse & 010) drm_da = dat & DRM_SMASK; /* load sector # */
|
||||
case 062: /* DBL, DCN */
|
||||
if ((pulse & 010) == 0) /* DBL? */
|
||||
drm_da = dat & 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? */
|
||||
sim_activate (&drm_unit, t); /* start operation */
|
||||
break;
|
||||
case 063: /* DTD */
|
||||
case 063: /* DTD */
|
||||
if (pulse == 011) return (stop_inst << IOT_V_REASON) | dat;
|
||||
if (iosta & IOS_DRM) return (dat | IOT_SKP); /* skip if done */
|
||||
break;
|
||||
case 064: /* DSE, DSP */
|
||||
case 064: /* DSE, DSP */
|
||||
if ((drm_err == 0) || (pulse & 010)) /* no error, par test? */
|
||||
return (dat | IOT_SKP);
|
||||
}
|
||||
return dat;
|
||||
} /* end case */
|
||||
return dat; } /* end if serial */
|
||||
|
||||
if ((drp_dev.flags & DEV_DIS) == 0) { /* parallel enabled? */
|
||||
switch (dev) { /* switch on device */
|
||||
case 061: /* DIA, DBA */
|
||||
drp_err = 0; /* clear error */
|
||||
iosta = iosta & ~IOS_DRP; /* not busy */
|
||||
drp_rde = DRP_GETRWE (dat); /* set read enable */
|
||||
drp_rdf = DRP_GETRWF (dat); /* set read field */
|
||||
drp_ta = dat & DRP_TAMASK; /* set track addr */
|
||||
if (IR & 02000) { /* DBA? */
|
||||
t = drp_ta - GET_POS (drp_time); /* delta words */
|
||||
if (t <= 0) t = t + DRP_NUMWDT; /* wrap around? */
|
||||
sim_activate (&drp_unit, t); /* start operation */
|
||||
drp_unit.FUNC = DRP_BRK; } /* mark as break */
|
||||
else drp_unit.FUNC = DRP_RW; /* no, read/write */
|
||||
break;
|
||||
case 062: /* DWC, DRA */
|
||||
if (IR & 02000) dat = GET_POS (drp_time) | /* DRA, get position */
|
||||
(drp_err? 0400000: 0);
|
||||
else { /* DWC */
|
||||
drp_wre = DRP_GETRWE (dat); /* set write enable */
|
||||
drp_wrf = DRP_GETRWF (dat); /* set write field */
|
||||
drp_wc = dat & DRP_WCMASK; } /* set word count */
|
||||
break;
|
||||
case 063: /* DCL */
|
||||
drp_ma = dat & AMASK; /* set mem address */
|
||||
t = drp_ta - GET_POS (drp_time); /* delta words */
|
||||
if (t <= 0) t = t + DRP_NUMWDT; /* wrap around? */
|
||||
sim_activate (&drp_unit, t); /* start operation */
|
||||
iosta = iosta | IOS_DRP; /* set busy */
|
||||
break;
|
||||
case 064: /* not assigned */
|
||||
return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */
|
||||
} /* end case */
|
||||
return dat; } /* end if parallel */
|
||||
|
||||
return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */
|
||||
}
|
||||
|
||||
/* Unit service - this code assumes the entire drum is buffered */
|
||||
/* Serial unit service - this code assumes the entire drum is buffered */
|
||||
|
||||
t_stat drm_svc (UNIT *uptr)
|
||||
{
|
||||
uint32 i, da;
|
||||
uint32 *fbuf = uptr->filebuf;
|
||||
|
||||
if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
|
||||
drm_err = 1; /* set error */
|
||||
|
@ -143,15 +251,15 @@ if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
|
|||
|
||||
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 (uptr->FUNC == DRM_READ) { /* read? */
|
||||
if (MEM_ADDR_OK (drm_ma)) /* if !nxm */
|
||||
M[drm_ma] = fbuf[da]; } /* read word */
|
||||
else { /* write */
|
||||
if ((drm_wlk >> (drm_da >> 4)) & 1) drm_err = 1;
|
||||
else {
|
||||
*(((int32 *) uptr->filebuf) + da) = M[drm_ma];
|
||||
else { /* not locked */
|
||||
fbuf[da] = M[drm_ma]; /* write word */
|
||||
if (da >= uptr->hwmark) uptr->hwmark = da + 1; } }
|
||||
drm_ma = (drm_ma + 1) & 0177777; } /* incr mem addr */
|
||||
drm_ma = (drm_ma + 1) & AMASK; } /* 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 */
|
||||
|
@ -162,8 +270,57 @@ return SCPE_OK;
|
|||
|
||||
t_stat drm_reset (DEVICE *dptr)
|
||||
{
|
||||
if ((drm_dev.flags & DEV_DIS) == 0)
|
||||
drp_dev.flags = drp_dev.flags | DEV_DIS;
|
||||
drm_da = drm_ma = drm_err = 0;
|
||||
iosta = iosta & ~IOS_DRM;
|
||||
sim_cancel (&drm_unit);
|
||||
drm_unit.FUNC = 0;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Parallel unit service - this code assumes the entire drum is buffered */
|
||||
|
||||
t_stat drp_svc (UNIT *uptr)
|
||||
{
|
||||
uint32 i, lim;
|
||||
uint32 *fbuf = uptr->filebuf;
|
||||
|
||||
if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
|
||||
drp_err = 1; /* set error */
|
||||
iosta = iosta & ~IOS_DRP; /* clear busy */
|
||||
if (uptr->FUNC) sbs = sbs | SB_RQ; /* req intr */
|
||||
return IORETURN (drp_stopioe, SCPE_UNATT); }
|
||||
|
||||
if (uptr->FUNC == DRP_RW) { /* read/write? */
|
||||
lim = drp_wc? drp_wc: DRP_TAMASK + 1; /* eff word count */
|
||||
for (i = 0; i < lim; i++) { /* do transfer */
|
||||
if (drp_wre) /* write enabled? */
|
||||
fbuf[(drp_wrf << DRP_V_FLD) | drp_ta] = M[drp_ma];
|
||||
if (drp_rde && MEM_ADDR_OK (drp_ma)) /* read enabled? */
|
||||
M[drp_ma] = fbuf[(drp_rdf << DRP_V_FLD) | drp_ta];
|
||||
drp_ta = (drp_ta + 1) & DRP_TAMASK; /* incr track addr */
|
||||
drp_ma = ((drp_ma & ~DRP_MAINCM) | ((drp_ma + 1) & DRP_MAINCM));
|
||||
} /* end for */
|
||||
} /* end if */
|
||||
iosta = iosta & ~IOS_DRP; /* clear busy */
|
||||
if (uptr->FUNC) sbs = sbs | SB_RQ; /* req intr */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat drp_reset (DEVICE *dptr)
|
||||
{
|
||||
if ((drp_dev.flags & DEV_DIS) == 0)
|
||||
drm_dev.flags = drm_dev.flags | DEV_DIS;
|
||||
drp_ta = 0;
|
||||
drp_rde = drp_rdf = drp_wre = drp_wrf = 0;
|
||||
drp_err = 0;
|
||||
drp_ma = 0;
|
||||
drp_wc = 0;
|
||||
iosta = iosta & ~IOS_DRP;
|
||||
sim_cancel (&drp_unit);
|
||||
drp_unit.FUNC = 0;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
dt Type 550/555 DECtape
|
||||
|
||||
26-Oct-03 RMS Cleaned up buffer copy code
|
||||
18-Oct-03 RMS Added DECtape off reel message, simplified timing
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
14-Mar-03 RMS Fixed variable size interaction with save/restore
|
||||
17-Oct-02 RMS Fixed bug in end of reel logic
|
||||
|
@ -41,13 +43,16 @@
|
|||
When a 16b or 12b DECtape file is read in, it is converted to 18b/36b format.
|
||||
|
||||
DECtape motion is measured in 3b lines. Time between lines is 33.33us.
|
||||
Tape density is nominally 300 lines per inch. The format of a DECtape is
|
||||
Tape density is nominally 300 lines per inch. The format of a DECtape (as
|
||||
taken from the TD8E formatter) is:
|
||||
|
||||
reverse end zone 36000 lines ~ 10 feet
|
||||
reverse end zone 8192 reverse end zone codes ~ 10 feet
|
||||
reverse buffer 200 interblock codes
|
||||
block 0
|
||||
:
|
||||
block n
|
||||
forward end zone 36000 lines ~ 10 feet
|
||||
forward buffer 200 interblock codes
|
||||
forward end zone 8192 forward end zone codes ~ 10 feet
|
||||
|
||||
A block consists of five 18b header words, a tape-specific number of data
|
||||
words, and five 18b trailer words. All systems except the PDP-8 use a
|
||||
|
@ -64,9 +69,9 @@
|
|||
header word 0 0
|
||||
header word 1 block number (for forward reads)
|
||||
header words 2,3 0
|
||||
header word 4 0
|
||||
header word 4 checksum (for reverse reads)
|
||||
:
|
||||
trailer word 4 checksum
|
||||
trailer word 4 checksum (for forward reads)
|
||||
trailer words 3,2 0
|
||||
trailer word 1 block number (for reverse reads)
|
||||
trailer word 0 0
|
||||
|
@ -97,13 +102,15 @@
|
|||
|
||||
/* System independent DECtape constants */
|
||||
|
||||
#define DT_EZLIN 36000 /* end zone length */
|
||||
#define DT_HTLIN 30 /* header/trailer lines */
|
||||
#define DT_BLKLN 6 /* blk no line in h/t */
|
||||
#define DT_CSMLN 24 /* checksum line in h/t */
|
||||
#define DT_HTWRD (DT_HTLIN / DT_WSIZE) /* header/trailer words */
|
||||
#define DT_BLKWD (DT_BLKLN / DT_WSIZE) /* blk no word in h/t */
|
||||
#define DT_CSMWD (DT_CSMLN / DT_WSIZE) /* checksum word in h/t */
|
||||
#define DT_LPERMC 6 /* lines per mark track */
|
||||
#define DT_BLKWD 1 /* blk no word in h/t */
|
||||
#define DT_CSMWD 4 /* checksum word in h/t */
|
||||
#define DT_HTWRD 5 /* header/trailer words */
|
||||
#define DT_EZLIN (8192 * DT_LPERMC) /* end zone length */
|
||||
#define DT_BFLIN (200 * DT_LPERMC) /* buffer length */
|
||||
#define DT_BLKLN (DT_BLKWD * DT_LPERMC) /* blk no line in h/t */
|
||||
#define DT_CSMLN (DT_CSMWD * DT_LPERMC) /* csum line in h/t */
|
||||
#define DT_HTLIN (DT_HTWRD * DT_LPERMC) /* header/trailer lines */
|
||||
|
||||
/* 16b, 18b, 36b DECtape constants */
|
||||
|
||||
|
@ -249,8 +256,7 @@ int32 dtsa = 0; /* status A */
|
|||
int32 dtsb = 0; /* status B */
|
||||
int32 dtdb = 0; /* data buffer */
|
||||
int32 dt_ltime = 12; /* interline time */
|
||||
int32 dt_actime = 54000; /* accel time */
|
||||
int32 dt_dctime = 72000; /* decel time */
|
||||
int32 dt_dctime = 40000; /* decel time */
|
||||
int32 dt_substate = 0;
|
||||
int32 dt_log = 0;
|
||||
int32 dt_logblk = 0;
|
||||
|
@ -306,7 +312,6 @@ REG dt_reg[] = {
|
|||
{ FLDATA (BEF, dtsb, DTB_V_BEF) },
|
||||
{ FLDATA (ERF, dtsb, DTB_V_ERF) },
|
||||
{ DRDATA (LTIME, dt_ltime, 31), REG_NZ },
|
||||
{ DRDATA (ACTIME, dt_actime, 31), REG_NZ },
|
||||
{ DRDATA (DCTIME, dt_dctime, 31), REG_NZ },
|
||||
{ ORDATA (SUBSTATE, dt_substate, 2) },
|
||||
{ ORDATA (LOG, dt_log, 4), REG_HIDDEN },
|
||||
|
@ -441,7 +446,7 @@ if ((prev_mving | new_mving) == 0) return; /* stop to stop */
|
|||
if (new_mving & ~prev_mving) { /* start? */
|
||||
if (dt_setpos (uptr)) return; /* update pos */
|
||||
sim_cancel (uptr); /* stop current */
|
||||
sim_activate (uptr, dt_actime); /* schedule accel */
|
||||
sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* sched accel */
|
||||
DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */
|
||||
DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */
|
||||
return; }
|
||||
|
@ -467,7 +472,7 @@ if (prev_dir ^ new_dir) { /* dir chg? */
|
|||
if (prev_mot < DTS_ACCF) { /* not accel/at speed? */
|
||||
if (dt_setpos (uptr)) return; /* update pos */
|
||||
sim_cancel (uptr); /* cancel cur */
|
||||
sim_activate (uptr, dt_actime); /* schedule accel */
|
||||
sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* sched accel */
|
||||
DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */
|
||||
DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */
|
||||
return; }
|
||||
|
@ -588,11 +593,13 @@ case DTS_STOP: /* stop */
|
|||
delta = 0;
|
||||
break;
|
||||
case DTS_DECF: /* slowing */
|
||||
ulin = ut / (uint32) dt_ltime; udelt = dt_dctime / dt_ltime;
|
||||
ulin = ut / (uint32) dt_ltime;
|
||||
udelt = dt_dctime / dt_ltime;
|
||||
delta = ((ulin * udelt * 2) - (ulin * ulin)) / (2 * udelt);
|
||||
break;
|
||||
case DTS_ACCF: /* accelerating */
|
||||
ulin = ut / (uint32) dt_ltime; udelt = dt_actime / dt_ltime;
|
||||
ulin = ut / (uint32) dt_ltime;
|
||||
udelt = (dt_dctime - (dt_dctime >> 2)) / dt_ltime;
|
||||
delta = (ulin * ulin) / (2 * udelt);
|
||||
break;
|
||||
case DTS_ATSF: /* at speed */
|
||||
|
@ -621,7 +628,7 @@ t_stat dt_svc (UNIT *uptr)
|
|||
int32 mot = DTS_GETMOT (uptr->STATE);
|
||||
int32 dir = mot & DTS_DIR;
|
||||
int32 fnc = DTS_GETFNC (uptr->STATE);
|
||||
int32 *bptr = uptr->filebuf;
|
||||
int32 *fbuf = uptr->filebuf;
|
||||
int32 unum = uptr - dt_dev.units;
|
||||
int32 blk, wrd, ma, relpos;
|
||||
uint32 ba;
|
||||
|
@ -635,10 +642,10 @@ uint32 ba;
|
|||
|
||||
switch (mot) {
|
||||
case DTS_DECF: case DTS_DECR: /* decelerating */
|
||||
if (dt_setpos (uptr)) return SCPE_OK; /* update pos */
|
||||
if (dt_setpos (uptr)) return STOP_DTOFF; /* update pos */
|
||||
uptr->STATE = DTS_NXTSTA (uptr->STATE); /* advance state */
|
||||
if (uptr->STATE) /* not stopped? */
|
||||
sim_activate (uptr, dt_actime); /* must be reversing */
|
||||
sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* reversing */
|
||||
return SCPE_OK;
|
||||
case DTS_ACCF: case DTS_ACCR: /* accelerating */
|
||||
dt_newfnc (uptr, DTS_NXTSTA (uptr->STATE)); /* adv state, sched */
|
||||
|
@ -656,7 +663,7 @@ default: /* other */
|
|||
Off reel - detach unit (it must be deselected)
|
||||
*/
|
||||
|
||||
if (dt_setpos (uptr)) return SCPE_OK; /* update pos */
|
||||
if (dt_setpos (uptr)) return STOP_DTOFF; /* update pos */
|
||||
if (DT_QEZ (uptr)) { /* in end zone? */
|
||||
dt_seterr (uptr, DTB_END); /* end zone error */
|
||||
return SCPE_OK; }
|
||||
|
@ -693,7 +700,7 @@ case FNC_READ: case FNC_RALL:
|
|||
(relpos < (DTU_LPERB (uptr) - DT_HTLIN))) {
|
||||
wrd = DT_LIN2WD (uptr->pos, uptr);
|
||||
ba = (blk * DTU_BSIZE (uptr)) + wrd;
|
||||
dtdb = bptr[ba]; /* get tape word */
|
||||
dtdb = fbuf[ba]; /* get tape word */
|
||||
dtsb = dtsb | DTB_DTF; } /* set flag */
|
||||
else {
|
||||
ma = (2 * DT_HTWRD) + DTU_BSIZE (uptr) - DT_CSMWD - 1;
|
||||
|
@ -722,8 +729,8 @@ case FNC_WRIT: case FNC_WALL:
|
|||
(relpos < (DTU_LPERB (uptr) - DT_HTLIN))) {
|
||||
wrd = DT_LIN2WD (uptr->pos, uptr);
|
||||
ba = (blk * DTU_BSIZE (uptr)) + wrd;
|
||||
if (dir) bptr[ba] = dt_comobv (dtdb); /* get data word */
|
||||
else bptr[ba] = dtdb;
|
||||
if (dir) fbuf[ba] = dt_comobv (dtdb); /* get data word */
|
||||
else fbuf[ba] = dtdb;
|
||||
if (ba >= uptr->hwmark) uptr->hwmark = ba + 1;
|
||||
if (wrd == (dir? 0: DTU_BSIZE (uptr) - 1))
|
||||
dtsb = dtsb | DTB_BEF; /* end block */
|
||||
|
@ -791,13 +798,13 @@ return dat;
|
|||
|
||||
int32 dt_csum (UNIT *uptr, int32 blk)
|
||||
{
|
||||
int32 *bptr = uptr->filebuf;
|
||||
int32 *fbuf = uptr->filebuf;
|
||||
int32 ba = blk * DTU_BSIZE (uptr);
|
||||
int32 i, csum, wrd;
|
||||
|
||||
csum = 0777777;
|
||||
for (i = 0; i < DTU_BSIZE (uptr); i++) { /* loop thru buf */
|
||||
wrd = bptr[ba + i]; /* get word */
|
||||
wrd = fbuf[ba + i]; /* get word */
|
||||
csum = csum + wrd; /* 1's comp add */
|
||||
if (csum > 0777777) csum = (csum + 1) & 0777777; }
|
||||
return (csum ^ 0777777); /* 1's comp res */
|
||||
|
@ -868,7 +875,7 @@ t_stat dt_attach (UNIT *uptr, char *cptr)
|
|||
{
|
||||
uint16 pdp8b[D8_NBSIZE];
|
||||
uint16 pdp11b[D18_BSIZE];
|
||||
uint32 ba, sz, k, *bptr;
|
||||
uint32 ba, sz, k, *fbuf;
|
||||
int32 u = uptr - dt_dev.units;
|
||||
t_stat r;
|
||||
|
||||
|
@ -891,7 +898,7 @@ uptr->filebuf = calloc (uptr->capac, sizeof (int32));
|
|||
if (uptr->filebuf == NULL) { /* can't alloc? */
|
||||
detach_unit (uptr);
|
||||
return SCPE_MEM; }
|
||||
bptr = uptr->filebuf; /* file buffer */
|
||||
fbuf = uptr->filebuf; /* file buffer */
|
||||
printf ("%s%d: ", sim_dname (&dt_dev), u);
|
||||
if (uptr->flags & UNIT_8FMT) printf ("12b format");
|
||||
else if (uptr->flags & UNIT_11FMT) printf ("16b format");
|
||||
|
@ -903,9 +910,9 @@ if (uptr->flags & UNIT_8FMT) { /* 12b? */
|
|||
if (k == 0) break;
|
||||
for ( ; k < D8_NBSIZE; k++) pdp8b[k] = 0;
|
||||
for (k = 0; k < D8_NBSIZE; k = k + 3) { /* loop thru blk */
|
||||
bptr[ba] = ((uint32) (pdp8b[k] & 07777) << 6) |
|
||||
fbuf[ba] = ((uint32) (pdp8b[k] & 07777) << 6) |
|
||||
((uint32) (pdp8b[k + 1] >> 6) & 077);
|
||||
bptr[ba + 1] = ((uint32) (pdp8b[k + 1] & 077) << 12) |
|
||||
fbuf[ba + 1] = ((uint32) (pdp8b[k + 1] & 077) << 12) |
|
||||
(pdp8b[k + 2] & 07777);
|
||||
ba = ba + 2; } /* end blk loop */
|
||||
} /* end file loop */
|
||||
|
@ -916,7 +923,7 @@ else if (uptr->flags & UNIT_11FMT) { /* 16b? */
|
|||
if (k == 0) break;
|
||||
for ( ; k < D18_BSIZE; k++) pdp11b[k] = 0;
|
||||
for (k = 0; k < D18_BSIZE; k++)
|
||||
bptr[ba++] = pdp11b[k]; }
|
||||
fbuf[ba++] = pdp11b[k]; }
|
||||
uptr->hwmark = ba; } /* end elif */
|
||||
else uptr->hwmark = fxread (uptr->filebuf, sizeof (int32),
|
||||
uptr->capac, uptr->fileref);
|
||||
|
@ -939,27 +946,27 @@ t_stat dt_detach (UNIT* uptr)
|
|||
{
|
||||
uint16 pdp8b[D8_NBSIZE];
|
||||
uint16 pdp11b[D18_BSIZE];
|
||||
uint32 ba, k, *bptr;
|
||||
uint32 ba, k, *fbuf;
|
||||
int32 u = uptr - dt_dev.units;
|
||||
|
||||
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK;
|
||||
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */
|
||||
if (sim_is_active (uptr)) {
|
||||
sim_cancel (uptr);
|
||||
if ((u == DTA_GETUNIT (dtsa)) && (dtsa & DTA_STSTP)) {
|
||||
dtsb = dtsb | DTB_ERF | DTB_SEL | DTB_DTF;
|
||||
DT_UPDINT; }
|
||||
uptr->STATE = uptr->pos = 0; }
|
||||
bptr = uptr->filebuf; /* file buffer */
|
||||
fbuf = uptr->filebuf; /* file buffer */
|
||||
if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */
|
||||
printf ("%s%d: writing buffer to file\n", sim_dname (&dt_dev), u);
|
||||
rewind (uptr->fileref); /* start of file */
|
||||
if (uptr->flags & UNIT_8FMT) { /* 12b? */
|
||||
for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */
|
||||
for (k = 0; k < D8_NBSIZE; k = k + 3) { /* loop blk */
|
||||
pdp8b[k] = (bptr[ba] >> 6) & 07777;
|
||||
pdp8b[k + 1] = ((bptr[ba] & 077) << 6) |
|
||||
((bptr[ba + 1] >> 12) & 077);
|
||||
pdp8b[k + 2] = bptr[ba + 1] & 07777;
|
||||
pdp8b[k] = (fbuf[ba] >> 6) & 07777;
|
||||
pdp8b[k + 1] = ((fbuf[ba] & 077) << 6) |
|
||||
((fbuf[ba + 1] >> 12) & 077);
|
||||
pdp8b[k + 2] = fbuf[ba + 1] & 07777;
|
||||
ba = ba + 2; } /* end loop blk */
|
||||
fxwrite (pdp8b, sizeof (int16), D8_NBSIZE, uptr->fileref);
|
||||
if (ferror (uptr->fileref)) break; } /* end loop file */
|
||||
|
@ -967,7 +974,7 @@ if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */
|
|||
else if (uptr->flags & UNIT_11FMT) { /* 16b? */
|
||||
for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */
|
||||
for (k = 0; k < D18_BSIZE; k++) /* loop blk */
|
||||
pdp11b[k] = bptr[ba++] & 0177777;
|
||||
pdp11b[k] = fbuf[ba++] & 0177777;
|
||||
fxwrite (pdp11b, sizeof (int16), D18_BSIZE, uptr->fileref);
|
||||
if (ferror (uptr->fileref)) break; } /* end loop file */
|
||||
} /* end if 16b */
|
||||
|
|
|
@ -143,27 +143,27 @@ if (cpls & CPLS_LPT) { /* completion pulse? */
|
|||
sbs = sbs | SB_RQ; /* req seq break */
|
||||
if (lpt_spc) { /* space? */
|
||||
iosta = iosta | IOS_SPC; /* set flag */
|
||||
if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
|
||||
return IORETURN (lpt_stopioe, SCPE_UNATT);
|
||||
fputs (lpt_cc[lpt_spc & 07], lpt_unit.fileref); /* print cctl */
|
||||
if (ferror (lpt_unit.fileref)) { /* error? */
|
||||
fputs (lpt_cc[lpt_spc & 07], uptr->fileref); /* print cctl */
|
||||
if (ferror (uptr->fileref)) { /* error? */
|
||||
perror ("LPT I/O error");
|
||||
clearerr (lpt_unit.fileref);
|
||||
clearerr (uptr->fileref);
|
||||
return SCPE_IOERR; }
|
||||
lpt_ovrpr = 0; } /* dont overprint */
|
||||
else { iosta = iosta | IOS_PNT; /* print */
|
||||
if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
|
||||
return IORETURN (lpt_stopioe, SCPE_UNATT);
|
||||
if (lpt_ovrpr) fputc ('\r', lpt_unit.fileref); /* overprint? */
|
||||
fputs (lpt_buf, lpt_unit.fileref); /* print buffer */
|
||||
if (ferror (lpt_unit.fileref)) { /* test error */
|
||||
if (lpt_ovrpr) fputc ('\r', uptr->fileref); /* overprint? */
|
||||
fputs (lpt_buf, uptr->fileref); /* print buffer */
|
||||
if (ferror (uptr->fileref)) { /* test error */
|
||||
perror ("LPT I/O error");
|
||||
clearerr (lpt_unit.fileref);
|
||||
clearerr (uptr->fileref);
|
||||
return SCPE_IOERR; }
|
||||
lpt_bptr = 0;
|
||||
for (i = 0; i <= LPT_BSIZE; i++) lpt_buf[i] = 0; /* clear buffer */
|
||||
lpt_ovrpr = 1; } /* set overprint */
|
||||
lpt_unit.pos = ftell (lpt_unit.fileref); /* update position */
|
||||
lpt_unit.pos = ftell (uptr->fileref); /* update position */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
tti keyboard
|
||||
tto teleprinter
|
||||
|
||||
29-Oct-03 RMS Added PTR FIODEC-to-ASCII translation (from Phil Budne)
|
||||
07-Sep-03 RMS Changed ioc to ios
|
||||
30-Aug-03 RMS Revised PTR to conform to Maintenance Manual;
|
||||
added deadlock prevention on errors
|
||||
|
@ -42,10 +43,14 @@
|
|||
07-Sep-01 RMS Moved function prototypes
|
||||
10-Jun-01 RMS Fixed comment
|
||||
30-Oct-00 RMS Standardized device naming
|
||||
|
||||
Note: PTP timeout must be >10X faster that TTY output timeout for Macro
|
||||
to work correctly!
|
||||
*/
|
||||
|
||||
#include "pdp1_defs.h"
|
||||
|
||||
#define FIODEC_STOP 013 /* stop code */
|
||||
#define FIODEC_UC 074
|
||||
#define FIODEC_LC 072
|
||||
#define UC_V 6 /* upper case */
|
||||
|
@ -55,10 +60,16 @@
|
|||
#define TT_WIDTH 077
|
||||
#define TTI 0
|
||||
#define TTO 1
|
||||
#define UNIT_V_ASCII (UNIT_V_UF + 0) /* ASCII/binary mode */
|
||||
#define UNIT_ASCII (1 << UNIT_V_ASCII)
|
||||
#define PTR_LEADER 20 /* ASCII leader chars */
|
||||
|
||||
int32 ptr_state = 0;
|
||||
int32 ptr_wait = 0;
|
||||
int32 ptr_stopioe = 0;
|
||||
int32 ptr_uc = 0; /* upper/lower case */
|
||||
int32 ptr_hold = 0; /* holding buffer */
|
||||
int32 ptr_leader = PTR_LEADER; /* leader count */
|
||||
int32 ptp_stopioe = 0;
|
||||
int32 tti_hold = 0; /* tti hold buf */
|
||||
int32 tty_buf = 0; /* tty buffer */
|
||||
|
@ -68,6 +79,7 @@ extern int32 sbs, ios, ioh, cpls, iosta;
|
|||
extern int32 PF, IO, PC, TA;
|
||||
extern int32 M[];
|
||||
|
||||
int ptr_get_ascii (UNIT *uptr);
|
||||
t_stat ptr_svc (UNIT *uptr);
|
||||
t_stat ptp_svc (UNIT *uptr);
|
||||
t_stat tti_svc (UNIT *uptr);
|
||||
|
@ -76,6 +88,7 @@ t_stat ptr_reset (DEVICE *dptr);
|
|||
t_stat ptp_reset (DEVICE *dptr);
|
||||
t_stat tty_reset (DEVICE *dptr);
|
||||
t_stat ptr_boot (int32 unitno, DEVICE *dptr);
|
||||
t_stat ptr_attach (UNIT *uptr, char *cptr);
|
||||
|
||||
/* Character translation tables */
|
||||
|
||||
|
@ -128,20 +141,28 @@ UNIT ptr_unit = {
|
|||
|
||||
REG ptr_reg[] = {
|
||||
{ ORDATA (BUF, ptr_unit.buf, 18) },
|
||||
{ FLDATA (UC, ptr_uc, UC_V) },
|
||||
{ FLDATA (DONE, iosta, IOS_V_PTR) },
|
||||
{ FLDATA (RPLS, cpls, CPLS_V_PTR) },
|
||||
{ ORDATA (HOLD, ptr_hold, 9), REG_HRO },
|
||||
{ ORDATA (STATE, ptr_state, 5), REG_HRO },
|
||||
{ FLDATA (WAIT, ptr_wait, 0), REG_HRO },
|
||||
{ DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },
|
||||
{ DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT },
|
||||
{ DRDATA (LEADER, ptr_leader, 6), REG_HRO },
|
||||
{ FLDATA (STOP_IOE, ptr_stopioe, 0) },
|
||||
{ NULL } };
|
||||
|
||||
MTAB ptr_mod[] = {
|
||||
{ UNIT_ASCII, UNIT_ASCII, "ASCII", "ASCII", NULL },
|
||||
{ UNIT_ASCII, 0, "FIODEC", "FIODEC", NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE ptr_dev = {
|
||||
"PTR", &ptr_unit, ptr_reg, NULL,
|
||||
"PTR", &ptr_unit, ptr_reg, ptr_mod,
|
||||
1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &ptr_reset,
|
||||
&ptr_boot, NULL, NULL,
|
||||
&ptr_boot, &ptr_attach, NULL,
|
||||
NULL, 0 };
|
||||
|
||||
/* PTP data structures
|
||||
|
@ -179,7 +200,7 @@ DEVICE ptp_dev = {
|
|||
|
||||
UNIT tty_unit[] = {
|
||||
{ UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT },
|
||||
{ UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT } };
|
||||
{ UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT * 10 } };
|
||||
|
||||
REG tty_reg[] = {
|
||||
{ ORDATA (BUF, tty_buf, 6) },
|
||||
|
@ -240,35 +261,74 @@ t_stat ptr_svc (UNIT *uptr)
|
|||
{
|
||||
int32 temp;
|
||||
|
||||
if ((ptr_unit.flags & UNIT_ATT) == 0) { /* attached? */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */
|
||||
if (ptr_wait) ptr_wait = ioh = 0; /* if wait, clr ioh */
|
||||
if ((cpls & CPLS_PTR) || ptr_stopioe) return SCPE_UNATT;
|
||||
return SCPE_OK; }
|
||||
if ((temp = getc (ptr_unit.fileref)) == EOF) { /* end of file? */
|
||||
if ((uptr->flags & UNIT_ASCII) && (ptr_state == 0)) /* ASCII mode, alpha read? */
|
||||
temp = ptr_get_ascii (uptr); /* get processed char */
|
||||
else if ((temp = getc (uptr->fileref)) != EOF) /* no, get raw char */
|
||||
uptr->pos = uptr->pos + 1; /* if not eof, count */
|
||||
if (temp == EOF) { /* end of file? */
|
||||
if (ptr_wait) ptr_wait = ioh = 0; /* if wait, clr ioh */
|
||||
if (feof (ptr_unit.fileref)) {
|
||||
if (feof (uptr->fileref)) {
|
||||
if ((cpls & CPLS_PTR) || ptr_stopioe) printf ("PTR end of file\n");
|
||||
else return SCPE_OK; }
|
||||
else perror ("PTR I/O error");
|
||||
clearerr (ptr_unit.fileref);
|
||||
clearerr (uptr->fileref);
|
||||
return SCPE_IOERR; }
|
||||
ptr_unit.pos = ptr_unit.pos + 1;
|
||||
if (ptr_state == 0) ptr_unit.buf = temp & 0377; /* alpha */
|
||||
if (ptr_state == 0) uptr->buf = temp & 0377; /* alpha */
|
||||
else if (temp & 0200) { /* binary */
|
||||
ptr_state = ptr_state - 6;
|
||||
ptr_unit.buf = ptr_unit.buf | ((temp & 077) << ptr_state); }
|
||||
uptr->buf = uptr->buf | ((temp & 077) << ptr_state); }
|
||||
if (ptr_state == 0) { /* done? */
|
||||
if (cpls & CPLS_PTR) { /* completion pulse? */
|
||||
iosta = iosta & ~IOS_PTR; /* clear flag */
|
||||
IO = ptr_unit.buf; /* fill IO */
|
||||
IO = uptr->buf; /* fill IO */
|
||||
ios = 1; /* restart */
|
||||
cpls = cpls & ~CPLS_PTR; }
|
||||
else { /* no, interrupt */
|
||||
iosta = iosta | IOS_PTR; /* set flag */
|
||||
sbs = sbs | SB_RQ; } } /* req seq break */
|
||||
else sim_activate (&ptr_unit, ptr_unit.wait); /* get next char */
|
||||
else sim_activate (uptr, uptr->wait); /* get next char */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Read next ASCII character */
|
||||
|
||||
int ptr_get_ascii (UNIT *uptr)
|
||||
{
|
||||
int c;
|
||||
int32 in;
|
||||
|
||||
if (ptr_leader > 0) { /* leader? */
|
||||
ptr_leader = ptr_leader - 1; /* count down */
|
||||
return 0; }
|
||||
if (ptr_hold & CW) { /* char waiting? */
|
||||
in = ptr_hold & TT_WIDTH; /* return char */
|
||||
ptr_hold = 0; } /* not waiting */
|
||||
else { for (;;) { /* until valid char */
|
||||
if ((c = getc (uptr->fileref)) == EOF) /* get next char, EOF? */
|
||||
return FIODEC_STOP; /* return STOP */
|
||||
uptr->pos = uptr->pos + 1; /* count char */
|
||||
c = c & 0177; /* cut to 7b */
|
||||
if (c == '\n') c = '\r'; /* NL -> CR */
|
||||
else if (c == '\r') continue; /* ignore CR */
|
||||
in = ascii_to_fiodec[c]; /* convert char */
|
||||
if ((in == 0) && (c != ' ')) continue; /* ignore unknowns */
|
||||
if ((in & BOTH) || ((in & UC) == ptr_uc)) /* case match? */
|
||||
in = in & TT_WIDTH; /* cut to 6b */
|
||||
else { /* no, case shift */
|
||||
ptr_hold = in | CW; /* set char waiting */
|
||||
ptr_uc = in & UC; /* set case */
|
||||
in = ptr_uc? FIODEC_UC: FIODEC_LC; } /* return case */
|
||||
break; }
|
||||
} /* end else */
|
||||
in = in * 010040201; /* even parity from */
|
||||
in = in | 027555555400; /* HACKMEM 167 */
|
||||
in = in % (9 << 7);
|
||||
return in & 0377;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
|
@ -276,6 +336,8 @@ t_stat ptr_reset (DEVICE *dptr)
|
|||
{
|
||||
ptr_state = 0; /* clear state */
|
||||
ptr_wait = 0;
|
||||
ptr_hold = 0;
|
||||
ptr_uc = 0;
|
||||
ptr_unit.buf = 0;
|
||||
cpls = cpls & ~CPLS_PTR;
|
||||
iosta = iosta & ~IOS_PTR; /* clear flag */
|
||||
|
@ -283,6 +345,14 @@ sim_cancel (&ptr_unit); /* deactivate unit */
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Attach routine */
|
||||
|
||||
t_stat ptr_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
ptr_leader = PTR_LEADER; /* set up leader */
|
||||
return attach_unit (uptr, cptr);
|
||||
}
|
||||
|
||||
/* Bootstrap routine */
|
||||
|
||||
int32 ptr_getw (UNIT *uptr)
|
||||
|
@ -341,13 +411,13 @@ if (cpls & CPLS_PTP) { /* completion pulse? */
|
|||
cpls = cpls & ~CPLS_PTP; }
|
||||
iosta = iosta | IOS_PTP; /* set flag */
|
||||
sbs = sbs | SB_RQ; /* req seq break */
|
||||
if ((ptp_unit.flags & UNIT_ATT) == 0) /* not attached? */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */
|
||||
return IORETURN (ptp_stopioe, SCPE_UNATT);
|
||||
if (putc (ptp_unit.buf, ptp_unit.fileref) == EOF) { /* I/O error? */
|
||||
if (putc (uptr->buf, uptr->fileref) == EOF) { /* I/O error? */
|
||||
perror ("PTP I/O error");
|
||||
clearerr (ptp_unit.fileref);
|
||||
clearerr (uptr->fileref);
|
||||
return SCPE_IOERR; }
|
||||
ptp_unit.pos = ptp_unit.pos + 1;
|
||||
uptr->pos = uptr->pos + 1;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -417,24 +487,22 @@ return SCPE_OK;
|
|||
|
||||
t_stat tto_svc (UNIT *uptr)
|
||||
{
|
||||
int32 out;
|
||||
int32 c;
|
||||
t_stat r;
|
||||
|
||||
if (tty_buf == FIODEC_UC) tty_uc = UC; /* upper case? */
|
||||
else if (tty_buf == FIODEC_LC) tty_uc = 0; /* lower case? */
|
||||
else { c = fiodec_to_ascii[tty_buf | tty_uc]; /* translate */
|
||||
if (c && ((r = sim_putchar_s (c)) != SCPE_OK)) {/* output; error? */
|
||||
sim_activate (uptr, uptr->wait); /* retry */
|
||||
return ((r == SCPE_STALL)? SCPE_OK: r); } }
|
||||
if (cpls & CPLS_TTO) { /* completion pulse? */
|
||||
ios = 1; /* restart */
|
||||
cpls = cpls & ~CPLS_TTO; }
|
||||
iosta = iosta | IOS_TTO; /* set flag */
|
||||
sbs = sbs | SB_RQ; /* req seq break */
|
||||
if (tty_buf == FIODEC_UC) { /* upper case? */
|
||||
tty_uc = UC;
|
||||
return SCPE_OK; }
|
||||
if (tty_buf == FIODEC_LC) { /* lower case? */
|
||||
tty_uc = 0;
|
||||
return SCPE_OK; }
|
||||
out = fiodec_to_ascii[tty_buf | tty_uc]; /* translate */
|
||||
if (out == 0) return SCPE_OK; /* no translation? */
|
||||
sim_putchar (out);
|
||||
uptr->pos = uptr->pos + 1;
|
||||
if (out == '\r') { /* cr? add lf */
|
||||
if (c == '\r') { /* cr? add lf */
|
||||
sim_putchar ('\n');
|
||||
uptr->pos = uptr->pos + 1; }
|
||||
return SCPE_OK;
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
08-Dec-03 RMS Added parallel drum support, drum mnemonics
|
||||
18-Oct-03 RMS Added DECtape off reel message
|
||||
01-Sep-03 RMS Added support for loading in multiple fields
|
||||
22-Jul-03 RMS Updated for "hardware" RIM loader
|
||||
05-Dec-02 RMS Added drum support
|
||||
|
@ -48,6 +50,7 @@ extern DEVICE tty_dev;
|
|||
extern DEVICE lpt_dev;
|
||||
extern DEVICE dt_dev;
|
||||
extern DEVICE drm_dev;
|
||||
extern DEVICE drp_dev;
|
||||
extern UNIT cpu_unit;
|
||||
extern REG cpu_reg[];
|
||||
extern int32 M[];
|
||||
|
@ -80,6 +83,7 @@ DEVICE *sim_devices[] = {
|
|||
&lpt_dev,
|
||||
&dt_dev,
|
||||
&drm_dev,
|
||||
&drp_dev,
|
||||
NULL };
|
||||
|
||||
const char *sim_stop_messages[] = {
|
||||
|
@ -89,11 +93,12 @@ const char *sim_stop_messages[] = {
|
|||
"Breakpoint",
|
||||
"Nested XCT's",
|
||||
"Nested indirect addresses",
|
||||
"Infinite I/O wait state" };
|
||||
"Infinite I/O wait state",
|
||||
"DECtape off reel" };
|
||||
|
||||
/* Binary loader - supports both RIM format and Macro block format */
|
||||
|
||||
int32 getw (FILE *inf)
|
||||
int32 pdp1_getw (FILE *inf)
|
||||
{
|
||||
int32 i, tmp, word;
|
||||
|
||||
|
@ -111,11 +116,11 @@ t_stat rim_load (FILE *inf, int32 fld)
|
|||
int32 origin, val;
|
||||
|
||||
for (;;) {
|
||||
if ((val = getw (inf)) < 0) return SCPE_FMT;
|
||||
if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT;
|
||||
if (((val & 0760000) == OP_DIO) || /* DIO? */
|
||||
((val & 0760000) == OP_DAC)) { /* hack - Macro1 err */
|
||||
origin = val & DAMASK;
|
||||
if ((val = getw (inf)) < 0) return SCPE_FMT;
|
||||
if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT;
|
||||
M[fld | origin] = val; }
|
||||
else if ((val & 0760000) == OP_JMP) { /* JMP? */
|
||||
PC = fld | (val & DAMASK);
|
||||
|
@ -130,23 +135,23 @@ t_stat blk_load (FILE *inf, int32 fld)
|
|||
int32 val, start, count, csum;
|
||||
|
||||
for (;;) {
|
||||
if ((val = getw (inf)) < 0) return SCPE_FMT; /* get word, EOF? */
|
||||
if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT; /* get word, EOF? */
|
||||
if ((val & 0760000) == OP_DIO) { /* DIO? */
|
||||
csum = val; /* init checksum */
|
||||
start = val & DAMASK; /* starting addr */
|
||||
if ((val = getw (inf)) < 0) return SCPE_FMT;
|
||||
if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT;
|
||||
if ((val & 0760000) != OP_DIO) return SCPE_FMT;
|
||||
csum = csum + val;
|
||||
if (csum > 0777777) csum = (csum + 1) & 0777777;
|
||||
count = (val & DAMASK) - start + 1; /* block count */
|
||||
if (count <= 0) return SCPE_FMT;
|
||||
while (count--) { /* loop on data */
|
||||
if ((val = getw (inf)) < 0) return SCPE_FMT;
|
||||
if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT;
|
||||
csum = csum + val;
|
||||
if (csum > 0777777) csum = (csum + 1) & 0777777;
|
||||
M[fld | start] = val;
|
||||
start = (start + 1) & DAMASK; }
|
||||
if ((val = getw (inf)) < 0) return SCPE_FMT;
|
||||
if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT;
|
||||
if (val != csum) return SCPE_CSUM; }
|
||||
else if ((val & 0760000) == OP_JMP) { /* JMP? */
|
||||
PC = fld | (val & DAMASK);
|
||||
|
@ -213,6 +218,9 @@ static const char *opcode[] = {
|
|||
"LSM", "ESM", "CBS",
|
||||
"LEM", "EEM", "CKS",
|
||||
"MSE", "MLC", "MRD", "MWR", "MRS",
|
||||
"DIA", "DBA", "DWC", "DRA", "DCL",
|
||||
"DRD", "DWR", "DBL", "DCN",
|
||||
"DTD", "DSE", "DSP",
|
||||
|
||||
"SKP", "SKP I", "CLO",
|
||||
"SFT", "LAW", "OPR",
|
||||
|
@ -265,6 +273,9 @@ static const int32 opc_val[] = {
|
|||
0720054+I_NPN, 0720055+I_NPN, 0720056+I_NPN,
|
||||
0720074+I_NPN, 0724074+I_NPN, 0720033+I_NPN,
|
||||
0720301+I_NPN, 0720401+I_NPN, 0720501+I_NPN, 0720601+I_NPN, 0720701+I_NPN,
|
||||
0720061+I_NPN, 0722061+I_NPN, 0720062+I_NPN, 0722062+I_NPN, 0720063+I_NPN,
|
||||
0720161+I_NPN, 0721161+I_NPN, 0720162+I_NPN, 0721162+I_NPN,
|
||||
0720163+I_NPN, 0720164+I_NPN, 0721164+I_NPN,
|
||||
|
||||
0640000+I_NPN, 0650000+I_NPN, 0651600+I_NPN,
|
||||
0660000+I_NPN, 0700000+I_LAW, 0760000+I_NPN,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp10_defs.h: PDP-10 simulator definitions
|
||||
|
||||
Copyright (c) 1993-2003, Robert M Supnik
|
||||
Copyright (c) 1993-2004, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -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.
|
||||
|
||||
29-Dec-03 RMS Added Q18 definition for PDP11 compatibility
|
||||
19-May-03 RMS Revised for new conditional compilation scheme
|
||||
09-Jan-03 RMS Added DEUNA/DELUA support
|
||||
29-Sep-02 RMS Added variable vector, RX211 support
|
||||
|
@ -609,9 +610,11 @@ typedef struct pdp_dib DIB;
|
|||
|
||||
#define DEV_V_UBUS (DEV_V_UF + 0) /* Unibus */
|
||||
#define DEV_V_QBUS (DEV_V_UF + 1) /* Qbus */
|
||||
#define DEV_V_FLTA (DEV_V_UF + 2) /* float addr */
|
||||
#define DEV_V_Q18 (DEV_V_UF + 2) /* Qbus, mem <= 256KB */
|
||||
#define DEV_V_FLTA (DEV_V_UF + 3) /* float addr */
|
||||
#define DEV_UBUS (1u << DEV_V_UBUS)
|
||||
#define DEV_QBUS (1u << DEV_V_QBUS)
|
||||
#define DEV_Q18 (1u << DEV_V_Q18)
|
||||
#define DEV_FLTA (1u << DEV_V_FLTA)
|
||||
|
||||
#define UNIBUS TRUE /* 18b only */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp10_fe.c: PDP-10 front end (console terminal) simulator
|
||||
|
||||
Copyright (c) 1993-2003, Robert M Supnik
|
||||
Copyright (c) 1993-2004, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -25,6 +25,7 @@
|
|||
|
||||
fe KS10 console front end
|
||||
|
||||
29-Dec-03 RMS Added console backpressure support
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
22-Dec-02 RMS Added break support
|
||||
30-May-02 RMS Widened COUNT to 32b
|
||||
|
@ -108,9 +109,8 @@ void fe_intr (void)
|
|||
{
|
||||
if (M[FE_CTYOUT] & FE_CVALID) { /* char to print? */
|
||||
feo_unit.buf = (int32) M[FE_CTYOUT] & 0177; /* pick it up */
|
||||
sim_putchar (feo_unit.buf); /* type it */
|
||||
feo_unit.pos = feo_unit.pos + 1;
|
||||
sim_activate (&feo_unit, feo_unit.time); } /* sched completion */
|
||||
sim_activate (&feo_unit, feo_unit.wait); } /* sched completion */
|
||||
else if ((M[FE_CTYIN] & FE_CVALID) == 0) { /* input char taken? */
|
||||
sim_cancel (&fei_unit); /* sched immediate */
|
||||
sim_activate (&fei_unit, 0); }; /* keyboard poll */
|
||||
|
@ -119,6 +119,11 @@ return;
|
|||
|
||||
t_stat feo_svc (UNIT *uptr)
|
||||
{
|
||||
t_stat r;
|
||||
|
||||
if ((r = sim_putchar_s (uptr->buf)) != SCPE_OK) { /* output; error? */
|
||||
sim_activate (uptr, uptr->wait); /* try again */
|
||||
return ((r == SCPE_STALL)? SCPE_OK: r); } /* !stall? report */
|
||||
M[FE_CTYOUT] = 0; /* clear char */
|
||||
apr_flg = apr_flg | APRF_CON; /* interrupt KS10 */
|
||||
return SCPE_OK;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp10_lp20.c: PDP-10 LP20 line printer simulator
|
||||
|
||||
Copyright (c) 1993-2003, Robert M Supnik
|
||||
Copyright (c) 1993-2004, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -25,6 +25,7 @@
|
|||
|
||||
lp20 line printer
|
||||
|
||||
29-Dec-03 RMS Fixed bug in scheduling
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
29-Sep-02 RMS Added variable vector support
|
||||
Modified to use common Unibus routines
|
||||
|
@ -283,7 +284,7 @@ case 00: /* LPCSA */
|
|||
if ((lpcsa & CSA_GO) == 0) { /* not set before? */
|
||||
if (lpcsb & CSB_ERR) lpcsb = lpcsb | CSB_GOE;
|
||||
lpcsum = 0; /* clear checksum */
|
||||
sim_activate (&lp20_unit, lp20_unit.time); } }
|
||||
sim_activate (&lp20_unit, lp20_unit.wait); } }
|
||||
else sim_cancel (&lp20_unit); /* go clr, stop DMA */
|
||||
lpcsa = (lpcsa & ~CSA_RW) | (data & CSA_RW);
|
||||
break;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp11_cpu.c: PDP-11 CPU simulator
|
||||
|
||||
Copyright (c) 1993-2003, Robert M Supnik
|
||||
Copyright (c) 1993-2004, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -25,6 +25,8 @@
|
|||
|
||||
cpu PDP-11 CPU (J-11 microprocessor)
|
||||
|
||||
29-Dec-03 RMS Formalized 18b Qbus support
|
||||
21-Dec-03 RMS Added autoconfiguration controls
|
||||
05-Jun-03 RMS Fixed bugs in memory size table
|
||||
12-Mar-03 RMS Added logical name support
|
||||
01-Feb-03 RMS Changed R display to follow PSW<rs>, added SP display
|
||||
|
@ -276,6 +278,7 @@ int32 stop_vecabort = 1; /* stop on vec abort */
|
|||
int32 stop_spabort = 1; /* stop on SP abort */
|
||||
int32 wait_enable = 0; /* wait state enable */
|
||||
int32 cpu_log = 0; /* logging */
|
||||
int32 autcon_enb = 1; /* autoconfig enable */
|
||||
uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
|
||||
int32 pcq_p = 0; /* PC queue ptr */
|
||||
REG *pcq_r = NULL; /* PC queue reg ptr */
|
||||
|
@ -323,6 +326,8 @@ void set_r_display (int32 rs, int32 cm);
|
|||
|
||||
extern t_stat build_dib_tab (int32 ubm);
|
||||
extern t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
extern t_stat set_autocon (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
extern t_stat show_autocon (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
extern t_stat iopageR (int32 *data, uint32 addr, int32 access);
|
||||
extern t_stat iopageW (int32 data, uint32 addr, int32 access);
|
||||
extern int32 calc_ints (int32 nipl, int32 trq);
|
||||
|
@ -532,6 +537,7 @@ REG cpu_reg[] = {
|
|||
{ GRDATA (UDPAR7, APRFILE[077], 8, 16, 16) },
|
||||
{ GRDATA (UDPDR7, APRFILE[077], 8, 16, 0) },
|
||||
{ BRDATA (UBMAP, ub_map, 8, 22, UBM_LNT_LW) },
|
||||
{ FLDATA (AUTOCON, autcon_enb, 0), REG_HRO },
|
||||
{ BRDATA (PCQ, pcq, 8, 16, PCQ_SIZE), REG_RO+REG_CIRC },
|
||||
{ ORDATA (PCQP, pcq_p, 6), REG_HRO },
|
||||
{ ORDATA (WRU, sim_int_char, 8) },
|
||||
|
@ -539,10 +545,10 @@ REG cpu_reg[] = {
|
|||
{ NULL} };
|
||||
|
||||
MTAB cpu_mod[] = {
|
||||
{ UNIT_MAP, UNIT_18B, "18b addressing", "18B", NULL },
|
||||
{ UNIT_MAP, UNIT_18B, "18b Unibus", "U18", &cpu_set_bus },
|
||||
{ UNIT_MAP, UNIT_UBM, "22b Unibus + RH70", "URH70", &cpu_set_bus },
|
||||
{ UNIT_MAP, UNIT_UBM + UNIT_RH11, "22b Unibus + RH11", "URH11", &cpu_set_bus },
|
||||
{ UNIT_MAP, 0, "22b addressing", "22B", &cpu_set_bus },
|
||||
{ UNIT_MAP, 0, "22b Qbus", "Q22", &cpu_set_bus },
|
||||
{ UNIT_CIS, UNIT_CIS, "CIS", "CIS", NULL },
|
||||
{ UNIT_CIS, 0, "no CIS", "NOCIS", NULL },
|
||||
{ UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size},
|
||||
|
@ -566,6 +572,10 @@ MTAB cpu_mod[] = {
|
|||
{ UNIT_MSIZE, 4186112, NULL, "4M", &cpu_set_size},
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "IOSPACE", NULL,
|
||||
NULL, &show_iospace },
|
||||
{ MTAB_XTD|MTAB_VDV, 1, "AUTOCONFIG", "AUTOCONFIG",
|
||||
&set_autocon, &show_autocon },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, NULL, "NOAUTOCONFIG",
|
||||
&set_autocon, NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE cpu_dev = {
|
||||
|
@ -2467,23 +2477,24 @@ for (i = 0; i < clim; i = i + 2) nM[i >> 1] = M[i >> 1];
|
|||
free (M);
|
||||
M = nM;
|
||||
MEMSIZE = val;
|
||||
return cpu_set_bus (uptr, (cpu_unit.flags & UNIT_MAP) | 1, cptr, desc); }
|
||||
return cpu_set_bus (uptr, cpu_unit.flags, cptr, desc); }
|
||||
|
||||
/* Bus configuration, disable Unibus or Qbus devices */
|
||||
|
||||
t_stat cpu_set_bus (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
DEVICE *dptr;
|
||||
uint32 i, target;
|
||||
uint32 i, mask;
|
||||
|
||||
if ((MEMSIZE <= UNIMEMSIZE) || (val & UNIT_18B) ||
|
||||
(!(val & 1) && ((uint32) val == (cpu_unit.flags & UNIT_MAP)))) return SCPE_OK;
|
||||
if (val & UNIT_MAP) target = DEV_QBUS; /* going to Ubus? */
|
||||
else target = DEV_UBUS; /* going to Qbus */
|
||||
if ((val & UNIT_MAP) || (val & UNIT_18B)) /* Unibus variant? */
|
||||
mask = DEV_UBUS;
|
||||
else if (MEMSIZE <= UNIMEMSIZE) /* 18b Qbus? */
|
||||
mask = DEV_QBUS | DEV_Q18;
|
||||
else mask = DEV_QBUS; /* must be 22b */
|
||||
for (i = 0; (dptr = sim_devices[i]) != NULL; i++) {
|
||||
if ((dptr->flags & DEV_DISABLE) && /* disable-able? */
|
||||
!(dptr->flags & DEV_DIS) && /* enabled? */
|
||||
((dptr->flags & (DEV_QBUS|DEV_UBUS)) == target)) {
|
||||
((dptr->flags & mask) == 0)) { /* not allowed? */
|
||||
printf ("Disabling %s\n", sim_dname (dptr));
|
||||
if (sim_log) fprintf (sim_log, "Disabling %s\n", sim_dname (dptr));
|
||||
dptr->flags = dptr->flags | DEV_DIS; } }
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
The author gratefully acknowledges the help of Max Burnet, Megan Gentry,
|
||||
and John Wilson in resolving questions about the PDP-11
|
||||
|
||||
22-Dec-03 RMS Added second DEUNA/DELUA support
|
||||
18-Oct-03 RMS Added DECtape off reel message
|
||||
19-May-03 RMS Revised for new conditional compilation
|
||||
05-Apr-03 RMS Fixed bug in MMR1 update (found by Tim Stark)
|
||||
28-Feb-03 RMS Added TM logging support
|
||||
|
@ -295,6 +297,7 @@ typedef struct fpac fpac_t;
|
|||
#define STOP_SPABORT (TRAP_V_MAX + 5) /* abort trap push */
|
||||
#define STOP_RQ (TRAP_V_MAX + 6) /* RQDX3 panic */
|
||||
#define STOP_SANITY (TRAP_V_MAX + 7) /* sanity timer exp */
|
||||
#define STOP_DTOFF (TRAP_V_MAX + 8) /* DECtape off reel */
|
||||
#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* cond error return */
|
||||
|
||||
/* Timers */
|
||||
|
@ -312,9 +315,11 @@ typedef struct fpac fpac_t;
|
|||
|
||||
#define DEV_V_UBUS (DEV_V_UF + 0) /* Unibus */
|
||||
#define DEV_V_QBUS (DEV_V_UF + 1) /* Qbus */
|
||||
#define DEV_V_FLTA (DEV_V_UF + 2) /* flt addr */
|
||||
#define DEV_V_Q18 (DEV_V_UF + 2) /* Qbus with <= 256KB */
|
||||
#define DEV_V_FLTA (DEV_V_UF + 3) /* flt addr */
|
||||
#define DEV_UBUS (1u << DEV_V_UBUS)
|
||||
#define DEV_QBUS (1u << DEV_V_QBUS)
|
||||
#define DEV_Q18 (1u << DEV_V_Q18)
|
||||
#define DEV_FLTA (1u << DEV_V_FLTA)
|
||||
|
||||
#define UNIBUS (cpu_18b || cpu_ubm) /* T if 18b */
|
||||
|
@ -341,10 +346,12 @@ struct pdp_dib {
|
|||
|
||||
typedef struct pdp_dib DIB;
|
||||
|
||||
/* I/O page layout - RQB,RQC,RQD float based on number of DZ's */
|
||||
/* I/O page layout - XUB, RQB,RQC,RQD float based on number of DZ's */
|
||||
|
||||
#define IOBA_DZ (IOPAGEBASE + 000100) /* DZ11 */
|
||||
#define IOLN_DZ 010
|
||||
#define IOBA_XUB (IOPAGEBASE + 000330 + (020 * (DZ_MUXES / 2)))
|
||||
#define IOLN_XUB 010
|
||||
#define IOBA_RQB (IOPAGEBASE + 000334 + (020 * (DZ_MUXES / 2)))
|
||||
#define IOLN_RQB 004
|
||||
#define IOBA_RQC (IOPAGEBASE + IOBA_RQB + IOLN_RQB)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
To: Users
|
||||
From: Bob Supnik
|
||||
Subj: PDP-11 Simulator Usage
|
||||
Date: 15-Sep-2003
|
||||
Date: 15-Dec-2003
|
||||
|
||||
COPYRIGHT NOTICE
|
||||
|
||||
|
@ -127,6 +127,7 @@ The PDP-11 simulator implements several unique stop conditions:
|
|||
- trap condition 'n' occurs, and register STOP_TRAP<n> is set
|
||||
- wait state entered, and no I/O operations outstanding
|
||||
(ie, no interrupt can ever occur)
|
||||
- a simulated DECtape runs off the end of its reel
|
||||
|
||||
The PDP-11 loader supports standard binary format tapes. The DUMP command
|
||||
is not implemented.
|
||||
|
@ -289,11 +290,13 @@ In addition to autoconfiguration, most devices support the SET ADDRESS
|
|||
command, which allows the I/O page address of the device to be changed,
|
||||
and the SET VECTOR command, which allows the vector of the device to be
|
||||
changed. Explicitly setting the I/O address of a device which normally
|
||||
uses autoconfiguration DISABLES autoconfiguration for that device. As
|
||||
a consequence, the user may have to manually configure all other
|
||||
autoconfigured devices, because the autoconfiguration algorithm no
|
||||
longer recognizes the explicitly configured device. A device can be
|
||||
reset to autoconfigure with the SET <device> AUTOCONFIGURE command.
|
||||
uses autoconfiguration DISABLES autoconfiguration for that device and for
|
||||
the entire system. As a consequence, the user may have to manually configure
|
||||
all other autoconfigured devices, because the autoconfiguration algorithm
|
||||
no longer recognizes the explicitly configured device. A device can be
|
||||
reset to autoconfigure with the SET <device> AUTOCONFIGURE command. Auto-
|
||||
configuration can be restored for the entire system with the SET CPU
|
||||
AUTOCONFIGURE command.
|
||||
|
||||
The current I/O map can be displayed with the SHOW CPU IOSPACE command.
|
||||
Addresses that have set by autoconfiguration are marked with an asterisk (*).
|
||||
|
@ -994,7 +997,6 @@ The TC controller implements these registers:
|
|||
IE 1 interrupt enable flag
|
||||
CTIME 31 time to complete transport stop
|
||||
LTIME 31 time between lines
|
||||
ACTIME 31 time to accelerate to full speed
|
||||
DCTIME 31 time to decelerate to a full stop
|
||||
SUBSTATE 2 read/write command substate
|
||||
POS[0:7] 32 position, in lines, units 0-7
|
||||
|
@ -1005,8 +1007,9 @@ among the DECtape parameters, or the DECtape simulator will fail to
|
|||
operate correctly.
|
||||
|
||||
- LTIME must be at least 6
|
||||
- ACTIME must be less than DCTIME, and both need to be at
|
||||
least 100 times LTIME
|
||||
- DCTIME needs to be at least 100 times LTIME
|
||||
|
||||
Acceleration time is set to 75% of deceleration time.
|
||||
|
||||
2.9 Magnetic Tape Controllers
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
hk RK611/RK06/RK07 disk
|
||||
|
||||
29-Dec-03 RMS Added 18b Qbus support
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
|
||||
This is a somewhat abstracted implementation of the RK611, more closely
|
||||
|
@ -438,7 +439,7 @@ DEVICE hk_dev = {
|
|||
HK_NUMDR, HK_RDX, 24, 1, HK_RDX, HK_WID,
|
||||
NULL, NULL, &hk_reset,
|
||||
&hk_boot, &hk_attach, &hk_detach,
|
||||
&hk_dib, DEV_DISABLE | DEV_UBUS };
|
||||
&hk_dib, DEV_DISABLE | DEV_UBUS | DEV_Q18 };
|
||||
|
||||
/* I/O dispatch routines, I/O addresses 17777440 - 17777476 */
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
21-Dec-03 RMS Fixed bug in autoconfigure vector assignment; added controls
|
||||
21-Nov-03 RMS Added check for interrupt slot conflict (found by Dave Hittner)
|
||||
12-Mar-03 RMS Added logical name support
|
||||
08-Oct-02 RMS Trimmed I/O bus addresses
|
||||
Added support for dynamic tables
|
||||
|
@ -43,6 +45,7 @@ extern UNIT cpu_unit;
|
|||
extern int32 cpu_bme, cpu_18b, cpu_ubm;
|
||||
extern int32 trap_req, ipl;
|
||||
extern int32 cpu_log;
|
||||
extern int32 autcon_enb;
|
||||
extern FILE *sim_log;
|
||||
extern DEVICE *sim_devices[];
|
||||
|
||||
|
@ -297,6 +300,24 @@ else { /* physical */
|
|||
return (lim - alim); }
|
||||
}
|
||||
|
||||
/* Enable/disable autoconfiguration */
|
||||
|
||||
t_stat set_autocon (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if (cptr != NULL) return SCPE_ARG;
|
||||
autcon_enb = val;
|
||||
return auto_config (0, 0);
|
||||
}
|
||||
|
||||
/* Show autoconfiguration status */
|
||||
|
||||
t_stat show_autocon (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
fprintf (st, "autoconfiguration ");
|
||||
fprintf (st, autcon_enb? "enabled": "disabled");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Change device address */
|
||||
|
||||
t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
|
@ -318,7 +339,8 @@ if ((newba <= IOPAGEBASE) || /* > IO page base? */
|
|||
(newba % ((uint32) val))) return SCPE_ARG; /* check modulus */
|
||||
dibp->ba = newba; /* store */
|
||||
dptr->flags = dptr->flags & ~DEV_FLTA; /* not floating */
|
||||
return auto_config (0, 0); /* autoconfigure */
|
||||
autcon_enb = 0; /* autoconfig off */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Show device address */
|
||||
|
@ -374,6 +396,8 @@ if ((r != SCPE_OK) || (newvec <= VEC_Q) ||
|
|||
((newvec + (dibp->vnum * 4)) >= (VEC_Q + 01000)) ||
|
||||
(newvec & ((dibp->vnum > 1)? 07: 03))) return SCPE_ARG;
|
||||
dibp->vec = newvec;
|
||||
dptr->flags = dptr->flags & ~DEV_FLTA; /* not floating */
|
||||
autcon_enb = 0; /* autoconfig off */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -427,14 +451,20 @@ return FALSE;
|
|||
|
||||
/* Build interrupt tables */
|
||||
|
||||
void build_int_vec (int32 vloc, int32 ivec, int32 (*iack)(void) )
|
||||
t_bool build_int_vec (int32 vloc, int32 ivec, int32 (*iack)(void) )
|
||||
{
|
||||
int32 ilvl = vloc / 32;
|
||||
int32 ibit = vloc % 32;
|
||||
|
||||
if (iack != NULL) int_ack[ilvl][ibit] = iack;
|
||||
else int_vec[ilvl][ibit] = ivec;
|
||||
return;
|
||||
if (iack != NULL) {
|
||||
if (int_ack[ilvl][ibit] &&
|
||||
(int_ack[ilvl][ibit] != iack)) return TRUE;
|
||||
int_ack[ilvl][ibit] = iack; }
|
||||
else if (ivec != 0) {
|
||||
if (int_vec[ilvl][ibit] &&
|
||||
(int_vec[ilvl][ibit] != ivec)) return TRUE;
|
||||
int_vec[ilvl][ibit] = ivec; }
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Build dib_tab from device list */
|
||||
|
@ -453,9 +483,15 @@ for (i = j = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */
|
|||
dibp = (DIB *) dptr->ctxt; /* get DIB */
|
||||
if (dibp && !(dptr->flags & DEV_DIS)) { /* defined, enabled? */
|
||||
if (dibp->vnum > VEC_DEVMAX) return SCPE_IERR;
|
||||
for (k = 0; k < dibp->vnum; k++) /* loop thru vec */
|
||||
build_int_vec (dibp->vloc + k, /* add vector */
|
||||
dibp->vec + (k * 4), dibp->ack[k]);
|
||||
for (k = 0; k < dibp->vnum; k++) { /* loop thru vec */
|
||||
if (build_int_vec (dibp->vloc + k, /* add vector */
|
||||
dibp->vec + (k * 4), dibp->ack[k])) {
|
||||
printf ("Device %s interrupt slot conflict at %d\n",
|
||||
sim_dname (dptr), dibp->vloc + k);
|
||||
if (sim_log) fprintf (sim_log,
|
||||
"Device %s interrupt slot conflict at %d\n",
|
||||
sim_dname (dptr), dibp->vloc + k);
|
||||
return SCPE_IERR; } }
|
||||
if (dibp->lnt != 0) { /* I/O addresses? */
|
||||
dib_tab[j++] = dibp; /* add DIB to dib_tab */
|
||||
if (j >= DIB_MAX) return SCPE_IERR; } /* too many? */
|
||||
|
@ -575,6 +611,7 @@ DIB *dibp;
|
|||
int32 i, j, k;
|
||||
extern DEVICE *find_dev (char *ptr);
|
||||
|
||||
if (autcon_enb == 0) return SCPE_OK; /* enabled? */
|
||||
if (rank > AUTO_LNT) return SCPE_IERR; /* legal rank? */
|
||||
if (rank) auto_tab[rank - 1].num = nctrl; /* update num? */
|
||||
for (i = 0, autp = auto_tab; i < AUTO_LNT; i++) { /* loop thru table */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp11_rk.c: RK11 cartridge disk simulator
|
||||
/* pdp11_rk.c: RK11/RKV11 cartridge disk simulator
|
||||
|
||||
Copyright (c) 1993-2003, Robert M Supnik
|
||||
Copyright (c) 1993-2004, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,8 +23,9 @@
|
|||
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.
|
||||
|
||||
rk RK11/RK05 cartridge disk
|
||||
rk RK11/RKV11/RK05 cartridge disk
|
||||
|
||||
29-Dec-03 RMS Added RKV11 support
|
||||
29-Sep-02 RMS Added variable address support to bootstrap
|
||||
Added vector change/display support
|
||||
Revised mapping mnemonics
|
||||
|
@ -261,7 +262,7 @@ DEVICE rk_dev = {
|
|||
RK_NUMDR, 8, 24, 1, 8, 16,
|
||||
NULL, NULL, &rk_reset,
|
||||
&rk_boot, NULL, NULL,
|
||||
&rk_dib, DEV_DISABLE | DEV_UBUS };
|
||||
&rk_dib, DEV_DISABLE | DEV_UBUS | DEV_Q18 };
|
||||
|
||||
/* I/O dispatch routine, I/O addresses 17777400 - 17777416
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
|
||||
rq RQDX3 disk controller
|
||||
|
||||
07-Oct-03 RMS Fixed problem with multiple RAUSER drives
|
||||
17-Sep-03 RMS Fixed MB to LBN conversion to be more accurate
|
||||
11-Jul-03 RMS Fixed bug in user disk size (found by Chaskiel M Grundman)
|
||||
19-May-03 RMS Revised for new conditional compilation scheme
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
|
@ -1422,7 +1424,8 @@ int32 rq_rw_valid (MSC *cp, int32 pkt, UNIT *uptr, uint32 cmd)
|
|||
uint32 dtyp = GET_DTYPE (uptr->flags); /* get drive type */
|
||||
uint32 lbn = GETP32 (pkt, RW_LBNL); /* get lbn */
|
||||
uint32 bc = GETP32 (pkt, RW_BCL); /* get byte cnt */
|
||||
uint32 maxlbn = drv_tab[dtyp].lbn; /* get max lbn */
|
||||
uint32 maxlbn = uptr->capac / RQ_NUMBY; /* get max lbn */
|
||||
/* uint32 maxlbn = drv_tab[dtyp].lbn; /* get max lbn */
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */
|
||||
return (ST_OFL | SB_OFL_NV); /* offl no vol */
|
||||
|
@ -1866,6 +1869,7 @@ return;
|
|||
void rq_putr_unit (MSC *cp, int32 pkt, UNIT *uptr, uint32 lu, t_bool all)
|
||||
{
|
||||
uint32 dtyp = GET_DTYPE (uptr->flags); /* get drive type */
|
||||
uint32 maxlbn = uptr->capac / RQ_NUMBY; /* get max lbn */
|
||||
|
||||
cp->pak[pkt].d[ONL_MLUN] = lu; /* unit */
|
||||
cp->pak[pkt].d[ONL_UFL] = uptr->uf | UF_RPL | RQ_WPH (uptr) | RQ_RMV (uptr);
|
||||
|
@ -1878,7 +1882,7 @@ cp->pak[pkt].d[ONL_UIDD] = (UID_DISK << ONL_UIDD_V_CLS) |
|
|||
(drv_tab[dtyp].mod << ONL_UIDD_V_MOD); /* UID hi */
|
||||
PUTP32 (pkt, ONL_MEDL, drv_tab[dtyp].med); /* media type */
|
||||
if (all) { /* if long form */
|
||||
PUTP32 (pkt, ONL_SIZL, drv_tab[dtyp].lbn); /* user LBNs */
|
||||
PUTP32 (pkt, ONL_SIZL, maxlbn); /* user LBNs */
|
||||
cp->pak[pkt].d[ONL_VSNL] = 01234 + lu; /* vol serial # */
|
||||
cp->pak[pkt].d[ONL_VSNH] = 0; }
|
||||
return;
|
||||
|
@ -2012,13 +2016,13 @@ if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
|
|||
if (cptr) {
|
||||
cap = (int32) get_uint (cptr, 10, max, &r);
|
||||
if ((r != SCPE_OK) || (cap < RA8U_MINC)) return SCPE_ARG;
|
||||
drv_tab[val].lbn = cap << (20 - 9); }
|
||||
drv_tab[val].lbn = cap * 1954; }
|
||||
uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (val << UNIT_V_DTYPE);
|
||||
uptr->capac = ((t_addr) drv_tab[val].lbn) * RQ_NUMBY;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Show unit type (and capacity if user defined) */
|
||||
/* Show unit type */
|
||||
|
||||
t_stat rq_show_type (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
|
@ -2034,7 +2038,6 @@ int32 dtyp = GET_DTYPE (uptr->flags);
|
|||
MSC *cp = rq_ctxmap[uptr->cnum];
|
||||
t_stat r;
|
||||
|
||||
uptr->capac = drv_tab[dtyp].lbn * RQ_NUMBY;
|
||||
r = attach_unit (uptr, cptr);
|
||||
if (r != SCPE_OK) return r;
|
||||
if (cp->csta == CST_UP) uptr->flags = uptr->flags | UNIT_ATP;
|
||||
|
|
|
@ -121,7 +121,7 @@ int32 rx_cwait = 100; /* command time */
|
|||
int32 rx_swait = 10; /* seek, per track */
|
||||
int32 rx_xwait = 1; /* tr set time */
|
||||
uint8 rx_buf[RX_NUMBY] = { 0 }; /* sector buffer */
|
||||
static int32 bptr = 0; /* buffer pointer */
|
||||
int32 rx_bptr = 0; /* buffer pointer */
|
||||
int32 rx_enb = 1; /* device enable */
|
||||
|
||||
DEVICE rx_dev;
|
||||
|
@ -157,7 +157,7 @@ REG rx_reg[] = {
|
|||
{ ORDATA (RXTA, rx_track, 8) },
|
||||
{ ORDATA (RXSA, rx_sector, 8) },
|
||||
{ DRDATA (STAPTR, rx_state, 3), REG_RO },
|
||||
{ DRDATA (BUFPTR, bptr, 7) },
|
||||
{ DRDATA (BUFPTR, rx_bptr, 7) },
|
||||
{ FLDATA (INT, IREQ (RX), INT_V_RX) },
|
||||
{ FLDATA (ERR, rx_csr, RXCS_V_ERR) },
|
||||
{ FLDATA (TR, rx_csr, RXCS_V_TR) },
|
||||
|
@ -237,7 +237,7 @@ case 0: /* RXCS */
|
|||
if ((data & CSR_GO) && (rx_state == IDLE)) { /* new function? */
|
||||
rx_csr = data & (RXCS_IE + RXCS_DRV + RXCS_FUNC);
|
||||
drv = ((rx_csr & RXCS_DRV)? 1: 0); /* reselect drive */
|
||||
bptr = 0; /* clear buf pointer */
|
||||
rx_bptr = 0; /* clear buf pointer */
|
||||
switch (RXCS_GETFNC (data)) { /* case on func */
|
||||
case RXCS_FILL:
|
||||
rx_state = FILL; /* state = fill */
|
||||
|
@ -287,10 +287,10 @@ return SCPE_OK;
|
|||
RWDS Save sector, set TR, set RWDT
|
||||
RWDT Save track, set RWXFR
|
||||
RWXFR Read/write buffer
|
||||
FILL copy ir to rx_buf[bptr], advance ptr
|
||||
if bptr > max, finish command, else set tr
|
||||
EMPTY if bptr > max, finish command, else
|
||||
copy rx_buf[bptr] to ir, advance ptr, set tr
|
||||
FILL copy ir to rx_buf[rx_bptr], advance ptr
|
||||
if rx_bptr > max, finish command, else set tr
|
||||
EMPTY if rx_bptr > max, finish command, else
|
||||
copy rx_buf[rx_bptr] to ir, advance ptr, set tr
|
||||
CMD_COMPLETE copy requested data to ir, finish command
|
||||
INIT_COMPLETE read drive 0, track 1, sector 1 to buffer, finish command
|
||||
|
||||
|
@ -302,6 +302,7 @@ t_stat rx_svc (UNIT *uptr)
|
|||
{
|
||||
int32 i, func;
|
||||
uint32 da;
|
||||
int8 *fbuf = uptr->filebuf;
|
||||
|
||||
func = RXCS_GETFNC (rx_csr); /* get function */
|
||||
switch (rx_state) { /* case on state */
|
||||
|
@ -310,17 +311,17 @@ case IDLE: /* idle */
|
|||
return SCPE_IERR; /* done */
|
||||
|
||||
case EMPTY: /* empty buffer */
|
||||
if (bptr >= RX_NUMBY) rx_done (0, 0); /* done all? */
|
||||
if (rx_bptr >= RX_NUMBY) rx_done (0, 0); /* done all? */
|
||||
else {
|
||||
rx_dbr = rx_buf[bptr]; /* get next */
|
||||
bptr = bptr + 1;
|
||||
rx_dbr = rx_buf[rx_bptr]; /* get next */
|
||||
rx_bptr = rx_bptr + 1;
|
||||
rx_csr = rx_csr | RXCS_TR; } /* set xfer */
|
||||
break;
|
||||
|
||||
case FILL: /* fill buffer */
|
||||
rx_buf[bptr] = rx_dbr; /* write next */
|
||||
bptr = bptr + 1;
|
||||
if (bptr < RX_NUMBY) rx_csr = rx_csr | RXCS_TR; /* if more, set xfer */
|
||||
rx_buf[rx_bptr] = rx_dbr; /* write next */
|
||||
rx_bptr = rx_bptr + 1;
|
||||
if (rx_bptr < RX_NUMBY) rx_csr = rx_csr | RXCS_TR; /* more? set xfer */
|
||||
else rx_done (0, 0); /* else done */
|
||||
break;
|
||||
|
||||
|
@ -350,13 +351,13 @@ case RWXFR:
|
|||
if (func == RXCS_WRDEL) rx_esr = rx_esr | RXES_DD; /* del data? */
|
||||
if (func == RXCS_READ) { /* read? */
|
||||
for (i = 0; i < RX_NUMBY; i++)
|
||||
rx_buf[i] = *(((int8 *) uptr->filebuf) + da + i); }
|
||||
rx_buf[i] = fbuf[da + i]; }
|
||||
else {
|
||||
if (uptr->flags & UNIT_WPRT) { /* write and locked? */
|
||||
rx_done (RXES_WLK, 0100); /* done, error */
|
||||
break; }
|
||||
for (i = 0; i < RX_NUMBY; i++) /* write */
|
||||
*(((int8 *) uptr->filebuf) + da + i) = rx_buf[i];
|
||||
fbuf[da + i] = rx_buf[i];
|
||||
da = da + RX_NUMBY;
|
||||
if (da > uptr->hwmark) uptr->hwmark = da; }
|
||||
rx_done (0, 0); /* done */
|
||||
|
@ -377,7 +378,7 @@ case INIT_COMPLETE: /* init complete */
|
|||
break; }
|
||||
da = CALC_DA (1, 1); /* track 1, sector 1 */
|
||||
for (i = 0; i < RX_NUMBY; i++) /* read sector */
|
||||
rx_buf[i] = *(((int8 *) uptr->filebuf) + da + i);
|
||||
rx_buf[i] = fbuf[da + i];
|
||||
rx_done (RXES_ID, 0); /* set done */
|
||||
if ((rx_unit[1].flags & UNIT_ATT) == 0) rx_ecode = 0020;
|
||||
break; } /* end case state */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp11_ry.c: RY11/RX02 floppy disk simulator
|
||||
/* pdp11_ry.c: RX211/RXV21/RX02 floppy disk simulator
|
||||
|
||||
Copyright (c) 1993-2003, Robert M Supnik
|
||||
Copyright (c) 1993-2004, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,8 +23,9 @@
|
|||
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.
|
||||
|
||||
ry RY11/RX02 floppy disk
|
||||
ry RX211/RXV21/RX02 floppy disk
|
||||
|
||||
29-Dec-03 RMS Added RXV21 support
|
||||
19-May-03 RMS Revised for new conditional compilation scheme
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
14-Mar-03 RMS Fixed variable size interaction with save/restore
|
||||
|
@ -146,7 +147,6 @@ int32 ry_cwait = 100; /* command time */
|
|||
int32 ry_swait = 10; /* seek, per track */
|
||||
int32 ry_xwait = 1; /* tr set time */
|
||||
uint8 rx2xb[RY_NUMBY] = { 0 }; /* sector buffer */
|
||||
int32 ry_enb = 0; /* device enable */
|
||||
|
||||
DEVICE ry_dev;
|
||||
t_stat ry_rd (int32 *data, int32 PA, int32 access);
|
||||
|
@ -227,7 +227,7 @@ DEVICE ry_dev = {
|
|||
RX_NUMDR, 8, 20, 1, 8, 8,
|
||||
NULL, NULL, &ry_reset,
|
||||
&ry_boot, &ry_attach, NULL,
|
||||
&ry_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS };
|
||||
&ry_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_Q18 };
|
||||
|
||||
/* I/O dispatch routine, I/O addresses 17777170 - 17777172
|
||||
|
||||
|
@ -341,6 +341,7 @@ t_stat ry_svc (UNIT *uptr)
|
|||
int32 i, t, func, bps;
|
||||
static uint8 estat[8];
|
||||
uint32 ba, da;
|
||||
int8 *fbuf = uptr->filebuf;
|
||||
|
||||
func = RYCS_GETFNC (ry_csr); /* get function */
|
||||
bps = (ry_csr & RYCS_DEN)? RY_NUMBY: RX_NUMBY; /* get sector size */
|
||||
|
@ -401,12 +402,12 @@ case RWXFR: /* read/write */
|
|||
if (func == RYCS_WRDEL) ry_esr = ry_esr | RYES_DD; /* del data? */
|
||||
if (func == RYCS_READ) { /* read? */
|
||||
for (i = 0; i < bps; i++)
|
||||
rx2xb[i] = *(((int8 *) uptr->filebuf) + da + i); }
|
||||
rx2xb[i] = fbuf[da + i]; }
|
||||
else { if (uptr->flags & UNIT_WPRT) { /* write and locked? */
|
||||
ry_done (0, 0100); /* done, error */
|
||||
break; }
|
||||
for (i = 0; i < bps; i++) /* write */
|
||||
*(((int8 *) uptr->filebuf) + da + i) = rx2xb[i];
|
||||
fbuf[da + i] = rx2xb[i];
|
||||
da = da + bps;
|
||||
if (da > uptr->hwmark) uptr->hwmark = da; }
|
||||
ry_done (0, 0); /* done */
|
||||
|
@ -420,8 +421,7 @@ case SDCNF: /* confirm set density */
|
|||
sim_activate (uptr, ry_cwait * 100); /* schedule operation */
|
||||
break;
|
||||
case SDXFR: /* erase disk */
|
||||
for (i = 0; i < (int32) uptr->capac; i++)
|
||||
*(((int8 *) uptr->filebuf) + i) = 0;
|
||||
for (i = 0; i < (int32) uptr->capac; i++) fbuf[i] = 0;
|
||||
uptr->hwmark = uptr->capac;
|
||||
if (ry_csr & RYCS_DEN) uptr->flags = uptr->flags | UNIT_DEN;
|
||||
else uptr->flags = uptr->flags & ~UNIT_DEN;
|
||||
|
@ -462,7 +462,7 @@ case INIT_COMPLETE: /* init complete */
|
|||
break; }
|
||||
da = CALC_DA (1, 1, bps); /* track 1, sector 1 */
|
||||
for (i = 0; i < bps; i++) /* read sector */
|
||||
rx2xb[i] = *(((int8 *) uptr->filebuf) + da + i);
|
||||
rx2xb[i] = fbuf[da + i];
|
||||
ry_done (RYES_ID, 0); /* set done */
|
||||
if ((ry_unit[1].flags & UNIT_ATT) == 0) ry_ecode = 0020;
|
||||
break; } /* end case state */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp11_stddev.c: PDP-11 standard I/O devices simulator
|
||||
|
||||
Copyright (c) 1993-2003, Robert M Supnik
|
||||
Copyright (c) 1993-2004, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -26,6 +26,7 @@
|
|||
tti,tto DL11 terminal input/output
|
||||
clk KW11L line frequency clock
|
||||
|
||||
29-Dec-03 RMS Added console backpressure support
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
01-Mar-03 RMS Added SET/SHOW CLOCK FREQ, SET TTI CTRL-C
|
||||
22-Nov-02 RMS Changed terminal default to 7B for UNIX
|
||||
|
@ -319,10 +320,12 @@ t_stat tto_svc (UNIT *uptr)
|
|||
int32 c;
|
||||
t_stat r;
|
||||
|
||||
c = tto_unit.buf & ((tto_unit.flags & UNIT_8B)? 0377: 0177);
|
||||
if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output; error? */
|
||||
sim_activate (uptr, uptr->wait); /* try again */
|
||||
return ((r == SCPE_STALL)? SCPE_OK: r); } /* !stall? report */
|
||||
tto_csr = tto_csr | CSR_DONE;
|
||||
if (tto_csr & CSR_IE) SET_INT (TTO);
|
||||
c = tto_unit.buf & ((tto_unit.flags & UNIT_8B)? 0377: 0177);
|
||||
if ((r = sim_putchar (c)) != SCPE_OK) return r;
|
||||
tto_unit.pos = tto_unit.pos + 1;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
|
|
@ -23,8 +23,10 @@
|
|||
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-Dec-03 RMS Added second DEUNA/DELUA support
|
||||
18-Oct-03 RMS Added DECtape off reel message
|
||||
06-May-03 RMS Added support for second DEQNA/DELQA
|
||||
09-Jan-03 RMS Added DELUA support
|
||||
09-Jan-03 RMS Added DELUA/DEUNA support
|
||||
17-Oct-02 RMS Fixed bugs in branch, SOB address parsing
|
||||
09-Oct-02 RMS Added DELQA support
|
||||
12-Sep-02 RMS Added TMSCP, KW11P, RX211 support, RAD50 examine
|
||||
|
@ -64,7 +66,7 @@ extern DEVICE dt_dev;
|
|||
extern DEVICE tm_dev, ts_dev;
|
||||
extern DEVICE tq_dev;
|
||||
extern DEVICE xq_dev, xqb_dev;
|
||||
extern DEVICE xu_dev;
|
||||
extern DEVICE xu_dev, xub_dev;
|
||||
extern UNIT cpu_unit;
|
||||
extern REG cpu_reg[];
|
||||
extern uint16 *M;
|
||||
|
@ -113,6 +115,7 @@ DEVICE *sim_devices[] = {
|
|||
&xq_dev,
|
||||
&xqb_dev,
|
||||
&xu_dev,
|
||||
&xub_dev,
|
||||
NULL };
|
||||
|
||||
const char *sim_stop_messages[] = {
|
||||
|
@ -138,7 +141,8 @@ const char *sim_stop_messages[] = {
|
|||
"Trap vector fetch abort",
|
||||
"Trap stack push abort",
|
||||
"RQDX3 consistency error",
|
||||
"Sanity timer expired" };
|
||||
"Sanity timer expired"
|
||||
"DECtape off reel" };
|
||||
|
||||
/* Binary loader.
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp11_tc.c: PDP-11 DECtape simulator
|
||||
|
||||
Copyright (c) 1993-2003, Robert M Supnik
|
||||
Copyright (c) 1993-2004, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -25,6 +25,10 @@
|
|||
|
||||
tc TC11/TU56 DECtape
|
||||
|
||||
29-Dec-03 RMS Changed initial status to disabled (in Qbus system)
|
||||
18-Oct-03 RMS Fixed reverse checksum in read all
|
||||
Added DECtape off reel message
|
||||
Simplified timing
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
14-Mar-03 RMS Fixed variable size interaction with save/restore
|
||||
29-Sep-02 RMS Added variable address support to bootstrap
|
||||
|
@ -58,13 +62,16 @@
|
|||
When a 16b or 12b DECtape file is read in, it is converted to 18b/36b format.
|
||||
|
||||
DECtape motion is measured in 3b lines. Time between lines is 33.33us.
|
||||
Tape density is nominally 300 lines per inch. The format of a DECtape is
|
||||
Tape density is nominally 300 lines per inch. The format of a DECtape (as
|
||||
taken from the TD8E formatter) is:
|
||||
|
||||
reverse end zone 36000 lines ~ 10 feet
|
||||
reverse end zone 8192 reverse end zone codes ~ 10 feet
|
||||
reverse buffer 200 interblock codes
|
||||
block 0
|
||||
:
|
||||
block n
|
||||
forward end zone 36000 lines ~ 10 feet
|
||||
forward buffer 200 interblock codes
|
||||
forward end zone 8192 forward end zone codes ~ 10 feet
|
||||
|
||||
A block consists of five 18b header words, a tape-specific number of data
|
||||
words, and five 18b trailer words. All systems except the PDP-8 use a
|
||||
|
@ -79,9 +86,9 @@
|
|||
header word 0 0
|
||||
header word 1 block number (for forward reads)
|
||||
header words 2,3 0
|
||||
header word 4 0
|
||||
header word 4 checksum (for reverse reads)
|
||||
:
|
||||
trailer word 4 checksum
|
||||
trailer word 4 checksum (for forward reads)
|
||||
trailer words 3,2 0
|
||||
trailer word 1 block number (for reverse reads)
|
||||
trailer word 0 0
|
||||
|
@ -106,13 +113,15 @@
|
|||
|
||||
/* System independent DECtape constants */
|
||||
|
||||
#define DT_EZLIN 36000 /* end zone length */
|
||||
#define DT_HTLIN 30 /* header/trailer lines */
|
||||
#define DT_BLKLN 6 /* blk no line in h/t */
|
||||
#define DT_CSMLN 24 /* checksum line in h/t */
|
||||
#define DT_HTWRD (DT_HTLIN / DT_WSIZE) /* header/trailer words */
|
||||
#define DT_BLKWD (DT_BLKLN / DT_WSIZE) /* blk no word in h/t */
|
||||
#define DT_CSMWD (DT_CSMLN / DT_WSIZE) /* checksum word in h/t */
|
||||
#define DT_LPERMC 6 /* lines per mark track */
|
||||
#define DT_BLKWD 1 /* blk no word in h/t */
|
||||
#define DT_CSMWD 4 /* checksum word in h/t */
|
||||
#define DT_HTWRD 5 /* header/trailer words */
|
||||
#define DT_EZLIN (8192 * DT_LPERMC) /* end zone length */
|
||||
#define DT_BFLIN (200 * DT_LPERMC) /* buffer length */
|
||||
#define DT_BLKLN (DT_BLKWD * DT_LPERMC) /* blk no line in h/t */
|
||||
#define DT_CSMLN (DT_CSMWD * DT_LPERMC) /* csum line in h/t */
|
||||
#define DT_HTLIN (DT_HTWRD * DT_LPERMC) /* header/trailer lines */
|
||||
|
||||
/* 16b, 18b, 36b DECtape constants */
|
||||
|
||||
|
@ -270,8 +279,7 @@ int32 tcba = 0; /* bus address */
|
|||
int32 tcdt = 0; /* data */
|
||||
int32 dt_ctime = 100; /* fast cmd time */
|
||||
int32 dt_ltime = 12; /* interline time */
|
||||
int32 dt_actime = 54000; /* accel time */
|
||||
int32 dt_dctime = 72000; /* decel time */
|
||||
int32 dt_dctime = 40000; /* decel time */
|
||||
int32 dt_substate = 0;
|
||||
int32 dt_logblk = 0;
|
||||
|
||||
|
@ -340,7 +348,6 @@ REG dt_reg[] = {
|
|||
{ FLDATA (IE, tccm, CSR_V_DONE) },
|
||||
{ DRDATA (CTIME, dt_ctime, 31), REG_NZ },
|
||||
{ DRDATA (LTIME, dt_ltime, 31), REG_NZ },
|
||||
{ DRDATA (ACTIME, dt_actime, 31), REG_NZ },
|
||||
{ DRDATA (DCTIME, dt_dctime, 31), REG_NZ },
|
||||
{ ORDATA (SUBSTATE, dt_substate, 1) },
|
||||
{ DRDATA (LBLK, dt_logblk, 12), REG_HIDDEN },
|
||||
|
@ -371,7 +378,7 @@ DEVICE dt_dev = {
|
|||
DT_NUMDR + 1, 8, 24, 1, 8, 18,
|
||||
NULL, NULL, &dt_reset,
|
||||
&dt_boot, &dt_attach, &dt_detach,
|
||||
&dt_dib, DEV_DISABLE | DEV_UBUS };
|
||||
&dt_dib, DEV_DISABLE | DEV_DIS | DEV_UBUS };
|
||||
|
||||
/* IO dispatch routines, I/O addresses 17777340 - 17777350 */
|
||||
|
||||
|
@ -523,7 +530,7 @@ if (new_fnc == FNC_SSEL) { /* stop unit? */
|
|||
if (prev_mot == DTS_STOP) { /* start? */
|
||||
if (dt_setpos (uptr)) return; /* update pos */
|
||||
sim_cancel (uptr); /* stop current */
|
||||
sim_activate (uptr, dt_actime); /* schedule accel */
|
||||
sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* sched accel */
|
||||
DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */
|
||||
DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */
|
||||
return; }
|
||||
|
@ -537,7 +544,7 @@ if (prev_dir ^ new_dir) { /* dir chg? */
|
|||
if (prev_mot < DTS_ACCF) { /* not accel/at speed? */
|
||||
if (dt_setpos (uptr)) return; /* update pos */
|
||||
sim_cancel (uptr); /* cancel cur */
|
||||
sim_activate (uptr, dt_actime); /* schedule accel */
|
||||
sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* sched accel */
|
||||
DTS_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */
|
||||
DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */
|
||||
return; }
|
||||
|
@ -674,11 +681,13 @@ case DTS_STOP: /* stop */
|
|||
delta = 0;
|
||||
break;
|
||||
case DTS_DECF: /* slowing */
|
||||
ulin = ut / (uint32) dt_ltime; udelt = dt_dctime / dt_ltime;
|
||||
ulin = ut / (uint32) dt_ltime;
|
||||
udelt = dt_dctime / dt_ltime;
|
||||
delta = ((ulin * udelt * 2) - (ulin * ulin)) / (2 * udelt);
|
||||
break;
|
||||
case DTS_ACCF: /* accelerating */
|
||||
ulin = ut / (uint32) dt_ltime; udelt = dt_actime / dt_ltime;
|
||||
ulin = ut / (uint32) dt_ltime;
|
||||
udelt = (dt_dctime - (dt_dctime >> 2)) / dt_ltime;
|
||||
delta = (ulin * ulin) / (2 * udelt);
|
||||
break;
|
||||
case DTS_ATSF: /* at speed */
|
||||
|
@ -715,7 +724,7 @@ t_stat dt_svc (UNIT *uptr)
|
|||
int32 mot = DTS_GETMOT (uptr->STATE);
|
||||
int32 dir = mot & DTS_DIR;
|
||||
int32 fnc = DTS_GETFNC (uptr->STATE);
|
||||
int32 *bptr = uptr->filebuf;
|
||||
int32 *fbuf = uptr->filebuf;
|
||||
int32 blk, wrd, relpos, dat;
|
||||
uint32 ba, ma, mma;
|
||||
|
||||
|
@ -728,10 +737,10 @@ uint32 ba, ma, mma;
|
|||
|
||||
switch (mot) {
|
||||
case DTS_DECF: case DTS_DECR: /* decelerating */
|
||||
if (dt_setpos (uptr)) return SCPE_OK; /* update pos */
|
||||
if (dt_setpos (uptr)) return STOP_DTOFF; /* update pos */
|
||||
uptr->STATE = DTS_NXTSTA (uptr->STATE); /* advance state */
|
||||
if (uptr->STATE) /* not stopped? */
|
||||
sim_activate (uptr, dt_actime); /* must be reversing */
|
||||
sim_activate (uptr, dt_dctime - (dt_dctime >> 2)); /* reversing */
|
||||
return SCPE_OK;
|
||||
case DTS_ACCF: case DTS_ACCR: /* accelerating */
|
||||
dt_newfnc (uptr, DTS_NXTSTA (uptr->STATE)); /* adv state, sched */
|
||||
|
@ -748,7 +757,7 @@ default: /* other */
|
|||
Off reel - detach unit (it must be deselected)
|
||||
*/
|
||||
|
||||
if (dt_setpos (uptr)) return SCPE_OK; /* update pos */
|
||||
if (dt_setpos (uptr)) return STOP_DTOFF; /* update pos */
|
||||
if (DT_QEZ (uptr)) { /* in end zone? */
|
||||
dt_seterr (uptr, STA_END); /* end zone error */
|
||||
return SCPE_OK; }
|
||||
|
@ -785,7 +794,7 @@ case FNC_READ: /* read */
|
|||
dt_seterr (uptr, STA_NXM);
|
||||
break; }
|
||||
ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */
|
||||
M[mma >> 1] = tcdt = bptr[ba] & DMASK; /* read word */
|
||||
M[mma >> 1] = tcdt = fbuf[ba] & DMASK; /* read word */
|
||||
tcwc = (tcwc + 1) & DMASK; /* incr MA, WC */
|
||||
tcba = (tcba + 2) & DMASK;
|
||||
if (tcba <= 1) tccm = CSR_INCMEX (tccm);
|
||||
|
@ -822,7 +831,7 @@ case FNC_WRIT: /* write */
|
|||
tcba = (tcba + 2) & DMASK;
|
||||
if (tcba <= 1) tccm = CSR_INCMEX (tccm); }
|
||||
ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */
|
||||
bptr[ba] = tcdt; /* write word */
|
||||
fbuf[ba] = tcdt; /* write word */
|
||||
if (ba >= uptr->hwmark) uptr->hwmark = ba + 1;
|
||||
if (tcwc == 0) dt_substate = 1;
|
||||
if (wrd != (dir? 0: DTU_BSIZE (uptr) - 1)) /* not end blk? */
|
||||
|
@ -844,7 +853,7 @@ case FNC_RALL:
|
|||
(relpos < (DTU_LPERB (uptr) - DT_HTLIN))) {
|
||||
wrd = DT_LIN2WD (uptr->pos, uptr);
|
||||
ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */
|
||||
dat = bptr[ba]; } /* get tape word */
|
||||
dat = fbuf[ba]; } /* get tape word */
|
||||
else dat = dt_gethdr (uptr, blk, relpos); /* get hdr */
|
||||
if (dir) dat = dt_comobv (dat); /* rev? comp obv */
|
||||
tcdt = dat & DMASK; /* low 16b */
|
||||
|
@ -866,7 +875,7 @@ case FNC_WALL:
|
|||
dat = (STA_GETXD (tcst) << 16) | tcdt; /* get data word */
|
||||
if (dir) dat = dt_comobv (dat); /* rev? comp obv */
|
||||
ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */
|
||||
bptr[ba] = dat; /* write word */
|
||||
fbuf[ba] = dat; /* write word */
|
||||
if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; }
|
||||
/* else /* ignore hdr */
|
||||
sim_activate (uptr, DT_WSIZE * dt_ltime);
|
||||
|
@ -941,13 +950,13 @@ return dat;
|
|||
|
||||
int32 dt_csum (UNIT *uptr, int32 blk)
|
||||
{
|
||||
int32 *bptr = uptr->filebuf;
|
||||
int32 *fbuf = uptr->filebuf;
|
||||
int32 ba = blk * DTU_BSIZE (uptr);
|
||||
int32 i, csum, wrd;
|
||||
|
||||
csum = 077; /* init csum */
|
||||
for (i = 0; i < DTU_BSIZE (uptr); i++) { /* loop thru buf */
|
||||
wrd = bptr[ba + i] ^ 0777777; /* get ~word */
|
||||
wrd = fbuf[ba + i] ^ 0777777; /* get ~word */
|
||||
csum = csum ^ (wrd >> 12) ^ (wrd >> 6) ^ wrd; }
|
||||
return (csum & 077);
|
||||
}
|
||||
|
@ -959,6 +968,7 @@ int32 dt_gethdr (UNIT *uptr, int32 blk, int32 relpos)
|
|||
int32 wrd = relpos / DT_WSIZE;
|
||||
|
||||
if (wrd == DT_BLKWD) return blk; /* fwd blknum */
|
||||
if (wrd == DT_CSMWD) return 077; /* rev csum */
|
||||
if (wrd == (2 * DT_HTWRD + DTU_BSIZE (uptr) - DT_CSMWD - 1)) /* fwd csum */
|
||||
return (dt_csum (uptr, blk) << 12);
|
||||
if (wrd == (2 * DT_HTWRD + DTU_BSIZE (uptr) - DT_BLKWD - 1)) /* rev blkno */
|
||||
|
@ -1067,7 +1077,7 @@ t_stat dt_attach (UNIT *uptr, char *cptr)
|
|||
{
|
||||
uint16 pdp8b[D8_NBSIZE];
|
||||
uint16 pdp11b[D18_BSIZE];
|
||||
uint32 ba, sz, k, *bptr;
|
||||
uint32 ba, sz, k, *fbuf;
|
||||
int32 u = uptr - dt_dev.units;
|
||||
t_stat r;
|
||||
|
||||
|
@ -1089,7 +1099,7 @@ uptr->filebuf = calloc (uptr->capac, sizeof (int32));
|
|||
if (uptr->filebuf == NULL) { /* can't alloc? */
|
||||
detach_unit (uptr);
|
||||
return SCPE_MEM; }
|
||||
bptr = uptr->filebuf; /* file buffer */
|
||||
fbuf = uptr->filebuf; /* file buffer */
|
||||
printf ("%s%d: ", sim_dname (&dt_dev), u);
|
||||
if (uptr->flags & UNIT_8FMT) printf ("12b format");
|
||||
else if (uptr->flags & UNIT_11FMT) printf ("16b format");
|
||||
|
@ -1101,9 +1111,9 @@ if (uptr->flags & UNIT_8FMT) { /* 12b? */
|
|||
if (k == 0) break;
|
||||
for ( ; k < D8_NBSIZE; k++) pdp8b[k] = 0;
|
||||
for (k = 0; k < D8_NBSIZE; k = k + 3) { /* loop thru blk */
|
||||
bptr[ba] = ((uint32) (pdp8b[k] & 07777) << 6) |
|
||||
fbuf[ba] = ((uint32) (pdp8b[k] & 07777) << 6) |
|
||||
((uint32) (pdp8b[k + 1] >> 6) & 077);
|
||||
bptr[ba + 1] = ((pdp8b[k + 1] & 077) << 12) |
|
||||
fbuf[ba + 1] = ((pdp8b[k + 1] & 077) << 12) |
|
||||
((uint32) (pdp8b[k + 2] & 07777));
|
||||
ba = ba + 2; } /* end blk loop */
|
||||
} /* end file loop */
|
||||
|
@ -1114,7 +1124,7 @@ else if (uptr->flags & UNIT_11FMT) { /* 16b? */
|
|||
if (k == 0) break;
|
||||
for ( ; k < D18_BSIZE; k++) pdp11b[k] = 0;
|
||||
for (k = 0; k < D18_BSIZE; k++)
|
||||
bptr[ba++] = pdp11b[k]; }
|
||||
fbuf[ba++] = pdp11b[k]; }
|
||||
uptr->hwmark = ba; } /* end elif */
|
||||
else uptr->hwmark = fxread (uptr->filebuf, sizeof (int32),
|
||||
uptr->capac, uptr->fileref);
|
||||
|
@ -1137,7 +1147,7 @@ t_stat dt_detach (UNIT* uptr)
|
|||
{
|
||||
uint16 pdp8b[D8_NBSIZE];
|
||||
uint16 pdp11b[D18_BSIZE];
|
||||
uint32 ba, k, *bptr;
|
||||
uint32 ba, k, *fbuf;
|
||||
int32 u = uptr - dt_dev.units;
|
||||
|
||||
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK;
|
||||
|
@ -1148,17 +1158,17 @@ if (sim_is_active (uptr)) { /* active? cancel op */
|
|||
tccm = tccm | CSR_ERR | CSR_DONE;
|
||||
if (tccm & CSR_IE) SET_INT (DTA); }
|
||||
uptr->STATE = uptr->pos = 0; }
|
||||
bptr = uptr->filebuf; /* file buffer */
|
||||
fbuf = uptr->filebuf; /* file buffer */
|
||||
if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */
|
||||
printf ("%s%d: writing buffer to file\n", sim_dname (&dt_dev), u);
|
||||
rewind (uptr->fileref); /* start of file */
|
||||
if (uptr->flags & UNIT_8FMT) { /* 12b? */
|
||||
for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */
|
||||
for (k = 0; k < D8_NBSIZE; k = k + 3) { /* loop blk */
|
||||
pdp8b[k] = (bptr[ba] >> 6) & 07777;
|
||||
pdp8b[k + 1] = ((bptr[ba] & 077) << 6) |
|
||||
((bptr[ba + 1] >> 12) & 077);
|
||||
pdp8b[k + 2] = bptr[ba + 1] & 07777;
|
||||
pdp8b[k] = (fbuf[ba] >> 6) & 07777;
|
||||
pdp8b[k + 1] = ((fbuf[ba] & 077) << 6) |
|
||||
((fbuf[ba + 1] >> 12) & 077);
|
||||
pdp8b[k + 2] = fbuf[ba + 1] & 07777;
|
||||
ba = ba + 2; } /* end loop blk */
|
||||
fxwrite (pdp8b, sizeof (int16), D8_NBSIZE, uptr->fileref);
|
||||
if (ferror (uptr->fileref)) break; } /* end loop file */
|
||||
|
@ -1166,7 +1176,7 @@ if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */
|
|||
else if (uptr->flags & UNIT_11FMT) { /* 16b? */
|
||||
for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */
|
||||
for (k = 0; k < D18_BSIZE; k++) /* loop blk */
|
||||
pdp11b[k] = bptr[ba++] & DMASK;
|
||||
pdp11b[k] = fbuf[ba++] & DMASK;
|
||||
fxwrite (pdp11b, sizeof (int16), D18_BSIZE, uptr->fileref);
|
||||
if (ferror (uptr->fileref)) break; } /* end loop file */
|
||||
} /* end if 16b */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp11_tm.c: PDP-11 magnetic tape simulator
|
||||
|
||||
Copyright (c) 1993-2003, Robert M Supnik
|
||||
Copyright (c) 1993-2004, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -25,6 +25,7 @@
|
|||
|
||||
tm TM11/TU10 magtape
|
||||
|
||||
29-Dec-03 RMS Added 18b Qbus support
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
28-Mar-03 RMS Added multiformat support
|
||||
28-Feb-03 RMS Revised for magtape library, added logging
|
||||
|
@ -231,7 +232,7 @@ DEVICE tm_dev = {
|
|||
TM_NUMDR, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &tm_reset,
|
||||
&tm_boot, &tm_attach, &tm_detach,
|
||||
&tm_dib, DEV_DISABLE | DEV_UBUS };
|
||||
&tm_dib, DEV_DISABLE | DEV_UBUS | DEV_Q18 };
|
||||
|
||||
/* I/O dispatch routine, I/O addresses 17772520 - 17772532
|
||||
|
||||
|
|
191
PDP11/pdp11_xq.c
|
@ -69,6 +69,27 @@
|
|||
|
||||
Modification history:
|
||||
|
||||
03-Dec-03 DTH Added minimum name length to show xq eth
|
||||
25-Nov-03 DTH Reworked interrupts to fix broken XQB implementation
|
||||
19-Nov-03 MP Rearranged timer reset sequencing to allow for a device to be
|
||||
disabled after it had been enabled.
|
||||
17-Nov-03 DTH Standardized #include of timeb.h
|
||||
28-Sep-03 MP - Fixed bug in xq_process_setup which would leave the
|
||||
device in promiscuous or all multicast mode once it
|
||||
ever had been there.
|
||||
- Fixed output format in show_xq_sanity to end in "\n"
|
||||
- Added display of All Multicase and promiscuous to
|
||||
xq_show_filters
|
||||
- The stuck in All Multicast or Promiscuous issue is
|
||||
worse than previously thought. See comments in
|
||||
xq_process_setup.
|
||||
- Change xq_setmac to also allow ":" as a address
|
||||
separator character, since sim_ether's eth_mac_fmt
|
||||
formats them with this separator character.
|
||||
- Changed xq_sw_reset to behave more like the set of
|
||||
actions described in Table 3-6 of the DELQA manua.
|
||||
The manual mentions "N/A" which I'm interpreting to
|
||||
mean "Not Affected".
|
||||
05-Jun-03 DTH Added receive packet splitting
|
||||
03-Jun-03 DTH Added SHOW XQ FILTERS
|
||||
02-Jun-03 DTH Added SET/SHOW XQ STATS (packet statistics), runt & giant processing
|
||||
|
@ -92,7 +113,7 @@
|
|||
of Receiver Enabled. This was an issue since the
|
||||
it seems that at least VMS's XQ driver makes this
|
||||
transition often and the resulting overhead reduces
|
||||
the simulated CPU instruction execution thruput by
|
||||
the simulated CPU instruction execution throughput by
|
||||
about 40%. I start the system id timer on device
|
||||
reset and it fires once a second so that it can
|
||||
leverage the reasonably recalibrated tmr_poll value.
|
||||
|
@ -100,7 +121,7 @@
|
|||
dynamically computed clock values to achieve an
|
||||
approximate interval of 100 per second. This is
|
||||
more than sufficient for normal system behaviour
|
||||
expecially since we service recieves with every
|
||||
expecially since we service receives with every
|
||||
transmit. The previous fixed value of 2500
|
||||
attempted to get 200/sec but it was a guess that
|
||||
didn't adapt. On faster host systems (possibly
|
||||
|
@ -128,7 +149,7 @@
|
|||
05-Dec-02 MP Restructured the flow of processing in xq_svc so that eth_read
|
||||
is called repeatedly until either a packet isn't found or
|
||||
there is no room for another one in the queue. Once that has
|
||||
been done, xq_processrdbl is called to pass the queued packets
|
||||
been done, xq_process_rdbl is called to pass the queued packets
|
||||
into the simulated system as space is available there.
|
||||
xq_process_rdbl is also called at the beginning of xq_svc to
|
||||
drain the queue into the simulated system, making more room
|
||||
|
@ -216,8 +237,6 @@ t_stat xq_process_xbdl(CTLR* xq);
|
|||
t_stat xq_dispatch_xbdl(CTLR* xq);
|
||||
void xq_start_receiver(void);
|
||||
void xq_sw_reset(CTLR* xq);
|
||||
int32 xq_inta (void);
|
||||
int32 xq_intb (void);
|
||||
t_stat xq_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
|
||||
t_stat xq_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
|
||||
void xq_start_santmr(CTLR* xq);
|
||||
|
@ -230,6 +249,9 @@ void xqa_read_callback(int status);
|
|||
void xqb_read_callback(int status);
|
||||
void xqa_write_callback(int status);
|
||||
void xqb_write_callback(int status);
|
||||
void xq_setint (CTLR* xq);
|
||||
void xq_clrint (CTLR* xq);
|
||||
int32 xq_int (void);
|
||||
|
||||
struct xq_device xqa = {
|
||||
xqa_read_callback, /* read callback routine */
|
||||
|
@ -249,7 +271,7 @@ struct xq_device xqb = {
|
|||
|
||||
/* SIMH device structures */
|
||||
DIB xqa_dib = { IOBA_XQ, IOLN_XQ, &xq_rd, &xq_wr,
|
||||
1, IVCL (XQ), 0, { &xq_inta } };
|
||||
1, IVCL (XQ), 0, { &xq_int } };
|
||||
|
||||
UNIT xqa_unit[] = {
|
||||
{ UDATA (&xq_svc, UNIT_ATTABLE + UNIT_DISABLE, 2047) }, /* receive timer */
|
||||
|
@ -268,6 +290,7 @@ REG xqa_reg[] = {
|
|||
{ GRDATA ( XBDL, xqa.xbdl, XQ_RDX, 32, 0) },
|
||||
{ GRDATA ( VAR, xqa.var, XQ_RDX, 16, 0) },
|
||||
{ GRDATA ( CSR, xqa.csr, XQ_RDX, 16, 0) },
|
||||
{ FLDATA ( INT, xqa.irq, 0) },
|
||||
{ GRDATA ( SETUP_PRM, xqa.setup.promiscuous, XQ_RDX, 32, 0), REG_HRO},
|
||||
{ GRDATA ( SETUP_MLT, xqa.setup.multicast, XQ_RDX, 32, 0), REG_HRO},
|
||||
{ GRDATA ( SETUP_L1, xqa.setup.l1, XQ_RDX, 32, 0), REG_HRO},
|
||||
|
@ -279,7 +302,7 @@ REG xqa_reg[] = {
|
|||
};
|
||||
|
||||
DIB xqb_dib = { IOBA_XQB, IOLN_XQB, &xq_rd, &xq_wr,
|
||||
1, IVCL (XQ), 0, { &xq_intb } };
|
||||
1, IVCL (XQ), 0, { &xq_int } };
|
||||
|
||||
UNIT xqb_unit[] = {
|
||||
{ UDATA (&xq_svc, UNIT_ATTABLE + UNIT_DISABLE, 2047) }, /* receive timer */
|
||||
|
@ -298,6 +321,7 @@ REG xqb_reg[] = {
|
|||
{ GRDATA ( XBDL, xqb.xbdl, XQ_RDX, 32, 0) },
|
||||
{ GRDATA ( VAR, xqb.var, XQ_RDX, 16, 0) },
|
||||
{ GRDATA ( CSR, xqb.csr, XQ_RDX, 16, 0) },
|
||||
{ FLDATA ( INT, xqb.irq, 0) },
|
||||
{ GRDATA ( SETUP_PRM, xqb.setup.promiscuous, XQ_RDX, 32, 0), REG_HRO},
|
||||
{ GRDATA ( SETUP_MLT, xqb.setup.multicast, XQ_RDX, 32, 0), REG_HRO},
|
||||
{ GRDATA ( SETUP_L1, xqb.setup.l1, XQ_RDX, 32, 0), REG_HRO},
|
||||
|
@ -372,7 +396,7 @@ void xq_csr_changes(CTLR* xq, uint16 data);
|
|||
void xq_var_changes(CTLR* xq, uint16 data);
|
||||
|
||||
/* sanity timer debugging */
|
||||
#include <sys\timeb.h>
|
||||
#include <sys/timeb.h>
|
||||
struct timeb start, finish;
|
||||
|
||||
#endif /* XQ_DEBUG */
|
||||
|
@ -575,7 +599,9 @@ t_stat xq_setmac (UNIT* uptr, int32 val, char* cptr, void* desc)
|
|||
if (len != 17) return SCPE_ARG;
|
||||
/* make sure byte separators are OK */
|
||||
for (i=2; i<len; i=i+3) {
|
||||
if ((cptr[i] != '-') && (cptr[i] != '.')) return SCPE_ARG;
|
||||
if ((cptr[i] != '-') &&
|
||||
(cptr[i] != '.') &&
|
||||
(cptr[i] != ':')) return SCPE_ARG;
|
||||
cptr[i] = '\0';
|
||||
}
|
||||
/* get and set address bytes */
|
||||
|
@ -601,15 +627,17 @@ t_stat xq_setmac (UNIT* uptr, int32 val, char* cptr, void* desc)
|
|||
t_stat xq_showeth (FILE* st, UNIT* uptr, int32 val, void* desc)
|
||||
{
|
||||
#define XQ_MAX_LIST 10
|
||||
int i;
|
||||
ETH_LIST list[XQ_MAX_LIST];
|
||||
int number = eth_devices(XQ_MAX_LIST, list);
|
||||
|
||||
fprintf(st, "ETH devices:\n");
|
||||
if (number)
|
||||
if (number) {
|
||||
int i, min, len;
|
||||
for (i=0, min=0; i<number; i++)
|
||||
if ((len = strlen(list[i].name)) > min) min = len;
|
||||
for (i=0; i<number; i++)
|
||||
fprintf(st," %d %s (%s)\n", i, list[i].name, list[i].desc);
|
||||
else
|
||||
fprintf(st," %d %-*s (%s)\n", i, min, list[i].name, list[i].desc);
|
||||
} else
|
||||
fprintf(st, " no network devices are available\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -662,6 +690,10 @@ t_stat xq_show_filters (FILE* st, UNIT* uptr, int32 val, void* desc)
|
|||
eth_mac_fmt((ETH_MAC*)xq->var->setup.macs[i], buffer);
|
||||
fprintf(st, " [%2d]: %s\n", i, buffer);
|
||||
};
|
||||
if (xq->var->setup.multicast)
|
||||
fprintf(st, "All Multicast Receive Mode\n");
|
||||
if (xq->var->setup.promiscuous)
|
||||
fprintf(st, "Promiscuous Receive Mode\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -695,8 +727,8 @@ t_stat xq_show_sanity (FILE* st, UNIT* uptr, int32 val, void* desc)
|
|||
|
||||
fprintf(st, "sanity=");
|
||||
switch (xq->var->sanity.enabled) {
|
||||
case 0: fprintf(st, "OFF"); break;
|
||||
case 1: fprintf(st, "ON"); break;
|
||||
case 0: fprintf(st, "OFF\n"); break;
|
||||
case 1: fprintf(st, "ON\n"); break;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -724,7 +756,7 @@ t_stat xq_nxm_error(CTLR* xq)
|
|||
|
||||
/* interrupt if required */
|
||||
if (xq->var->csr & XQ_CSR_IE)
|
||||
SET_INT(XQ);
|
||||
xq_setint(xq);
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -761,7 +793,7 @@ void xq_write_callback (CTLR* xq, int status)
|
|||
/* update csr */
|
||||
xq->var->csr |= XQ_CSR_XI;
|
||||
if (xq->var->csr & XQ_CSR_IE)
|
||||
SET_INT(XQ);
|
||||
xq_setint(xq);
|
||||
|
||||
/* reset sanity timer */
|
||||
xq_reset_santmr(xq);
|
||||
|
@ -846,7 +878,7 @@ t_stat xq_process_rbdl(CTLR* xq)
|
|||
uint16 b_length, w_length, rbl;
|
||||
uint32 address;
|
||||
struct xq_msg_itm* item;
|
||||
char* rbuf;
|
||||
uint8* rbuf;
|
||||
|
||||
#ifdef XQ_DEBUG
|
||||
fprintf(stderr,"%s: CSR - Processing read\n", xq->dev->name);
|
||||
|
@ -906,7 +938,7 @@ t_stat xq_process_rbdl(CTLR* xq)
|
|||
#endif
|
||||
/* pad runts with zeros up to minimum size - this allows "legal" (size - 60)
|
||||
processing of those weird short ARP packets that seem to occur occasionally */
|
||||
memset(&item->packet.msg[rbl], 0, ETH_MIN_PACKET);
|
||||
memset(&item->packet.msg[rbl], 0, ETH_MIN_PACKET-rbl);
|
||||
rbl = ETH_MIN_PACKET;
|
||||
};
|
||||
|
||||
|
@ -976,7 +1008,7 @@ t_stat xq_process_rbdl(CTLR* xq)
|
|||
/* mark transmission complete */
|
||||
xq->var->csr |= XQ_CSR_RI;
|
||||
if (xq->var->csr & XQ_CSR_IE)
|
||||
SET_INT(XQ);
|
||||
xq_setint(xq);
|
||||
|
||||
/* set to next bdl (implicit chain) */
|
||||
xq->var->rbdl_ba += 12;
|
||||
|
@ -1059,15 +1091,42 @@ t_stat xq_process_setup(CTLR* xq)
|
|||
xq->var->setup.macs[i+7][j] = xq->var->write_buffer.msg[(i + 0101) + (j * 8)];
|
||||
}
|
||||
|
||||
/*
|
||||
Under VMS the setup packet that is passed to turn promiscuous
|
||||
off after it has been on doesn't seem to follow the rules documented
|
||||
in both the DEQNA and DELQA manuals.
|
||||
These rules seem to say that setup packets less than 128 should only
|
||||
modify the address filter set and probably not the All-Multicast and
|
||||
Promiscuous modes, however, VMS V5-5 and V7.3 seem to send a 127 byte
|
||||
packet to turn this functionality off. I'm not sure how real hardware
|
||||
behaves in this case, since the only consequence is extra interrupt
|
||||
load. To realize and retain the benefits of the newly added BPF
|
||||
functionality in sim_ether, I've modified the logic implemented here
|
||||
to disable Promiscuous mode when a "small" setup packet is processed.
|
||||
I'm deliberately not modifying the All-Multicast mode the same way
|
||||
since I don't have an observable case of its behavior. These two
|
||||
different modes come from very different usage situations:
|
||||
1) Promiscuous mode is usually entered for relatively short periods
|
||||
of time due to the needs of a specific application program which
|
||||
is doing some sort of management/monitoring function (i.e. tcpdump)
|
||||
2) All-Multicast mode is only entered by the OS Kernel Port Driver
|
||||
when it happens to have clients (usually network stacks or service
|
||||
programs) which as a group need to listen to more multicast ethernet
|
||||
addresses than the 12 (or so) which the hardware supports directly.
|
||||
so, I believe that the All-Multicast mode, is first rarely used, and if
|
||||
it ever is used, once set, it will probably be set either forever or for
|
||||
long periods of time, and the additional interrupt processing load to
|
||||
deal with the distinctly lower multicast traffic set is clearly lower than
|
||||
that of the promiscuous mode.
|
||||
*/
|
||||
xq->var->setup.promiscuous = 0;
|
||||
/* process high byte count */
|
||||
if (xq->var->write_buffer.len > 128) {
|
||||
uint16 len = xq->var->write_buffer.len;
|
||||
uint16 led, san;
|
||||
|
||||
if (len & XQ_SETUP_MC)
|
||||
xq->var->setup.multicast = 1;
|
||||
if (len & XQ_SETUP_PM)
|
||||
xq->var->setup.promiscuous = 1;
|
||||
xq->var->setup.multicast = (0 != (len & XQ_SETUP_MC));
|
||||
xq->var->setup.promiscuous = (0 != (len & XQ_SETUP_PM));
|
||||
if (led = (len & XQ_SETUP_LD) >> 2) {
|
||||
switch (led) {
|
||||
case 1: xq->var->setup.l1 = 0; break;
|
||||
|
@ -1214,7 +1273,7 @@ t_stat xq_process_xbdl(CTLR* xq)
|
|||
/* mark transmission complete */
|
||||
xq->var->csr |= XQ_CSR_XI;
|
||||
if (xq->var->csr & XQ_CSR_IE)
|
||||
SET_INT(XQ);
|
||||
xq_setint(xq);
|
||||
|
||||
/* now trigger "read" of setup or loopback packet */
|
||||
if (~xq->var->csr & XQ_CSR_RL)
|
||||
|
@ -1446,13 +1505,26 @@ void xq_sw_reset(CTLR* xq)
|
|||
xq->var->csr |= XQ_CSR_OK;
|
||||
|
||||
/* clear CPU interrupts */
|
||||
CLR_INT(XQ);
|
||||
xq_clrint(xq);
|
||||
|
||||
/* flush read queue */
|
||||
xq_clear_queue(&xq->var->ReadQ);
|
||||
|
||||
/* clear setup info */
|
||||
memset (&xq->var->setup, 0, sizeof(xq->var->setup));
|
||||
xq->var->setup.multicast = 0;
|
||||
xq->var->setup.promiscuous = 0;
|
||||
if (xq->var->etherface) {
|
||||
int count = 0;
|
||||
ETH_MAC zeros = {0, 0, 0, 0, 0, 0};
|
||||
ETH_MAC filters[XQ_FILTER_MAX + 1];
|
||||
|
||||
/* set ethernet filter */
|
||||
/* memcpy (filters[count++], xq->mac, sizeof(ETH_MAC)); */
|
||||
for (i = 0; i < XQ_FILTER_MAX; i++)
|
||||
if (memcmp(zeros, &xq->var->setup.macs[i], sizeof(ETH_MAC)))
|
||||
memcpy (filters[count++], xq->var->setup.macs[i], sizeof(ETH_MAC));
|
||||
eth_filter (xq->var->etherface, count, filters, xq->var->setup.multicast, xq->var->setup.promiscuous);
|
||||
}
|
||||
}
|
||||
|
||||
/* write registers: */
|
||||
|
@ -1676,7 +1748,7 @@ t_stat xq_process_bootrom (CTLR* xq)
|
|||
/* mark transmission complete */
|
||||
xq->var->csr |= XQ_CSR_RI;
|
||||
if (xq->var->csr & XQ_CSR_IE)
|
||||
SET_INT(XQ);
|
||||
xq_setint(xq);
|
||||
|
||||
/* reset sanity timer */
|
||||
xq_reset_santmr(xq);
|
||||
|
@ -1724,8 +1796,8 @@ t_stat xq_wr_csr(CTLR* xq, int32 data)
|
|||
/* check and correct CPU interrupt state */
|
||||
old_int_state = (saved_csr & XQ_CSR_IE) && (saved_csr & (XQ_CSR_XI | XQ_CSR_RI));
|
||||
new_int_state = (xq->var->csr & XQ_CSR_IE) && (xq->var->csr & (XQ_CSR_XI | XQ_CSR_RI));
|
||||
if ( old_int_state && !new_int_state) CLR_INT(XQ);
|
||||
if (!old_int_state && new_int_state) SET_INT(XQ);
|
||||
if ( old_int_state && !new_int_state) xq_clrint(xq);
|
||||
if (!old_int_state && new_int_state) xq_setint(xq);
|
||||
|
||||
#ifdef VM_PDP11
|
||||
/* request boot/diagnostic rom? [PDP-11 only] */
|
||||
|
@ -1803,12 +1875,6 @@ t_stat xq_reset(DEVICE* dptr)
|
|||
/* init control status register */
|
||||
xq->var->csr = XQ_CSR_RL | XQ_CSR_XL;
|
||||
|
||||
/* reset ethernet interface */
|
||||
if (xq->var->etherface) {
|
||||
status = eth_filter (xq->var->etherface, 1, &xq->var->mac, 0, 0);
|
||||
xq->var->csr |= XQ_CSR_OK;
|
||||
}
|
||||
|
||||
/* init read queue (first time only) */
|
||||
status = xq_init_queue (xq, &xq->var->ReadQ);
|
||||
if (status != SCPE_OK)
|
||||
|
@ -1817,6 +1883,11 @@ t_stat xq_reset(DEVICE* dptr)
|
|||
/* clear read queue */
|
||||
xq_clear_queue(&xq->var->ReadQ);
|
||||
|
||||
/* reset ethernet interface */
|
||||
if (xq->var->etherface) {
|
||||
status = eth_filter (xq->var->etherface, 1, &xq->var->mac, 0, 0);
|
||||
xq->var->csr |= XQ_CSR_OK;
|
||||
|
||||
/* start sanity timer if power-on SANITY is set */
|
||||
switch (xq->var->type) {
|
||||
case XQ_T_DEQNA:
|
||||
|
@ -1830,6 +1901,8 @@ t_stat xq_reset(DEVICE* dptr)
|
|||
xq_start_idtmr(xq);
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -1841,11 +1914,9 @@ void xq_start_santmr(CTLR* xq)
|
|||
/* must be recalculated each time since tmr_poll is a dynamic number */
|
||||
const int32 quarter_sec = (clk_tps * tmr_poll) / 4;
|
||||
|
||||
#if 0
|
||||
#ifdef XQ_DEBUG
|
||||
fprintf(stderr,"%s: SANITY TIMER ENABLED, qsecs: %d, poll:%d\n",
|
||||
xq->dev->name, xq->var->sanity.quarter_secs, tmr_poll);
|
||||
#endif
|
||||
#endif
|
||||
if (sim_is_active(xq_santmr)) /* cancel timer, just in case */
|
||||
sim_cancel(xq_santmr);
|
||||
|
@ -1897,12 +1968,10 @@ t_stat xq_sansvc(UNIT* uptr)
|
|||
If this section is entered, it means that the sanity timer has expired
|
||||
without being reset, and the controller must reboot the processor.
|
||||
*/
|
||||
#if 0
|
||||
#ifdef XQ_DEBUG
|
||||
ftime(&finish);
|
||||
fprintf(stderr,"%s: SANITY TIMER EXPIRED, qsecs: %d, poll: %d, elapsed: %d\n",
|
||||
xq->dev->name, xq->var->sanity.quarter_secs, tmr_poll, finish.time - start.time);
|
||||
#endif
|
||||
#endif
|
||||
xq_boot_host();
|
||||
}
|
||||
|
@ -1944,6 +2013,9 @@ t_stat xq_system_id (CTLR* xq, const ETH_MAC dest, uint16 receipt_id)
|
|||
uint8* const msg = &system_id.msg[0];
|
||||
t_stat status;
|
||||
|
||||
#ifdef XQ_DEBUG
|
||||
fprintf(stderr,"%s: SYSTEM ID BROADCAST\n", xq->dev->name);
|
||||
#endif
|
||||
memset (&system_id, 0, sizeof(system_id));
|
||||
memcpy (&msg[0], dest, sizeof(ETH_MAC));
|
||||
memcpy (&msg[6], xq->var->setup.valid ? xq->var->setup.macs[0] : xq->var->mac, sizeof(ETH_MAC));
|
||||
|
@ -2089,6 +2161,9 @@ t_stat xq_attach(UNIT* uptr, char* cptr)
|
|||
/* turn on transceiver power indicator */
|
||||
xq->var->csr |= XQ_CSR_OK;
|
||||
|
||||
/* reset the device with the new attach info */
|
||||
xq_reset(xq->dev);
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -2098,6 +2173,7 @@ t_stat xq_detach(UNIT* uptr)
|
|||
{
|
||||
t_stat status;
|
||||
CTLR* xq = xq_unit2ctlr(uptr);
|
||||
int i;
|
||||
|
||||
if (uptr->flags & UNIT_ATT) {
|
||||
status = eth_close (xq->var->etherface);
|
||||
|
@ -2106,6 +2182,9 @@ t_stat xq_detach(UNIT* uptr)
|
|||
free(uptr->filename);
|
||||
uptr->filename = NULL;
|
||||
uptr->flags &= ~UNIT_ATT;
|
||||
/* cancel all timers (ethernet, sanity, system_id) */
|
||||
for (i=0; i<3; i++)
|
||||
sim_cancel(&xq->unit[i]);
|
||||
}
|
||||
|
||||
/* turn off transceiver power indicator */
|
||||
|
@ -2114,14 +2193,38 @@ t_stat xq_detach(UNIT* uptr)
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
int32 xq_inta (void)
|
||||
void xq_setint(CTLR* xq)
|
||||
{
|
||||
return xqa_dib.vec;
|
||||
xq->var->irq = 1;
|
||||
SET_INT(XQ);
|
||||
return;
|
||||
}
|
||||
|
||||
int32 xq_intb (void)
|
||||
void xq_clrint(CTLR* xq)
|
||||
{
|
||||
return xqb_dib.vec;
|
||||
int i;
|
||||
xq->var->irq = 0; /* set controller irq off */
|
||||
/* clear master interrupt? */
|
||||
for (i=0; i<XQ_MAX_CONTROLLERS; i++) /* check all controllers.. */
|
||||
if (xq_ctrl[i].var->irq) { /* if any irqs enabled */
|
||||
SET_INT(XQ); /* set master interrupt on */
|
||||
return;
|
||||
}
|
||||
CLR_INT(XQ); /* clear master interrupt */
|
||||
return;
|
||||
}
|
||||
|
||||
int32 xq_int (void)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<XQ_MAX_CONTROLLERS; i++) {
|
||||
CTLR* xq = &xq_ctrl[i];
|
||||
if (xq->var->irq) { /* if interrupt pending */
|
||||
xq_clrint(xq); /* clear interrupt */
|
||||
return xq->dib->vec; /* return vector */
|
||||
}
|
||||
}
|
||||
return 0; /* no interrupt request active */
|
||||
}
|
||||
|
||||
/*==============================================================================
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
Modification history:
|
||||
|
||||
25-Nov-03 DTH Added interrupt request flag
|
||||
02-Jun-03 DTH Added struct xq_stats
|
||||
28-May-03 DTH Made xq_msg_que.item dynamic
|
||||
28-May-03 MP Optimized structures, removed rtime variable
|
||||
|
@ -152,6 +153,7 @@ struct xq_device {
|
|||
uint16 xbdl[2];
|
||||
uint16 var;
|
||||
uint16 csr;
|
||||
uint32 irq; /* interrupt request flag */
|
||||
|
||||
/* buffers, etc. */
|
||||
struct xq_setup setup;
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
xu DEUNA/DELUNA Ethernet interface (stub)
|
||||
|
||||
22-Dec-03 RMS Added second (stub) device
|
||||
*/
|
||||
|
||||
#if defined (VM_PDP10) /* PDP10 version */
|
||||
|
@ -61,3 +63,29 @@ DEVICE xu_dev = {
|
|||
NULL, NULL, NULL,
|
||||
NULL, NULL, NULL,
|
||||
&xu_dib, DEV_DIS | DEV_UBUS };
|
||||
|
||||
#if defined (VM_PDP11)
|
||||
|
||||
/* XUB data structures
|
||||
|
||||
xub_dev XUB device descriptor
|
||||
xub_unit XUB unit list
|
||||
xub_reg XUB register list
|
||||
*/
|
||||
|
||||
DIB xub_dib = { IOBA_XUB, IOLN_XUB, NULL, NULL,
|
||||
1, IVCL (XU), VEC_XU, { NULL } };
|
||||
|
||||
UNIT xub_unit = { UDATA (NULL, 0, 0) };
|
||||
|
||||
REG xub_reg[] = {
|
||||
{ NULL } };
|
||||
|
||||
DEVICE xub_dev = {
|
||||
"XUB", &xub_unit, xub_reg, NULL,
|
||||
1, 8, 8, 1, 8, 8,
|
||||
NULL, NULL, NULL,
|
||||
NULL, NULL, NULL,
|
||||
&xub_dib, DEV_DIS | DEV_UBUS };
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp18b_cpu.c: 18b PDP CPU simulator
|
||||
|
||||
Copyright (c) 1993-2003, Robert M Supnik
|
||||
Copyright (c) 1993-2004, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -25,6 +25,10 @@
|
|||
|
||||
cpu PDP-4/7/9/15 central processor
|
||||
|
||||
31-Dec-03 RMS Fixed bug in cpu_set_hist
|
||||
02-Nov-03 RMS Changed PDP-9,-15 default to API
|
||||
26-Oct-03 RMS Fixed bug in PDP-4,-7,-9 autoincrement addressing
|
||||
19-Sep-03 RMS Changed instruction history to be dynamically sized
|
||||
31-Aug-03 RMS Added instruction history
|
||||
Fixed PDP-15-specific implementation of API priorities
|
||||
16-Aug-03 RMS Fixed PDP-15-specific handling of EAE unsigned mul/div
|
||||
|
@ -277,9 +281,11 @@
|
|||
#define UNIT_XVM (1 << UNIT_V_XVM)
|
||||
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
|
||||
|
||||
#define HIST_SIZE 4096
|
||||
#define HIST_API 0x40000000
|
||||
#define HIST_PI 0x20000000
|
||||
#define HIST_PC 0x10000000
|
||||
#define HIST_MIN 64
|
||||
#define HIST_MAX 65536
|
||||
#define HIST_M_LVL 0x3F
|
||||
#define HIST_V_LVL 6
|
||||
struct InstHistory {
|
||||
|
@ -303,7 +309,7 @@ struct InstHistory {
|
|||
#define PROT_DFLT 0
|
||||
#define ASW_DFLT 017763
|
||||
#else
|
||||
#define API_DFLT UNIT_NOAPI /* for now */
|
||||
#define API_DFLT 0
|
||||
#define PROT_DFLT UNIT_PROT
|
||||
#define ASW_DFLT 017720
|
||||
#endif
|
||||
|
@ -355,7 +361,7 @@ int32 pcq_p = 0; /* PC queue ptr */
|
|||
REG *pcq_r = NULL; /* PC queue reg ptr */
|
||||
int32 hst_p = 0; /* history pointer */
|
||||
int32 hst_lnt = 0; /* history length */
|
||||
static struct InstHistory hst[HIST_SIZE] = { { 0 } }; /* instruction history */
|
||||
struct InstHistory *hst = NULL; /* instruction history */
|
||||
|
||||
extern int32 sim_int_char;
|
||||
extern int32 sim_interval;
|
||||
|
@ -1510,7 +1516,7 @@ t_stat Ia (int32 ma, int32 *ea, t_bool jmp)
|
|||
int32 t;
|
||||
t_stat sta = MM_OK;
|
||||
|
||||
if ((ma & B_DAMASK) == 010) { /* autoindex? */
|
||||
if ((ma & B_DAMASK & ~07) == 010) { /* autoindex? */
|
||||
Read (ma, &t, DF); /* add 1 before use */
|
||||
t = (t + 1) & DMASK;
|
||||
sta = Write (ma, t, DF); }
|
||||
|
@ -1588,7 +1594,7 @@ t_stat Ia (int32 ma, int32 *ea, t_bool jmp)
|
|||
int32 t;
|
||||
t_stat sta = MM_OK;
|
||||
|
||||
if ((ma & B_DAMASK) == 010) { /* autoindex? */
|
||||
if ((ma & B_DAMASK & ~07) == 010) { /* autoindex? */
|
||||
ma = ma & 017; /* always in bank 0 */
|
||||
Read (ma, &t, DF); /* +1 before use */
|
||||
t = (t + 1) & DMASK;
|
||||
|
@ -1799,7 +1805,7 @@ t_stat cpu_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)
|
|||
if (usmd && (sw & SWMASK ('V'))) {
|
||||
if (XVM) addr = RelocXVM (addr, REL_C);
|
||||
else if (RELOC) addr = Reloc15 (addr, REL_C);
|
||||
if (addr < 0) return STOP_MME; }
|
||||
if ((int32) addr < 0) return STOP_MME; }
|
||||
#endif
|
||||
if (addr >= MEMSIZE) return SCPE_NXM;
|
||||
if (vptr != NULL) *vptr = M[addr] & DMASK;
|
||||
|
@ -1814,7 +1820,7 @@ t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw)
|
|||
if (usmd && (sw & SWMASK ('V'))) {
|
||||
if (XVM) addr = RelocXVM (addr, REL_C);
|
||||
else if (RELOC) addr = Reloc15 (addr, REL_C);
|
||||
if (addr < 0) return STOP_MME; }
|
||||
if ((int32) addr < 0) return STOP_MME; }
|
||||
#endif
|
||||
if (addr >= MEMSIZE) return SCPE_NXM;
|
||||
M[addr] = val & DMASK;
|
||||
|
@ -1933,11 +1939,20 @@ int32 i, lnt;
|
|||
t_stat r;
|
||||
|
||||
if (cptr == NULL) {
|
||||
for (i = 0; i < HIST_SIZE; i++) hst[i].pc = 0;
|
||||
for (i = 0; i < hst_lnt; i++) hst[i].pc = 0;
|
||||
hst_p = 0;
|
||||
return SCPE_OK; }
|
||||
lnt = (int32) get_uint (cptr, 10, HIST_SIZE, &r);
|
||||
if (r != SCPE_OK) return SCPE_ARG;
|
||||
hst_lnt = lnt;
|
||||
lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r);
|
||||
if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG;
|
||||
hst_p = 0;
|
||||
if (hst_lnt) {
|
||||
free (hst);
|
||||
hst_lnt = 0;
|
||||
hst = NULL; }
|
||||
if (lnt) {
|
||||
hst = calloc (sizeof (struct InstHistory), lnt);
|
||||
if (hst == NULL) return SCPE_MEM;
|
||||
hst_lnt = lnt; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -1952,25 +1967,26 @@ extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
|
|||
UNIT *uptr, int32 sw);
|
||||
|
||||
if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */
|
||||
di = hst_p + HIST_SIZE - hst_lnt; /* work forward */
|
||||
fprintf (st, "PC L AC MQ IR\n\n");
|
||||
di = hst_p; /* work forward */
|
||||
for (k = 0; k < hst_lnt; k++) { /* print specified */
|
||||
h = &hst[(di++) % HIST_SIZE]; /* entry pointer */
|
||||
if (h->pc == 0) continue; /* filled in? */
|
||||
if (h->pc & (HIST_API | HIST_PI)) { /* interrupt event? */
|
||||
h = &hst[(di++) % hst_lnt]; /* entry pointer */
|
||||
if (h->pc & HIST_PC) { /* instruction? */
|
||||
l = (h->lac >> 18) & 1; /* link */
|
||||
fprintf (st, "%06o %o %06o %06o ", h->pc & AMASK, l, h->lac & DMASK, h->mq);
|
||||
sim_eval[0] = h->ir;
|
||||
sim_eval[1] = h->ir1;
|
||||
if ((fprint_sym (st, h->pc & AMASK, sim_eval, &cpu_unit, SWMASK ('M'))) > 0)
|
||||
fprintf (st, "(undefined) %06o", h->ir);
|
||||
} /* end else instruction */
|
||||
else if (h->pc & (HIST_API | HIST_PI)) { /* interrupt event? */
|
||||
if (h->pc & HIST_PI) /* PI? */
|
||||
fprintf (st, "%06o PI LVL 0-4 =", h->pc & AMASK);
|
||||
else fprintf (st, "%06o API %d LVL 0-4 =", h->pc & AMASK, h->mq);
|
||||
for (j = API_HLVL; j >= 0; j--)
|
||||
fprintf (st, " %02o", (h->ir >> (j * HIST_V_LVL)) & HIST_M_LVL);
|
||||
}
|
||||
else { /* instruction */
|
||||
l = (h->lac >> 18) & 1; /* link */
|
||||
fprintf (st, "%06o %o %06o %06o ", h->pc, l, h->lac & DMASK, h->mq);
|
||||
sim_eval[0] = h->ir;
|
||||
sim_eval[1] = h->ir1;
|
||||
if ((fprint_sym (st, h->pc, sim_eval, &cpu_unit, SWMASK ('M'))) > 0)
|
||||
fprintf (st, "(undefined) %06o", h->ir);
|
||||
} /* end else instruction */
|
||||
else continue; /* invalid */
|
||||
fputc ('\n', st); /* end line */
|
||||
} /* end for */
|
||||
return SCPE_OK;
|
||||
|
@ -1980,13 +1996,17 @@ return SCPE_OK;
|
|||
|
||||
void cpu_inst_hist (int32 addr, int32 inst)
|
||||
{
|
||||
hst[hst_p].pc = addr;
|
||||
t_value word;
|
||||
|
||||
hst[hst_p].pc = addr | HIST_PC;
|
||||
hst[hst_p].ir = inst;
|
||||
if (cpu_ex (&hst[hst_p].ir1, (addr + 1) & AMASK, &cpu_unit, SWMASK ('V')))
|
||||
if (cpu_ex (&word, (addr + 1) & AMASK, &cpu_unit, SWMASK ('V')))
|
||||
hst[hst_p].ir1 = 0;
|
||||
else hst[hst_p].ir1 = word;
|
||||
hst[hst_p].lac = LAC;
|
||||
hst[hst_p].mq = MQ;
|
||||
hst_p = (hst_p + 1) % HIST_SIZE;
|
||||
hst_p = (hst_p + 1);
|
||||
if (hst_p >= hst_lnt) hst_p = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2001,6 +2021,7 @@ for (j = 0; j < API_HLVL+1; j++) hst[hst_p].ir =
|
|||
hst[hst_p].ir1 = 0;
|
||||
hst[hst_p].lac = 0;
|
||||
hst[hst_p].mq = lvl;
|
||||
hst_p = (hst_p + 1) % HIST_SIZE;
|
||||
hst_p = (hst_p + 1);
|
||||
if (hst_p >= hst_lnt) hst_p = 0;
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
||||
18-Oct-03 RMS Added DECtape off reel message
|
||||
18-Jul-03 RMS Added FP15 support
|
||||
Added XVM support
|
||||
Added EAE option for PDP-4
|
||||
|
@ -110,6 +111,7 @@
|
|||
#define STOP_NONSTD 6 /* non-std dev num */
|
||||
#define STOP_MME 7 /* mem mgt error */
|
||||
#define STOP_FPDIS 8 /* fp inst, fpp disabled */
|
||||
#define STOP_DTOFF 9 /* DECtape off reel */
|
||||
|
||||
/* Peripheral configuration */
|
||||
|
||||
|
|
|
@ -154,6 +154,7 @@ The 18b PDP simulators implement several unique stop conditions:
|
|||
instruction execution
|
||||
- an FP15 instruction is decoded, the FP15 is disabled,
|
||||
and register STOP_FPP is set
|
||||
- a simulated DECtape runs off the end of its real
|
||||
|
||||
The PDP-4 and PDP-7 LOAD command supports only "second stage" RIM format
|
||||
files (alternating DAC address instructions and data):
|
||||
|
@ -273,6 +274,16 @@ control registers for the interrupt system.
|
|||
"addr" signifies the address width of the system (13b for the PDP-4, 15b for
|
||||
the PDP-7 and PDP-9, 17b for the PDP-15).
|
||||
|
||||
The CPU can maintain a history of the most recently executed instructions.
|
||||
This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands:
|
||||
|
||||
SET CPU HISTORY clear history buffer
|
||||
SET CPU HISTORY=0 disable history
|
||||
SET CPU HISTORY=n enable history, display length = n
|
||||
SHOW CPU HISTORY print CPU history
|
||||
|
||||
The maximum length for the history is 65536 entries.
|
||||
|
||||
2.2 Floating Point Processor (FPP)
|
||||
|
||||
The PDP-15 features an optional floating point processor, the FP15 (FPP).
|
||||
|
@ -756,7 +767,6 @@ The DECtape controller implements these registers:
|
|||
9,15 CA 18 current address (memory location 30)
|
||||
9,15 WC 18 word count (memory location 31)
|
||||
all LTIME 31 time between lines
|
||||
all ACTIME 31 time to accelerate to full speed
|
||||
all DCTIME 31 time to decelerate to a full stop
|
||||
all SUBSTATE 2 read/write command substate
|
||||
all POS[0:7] 32 position, in lines, units 0-7
|
||||
|
@ -767,8 +777,9 @@ among the DECtape parameters, or the DECtape simulator will fail to
|
|||
operate correctly.
|
||||
|
||||
- LTIME must be at least 6
|
||||
- ACTIME must be less than DCTIME, and both need to be at
|
||||
least 100 times LTIME
|
||||
- DCTIME needs to be at least 100 times LTIME
|
||||
|
||||
Acceleration time is set to 75% of deceleration time.
|
||||
|
||||
2.9 TC59/TU10 Magnetic Tape (MT)
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
drm (PDP-4,PDP-7) Type 24 serial drum
|
||||
|
||||
26-Oct-03 RMS Cleaned up buffer copy code
|
||||
05-Dec-02 RMS Updated from Type 24 documentation
|
||||
22-Nov-02 RMS Added PDP-4 support
|
||||
05-Feb-02 RMS Added DIB, device number support
|
||||
|
@ -165,6 +166,7 @@ t_stat drm_svc (UNIT *uptr)
|
|||
{
|
||||
int32 i;
|
||||
uint32 da;
|
||||
int32 *fbuf = uptr->filebuf;
|
||||
|
||||
if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
|
||||
drm_err = 1; /* set error */
|
||||
|
@ -173,13 +175,13 @@ if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
|
|||
|
||||
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 (uptr->FUNC == DRM_READ) { /* read? */
|
||||
if (MEM_ADDR_OK (drm_ma)) /* if !nxm */
|
||||
M[drm_ma] = fbuf[da]; } /* read word */
|
||||
else { /* write */
|
||||
if ((drm_wlk >> (drm_da >> 4)) & 1) drm_err = 1;
|
||||
else {
|
||||
*(((int32 *) uptr->filebuf) + da) = M[drm_ma];
|
||||
else { /* not locked */
|
||||
fbuf[da] = M[drm_ma]; /* write word */
|
||||
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 */
|
||||
|
|