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
|
RESTRICTION: The FP15 and XVM features of the PDP-15 are only partially
|
||||||
debugged. Do NOT enable these features for normal operations.
|
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
|
- Added simulated Ethernet support for VMS, FreeBSD, Mac OS/X.
|
||||||
to be loaded.
|
- Added status return to tmxr_putc_ln.
|
||||||
- The PTR BOOT command takes its starting memory field from the TA (address
|
- Added sim_putchar_s to handle possible output stalls.
|
||||||
switch) register.
|
|
||||||
|
|
||||||
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
|
2.1 SCP and libraries
|
||||||
|
|
||||||
- Fixed end of file problem in dep, idep.
|
- Fixed numerous bugs in Ethernet library.
|
||||||
- Fixed handling of trailing spaces in dep, idep.
|
|
||||||
|
|
||||||
2.2 PDP-1
|
2.2 All DECtapes
|
||||||
|
|
||||||
- Fixed system hang if continue after PTR error.
|
- Fixed reverse checksum value in 'read all' mode.
|
||||||
- Fixed PTR to start/stop on successive rpa instructions.
|
- 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 bug in RX28 read status (found by Charles Dickman).
|
||||||
- Fixed sign handling in PDP-15 EAE unsigned mul/div (differs from PDP-9).
|
- Fixed RX28 double density write.
|
||||||
- Fixed bug in CAF, clears API subsystem.
|
|
||||||
|
|
||||||
2.4 1401
|
2.4 PDP-18b
|
||||||
|
|
||||||
- Fixed tape read end-of-record handling based on real 1401.
|
- Fixed autoincrement bug in PDP-4, PDP-7, PDP-9.
|
||||||
- Added diagnostic read (space forward).
|
|
||||||
|
|
||||||
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
|
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.
|
- Changed RESTORE to unconditionally detach files.
|
||||||
- Added E11 and TPC format support to magtape library.
|
- Added E11 and TPC format support to magtape library.
|
||||||
- Fixed bug in SHOW CONNECTIONS.
|
- Fixed bug in SHOW CONNECTIONS.
|
||||||
- Added USE_ADDR64 support
|
- Added USE_ADDR64 support.
|
||||||
|
|
||||||
3.2 All magtapes
|
3.2 All magtapes
|
||||||
|
|
||||||
|
@ -68,6 +135,10 @@ debugged. Do NOT enable these features for normal operations.
|
||||||
|
|
||||||
- Added block loader format support to LOAD.
|
- Added block loader format support to LOAD.
|
||||||
- Changed BOOT PTR to allow loading of all of the first bank of memory.
|
- 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
|
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. 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 CVTfi bug: integer overflow not set if exponent out of range
|
||||||
- Fixed EMODx bugs:
|
- Fixed EMODx bugs:
|
||||||
|
@ -91,7 +167,7 @@ debugged. Do NOT enable these features for normal operations.
|
||||||
fast host processors (fixes from Mark Pizzolato).
|
fast host processors (fixes from Mark Pizzolato).
|
||||||
- Fixed bug in user disk size (found by Chaskiel M Grundman).
|
- 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 mnemonic, instruction lengths, and reverse scan length check bug for MCS.
|
||||||
- Fixed MCE bug, BS off by 1 if zero suppress.
|
- 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.
|
- Added check for invalid 8 character MCW, LCA.
|
||||||
- Fixed magtape load-mode end of record response.
|
- Fixed magtape load-mode end of record response.
|
||||||
- Revised fetch to model hardware more closely.
|
- 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 DSK variable size interaction with restore.
|
||||||
- Fixed bug in DSK set size routine.
|
- Fixed bug in DSK set size routine.
|
||||||
|
|
||||||
4.4 PDP-1
|
4.5 PDP-1
|
||||||
|
|
||||||
- Fixed DT variable size interaction with restore.
|
- Fixed DT variable size interaction with restore.
|
||||||
- Updated CPU, line printer, standard devices to detect indefinite I/O wait.
|
- Updated CPU, line printer, standard devices to detect indefinite I/O wait.
|
||||||
- Fixed incorrect logical, missing activate, break in drum simulator.
|
- Fixed incorrect logical, missing activate, break in drum simulator.
|
||||||
- Fixed bugs in instruction decoding, overprinting for line printer.
|
- 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 DT variable size interaction with restore.
|
||||||
- Fixed bug in MMR1 update (found by Tim Stark).
|
- 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.
|
o Added explicit runt and giant packet processing.
|
||||||
- Fixed bug in user disk size (found by Chaskiel M Grundman).
|
- 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 DT, RF variable size interaction with restore.
|
||||||
- Fixed MT bug in MTTR.
|
- 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 PDP-15 memory protect/skip interaction.
|
||||||
- Fixed bug in RF set size routine.
|
- Fixed bug in RF set size routine.
|
||||||
- Increased PTP TIME for PDP-15 operating systems.
|
- 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 DT, DF, RF, RX variable size interaction with restore.
|
||||||
- Fixed MT bug in SKTR.
|
- Fixed MT bug in SKTR.
|
||||||
- Fixed bug in DF, RF set size routine.
|
- 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 (13210A controller only), DQ read status.
|
||||||
- Fixed bug in DP, DQ seek complete.
|
- Fixed bug in DP, DQ seek complete.
|
||||||
- Fixed DR drum sizes.
|
- Fixed DR drum sizes.
|
||||||
- Fixed DR variable capacity interaction with SAVE/RESTORE.
|
- Fixed DR variable capacity interaction with SAVE/RESTORE.
|
||||||
|
|
||||||
4.9 GRI
|
4.10 GRI
|
||||||
|
|
||||||
- Fixed bug in SC queue pointer management.
|
- Fixed bug in SC queue pointer management.
|
||||||
|
|
||||||
4.10 PDP-10
|
4.11 PDP-10
|
||||||
|
|
||||||
- Fixed bug in RP read header.
|
- Fixed bug in RP read header.
|
||||||
|
|
||||||
4.11 Ibm1130
|
4.12 Ibm1130
|
||||||
|
|
||||||
- Fixed bugs found by APL 1130.
|
- Fixed bugs found by APL 1130.
|
||||||
|
|
||||||
4.12 Altairz80
|
4.13 Altairz80
|
||||||
|
|
||||||
- Fixed bug in real-time clock on Windows host.
|
- 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
|
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
|
packet reads and writes, since all operating systems talk to real ethernet
|
||||||
cards/controllers differently. The host-dependant Sim_Ether module currently
|
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
|
Currently, the Sim_Ether module sets the selected ethernet card into
|
||||||
promiscuous mode to gather all packets, then filters out the packets that it
|
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
|
most of the undesirable traffic. You will only see "excessive" traffic if you
|
||||||
are on a direct or hub(repeater) segment.
|
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:
|
Windows notes:
|
||||||
1. The Windows-specific code uses the WinPCAP 3.0 package from
|
1. The Windows-specific code uses the WinPCAP 3.0 package from
|
||||||
http://winpcap.polito.it. This package for windows simulates the libpcap
|
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.
|
2. You must *install* the WinPCAP runtime package.
|
||||||
|
|
||||||
3. The first time the WinPCAP driver is used, it will be dynamically loaded,
|
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
|
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
|
to run as an unprivileged user, you must set the service to autostart. See
|
||||||
the WinPCAP documentation for details on the static load workaround.
|
the WinPCAP documentation for details on the static loading 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
|
4. If you want to use TAP devices, they must be created before running SIMH.
|
||||||
to the packet read filter was added to reject packets from the current MAC,
|
(TAP component from the OpenVPN project; http://openvpn.sourceforge.net)
|
||||||
but this defeats DECNET's duplicate node number detection scheme. A more
|
|
||||||
correct fix for WinPCAP will be explored as time allows.
|
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:
|
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,
|
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
|
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
|
3. Put the required .lib files (packet,wpcap).lib from the WinPCAP 3.0
|
||||||
developer's kit in the linker's path
|
developer's kit in the linker's path
|
||||||
|
|
||||||
4. If you're using Borland C++, use COFF2OMF to convert the .lib files into
|
4. If you're using Borland C++, use COFF2OMF to convert the .lib files into
|
||||||
a format that can be used by the compiler.
|
a format that can be used by the compiler.
|
||||||
|
|
||||||
5. Define USE_NETWORK if you want the network functionality.
|
5. Define USE_NETWORK if you want the network functionality.
|
||||||
|
|
||||||
6. Build it!
|
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
|
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
|
promiscuous mode by the driver. Alternative methods for avoiding the
|
||||||
'run as root' requirement will be welcomed.
|
'run as root' requirement will be welcomed.
|
||||||
|
|
||||||
Building on Linux, NetBSD, and OpenBSD:
|
2. If you want to use TAP devices, they must be created before running SIMH.
|
||||||
1. Get/install the libpcap package for your unix version. http://rpmfind.net
|
|
||||||
might be a useful site for finding the linux variants.
|
Linux, {Free|Net|Open}BSD, OS/X, Un*x notes:
|
||||||
2. Use Make USE_NETWORK=1 if you want the network functionality.
|
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!
|
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:
|
VAX simulator support:
|
||||||
|
|
||||||
An OpenVMS VAX v7.2 system with DECNET Phase IV, MultiNet 4.4a, and LAT 5.3 has
|
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:
|
PDP11 simulator support:
|
||||||
|
@ -88,15 +173,14 @@ Things planned for future releases:
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
Things which I need help with:
|
Things which I need help with:
|
||||||
1. Porting Sim_Ether packet driver to other host platforms, especially VMS.
|
1. Information about Remote MOP processing
|
||||||
2. Information about Remote MOP processing
|
2. VAX/PDP-11 hardware diagnotics image files and docs, to test XQ thoroughly.
|
||||||
3. VAX/PDP-11 hardware diagnotics image files and docs, to test XQ thoroughly.
|
3. Feedback on operation with other VAX/PDP-11 OS's.
|
||||||
4. Feedback on operation with other VAX/PDP-11 OS's.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
Please send all patches, questions, feedback, clarifications, and help to:
|
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!!
|
Thanks, and Enjoy!!
|
||||||
Dave
|
Dave
|
||||||
|
@ -106,33 +190,46 @@ Dave
|
||||||
Change Log
|
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:
|
05-Jun-03 Release:
|
||||||
1. Added SET/SHOW XQ STATS
|
1. Added SET/SHOW XQ STATS (David Hittner)
|
||||||
2. Added SHOW XQ FILTERS
|
2. Added SHOW XQ FILTERS (David Hittner)
|
||||||
3. Added ability to split received packet into multiple buffers
|
3. Added ability to split rcv packets into multiple buffers (David Hittner)
|
||||||
4. Added explicit runt & giant packet processing
|
4. Added explicit runt & giant packet processing (David Hittner)
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
30-May-03 Release:
|
30-May-03 Release:
|
||||||
1. Corrected bug in xq_setmac introduced in v3.0 (multiple people)
|
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)
|
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:
|
06-May-03 Release:
|
||||||
1. Added second XQ controller
|
1. Added second XQ controller (David Hittner)
|
||||||
2. Added SIMH v3.0 compatibility
|
2. Added SIMH v3.0 compatibility (David Hittner)
|
||||||
3. Removed SET ADDRESS functionality
|
3. Removed SET ADDRESS functionality (David Hittner)
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
10-Apr-03 Release:
|
10-Apr-03 Release:
|
||||||
1. Added preliminary support for RSTS/E
|
1. Added preliminary support for RSTS/E (David Hittner)
|
||||||
2. Added PDP-11 bootrom load via CSR flags
|
2. Added PDP-11 bootrom load via CSR flags (David Hittner)
|
||||||
3. Support for SPARC linux (thanks to Mark Pizzolato)
|
3. Support for SPARC linux (Mark Pizzolato)
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,10 @@
|
||||||
|
|
||||||
#include "altairz80_defs.h"
|
#include "altairz80_defs.h"
|
||||||
|
|
||||||
|
#if !defined (_WIN32)
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define PCQ_SIZE 64 /* must be 2**n */
|
#define PCQ_SIZE 64 /* must be 2**n */
|
||||||
#define PCQ_SIZE_LOG2 6 /* log2 of PCQ_SIZE */
|
#define PCQ_SIZE_LOG2 6 /* log2 of PCQ_SIZE */
|
||||||
#define PCQ_MASK (PCQ_SIZE - 1)
|
#define PCQ_MASK (PCQ_SIZE - 1)
|
||||||
|
@ -1686,14 +1690,18 @@ int32 sim_instr (void) {
|
||||||
register uint32 SP;
|
register uint32 SP;
|
||||||
register uint32 IX;
|
register uint32 IX;
|
||||||
register uint32 IY;
|
register uint32 IY;
|
||||||
register uint32 temp, acu, sum, cbits;
|
register uint32 temp = 0;
|
||||||
register uint32 op, adr;
|
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
|
/* 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 */
|
in one microsecond on a 1MHz CPU. tStates is used real-time simulation */
|
||||||
register uint32 tStates;
|
register uint32 tStates;
|
||||||
uint32 tStatesInSlice; /* number of t-states in 10 mSec time-slice */
|
uint32 tStatesInSlice; /* number of t-states in 10 mSec time-slice */
|
||||||
uint32 startTime;
|
uint32 startTime;
|
||||||
int32 br1, br2, tStateModifier;
|
int32 br1, br2, tStateModifier = FALSE;
|
||||||
|
|
||||||
pc = saved_PC & ADDRMASK; /* load local PC */
|
pc = saved_PC & ADDRMASK; /* load local PC */
|
||||||
af[af_sel] = AF_S;
|
af[af_sel] = AF_S;
|
||||||
|
@ -1744,7 +1752,16 @@ int32 sim_instr (void) {
|
||||||
/* clockFrequency != 0 implies that real time clock is available */
|
/* clockFrequency != 0 implies that real time clock is available */
|
||||||
startTime += sliceLength;
|
startTime += sliceLength;
|
||||||
tStates -= tStatesInSlice;
|
tStates -= tStatesInSlice;
|
||||||
|
#if defined (_WIN32)
|
||||||
while (sim_os_msec() <= startTime) {} /* poor man's sleep */
|
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)) {
|
if (timerInterrupt && (IFF & 1)) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* gri_stddev.c: GRI-909 standard devices
|
/* 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
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -29,6 +29,7 @@
|
||||||
hsp S42-006 high speed punch
|
hsp S42-006 high speed punch
|
||||||
rtc real time clock
|
rtc real time clock
|
||||||
|
|
||||||
|
29-Dec-03 RMS Added support for console backpressure
|
||||||
25-Apr-03 RMS Revised for extended file support
|
25-Apr-03 RMS Revised for extended file support
|
||||||
22-Dec-02 RMS Added break support
|
22-Dec-02 RMS Added break support
|
||||||
01-Nov-02 RMS Added 7b/8B support to terminal
|
01-Nov-02 RMS Added 7b/8B support to terminal
|
||||||
|
@ -246,12 +247,14 @@ t_stat tto_svc (UNIT *uptr)
|
||||||
int32 c;
|
int32 c;
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
dev_done = dev_done | INT_TTO; /* set ready */
|
|
||||||
if (tto_unit.flags & UNIT_KSR) { /* KSR? */
|
if (tto_unit.flags & UNIT_KSR) { /* KSR? */
|
||||||
c = tto_unit.buf & 0177; /* force 7b */
|
c = tto_unit.buf & 0177; /* force 7b */
|
||||||
if (islower (c)) c = toupper (c); } /* cvt to UC */
|
if (islower (c)) c = toupper (c); } /* cvt to UC */
|
||||||
else c = tto_unit.buf & ((tto_unit.flags & UNIT_8B)? 0377: 0177);
|
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;
|
tto_unit.pos = tto_unit.pos + 1;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
495
H316/h316_cpu.c
|
@ -1,6 +1,6 @@
|
||||||
/* h316_cpu.c: Honeywell 316/516 CPU simulator
|
/* 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
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
cpu H316/H516 CPU
|
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
|
30-Dec-01 RMS Added old PC queue
|
||||||
03-Nov-01 RMS Fixed NOHSA modifier
|
03-Nov-01 RMS Fixed NOHSA modifier
|
||||||
30-Nov-01 RMS Added extended SET/SHOW support
|
30-Nov-01 RMS Added extended SET/SHOW support
|
||||||
|
@ -167,10 +169,10 @@
|
||||||
|
|
||||||
2. Interrupts. Interrupts are maintained by two parallel variables:
|
2. Interrupts. Interrupts are maintained by two parallel variables:
|
||||||
|
|
||||||
dev_ready device ready flags
|
dev_int device interrupt flags
|
||||||
dev_enable device interrupt enable 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
|
defer flags. If interrupt enable and interrupt no defer are set, and
|
||||||
at least one interrupt request is pending, then an interrupt occurs.
|
at least one interrupt request is pending, then an interrupt occurs.
|
||||||
The order of flags in these variables corresponds to the order
|
The order of flags in these variables corresponds to the order
|
||||||
|
@ -194,8 +196,6 @@
|
||||||
#define PCQ_MASK (PCQ_SIZE - 1)
|
#define PCQ_MASK (PCQ_SIZE - 1)
|
||||||
#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = PC
|
#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = PC
|
||||||
#define PCQ_TOP pcq[pcq_p]
|
#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 m7 0001000 /* for generics */
|
||||||
#define m8 0000400
|
#define m8 0000400
|
||||||
#define m9 0000200
|
#define m9 0000200
|
||||||
|
@ -207,6 +207,20 @@
|
||||||
#define m15 0000002
|
#define m15 0000002
|
||||||
#define m16 0000001
|
#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 */
|
uint16 M[MAXMEMSIZE] = { 0 }; /* memory */
|
||||||
int32 saved_AR = 0; /* A register */
|
int32 saved_AR = 0; /* A register */
|
||||||
int32 saved_BR = 0; /* B register */
|
int32 saved_BR = 0; /* B register */
|
||||||
|
@ -219,27 +233,44 @@ int32 extoff_pending = 0; /* extend off pending */
|
||||||
int32 dp = 0; /* double mode */
|
int32 dp = 0; /* double mode */
|
||||||
int32 sc = 0; /* shift count */
|
int32 sc = 0; /* shift count */
|
||||||
int32 ss[4]; /* sense switches */
|
int32 ss[4]; /* sense switches */
|
||||||
int32 dev_ready = 0; /* dev ready */
|
int32 dev_int = 0; /* dev ready */
|
||||||
int32 dev_enable = 0; /* dev enable */
|
int32 dev_enb = 0; /* dev enable */
|
||||||
int32 ind_max = 8; /* iadr nest limit */
|
int32 ind_max = 8; /* iadr nest limit */
|
||||||
int32 stop_inst = 1; /* stop on ill inst */
|
int32 stop_inst = 1; /* stop on ill inst */
|
||||||
int32 stop_dev = 2; /* stop on ill dev */
|
int32 stop_dev = 2; /* stop on ill dev */
|
||||||
uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
|
uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
|
||||||
int32 pcq_p = 0; /* PC queue ptr */
|
int32 pcq_p = 0; /* PC queue ptr */
|
||||||
REG *pcq_r = NULL; /* PC queue reg ptr */
|
REG *pcq_r = NULL; /* PC queue reg ptr */
|
||||||
int32 dlog = 0; /* debug log */
|
uint32 dma_nch = DMA_MAX; /* number of chan */
|
||||||
int32 turnoff = 0;
|
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_int_char;
|
||||||
extern int32 sim_interval;
|
extern int32 sim_interval;
|
||||||
extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
|
extern int32 sim_brk_types, sim_brk_dflt, sim_brk_summ; /* breakpoint info */
|
||||||
extern FILE *sim_log;
|
extern FILE *sim_log;
|
||||||
|
extern DEVICE *sim_devices[];
|
||||||
|
|
||||||
|
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_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
|
||||||
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
|
t_stat cpu_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
|
||||||
t_stat cpu_reset (DEVICE *dptr);
|
t_stat cpu_reset (DEVICE *dptr);
|
||||||
t_stat cpu_set_noext (UNIT *uptr, int32 val, char *cptr, void *desc);
|
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_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,
|
extern t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
|
||||||
UNIT *uptr, int32 sw);
|
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
|
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) };
|
MAXMEMSIZE) };
|
||||||
|
|
||||||
REG cpu_reg[] = {
|
REG cpu_reg[] = {
|
||||||
|
@ -270,19 +303,23 @@ REG cpu_reg[] = {
|
||||||
{ FLDATA (SS2, ss[1], 0) },
|
{ FLDATA (SS2, ss[1], 0) },
|
||||||
{ FLDATA (SS3, ss[2], 0) },
|
{ FLDATA (SS3, ss[2], 0) },
|
||||||
{ FLDATA (SS4, ss[3], 0) },
|
{ FLDATA (SS4, ss[3], 0) },
|
||||||
{ FLDATA (ION, dev_ready, INT_V_ON) },
|
{ FLDATA (ION, dev_int, INT_V_ON) },
|
||||||
{ FLDATA (INODEF, dev_ready, INT_V_NODEF) },
|
{ FLDATA (INODEF, dev_int, INT_V_NODEF) },
|
||||||
{ ORDATA (DEVRDY, dev_ready, 16), REG_RO },
|
{ ORDATA (DEVINT, dev_int, 16), REG_RO },
|
||||||
{ ORDATA (DEVENB, dev_enable, 16), REG_RO },
|
{ ORDATA (DEVENB, dev_enb, 16), REG_RO },
|
||||||
{ FLDATA (MPERDY, dev_ready, INT_V_MPE) },
|
{ ORDATA (CHREQ, chan_req, DMA_MAX + DMC_MAX) },
|
||||||
{ FLDATA (MPEENB, dev_enable, INT_V_MPE) },
|
{ 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_INST, stop_inst, 0) },
|
||||||
{ FLDATA (STOP_DEV, stop_dev, 1) },
|
{ FLDATA (STOP_DEV, stop_dev, 1) },
|
||||||
{ DRDATA (INDMAX, ind_max, 8), REG_NZ + PV_LEFT },
|
{ DRDATA (INDMAX, ind_max, 8), REG_NZ + PV_LEFT },
|
||||||
{ BRDATA (PCQ, pcq, 8, 15, PCQ_SIZE), REG_RO + REG_CIRC },
|
{ BRDATA (PCQ, pcq, 8, 15, PCQ_SIZE), REG_RO + REG_CIRC },
|
||||||
{ ORDATA (PCQP, pcq_p, 6), REG_HRO },
|
{ ORDATA (PCQP, pcq_p, 6), REG_HRO },
|
||||||
{ ORDATA (WRU, sim_int_char, 8) },
|
{ ORDATA (WRU, sim_int_char, 8) },
|
||||||
{ FLDATA (DLOG, dlog, 0), REG_HIDDEN },
|
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
MTAB cpu_mod[] = {
|
MTAB cpu_mod[] = {
|
||||||
|
@ -296,47 +333,42 @@ MTAB cpu_mod[] = {
|
||||||
{ UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size },
|
{ UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size },
|
||||||
{ UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size },
|
{ UNIT_MSIZE, 24576, NULL, "24K", &cpu_set_size },
|
||||||
{ UNIT_MSIZE, 32768, NULL, "32K", &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 } };
|
{ 0 } };
|
||||||
|
|
||||||
DEVICE cpu_dev = {
|
DEVICE cpu_dev = {
|
||||||
"CPU", &cpu_unit, cpu_reg, cpu_mod,
|
"CPU", &cpu_unit, cpu_reg, cpu_mod,
|
||||||
1, 8, 15, 1, 8, 16,
|
1, 8, 15, 1, 8, 16,
|
||||||
&cpu_ex, &cpu_dep, &cpu_reset,
|
&cpu_ex, &cpu_dep, &cpu_reset,
|
||||||
NULL, NULL, NULL };
|
NULL, NULL, NULL,
|
||||||
|
&cpu_dib, 0 };
|
||||||
/* 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 };
|
|
||||||
|
|
||||||
|
|
||||||
t_stat sim_instr (void)
|
t_stat sim_instr (void)
|
||||||
{
|
{
|
||||||
extern UNIT clk_unit;
|
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;
|
uint32 ut;
|
||||||
t_stat reason;
|
t_stat reason;
|
||||||
t_stat Ea (int32 inst, int32 *addr);
|
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 Add16 (int32 val1, int32 val2);
|
||||||
int32 Add31 (int32 val1, int32 val2);
|
int32 Add31 (int32 val1, int32 val2);
|
||||||
int32 Operate (int32 MB, int32 AR);
|
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_S(h,l) (((h) << 15) | ((l) & MMASK))
|
||||||
#define GETDBL_U(h,l) (((h) << 16) | (l))
|
#define GETDBL_U(h,l) (((h) << 16) | (l))
|
||||||
#define PUTDBL_S(x) AR = ((x) >> 15) & DMASK; \
|
#define PUTDBL_S(x) AR = ((x) >> 15) & DMASK; \
|
||||||
|
@ -349,12 +381,12 @@ int32 Operate (int32 MB, int32 AR);
|
||||||
|
|
||||||
/* Restore register state */
|
/* Restore register state */
|
||||||
|
|
||||||
|
if (devtab_init ()) return SCPE_STOP; /* init tables */
|
||||||
AR = saved_AR & DMASK; /* restore reg */
|
AR = saved_AR & DMASK; /* restore reg */
|
||||||
BR = saved_BR & DMASK;
|
BR = saved_BR & DMASK;
|
||||||
XR = saved_XR & DMASK;
|
XR = saved_XR & DMASK;
|
||||||
PC = PC & ((cpu_unit.flags & UNIT_EXT)? X_AMASK: NX_AMASK); /* mask PC */
|
PC = PC & ((cpu_unit.flags & UNIT_EXT)? X_AMASK: NX_AMASK); /* mask PC */
|
||||||
reason = 0;
|
reason = 0;
|
||||||
turnoff = 0;
|
|
||||||
sim_rtc_init (clk_unit.wait); /* init calibration */
|
sim_rtc_init (clk_unit.wait); /* init calibration */
|
||||||
|
|
||||||
/* Main instruction fetch/decode loop */
|
/* Main instruction fetch/decode loop */
|
||||||
|
@ -363,14 +395,59 @@ while (reason == 0) { /* loop until halted */
|
||||||
if (sim_interval <= 0) { /* check clock queue */
|
if (sim_interval <= 0) { /* check clock queue */
|
||||||
if (reason = sim_process_event ()) break; }
|
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 */
|
pme = ext; /* save extend */
|
||||||
if (cpu_unit.flags & UNIT_EXT) ext = 1; /* ext opt? extend on */
|
if (cpu_unit.flags & UNIT_EXT) ext = 1; /* ext opt? extend on */
|
||||||
dev_ready = dev_ready & ~INT_ON; /* intr off */
|
dev_int = dev_int & ~INT_ON; /* intr off */
|
||||||
turnoff = 0;
|
|
||||||
if (dlog && sim_log) fprintf (sim_log, "Interrupt\n");
|
|
||||||
MB = 0120000 | M_INT; } /* inst = JST* 63 */
|
MB = 0120000 | M_INT; } /* inst = JST* 63 */
|
||||||
|
|
||||||
|
/* Instruction fetch */
|
||||||
|
|
||||||
else { if (sim_brk_summ &&
|
else { if (sim_brk_summ &&
|
||||||
sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
|
sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
|
||||||
reason = STOP_IBKPT; /* stop simulation */
|
reason = STOP_IBKPT; /* stop simulation */
|
||||||
|
@ -378,16 +455,17 @@ else { if (sim_brk_summ &&
|
||||||
Y = PC; /* set mem addr */
|
Y = PC; /* set mem addr */
|
||||||
MB = Read (Y); /* fetch instr */
|
MB = Read (Y); /* fetch instr */
|
||||||
PC = NEWA (Y, Y + 1); /* incr PC */
|
PC = NEWA (Y, Y + 1); /* incr PC */
|
||||||
dev_ready = dev_ready | INT_NODEF; }
|
dev_int = dev_int | INT_NODEF; }
|
||||||
|
|
||||||
sim_interval = sim_interval - 1;
|
sim_interval = sim_interval - 1;
|
||||||
if (dlog && sim_log && !turnoff) { /* cycle log? */
|
if (hst_lnt) { /* instr hist? */
|
||||||
int32 op = I_GETOP (MB) & 017; /* core opcode */
|
hst_p = (hst_p + 1); /* next entry */
|
||||||
t_value val = MB;
|
if (hst_p >= hst_lnt) hst_p = 0;
|
||||||
fprintf (sim_log, "A= %06o C= %1o P= %05o (", AR, C, PC);
|
hst[hst_p].pc = Y | HIST_PC | (C? HIST_C: 0); /* fill slots */
|
||||||
fprint_sym (sim_log, Y, &val, &cpu_unit, SWMASK ('M'));
|
hst[hst_p].ir = MB;
|
||||||
fprintf (sim_log, ")");
|
hst[hst_p].ar = AR;
|
||||||
if ((op == 0) || (op == 014)) fprintf (sim_log, "\n"); }
|
hst[hst_p].br = BR;
|
||||||
|
hst[hst_p].xr = XR; }
|
||||||
|
|
||||||
/* Memory reference instructions */
|
/* Memory reference instructions */
|
||||||
|
|
||||||
|
@ -397,12 +475,6 @@ case 001: case 021: case 041: case 061: /* JMP */
|
||||||
if (reason = Ea (MB, &Y)) break; /* eff addr */
|
if (reason = Ea (MB, &Y)) break; /* eff addr */
|
||||||
PCQ_ENTRY; /* save PC */
|
PCQ_ENTRY; /* save PC */
|
||||||
PC = NEWA (PC, Y); /* set new 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 */
|
if (extoff_pending) ext = extoff_pending = 0; /* cond ext off */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -423,10 +495,10 @@ case 003: case 023: case 043: case 063: /* ANA */
|
||||||
case 004: case 024: case 044: case 064: /* STA */
|
case 004: case 024: case 044: case 064: /* STA */
|
||||||
if (reason = Ea (MB, &Y)) break; /* eff addr */
|
if (reason = Ea (MB, &Y)) break; /* eff addr */
|
||||||
if (dp) { /* double prec? */
|
if (dp) { /* double prec? */
|
||||||
if ((Y & 1) == 0) Write (AR, Y); /* if even, store A */
|
if ((Y & 1) == 0) Write (Y, AR); /* if even, store A */
|
||||||
Write (BR, Y | 1); /* store B */
|
Write (Y | 1, BR); /* store B */
|
||||||
sc = 0; }
|
sc = 0; }
|
||||||
else Write (AR, Y); /* no, store word */
|
else Write (Y, AR); /* no, store word */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 005: case 025: case 045: case 065: /* ERA */
|
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 */
|
case 010: case 030: case 050: case 070: /* JST */
|
||||||
if (reason = Ea (MB, &Y)) break; /* eff addr */
|
if (reason = Ea (MB, &Y)) break; /* eff addr */
|
||||||
MB = NEWA (Read (Y), PC); /* merge old PC */
|
MB = NEWA (Read (Y), PC); /* merge old PC */
|
||||||
Write (MB, Y);
|
Write (Y, MB);
|
||||||
PCQ_ENTRY;
|
PCQ_ENTRY;
|
||||||
PC = NEWA (PC, Y + 1); /* set new PC */
|
PC = NEWA (PC, Y + 1); /* set new PC */
|
||||||
break;
|
break;
|
||||||
|
@ -476,20 +548,20 @@ case 011: case 031: case 051: case 071: /* CAS */
|
||||||
case 012: case 032: case 052: case 072: /* IRS */
|
case 012: case 032: case 052: case 072: /* IRS */
|
||||||
if (reason = Ea (MB, &Y)) break; /* eff addr */
|
if (reason = Ea (MB, &Y)) break; /* eff addr */
|
||||||
MB = (Read (Y) + 1) & DMASK; /* incr, rewrite */
|
MB = (Read (Y) + 1) & DMASK; /* incr, rewrite */
|
||||||
Write (MB, Y);
|
Write (Y, MB);
|
||||||
if (MB == 0) PC = NEWA (PC, PC + 1); /* skip if zero */
|
if (MB == 0) PC = NEWA (PC, PC + 1); /* skip if zero */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 013: case 033: case 053: case 073: /* IMA */
|
case 013: case 033: case 053: case 073: /* IMA */
|
||||||
if (reason = Ea (MB, &Y)) break; /* eff addr */
|
if (reason = Ea (MB, &Y)) break; /* eff addr */
|
||||||
MB = Read (Y);
|
MB = Read (Y);
|
||||||
Write (AR, Y); /* A to mem */
|
Write (Y, AR); /* A to mem */
|
||||||
AR = MB; /* mem to A */
|
AR = MB; /* mem to A */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 015: case 055: /* STX */
|
case 015: case 055: /* STX */
|
||||||
if (reason = Ea (MB & ~IDX, &Y)) break; /* eff addr */
|
if (reason = Ea (MB & ~IDX, &Y)) break; /* eff addr */
|
||||||
Write (XR, Y); /* store XR */
|
Write (Y, XR); /* store XR */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 035: case 075: /* LDX */
|
case 035: case 075: /* LDX */
|
||||||
|
@ -525,35 +597,32 @@ case 017: case 037: case 057: case 077: /* DIV */
|
||||||
/* I/O instructions */
|
/* I/O instructions */
|
||||||
|
|
||||||
case 014: /* OCP */
|
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;
|
reason = t2 >> IOT_V_REASON;
|
||||||
turnoff = 0;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 034: /* SKS */
|
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;
|
reason = t2 >> IOT_V_REASON;
|
||||||
if (t2 & IOT_SKIP) { /* skip? */
|
if (t2 & IOT_SKIP) PC = NEWA (PC, PC + 1); /* skip? */
|
||||||
PC = NEWA (PC, PC + 1);
|
|
||||||
turnoff = 0; }
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 054: /* INA */
|
case 054: /* INA */
|
||||||
|
dev = MB & DEVMASK;
|
||||||
if (MB & INCLRA) AR = 0;
|
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;
|
reason = t2 >> IOT_V_REASON;
|
||||||
if (t2 & IOT_SKIP) { /* skip? */
|
if (t2 & IOT_SKIP) PC = NEWA (PC, PC + 1); /* skip? */
|
||||||
PC = NEWA (PC, PC + 1);
|
|
||||||
turnoff = 0; }
|
|
||||||
AR = t2 & DMASK; /* data */
|
AR = t2 & DMASK; /* data */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 074: /* OTA */
|
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;
|
reason = t2 >> IOT_V_REASON;
|
||||||
if (t2 & IOT_SKIP) { /* skip? */
|
if (t2 & IOT_SKIP) PC = NEWA (PC, PC + 1); /* skip? */
|
||||||
PC = NEWA (PC, PC + 1);
|
|
||||||
turnoff = 0; }
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Control */
|
/* Control */
|
||||||
|
@ -571,8 +640,7 @@ case 000:
|
||||||
ext = 1;
|
ext = 1;
|
||||||
extoff_pending = 0; } /* DXA */
|
extoff_pending = 0; } /* DXA */
|
||||||
else extoff_pending = 1; }
|
else extoff_pending = 1; }
|
||||||
if (MB & m12) /* RMP */
|
if (MB & m12) CLR_INT (INT_MPE); /* RMP */
|
||||||
dev_ready = dev_ready & ~INT_MPE;
|
|
||||||
if (MB & m11) { /* SCA, INK */
|
if (MB & m11) { /* SCA, INK */
|
||||||
if (MB & m15) /* INK */
|
if (MB & m15) /* INK */
|
||||||
AR = (C << 15) | (dp << 14) | (pme << 13) | (sc & 037);
|
AR = (C << 15) | (dp << 14) | (pme << 13) | (sc & 037);
|
||||||
|
@ -594,9 +662,9 @@ case 000:
|
||||||
BR = AR;
|
BR = AR;
|
||||||
AR = sc; }
|
AR = sc; }
|
||||||
if (MB & m8) /* ENB */
|
if (MB & m8) /* ENB */
|
||||||
dev_ready = (dev_ready | INT_ON) & ~INT_NODEF;
|
dev_int = (dev_int | INT_ON) & ~INT_NODEF;
|
||||||
if (MB & m7) /* INH */
|
if (MB & m7) /* INH */
|
||||||
dev_ready = dev_ready & ~INT_ON;
|
dev_int = dev_int & ~INT_ON;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Shift
|
/* Shift
|
||||||
|
@ -841,15 +909,17 @@ else { /* non-extend */
|
||||||
Y = NEWA (Y, IR + ((IR & IDX)? XR: 0)); } /* post-index */
|
Y = NEWA (Y, IR + ((IR & IDX)? XR: 0)); } /* post-index */
|
||||||
} /* end else */
|
} /* end else */
|
||||||
*addr = Y = Y & X_AMASK; /* return addr */
|
*addr = Y = Y & X_AMASK; /* return addr */
|
||||||
if (dlog && sim_log && !turnoff) /* cycle log? */
|
if (hst_lnt) { /* history? */
|
||||||
fprintf (sim_log, " EA= %06o [%06o]\n", Y, M[Y]);
|
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? */
|
if (i >= ind_max) return STOP_IND; /* too many ind? */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write memory */
|
/* Write memory */
|
||||||
|
|
||||||
void Write (int32 val, int32 addr)
|
void Write (int32 addr, int32 val)
|
||||||
{
|
{
|
||||||
if (((addr == 0) || (addr >= 020)) && MEM_ADDR_OK (addr))
|
if (((addr == 0) || (addr >= 020)) && MEM_ADDR_OK (addr))
|
||||||
M[addr] = val;
|
M[addr] = val;
|
||||||
|
@ -878,10 +948,34 @@ return r;
|
||||||
|
|
||||||
/* Unimplemented I/O device */
|
/* 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);
|
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
|
/* Undefined operate instruction. This code is reached when the
|
||||||
opcode does not correspond to a standard operate instruction.
|
opcode does not correspond to a standard operate instruction.
|
||||||
|
@ -1027,12 +1121,16 @@ return ARx;
|
||||||
|
|
||||||
t_stat cpu_reset (DEVICE *dptr)
|
t_stat cpu_reset (DEVICE *dptr)
|
||||||
{
|
{
|
||||||
|
int32 i;
|
||||||
|
|
||||||
saved_AR = saved_BR = saved_XR = 0;
|
saved_AR = saved_BR = saved_XR = 0;
|
||||||
C = 0;
|
C = 0;
|
||||||
dp = 0;
|
dp = 0;
|
||||||
ext = pme = extoff_pending = 0;
|
ext = pme = extoff_pending = 0;
|
||||||
dev_ready = dev_ready & ~INT_PENDING;
|
dev_int = dev_int & ~INT_PENDING;
|
||||||
dev_enable = 0;
|
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);
|
pcq_r = find_reg ("PCQ", NULL, dptr);
|
||||||
if (pcq_r) pcq_r->qptr = 0;
|
if (pcq_r) pcq_r->qptr = 0;
|
||||||
else return SCPE_IERR;
|
else return SCPE_IERR;
|
||||||
|
@ -1086,3 +1184,216 @@ MEMSIZE = val;
|
||||||
for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0;
|
for (i = MEMSIZE; i < MAXMEMSIZE; i++) M[i] = 0;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
24-Oct-03 RMS Added DMA/DMC support
|
||||||
25-Apr-03 RMS Revised for extended file 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 */
|
#include "sim_defs.h" /* simulator defns */
|
||||||
|
|
||||||
/* Simulator stop codes */
|
/* Simulator stop codes */
|
||||||
|
@ -35,6 +39,10 @@
|
||||||
#define STOP_HALT 3 /* HALT */
|
#define STOP_HALT 3 /* HALT */
|
||||||
#define STOP_IBKPT 4 /* breakpoint */
|
#define STOP_IBKPT 4 /* breakpoint */
|
||||||
#define STOP_IND 5 /* indirect loop */
|
#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 */
|
/* Memory */
|
||||||
|
|
||||||
|
@ -56,10 +64,14 @@
|
||||||
|
|
||||||
/* CPU options */
|
/* 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_EXT (UNIT_V_UF + 1) /* extended mem */
|
||||||
#define UNIT_V_HSA (UNIT_V_UF + 2) /* high speed arith */
|
#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_EXT (1u << UNIT_V_EXT)
|
||||||
#define UNIT_HSA (1u << UNIT_V_HSA)
|
#define UNIT_HSA (1u << UNIT_V_HSA)
|
||||||
|
#define UNIT_DMC (1u << UNIT_V_DMC)
|
||||||
|
|
||||||
/* Instruction format */
|
/* Instruction format */
|
||||||
|
|
||||||
|
@ -84,8 +96,42 @@
|
||||||
#define ioSKS 1 /* skip if set */
|
#define ioSKS 1 /* skip if set */
|
||||||
#define ioINA 2 /* input to A */
|
#define ioINA 2 /* input to A */
|
||||||
#define ioOTA 3 /* output from 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 PTR 001 /* paper tape reader */
|
||||||
#define PTP 002 /* paper tape punch */
|
#define PTP 002 /* paper tape punch */
|
||||||
|
@ -93,11 +139,11 @@
|
||||||
#define TTY 004 /* console */
|
#define TTY 004 /* console */
|
||||||
#define CDR 005 /* card reader */
|
#define CDR 005 /* card reader */
|
||||||
#define MT 010 /* mag tape data */
|
#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 FHD 022 /* fixed head disk */
|
||||||
#define DMA 024 /* DMA control */
|
#define DMA 024 /* DMA control */
|
||||||
#define DP 025 /* moving head disk */
|
#define DP 025 /* moving head disk */
|
||||||
#define OPT 034 /* SKS/OCP option */
|
#define DEV_MAX 64
|
||||||
|
|
||||||
/* Interrupt flags, definitions correspond to SMK bits */
|
/* Interrupt flags, definitions correspond to SMK bits */
|
||||||
|
|
||||||
|
@ -119,7 +165,7 @@
|
||||||
#define IOT_V_REASON 17
|
#define IOT_V_REASON 17
|
||||||
#define IOT_V_SKIP 16
|
#define IOT_V_SKIP 16
|
||||||
#define IOT_SKIP (1u << IOT_V_SKIP)
|
#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 IOBADFNC(x) (((stop_inst) << IOT_V_REASON) | (x))
|
||||||
#define IOSKIP(x) (IOT_SKIP | (x))
|
#define IOSKIP(x) (IOT_SKIP | (x))
|
||||||
|
|
||||||
|
@ -137,8 +183,17 @@
|
||||||
#define INT_ON (1u << INT_V_ON)
|
#define INT_ON (1u << INT_V_ON)
|
||||||
#define INT_PENDING (INT_ON | INT_NODEF)
|
#define INT_PENDING (INT_ON | INT_NODEF)
|
||||||
|
|
||||||
#define SET_READY(x) dev_ready = dev_ready | (x)
|
#define SET_INT(x) dev_int = dev_int | (x)
|
||||||
#define CLR_READY(x) dev_ready = dev_ready & ~(x)
|
#define CLR_INT(x) dev_int = dev_int & ~(x)
|
||||||
#define TST_READY(x) ((dev_ready & (x)) != 0)
|
#define TST_INT(x) ((dev_int & (x)) != 0)
|
||||||
#define CLR_ENABLE(x) dev_enable = dev_enable & ~(x)
|
#define CLR_ENB(x) dev_enb = dev_enb & ~(x)
|
||||||
#define TST_INTREQ(x) ((dev_ready & dev_enable & (x)) != 0)
|
#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
|
To: Users
|
||||||
From: Bob Supnik
|
From: Bob Supnik
|
||||||
Subj: H316 Simulator Usage
|
Subj: H316 Simulator Usage
|
||||||
Date: 15-Jul-2003
|
Date: 15-Nov-2003
|
||||||
|
|
||||||
COPYRIGHT NOTICE
|
COPYRIGHT NOTICE
|
||||||
|
|
||||||
|
@ -41,15 +41,20 @@ The H316 requires the following files:
|
||||||
sim/ sim_defs.h
|
sim/ sim_defs.h
|
||||||
sim_rev.h
|
sim_rev.h
|
||||||
sim_sock.h
|
sim_sock.h
|
||||||
|
sim_tape.h
|
||||||
sim_tmxr.h
|
sim_tmxr.h
|
||||||
scp.c
|
scp.c
|
||||||
scp_tty.c
|
scp_tty.c
|
||||||
sim_sock.c
|
sim_sock.c
|
||||||
|
sim_tape.c
|
||||||
sim_tmxr.c
|
sim_tmxr.c
|
||||||
|
|
||||||
sim/h316/ h316_defs.h
|
sim/h316/ h316_defs.h
|
||||||
h316_cpu.c
|
h316_cpu.c
|
||||||
|
h316_fhd.c
|
||||||
h316_lp.c
|
h316_lp.c
|
||||||
|
h316_mt.c
|
||||||
|
h316_dp.c
|
||||||
h316_stddev.c
|
h316_stddev.c
|
||||||
h316_sys.c
|
h316_sys.c
|
||||||
|
|
||||||
|
@ -66,6 +71,9 @@ PTP 316/516-52 paper tape punch
|
||||||
TTY 316/516-33 console terminal
|
TTY 316/516-33 console terminal
|
||||||
CLK 316/516-12 real time clock
|
CLK 316/516-12 real time clock
|
||||||
LPT 316/516 line printer
|
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:
|
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
|
- reference to an undefined I/O device, and STOP_DEV is set
|
||||||
- more than INDMAX indirect references are detected during
|
- more than INDMAX indirect references are detected during
|
||||||
memory reference address decoding
|
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.
|
The H316/H516 loader is not implemented.
|
||||||
|
|
||||||
2.1 CPU
|
2.1 CPU
|
||||||
|
|
||||||
CPU options include choice of instruction set and memory size.
|
CPU options include choice of instruction set, memory size, DMC option,
|
||||||
|
and number of DMA channels.
|
||||||
|
|
||||||
SET CPU HSA high speed arithmetic instructions
|
SET CPU HSA high speed arithmetic instructions
|
||||||
SET CPU NOHSA no 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 16K set memory size = 16K
|
||||||
SET CPU 24K set memory size = 24K
|
SET CPU 24K set memory size = 24K
|
||||||
SET CPU 32K set memory size = 32K
|
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
|
If memory size is being reduced, and the memory being truncated contains
|
||||||
non-zero data, the simulator asks for confirmation. Data in the truncated
|
non-zero data, the simulator asks for confirmation. Data in the truncated
|
||||||
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
|
CPU registers include the visible state of the processor as well as the
|
||||||
control registers for the interrupt system.
|
control registers for the interrupt system.
|
||||||
|
@ -114,6 +138,10 @@ control registers for the interrupt system.
|
||||||
INTREQ 16 interrupt requests
|
INTREQ 16 interrupt requests
|
||||||
DEVRDY 16 device ready flags (read only)
|
DEVRDY 16 device ready flags (read only)
|
||||||
DEVENB 16 device interrupt enable 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_INST 1 stop on undefined instruction
|
||||||
STOP_DEV 1 stop on undefined device
|
STOP_DEV 1 stop on undefined device
|
||||||
INDMAX 1 indirect address limit
|
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
|
The real-time clock autocalibrates; the clock interval is adjusted up or
|
||||||
down so that the clock tracks actual elapsed time.
|
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
|
The line printer (LPT) writes data to a disk file. The POS register
|
||||||
specifies the number of the next data item to be written. Thus,
|
specifies the number of the next data item to be written. Thus,
|
||||||
by changing POS, the user can backspace or advance the printer.
|
by changing POS, the user can backspace or advance the printer.
|
||||||
|
|
||||||
|
The line printer 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:
|
The line printer implements these registers:
|
||||||
|
|
||||||
name size comments
|
name size comments
|
||||||
|
@ -243,8 +280,10 @@ The line printer implements these registers:
|
||||||
WDPOS 6 word position in current scan
|
WDPOS 6 word position in current scan
|
||||||
DRPOS 6 drum position
|
DRPOS 6 drum position
|
||||||
CRPOS 1 carriage position
|
CRPOS 1 carriage position
|
||||||
XFER 1 transfer ready flag
|
|
||||||
PRDN 1 print done 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
|
INTREQ 1 device interrupt request
|
||||||
ENABLE 1 device interrupt enable
|
ENABLE 1 device interrupt enable
|
||||||
SVCST 2 service state
|
SVCST 2 service state
|
||||||
|
@ -265,7 +304,207 @@ Error handling is as follows:
|
||||||
|
|
||||||
OS I/O error x report error and stop
|
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
|
The H316/H516 simulator implements symbolic display and input. Display is
|
||||||
controlled by command line switches:
|
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
|
lpt line printer
|
||||||
|
|
||||||
|
24-Oct-03 RMS Added DMA/DMC support
|
||||||
25-Apr-03 RMS Revised for extended file support
|
25-Apr-03 RMS Revised for extended file support
|
||||||
30-May-02 RMS Widened POS to 32b
|
30-May-02 RMS Widened POS to 32b
|
||||||
|
|
||||||
|
@ -55,8 +56,10 @@
|
||||||
lpt_crpos carriage position (0-1)
|
lpt_crpos carriage position (0-1)
|
||||||
lpt_svcst service state (shuttle, paper advance)
|
lpt_svcst service state (shuttle, paper advance)
|
||||||
lpt_svcch channel for paper advance (0 = no adv)
|
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_prdn printing done flag
|
||||||
|
lpt_dma use DMA/DMC
|
||||||
|
lpt_eor DMA/DMC end of range
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "h316_defs.h"
|
#include "h316_defs.h"
|
||||||
|
@ -67,22 +70,26 @@
|
||||||
#define LPT_SVCSH 01 /* shuttle */
|
#define LPT_SVCSH 01 /* shuttle */
|
||||||
#define LPT_SVCPA 02 /* paper advance */
|
#define LPT_SVCPA 02 /* paper advance */
|
||||||
|
|
||||||
extern int32 dev_ready, dev_enable;
|
extern int32 dev_int, dev_enb;
|
||||||
extern int32 stop_inst;
|
extern int32 stop_inst;
|
||||||
|
extern uint32 chan_req;
|
||||||
|
|
||||||
int32 lpt_wdpos = 0; /* word position */
|
int32 lpt_wdpos = 0; /* word position */
|
||||||
int32 lpt_drpos = 0; /* drum position */
|
int32 lpt_drpos = 0; /* drum position */
|
||||||
int32 lpt_crpos = 0; /* carriage position */
|
int32 lpt_crpos = 0; /* carriage position */
|
||||||
int32 lpt_svcst = 0; /* service state */
|
int32 lpt_svcst = 0; /* service state */
|
||||||
int32 lpt_svcch = 0; /* service channel */
|
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_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 */
|
char lpt_buf[LPT_WIDTH + 1] = { 0 }; /* line buffer */
|
||||||
int32 lpt_xtime = 5; /* transfer time */
|
int32 lpt_xtime = 5; /* transfer time */
|
||||||
int32 lpt_etime = 50; /* end of scan time */
|
int32 lpt_etime = 50; /* end of scan time */
|
||||||
int32 lpt_ptime = 5000; /* paper adv time */
|
int32 lpt_ptime = 5000; /* paper adv time */
|
||||||
int32 lpt_stopioe = 0; /* stop on error */
|
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_svc (UNIT *uptr);
|
||||||
t_stat lpt_reset (DEVICE *dptr);
|
t_stat lpt_reset (DEVICE *dptr);
|
||||||
|
|
||||||
|
@ -94,16 +101,20 @@ t_stat lpt_reset (DEVICE *dptr);
|
||||||
lpt_reg LPT register list
|
lpt_reg LPT register list
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
DIB lpt_dib = { LPT, IOBUS, 1, &lptio };
|
||||||
|
|
||||||
UNIT lpt_unit = { UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0) };
|
UNIT lpt_unit = { UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0) };
|
||||||
|
|
||||||
REG lpt_reg[] = {
|
REG lpt_reg[] = {
|
||||||
{ DRDATA (WDPOS, lpt_wdpos, 6) },
|
{ DRDATA (WDPOS, lpt_wdpos, 6) },
|
||||||
{ DRDATA (DRPOS, lpt_drpos, 6) },
|
{ DRDATA (DRPOS, lpt_drpos, 6) },
|
||||||
{ FLDATA (CRPOS, lpt_crpos, 0) },
|
{ 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 (PRDN, lpt_prdn, 0) },
|
||||||
{ FLDATA (INTREQ, dev_ready, INT_V_LPT) },
|
{ FLDATA (INTREQ, dev_int, INT_V_LPT) },
|
||||||
{ FLDATA (ENABLE, dev_enable, INT_V_LPT) },
|
{ FLDATA (ENABLE, dev_enb, INT_V_LPT) },
|
||||||
{ ORDATA (SVCST, lpt_svcst, 2) },
|
{ ORDATA (SVCST, lpt_svcst, 2) },
|
||||||
{ ORDATA (SVCCH, lpt_svcch, 2) },
|
{ ORDATA (SVCCH, lpt_svcch, 2) },
|
||||||
{ BRDATA (BUF, lpt_buf, 8, 8, 120) },
|
{ BRDATA (BUF, lpt_buf, 8, 8, 120) },
|
||||||
|
@ -118,12 +129,14 @@ DEVICE lpt_dev = {
|
||||||
"LPT", &lpt_unit, lpt_reg, NULL,
|
"LPT", &lpt_unit, lpt_reg, NULL,
|
||||||
1, 10, 31, 1, 8, 8,
|
1, 10, 31, 1, 8, 8,
|
||||||
NULL, NULL, &lpt_reset,
|
NULL, NULL, &lpt_reset,
|
||||||
NULL, NULL, NULL };
|
NULL, NULL, NULL,
|
||||||
|
&lpt_dib, DEV_DISABLE };
|
||||||
|
|
||||||
/* IO routine */
|
/* 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;
|
int32 chr;
|
||||||
|
|
||||||
switch (inst) { /* case on opcode */
|
switch (inst) { /* case on opcode */
|
||||||
|
@ -133,13 +146,26 @@ case ioOCP: /* OCP */
|
||||||
lpt_svcst = lpt_svcst | LPT_SVCPA; /* set state */
|
lpt_svcst = lpt_svcst | LPT_SVCPA; /* set state */
|
||||||
lpt_svcch = fnc >> 1; /* save channel */
|
lpt_svcch = fnc >> 1; /* save channel */
|
||||||
sim_activate (&lpt_unit, lpt_ptime);
|
sim_activate (&lpt_unit, lpt_ptime);
|
||||||
CLR_READY (INT_LPT); /* clear int */
|
CLR_INT (INT_LPT); /* clear int */
|
||||||
break;
|
break;
|
||||||
case 007: /* init scan */
|
case 003: /* init scan DMA/DMC */
|
||||||
lpt_prdn = 0; /* clear pr done */
|
lpt_prdn = 0; /* clear pr done */
|
||||||
lpt_wdpos = 0; /* init scan pos */
|
lpt_wdpos = 0; /* init scan pos */
|
||||||
if (!sim_is_active (&lpt_unit)) lpt_xfer = 1;
|
lpt_eor = 0;
|
||||||
CLR_READY (INT_LPT); /* clear int */
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
return IOBADFNC (dat); }
|
return IOBADFNC (dat); }
|
||||||
|
@ -148,7 +174,7 @@ case ioOCP: /* OCP */
|
||||||
case ioSKS: /* SKS */
|
case ioSKS: /* SKS */
|
||||||
switch (fnc) { /* case on fnc */
|
switch (fnc) { /* case on fnc */
|
||||||
case 000: /* if xfer rdy */
|
case 000: /* if xfer rdy */
|
||||||
if (lpt_xfer) return IOSKIP (dat);
|
if (lpt_rdy) return IOSKIP (dat);
|
||||||
break;
|
break;
|
||||||
case 002: /* if !alarm */
|
case 002: /* if !alarm */
|
||||||
if (lpt_unit.flags & UNIT_ATT) return IOSKIP (dat);
|
if (lpt_unit.flags & UNIT_ATT) return IOSKIP (dat);
|
||||||
|
@ -187,8 +213,8 @@ case ioSKS: /* SKS */
|
||||||
|
|
||||||
case ioOTA: /* OTA */
|
case ioOTA: /* OTA */
|
||||||
if (fnc) return IOBADFNC (dat); /* only fnc 0 */
|
if (fnc) return IOBADFNC (dat); /* only fnc 0 */
|
||||||
if (lpt_xfer) { /* xfer ready? */
|
if (lpt_rdy) { /* xfer ready? */
|
||||||
lpt_xfer = 0; /* clear xfer */
|
lpt_rdy = 0; /* clear xfer */
|
||||||
chr = (dat >> (lpt_crpos? 0: 8)) & 077; /* get 6b char */
|
chr = (dat >> (lpt_crpos? 0: 8)) & 077; /* get 6b char */
|
||||||
if (chr == lpt_drpos) { /* match drum pos? */
|
if (chr == lpt_drpos) { /* match drum pos? */
|
||||||
if (chr < 040) chr = chr | 0100;
|
if (chr < 040) chr = chr | 0100;
|
||||||
|
@ -207,6 +233,10 @@ case ioOTA: /* OTA */
|
||||||
} /* end if endscan */
|
} /* end if endscan */
|
||||||
else sim_activate (&lpt_unit, lpt_xtime);
|
else sim_activate (&lpt_unit, lpt_xtime);
|
||||||
return IOSKIP (dat); } /* skip return */
|
return IOSKIP (dat); } /* skip return */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ioEND: /* end DMA/DMC */
|
||||||
|
lpt_eor = 1; /* set end range */
|
||||||
break; } /* end case op */
|
break; } /* end case op */
|
||||||
return dat;
|
return dat;
|
||||||
}
|
}
|
||||||
|
@ -216,6 +246,7 @@ return dat;
|
||||||
t_stat lpt_svc (UNIT *uptr)
|
t_stat lpt_svc (UNIT *uptr)
|
||||||
{
|
{
|
||||||
int32 i;
|
int32 i;
|
||||||
|
int32 ch = lpt_dib.chan - 1; /* DMA/DMC chan */
|
||||||
static const char *lpt_cc[] = {
|
static const char *lpt_cc[] = {
|
||||||
"\r",
|
"\r",
|
||||||
"\n",
|
"\n",
|
||||||
|
@ -224,12 +255,18 @@ static const char *lpt_cc[] = {
|
||||||
|
|
||||||
if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */
|
if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */
|
||||||
return IORETURN (lpt_stopioe, SCPE_UNATT);
|
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 */
|
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_crpos == 0) lpt_prdn = 1; }
|
||||||
if (lpt_svcst & LPT_SVCPA) { /* paper advance */
|
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++) {
|
for (i = LPT_WIDTH - 1; i >= 0; i++) {
|
||||||
if (lpt_buf[i] != ' ') break; }
|
if (lpt_buf[i] != ' ') break; }
|
||||||
lpt_buf[i + 1] = 0;
|
lpt_buf[i + 1] = 0;
|
||||||
|
@ -250,12 +287,14 @@ int32 i;
|
||||||
|
|
||||||
lpt_wdpos = lpt_drpos = lpt_crpos = 0; /* clear positions */
|
lpt_wdpos = lpt_drpos = lpt_crpos = 0; /* clear positions */
|
||||||
lpt_svcst = lpt_svcch = 0; /* idle state */
|
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_prdn = 1; /* printing done */
|
||||||
|
lpt_eor = 0;
|
||||||
|
lpt_dma = 0;
|
||||||
for (i = 0; i < LPT_WIDTH; i++) lpt_buf[i] = ' '; /* clear buffer */
|
for (i = 0; i < LPT_WIDTH; i++) lpt_buf[i] = ' '; /* clear buffer */
|
||||||
lpt_buf[LPT_WIDTH] = 0;
|
lpt_buf[LPT_WIDTH] = 0;
|
||||||
CLR_READY (INT_LPT); /* clear int, enb */
|
CLR_INT (INT_LPT); /* clear int, enb */
|
||||||
CLR_ENABLE (INT_LPT);
|
CLR_ENB (INT_LPT);
|
||||||
sim_cancel (&lpt_unit); /* deactivate unit */
|
sim_cancel (&lpt_unit); /* deactivate unit */
|
||||||
return SCPE_OK;
|
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
|
tty 316/516-33 teleprinter
|
||||||
clk/options 316/516-12 real time clocks/internal options
|
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
|
25-Apr-03 RMS Revised for extended file support
|
||||||
01-Mar-03 RMS Added SET/SHOW CLK FREQ support
|
01-Mar-03 RMS Added SET/SHOW CLK FREQ support
|
||||||
22-Dec-02 RMS Added break support
|
22-Dec-02 RMS Added break support
|
||||||
|
@ -50,7 +51,7 @@ extern uint16 M[];
|
||||||
extern int32 PC;
|
extern int32 PC;
|
||||||
extern int32 stop_inst;
|
extern int32 stop_inst;
|
||||||
extern int32 C, dp, ext, extoff_pending, sc;
|
extern int32 C, dp, ext, extoff_pending, sc;
|
||||||
extern int32 dev_ready, dev_enable;
|
extern int32 dev_int, dev_enb;
|
||||||
extern UNIT cpu_unit;
|
extern UNIT cpu_unit;
|
||||||
|
|
||||||
int32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */
|
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 tty_mode = 0, tty_buf = 0; /* tty mode, buf */
|
||||||
int32 clk_tps = 60; /* ticks per second */
|
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_svc (UNIT *uptr);
|
||||||
t_stat ptr_reset (DEVICE *dptr);
|
t_stat ptr_reset (DEVICE *dptr);
|
||||||
t_stat ptr_boot (int32 unitno, 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_svc (UNIT *uptr);
|
||||||
t_stat ptp_reset (DEVICE *dptr);
|
t_stat ptp_reset (DEVICE *dptr);
|
||||||
|
int32 ttyio (int32 inst, int32 fnc, int32 dat, int32 dev);
|
||||||
t_stat tti_svc (UNIT *uptr);
|
t_stat tti_svc (UNIT *uptr);
|
||||||
t_stat tto_svc (UNIT *uptr);
|
t_stat tto_svc (UNIT *uptr);
|
||||||
t_stat tty_reset (DEVICE *dptr);
|
t_stat tty_reset (DEVICE *dptr);
|
||||||
t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc);
|
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_svc (UNIT *uptr);
|
||||||
t_stat clk_reset (DEVICE *dptr);
|
t_stat clk_reset (DEVICE *dptr);
|
||||||
t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
@ -80,14 +85,16 @@ t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
ptr_reg PTR register list
|
ptr_reg PTR register list
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
DIB ptr_dib = { PTR, IOBUS, 1, &ptrio };
|
||||||
|
|
||||||
UNIT ptr_unit = {
|
UNIT ptr_unit = {
|
||||||
UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0),
|
UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0),
|
||||||
SERIAL_IN_WAIT };
|
SERIAL_IN_WAIT };
|
||||||
|
|
||||||
REG ptr_reg[] = {
|
REG ptr_reg[] = {
|
||||||
{ ORDATA (BUF, ptr_unit.buf, 8) },
|
{ ORDATA (BUF, ptr_unit.buf, 8) },
|
||||||
{ FLDATA (READY, dev_ready, INT_V_PTR) },
|
{ FLDATA (READY, dev_int, INT_V_PTR) },
|
||||||
{ FLDATA (ENABLE, dev_enable, INT_V_PTR) },
|
{ FLDATA (ENABLE, dev_enb, INT_V_PTR) },
|
||||||
{ DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },
|
{ DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },
|
||||||
{ DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT },
|
{ DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT },
|
||||||
{ FLDATA (STOP_IOE, ptr_stopioe, 0) },
|
{ FLDATA (STOP_IOE, ptr_stopioe, 0) },
|
||||||
|
@ -97,7 +104,8 @@ DEVICE ptr_dev = {
|
||||||
"PTR", &ptr_unit, ptr_reg, NULL,
|
"PTR", &ptr_unit, ptr_reg, NULL,
|
||||||
1, 10, 31, 1, 8, 8,
|
1, 10, 31, 1, 8, 8,
|
||||||
NULL, NULL, &ptr_reset,
|
NULL, NULL, &ptr_reset,
|
||||||
&ptr_boot, NULL, NULL };
|
&ptr_boot, NULL, NULL,
|
||||||
|
&ptr_dib, 0 };
|
||||||
|
|
||||||
/* PTP data structures
|
/* PTP data structures
|
||||||
|
|
||||||
|
@ -107,13 +115,15 @@ DEVICE ptr_dev = {
|
||||||
ptp_reg PTP register list
|
ptp_reg PTP register list
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
DIB ptp_dib = { PTP, IOBUS, 1, &ptpio };
|
||||||
|
|
||||||
UNIT ptp_unit = {
|
UNIT ptp_unit = {
|
||||||
UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT };
|
UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT };
|
||||||
|
|
||||||
REG ptp_reg[] = {
|
REG ptp_reg[] = {
|
||||||
{ ORDATA (BUF, ptp_unit.buf, 8) },
|
{ ORDATA (BUF, ptp_unit.buf, 8) },
|
||||||
{ FLDATA (READY, dev_ready, INT_V_PTP) },
|
{ FLDATA (READY, dev_int, INT_V_PTP) },
|
||||||
{ FLDATA (ENABLE, dev_enable, INT_V_PTP) },
|
{ FLDATA (ENABLE, dev_enb, INT_V_PTP) },
|
||||||
{ FLDATA (POWER, ptp_power, 0) },
|
{ FLDATA (POWER, ptp_power, 0) },
|
||||||
{ DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT },
|
{ DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT },
|
||||||
{ DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT },
|
{ DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT },
|
||||||
|
@ -121,12 +131,12 @@ REG ptp_reg[] = {
|
||||||
{ FLDATA (STOP_IOE, ptp_stopioe, 0) },
|
{ FLDATA (STOP_IOE, ptp_stopioe, 0) },
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
|
|
||||||
DEVICE ptp_dev = {
|
DEVICE ptp_dev = {
|
||||||
"PTP", &ptp_unit, ptp_reg, NULL,
|
"PTP", &ptp_unit, ptp_reg, NULL,
|
||||||
1, 10, 31, 1, 8, 8,
|
1, 10, 31, 1, 8, 8,
|
||||||
NULL, NULL, &ptp_reset,
|
NULL, NULL, &ptp_reset,
|
||||||
NULL, NULL, NULL };
|
NULL, NULL, NULL,
|
||||||
|
&ptp_dib, 0 };
|
||||||
|
|
||||||
/* TTY data structures
|
/* TTY data structures
|
||||||
|
|
||||||
|
@ -139,6 +149,8 @@ DEVICE ptp_dev = {
|
||||||
#define TTI 0
|
#define TTI 0
|
||||||
#define TTO 1
|
#define TTO 1
|
||||||
|
|
||||||
|
DIB tty_dib = { TTY, IOBUS, 1, &ttyio };
|
||||||
|
|
||||||
UNIT tty_unit[] = {
|
UNIT tty_unit[] = {
|
||||||
{ UDATA (&tti_svc, UNIT_KSR, 0), KBD_POLL_WAIT },
|
{ UDATA (&tti_svc, UNIT_KSR, 0), KBD_POLL_WAIT },
|
||||||
{ UDATA (&tto_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT } };
|
{ UDATA (&tto_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT } };
|
||||||
|
@ -146,8 +158,8 @@ UNIT tty_unit[] = {
|
||||||
REG tty_reg[] = {
|
REG tty_reg[] = {
|
||||||
{ ORDATA (BUF, tty_buf, 8) },
|
{ ORDATA (BUF, tty_buf, 8) },
|
||||||
{ FLDATA (MODE, tty_mode, 0) },
|
{ FLDATA (MODE, tty_mode, 0) },
|
||||||
{ FLDATA (READY, dev_ready, INT_V_TTY) },
|
{ FLDATA (READY, dev_int, INT_V_TTY) },
|
||||||
{ FLDATA (ENABLE, dev_enable, INT_V_TTY) },
|
{ FLDATA (ENABLE, dev_enb, INT_V_TTY) },
|
||||||
{ DRDATA (KPOS, tty_unit[TTI].pos, T_ADDR_W), PV_LEFT },
|
{ DRDATA (KPOS, tty_unit[TTI].pos, T_ADDR_W), PV_LEFT },
|
||||||
{ DRDATA (KTIME, tty_unit[TTI].wait, 24), REG_NZ + PV_LEFT },
|
{ DRDATA (KTIME, tty_unit[TTI].wait, 24), REG_NZ + PV_LEFT },
|
||||||
{ DRDATA (TPOS, tty_unit[TTO].pos, T_ADDR_W), 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,
|
"TTY", tty_unit, tty_reg, tty_mod,
|
||||||
2, 10, 31, 1, 8, 8,
|
2, 10, 31, 1, 8, 8,
|
||||||
NULL, NULL, &tty_reset,
|
NULL, NULL, &tty_reset,
|
||||||
NULL, NULL, NULL };
|
NULL, NULL, NULL,
|
||||||
|
&tty_dib, 0 };
|
||||||
|
|
||||||
/* CLK data structures
|
/* CLK data structures
|
||||||
|
|
||||||
|
@ -174,12 +187,14 @@ DEVICE tty_dev = {
|
||||||
clk_reg CLK register list
|
clk_reg CLK register list
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
DIB clk_dib = { CLK_KEYS, IOBUS, 1, &clkio };
|
||||||
|
|
||||||
UNIT clk_unit = {
|
UNIT clk_unit = {
|
||||||
UDATA (&clk_svc, 0, 0), 16000 };
|
UDATA (&clk_svc, 0, 0), 16000 };
|
||||||
|
|
||||||
REG clk_reg[] = {
|
REG clk_reg[] = {
|
||||||
{ FLDATA (READY, dev_ready, INT_V_CLK) },
|
{ FLDATA (READY, dev_int, INT_V_CLK) },
|
||||||
{ FLDATA (ENABLE, dev_enable, INT_V_CLK) },
|
{ FLDATA (ENABLE, dev_enb, INT_V_CLK) },
|
||||||
{ DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT },
|
{ DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT },
|
||||||
{ DRDATA (TPS, clk_tps, 8), PV_LEFT + REG_HRO },
|
{ DRDATA (TPS, clk_tps, 8), PV_LEFT + REG_HRO },
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
@ -197,11 +212,12 @@ DEVICE clk_dev = {
|
||||||
"CLK", &clk_unit, clk_reg, clk_mod,
|
"CLK", &clk_unit, clk_reg, clk_mod,
|
||||||
1, 0, 0, 0, 0, 0,
|
1, 0, 0, 0, 0, 0,
|
||||||
NULL, NULL, &clk_reset,
|
NULL, NULL, &clk_reset,
|
||||||
NULL, NULL, NULL };
|
NULL, NULL, NULL,
|
||||||
|
&clk_dib, 0 };
|
||||||
|
|
||||||
/* Paper tape reader: IO routine */
|
/* 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 */
|
switch (inst) { /* case on opcode */
|
||||||
case ioOCP: /* OCP */
|
case ioOCP: /* OCP */
|
||||||
|
@ -211,14 +227,14 @@ case ioOCP: /* OCP */
|
||||||
break;
|
break;
|
||||||
case ioSKS: /* SKS */
|
case ioSKS: /* SKS */
|
||||||
if (fnc & 013) return IOBADFNC (dat); /* only fnc 0,4 */
|
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 */
|
((fnc == 4) && !TST_INTREQ (INT_PTR))) /* fnc 4? skip !int */
|
||||||
return IOSKIP (dat);
|
return IOSKIP (dat);
|
||||||
break;
|
break;
|
||||||
case ioINA: /* INA */
|
case ioINA: /* INA */
|
||||||
if (fnc & 007) return IOBADFNC (dat); /* only fnc 0,10 */
|
if (fnc) return IOBADFNC (dat); /* only fnc 0 */
|
||||||
if (TST_READY (INT_PTR)) { /* ready? */
|
if (TST_INT (INT_PTR)) { /* ready? */
|
||||||
CLR_READY (INT_PTR); /* clear ready */
|
CLR_INT (INT_PTR); /* clear ready */
|
||||||
return IOSKIP (ptr_unit.buf | dat); } /* ret buf, skip */
|
return IOSKIP (ptr_unit.buf | dat); } /* ret buf, skip */
|
||||||
break; } /* end case op */
|
break; } /* end case op */
|
||||||
return dat;
|
return dat;
|
||||||
|
@ -239,7 +255,7 @@ if ((temp = getc (ptr_unit.fileref)) == EOF) { /* read byte */
|
||||||
else perror ("PTR I/O error");
|
else perror ("PTR I/O error");
|
||||||
clearerr (ptr_unit.fileref);
|
clearerr (ptr_unit.fileref);
|
||||||
return SCPE_IOERR; }
|
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.buf = temp & 0377; /* get byte */
|
||||||
ptr_unit.pos = ftell (ptr_unit.fileref); /* update pos */
|
ptr_unit.pos = ftell (ptr_unit.fileref); /* update pos */
|
||||||
sim_activate (&ptr_unit, ptr_unit.wait); /* reactivate */
|
sim_activate (&ptr_unit, ptr_unit.wait); /* reactivate */
|
||||||
|
@ -250,8 +266,8 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat ptr_reset (DEVICE *dptr)
|
t_stat ptr_reset (DEVICE *dptr)
|
||||||
{
|
{
|
||||||
CLR_READY (INT_PTR); /* clear ready, enb */
|
CLR_INT (INT_PTR); /* clear ready, enb */
|
||||||
CLR_ENABLE (INT_PTR);
|
CLR_ENB (INT_PTR);
|
||||||
ptr_unit.buf = 0; /* clear buffer */
|
ptr_unit.buf = 0; /* clear buffer */
|
||||||
sim_cancel (&ptr_unit); /* deactivate unit */
|
sim_cancel (&ptr_unit); /* deactivate unit */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -292,13 +308,13 @@ return SCPE_OK;
|
||||||
|
|
||||||
/* Paper tape punch: IO routine */
|
/* 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 */
|
switch (inst) { /* case on opcode */
|
||||||
case ioOCP: /* OCP */
|
case ioOCP: /* OCP */
|
||||||
if (fnc & 016) return IOBADFNC (dat); /* only fnc 0,1 */
|
if (fnc & 016) return IOBADFNC (dat); /* only fnc 0,1 */
|
||||||
if (fnc) { /* fnc 1? pwr off */
|
if (fnc) { /* fnc 1? pwr off */
|
||||||
CLR_READY (INT_PTP); /* not ready */
|
CLR_INT (INT_PTP); /* not ready */
|
||||||
ptp_power = 0; /* turn off power */
|
ptp_power = 0; /* turn off power */
|
||||||
sim_cancel (&ptp_unit); } /* stop punch */
|
sim_cancel (&ptp_unit); } /* stop punch */
|
||||||
else if (ptp_power == 0) /* fnc 0? start */
|
else if (ptp_power == 0) /* fnc 0? start */
|
||||||
|
@ -307,7 +323,7 @@ case ioOCP: /* OCP */
|
||||||
case ioSKS: /* SKS */
|
case ioSKS: /* SKS */
|
||||||
if ((fnc & 012) || (fnc == 005)) /* only 0, 1, 4 */
|
if ((fnc & 012) || (fnc == 005)) /* only 0, 1, 4 */
|
||||||
return IOBADFNC (dat);
|
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 */
|
((fnc == 01) /* fnc 1? skip ptp on */
|
||||||
&& (ptp_power || sim_is_active (&ptp_unit))) ||
|
&& (ptp_power || sim_is_active (&ptp_unit))) ||
|
||||||
((fnc == 04) && !TST_INTREQ (INT_PTP))) /* fnc 4? skip !int */
|
((fnc == 04) && !TST_INTREQ (INT_PTP))) /* fnc 4? skip !int */
|
||||||
|
@ -315,8 +331,8 @@ case ioSKS: /* SKS */
|
||||||
break;
|
break;
|
||||||
case ioOTA: /* OTA */
|
case ioOTA: /* OTA */
|
||||||
if (fnc) return IOBADFNC (dat); /* only fnc 0 */
|
if (fnc) return IOBADFNC (dat); /* only fnc 0 */
|
||||||
if (TST_READY (INT_PTP)) { /* if ptp ready */
|
if (TST_INT (INT_PTP)) { /* if ptp ready */
|
||||||
CLR_READY (INT_PTP); /* clear ready */
|
CLR_INT (INT_PTP); /* clear ready */
|
||||||
ptp_unit.buf = dat & 0377; /* store byte */
|
ptp_unit.buf = dat & 0377; /* store byte */
|
||||||
sim_activate (&ptp_unit, ptp_unit.wait);
|
sim_activate (&ptp_unit, ptp_unit.wait);
|
||||||
return IOSKIP (dat); } /* skip return */
|
return IOSKIP (dat); } /* skip return */
|
||||||
|
@ -329,7 +345,7 @@ return dat;
|
||||||
t_stat ptp_svc (UNIT *uptr)
|
t_stat ptp_svc (UNIT *uptr)
|
||||||
{
|
{
|
||||||
|
|
||||||
SET_READY (INT_PTP); /* set flag */
|
SET_INT (INT_PTP); /* set flag */
|
||||||
if (ptp_power == 0) { /* power on? */
|
if (ptp_power == 0) { /* power on? */
|
||||||
ptp_power = 1; /* ptp is ready */
|
ptp_power = 1; /* ptp is ready */
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
|
@ -347,8 +363,8 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat ptp_reset (DEVICE *dptr)
|
t_stat ptp_reset (DEVICE *dptr)
|
||||||
{
|
{
|
||||||
CLR_READY (INT_PTP); /* clear ready, enb */
|
CLR_INT (INT_PTP); /* clear ready, enb */
|
||||||
CLR_ENABLE (INT_PTP);
|
CLR_ENB (INT_PTP);
|
||||||
ptp_power = 0; /* power off */
|
ptp_power = 0; /* power off */
|
||||||
ptp_unit.buf = 0; /* clear buffer */
|
ptp_unit.buf = 0; /* clear buffer */
|
||||||
sim_cancel (&ptp_unit); /* deactivate unit */
|
sim_cancel (&ptp_unit); /* deactivate unit */
|
||||||
|
@ -357,22 +373,22 @@ return SCPE_OK;
|
||||||
|
|
||||||
/* Terminal: IO routine */
|
/* 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 */
|
switch (inst) { /* case on opcode */
|
||||||
case ioOCP: /* OCP */
|
case ioOCP: /* OCP */
|
||||||
if (fnc & 016) return IOBADFNC (dat); /* only fnc 0,1 */
|
if (fnc & 016) return IOBADFNC (dat); /* only fnc 0,1 */
|
||||||
if (fnc && (tty_mode == 0)) { /* input to output? */
|
if (fnc && (tty_mode == 0)) { /* input to output? */
|
||||||
if (!sim_is_active (&tty_unit[TTO])) /* set ready */
|
if (!sim_is_active (&tty_unit[TTO])) /* set ready */
|
||||||
SET_READY (INT_TTY);
|
SET_INT (INT_TTY);
|
||||||
tty_mode = 1; } /* mode is output */
|
tty_mode = 1; } /* mode is output */
|
||||||
else if ((fnc == 0) && tty_mode) { /* output to input? */
|
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 */
|
tty_mode = 0; } /* mode is input */
|
||||||
break;
|
break;
|
||||||
case ioSKS: /* SKS */
|
case ioSKS: /* SKS */
|
||||||
if (fnc & 012) return IOBADFNC (dat); /* fnc 0,1,4,5 */
|
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 */
|
((fnc == 1) && /* fnc 1? skip !busy */
|
||||||
tty_mode && !sim_is_active (&tty_unit[TTO])) ||
|
tty_mode && !sim_is_active (&tty_unit[TTO])) ||
|
||||||
((fnc == 4) && !TST_INTREQ (INT_TTY)) || /* fnc 4? skip !int */
|
((fnc == 4) && !TST_INTREQ (INT_TTY)) || /* fnc 4? skip !int */
|
||||||
|
@ -381,22 +397,22 @@ case ioSKS: /* SKS */
|
||||||
return IOSKIP (dat);
|
return IOSKIP (dat);
|
||||||
break;
|
break;
|
||||||
case ioINA: /* INA */
|
case ioINA: /* INA */
|
||||||
if (fnc & 005) return IOBADFNC (dat); /* only 0,2,10,12 */
|
if (fnc & 005) return IOBADFNC (dat); /* only 0,2 */
|
||||||
if (TST_READY (INT_TTY)) { /* ready? */
|
if (TST_INT (INT_TTY)) { /* ready? */
|
||||||
if (tty_mode == 0) CLR_READY (INT_TTY); /* inp? clear rdy */
|
if (tty_mode == 0) CLR_INT (INT_TTY); /* inp? clear rdy */
|
||||||
return IOSKIP (dat |
|
return IOSKIP (dat |
|
||||||
(tty_buf & ((fnc & 002)? 077: 0377))); }
|
(tty_buf & ((fnc & 002)? 077: 0377))); }
|
||||||
break;
|
break;
|
||||||
case ioOTA:
|
case ioOTA:
|
||||||
if (fnc & 015) return IOBADFNC (dat); /* only 0,2 */
|
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 */
|
tty_buf = dat & 0377; /* store char */
|
||||||
if (fnc & 002) { /* binary mode? */
|
if (fnc & 002) { /* binary mode? */
|
||||||
tty_buf = tty_buf | 0100; /* set ch 7 */
|
tty_buf = tty_buf | 0100; /* set ch 7 */
|
||||||
if (tty_buf & 040) tty_buf = tty_buf & 0277; }
|
if (tty_buf & 040) tty_buf = tty_buf & 0277; }
|
||||||
if (tty_mode) {
|
if (tty_mode) {
|
||||||
sim_activate (&tty_unit[TTO], tty_unit[TTO].wait);
|
sim_activate (&tty_unit[TTO], tty_unit[TTO].wait);
|
||||||
CLR_READY (INT_TTY); }
|
CLR_INT (INT_TTY); }
|
||||||
return IOSKIP (dat); }
|
return IOSKIP (dat); }
|
||||||
break; } /* end case op */
|
break; } /* end case op */
|
||||||
return dat;
|
return dat;
|
||||||
|
@ -419,7 +435,7 @@ else c = c & ((tty_unit[TTI].flags & UNIT_8B)? 0377: 0177);
|
||||||
if (tty_mode == 0) { /* input mode? */
|
if (tty_mode == 0) { /* input mode? */
|
||||||
tty_buf = c; /* put char in buf */
|
tty_buf = c; /* put char in buf */
|
||||||
tty_unit[TTI].pos = tty_unit[TTI].pos + 1;
|
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 */
|
if (out) sim_putchar (out); } /* echo */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -429,12 +445,14 @@ t_stat tto_svc (UNIT *uptr)
|
||||||
int32 c;
|
int32 c;
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
SET_READY (INT_TTY); /* set done flag */
|
|
||||||
if (tty_unit[TTO].flags & UNIT_KSR) { /* UC only? */
|
if (tty_unit[TTO].flags & UNIT_KSR) { /* UC only? */
|
||||||
c = tty_buf & 0177; /* mask to 7b */
|
c = tty_buf & 0177; /* mask to 7b */
|
||||||
if (islower (c)) c = toupper (c); } /* cvt to UC */
|
if (islower (c)) c = toupper (c); } /* cvt to UC */
|
||||||
else c = tty_buf & ((tty_unit[TTO].flags & UNIT_8B)? 0377: 0177);
|
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;
|
tty_unit[TTO].pos = tty_unit[TTO].pos + 1;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -443,8 +461,8 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat tty_reset (DEVICE *dptr)
|
t_stat tty_reset (DEVICE *dptr)
|
||||||
{
|
{
|
||||||
CLR_READY (INT_TTY); /* clear ready, enb */
|
CLR_INT (INT_TTY); /* clear ready, enb */
|
||||||
CLR_ENABLE (INT_TTY);
|
CLR_ENB (INT_TTY);
|
||||||
tty_mode = 0; /* mode = input */
|
tty_mode = 0; /* mode = input */
|
||||||
tty_buf = 0;
|
tty_buf = 0;
|
||||||
sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* activate poll */
|
sim_activate (&tty_unit[TTI], tty_unit[TTI].wait); /* activate poll */
|
||||||
|
@ -461,12 +479,12 @@ return SCPE_OK;
|
||||||
|
|
||||||
/* Clock/options: IO routine */
|
/* 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 */
|
switch (inst) { /* case on opcode */
|
||||||
case ioOCP: /* OCP */
|
case ioOCP: /* OCP */
|
||||||
if (fnc & 015) return IOBADFNC (dat); /* only fnc 0,2 */
|
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 */
|
if (fnc) sim_cancel (&clk_unit); /* fnc = 2? stop */
|
||||||
else { /* fnc = 0? */
|
else { /* fnc = 0? */
|
||||||
if (!sim_is_active (&clk_unit))
|
if (!sim_is_active (&clk_unit))
|
||||||
|
@ -477,13 +495,13 @@ case ioSKS: /* SKS */
|
||||||
if (fnc == 0) { /* clock skip !int */
|
if (fnc == 0) { /* clock skip !int */
|
||||||
if (!TST_INTREQ (INT_CLK)) return IOSKIP (dat); }
|
if (!TST_INTREQ (INT_CLK)) return IOSKIP (dat); }
|
||||||
else if ((fnc & 007) == 002) { /* mem parity? */
|
else if ((fnc & 007) == 002) { /* mem parity? */
|
||||||
if (((fnc == 002) && !TST_READY (INT_MPE)) ||
|
if (((fnc == 002) && !TST_INT (INT_MPE)) ||
|
||||||
((fnc == 012) && TST_READY (INT_MPE)))
|
((fnc == 012) && TST_INT (INT_MPE)))
|
||||||
return IOSKIP (dat); }
|
return IOSKIP (dat); }
|
||||||
else return IOBADFNC (dat); /* invalid fnc */
|
else return IOBADFNC (dat); /* invalid fnc */
|
||||||
break;
|
break;
|
||||||
case ioOTA: /* OTA */
|
case ioOTA: /* OTA */
|
||||||
if (fnc == 000) dev_enable = dat; /* SMK */
|
if (fnc == 000) dev_enb = dat; /* SMK */
|
||||||
else if (fnc == 010) { /* OTK */
|
else if (fnc == 010) { /* OTK */
|
||||||
C = (dat >> 15) & 1; /* set C */
|
C = (dat >> 15) & 1; /* set C */
|
||||||
if (cpu_unit.flags & UNIT_HSA) /* HSA included? */
|
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 */
|
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 */
|
sim_activate (&clk_unit, sim_rtc_calb (clk_tps)); /* reactivate */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -514,8 +532,8 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat clk_reset (DEVICE *dptr)
|
t_stat clk_reset (DEVICE *dptr)
|
||||||
{
|
{
|
||||||
CLR_READY (INT_CLK); /* clear ready, enb */
|
CLR_INT (INT_CLK); /* clear ready, enb */
|
||||||
CLR_ENABLE (INT_CLK);
|
CLR_ENB (INT_CLK);
|
||||||
sim_cancel (&clk_unit); /* deactivate unit */
|
sim_cancel (&clk_unit); /* deactivate unit */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
24-Oct-03 RMS Added DMA/DMC support
|
||||||
17-Sep-01 RMS Removed multiconsole support
|
17-Sep-01 RMS Removed multiconsole support
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -31,9 +32,14 @@
|
||||||
|
|
||||||
extern DEVICE cpu_dev;
|
extern DEVICE cpu_dev;
|
||||||
extern UNIT cpu_unit;
|
extern UNIT cpu_unit;
|
||||||
extern DEVICE ptr_dev, ptp_dev;
|
extern DEVICE ptr_dev;
|
||||||
extern DEVICE tty_dev, lpt_dev;
|
extern DEVICE ptp_dev;
|
||||||
|
extern DEVICE tty_dev;
|
||||||
|
extern DEVICE lpt_dev;
|
||||||
extern DEVICE clk_dev;
|
extern DEVICE clk_dev;
|
||||||
|
extern DEVICE dp_dev;
|
||||||
|
extern DEVICE fhd_dev;
|
||||||
|
extern DEVICE mt_dev;
|
||||||
extern REG cpu_reg[];
|
extern REG cpu_reg[];
|
||||||
extern uint16 M[];
|
extern uint16 M[];
|
||||||
extern int32 sim_switches;
|
extern int32 sim_switches;
|
||||||
|
@ -54,10 +60,16 @@ REG *sim_PC = &cpu_reg[0];
|
||||||
|
|
||||||
int32 sim_emax = 1;
|
int32 sim_emax = 1;
|
||||||
|
|
||||||
DEVICE *sim_devices[] = { &cpu_dev,
|
DEVICE *sim_devices[] = {
|
||||||
&ptr_dev, &ptp_dev,
|
&cpu_dev,
|
||||||
&tty_dev, &lpt_dev,
|
&ptr_dev,
|
||||||
|
&ptp_dev,
|
||||||
|
&tty_dev,
|
||||||
|
&lpt_dev,
|
||||||
&clk_dev,
|
&clk_dev,
|
||||||
|
&dp_dev,
|
||||||
|
&fhd_dev,
|
||||||
|
&mt_dev,
|
||||||
NULL };
|
NULL };
|
||||||
|
|
||||||
const char *sim_stop_messages[] = {
|
const char *sim_stop_messages[] = {
|
||||||
|
@ -66,7 +78,11 @@ const char *sim_stop_messages[] = {
|
||||||
"Unimplemented I/O device",
|
"Unimplemented I/O device",
|
||||||
"HALT instruction",
|
"HALT instruction",
|
||||||
"Breakpoint",
|
"Breakpoint",
|
||||||
"Indirect address loop" };
|
"Indirect address loop",
|
||||||
|
"DMA error",
|
||||||
|
"MT write protected",
|
||||||
|
"DP write overrun, track destroyed",
|
||||||
|
"DP track format invalid" };
|
||||||
|
|
||||||
/* Binary loader
|
/* Binary loader
|
||||||
|
|
||||||
|
|
|
@ -291,6 +291,7 @@ t_stat drc_svc (UNIT *uptr)
|
||||||
{
|
{
|
||||||
int32 devd, trk, sec;
|
int32 devd, trk, sec;
|
||||||
uint32 da;
|
uint32 da;
|
||||||
|
uint16 *bptr = uptr->filebuf;
|
||||||
|
|
||||||
if ((uptr->flags & UNIT_ATT) == 0) {
|
if ((uptr->flags & UNIT_ATT) == 0) {
|
||||||
drc_sta = DRS_ABO;
|
drc_sta = DRS_ABO;
|
||||||
|
@ -304,7 +305,7 @@ da = ((trk * DR_NUMSC) + sec) * DR_NUMWD;
|
||||||
|
|
||||||
if (drc_cw & CW_WR) { /* write? */
|
if (drc_cw & CW_WR) { /* write? */
|
||||||
if ((da < uptr->capac) && (sec < DR_NUMSC)) {
|
if ((da < uptr->capac) && (sec < DR_NUMSC)) {
|
||||||
*(((uint16 *) uptr->filebuf) + da + drd_ptr) = drd_obuf;
|
bptr[da + drd_ptr] = drd_obuf;
|
||||||
if (((uint32) (da + drd_ptr)) >= uptr->hwmark)
|
if (((uint32) (da + drd_ptr)) >= uptr->hwmark)
|
||||||
uptr->hwmark = da + drd_ptr + 1; }
|
uptr->hwmark = da + drd_ptr + 1; }
|
||||||
drd_ptr = dr_incda (trk, sec, drd_ptr); /* inc disk addr */
|
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 */
|
sim_activate (uptr, dr_time); } /* sched next word */
|
||||||
else if (drd_ptr) { /* done, need to fill? */
|
else if (drd_ptr) { /* done, need to fill? */
|
||||||
for ( ; drd_ptr < DR_NUMWD; drd_ptr++)
|
for ( ; drd_ptr < DR_NUMWD; drd_ptr++)
|
||||||
*(((uint16 *) uptr->filebuf) + da + drd_ptr) = 0; }
|
bptr[da + drd_ptr] = 0; }
|
||||||
} /* end write */
|
} /* end write */
|
||||||
else { /* read */
|
else { /* read */
|
||||||
if (CMD (devd)) { /* dch active? */
|
if (CMD (devd)) { /* dch active? */
|
||||||
if ((da >= uptr->capac) || (sec >= DR_NUMSC)) drd_ibuf = 0;
|
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);
|
drd_ptr = dr_incda (trk, sec, drd_ptr);
|
||||||
setFLG (devd); /* set dch flg */
|
setFLG (devd); /* set dch flg */
|
||||||
sim_activate (uptr, dr_time); } /* sched next word */
|
sim_activate (uptr, dr_time); } /* sched next word */
|
||||||
|
@ -367,6 +368,7 @@ if (sz == 0) return SCPE_IERR;
|
||||||
uptr->capac = sz;
|
uptr->capac = sz;
|
||||||
return attach_unit (uptr, cptr);
|
return attach_unit (uptr, cptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set size routine */
|
/* Set size routine */
|
||||||
|
|
||||||
t_stat dr_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
t_stat dr_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
ipli, iplo 12556B interprocessor link pair
|
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
|
09-May-03 RMS Added network device flag
|
||||||
31-Jan-03 RMS Links are full duplex (found by Mike Gemeny)
|
31-Jan-03 RMS Links are full duplex (found by Mike Gemeny)
|
||||||
*/
|
*/
|
||||||
|
@ -49,7 +50,7 @@
|
||||||
extern uint32 PC;
|
extern uint32 PC;
|
||||||
extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2];
|
extern uint32 dev_cmd[2], dev_ctl[2], dev_flg[2], dev_fbf[2];
|
||||||
extern FILE *sim_log;
|
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_stopioe = 0; /* stop on error */
|
||||||
int32 ipl_hold[2] = { 0 }; /* holding character */
|
int32 ipl_hold[2] = { 0 }; /* holding character */
|
||||||
|
|
||||||
|
@ -339,7 +340,7 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat ipl_detach (UNIT *uptr)
|
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);
|
if (uptr->flags & UNIT_ACTV) sim_close_sock (uptr->DSOCKET, 1);
|
||||||
else { if (uptr->flags & UNIT_ESTB) /* if established, */
|
else { if (uptr->flags & UNIT_ESTB) /* if established, */
|
||||||
sim_close_sock (uptr->DSOCKET, 0); /* close data socket */
|
sim_close_sock (uptr->DSOCKET, 0); /* close data socket */
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
mt 12559A 3030 nine track magnetic tape
|
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
|
25-Apr-03 RMS Revised for extended file support
|
||||||
28-Mar-03 RMS Added multiformat support
|
28-Mar-03 RMS Added multiformat support
|
||||||
28-Feb-03 RMS Revised for magtape library
|
28-Feb-03 RMS Revised for magtape library
|
||||||
|
@ -92,7 +93,7 @@ int32 mtc_fnc = 0; /* function */
|
||||||
int32 mtc_sta = 0; /* status register */
|
int32 mtc_sta = 0; /* status register */
|
||||||
int32 mtc_dtf = 0; /* data xfer flop */
|
int32 mtc_dtf = 0; /* data xfer flop */
|
||||||
int32 mtc_1st = 0; /* first svc 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_gtime = 1000; /* gap stop time */
|
||||||
int32 mtc_xtime = 15; /* data xfer time */
|
int32 mtc_xtime = 15; /* data xfer time */
|
||||||
int32 mtc_stopioe = 1; /* stop on error */
|
int32 mtc_stopioe = 1; /* stop on error */
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
mux,muxl,muxc 12920A terminal multiplexor
|
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
|
09-May-03 RMS Added network device flag
|
||||||
01-Nov-02 RMS Added 7B/8B support
|
01-Nov-02 RMS Added 7B/8B support
|
||||||
22-Aug-02 RMS Updated for changes to sim_tmxr
|
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? */
|
if (mux_xpar[ln] & OTL_DIAG) /* xmt diag? */
|
||||||
mux_diag (mux_xbuf[ln]); /* before munge */
|
mux_diag (mux_xbuf[ln]); /* before munge */
|
||||||
mux_xdon[ln] = 1; /* set done */
|
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_putc_ln (lp, c); /* output char */
|
||||||
tmxr_poll_tx (&mux_desc); } } /* poll xmt */
|
tmxr_poll_tx (&mux_desc); } } /* poll xmt */
|
||||||
else { /* buf full */
|
else { /* buf full */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* hp2100_stddev.c: HP2100 standard devices simulator
|
/* 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
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -28,6 +28,7 @@
|
||||||
tty 12531C buffered teleprinter interface
|
tty 12531C buffered teleprinter interface
|
||||||
clk 12539C time base generator
|
clk 12539C time base generator
|
||||||
|
|
||||||
|
29-Mar-03 RMS Added support for console backpressure
|
||||||
25-Apr-03 RMS Added extended file support
|
25-Apr-03 RMS Added extended file support
|
||||||
22-Dec-02 RMS Added break support
|
22-Dec-02 RMS Added break support
|
||||||
01-Nov-02 RMS Revised BOOT command for IBL ROMs
|
01-Nov-02 RMS Revised BOOT command for IBL ROMs
|
||||||
|
@ -538,15 +539,20 @@ return dat;
|
||||||
|
|
||||||
t_stat tto_out (int32 c)
|
t_stat tto_out (int32 c)
|
||||||
{
|
{
|
||||||
t_stat ret = SCPE_OK;
|
t_stat r;
|
||||||
|
|
||||||
if (tty_mode & TM_PRI) { /* printing? */
|
if (tty_mode & TM_PRI) { /* printing? */
|
||||||
if (tty_unit[TTO].flags & UNIT_UC) { /* UC only? */
|
if (tty_unit[TTO].flags & UNIT_UC) { /* UC only? */
|
||||||
c = c & 0177;
|
c = c & 0177;
|
||||||
if (islower (c)) c = toupper (c); }
|
if (islower (c)) c = toupper (c); }
|
||||||
else c = c & ((tty_unit[TTO].flags & UNIT_8B)? 0377: 0177);
|
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; }
|
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_mode & TM_PUN) { /* punching? */
|
||||||
if ((tty_unit[TTP].flags & UNIT_ATT) == 0) /* attached? */
|
if ((tty_unit[TTP].flags & UNIT_ATT) == 0) /* attached? */
|
||||||
return IORETURN (ttp_stopioe, SCPE_UNATT);
|
return IORETURN (ttp_stopioe, SCPE_UNATT);
|
||||||
|
@ -555,7 +561,7 @@ if (tty_mode & TM_PUN) { /* punching? */
|
||||||
clearerr (tty_unit[TTP].fileref);
|
clearerr (tty_unit[TTP].fileref);
|
||||||
return SCPE_IOERR; }
|
return SCPE_IOERR; }
|
||||||
tty_unit[TTP].pos = ftell (tty_unit[TTP].fileref); }
|
tty_unit[TTP].pos = ftell (tty_unit[TTP].fileref); }
|
||||||
return ret;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
t_stat tti_svc (UNIT *uptr)
|
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_buf = c; /* put char in buf */
|
||||||
tty_unit[TTI].pos = tty_unit[TTI].pos + 1;
|
tty_unit[TTI].pos = tty_unit[TTI].pos + 1;
|
||||||
setFLG (dev); /* set flag */
|
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;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
t_stat tto_svc (UNIT *uptr)
|
t_stat tto_svc (UNIT *uptr)
|
||||||
{
|
{
|
||||||
int32 c, dev;
|
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 */
|
dev = tty_dib.devno; /* get device no */
|
||||||
setFLG (dev); /* set done flag */
|
setFLG (dev); /* set done flag */
|
||||||
c = tty_buf;
|
return ttp_out (c); /* punch if enabled */
|
||||||
tty_buf = 0377; /* defang buf */
|
|
||||||
return tto_out (c); /* print and/or punch */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset routine */
|
/* Reset routine */
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
This CPU module incorporates code and comments from the 1620 simulator by
|
This CPU module incorporates code and comments from the 1620 simulator by
|
||||||
Geoff Kuenning, with his permission.
|
Geoff Kuenning, with his permission.
|
||||||
|
|
||||||
|
02-Nov-03 RMS Fixed bug in branch digit (found by Dave Babcock)
|
||||||
21-Aug-03 RMS Fixed bug in immediate index add (found by Michael Short)
|
21-Aug-03 RMS Fixed bug in immediate index add (found by Michael Short)
|
||||||
25-Apr-03 RMS Changed t_addr to uint32 throughout
|
25-Apr-03 RMS Changed t_addr to uint32 throughout
|
||||||
18-Oct-02 RMS Fixed bugs in invalid result testing (found by Hans Pufal)
|
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 */
|
else reason = STOP_INVRTN; /* MAR check */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Branch on digit (zero) - P,Q are valid */
|
/* Branch on digit (not zero) - P,Q are valid */
|
||||||
|
|
||||||
case OP_BD:
|
case OP_BD:
|
||||||
if ((M[QAR] & DIGIT) == 0) { /* digit == 0? */
|
if ((M[QAR] & DIGIT) != 0) { /* digit != 0? */
|
||||||
BRANCH (PAR); } /* branch */
|
BRANCH (PAR); } /* branch */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
lpt 1443 line printer
|
lpt 1443 line printer
|
||||||
|
|
||||||
|
29-Dec-03 RMS Fixed bug in scheduling
|
||||||
25-Apr-03 RMS Revised for extended file support
|
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; }
|
return SCPE_UNATT; }
|
||||||
|
|
||||||
ind[IN_PRBSY] = 1; /* print busy */
|
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 */
|
for (i = LPT_WIDTH; i <= LPT_BSIZE; i++) /* clear unprintable */
|
||||||
lpt_buf[i] = ' ';
|
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
|
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 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\
|
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"
|
/PDB:$(OUTDIR)/"ibm1130.pdb" /MACHINE:I386 /OUT:$(OUTDIR)/"ibm1130.exe"
|
||||||
DEF_FILE=
|
DEF_FILE=
|
||||||
LINK32_OBJS= \
|
LINK32_OBJS= \
|
||||||
|
@ -161,9 +161,10 @@ $(OUTDIR)/ibm1130.bsc : $(OUTDIR) $(BSC32_SBRS)
|
||||||
|
|
||||||
LINK32=link.exe
|
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 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\
|
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"
|
/PDB:$(OUTDIR)/"ibm1130.pdb" /DEBUG /MACHINE:I386 /OUT:$(OUTDIR)/"ibm1130.exe"
|
||||||
DEF_FILE=
|
DEF_FILE=
|
||||||
LINK32_OBJS= \
|
LINK32_OBJS= \
|
||||||
|
|
|
@ -45,9 +45,21 @@ END
|
||||||
// Bitmap
|
// 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
|
#ifndef APSTUDIO_INVOKED
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
16-Aug-02 BLK Fixed bug in multiply instruction; didn't work with negative values
|
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
|
18-Mar-03 BLK Fixed bug in divide instruction; didn't work with negative values
|
||||||
23-Jul-03 BLK Prevented tti polling in CGI mode
|
23-Jul-03 BLK Prevented tti polling in CGI mode
|
||||||
|
24-Nov-03 BLK Fixed carry bit error in subtract and subtract double, found by Bob Flanders
|
||||||
|
|
||||||
The register state for the IBM 1130 CPU is:
|
The register state for the IBM 1130 CPU is:
|
||||||
|
|
||||||
|
@ -556,6 +557,8 @@ t_stat sim_instr (void)
|
||||||
if (cpu_unit.flags & UNIT_ATT)
|
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);
|
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 */
|
ACC = 0; /* ACC is destroyed, and default XIO_SENSE_DEV result is 0 */
|
||||||
|
|
||||||
switch (iocc_func) {
|
switch (iocc_func) {
|
||||||
|
@ -895,7 +898,7 @@ t_stat sim_instr (void)
|
||||||
src2 = ReadW(eaddr);
|
src2 = ReadW(eaddr);
|
||||||
ACC = (ACC-src2) & 0xFFFF;
|
ACC = (ACC-src2) & 0xFFFF;
|
||||||
|
|
||||||
C = src2 < src;
|
C = src < src2;
|
||||||
if (! V)
|
if (! V)
|
||||||
V = SIGN_BIT((src ^ src2) & (src ^ ACC));
|
V = SIGN_BIT((src ^ src2) & (src ^ ACC));
|
||||||
break;
|
break;
|
||||||
|
@ -907,7 +910,7 @@ t_stat sim_instr (void)
|
||||||
ACC = (dst >> 16) & 0xFFFF;
|
ACC = (dst >> 16) & 0xFFFF;
|
||||||
EXT = dst & 0xFFFF;
|
EXT = dst & 0xFFFF;
|
||||||
|
|
||||||
C = (unsigned int32) src2 < (unsigned int32) src;
|
C = (unsigned int32) src < (unsigned int32) src2;
|
||||||
if (! V)
|
if (! V)
|
||||||
V = DWSIGN_BIT((src ^ src2) & (src ^ dst));
|
V = DWSIGN_BIT((src ^ src2) & (src ^ dst));
|
||||||
break;
|
break;
|
||||||
|
@ -1527,7 +1530,7 @@ static t_stat cpu_attach (UNIT *uptr, char *cptr)
|
||||||
fclose(fd);
|
fclose(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
return attach_unit(uptr, cptr);
|
return attach_unit(uptr, quotefix(cptr)); /* fix quotes in filenames & attach */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void trace_instruction (void)
|
static void trace_instruction (void)
|
||||||
|
@ -1795,6 +1798,7 @@ static void cgi_stop(t_stat reason)
|
||||||
ORIGIN orig;
|
ORIGIN orig;
|
||||||
char *msg;
|
char *msg;
|
||||||
} pretstop[] = {
|
} 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",
|
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",
|
0xF001, O_FORTRAN, "Local unit defined incorrectly, or no *IOCS for specified device",
|
||||||
0xF002, O_FORTRAN, "Requested record exceeds buffer size",
|
0xF002, O_FORTRAN, "Requested record exceeds buffer size",
|
||||||
|
|
|
@ -260,6 +260,8 @@ void xio_error (char *msg);
|
||||||
void bail (char *msg);
|
void bail (char *msg);
|
||||||
t_stat load_cr_boot (int drv, int switches);
|
t_stat load_cr_boot (int drv, int switches);
|
||||||
t_stat cr_boot (int unitno, DEVICE *dptr);
|
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 calc_ints (void); /* recalculate interrupt bitmask */
|
||||||
void trace_io (char *fmt, ...); /* debugging printout */
|
void trace_io (char *fmt, ...); /* debugging printout */
|
||||||
void scp_panic (char *msg); /* bail out of simulator */
|
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);
|
t_bool gdu_active (void);
|
||||||
void remark_cmd (char *remark);
|
void remark_cmd (char *remark);
|
||||||
void stuff_cmd (char *cmd);
|
void stuff_cmd (char *cmd);
|
||||||
|
t_bool stuff_and_wait (char *cmd, int timeout, int delay);
|
||||||
void update_gui (t_bool force);
|
void update_gui (t_bool force);
|
||||||
void sim_init (void);
|
void sim_init (void);
|
||||||
t_stat register_cmd (char *name, t_stat (*action)(int32 flag, char *ptr), int arg, char *help);
|
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 */
|
/* GUI interface routines */
|
||||||
t_bool keyboard_is_busy (void);
|
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
|
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);
|
SETBIT(dsk_dsw[drv], DSK_DSW_NOT_READY);
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,10 +57,10 @@
|
||||||
// -------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
#include "ibm1130_fmt.h"
|
#include "ibm1130_fmt.h"
|
||||||
|
|
||||||
#define MAXLINE 81 // maximum output line size
|
#define MAXLINE 81 // maximum output line size
|
||||||
|
|
|
@ -662,7 +662,7 @@ static HBITMAP hBmp = NULL;
|
||||||
static int curwid = 0;
|
static int curwid = 0;
|
||||||
static int curht = 0;
|
static int curht = 0;
|
||||||
static BOOL wcInited = FALSE;
|
static BOOL wcInited = FALSE;
|
||||||
static int GDUPumpID = 0;
|
static DWORD GDUPumpID = 0;
|
||||||
static HANDLE hGDUPump = INVALID_HANDLE_VALUE;
|
static HANDLE hGDUPump = INVALID_HANDLE_VALUE;
|
||||||
static HPEN hGreenPen = NULL;
|
static HPEN hGreenPen = NULL;
|
||||||
static HBRUSH hRedBrush = NULL;
|
static HBRUSH hRedBrush = NULL;
|
||||||
|
|
|
@ -11,6 +11,10 @@
|
||||||
* This is not a supported product, but I welcome bug reports and fixes.
|
* This is not a supported product, but I welcome bug reports and fixes.
|
||||||
* Mail to simh@ibm1130.org
|
* Mail to simh@ibm1130.org
|
||||||
*
|
*
|
||||||
|
* 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
|
* 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
|
# define UPDATE_INTERVAL 5000 // GUI: set to 100000/f where f = desired updates/second of 1130 time
|
||||||
#endif
|
#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
|
* Function declarations
|
||||||
* ------------------------------------------------------------------------ */
|
* ------------------------------------------------------------------------ */
|
||||||
|
@ -71,6 +83,10 @@ DEVICE console_dev = {
|
||||||
|
|
||||||
extern char *read_line (char *cptr, int size, FILE *stream);
|
extern char *read_line (char *cptr, int size, FILE *stream);
|
||||||
extern FILE *sim_log;
|
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
|
#ifndef GUI_SUPPORT
|
||||||
void update_gui (int force) {} /* stubs for non-GUI builds */
|
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;}
|
t_stat console_reset (DEVICE *dptr) {return SCPE_OK;}
|
||||||
void stuff_cmd (char *cmd) {}
|
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);}
|
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);}
|
void remark_cmd (char *remark) {printf("%s\n", remark); if (sim_log) fprintf(sim_log, "%s\n", remark);}
|
||||||
#else
|
#else
|
||||||
|
@ -134,15 +151,29 @@ void scp_panic (char *msg)
|
||||||
#define IDC_RESET 14
|
#define IDC_RESET 14
|
||||||
#define IDC_PROGRAM_LOAD 15
|
#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 LAMPTIME 500 // 500 msec delay on updating
|
||||||
#define FLASH_TIMER_ID 1
|
#define FLASH_TIMER_ID 1
|
||||||
#define UPDATE_TIMER_ID 2
|
#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 BOOL class_defined = FALSE;
|
||||||
static HWND hConsoleWnd = NULL;
|
static HWND hConsoleWnd = NULL;
|
||||||
static HBITMAP hBitmap = NULL;
|
static HBITMAP hBitmap = NULL;
|
||||||
static HFONT hFont = NULL;
|
static HFONT hFont = NULL;
|
||||||
static HFONT hBtnFont = NULL;
|
static HFONT hBtnFont = NULL;
|
||||||
|
static HFONT hTinyFont = NULL;
|
||||||
static HBRUSH hbLampOut = NULL;
|
static HBRUSH hbLampOut = NULL;
|
||||||
static HBRUSH hbWhite = NULL;
|
static HBRUSH hbWhite = NULL;
|
||||||
static HBRUSH hbBlack = NULL;
|
static HBRUSH hbBlack = NULL;
|
||||||
|
@ -164,41 +195,80 @@ static char szConsoleClassName[] = "1130CONSOLE";
|
||||||
static DWORD PumpID = 0;
|
static DWORD PumpID = 0;
|
||||||
static HANDLE hPump = INVALID_HANDLE_VALUE;
|
static HANDLE hPump = INVALID_HANDLE_VALUE;
|
||||||
static int bmwid, bmht;
|
static int bmwid, bmht;
|
||||||
|
static HANDLE hbm1442_full, hbm1442_empty, hbm1442_eof, hbm1442_middle;
|
||||||
|
static HANDLE hbm1132_full, hbm1132_empty;
|
||||||
|
|
||||||
static struct tag_btn {
|
static struct tag_btn {
|
||||||
int x, y;
|
int x, y, wx, wy;
|
||||||
char *txt;
|
char *txt;
|
||||||
BOOL pushable, state;
|
BOOL pushable, state;
|
||||||
COLORREF clr;
|
COLORREF clr;
|
||||||
HBRUSH hbrLit, hbrDark;
|
HBRUSH hbrLit, hbrDark;
|
||||||
HWND hBtn;
|
HWND hBtn;
|
||||||
|
BOOL subclassed;
|
||||||
|
|
||||||
} btn[] = {
|
} btn[] = {
|
||||||
0, 0, "KEYBOARD\nSELECT", FALSE, FALSE, RGB(255,255,180), NULL, NULL, NULL,
|
0, 0, BUTTON_WIDTH, BUTTON_HEIGHT, "KEYBOARD\nSELECT", FALSE, FALSE, RGB(255,255,180), NULL, NULL, NULL, TRUE,
|
||||||
0, 1, "DISK\nUNLOCK", FALSE, TRUE, RGB(255,255,180), NULL, NULL, NULL,
|
0, 1, BUTTON_WIDTH, BUTTON_HEIGHT, "DISK\nUNLOCK", FALSE, TRUE, RGB(255,255,180), NULL, NULL, NULL, TRUE,
|
||||||
0, 2, "RUN", FALSE, FALSE, RGB(0,255,0), NULL, NULL, NULL,
|
0, 2, BUTTON_WIDTH, BUTTON_HEIGHT, "RUN", FALSE, FALSE, RGB(0,255,0), NULL, NULL, NULL, TRUE,
|
||||||
0, 3, "PARITY\nCHECK", FALSE, FALSE, RGB(255,0,0), NULL, NULL, NULL,
|
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, 0, BUTTON_WIDTH, BUTTON_HEIGHT, "", FALSE, FALSE, RGB(255,255,180), NULL, NULL, NULL, TRUE,
|
||||||
1, 1, "FILE\nREADY", FALSE, FALSE, RGB(0,255,0), NULL, NULL, NULL,
|
1, 1, BUTTON_WIDTH, BUTTON_HEIGHT, "FILE\nREADY", FALSE, FALSE, RGB(0,255,0), NULL, NULL, NULL, TRUE,
|
||||||
1, 2, "FORMS\nCHECK", FALSE, FALSE, RGB(255,255,0), NULL, NULL, NULL,
|
1, 2, BUTTON_WIDTH, BUTTON_HEIGHT, "FORMS\nCHECK", FALSE, FALSE, RGB(255,255,0), NULL, NULL, NULL, TRUE,
|
||||||
1, 3, "POWER\nON", FALSE, TRUE, RGB(255,255,180), NULL, NULL, NULL,
|
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, 0, BUTTON_WIDTH, BUTTON_HEIGHT, "POWER", TRUE, FALSE, RGB(255,255,180), NULL, NULL, NULL, TRUE,
|
||||||
2, 1, "PROGRAM\nSTART", TRUE, FALSE, RGB(0,255,0), NULL, NULL, NULL,
|
2, 1, BUTTON_WIDTH, BUTTON_HEIGHT, "PROGRAM\nSTART", TRUE, FALSE, RGB(0,255,0), NULL, NULL, NULL, TRUE,
|
||||||
2, 2, "PROGRAM\nSTOP", TRUE, FALSE, RGB(255,0,0), NULL, NULL, NULL,
|
2, 2, BUTTON_WIDTH, BUTTON_HEIGHT, "PROGRAM\nSTOP", TRUE, FALSE, RGB(255,0,0), NULL, NULL, NULL, TRUE,
|
||||||
2, 3, "LOAD\nIAR", TRUE, FALSE, RGB(0,0,255), NULL, NULL, NULL,
|
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, 0, BUTTON_WIDTH, BUTTON_HEIGHT, "KEYBOARD", TRUE, FALSE, RGB(255,255,180), NULL, NULL, NULL, TRUE,
|
||||||
3, 1, "IMM\nSTOP", TRUE, FALSE, RGB(255,0,0), NULL, NULL, NULL,
|
3, 1, BUTTON_WIDTH, BUTTON_HEIGHT, "IMM\nSTOP", TRUE, FALSE, RGB(255,0,0), NULL, NULL, NULL, TRUE,
|
||||||
3, 2, "CHECK\nRESET", TRUE, FALSE, RGB(0,0,255), NULL, NULL, NULL,
|
3, 2, BUTTON_WIDTH, BUTTON_HEIGHT, "CHECK\nRESET", TRUE, FALSE, RGB(0,0,255), NULL, NULL, NULL, TRUE,
|
||||||
3, 3, "PROGRAM\nLOAD", TRUE, FALSE, RGB(0,0,255), NULL, NULL, NULL,
|
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 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 init_console_window (void);
|
||||||
static void destroy_console_window (void);
|
static void destroy_console_window (void);
|
||||||
LRESULT CALLBACK ConsoleWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
LRESULT CALLBACK ConsoleWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||||
static DWORD WINAPI Pump (LPVOID arg);
|
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;}
|
#define NIXOBJECT(hObj) if (hObj != NULL) {DeleteObject(hObj); hObj = NULL;}
|
||||||
|
|
||||||
|
@ -249,6 +319,7 @@ static void destroy_console_window (void)
|
||||||
NIXOBJECT(hbLampOut)
|
NIXOBJECT(hbLampOut)
|
||||||
NIXOBJECT(hFont)
|
NIXOBJECT(hFont)
|
||||||
NIXOBJECT(hBtnFont);
|
NIXOBJECT(hBtnFont);
|
||||||
|
NIXOBJECT(hTinyFont);
|
||||||
NIXOBJECT(hcHand)
|
NIXOBJECT(hcHand)
|
||||||
NIXOBJECT(hSwitchPen)
|
NIXOBJECT(hSwitchPen)
|
||||||
NIXOBJECT(hLtGreyPen)
|
NIXOBJECT(hLtGreyPen)
|
||||||
|
@ -322,6 +393,7 @@ void update_gui (BOOL force)
|
||||||
BOOL state;
|
BOOL state;
|
||||||
static int in_here = FALSE;
|
static int in_here = FALSE;
|
||||||
static int32 displayed = 0;
|
static int32 displayed = 0;
|
||||||
|
RECT xin;
|
||||||
|
|
||||||
if ((int32)(console_unit.flags & UNIT_DISPLAY) != displayed) { // setting has changed
|
if ((int32)(console_unit.flags & UNIT_DISPLAY) != displayed) { // setting has changed
|
||||||
displayed = console_unit.flags & UNIT_DISPLAY;
|
displayed = console_unit.flags & UNIT_DISPLAY;
|
||||||
|
@ -380,9 +452,9 @@ void update_gui (BOOL force)
|
||||||
if ((wait_state|wait_lamp) != shown_wait)
|
if ((wait_state|wait_lamp) != shown_wait)
|
||||||
{shown_wait= (wait_state|wait_lamp); RedrawRegion(hConsoleWnd, 380, 77, 414, 97);}
|
{shown_wait= (wait_state|wait_lamp); RedrawRegion(hConsoleWnd, 380, 77, 414, 97);}
|
||||||
if (CES != shown_ces)
|
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)
|
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;
|
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;
|
in_here = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,6 +595,9 @@ void PaintButton (LPDRAWITEMSTRUCT dis)
|
||||||
if (! BETWEEN(i, 0, NBUTTONS-1))
|
if (! BETWEEN(i, 0, NBUTTONS-1))
|
||||||
return;
|
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);
|
FillRect(dis->hDC, &dis->rcItem, ((btn[i].pushable || power) && IsWindowEnabled(btn[i].hBtn)) ? btn[i].hbrLit : btn[i].hbrDark);
|
||||||
|
|
||||||
if (! btn[i].pushable) {
|
if (! btn[i].pushable) {
|
||||||
|
@ -565,7 +689,7 @@ HWND CreateSubclassedButton (HWND hwParent, int i)
|
||||||
int r, g, b;
|
int r, g, b;
|
||||||
|
|
||||||
y = bmht - (4*BUTTON_HEIGHT) + BUTTON_HEIGHT * btn[i].y;
|
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,
|
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)
|
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");
|
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)
|
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");
|
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 == 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;
|
PumpID = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DragAcceptFiles(hConsoleWnd, TRUE); /* let it accept dragged files (scripts) */
|
||||||
}
|
}
|
||||||
|
|
||||||
GetObject(hBitmap, sizeof(bm), &bm); /* get bitmap size */
|
GetObject(hBitmap, sizeof(bm), &bm); /* get bitmap size */
|
||||||
|
@ -667,12 +795,52 @@ static DWORD WINAPI Pump (LPVOID arg)
|
||||||
bmht = bm.bmHeight;
|
bmht = bm.bmHeight;
|
||||||
|
|
||||||
for (i = 0; i < NBUTTONS; i++) {
|
for (i = 0; i < NBUTTONS; i++) {
|
||||||
CreateSubclassedButton(hConsoleWnd, i);
|
if (! btn[i].subclassed)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
CreateSubclassedButton(hConsoleWnd, i);
|
||||||
if (! btn[i].pushable)
|
if (! btn[i].pushable)
|
||||||
EnableWindow(btn[i].hBtn, btn[i].state);
|
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 */
|
GetWindowRect(hConsoleWnd, &r); /* get window size as created */
|
||||||
wx = r.right - r.left + 1;
|
wx = r.right - r.left + 1;
|
||||||
wy = r.bottom - r.top + 1;
|
wy = r.bottom - r.top + 1;
|
||||||
|
@ -712,6 +880,7 @@ static DWORD WINAPI Pump (LPVOID arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hConsoleWnd != NULL) {
|
if (hConsoleWnd != NULL) {
|
||||||
|
DragAcceptFiles(hConsoleWnd, FALSE); /* unregister as drag/drop target */
|
||||||
DestroyWindow(hConsoleWnd); /* but if a quit message got posted, clean up */
|
DestroyWindow(hConsoleWnd); /* but if a quit message got posted, clean up */
|
||||||
hConsoleWnd = NULL;
|
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
|
* DrawToggles - display the console sense switches
|
||||||
* ------------------------------------------------------------------------ */
|
* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
|
||||||
static void DrawToggles (HDC hDC, int bits)
|
static void DrawToggles (HDC hDC, int bits)
|
||||||
{
|
{
|
||||||
int b, x;
|
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 */
|
if (shown_ces & b) { /* up */
|
||||||
SelectObject(hDC, hbWhite);
|
SelectObject(hDC, hbWhite);
|
||||||
Rectangle(hDC, x, 232, x+9, 240);
|
Rectangle(hDC, x, 232, x+9, 240);
|
||||||
|
@ -789,10 +959,10 @@ void DrawRunmode (HDC hDC, int mode)
|
||||||
ca = cos(angle);
|
ca = cos(angle);
|
||||||
sa = sin(angle);
|
sa = sin(angle);
|
||||||
|
|
||||||
x0 = 301 + (int) (20.*ca + 0.5); /* inner radius */
|
x0 = RUNSWITCH_X + (int) (20.*ca + 0.5); /* inner radius */
|
||||||
y0 = 389 - (int) (20.*sa + 0.5);
|
y0 = RUNSWITCH_Y - (int) (20.*sa + 0.5);
|
||||||
x1 = 301 + (int) (25.*ca + 0.5); /* outer radius */
|
x1 = RUNSWITCH_X + (int) (25.*ca + 0.5); /* outer radius */
|
||||||
y1 = 389 - (int) (25.*sa + 0.5);
|
y1 = RUNSWITCH_Y - (int) (25.*sa + 0.5);
|
||||||
|
|
||||||
hOldPen = SelectObject(hDC, hSwitchPen);
|
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;
|
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 (BETWEEN(xh, x-3, x+8+3) && BETWEEN(yh, 230, 275)) {
|
||||||
if (actual) {
|
if (actual) {
|
||||||
CES ^= b; /* a hit. Invert the bit and redisplay */
|
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;
|
x += (b & 0x1111) ? 31 : 21;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BETWEEN(xh, 245, 355) && BETWEEN(yh, 345, 425)) { /* hit near rotary switch */
|
if (BETWEEN(xh, RUNSWITCH_X-50, RUNSWITCH_X+50) && BETWEEN(yh, RUNSWITCH_Y-50, RUNSWITCH_Y+50)) { /* hit near rotary switch */
|
||||||
ang = (int) (atan2(301.-xh, 389.-yh)*180./3.1415926); /* this does implicit 90 deg rotation by the way */
|
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-301)*(xh-301)+(yh-389)*(yh-389));
|
r = (int) sqrt((xh-RUNSWITCH_X)*(xh-RUNSWITCH_X)+(yh-RUNSWITCH_Y)*(yh-RUNSWITCH_Y));
|
||||||
if (r > 12) {
|
if (r > 12) {
|
||||||
for (i = MODE_LOAD; i <= MODE_INT_RUN; i++) {
|
for (i = MODE_LOAD; i <= MODE_INT_RUN; i++) {
|
||||||
if (BETWEEN(ang, i*45-12, i*45+12)) {
|
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.
|
* 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 digits[] = " 0 1 2 3 4 5 6 7 8 9101112131415";
|
||||||
static char cccs[] = "3216 8 4 2 1";
|
static char cccs[] = "3216 8 4 2 1";
|
||||||
static char cnds[] = " C V";
|
static char cnds[] = " C V";
|
||||||
static char waits[] = " W";
|
static char waits[] = " W";
|
||||||
HFONT hOldFont, hOldBrush;
|
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 */
|
hOldFont = SelectObject(hDC, hFont); /* use that tiny font */
|
||||||
hOldBrush = SelectObject(hDC, hbWhite);
|
hOldBrush = SelectObject(hDC, hbWhite);
|
||||||
|
@ -885,6 +1061,47 @@ static void DrawConsole (HDC hDC)
|
||||||
|
|
||||||
SelectObject(hDC, hOldFont);
|
SelectObject(hDC, hOldFont);
|
||||||
SelectObject(hDC, hOldBrush);
|
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 */
|
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;
|
int i;
|
||||||
|
|
||||||
switch (wParam) {
|
switch (idCtl) {
|
||||||
case IDC_POWER: /* toggle system power */
|
case IDC_POWER: /* toggle system power */
|
||||||
power = ! power;
|
power = ! power;
|
||||||
reset_all(0);
|
reset_all(0);
|
||||||
|
@ -1009,6 +1226,21 @@ void HandleCommand (HWND hWnd, WPARAM wParam, LPARAM lParam)
|
||||||
remark_cmd("IPL failed");
|
remark_cmd("IPL failed");
|
||||||
}
|
}
|
||||||
break;
|
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);
|
update_gui(FALSE);
|
||||||
|
@ -1050,12 +1282,17 @@ LRESULT CALLBACK ConsoleWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa
|
||||||
|
|
||||||
case WM_PAINT:
|
case WM_PAINT:
|
||||||
hDC = BeginPaint(hWnd, &ps);
|
hDC = BeginPaint(hWnd, &ps);
|
||||||
DrawConsole(hDC);
|
DrawConsole(hDC, &ps);
|
||||||
EndPaint(hWnd, &ps);
|
EndPaint(hWnd, &ps);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_COMMAND: /* button click */
|
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;
|
break;
|
||||||
|
|
||||||
case WM_DRAWITEM:
|
case WM_DRAWITEM:
|
||||||
|
@ -1085,6 +1322,10 @@ LRESULT CALLBACK ConsoleWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPa
|
||||||
update_gui(FALSE);
|
update_gui(FALSE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case WM_DROPFILES:
|
||||||
|
accept_dropped_file((HANDLE) wParam); // console window - dragged file is a script or card deck
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
return DefWindowProc(hWnd, uMsg, wParam, lParam);
|
||||||
}
|
}
|
||||||
|
@ -1160,6 +1401,81 @@ void disk_unlocked (int unlocked)
|
||||||
EnableWindow(btn[IDC_DISK_UNLOCK].hBtn, 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;
|
CRITICAL_SECTION critsect;
|
||||||
|
|
||||||
void begin_critical_section (void)
|
void begin_critical_section (void)
|
||||||
|
@ -1201,6 +1517,7 @@ static DWORD WINAPI CmdThread (LPVOID arg)
|
||||||
WaitForSingleObject(hCmdReadEvent, INFINITE); /* wait for request */
|
WaitForSingleObject(hCmdReadEvent, INFINITE); /* wait for request */
|
||||||
read_line(cmdbuffer, sizeof(cmdbuffer), stdin); /* read one line */
|
read_line(cmdbuffer, sizeof(cmdbuffer), stdin); /* read one line */
|
||||||
scp_stuffed = FALSE; /* say how we got it */
|
scp_stuffed = FALSE; /* say how we got it */
|
||||||
|
scp_reading = FALSE;
|
||||||
SetEvent(hCmdReadyEvent); /* notify main thread a line is ready */
|
SetEvent(hCmdReadyEvent); /* notify main thread a line is ready */
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1225,9 +1542,6 @@ char *read_cmdline (char *ptr, int size, FILE *stream)
|
||||||
|
|
||||||
SetEvent(hCmdReadEvent); /* let read thread get one line */
|
SetEvent(hCmdReadEvent); /* let read thread get one line */
|
||||||
WaitForSingleObject(hCmdReadyEvent, INFINITE); /* wait for read thread or GUI to respond */
|
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 */
|
strncpy(ptr, cmdbuffer, MIN(size, sizeof(cmdbuffer))); /* copy line to caller's buffer */
|
||||||
|
|
||||||
for (cptr = ptr; isspace(*cptr); cptr++) /* absorb spaces */
|
for (cptr = ptr; isspace(*cptr); cptr++) /* absorb spaces */
|
||||||
|
@ -1247,9 +1561,58 @@ void stuff_cmd (char *cmd)
|
||||||
{
|
{
|
||||||
strcpy(cmdbuffer, cmd); /* save the string */
|
strcpy(cmdbuffer, cmd); /* save the string */
|
||||||
scp_stuffed = TRUE; /* note where it came from */
|
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 */
|
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
|
/* 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
|
* into account the possiblity that the command might have been stuffed, in which
|
||||||
* case the sim> prompt needs to be reprinted.
|
* case the sim> prompt needs to be reprinted.
|
||||||
|
@ -1257,8 +1620,14 @@ void stuff_cmd (char *cmd)
|
||||||
|
|
||||||
void remark_cmd (char *remark)
|
void remark_cmd (char *remark)
|
||||||
{
|
{
|
||||||
|
if (scp_reading) {
|
||||||
|
putchar('\n');
|
||||||
|
if (sim_log) putc('\n', sim_log);
|
||||||
|
}
|
||||||
|
|
||||||
printf("%s\n", remark);
|
printf("%s\n", remark);
|
||||||
if (sim_log) fprintf(sim_log, "%s\n", remark);
|
if (sim_log) fprintf(sim_log, "%s\n", remark);
|
||||||
|
|
||||||
if (scp_reading) {
|
if (scp_reading) {
|
||||||
printf("sim> ");
|
printf("sim> ");
|
||||||
if (sim_log) fprintf(sim_log, "sim> ");
|
if (sim_log) fprintf(sim_log, "sim> ");
|
||||||
|
|
|
@ -4,6 +4,15 @@
|
||||||
|
|
||||||
Brian Knittel
|
Brian Knittel
|
||||||
Revision History
|
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
|
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
|
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_PARITYCHECK (UNIT_V_UF + 7) /* error flags for 1403 */
|
||||||
#define UNIT_V_RINGCHECK (UNIT_V_UF + 8)
|
#define UNIT_V_RINGCHECK (UNIT_V_UF + 8)
|
||||||
#define UNIT_V_SYNCCHECK (UNIT_V_UF + 9)
|
#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_FORMCHECK (1u << UNIT_V_FORMCHECK)
|
||||||
#define UNIT_DATACHECK (1u << UNIT_V_DATACHECK)
|
#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_PARITYCHECK (1u << UNIT_V_PARITYCHECK)
|
||||||
#define UNIT_RINGCHECK (1u << UNIT_V_RINGCHECK)
|
#define UNIT_RINGCHECK (1u << UNIT_V_RINGCHECK)
|
||||||
#define UNIT_SYNCCHECK (1u << UNIT_V_SYNCCHECK)
|
#define UNIT_SYNCCHECK (1u << UNIT_V_SYNCCHECK)
|
||||||
|
#define UNIT_PHYSICAL_PTR (1u << UNIT_V_PHYSICAL_PTR)
|
||||||
|
|
||||||
UNIT prt_unit[] = {
|
UNIT prt_unit[] = {
|
||||||
{ UDATA (&prt_svc, UNIT_ATTABLE, 0) },
|
{ 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_1403(uptr) (uptr->flags & UNIT_1403) /* model test */
|
||||||
#define IS_1132(uptr) ((uptr->flags & UNIT_1403) == 0) /* 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) */
|
/* Parameter in the unit descriptor (1132 printer) */
|
||||||
|
|
||||||
|
@ -118,8 +130,8 @@ REG prt_reg[] = {
|
||||||
{ HRDATA (PRTDSW, PRT_DSW, 16) }, /* device status word */
|
{ HRDATA (PRTDSW, PRT_DSW, 16) }, /* device status word */
|
||||||
{ DRDATA (STIME, prt_swait, 24), PV_LEFT }, /* line skip wait */
|
{ DRDATA (STIME, prt_swait, 24), PV_LEFT }, /* line skip wait */
|
||||||
{ DRDATA (CTIME, prt_cwait, 24), PV_LEFT }, /* character rotation wait */
|
{ DRDATA (CTIME, prt_cwait, 24), PV_LEFT }, /* character rotation wait */
|
||||||
{ DRDATA (CTIME, prt_fwait, 24), PV_LEFT }, /* 1403 fast wait */
|
{ DRDATA (FTIME, prt_fwait, 24), PV_LEFT }, /* 1403 fast wait */
|
||||||
{ DRDATA (CTIME, prt_twait, 24), PV_LEFT }, /* 1403 transfer wait */
|
{ DRDATA (TTIME, prt_twait, 24), PV_LEFT }, /* 1403 transfer wait */
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
MTAB prt_mod[] = {
|
MTAB prt_mod[] = {
|
||||||
|
@ -175,6 +187,8 @@ cccgi[] = {
|
||||||
|
|
||||||
#include "ibm1130_prtwheel.h"
|
#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
|
// 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)
|
static int cc_format_1132 (int bits)
|
||||||
|
@ -239,7 +253,7 @@ static void newpage (FILE *fd)
|
||||||
putc('\f', fd); // formfeed
|
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;
|
int r;
|
||||||
|
|
||||||
|
@ -262,6 +276,7 @@ static void flush_prt_line (FILE *fd, int spacemode)
|
||||||
else
|
else
|
||||||
prt_nnl++;
|
prt_nnl++;
|
||||||
|
|
||||||
|
prt_unit->pos++; // note something written
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,7 +311,11 @@ static void flush_prt_line (FILE *fd, int spacemode)
|
||||||
|
|
||||||
reset_prt_line();
|
reset_prt_line();
|
||||||
|
|
||||||
|
prt_unit->pos++; // note something written
|
||||||
prt_nnl++; // queue a newline
|
prt_nnl++; // queue a newline
|
||||||
|
|
||||||
|
if (phys_flush) // if physical printer, send buffered output to device
|
||||||
|
fflush(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1132 printer commands
|
// 1132 printer commands
|
||||||
|
@ -412,7 +431,7 @@ static t_stat prt1132_svc (UNIT *uptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uptr->flags & UNIT_SPACING) {
|
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);
|
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);
|
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) {
|
if (uptr->flags & UNIT_SKIPPING) {
|
||||||
do {
|
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);
|
CLRBIT(PRT_DSW, PRT1132_DSW_CHANNEL_MASK);
|
||||||
SETBIT(PRT_DSW, cc_format_1132(cctape[prt_row]));
|
SETBIT(PRT_DSW, cc_format_1132(cctape[prt_row]));
|
||||||
} while ((cctape[prt_row] & CC_1132_BITS) == 0); // slew directly to a cc tape punch
|
} 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) {
|
else if (uptr->flags & UNIT_SKIPPING) {
|
||||||
do { // find line with exact match of tape punches
|
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
|
} while (cctape[prt_row] != SKIPTARGET); // slew directly to requested cc tape punch
|
||||||
|
|
||||||
CLRBIT(uptr->flags, UNIT_SKIPPING); // done with this
|
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);
|
SETBIT(ILSW[4], ILSW_4_1403_PRINTER);
|
||||||
}
|
}
|
||||||
else if (uptr->flags & UNIT_SPACING) {
|
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(uptr->flags, UNIT_SPACING); // done with this
|
||||||
CLRBIT(PRT_DSW, PRT1403_DSW_CARRIAGE_BUSY);
|
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);
|
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? */
|
if (uptr -> flags & UNIT_DIS) return SCPE_UDIS; /* disabled? */
|
||||||
uptr->filename = calloc(CBUFSIZE, sizeof(char));
|
uptr->filename = calloc(CBUFSIZE, sizeof(char));
|
||||||
strcpy(uptr->filename, "(stdout)");
|
strcpy(uptr->filename, "(stdout)");
|
||||||
|
@ -695,11 +719,13 @@ static t_stat prt_attach (UNIT *uptr, char *cptr)
|
||||||
SETBIT(uptr->flags, UNIT_ATT);
|
SETBIT(uptr->flags, UNIT_ATT);
|
||||||
uptr->pos = 0;
|
uptr->pos = 0;
|
||||||
}
|
}
|
||||||
else if ((rval = attach_unit(uptr, cptr)) != SCPE_OK) {
|
else {
|
||||||
|
if ((rval = attach_unit(uptr, quotefix(cptr))) != SCPE_OK)
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
fseek(uptr->fileref, 0, SEEK_END); /* if we opened an existing file, append to it */
|
fseek(uptr->fileref, 0, SEEK_END); /* if we opened an existing file, append to it */
|
||||||
|
uptr->pos = ftell(uptr->fileref);
|
||||||
|
|
||||||
if (IS_1132(uptr)) {
|
if (IS_1132(uptr)) {
|
||||||
CLRBIT(ILSW[1], ILSW_1_1132_PRINTER);
|
CLRBIT(ILSW[1], ILSW_1_1132_PRINTER);
|
||||||
|
@ -743,7 +769,7 @@ static t_stat prt_detach (UNIT *uptr)
|
||||||
{
|
{
|
||||||
t_stat rval;
|
t_stat rval;
|
||||||
|
|
||||||
flush_prt_line(uptr->fileref, TRUE);
|
flush_prt_line(uptr->fileref, TRUE, TRUE);
|
||||||
|
|
||||||
if (uptr->fileref == stdout) {
|
if (uptr->fileref == stdout) {
|
||||||
CLRBIT(uptr->flags, UNIT_ATT);
|
CLRBIT(uptr->flags, UNIT_ATT);
|
||||||
|
|
|
@ -5,6 +5,10 @@
|
||||||
Brian Knittel
|
Brian Knittel
|
||||||
|
|
||||||
Revision History:
|
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
|
2003.06.15 - added output translation code to accomodate APL font
|
||||||
added input translation feature to assist emulation of 1130 console keyboard for APL
|
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
|
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,
|
"KEYBOARD", &tti_unit, tti_reg, tti_mod,
|
||||||
1, 10, 31, 1, 8, 8,
|
1, 10, 31, 1, 8, 8,
|
||||||
NULL, NULL, &tti_reset,
|
NULL, NULL, &tti_reset,
|
||||||
NULL, NULL, NULL };
|
NULL, basic_attach, NULL };
|
||||||
|
|
||||||
/* TTO data structures
|
/* TTO data structures
|
||||||
|
|
||||||
|
@ -206,7 +210,11 @@ DEVICE tti_dev = {
|
||||||
tto_reg TTO register list
|
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[] = {
|
REG tto_reg[] = {
|
||||||
{ ORDATA (BUF, tto_unit.buf, 16) },
|
{ ORDATA (BUF, tto_unit.buf, 16) },
|
||||||
|
@ -227,7 +235,7 @@ DEVICE tto_dev = {
|
||||||
"TTO", &tto_unit, tto_reg, tto_mod,
|
"TTO", &tto_unit, tto_reg, tto_mod,
|
||||||
1, 10, 31, 1, 8, 8,
|
1, 10, 31, 1, 8, 8,
|
||||||
NULL, NULL, &tto_reset,
|
NULL, NULL, &tto_reset,
|
||||||
NULL, NULL, NULL };
|
NULL, basic_attach, NULL };
|
||||||
|
|
||||||
/* Terminal input routines
|
/* 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 */
|
ch = (ReadW(iocc_addr) >> 8) & 0xFF; /* get character to write */
|
||||||
tto_unit.buf = emit_conout_character(ch); /* output character and save write status */
|
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);
|
SETBIT(tto_dsw, TT_DSW_PRINTER_BUSY);
|
||||||
sim_activate(&tto_unit, tto_unit.wait); /* schedule interrupt */
|
sim_activate(&tto_unit, tto_unit.wait); /* schedule interrupt */
|
||||||
break;
|
break;
|
||||||
|
@ -288,6 +298,8 @@ void xio_1131_console (int32 iocc_addr, int32 func, int32 modify)
|
||||||
sprintf(msg, "Invalid console XIO function %x", func);
|
sprintf(msg, "Invalid console XIO function %x", func);
|
||||||
xio_error(msg);
|
xio_error(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fprintf(stderr, "After XIO %04x %04x\n", tti_dsw, tto_dsw);
|
||||||
}
|
}
|
||||||
|
|
||||||
// emit_conout_character - write character with 1130 console code 'ch'
|
// 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, */
|
/* otherwise, so ^E can interrupt the simulator, */
|
||||||
sim_activate(&tti_unit, tti_unit.wait); /* always continue polling keyboard */
|
sim_activate(&tti_unit, tti_unit.wait); /* always continue polling keyboard */
|
||||||
|
|
||||||
|
assert(sim_clock_queue != NULL);
|
||||||
|
|
||||||
temp = sim_poll_kbd();
|
temp = sim_poll_kbd();
|
||||||
|
|
||||||
if (temp < SCPE_KFLAG)
|
if (temp < SCPE_KFLAG)
|
||||||
|
@ -411,6 +425,8 @@ static t_stat tti_svc (UNIT *uptr)
|
||||||
SETBIT(ILSW[4], ILSW_4_CONSOLE);
|
SETBIT(ILSW[4], ILSW_4_CONSOLE);
|
||||||
calc_ints();
|
calc_ints();
|
||||||
|
|
||||||
|
// fprintf(stderr, "TTI interrupt svc SET %04x %04x\n", tti_dsw, tto_dsw);
|
||||||
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -433,6 +449,35 @@ static t_stat tti_reset (DEVICE *dptr)
|
||||||
return SCPE_OK;
|
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 */
|
t_bool keyboard_is_busy (void) /* return TRUE if keyboard is not expecting a character */
|
||||||
{
|
{
|
||||||
return (tti_dsw & TT_DSW_KEYBOARD_BUSY);
|
return (tti_dsw & TT_DSW_KEYBOARD_BUSY);
|
||||||
|
@ -446,6 +491,8 @@ static t_stat tto_svc (UNIT *uptr)
|
||||||
SETBIT(ILSW[4], ILSW_4_CONSOLE);
|
SETBIT(ILSW[4], ILSW_4_CONSOLE);
|
||||||
calc_ints();
|
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 */
|
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--;
|
curcol--;
|
||||||
}
|
}
|
||||||
else if (n_os_mappings && ch != (unsigned char) IGNR_) {
|
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
|
if (curcol > maxcol) { // first time in this column, no overstrike possible yet
|
||||||
os_buf[curcol].nin = 0;
|
os_buf[curcol].nin = 0;
|
||||||
maxcol = curcol;
|
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++;
|
curcol++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -897,18 +947,15 @@ static t_stat font_cmd (int32 flag, char *cptr)
|
||||||
if (! *cptr) return SCPE_2FARG; /* argument missing */
|
if (! *cptr) return SCPE_2FARG; /* argument missing */
|
||||||
|
|
||||||
fname = cptr; /* save start */
|
fname = cptr; /* save start */
|
||||||
while (*cptr && (*cptr > ' ')) {
|
|
||||||
if (*cptr == '\'' || *cptr == '"') { /* quoted string */
|
if (*cptr == '\'' || *cptr == '"') { /* quoted string */
|
||||||
quote = *cptr; /* remember quote character */
|
quote = *cptr++; /* remember quote character */
|
||||||
strcpy(cptr, cptr+1); /* slide string down over the quote */
|
fname++; /* skip the quote */
|
||||||
|
|
||||||
while (*cptr && *cptr != quote) /* find closing quote */
|
while (*cptr && (*cptr != quote)) /* find closing quote */
|
||||||
cptr++;
|
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++;
|
||||||
}
|
}
|
||||||
*cptr = '\0'; /* terminate name */
|
*cptr = '\0'; /* terminate name */
|
||||||
|
|
|
@ -46,7 +46,6 @@ extern int32 saved_PC;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char sim_name[] = "IBM 1130";
|
char sim_name[] = "IBM 1130";
|
||||||
char sim_version[] = "V0.30";
|
|
||||||
|
|
||||||
REG *sim_PC = &cpu_reg[0];
|
REG *sim_PC = &cpu_reg[0];
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
// Microsoft Visual C++ generated include file.
|
// Microsoft Visual C++ generated include file.
|
||||||
// Used by ibm1130.rc
|
// Used by ibm1130.rc
|
||||||
//
|
//
|
||||||
|
|
||||||
#define IDB_CONSOLE 101
|
#define IDB_CONSOLE 101
|
||||||
#define IDC_HAND 102
|
#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):
|
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
|
2003-07-10 Fixed disk and console terminal bugs uncovered by
|
||||||
APL\1130. Added APL keyboard and output font support
|
APL\1130. Added APL keyboard and output font support
|
||||||
to enable use of APL\1130. APL will be released soon.
|
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
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
cpu 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)
|
07-Feb-03 RMS Fixed bug in SETM, SETMR (found by Mark Pizzolato)
|
||||||
|
|
||||||
The register state for the Interdata 16b CPU is:
|
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, /* FXR */
|
||||||
OP_NO | OP_816, /* FLR */
|
OP_NO | OP_816, /* FLR */
|
||||||
0, 0, 0, /* 30:32 */
|
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 */
|
0, 0, 0, 0, /* 34:37 */
|
||||||
OP_NO | OP_816 | OP_DPF, /* LDR */
|
OP_NO | OP_816 | OP_DPF, /* LDR */
|
||||||
OP_NO | OP_816 | OP_DPF, /* CDR */
|
OP_NO | OP_816 | OP_DPF, /* CDR */
|
||||||
|
@ -328,8 +331,8 @@ const uint16 decrom[256] = {
|
||||||
OP_NO | OP_716, /* SRLS */
|
OP_NO | OP_716, /* SRLS */
|
||||||
OP_NO | OP_716, /* SLLS */
|
OP_NO | OP_716, /* SLLS */
|
||||||
OP_NO, /* STBR */
|
OP_NO, /* STBR */
|
||||||
OP_NO, /* LDBR */
|
OP_RR, /* LDBR */
|
||||||
OP_NO | OP_716, /* EXBR */
|
OP_RR | OP_716, /* EXBR */
|
||||||
OP_NO | OP_716 | OP_PRV, /* EPSR */
|
OP_NO | OP_716 | OP_PRV, /* EPSR */
|
||||||
OP_RR | OP_PRV, /* WBR */
|
OP_RR | OP_PRV, /* WBR */
|
||||||
OP_RR | OP_PRV, /* RBR */
|
OP_RR | OP_PRV, /* RBR */
|
||||||
|
@ -364,8 +367,8 @@ const uint16 decrom[256] = {
|
||||||
OP_RX | OP_ID4, /* STM */
|
OP_RX | OP_ID4, /* STM */
|
||||||
OP_RX | OP_ID4, /* LM */
|
OP_RX | OP_ID4, /* LM */
|
||||||
OP_RX, /* STB */
|
OP_RX, /* STB */
|
||||||
OP_RX, /* LDB */
|
OP_RXB, /* LDB */
|
||||||
OP_RX | OP_716, /* CLB */
|
OP_RXB | OP_716, /* CLB */
|
||||||
OP_RX | OP_ID4 | OP_PRV, /* AL */
|
OP_RX | OP_ID4 | OP_PRV, /* AL */
|
||||||
OP_RXH | OP_PRV, /* WB */
|
OP_RXH | OP_PRV, /* WB */
|
||||||
OP_RXH | OP_PRV, /* RB */
|
OP_RXH | OP_PRV, /* RB */
|
||||||
|
@ -552,6 +555,7 @@ while (reason == 0) { /* loop until halted */
|
||||||
uint32 dev, drom, inc, lim, opnd;
|
uint32 dev, drom, inc, lim, opnd;
|
||||||
uint32 op, r1, r1p1, r2, ea, oPC;
|
uint32 op, r1, r1p1, r2, ea, oPC;
|
||||||
uint32 rslt, t, map;
|
uint32 rslt, t, map;
|
||||||
|
uint32 ir1, ir2, ityp;
|
||||||
int32 sr, st;
|
int32 sr, st;
|
||||||
|
|
||||||
if (sim_interval <= 0) { /* check clock queue */
|
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;
|
sim_interval = sim_interval - 1;
|
||||||
|
|
||||||
t = ReadH (oPC = PC); /* fetch instr */
|
ir1 = ReadH (oPC = PC); /* fetch instr */
|
||||||
op = (t >> 8) & 0xFF; /* isolate op, R1, R2 */
|
op = (ir1 >> 8) & 0xFF; /* isolate op, R1, R2 */
|
||||||
r1 = (t >> 4) & 0xF;
|
r1 = (ir1 >> 4) & 0xF;
|
||||||
r2 = t & 0xF;
|
r2 = ir1 & 0xF;
|
||||||
drom = decrom[op];
|
drom = decrom[op];
|
||||||
|
ityp = drom & OP_MASK;
|
||||||
|
|
||||||
if ((drom == 0) || (drom & dec_flgs)) { /* not in model? */
|
if ((drom == 0) || (drom & dec_flgs)) { /* not in model? */
|
||||||
if (stop_inst) reason = STOP_RSRV; /* stop or */
|
if (stop_inst) reason = STOP_RSRV; /* stop or */
|
||||||
else cc = swap_psw (ILOPSW, cc); /* swap PSW */
|
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? */
|
if ((drom & OP_PRV) && (PSW & PSW_PRO)) { /* priv & protected? */
|
||||||
cc = swap_psw (ILOPSW, cc); /* swap PSW */
|
cc = swap_psw (ILOPSW, cc); /* swap PSW */
|
||||||
continue; }
|
continue; }
|
||||||
switch (drom & OP_MASK) { /* decode instruction */
|
|
||||||
|
switch (ityp) { /* decode instruction */
|
||||||
case OP_NO: /* no operand */
|
case OP_NO: /* no operand */
|
||||||
opnd = r2; /* assume short */
|
opnd = r2; /* assume short */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_RR: /* reg-reg */
|
case OP_RR: /* reg-reg */
|
||||||
opnd = R[r2]; /* operand is R2 */
|
opnd = R[r2]; /* operand is R2 */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_RS: /* reg-storage */
|
case OP_RS: /* reg-storage */
|
||||||
case OP_RX: /* reg-mem */
|
case OP_RX: /* reg-mem */
|
||||||
PC = (PC + 2) & VAMASK; /* increment PC */
|
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 */
|
if (r2) ea = (ir2 + R[r2]) & VAMASK; /* index calculation */
|
||||||
opnd = ea; /* operand is ea */
|
opnd = ea; /* operand is ea */
|
||||||
break;
|
break;
|
||||||
case OP_RXH: /* reg-mem read */
|
|
||||||
|
case OP_RXB: /* reg-mem byte */
|
||||||
PC = (PC + 2) & VAMASK; /* increment PC */
|
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 */
|
if (r2) ea = (ea + R[r2]) & VAMASK; /* index calculation */
|
||||||
opnd = ReadH (ea); /* fetch operand */
|
opnd = ReadH (ea); /* fetch operand */
|
||||||
break; }
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return SCPE_IERR; }
|
||||||
|
|
||||||
PC = (PC + 2) & VAMASK; /* increment PC */
|
PC = (PC + 2) & VAMASK; /* increment PC */
|
||||||
switch (op) { /* case on opcode */
|
switch (op) { /* case on opcode */
|
||||||
|
|
||||||
|
@ -672,11 +693,9 @@ case 0xD0: /* STM - RX */
|
||||||
ea = (ea + 2) & VAMASK; } /* incr mem addr */
|
ea = (ea + 2) & VAMASK; } /* incr mem addr */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x93: /* LDBR - NO */
|
case 0x93: /* LDBR - RR */
|
||||||
R[r1] = R[r2] & DMASK8; /* load byte */
|
case 0xD3: /* LDB - RXB */
|
||||||
break;
|
R[r1] = opnd & DMASK8; /* load byte */
|
||||||
case 0xD3: /* LDB - RX */
|
|
||||||
R[r1] = ReadB (ea); /* load byte */
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x92: /* STBR - NO */
|
case 0x92: /* STBR - NO */
|
||||||
|
@ -686,8 +705,8 @@ case 0xD2: /* STB - RX */
|
||||||
WriteB (ea, R[r1] & DMASK8); /* store byte */
|
WriteB (ea, R[r1] & DMASK8); /* store byte */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x94: /* EXBR - NO */
|
case 0x94: /* EXBR - RR */
|
||||||
R[r1] = (R[r2] >> 8) | ((R[r2] & DMASK8) << 8);
|
R[r1] = (opnd >> 8) | ((opnd & DMASK8) << 8);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Control instructions */
|
/* Control instructions */
|
||||||
|
@ -792,8 +811,7 @@ case 0xC5: /* CLHI - RS */
|
||||||
if (((R[r1] ^ opnd) & (~opnd ^ rslt)) & SIGN16) cc = cc | CC_V;
|
if (((R[r1] ^ opnd) & (~opnd ^ rslt)) & SIGN16) cc = cc | CC_V;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xD4: /* CLB - RX */
|
case 0xD4: /* CLB - RXB */
|
||||||
opnd = ReadB (ea); /* get operand */
|
|
||||||
t = R[r1] & DMASK8;
|
t = R[r1] & DMASK8;
|
||||||
rslt = (t - opnd) & DMASK16; /* result */
|
rslt = (t - opnd) & DMASK16; /* result */
|
||||||
CC_GL_16 (rslt); /* set G,L */
|
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 */
|
if (PSW & PSW_SQI) cc = testsysq (cc); /* test for q */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x95: /* EPSR - RR */
|
case 0x95: /* EPSR - NO */
|
||||||
R[r1] = BUILD_PSW (cc); /* save PSW */
|
R[r1] = BUILD_PSW (cc); /* save PSW */
|
||||||
case 0x33: /* LPSR - NO */
|
case 0x33: /* LPSR - NO */
|
||||||
cc = newPSW (R[r2]); /* load new PSW */
|
cc = newPSW (R[r2]); /* load new PSW */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* id32_cpu.c: Interdata 32b CPU simulator
|
/* 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
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
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
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
cpu 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:
|
The register state for an Interdata 32b CPU is:
|
||||||
|
|
||||||
REG[0:F][2]<0:31> general register sets
|
REG[0:F][2]<0:31> general register sets
|
||||||
|
@ -156,6 +162,18 @@
|
||||||
#define UNIT_832 (1 << UNIT_V_832)
|
#define UNIT_832 (1 << UNIT_V_832)
|
||||||
#define UNIT_TYPE (UNIT_DPFP | UNIT_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)): \
|
#define SEXT32(x) (((x) & SIGN32)? ((int32) ((x) | ~0x7FFFFFFF)): \
|
||||||
((int32) ((x) & 0x7FFFFFFF)))
|
((int32) ((x) & 0x7FFFFFFF)))
|
||||||
#define SEXT16(x) (((x) & SIGN16)? ((int32) ((x) | ~0x7FFF)): \
|
#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 fp_in_hwre = 0; /* ucode vs hwre fp */
|
||||||
uint32 pawidth = PAWIDTH32; /* addr mask */
|
uint32 pawidth = PAWIDTH32; /* addr mask */
|
||||||
uint32 cpu_log = 0; /* debug logging */
|
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 */
|
jmp_buf save_env; /* abort handler */
|
||||||
struct BlockIO blk_io; /* block I/O status */
|
struct BlockIO blk_io; /* block I/O status */
|
||||||
uint32 (*dev_tab[DEVNO])(uint32 dev, uint32 op, uint32 datout) = { NULL };
|
uint32 (*dev_tab[DEVNO])(uint32 dev, uint32 op, uint32 datout) = { NULL };
|
||||||
|
@ -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_reset (DEVICE *dptr);
|
||||||
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat cpu_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
t_stat cpu_set_consint (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat cpu_set_consint (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat cpu_show_hist (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
void set_r_display (uint32 *rbase);
|
void set_r_display (uint32 *rbase);
|
||||||
|
|
||||||
extern t_bool devtab_init (void);
|
extern t_bool devtab_init (void);
|
||||||
|
@ -329,8 +352,8 @@ const uint16 decrom[256] = {
|
||||||
OP_RXF, /* S */
|
OP_RXF, /* S */
|
||||||
OP_RXF, /* M */
|
OP_RXF, /* M */
|
||||||
OP_RXF, /* D */
|
OP_RXF, /* D */
|
||||||
OP_RX, /* CRC12 */
|
OP_RXH, /* CRC12 */
|
||||||
OP_RX, /* CRC16 */
|
OP_RXH, /* CRC16 */
|
||||||
OP_RX, /* STE */
|
OP_RX, /* STE */
|
||||||
OP_RXH, /* AHM */
|
OP_RXH, /* AHM */
|
||||||
0, /* PB - 8/32C */
|
0, /* PB - 8/32C */
|
||||||
|
@ -349,7 +372,7 @@ const uint16 decrom[256] = {
|
||||||
OP_RX | OP_DPF, /* STD */
|
OP_RX | OP_DPF, /* STD */
|
||||||
OP_RX, /* SME */
|
OP_RX, /* SME */
|
||||||
OP_RX, /* LME */
|
OP_RX, /* LME */
|
||||||
OP_RX, /* LHL */
|
OP_RXH, /* LHL */
|
||||||
OP_RX, /* TBT */
|
OP_RX, /* TBT */
|
||||||
OP_RX, /* SBT */
|
OP_RX, /* SBT */
|
||||||
OP_RX, /* RBT */
|
OP_RX, /* RBT */
|
||||||
|
@ -367,8 +390,8 @@ const uint16 decrom[256] = {
|
||||||
OP_NO, /* SRHLS */
|
OP_NO, /* SRHLS */
|
||||||
OP_NO, /* SLHLS */
|
OP_NO, /* SLHLS */
|
||||||
OP_NO, /* STBR */
|
OP_NO, /* STBR */
|
||||||
OP_NO, /* LDBR */
|
OP_RR, /* LDBR */
|
||||||
OP_NO, /* EXBR */
|
OP_RR, /* EXBR */
|
||||||
OP_NO | OP_PRV, /* EPSR */
|
OP_NO | OP_PRV, /* EPSR */
|
||||||
OP_RR | OP_PRV, /* WBR */
|
OP_RR | OP_PRV, /* WBR */
|
||||||
OP_RR | OP_PRV, /* RBR */
|
OP_RR | OP_PRV, /* RBR */
|
||||||
|
@ -403,8 +426,8 @@ const uint16 decrom[256] = {
|
||||||
OP_RX, /* STM */
|
OP_RX, /* STM */
|
||||||
OP_RX, /* LM */
|
OP_RX, /* LM */
|
||||||
OP_RX, /* STB */
|
OP_RX, /* STB */
|
||||||
OP_RX, /* LDB */
|
OP_RXB, /* LDB */
|
||||||
OP_RX, /* CLB */
|
OP_RXB, /* CLB */
|
||||||
OP_RX | OP_PRV, /* AL */
|
OP_RX | OP_PRV, /* AL */
|
||||||
OP_RXF | OP_PRV, /* WB */
|
OP_RXF | OP_PRV, /* WB */
|
||||||
OP_RXF | OP_PRV, /* RB */
|
OP_RXF | OP_PRV, /* RB */
|
||||||
|
@ -419,7 +442,7 @@ const uint16 decrom[256] = {
|
||||||
OP_RXH, /* TS */
|
OP_RXH, /* TS */
|
||||||
OP_RX, /* SVC */
|
OP_RX, /* SVC */
|
||||||
OP_RI1 | OP_PRV, /* SINT */
|
OP_RI1 | OP_PRV, /* SINT */
|
||||||
OP_RX | OP_PRV, /* SCP */
|
OP_RXH | OP_PRV, /* SCP */
|
||||||
0, 0, /* E4:E5 */
|
0, 0, /* E4:E5 */
|
||||||
OP_RX, /* LA */
|
OP_RX, /* LA */
|
||||||
OP_RXF, /* TLATE */
|
OP_RXF, /* TLATE */
|
||||||
|
@ -534,6 +557,8 @@ MTAB cpu_mod[] = {
|
||||||
{ UNIT_TYPE, UNIT_DPFP | UNIT_832, "8/32", "832", NULL },
|
{ UNIT_TYPE, UNIT_DPFP | UNIT_832, "8/32", "832", NULL },
|
||||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "CONSINT",
|
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, NULL, "CONSINT",
|
||||||
&cpu_set_consint, NULL, NULL },
|
&cpu_set_consint, NULL, NULL },
|
||||||
|
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "HISTORY", "HISTORY",
|
||||||
|
&cpu_set_hist, &cpu_show_hist },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
|
||||||
DEVICE cpu_dev = {
|
DEVICE cpu_dev = {
|
||||||
|
@ -586,6 +611,7 @@ uint32 dev, drom, opnd, inc, lim, bufa;
|
||||||
uint32 op, r1, r1p1, r2, rx2, ea;
|
uint32 op, r1, r1p1, r2, rx2, ea;
|
||||||
uint32 mpy, mpc, dvr;
|
uint32 mpy, mpc, dvr;
|
||||||
uint32 i, rslt, rlo, t;
|
uint32 i, rslt, rlo, t;
|
||||||
|
uint32 ir1, ir2, ir3, ityp;
|
||||||
int32 sr, st;
|
int32 sr, st;
|
||||||
|
|
||||||
if (sim_interval <= 0) { /* check clock queue */
|
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;
|
sim_interval = sim_interval - 1;
|
||||||
|
|
||||||
t = ReadH (oPC = PC, VE); /* fetch instr */
|
ir1 = ReadH (oPC = PC, VE); /* fetch instr */
|
||||||
op = (t >> 8) & 0xFF; /* extract op,R1,R2 */
|
op = (ir1 >> 8) & 0xFF; /* extract op,R1,R2 */
|
||||||
r1 = (t >> 4) & 0xF;
|
r1 = (ir1 >> 4) & 0xF;
|
||||||
r2 = t & 0xF;
|
r2 = ir1 & 0xF;
|
||||||
drom = decrom[op]; /* get decode flags */
|
drom = decrom[op]; /* get decode flags */
|
||||||
|
ityp = drom & OP_MASK; /* instruction type */
|
||||||
|
|
||||||
if ((drom == 0) || (drom & dec_flgs)) { /* not in model? */
|
if ((drom == 0) || (drom & dec_flgs)) { /* not in model? */
|
||||||
if (stop_inst) reason = STOP_RSRV; /* stop or */
|
if (stop_inst) reason = STOP_RSRV; /* stop or */
|
||||||
else cc = exception (ILOPSW, cc, 0); /* exception */
|
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 */
|
cc = exception (ILOPSW, cc, 0); /* exception */
|
||||||
continue; }
|
continue; }
|
||||||
|
|
||||||
switch (drom & OP_MASK) { /* decode instruction */
|
switch (ityp) { /* decode instruction */
|
||||||
case OP_NO: /* no operand */
|
case OP_NO: /* no operand */
|
||||||
opnd = r2; /* assume short */
|
opnd = r2; /* assume short */
|
||||||
PC = (PC + 2) & VAMASK; /* increment PC */
|
PC = (PC + 2) & VAMASK; /* increment PC */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_RR: /* reg-reg */
|
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 */
|
PC = (PC + 2) & VAMASK; /* increment PC */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_RI1: /* reg-imm 1 */
|
case OP_RI1: /* reg-imm 1 */
|
||||||
t = ReadH ((PC + 2) & VAMASK, VE); /* fetch immed */
|
ir2 = ReadH ((PC + 2) & VAMASK, VE); /* fetch immed */
|
||||||
opnd = SEXT16 (t); /* sign extend */
|
opnd = SEXT16 (ir2); /* sign extend */
|
||||||
if (r2) opnd = (opnd + R[r2]) & DMASK32; /* index calculation */
|
if (r2) opnd = (opnd + R[r2]) & DMASK32; /* index calculation */
|
||||||
PC = (PC + 4) & VAMASK; /* increment PC */
|
PC = (PC + 4) & VAMASK; /* increment PC */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_RI2: /* reg-imm 2 */
|
case OP_RI2: /* reg-imm 2 */
|
||||||
t = ReadH ((PC + 2) & VAMASK, VE); /* fetch imm hi */
|
ir2 = ReadH ((PC + 2) & VAMASK, VE); /* fetch imm hi */
|
||||||
opnd = t << 16; /* shift to place */
|
ir3 = ReadH ((PC + 4) & VAMASK, VE); /* fetch imm lo */
|
||||||
t = ReadH ((PC + 4) & VAMASK, VE); /* fetch imm lo */
|
opnd = (ir2 << 16) | ir3; /* 32b immediate */
|
||||||
opnd = opnd | t; /* complete imm */
|
|
||||||
if (r2) opnd = (opnd + R[r2]) & DMASK32; /* index calculation */
|
if (r2) opnd = (opnd + R[r2]) & DMASK32; /* index calculation */
|
||||||
PC = (PC + 6) & VAMASK; /* increment PC */
|
PC = (PC + 6) & VAMASK; /* increment PC */
|
||||||
break;
|
break;
|
||||||
case OP_RX: case OP_RXH: case OP_RXF: /* reg-mem */
|
|
||||||
t = ReadH ((PC + 2) & VAMASK, VE); /* fetch addr */
|
case OP_RX: case OP_RXB: case OP_RXH: case OP_RXF: /* reg-mem */
|
||||||
if ((t & 0xC000) == 0) { /* displacement? */
|
ir2 = ReadH ((PC + 2) & VAMASK, VE); /* fetch addr */
|
||||||
|
if ((ir2 & 0xC000) == 0) { /* displacement? */
|
||||||
PC = (PC + 4) & VAMASK; /* increment PC */
|
PC = (PC + 4) & VAMASK; /* increment PC */
|
||||||
ea = t; } /* abs 14b displ */
|
ea = ir2; } /* abs 14b displ */
|
||||||
else if (t & 0x8000) { /* relative? */
|
else if (ir2 & 0x8000) { /* relative? */
|
||||||
PC = (PC + 4) & VAMASK; /* increment PC */
|
PC = (PC + 4) & VAMASK; /* increment PC */
|
||||||
ea = PC + SEXT15 (t); } /* add to incr PC */
|
ea = PC + SEXT15 (ir2); } /* add to incr PC */
|
||||||
else { /* absolute */
|
else { /* absolute */
|
||||||
rx2 = (t >> 8) & 0xF; /* get second index */
|
rx2 = (ir2 >> 8) & 0xF; /* get second index */
|
||||||
ea = (t & 0xFF) << 16; /* shift to place */
|
ea = (ir2 & 0xFF) << 16; /* shift to place */
|
||||||
t = ReadH ((PC + 4) & VAMASK, VE); /* fetch addr lo */
|
ir3 = ReadH ((PC + 4) & VAMASK, VE); /* fetch addr lo */
|
||||||
ea = ea | t; /* finish addr */
|
ea = ea | ir3; /* finish addr */
|
||||||
if (rx2) ea = ea + R[rx2]; /* index calc 2 */
|
if (rx2) ea = ea + R[rx2]; /* index calc 2 */
|
||||||
PC = (PC + 6) & VAMASK; } /* increment PC */
|
PC = (PC + 6) & VAMASK; } /* increment PC */
|
||||||
if (r2) ea = ea + R[r2]; /* index calculation */
|
if (r2) ea = ea + R[r2]; /* index calculation */
|
||||||
ea = ea & VAMASK;
|
ea = ea & VAMASK;
|
||||||
if ((drom & OP_MASK) == OP_RXF) /* get fw operand? */
|
if (ityp == OP_RXF) opnd = ReadF (ea, VR); /* get fw operand? */
|
||||||
opnd = ReadF (ea, VR); /* read fullword */
|
else if (ityp == OP_RXH) { /* get hw operand? */
|
||||||
else if ((drom & OP_MASK) == OP_RXH) { /* get hw operand? */
|
|
||||||
t = ReadH (ea, VR); /* read halfword */
|
t = ReadH (ea, VR); /* read halfword */
|
||||||
opnd = SEXT16 (t); } /* sign extend */
|
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;
|
break;
|
||||||
case OP_UNDEF:
|
|
||||||
|
default:
|
||||||
return SCPE_IERR; }
|
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? */
|
if (qevent & EV_MAC) continue; /* MAC abort on fetch? */
|
||||||
switch (op) { /* case on opcode */
|
switch (op) { /* case on opcode */
|
||||||
|
|
||||||
|
@ -721,8 +764,8 @@ case 0xF8: /* LI - RI2 */
|
||||||
CC_GL_32 (R[r1]); /* set G,L */
|
CC_GL_32 (R[r1]); /* set G,L */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x73: /* LHL - RX */
|
case 0x73: /* LHL - RXH */
|
||||||
R[r1] = ReadH (ea, VR); /* get op, zero ext */
|
R[r1] = opnd & DMASK16; /* get op, zero ext */
|
||||||
CC_GL_32 (R[r1]); /* set G, L */
|
CC_GL_32 (R[r1]); /* set G, L */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -764,11 +807,9 @@ case 0xE0: /* TS - RXH */
|
||||||
WriteH (ea, opnd | SIGN16, VW); /* set MSB */
|
WriteH (ea, opnd | SIGN16, VW); /* set MSB */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x93: /* LDBR - NO */
|
case 0x93: /* LDBR - RR */
|
||||||
R[r1] = R[r2] & DMASK8; /* load byte */
|
case 0xD3: /* LDB - RXB */
|
||||||
break;
|
R[r1] = opnd & DMASK8; /* load byte */
|
||||||
case 0xD3: /* LDB - RX */
|
|
||||||
R[r1] = ReadB (ea, VR); /* load byte */
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x92: /* STBR - NO */
|
case 0x92: /* STBR - NO */
|
||||||
|
@ -778,13 +819,13 @@ case 0xD2: /* STB - RX */
|
||||||
WriteB (ea, R[r1], VW); /* store byte */
|
WriteB (ea, R[r1], VW); /* store byte */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x34: /* EXHR - NO */
|
case 0x34: /* EXHR - RR */
|
||||||
R[r1] = ((R[r2] >> 16) & DMASK16) | ((R[r2] & DMASK16) << 16);
|
R[r1] = ((opnd >> 16) & DMASK16) | ((opnd & DMASK16) << 16);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x94: /* EXBR - NO */
|
case 0x94: /* EXBR - RR */
|
||||||
R[r1] = (R[r1] & ~DMASK16) |
|
R[r1] = (R[r1] & ~DMASK16) |
|
||||||
((R[r2] >> 8) & DMASK8) | ((R[r2] & DMASK8) << 8);
|
((opnd >> 8) & DMASK8) | ((opnd & DMASK8) << 8);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Control instructions */
|
/* Control instructions */
|
||||||
|
@ -793,14 +834,14 @@ case 0x01: /* BALR - RR */
|
||||||
case 0x41: /* BAL - RX */
|
case 0x41: /* BAL - RX */
|
||||||
PCQ_ENTRY; /* save old PC */
|
PCQ_ENTRY; /* save old PC */
|
||||||
R[r1] = PC; /* save cur PC */
|
R[r1] = PC; /* save cur PC */
|
||||||
PC = ea; /* branch */
|
PC = opnd; /* branch */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x02: /* BTCR - RR */
|
case 0x02: /* BTCR - RR */
|
||||||
case 0x42: /* BTC - RX */
|
case 0x42: /* BTC - RX */
|
||||||
if (cc & r1) { /* test CC's */
|
if (cc & r1) { /* test CC's */
|
||||||
PCQ_ENTRY; /* branch if true */
|
PCQ_ENTRY; /* branch if true */
|
||||||
PC = ea; }
|
PC = opnd; }
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x20: /* BTBS - NO */
|
case 0x20: /* BTBS - NO */
|
||||||
|
@ -819,7 +860,7 @@ case 0x03: /* BFCR - RR */
|
||||||
case 0x43: /* BFC - RX */
|
case 0x43: /* BFC - RX */
|
||||||
if ((cc & r1) == 0) { /* test CC's */
|
if ((cc & r1) == 0) { /* test CC's */
|
||||||
PCQ_ENTRY; /* branch if false */
|
PCQ_ENTRY; /* branch if false */
|
||||||
PC = ea; }
|
PC = opnd; }
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x22: /* BFBS - NO */
|
case 0x22: /* BFBS - NO */
|
||||||
|
@ -840,16 +881,16 @@ case 0xC0: /* BXH - RX */
|
||||||
R[r1] = (R[r1] + inc) & DMASK32; /* R1 = R1 + inc */
|
R[r1] = (R[r1] + inc) & DMASK32; /* R1 = R1 + inc */
|
||||||
if (R[r1] > lim) { /* if R1 > lim */
|
if (R[r1] > lim) { /* if R1 > lim */
|
||||||
PCQ_ENTRY; /* branch */
|
PCQ_ENTRY; /* branch */
|
||||||
PC = ea; }
|
PC = opnd; }
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xC1: /* BXLE - RS */
|
case 0xC1: /* BXLE - RX */
|
||||||
inc = R[(r1 + 1) & 0xF]; /* inc = R1 + 1 */
|
inc = R[(r1 + 1) & 0xF]; /* inc = R1 + 1 */
|
||||||
lim = R[(r1 + 2) & 0xF]; /* lim = R1 + 2 */
|
lim = R[(r1 + 2) & 0xF]; /* lim = R1 + 2 */
|
||||||
R[r1] = (R[r1] + inc) & DMASK32; /* R1 = R1 + inc */
|
R[r1] = (R[r1] + inc) & DMASK32; /* R1 = R1 + inc */
|
||||||
if (R[r1] <= lim) { /* if R1 <= lim */
|
if (R[r1] <= lim) { /* if R1 <= lim */
|
||||||
PCQ_ENTRY; /* branch */
|
PCQ_ENTRY; /* branch */
|
||||||
PC = ea; }
|
PC = opnd; }
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Logical instructions */
|
/* Logical instructions */
|
||||||
|
@ -898,8 +939,7 @@ case 0xF5: /* CI - RI2 */
|
||||||
if (((R[r1] ^ opnd) & (~opnd ^ rslt)) & SIGN32) cc = cc | CC_V;
|
if (((R[r1] ^ opnd) & (~opnd ^ rslt)) & SIGN32) cc = cc | CC_V;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xD4: /* CLB - RX */
|
case 0xD4: /* CLB - RXB */
|
||||||
opnd = ReadB (ea, VR); /* get operand */
|
|
||||||
t = R[r1] & DMASK8;
|
t = R[r1] & DMASK8;
|
||||||
rslt = (t - opnd) & DMASK16; /* result */
|
rslt = (t - opnd) & DMASK16; /* result */
|
||||||
CC_GL_16 (rslt); /* set G,L 16b */
|
CC_GL_16 (rslt); /* set G,L 16b */
|
||||||
|
@ -1278,8 +1318,8 @@ case 0xE2: /* SINT - RI1 */
|
||||||
int_eval ();
|
int_eval ();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xE3: /* SCP - RX */
|
case 0xE3: /* SCP - RXH */
|
||||||
opnd = ReadH (ea, VR); /* zero ext operand */
|
opnd = opnd & DMASK16; /* zero ext operand */
|
||||||
if (opnd & CCW32_B1) t = ea + CCB32_B1C; /* point to buf */
|
if (opnd & CCW32_B1) t = ea + CCB32_B1C; /* point to buf */
|
||||||
else t = ea + CCB32_B0C;
|
else t = ea + CCB32_B0C;
|
||||||
sr = ReadH (t & VAMASK, VR); /* get count */
|
sr = ReadH (t & VAMASK, VR); /* get count */
|
||||||
|
@ -1335,7 +1375,7 @@ case 0x67: /* RBL - RX */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x5E: /* CRC12 - RXH */
|
case 0x5E: /* CRC12 - RXH */
|
||||||
opnd = ReadH (ea, VR); /* zero ext opnd */
|
opnd = opnd & DMASK16; /* zero ext opnd */
|
||||||
t = (R[r1] & 0x3F) ^ opnd;
|
t = (R[r1] & 0x3F) ^ opnd;
|
||||||
for (i = 0; i < 6; i++) {
|
for (i = 0; i < 6; i++) {
|
||||||
if (t & 1) t = (t >> 1) ^ 0x0F01;
|
if (t & 1) t = (t >> 1) ^ 0x0F01;
|
||||||
|
@ -1344,7 +1384,7 @@ case 0x5E: /* CRC12 - RXH */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x5F: /* CRC16 - RXH */
|
case 0x5F: /* CRC16 - RXH */
|
||||||
opnd = ReadH (ea, VR); /* zero ext opnd */
|
opnd = opnd & DMASK16; /* zero ext opnd */
|
||||||
t = (R[r1] & 0xFF) ^ opnd;
|
t = (R[r1] & 0xFF) ^ opnd;
|
||||||
for (i = 0; i < 8; i++) {
|
for (i = 0; i < 8; i++) {
|
||||||
if (t & 1) t = (t >> 1) ^ 0xA001;
|
if (t & 1) t = (t >> 1) ^ 0xA001;
|
||||||
|
@ -1417,7 +1457,7 @@ case 0xDB: /* RD - RX */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x99: /* RHR - RR */
|
case 0x99: /* RHR - RR */
|
||||||
case 0xD9: /* RH - RS */
|
case 0xD9: /* RH - RX */
|
||||||
dev = R[r1] & DEV_MAX;
|
dev = R[r1] & DEV_MAX;
|
||||||
if (DEV_ACC (dev)) { /* dev exist? */
|
if (DEV_ACC (dev)) { /* dev exist? */
|
||||||
if (dev_tab[dev] (dev, IO_ADR, 0)) /* select, hw ok? */
|
if (dev_tab[dev] (dev, IO_ADR, 0)) /* select, hw ok? */
|
||||||
|
@ -1436,7 +1476,7 @@ case 0xD9: /* RH - RS */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x9D: /* SSR - RR */
|
case 0x9D: /* SSR - RR */
|
||||||
case 0xDD: /* SS - RS */
|
case 0xDD: /* SS - RX */
|
||||||
dev = R[r1] & DEV_MAX;
|
dev = R[r1] & DEV_MAX;
|
||||||
if (DEV_ACC (dev)) { /* dev exist? */
|
if (DEV_ACC (dev)) { /* dev exist? */
|
||||||
dev_tab[dev] (dev, IO_ADR, 0); /* select */
|
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);
|
if (PSW & PSW_EXI) SET_INT (v_DS);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set history */
|
||||||
|
|
||||||
|
t_stat cpu_set_hist (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
uint32 i, lnt;
|
||||||
|
t_stat r;
|
||||||
|
|
||||||
|
if (cptr == NULL) {
|
||||||
|
for (i = 0; i < hst_lnt; i++) hst[i].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,
|
The author gratefully acknowledges the help of Carl Friend and Al Kossow,
|
||||||
who provided key documents about the Interdata product line.
|
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
|
21-Jun-03 RMS Changed subroutine argument for ARM compiler conflict
|
||||||
25-Apr-03 RMS Revised for extended file support
|
25-Apr-03 RMS Revised for extended file support
|
||||||
28-Feb-03 RMS Changed magtape device default to 0x85
|
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_RS 0x0003 /* 16b: reg-storage */
|
||||||
#define OP_RI1 0x0003 /* 32b: reg-imm 16b */
|
#define OP_RI1 0x0003 /* 32b: reg-imm 16b */
|
||||||
#define OP_RX 0x0004 /* all: reg-mem */
|
#define OP_RX 0x0004 /* all: reg-mem */
|
||||||
#define OP_RXH 0x0005 /* all: reg-mem, rd HW */
|
#define OP_RXB 0x0005 /* all: reg-mem, rd BY */
|
||||||
#define OP_RXF 0x0006 /* 32b: reg-mem, rd FW */
|
#define OP_RXH 0x0006 /* all: reg-mem, rd HW */
|
||||||
#define OP_RI2 0x0007 /* 32b: reg-imm 32b */
|
#define OP_RXF 0x0007 /* 32b: reg-mem, rd FW */
|
||||||
|
#define OP_RI2 0x0008 /* 32b: reg-imm 32b */
|
||||||
#define OP_MASK 0x000F
|
#define OP_MASK 0x000F
|
||||||
|
|
||||||
#define OP_ID4 0x0010 /* 16b: ID4 */
|
#define OP_ID4 0x0010 /* 16b: ID4 */
|
||||||
|
|
|
@ -69,7 +69,7 @@ sim> boot pt0
|
||||||
|
|
||||||
Breakpoint: PC: 00C2 (EXBR R8,R6)
|
Breakpoint: PC: 00C2 (EXBR R8,R6)
|
||||||
|
|
||||||
sim> run 100
|
sim> run 2d0
|
||||||
|
|
||||||
MODEL 8/16E PROCESSOR TEST PART 2 06-212R00
|
MODEL 8/16E PROCESSOR TEST PART 2 06-212R00
|
||||||
CPU
|
CPU
|
||||||
|
|
|
@ -259,6 +259,16 @@ control registers for the interrupt system.
|
||||||
most recent PC change first
|
most recent PC change first
|
||||||
WRU 8 interrupt character
|
WRU 8 interrupt character
|
||||||
|
|
||||||
|
The CPU can maintain a history of the most recently executed instructions.
|
||||||
|
This is controlled by the SET CPU HISTORY and SHOW CPU HISTORY commands:
|
||||||
|
|
||||||
|
SET CPU HISTORY clear history buffer
|
||||||
|
SET CPU HISTORY=0 disable history
|
||||||
|
SET CPU HISTORY=n enable history, display length = n
|
||||||
|
SHOW CPU HISTORY print CPU history
|
||||||
|
|
||||||
|
The maximum length for the history is 65536 entries.
|
||||||
|
|
||||||
2.3 Selector Channel (SELCH)
|
2.3 Selector Channel (SELCH)
|
||||||
|
|
||||||
An Interdata system can have 1 to 4 selector channels (SELCH0, SELCH1,
|
An Interdata system can have 1 to 4 selector channels (SELCH0, SELCH1,
|
||||||
|
|
|
@ -276,6 +276,7 @@ return 0;
|
||||||
t_stat fd_svc (UNIT *uptr)
|
t_stat fd_svc (UNIT *uptr)
|
||||||
{
|
{
|
||||||
uint32 i, u, tk, sc, crc, fnc, da;
|
uint32 i, u, tk, sc, crc, fnc, da;
|
||||||
|
uint8 *fbuf = uptr->filebuf;
|
||||||
|
|
||||||
u = uptr - fd_dev.units; /* get unit number */
|
u = uptr - fd_dev.units; /* get unit number */
|
||||||
fnc = GET_FNC (uptr->FNC); /* get function */
|
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? */
|
if (fd_dte (uptr, FALSE)) return SCPE_OK; /* xfr error? */
|
||||||
da = GET_DA (uptr->LRN); /* get disk addr */
|
da = GET_DA (uptr->LRN); /* get disk addr */
|
||||||
for (i = 0; i < FD_NUMBY; i++) /* read sector */
|
for (i = 0; i < FD_NUMBY; i++) /* read sector */
|
||||||
fdxb[i] = *(((uint8 *) uptr->filebuf) + da + i);
|
fdxb[i] = fbuf[da + i];
|
||||||
if (*(((uint8 *) uptr->filebuf) + FD_SIZE + uptr->LRN - 1)) {
|
if (fbuf[FD_SIZE + uptr->LRN - 1]) { /* deleted? set err */
|
||||||
fd_sta = fd_sta | STA_DEL; /* deleted? set err */
|
fd_sta = fd_sta | STA_DEL;
|
||||||
fd_es[u][0] = fd_es[u][0] | ES0_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][2] = GET_SEC (uptr->LRN); /* set ext sec/trk */
|
||||||
fd_es[u][3] = GET_TRK (uptr->LRN);
|
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 */
|
for (i = fd_bptr; i < FD_NUMBY; i++) /* pad sector */
|
||||||
fdxb[i] = fd_db;
|
fdxb[i] = fd_db;
|
||||||
for (i = 0; i < FD_NUMBY; i++) /* write sector */
|
for (i = 0; i < FD_NUMBY; i++) /* write sector */
|
||||||
*(((uint8 *) uptr->filebuf) + da + i) = fdxb[i];
|
fbuf[da + i] = fdxb[i]; /* then dir */
|
||||||
*(((uint8 *) uptr->filebuf) + FD_SIZE + uptr->LRN - 1) =
|
fbuf[FD_SIZE + uptr->LRN - 1] = ((fnc == FNC_DEL)? 1: 0);
|
||||||
(fnc == FNC_DEL)? 1: 0; /* write dir */
|
|
||||||
uptr->hwmark = uptr->capac; /* rewrite all */
|
uptr->hwmark = uptr->capac; /* rewrite all */
|
||||||
fd_es[u][2] = GET_SEC (uptr->LRN); /* set ext sec/trk */
|
fd_es[u][2] = GET_SEC (uptr->LRN); /* set ext sec/trk */
|
||||||
fd_es[u][3] = GET_TRK (uptr->LRN);
|
fd_es[u][3] = GET_TRK (uptr->LRN);
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
tt console
|
tt console
|
||||||
|
|
||||||
|
29-Dec-03 RMS Added support for console backpressure
|
||||||
25-Apr-03 RMS Revised for extended file support
|
25-Apr-03 RMS Revised for extended file support
|
||||||
11-Jan-03 RMS Added TTP support
|
11-Jan-03 RMS Added TTP support
|
||||||
22-Dec-02 RMS Added break support
|
22-Dec-02 RMS Added break support
|
||||||
|
@ -192,16 +193,18 @@ t_stat tto_svc (UNIT *uptr)
|
||||||
int32 ch;
|
int32 ch;
|
||||||
t_stat r;
|
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? */
|
if (uptr->flags & UNIT_KSR) { /* KSR mode? */
|
||||||
ch = uptr->buf & 0x7F; /* mask to 7b */
|
ch = uptr->buf & 0x7F; /* mask to 7b */
|
||||||
if (islower (ch)) ch = toupper (ch); } /* cvt to UC */
|
if (islower (ch)) ch = toupper (ch); } /* cvt to UC */
|
||||||
else ch = uptr->buf & ((tt_unit[TTO].flags & UNIT_8B)? 0xFF: 0x7F);
|
else ch = uptr->buf & ((tt_unit[TTO].flags & UNIT_8B)? 0xFF: 0x7F);
|
||||||
if (!(uptr->flags & UNIT_8B) && /* KSR or 7b? */
|
if ((uptr->flags & UNIT_8B) || /* KSR or 7b? */
|
||||||
((ch == 0) || (ch == 0x7F))) return SCPE_OK; /* supr NULL, DEL */
|
((ch != 0) && (ch != 0x7F))) { /* supr NULL, DEL */
|
||||||
if ((r = sim_putchar (ch)) != SCPE_OK) return r; /* output */
|
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 */
|
uptr->pos = uptr->pos + 1; /* incr count */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* id_ttp.c: Interdata PASLA console interface
|
/* 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
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
ttp console (on PAS)
|
ttp console (on PAS)
|
||||||
|
|
||||||
|
29-Dec-03 RMS Added support for console backpressure
|
||||||
25-Apr-03 RMS Revised for extended file support
|
25-Apr-03 RMS Revised for extended file support
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -195,16 +196,18 @@ t_stat ttpo_svc (UNIT *uptr)
|
||||||
int32 c;
|
int32 c;
|
||||||
t_stat r;
|
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? */
|
if (uptr->flags & UNIT_8B) /* 8b? */
|
||||||
c = pas_par (ttp_cmd, uptr->buf); /* apply parity */
|
c = pas_par (ttp_cmd, uptr->buf); /* apply parity */
|
||||||
else { c = uptr->buf & 0x7F; /* mask char */
|
else { c = uptr->buf & 0x7F; /* mask char */
|
||||||
if ((uptr->flags & UNIT_UC) && islower (c))
|
if ((uptr->flags & UNIT_UC) && islower (c))
|
||||||
c = toupper (c); } /* cvt to UC */
|
c = toupper (c); } /* cvt to UC */
|
||||||
if (!(uptr->flags & UNIT_8B) && /* UC or 7b? */
|
if ((uptr->flags & UNIT_8B) || /* UC or 7b? */
|
||||||
((c == 0) || (c == 0x7F))) return SCPE_OK; /* supr NULL, DEL */
|
((c != 0) && (c != 0x7F))){ /* supr NULL, DEL */
|
||||||
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); } }
|
||||||
|
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 */
|
uptr->pos = uptr->pos + 1; /* incr count */
|
||||||
return SCPE_OK;
|
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
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
22-Nov-03 CEO Added support for PIT device
|
||||||
19-Jan-03 RMS Changed CMASK to CDMASK for Apple Dev kit conflict
|
19-Jan-03 RMS Changed CMASK to CDMASK for Apple Dev kit conflict
|
||||||
03-Oct-02 RMS Added device information structure
|
03-Oct-02 RMS Added device information structure
|
||||||
22-Dec-00 RMS Added Bruce Ray's second terminal support
|
22-Dec-00 RMS Added Bruce Ray's second terminal support
|
||||||
|
@ -174,6 +175,7 @@
|
||||||
#define DEV_ADCV 030 /* A/D converter */
|
#define DEV_ADCV 030 /* A/D converter */
|
||||||
#define DEV_DKP 033 /* disk pack */
|
#define DEV_DKP 033 /* disk pack */
|
||||||
#define DEV_CAS 034 /* cassette */
|
#define DEV_CAS 034 /* cassette */
|
||||||
|
#define DEV_PIT 043 /* programmable interval timer */
|
||||||
#define DEV_TTI1 050 /* second console input */
|
#define DEV_TTI1 050 /* second console input */
|
||||||
#define DEV_TTO1 051 /* second console output */
|
#define DEV_TTO1 051 /* second console output */
|
||||||
#define DEV_CPU 077 /* CPU control */
|
#define DEV_CPU 077 /* CPU control */
|
||||||
|
@ -211,6 +213,7 @@ typedef struct nova_dib DIB;
|
||||||
Priority (for INTA) runs from low numbers to high
|
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_DKP 3 /* moving head disk */
|
||||||
#define INT_V_DSK 4 /* fixed head disk */
|
#define INT_V_DSK 4 /* fixed head disk */
|
||||||
#define INT_V_MTA 5 /* magnetic tape */
|
#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_NO_ION_PENDING 16 /* ion delay */
|
||||||
#define INT_V_ION 17 /* interrupts on */
|
#define INT_V_ION 17 /* interrupts on */
|
||||||
|
|
||||||
|
#define INT_PIT (1 << INT_V_PIT)
|
||||||
#define INT_DKP (1 << INT_V_DKP)
|
#define INT_DKP (1 << INT_V_DKP)
|
||||||
#define INT_DSK (1 << INT_V_DSK)
|
#define INT_DSK (1 << INT_V_DSK)
|
||||||
#define INT_MTA (1 << INT_V_MTA)
|
#define INT_MTA (1 << INT_V_MTA)
|
||||||
|
@ -247,6 +251,7 @@ typedef struct nova_dib DIB;
|
||||||
|
|
||||||
/* PI disable bits */
|
/* PI disable bits */
|
||||||
|
|
||||||
|
#define PI_PIT 0001000
|
||||||
#define PI_DKP 0000400
|
#define PI_DKP 0000400
|
||||||
#define PI_DSK 0000100
|
#define PI_DSK 0000100
|
||||||
#define PI_MTA 0000040
|
#define PI_MTA 0000040
|
||||||
|
|
|
@ -25,6 +25,9 @@
|
||||||
|
|
||||||
dkp moving head disk
|
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
|
25-Apr-03 RMS Revised autosizing
|
||||||
08-Oct-02 RMS Added DIB
|
08-Oct-02 RMS Added DIB
|
||||||
06-Jan-02 RMS Revised enable/disable support
|
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;
|
extern int32 int_req, dev_busy, dev_done, dev_disable;
|
||||||
|
|
||||||
int32 dkp_ma = 0; /* memory address */
|
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_ussc = 0; /* unit/sf/sc/cnt */
|
||||||
int32 dkp_fccy = 0; /* flags/cylinder */
|
int32 dkp_fccy = 0; /* flags/cylinder */
|
||||||
int32 dkp_sta = 0; /* status register */
|
int32 dkp_sta = 0; /* status register */
|
||||||
int32 dkp_swait = 100; /* seek latency */
|
int32 dkp_swait = 100; /* seek latency */
|
||||||
int32 dkp_rwait = 100; /* rotate latency */
|
int32 dkp_rwait = 100; /* rotate latency */
|
||||||
|
int32 dkp_diagmode = 0; /* diagnostic mode */
|
||||||
|
|
||||||
DEVICE dkp_dev;
|
DEVICE dkp_dev;
|
||||||
int32 dkp (int32 pulse, int32 code, int32 AC);
|
int32 dkp (int32 pulse, int32 code, int32 AC);
|
||||||
|
@ -322,6 +327,8 @@ REG dkp_reg[] = {
|
||||||
{ FLDATA (BUSY, dev_busy, INT_V_DKP) },
|
{ FLDATA (BUSY, dev_busy, INT_V_DKP) },
|
||||||
{ FLDATA (DONE, dev_done, INT_V_DKP) },
|
{ FLDATA (DONE, dev_done, INT_V_DKP) },
|
||||||
{ FLDATA (DISABLE, dev_disable, 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 (STIME, dkp_swait, 24), PV_LEFT },
|
||||||
{ DRDATA (RTIME, dkp_rwait, 24), PV_LEFT },
|
{ DRDATA (RTIME, dkp_rwait, 24), PV_LEFT },
|
||||||
{ URDATA (CAPAC, dkp_unit[0].capac, 10, T_ADDR_W, 0,
|
{ URDATA (CAPAC, dkp_unit[0].capac, 10, T_ADDR_W, 0,
|
||||||
|
@ -452,22 +459,32 @@ case ioDIA: /* DIA */
|
||||||
rval = dkp_sta;
|
rval = dkp_sta;
|
||||||
break;
|
break;
|
||||||
case ioDOA: /* DOA */
|
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) {
|
if ((dev_busy & INT_DKP) == 0) {
|
||||||
dkp_fccy = AC; /* save cmd, cyl */
|
dkp_fccy = AC; /* save cmd, cyl */
|
||||||
dkp_sta = dkp_sta & ~(AC & FCCY_FLAGS); }
|
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;
|
break;
|
||||||
case ioDIB: /* DIB */
|
case ioDIB: /* DIB */
|
||||||
rval = dkp_ma; /* return buf addr */
|
rval = dkp_ma; /* return buf addr */
|
||||||
break;
|
break;
|
||||||
case ioDOB: /* DOB */
|
case ioDOB: /* DOB */
|
||||||
if ((dev_busy & INT_DKP) == 0) dkp_ma =
|
if ((dev_busy & INT_DKP) == 0) {
|
||||||
AC & (drv_tab[dtype].newf? DMASK: AMASK);
|
dkp_ma = AC & (drv_tab[dtype].newf? DMASK: AMASK);
|
||||||
|
if (AC & 0100000) dkp_map = 3; /* high bit is map */
|
||||||
|
else dkp_map = 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case ioDIC: /* DIC */
|
case ioDIC: /* DIC */
|
||||||
rval = dkp_ussc; /* return unit, sect */
|
rval = dkp_ussc; /* return unit, sect */
|
||||||
break;
|
break;
|
||||||
case ioDOC: /* DOC */
|
case ioDOC: /* DOC */
|
||||||
if ((dev_busy & INT_DKP) == 0) dkp_ussc = AC; /* save unit, sect */
|
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 */
|
break; } /* end switch code */
|
||||||
|
|
||||||
/* IOT, continued */
|
/* IOT, continued */
|
||||||
|
@ -478,7 +495,14 @@ case iopS: /* start */
|
||||||
dev_busy = dev_busy | INT_DKP; /* set busy */
|
dev_busy = dev_busy | INT_DKP; /* set busy */
|
||||||
dev_done = dev_done & ~INT_DKP; /* clear done */
|
dev_done = dev_done & ~INT_DKP; /* clear done */
|
||||||
int_req = int_req & ~INT_DKP; /* clear int */
|
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? */
|
if (dkp_go ()) break; /* new cmd, error? */
|
||||||
|
}
|
||||||
dev_busy = dev_busy & ~INT_DKP; /* clear busy */
|
dev_busy = dev_busy & ~INT_DKP; /* clear busy */
|
||||||
dev_done = dev_done | INT_DKP; /* set done */
|
dev_done = dev_done | INT_DKP; /* set done */
|
||||||
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
|
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
|
||||||
|
@ -558,6 +582,13 @@ static uint16 tbuf[DKP_NUMWD]; /* transfer buffer */
|
||||||
|
|
||||||
rval = SCPE_OK;
|
rval = SCPE_OK;
|
||||||
dtype = GET_DTYPE (uptr->flags); /* get drive type */
|
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->FUNC == FCCY_SEEK) { /* seek? */
|
||||||
if (uptr->CYL >= drv_tab[dtype].cyl) /* bad cylinder? */
|
if (uptr->CYL >= drv_tab[dtype].cyl) /* bad cylinder? */
|
||||||
dkp_sta = dkp_sta | STA_ERR | STA_CYL;
|
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;
|
for ( ; awc < DKP_NUMWD; awc++) tbuf[awc] = 0;
|
||||||
if (err = ferror (uptr->fileref)) break;
|
if (err = ferror (uptr->fileref)) break;
|
||||||
for (dx = 0; dx < DKP_NUMWD; dx++) { /* loop thru buffer */
|
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];
|
if (MEM_ADDR_OK (pa)) M[pa] = tbuf[dx];
|
||||||
dkp_ma = (dkp_ma + 1) & AMASK; } } }
|
dkp_ma = (dkp_ma + 1) & AMASK; } } }
|
||||||
|
|
||||||
if (uptr->FUNC == FCCY_WRITE) { /* write? */
|
if (uptr->FUNC == FCCY_WRITE) { /* write? */
|
||||||
for (sx = 0; sx < sc; sx++) { /* loop thru sectors */
|
for (sx = 0; sx < sc; sx++) { /* loop thru sectors */
|
||||||
for (dx = 0; dx < DKP_NUMWD; dx++) { /* loop into buffer */
|
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];
|
tbuf[dx] = M[pa];
|
||||||
dkp_ma = (dkp_ma + 1) & AMASK; }
|
dkp_ma = (dkp_ma + 1) & AMASK; }
|
||||||
fxwrite (tbuf, sizeof(int16), DKP_NUMWD, uptr->fileref);
|
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 */
|
dev_done = dev_done & ~INT_DKP; /* clear done, int */
|
||||||
int_req = int_req & ~INT_DKP;
|
int_req = int_req & ~INT_DKP;
|
||||||
dkp_fccy = dkp_ussc = dkp_ma = dkp_sta = 0; /* clear registers */
|
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 */
|
for (u = 0; u < DKP_NUMDR; u++) { /* loop thru units */
|
||||||
uptr = dkp_dev.units + u;
|
uptr = dkp_dev.units + u;
|
||||||
sim_cancel (uptr); /* cancel activity */
|
sim_cancel (uptr); /* cancel activity */
|
||||||
|
@ -685,33 +718,33 @@ return SCPE_OK;
|
||||||
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int))
|
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int))
|
||||||
|
|
||||||
static const int32 boot_rom[] = {
|
static const int32 boot_rom[] = {
|
||||||
060233, /* NIOC 0,DKP ; clear disk */
|
0060233, /* NIOC 0,DKP ; clear disk */
|
||||||
020420, /* LDA 0,USSC ; unit, sfc, sec, cnt */
|
0020420, /* LDA 0,USSC ; unit, sfc, sec, cnt */
|
||||||
063033, /* DOC 0,DKP ; select disk */
|
0063033, /* DOC 0,DKP ; select disk */
|
||||||
020417, /* LDA 0,SEKCMD ; command, cylinder */
|
0020417, /* LDA 0,SEKCMD ; command, cylinder */
|
||||||
061333, /* DOAP 0,DKP ; start seek */
|
0061333, /* DOAP 0,DKP ; start seek */
|
||||||
024415, /* LDA 1,SEKDN */
|
0024415, /* LDA 1,SEKDN */
|
||||||
060433, /* DIA 0,DKP ; get status */
|
0060433, /* DIA 0,DKP ; get status */
|
||||||
0123415, /* AND# 1,0,SZR ; skip if done */
|
0123415, /* AND# 1,0,SZR ; skip if done */
|
||||||
000776, /* JMP .-2 */
|
0000776, /* JMP .-2 */
|
||||||
0102400, /* SUB 0,0 ; mem addr = 0 */
|
0102400, /* SUB 0,0 ; mem addr = 0 */
|
||||||
062033, /* DOB 0,DKP */
|
0062033, /* DOB 0,DKP */
|
||||||
020411, /* LDA 0,REDCMD ; command, cylinder */
|
0020411, /* LDA 0,REDCMD ; command, cylinder */
|
||||||
061133, /* DOAS 0,DKP ; start read */
|
0061133, /* DOAS 0,DKP ; start read */
|
||||||
060433, /* DIA 0, DKP ; get status */
|
0060433, /* DIA 0, DKP ; get status */
|
||||||
0101113, /* MOVL# 0,0,SNC ; skip if done */
|
0101113, /* MOVL# 0,0,SNC ; skip if done */
|
||||||
000776, /* JMP .-2 */
|
0000776, /* JMP .-2 */
|
||||||
000377, /* JMP 377 */
|
0000377, /* JMP 377 */
|
||||||
000016, /* USSC: 0.B1+0.B7+0.B11+16 */
|
0000016, /* USSC: 0.B1+0.B7+0.B11+16 */
|
||||||
0175000, /* SEKCMD: 175000 */
|
0175000, /* SEKCMD: 175000 */
|
||||||
074000, /* SEKDN: 074000 */
|
0074000, /* SEKDN: 074000 */
|
||||||
0174000 /* REDCMD: 174000 */
|
0174000 /* REDCMD: 174000 */
|
||||||
};
|
};
|
||||||
|
|
||||||
t_stat dkp_boot (int32 unitno, DEVICE *dptr)
|
t_stat dkp_boot (int32 unitno, DEVICE *dptr)
|
||||||
{
|
{
|
||||||
int32 i, dtype;
|
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];
|
for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i];
|
||||||
unitno = unitno & USSC_M_UNIT;
|
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);
|
M[BOOT_UNIT] = M[BOOT_UNIT] | (unitno << USSC_V_UNIT);
|
||||||
if (drv_tab[dtype].newf) M[BOOT_SEEK] = 0176000;
|
if (drv_tab[dtype].newf) M[BOOT_SEEK] = 0176000;
|
||||||
saved_PC = BOOT_START;
|
saved_PC = BOOT_START;
|
||||||
|
SR = 0100000 + DEV_DKP;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -485,6 +485,8 @@ The moving head disk controller implements these registers:
|
||||||
DONE 1 device done flag
|
DONE 1 device done flag
|
||||||
DISABLE 1 interrupt disable flag
|
DISABLE 1 interrupt disable flag
|
||||||
INT 1 interrupt pending flag
|
INT 1 interrupt pending flag
|
||||||
|
DIAG 1 diagnostic mode flag
|
||||||
|
MAP 2 map select
|
||||||
STIME 24 seek time, per cylinder
|
STIME 24 seek time, per cylinder
|
||||||
RTIME 24 rotational delay
|
RTIME 24 rotational delay
|
||||||
|
|
||||||
|
|
|
@ -205,6 +205,7 @@ return rval;
|
||||||
t_stat dsk_svc (UNIT *uptr)
|
t_stat dsk_svc (UNIT *uptr)
|
||||||
{
|
{
|
||||||
int32 i, da, pa;
|
int32 i, da, pa;
|
||||||
|
int16 *fbuf = uptr->filebuf;
|
||||||
|
|
||||||
dev_busy = dev_busy & ~INT_DSK; /* clear busy */
|
dev_busy = dev_busy & ~INT_DSK; /* clear busy */
|
||||||
dev_done = dev_done | INT_DSK; /* set done */
|
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? */
|
if (uptr->FUNC == iopS) { /* read? */
|
||||||
for (i = 0; i < DSK_NUMWD; i++) { /* copy sector */
|
for (i = 0; i < DSK_NUMWD; i++) { /* copy sector */
|
||||||
pa = MapAddr (0, (dsk_ma + i) & AMASK); /* map address */
|
pa = MapAddr (0, (dsk_ma + i) & AMASK); /* map address */
|
||||||
if (MEM_ADDR_OK (pa)) M[pa] =
|
if (MEM_ADDR_OK (pa)) M[pa] = fbuf[da + i]; }
|
||||||
*(((int16 *) uptr->filebuf) + da + i); }
|
|
||||||
dsk_ma = (dsk_ma + DSK_NUMWD) & AMASK; }
|
dsk_ma = (dsk_ma + DSK_NUMWD) & AMASK; }
|
||||||
if (uptr->FUNC == iopP) { /* write? */
|
if (uptr->FUNC == iopP) { /* write? */
|
||||||
for (i = 0; i < DSK_NUMWD; i++) { /* copy sector */
|
for (i = 0; i < DSK_NUMWD; i++) { /* copy sector */
|
||||||
pa = MapAddr (0, (dsk_ma + i) & AMASK); /* map address */
|
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? */
|
if (((uint32) (da + i)) >= uptr->hwmark) /* past end? */
|
||||||
uptr->hwmark = da + i + 1; /* upd hwmark */
|
uptr->hwmark = da + i + 1; /* upd hwmark */
|
||||||
dsk_ma = (dsk_ma + DSK_NUMWD + 3) & AMASK; }
|
dsk_ma = (dsk_ma + DSK_NUMWD + 3) & AMASK; }
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
mta magnetic tape
|
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
|
25-Apr-03 RMS Revised for extended file support
|
||||||
28-Mar-03 RMS Added multiformat support
|
28-Mar-03 RMS Added multiformat support
|
||||||
28-Feb-03 RMS Revised for magtape library
|
28-Feb-03 RMS Revised for magtape library
|
||||||
|
@ -397,6 +399,7 @@ case CU_SPACEF: /* space forward */
|
||||||
}
|
}
|
||||||
while (mta_wc != 0);
|
while (mta_wc != 0);
|
||||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY);
|
mta_upddsta (uptr, uptr->USTAT | STA_RDY);
|
||||||
|
mta_ma = mta_wc; /* Word count = # records */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CU_SPACER: /* space reverse */
|
case CU_SPACER: /* space reverse */
|
||||||
|
@ -408,6 +411,7 @@ case CU_SPACER: /* space reverse */
|
||||||
}
|
}
|
||||||
while (mta_wc != 0);
|
while (mta_wc != 0);
|
||||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY);
|
mta_upddsta (uptr, uptr->USTAT | STA_RDY);
|
||||||
|
mta_ma = mta_wc; /* Word count = # records */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: /* reserved */
|
default: /* reserved */
|
||||||
|
@ -503,8 +507,15 @@ dev_done = dev_done & ~INT_MTA; /* clear done, int */
|
||||||
int_req = int_req & ~INT_MTA;
|
int_req = int_req & ~INT_MTA;
|
||||||
mta_cu = mta_wc = mta_ma = mta_sta = 0; /* clear registers */
|
mta_cu = mta_wc = mta_ma = mta_sta = 0; /* clear registers */
|
||||||
mta_ep = 0;
|
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 */
|
for (u = 0; u < MTA_NUMDR; u++) { /* loop thru units */
|
||||||
uptr = mta_dev.units + u;
|
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_tape_reset (uptr); /* clear pos flag */
|
||||||
sim_cancel (uptr); /* cancel activity */
|
sim_cancel (uptr); /* cancel activity */
|
||||||
if (uptr->flags & UNIT_ATT) uptr->USTAT = STA_RDY |
|
if (uptr->flags & UNIT_ATT) uptr->USTAT = STA_RDY |
|
||||||
|
@ -556,34 +567,35 @@ return SCPE_OK;
|
||||||
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int))
|
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int))
|
||||||
|
|
||||||
static const int32 boot_rom[] = {
|
static const int32 boot_rom[] = {
|
||||||
060222, /* NIOC 0,MTA ; clear disk */
|
0060222, /* NIOC 0,MTA ; clear disk */
|
||||||
020417, /* LDA 0,UNIT ; unit */
|
0020417, /* LDA 0,UNIT ; unit */
|
||||||
024417, /* LDA 1,REWIND ; cmd */
|
0024417, /* LDA 1,REWIND ; cmd */
|
||||||
0107000, /* ADD 0,1 ; cmd + unit */
|
0107000, /* ADD 0,1 ; cmd + unit */
|
||||||
065122, /* DOAS 1,MTA ; start rewind */
|
0065122, /* DOAS 1,MTA ; start rewind */
|
||||||
070422, /* DIA 2,MTA ; get status */
|
0070422, /* DIA 2,MTA ; get status */
|
||||||
0151213, /* MOVR# 2,2,SNC ; skip if done */
|
0151213, /* MOVR# 2,2,SNC ; skip if done */
|
||||||
000776, /* JMP .-2 */
|
0000776, /* JMP .-2 */
|
||||||
0126400, /* SUB 1,1 ; ma, wc = 0 */
|
0126400, /* SUB 1,1 ; ma, wc = 0 */
|
||||||
066022, /* DOB 1,MTA */
|
0066022, /* DOB 1,MTA */
|
||||||
067022, /* DOC 1,MTA */
|
0067022, /* DOC 1,MTA */
|
||||||
061122, /* DOAS 0,MTA ; start read */
|
0061122, /* DOAS 0,MTA ; start read */
|
||||||
070422, /* DIA 2,MTA ; get status */
|
0070422, /* DIA 2,MTA ; get status */
|
||||||
0151213, /* MOVR# 2,2,SNC ; skip if done */
|
0151213, /* MOVR# 2,2,SNC ; skip if done */
|
||||||
000776, /* JMP .-2 */
|
0000776, /* JMP .-2 */
|
||||||
000377, /* JMP 377 */
|
0000377, /* JMP 377 */
|
||||||
000000, /* UNIT: */
|
0000000, /* UNIT: */
|
||||||
000010 /* REWIND: 10 */
|
0000010 /* REWIND: 10 */
|
||||||
};
|
};
|
||||||
|
|
||||||
t_stat mta_boot (int32 unitno, DEVICE *dptr)
|
t_stat mta_boot (int32 unitno, DEVICE *dptr)
|
||||||
{
|
{
|
||||||
int32 i;
|
int32 i;
|
||||||
extern int32 saved_PC;
|
extern int32 saved_PC, SR;
|
||||||
|
|
||||||
sim_tape_rewind (&mta_unit[unitno]);
|
sim_tape_rewind (&mta_unit[unitno]);
|
||||||
for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i];
|
for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i];
|
||||||
M[BOOT_UNIT] = (unitno & CU_M_UNIT) << CU_V_UNIT;
|
M[BOOT_UNIT] = (unitno & CU_M_UNIT) << CU_V_UNIT;
|
||||||
saved_PC = BOOT_START;
|
saved_PC = BOOT_START;
|
||||||
|
SR = 0100000 + DEV_MTA;
|
||||||
return SCPE_OK;
|
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
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
24-Nov-03 CEO Added symbolic support for LEF instruction
|
||||||
17-Sep-01 RMS Removed multiconsole support
|
17-Sep-01 RMS Removed multiconsole support
|
||||||
31-May-01 RMS Added multiconsole support
|
31-May-01 RMS Added multiconsole support
|
||||||
14-Mar-01 RMS Revised load/dump interface (again)
|
14-Mar-01 RMS Revised load/dump interface (again)
|
||||||
|
@ -43,16 +44,23 @@ extern DEVICE cpu_dev;
|
||||||
extern UNIT cpu_unit;
|
extern UNIT cpu_unit;
|
||||||
#if defined (ECLIPSE)
|
#if defined (ECLIPSE)
|
||||||
extern DEVICE map_dev;
|
extern DEVICE map_dev;
|
||||||
|
extern DEVICE fpu_dev;
|
||||||
|
extern DEVICE pit_dev;
|
||||||
|
extern int32 Usermap;
|
||||||
|
extern int32 MapStat;
|
||||||
#endif
|
#endif
|
||||||
extern DEVICE ptr_dev, ptp_dev;
|
extern DEVICE ptr_dev;
|
||||||
|
extern DEVICE ptp_dev;
|
||||||
extern DEVICE plt_dev;
|
extern DEVICE plt_dev;
|
||||||
extern DEVICE tti_dev, tto_dev;
|
extern DEVICE tti_dev;
|
||||||
extern DEVICE tti1_dev, tto1_dev;
|
extern DEVICE tto_dev;
|
||||||
extern DEVICE clk_dev, lpt_dev;
|
extern DEVICE tti1_dev;
|
||||||
extern DEVICE dkp_dev, dsk_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 DEVICE mta_dev;
|
||||||
extern UNIT tti_unit, tto_unit;
|
|
||||||
extern UNIT tti1_unit, tto1_unit;
|
|
||||||
extern REG cpu_reg[];
|
extern REG cpu_reg[];
|
||||||
extern uint16 M[];
|
extern uint16 M[];
|
||||||
extern int32 saved_PC;
|
extern int32 saved_PC;
|
||||||
|
@ -81,13 +89,21 @@ DEVICE *sim_devices[] = {
|
||||||
&cpu_dev,
|
&cpu_dev,
|
||||||
#if defined (ECLIPSE)
|
#if defined (ECLIPSE)
|
||||||
&map_dev,
|
&map_dev,
|
||||||
|
&fpu_dev,
|
||||||
|
&pit_dev,
|
||||||
#endif
|
#endif
|
||||||
&ptr_dev, &ptp_dev,
|
&ptr_dev,
|
||||||
&tti_dev, &tto_dev,
|
&ptp_dev,
|
||||||
&tti1_dev, &tto1_dev,
|
&tti_dev,
|
||||||
&clk_dev, &plt_dev,
|
&tto_dev,
|
||||||
&lpt_dev, &dsk_dev,
|
&tti1_dev,
|
||||||
&dkp_dev, &mta_dev,
|
&tto1_dev,
|
||||||
|
&clk_dev,
|
||||||
|
&plt_dev,
|
||||||
|
&lpt_dev,
|
||||||
|
&dsk_dev,
|
||||||
|
&dkp_dev,
|
||||||
|
&mta_dev,
|
||||||
NULL };
|
NULL };
|
||||||
|
|
||||||
const char *sim_stop_messages[] = {
|
const char *sim_stop_messages[] = {
|
||||||
|
@ -256,7 +272,7 @@ static const char *opcode[] = {
|
||||||
"BTO", "BTZ", "SBZ", "SZBO",
|
"BTO", "BTZ", "SBZ", "SZBO",
|
||||||
"LOB", "LRB", "COB", "LDB",
|
"LOB", "LRB", "COB", "LDB",
|
||||||
"STB", "PSH", "POP",
|
"STB", "PSH", "POP",
|
||||||
"LMP", "SYSC",
|
"LMP", "SYC",
|
||||||
"PSHR", "POPB", "BAM", "POPJ",
|
"PSHR", "POPB", "BAM", "POPJ",
|
||||||
"RTN", "BLM", "DIVX",
|
"RTN", "BLM", "DIVX",
|
||||||
"MUL", "MULS", "DIV", "DIVS",
|
"MUL", "MULS", "DIV", "DIVS",
|
||||||
|
@ -366,6 +382,9 @@ static const char *opcode[] = {
|
||||||
"DIC", "DICS", "DICC", "DICP",
|
"DIC", "DICS", "DICC", "DICP",
|
||||||
"DOC", "DOCS", "DOCC", "DOCP",
|
"DOC", "DOCS", "DOCC", "DOCP",
|
||||||
"SKPBN", "SKPBZ", "SKPDN", "SKPDZ",
|
"SKPBN", "SKPBZ", "SKPDN", "SKPDZ",
|
||||||
|
#if defined (ECLIPSE)
|
||||||
|
"LEF", "LEF", "LEF", "LEF",
|
||||||
|
#endif
|
||||||
NULL };
|
NULL };
|
||||||
|
|
||||||
static const opc_val[] = {
|
static const opc_val[] = {
|
||||||
|
@ -379,7 +398,7 @@ static const opc_val[] = {
|
||||||
0102010+I_2AC, 0102110+I_2AC, 0102210+I_2AC, 0102310+I_2AC,
|
0102010+I_2AC, 0102110+I_2AC, 0102210+I_2AC, 0102310+I_2AC,
|
||||||
0102410+I_2AC, 0102510+I_2AC, 0102610+I_2AC, 0102710+I_2AC,
|
0102410+I_2AC, 0102510+I_2AC, 0102610+I_2AC, 0102710+I_2AC,
|
||||||
0103010+I_2AC, 0103110+I_2AC, 0103210+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,
|
0103710+I_NPN, 0107710+I_NPN, 0113710+I_NPN, 0117710+I_NPN,
|
||||||
0127710+I_NPN, 0133710+I_NPN, 0137710+I_NPN,
|
0127710+I_NPN, 0133710+I_NPN, 0137710+I_NPN,
|
||||||
0143710+I_NPN, 0147710+I_NPN, 0153710+I_NPN, 0157710+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,
|
0062400+I_RD, 0062500+I_RD, 0062600+I_RD, 0062700+I_RD,
|
||||||
0063000+I_RD, 0063100+I_RD, 0063200+I_RD, 0063300+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,
|
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 };
|
-1 };
|
||||||
|
|
||||||
static const char *skip[] = {
|
static const char *skip[] = {
|
||||||
|
@ -579,8 +601,8 @@ int32 ind, mode, disp, dev;
|
||||||
int32 byac, extind, extdisp, xop;
|
int32 byac, extind, extdisp, xop;
|
||||||
|
|
||||||
cflag = (uptr == NULL) || (uptr == &cpu_unit);
|
cflag = (uptr == NULL) || (uptr == &cpu_unit);
|
||||||
c1 = (val[0] >> 8) & 0177;
|
c1 = ((int32) val[0] >> 8) & 0177;
|
||||||
c2 = val[0] & 0177;
|
c2 = (int32) val[0] & 0177;
|
||||||
if (sw & SWMASK ('A')) { /* ASCII? */
|
if (sw & SWMASK ('A')) { /* ASCII? */
|
||||||
fprintf (of, (c2 < 040)? "<%03o>": "%c", c2);
|
fprintf (of, (c2 < 040)? "<%03o>": "%c", c2);
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
|
@ -592,7 +614,7 @@ if (!(sw & SWMASK ('M'))) return SCPE_ARG; /* mnemonic? */
|
||||||
|
|
||||||
/* Instruction decode */
|
/* Instruction decode */
|
||||||
|
|
||||||
inst = val[0];
|
inst = (int32) val[0];
|
||||||
for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
|
for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
|
||||||
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
|
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
|
||||||
if ((opc_val[i] & 0177777) == (inst & masks[j])) { /* match? */
|
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 */
|
dev = I_GETDEV (inst); /* IOT fields */
|
||||||
byac = I_GETPULSE (inst); /* byte fields */
|
byac = I_GETPULSE (inst); /* byte fields */
|
||||||
xop = I_GETXOP (inst); /* XOP fields */
|
xop = I_GETXOP (inst); /* XOP fields */
|
||||||
extind = val[1] & A_IND; /* extended fields */
|
extind = (int32) val[1] & A_IND; /* extended fields */
|
||||||
extdisp = val[1] & AMASK;
|
extdisp = (int32) val[1] & AMASK;
|
||||||
for (dv = 0; (dev_val[dv] >= 0) && (dev_val[dv] != dev); dv++) ;
|
for (dv = 0; (dev_val[dv] >= 0) && (dev_val[dv] != dev); dv++) ;
|
||||||
|
|
||||||
switch (j) { /* switch on class */
|
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);
|
fprintf (of, "%s %-o", opcode[i], dst);
|
||||||
break;
|
break;
|
||||||
case I_V_D: /* dev only */
|
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)
|
if (dev_val[dv] >= 0)
|
||||||
fprintf (of, "%s %s", opcode[i], device[dv]);
|
fprintf (of, "%s %s", opcode[i], device[dv]);
|
||||||
else fprintf (of, "%s %-o", opcode[i], dev);
|
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;
|
return -1;
|
||||||
case I_V_XP: /* XOP */
|
case I_V_XP: /* XOP */
|
||||||
fprintf (of, "%s %-o,%-o,%-o", opcode[i], src, dst, 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 */
|
return SCPE_OK; } /* end if */
|
||||||
} /* end for */
|
} /* end for */
|
||||||
return SCPE_ARG;
|
return SCPE_ARG;
|
||||||
|
@ -726,12 +758,12 @@ else if (*cptr == '-') { /* - sign? */
|
||||||
cptr++; }
|
cptr++; }
|
||||||
if (*cptr != 0) { /* number? */
|
if (*cptr != 0) { /* number? */
|
||||||
cptr = get_glyph (cptr, gbuf, ','); /* get glyph */
|
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;
|
if (r != SCPE_OK) return NULL;
|
||||||
pflag = pflag | A_NUM; }
|
pflag = pflag | A_NUM; }
|
||||||
if (*cptr != 0) { /* index? */
|
if (*cptr != 0) { /* index? */
|
||||||
cptr = get_glyph (cptr, gbuf, 0); /* get glyph */
|
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;
|
if ((r != SCPE_OK) || (x < 2)) return NULL;
|
||||||
pflag = pflag | A_NX; }
|
pflag = pflag | A_NX; }
|
||||||
|
|
||||||
|
@ -786,10 +818,10 @@ char gbuf[CBUFSIZE];
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
cptr = get_glyph (cptr, gbuf, ','); /* get register */
|
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;
|
if (r != SCPE_OK) return NULL;
|
||||||
cptr = get_glyph (cptr, gbuf, term); /* get register */
|
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;
|
if (r != SCPE_OK) return NULL;
|
||||||
return cptr;
|
return cptr;
|
||||||
}
|
}
|
||||||
|
@ -837,13 +869,13 @@ case I_V_NPN: /* no operand */
|
||||||
break;
|
break;
|
||||||
case I_V_R: /* IOT reg */
|
case I_V_R: /* IOT reg */
|
||||||
cptr = get_glyph (cptr, gbuf, 0); /* get register */
|
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;
|
if (r != SCPE_OK) return SCPE_ARG;
|
||||||
val[0] = val[0] | (d << I_V_DST); /* put in place */
|
val[0] = val[0] | (d << I_V_DST); /* put in place */
|
||||||
break;
|
break;
|
||||||
case I_V_RD: /* IOT reg,dev */
|
case I_V_RD: /* IOT reg,dev */
|
||||||
cptr = get_glyph (cptr, gbuf, ','); /* get register */
|
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;
|
if (r != SCPE_OK) return SCPE_ARG;
|
||||||
val[0] = val[0] | (d << I_V_DST); /* put in place */
|
val[0] = val[0] | (d << I_V_DST); /* put in place */
|
||||||
case I_V_D: /* IOT dev */
|
case I_V_D: /* IOT dev */
|
||||||
|
@ -852,13 +884,13 @@ case I_V_D: /* IOT dev */
|
||||||
(strcmp (device[i], gbuf) != 0); i++);
|
(strcmp (device[i], gbuf) != 0); i++);
|
||||||
if (device[i] != NULL) val[0] = val[0] | dev_val[i];
|
if (device[i] != NULL) val[0] = val[0] | dev_val[i];
|
||||||
else {
|
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;
|
if (r != SCPE_OK) return SCPE_ARG;
|
||||||
val[0] = val[0] | (d << I_V_DEV); }
|
val[0] = val[0] | (d << I_V_DEV); }
|
||||||
break;
|
break;
|
||||||
case I_V_RM: /* reg, addr */
|
case I_V_RM: /* reg, addr */
|
||||||
cptr = get_glyph (cptr, gbuf, ','); /* get register */
|
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;
|
if (r != SCPE_OK) return SCPE_ARG;
|
||||||
val[0] = val[0] | (d << I_V_DST); /* put in place */
|
val[0] = val[0] | (d << I_V_DST); /* put in place */
|
||||||
case I_V_M: /* addr */
|
case I_V_M: /* addr */
|
||||||
|
@ -889,33 +921,33 @@ case I_V_2AC: /* reg, reg */
|
||||||
break;
|
break;
|
||||||
case I_V_RSI: /* reg, short imm */
|
case I_V_RSI: /* reg, short imm */
|
||||||
cptr = get_glyph (cptr, gbuf, ','); /* get immediate */
|
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;
|
if ((d == 0) || (r != SCPE_OK)) return SCPE_ARG;
|
||||||
val[0] = val[0] | ((d - 1) << I_V_SRC); /* put in place */
|
val[0] = val[0] | ((d - 1) << I_V_SRC); /* put in place */
|
||||||
cptr = get_glyph (cptr, gbuf, 0); /* get register */
|
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;
|
if (r != SCPE_OK) return SCPE_ARG;
|
||||||
val[0] = val[0] | (d << I_V_DST); /* put in place */
|
val[0] = val[0] | (d << I_V_DST); /* put in place */
|
||||||
break;
|
break;
|
||||||
case I_V_RLI: /* reg, long imm */
|
case I_V_RLI: /* reg, long imm */
|
||||||
cptr = get_glyph (cptr, gbuf, ','); /* get immediate */
|
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;
|
if (r != SCPE_OK) return SCPE_ARG;
|
||||||
cptr = get_glyph (cptr, gbuf, 0); /* get register */
|
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;
|
if (r != SCPE_OK) return SCPE_ARG;
|
||||||
val[0] = val[0] | (d << I_V_DST); /* put in place */
|
val[0] = val[0] | (d << I_V_DST); /* put in place */
|
||||||
rtn = -1;
|
rtn = -1;
|
||||||
break;
|
break;
|
||||||
case I_V_LI: /* long imm */
|
case I_V_LI: /* long imm */
|
||||||
cptr = get_glyph (cptr, gbuf, 0); /* get immediate */
|
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;
|
if (r != SCPE_OK) return SCPE_ARG;
|
||||||
rtn = -1;
|
rtn = -1;
|
||||||
break;
|
break;
|
||||||
case I_V_RLM: /* reg, long mem */
|
case I_V_RLM: /* reg, long mem */
|
||||||
cptr = get_glyph (cptr, gbuf, ','); /* get register */
|
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;
|
if (r != SCPE_OK) return SCPE_ARG;
|
||||||
val[0] = val[0] | (d << I_V_DST); /* put in place */
|
val[0] = val[0] | (d << I_V_DST); /* put in place */
|
||||||
case I_V_LM: /* long mem */
|
case I_V_LM: /* long mem */
|
||||||
|
@ -927,7 +959,7 @@ case I_V_LM: /* long mem */
|
||||||
break;
|
break;
|
||||||
case I_V_FRM: /* flt reg, long mem */
|
case I_V_FRM: /* flt reg, long mem */
|
||||||
cptr = get_glyph (cptr, gbuf, ','); /* get register */
|
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;
|
if (r != SCPE_OK) return SCPE_ARG;
|
||||||
val[0] = val[0] | (d << I_V_DST); /* put in place */
|
val[0] = val[0] | (d << I_V_DST); /* put in place */
|
||||||
cptr = get_addr (cptr, addr, TRUE, cflag, amd);
|
cptr = get_addr (cptr, addr, TRUE, cflag, amd);
|
||||||
|
@ -948,7 +980,7 @@ case I_V_XP: /* XOP */
|
||||||
if (cptr == NULL) return SCPE_ARG;
|
if (cptr == NULL) return SCPE_ARG;
|
||||||
val[0] = val[0] | (amd[0] << I_V_SRC) | (amd[1] << I_V_DST);
|
val[0] = val[0] | (amd[0] << I_V_SRC) | (amd[1] << I_V_DST);
|
||||||
cptr = get_glyph (cptr, gbuf, 0); /* get argument */
|
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;
|
if (r != SCPE_OK) return SCPE_ARG;
|
||||||
val[0] = val[0] | (d << I_V_XOP);
|
val[0] = val[0] | (d << I_V_XOP);
|
||||||
break; } /* end case */
|
break; } /* end case */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* nova_tt.c: NOVA console terminal simulator
|
/* 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
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -26,6 +26,7 @@
|
||||||
tti terminal input
|
tti terminal input
|
||||||
tto terminal output
|
tto terminal output
|
||||||
|
|
||||||
|
29-Dec-03 RMS Added console backpressure support
|
||||||
25-Apr-03 RMS Revised for extended file support
|
25-Apr-03 RMS Revised for extended file support
|
||||||
05-Jan-02 RMS Fixed calling sequence for setmod
|
05-Jan-02 RMS Fixed calling sequence for setmod
|
||||||
03-Oct-02 RMS Added DIBs
|
03-Oct-02 RMS Added DIBs
|
||||||
|
@ -188,14 +189,17 @@ return 0;
|
||||||
|
|
||||||
t_stat tto_svc (UNIT *uptr)
|
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_busy = dev_busy & ~INT_TTO; /* clear busy */
|
||||||
dev_done = dev_done | INT_TTO; /* set done */
|
dev_done = dev_done | INT_TTO; /* set done */
|
||||||
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
|
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;
|
tto_unit.pos = tto_unit.pos + 1;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
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
|
22-Jul-03 RMS Updated for "hardware" RIM loader
|
||||||
Revised to detect I/O wait hang
|
Revised to detect I/O wait hang
|
||||||
05-Dec-02 RMS Added IOT skip support (required by drum)
|
05-Dec-02 RMS Added IOT skip support (required by drum)
|
||||||
|
@ -36,6 +38,7 @@
|
||||||
|
|
||||||
Automatic multiply/divide Type 10
|
Automatic multiply/divide Type 10
|
||||||
Memory extension control Type 15
|
Memory extension control Type 15
|
||||||
|
Parallel drum Type 23
|
||||||
Serial drum Type 24
|
Serial drum Type 24
|
||||||
Line printer control Type 62
|
Line printer control Type 62
|
||||||
Microtape (DECtape) control Type 550
|
Microtape (DECtape) control Type 550
|
||||||
|
@ -51,6 +54,7 @@
|
||||||
#define STOP_XCT 4 /* nested XCT's */
|
#define STOP_XCT 4 /* nested XCT's */
|
||||||
#define STOP_IND 5 /* nested indirects */
|
#define STOP_IND 5 /* nested indirects */
|
||||||
#define STOP_WAIT 6 /* IO wait hang */
|
#define STOP_WAIT 6 /* IO wait hang */
|
||||||
|
#define STOP_DTOFF 7 /* DECtape off reel */
|
||||||
|
|
||||||
/* Memory */
|
/* Memory */
|
||||||
|
|
||||||
|
@ -92,6 +96,7 @@
|
||||||
#define IOS_V_SQB 11 /* sequence break */
|
#define IOS_V_SQB 11 /* sequence break */
|
||||||
#define IOS_V_PNT 2 /* print done */
|
#define IOS_V_PNT 2 /* print done */
|
||||||
#define IOS_V_SPC 1 /* space 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_LPN (1 << IOS_V_LPN)
|
||||||
#define IOS_PTR (1 << IOS_V_PTR)
|
#define IOS_PTR (1 << IOS_V_PTR)
|
||||||
|
@ -102,6 +107,7 @@
|
||||||
#define IOS_SQB (1 << IOS_V_SQB)
|
#define IOS_SQB (1 << IOS_V_SQB)
|
||||||
#define IOS_PNT (1 << IOS_V_PNT)
|
#define IOS_PNT (1 << IOS_V_PNT)
|
||||||
#define IOS_SPC (1 << IOS_V_SPC)
|
#define IOS_SPC (1 << IOS_V_SPC)
|
||||||
|
#define IOS_DRP (1 << IOS_V_DRP)
|
||||||
|
|
||||||
/* Completion pulses */
|
/* Completion pulses */
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
To: Users
|
To: Users
|
||||||
From: Bob Supnik
|
From: Bob Supnik
|
||||||
Subj: PDP-1 Simulator Usage
|
Subj: PDP-1 Simulator Usage
|
||||||
Date: 15-Sep-2003
|
Date: 15-Dec-2003
|
||||||
|
|
||||||
COPYRIGHT NOTICE
|
COPYRIGHT NOTICE
|
||||||
|
|
||||||
|
@ -65,6 +65,7 @@ PTR,PTP integral paper tape reader/punch
|
||||||
TTY console typewriter
|
TTY console typewriter
|
||||||
LPT Type 62 line printer
|
LPT Type 62 line printer
|
||||||
DRM Type 24 serial drum
|
DRM Type 24 serial drum
|
||||||
|
DRP Type 23 parallel drum
|
||||||
DT Type 550 Microtape (DECtape)
|
DT Type 550 Microtape (DECtape)
|
||||||
|
|
||||||
The PDP-1 simulator implements the following unique stop conditions:
|
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
|
instruction execution
|
||||||
- I/O wait, and no I/O operations outstanding (i.e, no I/O
|
- I/O wait, and no I/O operations outstanding (i.e, no I/O
|
||||||
completion will ever occur)
|
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 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,
|
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
|
BEF 1 block end flag
|
||||||
ERF 1 error flag
|
ERF 1 error flag
|
||||||
LTIME 31 time between lines
|
LTIME 31 time between lines
|
||||||
ACTIME 31 time to accelerate to full speed
|
|
||||||
DCTIME 31 time to decelerate to a full stop
|
DCTIME 31 time to decelerate to a full stop
|
||||||
SUBSTATE 2 read/write command substate
|
SUBSTATE 2 read/write command substate
|
||||||
POS[0:7] 32 position, in lines, units 0-7
|
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.
|
operate correctly.
|
||||||
|
|
||||||
- LTIME must be at least 6
|
- LTIME must be at least 6
|
||||||
- ACTIME must be less than DCTIME, and both need to be at
|
- DCTIME needs to be at least 100 times LTIME
|
||||||
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:
|
The serial drum (DRM) implements these registers:
|
||||||
|
|
||||||
|
@ -324,7 +334,6 @@ The serial drum (DRM) implements these registers:
|
||||||
|
|
||||||
DA 9 drum address (sector number)
|
DA 9 drum address (sector number)
|
||||||
MA 16 current memory address
|
MA 16 current memory address
|
||||||
INT 1 interrupt pending flag
|
|
||||||
DONE 1 device done flag
|
DONE 1 device done flag
|
||||||
ERR 1 error flag
|
ERR 1 error flag
|
||||||
WLK 32 write lock switches
|
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
|
Drum data files are buffered in memory; therefore, end of file and OS
|
||||||
I/O errors cannot occur.
|
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
|
2.5 Symbolic Display and Input
|
||||||
|
|
||||||
The PDP-1 simulator implements symbolic display and input. Display is
|
The PDP-1 simulator implements symbolic display and input. Display is
|
||||||
|
|
201
PDP1/pdp1_drm.c
|
@ -23,8 +23,12 @@
|
||||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
drp Type 23 parallel drum
|
||||||
drm Type 24 serial 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
|
23-Jul-03 RMS Fixed incorrect logical, missing activate
|
||||||
05-Dec-02 RMS Cloned from pdp18b_drm.c
|
05-Dec-02 RMS Cloned from pdp18b_drm.c
|
||||||
*/
|
*/
|
||||||
|
@ -32,21 +36,36 @@
|
||||||
#include "pdp1_defs.h"
|
#include "pdp1_defs.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
/* Constants */
|
/* Serial drum constants */
|
||||||
|
|
||||||
#define DRM_NUMWDS 256 /* words/sector */
|
#define DRM_NUMWDS 256 /* words/sector */
|
||||||
#define DRM_NUMSC 2 /* sectors/track */
|
#define DRM_NUMSC 2 /* sectors/track */
|
||||||
#define DRM_NUMTR 256 /* tracks/drum */
|
#define DRM_NUMTR 256 /* tracks/drum */
|
||||||
#define DRM_NUMDK 1 /* drum/controller */
|
|
||||||
#define DRM_NUMWDT (DRM_NUMWDS * DRM_NUMSC) /* words/track */
|
#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 */
|
#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 */
|
/* Parameters in the unit descriptor */
|
||||||
|
|
||||||
#define FUNC u4 /* function */
|
#define FUNC u4 /* function */
|
||||||
#define DRM_READ 000 /* read */
|
#define DRM_READ 000 /* read */
|
||||||
#define DRM_WRITE 010 /* write */
|
#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)), \
|
#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \
|
||||||
((double) DRM_NUMWDT)))
|
((double) DRM_NUMWDT)))
|
||||||
|
@ -56,15 +75,34 @@ extern int32 iosta, sbs;
|
||||||
extern int32 stop_inst;
|
extern int32 stop_inst;
|
||||||
extern UNIT cpu_unit;
|
extern UNIT cpu_unit;
|
||||||
|
|
||||||
int32 drm_da = 0; /* track address */
|
/* Serial drum variables */
|
||||||
int32 drm_ma = 0; /* memory address */
|
|
||||||
int32 drm_err = 0; /* error flag */
|
uint32 drm_da = 0; /* track address */
|
||||||
int32 drm_wlk = 0; /* write lock */
|
uint32 drm_ma = 0; /* memory address */
|
||||||
int32 drm_time = 10; /* inter-word time */
|
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 */
|
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_svc (UNIT *uptr);
|
||||||
t_stat drm_reset (DEVICE *dptr);
|
t_stat drm_reset (DEVICE *dptr);
|
||||||
|
t_stat drp_svc (UNIT *uptr);
|
||||||
|
t_stat drp_reset (DEVICE *dptr);
|
||||||
|
|
||||||
/* DRM data structures
|
/* DRM data structures
|
||||||
|
|
||||||
|
@ -93,6 +131,38 @@ DEVICE drm_dev = {
|
||||||
NULL, NULL, &drm_reset,
|
NULL, NULL, &drm_reset,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
NULL, DEV_DISABLE };
|
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 */
|
/* IOT routines */
|
||||||
|
|
||||||
|
@ -101,17 +171,17 @@ int32 drm (int32 IR, int32 dev, int32 dat)
|
||||||
int32 t;
|
int32 t;
|
||||||
int32 pulse = (IR >> 6) & 037;
|
int32 pulse = (IR >> 6) & 037;
|
||||||
|
|
||||||
if (drm_dev.flags & DEV_DIS) /* disabled? */
|
if ((drm_dev.flags & DEV_DIS) == 0) { /* serial enabled? */
|
||||||
return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */
|
|
||||||
if ((pulse != 001) && (pulse != 011)) /* invalid pulse? */
|
if ((pulse != 001) && (pulse != 011)) /* invalid pulse? */
|
||||||
return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */
|
return (stop_inst << IOT_V_REASON) | dat; /* stop if requested */
|
||||||
switch (dev) { /* switch on device */
|
switch (dev) { /* switch on device */
|
||||||
case 061: /* DWR, DRD */
|
case 061: /* DWR, DRD */
|
||||||
drm_ma = dat & 0177777; /* load mem addr */
|
drm_ma = dat & AMASK; /* load mem addr */
|
||||||
drm_unit.FUNC = pulse & DRM_WRITE; /* save function */
|
drm_unit.FUNC = pulse & DRM_WRITE; /* save function */
|
||||||
break;
|
break;
|
||||||
case 062: /* DBL, DCN */
|
case 062: /* DBL, DCN */
|
||||||
if (pulse & 010) drm_da = dat & DRM_SMASK; /* load sector # */
|
if ((pulse & 010) == 0) /* DBL? */
|
||||||
|
drm_da = dat & DRM_SMASK; /* load sector # */
|
||||||
iosta = iosta & ~IOS_DRM; /* clear flags */
|
iosta = iosta & ~IOS_DRM; /* clear flags */
|
||||||
drm_err = 0;
|
drm_err = 0;
|
||||||
t = ((drm_da % DRM_NUMSC) * DRM_NUMWDS) - GET_POS (drm_time);
|
t = ((drm_da % DRM_NUMSC) * DRM_NUMWDS) - GET_POS (drm_time);
|
||||||
|
@ -125,15 +195,53 @@ case 063: /* DTD */
|
||||||
case 064: /* DSE, DSP */
|
case 064: /* DSE, DSP */
|
||||||
if ((drm_err == 0) || (pulse & 010)) /* no error, par test? */
|
if ((drm_err == 0) || (pulse & 010)) /* no error, par test? */
|
||||||
return (dat | IOT_SKP);
|
return (dat | IOT_SKP);
|
||||||
}
|
} /* end case */
|
||||||
return dat;
|
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)
|
t_stat drm_svc (UNIT *uptr)
|
||||||
{
|
{
|
||||||
uint32 i, da;
|
uint32 i, da;
|
||||||
|
uint32 *fbuf = uptr->filebuf;
|
||||||
|
|
||||||
if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
|
if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
|
||||||
drm_err = 1; /* set error */
|
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 */
|
da = drm_da * DRM_NUMWDS; /* compute dev addr */
|
||||||
for (i = 0; i < DRM_NUMWDS; i++, da++) { /* do transfer */
|
for (i = 0; i < DRM_NUMWDS; i++, da++) { /* do transfer */
|
||||||
if (uptr->FUNC == DRM_READ) {
|
if (uptr->FUNC == DRM_READ) { /* read? */
|
||||||
if (MEM_ADDR_OK (drm_ma)) /* read, check nxm */
|
if (MEM_ADDR_OK (drm_ma)) /* if !nxm */
|
||||||
M[drm_ma] = *(((int32 *) uptr->filebuf) + da); }
|
M[drm_ma] = fbuf[da]; } /* read word */
|
||||||
else {
|
else { /* write */
|
||||||
if ((drm_wlk >> (drm_da >> 4)) & 1) drm_err = 1;
|
if ((drm_wlk >> (drm_da >> 4)) & 1) drm_err = 1;
|
||||||
else {
|
else { /* not locked */
|
||||||
*(((int32 *) uptr->filebuf) + da) = M[drm_ma];
|
fbuf[da] = M[drm_ma]; /* write word */
|
||||||
if (da >= uptr->hwmark) uptr->hwmark = da + 1; } }
|
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 */
|
drm_da = (drm_da + 1) & DRM_SMASK; /* incr dev addr */
|
||||||
iosta = iosta | IOS_DRM; /* set done */
|
iosta = iosta | IOS_DRM; /* set done */
|
||||||
sbs = sbs | SB_RQ; /* req intr */
|
sbs = sbs | SB_RQ; /* req intr */
|
||||||
|
@ -162,8 +270,57 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat drm_reset (DEVICE *dptr)
|
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;
|
drm_da = drm_ma = drm_err = 0;
|
||||||
iosta = iosta & ~IOS_DRM;
|
iosta = iosta & ~IOS_DRM;
|
||||||
sim_cancel (&drm_unit);
|
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;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
dt Type 550/555 DECtape
|
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
|
25-Apr-03 RMS Revised for extended file support
|
||||||
14-Mar-03 RMS Fixed variable size interaction with save/restore
|
14-Mar-03 RMS Fixed variable size interaction with save/restore
|
||||||
17-Oct-02 RMS Fixed bug in end of reel logic
|
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.
|
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.
|
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 0
|
||||||
:
|
:
|
||||||
block n
|
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
|
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
|
words, and five 18b trailer words. All systems except the PDP-8 use a
|
||||||
|
@ -64,9 +69,9 @@
|
||||||
header word 0 0
|
header word 0 0
|
||||||
header word 1 block number (for forward reads)
|
header word 1 block number (for forward reads)
|
||||||
header words 2,3 0
|
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 words 3,2 0
|
||||||
trailer word 1 block number (for reverse reads)
|
trailer word 1 block number (for reverse reads)
|
||||||
trailer word 0 0
|
trailer word 0 0
|
||||||
|
@ -97,13 +102,15 @@
|
||||||
|
|
||||||
/* System independent DECtape constants */
|
/* System independent DECtape constants */
|
||||||
|
|
||||||
#define DT_EZLIN 36000 /* end zone length */
|
#define DT_LPERMC 6 /* lines per mark track */
|
||||||
#define DT_HTLIN 30 /* header/trailer lines */
|
#define DT_BLKWD 1 /* blk no word in h/t */
|
||||||
#define DT_BLKLN 6 /* blk no line in h/t */
|
#define DT_CSMWD 4 /* checksum word in h/t */
|
||||||
#define DT_CSMLN 24 /* checksum line in h/t */
|
#define DT_HTWRD 5 /* header/trailer words */
|
||||||
#define DT_HTWRD (DT_HTLIN / DT_WSIZE) /* header/trailer words */
|
#define DT_EZLIN (8192 * DT_LPERMC) /* end zone length */
|
||||||
#define DT_BLKWD (DT_BLKLN / DT_WSIZE) /* blk no word in h/t */
|
#define DT_BFLIN (200 * DT_LPERMC) /* buffer length */
|
||||||
#define DT_CSMWD (DT_CSMLN / DT_WSIZE) /* checksum word in h/t */
|
#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 */
|
/* 16b, 18b, 36b DECtape constants */
|
||||||
|
|
||||||
|
@ -249,8 +256,7 @@ int32 dtsa = 0; /* status A */
|
||||||
int32 dtsb = 0; /* status B */
|
int32 dtsb = 0; /* status B */
|
||||||
int32 dtdb = 0; /* data buffer */
|
int32 dtdb = 0; /* data buffer */
|
||||||
int32 dt_ltime = 12; /* interline time */
|
int32 dt_ltime = 12; /* interline time */
|
||||||
int32 dt_actime = 54000; /* accel time */
|
int32 dt_dctime = 40000; /* decel time */
|
||||||
int32 dt_dctime = 72000; /* decel time */
|
|
||||||
int32 dt_substate = 0;
|
int32 dt_substate = 0;
|
||||||
int32 dt_log = 0;
|
int32 dt_log = 0;
|
||||||
int32 dt_logblk = 0;
|
int32 dt_logblk = 0;
|
||||||
|
@ -306,7 +312,6 @@ REG dt_reg[] = {
|
||||||
{ FLDATA (BEF, dtsb, DTB_V_BEF) },
|
{ FLDATA (BEF, dtsb, DTB_V_BEF) },
|
||||||
{ FLDATA (ERF, dtsb, DTB_V_ERF) },
|
{ FLDATA (ERF, dtsb, DTB_V_ERF) },
|
||||||
{ DRDATA (LTIME, dt_ltime, 31), REG_NZ },
|
{ DRDATA (LTIME, dt_ltime, 31), REG_NZ },
|
||||||
{ DRDATA (ACTIME, dt_actime, 31), REG_NZ },
|
|
||||||
{ DRDATA (DCTIME, dt_dctime, 31), REG_NZ },
|
{ DRDATA (DCTIME, dt_dctime, 31), REG_NZ },
|
||||||
{ ORDATA (SUBSTATE, dt_substate, 2) },
|
{ ORDATA (SUBSTATE, dt_substate, 2) },
|
||||||
{ ORDATA (LOG, dt_log, 4), REG_HIDDEN },
|
{ 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 (new_mving & ~prev_mving) { /* start? */
|
||||||
if (dt_setpos (uptr)) return; /* update pos */
|
if (dt_setpos (uptr)) return; /* update pos */
|
||||||
sim_cancel (uptr); /* stop current */
|
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_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */
|
||||||
DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */
|
DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */
|
||||||
return; }
|
return; }
|
||||||
|
@ -467,7 +472,7 @@ if (prev_dir ^ new_dir) { /* dir chg? */
|
||||||
if (prev_mot < DTS_ACCF) { /* not accel/at speed? */
|
if (prev_mot < DTS_ACCF) { /* not accel/at speed? */
|
||||||
if (dt_setpos (uptr)) return; /* update pos */
|
if (dt_setpos (uptr)) return; /* update pos */
|
||||||
sim_cancel (uptr); /* cancel cur */
|
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_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */
|
||||||
DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */
|
DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */
|
||||||
return; }
|
return; }
|
||||||
|
@ -588,11 +593,13 @@ case DTS_STOP: /* stop */
|
||||||
delta = 0;
|
delta = 0;
|
||||||
break;
|
break;
|
||||||
case DTS_DECF: /* slowing */
|
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);
|
delta = ((ulin * udelt * 2) - (ulin * ulin)) / (2 * udelt);
|
||||||
break;
|
break;
|
||||||
case DTS_ACCF: /* accelerating */
|
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);
|
delta = (ulin * ulin) / (2 * udelt);
|
||||||
break;
|
break;
|
||||||
case DTS_ATSF: /* at speed */
|
case DTS_ATSF: /* at speed */
|
||||||
|
@ -621,7 +628,7 @@ t_stat dt_svc (UNIT *uptr)
|
||||||
int32 mot = DTS_GETMOT (uptr->STATE);
|
int32 mot = DTS_GETMOT (uptr->STATE);
|
||||||
int32 dir = mot & DTS_DIR;
|
int32 dir = mot & DTS_DIR;
|
||||||
int32 fnc = DTS_GETFNC (uptr->STATE);
|
int32 fnc = DTS_GETFNC (uptr->STATE);
|
||||||
int32 *bptr = uptr->filebuf;
|
int32 *fbuf = uptr->filebuf;
|
||||||
int32 unum = uptr - dt_dev.units;
|
int32 unum = uptr - dt_dev.units;
|
||||||
int32 blk, wrd, ma, relpos;
|
int32 blk, wrd, ma, relpos;
|
||||||
uint32 ba;
|
uint32 ba;
|
||||||
|
@ -635,10 +642,10 @@ uint32 ba;
|
||||||
|
|
||||||
switch (mot) {
|
switch (mot) {
|
||||||
case DTS_DECF: case DTS_DECR: /* decelerating */
|
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 */
|
uptr->STATE = DTS_NXTSTA (uptr->STATE); /* advance state */
|
||||||
if (uptr->STATE) /* not stopped? */
|
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;
|
return SCPE_OK;
|
||||||
case DTS_ACCF: case DTS_ACCR: /* accelerating */
|
case DTS_ACCF: case DTS_ACCR: /* accelerating */
|
||||||
dt_newfnc (uptr, DTS_NXTSTA (uptr->STATE)); /* adv state, sched */
|
dt_newfnc (uptr, DTS_NXTSTA (uptr->STATE)); /* adv state, sched */
|
||||||
|
@ -656,7 +663,7 @@ default: /* other */
|
||||||
Off reel - detach unit (it must be deselected)
|
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? */
|
if (DT_QEZ (uptr)) { /* in end zone? */
|
||||||
dt_seterr (uptr, DTB_END); /* end zone error */
|
dt_seterr (uptr, DTB_END); /* end zone error */
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
|
@ -693,7 +700,7 @@ case FNC_READ: case FNC_RALL:
|
||||||
(relpos < (DTU_LPERB (uptr) - DT_HTLIN))) {
|
(relpos < (DTU_LPERB (uptr) - DT_HTLIN))) {
|
||||||
wrd = DT_LIN2WD (uptr->pos, uptr);
|
wrd = DT_LIN2WD (uptr->pos, uptr);
|
||||||
ba = (blk * DTU_BSIZE (uptr)) + wrd;
|
ba = (blk * DTU_BSIZE (uptr)) + wrd;
|
||||||
dtdb = bptr[ba]; /* get tape word */
|
dtdb = fbuf[ba]; /* get tape word */
|
||||||
dtsb = dtsb | DTB_DTF; } /* set flag */
|
dtsb = dtsb | DTB_DTF; } /* set flag */
|
||||||
else {
|
else {
|
||||||
ma = (2 * DT_HTWRD) + DTU_BSIZE (uptr) - DT_CSMWD - 1;
|
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))) {
|
(relpos < (DTU_LPERB (uptr) - DT_HTLIN))) {
|
||||||
wrd = DT_LIN2WD (uptr->pos, uptr);
|
wrd = DT_LIN2WD (uptr->pos, uptr);
|
||||||
ba = (blk * DTU_BSIZE (uptr)) + wrd;
|
ba = (blk * DTU_BSIZE (uptr)) + wrd;
|
||||||
if (dir) bptr[ba] = dt_comobv (dtdb); /* get data word */
|
if (dir) fbuf[ba] = dt_comobv (dtdb); /* get data word */
|
||||||
else bptr[ba] = dtdb;
|
else fbuf[ba] = dtdb;
|
||||||
if (ba >= uptr->hwmark) uptr->hwmark = ba + 1;
|
if (ba >= uptr->hwmark) uptr->hwmark = ba + 1;
|
||||||
if (wrd == (dir? 0: DTU_BSIZE (uptr) - 1))
|
if (wrd == (dir? 0: DTU_BSIZE (uptr) - 1))
|
||||||
dtsb = dtsb | DTB_BEF; /* end block */
|
dtsb = dtsb | DTB_BEF; /* end block */
|
||||||
|
@ -791,13 +798,13 @@ return dat;
|
||||||
|
|
||||||
int32 dt_csum (UNIT *uptr, int32 blk)
|
int32 dt_csum (UNIT *uptr, int32 blk)
|
||||||
{
|
{
|
||||||
int32 *bptr = uptr->filebuf;
|
int32 *fbuf = uptr->filebuf;
|
||||||
int32 ba = blk * DTU_BSIZE (uptr);
|
int32 ba = blk * DTU_BSIZE (uptr);
|
||||||
int32 i, csum, wrd;
|
int32 i, csum, wrd;
|
||||||
|
|
||||||
csum = 0777777;
|
csum = 0777777;
|
||||||
for (i = 0; i < DTU_BSIZE (uptr); i++) { /* loop thru buf */
|
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 */
|
csum = csum + wrd; /* 1's comp add */
|
||||||
if (csum > 0777777) csum = (csum + 1) & 0777777; }
|
if (csum > 0777777) csum = (csum + 1) & 0777777; }
|
||||||
return (csum ^ 0777777); /* 1's comp res */
|
return (csum ^ 0777777); /* 1's comp res */
|
||||||
|
@ -868,7 +875,7 @@ t_stat dt_attach (UNIT *uptr, char *cptr)
|
||||||
{
|
{
|
||||||
uint16 pdp8b[D8_NBSIZE];
|
uint16 pdp8b[D8_NBSIZE];
|
||||||
uint16 pdp11b[D18_BSIZE];
|
uint16 pdp11b[D18_BSIZE];
|
||||||
uint32 ba, sz, k, *bptr;
|
uint32 ba, sz, k, *fbuf;
|
||||||
int32 u = uptr - dt_dev.units;
|
int32 u = uptr - dt_dev.units;
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
|
@ -891,7 +898,7 @@ uptr->filebuf = calloc (uptr->capac, sizeof (int32));
|
||||||
if (uptr->filebuf == NULL) { /* can't alloc? */
|
if (uptr->filebuf == NULL) { /* can't alloc? */
|
||||||
detach_unit (uptr);
|
detach_unit (uptr);
|
||||||
return SCPE_MEM; }
|
return SCPE_MEM; }
|
||||||
bptr = uptr->filebuf; /* file buffer */
|
fbuf = uptr->filebuf; /* file buffer */
|
||||||
printf ("%s%d: ", sim_dname (&dt_dev), u);
|
printf ("%s%d: ", sim_dname (&dt_dev), u);
|
||||||
if (uptr->flags & UNIT_8FMT) printf ("12b format");
|
if (uptr->flags & UNIT_8FMT) printf ("12b format");
|
||||||
else if (uptr->flags & UNIT_11FMT) printf ("16b format");
|
else if (uptr->flags & UNIT_11FMT) printf ("16b format");
|
||||||
|
@ -903,9 +910,9 @@ if (uptr->flags & UNIT_8FMT) { /* 12b? */
|
||||||
if (k == 0) break;
|
if (k == 0) break;
|
||||||
for ( ; k < D8_NBSIZE; k++) pdp8b[k] = 0;
|
for ( ; k < D8_NBSIZE; k++) pdp8b[k] = 0;
|
||||||
for (k = 0; k < D8_NBSIZE; k = k + 3) { /* loop thru blk */
|
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);
|
((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);
|
(pdp8b[k + 2] & 07777);
|
||||||
ba = ba + 2; } /* end blk loop */
|
ba = ba + 2; } /* end blk loop */
|
||||||
} /* end file loop */
|
} /* end file loop */
|
||||||
|
@ -916,7 +923,7 @@ else if (uptr->flags & UNIT_11FMT) { /* 16b? */
|
||||||
if (k == 0) break;
|
if (k == 0) break;
|
||||||
for ( ; k < D18_BSIZE; k++) pdp11b[k] = 0;
|
for ( ; k < D18_BSIZE; k++) pdp11b[k] = 0;
|
||||||
for (k = 0; k < D18_BSIZE; k++)
|
for (k = 0; k < D18_BSIZE; k++)
|
||||||
bptr[ba++] = pdp11b[k]; }
|
fbuf[ba++] = pdp11b[k]; }
|
||||||
uptr->hwmark = ba; } /* end elif */
|
uptr->hwmark = ba; } /* end elif */
|
||||||
else uptr->hwmark = fxread (uptr->filebuf, sizeof (int32),
|
else uptr->hwmark = fxread (uptr->filebuf, sizeof (int32),
|
||||||
uptr->capac, uptr->fileref);
|
uptr->capac, uptr->fileref);
|
||||||
|
@ -939,27 +946,27 @@ t_stat dt_detach (UNIT* uptr)
|
||||||
{
|
{
|
||||||
uint16 pdp8b[D8_NBSIZE];
|
uint16 pdp8b[D8_NBSIZE];
|
||||||
uint16 pdp11b[D18_BSIZE];
|
uint16 pdp11b[D18_BSIZE];
|
||||||
uint32 ba, k, *bptr;
|
uint32 ba, k, *fbuf;
|
||||||
int32 u = uptr - dt_dev.units;
|
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)) {
|
if (sim_is_active (uptr)) {
|
||||||
sim_cancel (uptr);
|
sim_cancel (uptr);
|
||||||
if ((u == DTA_GETUNIT (dtsa)) && (dtsa & DTA_STSTP)) {
|
if ((u == DTA_GETUNIT (dtsa)) && (dtsa & DTA_STSTP)) {
|
||||||
dtsb = dtsb | DTB_ERF | DTB_SEL | DTB_DTF;
|
dtsb = dtsb | DTB_ERF | DTB_SEL | DTB_DTF;
|
||||||
DT_UPDINT; }
|
DT_UPDINT; }
|
||||||
uptr->STATE = uptr->pos = 0; }
|
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? */
|
if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */
|
||||||
printf ("%s%d: writing buffer to file\n", sim_dname (&dt_dev), u);
|
printf ("%s%d: writing buffer to file\n", sim_dname (&dt_dev), u);
|
||||||
rewind (uptr->fileref); /* start of file */
|
rewind (uptr->fileref); /* start of file */
|
||||||
if (uptr->flags & UNIT_8FMT) { /* 12b? */
|
if (uptr->flags & UNIT_8FMT) { /* 12b? */
|
||||||
for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */
|
for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */
|
||||||
for (k = 0; k < D8_NBSIZE; k = k + 3) { /* loop blk */
|
for (k = 0; k < D8_NBSIZE; k = k + 3) { /* loop blk */
|
||||||
pdp8b[k] = (bptr[ba] >> 6) & 07777;
|
pdp8b[k] = (fbuf[ba] >> 6) & 07777;
|
||||||
pdp8b[k + 1] = ((bptr[ba] & 077) << 6) |
|
pdp8b[k + 1] = ((fbuf[ba] & 077) << 6) |
|
||||||
((bptr[ba + 1] >> 12) & 077);
|
((fbuf[ba + 1] >> 12) & 077);
|
||||||
pdp8b[k + 2] = bptr[ba + 1] & 07777;
|
pdp8b[k + 2] = fbuf[ba + 1] & 07777;
|
||||||
ba = ba + 2; } /* end loop blk */
|
ba = ba + 2; } /* end loop blk */
|
||||||
fxwrite (pdp8b, sizeof (int16), D8_NBSIZE, uptr->fileref);
|
fxwrite (pdp8b, sizeof (int16), D8_NBSIZE, uptr->fileref);
|
||||||
if (ferror (uptr->fileref)) break; } /* end loop file */
|
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? */
|
else if (uptr->flags & UNIT_11FMT) { /* 16b? */
|
||||||
for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */
|
for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */
|
||||||
for (k = 0; k < D18_BSIZE; k++) /* loop blk */
|
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);
|
fxwrite (pdp11b, sizeof (int16), D18_BSIZE, uptr->fileref);
|
||||||
if (ferror (uptr->fileref)) break; } /* end loop file */
|
if (ferror (uptr->fileref)) break; } /* end loop file */
|
||||||
} /* end if 16b */
|
} /* end if 16b */
|
||||||
|
|
|
@ -143,27 +143,27 @@ if (cpls & CPLS_LPT) { /* completion pulse? */
|
||||||
sbs = sbs | SB_RQ; /* req seq break */
|
sbs = sbs | SB_RQ; /* req seq break */
|
||||||
if (lpt_spc) { /* space? */
|
if (lpt_spc) { /* space? */
|
||||||
iosta = iosta | IOS_SPC; /* set flag */
|
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);
|
return IORETURN (lpt_stopioe, SCPE_UNATT);
|
||||||
fputs (lpt_cc[lpt_spc & 07], lpt_unit.fileref); /* print cctl */
|
fputs (lpt_cc[lpt_spc & 07], uptr->fileref); /* print cctl */
|
||||||
if (ferror (lpt_unit.fileref)) { /* error? */
|
if (ferror (uptr->fileref)) { /* error? */
|
||||||
perror ("LPT I/O error");
|
perror ("LPT I/O error");
|
||||||
clearerr (lpt_unit.fileref);
|
clearerr (uptr->fileref);
|
||||||
return SCPE_IOERR; }
|
return SCPE_IOERR; }
|
||||||
lpt_ovrpr = 0; } /* dont overprint */
|
lpt_ovrpr = 0; } /* dont overprint */
|
||||||
else { iosta = iosta | IOS_PNT; /* print */
|
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);
|
return IORETURN (lpt_stopioe, SCPE_UNATT);
|
||||||
if (lpt_ovrpr) fputc ('\r', lpt_unit.fileref); /* overprint? */
|
if (lpt_ovrpr) fputc ('\r', uptr->fileref); /* overprint? */
|
||||||
fputs (lpt_buf, lpt_unit.fileref); /* print buffer */
|
fputs (lpt_buf, uptr->fileref); /* print buffer */
|
||||||
if (ferror (lpt_unit.fileref)) { /* test error */
|
if (ferror (uptr->fileref)) { /* test error */
|
||||||
perror ("LPT I/O error");
|
perror ("LPT I/O error");
|
||||||
clearerr (lpt_unit.fileref);
|
clearerr (uptr->fileref);
|
||||||
return SCPE_IOERR; }
|
return SCPE_IOERR; }
|
||||||
lpt_bptr = 0;
|
lpt_bptr = 0;
|
||||||
for (i = 0; i <= LPT_BSIZE; i++) lpt_buf[i] = 0; /* clear buffer */
|
for (i = 0; i <= LPT_BSIZE; i++) lpt_buf[i] = 0; /* clear buffer */
|
||||||
lpt_ovrpr = 1; } /* set overprint */
|
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;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
tti keyboard
|
tti keyboard
|
||||||
tto teleprinter
|
tto teleprinter
|
||||||
|
|
||||||
|
29-Oct-03 RMS Added PTR FIODEC-to-ASCII translation (from Phil Budne)
|
||||||
07-Sep-03 RMS Changed ioc to ios
|
07-Sep-03 RMS Changed ioc to ios
|
||||||
30-Aug-03 RMS Revised PTR to conform to Maintenance Manual;
|
30-Aug-03 RMS Revised PTR to conform to Maintenance Manual;
|
||||||
added deadlock prevention on errors
|
added deadlock prevention on errors
|
||||||
|
@ -42,10 +43,14 @@
|
||||||
07-Sep-01 RMS Moved function prototypes
|
07-Sep-01 RMS Moved function prototypes
|
||||||
10-Jun-01 RMS Fixed comment
|
10-Jun-01 RMS Fixed comment
|
||||||
30-Oct-00 RMS Standardized device naming
|
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"
|
#include "pdp1_defs.h"
|
||||||
|
|
||||||
|
#define FIODEC_STOP 013 /* stop code */
|
||||||
#define FIODEC_UC 074
|
#define FIODEC_UC 074
|
||||||
#define FIODEC_LC 072
|
#define FIODEC_LC 072
|
||||||
#define UC_V 6 /* upper case */
|
#define UC_V 6 /* upper case */
|
||||||
|
@ -55,10 +60,16 @@
|
||||||
#define TT_WIDTH 077
|
#define TT_WIDTH 077
|
||||||
#define TTI 0
|
#define TTI 0
|
||||||
#define TTO 1
|
#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_state = 0;
|
||||||
int32 ptr_wait = 0;
|
int32 ptr_wait = 0;
|
||||||
int32 ptr_stopioe = 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 ptp_stopioe = 0;
|
||||||
int32 tti_hold = 0; /* tti hold buf */
|
int32 tti_hold = 0; /* tti hold buf */
|
||||||
int32 tty_buf = 0; /* tty buffer */
|
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 PF, IO, PC, TA;
|
||||||
extern int32 M[];
|
extern int32 M[];
|
||||||
|
|
||||||
|
int ptr_get_ascii (UNIT *uptr);
|
||||||
t_stat ptr_svc (UNIT *uptr);
|
t_stat ptr_svc (UNIT *uptr);
|
||||||
t_stat ptp_svc (UNIT *uptr);
|
t_stat ptp_svc (UNIT *uptr);
|
||||||
t_stat tti_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 ptp_reset (DEVICE *dptr);
|
||||||
t_stat tty_reset (DEVICE *dptr);
|
t_stat tty_reset (DEVICE *dptr);
|
||||||
t_stat ptr_boot (int32 unitno, DEVICE *dptr);
|
t_stat ptr_boot (int32 unitno, DEVICE *dptr);
|
||||||
|
t_stat ptr_attach (UNIT *uptr, char *cptr);
|
||||||
|
|
||||||
/* Character translation tables */
|
/* Character translation tables */
|
||||||
|
|
||||||
|
@ -128,20 +141,28 @@ UNIT ptr_unit = {
|
||||||
|
|
||||||
REG ptr_reg[] = {
|
REG ptr_reg[] = {
|
||||||
{ ORDATA (BUF, ptr_unit.buf, 18) },
|
{ ORDATA (BUF, ptr_unit.buf, 18) },
|
||||||
|
{ FLDATA (UC, ptr_uc, UC_V) },
|
||||||
{ FLDATA (DONE, iosta, IOS_V_PTR) },
|
{ FLDATA (DONE, iosta, IOS_V_PTR) },
|
||||||
{ FLDATA (RPLS, cpls, CPLS_V_PTR) },
|
{ FLDATA (RPLS, cpls, CPLS_V_PTR) },
|
||||||
|
{ ORDATA (HOLD, ptr_hold, 9), REG_HRO },
|
||||||
{ ORDATA (STATE, ptr_state, 5), REG_HRO },
|
{ ORDATA (STATE, ptr_state, 5), REG_HRO },
|
||||||
{ FLDATA (WAIT, ptr_wait, 0), REG_HRO },
|
{ FLDATA (WAIT, ptr_wait, 0), REG_HRO },
|
||||||
{ DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },
|
{ DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },
|
||||||
{ DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT },
|
{ DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT },
|
||||||
|
{ DRDATA (LEADER, ptr_leader, 6), REG_HRO },
|
||||||
{ FLDATA (STOP_IOE, ptr_stopioe, 0) },
|
{ FLDATA (STOP_IOE, ptr_stopioe, 0) },
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
|
MTAB ptr_mod[] = {
|
||||||
|
{ UNIT_ASCII, UNIT_ASCII, "ASCII", "ASCII", NULL },
|
||||||
|
{ UNIT_ASCII, 0, "FIODEC", "FIODEC", NULL },
|
||||||
|
{ 0 } };
|
||||||
|
|
||||||
DEVICE ptr_dev = {
|
DEVICE ptr_dev = {
|
||||||
"PTR", &ptr_unit, ptr_reg, NULL,
|
"PTR", &ptr_unit, ptr_reg, ptr_mod,
|
||||||
1, 10, 31, 1, 8, 8,
|
1, 10, 31, 1, 8, 8,
|
||||||
NULL, NULL, &ptr_reset,
|
NULL, NULL, &ptr_reset,
|
||||||
&ptr_boot, NULL, NULL,
|
&ptr_boot, &ptr_attach, NULL,
|
||||||
NULL, 0 };
|
NULL, 0 };
|
||||||
|
|
||||||
/* PTP data structures
|
/* PTP data structures
|
||||||
|
@ -179,7 +200,7 @@ DEVICE ptp_dev = {
|
||||||
|
|
||||||
UNIT tty_unit[] = {
|
UNIT tty_unit[] = {
|
||||||
{ UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT },
|
{ 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[] = {
|
REG tty_reg[] = {
|
||||||
{ ORDATA (BUF, tty_buf, 6) },
|
{ ORDATA (BUF, tty_buf, 6) },
|
||||||
|
@ -240,35 +261,74 @@ t_stat ptr_svc (UNIT *uptr)
|
||||||
{
|
{
|
||||||
int32 temp;
|
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 (ptr_wait) ptr_wait = ioh = 0; /* if wait, clr ioh */
|
||||||
if ((cpls & CPLS_PTR) || ptr_stopioe) return SCPE_UNATT;
|
if ((cpls & CPLS_PTR) || ptr_stopioe) return SCPE_UNATT;
|
||||||
return SCPE_OK; }
|
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 (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");
|
if ((cpls & CPLS_PTR) || ptr_stopioe) printf ("PTR end of file\n");
|
||||||
else return SCPE_OK; }
|
else return SCPE_OK; }
|
||||||
else perror ("PTR I/O error");
|
else perror ("PTR I/O error");
|
||||||
clearerr (ptr_unit.fileref);
|
clearerr (uptr->fileref);
|
||||||
return SCPE_IOERR; }
|
return SCPE_IOERR; }
|
||||||
ptr_unit.pos = ptr_unit.pos + 1;
|
if (ptr_state == 0) uptr->buf = temp & 0377; /* alpha */
|
||||||
if (ptr_state == 0) ptr_unit.buf = temp & 0377; /* alpha */
|
|
||||||
else if (temp & 0200) { /* binary */
|
else if (temp & 0200) { /* binary */
|
||||||
ptr_state = ptr_state - 6;
|
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 (ptr_state == 0) { /* done? */
|
||||||
if (cpls & CPLS_PTR) { /* completion pulse? */
|
if (cpls & CPLS_PTR) { /* completion pulse? */
|
||||||
iosta = iosta & ~IOS_PTR; /* clear flag */
|
iosta = iosta & ~IOS_PTR; /* clear flag */
|
||||||
IO = ptr_unit.buf; /* fill IO */
|
IO = uptr->buf; /* fill IO */
|
||||||
ios = 1; /* restart */
|
ios = 1; /* restart */
|
||||||
cpls = cpls & ~CPLS_PTR; }
|
cpls = cpls & ~CPLS_PTR; }
|
||||||
else { /* no, interrupt */
|
else { /* no, interrupt */
|
||||||
iosta = iosta | IOS_PTR; /* set flag */
|
iosta = iosta | IOS_PTR; /* set flag */
|
||||||
sbs = sbs | SB_RQ; } } /* req seq break */
|
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;
|
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 */
|
/* Reset routine */
|
||||||
|
|
||||||
|
@ -276,6 +336,8 @@ t_stat ptr_reset (DEVICE *dptr)
|
||||||
{
|
{
|
||||||
ptr_state = 0; /* clear state */
|
ptr_state = 0; /* clear state */
|
||||||
ptr_wait = 0;
|
ptr_wait = 0;
|
||||||
|
ptr_hold = 0;
|
||||||
|
ptr_uc = 0;
|
||||||
ptr_unit.buf = 0;
|
ptr_unit.buf = 0;
|
||||||
cpls = cpls & ~CPLS_PTR;
|
cpls = cpls & ~CPLS_PTR;
|
||||||
iosta = iosta & ~IOS_PTR; /* clear flag */
|
iosta = iosta & ~IOS_PTR; /* clear flag */
|
||||||
|
@ -283,6 +345,14 @@ sim_cancel (&ptr_unit); /* deactivate unit */
|
||||||
return SCPE_OK;
|
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 */
|
/* Bootstrap routine */
|
||||||
|
|
||||||
int32 ptr_getw (UNIT *uptr)
|
int32 ptr_getw (UNIT *uptr)
|
||||||
|
@ -341,13 +411,13 @@ if (cpls & CPLS_PTP) { /* completion pulse? */
|
||||||
cpls = cpls & ~CPLS_PTP; }
|
cpls = cpls & ~CPLS_PTP; }
|
||||||
iosta = iosta | IOS_PTP; /* set flag */
|
iosta = iosta | IOS_PTP; /* set flag */
|
||||||
sbs = sbs | SB_RQ; /* req seq break */
|
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);
|
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");
|
perror ("PTP I/O error");
|
||||||
clearerr (ptp_unit.fileref);
|
clearerr (uptr->fileref);
|
||||||
return SCPE_IOERR; }
|
return SCPE_IOERR; }
|
||||||
ptp_unit.pos = ptp_unit.pos + 1;
|
uptr->pos = uptr->pos + 1;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,24 +487,22 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat tto_svc (UNIT *uptr)
|
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? */
|
if (cpls & CPLS_TTO) { /* completion pulse? */
|
||||||
ios = 1; /* restart */
|
ios = 1; /* restart */
|
||||||
cpls = cpls & ~CPLS_TTO; }
|
cpls = cpls & ~CPLS_TTO; }
|
||||||
iosta = iosta | IOS_TTO; /* set flag */
|
iosta = iosta | IOS_TTO; /* set flag */
|
||||||
sbs = sbs | SB_RQ; /* req seq break */
|
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;
|
uptr->pos = uptr->pos + 1;
|
||||||
if (out == '\r') { /* cr? add lf */
|
if (c == '\r') { /* cr? add lf */
|
||||||
sim_putchar ('\n');
|
sim_putchar ('\n');
|
||||||
uptr->pos = uptr->pos + 1; }
|
uptr->pos = uptr->pos + 1; }
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
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
|
01-Sep-03 RMS Added support for loading in multiple fields
|
||||||
22-Jul-03 RMS Updated for "hardware" RIM loader
|
22-Jul-03 RMS Updated for "hardware" RIM loader
|
||||||
05-Dec-02 RMS Added drum support
|
05-Dec-02 RMS Added drum support
|
||||||
|
@ -48,6 +50,7 @@ extern DEVICE tty_dev;
|
||||||
extern DEVICE lpt_dev;
|
extern DEVICE lpt_dev;
|
||||||
extern DEVICE dt_dev;
|
extern DEVICE dt_dev;
|
||||||
extern DEVICE drm_dev;
|
extern DEVICE drm_dev;
|
||||||
|
extern DEVICE drp_dev;
|
||||||
extern UNIT cpu_unit;
|
extern UNIT cpu_unit;
|
||||||
extern REG cpu_reg[];
|
extern REG cpu_reg[];
|
||||||
extern int32 M[];
|
extern int32 M[];
|
||||||
|
@ -80,6 +83,7 @@ DEVICE *sim_devices[] = {
|
||||||
&lpt_dev,
|
&lpt_dev,
|
||||||
&dt_dev,
|
&dt_dev,
|
||||||
&drm_dev,
|
&drm_dev,
|
||||||
|
&drp_dev,
|
||||||
NULL };
|
NULL };
|
||||||
|
|
||||||
const char *sim_stop_messages[] = {
|
const char *sim_stop_messages[] = {
|
||||||
|
@ -89,11 +93,12 @@ const char *sim_stop_messages[] = {
|
||||||
"Breakpoint",
|
"Breakpoint",
|
||||||
"Nested XCT's",
|
"Nested XCT's",
|
||||||
"Nested indirect addresses",
|
"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 */
|
/* Binary loader - supports both RIM format and Macro block format */
|
||||||
|
|
||||||
int32 getw (FILE *inf)
|
int32 pdp1_getw (FILE *inf)
|
||||||
{
|
{
|
||||||
int32 i, tmp, word;
|
int32 i, tmp, word;
|
||||||
|
|
||||||
|
@ -111,11 +116,11 @@ t_stat rim_load (FILE *inf, int32 fld)
|
||||||
int32 origin, val;
|
int32 origin, val;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if ((val = getw (inf)) < 0) return SCPE_FMT;
|
if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT;
|
||||||
if (((val & 0760000) == OP_DIO) || /* DIO? */
|
if (((val & 0760000) == OP_DIO) || /* DIO? */
|
||||||
((val & 0760000) == OP_DAC)) { /* hack - Macro1 err */
|
((val & 0760000) == OP_DAC)) { /* hack - Macro1 err */
|
||||||
origin = val & DAMASK;
|
origin = val & DAMASK;
|
||||||
if ((val = getw (inf)) < 0) return SCPE_FMT;
|
if ((val = pdp1_getw (inf)) < 0) return SCPE_FMT;
|
||||||
M[fld | origin] = val; }
|
M[fld | origin] = val; }
|
||||||
else if ((val & 0760000) == OP_JMP) { /* JMP? */
|
else if ((val & 0760000) == OP_JMP) { /* JMP? */
|
||||||
PC = fld | (val & DAMASK);
|
PC = fld | (val & DAMASK);
|
||||||
|
@ -130,23 +135,23 @@ t_stat blk_load (FILE *inf, int32 fld)
|
||||||
int32 val, start, count, csum;
|
int32 val, start, count, csum;
|
||||||
|
|
||||||
for (;;) {
|
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? */
|
if ((val & 0760000) == OP_DIO) { /* DIO? */
|
||||||
csum = val; /* init checksum */
|
csum = val; /* init checksum */
|
||||||
start = val & DAMASK; /* starting addr */
|
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;
|
if ((val & 0760000) != OP_DIO) return SCPE_FMT;
|
||||||
csum = csum + val;
|
csum = csum + val;
|
||||||
if (csum > 0777777) csum = (csum + 1) & 0777777;
|
if (csum > 0777777) csum = (csum + 1) & 0777777;
|
||||||
count = (val & DAMASK) - start + 1; /* block count */
|
count = (val & DAMASK) - start + 1; /* block count */
|
||||||
if (count <= 0) return SCPE_FMT;
|
if (count <= 0) return SCPE_FMT;
|
||||||
while (count--) { /* loop on data */
|
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;
|
csum = csum + val;
|
||||||
if (csum > 0777777) csum = (csum + 1) & 0777777;
|
if (csum > 0777777) csum = (csum + 1) & 0777777;
|
||||||
M[fld | start] = val;
|
M[fld | start] = val;
|
||||||
start = (start + 1) & DAMASK; }
|
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; }
|
if (val != csum) return SCPE_CSUM; }
|
||||||
else if ((val & 0760000) == OP_JMP) { /* JMP? */
|
else if ((val & 0760000) == OP_JMP) { /* JMP? */
|
||||||
PC = fld | (val & DAMASK);
|
PC = fld | (val & DAMASK);
|
||||||
|
@ -213,6 +218,9 @@ static const char *opcode[] = {
|
||||||
"LSM", "ESM", "CBS",
|
"LSM", "ESM", "CBS",
|
||||||
"LEM", "EEM", "CKS",
|
"LEM", "EEM", "CKS",
|
||||||
"MSE", "MLC", "MRD", "MWR", "MRS",
|
"MSE", "MLC", "MRD", "MWR", "MRS",
|
||||||
|
"DIA", "DBA", "DWC", "DRA", "DCL",
|
||||||
|
"DRD", "DWR", "DBL", "DCN",
|
||||||
|
"DTD", "DSE", "DSP",
|
||||||
|
|
||||||
"SKP", "SKP I", "CLO",
|
"SKP", "SKP I", "CLO",
|
||||||
"SFT", "LAW", "OPR",
|
"SFT", "LAW", "OPR",
|
||||||
|
@ -265,6 +273,9 @@ static const int32 opc_val[] = {
|
||||||
0720054+I_NPN, 0720055+I_NPN, 0720056+I_NPN,
|
0720054+I_NPN, 0720055+I_NPN, 0720056+I_NPN,
|
||||||
0720074+I_NPN, 0724074+I_NPN, 0720033+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,
|
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,
|
0640000+I_NPN, 0650000+I_NPN, 0651600+I_NPN,
|
||||||
0660000+I_NPN, 0700000+I_LAW, 0760000+I_NPN,
|
0660000+I_NPN, 0700000+I_LAW, 0760000+I_NPN,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* pdp10_defs.h: PDP-10 simulator definitions
|
/* 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
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
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
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
29-Dec-03 RMS Added Q18 definition for PDP11 compatibility
|
||||||
19-May-03 RMS Revised for new conditional compilation scheme
|
19-May-03 RMS Revised for new conditional compilation scheme
|
||||||
09-Jan-03 RMS Added DEUNA/DELUA support
|
09-Jan-03 RMS Added DEUNA/DELUA support
|
||||||
29-Sep-02 RMS Added variable vector, RX211 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_UBUS (DEV_V_UF + 0) /* Unibus */
|
||||||
#define DEV_V_QBUS (DEV_V_UF + 1) /* Qbus */
|
#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_UBUS (1u << DEV_V_UBUS)
|
||||||
#define DEV_QBUS (1u << DEV_V_QBUS)
|
#define DEV_QBUS (1u << DEV_V_QBUS)
|
||||||
|
#define DEV_Q18 (1u << DEV_V_Q18)
|
||||||
#define DEV_FLTA (1u << DEV_V_FLTA)
|
#define DEV_FLTA (1u << DEV_V_FLTA)
|
||||||
|
|
||||||
#define UNIBUS TRUE /* 18b only */
|
#define UNIBUS TRUE /* 18b only */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* pdp10_fe.c: PDP-10 front end (console terminal) simulator
|
/* 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
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
fe KS10 console front end
|
fe KS10 console front end
|
||||||
|
|
||||||
|
29-Dec-03 RMS Added console backpressure support
|
||||||
25-Apr-03 RMS Revised for extended file support
|
25-Apr-03 RMS Revised for extended file support
|
||||||
22-Dec-02 RMS Added break support
|
22-Dec-02 RMS Added break support
|
||||||
30-May-02 RMS Widened COUNT to 32b
|
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? */
|
if (M[FE_CTYOUT] & FE_CVALID) { /* char to print? */
|
||||||
feo_unit.buf = (int32) M[FE_CTYOUT] & 0177; /* pick it up */
|
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;
|
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? */
|
else if ((M[FE_CTYIN] & FE_CVALID) == 0) { /* input char taken? */
|
||||||
sim_cancel (&fei_unit); /* sched immediate */
|
sim_cancel (&fei_unit); /* sched immediate */
|
||||||
sim_activate (&fei_unit, 0); }; /* keyboard poll */
|
sim_activate (&fei_unit, 0); }; /* keyboard poll */
|
||||||
|
@ -119,6 +119,11 @@ return;
|
||||||
|
|
||||||
t_stat feo_svc (UNIT *uptr)
|
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 */
|
M[FE_CTYOUT] = 0; /* clear char */
|
||||||
apr_flg = apr_flg | APRF_CON; /* interrupt KS10 */
|
apr_flg = apr_flg | APRF_CON; /* interrupt KS10 */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* pdp10_lp20.c: PDP-10 LP20 line printer simulator
|
/* 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
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
lp20 line printer
|
lp20 line printer
|
||||||
|
|
||||||
|
29-Dec-03 RMS Fixed bug in scheduling
|
||||||
25-Apr-03 RMS Revised for extended file support
|
25-Apr-03 RMS Revised for extended file support
|
||||||
29-Sep-02 RMS Added variable vector support
|
29-Sep-02 RMS Added variable vector support
|
||||||
Modified to use common Unibus routines
|
Modified to use common Unibus routines
|
||||||
|
@ -283,7 +284,7 @@ case 00: /* LPCSA */
|
||||||
if ((lpcsa & CSA_GO) == 0) { /* not set before? */
|
if ((lpcsa & CSA_GO) == 0) { /* not set before? */
|
||||||
if (lpcsb & CSB_ERR) lpcsb = lpcsb | CSB_GOE;
|
if (lpcsb & CSB_ERR) lpcsb = lpcsb | CSB_GOE;
|
||||||
lpcsum = 0; /* clear checksum */
|
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 */
|
else sim_cancel (&lp20_unit); /* go clr, stop DMA */
|
||||||
lpcsa = (lpcsa & ~CSA_RW) | (data & CSA_RW);
|
lpcsa = (lpcsa & ~CSA_RW) | (data & CSA_RW);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* pdp11_cpu.c: PDP-11 CPU simulator
|
/* 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
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
cpu PDP-11 CPU (J-11 microprocessor)
|
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
|
05-Jun-03 RMS Fixed bugs in memory size table
|
||||||
12-Mar-03 RMS Added logical name support
|
12-Mar-03 RMS Added logical name support
|
||||||
01-Feb-03 RMS Changed R display to follow PSW<rs>, added SP display
|
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 stop_spabort = 1; /* stop on SP abort */
|
||||||
int32 wait_enable = 0; /* wait state enable */
|
int32 wait_enable = 0; /* wait state enable */
|
||||||
int32 cpu_log = 0; /* logging */
|
int32 cpu_log = 0; /* logging */
|
||||||
|
int32 autcon_enb = 1; /* autoconfig enable */
|
||||||
uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
|
uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
|
||||||
int32 pcq_p = 0; /* PC queue ptr */
|
int32 pcq_p = 0; /* PC queue ptr */
|
||||||
REG *pcq_r = NULL; /* PC queue reg ptr */
|
REG *pcq_r = NULL; /* PC queue reg ptr */
|
||||||
|
@ -323,6 +326,8 @@ void set_r_display (int32 rs, int32 cm);
|
||||||
|
|
||||||
extern t_stat build_dib_tab (int32 ubm);
|
extern t_stat build_dib_tab (int32 ubm);
|
||||||
extern t_stat show_iospace (FILE *st, UNIT *uptr, int32 val, void *desc);
|
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 iopageR (int32 *data, uint32 addr, int32 access);
|
||||||
extern t_stat iopageW (int32 data, uint32 addr, int32 access);
|
extern t_stat iopageW (int32 data, uint32 addr, int32 access);
|
||||||
extern int32 calc_ints (int32 nipl, int32 trq);
|
extern int32 calc_ints (int32 nipl, int32 trq);
|
||||||
|
@ -532,6 +537,7 @@ REG cpu_reg[] = {
|
||||||
{ GRDATA (UDPAR7, APRFILE[077], 8, 16, 16) },
|
{ GRDATA (UDPAR7, APRFILE[077], 8, 16, 16) },
|
||||||
{ GRDATA (UDPDR7, APRFILE[077], 8, 16, 0) },
|
{ GRDATA (UDPDR7, APRFILE[077], 8, 16, 0) },
|
||||||
{ BRDATA (UBMAP, ub_map, 8, 22, UBM_LNT_LW) },
|
{ 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 },
|
{ BRDATA (PCQ, pcq, 8, 16, PCQ_SIZE), REG_RO+REG_CIRC },
|
||||||
{ ORDATA (PCQP, pcq_p, 6), REG_HRO },
|
{ ORDATA (PCQP, pcq_p, 6), REG_HRO },
|
||||||
{ ORDATA (WRU, sim_int_char, 8) },
|
{ ORDATA (WRU, sim_int_char, 8) },
|
||||||
|
@ -539,10 +545,10 @@ REG cpu_reg[] = {
|
||||||
{ NULL} };
|
{ NULL} };
|
||||||
|
|
||||||
MTAB cpu_mod[] = {
|
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, "22b Unibus + RH70", "URH70", &cpu_set_bus },
|
||||||
{ UNIT_MAP, UNIT_UBM + UNIT_RH11, "22b Unibus + RH11", "URH11", &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, UNIT_CIS, "CIS", "CIS", NULL },
|
||||||
{ UNIT_CIS, 0, "no CIS", "NOCIS", NULL },
|
{ UNIT_CIS, 0, "no CIS", "NOCIS", NULL },
|
||||||
{ UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size},
|
{ UNIT_MSIZE, 16384, NULL, "16K", &cpu_set_size},
|
||||||
|
@ -566,6 +572,10 @@ MTAB cpu_mod[] = {
|
||||||
{ UNIT_MSIZE, 4186112, NULL, "4M", &cpu_set_size},
|
{ UNIT_MSIZE, 4186112, NULL, "4M", &cpu_set_size},
|
||||||
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "IOSPACE", NULL,
|
{ MTAB_XTD|MTAB_VDV|MTAB_NMO, 0, "IOSPACE", NULL,
|
||||||
NULL, &show_iospace },
|
NULL, &show_iospace },
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 1, "AUTOCONFIG", "AUTOCONFIG",
|
||||||
|
&set_autocon, &show_autocon },
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 0, NULL, "NOAUTOCONFIG",
|
||||||
|
&set_autocon, NULL },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
|
||||||
DEVICE cpu_dev = {
|
DEVICE cpu_dev = {
|
||||||
|
@ -2467,23 +2477,24 @@ for (i = 0; i < clim; i = i + 2) nM[i >> 1] = M[i >> 1];
|
||||||
free (M);
|
free (M);
|
||||||
M = nM;
|
M = nM;
|
||||||
MEMSIZE = val;
|
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 */
|
/* Bus configuration, disable Unibus or Qbus devices */
|
||||||
|
|
||||||
t_stat cpu_set_bus (UNIT *uptr, int32 val, char *cptr, void *desc)
|
t_stat cpu_set_bus (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
{
|
{
|
||||||
DEVICE *dptr;
|
DEVICE *dptr;
|
||||||
uint32 i, target;
|
uint32 i, mask;
|
||||||
|
|
||||||
if ((MEMSIZE <= UNIMEMSIZE) || (val & UNIT_18B) ||
|
if ((val & UNIT_MAP) || (val & UNIT_18B)) /* Unibus variant? */
|
||||||
(!(val & 1) && ((uint32) val == (cpu_unit.flags & UNIT_MAP)))) return SCPE_OK;
|
mask = DEV_UBUS;
|
||||||
if (val & UNIT_MAP) target = DEV_QBUS; /* going to Ubus? */
|
else if (MEMSIZE <= UNIMEMSIZE) /* 18b Qbus? */
|
||||||
else target = DEV_UBUS; /* going to Qbus */
|
mask = DEV_QBUS | DEV_Q18;
|
||||||
|
else mask = DEV_QBUS; /* must be 22b */
|
||||||
for (i = 0; (dptr = sim_devices[i]) != NULL; i++) {
|
for (i = 0; (dptr = sim_devices[i]) != NULL; i++) {
|
||||||
if ((dptr->flags & DEV_DISABLE) && /* disable-able? */
|
if ((dptr->flags & DEV_DISABLE) && /* disable-able? */
|
||||||
!(dptr->flags & DEV_DIS) && /* enabled? */
|
!(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));
|
printf ("Disabling %s\n", sim_dname (dptr));
|
||||||
if (sim_log) fprintf (sim_log, "Disabling %s\n", sim_dname (dptr));
|
if (sim_log) fprintf (sim_log, "Disabling %s\n", sim_dname (dptr));
|
||||||
dptr->flags = dptr->flags | DEV_DIS; } }
|
dptr->flags = dptr->flags | DEV_DIS; } }
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
The author gratefully acknowledges the help of Max Burnet, Megan Gentry,
|
The author gratefully acknowledges the help of Max Burnet, Megan Gentry,
|
||||||
and John Wilson in resolving questions about the PDP-11
|
and John Wilson in resolving questions about the PDP-11
|
||||||
|
|
||||||
|
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
|
19-May-03 RMS Revised for new conditional compilation
|
||||||
05-Apr-03 RMS Fixed bug in MMR1 update (found by Tim Stark)
|
05-Apr-03 RMS Fixed bug in MMR1 update (found by Tim Stark)
|
||||||
28-Feb-03 RMS Added TM logging support
|
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_SPABORT (TRAP_V_MAX + 5) /* abort trap push */
|
||||||
#define STOP_RQ (TRAP_V_MAX + 6) /* RQDX3 panic */
|
#define STOP_RQ (TRAP_V_MAX + 6) /* RQDX3 panic */
|
||||||
#define STOP_SANITY (TRAP_V_MAX + 7) /* sanity timer exp */
|
#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 */
|
#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* cond error return */
|
||||||
|
|
||||||
/* Timers */
|
/* Timers */
|
||||||
|
@ -312,9 +315,11 @@ typedef struct fpac fpac_t;
|
||||||
|
|
||||||
#define DEV_V_UBUS (DEV_V_UF + 0) /* Unibus */
|
#define DEV_V_UBUS (DEV_V_UF + 0) /* Unibus */
|
||||||
#define DEV_V_QBUS (DEV_V_UF + 1) /* Qbus */
|
#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_UBUS (1u << DEV_V_UBUS)
|
||||||
#define DEV_QBUS (1u << DEV_V_QBUS)
|
#define DEV_QBUS (1u << DEV_V_QBUS)
|
||||||
|
#define DEV_Q18 (1u << DEV_V_Q18)
|
||||||
#define DEV_FLTA (1u << DEV_V_FLTA)
|
#define DEV_FLTA (1u << DEV_V_FLTA)
|
||||||
|
|
||||||
#define UNIBUS (cpu_18b || cpu_ubm) /* T if 18b */
|
#define UNIBUS (cpu_18b || cpu_ubm) /* T if 18b */
|
||||||
|
@ -341,10 +346,12 @@ struct pdp_dib {
|
||||||
|
|
||||||
typedef struct pdp_dib 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 IOBA_DZ (IOPAGEBASE + 000100) /* DZ11 */
|
||||||
#define IOLN_DZ 010
|
#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 IOBA_RQB (IOPAGEBASE + 000334 + (020 * (DZ_MUXES / 2)))
|
||||||
#define IOLN_RQB 004
|
#define IOLN_RQB 004
|
||||||
#define IOBA_RQC (IOPAGEBASE + IOBA_RQB + IOLN_RQB)
|
#define IOBA_RQC (IOPAGEBASE + IOBA_RQB + IOLN_RQB)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
To: Users
|
To: Users
|
||||||
From: Bob Supnik
|
From: Bob Supnik
|
||||||
Subj: PDP-11 Simulator Usage
|
Subj: PDP-11 Simulator Usage
|
||||||
Date: 15-Sep-2003
|
Date: 15-Dec-2003
|
||||||
|
|
||||||
COPYRIGHT NOTICE
|
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
|
- trap condition 'n' occurs, and register STOP_TRAP<n> is set
|
||||||
- wait state entered, and no I/O operations outstanding
|
- wait state entered, and no I/O operations outstanding
|
||||||
(ie, no interrupt can ever occur)
|
(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
|
The PDP-11 loader supports standard binary format tapes. The DUMP command
|
||||||
is not implemented.
|
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,
|
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
|
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
|
changed. Explicitly setting the I/O address of a device which normally
|
||||||
uses autoconfiguration DISABLES autoconfiguration for that device. As
|
uses autoconfiguration DISABLES autoconfiguration for that device and for
|
||||||
a consequence, the user may have to manually configure all other
|
the entire system. As a consequence, the user may have to manually configure
|
||||||
autoconfigured devices, because the autoconfiguration algorithm no
|
all other autoconfigured devices, because the autoconfiguration algorithm
|
||||||
longer recognizes the explicitly configured device. A device can be
|
no longer recognizes the explicitly configured device. A device can be
|
||||||
reset to autoconfigure with the SET <device> AUTOCONFIGURE command.
|
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.
|
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 (*).
|
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
|
IE 1 interrupt enable flag
|
||||||
CTIME 31 time to complete transport stop
|
CTIME 31 time to complete transport stop
|
||||||
LTIME 31 time between lines
|
LTIME 31 time between lines
|
||||||
ACTIME 31 time to accelerate to full speed
|
|
||||||
DCTIME 31 time to decelerate to a full stop
|
DCTIME 31 time to decelerate to a full stop
|
||||||
SUBSTATE 2 read/write command substate
|
SUBSTATE 2 read/write command substate
|
||||||
POS[0:7] 32 position, in lines, units 0-7
|
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.
|
operate correctly.
|
||||||
|
|
||||||
- LTIME must be at least 6
|
- LTIME must be at least 6
|
||||||
- ACTIME must be less than DCTIME, and both need to be at
|
- DCTIME needs to be at least 100 times LTIME
|
||||||
least 100 times LTIME
|
|
||||||
|
Acceleration time is set to 75% of deceleration time.
|
||||||
|
|
||||||
2.9 Magnetic Tape Controllers
|
2.9 Magnetic Tape Controllers
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
hk RK611/RK06/RK07 disk
|
hk RK611/RK06/RK07 disk
|
||||||
|
|
||||||
|
29-Dec-03 RMS Added 18b Qbus support
|
||||||
25-Apr-03 RMS Revised for extended file support
|
25-Apr-03 RMS Revised for extended file support
|
||||||
|
|
||||||
This is a somewhat abstracted implementation of the RK611, more closely
|
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,
|
HK_NUMDR, HK_RDX, 24, 1, HK_RDX, HK_WID,
|
||||||
NULL, NULL, &hk_reset,
|
NULL, NULL, &hk_reset,
|
||||||
&hk_boot, &hk_attach, &hk_detach,
|
&hk_boot, &hk_attach, &hk_detach,
|
||||||
&hk_dib, DEV_DISABLE | DEV_UBUS };
|
&hk_dib, DEV_DISABLE | DEV_UBUS | DEV_Q18 };
|
||||||
|
|
||||||
/* I/O dispatch routines, I/O addresses 17777440 - 17777476 */
|
/* 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
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
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
|
12-Mar-03 RMS Added logical name support
|
||||||
08-Oct-02 RMS Trimmed I/O bus addresses
|
08-Oct-02 RMS Trimmed I/O bus addresses
|
||||||
Added support for dynamic tables
|
Added support for dynamic tables
|
||||||
|
@ -43,6 +45,7 @@ extern UNIT cpu_unit;
|
||||||
extern int32 cpu_bme, cpu_18b, cpu_ubm;
|
extern int32 cpu_bme, cpu_18b, cpu_ubm;
|
||||||
extern int32 trap_req, ipl;
|
extern int32 trap_req, ipl;
|
||||||
extern int32 cpu_log;
|
extern int32 cpu_log;
|
||||||
|
extern int32 autcon_enb;
|
||||||
extern FILE *sim_log;
|
extern FILE *sim_log;
|
||||||
extern DEVICE *sim_devices[];
|
extern DEVICE *sim_devices[];
|
||||||
|
|
||||||
|
@ -297,6 +300,24 @@ else { /* physical */
|
||||||
return (lim - alim); }
|
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 */
|
/* Change device address */
|
||||||
|
|
||||||
t_stat set_addr (UNIT *uptr, int32 val, char *cptr, void *desc)
|
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 */
|
(newba % ((uint32) val))) return SCPE_ARG; /* check modulus */
|
||||||
dibp->ba = newba; /* store */
|
dibp->ba = newba; /* store */
|
||||||
dptr->flags = dptr->flags & ~DEV_FLTA; /* not floating */
|
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 */
|
/* Show device address */
|
||||||
|
@ -374,6 +396,8 @@ if ((r != SCPE_OK) || (newvec <= VEC_Q) ||
|
||||||
((newvec + (dibp->vnum * 4)) >= (VEC_Q + 01000)) ||
|
((newvec + (dibp->vnum * 4)) >= (VEC_Q + 01000)) ||
|
||||||
(newvec & ((dibp->vnum > 1)? 07: 03))) return SCPE_ARG;
|
(newvec & ((dibp->vnum > 1)? 07: 03))) return SCPE_ARG;
|
||||||
dibp->vec = newvec;
|
dibp->vec = newvec;
|
||||||
|
dptr->flags = dptr->flags & ~DEV_FLTA; /* not floating */
|
||||||
|
autcon_enb = 0; /* autoconfig off */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,14 +451,20 @@ return FALSE;
|
||||||
|
|
||||||
/* Build interrupt tables */
|
/* 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 ilvl = vloc / 32;
|
||||||
int32 ibit = vloc % 32;
|
int32 ibit = vloc % 32;
|
||||||
|
|
||||||
if (iack != NULL) int_ack[ilvl][ibit] = iack;
|
if (iack != NULL) {
|
||||||
else int_vec[ilvl][ibit] = ivec;
|
if (int_ack[ilvl][ibit] &&
|
||||||
return;
|
(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 */
|
/* 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 */
|
dibp = (DIB *) dptr->ctxt; /* get DIB */
|
||||||
if (dibp && !(dptr->flags & DEV_DIS)) { /* defined, enabled? */
|
if (dibp && !(dptr->flags & DEV_DIS)) { /* defined, enabled? */
|
||||||
if (dibp->vnum > VEC_DEVMAX) return SCPE_IERR;
|
if (dibp->vnum > VEC_DEVMAX) return SCPE_IERR;
|
||||||
for (k = 0; k < dibp->vnum; k++) /* loop thru vec */
|
for (k = 0; k < dibp->vnum; k++) { /* loop thru vec */
|
||||||
build_int_vec (dibp->vloc + k, /* add vector */
|
if (build_int_vec (dibp->vloc + k, /* add vector */
|
||||||
dibp->vec + (k * 4), dibp->ack[k]);
|
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? */
|
if (dibp->lnt != 0) { /* I/O addresses? */
|
||||||
dib_tab[j++] = dibp; /* add DIB to dib_tab */
|
dib_tab[j++] = dibp; /* add DIB to dib_tab */
|
||||||
if (j >= DIB_MAX) return SCPE_IERR; } /* too many? */
|
if (j >= DIB_MAX) return SCPE_IERR; } /* too many? */
|
||||||
|
@ -575,6 +611,7 @@ DIB *dibp;
|
||||||
int32 i, j, k;
|
int32 i, j, k;
|
||||||
extern DEVICE *find_dev (char *ptr);
|
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_LNT) return SCPE_IERR; /* legal rank? */
|
||||||
if (rank) auto_tab[rank - 1].num = nctrl; /* update num? */
|
if (rank) auto_tab[rank - 1].num = nctrl; /* update num? */
|
||||||
for (i = 0, autp = auto_tab; i < AUTO_LNT; i++) { /* loop thru table */
|
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
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
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
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
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
|
29-Sep-02 RMS Added variable address support to bootstrap
|
||||||
Added vector change/display support
|
Added vector change/display support
|
||||||
Revised mapping mnemonics
|
Revised mapping mnemonics
|
||||||
|
@ -261,7 +262,7 @@ DEVICE rk_dev = {
|
||||||
RK_NUMDR, 8, 24, 1, 8, 16,
|
RK_NUMDR, 8, 24, 1, 8, 16,
|
||||||
NULL, NULL, &rk_reset,
|
NULL, NULL, &rk_reset,
|
||||||
&rk_boot, NULL, NULL,
|
&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
|
/* I/O dispatch routine, I/O addresses 17777400 - 17777416
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
|
|
||||||
rq RQDX3 disk controller
|
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)
|
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
|
19-May-03 RMS Revised for new conditional compilation scheme
|
||||||
25-Apr-03 RMS Revised for extended file support
|
25-Apr-03 RMS Revised for extended file support
|
||||||
|
@ -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 dtyp = GET_DTYPE (uptr->flags); /* get drive type */
|
||||||
uint32 lbn = GETP32 (pkt, RW_LBNL); /* get lbn */
|
uint32 lbn = GETP32 (pkt, RW_LBNL); /* get lbn */
|
||||||
uint32 bc = GETP32 (pkt, RW_BCL); /* get byte cnt */
|
uint32 bc = GETP32 (pkt, RW_BCL); /* get byte cnt */
|
||||||
uint32 maxlbn = 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? */
|
if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */
|
||||||
return (ST_OFL | SB_OFL_NV); /* offl no vol */
|
return (ST_OFL | SB_OFL_NV); /* offl no vol */
|
||||||
|
@ -1866,6 +1869,7 @@ return;
|
||||||
void rq_putr_unit (MSC *cp, int32 pkt, UNIT *uptr, uint32 lu, t_bool all)
|
void rq_putr_unit (MSC *cp, int32 pkt, UNIT *uptr, uint32 lu, t_bool all)
|
||||||
{
|
{
|
||||||
uint32 dtyp = GET_DTYPE (uptr->flags); /* get drive type */
|
uint32 dtyp = GET_DTYPE (uptr->flags); /* get drive type */
|
||||||
|
uint32 maxlbn = uptr->capac / RQ_NUMBY; /* get max lbn */
|
||||||
|
|
||||||
cp->pak[pkt].d[ONL_MLUN] = lu; /* unit */
|
cp->pak[pkt].d[ONL_MLUN] = lu; /* unit */
|
||||||
cp->pak[pkt].d[ONL_UFL] = uptr->uf | UF_RPL | RQ_WPH (uptr) | RQ_RMV (uptr);
|
cp->pak[pkt].d[ONL_UFL] = uptr->uf | UF_RPL | RQ_WPH (uptr) | RQ_RMV (uptr);
|
||||||
|
@ -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 */
|
(drv_tab[dtyp].mod << ONL_UIDD_V_MOD); /* UID hi */
|
||||||
PUTP32 (pkt, ONL_MEDL, drv_tab[dtyp].med); /* media type */
|
PUTP32 (pkt, ONL_MEDL, drv_tab[dtyp].med); /* media type */
|
||||||
if (all) { /* if long form */
|
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_VSNL] = 01234 + lu; /* vol serial # */
|
||||||
cp->pak[pkt].d[ONL_VSNH] = 0; }
|
cp->pak[pkt].d[ONL_VSNH] = 0; }
|
||||||
return;
|
return;
|
||||||
|
@ -2012,13 +2016,13 @@ if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
|
||||||
if (cptr) {
|
if (cptr) {
|
||||||
cap = (int32) get_uint (cptr, 10, max, &r);
|
cap = (int32) get_uint (cptr, 10, max, &r);
|
||||||
if ((r != SCPE_OK) || (cap < RA8U_MINC)) return SCPE_ARG;
|
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->flags = (uptr->flags & ~UNIT_DTYPE) | (val << UNIT_V_DTYPE);
|
||||||
uptr->capac = ((t_addr) drv_tab[val].lbn) * RQ_NUMBY;
|
uptr->capac = ((t_addr) drv_tab[val].lbn) * RQ_NUMBY;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Show unit type (and capacity if user defined) */
|
/* Show unit type */
|
||||||
|
|
||||||
t_stat rq_show_type (FILE *st, UNIT *uptr, int32 val, void *desc)
|
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];
|
MSC *cp = rq_ctxmap[uptr->cnum];
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
uptr->capac = drv_tab[dtyp].lbn * RQ_NUMBY;
|
|
||||||
r = attach_unit (uptr, cptr);
|
r = attach_unit (uptr, cptr);
|
||||||
if (r != SCPE_OK) return r;
|
if (r != SCPE_OK) return r;
|
||||||
if (cp->csta == CST_UP) uptr->flags = uptr->flags | UNIT_ATP;
|
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_swait = 10; /* seek, per track */
|
||||||
int32 rx_xwait = 1; /* tr set time */
|
int32 rx_xwait = 1; /* tr set time */
|
||||||
uint8 rx_buf[RX_NUMBY] = { 0 }; /* sector buffer */
|
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 */
|
int32 rx_enb = 1; /* device enable */
|
||||||
|
|
||||||
DEVICE rx_dev;
|
DEVICE rx_dev;
|
||||||
|
@ -157,7 +157,7 @@ REG rx_reg[] = {
|
||||||
{ ORDATA (RXTA, rx_track, 8) },
|
{ ORDATA (RXTA, rx_track, 8) },
|
||||||
{ ORDATA (RXSA, rx_sector, 8) },
|
{ ORDATA (RXSA, rx_sector, 8) },
|
||||||
{ DRDATA (STAPTR, rx_state, 3), REG_RO },
|
{ DRDATA (STAPTR, rx_state, 3), REG_RO },
|
||||||
{ DRDATA (BUFPTR, bptr, 7) },
|
{ DRDATA (BUFPTR, rx_bptr, 7) },
|
||||||
{ FLDATA (INT, IREQ (RX), INT_V_RX) },
|
{ FLDATA (INT, IREQ (RX), INT_V_RX) },
|
||||||
{ FLDATA (ERR, rx_csr, RXCS_V_ERR) },
|
{ FLDATA (ERR, rx_csr, RXCS_V_ERR) },
|
||||||
{ FLDATA (TR, rx_csr, RXCS_V_TR) },
|
{ FLDATA (TR, rx_csr, RXCS_V_TR) },
|
||||||
|
@ -237,7 +237,7 @@ case 0: /* RXCS */
|
||||||
if ((data & CSR_GO) && (rx_state == IDLE)) { /* new function? */
|
if ((data & CSR_GO) && (rx_state == IDLE)) { /* new function? */
|
||||||
rx_csr = data & (RXCS_IE + RXCS_DRV + RXCS_FUNC);
|
rx_csr = data & (RXCS_IE + RXCS_DRV + RXCS_FUNC);
|
||||||
drv = ((rx_csr & RXCS_DRV)? 1: 0); /* reselect drive */
|
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 */
|
switch (RXCS_GETFNC (data)) { /* case on func */
|
||||||
case RXCS_FILL:
|
case RXCS_FILL:
|
||||||
rx_state = FILL; /* state = fill */
|
rx_state = FILL; /* state = fill */
|
||||||
|
@ -287,10 +287,10 @@ return SCPE_OK;
|
||||||
RWDS Save sector, set TR, set RWDT
|
RWDS Save sector, set TR, set RWDT
|
||||||
RWDT Save track, set RWXFR
|
RWDT Save track, set RWXFR
|
||||||
RWXFR Read/write buffer
|
RWXFR Read/write buffer
|
||||||
FILL copy ir to rx_buf[bptr], advance ptr
|
FILL copy ir to rx_buf[rx_bptr], advance ptr
|
||||||
if bptr > max, finish command, else set tr
|
if rx_bptr > max, finish command, else set tr
|
||||||
EMPTY if bptr > max, finish command, else
|
EMPTY if rx_bptr > max, finish command, else
|
||||||
copy rx_buf[bptr] to ir, advance ptr, set tr
|
copy rx_buf[rx_bptr] to ir, advance ptr, set tr
|
||||||
CMD_COMPLETE copy requested data to ir, finish command
|
CMD_COMPLETE copy requested data to ir, finish command
|
||||||
INIT_COMPLETE read drive 0, track 1, sector 1 to buffer, 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;
|
int32 i, func;
|
||||||
uint32 da;
|
uint32 da;
|
||||||
|
int8 *fbuf = uptr->filebuf;
|
||||||
|
|
||||||
func = RXCS_GETFNC (rx_csr); /* get function */
|
func = RXCS_GETFNC (rx_csr); /* get function */
|
||||||
switch (rx_state) { /* case on state */
|
switch (rx_state) { /* case on state */
|
||||||
|
@ -310,17 +311,17 @@ case IDLE: /* idle */
|
||||||
return SCPE_IERR; /* done */
|
return SCPE_IERR; /* done */
|
||||||
|
|
||||||
case EMPTY: /* empty buffer */
|
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 {
|
else {
|
||||||
rx_dbr = rx_buf[bptr]; /* get next */
|
rx_dbr = rx_buf[rx_bptr]; /* get next */
|
||||||
bptr = bptr + 1;
|
rx_bptr = rx_bptr + 1;
|
||||||
rx_csr = rx_csr | RXCS_TR; } /* set xfer */
|
rx_csr = rx_csr | RXCS_TR; } /* set xfer */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FILL: /* fill buffer */
|
case FILL: /* fill buffer */
|
||||||
rx_buf[bptr] = rx_dbr; /* write next */
|
rx_buf[rx_bptr] = rx_dbr; /* write next */
|
||||||
bptr = bptr + 1;
|
rx_bptr = rx_bptr + 1;
|
||||||
if (bptr < RX_NUMBY) rx_csr = rx_csr | RXCS_TR; /* if more, set xfer */
|
if (rx_bptr < RX_NUMBY) rx_csr = rx_csr | RXCS_TR; /* more? set xfer */
|
||||||
else rx_done (0, 0); /* else done */
|
else rx_done (0, 0); /* else done */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -350,13 +351,13 @@ case RWXFR:
|
||||||
if (func == RXCS_WRDEL) rx_esr = rx_esr | RXES_DD; /* del data? */
|
if (func == RXCS_WRDEL) rx_esr = rx_esr | RXES_DD; /* del data? */
|
||||||
if (func == RXCS_READ) { /* read? */
|
if (func == RXCS_READ) { /* read? */
|
||||||
for (i = 0; i < RX_NUMBY; i++)
|
for (i = 0; i < RX_NUMBY; i++)
|
||||||
rx_buf[i] = *(((int8 *) uptr->filebuf) + da + i); }
|
rx_buf[i] = fbuf[da + i]; }
|
||||||
else {
|
else {
|
||||||
if (uptr->flags & UNIT_WPRT) { /* write and locked? */
|
if (uptr->flags & UNIT_WPRT) { /* write and locked? */
|
||||||
rx_done (RXES_WLK, 0100); /* done, error */
|
rx_done (RXES_WLK, 0100); /* done, error */
|
||||||
break; }
|
break; }
|
||||||
for (i = 0; i < RX_NUMBY; i++) /* write */
|
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;
|
da = da + RX_NUMBY;
|
||||||
if (da > uptr->hwmark) uptr->hwmark = da; }
|
if (da > uptr->hwmark) uptr->hwmark = da; }
|
||||||
rx_done (0, 0); /* done */
|
rx_done (0, 0); /* done */
|
||||||
|
@ -377,7 +378,7 @@ case INIT_COMPLETE: /* init complete */
|
||||||
break; }
|
break; }
|
||||||
da = CALC_DA (1, 1); /* track 1, sector 1 */
|
da = CALC_DA (1, 1); /* track 1, sector 1 */
|
||||||
for (i = 0; i < RX_NUMBY; i++) /* read sector */
|
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 */
|
rx_done (RXES_ID, 0); /* set done */
|
||||||
if ((rx_unit[1].flags & UNIT_ATT) == 0) rx_ecode = 0020;
|
if ((rx_unit[1].flags & UNIT_ATT) == 0) rx_ecode = 0020;
|
||||||
break; } /* end case state */
|
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
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
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
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
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
|
19-May-03 RMS Revised for new conditional compilation scheme
|
||||||
25-Apr-03 RMS Revised for extended file support
|
25-Apr-03 RMS Revised for extended file support
|
||||||
14-Mar-03 RMS Fixed variable size interaction with save/restore
|
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_swait = 10; /* seek, per track */
|
||||||
int32 ry_xwait = 1; /* tr set time */
|
int32 ry_xwait = 1; /* tr set time */
|
||||||
uint8 rx2xb[RY_NUMBY] = { 0 }; /* sector buffer */
|
uint8 rx2xb[RY_NUMBY] = { 0 }; /* sector buffer */
|
||||||
int32 ry_enb = 0; /* device enable */
|
|
||||||
|
|
||||||
DEVICE ry_dev;
|
DEVICE ry_dev;
|
||||||
t_stat ry_rd (int32 *data, int32 PA, int32 access);
|
t_stat ry_rd (int32 *data, int32 PA, int32 access);
|
||||||
|
@ -227,7 +227,7 @@ DEVICE ry_dev = {
|
||||||
RX_NUMDR, 8, 20, 1, 8, 8,
|
RX_NUMDR, 8, 20, 1, 8, 8,
|
||||||
NULL, NULL, &ry_reset,
|
NULL, NULL, &ry_reset,
|
||||||
&ry_boot, &ry_attach, NULL,
|
&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
|
/* I/O dispatch routine, I/O addresses 17777170 - 17777172
|
||||||
|
|
||||||
|
@ -341,6 +341,7 @@ t_stat ry_svc (UNIT *uptr)
|
||||||
int32 i, t, func, bps;
|
int32 i, t, func, bps;
|
||||||
static uint8 estat[8];
|
static uint8 estat[8];
|
||||||
uint32 ba, da;
|
uint32 ba, da;
|
||||||
|
int8 *fbuf = uptr->filebuf;
|
||||||
|
|
||||||
func = RYCS_GETFNC (ry_csr); /* get function */
|
func = RYCS_GETFNC (ry_csr); /* get function */
|
||||||
bps = (ry_csr & RYCS_DEN)? RY_NUMBY: RX_NUMBY; /* get sector size */
|
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_WRDEL) ry_esr = ry_esr | RYES_DD; /* del data? */
|
||||||
if (func == RYCS_READ) { /* read? */
|
if (func == RYCS_READ) { /* read? */
|
||||||
for (i = 0; i < bps; i++)
|
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? */
|
else { if (uptr->flags & UNIT_WPRT) { /* write and locked? */
|
||||||
ry_done (0, 0100); /* done, error */
|
ry_done (0, 0100); /* done, error */
|
||||||
break; }
|
break; }
|
||||||
for (i = 0; i < bps; i++) /* write */
|
for (i = 0; i < bps; i++) /* write */
|
||||||
*(((int8 *) uptr->filebuf) + da + i) = rx2xb[i];
|
fbuf[da + i] = rx2xb[i];
|
||||||
da = da + bps;
|
da = da + bps;
|
||||||
if (da > uptr->hwmark) uptr->hwmark = da; }
|
if (da > uptr->hwmark) uptr->hwmark = da; }
|
||||||
ry_done (0, 0); /* done */
|
ry_done (0, 0); /* done */
|
||||||
|
@ -420,8 +421,7 @@ case SDCNF: /* confirm set density */
|
||||||
sim_activate (uptr, ry_cwait * 100); /* schedule operation */
|
sim_activate (uptr, ry_cwait * 100); /* schedule operation */
|
||||||
break;
|
break;
|
||||||
case SDXFR: /* erase disk */
|
case SDXFR: /* erase disk */
|
||||||
for (i = 0; i < (int32) uptr->capac; i++)
|
for (i = 0; i < (int32) uptr->capac; i++) fbuf[i] = 0;
|
||||||
*(((int8 *) uptr->filebuf) + i) = 0;
|
|
||||||
uptr->hwmark = uptr->capac;
|
uptr->hwmark = uptr->capac;
|
||||||
if (ry_csr & RYCS_DEN) uptr->flags = uptr->flags | UNIT_DEN;
|
if (ry_csr & RYCS_DEN) uptr->flags = uptr->flags | UNIT_DEN;
|
||||||
else uptr->flags = uptr->flags & ~UNIT_DEN;
|
else uptr->flags = uptr->flags & ~UNIT_DEN;
|
||||||
|
@ -462,7 +462,7 @@ case INIT_COMPLETE: /* init complete */
|
||||||
break; }
|
break; }
|
||||||
da = CALC_DA (1, 1, bps); /* track 1, sector 1 */
|
da = CALC_DA (1, 1, bps); /* track 1, sector 1 */
|
||||||
for (i = 0; i < bps; i++) /* read sector */
|
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 */
|
ry_done (RYES_ID, 0); /* set done */
|
||||||
if ((ry_unit[1].flags & UNIT_ATT) == 0) ry_ecode = 0020;
|
if ((ry_unit[1].flags & UNIT_ATT) == 0) ry_ecode = 0020;
|
||||||
break; } /* end case state */
|
break; } /* end case state */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* pdp11_stddev.c: PDP-11 standard I/O devices simulator
|
/* 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
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -26,6 +26,7 @@
|
||||||
tti,tto DL11 terminal input/output
|
tti,tto DL11 terminal input/output
|
||||||
clk KW11L line frequency clock
|
clk KW11L line frequency clock
|
||||||
|
|
||||||
|
29-Dec-03 RMS Added console backpressure support
|
||||||
25-Apr-03 RMS Revised for extended file support
|
25-Apr-03 RMS Revised for extended file support
|
||||||
01-Mar-03 RMS Added SET/SHOW CLOCK FREQ, SET TTI CTRL-C
|
01-Mar-03 RMS Added SET/SHOW CLOCK FREQ, SET TTI CTRL-C
|
||||||
22-Nov-02 RMS Changed terminal default to 7B for UNIX
|
22-Nov-02 RMS Changed terminal default to 7B for UNIX
|
||||||
|
@ -319,10 +320,12 @@ t_stat tto_svc (UNIT *uptr)
|
||||||
int32 c;
|
int32 c;
|
||||||
t_stat r;
|
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;
|
tto_csr = tto_csr | CSR_DONE;
|
||||||
if (tto_csr & CSR_IE) SET_INT (TTO);
|
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;
|
tto_unit.pos = tto_unit.pos + 1;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,10 @@
|
||||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
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
|
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
|
17-Oct-02 RMS Fixed bugs in branch, SOB address parsing
|
||||||
09-Oct-02 RMS Added DELQA support
|
09-Oct-02 RMS Added DELQA support
|
||||||
12-Sep-02 RMS Added TMSCP, KW11P, RX211 support, RAD50 examine
|
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 tm_dev, ts_dev;
|
||||||
extern DEVICE tq_dev;
|
extern DEVICE tq_dev;
|
||||||
extern DEVICE xq_dev, xqb_dev;
|
extern DEVICE xq_dev, xqb_dev;
|
||||||
extern DEVICE xu_dev;
|
extern DEVICE xu_dev, xub_dev;
|
||||||
extern UNIT cpu_unit;
|
extern UNIT cpu_unit;
|
||||||
extern REG cpu_reg[];
|
extern REG cpu_reg[];
|
||||||
extern uint16 *M;
|
extern uint16 *M;
|
||||||
|
@ -113,6 +115,7 @@ DEVICE *sim_devices[] = {
|
||||||
&xq_dev,
|
&xq_dev,
|
||||||
&xqb_dev,
|
&xqb_dev,
|
||||||
&xu_dev,
|
&xu_dev,
|
||||||
|
&xub_dev,
|
||||||
NULL };
|
NULL };
|
||||||
|
|
||||||
const char *sim_stop_messages[] = {
|
const char *sim_stop_messages[] = {
|
||||||
|
@ -138,7 +141,8 @@ const char *sim_stop_messages[] = {
|
||||||
"Trap vector fetch abort",
|
"Trap vector fetch abort",
|
||||||
"Trap stack push abort",
|
"Trap stack push abort",
|
||||||
"RQDX3 consistency error",
|
"RQDX3 consistency error",
|
||||||
"Sanity timer expired" };
|
"Sanity timer expired"
|
||||||
|
"DECtape off reel" };
|
||||||
|
|
||||||
/* Binary loader.
|
/* Binary loader.
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* pdp11_tc.c: PDP-11 DECtape simulator
|
/* 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
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,10 @@
|
||||||
|
|
||||||
tc TC11/TU56 DECtape
|
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
|
25-Apr-03 RMS Revised for extended file support
|
||||||
14-Mar-03 RMS Fixed variable size interaction with save/restore
|
14-Mar-03 RMS Fixed variable size interaction with save/restore
|
||||||
29-Sep-02 RMS Added variable address support to bootstrap
|
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.
|
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.
|
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 0
|
||||||
:
|
:
|
||||||
block n
|
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
|
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
|
words, and five 18b trailer words. All systems except the PDP-8 use a
|
||||||
|
@ -79,9 +86,9 @@
|
||||||
header word 0 0
|
header word 0 0
|
||||||
header word 1 block number (for forward reads)
|
header word 1 block number (for forward reads)
|
||||||
header words 2,3 0
|
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 words 3,2 0
|
||||||
trailer word 1 block number (for reverse reads)
|
trailer word 1 block number (for reverse reads)
|
||||||
trailer word 0 0
|
trailer word 0 0
|
||||||
|
@ -106,13 +113,15 @@
|
||||||
|
|
||||||
/* System independent DECtape constants */
|
/* System independent DECtape constants */
|
||||||
|
|
||||||
#define DT_EZLIN 36000 /* end zone length */
|
#define DT_LPERMC 6 /* lines per mark track */
|
||||||
#define DT_HTLIN 30 /* header/trailer lines */
|
#define DT_BLKWD 1 /* blk no word in h/t */
|
||||||
#define DT_BLKLN 6 /* blk no line in h/t */
|
#define DT_CSMWD 4 /* checksum word in h/t */
|
||||||
#define DT_CSMLN 24 /* checksum line in h/t */
|
#define DT_HTWRD 5 /* header/trailer words */
|
||||||
#define DT_HTWRD (DT_HTLIN / DT_WSIZE) /* header/trailer words */
|
#define DT_EZLIN (8192 * DT_LPERMC) /* end zone length */
|
||||||
#define DT_BLKWD (DT_BLKLN / DT_WSIZE) /* blk no word in h/t */
|
#define DT_BFLIN (200 * DT_LPERMC) /* buffer length */
|
||||||
#define DT_CSMWD (DT_CSMLN / DT_WSIZE) /* checksum word in h/t */
|
#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 */
|
/* 16b, 18b, 36b DECtape constants */
|
||||||
|
|
||||||
|
@ -270,8 +279,7 @@ int32 tcba = 0; /* bus address */
|
||||||
int32 tcdt = 0; /* data */
|
int32 tcdt = 0; /* data */
|
||||||
int32 dt_ctime = 100; /* fast cmd time */
|
int32 dt_ctime = 100; /* fast cmd time */
|
||||||
int32 dt_ltime = 12; /* interline time */
|
int32 dt_ltime = 12; /* interline time */
|
||||||
int32 dt_actime = 54000; /* accel time */
|
int32 dt_dctime = 40000; /* decel time */
|
||||||
int32 dt_dctime = 72000; /* decel time */
|
|
||||||
int32 dt_substate = 0;
|
int32 dt_substate = 0;
|
||||||
int32 dt_logblk = 0;
|
int32 dt_logblk = 0;
|
||||||
|
|
||||||
|
@ -340,7 +348,6 @@ REG dt_reg[] = {
|
||||||
{ FLDATA (IE, tccm, CSR_V_DONE) },
|
{ FLDATA (IE, tccm, CSR_V_DONE) },
|
||||||
{ DRDATA (CTIME, dt_ctime, 31), REG_NZ },
|
{ DRDATA (CTIME, dt_ctime, 31), REG_NZ },
|
||||||
{ DRDATA (LTIME, dt_ltime, 31), REG_NZ },
|
{ DRDATA (LTIME, dt_ltime, 31), REG_NZ },
|
||||||
{ DRDATA (ACTIME, dt_actime, 31), REG_NZ },
|
|
||||||
{ DRDATA (DCTIME, dt_dctime, 31), REG_NZ },
|
{ DRDATA (DCTIME, dt_dctime, 31), REG_NZ },
|
||||||
{ ORDATA (SUBSTATE, dt_substate, 1) },
|
{ ORDATA (SUBSTATE, dt_substate, 1) },
|
||||||
{ DRDATA (LBLK, dt_logblk, 12), REG_HIDDEN },
|
{ DRDATA (LBLK, dt_logblk, 12), REG_HIDDEN },
|
||||||
|
@ -371,7 +378,7 @@ DEVICE dt_dev = {
|
||||||
DT_NUMDR + 1, 8, 24, 1, 8, 18,
|
DT_NUMDR + 1, 8, 24, 1, 8, 18,
|
||||||
NULL, NULL, &dt_reset,
|
NULL, NULL, &dt_reset,
|
||||||
&dt_boot, &dt_attach, &dt_detach,
|
&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 */
|
/* 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 (prev_mot == DTS_STOP) { /* start? */
|
||||||
if (dt_setpos (uptr)) return; /* update pos */
|
if (dt_setpos (uptr)) return; /* update pos */
|
||||||
sim_cancel (uptr); /* stop current */
|
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_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */
|
||||||
DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */
|
DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */
|
||||||
return; }
|
return; }
|
||||||
|
@ -537,7 +544,7 @@ if (prev_dir ^ new_dir) { /* dir chg? */
|
||||||
if (prev_mot < DTS_ACCF) { /* not accel/at speed? */
|
if (prev_mot < DTS_ACCF) { /* not accel/at speed? */
|
||||||
if (dt_setpos (uptr)) return; /* update pos */
|
if (dt_setpos (uptr)) return; /* update pos */
|
||||||
sim_cancel (uptr); /* cancel cur */
|
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_SETSTA (DTS_ACCF | new_dir, 0); /* state = accel */
|
||||||
DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */
|
DTS_SET2ND (DTS_ATSF | new_dir, new_fnc); /* next = fnc */
|
||||||
return; }
|
return; }
|
||||||
|
@ -674,11 +681,13 @@ case DTS_STOP: /* stop */
|
||||||
delta = 0;
|
delta = 0;
|
||||||
break;
|
break;
|
||||||
case DTS_DECF: /* slowing */
|
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);
|
delta = ((ulin * udelt * 2) - (ulin * ulin)) / (2 * udelt);
|
||||||
break;
|
break;
|
||||||
case DTS_ACCF: /* accelerating */
|
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);
|
delta = (ulin * ulin) / (2 * udelt);
|
||||||
break;
|
break;
|
||||||
case DTS_ATSF: /* at speed */
|
case DTS_ATSF: /* at speed */
|
||||||
|
@ -715,7 +724,7 @@ t_stat dt_svc (UNIT *uptr)
|
||||||
int32 mot = DTS_GETMOT (uptr->STATE);
|
int32 mot = DTS_GETMOT (uptr->STATE);
|
||||||
int32 dir = mot & DTS_DIR;
|
int32 dir = mot & DTS_DIR;
|
||||||
int32 fnc = DTS_GETFNC (uptr->STATE);
|
int32 fnc = DTS_GETFNC (uptr->STATE);
|
||||||
int32 *bptr = uptr->filebuf;
|
int32 *fbuf = uptr->filebuf;
|
||||||
int32 blk, wrd, relpos, dat;
|
int32 blk, wrd, relpos, dat;
|
||||||
uint32 ba, ma, mma;
|
uint32 ba, ma, mma;
|
||||||
|
|
||||||
|
@ -728,10 +737,10 @@ uint32 ba, ma, mma;
|
||||||
|
|
||||||
switch (mot) {
|
switch (mot) {
|
||||||
case DTS_DECF: case DTS_DECR: /* decelerating */
|
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 */
|
uptr->STATE = DTS_NXTSTA (uptr->STATE); /* advance state */
|
||||||
if (uptr->STATE) /* not stopped? */
|
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;
|
return SCPE_OK;
|
||||||
case DTS_ACCF: case DTS_ACCR: /* accelerating */
|
case DTS_ACCF: case DTS_ACCR: /* accelerating */
|
||||||
dt_newfnc (uptr, DTS_NXTSTA (uptr->STATE)); /* adv state, sched */
|
dt_newfnc (uptr, DTS_NXTSTA (uptr->STATE)); /* adv state, sched */
|
||||||
|
@ -748,7 +757,7 @@ default: /* other */
|
||||||
Off reel - detach unit (it must be deselected)
|
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? */
|
if (DT_QEZ (uptr)) { /* in end zone? */
|
||||||
dt_seterr (uptr, STA_END); /* end zone error */
|
dt_seterr (uptr, STA_END); /* end zone error */
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
|
@ -785,7 +794,7 @@ case FNC_READ: /* read */
|
||||||
dt_seterr (uptr, STA_NXM);
|
dt_seterr (uptr, STA_NXM);
|
||||||
break; }
|
break; }
|
||||||
ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */
|
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 */
|
tcwc = (tcwc + 1) & DMASK; /* incr MA, WC */
|
||||||
tcba = (tcba + 2) & DMASK;
|
tcba = (tcba + 2) & DMASK;
|
||||||
if (tcba <= 1) tccm = CSR_INCMEX (tccm);
|
if (tcba <= 1) tccm = CSR_INCMEX (tccm);
|
||||||
|
@ -822,7 +831,7 @@ case FNC_WRIT: /* write */
|
||||||
tcba = (tcba + 2) & DMASK;
|
tcba = (tcba + 2) & DMASK;
|
||||||
if (tcba <= 1) tccm = CSR_INCMEX (tccm); }
|
if (tcba <= 1) tccm = CSR_INCMEX (tccm); }
|
||||||
ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */
|
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 (ba >= uptr->hwmark) uptr->hwmark = ba + 1;
|
||||||
if (tcwc == 0) dt_substate = 1;
|
if (tcwc == 0) dt_substate = 1;
|
||||||
if (wrd != (dir? 0: DTU_BSIZE (uptr) - 1)) /* not end blk? */
|
if (wrd != (dir? 0: DTU_BSIZE (uptr) - 1)) /* not end blk? */
|
||||||
|
@ -844,7 +853,7 @@ case FNC_RALL:
|
||||||
(relpos < (DTU_LPERB (uptr) - DT_HTLIN))) {
|
(relpos < (DTU_LPERB (uptr) - DT_HTLIN))) {
|
||||||
wrd = DT_LIN2WD (uptr->pos, uptr);
|
wrd = DT_LIN2WD (uptr->pos, uptr);
|
||||||
ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */
|
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 */
|
else dat = dt_gethdr (uptr, blk, relpos); /* get hdr */
|
||||||
if (dir) dat = dt_comobv (dat); /* rev? comp obv */
|
if (dir) dat = dt_comobv (dat); /* rev? comp obv */
|
||||||
tcdt = dat & DMASK; /* low 16b */
|
tcdt = dat & DMASK; /* low 16b */
|
||||||
|
@ -866,7 +875,7 @@ case FNC_WALL:
|
||||||
dat = (STA_GETXD (tcst) << 16) | tcdt; /* get data word */
|
dat = (STA_GETXD (tcst) << 16) | tcdt; /* get data word */
|
||||||
if (dir) dat = dt_comobv (dat); /* rev? comp obv */
|
if (dir) dat = dt_comobv (dat); /* rev? comp obv */
|
||||||
ba = (blk * DTU_BSIZE (uptr)) + wrd; /* buffer ptr */
|
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; }
|
if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; }
|
||||||
/* else /* ignore hdr */
|
/* else /* ignore hdr */
|
||||||
sim_activate (uptr, DT_WSIZE * dt_ltime);
|
sim_activate (uptr, DT_WSIZE * dt_ltime);
|
||||||
|
@ -941,13 +950,13 @@ return dat;
|
||||||
|
|
||||||
int32 dt_csum (UNIT *uptr, int32 blk)
|
int32 dt_csum (UNIT *uptr, int32 blk)
|
||||||
{
|
{
|
||||||
int32 *bptr = uptr->filebuf;
|
int32 *fbuf = uptr->filebuf;
|
||||||
int32 ba = blk * DTU_BSIZE (uptr);
|
int32 ba = blk * DTU_BSIZE (uptr);
|
||||||
int32 i, csum, wrd;
|
int32 i, csum, wrd;
|
||||||
|
|
||||||
csum = 077; /* init csum */
|
csum = 077; /* init csum */
|
||||||
for (i = 0; i < DTU_BSIZE (uptr); i++) { /* loop thru buf */
|
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; }
|
csum = csum ^ (wrd >> 12) ^ (wrd >> 6) ^ wrd; }
|
||||||
return (csum & 077);
|
return (csum & 077);
|
||||||
}
|
}
|
||||||
|
@ -959,6 +968,7 @@ int32 dt_gethdr (UNIT *uptr, int32 blk, int32 relpos)
|
||||||
int32 wrd = relpos / DT_WSIZE;
|
int32 wrd = relpos / DT_WSIZE;
|
||||||
|
|
||||||
if (wrd == DT_BLKWD) return blk; /* fwd blknum */
|
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 */
|
if (wrd == (2 * DT_HTWRD + DTU_BSIZE (uptr) - DT_CSMWD - 1)) /* fwd csum */
|
||||||
return (dt_csum (uptr, blk) << 12);
|
return (dt_csum (uptr, blk) << 12);
|
||||||
if (wrd == (2 * DT_HTWRD + DTU_BSIZE (uptr) - DT_BLKWD - 1)) /* rev blkno */
|
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 pdp8b[D8_NBSIZE];
|
||||||
uint16 pdp11b[D18_BSIZE];
|
uint16 pdp11b[D18_BSIZE];
|
||||||
uint32 ba, sz, k, *bptr;
|
uint32 ba, sz, k, *fbuf;
|
||||||
int32 u = uptr - dt_dev.units;
|
int32 u = uptr - dt_dev.units;
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
|
@ -1089,7 +1099,7 @@ uptr->filebuf = calloc (uptr->capac, sizeof (int32));
|
||||||
if (uptr->filebuf == NULL) { /* can't alloc? */
|
if (uptr->filebuf == NULL) { /* can't alloc? */
|
||||||
detach_unit (uptr);
|
detach_unit (uptr);
|
||||||
return SCPE_MEM; }
|
return SCPE_MEM; }
|
||||||
bptr = uptr->filebuf; /* file buffer */
|
fbuf = uptr->filebuf; /* file buffer */
|
||||||
printf ("%s%d: ", sim_dname (&dt_dev), u);
|
printf ("%s%d: ", sim_dname (&dt_dev), u);
|
||||||
if (uptr->flags & UNIT_8FMT) printf ("12b format");
|
if (uptr->flags & UNIT_8FMT) printf ("12b format");
|
||||||
else if (uptr->flags & UNIT_11FMT) printf ("16b format");
|
else if (uptr->flags & UNIT_11FMT) printf ("16b format");
|
||||||
|
@ -1101,9 +1111,9 @@ if (uptr->flags & UNIT_8FMT) { /* 12b? */
|
||||||
if (k == 0) break;
|
if (k == 0) break;
|
||||||
for ( ; k < D8_NBSIZE; k++) pdp8b[k] = 0;
|
for ( ; k < D8_NBSIZE; k++) pdp8b[k] = 0;
|
||||||
for (k = 0; k < D8_NBSIZE; k = k + 3) { /* loop thru blk */
|
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);
|
((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));
|
((uint32) (pdp8b[k + 2] & 07777));
|
||||||
ba = ba + 2; } /* end blk loop */
|
ba = ba + 2; } /* end blk loop */
|
||||||
} /* end file loop */
|
} /* end file loop */
|
||||||
|
@ -1114,7 +1124,7 @@ else if (uptr->flags & UNIT_11FMT) { /* 16b? */
|
||||||
if (k == 0) break;
|
if (k == 0) break;
|
||||||
for ( ; k < D18_BSIZE; k++) pdp11b[k] = 0;
|
for ( ; k < D18_BSIZE; k++) pdp11b[k] = 0;
|
||||||
for (k = 0; k < D18_BSIZE; k++)
|
for (k = 0; k < D18_BSIZE; k++)
|
||||||
bptr[ba++] = pdp11b[k]; }
|
fbuf[ba++] = pdp11b[k]; }
|
||||||
uptr->hwmark = ba; } /* end elif */
|
uptr->hwmark = ba; } /* end elif */
|
||||||
else uptr->hwmark = fxread (uptr->filebuf, sizeof (int32),
|
else uptr->hwmark = fxread (uptr->filebuf, sizeof (int32),
|
||||||
uptr->capac, uptr->fileref);
|
uptr->capac, uptr->fileref);
|
||||||
|
@ -1137,7 +1147,7 @@ t_stat dt_detach (UNIT* uptr)
|
||||||
{
|
{
|
||||||
uint16 pdp8b[D8_NBSIZE];
|
uint16 pdp8b[D8_NBSIZE];
|
||||||
uint16 pdp11b[D18_BSIZE];
|
uint16 pdp11b[D18_BSIZE];
|
||||||
uint32 ba, k, *bptr;
|
uint32 ba, k, *fbuf;
|
||||||
int32 u = uptr - dt_dev.units;
|
int32 u = uptr - dt_dev.units;
|
||||||
|
|
||||||
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK;
|
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;
|
tccm = tccm | CSR_ERR | CSR_DONE;
|
||||||
if (tccm & CSR_IE) SET_INT (DTA); }
|
if (tccm & CSR_IE) SET_INT (DTA); }
|
||||||
uptr->STATE = uptr->pos = 0; }
|
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? */
|
if (uptr->hwmark && ((uptr->flags & UNIT_RO) == 0)) { /* any data? */
|
||||||
printf ("%s%d: writing buffer to file\n", sim_dname (&dt_dev), u);
|
printf ("%s%d: writing buffer to file\n", sim_dname (&dt_dev), u);
|
||||||
rewind (uptr->fileref); /* start of file */
|
rewind (uptr->fileref); /* start of file */
|
||||||
if (uptr->flags & UNIT_8FMT) { /* 12b? */
|
if (uptr->flags & UNIT_8FMT) { /* 12b? */
|
||||||
for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */
|
for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */
|
||||||
for (k = 0; k < D8_NBSIZE; k = k + 3) { /* loop blk */
|
for (k = 0; k < D8_NBSIZE; k = k + 3) { /* loop blk */
|
||||||
pdp8b[k] = (bptr[ba] >> 6) & 07777;
|
pdp8b[k] = (fbuf[ba] >> 6) & 07777;
|
||||||
pdp8b[k + 1] = ((bptr[ba] & 077) << 6) |
|
pdp8b[k + 1] = ((fbuf[ba] & 077) << 6) |
|
||||||
((bptr[ba + 1] >> 12) & 077);
|
((fbuf[ba + 1] >> 12) & 077);
|
||||||
pdp8b[k + 2] = bptr[ba + 1] & 07777;
|
pdp8b[k + 2] = fbuf[ba + 1] & 07777;
|
||||||
ba = ba + 2; } /* end loop blk */
|
ba = ba + 2; } /* end loop blk */
|
||||||
fxwrite (pdp8b, sizeof (int16), D8_NBSIZE, uptr->fileref);
|
fxwrite (pdp8b, sizeof (int16), D8_NBSIZE, uptr->fileref);
|
||||||
if (ferror (uptr->fileref)) break; } /* end loop file */
|
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? */
|
else if (uptr->flags & UNIT_11FMT) { /* 16b? */
|
||||||
for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */
|
for (ba = 0; ba < uptr->hwmark; ) { /* loop thru file */
|
||||||
for (k = 0; k < D18_BSIZE; k++) /* loop blk */
|
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);
|
fxwrite (pdp11b, sizeof (int16), D18_BSIZE, uptr->fileref);
|
||||||
if (ferror (uptr->fileref)) break; } /* end loop file */
|
if (ferror (uptr->fileref)) break; } /* end loop file */
|
||||||
} /* end if 16b */
|
} /* end if 16b */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* pdp11_tm.c: PDP-11 magnetic tape simulator
|
/* 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
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
tm TM11/TU10 magtape
|
tm TM11/TU10 magtape
|
||||||
|
|
||||||
|
29-Dec-03 RMS Added 18b Qbus support
|
||||||
25-Apr-03 RMS Revised for extended file support
|
25-Apr-03 RMS Revised for extended file support
|
||||||
28-Mar-03 RMS Added multiformat support
|
28-Mar-03 RMS Added multiformat support
|
||||||
28-Feb-03 RMS Revised for magtape library, added logging
|
28-Feb-03 RMS Revised for magtape library, added logging
|
||||||
|
@ -231,7 +232,7 @@ DEVICE tm_dev = {
|
||||||
TM_NUMDR, 10, 31, 1, 8, 8,
|
TM_NUMDR, 10, 31, 1, 8, 8,
|
||||||
NULL, NULL, &tm_reset,
|
NULL, NULL, &tm_reset,
|
||||||
&tm_boot, &tm_attach, &tm_detach,
|
&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
|
/* I/O dispatch routine, I/O addresses 17772520 - 17772532
|
||||||
|
|
||||||
|
|
191
PDP11/pdp11_xq.c
|
@ -69,6 +69,27 @@
|
||||||
|
|
||||||
Modification history:
|
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
|
05-Jun-03 DTH Added receive packet splitting
|
||||||
03-Jun-03 DTH Added SHOW XQ FILTERS
|
03-Jun-03 DTH Added SHOW XQ FILTERS
|
||||||
02-Jun-03 DTH Added SET/SHOW XQ STATS (packet statistics), runt & giant processing
|
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
|
of Receiver Enabled. This was an issue since the
|
||||||
it seems that at least VMS's XQ driver makes this
|
it seems that at least VMS's XQ driver makes this
|
||||||
transition often and the resulting overhead reduces
|
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
|
about 40%. I start the system id timer on device
|
||||||
reset and it fires once a second so that it can
|
reset and it fires once a second so that it can
|
||||||
leverage the reasonably recalibrated tmr_poll value.
|
leverage the reasonably recalibrated tmr_poll value.
|
||||||
|
@ -100,7 +121,7 @@
|
||||||
dynamically computed clock values to achieve an
|
dynamically computed clock values to achieve an
|
||||||
approximate interval of 100 per second. This is
|
approximate interval of 100 per second. This is
|
||||||
more than sufficient for normal system behaviour
|
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
|
transmit. The previous fixed value of 2500
|
||||||
attempted to get 200/sec but it was a guess that
|
attempted to get 200/sec but it was a guess that
|
||||||
didn't adapt. On faster host systems (possibly
|
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
|
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
|
is called repeatedly until either a packet isn't found or
|
||||||
there is no room for another one in the queue. Once that has
|
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.
|
into the simulated system as space is available there.
|
||||||
xq_process_rdbl is also called at the beginning of xq_svc to
|
xq_process_rdbl is also called at the beginning of xq_svc to
|
||||||
drain the queue into the simulated system, making more room
|
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);
|
t_stat xq_dispatch_xbdl(CTLR* xq);
|
||||||
void xq_start_receiver(void);
|
void xq_start_receiver(void);
|
||||||
void xq_sw_reset(CTLR* xq);
|
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_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);
|
t_stat xq_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
|
||||||
void xq_start_santmr(CTLR* xq);
|
void xq_start_santmr(CTLR* xq);
|
||||||
|
@ -230,6 +249,9 @@ void xqa_read_callback(int status);
|
||||||
void xqb_read_callback(int status);
|
void xqb_read_callback(int status);
|
||||||
void xqa_write_callback(int status);
|
void xqa_write_callback(int status);
|
||||||
void xqb_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 = {
|
struct xq_device xqa = {
|
||||||
xqa_read_callback, /* read callback routine */
|
xqa_read_callback, /* read callback routine */
|
||||||
|
@ -249,7 +271,7 @@ struct xq_device xqb = {
|
||||||
|
|
||||||
/* SIMH device structures */
|
/* SIMH device structures */
|
||||||
DIB xqa_dib = { IOBA_XQ, IOLN_XQ, &xq_rd, &xq_wr,
|
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[] = {
|
UNIT xqa_unit[] = {
|
||||||
{ UDATA (&xq_svc, UNIT_ATTABLE + UNIT_DISABLE, 2047) }, /* receive timer */
|
{ 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 ( XBDL, xqa.xbdl, XQ_RDX, 32, 0) },
|
||||||
{ GRDATA ( VAR, xqa.var, XQ_RDX, 16, 0) },
|
{ GRDATA ( VAR, xqa.var, XQ_RDX, 16, 0) },
|
||||||
{ GRDATA ( CSR, xqa.csr, 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_PRM, xqa.setup.promiscuous, XQ_RDX, 32, 0), REG_HRO},
|
||||||
{ GRDATA ( SETUP_MLT, xqa.setup.multicast, 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},
|
{ 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,
|
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[] = {
|
UNIT xqb_unit[] = {
|
||||||
{ UDATA (&xq_svc, UNIT_ATTABLE + UNIT_DISABLE, 2047) }, /* receive timer */
|
{ 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 ( XBDL, xqb.xbdl, XQ_RDX, 32, 0) },
|
||||||
{ GRDATA ( VAR, xqb.var, XQ_RDX, 16, 0) },
|
{ GRDATA ( VAR, xqb.var, XQ_RDX, 16, 0) },
|
||||||
{ GRDATA ( CSR, xqb.csr, 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_PRM, xqb.setup.promiscuous, XQ_RDX, 32, 0), REG_HRO},
|
||||||
{ GRDATA ( SETUP_MLT, xqb.setup.multicast, 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},
|
{ 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);
|
void xq_var_changes(CTLR* xq, uint16 data);
|
||||||
|
|
||||||
/* sanity timer debugging */
|
/* sanity timer debugging */
|
||||||
#include <sys\timeb.h>
|
#include <sys/timeb.h>
|
||||||
struct timeb start, finish;
|
struct timeb start, finish;
|
||||||
|
|
||||||
#endif /* XQ_DEBUG */
|
#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;
|
if (len != 17) return SCPE_ARG;
|
||||||
/* make sure byte separators are OK */
|
/* make sure byte separators are OK */
|
||||||
for (i=2; i<len; i=i+3) {
|
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';
|
cptr[i] = '\0';
|
||||||
}
|
}
|
||||||
/* get and set address bytes */
|
/* 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)
|
t_stat xq_showeth (FILE* st, UNIT* uptr, int32 val, void* desc)
|
||||||
{
|
{
|
||||||
#define XQ_MAX_LIST 10
|
#define XQ_MAX_LIST 10
|
||||||
int i;
|
|
||||||
ETH_LIST list[XQ_MAX_LIST];
|
ETH_LIST list[XQ_MAX_LIST];
|
||||||
int number = eth_devices(XQ_MAX_LIST, list);
|
int number = eth_devices(XQ_MAX_LIST, list);
|
||||||
|
|
||||||
fprintf(st, "ETH devices:\n");
|
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++)
|
for (i=0; i<number; i++)
|
||||||
fprintf(st," %d %s (%s)\n", i, list[i].name, list[i].desc);
|
fprintf(st," %d %-*s (%s)\n", i, min, list[i].name, list[i].desc);
|
||||||
else
|
} else
|
||||||
fprintf(st, " no network devices are available\n");
|
fprintf(st, " no network devices are available\n");
|
||||||
return SCPE_OK;
|
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);
|
eth_mac_fmt((ETH_MAC*)xq->var->setup.macs[i], buffer);
|
||||||
fprintf(st, " [%2d]: %s\n", 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;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -695,8 +727,8 @@ t_stat xq_show_sanity (FILE* st, UNIT* uptr, int32 val, void* desc)
|
||||||
|
|
||||||
fprintf(st, "sanity=");
|
fprintf(st, "sanity=");
|
||||||
switch (xq->var->sanity.enabled) {
|
switch (xq->var->sanity.enabled) {
|
||||||
case 0: fprintf(st, "OFF"); break;
|
case 0: fprintf(st, "OFF\n"); break;
|
||||||
case 1: fprintf(st, "ON"); break;
|
case 1: fprintf(st, "ON\n"); break;
|
||||||
}
|
}
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -724,7 +756,7 @@ t_stat xq_nxm_error(CTLR* xq)
|
||||||
|
|
||||||
/* interrupt if required */
|
/* interrupt if required */
|
||||||
if (xq->var->csr & XQ_CSR_IE)
|
if (xq->var->csr & XQ_CSR_IE)
|
||||||
SET_INT(XQ);
|
xq_setint(xq);
|
||||||
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -761,7 +793,7 @@ void xq_write_callback (CTLR* xq, int status)
|
||||||
/* update csr */
|
/* update csr */
|
||||||
xq->var->csr |= XQ_CSR_XI;
|
xq->var->csr |= XQ_CSR_XI;
|
||||||
if (xq->var->csr & XQ_CSR_IE)
|
if (xq->var->csr & XQ_CSR_IE)
|
||||||
SET_INT(XQ);
|
xq_setint(xq);
|
||||||
|
|
||||||
/* reset sanity timer */
|
/* reset sanity timer */
|
||||||
xq_reset_santmr(xq);
|
xq_reset_santmr(xq);
|
||||||
|
@ -846,7 +878,7 @@ t_stat xq_process_rbdl(CTLR* xq)
|
||||||
uint16 b_length, w_length, rbl;
|
uint16 b_length, w_length, rbl;
|
||||||
uint32 address;
|
uint32 address;
|
||||||
struct xq_msg_itm* item;
|
struct xq_msg_itm* item;
|
||||||
char* rbuf;
|
uint8* rbuf;
|
||||||
|
|
||||||
#ifdef XQ_DEBUG
|
#ifdef XQ_DEBUG
|
||||||
fprintf(stderr,"%s: CSR - Processing read\n", xq->dev->name);
|
fprintf(stderr,"%s: CSR - Processing read\n", xq->dev->name);
|
||||||
|
@ -906,7 +938,7 @@ t_stat xq_process_rbdl(CTLR* xq)
|
||||||
#endif
|
#endif
|
||||||
/* pad runts with zeros up to minimum size - this allows "legal" (size - 60)
|
/* 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 */
|
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;
|
rbl = ETH_MIN_PACKET;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -976,7 +1008,7 @@ t_stat xq_process_rbdl(CTLR* xq)
|
||||||
/* mark transmission complete */
|
/* mark transmission complete */
|
||||||
xq->var->csr |= XQ_CSR_RI;
|
xq->var->csr |= XQ_CSR_RI;
|
||||||
if (xq->var->csr & XQ_CSR_IE)
|
if (xq->var->csr & XQ_CSR_IE)
|
||||||
SET_INT(XQ);
|
xq_setint(xq);
|
||||||
|
|
||||||
/* set to next bdl (implicit chain) */
|
/* set to next bdl (implicit chain) */
|
||||||
xq->var->rbdl_ba += 12;
|
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)];
|
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 */
|
/* process high byte count */
|
||||||
if (xq->var->write_buffer.len > 128) {
|
if (xq->var->write_buffer.len > 128) {
|
||||||
uint16 len = xq->var->write_buffer.len;
|
uint16 len = xq->var->write_buffer.len;
|
||||||
uint16 led, san;
|
uint16 led, san;
|
||||||
|
|
||||||
if (len & XQ_SETUP_MC)
|
xq->var->setup.multicast = (0 != (len & XQ_SETUP_MC));
|
||||||
xq->var->setup.multicast = 1;
|
xq->var->setup.promiscuous = (0 != (len & XQ_SETUP_PM));
|
||||||
if (len & XQ_SETUP_PM)
|
|
||||||
xq->var->setup.promiscuous = 1;
|
|
||||||
if (led = (len & XQ_SETUP_LD) >> 2) {
|
if (led = (len & XQ_SETUP_LD) >> 2) {
|
||||||
switch (led) {
|
switch (led) {
|
||||||
case 1: xq->var->setup.l1 = 0; break;
|
case 1: xq->var->setup.l1 = 0; break;
|
||||||
|
@ -1214,7 +1273,7 @@ t_stat xq_process_xbdl(CTLR* xq)
|
||||||
/* mark transmission complete */
|
/* mark transmission complete */
|
||||||
xq->var->csr |= XQ_CSR_XI;
|
xq->var->csr |= XQ_CSR_XI;
|
||||||
if (xq->var->csr & XQ_CSR_IE)
|
if (xq->var->csr & XQ_CSR_IE)
|
||||||
SET_INT(XQ);
|
xq_setint(xq);
|
||||||
|
|
||||||
/* now trigger "read" of setup or loopback packet */
|
/* now trigger "read" of setup or loopback packet */
|
||||||
if (~xq->var->csr & XQ_CSR_RL)
|
if (~xq->var->csr & XQ_CSR_RL)
|
||||||
|
@ -1446,13 +1505,26 @@ void xq_sw_reset(CTLR* xq)
|
||||||
xq->var->csr |= XQ_CSR_OK;
|
xq->var->csr |= XQ_CSR_OK;
|
||||||
|
|
||||||
/* clear CPU interrupts */
|
/* clear CPU interrupts */
|
||||||
CLR_INT(XQ);
|
xq_clrint(xq);
|
||||||
|
|
||||||
/* flush read queue */
|
/* flush read queue */
|
||||||
xq_clear_queue(&xq->var->ReadQ);
|
xq_clear_queue(&xq->var->ReadQ);
|
||||||
|
|
||||||
/* clear setup info */
|
/* 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: */
|
/* write registers: */
|
||||||
|
@ -1676,7 +1748,7 @@ t_stat xq_process_bootrom (CTLR* xq)
|
||||||
/* mark transmission complete */
|
/* mark transmission complete */
|
||||||
xq->var->csr |= XQ_CSR_RI;
|
xq->var->csr |= XQ_CSR_RI;
|
||||||
if (xq->var->csr & XQ_CSR_IE)
|
if (xq->var->csr & XQ_CSR_IE)
|
||||||
SET_INT(XQ);
|
xq_setint(xq);
|
||||||
|
|
||||||
/* reset sanity timer */
|
/* reset sanity timer */
|
||||||
xq_reset_santmr(xq);
|
xq_reset_santmr(xq);
|
||||||
|
@ -1724,8 +1796,8 @@ t_stat xq_wr_csr(CTLR* xq, int32 data)
|
||||||
/* check and correct CPU interrupt state */
|
/* check and correct CPU interrupt state */
|
||||||
old_int_state = (saved_csr & XQ_CSR_IE) && (saved_csr & (XQ_CSR_XI | XQ_CSR_RI));
|
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));
|
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) xq_clrint(xq);
|
||||||
if (!old_int_state && new_int_state) SET_INT(XQ);
|
if (!old_int_state && new_int_state) xq_setint(xq);
|
||||||
|
|
||||||
#ifdef VM_PDP11
|
#ifdef VM_PDP11
|
||||||
/* request boot/diagnostic rom? [PDP-11 only] */
|
/* request boot/diagnostic rom? [PDP-11 only] */
|
||||||
|
@ -1803,12 +1875,6 @@ t_stat xq_reset(DEVICE* dptr)
|
||||||
/* init control status register */
|
/* init control status register */
|
||||||
xq->var->csr = XQ_CSR_RL | XQ_CSR_XL;
|
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) */
|
/* init read queue (first time only) */
|
||||||
status = xq_init_queue (xq, &xq->var->ReadQ);
|
status = xq_init_queue (xq, &xq->var->ReadQ);
|
||||||
if (status != SCPE_OK)
|
if (status != SCPE_OK)
|
||||||
|
@ -1817,6 +1883,11 @@ t_stat xq_reset(DEVICE* dptr)
|
||||||
/* clear read queue */
|
/* clear read queue */
|
||||||
xq_clear_queue(&xq->var->ReadQ);
|
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 */
|
/* start sanity timer if power-on SANITY is set */
|
||||||
switch (xq->var->type) {
|
switch (xq->var->type) {
|
||||||
case XQ_T_DEQNA:
|
case XQ_T_DEQNA:
|
||||||
|
@ -1830,6 +1901,8 @@ t_stat xq_reset(DEVICE* dptr)
|
||||||
xq_start_idtmr(xq);
|
xq_start_idtmr(xq);
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return SCPE_OK;
|
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 */
|
/* must be recalculated each time since tmr_poll is a dynamic number */
|
||||||
const int32 quarter_sec = (clk_tps * tmr_poll) / 4;
|
const int32 quarter_sec = (clk_tps * tmr_poll) / 4;
|
||||||
|
|
||||||
#if 0
|
|
||||||
#ifdef XQ_DEBUG
|
#ifdef XQ_DEBUG
|
||||||
fprintf(stderr,"%s: SANITY TIMER ENABLED, qsecs: %d, poll:%d\n",
|
fprintf(stderr,"%s: SANITY TIMER ENABLED, qsecs: %d, poll:%d\n",
|
||||||
xq->dev->name, xq->var->sanity.quarter_secs, tmr_poll);
|
xq->dev->name, xq->var->sanity.quarter_secs, tmr_poll);
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
if (sim_is_active(xq_santmr)) /* cancel timer, just in case */
|
if (sim_is_active(xq_santmr)) /* cancel timer, just in case */
|
||||||
sim_cancel(xq_santmr);
|
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
|
If this section is entered, it means that the sanity timer has expired
|
||||||
without being reset, and the controller must reboot the processor.
|
without being reset, and the controller must reboot the processor.
|
||||||
*/
|
*/
|
||||||
#if 0
|
|
||||||
#ifdef XQ_DEBUG
|
#ifdef XQ_DEBUG
|
||||||
ftime(&finish);
|
ftime(&finish);
|
||||||
fprintf(stderr,"%s: SANITY TIMER EXPIRED, qsecs: %d, poll: %d, elapsed: %d\n",
|
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);
|
xq->dev->name, xq->var->sanity.quarter_secs, tmr_poll, finish.time - start.time);
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
xq_boot_host();
|
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];
|
uint8* const msg = &system_id.msg[0];
|
||||||
t_stat status;
|
t_stat status;
|
||||||
|
|
||||||
|
#ifdef XQ_DEBUG
|
||||||
|
fprintf(stderr,"%s: SYSTEM ID BROADCAST\n", xq->dev->name);
|
||||||
|
#endif
|
||||||
memset (&system_id, 0, sizeof(system_id));
|
memset (&system_id, 0, sizeof(system_id));
|
||||||
memcpy (&msg[0], dest, sizeof(ETH_MAC));
|
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));
|
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 */
|
/* turn on transceiver power indicator */
|
||||||
xq->var->csr |= XQ_CSR_OK;
|
xq->var->csr |= XQ_CSR_OK;
|
||||||
|
|
||||||
|
/* reset the device with the new attach info */
|
||||||
|
xq_reset(xq->dev);
|
||||||
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2098,6 +2173,7 @@ t_stat xq_detach(UNIT* uptr)
|
||||||
{
|
{
|
||||||
t_stat status;
|
t_stat status;
|
||||||
CTLR* xq = xq_unit2ctlr(uptr);
|
CTLR* xq = xq_unit2ctlr(uptr);
|
||||||
|
int i;
|
||||||
|
|
||||||
if (uptr->flags & UNIT_ATT) {
|
if (uptr->flags & UNIT_ATT) {
|
||||||
status = eth_close (xq->var->etherface);
|
status = eth_close (xq->var->etherface);
|
||||||
|
@ -2106,6 +2182,9 @@ t_stat xq_detach(UNIT* uptr)
|
||||||
free(uptr->filename);
|
free(uptr->filename);
|
||||||
uptr->filename = NULL;
|
uptr->filename = NULL;
|
||||||
uptr->flags &= ~UNIT_ATT;
|
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 */
|
/* turn off transceiver power indicator */
|
||||||
|
@ -2114,14 +2193,38 @@ t_stat xq_detach(UNIT* uptr)
|
||||||
return SCPE_OK;
|
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:
|
Modification history:
|
||||||
|
|
||||||
|
25-Nov-03 DTH Added interrupt request flag
|
||||||
02-Jun-03 DTH Added struct xq_stats
|
02-Jun-03 DTH Added struct xq_stats
|
||||||
28-May-03 DTH Made xq_msg_que.item dynamic
|
28-May-03 DTH Made xq_msg_que.item dynamic
|
||||||
28-May-03 MP Optimized structures, removed rtime variable
|
28-May-03 MP Optimized structures, removed rtime variable
|
||||||
|
@ -152,6 +153,7 @@ struct xq_device {
|
||||||
uint16 xbdl[2];
|
uint16 xbdl[2];
|
||||||
uint16 var;
|
uint16 var;
|
||||||
uint16 csr;
|
uint16 csr;
|
||||||
|
uint32 irq; /* interrupt request flag */
|
||||||
|
|
||||||
/* buffers, etc. */
|
/* buffers, etc. */
|
||||||
struct xq_setup setup;
|
struct xq_setup setup;
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
xu DEUNA/DELUNA Ethernet interface (stub)
|
xu DEUNA/DELUNA Ethernet interface (stub)
|
||||||
|
|
||||||
|
22-Dec-03 RMS Added second (stub) device
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined (VM_PDP10) /* PDP10 version */
|
#if defined (VM_PDP10) /* PDP10 version */
|
||||||
|
@ -61,3 +63,29 @@ DEVICE xu_dev = {
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
&xu_dib, DEV_DIS | DEV_UBUS };
|
&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
|
/* 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
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,10 @@
|
||||||
|
|
||||||
cpu PDP-4/7/9/15 central processor
|
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
|
31-Aug-03 RMS Added instruction history
|
||||||
Fixed PDP-15-specific implementation of API priorities
|
Fixed PDP-15-specific implementation of API priorities
|
||||||
16-Aug-03 RMS Fixed PDP-15-specific handling of EAE unsigned mul/div
|
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_XVM (1 << UNIT_V_XVM)
|
||||||
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
|
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
|
||||||
|
|
||||||
#define HIST_SIZE 4096
|
|
||||||
#define HIST_API 0x40000000
|
#define HIST_API 0x40000000
|
||||||
#define HIST_PI 0x20000000
|
#define HIST_PI 0x20000000
|
||||||
|
#define HIST_PC 0x10000000
|
||||||
|
#define HIST_MIN 64
|
||||||
|
#define HIST_MAX 65536
|
||||||
#define HIST_M_LVL 0x3F
|
#define HIST_M_LVL 0x3F
|
||||||
#define HIST_V_LVL 6
|
#define HIST_V_LVL 6
|
||||||
struct InstHistory {
|
struct InstHistory {
|
||||||
|
@ -303,7 +309,7 @@ struct InstHistory {
|
||||||
#define PROT_DFLT 0
|
#define PROT_DFLT 0
|
||||||
#define ASW_DFLT 017763
|
#define ASW_DFLT 017763
|
||||||
#else
|
#else
|
||||||
#define API_DFLT UNIT_NOAPI /* for now */
|
#define API_DFLT 0
|
||||||
#define PROT_DFLT UNIT_PROT
|
#define PROT_DFLT UNIT_PROT
|
||||||
#define ASW_DFLT 017720
|
#define ASW_DFLT 017720
|
||||||
#endif
|
#endif
|
||||||
|
@ -355,7 +361,7 @@ int32 pcq_p = 0; /* PC queue ptr */
|
||||||
REG *pcq_r = NULL; /* PC queue reg ptr */
|
REG *pcq_r = NULL; /* PC queue reg ptr */
|
||||||
int32 hst_p = 0; /* history pointer */
|
int32 hst_p = 0; /* history pointer */
|
||||||
int32 hst_lnt = 0; /* history length */
|
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_int_char;
|
||||||
extern int32 sim_interval;
|
extern int32 sim_interval;
|
||||||
|
@ -1510,7 +1516,7 @@ t_stat Ia (int32 ma, int32 *ea, t_bool jmp)
|
||||||
int32 t;
|
int32 t;
|
||||||
t_stat sta = MM_OK;
|
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 */
|
Read (ma, &t, DF); /* add 1 before use */
|
||||||
t = (t + 1) & DMASK;
|
t = (t + 1) & DMASK;
|
||||||
sta = Write (ma, t, DF); }
|
sta = Write (ma, t, DF); }
|
||||||
|
@ -1588,7 +1594,7 @@ t_stat Ia (int32 ma, int32 *ea, t_bool jmp)
|
||||||
int32 t;
|
int32 t;
|
||||||
t_stat sta = MM_OK;
|
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 */
|
ma = ma & 017; /* always in bank 0 */
|
||||||
Read (ma, &t, DF); /* +1 before use */
|
Read (ma, &t, DF); /* +1 before use */
|
||||||
t = (t + 1) & DMASK;
|
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 (usmd && (sw & SWMASK ('V'))) {
|
||||||
if (XVM) addr = RelocXVM (addr, REL_C);
|
if (XVM) addr = RelocXVM (addr, REL_C);
|
||||||
else if (RELOC) addr = Reloc15 (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
|
#endif
|
||||||
if (addr >= MEMSIZE) return SCPE_NXM;
|
if (addr >= MEMSIZE) return SCPE_NXM;
|
||||||
if (vptr != NULL) *vptr = M[addr] & DMASK;
|
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 (usmd && (sw & SWMASK ('V'))) {
|
||||||
if (XVM) addr = RelocXVM (addr, REL_C);
|
if (XVM) addr = RelocXVM (addr, REL_C);
|
||||||
else if (RELOC) addr = Reloc15 (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
|
#endif
|
||||||
if (addr >= MEMSIZE) return SCPE_NXM;
|
if (addr >= MEMSIZE) return SCPE_NXM;
|
||||||
M[addr] = val & DMASK;
|
M[addr] = val & DMASK;
|
||||||
|
@ -1933,11 +1939,20 @@ int32 i, lnt;
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
if (cptr == NULL) {
|
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; }
|
return SCPE_OK; }
|
||||||
lnt = (int32) get_uint (cptr, 10, HIST_SIZE, &r);
|
lnt = (int32) get_uint (cptr, 10, HIST_MAX, &r);
|
||||||
if (r != SCPE_OK) return SCPE_ARG;
|
if ((r != SCPE_OK) || (lnt && (lnt < HIST_MIN))) return SCPE_ARG;
|
||||||
hst_lnt = lnt;
|
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;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1952,25 +1967,26 @@ extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
|
||||||
UNIT *uptr, int32 sw);
|
UNIT *uptr, int32 sw);
|
||||||
|
|
||||||
if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */
|
if (hst_lnt == 0) return SCPE_NOFNC; /* enabled? */
|
||||||
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 */
|
for (k = 0; k < hst_lnt; k++) { /* print specified */
|
||||||
h = &hst[(di++) % HIST_SIZE]; /* entry pointer */
|
h = &hst[(di++) % hst_lnt]; /* entry pointer */
|
||||||
if (h->pc == 0) continue; /* filled in? */
|
if (h->pc & HIST_PC) { /* instruction? */
|
||||||
if (h->pc & (HIST_API | HIST_PI)) { /* interrupt event? */
|
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? */
|
if (h->pc & HIST_PI) /* PI? */
|
||||||
fprintf (st, "%06o PI LVL 0-4 =", h->pc & AMASK);
|
fprintf (st, "%06o PI LVL 0-4 =", h->pc & AMASK);
|
||||||
else fprintf (st, "%06o API %d LVL 0-4 =", h->pc & AMASK, h->mq);
|
else fprintf (st, "%06o API %d LVL 0-4 =", h->pc & AMASK, h->mq);
|
||||||
for (j = API_HLVL; j >= 0; j--)
|
for (j = API_HLVL; j >= 0; j--)
|
||||||
fprintf (st, " %02o", (h->ir >> (j * HIST_V_LVL)) & HIST_M_LVL);
|
fprintf (st, " %02o", (h->ir >> (j * HIST_V_LVL)) & HIST_M_LVL);
|
||||||
}
|
}
|
||||||
else { /* instruction */
|
else continue; /* invalid */
|
||||||
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 */
|
|
||||||
fputc ('\n', st); /* end line */
|
fputc ('\n', st); /* end line */
|
||||||
} /* end for */
|
} /* end for */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -1980,13 +1996,17 @@ return SCPE_OK;
|
||||||
|
|
||||||
void cpu_inst_hist (int32 addr, int32 inst)
|
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;
|
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;
|
hst[hst_p].ir1 = 0;
|
||||||
|
else hst[hst_p].ir1 = word;
|
||||||
hst[hst_p].lac = LAC;
|
hst[hst_p].lac = LAC;
|
||||||
hst[hst_p].mq = MQ;
|
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;
|
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].ir1 = 0;
|
||||||
hst[hst_p].lac = 0;
|
hst[hst_p].lac = 0;
|
||||||
hst[hst_p].mq = lvl;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
18-Oct-03 RMS Added DECtape off reel message
|
||||||
18-Jul-03 RMS Added FP15 support
|
18-Jul-03 RMS Added FP15 support
|
||||||
Added XVM support
|
Added XVM support
|
||||||
Added EAE option for PDP-4
|
Added EAE option for PDP-4
|
||||||
|
@ -110,6 +111,7 @@
|
||||||
#define STOP_NONSTD 6 /* non-std dev num */
|
#define STOP_NONSTD 6 /* non-std dev num */
|
||||||
#define STOP_MME 7 /* mem mgt error */
|
#define STOP_MME 7 /* mem mgt error */
|
||||||
#define STOP_FPDIS 8 /* fp inst, fpp disabled */
|
#define STOP_FPDIS 8 /* fp inst, fpp disabled */
|
||||||
|
#define STOP_DTOFF 9 /* DECtape off reel */
|
||||||
|
|
||||||
/* Peripheral configuration */
|
/* Peripheral configuration */
|
||||||
|
|
||||||
|
|
|
@ -154,6 +154,7 @@ The 18b PDP simulators implement several unique stop conditions:
|
||||||
instruction execution
|
instruction execution
|
||||||
- an FP15 instruction is decoded, the FP15 is disabled,
|
- an FP15 instruction is decoded, the FP15 is disabled,
|
||||||
and register STOP_FPP is set
|
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
|
The PDP-4 and PDP-7 LOAD command supports only "second stage" RIM format
|
||||||
files (alternating DAC address instructions and data):
|
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
|
"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 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)
|
2.2 Floating Point Processor (FPP)
|
||||||
|
|
||||||
The PDP-15 features an optional floating point processor, the FP15 (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 CA 18 current address (memory location 30)
|
||||||
9,15 WC 18 word count (memory location 31)
|
9,15 WC 18 word count (memory location 31)
|
||||||
all LTIME 31 time between lines
|
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 DCTIME 31 time to decelerate to a full stop
|
||||||
all SUBSTATE 2 read/write command substate
|
all SUBSTATE 2 read/write command substate
|
||||||
all POS[0:7] 32 position, in lines, units 0-7
|
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.
|
operate correctly.
|
||||||
|
|
||||||
- LTIME must be at least 6
|
- LTIME must be at least 6
|
||||||
- ACTIME must be less than DCTIME, and both need to be at
|
- DCTIME needs to be at least 100 times LTIME
|
||||||
least 100 times LTIME
|
|
||||||
|
Acceleration time is set to 75% of deceleration time.
|
||||||
|
|
||||||
2.9 TC59/TU10 Magnetic Tape (MT)
|
2.9 TC59/TU10 Magnetic Tape (MT)
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
drm (PDP-4,PDP-7) Type 24 serial drum
|
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
|
05-Dec-02 RMS Updated from Type 24 documentation
|
||||||
22-Nov-02 RMS Added PDP-4 support
|
22-Nov-02 RMS Added PDP-4 support
|
||||||
05-Feb-02 RMS Added DIB, device number support
|
05-Feb-02 RMS Added DIB, device number support
|
||||||
|
@ -165,6 +166,7 @@ t_stat drm_svc (UNIT *uptr)
|
||||||
{
|
{
|
||||||
int32 i;
|
int32 i;
|
||||||
uint32 da;
|
uint32 da;
|
||||||
|
int32 *fbuf = uptr->filebuf;
|
||||||
|
|
||||||
if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
|
if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
|
||||||
drm_err = 1; /* set error */
|
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 */
|
da = drm_da * DRM_NUMWDS; /* compute dev addr */
|
||||||
for (i = 0; i < DRM_NUMWDS; i++, da++) { /* do transfer */
|
for (i = 0; i < DRM_NUMWDS; i++, da++) { /* do transfer */
|
||||||
if (uptr->FUNC == DRM_READ) {
|
if (uptr->FUNC == DRM_READ) { /* read? */
|
||||||
if (MEM_ADDR_OK (drm_ma)) /* read, check nxm */
|
if (MEM_ADDR_OK (drm_ma)) /* if !nxm */
|
||||||
M[drm_ma] = *(((int32 *) uptr->filebuf) + da); }
|
M[drm_ma] = fbuf[da]; } /* read word */
|
||||||
else {
|
else { /* write */
|
||||||
if ((drm_wlk >> (drm_da >> 4)) & 1) drm_err = 1;
|
if ((drm_wlk >> (drm_da >> 4)) & 1) drm_err = 1;
|
||||||
else {
|
else { /* not locked */
|
||||||
*(((int32 *) uptr->filebuf) + da) = M[drm_ma];
|
fbuf[da] = M[drm_ma]; /* write word */
|
||||||
if (da >= uptr->hwmark) uptr->hwmark = da + 1; } }
|
if (da >= uptr->hwmark) uptr->hwmark = da + 1; } }
|
||||||
drm_ma = (drm_ma + 1) & 0177777; } /* incr mem addr */
|
drm_ma = (drm_ma + 1) & 0177777; } /* incr mem addr */
|
||||||
drm_da = (drm_da + 1) & DRM_SMASK; /* incr dev addr */
|
drm_da = (drm_da + 1) & DRM_SMASK; /* incr dev addr */
|
||||||
|
|