Notes For V3.8
The makefile now works for Linux and most Unix's. However, for Solaris and MacOS, you must first export the OSTYPE environment variable: > export OSTYPE > make Otherwise, you will get build errors. 1. New Features 1.1 3.8-0 1.1.1 SCP and Libraries - BREAK, NOBREAK, and SHOW BREAK with no argument will set, clear, and show (respectively) a breakpoint at the current PC. 1.1.2 GRI - Added support for the GRI-99 processor. 1.1.3 HP2100 - Added support for the BACI terminal interface. - Added support for RTE OS/VMA/EMA, SIGNAL, VIS firmware extensions. 1.1.4 Nova - Added support for 64KW memory (implemented in third-party CPU's). 1.1.5 PDP-11 - Added support for DC11, RC11, KE11A, KG11A. - Added modem control support for DL11. - Added ASCII character support for all 8b devices. 1.2 3.8-1 1.2.1 SCP and libraries - Added capability to set line connection order for terminal multiplexers. 1.2.2 HP2100 - Added support for 12620A/12936A privileged interrupt fence. - Added support for 12792C eight-channel asynchronous multiplexer. 1.3 3.8-2 1.3.1 SCP and libraries - Added line history capability for *nix hosts. - Added "SHOW SHOW" and "SHOW <dev> SHOW" commands. 1.3.2 1401 - Added "no rewind" option to magtape boot. 1.3.3 PDP-11 - Added RD32 support to RQ - Added debug support to RL 1.3.4 PDP-8 - Added FPP support (many thanks to Rick Murphy for debugging the code) 1.3.5 VAX-11/780 - Added AUTORESTART switch support, and VMS REBOOT command support 2. Bugs Fixed Please see the revision history on http://simh.trailing-edge.com or in the source module sim_rev.h.
This commit is contained in:
parent
35eac703c3
commit
a9fd3dd518
77 changed files with 12846 additions and 1522 deletions
|
@ -51,19 +51,28 @@ Otherwise, you will get build errors.
|
|||
|
||||
1.3 3.8-2
|
||||
|
||||
1.3.1 1401
|
||||
1.3.1 SCP and libraries
|
||||
|
||||
- Added line history capability for *nix hosts.
|
||||
- Added "SHOW SHOW" and "SHOW <dev> SHOW" commands.
|
||||
|
||||
1.3.2 1401
|
||||
|
||||
- Added "no rewind" option to magtape boot.
|
||||
|
||||
1.3.2 PDP-11
|
||||
1.3.3 PDP-11
|
||||
|
||||
- Added RD32 support to RQ
|
||||
- Added debug support to RL
|
||||
|
||||
1.3.3 PDP-8
|
||||
1.3.4 PDP-8
|
||||
|
||||
- Added FPP support (many thanks to Rick Murphy for debugging the code)
|
||||
|
||||
1.3.5 VAX-11/780
|
||||
|
||||
- Added AUTORESTART switch support, and VMS REBOOT command support
|
||||
|
||||
|
||||
2. Bugs Fixed
|
||||
|
||||
|
|
|
@ -2,45 +2,125 @@ This file contains information about the SIMH Ethernet package.
|
|||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
The XQ emulator is a host-independant software emulation of Digital's
|
||||
DELQA (M7516) and DEQNA (M7504) Q-bus ethernet cards for the SIMH emulator.
|
||||
The XQ emulator is a host-independent software emulation of Digital's
|
||||
DELQA-T (M7516-YM), DELQA (M7516) and DEQNA (M7504) Q-bus Ethernet cards
|
||||
for the SIMH emulator.
|
||||
|
||||
The XU emulator is a host-independant software emulation of Digital's DEUNA
|
||||
(M7792/M7793) and DELUA (M7521) Unibus ethernet cards for the SIMH emulator.
|
||||
The XU emulator is a host-independent software emulation of Digital's DEUNA
|
||||
(M7792/M7793) and DELUA (M7521) Unibus Ethernet cards for the SIMH emulator.
|
||||
|
||||
The XQ and XU simulators use the Sim_Ether module to execute host-specific
|
||||
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. See the comments at the top of sim_ether.c
|
||||
for the list of currently supported host platforms.
|
||||
|
||||
The Sim_Ether module sets the selected ethernet card into
|
||||
The Sim_Ether module sets the selected Ethernet card into
|
||||
promiscuous mode to gather all packets, then filters out the packets that it
|
||||
doesn't want. In Windows, packets having the same source MAC address as the
|
||||
controller are ignored for WinPCAP compatibility (see Windows notes below).
|
||||
|
||||
If your ethernet card is plugged into a switch, the promiscuous mode setting
|
||||
If your Ethernet card is plugged into a switch, the promiscuous mode setting
|
||||
should not cause much of a problem, since the switch will still filter out
|
||||
most of the undesirable traffic. You will only see "excessive" traffic if you
|
||||
are on a 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.
|
||||
On Windows using the WinPcap interface, the simulated computer can "talk" to
|
||||
the host computer on the same interface. On other platforms with libpcap
|
||||
(*nix), the simulated computer can not "talk" to the host computer via the
|
||||
selected interface, since simulator transmitted packets are not received
|
||||
by the host's network stack. 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.
|
||||
Integrated 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 a pseudo network interface, 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.
|
||||
|
||||
Integrated Universal TUN/TAP support can be used for host<->simulator network
|
||||
traffic (on the platforms where it is available) by using the SIMH command:
|
||||
"attach xq tap:tapN" (i.e. attach xq tap:tap0). Platforms that this has been
|
||||
tested on include: Linux, FreeBSD, OpenBSD, NetBSD. Each of these platforms
|
||||
has some way to create a tap pseudo device and then bridge it with a physical
|
||||
network interface.
|
||||
|
||||
The following steps were performed to get a working SIMH vax simulator
|
||||
sharing a physical NIC and allowing Host<->SIMH vax communications:
|
||||
|
||||
Linux (Ubuntu 10.04):
|
||||
apt-get install bridge-utils
|
||||
apt-get install uml-utilities
|
||||
|
||||
|
||||
#!/bin/sh
|
||||
HOSTIP=`/sbin/ifconfig eth0 | grep "inet addr" | gawk -- '{ print $2 }' | gawk -F : -- '{ print $2 }'`
|
||||
HOSTNETMASK=`/sbin/ifconfig eth0 | grep "inet addr" | gawk -- '{ print $4 }' | gawk -F : -- '{ print $2 }'`
|
||||
HOSTBCASTADDR=`/sbin/ifconfig eth0 | grep "inet addr" | gawk -- '{ print $3 }' | gawk -F : -- '{ print $2 }'`
|
||||
HOSTDEFAULTGATEWAY=`/sbin/route -n | grep ^0.0.0.0 | gawk -- '{ print $2 }'`
|
||||
#
|
||||
/usr/sbin/tunctl -t tap0 [-u someuser]
|
||||
/sbin/ifconfig tap0 up
|
||||
#
|
||||
# Now convert eth0 to a bridge and bridge it with the TAP interface
|
||||
/usr/sbin/brctl addbr br0
|
||||
/usr/sbin/brctl addif br0 eth0
|
||||
/usr/sbin/brctl setfd br0 0
|
||||
/sbin/ifconfig eth0 0.0.0.0
|
||||
/sbin/ifconfig br0 $HOSTIP netmask $HOSTNETMASK broadcast $HOSTBCASTADDR up
|
||||
# set the default route to the br0 interface
|
||||
/sbin/route add -net 0.0.0.0/0 gw $HOSTDEFAULTGATEWAY
|
||||
# bridge in the tap device
|
||||
/usr/sbin/brctl addif br0 tap0
|
||||
/sbin/ifconfig tap0 0.0.0.0
|
||||
|
||||
# Run simulator and "attach xq tap:tap0"
|
||||
|
||||
OpenBSD (OpenBSD 4.6)
|
||||
|
||||
/sbin/ifconfig tun0 create
|
||||
/sbin/ifconfig tun0 link0
|
||||
/sbin/ifconfig tun0 up
|
||||
|
||||
/sbin/ifconfig bridge0 create
|
||||
/sbin/brconfig bridge0 fwddelay 4
|
||||
/sbin/brconfig bridge0 add em0 add tun0 # Change em0 to reflect your physical NIC name
|
||||
/sbin/brconfig bridge0 up
|
||||
|
||||
# Run simulator and "attach xq tap:tun0"
|
||||
|
||||
FreeBSD (FreeBSD 8.0)
|
||||
|
||||
/sbin/ifconfig tap0 create
|
||||
/sbin/ifconfig tap0 up
|
||||
|
||||
/sbin/ifconfig bridge0 create
|
||||
/sbin/ifconfig bridge0 addm em0 addm tap0 # Change em0 to reflect your physical NIC name
|
||||
/sbin/ifconfig bridge0 up
|
||||
|
||||
# Run simulator and "attach xq tap:tap0"
|
||||
# Note: it seems that on FreeBSD you may have to
|
||||
# "/sbin/ifconfig tap0 up" and "/sbin/ifconfig bridge0 up" prior to each
|
||||
# time simh "attach"es the tap:tap0 device
|
||||
|
||||
NetBSD (NetBSD 5.0.2)
|
||||
|
||||
/sbin/ifconfig tap0 create
|
||||
/sbin/ifconfig tap0 up
|
||||
|
||||
/sbin/ifconfig bridge0 create
|
||||
/sbin/brconfig bridge0 fwddelay 1
|
||||
/sbin/brconfig bridge0 add wm0 add tap0 # Change wm0 to reflect your physical NIC name
|
||||
/sbin/brconfig bridge0 up
|
||||
|
||||
# Run simulator and "attach xq tap:tap0"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Windows notes:
|
||||
1. The Windows-specific code uses the WinPCAP 3.0 package from
|
||||
1. The Windows-specific code uses the WinPCAP 4.x package from
|
||||
http://www.winpcap.org. This package for windows simulates the libpcap
|
||||
package that is freely available for un*x systems.
|
||||
|
||||
|
@ -48,29 +128,27 @@ Windows notes:
|
|||
|
||||
3. The first time the WinPCAP driver is used, it will be dynamically loaded,
|
||||
and the user must be an Administrator on the machine to do so. If you need
|
||||
to run as an unprivileged user, you must set the service to autostart. See
|
||||
the WinPCAP documentation for details on the static loading workaround.
|
||||
|
||||
4. If you want to use TAP devices, they must be created before running SIMH.
|
||||
(TAP component from the OpenVPN project; http://openvpn.sourceforge.net)
|
||||
|
||||
5. Compaq PATHWORKS 32 v7.2 also enabled bridging for the ethernet adapters
|
||||
when the DECNET and LAT drivers were installed; TAP was not needed.
|
||||
to run as an unprivileged user, you must set the "npf" driver to autostart.
|
||||
Current WinPcap installers provide an option to configure this at
|
||||
installation time.
|
||||
|
||||
|
||||
Building on Windows:
|
||||
1. Install WinPCAP 3.0 runtime and the WinPCAP Developer's kit.
|
||||
1. Install WinPCAP 4.x runtime and the WinPCAP Developer's kit.
|
||||
|
||||
2. Put the required .h files (bittypes,devioctl,ip6_misc,packet32,pcap,
|
||||
pcap-stdinc).h from the WinPCAP 3.0 developer's kit in the compiler's path
|
||||
2. Put the required .h files (bittypes,devioctl,ip6_misc,pcap,pcap-stdinc
|
||||
packet32,ntddndis).h from the WinPCAP 4.x developer's kit in the
|
||||
compiler's include file path
|
||||
|
||||
3. Put the required .lib files (packet,wpcap).lib from the WinPCAP 3.0
|
||||
developer's kit in the linker's path
|
||||
3. Put the required .lib files (packet,wpcap).lib from the WinPCAP 4.x
|
||||
developer's kit in the linker's library path
|
||||
|
||||
4. If you're using Borland C++, use COFF2OMF to convert the .lib files into
|
||||
a format that can be used by the compiler.
|
||||
|
||||
5. Define USE_NETWORK.
|
||||
5. Define USE_NETWORK. The current windows network built binaries will
|
||||
run on any system. regardless of whether or not WinPcap is installed,
|
||||
and will provide Network functionality when WinPcap is available.
|
||||
|
||||
6. Build it!
|
||||
|
||||
|
@ -85,28 +163,31 @@ need to get a version of libpcap that is 0.9 or greater. This can be
|
|||
downloaded from www.tcpdump.org - see the comments at the top of Sim_ether.c
|
||||
for details.
|
||||
|
||||
At the time of this release, the "Current Version" available at:
|
||||
http://www.tcpdump.org/daily/libpcap-current.tar.gz is the
|
||||
latest checked-in source code that is actually higher than the released
|
||||
0.8.3 version number. Specifically, for all platforms, it contains code that
|
||||
opens the ethernet device in Read/Write mode instead of the Read-Only mode
|
||||
that previous libpcap versions for platforms which use one of pcap-bpf.c,
|
||||
pcap-pf.c, or pcap-snit.c. This capabiligy now exists to support a newly
|
||||
provided generic packet sending capability.
|
||||
|
||||
----- WARNING ----- WARNING ----- WARNING ----- WARNING ----- WARNING -----
|
||||
|
||||
1. For all platforms, you must run SIMH(scp) with sufficient privilege to
|
||||
allow the ethernet card can be set into promiscuous mode and to write
|
||||
packets through the driver. For most Unix/Unix-like platforms this will
|
||||
mean running as root. For systems which use bpf devices (NetBSD,
|
||||
OpenBSD, FreeBSD and OS/X) it is possible to set permissions on the bpf
|
||||
devices to allow read and write access to users other than root (For
|
||||
example: chmod 666 /dev/bpf*). Doing this, has its own security issues.
|
||||
allow the Ethernet card can be set into promiscuous mode and to write
|
||||
packets through the driver.
|
||||
a) For Windows systems this means having administrator privileges to
|
||||
start the "npf" driver. The current WinPcap installer offers an
|
||||
option to autostart the "npf" driver when the system boots.
|
||||
b) For more recent Linux systems, The concepts leveraging "Filesystem
|
||||
Capabilities" can be used to specifically grant the simh binary
|
||||
the needed privileges to access the network. The article at:
|
||||
http://packetlife.net/blog/2010/mar/19/sniffing-wireshark-non-root-user/
|
||||
describes how to do this for wireshark. The exact same capabilities
|
||||
are needed by SIMH for network support. Use that article as a guide.
|
||||
c) For Unix/Unix-like systems which use bpf devices (NetBSD,
|
||||
OpenBSD, FreeBSD and OS/X) it is possible to set permissions on
|
||||
the bpf devices to allow read and write access to users other
|
||||
than root (For example: chmod 666 /dev/bpf*). Doing this, has
|
||||
its own security issues.
|
||||
d) For other platforms this will likely mean running as root.
|
||||
Additional alternative methods for avoiding the 'run as root' requirement
|
||||
will be welcomed.
|
||||
|
||||
2. If you want to use TAP devices, they must be created before running SIMH.
|
||||
2. If you want to use TAP devices, and any surrounding system network/bridge
|
||||
setup must be done before running SIMH.
|
||||
|
||||
Building on Linux, {Free|Net|Open}BSD, OS/X, Un*x:
|
||||
|
||||
|
@ -116,12 +197,18 @@ Building on Linux, {Free|Net|Open}BSD, OS/X, Un*x:
|
|||
Linux : search for your variant on http://rpmfind.net
|
||||
OS/X : Apple Developer's site?
|
||||
|
||||
NOTE: These repositories will not likely contain a version
|
||||
of libpcap greater than 0.8.1 for several years since
|
||||
other packages in these repositories don't depend on a
|
||||
later version than they currently have.
|
||||
NOTE: These repositories for older versions of these platforms
|
||||
don't contain a version of libpcap greater than 0.8.1.
|
||||
However, most(all) recent releases of *nix environments ship
|
||||
with sufficiently recent versions of libpcap either automatically
|
||||
installed or available for installation as part of the
|
||||
distribution.
|
||||
|
||||
2. Use 'make USE_NETWORK=1'
|
||||
2. If you install the vendor supplied libpcap-dev package and it provides
|
||||
a /usr/lib/libpcap.a file, then the existing makefile will automatically
|
||||
use the vendor supplied library without any additional arguments.
|
||||
If you have downloaded and built the libpcap from tcpdump.org, then
|
||||
you can use it during a build by typing 'make USE_NETWORK=1'
|
||||
|
||||
3. Build it!
|
||||
|
||||
|
@ -132,27 +219,27 @@ OpenVMS Alpha notes:
|
|||
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
|
||||
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:
|
||||
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
|
||||
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. Note: This is done by the
|
||||
running a simulator with Ethernet support. Note: This is done by the
|
||||
build commands in descrip.mms.
|
||||
|
||||
3. You must have CMKRNL privilege to SHOW or ATTACH an ethernet device;
|
||||
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
|
||||
|
@ -162,13 +249,13 @@ OpenVMS Alpha notes:
|
|||
|
||||
Building on OpenVMS Alpha:
|
||||
The current descrip.mms file will build simulators capable of using
|
||||
ethernet support with them automatically. These currently are: VAX,
|
||||
Ethernet support with them automatically. These currently are: VAX,
|
||||
PDP11, and PDP10. The descrip.mms driven builds will also build the
|
||||
pcap library and build and install the VCI execlet.
|
||||
|
||||
1. Fetch the VMS-PCAP zip file from:
|
||||
http://simh.trailing-edge.com/sources/vms-pcap.zip
|
||||
2. Unzip it into the base of the simh distribution directory.
|
||||
2. Unzip it into the base of the SIMH distribution directory.
|
||||
3. Build the simulator(s) with MMS or MMK:
|
||||
$ MMx {VAX,PDP11,PDP10, etc...}
|
||||
|
||||
|
@ -195,15 +282,15 @@ RSX11M+ system image that also contains DECNET, LAT, and/or TCP/IP software.
|
|||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
How to debug problems with the ethernet subsystems:
|
||||
How to debug problems with the Ethernet subsystems:
|
||||
|
||||
PLEASE read the host-specific notes in sim_ether.c!
|
||||
|
||||
While running SCP, the following commands can be used to enable debug messages:
|
||||
|
||||
scp> SET DEBUG STDERR
|
||||
scp> SET XQ DEBUG={ETH|TRC|REG|WRN|CSR|VAR|SAN|SET|PCK}
|
||||
scp> SET XU DEBUG={ETH|TRC|REG|WRN}
|
||||
sim> SET DEBUG STDERR
|
||||
sim> SET XQ DEBUG=TRACE;CSR;VAR;WARN;SETUP;SANITY;REG;PACKET;DATA;ETH
|
||||
sim> SET XU DEBUG=ETH;TRACE;REG;WARN;PACKET;DATA
|
||||
|
||||
Documentation of the functionality of these debug modifiers can be found in
|
||||
pdp11_xq.h and pdp11_xu.h. Inline debugging has replaced the previous #ifdef
|
||||
|
@ -212,16 +299,13 @@ style of debugging, which required recompilation before debugging.
|
|||
-------------------------------------------------------------------------------
|
||||
|
||||
Things planned for future releases:
|
||||
1. PDP-11 bootstrap/bootrom
|
||||
2. Full MOP implementation
|
||||
3. DESQA support (if someone can get me the user manuals)
|
||||
4. DETQA support [DELQA-Turbo] (I have the manual)
|
||||
1. Full MOP implementation
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Things which I need help with:
|
||||
1. Information about Remote MOP processing
|
||||
2. VAX/PDP-11 hardware diagnotics image files and docs, to test XQ thoroughly.
|
||||
2. VAX/PDP-11 hardware diagnostics image files and docs, to test XQ thoroughly.
|
||||
3. Feedback on operation with other VAX/PDP-11 OS's.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
@ -237,11 +321,160 @@ Dave
|
|||
Change Log
|
||||
===============================================================================
|
||||
|
||||
12-Jan-11 DTH Added SHOW XU FILTERS modifier
|
||||
11-Jan-11 DTH Corrected DEUNA/DELUA SELFTEST command, enabling use by
|
||||
VMS 3.7, VMS 4.7, and Ultrix 1.1
|
||||
09-Jan-11 MP Fixed missing crc data when USE_READER_THREAD is defined and
|
||||
crc's are needed (only the pdp11_xu)
|
||||
16-Dec-10 MP added priority boost for read and write threads when
|
||||
USE_READER_THREAD does I/O in separate threads. This helps
|
||||
throughput since it allows these I/O bound threads to preempt
|
||||
the main thread (which is executing simulated instructions).
|
||||
09-Dec-10 MP allowed more flexible parsing of MAC address strings
|
||||
09-Dec-10 MP Added support to determine if network address conflicts exist
|
||||
07-Dec-10 MP Reworked DECnet self detection to the more general approach
|
||||
of loopback self when any Physical Address is being set.
|
||||
06-Dec-10 MP Added loopback processing support to pdp11_xu.c
|
||||
06-Dec-10 MP Fixed loopback processing to correctly handle forward packets.
|
||||
04-Dec-10 MP Changed eth_write to do nonblocking writes when
|
||||
USE_READER_THREAD is defined.
|
||||
30-Nov-10 MP Fixed the fact that no broadcast packets were received by the DEUNA
|
||||
29-Nov-10 MP Fixed interrupt dispatch issue which caused delivered packets
|
||||
(in and out) to sometimes not interrupt the CPU after processing.
|
||||
17-Jun-10 MP Fixed bug in the AUTODIN II hash filtering.
|
||||
14-Jun-10 MP Added support for integrated Tap networking interfaces on BSD
|
||||
platforms.
|
||||
13-Jun-10 MP Added support for integrated Tap networking interfaces on Linux
|
||||
platforms.
|
||||
31-May-10 MP Added support for more TOE (TCP Offload Engine) features for IPv4
|
||||
network traffic from the host and/or from hosts on the LAN. These
|
||||
new TOE features are: LSO (Large Send Offload) and Jumbo packet
|
||||
fragmentation support. These features allow a simulated network
|
||||
device to support traffic when a host leverages a NIC's Large
|
||||
Send Offload capabilities to fragment and/or segment outgoing
|
||||
network traffic. Additionally a simulated network device can
|
||||
reasonably exist on a LAN which is configured to use Jumbo frames.
|
||||
21-May-10 MP Added functionality to fix up IP header checksums to accommodate
|
||||
packets from a host with a NIC which has TOE (TCP Offload Engine)
|
||||
enabled which is expected to implement the checksum computations
|
||||
in hardware. Since we catch packets before they arrive at the
|
||||
NIC the expected checksum insertions haven't been performed yet.
|
||||
This processing is only done for packets sent from the host to
|
||||
the guest we're supporting. In general this will be a relatively
|
||||
small number of packets so it is done for all IP frame packets
|
||||
coming from the host to the guest. In order to make the
|
||||
determination of packets specifically arriving from the host we
|
||||
need to know the hardware MAC address of the host NIC. Currently
|
||||
determining a NIC's MAC address is relatively easy on Windows.
|
||||
The non-windows code works on linux and may work on other *nix
|
||||
platforms either as is or with slight modifications. The code,
|
||||
as implemented, only messes with this activity if the host
|
||||
interface MAC address can be determined.
|
||||
20-May-10 MP Added general support to deal with receiving packets smaller
|
||||
than ETH_MIN_PACKET in length. These come from packets
|
||||
looped back by some bridging mechanism and need to be padded
|
||||
to the minimum frame size. A real NIC won't pass us any
|
||||
packets like that. This fix belongs here since this layer
|
||||
is responsible for interfacing to the physical layer
|
||||
devices, AND it belongs here to get CRC processing right.
|
||||
15-Aug-08 MP Fixed transmitted packets to have the correct source MAC address.
|
||||
Fixed incorrect address filter setting calling eth_filter().
|
||||
07-Mar-08 MP Fixed the SCP visible SA registers to always display the
|
||||
ROM MAC address, even after it is changed by SET XQ MAC=.
|
||||
07-Mar-08 MP Added changes so that the Console DELQA diagnostic (>>>TEST 82)
|
||||
will succeed.
|
||||
03-Mar-08 MP Added DELQA-T (aka DELQA Plus) device emulation support.
|
||||
06-Feb-08 MP Added dropped frame statistics to record when the receiver discards
|
||||
received packets due to the receiver being disabled, or due to the
|
||||
XQ device's packet receive queue being full.
|
||||
Fixed bug in receive processing when we're not polling. This could
|
||||
cause receive processing to never be activated again if we don't
|
||||
read all available packets via eth_read each time we get the
|
||||
opportunity.
|
||||
31-Jan-08 MP Added the ability to Coalesce received packet interrupts. This
|
||||
is enabled by SET XQ POLL=DELAY=nnn where nnn is a number of
|
||||
microseconds to delay the triggering of an interrupt when a packet
|
||||
is received.
|
||||
29-Jan-08 MP Added SET XQ POLL=DISABLE (aka SET XQ POLL=0) to operate without
|
||||
polling for packet read completion.
|
||||
29-Jan-08 MP Changed the sanity and id timer mechanisms to use a separate timer
|
||||
unit so that transmit and receive activities can be dealt with
|
||||
by the normal xq_svc routine.
|
||||
Dynamically determine the timer polling rate based on the
|
||||
calibrated tmr_poll and clk_tps values of the simulator.
|
||||
25-Jan-08 MP Enabled the SET XQ POLL to be meaningful if the simulator currently
|
||||
doesn't support idling.
|
||||
25-Jan-08 MP Changed xq_debug_setup to use sim_debug instead of printf so that
|
||||
all debug output goes to the same place.
|
||||
25-Jan-08 MP Restored the call to xq_svc after all successful calls to eth_write
|
||||
to allow receive processing to happen before the next event
|
||||
service time. This must have been inadvertently commented out
|
||||
while other things were being tested.
|
||||
23-Jan-08 MP Added debugging support to display packet headers and packet data
|
||||
18-Jun-07 RMS Added UNIT_IDLE flag
|
||||
29-Oct-06 RMS Synced poll and clock
|
||||
27-Jan-06 RMS Fixed unaligned accesses in XQB (found by Doug Carman)
|
||||
07-Jan-06 RMS Fixed unaligned access bugs (found by Doug Carman)
|
||||
07-Sep-05 DTH Removed unused variable
|
||||
16-Aug-05 RMS Fixed C++ declaration and cast problems
|
||||
|
||||
05-Mar-08 MP Added optional multicast filtering support for doing
|
||||
LANCE style AUTODIN II based hashed filtering.
|
||||
07-Feb-08 MP Added eth_show_dev to display Ethernet state
|
||||
Changed the return value from eth_read to return whether
|
||||
or not a packet was read. No existing callers used or
|
||||
checked constant return value that previously was being
|
||||
supplied.
|
||||
29-Jan-08 MP Added eth_set_async to provide a mechanism (when
|
||||
USE_READER_THREAD is enabled) to allow packet reception
|
||||
to dynamically update the simulator event queue and
|
||||
potentially avoid polling for I/O. This provides a minimal
|
||||
overhead (no polling) maximal responsiveness for network
|
||||
activities.
|
||||
29-Jan-08 MP Properly sequenced activities in eth_close to avoid a race
|
||||
condition when USE_READER_THREAD is enabled.
|
||||
25-Jan-08 MP Changed the following when USE_READER_THREAD is enabled:
|
||||
- Fixed bug when the simulated device doesn't need crc
|
||||
in packet data which is read.
|
||||
- Added call to pcap_setmintocopy to minimize packet
|
||||
delivery latencies.
|
||||
- Added ethq_destroy and used it to avoid a memory leak in
|
||||
eth_close.
|
||||
- Properly cleaned up pthread mutexes in eth_close.
|
||||
Migrated to using sim_os_ms_sleep for a delay instead of
|
||||
a call to select().
|
||||
Fixed the bpf filter used when no traffic is to be matched.
|
||||
Reworked eth_add_packet_crc32 implementation to avoid an
|
||||
extra buffer copy while reading packets.
|
||||
Fixed up #ifdef's relating to USE_SHARED so that setting
|
||||
USE_SHARED or USE_NETWORK will build a working network
|
||||
environment.
|
||||
23-Jan-08 MP Reworked eth_packet_trace and eth_packet_trace_ex to allow
|
||||
only output Ethernet header+crc and provide a mechanism for
|
||||
the simulated device to display full packet data debugging.
|
||||
17-May-07 DTH Fixed non-Ethernet device removal loop (from Naoki Hamada)
|
||||
15-May-07 DTH Added dynamic loading of wpcap.dll;
|
||||
Corrected exceed max index bug in ethX lookup
|
||||
04-May-07 DTH Corrected failure to look up Ethernet device names in
|
||||
the registry on Windows XP x64
|
||||
10-Jul-06 RMS Fixed linux conditionalization (from Chaskiel Grundman)
|
||||
02-Jun-06 JDB Fixed compiler warning for incompatible sscanf parameter
|
||||
15-Dec-05 DTH Patched eth_host_devices [remove non-Ethernet devices]
|
||||
(from Mark Pizzolato and Galen Tackett, 08-Jun-05)
|
||||
Patched eth_open [tun fix](from Antal Ritter, 06-Oct-05)
|
||||
30-Nov-05 DTH Added option to regenerate CRC on received packets; some
|
||||
Ethernet devices need to pass it on to the simulation, and by
|
||||
the time libpcap/winpcap gets the packet, the host OS network
|
||||
layer has already stripped CRC out of the packet
|
||||
01-Dec-04 DTH Added Windows user-defined adapter names (from Timothe Litt)
|
||||
|
||||
|
||||
|
||||
19-Mar-04 Release:
|
||||
1. Genericized Sim_Ether code, reduced #ifdefs (David Hittner)
|
||||
2. Further refinement of sim_ether, qualified more platforms (Mark Pizzolato)
|
||||
3. Added XU module (David Hittner)
|
||||
4. Corrected XQ interrupt signalling for PDP11s (David Hittner)
|
||||
4. Corrected XQ interrupt signaling for PDP11s (David Hittner)
|
||||
5. Added inline debugging support (David Hittner)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
@ -251,7 +484,7 @@ Dave
|
|||
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 Sofware Reset (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)
|
||||
|
@ -271,7 +504,7 @@ Dave
|
|||
1. Corrected bug in xq_setmac introduced in v3.0 (multiple people)
|
||||
2. Made XQ rcv buffer allocation dynamic to reduce scp size (David Hittner)
|
||||
3. Optimized some structs, removed legacy variables (Mark Pizzolato)
|
||||
4. Changed #ifdef WIN32 to _WIN32 for consistancy (Mark Pizzolato)
|
||||
4. Changed #ifdef WIN32 to _WIN32 for consistency (Mark Pizzolato)
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
@ -308,7 +541,7 @@ Dave
|
|||
|
||||
08-Nov-02 Release:
|
||||
1. Added USE_NETWORK conditional to Sim_Ether
|
||||
2. Fixed behaviour of SHOW XQ ETH if no devices exist
|
||||
2. Fixed behavior of SHOW XQ ETH if no devices exist
|
||||
3. Added OpenBSD support to Sim_Ether (courtesy of Federico Schwindt)
|
||||
4. Added ethX detection simplification (from Megan Gentry)
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@
|
|||
#define OUT_MSG (1 << 1)
|
||||
#define CMD_MSG (1 << 2)
|
||||
#define VERBOSE_MSG (1 << 3)
|
||||
#define BUFFER_EMPTY_MSG (1 << 4)
|
||||
|
||||
#define UNIT_V_SIO_ANSI (UNIT_V_UF + 0) /* ANSI mode, strip bit 8 on output */
|
||||
#define UNIT_SIO_ANSI (1 << UNIT_V_SIO_ANSI)
|
||||
|
@ -164,6 +165,7 @@ static DEBTAB generic_dt[] = {
|
|||
{ "OUT", OUT_MSG },
|
||||
{ "CMD", CMD_MSG },
|
||||
{ "VERBOSE", VERBOSE_MSG },
|
||||
{ "BUFFEREMPTY", BUFFER_EMPTY_MSG },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
|
@ -256,7 +258,7 @@ static UNIT sio_unit = {
|
|||
100000, /* wait */
|
||||
FALSE, /* u3 = FALSE, no character available in buffer */
|
||||
FALSE, /* u4 = FALSE, terminal input is not attached to a file */
|
||||
FALSE, /* u5 = FALSE, terminal input has not yet reached EOF */
|
||||
0, /* u5 = 0, not used */
|
||||
0 /* u6 = 0, not used */
|
||||
};
|
||||
|
||||
|
@ -267,7 +269,6 @@ static REG sio_reg[] = {
|
|||
{ DRDATA (WRNPTRE, warnPTREOF, 32) },
|
||||
{ DRDATA (WRUPORT, warnUnassignedPort, 32) },
|
||||
{ HRDATA (FILEATT, sio_unit.u4, 8), REG_RO }, /* TRUE iff terminal input is attached to a file */
|
||||
{ HRDATA (FILEEOF, sio_unit.u5, 8), REG_RO }, /* TRUE iff terminal input file has reached EOF */
|
||||
{ HRDATA (TSTATUS, sio_unit.u3, 8) }, /* TRUE iff a character available in sio_unit.buf */
|
||||
{ DRDATA (TBUFFER, sio_unit.buf, 8) }, /* input buffer for one character */
|
||||
{ DRDATA (KEYBDI, keyboardInterrupt, 3), REG_RO },
|
||||
|
@ -412,7 +413,6 @@ static t_stat sio_attach(UNIT *uptr, char *cptr) {
|
|||
return tmxr_attach(&altairTMXR, uptr, cptr); /* attach mux */
|
||||
}
|
||||
sio_unit.u4 = TRUE; /* terminal input is attached to a file */
|
||||
sio_unit.u5 = FALSE; /* EOF not yet reached */
|
||||
return attach_unit(uptr, cptr);
|
||||
}
|
||||
|
||||
|
@ -440,11 +440,10 @@ static t_stat sio_reset(DEVICE *dptr) {
|
|||
int32 i;
|
||||
TRACE_PRINT(sio_dev, VERBOSE_MSG, ("SIO: " ADDRESS_FORMAT " Reset" NLP, PCX));
|
||||
sio_unit.u3 = FALSE; /* no character in terminal input buffer */
|
||||
sio_unit.buf = 0;
|
||||
resetSIOWarningFlags();
|
||||
if (sio_unit.u4) { /* is terminal input attached to a file? */
|
||||
if (sio_unit.u4) /* is terminal input attached to a file? */
|
||||
rewind(sio_unit.fileref); /* yes, rewind input */
|
||||
sio_unit.u5 = FALSE; /* EOF not yet reached */
|
||||
}
|
||||
else if (sio_unit.flags & UNIT_ATT)
|
||||
for (i = 0; i < TERMINALS; i++)
|
||||
if (TerminalLines[i].conn)
|
||||
|
@ -457,6 +456,7 @@ static t_stat ptr_reset(DEVICE *dptr) {
|
|||
TRACE_PRINT(ptr_dev, VERBOSE_MSG, ("PTR: " ADDRESS_FORMAT " Reset" NLP, PCX));
|
||||
resetSIOWarningFlags();
|
||||
ptr_unit.u3 = FALSE; /* End Of File not yet reached */
|
||||
ptr_unit.buf = 0;
|
||||
if (ptr_unit.flags & UNIT_ATT) /* attached? */
|
||||
rewind(ptr_unit.fileref);
|
||||
sim_map_resource(0x12, 1, RESOURCE_TYPE_IO, &sio1s, dptr->flags & DEV_DIS);
|
||||
|
@ -629,15 +629,23 @@ static void voidSleep(void) {
|
|||
/* generic status port for keyboard input / terminal output */
|
||||
static int32 sio0sCore(const int32 port, const int32 io, const int32 data) {
|
||||
int32 ch, result;
|
||||
SIO_PORT_INFO spi = lookupPortInfo(port, &ch);
|
||||
const SIO_PORT_INFO spi = lookupPortInfo(port, &ch);
|
||||
assert(spi.port == port);
|
||||
pollConnection();
|
||||
if (io == 0) { /* IN */
|
||||
if (sio_unit.u4) { /* attached to a file? */
|
||||
if (sio_unit.u5) /* EOF reached? */
|
||||
sio_detach(&sio_unit); /* detach file and switch to keyboard input */
|
||||
else
|
||||
if (sio_unit.u3) /* character available? */
|
||||
return spi.sio_can_read | spi.sio_can_write;
|
||||
ch = getc(sio_unit.fileref);
|
||||
if (ch == EOF) {
|
||||
sio_detach(&sio_unit); /* detach file and switch to keyboard input */
|
||||
return spi.sio_cannot_read | spi.sio_can_write;
|
||||
}
|
||||
else {
|
||||
sio_unit.u3 = TRUE; /* indicate character available */
|
||||
sio_unit.buf = ch; /* store character in buffer */
|
||||
return spi.sio_can_read | spi.sio_can_write;
|
||||
}
|
||||
}
|
||||
if (sio_unit.flags & UNIT_ATT) { /* attached to a port? */
|
||||
if (tmxr_rqln(&TerminalLines[spi.terminalLine]))
|
||||
|
@ -658,19 +666,20 @@ static int32 sio0sCore(const int32 port, const int32 io, const int32 data) {
|
|||
if (ch == SCPE_STOP) { /* stop CPU in case ^E (default) was typed */
|
||||
stop_cpu = TRUE;
|
||||
sim_interval = 0; /* detect stop condition as soon as possible*/
|
||||
return spi.sio_can_write | spi.sio_cannot_read; /* do not consume stop character */
|
||||
return spi.sio_cannot_read | spi.sio_can_write; /* do not consume stop character */
|
||||
}
|
||||
sio_unit.u3 = TRUE; /* indicate character available */
|
||||
sio_unit.buf = ch; /* store character in buffer */
|
||||
return spi.sio_can_read | spi.sio_can_write;
|
||||
}
|
||||
checkSleep();
|
||||
return spi.sio_can_write | spi.sio_cannot_read;
|
||||
return spi.sio_cannot_read | spi.sio_can_write;
|
||||
} /* OUT follows, no fall-through from IN */
|
||||
if (spi.hasReset && (data == spi.sio_reset)) { /* reset command */
|
||||
if (!sio_unit.u4) /* only reset for regular console I/O */
|
||||
sio_unit.u3 = FALSE; /* indicate that no character is available */
|
||||
TRACE_PRINT(sio_dev, CMD_MSG,
|
||||
("SIO: " ADDRESS_FORMAT " Command OUT(0x%03x) = 0x%02x" NLP, PCX, port, data));
|
||||
("\tSIO_S: " ADDRESS_FORMAT " Command OUT(0x%03x) = 0x%02x" NLP, PCX, port, data));
|
||||
}
|
||||
return 0x00; /* ignored since OUT */
|
||||
}
|
||||
|
@ -678,32 +687,23 @@ static int32 sio0sCore(const int32 port, const int32 io, const int32 data) {
|
|||
int32 sio0s(const int32 port, const int32 io, const int32 data) {
|
||||
const int32 result = sio0sCore(port, io, data);
|
||||
if ((io == 0) && (sio_dev.dctrl & IN_MSG))
|
||||
printf("SIO_S: " ADDRESS_FORMAT " IN(0x%03x) = 0x%02x" NLP, PCX, port, result);
|
||||
printf("\tSIO_S: " ADDRESS_FORMAT " IN(0x%03x) = 0x%02x" NLP, PCX, port, result);
|
||||
else if ((io) && (sio_dev.dctrl & OUT_MSG))
|
||||
printf("SIO_S: " ADDRESS_FORMAT " OUT(0x%03x) = 0x%02x" NLP, PCX, port, data);
|
||||
printf("\tSIO_S: " ADDRESS_FORMAT " OUT(0x%03x) = 0x%02x" NLP, PCX, port, data);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* generic data port for keyboard input / terminal output */
|
||||
static int32 sio0dCore(const int32 port, const int32 io, const int32 data) {
|
||||
int32 ch;
|
||||
SIO_PORT_INFO spi = lookupPortInfo(port, &ch);
|
||||
const SIO_PORT_INFO spi = lookupPortInfo(port, &ch);
|
||||
assert(spi.port == port);
|
||||
pollConnection();
|
||||
if (io == 0) { /* IN */
|
||||
if (sio_unit.u4) { /* attached to a file? */
|
||||
if (sio_unit.u5) { /* EOF reached? */
|
||||
sio_detach(&sio_unit); /* detach file and switch to keyboard input */
|
||||
return CONTROLC_CHAR; /* this time return ^C after all */
|
||||
}
|
||||
if ((ch = getc(sio_unit.fileref)) == EOF) { /* end of file? */
|
||||
sio_unit.u5 = TRUE; /* terminal input file has reached EOF */
|
||||
return CONTROLC_CHAR; /* result is ^C (= CP/M interrupt) */
|
||||
}
|
||||
return mapCharacter(ch); /* return mapped character */
|
||||
}
|
||||
if (sio_unit.flags & UNIT_ATT)
|
||||
if ((sio_unit.flags & UNIT_ATT) && (!sio_unit.u4))
|
||||
return mapCharacter(tmxr_getc_ln(&TerminalLines[spi.terminalLine]));
|
||||
if ((!sio_unit.u3) && (sio_dev.dctrl & BUFFER_EMPTY_MSG))
|
||||
printf("\tSIO_D: " ADDRESS_FORMAT " IN(0x%03x) for empty character buffer" NLP, PCX, port);
|
||||
sio_unit.u3 = FALSE; /* no character is available any more */
|
||||
return mapCharacter(sio_unit.buf); /* return previous character */
|
||||
} /* OUT follows, no fall-through from IN */
|
||||
|
@ -720,12 +720,21 @@ static int32 sio0dCore(const int32 port, const int32 io, const int32 data) {
|
|||
return 0x00; /* ignored since OUT */
|
||||
}
|
||||
|
||||
static char* printable(char* result, int32 data, const int32 isIn) {
|
||||
result[0] = 0;
|
||||
data &= 0x7f;
|
||||
if ((0x20 <= data) && (data < 0x7f))
|
||||
sprintf(result, isIn ? " <-\"%c\"" : " ->\"%c\"", data);
|
||||
return result;
|
||||
}
|
||||
|
||||
int32 sio0d(const int32 port, const int32 io, const int32 data) {
|
||||
char buffer[8];
|
||||
const int32 result = sio0dCore(port, io, data);
|
||||
if ((io == 0) && (sio_dev.dctrl & IN_MSG))
|
||||
printf("SIO_D: " ADDRESS_FORMAT " IN(0x%03x) = 0x%02x" NLP, PCX, port, result);
|
||||
printf("\tSIO_D: " ADDRESS_FORMAT " IN(0x%03x) = 0x%02x%s" NLP, PCX, port, result, printable(buffer, result, TRUE));
|
||||
else if ((io) && (sio_dev.dctrl & OUT_MSG))
|
||||
printf("SIO_D: " ADDRESS_FORMAT " OUT(0x%03x) = 0x%02x" NLP, PCX, port, data);
|
||||
printf("\tSIO_D: " ADDRESS_FORMAT " OUT(0x%03x) = 0x%02x%s" NLP, PCX, port, data, printable(buffer, data, FALSE));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* gri_defs.h: GRI-909 simulator definitions
|
||||
|
||||
Copyright (c) 2001-2008, Robert M. Supnik
|
||||
Copyright (c) 2001-2010, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,7 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
22-May-10 RMS Added check for 64b definitions
|
||||
12-Jan-08 RMS Added GRI-99 support
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
19-Sep-02 RMS Fixed declarations in gdev structure
|
||||
|
@ -46,8 +47,15 @@
|
|||
5. How does the EAO handle divide overflow? Answer: set link.
|
||||
*/
|
||||
|
||||
#ifndef _GRI_DEFS_H_
|
||||
#define _GRI_DEFS_H_ 0
|
||||
|
||||
#include "sim_defs.h" /* simulator defns */
|
||||
|
||||
#if defined(USE_INT64) || defined(USE_ADDR64)
|
||||
#error "GRI does not support 64b values!"
|
||||
#endif
|
||||
|
||||
/* Simulator stop codes */
|
||||
|
||||
#define STOP_DEV 1 /* must be 1 */
|
||||
|
@ -244,3 +252,5 @@ struct gdev {
|
|||
#define VEC_CASR 0047
|
||||
#define VEC_DISK 0055 /* disk */
|
||||
#define VEC_RTC 0100 /* clock */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* h316_defs.h: Honeywell 316/516 simulator definitions
|
||||
|
||||
Copyright (c) 1999-2008, Robert M. Supnik
|
||||
Copyright (c) 1999-2010, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,7 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
22-May-10 RMS Added check for 64b definitions
|
||||
15-Feb-05 RMS Added start button interrupt
|
||||
01-Dec-04 RMS Added double precision constants
|
||||
24-Oct-03 RMS Added DMA/DMC support
|
||||
|
@ -34,6 +35,10 @@
|
|||
|
||||
#include "sim_defs.h" /* simulator defns */
|
||||
|
||||
#if defined(USE_INT64) || defined(USE_ADDR64)
|
||||
#error "H316 does not support 64b values!"
|
||||
#endif
|
||||
|
||||
/* Simulator stop codes */
|
||||
|
||||
#define STOP_RSRV 1 /* must be 1 */
|
||||
|
|
|
@ -274,7 +274,8 @@ switch (inst) { /* case on opcode */
|
|||
break;
|
||||
|
||||
case 003: /* !BOT */
|
||||
if (!(uptr->UST & STA_BOT)) return IOSKIP (dat);
|
||||
if (!(uptr->UST & STA_BOT))
|
||||
return IOSKIP (dat);
|
||||
break;
|
||||
|
||||
case 004: /* !interrupting */
|
||||
|
|
|
@ -732,14 +732,16 @@ switch (uptr->FNC) { /* case on function */
|
|||
case FNC_FSR: /* space forward */
|
||||
if (st = sim_tape_sprecf (uptr, &tbc)) /* space rec fwd, err? */
|
||||
r = ms_map_err (uptr, st); /* map error */
|
||||
if (tbc & 1) msc_sta = msc_sta | STA_ODD;
|
||||
if (tbc & 1)
|
||||
msc_sta = msc_sta | STA_ODD;
|
||||
else msc_sta = msc_sta & ~STA_ODD;
|
||||
break;
|
||||
|
||||
case FNC_BSR: /* space reverse */
|
||||
if (st = sim_tape_sprecr (uptr, &tbc)) /* space rec rev, err? */
|
||||
r = ms_map_err (uptr, st); /* map error */
|
||||
if (tbc & 1) msc_sta = msc_sta | STA_ODD;
|
||||
if (tbc & 1)
|
||||
msc_sta = msc_sta | STA_ODD;
|
||||
else msc_sta = msc_sta & ~STA_ODD;
|
||||
break;
|
||||
|
||||
|
@ -786,7 +788,8 @@ switch (uptr->FNC) { /* case on function */
|
|||
sim_activate (uptr, msc_xtime); /* re-activate */
|
||||
return SCPE_OK;
|
||||
}
|
||||
if (ms_max & 1) msc_sta = msc_sta | STA_ODD; /* set ODD by rec len */
|
||||
if (ms_max & 1) /* set ODD by rec len */
|
||||
msc_sta = msc_sta | STA_ODD;
|
||||
else msc_sta = msc_sta & ~STA_ODD;
|
||||
sim_activate (uptr, msc_itime); /* sched IRG */
|
||||
if (uptr->FNC == FNC_RFF) msc_1st = 1; /* diagnostic? */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* i1401_cpu.c: IBM 1401 CPU simulator
|
||||
|
||||
Copyright (c) 1993-2010, Robert M. Supnik
|
||||
Copyright (c) 1993-2011, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,9 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
19-Mar-11 RMS Reverted multiple tape indicator implementation
|
||||
20-Jan-11 RMS Fixed branch on EOT indicator per hardware (from Van Snyder)
|
||||
07-Nov-10 RMS Fixed divide not to clear word marks in quotient
|
||||
24-Apr-10 RMS Revised divide algorithm (from Van Snyder)
|
||||
11-Jul-08 RMS Added missing A magtape modifier (from Van Snyder)
|
||||
Fixed tape indicator implementation (from Bob Abeles)
|
||||
|
@ -226,7 +229,6 @@ extern t_stat inq_io (int32 flag, int32 mod);
|
|||
extern t_stat mt_io (int32 unit, int32 flag, int32 mod);
|
||||
extern t_stat dp_io (int32 fnc, int32 flag, int32 mod);
|
||||
extern t_stat mt_func (int32 unit, int32 flag, int32 mod);
|
||||
extern t_bool mt_testind (void);
|
||||
extern t_stat sim_activate (UNIT *uptr, int32 delay);
|
||||
extern t_stat fprint_sym (FILE *of, t_addr addr, t_value *val, UNIT *uptr, int32 sw);
|
||||
|
||||
|
@ -432,7 +434,7 @@ static const int32 ind_table[64] = {
|
|||
0, 0, 0, 0, 0, 0, 0, 0, /* 10 - 17 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 27 */
|
||||
0, 1, 1, 0, 1, 0, 0, 0, /* 30 - 37 */
|
||||
0, 0, 1, 0, 0, 0, 0, 0, /* 40 - 47 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 47 */
|
||||
0, 0, 1, 0, 1, 0, 0, 0, /* 50 - 57 */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, /* 60 - 67 */
|
||||
0, 0, 1, 0, 0, 0, 0, 0 /* 70 - 77 */
|
||||
|
@ -841,12 +843,6 @@ CHECK_LENGTH:
|
|||
BRANCH;
|
||||
}
|
||||
else if (ilnt == 5) { /* branch on ind? */
|
||||
if (D == IN_END) { /* tape indicator */
|
||||
if (mt_testind ()) { /* test, reset */
|
||||
BRANCH;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
if (ind[D]) { /* test indicator */
|
||||
BRANCH;
|
||||
}
|
||||
|
@ -1706,7 +1702,7 @@ do {
|
|||
r = bcd_to_bin[b & DIGIT] + /* sum digits + c */
|
||||
bcd_to_bin[a & DIGIT] + c;
|
||||
c = (r >= 10); /* set carry out */
|
||||
M[bp] = sum_table[r]; /* store result */
|
||||
M[bp] = (M[bp] & WM) | sum_table[r]; /* store result */
|
||||
ap--;
|
||||
bp--;
|
||||
} while ((a & WM) == 0);
|
||||
|
@ -1726,14 +1722,14 @@ do {
|
|||
r = bcd_to_bin[b & DIGIT] - /* a - b - borrow */
|
||||
bcd_to_bin[a & DIGIT] - c;
|
||||
c = (r < 0); /* set borrow out */
|
||||
M[bp] = sum_table[r + 10]; /* store result */
|
||||
M[bp] = (M[bp] & WM) | sum_table[r + 10]; /* store result */
|
||||
ap--;
|
||||
bp--;
|
||||
} while ((a & WM) == 0);
|
||||
b = M[bp]; /* borrow position */
|
||||
if (bcd_to_bin[b & DIGIT] != 0) { /* non-zero? */
|
||||
r = bcd_to_bin[b & DIGIT] - c; /* subtract borrow */
|
||||
M[bp] = sum_table[r]; /* store result */
|
||||
M[bp] = (M[bp] & WM) | sum_table[r]; /* store result */
|
||||
return 0; /* subtract worked */
|
||||
}
|
||||
return c; /* return borrow */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* i1401_defs.h: IBM 1401 simulator definitions
|
||||
|
||||
Copyright (c) 1993-2008, Robert M. Supnik
|
||||
Copyright (c) 1993-2010, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,8 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
06-JUl-10 RMS Added overlap indicator definitions
|
||||
22-May-10 RMS Added check for 64b definitions
|
||||
11-Jul-08 RMS Added IO mode flag for boot (from Bob Abeles)
|
||||
28-Jun-07 RMS Defined character code for tape mark
|
||||
14-Nov-04 RMS Added column binary support
|
||||
|
@ -42,6 +44,10 @@
|
|||
|
||||
#include "sim_defs.h"
|
||||
|
||||
#if defined(USE_INT64) || defined(USE_ADDR64)
|
||||
#error "1401 does not support 64b values!"
|
||||
#endif
|
||||
|
||||
/* Simulator stop codes */
|
||||
|
||||
#define STOP_NXI 1 /* unimpl instr */
|
||||
|
@ -267,6 +273,7 @@
|
|||
#define IN_LPT 032 /* printer error */
|
||||
#define IN_PRO 034 /* process check */
|
||||
#define IN_DBY 036 /* disk busy */
|
||||
#define IN_TBY 041 /* tape busy */
|
||||
#define IN_END 042 /* end indicator */
|
||||
#define IN_TAP 043 /* tape error */
|
||||
#define IN_ACC 045 /* access error */
|
||||
|
@ -282,6 +289,8 @@
|
|||
#define IN_SSE 065 /* sense switch E */
|
||||
#define IN_SSF 066 /* sense switch F */
|
||||
#define IN_SSG 067 /* sense switch G */
|
||||
#define IN_RBY 070 /* reader busy */
|
||||
#define IN_PBY 071 /* punch busy */
|
||||
#define IN_READ 072 /* reader error */
|
||||
|
||||
#define CRETIOE(f,c) return ((f)? (c): SCPE_OK)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* i1401_mt.c: IBM 1401 magnetic tape simulator
|
||||
|
||||
Copyright (c) 1993-2010, Robert M. Supnik
|
||||
Copyright (c) 1993-2011, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -25,6 +25,10 @@
|
|||
|
||||
mt 7-track magtape
|
||||
|
||||
19-Mar-11 RMS Restored lost edit to insert EOF in memory on read EOF
|
||||
Reverted multiple tape indicator implementation
|
||||
20-Jan-11 RMS Fixed branch on END indicator per hardware (from Van Snyder)
|
||||
26-Jun-10 RMS Fixed backspace over tapemark not to set EOR (from Van Snyder)
|
||||
11-Jul-08 RMS Added -n (no rewind) option to BOOT (from Van Snyder)
|
||||
Added tape mark detect to diagnostic read (from Bob Abeles)
|
||||
Added tape mark detect in multi-character records (from Bob Abeles)
|
||||
|
@ -102,10 +106,8 @@
|
|||
|
||||
#define MT_NUMDR 7 /* #drives */
|
||||
#define MT_MAXFR (MAXMEMSIZE * 2) /* max transfer */
|
||||
#define IND u3 /* drive indicator */
|
||||
|
||||
uint8 dbuf[MT_MAXFR]; /* tape buffer */
|
||||
int32 mt_sel = 0; /* selected unit */
|
||||
|
||||
extern uint8 M[]; /* memory */
|
||||
extern int32 ind[64];
|
||||
|
@ -115,8 +117,6 @@ extern FILE *sim_deb;
|
|||
|
||||
t_stat mt_reset (DEVICE *dptr);
|
||||
t_stat mt_boot (int32 unitno, DEVICE *dptr);
|
||||
t_stat mt_attach (UNIT *uptr, char *cp);
|
||||
t_stat mt_detach (UNIT *uptr);
|
||||
t_stat mt_map_status (t_stat st);
|
||||
UNIT *mt_sel_unit (int32 unit);
|
||||
|
||||
|
@ -145,13 +145,8 @@ UNIT mt_unit[] = {
|
|||
};
|
||||
|
||||
REG mt_reg[] = {
|
||||
{ FLDATA (IND, ind[IN_END], 0) },
|
||||
{ FLDATA (ERR, ind[IN_TAP], 0) },
|
||||
{ FLDATA (IND1, mt_unit[1].IND, 0) },
|
||||
{ FLDATA (IND2, mt_unit[2].IND, 0) },
|
||||
{ FLDATA (IND3, mt_unit[3].IND, 0) },
|
||||
{ FLDATA (IND4, mt_unit[4].IND, 0) },
|
||||
{ FLDATA (IND5, mt_unit[5].IND, 0) },
|
||||
{ FLDATA (IND6, mt_unit[6].IND, 0) },
|
||||
{ DRDATA (POS1, mt_unit[1].pos, T_ADDR_W), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS2, mt_unit[2].pos, T_ADDR_W), PV_LEFT + REG_RO },
|
||||
{ DRDATA (POS3, mt_unit[3].pos, T_ADDR_W), PV_LEFT + REG_RO },
|
||||
|
@ -175,7 +170,7 @@ DEVICE mt_dev = {
|
|||
"MT", mt_unit, mt_reg, mt_mod,
|
||||
MT_NUMDR, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &mt_reset,
|
||||
&mt_boot, &mt_attach, &mt_detach,
|
||||
&mt_boot, NULL, NULL,
|
||||
NULL, DEV_DEBUG
|
||||
};
|
||||
|
||||
|
@ -195,11 +190,12 @@ t_mtrlnt tbc;
|
|||
UNIT *uptr;
|
||||
t_stat st;
|
||||
|
||||
ind[IN_TAP] = 0; /* clear error */
|
||||
if ((uptr = mt_sel_unit (unit)) == NULL) /* sel unit, save */
|
||||
return STOP_INVMTU; /* (not valid) */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
|
||||
return SCPE_UNATT;
|
||||
ind[IN_TAP] = 0; /* clear error */
|
||||
ind[IN_END] = 0; /* clear indicator */
|
||||
switch (mod) { /* case on modifier */
|
||||
|
||||
case BCD_A: /* diagnostic read */
|
||||
|
@ -216,7 +212,7 @@ switch (mod) { /* case on modifier */
|
|||
}
|
||||
if (!(flag & MD_BIN) && /* BCD tape and */
|
||||
((dbuf[0] & CHAR) == BCD_TAPMRK)) /* first char TMK? */
|
||||
uptr->IND = 1; /* set indicator */
|
||||
ind[IN_END] = 1; /* set indicator */
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -224,6 +220,8 @@ switch (mod) { /* case on modifier */
|
|||
if (DEBUG_PRS (mt_dev))
|
||||
fprintf (sim_deb, ">>MT%d: backspace\n", unit);
|
||||
st = sim_tape_sprecr (uptr, &tbc); /* space rev */
|
||||
if (st == MTSE_TMK) /* ignore TMK */
|
||||
st = MTSE_OK;
|
||||
break; /* end case */
|
||||
|
||||
case BCD_E: /* erase = nop */
|
||||
|
@ -249,8 +247,7 @@ switch (mod) { /* case on modifier */
|
|||
if (DEBUG_PRS (mt_dev))
|
||||
fprintf (sim_deb, ">>MT%d: rewind and unload\n", unit);
|
||||
sim_tape_rewind (uptr); /* update position */
|
||||
st = mt_detach (uptr); /* detach */
|
||||
break;
|
||||
return sim_tape_detach (uptr); /* detach */
|
||||
|
||||
default:
|
||||
return STOP_INVM;
|
||||
|
@ -283,11 +280,12 @@ t_stat st;
|
|||
t_bool passed_eot;
|
||||
UNIT *uptr;
|
||||
|
||||
ind[IN_TAP] = 0; /* clear error */
|
||||
if ((uptr = mt_sel_unit (unit)) == NULL) /* sel unit, save */
|
||||
return STOP_INVMTU; /* (not valid) */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
|
||||
return SCPE_UNATT;
|
||||
ind[IN_TAP] = 0; /* clear error */
|
||||
ind[IN_END] = 0; /* clear indicator */
|
||||
|
||||
switch (mod) {
|
||||
|
||||
|
@ -296,7 +294,12 @@ switch (mod) {
|
|||
fprintf (sim_deb, ">>MT%d: read from %d", unit, BS);
|
||||
wm_seen = 0; /* no word mk seen */
|
||||
st = sim_tape_rdrecf (uptr, dbuf, &tbc, MT_MAXFR); /* read rec */
|
||||
if (st != MTSE_TMK) { /* not tmk? */
|
||||
if (st == MTSE_TMK) { /* tape mark? */
|
||||
ind[IN_END] = 1; /* set indicator */
|
||||
tbc = 1; /* one char read */
|
||||
dbuf[0] = BCD_TAPMRK; /* BCD tapemark */
|
||||
}
|
||||
else { /* not tmk? */
|
||||
if (st == MTSE_RECE) /* rec in error? */
|
||||
ind[IN_TAP] = 1;
|
||||
else if (st != MTSE_OK) { /* stop on error */
|
||||
|
@ -306,7 +309,7 @@ switch (mod) {
|
|||
}
|
||||
if (!(flag & MD_BIN) && /* BCD tape and */
|
||||
((dbuf[0] & CHAR) == BCD_TAPMRK)) /* first char TMK? */
|
||||
uptr->IND = 1; /* set indicator */
|
||||
ind[IN_END] = 1; /* set indicator */
|
||||
}
|
||||
for (i = 0; i < tbc; i++) { /* loop thru buf */
|
||||
if (!(flag & MD_BOOT) && /* not boot? check */
|
||||
|
@ -390,13 +393,12 @@ switch (mod) {
|
|||
return mt_map_status (st);
|
||||
}
|
||||
|
||||
/* Select unit - save selection if valid, return unit pointer */
|
||||
/* Select unit - return unit pointer if valid */
|
||||
|
||||
UNIT *mt_sel_unit (int32 unit)
|
||||
{
|
||||
if ((unit <= 0) || (unit >= MT_NUMDR))
|
||||
return NULL;
|
||||
mt_sel = unit; /* save selected unit */
|
||||
return mt_dev.units + unit;
|
||||
}
|
||||
|
||||
|
@ -420,8 +422,7 @@ switch (st) {
|
|||
return SCPE_MTRLNT;
|
||||
|
||||
case MTSE_TMK: /* end of file */
|
||||
if (mt_sel != 0)
|
||||
mt_unit[mt_sel].IND = 1; /* set indicator latch */
|
||||
ind[IN_END] = 1; /* set indicator */
|
||||
break;
|
||||
|
||||
case MTSE_IOERR: /* IO error */
|
||||
|
@ -442,21 +443,6 @@ switch (st) {
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Test and reset selected tape drive's indicator latch */
|
||||
|
||||
t_bool mt_testind ()
|
||||
{
|
||||
t_bool v;
|
||||
|
||||
if (mt_sel == 0) /* any mt selected? */
|
||||
return FALSE;
|
||||
if (!(mt_unit[mt_sel].flags & UNIT_ATT)) /* attached? */
|
||||
return FALSE;
|
||||
v = mt_unit[mt_sel].IND; /* save latch */
|
||||
mt_unit[mt_sel].IND = 0; /* reset latch */
|
||||
return v;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
||||
t_stat mt_reset (DEVICE *dptr)
|
||||
|
@ -467,11 +453,10 @@ UNIT *uptr;
|
|||
for (i = 0; i < MT_NUMDR; i++) { /* per drive resets */
|
||||
if (uptr = mt_sel_unit (i)) {
|
||||
MT_CLR_PNU (uptr); /* clear pos flag */
|
||||
uptr->IND = 0; /* clear ind latch */
|
||||
}
|
||||
}
|
||||
ind[IN_TAP] = 0; /* clear mt err ind */
|
||||
mt_sel = 0; /* clear unit select */
|
||||
ind[IN_END] = 0; /* clear mt end ind */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -493,19 +478,3 @@ mt_io (unitno, MD_WM + MD_BOOT, BCD_R); /* LDA %U1 001 R */
|
|||
saved_IS = 1;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Attach routine */
|
||||
|
||||
t_stat mt_attach (UNIT *uptr, char *cp)
|
||||
{
|
||||
uptr->IND = 0; /* reset indicator latch */
|
||||
return sim_tape_attach (uptr, cp); /* tape unit attach */
|
||||
}
|
||||
|
||||
/* Detach routine */
|
||||
|
||||
t_stat mt_detach (UNIT *uptr)
|
||||
{
|
||||
uptr->IND = 0; /* reset indicator latch */
|
||||
return sim_tape_detach (uptr); /* tape unit detach */
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* i1620_defs.h: IBM 1620 simulator definitions
|
||||
|
||||
Copyright (c) 2002-2008, Robert M. Supnik
|
||||
Copyright (c) 2002-2010, 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"),
|
||||
|
@ -27,6 +27,7 @@
|
|||
I am grateful to Al Kossow, the Computer History Museum, and the IBM Corporate
|
||||
Archives for their help in gathering documentation about the IBM 1620.
|
||||
|
||||
22-May-10 RMS Added check for 64b definitions
|
||||
18-Oct-02 RMS Fixed bug in ADDR_S macro (found by Hans Pufal)
|
||||
*/
|
||||
|
||||
|
@ -35,6 +36,10 @@
|
|||
|
||||
#include "sim_defs.h" /* simulator defns */
|
||||
|
||||
#if defined(USE_INT64) || defined(USE_ADDR64)
|
||||
#error "1620 does not support 64b values!"
|
||||
#endif
|
||||
|
||||
/* Simulator stop codes */
|
||||
|
||||
#define STOP_HALT 1 /* HALT */
|
||||
|
|
|
@ -20,8 +20,8 @@ Bugs Found and Fixed During Simulator Debug
|
|||
18. CPU: Shift count is 8b wide, not 9b.
|
||||
19. SYS: Mnemonic is LDQ not LMQ.
|
||||
20. SYS: RQL opcode incorrect in symbolic decode table.
|
||||
21. CPU: Multi-tag mode stores OR'd value of tags on any index read except
|
||||
normal effective address.
|
||||
21. CPU: Multi-tag mode stores OR'd value of tags on any index read except normal
|
||||
effective address.
|
||||
22. CPU: Floating point trap does not write location 0 if trap suppressed.
|
||||
23. SYS: TRA instructions should have symbolic class MXN not MXR.
|
||||
24. CPU: Floating add instructions test for zero result only if normalization enabled.
|
||||
|
@ -58,12 +58,10 @@ Bugs Found and Fixed During Simulator Debug
|
|||
63. IO: 7607 channel modeled incorrectly, could stall.
|
||||
64. IO: All 7607 "effective NOP" conditions must be tested when a new command is
|
||||
decoded (wc == 0 for IOCx and IOSx, EOR set for IOSx and IORx).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
65. MT: BSR, BSF release the data channel in a few microseconds, like REW.
|
||||
66. CPU: Not all PSE and MSE variants are trapped in user mode.
|
||||
67. CPU: Storage nullification mask not recalculated at all points needed;
|
||||
replaced with macro.
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* i7094_com.c: IBM 7094 7750 communications interface simulator
|
||||
|
||||
Copyright (c) 2005-2008, Robert M Supnik
|
||||
Copyright (c) 2005-2010, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -26,6 +26,7 @@
|
|||
com 7750 controller
|
||||
coml 7750 lines
|
||||
|
||||
12-Aug-2010 RMS Major rewrite for CTSS (from Dave Pitts)
|
||||
19-Nov-2008 RMS Revised for common TMXR show routines
|
||||
|
||||
This module implements an abstract simulator for the IBM 7750 communications
|
||||
|
@ -35,8 +36,9 @@
|
|||
supports only terminals. The 7750 can handle many different kinds of
|
||||
terminals; the simulator supports only a limited subset.
|
||||
|
||||
Input is asynchronous. The 7750 sets ATN1 to signal availability of input.
|
||||
When the 7094 issues a CTLRN, the 7750 gathers available input characters
|
||||
Input is asynchronous and line buffered. When valid input (a line or a
|
||||
control message) is available, the 7750 sets ATN1 to signal availability of
|
||||
input. When the 7094 issues a CTLRN, the 7750 gathers available input characters
|
||||
into a message. The message has a 12b sequence number, followed by 12b line
|
||||
number/character pairs, followed by end-of-medium (03777). Input characters
|
||||
can either be control characters (bit 02000 set) or data characters. Data
|
||||
|
@ -65,7 +67,7 @@
|
|||
#include "sim_tmxr.h"
|
||||
#include <ctype.h>
|
||||
|
||||
#define COM_MLINES 32 /* mux lines */
|
||||
#define COM_MLINES 31 /* mux lines */
|
||||
#define COM_TLINES (COM_MLINES + 1) /* total lines */
|
||||
#define COM_BUFSIZ 120 /* max chan transfer */
|
||||
#define COM_PKTSIZ 16384 /* character buffer */
|
||||
|
@ -77,6 +79,8 @@
|
|||
|
||||
#define CONN u3 /* line is connected */
|
||||
#define NEEDID u4 /* need to send ID */
|
||||
#define NOECHO u5 /* no echo */
|
||||
#define INPP u6 /* input pending */
|
||||
|
||||
#define COM_INIT_POLL 8000 /* polling interval */
|
||||
#define COMC_WAIT 2 /* channel delay time */
|
||||
|
@ -113,7 +117,7 @@
|
|||
#define COMO_LIN12B 0200000000000 /* line is 12b */
|
||||
#define COMO_LINCTL 0100000000000 /* control msg */
|
||||
#define COMO_GETLN(x) (((uint32) ((x) >> 24)) & 0777)
|
||||
#define COMO_CTLRST 0000077770000 /* control reset */
|
||||
#define COMO_CTLRST 00000 /* control reset */
|
||||
#define COMO_BITRPT 03777 /* bit repeat */
|
||||
#define COMO_EOM12B 07777 /* end of medium */
|
||||
#define COMO_BMAX 94 /* buffer max, words */
|
||||
|
@ -157,13 +161,9 @@ typedef struct {
|
|||
/* The 7750 character buffer is maintained as linked lists. The lists are:
|
||||
|
||||
free free list
|
||||
inpq input queue
|
||||
inpq[ln] input queue for line n
|
||||
outq[ln] output queue for line ln
|
||||
|
||||
The input queue has two entries for each character; the first is the
|
||||
line number, the second the character. The output queues have only
|
||||
one entry for each character.
|
||||
|
||||
Links are done as subscripts in array com_pkt. This allows the list
|
||||
headers and the queues themselves to be saved and restored. */
|
||||
|
||||
|
@ -172,19 +172,19 @@ uint32 com_enab = 0; /* 7750 enabled */
|
|||
uint32 com_msgn = 0; /* next input msg num */
|
||||
uint32 com_sta = 0; /* 7750 state */
|
||||
uint32 com_stop = 0; /* channel stop */
|
||||
uint32 com_quit = 0; /* quit code */
|
||||
uint32 com_quit = 003; /* quit code */
|
||||
uint32 com_intr = 0; /* interrupt code */
|
||||
uint32 com_bptr = 0; /* buffer pointer */
|
||||
uint32 com_blim = 0; /* buffer count */
|
||||
uint32 com_tps = 50; /* polls/second */
|
||||
uint32 com_not_ret[COM_TLINES] = { 0 }; /* chars not returned */
|
||||
t_uint64 com_sns = 0; /* sense word */
|
||||
t_uint64 com_chob = 0; /* chan output buf */
|
||||
uint32 com_chob_v = 0; /* valid flag */
|
||||
t_uint64 com_buf[COM_BUFSIZ]; /* channel buffer */
|
||||
LISTHD com_free; /* free list */
|
||||
LISTHD com_inpq; /* input queue */
|
||||
LISTHD com_outq[COM_TLINES]; /* output queue */
|
||||
uint32 com_not_ret[COM_TLINES] = { 0 }; /* chars not returned */
|
||||
LISTHD com_inpq[COM_TLINES] = { 0 }; /* input queues */
|
||||
LISTHD com_outq[COM_TLINES] = { 0 }; /* output queues */
|
||||
LISTENT com_pkt[COM_PKTSIZ]; /* character packets */
|
||||
TMLN com_ldsc[COM_MLINES] = { 0 }; /* line descriptors */
|
||||
TMXR com_desc = { COM_MLINES, 0, 0, com_ldsc }; /* mux descriptor */
|
||||
|
@ -225,23 +225,24 @@ t_stat com_attach (UNIT *uptr, char *cptr);
|
|||
t_stat com_detach (UNIT *uptr);
|
||||
t_stat com_show_ctrl (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
t_stat com_show_freeq (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
t_stat com_show_inq (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
t_stat com_show_aoutq (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
t_stat com_show_outq (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
t_stat com_show_allq (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
t_stat com_show_oneq (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
void com_reset_ln (uint32 i);
|
||||
uint16 com_get_nexti (uint32 *ln);
|
||||
uint16 com_gethd_free (LISTHD *lh);
|
||||
uint16 com_gethd (LISTHD *lh);
|
||||
uint16 com_gettl_free (LISTHD *lh);
|
||||
uint16 com_gettl (LISTHD *lh);
|
||||
t_bool com_new_puttl (LISTHD *lh, uint16 val);
|
||||
void com_puttl (LISTHD *lh, uint16 ent);
|
||||
t_bool com_inp_msg (uint32 ln, uint16 msg);
|
||||
void com_skip_outc (uint32 ln);
|
||||
t_stat com_test_atn (uint32 ch);
|
||||
t_bool com_test_inp (void);
|
||||
void com_set_inpp (uint32 ln);
|
||||
t_uint64 com_getob (uint32 ch);
|
||||
t_bool com_qdone (uint32 ch);
|
||||
void com_end (uint32 ch, uint32 fl, uint32 st);
|
||||
t_stat com_send_id (uint32 ln);
|
||||
t_stat com_send_ccmp (uint32 ln);
|
||||
t_stat com_queue_in (uint32 ln, uint32 ch);
|
||||
uint32 com_gen_ccmp (uint32 ln);
|
||||
t_bool com_queue_in (uint32 ln, uint32 ch);
|
||||
uint32 com_queue_out (uint32 ln, uint32 *c1);
|
||||
void com_set_sns (t_uint64 stat);
|
||||
|
||||
|
@ -262,64 +263,6 @@ UNIT com_unit[] = {
|
|||
{ UDATA (&coms_svc, UNIT_DIS, 0), COMC_WAIT }
|
||||
};
|
||||
|
||||
REG com_reg[] = {
|
||||
{ FLDATA (ENABLE, com_enab, 0) },
|
||||
{ ORDATA (STATE, com_sta, 6) },
|
||||
{ ORDATA (MSGNUM, com_msgn, 12) },
|
||||
{ ORDATA (SNS, com_sns, 60) },
|
||||
{ ORDATA (CHOB, com_chob, 36) },
|
||||
{ FLDATA (CHOBV, com_chob_v, 0) },
|
||||
{ FLDATA (STOP, com_stop, 0) },
|
||||
{ BRDATA (BUF, com_buf, 8, 36, COM_BUFSIZ) },
|
||||
{ DRDATA (BPTR, com_bptr, 7), REG_RO },
|
||||
{ DRDATA (BLIM, com_blim, 7), REG_RO },
|
||||
{ BRDATA (NRET, com_not_ret, 10, 32, COM_TLINES), REG_RO + PV_LEFT },
|
||||
{ BRDATA (FREEQ, &com_free, 10, 16, 2) },
|
||||
{ BRDATA (INPQ, &com_inpq, 10, 16, 2) },
|
||||
{ BRDATA (OUTQ, com_outq, 10, 16, 2 * COM_TLINES) },
|
||||
{ BRDATA (PKTB, com_pkt, 10, 16, 2 * COM_PKTSIZ) },
|
||||
{ DRDATA (TTIME, com_unit[COM_CIU].wait, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (WTIME, com_unit[COM_CHU].wait, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (CHAN, com_ch, 3), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB com_mod[] = {
|
||||
{ UNIT_ATT, UNIT_ATT, "summary", NULL,
|
||||
NULL, &tmxr_show_summ, (void *) &com_desc },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL,
|
||||
NULL, &tmxr_show_cstat, (void *) &com_desc },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL,
|
||||
NULL, &tmxr_show_cstat, (void *) &com_desc },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, COMR_FQ, "FREEQ", NULL,
|
||||
NULL, &com_show_ctrl, 0 },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, COMR_IQ, "INQ", NULL,
|
||||
NULL, &com_show_ctrl, 0 },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, COMR_OQ, "OUTQ", NULL,
|
||||
NULL, &com_show_ctrl, 0 },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, -1, "ALL", NULL,
|
||||
NULL, &com_show_ctrl, 0 },
|
||||
{ MTAB_XTD | MTAB_VUN | MTAB_NMO, 0, "OUTQ", NULL,
|
||||
NULL, &com_show_outq, 0 },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE com_dev = {
|
||||
"COM", com_unit, com_reg, com_mod,
|
||||
3, 10, 31, 1, 16, 8,
|
||||
&tmxr_ex, &tmxr_dep, &com_reset,
|
||||
NULL, &com_attach, &com_detach,
|
||||
&com_dib, DEV_NET | DEV_DIS
|
||||
};
|
||||
|
||||
/* COML data structures
|
||||
|
||||
coml_dev COML device descriptor
|
||||
coml_unit COML unit descriptor
|
||||
coml_reg COML register list
|
||||
coml_mod COML modifiers list
|
||||
*/
|
||||
|
||||
UNIT coml_unit[] = {
|
||||
{ UDATA (&como_svc, 0, 0), COML_WAIT },
|
||||
{ UDATA (&como_svc, 0, 0), COML_WAIT },
|
||||
|
@ -352,10 +295,70 @@ UNIT coml_unit[] = {
|
|||
{ UDATA (&como_svc, 0, 0), COML_WAIT },
|
||||
{ UDATA (&como_svc, 0, 0), COML_WAIT },
|
||||
{ UDATA (&como_svc, 0, 0), COML_WAIT },
|
||||
{ UDATA (&como_svc, 0, 0), COML_WAIT },
|
||||
{ UDATA (&comto_svc, 0, 0), COML_WAIT },
|
||||
};
|
||||
|
||||
REG com_reg[] = {
|
||||
{ FLDATA (ENABLE, com_enab, 0) },
|
||||
{ ORDATA (STATE, com_sta, 6) },
|
||||
{ ORDATA (MSGNUM, com_msgn, 12) },
|
||||
{ ORDATA (SNS, com_sns, 60) },
|
||||
{ ORDATA (CHOB, com_chob, 36) },
|
||||
{ FLDATA (CHOBV, com_chob_v, 0) },
|
||||
{ FLDATA (STOP, com_stop, 0) },
|
||||
{ ORDATA (QUIT, com_quit, 7) },
|
||||
{ ORDATA (INTR, com_intr, 7) },
|
||||
{ BRDATA (BUF, com_buf, 8, 36, COM_BUFSIZ) },
|
||||
{ DRDATA (BPTR, com_bptr, 7), REG_RO },
|
||||
{ DRDATA (BLIM, com_blim, 7), REG_RO },
|
||||
{ BRDATA (NRET, com_not_ret, 10, 32, COM_TLINES), REG_RO + PV_LEFT },
|
||||
{ URDATA (NEEDID, coml_unit[0].NEEDID, 8, 1, 0, COM_TLINES, 0) },
|
||||
{ URDATA (NOECHO, coml_unit[0].NOECHO, 8, 1, 0, COM_TLINES, 0) },
|
||||
{ URDATA (INPP, coml_unit[0].INPP, 8, 1, 0, COM_TLINES, 0) },
|
||||
{ BRDATA (FREEQ, &com_free, 10, 16, 2) },
|
||||
{ BRDATA (INPQ, com_inpq, 10, 16, 2 * COM_TLINES) },
|
||||
{ BRDATA (OUTQ, com_outq, 10, 16, 2 * COM_TLINES) },
|
||||
{ BRDATA (PKTB, com_pkt, 10, 16, 2 * COM_PKTSIZ) },
|
||||
{ DRDATA (TTIME, com_unit[COM_CIU].wait, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (WTIME, com_unit[COM_CHU].wait, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (CHAN, com_ch, 3), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
MTAB com_mod[] = {
|
||||
{ UNIT_ATT, UNIT_ATT, "summary", NULL,
|
||||
NULL, &tmxr_show_summ, (void *) &com_desc },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL,
|
||||
NULL, &tmxr_show_cstat, (void *) &com_desc },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL,
|
||||
NULL, &tmxr_show_cstat, (void *) &com_desc },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, COMR_FQ, "FREEQ", NULL,
|
||||
NULL, &com_show_ctrl, 0 },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, COMR_IQ, "INPQ", NULL,
|
||||
NULL, &com_show_ctrl, 0 },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, COMR_OQ, "OUTQ", NULL,
|
||||
NULL, &com_show_ctrl, 0 },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, -1, "ALL", NULL,
|
||||
NULL, &com_show_ctrl, 0 },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
DEVICE com_dev = {
|
||||
"COM", com_unit, com_reg, com_mod,
|
||||
3, 10, 31, 1, 16, 8,
|
||||
&tmxr_ex, &tmxr_dep, &com_reset,
|
||||
NULL, &com_attach, &com_detach,
|
||||
&com_dib, DEV_NET | DEV_DIS
|
||||
};
|
||||
|
||||
/* COML data structures
|
||||
|
||||
coml_dev COML device descriptor
|
||||
coml_unit COML unit descriptor
|
||||
coml_reg COML register list
|
||||
coml_mod COML modifiers list
|
||||
*/
|
||||
|
||||
MTAB coml_mod[] = {
|
||||
{ UNIT_K35+UNIT_2741, 0 , "KSR-37", "KSR-37", NULL },
|
||||
{ UNIT_K35+UNIT_2741, UNIT_K35 , "KSR-35", "KSR-35", NULL },
|
||||
|
@ -366,6 +369,10 @@ MTAB coml_mod[] = {
|
|||
&tmxr_set_log, &tmxr_show_log, (void*) &com_desc },
|
||||
{ MTAB_XTD|MTAB_VUN|MTAB_NC, 0, NULL, "NOLOG",
|
||||
&tmxr_set_nolog, NULL, (void *) &com_desc },
|
||||
{ MTAB_XTD | MTAB_VUN | MTAB_NMO, 0, "INPQ", NULL,
|
||||
NULL, &com_show_oneq, 0 },
|
||||
{ MTAB_XTD | MTAB_VUN | MTAB_NMO, 1, "OUTQ", NULL,
|
||||
NULL, &com_show_oneq, 0 },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
@ -441,7 +448,7 @@ switch (com_sta) { /* case on state */
|
|||
com_sns &= ~COMS_DYN; /* clear dynamic flags */
|
||||
if (com_free.head) /* free space? */
|
||||
com_set_sns (COMS_INBF);
|
||||
if (com_inpq.head) /* pending input? */
|
||||
if (com_test_inp ()) /* pending input? */
|
||||
com_set_sns (COMS_DATR);
|
||||
com_buf[0] = (com_sns >> 24) & DMASK; /* buffer is 2 words */
|
||||
com_buf[1] = (com_sns << 12) & DMASK;
|
||||
|
@ -478,8 +485,8 @@ return SCPE_OK;
|
|||
|
||||
t_stat comc_svc (UNIT *uptr)
|
||||
{
|
||||
uint32 i, j, k, ccnt, ln, uln, ent;
|
||||
uint16 chr;
|
||||
uint32 i, j, k, ccnt, ln, uln;
|
||||
uint16 chr, ent;
|
||||
t_uint64 dat;
|
||||
|
||||
switch (com_sta) { /* case on state */
|
||||
|
@ -489,15 +496,27 @@ switch (com_sta) { /* case on state */
|
|||
com_buf[i] = 0;
|
||||
com_buf[0] = com_msgn; /* 1st char is msg num */
|
||||
com_msgn = (com_msgn + 1) & 03777; /* incr msg num */
|
||||
for (i = 1, j = 0; i < COMI_12BMAX; i++) { /* fill buffer */
|
||||
ent = com_gethd_free (&com_inpq); /* get next entry */
|
||||
if (ent == 0) /* q empty, done */
|
||||
break;
|
||||
if ((i % 3) == 0) /* next word? */
|
||||
for (i = 1, j = 0, ln = 0; /* check all lines */
|
||||
(ln < COM_TLINES) && (i < COMI_12BMAX); /* until buffer full */
|
||||
ln++) {
|
||||
chr = (uint16) com_gen_ccmp (ln); /* completion msg? */
|
||||
if ((chr == 0) && coml_unit[ln].INPP) { /* no, line input? */
|
||||
ent = com_gethd_free (&com_inpq[ln]); /* get first char */
|
||||
if (ent != 0) /* any input? */
|
||||
chr = com_pkt[ent].data; /* return char */
|
||||
else coml_unit[i].INPP = 0; /* this line is idle */
|
||||
} /* end if input pending */
|
||||
if (chr != 0) { /* got something? */
|
||||
if ((i++ % 3) == 0) /* next word? */
|
||||
j++;
|
||||
com_buf[j] = (com_buf[j] << 12) | /* pack line number */
|
||||
((t_uint64) ((ln + COM_LBASE) | COMI_VALIDL));
|
||||
if ((i++ % 3) == 0) /* next word? */
|
||||
j++;
|
||||
com_buf[j] = (com_buf[j] << 12) | /* pack data */
|
||||
((t_uint64) (com_pkt[ent].data & 07777));
|
||||
}
|
||||
((t_uint64) (chr & 07777));
|
||||
} /* end if char */
|
||||
} /* end for buffer */
|
||||
for (k = i % 3; k < 3; k++) { /* fill with EOM */
|
||||
if (k == 0) /* next word? */
|
||||
j++;
|
||||
|
@ -519,8 +538,11 @@ switch (com_sta) { /* case on state */
|
|||
break;
|
||||
|
||||
case CHSL_RDS|CHSL_3RD: /* read end */
|
||||
if (com_qdone (com_ch)) /* done? */
|
||||
return com_test_atn (com_ch); /* test atn, exit */
|
||||
if (com_qdone (com_ch)) { /* done? */
|
||||
if (com_test_inp ()) /* more data waiting? */
|
||||
ch9_set_atn (com_ch);
|
||||
return SCPE_OK; /* exit */
|
||||
}
|
||||
com_sta = CHSL_RDS; /* repeat sequence */
|
||||
break;
|
||||
|
||||
|
@ -545,7 +567,8 @@ switch (com_sta) { /* case on state */
|
|||
ln = COMO_GETLN (dat); /* line number */
|
||||
if (ln >= (COM_TLINES + COM_LBASE)) /* invalid line? */
|
||||
return STOP_INVLIN;
|
||||
if (dat & COMO_CTLRST) /* char must be 0 */
|
||||
chr = (uint16) ((dat >> 12) & 07777); /* control message */
|
||||
if (chr != COMO_CTLRST) /* char must be 0 */
|
||||
return STOP_INVMSG;
|
||||
if (ln >= COM_LBASE)
|
||||
com_reset_ln (ln - COM_LBASE);
|
||||
|
@ -593,7 +616,7 @@ switch (com_sta) { /* case on state */
|
|||
|
||||
case CHSL_WRS|CHSL_4TH: /* buffer done */
|
||||
if (com_qdone (com_ch)) /* done? */
|
||||
return com_test_atn (com_ch); /* test atn, exit */
|
||||
return SCPE_OK; /* exit */
|
||||
com_sta = CHSL_WRS; /* repeat sequence */
|
||||
break;
|
||||
|
||||
|
@ -609,8 +632,8 @@ return SCPE_OK;
|
|||
|
||||
t_stat comti_svc (UNIT *uptr)
|
||||
{
|
||||
int32 c;
|
||||
t_stat r;
|
||||
int32 c, ln = COM_MLINES;
|
||||
uint16 ent;
|
||||
|
||||
sim_activate (uptr, uptr->wait); /* continue poll */
|
||||
c = sim_poll_kbd (); /* get character */
|
||||
|
@ -618,17 +641,25 @@ if (c && !(c & (SCPE_BREAK|SCPE_KFLAG))) /* error? */
|
|||
return c;
|
||||
if (!com_enab || (c & SCPE_BREAK)) /* !enab, break? done */
|
||||
return SCPE_OK;
|
||||
if (coml_unit[COM_MLINES].NEEDID) /* ID needed? */
|
||||
return com_send_id (COM_MLINES);
|
||||
if (coml_unit[ln].NEEDID) /* ID needed? */
|
||||
return com_send_id (ln);
|
||||
if ((c & SCPE_KFLAG) && ((c = c & 0177) != 0)) { /* char input? */
|
||||
if (r = com_queue_in (COM_MLINES, c))
|
||||
return r;
|
||||
if (sim_tt_outcvt (c, TT_MODE_7P) >= 0)
|
||||
if ((c == 0177) || (c == '\b')) { /* delete? */
|
||||
ent = com_gettl_free (&com_inpq[ln]); /* remove last char */
|
||||
if (!coml_unit[ln].NOECHO)
|
||||
sim_putchar (ent? '\b': '\a');
|
||||
return SCPE_OK;
|
||||
}
|
||||
if (!com_queue_in (ln, c)) /* add to inp queue */
|
||||
return STOP_NOIFREE;
|
||||
if (!coml_unit[ln].NOECHO) { /* echo enabled? */
|
||||
if (sim_tt_outcvt (c, TT_MODE_7P) >= 0) /* printable? */
|
||||
sim_putchar (c);
|
||||
if (c == '\r')
|
||||
if (c == '\r') /* line end? */
|
||||
sim_putchar ('\n');
|
||||
}
|
||||
return com_test_atn (com_ch); /* set ATN if input */
|
||||
}
|
||||
return SCPE_OK; /* set ATN if input */
|
||||
}
|
||||
|
||||
/* Unit service - receive side
|
||||
|
@ -639,7 +670,7 @@ return com_test_atn (com_ch); /* set ATN if input */
|
|||
t_stat comi_svc (UNIT *uptr)
|
||||
{
|
||||
int32 c, ln, t;
|
||||
t_stat r;
|
||||
uint16 ent;
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
|
||||
return SCPE_OK;
|
||||
|
@ -652,6 +683,8 @@ if (ln >= 0) { /* got one? */
|
|||
com_ldsc[ln].rcve = 1; /* rcv enabled */
|
||||
coml_unit[ln].CONN = 1; /* flag connected */
|
||||
coml_unit[ln].NEEDID = 1; /* need ID */
|
||||
coml_unit[ln].NOECHO = 0; /* echo enabled */
|
||||
coml_unit[ln].INPP = 0; /* no input pending */
|
||||
}
|
||||
tmxr_poll_rx (&com_desc); /* poll for input */
|
||||
for (ln = 0; ln < COM_MLINES; ln++) { /* loop thru mux */
|
||||
|
@ -661,13 +694,21 @@ for (ln = 0; ln < COM_MLINES; ln++) { /* loop thru mux */
|
|||
c = tmxr_getc_ln (&com_ldsc[ln]); /* get char */
|
||||
if (c) { /* any char? */
|
||||
c = c & 0177; /* mask to 7b */
|
||||
if (r = com_queue_in (ln, c)) /* queue char, err? */
|
||||
return r;
|
||||
if ((c == 0177) || (c == '\b')) { /* delete? */
|
||||
ent = com_gettl_free (&com_inpq[ln]); /* remove last char */
|
||||
if (!coml_unit[ln].NOECHO)
|
||||
tmxr_putc_ln (&com_ldsc[ln], ent? '\b': '\a');
|
||||
return SCPE_OK;
|
||||
}
|
||||
if (!com_queue_in (ln, c)) /* queue char, err? */
|
||||
return STOP_NOIFREE;
|
||||
if (com_ldsc[ln].xmte) { /* output enabled? */
|
||||
if (sim_tt_outcvt (c, TT_MODE_7P) >= 0) /* echo char */
|
||||
if (!coml_unit[ln].NOECHO) { /* echo enabled? */
|
||||
if (sim_tt_outcvt (c, TT_MODE_7P) >= 0)
|
||||
tmxr_putc_ln (&com_ldsc[ln], c);
|
||||
if (c == '\r') /* add LF after CR */
|
||||
tmxr_putc_ln (&com_ldsc[ln], '\n');
|
||||
}
|
||||
tmxr_poll_tx (&com_desc); /* poll xmt */
|
||||
} /* end if enabled */
|
||||
} /* end if char */
|
||||
|
@ -675,29 +716,29 @@ for (ln = 0; ln < COM_MLINES; ln++) { /* loop thru mux */
|
|||
else if (coml_unit[ln].CONN) { /* not conn, was conn? */
|
||||
coml_unit[ln].CONN = 0; /* clear connected */
|
||||
coml_unit[ln].NEEDID = 0; /* clear need id */
|
||||
if (!com_inp_msg (ln, COMI_HANGUP)) /* hangup message */
|
||||
com_set_inpp (ln); /* input pending, ATN1 */
|
||||
if (!com_new_puttl (&com_inpq[ln], COMI_HANGUP))/* hangup message */
|
||||
return STOP_NOIFREE;
|
||||
}
|
||||
} /* end for */
|
||||
return com_test_atn (com_ch); /* set ATN if input */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Unit service - console transmit */
|
||||
|
||||
t_stat comto_svc (UNIT *uptr)
|
||||
{
|
||||
uint32 ln = COM_MLINES;
|
||||
uint32 c, c1;
|
||||
|
||||
if (com_outq[COM_MLINES].head == 0) /* no more characters? */
|
||||
return com_send_ccmp (COM_MLINES); /* free any remaining */
|
||||
c = com_queue_out (COM_MLINES, &c1); /* get character, cvt */
|
||||
c = com_queue_out (ln, &c1); /* get character, cvt */
|
||||
if (c) /* printable? output */
|
||||
sim_putchar (c);
|
||||
if (c1) /* second char? output */
|
||||
sim_putchar (c1);
|
||||
sim_activate (uptr, uptr->wait); /* next char */
|
||||
if (com_not_ret[COM_MLINES] >= COMI_CMAX) /* completion needed? */
|
||||
return com_send_ccmp (COM_MLINES); /* generate msg */
|
||||
if (com_outq[ln].head == 0) /* line idle? */
|
||||
ch9_set_atn (com_ch); /* set ATN1 */
|
||||
else sim_activate (uptr, uptr->wait); /* next char */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -708,8 +749,6 @@ t_stat como_svc (UNIT *uptr)
|
|||
uint32 c, c1;
|
||||
int32 ln = uptr - coml_unit; /* line # */
|
||||
|
||||
if (com_outq[ln].head == 0) /* no more characters? */
|
||||
return com_send_ccmp (ln); /* free any remaining */
|
||||
if (com_ldsc[ln].conn) { /* connected? */
|
||||
if (com_ldsc[ln].xmte) { /* output enabled? */
|
||||
c = com_queue_out (ln, &c1); /* get character, cvt */
|
||||
|
@ -719,9 +758,9 @@ if (com_ldsc[ln].conn) { /* connected? */
|
|||
tmxr_putc_ln (&com_ldsc[ln], c1);
|
||||
} /* end if */
|
||||
tmxr_poll_tx (&com_desc); /* poll xmt */
|
||||
sim_activate (uptr, uptr->wait); /* next char */
|
||||
if (com_not_ret[ln] >= COMI_CMAX) /* completion needed? */
|
||||
return com_send_ccmp (ln); /* generate msg */
|
||||
if (com_outq[ln].head == 0) /* line idle? */
|
||||
ch9_set_atn (com_ch); /* set ATN1 */
|
||||
else sim_activate (uptr, uptr->wait); /* next char */
|
||||
} /* end if conn */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -730,32 +769,39 @@ return SCPE_OK;
|
|||
|
||||
t_stat com_send_id (uint32 ln)
|
||||
{
|
||||
com_inp_msg (ln, COMI_DIALUP); /* input message: */
|
||||
com_new_puttl (&com_inpq[ln], COMI_DIALUP); /* input message: */
|
||||
if (coml_unit[ln].flags & UNIT_K35) /* dialup, ID, endID */
|
||||
com_inp_msg (ln, COMI_K35);
|
||||
else com_inp_msg (ln, COMI_K37);
|
||||
com_inp_msg (ln, 0);
|
||||
com_inp_msg (ln, 0);
|
||||
com_inp_msg (ln, 0);
|
||||
com_inp_msg (ln, 0);
|
||||
com_inp_msg (ln, (uint16) (ln + COM_LBASE));
|
||||
if (!com_inp_msg (ln, COMI_ENDID)) /* make sure there */
|
||||
com_new_puttl (&com_inpq[ln], COMI_K35);
|
||||
else com_new_puttl (&com_inpq[ln], COMI_K37);
|
||||
com_new_puttl (&com_inpq[ln], 0);
|
||||
com_new_puttl (&com_inpq[ln], 0);
|
||||
com_new_puttl (&com_inpq[ln], 0);
|
||||
com_new_puttl (&com_inpq[ln], 0);
|
||||
com_new_puttl (&com_inpq[ln], (uint16) (ln + COM_LBASE));
|
||||
if (!com_new_puttl (&com_inpq[ln], COMI_ENDID)) /* make sure there */
|
||||
return STOP_NOIFREE; /* was room for msg */
|
||||
coml_unit[ln].NEEDID = 0;
|
||||
com_set_inpp (ln); /* input pending, ATN1 */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Translate and queue input character */
|
||||
|
||||
t_stat com_queue_in (uint32 ln, uint32 c)
|
||||
t_bool com_queue_in (uint32 ln, uint32 c)
|
||||
{
|
||||
uint16 out;
|
||||
|
||||
if (c == com_intr)
|
||||
if (c == com_intr) {
|
||||
out = COMI_INTR;
|
||||
else if (c == com_quit)
|
||||
com_set_inpp (ln);
|
||||
}
|
||||
else if (c == com_quit) {
|
||||
out = COMI_QUIT;
|
||||
com_set_inpp (ln);
|
||||
}
|
||||
else {
|
||||
if (c == '\r')
|
||||
com_set_inpp (ln);
|
||||
if (coml_unit[ln].flags & UNIT_K35) { /* KSR-35? */
|
||||
if (islower (c)) /* convert LC to UC */
|
||||
c = toupper (c);
|
||||
|
@ -763,9 +809,7 @@ else {
|
|||
else c |= (com_epar[c]? COMI_PARITY: 0); /* add even parity */
|
||||
out = (~c) & 0377; /* 1's complement */
|
||||
}
|
||||
if (!com_inp_msg (ln, out)) /* input message */
|
||||
return STOP_NOIFREE;
|
||||
return SCPE_OK;
|
||||
return com_new_puttl (&com_inpq[ln], out); /* input message */
|
||||
}
|
||||
|
||||
/* Retrieve and translate output character */
|
||||
|
@ -775,19 +819,17 @@ uint32 com_queue_out (uint32 ln, uint32 *c1)
|
|||
uint32 c, ent, raw;
|
||||
|
||||
*c1 = 0; /* assume non-printing */
|
||||
ent = com_gethd_free (&com_outq[ln]); /* get character */
|
||||
if (ent == 0) /* nothing? */
|
||||
return 0;
|
||||
if ((ent = com_gethd_free (&com_outq[ln])) == 0) /* get character */
|
||||
return 0; /* nothing, exit */
|
||||
raw = com_pkt[ent].data; /* get 12b character */
|
||||
com_not_ret[ln]++;
|
||||
if (raw == COMO_BITRPT) { /* insert delay? */
|
||||
com_skip_outc (ln);
|
||||
if (com_gethd_free (&com_outq[ln])) /* skip next char */
|
||||
com_not_ret[ln]++; /* and count it */
|
||||
return 0;
|
||||
}
|
||||
c = (~raw >> 1) & 0177; /* remove start, parity */
|
||||
if (c >= 040) { /* printable? */
|
||||
if (c == 0177) /* DEL? ignore */
|
||||
return 0;
|
||||
if ((c >= 040) && (c != 0177)) { /* printable? */
|
||||
if ((coml_unit[ln].flags & UNIT_K35) && islower (c))/* KSR-35 LC? */
|
||||
c = toupper (c); /* cvt to UC */
|
||||
return c;
|
||||
|
@ -798,28 +840,20 @@ switch (c) {
|
|||
return c;
|
||||
|
||||
case '\r': /* carriage return? */
|
||||
if (coml_unit[ln].flags & UNIT_K35) /* KSR-35? */
|
||||
*c1 = '\n'; /* lf after cr */
|
||||
return c;
|
||||
|
||||
case '\n': /* line feed? */
|
||||
if (!(coml_unit[ln].flags & UNIT_K35)) { /* KSR-37? */
|
||||
*c1 = '\n'; /* lf after cr */
|
||||
return '\r';
|
||||
}
|
||||
return c; /* print lf */
|
||||
|
||||
case 022: /* DC2 */
|
||||
if (!(com_unit[ln].flags & UNIT_K35)) { /* KSR-37? */
|
||||
com_skip_outc (ln); /* skip next */
|
||||
return '\n'; /* print lf */
|
||||
}
|
||||
break;
|
||||
coml_unit[ln].NOECHO = 1;
|
||||
return 0;
|
||||
|
||||
case 023: /* DC3 */
|
||||
if (!(com_unit[ln].flags & UNIT_K35)) /* KSR-37? */
|
||||
com_skip_outc (ln); /* skip next */
|
||||
break;
|
||||
case 024: /* DC4 */
|
||||
coml_unit[ln].NOECHO = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0; /* ignore others */
|
||||
|
@ -827,27 +861,17 @@ return 0; /* ignore others */
|
|||
|
||||
/* Generate completion message, if needed */
|
||||
|
||||
t_stat com_send_ccmp (uint32 ln)
|
||||
uint32 com_gen_ccmp (uint32 ln)
|
||||
{
|
||||
uint32 t;
|
||||
|
||||
if (t = com_not_ret[ln]) { /* chars not returned? */
|
||||
if ((t = com_not_ret[ln]) != 0) { /* chars not returned? */
|
||||
if (t > COMI_CMAX) /* limit to max */
|
||||
t = COMI_CMAX;
|
||||
com_not_ret[ln] -= t; /* keep count */
|
||||
if (!com_inp_msg (ln, COMI_COMP (t))) /* gen completion msg */
|
||||
return STOP_NOIFREE;
|
||||
return COMI_COMP (t); /* gen completion msg */
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Skip next char in output queue */
|
||||
|
||||
void com_skip_outc (uint32 ln)
|
||||
{
|
||||
if (com_gethd_free (&com_outq[ln])) /* count it */
|
||||
com_not_ret[ln]++;
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read and validate output buffer */
|
||||
|
@ -863,13 +887,26 @@ else if (!com_stop) { /* not stopped? */
|
|||
return com_chob;
|
||||
}
|
||||
|
||||
/* Set attention if input pending */
|
||||
/* Test whether input pending */
|
||||
|
||||
t_stat com_test_atn (uint32 ch)
|
||||
t_bool com_test_inp (void)
|
||||
{
|
||||
if (com_inpq.head)
|
||||
ch9_set_atn (ch);
|
||||
return SCPE_OK;
|
||||
uint32 i;
|
||||
|
||||
for (i = 0; i < COM_TLINES; i++) {
|
||||
if ((com_not_ret[i] != 0) || coml_unit[i].INPP)
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Set input pending and attention */
|
||||
|
||||
void com_set_inpp (uint32 ln)
|
||||
{
|
||||
coml_unit[ln].INPP = 1;
|
||||
ch9_set_atn (com_ch);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Test for done */
|
||||
|
@ -904,6 +941,17 @@ if ((ent = com_gethd (lh)) != 0)
|
|||
return ent;
|
||||
}
|
||||
|
||||
/* Remove from tail and free */
|
||||
|
||||
uint16 com_gettl_free (LISTHD *lh)
|
||||
{
|
||||
uint16 ent;
|
||||
|
||||
if ((ent = com_gethd (lh)) != 0)
|
||||
com_puttl (&com_free, ent);
|
||||
return ent;
|
||||
}
|
||||
|
||||
/* Get free entry and insert at tail */
|
||||
|
||||
t_bool com_new_puttl (LISTHD *lh, uint16 val)
|
||||
|
@ -933,6 +981,29 @@ else lh->tail = 0;
|
|||
return ent;
|
||||
}
|
||||
|
||||
/* Remove from tail */
|
||||
|
||||
uint16 com_gettl (LISTHD *lh)
|
||||
{
|
||||
uint16 ent, next;
|
||||
uint32 i;
|
||||
|
||||
ent = lh->tail;
|
||||
if (lh->head == lh->tail) {
|
||||
lh->head = lh->tail = 0;
|
||||
return ent;
|
||||
}
|
||||
next = lh->head;
|
||||
for (i = 0; i < COM_PKTSIZ; i++) {
|
||||
if (com_pkt[next].next == ent) {
|
||||
com_pkt[next].next = 0;
|
||||
lh->tail = next;
|
||||
return ent;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Insert at tail */
|
||||
|
||||
void com_puttl (LISTHD *lh, uint16 ent)
|
||||
|
@ -945,25 +1016,6 @@ lh->tail = ent;
|
|||
return;
|
||||
}
|
||||
|
||||
/* Insert line and message into input queue */
|
||||
|
||||
t_bool com_inp_msg (uint32 ln, uint16 msg)
|
||||
{
|
||||
uint16 ent1, ent2;
|
||||
|
||||
if ((ent1 = com_gethd (&com_free)) != 0) { /* pkt avail? */
|
||||
if ((ent2 = com_gethd (&com_free)) != 0) { /* 2nd pkt avail? */
|
||||
com_pkt[ent1].data = (ln + COM_LBASE) | COMI_VALIDL; /* 1st pkt = line# */
|
||||
com_pkt[ent2].data = msg; /* 2nd pkt = char */
|
||||
com_puttl (&com_inpq, ent1); /* queue pkts */
|
||||
com_puttl (&com_inpq, ent2);
|
||||
return TRUE;
|
||||
}
|
||||
com_puttl (&com_free, ent1); /* free 1st */
|
||||
}
|
||||
return FALSE; /* failed */
|
||||
}
|
||||
|
||||
/* Set flag in sense */
|
||||
|
||||
void com_set_sns (t_uint64 stat)
|
||||
|
@ -1011,9 +1063,9 @@ com_bptr = 0;
|
|||
com_blim = 0;
|
||||
for (i = 0; i < COM_BUFSIZ; i++)
|
||||
com_buf[i] = 0;
|
||||
com_inpq.head = 0; /* init queues */
|
||||
com_inpq.tail = 0;
|
||||
for (i = 0; i < COM_TLINES; i++) {
|
||||
for (i = 0; i < COM_TLINES; i++) { /* init lines */
|
||||
com_inpq[i].head = 0;
|
||||
com_inpq[i].tail = 0;
|
||||
com_outq[i].head = 0;
|
||||
com_outq[i].tail = 0;
|
||||
com_reset_ln (i);
|
||||
|
@ -1063,8 +1115,12 @@ return r;
|
|||
|
||||
void com_reset_ln (uint32 ln)
|
||||
{
|
||||
while (com_gethd_free (&com_inpq[ln])) ;
|
||||
while (com_gethd_free (&com_outq[ln])) ;
|
||||
com_not_ret[ln] = 0;
|
||||
coml_unit[ln].NEEDID = 0;
|
||||
coml_unit[ln].NOECHO = 0;
|
||||
coml_unit[ln].INPP = 0;
|
||||
sim_cancel (&coml_unit[ln]);
|
||||
if ((ln < COM_MLINES) && (com_ldsc[ln].conn == 0))
|
||||
coml_unit[ln].CONN = 0;
|
||||
|
@ -1084,7 +1140,7 @@ for (i = 0; i < COM_PKTSIZ; i++) {
|
|||
fprintf (st, "%s is empty\n", name);
|
||||
else if (i == 1)
|
||||
fprintf (st, "%s has 1 entry\n", name);
|
||||
else fprintf (st, "%s had %d entries\n", name, i);
|
||||
else fprintf (st, "%s has %d entries\n", name, i);
|
||||
return i;
|
||||
}
|
||||
next = com_pkt[next].next;
|
||||
|
@ -1110,44 +1166,21 @@ com_show_qsumm (st, &com_free, "Free queue");
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat com_show_inq (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
uint32 entc, ln, i, next;
|
||||
|
||||
if (entc = com_show_qsumm (st, &com_inpq, "Input queue")) {
|
||||
for (i = 0, next = com_inpq.head; next != 0;
|
||||
i++, next = com_pkt[next].next) {
|
||||
if ((i % 4) == 0)
|
||||
fprintf (st, "%d:\t", i);
|
||||
ln = com_pkt[next].data;
|
||||
next = com_pkt[next].next;
|
||||
if (next == 0) {
|
||||
fprintf (st, "Line number without data\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
fprintf (st, "%d/", ln);
|
||||
com_show_char (st, com_pkt[next].data);
|
||||
fputc ((((i % 4) == 3)? '\n': '\t'), st);
|
||||
}
|
||||
if (i % 4)
|
||||
fputc ('\n', st);
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat com_show_outq (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
t_stat com_show_oneq (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
uint32 entc, ln, i, next;
|
||||
LISTHD *lh;
|
||||
char name[20];
|
||||
|
||||
ln = uptr - com_dev.units;
|
||||
sprintf (name, "Output queue %d", ln);
|
||||
if (entc = com_show_qsumm (st, &com_outq[ln], name)) {
|
||||
for (i = 0, next = com_outq[ln].head; next != 0;
|
||||
ln = uptr - coml_dev.units;
|
||||
sprintf (name, val? "Output queue %d": "Input queue %d", ln);
|
||||
lh = val? &com_outq[ln]: &com_inpq[ln];
|
||||
if (entc = com_show_qsumm (st, lh, name)) {
|
||||
for (i = 0, next = lh->head; next != 0;
|
||||
i++, next = com_pkt[next].next) {
|
||||
if ((i % 8) == 0)
|
||||
fprintf (st, "%d:\t", i);
|
||||
com_show_char (st, com_pkt[next].data >> 1);
|
||||
com_show_char (st, com_pkt[next].data >> (val? 1: 0));
|
||||
fputc ((((i % 8) == 7)? '\n': '\t'), st);
|
||||
}
|
||||
if (i % 8)
|
||||
|
@ -1156,12 +1189,12 @@ if (entc = com_show_qsumm (st, &com_outq[ln], name)) {
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat com_show_aoutq (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
t_stat com_show_allq (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
uint32 i;
|
||||
|
||||
for (i = 0; i < COM_TLINES; i++)
|
||||
com_show_outq (st, com_dev.units + i, 1, desc);
|
||||
com_show_oneq (st, coml_dev.units + i, val, desc);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -1170,10 +1203,10 @@ t_stat com_show_ctrl (FILE *st, UNIT *uptr, int32 val, void *desc)
|
|||
if (!com_enab)
|
||||
fprintf (st, "Controller is not initialized\n");
|
||||
if (val & COMR_FQ)
|
||||
com_show_freeq (st, uptr, 1, desc);
|
||||
com_show_freeq (st, uptr, 0, desc);
|
||||
if (val & COMR_IQ)
|
||||
com_show_inq (st, uptr, 1, desc);
|
||||
com_show_allq (st, uptr, 0, desc);
|
||||
if (val & COMR_OQ)
|
||||
com_show_aoutq (st, uptr, 1, desc);
|
||||
com_show_allq (st, uptr, 1, desc);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
|
1179
I7094/i7094_com_old.c
Normal file
1179
I7094/i7094_com_old.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
/* i7094_cpu.c: IBM 7094 CPU simulator
|
||||
|
||||
Copyright (c) 2003-2007, Robert M. Supnik
|
||||
Copyright (c) 2003-2010, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -25,6 +25,8 @@
|
|||
|
||||
cpu 7094 central processor
|
||||
|
||||
16-Jul-10 RMS Fixed PSE, MSE user mode protection (found by Dave Pitts)
|
||||
Fixed issues in storage nullification mode
|
||||
28-Apr-07 RMS Removed clock initialization
|
||||
29-Oct-06 RMS Added additional expanded core instructions
|
||||
17-Oct-06 RMS Fixed the fix in halt IO wait loop
|
||||
|
@ -148,6 +150,8 @@
|
|||
|
||||
#define HALT_IO_LIMIT ((2 << 18) + 1) /* max wait to stop */
|
||||
|
||||
#define EAMASK (mode_storn? A704_MASK: AMASK) /* eff addr mask */
|
||||
|
||||
t_uint64 *M = NULL; /* memory */
|
||||
t_uint64 AC = 0; /* AC */
|
||||
t_uint64 MQ = 0; /* MQ */
|
||||
|
@ -185,7 +189,6 @@ uint32 ht_pend = 0; /* HTR pending */
|
|||
uint32 ht_addr = 0; /* HTR address */
|
||||
uint32 stop_illop = 1; /* stop on ill op */
|
||||
uint32 cpu_astop = 0; /* address stop */
|
||||
static uint32 eamask = AMASK; /* (dynamic) addr mask */
|
||||
|
||||
uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
|
||||
int32 pcq_p = 0; /* PC queue ptr */
|
||||
|
@ -619,7 +622,6 @@ t_bool tracing;
|
|||
ch_set_map (); /* set dispatch map */
|
||||
if (!(cpu_model & (I_94|I_CT))) /* ~7094? MTM always on */
|
||||
mode_multi = 1;
|
||||
eamask = mode_storn? A704_MASK: AMASK; /* set eff addr mask */
|
||||
inst_base = inst_base & ~AMASK; /* A/B sel is 1b */
|
||||
data_base = data_base & ~AMASK;
|
||||
ind_reloc = ind_reloc & VA_BLK; /* canonical form */
|
||||
|
@ -684,7 +686,7 @@ while (reason == SCPE_OK) { /* loop until error */
|
|||
chtr_pend = chtr_eval (NULL); /* re-evaluate */
|
||||
}
|
||||
oldPC = PC; /* save current PC */
|
||||
PC = (PC + 1) & eamask; /* increment PC */
|
||||
PC = (PC + 1) & EAMASK; /* increment PC */
|
||||
if (!ReadI (oldPC, &IR)) /* get inst; trap? */
|
||||
continue;
|
||||
}
|
||||
|
@ -695,7 +697,7 @@ while (reason == SCPE_OK) { /* loop until error */
|
|||
XEC:
|
||||
|
||||
tag = GET_TAG (IR); /* get tag */
|
||||
addr = (uint32) IR & eamask; /* get base addr */
|
||||
addr = (uint32) IR & EAMASK; /* get base addr */
|
||||
|
||||
/* Decrement format instructions */
|
||||
|
||||
|
@ -788,15 +790,15 @@ while (reason == SCPE_OK) { /* loop until error */
|
|||
continue;
|
||||
}
|
||||
if (tag && (fl & I_X)) /* tag and indexable? */
|
||||
ea = (addr - get_xri (tag)) & eamask; /* do indexing */
|
||||
ea = (addr - get_xri (tag)) & EAMASK; /* do indexing */
|
||||
else ea = addr;
|
||||
if (TST_IND (IR) && (fl & I_N)) { /* indirect? */
|
||||
if (!ReadI (ea, &SR)) /* get ind; trap? */
|
||||
continue;
|
||||
addr = (uint32) SR & eamask; /* get address */
|
||||
addr = (uint32) SR & EAMASK; /* get address */
|
||||
tagi = GET_TAG (SR); /* get tag */
|
||||
if (tagi) /* tag? */
|
||||
ea = (addr - get_xri (tagi)) & eamask; /* do indexing */
|
||||
ea = (addr - get_xri (tagi)) & EAMASK; /* do indexing */
|
||||
else ea = addr;
|
||||
}
|
||||
if ((fl & I_R) && !Read (ea, &SR)) /* read opnd; trap? */
|
||||
|
@ -901,7 +903,7 @@ while (reason == SCPE_OK) { /* loop until error */
|
|||
case 00054: /* RFT */
|
||||
t = IR & RMASK;
|
||||
if ((SI & t) == 0) /* if ind off, skip */
|
||||
PC = (PC + 1) & eamask;
|
||||
PC = (PC + 1) & EAMASK;
|
||||
break;
|
||||
|
||||
case 00055: /* SIR */
|
||||
|
@ -911,7 +913,7 @@ while (reason == SCPE_OK) { /* loop until error */
|
|||
case 00056: /* RNT */
|
||||
t = IR & RMASK;
|
||||
if ((SI & t) == t) /* if ind on, skip */
|
||||
PC = (PC + 1) & eamask;
|
||||
PC = (PC + 1) & EAMASK;
|
||||
break;
|
||||
|
||||
case 00057: /* RIR */
|
||||
|
@ -952,7 +954,7 @@ while (reason == SCPE_OK) { /* loop until error */
|
|||
sc = GET_CCNT (IR);
|
||||
SR = ea;
|
||||
while (sc) {
|
||||
ea = (uint32) ((AC & 077) + SR) & eamask;
|
||||
ea = (uint32) ((AC & 077) + SR) & EAMASK;
|
||||
if (!Read (ea, &SR))
|
||||
break;
|
||||
AC = (AC & AC_S) | ((AC >> 6) & 0017777777777) |
|
||||
|
@ -1152,12 +1154,12 @@ while (reason == SCPE_OK) { /* loop until error */
|
|||
t2 = SR & MMASK;
|
||||
if (s1 ^ s2) { /* diff signs? */
|
||||
if (s1) /* AC < mem? skip 2 */
|
||||
PC = (PC + 2) & eamask;
|
||||
PC = (PC + 2) & EAMASK;
|
||||
}
|
||||
else if (t1 == t2) /* equal? skip 1 */
|
||||
PC = (PC + 1) & eamask;
|
||||
PC = (PC + 1) & EAMASK;
|
||||
else if ((t1 < t2) ^ s1) /* AC < mem, AC +, or */
|
||||
PC = (PC + 2) & eamask; /* AC > mem, AC -? */
|
||||
PC = (PC + 2) & EAMASK; /* AC > mem, AC -? */
|
||||
break;
|
||||
|
||||
case 00361: /* ACL */
|
||||
|
@ -1208,7 +1210,7 @@ while (reason == SCPE_OK) { /* loop until error */
|
|||
|
||||
case 00444: /* OFT */
|
||||
if ((SI & SR) == 0) /* skip if ind off */
|
||||
PC = (PC + 1) & eamask;
|
||||
PC = (PC + 1) & EAMASK;
|
||||
break;
|
||||
|
||||
case 00445: /* RIS */
|
||||
|
@ -1217,7 +1219,7 @@ while (reason == SCPE_OK) { /* loop until error */
|
|||
|
||||
case 00446: /* ONT */
|
||||
if ((SI & SR) == SR) /* skip if ind on */
|
||||
PC = (PC + 1) & eamask;
|
||||
PC = (PC + 1) & EAMASK;
|
||||
break;
|
||||
|
||||
case 00460: /* LDA (704) */
|
||||
|
@ -1234,7 +1236,7 @@ while (reason == SCPE_OK) { /* loop until error */
|
|||
|
||||
case 00520: /* ZET */
|
||||
if ((SR & MMASK) == 0) /* skip if M 1-35 = 0 */
|
||||
PC = (PC + 1) & eamask;
|
||||
PC = (PC + 1) & EAMASK;
|
||||
break;
|
||||
|
||||
case 00522: /* XEC */
|
||||
|
@ -1348,8 +1350,6 @@ while (reason == SCPE_OK) { /* loop until error */
|
|||
break;
|
||||
|
||||
case 00760: /* PSE */
|
||||
if (prot_trap (0)) /* user mode? */
|
||||
break;
|
||||
reason = op_pse (ea);
|
||||
break;
|
||||
|
||||
|
@ -1400,7 +1400,7 @@ while (reason == SCPE_OK) { /* loop until error */
|
|||
case 01054: /* LFT */
|
||||
t = (IR & RMASK) << 18;
|
||||
if ((SI & t) == 0) /* if ind off, skip */
|
||||
PC = (PC + 1) & eamask;
|
||||
PC = (PC + 1) & EAMASK;
|
||||
break;
|
||||
|
||||
case 01055: /* SIL */
|
||||
|
@ -1410,7 +1410,7 @@ while (reason == SCPE_OK) { /* loop until error */
|
|||
case 01056: /* LNT */
|
||||
t = (IR & RMASK) << 18;
|
||||
if ((SI & t) == t) /* if ind on, skip */
|
||||
PC = (PC + 1) & eamask;
|
||||
PC = (PC + 1) & EAMASK;
|
||||
break;
|
||||
|
||||
case 01057: /* RIL */
|
||||
|
@ -1441,7 +1441,7 @@ while (reason == SCPE_OK) { /* loop until error */
|
|||
sc = GET_CCNT (IR);
|
||||
SR = ea;
|
||||
while (sc) {
|
||||
ea = (uint32) ((MQ >> 30) + SR) & eamask;
|
||||
ea = (uint32) ((MQ >> 30) + SR) & EAMASK;
|
||||
if (!Read (ea, &SR))
|
||||
break;
|
||||
MQ = ((MQ << 6) & DMASK) | (MQ >> 30);
|
||||
|
@ -1485,7 +1485,7 @@ while (reason == SCPE_OK) { /* loop until error */
|
|||
sc = GET_CCNT (IR);
|
||||
SR = ea;
|
||||
while (sc) {
|
||||
ea = (uint32) ((MQ >> 30) + SR) & eamask;
|
||||
ea = (uint32) ((MQ >> 30) + SR) & EAMASK;
|
||||
if (!Read (ea, &SR))
|
||||
break;
|
||||
MQ = ((MQ << 6) & DMASK) | (SR >> 30);
|
||||
|
@ -1587,9 +1587,9 @@ while (reason == SCPE_OK) { /* loop until error */
|
|||
case 01340: /* LAS */
|
||||
t = AC & AC_MMASK; /* AC Q,P,1-35 */
|
||||
if (t < SR)
|
||||
PC = (PC + 2) & eamask;
|
||||
PC = (PC + 2) & EAMASK;
|
||||
else if (t == SR)
|
||||
PC = (PC + 1) & eamask;
|
||||
PC = (PC + 1) & EAMASK;
|
||||
break;
|
||||
|
||||
case 01400: /* SBM */
|
||||
|
@ -1606,7 +1606,7 @@ while (reason == SCPE_OK) { /* loop until error */
|
|||
|
||||
case 01520: /* NZT */
|
||||
if ((SR & MMASK) != 0)
|
||||
PC = (PC + 1) & eamask;
|
||||
PC = (PC + 1) & EAMASK;
|
||||
break;
|
||||
|
||||
case 01534: /* LXD */
|
||||
|
@ -1639,7 +1639,7 @@ while (reason == SCPE_OK) { /* loop until error */
|
|||
SR = (AC & MMASK) | ((AC & AC_S)? SIGN: 0);
|
||||
if (!Write (ea, SR))
|
||||
break;
|
||||
Write ((ea + 1) & eamask, MQ);
|
||||
Write ((ea + 1) & EAMASK, MQ);
|
||||
break;
|
||||
|
||||
case 01620: /* SLQ */
|
||||
|
@ -1687,8 +1687,6 @@ while (reason == SCPE_OK) { /* loop until error */
|
|||
break; /* -xr -> AC decr */
|
||||
|
||||
case 01760: /* MSE */
|
||||
if (prot_trap (0)) /* user mode? */
|
||||
break;
|
||||
reason = op_mse (ea);
|
||||
break;
|
||||
|
||||
|
@ -1701,11 +1699,11 @@ while (reason == SCPE_OK) { /* loop until error */
|
|||
data_base = BCORE_BASE;
|
||||
else if (ea == 043) { /* IFT? */
|
||||
if (inst_base == 0)
|
||||
PC = (PC + 1) & eamask;
|
||||
PC = (PC + 1) & EAMASK;
|
||||
}
|
||||
else if (ea == 044) { /* EFT? */
|
||||
if (data_base == 0)
|
||||
PC = (PC + 1) & eamask;
|
||||
PC = (PC + 1) & EAMASK;
|
||||
}
|
||||
else if (stop_illop)
|
||||
reason = STOP_ILLEG;
|
||||
|
@ -1967,9 +1965,9 @@ if (tag) {
|
|||
r = r | XR[2];
|
||||
if (tag & 4)
|
||||
r = r | XR[4];
|
||||
return r & eamask;
|
||||
return r & EAMASK;
|
||||
}
|
||||
return XR[tag] & eamask;
|
||||
return XR[tag] & EAMASK;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1994,9 +1992,9 @@ if (tag) {
|
|||
if (tag & 4)
|
||||
r = r | XR[4];
|
||||
put_xr (tag, r);
|
||||
return r & eamask;
|
||||
return r & EAMASK;
|
||||
}
|
||||
return XR[tag] & eamask;
|
||||
return XR[tag] & EAMASK;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -2006,7 +2004,7 @@ return 0;
|
|||
void put_xr (uint32 tag, uint32 dat)
|
||||
{
|
||||
tag = tag & INST_M_TAG;
|
||||
dat = dat & eamask;
|
||||
dat = dat & EAMASK;
|
||||
|
||||
if (tag) {
|
||||
if (mode_multi) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* i7094_cpu1.c: IBM 7094 CPU complex instructions
|
||||
|
||||
Copyright (c) 2003-2008, Robert M. Supnik
|
||||
Copyright (c) 2003-2010, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -22,6 +22,9 @@
|
|||
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.
|
||||
|
||||
16-Jul-10 RMS Fixed PSE and MSE user-mode protection (from Dave Pitts)
|
||||
Added SPUx, SPTx, SPRx
|
||||
*/
|
||||
|
||||
#include "i7094_defs.h"
|
||||
|
@ -44,6 +47,8 @@ extern uint32 mode_storn, mode_multi;
|
|||
extern uint32 chtr_pend, chtr_inht, chtr_inhi;
|
||||
extern uint32 ch_flags[NUM_CHAN];
|
||||
|
||||
extern t_bool prot_trap (uint32 decr);
|
||||
|
||||
typedef struct { /* unpacked fp */
|
||||
uint32 s; /* sign: 0 +, 1 - */
|
||||
int32 ch; /* exponent */
|
||||
|
@ -279,6 +284,8 @@ switch (addr) {
|
|||
break;
|
||||
|
||||
case 00005: /* IOT */
|
||||
if (prot_trap (0)) /* user mode? */
|
||||
break;
|
||||
if (ind_ioc)
|
||||
ind_ioc = 0;
|
||||
else PC = (PC + 1) & AMASK;
|
||||
|
@ -289,6 +296,8 @@ switch (addr) {
|
|||
break;
|
||||
|
||||
case 00007: /* ETM */
|
||||
if (prot_trap (0)) /* user mode? */
|
||||
break;
|
||||
if (cpu_model & I_9X) /* 709X only */
|
||||
mode_ttrap = 1;
|
||||
break;
|
||||
|
@ -339,8 +348,10 @@ switch (addr) {
|
|||
PC = (PC + 1) & AMASK;
|
||||
break;
|
||||
|
||||
case 01000: case 02000: case 03000: case 04000: /* BTT */
|
||||
case 05000: case 06000: case 07000: case 10000:
|
||||
case 001000: case 002000: case 003000: case 004000: /* BTT */
|
||||
case 005000: case 060000: case 070000: case 010000:
|
||||
if (prot_trap (0)) /* user mode? */
|
||||
break;
|
||||
if (cpu_model & I_9X) { /* 709X only */
|
||||
if (sel_trap (PC)) /* sel trap? */
|
||||
break;
|
||||
|
@ -353,13 +364,41 @@ switch (addr) {
|
|||
|
||||
case 001350: case 002350: case 003350: case 004350: /* RICx */
|
||||
case 005350: case 006350: case 007350: case 010350:
|
||||
if (prot_trap (0)) /* user mode? */
|
||||
break;
|
||||
ch = GET_U_CH (addr); /* get channel */
|
||||
return ch_op_reset (ch, 1);
|
||||
|
||||
case 001352: case 002352: case 003352: case 004352: /* RDCx */
|
||||
case 005352: case 006352: case 007352: case 010352:
|
||||
if (prot_trap (0)) /* user mode? */
|
||||
break;
|
||||
ch = GET_U_CH (addr); /* get channel */
|
||||
return ch_op_reset (ch, 0);
|
||||
|
||||
case 001341: case 002341: case 003341: case 004341: /* SPUx */
|
||||
case 005341: case 006341: case 007341: case 010341:
|
||||
case 001342: case 002342: case 003342: case 004342: /* SPUx 2 */
|
||||
case 005342: case 006342: case 007342: case 010342:
|
||||
case 001360: case 002360: case 003360: case 004360: /* SPTx */
|
||||
case 005360: case 006360: case 007360: case 010360:
|
||||
case 001361: case 002361: case 003361: case 004361: /* SPRx */
|
||||
case 005361: case 006361: case 007361: case 010361:
|
||||
case 001362: case 002362: case 003362: case 004362: /* SPRx 2 */
|
||||
case 005362: case 006362: case 007362: case 010362:
|
||||
case 001363: case 002363: case 003363: case 004363: /* SPRx 3 */
|
||||
case 005363: case 006363: case 007363: case 010363:
|
||||
case 001364: case 002364: case 003364: case 004364: /* SPRx 4 */
|
||||
case 005364: case 006364: case 007364: case 010364:
|
||||
case 001365: case 002365: case 003365: case 004365: /* SPRx 5 */
|
||||
case 005365: case 006365: case 007365: case 010365:
|
||||
case 001366: case 002366: case 003366: case 004366: /* SPRx 6 */
|
||||
case 005366: case 006366: case 007366: case 010366:
|
||||
case 001367: case 002367: case 003367: case 004367: /* SPRx 7 */
|
||||
case 005367: case 006367: case 007367: case 010367:
|
||||
if (prot_trap (0)) /* user mode? */
|
||||
break;
|
||||
break; /* no ops */
|
||||
} /* end case */
|
||||
|
||||
return SCPE_OK;
|
||||
|
@ -384,6 +423,8 @@ switch (addr) {
|
|||
break;
|
||||
|
||||
case 00002: /* EFTM */
|
||||
if (prot_trap (0)) /* user mode? */
|
||||
break;
|
||||
if (cpu_model & I_9X) { /* 709X only */
|
||||
mode_ftrap = 1;
|
||||
ind_mqo = 0; /* clears MQ ovf */
|
||||
|
@ -396,6 +437,8 @@ switch (addr) {
|
|||
break;
|
||||
|
||||
case 00004: /* LFTM */
|
||||
if (prot_trap (0)) /* user mode? */
|
||||
break;
|
||||
if (cpu_model & I_9X) /* 709X only */
|
||||
mode_ftrap = 0;
|
||||
break;
|
||||
|
@ -411,6 +454,8 @@ switch (addr) {
|
|||
break;
|
||||
|
||||
case 00007: /* LTM */
|
||||
if (prot_trap (0)) /* user mode? */
|
||||
break;
|
||||
if (cpu_model & I_9X) /* 709X only */
|
||||
mode_ttrap = 0;
|
||||
break;
|
||||
|
|
887
I7094/i7094_cpu1_old.c
Normal file
887
I7094/i7094_cpu1_old.c
Normal file
|
@ -0,0 +1,887 @@
|
|||
/* i7094_cpu1.c: IBM 7094 CPU complex instructions
|
||||
|
||||
Copyright (c) 2003-2008, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
*/
|
||||
|
||||
#include "i7094_defs.h"
|
||||
|
||||
#define FP_HIFRAC(x) ((uint32) ((x) >> FP_N_FR) & FP_FMASK)
|
||||
#define FP_LOFRAC(x) ((uint32) (x) & FP_FMASK)
|
||||
|
||||
#define FP_PACK38(s,e,f) (((s)? AC_S: 0) | ((t_uint64) (f)) | \
|
||||
(((t_uint64) ((e) & FP_M_ACCH)) << FP_V_CH))
|
||||
#define FP_PACK36(s,e,f) (((s)? SIGN: 0) | ((t_uint64) (f)) | \
|
||||
(((t_uint64) ((e) & FP_M_CH)) << FP_V_CH))
|
||||
|
||||
extern t_uint64 AC, MQ, SI, KEYS;
|
||||
extern uint32 PC;
|
||||
extern uint32 SLT, SSW;
|
||||
extern uint32 cpu_model, stop_illop;
|
||||
extern uint32 ind_ovf, ind_dvc, ind_ioc, ind_mqo;
|
||||
extern uint32 mode_ttrap, mode_strap, mode_ctrap, mode_ftrap;
|
||||
extern uint32 mode_storn, mode_multi;
|
||||
extern uint32 chtr_pend, chtr_inht, chtr_inhi;
|
||||
extern uint32 ch_flags[NUM_CHAN];
|
||||
|
||||
typedef struct { /* unpacked fp */
|
||||
uint32 s; /* sign: 0 +, 1 - */
|
||||
int32 ch; /* exponent */
|
||||
t_uint64 fr; /* fraction (54b) */
|
||||
} UFP;
|
||||
|
||||
uint32 op_frnd (void);
|
||||
t_uint64 fp_fracdiv (t_uint64 dvd, t_uint64 dvr, t_uint64 *rem);
|
||||
void fp_norm (UFP *op);
|
||||
void fp_unpack (t_uint64 h, t_uint64 l, t_bool q_ac, UFP *op);
|
||||
uint32 fp_pack (UFP *op, uint32 mqs, int32 mqch);
|
||||
|
||||
extern t_bool fp_trap (uint32 spill);
|
||||
extern t_bool sel_trap (uint32 va);
|
||||
extern t_stat ch_op_reset (uint32 ch, t_bool ch7909);
|
||||
|
||||
/* Integer add
|
||||
|
||||
Sherman: "As the result of an addition or subtraction, if the C(AC) is
|
||||
zero, the sign of AC is unchanged." */
|
||||
|
||||
void op_add (t_uint64 op)
|
||||
{
|
||||
t_uint64 mac = AC & AC_MMASK; /* get magnitudes */
|
||||
t_uint64 mop = op & MMASK;
|
||||
|
||||
AC = AC & AC_S; /* isolate AC sign */
|
||||
if ((AC? 1: 0) ^ ((op & SIGN)? 1: 0)) { /* signs diff? sub */
|
||||
if (mac >= mop) /* AC >= MQ */
|
||||
AC = AC | (mac - mop);
|
||||
else AC = (AC ^ AC_S) | (mop - mac); /* <, sign change */
|
||||
}
|
||||
else {
|
||||
AC = AC | ((mac + mop) & AC_MMASK); /* signs same, add */
|
||||
if ((AC ^ mac) & AC_P) /* P change? overflow */
|
||||
ind_ovf = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Multiply */
|
||||
|
||||
void op_mpy (t_uint64 ac, t_uint64 sr, uint32 sc)
|
||||
{
|
||||
uint32 sign;
|
||||
|
||||
if (sc == 0) /* sc = 0? nop */
|
||||
return;
|
||||
sign = ((MQ & SIGN)? 1: 0) ^ ((sr & SIGN)? 1: 0); /* result sign */
|
||||
ac = ac & AC_MMASK; /* clear AC sign */
|
||||
sr = sr & MMASK; /* mpy magnitude */
|
||||
MQ = MQ & MMASK; /* MQ magnitude */
|
||||
if (sr && MQ) { /* mpy != 0? */
|
||||
while (sc--) { /* for sc */
|
||||
if (MQ & 1) /* MQ35? AC += mpy */
|
||||
ac = (ac + sr) & AC_MMASK;
|
||||
MQ = (MQ >> 1) | ((ac & 1) << 34); /* AC'MQ >> 1 */
|
||||
ac = ac >> 1;
|
||||
}
|
||||
}
|
||||
else ac = MQ = 0; /* result = 0 */
|
||||
if (sign) { /* negative? */
|
||||
ac = ac | AC_S; /* insert signs */
|
||||
MQ = MQ | SIGN;
|
||||
}
|
||||
AC = ac; /* update AC */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Divide */
|
||||
|
||||
t_bool op_div (t_uint64 sr, uint32 sc)
|
||||
{
|
||||
uint32 signa, signm;
|
||||
|
||||
if (sc == 0) /* sc = 0? nop */
|
||||
return FALSE;
|
||||
signa = (AC & AC_S)? 1: 0; /* get signs */
|
||||
signm = (sr & SIGN)? 1: 0;
|
||||
sr = sr & MMASK; /* get dvr magn */
|
||||
if ((AC & AC_MMASK) >= sr) /* |AC| >= |sr|? */
|
||||
return TRUE;
|
||||
AC = AC & AC_MMASK; /* AC, MQ magn */
|
||||
MQ = MQ & MMASK;
|
||||
while (sc--) { /* for sc */
|
||||
AC = ((AC << 1) & AC_MMASK) | (MQ >> 34); /* AC'MQ << 1 */
|
||||
MQ = (MQ << 1) & MMASK;
|
||||
if (AC >= sr) { /* AC >= dvr? */
|
||||
AC = AC - sr; /* AC -= dvr */
|
||||
MQ = MQ | 1; /* set quo bit */
|
||||
}
|
||||
}
|
||||
if (signa ^ signm) /* quo neg? */
|
||||
MQ = MQ | SIGN;
|
||||
if (signa) /* rem neg? */
|
||||
AC = AC | AC_S;
|
||||
return FALSE; /* div ok */
|
||||
}
|
||||
|
||||
/* Shifts */
|
||||
|
||||
void op_als (uint32 addr)
|
||||
{
|
||||
uint32 sc = addr & SCMASK;
|
||||
|
||||
if ((sc >= 35)? /* shift >= 35? */
|
||||
((AC & MMASK) != 0): /* test all bits for ovf */
|
||||
(((AC & MMASK) >> (35 - sc)) != 0)) /* test only 35-sc bits */
|
||||
ind_ovf = 1;
|
||||
if (sc >= 37) /* sc >= 37? result 0 */
|
||||
AC = AC & AC_S;
|
||||
else AC = (AC & AC_S) | ((AC << sc) & AC_MMASK); /* shift, save sign */
|
||||
return;
|
||||
}
|
||||
|
||||
void op_ars (uint32 addr)
|
||||
{
|
||||
uint32 sc = addr & SCMASK;
|
||||
|
||||
if (sc >= 37) /* sc >= 37? result 0 */
|
||||
AC = AC & AC_S;
|
||||
else AC = (AC & AC_S) | ((AC & AC_MMASK) >> sc); /* shift, save sign */
|
||||
return;
|
||||
}
|
||||
|
||||
void op_lls (uint32 addr)
|
||||
{
|
||||
uint32 sc; /* get sc */
|
||||
|
||||
AC = AC & AC_MMASK; /* clear AC sign */
|
||||
for (sc = addr & SCMASK; sc != 0; sc--) { /* for SC */
|
||||
AC = ((AC << 1) & AC_MMASK) | ((MQ >> 34) & 1); /* AC'MQ << 1 */
|
||||
MQ = (MQ & SIGN) | ((MQ << 1) & MMASK); /* preserve MQ sign */
|
||||
if (AC & AC_P) /* if P, overflow */
|
||||
ind_ovf = 1;
|
||||
}
|
||||
if (MQ & SIGN) /* set ACS from MQS */
|
||||
AC = AC | AC_S;
|
||||
return;
|
||||
}
|
||||
|
||||
void op_lrs (uint32 addr)
|
||||
{
|
||||
uint32 sc = addr & SCMASK;
|
||||
t_uint64 mac;
|
||||
|
||||
MQ = MQ & MMASK; /* get MQ magnitude */
|
||||
if (sc != 0) {
|
||||
mac = AC & AC_MMASK; /* get AC magnitude, */
|
||||
AC = AC & AC_S; /* sign */
|
||||
if (sc < 35) { /* sc [1,34]? */
|
||||
MQ = ((MQ >> sc) | (mac << (35 - sc))) & MMASK; /* MQ has AC'MQ */
|
||||
AC = AC | (mac >> sc); /* AC has AC only */
|
||||
}
|
||||
else if (sc < 37) { /* sc [35:36]? */
|
||||
MQ = (mac >> (sc - 35)) & MMASK; /* MQ has AC only */
|
||||
AC = AC | (mac >> sc); /* AC has <QP> */
|
||||
}
|
||||
else if (sc < 72) /* sc [37:71]? */
|
||||
MQ = (mac >> (sc - 35)) & MMASK; /* MQ has AC only */
|
||||
else MQ = 0; /* >72? MQ = 0 */
|
||||
}
|
||||
if (AC & AC_S) /* set MQS from ACS */
|
||||
MQ = MQ | SIGN;
|
||||
return;
|
||||
}
|
||||
|
||||
void op_lgl (uint32 addr)
|
||||
{
|
||||
uint32 sc; /* get sc */
|
||||
|
||||
for (sc = addr & SCMASK; sc != 0; sc--) { /* for SC */
|
||||
AC = (AC & AC_S) | ((AC << 1) & AC_MMASK) | /* AC'MQ << 1 */
|
||||
((MQ >> 35) & 1); /* preserve AC sign */
|
||||
MQ = (MQ << 1) & DMASK;
|
||||
if (AC & AC_P) /* if P, overflow */
|
||||
ind_ovf = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void op_lgr (uint32 addr)
|
||||
{
|
||||
uint32 sc = addr & SCMASK;
|
||||
t_uint64 mac;
|
||||
|
||||
if (sc != 0) {
|
||||
mac = AC & AC_MMASK; /* get AC magnitude, */
|
||||
AC = AC & AC_S; /* sign */
|
||||
if (sc < 36) { /* sc [1,35]? */
|
||||
MQ = ((MQ >> sc) | (mac << (36 - sc))) & DMASK; /* MQ has AC'MQ */
|
||||
AC = AC | (mac >> sc); /* AC has AC only */
|
||||
}
|
||||
else if (sc == 36) { /* sc [36]? */
|
||||
MQ = mac & DMASK; /* MQ = AC<P,1:35> */
|
||||
AC = AC | (mac >> 36); /* AC = AC<Q> */
|
||||
}
|
||||
else if (sc < 73) /* sc [37, 72]? */
|
||||
MQ = (mac >> (sc - 36)) & DMASK; /* MQ has AC only */
|
||||
else MQ = 0; /* >72, AC,MQ = 0 */
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Plus sense - undefined operations are NOPs */
|
||||
|
||||
t_stat op_pse (uint32 addr)
|
||||
{
|
||||
uint32 ch, spill;
|
||||
|
||||
switch (addr) {
|
||||
|
||||
case 00000: /* CLM */
|
||||
if (cpu_model & I_9X) /* 709X only */
|
||||
AC = AC & AC_S;
|
||||
break;
|
||||
|
||||
case 00001: /* LBT */
|
||||
if ((AC & 1) != 0)
|
||||
PC = (PC + 1) & AMASK;
|
||||
break;
|
||||
|
||||
case 00002: /* CHS */
|
||||
AC = AC ^ AC_S;
|
||||
break;
|
||||
|
||||
case 00003: /* SSP */
|
||||
AC = AC & ~AC_S;
|
||||
break;
|
||||
|
||||
case 00004: /* ENK */
|
||||
MQ = KEYS;
|
||||
break;
|
||||
|
||||
case 00005: /* IOT */
|
||||
if (ind_ioc)
|
||||
ind_ioc = 0;
|
||||
else PC = (PC + 1) & AMASK;
|
||||
break;
|
||||
|
||||
case 00006: /* COM */
|
||||
AC = AC ^ AC_MMASK;
|
||||
break;
|
||||
|
||||
case 00007: /* ETM */
|
||||
if (cpu_model & I_9X) /* 709X only */
|
||||
mode_ttrap = 1;
|
||||
break;
|
||||
|
||||
case 00010: /* RND */
|
||||
if ((cpu_model & I_9X) && (MQ & B1)) /* 709X only, MQ1 set? */
|
||||
op_add ((t_uint64) 1); /* incr AC */
|
||||
break;
|
||||
|
||||
case 00011: /* FRN */
|
||||
if (cpu_model & I_9X) { /* 709X only */
|
||||
spill = op_frnd ();
|
||||
if (spill)
|
||||
fp_trap (spill);
|
||||
}
|
||||
break;
|
||||
|
||||
case 00012: /* DCT */
|
||||
if (ind_dvc)
|
||||
ind_dvc = 0;
|
||||
else PC = (PC + 1) & AMASK;
|
||||
break;
|
||||
|
||||
case 00014: /* RCT */
|
||||
chtr_inhi = 1; /* 1 cycle delay */
|
||||
chtr_inht = 0; /* clr inhibit trap */
|
||||
chtr_pend = 0; /* no trap now */
|
||||
break;
|
||||
|
||||
case 00016: /* LMTM */
|
||||
if (cpu_model & I_94) /* 709X only */
|
||||
mode_multi = 0;
|
||||
break;
|
||||
|
||||
case 00140: /* SLF */
|
||||
if (cpu_model & I_9X) /* 709X only */
|
||||
SLT = 0;
|
||||
break;
|
||||
|
||||
case 00141: case 00142: case 00143: case 00144: /* SLN */
|
||||
if (cpu_model & I_9X) /* 709X only */
|
||||
SLT = SLT | (1u << (00144 - addr));
|
||||
break;
|
||||
|
||||
case 00161: case 00162: case 00163: /* SWT */
|
||||
case 00164: case 00165: case 00166:
|
||||
if ((SSW & (1u << (00166 - addr))) != 0)
|
||||
PC = (PC + 1) & AMASK;
|
||||
break;
|
||||
|
||||
case 01000: case 02000: case 03000: case 04000: /* BTT */
|
||||
case 05000: case 06000: case 07000: case 10000:
|
||||
if (cpu_model & I_9X) { /* 709X only */
|
||||
if (sel_trap (PC)) /* sel trap? */
|
||||
break;
|
||||
ch = GET_U_CH (addr); /* get channel */
|
||||
if (ch_flags[ch] & CHF_BOT) /* BOT? */
|
||||
ch_flags[ch] &= ~CHF_BOT; /* clear */
|
||||
else PC = (PC + 1) & AMASK; /* else skip */
|
||||
}
|
||||
break;
|
||||
|
||||
case 001350: case 002350: case 003350: case 004350: /* RICx */
|
||||
case 005350: case 006350: case 007350: case 010350:
|
||||
ch = GET_U_CH (addr); /* get channel */
|
||||
return ch_op_reset (ch, 1);
|
||||
|
||||
case 001352: case 002352: case 003352: case 004352: /* RDCx */
|
||||
case 005352: case 006352: case 007352: case 010352:
|
||||
ch = GET_U_CH (addr); /* get channel */
|
||||
return ch_op_reset (ch, 0);
|
||||
} /* end case */
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Minus sense */
|
||||
|
||||
t_stat op_mse (uint32 addr)
|
||||
{
|
||||
uint32 t, ch;
|
||||
|
||||
switch (addr) {
|
||||
|
||||
case 00000: /* CLM */
|
||||
if (cpu_model & I_9X) /* 709X only */
|
||||
AC = AC & AC_S;
|
||||
break;
|
||||
|
||||
case 00001: /* PBT */
|
||||
if ((AC & AC_P) != 0)
|
||||
PC = (PC + 1) & AMASK;
|
||||
break;
|
||||
|
||||
case 00002: /* EFTM */
|
||||
if (cpu_model & I_9X) { /* 709X only */
|
||||
mode_ftrap = 1;
|
||||
ind_mqo = 0; /* clears MQ ovf */
|
||||
}
|
||||
break;
|
||||
|
||||
case 00003: /* SSM */
|
||||
if (cpu_model & I_9X) /* 709X only */
|
||||
AC = AC | AC_S;
|
||||
break;
|
||||
|
||||
case 00004: /* LFTM */
|
||||
if (cpu_model & I_9X) /* 709X only */
|
||||
mode_ftrap = 0;
|
||||
break;
|
||||
|
||||
case 00005: /* ESTM */
|
||||
if (cpu_model & I_9X) /* 709X only */
|
||||
mode_strap = 1;
|
||||
break;
|
||||
|
||||
case 00006: /* ECTM */
|
||||
if (cpu_model & I_9X) /* 709X only */
|
||||
mode_ctrap = 1;
|
||||
break;
|
||||
|
||||
case 00007: /* LTM */
|
||||
if (cpu_model & I_9X) /* 709X only */
|
||||
mode_ttrap = 0;
|
||||
break;
|
||||
|
||||
case 00010: /* LSNM */
|
||||
if (cpu_model & I_9X) /* 709X only */
|
||||
mode_storn = 0;
|
||||
break;
|
||||
|
||||
case 00012: /* RTT (704) */
|
||||
if (cpu_model & I_9X) /* 709X only */
|
||||
sel_trap (PC);
|
||||
break;
|
||||
|
||||
case 00016: /* EMTM */
|
||||
mode_multi = 1;
|
||||
break;
|
||||
|
||||
case 00140: /* SLF */
|
||||
if (cpu_model & I_9X) /* 709X only */
|
||||
SLT = 0;
|
||||
break;
|
||||
|
||||
case 00141: case 00142: case 00143: case 00144: /* SLT */
|
||||
if (cpu_model & I_9X) { /* 709X only */
|
||||
t = SLT & (1u << (00144 - addr));
|
||||
SLT = SLT & ~t;
|
||||
if (t != 0)
|
||||
PC = (PC + 1) & AMASK;
|
||||
}
|
||||
break;
|
||||
|
||||
case 00161: case 00162: case 00163: /* SWT */
|
||||
case 00164: case 00165: case 00166:
|
||||
if ((cpu_model & I_9X) && /* 709X only */
|
||||
((SSW & (1u << (00166 - addr))) != 0))
|
||||
PC = (PC + 1) & AMASK;
|
||||
break;
|
||||
|
||||
case 001000: case 002000: case 003000: case 004000: /* ETT */
|
||||
case 005000: case 006000: case 007000: case 010000:
|
||||
if (sel_trap (PC)) /* sel trap? */
|
||||
break;
|
||||
ch = GET_U_CH (addr); /* get channel */
|
||||
if (ch_flags[ch] & CHF_EOT) /* EOT? */
|
||||
ch_flags[ch] = ch_flags[ch] & ~CHF_EOT; /* clear */
|
||||
else PC = (PC + 1) & AMASK; /* else skip */
|
||||
break;
|
||||
}
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Floating add
|
||||
|
||||
Notes:
|
||||
- AC<Q,P> enter into the initial exponent comparison. If either is set,
|
||||
the numbers are always swapped. AC<P> gets OR'd into AC<S> during the
|
||||
swap, and AC<Q,P> are cleared afterwards
|
||||
- The early end test is actually > 077 if AC <= SR and > 100 if
|
||||
AC > SR. However, any shift >= 54 will produce a zero fraction,
|
||||
so the difference can be ignored */
|
||||
|
||||
uint32 op_fad (t_uint64 sr, t_bool norm)
|
||||
{
|
||||
UFP op1, op2, t;
|
||||
int32 mqch, diff;
|
||||
|
||||
MQ = 0; /* clear MQ */
|
||||
fp_unpack (AC, 0, 1, &op1); /* unpack AC */
|
||||
fp_unpack (sr, 0, 0, &op2); /* unpack sr */
|
||||
if (op1.ch > op2.ch) { /* AC exp > SR exp? */
|
||||
if (AC & AC_P) /* AC P or's with S */
|
||||
op1.s = 1;
|
||||
t = op1; /* swap operands */
|
||||
op1 = op2;
|
||||
op2 = t;
|
||||
op2.ch = op2.ch & FP_M_CH; /* clear P,Q */
|
||||
}
|
||||
diff = op2.ch - op1.ch; /* exp diff */
|
||||
if (diff) { /* any shift? */
|
||||
if ((diff < 0) || (diff > 077)) /* diff > 63? */
|
||||
op1.fr = 0;
|
||||
else op1.fr = op1.fr >> diff; /* no, denormalize */
|
||||
}
|
||||
if (op1.s ^ op2.s) { /* subtract? */
|
||||
if (op1.fr >= op2.fr) { /* op1 > op2? */
|
||||
op2.fr = op1.fr - op2.fr; /* op1 - op2 */
|
||||
op2.s = op1.s; /* op2 sign is result */
|
||||
}
|
||||
else op2.fr = op2.fr - op1.fr; /* else op2 - op1 */
|
||||
}
|
||||
else {
|
||||
op2.fr = op2.fr + op1.fr; /* op2 + op1 */
|
||||
if (op2.fr & FP_FCRY) { /* carry? */
|
||||
op2.fr = op2.fr >> 1; /* renormalize */
|
||||
op2.ch++; /* incr exp */
|
||||
}
|
||||
}
|
||||
if (norm) { /* normalize? */
|
||||
if (op2.fr) { /* non-zero frac? */
|
||||
fp_norm (&op2);
|
||||
mqch = op2.ch - FP_N_FR;
|
||||
}
|
||||
else op2.ch = mqch = 0; /* else true zero */
|
||||
}
|
||||
else mqch = op2.ch - FP_N_FR;
|
||||
return fp_pack (&op2, op2.s, mqch); /* pack AC, MQ */
|
||||
}
|
||||
|
||||
/* Floating multiply */
|
||||
|
||||
uint32 op_fmp (t_uint64 sr, t_bool norm)
|
||||
{
|
||||
UFP op1, op2;
|
||||
int32 mqch;
|
||||
uint32 f1h, f2h;
|
||||
|
||||
fp_unpack (MQ, 0, 0, &op1); /* unpack MQ */
|
||||
fp_unpack (sr, 0, 0, &op2); /* unpack sr */
|
||||
op1.s = op1.s ^ op2.s; /* result sign */
|
||||
if ((op2.ch == 0) && (op2.fr == 0)) { /* sr a normal 0? */
|
||||
AC = op1.s? AC_S: 0; /* result is 0 */
|
||||
MQ = op1.s? SIGN: 0;
|
||||
return 0;
|
||||
}
|
||||
f1h = FP_HIFRAC (op1.fr); /* get hi fracs */
|
||||
f2h = FP_HIFRAC (op2.fr);
|
||||
op1.fr = ((t_uint64) f1h) * ((t_uint64) f2h); /* f1h * f2h */
|
||||
op1.ch = (op1.ch & FP_M_CH) + op2.ch - FP_BIAS; /* result exponent */
|
||||
if (norm) { /* normalize? */
|
||||
if (!(op1.fr & FP_FNORM)) { /* not normalized? */
|
||||
op1.fr = op1.fr << 1; /* shift frac left 1 */
|
||||
op1.ch--; /* decr exp */
|
||||
}
|
||||
if (FP_HIFRAC (op1.fr)) /* hi result non-zero? */
|
||||
mqch = op1.ch - FP_N_FR; /* set MQ exp */
|
||||
else op1.ch = mqch = 0; /* clear AC, MQ exp */
|
||||
}
|
||||
else mqch = op1.ch - FP_N_FR; /* set MQ exp */
|
||||
return fp_pack (&op1, op1.s, mqch); /* pack AC, MQ */
|
||||
}
|
||||
|
||||
/* Floating divide */
|
||||
|
||||
uint32 op_fdv (t_uint64 sr)
|
||||
{
|
||||
UFP op1, op2;
|
||||
int32 mqch;
|
||||
uint32 spill, quos;
|
||||
t_uint64 rem;
|
||||
|
||||
fp_unpack (AC, 0, 1, &op1); /* unpack AC */
|
||||
fp_unpack (sr, 0, 0, &op2); /* unpack sr */
|
||||
quos = op1.s ^ op2.s; /* quotient sign */
|
||||
if (op1.fr >= (2 * op2.fr)) { /* |AC| >= 2*|sr|? */
|
||||
MQ = quos? SIGN: 0; /* MQ = sign only */
|
||||
return TRAP_F_DVC; /* divide check */
|
||||
}
|
||||
if (op1.fr == 0) { /* |AC| == 0? */
|
||||
MQ = quos? SIGN: 0; /* MQ = sign only */
|
||||
AC = 0; /* AC = +0 */
|
||||
return 0; /* done */
|
||||
}
|
||||
op1.ch = op1.ch & FP_M_CH; /* remove AC<Q,P> */
|
||||
if (op1.fr >= op2.fr) { /* |AC| >= |sr|? */
|
||||
op1.fr = op1.fr >> 1; /* denorm AC */
|
||||
op1.ch++;
|
||||
}
|
||||
op1.fr = fp_fracdiv (op1.fr, op2.fr, &rem); /* fraction divide */
|
||||
op1.fr = op1.fr | (rem << FP_N_FR); /* rem'quo */
|
||||
mqch = op1.ch - op2.ch + FP_BIAS; /* quotient exp */
|
||||
op1.ch = op1.ch - FP_N_FR; /* remainder exp */
|
||||
spill = fp_pack (&op1, quos, mqch); /* pack up */
|
||||
return (spill? (spill | TRAP_F_SGL): 0); /* if spill, set SGL */
|
||||
}
|
||||
|
||||
/* Double floating add
|
||||
|
||||
Notes:
|
||||
- AC<Q,P> enter into the initial exponent comparison. If either is set,
|
||||
the numbers are always swapped. AC<P> gets OR'd into AC<S> during the
|
||||
swap, and AC<Q,P> are cleared afterwards
|
||||
- For most cases, SI ends up with the high order part of the larger number
|
||||
- The 'early end' cases (smaller number is shifted away) must be tracked
|
||||
exactly for SI impacts. The early end cases are:
|
||||
|
||||
(a) AC > SR, diff > 0100, and AC normalized
|
||||
(b) AC <= SR, diff > 077, and SR normalized
|
||||
|
||||
In case (a), SI is unchanged. In case (b), SI ends up with the SR sign
|
||||
and characteristic but the MQ (!) fraction */
|
||||
|
||||
uint32 op_dfad (t_uint64 sr, t_uint64 sr1, t_bool norm)
|
||||
{
|
||||
UFP op1, op2, t;
|
||||
int32 mqch, diff;
|
||||
|
||||
fp_unpack (AC, MQ, 1, &op1); /* unpack AC'MQ */
|
||||
fp_unpack (sr, sr1, 0, &op2); /* unpack sr'sr1 */
|
||||
if (op1.ch > op2.ch) { /* AC exp > SR exp? */
|
||||
if (((op1.ch - op2.ch) > 0100) && (AC & B9)) ; /* early out */
|
||||
else SI = FP_PACK36 (op1.s, op1.ch, FP_HIFRAC (op1.fr));
|
||||
if (AC & AC_P) /* AC P or's with S */
|
||||
op1.s = 1;
|
||||
t = op1; /* swap operands */
|
||||
op1 = op2;
|
||||
op2 = t;
|
||||
op2.ch = op2.ch & FP_M_CH; /* clear P,Q */
|
||||
}
|
||||
else { /* AC <= SR */
|
||||
if (((op2.ch - op1.ch) > 077) && (sr & B9)) /* early out */
|
||||
SI = FP_PACK36 (op2.s, op2.ch, FP_LOFRAC (MQ));
|
||||
else SI = FP_PACK36 (op2.s, op2.ch, FP_HIFRAC (op2.fr));
|
||||
}
|
||||
diff = op2.ch - op1.ch; /* exp diff */
|
||||
if (diff) { /* any shift? */
|
||||
if ((diff < 0) || (diff > 077)) /* diff > 63? */
|
||||
op1.fr = 0;
|
||||
else op1.fr = op1.fr >> diff; /* no, denormalize */
|
||||
}
|
||||
if (op1.s ^ op2.s) { /* subtract? */
|
||||
if (op1.fr >= op2.fr) { /* op1 > op2? */
|
||||
op2.fr = op1.fr - op2.fr; /* op1 - op2 */
|
||||
op2.s = op1.s; /* op2 sign is result */
|
||||
}
|
||||
else op2.fr = op2.fr - op1.fr; /* op2 - op1 */
|
||||
}
|
||||
else {
|
||||
op2.fr = op2.fr + op1.fr; /* op2 + op1 */
|
||||
if (op2.fr & FP_FCRY) { /* carry? */
|
||||
op2.fr = op2.fr >> 1; /* renormalize */
|
||||
op2.ch++; /* incr exp */
|
||||
}
|
||||
}
|
||||
if (norm) { /* normalize? */
|
||||
if (op2.fr) { /* non-zero frac? */
|
||||
fp_norm (&op2);
|
||||
mqch = op2.ch - FP_N_FR;
|
||||
}
|
||||
else op2.ch = mqch = 0; /* else true zero */
|
||||
}
|
||||
else mqch = op2.ch - FP_N_FR;
|
||||
return fp_pack (&op2, op2.s, mqch); /* pack AC, MQ */
|
||||
}
|
||||
|
||||
/* Double floating multiply
|
||||
|
||||
Notes (notation is A+B' * C+D', where ' denotes 2^-27):
|
||||
- The instruction returns 0 if A and C are both zero, because B*D is never
|
||||
done as part of the algorithm
|
||||
- For most cases, SI ends up with B*C, with a zero sign and exponent
|
||||
- For the A+B' both zero 'early end' case SI ends up with A or C,
|
||||
depending on whether the operation is normalized or not */
|
||||
|
||||
uint32 op_dfmp (t_uint64 sr, t_uint64 sr1, t_bool norm)
|
||||
{
|
||||
UFP op1, op2;
|
||||
int32 mqch;
|
||||
uint32 f1h, f2h, f1l, f2l;
|
||||
t_uint64 tx;
|
||||
|
||||
fp_unpack (AC, MQ, 1, &op1); /* unpack AC'MQ */
|
||||
fp_unpack (sr, sr1, 0, &op2); /* unpack sr'sr1 */
|
||||
op1.s = op1.s ^ op2.s; /* result sign */
|
||||
f1h = FP_HIFRAC (op1.fr); /* A */
|
||||
f1l = FP_LOFRAC (op1.fr); /* B */
|
||||
f2h = FP_HIFRAC (op2.fr); /* C */
|
||||
f2l = FP_LOFRAC (op2.fr); /* D */
|
||||
if (((op1.ch == 0) && (op1.fr == 0)) || /* AC'MQ normal 0? */
|
||||
((op2.ch == 0) && (op2.fr == 0)) || /* sr'sr1 normal 0? */
|
||||
((f1h == 0) && (f2h == 0))) { /* both hi frac zero? */
|
||||
AC = op1.s? AC_S: 0; /* result is 0 */
|
||||
MQ = op1.s? SIGN: 0;
|
||||
SI = sr; /* SI has C */
|
||||
return 0;
|
||||
}
|
||||
op1.ch = (op1.ch & FP_M_CH) + op2.ch - FP_BIAS; /* result exponent */
|
||||
if (op1.fr) { /* A'B != 0? */
|
||||
op1.fr = ((t_uint64) f1h) * ((t_uint64) f2h); /* A * C */
|
||||
tx = ((t_uint64) f1h) * ((t_uint64) f2l); /* A * D */
|
||||
op1.fr = op1.fr + (tx >> FP_N_FR); /* add in hi 27b */
|
||||
tx = ((t_uint64) f1l) * ((t_uint64) f2h); /* B * C */
|
||||
op1.fr = op1.fr + (tx >> FP_N_FR); /* add in hi 27b */
|
||||
SI = tx >> FP_N_FR; /* SI keeps B * C */
|
||||
}
|
||||
else {
|
||||
if (norm) /* early out */
|
||||
SI = sr;
|
||||
else SI = FP_PACK36 (op2.s, op2.ch, 0);
|
||||
}
|
||||
if (norm) { /* normalize? */
|
||||
if (!(op1.fr & FP_FNORM)) { /* not normalized? */
|
||||
op1.fr = op1.fr << 1; /* shift frac left 1 */
|
||||
op1.ch--; /* decr exp */
|
||||
}
|
||||
if (FP_HIFRAC (op1.fr)) { /* non-zero? */
|
||||
mqch = op1.ch - FP_N_FR; /* set MQ exp */
|
||||
}
|
||||
else op1.ch = mqch = 0; /* clear AC, MQ exp */
|
||||
}
|
||||
else mqch = op1.ch - FP_N_FR; /* set MQ exp */
|
||||
return fp_pack (&op1, op1.s, mqch); /* pack AC, MQ */
|
||||
}
|
||||
|
||||
/* Double floating divide
|
||||
|
||||
|
||||
Notes:
|
||||
- This is a Taylor series expansion (where ' denotes >> 27):
|
||||
|
||||
(A+B') * (C+D')^-1 = (A+B') * C^-1 - (A+B') * D'* C^-2 +...
|
||||
|
||||
to two terms, which can be rewritten as terms Q1, Q2:
|
||||
|
||||
Q1 = (A+B')/C
|
||||
Q2' = (R - Q1*D)'/C
|
||||
|
||||
- Tracking the sign of Q2' is complicated:
|
||||
|
||||
Q1 has the sign of the quotient, s_AC ^ s_SR
|
||||
D has the sign of the divisor, s_SR
|
||||
R has the sign of the dividend, s_AC
|
||||
Q1*D sign is s_AC ^ s_SR ^ s^SR = s^AC
|
||||
Therefore, R and Q1*D have the same sign, s_AC
|
||||
Q2' sign is s^AC ^ s_SR, which is the sign of the quotient
|
||||
|
||||
- For first divide check, SI is 0
|
||||
- For other cases, including second divide check, SI ends up with Q1
|
||||
- R-Q1*D is only calculated to the high 27b; using the full 54b
|
||||
throws off the result
|
||||
- The second divide must check for divd >= divr, otherwise an extra
|
||||
bit of quotient would be devloped, throwing off the result
|
||||
- A late ECO added full post-normalization; single precision divide
|
||||
does no normalization */
|
||||
|
||||
uint32 op_dfdv (t_uint64 sr, t_uint64 sr1)
|
||||
{
|
||||
UFP op1, op2;
|
||||
int32 mqch;
|
||||
uint32 csign, ac_s;
|
||||
t_uint64 f1h, f2h, tr, tq1, tq1d, trmq1d, tq2;
|
||||
|
||||
fp_unpack (AC, MQ, 1, &op1); /* unpack AC'MQ */
|
||||
fp_unpack (sr, 0, 0, &op2); /* unpack sr only */
|
||||
ac_s = op1.s; /* save AC sign */
|
||||
op1.s = op1.s ^ op2.s; /* sign of result */
|
||||
f1h = FP_HIFRAC (op1.fr);
|
||||
f2h = FP_HIFRAC (op2.fr);
|
||||
if (f1h >= (2 * f2h)) { /* |A| >= 2*|C|? */
|
||||
SI = 0; /* clear SI */
|
||||
return TRAP_F_DVC; /* divide check */
|
||||
}
|
||||
if (f1h == 0) { /* |AC| == 0? */
|
||||
SI = MQ = op1.s? SIGN: 0; /* MQ, SI = sign only */
|
||||
AC = op1.s? AC_S: 0; /* AC = sign only */
|
||||
return 0; /* done */
|
||||
}
|
||||
op1.ch = op1.ch & FP_M_CH; /* remove AC<Q,P> */
|
||||
if (f1h >= f2h) { /* |A| >= |C|? */
|
||||
op1.fr = op1.fr >> 1; /* denorm AC */
|
||||
op1.ch++;
|
||||
}
|
||||
op1.ch = op1.ch - op2.ch + FP_BIAS; /* exp of quotient */
|
||||
tq1 = fp_fracdiv (op1.fr, op2.fr, &tr); /* |A+B| / |C| */
|
||||
tr = tr << FP_N_FR; /* R << 27 */
|
||||
tq1d = (tq1 * ((t_uint64) FP_LOFRAC (sr1))) & /* Q1 * D */
|
||||
~((t_uint64) FP_FMASK); /* top 27 bits */
|
||||
csign = (tr < tq1d); /* correction sign */
|
||||
if (csign) /* |R|<|Q1*D|? compl */
|
||||
trmq1d = tq1d - tr;
|
||||
else trmq1d = tr - tq1d; /* no, subtr ok */
|
||||
SI = FP_PACK36 (op1.s, op1.ch, tq1); /* SI has Q1 */
|
||||
if (trmq1d >= (2 * op2.fr)) { /* |R-Q1*D| >= 2*|C|? */
|
||||
AC = FP_PACK38 (csign ^ ac_s, 0, FP_HIFRAC (trmq1d)); /* AC has R-Q1*D */
|
||||
MQ = (csign ^ ac_s)? SIGN: 0; /* MQ = sign only */
|
||||
return TRAP_F_DVC; /* divide check */
|
||||
}
|
||||
tq2 = fp_fracdiv (trmq1d, op2.fr, NULL); /* |R-Q1*D| / |C| */
|
||||
if (trmq1d >= op2.fr) /* can only gen 27b quo */
|
||||
tq2 &= ~((t_uint64) 1);
|
||||
op1.fr = tq1 << FP_N_FR; /* shift Q1 into place */
|
||||
if (csign) /* sub or add Q2 */
|
||||
op1.fr = op1.fr - tq2;
|
||||
else op1.fr = op1.fr + tq2;
|
||||
fp_norm (&op1); /* normalize */
|
||||
if (op1.fr) /* non-zero? */
|
||||
mqch = op1.ch - FP_N_FR;
|
||||
else op1.ch = mqch = 0; /* clear AC, MQ exp */
|
||||
return fp_pack (&op1, op1.s, mqch); /* pack AC, MQ */
|
||||
}
|
||||
|
||||
/* Floating round */
|
||||
|
||||
uint32 op_frnd (void)
|
||||
{
|
||||
UFP op;
|
||||
uint32 spill;
|
||||
|
||||
spill = 0; /* no error */
|
||||
if (MQ & B9) { /* MQ9 set? */
|
||||
fp_unpack (AC, 0, 1, &op); /* unpack AC */
|
||||
op.fr = op.fr + ((t_uint64) (1 << FP_N_FR)); /* round up */
|
||||
if (op.fr & FP_FCRY) { /* carry out? */
|
||||
op.fr = op.fr >> 1; /* renormalize */
|
||||
op.ch++; /* incr exp */
|
||||
if (op.ch == (FP_M_CH + 1)) /* ovf with QP = 0? */
|
||||
spill = TRAP_F_OVF | TRAP_F_AC;
|
||||
}
|
||||
AC = FP_PACK38 (op.s, op.ch, FP_HIFRAC (op.fr)); /* pack AC */
|
||||
}
|
||||
return spill;
|
||||
}
|
||||
|
||||
/* Fraction divide - 54/27'0 yielding quotient and remainder */
|
||||
|
||||
t_uint64 fp_fracdiv (t_uint64 dvd, t_uint64 dvr, t_uint64 *rem)
|
||||
{
|
||||
dvr = dvr >> FP_N_FR;
|
||||
if (rem)
|
||||
*rem = dvd % dvr;
|
||||
return (dvd / dvr);
|
||||
}
|
||||
|
||||
/* Floating point normalize */
|
||||
|
||||
void fp_norm (UFP *op)
|
||||
{
|
||||
op->fr = op->fr & FP_DFMASK; /* mask fraction */
|
||||
if (op->fr == 0) /* zero? */
|
||||
return;
|
||||
while ((op->fr & FP_FNORM) == 0) { /* until norm */
|
||||
op->fr = op->fr << 1; /* lsh 1 */
|
||||
op->ch--; /* decr exp */
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Floating point unpack */
|
||||
|
||||
void fp_unpack (t_uint64 h, t_uint64 l, t_bool q_ac, UFP *op)
|
||||
{
|
||||
if (q_ac) { /* AC? */
|
||||
op->s = (h & AC_S)? 1: 0; /* get sign */
|
||||
op->ch = (uint32) ((h >> FP_V_CH) & FP_M_ACCH); /* get exp */
|
||||
}
|
||||
else {
|
||||
op->s = (h & SIGN)? 1: 0; /* no, mem */
|
||||
op->ch = (uint32) ((h >> FP_V_CH) & FP_M_CH);
|
||||
}
|
||||
op->fr = (((t_uint64) FP_LOFRAC (h)) << FP_N_FR) | /* get frac hi */
|
||||
((t_uint64) FP_LOFRAC (l)); /* get frac lo */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Floating point pack */
|
||||
|
||||
uint32 fp_pack (UFP *op, uint32 mqs, int32 mqch)
|
||||
{
|
||||
uint32 spill;
|
||||
|
||||
AC = FP_PACK38 (op->s, op->ch, FP_HIFRAC (op->fr)); /* pack AC */
|
||||
MQ = FP_PACK36 (mqs, mqch, FP_LOFRAC (op->fr)); /* pack MQ */
|
||||
if (op->ch > FP_M_CH) /* check AC exp */
|
||||
spill = TRAP_F_OVF | TRAP_F_AC;
|
||||
else if (op->ch < 0)
|
||||
spill = TRAP_F_AC;
|
||||
else spill = 0;
|
||||
if (mqch > FP_M_CH) /* check MQ exp */
|
||||
spill |= (TRAP_F_OVF | TRAP_F_MQ);
|
||||
else if (mqch < 0)
|
||||
spill |= TRAP_F_MQ;
|
||||
return spill;
|
||||
}
|
2439
I7094/i7094_cpu_old.c
Normal file
2439
I7094/i7094_cpu_old.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
/* i7094_defs.h: IBM 7094 simulator definitions
|
||||
|
||||
Copyright (c) 2003-2008, Robert M Supnik
|
||||
Copyright (c) 2003-2010, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -26,13 +26,21 @@
|
|||
This simulator incorporates prior work by Paul Pierce, Dave Pitts, and Rob
|
||||
Storey. Tom Van Vleck, Stan Dunten, Jerry Saltzer, and other CTSS veterans
|
||||
helped to reconstruct the CTSS hardware RPQ's. Dave Pitts gets special
|
||||
thanks for patiently coaching me through IBSYS debug. */
|
||||
thanks for patiently coaching me through IBSYS debug.
|
||||
|
||||
22-May-10 RMS Added check for 64b addresses
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _I7094_DEFS_H_
|
||||
#define _I7094_DEFS_H_ 0
|
||||
|
||||
#include "sim_defs.h" /* simulator defns */
|
||||
|
||||
#if defined(USE_ADDR64)
|
||||
#error "7094 does not support 64b addresses!"
|
||||
#endif
|
||||
|
||||
/* Simulator stop codes */
|
||||
|
||||
#define STOP_HALT 1 /* halted */
|
||||
|
@ -168,6 +176,8 @@ typedef struct {
|
|||
#define INST_M_TAG 07
|
||||
#define INST_V_ADDR 0
|
||||
#define INST_M_ADDR 077777
|
||||
#define INST_V_4B 0
|
||||
#define INST_M_4B 017
|
||||
|
||||
#define GET_OPD(x) ((uint32) (((x) >> INST_V_OPD) & INST_M_OPD))
|
||||
#define GET_DEC(x) ((uint32) (((x) >> INST_V_DEC) & INST_M_DEC))
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
mt magtape simulator
|
||||
|
||||
16-Jul-10 RMS Fixed handling of BSR, BSF (from Dave Pitts)
|
||||
*/
|
||||
|
||||
#include "i7094_defs.h"
|
||||
|
@ -44,7 +46,7 @@ uint32 mt_bptr[NUM_CHAN];
|
|||
uint32 mt_blnt[NUM_CHAN];
|
||||
t_uint64 mt_chob[NUM_CHAN];
|
||||
uint32 mt_chob_v[NUM_CHAN];
|
||||
uint32 mt_tshort = 2;
|
||||
uint32 mt_tshort = 2; /* "a few microseconds" */
|
||||
uint32 mt_twef = 25000; /* 50 msec */
|
||||
uint32 mt_tstart = 29000; /* 58 msec */
|
||||
uint32 mt_tstop = 10000; /* 20 msec */
|
||||
|
@ -474,8 +476,6 @@ else { /* real tape */
|
|||
|
||||
case CHSL_RDS:
|
||||
case CHSL_WRS:
|
||||
case CHSL_BSR:
|
||||
case CHSL_BSF: /* rd, wr, backspace */
|
||||
sim_activate (uptr, mt_tstart); /* schedule op */
|
||||
break;
|
||||
|
||||
|
@ -483,10 +483,10 @@ else { /* real tape */
|
|||
sim_activate (uptr, mt_twef); /* schedule op */
|
||||
break;
|
||||
|
||||
case CHSL_RUN:
|
||||
sim_activate (uptr, mt_tshort); /* schedule quick event */
|
||||
break;
|
||||
case CHSL_BSR:
|
||||
case CHSL_BSF: /* backspace */
|
||||
case CHSL_REW:
|
||||
case CHSL_RUN:
|
||||
case CHSL_SDN: /* rew, rew/unl, set det */
|
||||
sim_activate (uptr, mt_tshort); /* schedule quick event */
|
||||
break;
|
||||
|
@ -649,10 +649,15 @@ switch (uptr->UST) { /* case on state */
|
|||
mt_unit[ch]? "continuing": "disconnecting");
|
||||
return SCPE_OK;
|
||||
|
||||
case CHSL_BSR: /* backspace rec */
|
||||
case CHSL_BSR: case CHSL_BSF: /* backspace */
|
||||
uptr->UST = uptr->UST | CHSL_2ND; /* set 2nd state */
|
||||
sim_activate (uptr, mt_tstart); /* reactivate */
|
||||
ch6_end_nds (ch); /* disconnect */
|
||||
return SCPE_OK;
|
||||
|
||||
case CHSL_BSR|CHSL_2ND: /* backspace rec */
|
||||
r = sim_tape_sprecr (uptr, &bc); /* space backwards */
|
||||
mt_unit[ch] = 0; /* clr ctrl busy */
|
||||
ch6_end_nds (ch); /* disconnect */
|
||||
if (DEBUG_PRS (mt_dev[ch]))
|
||||
fprintf (sim_deb, ">>%s%d BSR complete, pos = %d\n",
|
||||
mt_dev[ch].name, u, uptr->pos);
|
||||
|
@ -660,10 +665,9 @@ switch (uptr->UST) { /* case on state */
|
|||
return SCPE_OK;
|
||||
return mt_map_err (uptr, r);
|
||||
|
||||
case CHSL_BSF: /* backspace file */
|
||||
case CHSL_BSF|CHSL_2ND: /* backspace file */
|
||||
while ((r = sim_tape_sprecr (uptr, &bc)) == MTSE_OK) ;
|
||||
mt_unit[ch] = 0; /* clr ctrl busy */
|
||||
ch6_end_nds (ch); /* disconnect */
|
||||
if (DEBUG_PRS (mt_dev[ch]))
|
||||
fprintf (sim_deb, ">>%s%d BSF complete, pos = %d\n",
|
||||
mt_dev[ch].name, u, uptr->pos);
|
||||
|
|
861
I7094/i7094_mt_old.c
Normal file
861
I7094/i7094_mt_old.c
Normal file
|
@ -0,0 +1,861 @@
|
|||
/* i7094_mt.c: IBM 7094 magnetic tape simulator
|
||||
|
||||
Copyright (c) 2003-2008, 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 magtape simulator
|
||||
*/
|
||||
|
||||
#include "i7094_defs.h"
|
||||
#include "sim_tape.h"
|
||||
|
||||
#define UST u3 /* unit state */
|
||||
#define UCH u4 /* channel number */
|
||||
#define MTUF_V_LDN (MTUF_V_UF + 0)
|
||||
#define MTUF_LDN (1 << MTUF_V_LDN)
|
||||
#define MT_MAXFR ((1 << 18) + 2)
|
||||
|
||||
#define QCHRONO(c,u) ((cpu_model & I_CT) && \
|
||||
((c) == CHRONO_CH) && ((u) == CHRONO_UNIT))
|
||||
|
||||
uint8 *mtxb[NUM_CHAN] = { NULL }; /* xfer buffer */
|
||||
uint32 mt_unit[NUM_CHAN]; /* unit */
|
||||
uint32 mt_bptr[NUM_CHAN];
|
||||
uint32 mt_blnt[NUM_CHAN];
|
||||
t_uint64 mt_chob[NUM_CHAN];
|
||||
uint32 mt_chob_v[NUM_CHAN];
|
||||
uint32 mt_tshort = 2;
|
||||
uint32 mt_twef = 25000; /* 50 msec */
|
||||
uint32 mt_tstart = 29000; /* 58 msec */
|
||||
uint32 mt_tstop = 10000; /* 20 msec */
|
||||
uint32 mt_tword = 50; /* 125 usec */
|
||||
|
||||
static const uint8 odd_par[64] = {
|
||||
1, 0, 0, 1, 0, 1, 1, 0,
|
||||
0, 1, 1, 0, 1, 0, 0, 1,
|
||||
0, 1, 1, 0, 1, 0, 0, 1,
|
||||
1, 0, 0, 1, 0, 1, 1, 0,
|
||||
0, 1, 1, 0, 1, 0, 0, 1,
|
||||
1, 0, 0, 1, 0, 1, 1, 0,
|
||||
1, 0, 0, 1, 0, 1, 1, 0,
|
||||
0, 1, 1, 0, 1, 0, 0, 1
|
||||
};
|
||||
|
||||
static const char *tape_stat[] = {
|
||||
"OK", "TMK", "UNATT", "IOERR", "INVRECLNT",
|
||||
"FMT", "BOT", "EOM", "RECERR", "WRPROT"
|
||||
};
|
||||
|
||||
extern uint32 PC;
|
||||
extern uint32 cpu_model;
|
||||
extern uint32 ind_ioc;
|
||||
extern FILE *sim_deb;
|
||||
extern char *sel_name[];
|
||||
|
||||
t_stat mt_chsel (uint32 ch, uint32 sel, uint32 unit);
|
||||
t_stat mt_chwr (uint32 ch, t_uint64 val, uint32 flags);
|
||||
t_stat mt_rec_end (UNIT *uptr);
|
||||
t_stat mt_svc (UNIT *uptr);
|
||||
t_stat mt_reset (DEVICE *dptr);
|
||||
t_stat mt_attach (UNIT *uptr, char *cptr);
|
||||
t_stat mt_boot (int32 unitno, DEVICE *dptr);
|
||||
t_stat mt_map_err (UNIT *uptr, t_stat st);
|
||||
|
||||
extern uint32 chrono_rd (uint8 *buf, uint32 bufsiz);
|
||||
|
||||
/* 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_chsel, &mt_chwr };
|
||||
|
||||
MTAB mt_mod[] = {
|
||||
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
|
||||
{ MTUF_LDN, 0, "high density", "HIGH", NULL },
|
||||
{ MTUF_LDN, MTUF_LDN, "low density", "LOW", NULL },
|
||||
{ MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
|
||||
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
UNIT mta_unit[] = {
|
||||
{ UDATA (NULL, UNIT_DIS, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }
|
||||
};
|
||||
|
||||
REG mta_reg[] = {
|
||||
{ ORDATA (UNIT, mt_unit[0], 5) },
|
||||
{ ORDATA (CHOB, mt_chob[0], 36) },
|
||||
{ FLDATA (CHOBV, mt_chob_v[0], 0) },
|
||||
{ DRDATA (BPTR, mt_bptr[0], 16), PV_LEFT },
|
||||
{ DRDATA (BLNT, mt_blnt[0], 16), PV_LEFT },
|
||||
{ BRDATA (BUF, NULL, 8, 7, MT_MAXFR) },
|
||||
{ DRDATA (TWEF, mt_twef, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TSHORT, mt_tshort, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TSTART, mt_tstart, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TSTOP, mt_tstop, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TWORD, mt_tword, 24), REG_NZ + PV_LEFT },
|
||||
{ URDATA (UST, mta_unit[0].UST, 8, 5, 0, MT_NUMDR + 1, 0) },
|
||||
{ URDATA (POS, mta_unit[0].pos, 10, T_ADDR_W, 0,
|
||||
MT_NUMDR + 1, PV_LEFT | REG_RO) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
UNIT mtb_unit[] = {
|
||||
{ UDATA (NULL, UNIT_DIS, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }
|
||||
};
|
||||
|
||||
REG mtb_reg[] = {
|
||||
{ ORDATA (UNIT, mt_unit[1], 5) },
|
||||
{ ORDATA (CHOB, mt_chob[1], 36) },
|
||||
{ FLDATA (CHOBV, mt_chob_v[1], 0) },
|
||||
{ DRDATA (BPTR, mt_bptr[1], 16), PV_LEFT },
|
||||
{ DRDATA (BLNT, mt_blnt[1], 16), PV_LEFT },
|
||||
{ BRDATA (BUF, NULL, 8, 7, MT_MAXFR) },
|
||||
{ DRDATA (TWEF, mt_twef, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TSHORT, mt_tshort, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TSTART, mt_tstart, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TSTOP, mt_tstop, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TWORD, mt_tword, 24), REG_NZ + PV_LEFT },
|
||||
{ URDATA (UST, mtb_unit[0].UST, 8, 5, 0, MT_NUMDR + 1, 0) },
|
||||
{ URDATA (POS, mtb_unit[0].pos, 10, T_ADDR_W, 0,
|
||||
MT_NUMDR + 1, PV_LEFT | REG_RO) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
UNIT mtc_unit[] = {
|
||||
{ UDATA (NULL, UNIT_DIS, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }
|
||||
};
|
||||
|
||||
REG mtc_reg[] = {
|
||||
{ ORDATA (UNIT, mt_unit[2], 5) },
|
||||
{ ORDATA (CHOB, mt_chob[2], 36) },
|
||||
{ FLDATA (CHOBV, mt_chob_v[2], 0) },
|
||||
{ DRDATA (BPTR, mt_bptr[2], 16), PV_LEFT },
|
||||
{ DRDATA (BLNT, mt_blnt[2], 16), PV_LEFT },
|
||||
{ BRDATA (BUF, NULL, 8, 7, MT_MAXFR) },
|
||||
{ DRDATA (TWEF, mt_twef, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TSHORT, mt_tshort, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TSTART, mt_tstart, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TSTOP, mt_tstop, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TWORD, mt_tword, 24), REG_NZ + PV_LEFT },
|
||||
{ URDATA (UST, mtc_unit[0].UST, 8, 5, 0, MT_NUMDR + 1, 0) },
|
||||
{ URDATA (POS, mtc_unit[0].pos, 10, T_ADDR_W, 0,
|
||||
MT_NUMDR + 1, PV_LEFT | REG_RO) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
UNIT mtd_unit[] = {
|
||||
{ UDATA (NULL, UNIT_DIS, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }
|
||||
};
|
||||
|
||||
REG mtd_reg[] = {
|
||||
{ ORDATA (UNIT, mt_unit[3], 5) },
|
||||
{ ORDATA (CHOB, mt_chob[3], 36) },
|
||||
{ FLDATA (CHOBV, mt_chob_v[3], 0) },
|
||||
{ DRDATA (BPTR, mt_bptr[3], 16), PV_LEFT },
|
||||
{ DRDATA (BLNT, mt_blnt[3], 16), PV_LEFT },
|
||||
{ BRDATA (BUF, NULL, 8, 7, MT_MAXFR) },
|
||||
{ DRDATA (TWEF, mt_twef, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TSHORT, mt_tshort, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TSTART, mt_tstart, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TSTOP, mt_tstop, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TWORD, mt_tword, 24), REG_NZ + PV_LEFT },
|
||||
{ URDATA (UST, mtd_unit[0].UST, 8, 5, 0, MT_NUMDR + 1, 0) },
|
||||
{ URDATA (POS, mtd_unit[0].pos, 10, T_ADDR_W, 0,
|
||||
MT_NUMDR + 1, PV_LEFT | REG_RO) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
UNIT mte_unit[] = {
|
||||
{ UDATA (NULL, UNIT_DIS, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }
|
||||
};
|
||||
|
||||
REG mte_reg[] = {
|
||||
{ ORDATA (UNIT, mt_unit[4], 5) },
|
||||
{ ORDATA (CHOB, mt_chob[4], 36) },
|
||||
{ FLDATA (CHOBV, mt_chob_v[4], 0) },
|
||||
{ DRDATA (BPTR, mt_bptr[4], 16), PV_LEFT },
|
||||
{ DRDATA (BLNT, mt_blnt[4], 16), PV_LEFT },
|
||||
{ BRDATA (BUF, NULL, 8, 7, MT_MAXFR) },
|
||||
{ DRDATA (TWEF, mt_twef, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TSHORT, mt_tshort, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TSTART, mt_tstart, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TSTOP, mt_tstop, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TWORD, mt_tword, 24), REG_NZ + PV_LEFT },
|
||||
{ URDATA (UST, mte_unit[0].UST, 8, 5, 0, MT_NUMDR + 1, 0) },
|
||||
{ URDATA (POS, mte_unit[0].pos, 10, T_ADDR_W, 0,
|
||||
MT_NUMDR + 1, PV_LEFT | REG_RO) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
UNIT mtf_unit[] = {
|
||||
{ UDATA (NULL, UNIT_DIS, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }
|
||||
};
|
||||
|
||||
REG mtf_reg[] = {
|
||||
{ ORDATA (UNIT, mt_unit[5], 5) },
|
||||
{ ORDATA (CHOB, mt_chob[5], 36) },
|
||||
{ FLDATA (CHOBV, mt_chob_v[5], 0) },
|
||||
{ DRDATA (BPTR, mt_bptr[5], 16), PV_LEFT },
|
||||
{ DRDATA (BLNT, mt_blnt[5], 16), PV_LEFT },
|
||||
{ BRDATA (BUF, NULL, 8, 7, MT_MAXFR) },
|
||||
{ DRDATA (TWEF, mt_twef, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TSHORT, mt_tshort, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TSTART, mt_tstart, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TSTOP, mt_tstop, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TWORD, mt_tword, 24), REG_NZ + PV_LEFT },
|
||||
{ URDATA (UST, mtf_unit[0].UST, 8, 5, 0, MT_NUMDR + 1, 0) },
|
||||
{ URDATA (POS, mtf_unit[0].pos, 10, T_ADDR_W, 0,
|
||||
MT_NUMDR + 1, PV_LEFT | REG_RO) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
UNIT mtg_unit[] = {
|
||||
{ UDATA (NULL, UNIT_DIS, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }
|
||||
};
|
||||
|
||||
REG mtg_reg[] = {
|
||||
{ ORDATA (UNIT, mt_unit[6], 5) },
|
||||
{ ORDATA (CHOB, mt_chob[6], 36) },
|
||||
{ FLDATA (CHOBV, mt_chob_v[6], 0) },
|
||||
{ DRDATA (BPTR, mt_bptr[6], 16), PV_LEFT },
|
||||
{ DRDATA (BLNT, mt_blnt[6], 16), PV_LEFT },
|
||||
{ BRDATA (BUF, NULL, 8, 7, MT_MAXFR) },
|
||||
{ DRDATA (TWEF, mt_twef, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TSHORT, mt_tshort, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TSTART, mt_tstart, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TSTOP, mt_tstop, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TWORD, mt_tword, 24), REG_NZ + PV_LEFT },
|
||||
{ URDATA (UST, mtg_unit[0].UST, 8, 5, 0, MT_NUMDR + 1, 0) },
|
||||
{ URDATA (POS, mtg_unit[0].pos, 10, T_ADDR_W, 0,
|
||||
MT_NUMDR + 1, PV_LEFT | REG_RO) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
UNIT mth_unit[] = {
|
||||
{ UDATA (NULL, UNIT_DIS, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) },
|
||||
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_ROABLE+UNIT_DISABLE, 0) }
|
||||
};
|
||||
|
||||
REG mth_reg[] = {
|
||||
{ ORDATA (UNIT, mt_unit[7], 5) },
|
||||
{ ORDATA (CHOB, mt_chob[7], 36) },
|
||||
{ FLDATA (CHOBV, mt_chob_v[7], 0) },
|
||||
{ DRDATA (BPTR, mt_bptr[7], 16), PV_LEFT },
|
||||
{ DRDATA (BLNT, mt_blnt[7], 16), PV_LEFT },
|
||||
{ BRDATA (BUF, NULL, 8, 7, MT_MAXFR) },
|
||||
{ DRDATA (TWEF, mt_twef, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TSHORT, mt_tshort, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TSTART, mt_tstart, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TSTOP, mt_tstop, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TWORD, mt_tword, 24), REG_NZ + PV_LEFT },
|
||||
{ URDATA (UST, mth_unit[0].UST, 8, 5, 0, MT_NUMDR + 1, 0) },
|
||||
{ URDATA (POS, mth_unit[0].pos, 10, T_ADDR_W, 0,
|
||||
MT_NUMDR + 1, PV_LEFT | REG_RO) },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
DEVICE mt_dev[NUM_CHAN] = {
|
||||
{
|
||||
"MTA", mta_unit, mta_reg, mt_mod,
|
||||
MT_NUMDR + 1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &mt_reset,
|
||||
&mt_boot, &mt_attach, &sim_tape_detach,
|
||||
&mt_dib, DEV_DEBUG
|
||||
},
|
||||
{
|
||||
"MTB", mtb_unit, mtb_reg, mt_mod,
|
||||
MT_NUMDR + 1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &mt_reset,
|
||||
NULL, &mt_attach, &sim_tape_detach,
|
||||
&mt_dib, DEV_DIS|DEV_DEBUG
|
||||
},
|
||||
{
|
||||
"MTC", mtc_unit, mtc_reg, mt_mod,
|
||||
MT_NUMDR + 1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &mt_reset,
|
||||
NULL, &mt_attach, &sim_tape_detach,
|
||||
&mt_dib, DEV_DIS|DEV_DEBUG
|
||||
},
|
||||
{
|
||||
"MTD", mtd_unit, mtd_reg, mt_mod,
|
||||
MT_NUMDR + 1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &mt_reset,
|
||||
NULL, &mt_attach, &sim_tape_detach,
|
||||
&mt_dib, DEV_DIS|DEV_DEBUG
|
||||
},
|
||||
{
|
||||
"MTE", mte_unit, mte_reg, mt_mod,
|
||||
MT_NUMDR + 1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &mt_reset,
|
||||
NULL, &mt_attach, &sim_tape_detach,
|
||||
&mt_dib, DEV_DIS|DEV_DEBUG
|
||||
},
|
||||
{
|
||||
"MTF", mtf_unit, mtf_reg, mt_mod,
|
||||
MT_NUMDR + 1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &mt_reset,
|
||||
NULL, &mt_attach, &sim_tape_detach,
|
||||
&mt_dib, DEV_DIS|DEV_DEBUG
|
||||
},
|
||||
{
|
||||
"MTG", mtg_unit, mtg_reg, mt_mod,
|
||||
MT_NUMDR + 1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &mt_reset,
|
||||
NULL, &mt_attach, &sim_tape_detach,
|
||||
&mt_dib, DEV_DIS|DEV_DEBUG
|
||||
},
|
||||
{
|
||||
"MTH", mth_unit, mth_reg, mt_mod,
|
||||
MT_NUMDR + 1, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &mt_reset,
|
||||
NULL, &mt_attach, &sim_tape_detach,
|
||||
&mt_dib, DEV_DIS|DEV_DEBUG
|
||||
}
|
||||
};
|
||||
|
||||
/* Select controller
|
||||
|
||||
Inputs:
|
||||
ch = channel
|
||||
cmd = select command
|
||||
unit = unit
|
||||
Outputs:
|
||||
status = SCPE_OK if ok
|
||||
STOP_STALL if busy
|
||||
error code if error
|
||||
*/
|
||||
|
||||
static const int mt_must_att[CHSL_NUM] = {
|
||||
0, 1, 1, 0, 1, 1, 0, 0,
|
||||
1, 1, 1, 1, 1, 1, 0, 0
|
||||
};
|
||||
|
||||
static const int mt_will_wrt[CHSL_NUM] = {
|
||||
0, 0, 1, 0, 0, 1, 0, 0,
|
||||
1, 1, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
t_stat mt_chsel (uint32 ch, uint32 cmd, uint32 unit)
|
||||
{
|
||||
UNIT *uptr;
|
||||
uint32 u = unit & 017;
|
||||
|
||||
if ((ch >= NUM_CHAN) || (cmd == 0) || (cmd >= CHSL_NUM))
|
||||
return SCPE_IERR; /* invalid arg? */
|
||||
if (mt_dev[ch].flags & DEV_DIS) /* disabled? */
|
||||
return STOP_NXDEV;
|
||||
if ((u == 0) || (u > MT_NUMDR)) /* valid unit? */
|
||||
return STOP_NXDEV;
|
||||
uptr = mt_dev[ch].units + u; /* get unit ptr */
|
||||
if (uptr->flags & UNIT_DIS) /* disabled? */
|
||||
return STOP_NXDEV;
|
||||
if (mt_unit[ch] || sim_is_active (uptr)) /* ctrl or unit busy? */
|
||||
return ERR_STALL; /* stall */
|
||||
if (QCHRONO (ch, u)) { /* Chronolog clock? */
|
||||
if (cmd != CHSL_RDS) /* only reads */
|
||||
return STOP_ILLIOP;
|
||||
sim_activate (uptr, mt_tword); /* responds quickly */
|
||||
}
|
||||
else { /* real tape */
|
||||
if (!(uptr->flags & UNIT_ATT) && mt_must_att[cmd]) /* unit unatt? */
|
||||
return SCPE_UNATT;
|
||||
if (sim_tape_wrp (uptr) && mt_will_wrt[cmd]) /* unit wrp && write? */
|
||||
return STOP_WRP;
|
||||
if (DEBUG_PRS (mt_dev[ch]))
|
||||
fprintf (sim_deb, ">>%s%d %s, pos = %d\n",
|
||||
mt_dev[ch].name, u, sel_name[cmd], uptr->pos);
|
||||
|
||||
switch (cmd) { /* case on cmd */
|
||||
|
||||
case CHSL_RDS:
|
||||
case CHSL_WRS:
|
||||
case CHSL_BSR:
|
||||
case CHSL_BSF: /* rd, wr, backspace */
|
||||
sim_activate (uptr, mt_tstart); /* schedule op */
|
||||
break;
|
||||
|
||||
case CHSL_WEF: /* write eof? */
|
||||
sim_activate (uptr, mt_twef); /* schedule op */
|
||||
break;
|
||||
|
||||
case CHSL_RUN:
|
||||
sim_activate (uptr, mt_tshort); /* schedule quick event */
|
||||
break;
|
||||
case CHSL_REW:
|
||||
case CHSL_SDN: /* rew, rew/unl, set det */
|
||||
sim_activate (uptr, mt_tshort); /* schedule quick event */
|
||||
break;
|
||||
|
||||
default:
|
||||
return SCPE_IERR;
|
||||
} /* end switch */
|
||||
} /* end else */
|
||||
|
||||
uptr->UST = cmd; /* set cmd */
|
||||
mt_unit[ch] = unit & 0777; /* save unit */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Channel write routine */
|
||||
|
||||
t_stat mt_chwr (uint32 ch, t_uint64 val, uint32 eorfl)
|
||||
{
|
||||
int32 k, u;
|
||||
uint8 by, *xb;
|
||||
UNIT *uptr;
|
||||
|
||||
if (ch >= NUM_CHAN) /* invalid chan? */
|
||||
return SCPE_IERR;
|
||||
xb = mtxb[ch]; /* get xfer buf */
|
||||
u = mt_unit[ch] & 017;
|
||||
if ((xb == NULL) || (u > MT_NUMDR)) /* invalid args? */
|
||||
return SCPE_IERR;
|
||||
uptr = mt_dev[ch].units + u; /* get unit */
|
||||
mt_chob[ch] = val & DMASK; /* save word from chan */
|
||||
mt_chob_v[ch] = 1; /* set valid */
|
||||
|
||||
if (uptr->UST == (CHSL_WRS|CHSL_2ND)) { /* data write? */
|
||||
for (k = 30; /* proc 6 bytes */
|
||||
(k >= 0) && (mt_bptr[ch] < MT_MAXFR);
|
||||
k = k - 6) {
|
||||
by = (uint8) ((val >> k) & 077); /* get byte */
|
||||
if ((mt_unit[ch] & 020) == 0) { /* BCD? */
|
||||
if (by == 0) /* cvt bin 0 */
|
||||
by = BCD_ZERO;
|
||||
else if (by & 020) /* invert zones */
|
||||
by = by ^ 040;
|
||||
if (!odd_par[by]) /* even parity */
|
||||
by = by | 0100;
|
||||
}
|
||||
else if (odd_par[by]) /* bin, odd par */
|
||||
by = by | 0100;
|
||||
xb[mt_bptr[ch]++] = by; /* put in buffer */
|
||||
}
|
||||
if (eorfl)
|
||||
return mt_rec_end (uptr); /* EOR? write rec */
|
||||
return SCPE_OK;
|
||||
}
|
||||
return SCPE_IERR;
|
||||
}
|
||||
|
||||
/* Unit timeout */
|
||||
|
||||
t_stat mt_svc (UNIT *uptr)
|
||||
{
|
||||
uint32 i, u, ch = uptr->UCH; /* get channel number */
|
||||
uint8 by, *xb = mtxb[ch]; /* get xfer buffer */
|
||||
t_uint64 dat;
|
||||
t_mtrlnt bc;
|
||||
t_stat r;
|
||||
|
||||
if (xb == NULL) /* valid buffer? */
|
||||
return SCPE_IERR;
|
||||
u = uptr - mt_dev[ch].units;
|
||||
switch (uptr->UST) { /* case on state */
|
||||
|
||||
case CHSL_RDS: /* read start */
|
||||
if (QCHRONO (ch, mt_unit[ch] & 017)) /* Chronolog clock? */
|
||||
bc = chrono_rd (xb, MT_MAXFR); /* read clock */
|
||||
else { /* real tape */
|
||||
r = sim_tape_rdrecf (uptr, xb, &bc, MT_MAXFR); /* read record */
|
||||
if (r = mt_map_err (uptr, r)) /* map status */
|
||||
return r;
|
||||
if (mt_unit[ch] == 0) /* disconnected? */
|
||||
return SCPE_OK;
|
||||
} /* end else Chrono */
|
||||
if (!ch6_qconn (ch, mt_unit[ch])) { /* chan disconnected? */
|
||||
mt_unit[ch] = 0; /* clr ctrl busy */
|
||||
return SCPE_OK;
|
||||
}
|
||||
for (i = bc; i < (bc + 6); i++) /* extra 0's */
|
||||
xb[i] = 0;
|
||||
mt_bptr[ch] = 0; /* set ptr, lnt */
|
||||
mt_blnt[ch] = bc;
|
||||
uptr->UST = CHSL_RDS|CHSL_2ND; /* next state */
|
||||
sim_activate (uptr, mt_tword);
|
||||
break;
|
||||
|
||||
case CHSL_RDS|CHSL_2ND: /* read word */
|
||||
for (i = 0, dat = 0; i < 6; i++) { /* proc 6 bytes */
|
||||
by = xb[mt_bptr[ch]++] & 077; /* get next byte */
|
||||
if ((mt_unit[ch] & 020) == 0) { /* BCD? */
|
||||
if (by == BCD_ZERO) /* cvt BCD 0 */
|
||||
by = 0;
|
||||
else if (by & 020) /* invert zones */
|
||||
by = by ^ 040;
|
||||
}
|
||||
dat = (dat << 6) | ((t_uint64) by);
|
||||
}
|
||||
if (mt_bptr[ch] >= mt_blnt[ch]) { /* end of record? */
|
||||
ch6_req_rd (ch, mt_unit[ch], dat, CH6DF_EOR);
|
||||
uptr->UST = CHSL_RDS|CHSL_3RD; /* next state */
|
||||
sim_activate (uptr, mt_tstop); /* long timing */
|
||||
}
|
||||
else {
|
||||
ch6_req_rd (ch, mt_unit[ch], dat, 0); /* send to channel */
|
||||
sim_activate (uptr, mt_tword); /* next word */
|
||||
}
|
||||
break;
|
||||
|
||||
case CHSL_RDS|CHSL_3RD: /* end record */
|
||||
if (ch6_qconn (ch, mt_unit[ch])) { /* ch still conn? */
|
||||
uptr->UST = CHSL_RDS; /* initial state */
|
||||
sim_activate (uptr, mt_tshort); /* sched next record */
|
||||
}
|
||||
else mt_unit[ch] = 0; /* clr ctrl busy */
|
||||
if (DEBUG_PRS (mt_dev[ch]))
|
||||
fprintf (sim_deb, ">>%s%d RDS complete, pos = %d, %s\n",
|
||||
mt_dev[ch].name, u, uptr->pos,
|
||||
mt_unit[ch]? "continuing": "disconnecting");
|
||||
return SCPE_OK;
|
||||
|
||||
case CHSL_WRS: /* write start */
|
||||
if (!ch6_qconn (ch, mt_unit[ch])) { /* chan disconnected? */
|
||||
mt_unit[ch] = 0; /* clr ctrl busy */
|
||||
return SCPE_OK; /* (writes blank tape) */
|
||||
}
|
||||
mt_bptr[ch] = 0; /* init buffer */
|
||||
uptr->UST = CHSL_WRS|CHSL_2ND; /* next state */
|
||||
ch6_req_wr (ch, mt_unit[ch]); /* request channel */
|
||||
mt_chob[ch] = 0; /* clr, inval buffer */
|
||||
mt_chob_v[ch] = 0;
|
||||
sim_activate (uptr, mt_tword); /* wait for word */
|
||||
break;
|
||||
|
||||
case CHSL_WRS|CHSL_2ND: /* write word */
|
||||
if (!ch6_qconn (ch, mt_unit[ch])) /* disconnected? */
|
||||
return mt_rec_end (uptr); /* write record */
|
||||
if (mt_chob_v[ch]) /* valid? clear */
|
||||
mt_chob_v[ch] = 0;
|
||||
else ind_ioc = 1; /* no, io check */
|
||||
ch6_req_wr (ch, mt_unit[ch]); /* request channel */
|
||||
sim_activate (uptr, mt_tword); /* next word */
|
||||
break;
|
||||
|
||||
case CHSL_WRS|CHSL_3RD: /* write stop */
|
||||
if (ch6_qconn (ch, mt_unit[ch])) { /* chan active? */
|
||||
uptr->UST = CHSL_WRS; /* initial state */
|
||||
sim_activate (uptr, mt_tshort); /* sched next record */
|
||||
}
|
||||
else mt_unit[ch] = 0; /* clr ctrl busy */
|
||||
if (DEBUG_PRS (mt_dev[ch]))
|
||||
fprintf (sim_deb, ">>%s%d WRS complete, pos = %d, %s\n",
|
||||
mt_dev[ch].name, u, uptr->pos,
|
||||
mt_unit[ch]? "continuing": "disconnecting");
|
||||
return SCPE_OK;
|
||||
|
||||
case CHSL_BSR: /* backspace rec */
|
||||
r = sim_tape_sprecr (uptr, &bc); /* space backwards */
|
||||
mt_unit[ch] = 0; /* clr ctrl busy */
|
||||
ch6_end_nds (ch); /* disconnect */
|
||||
if (DEBUG_PRS (mt_dev[ch]))
|
||||
fprintf (sim_deb, ">>%s%d BSR complete, pos = %d\n",
|
||||
mt_dev[ch].name, u, uptr->pos);
|
||||
if (r == MTSE_TMK) /* allow tape mark */
|
||||
return SCPE_OK;
|
||||
return mt_map_err (uptr, r);
|
||||
|
||||
case CHSL_BSF: /* backspace file */
|
||||
while ((r = sim_tape_sprecr (uptr, &bc)) == MTSE_OK) ;
|
||||
mt_unit[ch] = 0; /* clr ctrl busy */
|
||||
ch6_end_nds (ch); /* disconnect */
|
||||
if (DEBUG_PRS (mt_dev[ch]))
|
||||
fprintf (sim_deb, ">>%s%d BSF complete, pos = %d\n",
|
||||
mt_dev[ch].name, u, uptr->pos);
|
||||
if (r == MTSE_TMK) /* allow tape mark */
|
||||
return SCPE_OK;
|
||||
return mt_map_err (uptr, r); /* map others */
|
||||
|
||||
case CHSL_WEF: /* write eof */
|
||||
r = sim_tape_wrtmk (uptr); /* write tape mark */
|
||||
mt_unit[ch] = 0; /* clr ctrl busy */
|
||||
ch6_end_nds (ch); /* disconnect */
|
||||
if (DEBUG_PRS (mt_dev[ch]))
|
||||
fprintf (sim_deb, ">>%s%d WEF complete, pos = %d\n",
|
||||
mt_dev[ch].name, u, uptr->pos);
|
||||
return mt_map_err (uptr, r);
|
||||
|
||||
case CHSL_REW: case CHSL_RUN: /* rewind, unload */
|
||||
uptr->UST = uptr->UST | CHSL_2ND; /* set 2nd state */
|
||||
sim_activate (uptr, mt_tstart); /* reactivate */
|
||||
mt_unit[ch] = 0; /* clr ctrl busy */
|
||||
ch6_end_nds (ch); /* disconnect */
|
||||
return SCPE_OK;
|
||||
|
||||
case CHSL_REW | CHSL_2ND:
|
||||
sim_tape_rewind (uptr);
|
||||
if (DEBUG_PRS (mt_dev[ch]))
|
||||
fprintf (sim_deb, ">>%s%d REW complete, pos = %d\n",
|
||||
mt_dev[ch].name, u, uptr->pos);
|
||||
return SCPE_OK;
|
||||
|
||||
case CHSL_RUN | CHSL_2ND:
|
||||
sim_tape_detach (uptr);
|
||||
if (DEBUG_PRS (mt_dev[ch]))
|
||||
fprintf (sim_deb, ">>%s%d RUN complete, pos = %d\n",
|
||||
mt_dev[ch].name, u, uptr->pos);
|
||||
return SCPE_OK;
|
||||
|
||||
case CHSL_SDN:
|
||||
if (mt_unit[ch] & 020) /* set density flag */
|
||||
uptr->flags = uptr-> flags & ~MTUF_LDN;
|
||||
else uptr->flags = uptr->flags | MTUF_LDN;
|
||||
mt_unit[ch] = 0; /* clr ctrl busy */
|
||||
ch6_end_nds (ch); /* disconnect */
|
||||
if (DEBUG_PRS (mt_dev[ch]))
|
||||
fprintf (sim_deb, ">>%s%d SDN complete, pos = %d\n",
|
||||
mt_dev[ch].name, u, uptr->pos);
|
||||
return SCPE_OK;
|
||||
|
||||
default:
|
||||
return SCPE_IERR;
|
||||
}
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* End record routine */
|
||||
|
||||
t_stat mt_rec_end (UNIT *uptr)
|
||||
{
|
||||
uint32 ch = uptr->UCH;
|
||||
uint8 *xb = mtxb[ch];
|
||||
t_stat r;
|
||||
|
||||
if (mt_bptr[ch]) { /* any data? */
|
||||
if (xb == NULL)
|
||||
return SCPE_IERR;
|
||||
r = sim_tape_wrrecf (uptr, xb, mt_bptr[ch]); /* write record */
|
||||
if (r = mt_map_err (uptr, r)) /* map error */
|
||||
return r;
|
||||
}
|
||||
uptr->UST = CHSL_WRS|CHSL_3RD; /* next state */
|
||||
sim_cancel (uptr); /* cancel current */
|
||||
sim_activate (uptr, mt_tstop); /* long timing */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Map tape error status */
|
||||
|
||||
t_stat mt_map_err (UNIT *uptr, t_stat st)
|
||||
{
|
||||
uint32 ch = uptr->UCH;
|
||||
uint32 u = mt_unit[ch];
|
||||
uint32 up = uptr - mt_dev[ch].units;
|
||||
|
||||
if ((st != MTSE_OK) && DEBUG_PRS (mt_dev[ch]))
|
||||
fprintf (sim_deb, ">>%s%d status = %s, pos = %d\n",
|
||||
mt_dev[ch].name, up, tape_stat[st], uptr->pos);
|
||||
|
||||
switch (st) {
|
||||
|
||||
case MTSE_FMT: /* illegal fmt */
|
||||
case MTSE_UNATT: /* not attached */
|
||||
ch6_err_disc (ch, u, CHF_TRC);
|
||||
mt_unit[ch] = 0; /* disconnect */
|
||||
return SCPE_IERR;
|
||||
|
||||
case MTSE_IOERR: /* IO error */
|
||||
ch6_err_disc (ch, u, CHF_TRC);
|
||||
mt_unit[ch] = 0; /* disconnect */
|
||||
return SCPE_IOERR;
|
||||
|
||||
case MTSE_INVRL: /* invalid rec lnt */
|
||||
ch6_err_disc (ch, u, CHF_TRC);
|
||||
mt_unit[ch] = 0; /* disconnect */
|
||||
return SCPE_MTRLNT;
|
||||
|
||||
case MTSE_WRP: /* write protect */
|
||||
ch6_err_disc (ch, u, 0);
|
||||
mt_unit[ch] = 0; /* disconnect */
|
||||
return STOP_WRP;
|
||||
|
||||
case MTSE_EOM: /* end of medium */
|
||||
case MTSE_TMK: /* tape mark */
|
||||
ch6_err_disc (ch, u, CHF_EOF);
|
||||
mt_unit[ch] = 0; /* disconnect */
|
||||
break;
|
||||
|
||||
case MTSE_RECE: /* record in error */
|
||||
ch6_set_flags (ch, u, CHF_TRC);
|
||||
break;
|
||||
|
||||
case MTSE_BOT: /* reverse into BOT */
|
||||
ch6_set_flags (ch, u, CHF_BOT);
|
||||
break;
|
||||
|
||||
case MTSE_OK: /* no error */
|
||||
break;
|
||||
}
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Magtape reset */
|
||||
|
||||
t_stat mt_reset (DEVICE *dptr)
|
||||
{
|
||||
uint32 ch = dptr - &mt_dev[0];
|
||||
uint32 j;
|
||||
REG *rptr;
|
||||
UNIT *uptr;
|
||||
|
||||
if (mtxb[ch] == NULL)
|
||||
mtxb[ch] = (uint8 *) calloc (MT_MAXFR + 6, sizeof (uint8));
|
||||
if (mtxb[ch] == NULL) /* allocate buffer */
|
||||
return SCPE_MEM;
|
||||
rptr = find_reg ("BUF", NULL, dptr); /* update reg ptr */
|
||||
if (rptr == NULL)
|
||||
return SCPE_IERR;
|
||||
rptr->loc = (void *) mtxb[ch];
|
||||
mt_unit[ch] = 0; /* clear busy */
|
||||
mt_bptr[ch] = 0; /* clear buf ptrs */
|
||||
mt_blnt[ch] = 0;
|
||||
mt_chob[ch] = 0;
|
||||
mt_chob_v[ch] = 0;
|
||||
for (j = 1; j <= MT_NUMDR; j++) { /* for all units */
|
||||
uptr = dptr->units + j;
|
||||
uptr->UST = 0; /* clear state */
|
||||
uptr->UCH = ch;
|
||||
sim_cancel (uptr); /* stop activity */
|
||||
} /* end for */
|
||||
return SCPE_OK; /* done */
|
||||
}
|
||||
|
||||
/* Magtape attach */
|
||||
|
||||
t_stat mt_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
uptr->flags = uptr->flags & ~MTUF_LDN; /* start as hi den */
|
||||
return sim_tape_attach (uptr, cptr);
|
||||
}
|
||||
|
||||
/* Magtape boot */
|
||||
|
||||
#define BOOT_START 01000
|
||||
|
||||
static const t_uint64 boot_rom[5] = {
|
||||
0076200000000 + U_MTBIN - 1, /* RDS MT_binary */
|
||||
0054000000000 + BOOT_START + 4, /* RCHA *+3 */
|
||||
0054400000000, /* LCHA 0 */
|
||||
0002100000001, /* TTR 1 */
|
||||
0500003000000, /* IOCT 0,,3 */
|
||||
};
|
||||
|
||||
t_stat mt_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
uint32 i, chan;
|
||||
extern t_uint64 *M;
|
||||
|
||||
chan = dptr - &mt_dev[0] + 1;
|
||||
WriteP (BOOT_START, boot_rom[0] + unitno + (chan << 9));
|
||||
for (i = 1; i < 5; i++)
|
||||
WriteP (BOOT_START + i, boot_rom[i]);
|
||||
PC = BOOT_START;
|
||||
return SCPE_OK;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/* i7094_sys.c: IBM 7094 simulator interface
|
||||
|
||||
Copyright (c) 2003-2008, Robert M Supnik
|
||||
Copyright (c) 2003-2010, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,7 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
16-Jul-10 RMS Added SPUx, SPTx, SPRx
|
||||
29-Oct-06 RMS Added additional expanded core instructions
|
||||
08-Jun-06 RMS Added Dave Pitts' binary loader
|
||||
*/
|
||||
|
@ -154,6 +155,7 @@ return SCPE_NOFNC;
|
|||
#define I_TCH 0130000000000000 /* transfer channel */
|
||||
#define I_I9N 0140000000000000 /* 7909 with nostore */
|
||||
#define I_I9S 0150000000000000 /* 7909 */
|
||||
#define I_SPX 0160000000000000 /* SPU, SPR */
|
||||
#define IFAKE_7607 0001000000000000 /* fake op extensions */
|
||||
#define IFAKE_7909 0002000000000000
|
||||
#define DFAKE (DMASK|IFAKE_7607|IFAKE_7909)
|
||||
|
@ -171,6 +173,7 @@ return SCPE_NOFNC;
|
|||
#define I_N_TCH 013
|
||||
#define I_N_I9N 014
|
||||
#define I_N_I9S 015
|
||||
#define I_N_SPX 016
|
||||
|
||||
#define INST_P_XIT 0 /* exit */
|
||||
#define INST_P_SKP 1 /* do not print */
|
||||
|
@ -178,16 +181,17 @@ return SCPE_NOFNC;
|
|||
#define INST_P_PNZ 3 /* print if nz */
|
||||
#define INST_P_PNT 4 /* print if nz, term */
|
||||
|
||||
static const t_uint64 masks[14] = {
|
||||
static const t_uint64 masks[15] = {
|
||||
03777700000000, 03777700000000,
|
||||
03777700000000, 03777700000000,
|
||||
03777400000000, 03700000000000,
|
||||
03700000000000, 03777700077777,
|
||||
03777700000000, 03777700000000,
|
||||
03700000200000, 03700000200000,
|
||||
03760000200000, 03740000200000 };
|
||||
03760000200000, 03740000200000,
|
||||
03777700077760 };
|
||||
|
||||
static const uint32 fld_max[14][3] = { /* addr,tag,decr limit */
|
||||
static const uint32 fld_max[15][3] = { /* addr,tag,decr limit */
|
||||
{ INST_M_ADDR, INST_M_TAG, 0 },
|
||||
{ INST_M_ADDR, INST_M_TAG, 0 },
|
||||
{ INST_M_ADDR, INST_M_TAG, 0 },
|
||||
|
@ -201,10 +205,11 @@ static const uint32 fld_max[14][3] = { /* addr,tag,decr limit *
|
|||
{ INST_M_ADDR, 1, INST_M_DEC },
|
||||
{ INST_M_ADDR, 1, 0 },
|
||||
{ INST_M_ADDR, 1, 0 },
|
||||
{ INST_M_ADDR, 1, 0 }
|
||||
{ INST_M_ADDR, 1, 0 },
|
||||
{ INST_M_4B, INST_M_TAG, 0 }
|
||||
};
|
||||
|
||||
static const uint32 fld_fmt[14][3] = { /* addr,tag,decr print */
|
||||
static const uint32 fld_fmt[15][3] = { /* addr,tag,decr print */
|
||||
{ INST_P_PNT, INST_P_PNT, INST_P_XIT }, /* nop: all optional */
|
||||
{ INST_P_PRA, INST_P_PNT, INST_P_XIT }, /* mxr: tag optional */
|
||||
{ INST_P_PRA, INST_P_PNT, INST_P_XIT }, /* mxn: tag optional */
|
||||
|
@ -218,12 +223,13 @@ static const uint32 fld_fmt[14][3] = { /* addr,tag,decr print *
|
|||
{ INST_P_PRA, INST_P_PNZ, INST_P_PRA }, /* iox: tag optional */
|
||||
{ INST_P_PRA, INST_P_PNT, INST_P_XIT }, /* tch: tag optional */
|
||||
{ INST_P_PRA, INST_P_PNT, INST_P_XIT }, /* i9n: tag optional */
|
||||
{ INST_P_PRA, INST_P_PNT, INST_P_XIT } /* i9s: tag optional */
|
||||
{ INST_P_PRA, INST_P_PNT, INST_P_XIT }, /* i9s: tag optional */
|
||||
{ INST_P_PNZ, INST_P_PNT, INST_P_XIT } /* SPx: tag optional */
|
||||
};
|
||||
|
||||
static const t_uint64 ind_test[14] = {
|
||||
0, 0, INST_IND, 0, 0, 0, 0,
|
||||
0, 0, 0, CHI_IND, CHI_IND, CHI_IND, CHI_IND
|
||||
static const t_uint64 ind_test[15] = {
|
||||
0, 0, INST_IND, 0, 0, 0, 0, 0,
|
||||
0, 0, CHI_IND, CHI_IND, CHI_IND, CHI_IND, 0
|
||||
};
|
||||
|
||||
static const char *opcode[] = {
|
||||
|
@ -248,6 +254,15 @@ static const char *opcode[] = {
|
|||
"RDCA", "RDCB", "RDCC",
|
||||
"RDCD", "RDCE", "RDCF",
|
||||
"RDCG", "RDCH",
|
||||
"SPUA", "SPUB", "SPUC",
|
||||
"SPUD", "SPUE", "SPUF",
|
||||
"SPUG", "SPUH",
|
||||
"SPTA", "SPTB", "SPTC",
|
||||
"SPTD", "SPTE", "SPTF",
|
||||
"SPTG", "SPTH",
|
||||
"SPRA", "SPRB", "SPRC",
|
||||
"SPRD", "SPRE", "SPRF",
|
||||
"SPRG", "SPRH",
|
||||
|
||||
"TRCA", "TRCC",
|
||||
"TRCE", "TRCG",
|
||||
|
@ -410,6 +425,15 @@ static const t_uint64 opc_v[] = {
|
|||
0076000001352+I_SNS, 0076000002352+I_SNS, 0076000003352+I_SNS,
|
||||
0076000004352+I_SNS, 0076000005352+I_SNS, 0076000006352+I_SNS,
|
||||
0076000007352+I_SNS, 0076000010352+I_SNS,
|
||||
0076000001340+I_SNS, 0076000002340+I_SNS, 0076000003340+I_SNS,
|
||||
0076000004340+I_SNS, 0076000005340+I_SNS, 0076000006340+I_SNS,
|
||||
0076000007340+I_SNS, 0076000010340+I_SNS,
|
||||
0076000001360+I_SNS, 0076000002360+I_SNS, 0076000003360+I_SNS,
|
||||
0076000004360+I_SNS, 0076000005360+I_SNS, 0076000006360+I_SNS,
|
||||
0076000007360+I_SNS, 0076000010360+I_SNS,
|
||||
0076000001360+I_SNS, 0076000002360+I_SNS, 0076000003360+I_SNS,
|
||||
0076000004360+I_SNS, 0076000005360+I_SNS, 0076000006360+I_SNS,
|
||||
0076000007360+I_SNS, 0076000010360+I_SNS,
|
||||
|
||||
0002200000000+I_MXN, 0002400000000+I_MXN,
|
||||
0002600000000+I_MXN, 0002700000000+I_MXN,
|
||||
|
@ -618,7 +642,8 @@ for (i = 0; opc_v[i] > 0; i++) { /* loop thru ops */
|
|||
switch (fmt) { /* case on format */
|
||||
|
||||
case INST_P_PNT: /* print nz, else term */
|
||||
for (l = k, c = 0; l < 3; l++) c |= fld[k];
|
||||
for (l = k, c = 0; l < 3; l++)
|
||||
c |= fld[k];
|
||||
if (c == 0)
|
||||
return SCPE_OK;
|
||||
case INST_P_PNZ: /* print non-zero */
|
||||
|
|
748
I7094/i7094_sys_old.c
Normal file
748
I7094/i7094_sys_old.c
Normal file
|
@ -0,0 +1,748 @@
|
|||
/* i7094_sys.c: IBM 7094 simulator interface
|
||||
|
||||
Copyright (c) 2003-2008, 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.
|
||||
|
||||
29-Oct-06 RMS Added additional expanded core instructions
|
||||
08-Jun-06 RMS Added Dave Pitts' binary loader
|
||||
*/
|
||||
|
||||
#include "i7094_defs.h"
|
||||
#include <ctype.h>
|
||||
#include "i7094_dat.h"
|
||||
|
||||
extern DEVICE cpu_dev;
|
||||
extern DEVICE ch_dev[NUM_CHAN];
|
||||
extern DEVICE mt_dev[NUM_CHAN];
|
||||
extern DEVICE drm_dev;
|
||||
extern DEVICE dsk_dev;
|
||||
extern DEVICE com_dev, coml_dev;
|
||||
extern DEVICE cdr_dev, cdp_dev;
|
||||
extern DEVICE lpt_dev;
|
||||
extern DEVICE clk_dev;
|
||||
extern UNIT cpu_unit;
|
||||
extern REG cpu_reg[];
|
||||
|
||||
uint32 cvt_code_to_ascii (uint32 c, int32 sw);
|
||||
uint32 cvt_ascii_to_code (uint32 c, int32 sw);
|
||||
|
||||
/* SCP data structures and interface routines
|
||||
|
||||
sim_name simulator name string
|
||||
sim_PC pointer to saved PC register descriptor
|
||||
sim_emax number of words for examine
|
||||
sim_devices array of pointers to simulated devices
|
||||
sim_stop_messages array of pointers to stop messages
|
||||
sim_load binary loader
|
||||
*/
|
||||
|
||||
char sim_name[] = "IBM 7094";
|
||||
|
||||
REG *sim_PC = &cpu_reg[0];
|
||||
|
||||
int32 sim_emax = 1;
|
||||
|
||||
DEVICE *sim_devices[] = {
|
||||
&cpu_dev,
|
||||
&clk_dev,
|
||||
&ch_dev[0],
|
||||
&ch_dev[1],
|
||||
&ch_dev[2],
|
||||
&ch_dev[3],
|
||||
&ch_dev[4],
|
||||
&ch_dev[5],
|
||||
&ch_dev[6],
|
||||
&ch_dev[7],
|
||||
&mt_dev[0],
|
||||
&mt_dev[1],
|
||||
&mt_dev[2],
|
||||
&mt_dev[3],
|
||||
&mt_dev[4],
|
||||
&mt_dev[5],
|
||||
&mt_dev[6],
|
||||
&mt_dev[7],
|
||||
&cdr_dev,
|
||||
&cdp_dev,
|
||||
&lpt_dev,
|
||||
&dsk_dev,
|
||||
&drm_dev,
|
||||
&com_dev,
|
||||
&coml_dev,
|
||||
NULL
|
||||
};
|
||||
|
||||
char ch_bkpt_msg[] = "Channel A breakpoint, CLC: xxxxxx";
|
||||
|
||||
const char *sim_stop_messages[] = {
|
||||
"Unknown error",
|
||||
"HALT instruction",
|
||||
"Breakpoint",
|
||||
"Undefined instruction",
|
||||
"Divide check",
|
||||
"Nested XEC limit exceeded",
|
||||
"Address stop",
|
||||
"Non-existent channel",
|
||||
"Illegal instruction for 7909 channel",
|
||||
"Illegal instruction for non-7909 channel",
|
||||
"Non-existent device",
|
||||
"Undefined channel instruction",
|
||||
"Write to protected device",
|
||||
"Illegal instruction for device",
|
||||
"Invalid 7631 track format",
|
||||
"7750 buffer pool empty on input",
|
||||
"7750 buffer pool empty on output",
|
||||
"7750 invalid line number",
|
||||
"7750 invalid message",
|
||||
ch_bkpt_msg
|
||||
};
|
||||
|
||||
/* Modify channel breakpoint message */
|
||||
|
||||
t_stat ch_bkpt (uint32 ch, uint32 clc)
|
||||
{
|
||||
ch_bkpt_msg[8] = 'A' + ch;
|
||||
sprintf (&ch_bkpt_msg[27], "%06o", clc);
|
||||
return STOP_CHBKPT;
|
||||
}
|
||||
|
||||
/* Binary loader, not implemented */
|
||||
|
||||
t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
|
||||
{
|
||||
extern t_stat binloader (FILE *fd, char *file, int loadpt);
|
||||
|
||||
if (flag == 0)
|
||||
return binloader (fileref, cptr, 0);
|
||||
return SCPE_NOFNC;
|
||||
}
|
||||
|
||||
/* Symbol tables */
|
||||
|
||||
#define I_V_FL 39 /* inst class */
|
||||
#define I_M_FL 017 /* class mask */
|
||||
#define I_NOP 0000000000000000 /* no operand */
|
||||
#define I_MXR 0010000000000000 /* addr(tag) */
|
||||
#define I_MXN 0020000000000000 /* *addr(tag) */
|
||||
#define I_MXV 0030000000000000 /* var mul/div */
|
||||
#define I_MXC 0040000000000000 /* convert */
|
||||
#define I_DNP 0050000000000000 /* decr, no oper */
|
||||
#define I_DEC 0060000000000000 /* decrement */
|
||||
#define I_SNS 0070000000000000 /* sense */
|
||||
#define I_IMM 0100000000000000 /* 18b immediate */
|
||||
#define I_TAG 0110000000000000 /* tag only */
|
||||
#define I_IOX 0120000000000000 /* IO channel */
|
||||
#define I_TCH 0130000000000000 /* transfer channel */
|
||||
#define I_I9N 0140000000000000 /* 7909 with nostore */
|
||||
#define I_I9S 0150000000000000 /* 7909 */
|
||||
#define IFAKE_7607 0001000000000000 /* fake op extensions */
|
||||
#define IFAKE_7909 0002000000000000
|
||||
#define DFAKE (DMASK|IFAKE_7607|IFAKE_7909)
|
||||
#define I_N_NOP 000
|
||||
#define I_N_MXR 001
|
||||
#define I_N_MXN 002
|
||||
#define I_N_MXV 003
|
||||
#define I_N_MXC 004
|
||||
#define I_N_DNP 005
|
||||
#define I_N_DEC 006
|
||||
#define I_N_SNS 007
|
||||
#define I_N_IMM 010
|
||||
#define I_N_TAG 011
|
||||
#define I_N_IOX 012
|
||||
#define I_N_TCH 013
|
||||
#define I_N_I9N 014
|
||||
#define I_N_I9S 015
|
||||
|
||||
#define INST_P_XIT 0 /* exit */
|
||||
#define INST_P_SKP 1 /* do not print */
|
||||
#define INST_P_PRA 2 /* print always */
|
||||
#define INST_P_PNZ 3 /* print if nz */
|
||||
#define INST_P_PNT 4 /* print if nz, term */
|
||||
|
||||
static const t_uint64 masks[14] = {
|
||||
03777700000000, 03777700000000,
|
||||
03777700000000, 03777700000000,
|
||||
03777400000000, 03700000000000,
|
||||
03700000000000, 03777700077777,
|
||||
03777700000000, 03777700000000,
|
||||
03700000200000, 03700000200000,
|
||||
03760000200000, 03740000200000 };
|
||||
|
||||
static const uint32 fld_max[14][3] = { /* addr,tag,decr limit */
|
||||
{ INST_M_ADDR, INST_M_TAG, 0 },
|
||||
{ INST_M_ADDR, INST_M_TAG, 0 },
|
||||
{ INST_M_ADDR, INST_M_TAG, 0 },
|
||||
{ INST_M_ADDR, INST_M_TAG, INST_M_VCNT },
|
||||
{ INST_M_ADDR, INST_M_TAG, INST_M_CCNT },
|
||||
{ INST_M_ADDR, INST_M_TAG, INST_M_DEC },
|
||||
{ INST_M_ADDR, INST_M_TAG, INST_M_DEC },
|
||||
{ 0, INST_M_TAG, 0 },
|
||||
{ RMASK, 0, 0 },
|
||||
{ INST_M_ADDR, INST_M_TAG, 0 },
|
||||
{ INST_M_ADDR, 1, INST_M_DEC },
|
||||
{ INST_M_ADDR, 1, 0 },
|
||||
{ INST_M_ADDR, 1, 0 },
|
||||
{ INST_M_ADDR, 1, 0 }
|
||||
};
|
||||
|
||||
static const uint32 fld_fmt[14][3] = { /* addr,tag,decr print */
|
||||
{ INST_P_PNT, INST_P_PNT, INST_P_XIT }, /* nop: all optional */
|
||||
{ INST_P_PRA, INST_P_PNT, INST_P_XIT }, /* mxr: tag optional */
|
||||
{ INST_P_PRA, INST_P_PNT, INST_P_XIT }, /* mxn: tag optional */
|
||||
{ INST_P_PRA, INST_P_PNZ, INST_P_PRA }, /* mxv: tag optional */
|
||||
{ INST_P_PRA, INST_P_PNZ, INST_P_PRA }, /* cvt: tag optional */
|
||||
{ INST_P_PNT, INST_P_PNT, INST_P_PNT }, /* dnp: all optional */
|
||||
{ INST_P_PRA, INST_P_PRA, INST_P_PRA }, /* dec: print all */
|
||||
{ INST_P_SKP, INST_P_PNT, INST_P_XIT }, /* sns: skip addr, tag opt */
|
||||
{ INST_P_PRA, INST_P_XIT, INST_P_XIT }, /* immediate: addr only */
|
||||
{ INST_P_PNZ, INST_P_PRA, INST_P_XIT }, /* tag: addr optional */
|
||||
{ INST_P_PRA, INST_P_PNZ, INST_P_PRA }, /* iox: tag optional */
|
||||
{ INST_P_PRA, INST_P_PNT, INST_P_XIT }, /* tch: tag optional */
|
||||
{ INST_P_PRA, INST_P_PNT, INST_P_XIT }, /* i9n: tag optional */
|
||||
{ INST_P_PRA, INST_P_PNT, INST_P_XIT } /* i9s: tag optional */
|
||||
};
|
||||
|
||||
static const t_uint64 ind_test[14] = {
|
||||
0, 0, INST_IND, 0, 0, 0, 0,
|
||||
0, 0, 0, CHI_IND, CHI_IND, CHI_IND, CHI_IND
|
||||
};
|
||||
|
||||
static const char *opcode[] = {
|
||||
"TXI", "TIX", "TXH",
|
||||
"STR", "TNX", "TXL",
|
||||
"HTR", "TRA", "TTR",
|
||||
|
||||
"CLM", "LBT", "CHS",
|
||||
"SSP", "ENK", "IOT",
|
||||
"COM", "ETM", "RND",
|
||||
"FRN", "DCT", "RCT",
|
||||
"LMTM", "SLF", "SLN1",
|
||||
"SLN2", "SLN3", "SLN4",
|
||||
"SWT1", "SWT2", "SWT3",
|
||||
"SWT4", "SWT5", "SWT6",
|
||||
"BTTA", "BTTB", "BTTC",
|
||||
"BTTD", "BTTE", "BTTF",
|
||||
"BTTG", "BTTH",
|
||||
"RICA", "RICB", "RICC",
|
||||
"RICD", "RICE", "RICF",
|
||||
"RICG", "RICH",
|
||||
"RDCA", "RDCB", "RDCC",
|
||||
"RDCD", "RDCE", "RDCF",
|
||||
"RDCG", "RDCH",
|
||||
|
||||
"TRCA", "TRCC",
|
||||
"TRCE", "TRCG",
|
||||
"TEFA", "TEFC",
|
||||
"TEFE", "TEFG",
|
||||
"TLQ", "IIA", "TIO",
|
||||
"OAI", "PAI", "TIF",
|
||||
"IIR", "RFT", "SIR",
|
||||
"RNT", "RIR",
|
||||
"TCOA", "TCOB", "TCOC",
|
||||
"TCOD", "TCOE", "TCOF",
|
||||
"TCOG", "TCOH", "TSX",
|
||||
"TZE", "CVR", "TPL",
|
||||
"XCA", "TOV",
|
||||
"TQO", "TQP",
|
||||
"MPY", "VLM", "VLM1",
|
||||
"DVH", "DVP",
|
||||
"VDH", "VDP",
|
||||
"VDH2", "VDP2",
|
||||
"FDH", "FDP",
|
||||
"FMP", "DFMP",
|
||||
"FAD", "DFAD",
|
||||
"FSB", "DFSB",
|
||||
"FAM", "DFAM",
|
||||
"FSM", "DFSM",
|
||||
"ANS", "ERA",
|
||||
"CAS", "ACL",
|
||||
"ADD", "ADM",
|
||||
"SUB", "SBM",
|
||||
"HPR", "IIS", "LDI",
|
||||
"OSI", "DLD", "OFT",
|
||||
"RIS", "ONT",
|
||||
"CLA", "CLS",
|
||||
"ZET", "XEC",
|
||||
"LXA", "LAC",
|
||||
"RCHA", "RCHC",
|
||||
"RCHE", "RCHG",
|
||||
"LCHA", "LCHC",
|
||||
"LCHE", "LCHG",
|
||||
"RSCA", "RSCC",
|
||||
"RSCE", "RSCG",
|
||||
"STCA", "STCC",
|
||||
"STCE", "STCG",
|
||||
"LDQ", "ENB",
|
||||
"STZ", "STO", "SLW",
|
||||
"STI", "STA", "STD",
|
||||
"STT", "STP",
|
||||
"SXA", "SCA",
|
||||
"SCHA", "SCHC",
|
||||
"SCHE", "SCHG",
|
||||
"SCDA", "SCDC",
|
||||
"SCDE", "SCDG",
|
||||
"PAX", "PAC",
|
||||
"PXA", "PCA",
|
||||
"PSE", "NOP", "RDS",
|
||||
"LLS", "BSR", "LRS",
|
||||
"WRS", "ALS", "WEF",
|
||||
"ARS", "REW", "AXT",
|
||||
"SDN",
|
||||
|
||||
"CLM", "PBT", "EFTM",
|
||||
"SSM", "LFTM", "ESTM",
|
||||
"ECTM", "LTM", "LSNM",
|
||||
"EMTM", "SLT1", "SLT2",
|
||||
"SLT3", "SLT4",
|
||||
"ETTA", "ETTB", "ETTC",
|
||||
"ETTD", "ETTE", "ETTF",
|
||||
"ETTG", "ETTH",
|
||||
|
||||
"ESNT",
|
||||
"TRCB", "TRCD",
|
||||
"TRCF", "TRCH",
|
||||
"TEFB", "TEFD",
|
||||
"TEFF", "TEFH",
|
||||
"RIA", "PIA",
|
||||
"IIL", "LFT", "SIL",
|
||||
"LNT", "RIL",
|
||||
"TCNA", "TCNB", "TCNC",
|
||||
"TCND", "TCNE", "TCNF",
|
||||
"TCNG", "TCNH",
|
||||
"TNZ", "CVR", "TMI",
|
||||
"XCL", "TNO", "CRQ",
|
||||
"MPR", "DFDH", "DFDP",
|
||||
"UFM", "DUFM",
|
||||
"UFA", "DUFA",
|
||||
"UFS", "DUFS",
|
||||
"UAM", "DUAM",
|
||||
"USM", "DUSM",
|
||||
"ANA", "LAS",
|
||||
"CAL", "ORA", "NZT",
|
||||
"LXD", "LXC",
|
||||
"RCHB", "RCHD",
|
||||
"RCHF", "RCHH",
|
||||
"LCHB", "LCHD",
|
||||
"LCHF", "LCHH",
|
||||
"RSCB", "RSCD",
|
||||
"RSCF", "RSCH",
|
||||
"STCB", "STCD",
|
||||
"STCF", "STCH",
|
||||
"STQ", "ORS", "DST",
|
||||
"SLQ", "STL",
|
||||
"SXD", "SCD",
|
||||
"SCHB", "SCHD",
|
||||
"SCHF", "SCHH",
|
||||
"SCDB", "SCDD",
|
||||
"SCDF", "SCDH",
|
||||
"PDX", "PDC",
|
||||
"PXD", "PCD",
|
||||
"MSE", "LGL", "BSF",
|
||||
"LGR", "RQL", "RUN",
|
||||
"AXC",
|
||||
|
||||
"TIA", "TIB",
|
||||
"LRI", "LPI",
|
||||
"SEA", "SEB",
|
||||
"IFT", "EFT",
|
||||
|
||||
"IOCD", "IOCDN", "TCH",
|
||||
"IORP", "IORPN",
|
||||
"IORT", "IORTN",
|
||||
"IOCP", "IOCPN",
|
||||
"IOCT", "IOCTN",
|
||||
"IOSP", "IOSPN",
|
||||
"IOST", "IOSTN",
|
||||
|
||||
"WTR", "XMT",
|
||||
"TCH", "LIPT",
|
||||
"CTL", "CTLN",
|
||||
"CTLR", "CTLRN",
|
||||
"CTLW", "CTLWN",
|
||||
"SNS",
|
||||
"LAR", "SAR", "TWT",
|
||||
"CPYP",
|
||||
"CPYD", "TCM",
|
||||
"LIP", "TDC", "LCC",
|
||||
"SMS", "ICC",
|
||||
|
||||
NULL
|
||||
};
|
||||
|
||||
static const t_uint64 opc_v[] = {
|
||||
0100000000000+I_DEC, 0200000000000+I_DEC, 0300000000000+I_DEC,
|
||||
0500000000000+I_DNP, 0600000000000+I_DEC, 0700000000000+I_DEC,
|
||||
0000000000000+I_MXN, 0002000000000+I_MXN, 0002100000000+I_MXN,
|
||||
|
||||
0076000000000+I_SNS, 0076000000001+I_SNS, 0076000000002+I_SNS,
|
||||
0076000000003+I_SNS, 0076000000004+I_SNS, 0076000000005+I_SNS,
|
||||
0076000000006+I_SNS, 0076000000007+I_SNS, 0076000000010+I_SNS,
|
||||
0076000000011+I_SNS, 0076000000012+I_SNS, 0076000000014+I_SNS,
|
||||
0076000000016+I_SNS, 0076000000140+I_SNS, 0076000000141+I_SNS,
|
||||
0076000000142+I_SNS, 0076000000143+I_SNS, 0076000000144+I_SNS,
|
||||
0076000000161+I_SNS, 0076000000162+I_SNS, 0076000000163+I_SNS,
|
||||
0076000000164+I_SNS, 0076000000165+I_SNS, 0076000000166+I_SNS,
|
||||
0076000001000+I_SNS, 0076000002000+I_SNS, 0076000003000+I_SNS,
|
||||
0076000004000+I_SNS, 0076000005000+I_SNS, 0076000006000+I_SNS,
|
||||
0076000007000+I_SNS, 0076000010000+I_SNS,
|
||||
0076000001350+I_SNS, 0076000002350+I_SNS, 0076000003350+I_SNS,
|
||||
0076000004350+I_SNS, 0076000005350+I_SNS, 0076000006350+I_SNS,
|
||||
0076000007350+I_SNS, 0076000010350+I_SNS,
|
||||
0076000001352+I_SNS, 0076000002352+I_SNS, 0076000003352+I_SNS,
|
||||
0076000004352+I_SNS, 0076000005352+I_SNS, 0076000006352+I_SNS,
|
||||
0076000007352+I_SNS, 0076000010352+I_SNS,
|
||||
|
||||
0002200000000+I_MXN, 0002400000000+I_MXN,
|
||||
0002600000000+I_MXN, 0002700000000+I_MXN,
|
||||
0003000000000+I_MXN, 0003100000000+I_MXN,
|
||||
0003200000000+I_MXN, 0003300000000+I_MXN,
|
||||
0004000000000+I_MXN, 0004100000000+I_NOP, 0004200000000+I_MXR,
|
||||
0004300000000+I_NOP, 0004400000000+I_NOP, 0004600000000+I_MXR,
|
||||
0005100000000+I_IMM, 0005400000000+I_IMM, 0005500000000+I_IMM,
|
||||
0005600000000+I_IMM, 0005700000000+I_IMM,
|
||||
0006000000000+I_MXN, 0006100000000+I_MXN, 0006200000000+I_MXN,
|
||||
0006300000000+I_MXN, 0006400000000+I_MXN, 0006500000000+I_MXN,
|
||||
0006600000000+I_MXN, 0006700000000+I_MXN, 0007400000000+I_MXR,
|
||||
0010000000000+I_MXN, 0011400000000+I_MXC, 0012000000000+I_MXN,
|
||||
0013100000000+I_NOP, 0014000000000+I_MXN,
|
||||
0016100000000+I_MXN, 0016200000000+I_MXN,
|
||||
0020000000000+I_MXN, 0020400000000+I_MXV, 0020500000000+I_MXV,
|
||||
0022000000000+I_MXN, 0022100000000+I_MXN,
|
||||
0022400000000+I_MXV, 0022500000000+I_MXV,
|
||||
0022600000000+I_MXV, 0022700000000+I_MXV,
|
||||
0024000000000+I_MXN, 0024100000000+I_MXN,
|
||||
0026000000000+I_MXN, 0026100000000+I_MXN,
|
||||
0030000000000+I_MXN, 0030100000000+I_MXN,
|
||||
0030200000000+I_MXN, 0030300000000+I_MXN,
|
||||
0030400000000+I_MXN, 0030500000000+I_MXN,
|
||||
0030600000000+I_MXN, 0030700000000+I_MXN,
|
||||
0032000000000+I_MXN, 0032200000000+I_MXN,
|
||||
0034000000000+I_MXN, 0036100000000+I_MXN,
|
||||
0040000000000+I_MXN, 0040100000000+I_MXN,
|
||||
0040200000000+I_MXN, 0440000000000+I_MXN,
|
||||
0042000000000+I_NOP, 0044000000000+I_MXN, 0044100000000+I_MXN,
|
||||
0044200000000+I_MXN, 0044300000000+I_MXN, 0044400000000+I_MXN,
|
||||
0044500000000+I_MXN, 0044600000000+I_MXN,
|
||||
0050000000000+I_MXN, 0050200000000+I_MXN,
|
||||
0052000000000+I_MXN, 0052200000000+I_MXN,
|
||||
0053400000000+I_MXR, 0053500000000+I_MXR,
|
||||
0054000000000+I_MXN, 0054100000000+I_MXN,
|
||||
0054200000000+I_MXN, 0054300000000+I_MXN,
|
||||
0054400000000+I_MXN, 0054500000000+I_MXN,
|
||||
0054600000000+I_MXN, 0054700000000+I_MXN,
|
||||
0054000000000+I_MXN, 0054100000000+I_MXN,
|
||||
0054200000000+I_MXN, 0054300000000+I_MXN,
|
||||
0054400000000+I_MXN, 0054500000000+I_MXN,
|
||||
0054600000000+I_MXN, 0054700000000+I_MXN,
|
||||
0056000000000+I_MXN, 0056400000000+I_MXN,
|
||||
0060000000000+I_MXN, 0060100000000+I_MXN, 0060200000000+I_MXN,
|
||||
0060400000000+I_MXN, 0062100000000+I_MXN, 0062200000000+I_MXN,
|
||||
0062500000000+I_MXN, 0063000000000+I_MXN,
|
||||
0063400000000+I_MXR, 0063600000000+I_MXR,
|
||||
0064000000000+I_MXN, 0064000000000+I_MXN,
|
||||
0064200000000+I_MXN, 0064300000000+I_MXN,
|
||||
0064400000000+I_MXN, 0064500000000+I_MXN,
|
||||
0064600000000+I_MXN, 0064700000000+I_MXN,
|
||||
0073400000000+I_TAG, 0073700000000+I_TAG,
|
||||
0075400000000+I_TAG, 0075600000000+I_TAG,
|
||||
0076000000000+I_MXR, 0076100000000+I_NOP, 0076200000000+I_MXR,
|
||||
0076300000000+I_MXR, 0076400000000+I_MXR, 0076500000000+I_MXR,
|
||||
0076600000000+I_MXR, 0076700000000+I_MXR, 0077000000000+I_MXR,
|
||||
0077100000000+I_MXR, 0077200000000+I_MXR, 0077400000000+I_MXR,
|
||||
0077600000000+I_MXR,
|
||||
|
||||
0476000000000+I_SNS, 0476000000001+I_SNS, 0476000000002+I_SNS,
|
||||
0476000000003+I_SNS, 0476000000004+I_SNS, 0476000000005+I_SNS,
|
||||
0476000000006+I_SNS, 0476000000007+I_SNS, 0476000000010+I_SNS,
|
||||
0476000000016+I_SNS, 0476000000141+I_SNS, 0476000000142+I_SNS,
|
||||
0476000000143+I_SNS, 0476000000144+I_SNS,
|
||||
0476000001000+I_SNS, 0476000002000+I_SNS, 0476000003000+I_SNS,
|
||||
0476000004000+I_SNS, 0476000005000+I_SNS, 0476000006000+I_SNS,
|
||||
0476000007000+I_SNS, 0476000010000+I_SNS,
|
||||
|
||||
0402100000000+I_MXN,
|
||||
0402200000000+I_MXN, 0402400000000+I_MXN,
|
||||
0402600000000+I_MXN, 0402700000000+I_MXN,
|
||||
0403000000000+I_MXN, 0403100000000+I_MXN,
|
||||
0403200000000+I_MXN, 0403300000000+I_MXN,
|
||||
0404200000000+I_NOP, 0404600000000+I_NOP,
|
||||
0405100000000+I_IMM, 0405400000000+I_IMM, 0405500000000+I_IMM,
|
||||
0405600000000+I_IMM, 0405700000000+I_IMM,
|
||||
0406000000000+I_MXN, 0406100000000+I_MXN, 0406200000000+I_MXN,
|
||||
0406300000000+I_MXN, 0406400000000+I_MXN, 0406500000000+I_MXN,
|
||||
0406600000000+I_MXN, 0406700000000+I_MXN,
|
||||
0410000000000+I_MXN, 0411400000000+I_MXC, 0412000000000+I_MXN,
|
||||
0413000000000+I_NOP, 0414000000000+I_MXN, 0415400000000+I_MXC,
|
||||
0420000000000+I_MXN, 0424000000000+I_MXN, 0424100000000+I_MXN,
|
||||
0426000000000+I_MXN, 0426100000000+I_MXN,
|
||||
0430000000000+I_MXN, 0430100000000+I_MXN,
|
||||
0430200000000+I_MXN, 0430300000000+I_MXN,
|
||||
0430400000000+I_MXN, 0430500000000+I_MXN,
|
||||
0430600000000+I_MXN, 0430700000000+I_MXN,
|
||||
0432000000000+I_MXN, 0434000000000+I_MXN,
|
||||
0450000000000+I_MXN, 0450100000000+I_MXN, 0452000000000+I_MXN,
|
||||
0453400000000+I_MXR, 0453500000000+I_MXR,
|
||||
0454000000000+I_MXN, 0454100000000+I_MXN,
|
||||
0454200000000+I_MXN, 0454300000000+I_MXN,
|
||||
0454400000000+I_MXN, 0454500000000+I_MXN,
|
||||
0454600000000+I_MXN, 0454700000000+I_MXN,
|
||||
0454000000000+I_MXN, 0454100000000+I_MXN,
|
||||
0454200000000+I_MXN, 0454300000000+I_MXN,
|
||||
0454400000000+I_MXN, 0454500000000+I_MXN,
|
||||
0454600000000+I_MXN, 0454700000000+I_MXN,
|
||||
0460000000000+I_MXN, 0460200000000+I_MXN, 0460300000000+I_MXN,
|
||||
0462000000000+I_MXN, 0462500000000+I_MXN,
|
||||
0463400000000+I_MXR, 0463600000000+I_MXR,
|
||||
0464000000000+I_MXN, 0464000000000+I_MXN,
|
||||
0464200000000+I_MXN, 0464300000000+I_MXN,
|
||||
0464400000000+I_MXN, 0464500000000+I_MXN,
|
||||
0464600000000+I_MXN, 0464700000000+I_MXN,
|
||||
0473400000000+I_TAG, 0473700000000+I_TAG,
|
||||
0475400000000+I_TAG, 0475600000000+I_TAG,
|
||||
0476000000000+I_MXR, 0476300000000+I_MXR, 0476400000000+I_MXR,
|
||||
0476500000000+I_MXR, 0477300000000+I_MXR, 0477200000000+I_MXR,
|
||||
0477400000000+I_MXR,
|
||||
|
||||
0010100000000+I_MXN, 0410100000000+I_MXN,
|
||||
0056200000000+I_MXN, 0456400000000+I_MXN,
|
||||
0476100000041+I_SNS, 0476100000042+I_SNS,
|
||||
0476100000043+I_SNS, 0476100000044+I_SNS,
|
||||
|
||||
01000000000000+I_IOX, 01000000200000+I_IOX, 01100000000000+I_TCH,
|
||||
01200000000000+I_IOX, 01200000200000+I_IOX,
|
||||
01300000000000+I_IOX, 01300000200000+I_IOX,
|
||||
01400000000000+I_IOX, 01400000200000+I_IOX,
|
||||
01500000000000+I_IOX, 01500000200000+I_IOX,
|
||||
01600000000000+I_IOX, 01600000200000+I_IOX,
|
||||
01700000000000+I_IOX, 01700000200000+I_IOX,
|
||||
|
||||
02000000000000+I_TCH, 02000000200000+I_IOX,
|
||||
02100000000000+I_TCH, 02100000200000+I_TCH,
|
||||
02200000000000+I_I9N, 02220000000000+I_TCH,
|
||||
02200000200000+I_I9N, 02220000200000+I_TCH,
|
||||
02240000000000+I_I9N, 02260000000000+I_TCH,
|
||||
02240000200000+I_I9N,
|
||||
02300000000000+I_I9S, 02300000200000+I_I9S,
|
||||
02340000000000+I_I9S,
|
||||
02400000000000+I_IOX,
|
||||
02500000000000+I_IOX, 02500000200000+I_IOX,
|
||||
02600000200000+I_I9S, 02640000000000+I_I9S, 02640000200000+I_I9S,
|
||||
02700000000000+I_I9S, 02700000200000+I_IOX,
|
||||
|
||||
0
|
||||
};
|
||||
|
||||
/* Symbolic decode
|
||||
|
||||
Inputs:
|
||||
*of = output stream
|
||||
addr = current PC
|
||||
*val = pointer to values
|
||||
*uptr = pointer to unit
|
||||
sw = switches
|
||||
Outputs:
|
||||
return = status code
|
||||
*/
|
||||
|
||||
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
|
||||
UNIT *uptr, int32 sw)
|
||||
{
|
||||
uint32 i, j, k, l, fmt, c, fld[3];
|
||||
DEVICE *dptr;
|
||||
t_uint64 inst;
|
||||
|
||||
inst = val[0];
|
||||
if (uptr == NULL)
|
||||
uptr = &cpu_unit;
|
||||
dptr = find_dev_from_unit (uptr);
|
||||
if (dptr == NULL)
|
||||
return SCPE_IERR;
|
||||
|
||||
if (sw & SWMASK ('C')) { /* character? */
|
||||
c = (uint32) (inst & 077);
|
||||
fprintf (of, "%c", cvt_code_to_ascii (c, sw));
|
||||
return SCPE_OK;
|
||||
}
|
||||
if (sw & SWMASK ('S')) { /* string? */
|
||||
for (i = 36; i > 0; i = i - 6) {
|
||||
c = (uint32) ((inst >> (i - 6)) & 077);
|
||||
fprintf (of, "%c", cvt_code_to_ascii (c, sw));
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
if (!(sw & (SWMASK ('M')|SWMASK ('I')|SWMASK ('N'))) || /* M, N or I? */
|
||||
(dptr->dwidth != 36))
|
||||
return SCPE_ARG;
|
||||
|
||||
/* Instruction decode */
|
||||
|
||||
fld[0] = ((uint32) inst & 0777777);
|
||||
fld[1] = GET_TAG (inst); /* get 3 fields */
|
||||
fld[2] = GET_DEC (inst);
|
||||
if (sw & SWMASK ('I')) /* decode as 7607? */
|
||||
inst |= IFAKE_7607;
|
||||
if (sw & SWMASK ('N')) /* decode as 7909? */
|
||||
inst |= IFAKE_7909;
|
||||
|
||||
for (i = 0; opc_v[i] > 0; i++) { /* loop thru ops */
|
||||
j = (int32) ((opc_v[i] >> I_V_FL) & I_M_FL); /* get class */
|
||||
if ((opc_v[i] & DFAKE) == (inst & masks[j])) { /* match? */
|
||||
if (inst & ind_test[j]) /* indirect? */
|
||||
fprintf (of, "%s*", opcode[i]);
|
||||
else fprintf (of, "%s", opcode[i]); /* opcode */
|
||||
for (k = 0; k < 3; k++)
|
||||
fld[k] = fld[k] & fld_max[j][k];
|
||||
for (k = 0; k < 3; k++) { /* loop thru fields */
|
||||
fmt = fld_fmt[j][k]; /* get format */
|
||||
if (fmt == INST_P_XIT)
|
||||
return SCPE_OK;
|
||||
switch (fmt) { /* case on format */
|
||||
|
||||
case INST_P_PNT: /* print nz, else term */
|
||||
for (l = k, c = 0; l < 3; l++) c |= fld[k];
|
||||
if (c == 0)
|
||||
return SCPE_OK;
|
||||
case INST_P_PNZ: /* print non-zero */
|
||||
fputc (k? ',': ' ', of);
|
||||
if (fld[k])
|
||||
fprintf (of, "%-o", fld[k]);
|
||||
break;
|
||||
case INST_P_PRA: /* print always */
|
||||
fputc (k? ',': ' ', of);
|
||||
fprintf (of, "%-o", fld[k]);
|
||||
break;
|
||||
case INST_P_SKP: /* skip */
|
||||
break;
|
||||
} /* end switch */
|
||||
} /* end for k */
|
||||
return SCPE_OK; /* done */
|
||||
} /* end if */
|
||||
} /* end for i */
|
||||
return SCPE_ARG;
|
||||
}
|
||||
|
||||
/* Convert character to code to ASCII
|
||||
|
||||
-b BCD
|
||||
-a business-chain */
|
||||
|
||||
uint32 cvt_code_to_ascii (uint32 c, int32 sw)
|
||||
{
|
||||
if (sw & SWMASK ('B')) {
|
||||
if (sw & SWMASK ('A'))
|
||||
return bcd_to_ascii_a[c];
|
||||
else return bcd_to_ascii_h[c];
|
||||
}
|
||||
else if (sw & SWMASK ('A'))
|
||||
return nine_to_ascii_a[c];
|
||||
else return nine_to_ascii_h[c];
|
||||
}
|
||||
|
||||
/* Symbolic input
|
||||
|
||||
Inputs:
|
||||
*cptr = pointer to input string
|
||||
addr = current PC
|
||||
uptr = pointer to unit
|
||||
*val = pointer to output values
|
||||
sw = switches
|
||||
Outputs:
|
||||
status = error status
|
||||
*/
|
||||
|
||||
t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
|
||||
{
|
||||
uint32 i, j, c;
|
||||
t_uint64 fld[3];
|
||||
t_bool ind;
|
||||
t_stat r;
|
||||
char gbuf[CBUFSIZE];
|
||||
|
||||
while (isspace (*cptr)) cptr++;
|
||||
if ((sw & SWMASK ('C')) || ((*cptr == '\'') && cptr++)) { /* character? */
|
||||
if (cptr[0] == 0) /* must have 1 char */
|
||||
return SCPE_ARG;
|
||||
val[0] = (t_value) cvt_ascii_to_code (cptr[0] & 0177, sw);
|
||||
return SCPE_OK;
|
||||
}
|
||||
if ((sw & SWMASK ('S')) || ((*cptr == '"') && cptr++)) { /* sixbit string? */
|
||||
if (cptr[0] == 0) /* must have 1 char */
|
||||
return SCPE_ARG;
|
||||
for (i = 0; i < 6; i++) {
|
||||
c = cptr[0] & 0177;
|
||||
if (c)
|
||||
val[0] = (val[0] << 6) | ((t_value) cvt_ascii_to_code (c, sw));
|
||||
else {
|
||||
val[0] = val[0] << (6 * (6 - i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get opcode */
|
||||
j = strlen (gbuf); /* get length */
|
||||
if (gbuf[j - 1] == '*') { /* indirect? */
|
||||
ind = TRUE;
|
||||
gbuf[j - 1] = 0;
|
||||
}
|
||||
else ind = FALSE;
|
||||
for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;
|
||||
if (opcode[i] == NULL)
|
||||
return SCPE_ARG;
|
||||
j = (uint32) ((opc_v[i] >> I_V_FL) & I_M_FL); /* get class */
|
||||
val[0] = opc_v[i] & DMASK;
|
||||
if (ind) {
|
||||
if (ind_test[j])
|
||||
val[0] |= ind_test[j];
|
||||
else return SCPE_ARG;
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; i++) /* clear inputs */
|
||||
fld[i] = 0;
|
||||
for (i = 0; (i < 3) && *cptr; i++) { /* parse inputs */
|
||||
if (i < 2) /* get glyph */
|
||||
cptr = get_glyph (cptr, gbuf, ',');
|
||||
else cptr = get_glyph (cptr, gbuf, 0);
|
||||
if (gbuf[0]) { /* anything? */
|
||||
fld[i] = get_uint (gbuf, 8, fld_max[j][i], &r);
|
||||
if ((r != SCPE_OK) || (fld_max[j][i] == 0))
|
||||
return SCPE_ARG;
|
||||
}
|
||||
}
|
||||
if (*cptr != 0) /* junk at end? */
|
||||
return SCPE_ARG;
|
||||
|
||||
val[0] = val[0] | fld[0] | (fld[1] << INST_V_TAG) | (fld[2] << INST_V_DEC);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Convert ASCII to character code
|
||||
|
||||
-b BCD */
|
||||
|
||||
uint32 cvt_ascii_to_code (uint32 c, int32 sw)
|
||||
{
|
||||
if (sw & SWMASK ('B'))
|
||||
return ascii_to_bcd[c];
|
||||
else return ascii_to_nine[c];
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/* id_defs.h: Interdata 16b/32b simulator definitions
|
||||
|
||||
Copyright (c) 2000-2006, Robert M. Supnik
|
||||
Copyright (c) 2000-2010, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -26,6 +26,7 @@
|
|||
The author gratefully acknowledges the help of Carl Friend and Al Kossow,
|
||||
who provided key documents about the Interdata product line.
|
||||
|
||||
22-May-10 RMS Added check for 64b definitions
|
||||
09-Mar-06 RMS Increased register sets to architectural limit
|
||||
25-Jan-04 RMS Removed local logging support
|
||||
22-Sep-03 RMS Added additional instruction decode types
|
||||
|
@ -39,6 +40,10 @@
|
|||
|
||||
#include "sim_defs.h" /* simulator defns */
|
||||
|
||||
#if defined(USE_INT64) || defined(USE_ADDR64)
|
||||
#error "Interdata 16/32 does not support 64b values!"
|
||||
#endif
|
||||
|
||||
/* Simulator stop codes */
|
||||
|
||||
#define STOP_RSRV 1 /* undef instr */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* lgp_defs.h: LGP simulator definitions
|
||||
|
||||
Copyright (c) 2004-2008, Robert M. Supnik
|
||||
Copyright (c) 2004-2010, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -22,6 +22,9 @@
|
|||
Except as contained in this notice, the name of Robert M Supnik shall not be
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
22-May-10 RMS Added check for 64b definitions
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _LGP_DEFS_H_
|
||||
|
@ -29,6 +32,10 @@
|
|||
|
||||
#include "sim_defs.h" /* simulator defns */
|
||||
|
||||
#if defined(USE_INT64) || defined(USE_ADDR64)
|
||||
#error "LGP-30 does not support 64b values!"
|
||||
#endif
|
||||
|
||||
/* Simulator stop codes */
|
||||
|
||||
#define STOP_STOP 1 /* STOP */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* nova_defs.h: NOVA/Eclipse simulator definitions
|
||||
|
||||
Copyright (c) 1993-2008, Robert M. Supnik
|
||||
Copyright (c) 1993-2010, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,7 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
22-May-10 RMS Added check for 64b definitions
|
||||
04-Jul-07 BKR BUSY/DONE/INTR "convenience" macros added,
|
||||
INT_TRAP added for Nova 3, 4 trap instruction handling,
|
||||
support for 3rd-party 64KW Nova extensions added,
|
||||
|
@ -49,6 +50,10 @@
|
|||
|
||||
#include "sim_defs.h" /* simulator defns */
|
||||
|
||||
#if defined(USE_INT64) || defined(USE_ADDR64)
|
||||
#error "Nova does not support 64b values!"
|
||||
#endif
|
||||
|
||||
/* Simulator stop codes */
|
||||
|
||||
#define STOP_RSRV 1 /* must be 1 */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp1_defs.h: 18b PDP simulator definitions
|
||||
|
||||
Copyright (c) 1993-2008, Robert M. Supnik
|
||||
Copyright (c) 1993-2010, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,7 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
22-May-10 RMS Added check for 64b definitions
|
||||
21-Dec-06 RMS Added 16-channel sequence break support
|
||||
22-Jul-05 RMS Fixed definition of CPLS_DPY
|
||||
08-Feb-04 PLB Added support for display
|
||||
|
@ -53,6 +54,10 @@
|
|||
|
||||
#include "sim_defs.h"
|
||||
|
||||
#if defined(USE_INT64) || defined(USE_ADDR64)
|
||||
#error "PDP-1 does not support 64b values!"
|
||||
#endif
|
||||
|
||||
/* Simulator stop codes */
|
||||
|
||||
#define STOP_RSRV 1 /* must be 1 */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp10_defs.h: PDP-10 simulator definitions
|
||||
|
||||
Copyright (c) 1993-2008, Robert M Supnik
|
||||
Copyright (c) 1993-2010, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,7 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
22-May-10 RMS Added check for 64b addresses
|
||||
01-Feb-07 RMS Added CD support
|
||||
29-Oct-06 RMS Added clock coscheduling function
|
||||
29-Dec-03 RMS Added Q18 definition for PDP11 compatibility
|
||||
|
@ -49,6 +50,10 @@
|
|||
|
||||
#include "sim_defs.h" /* simulator defns */
|
||||
|
||||
#if defined(USE_ADDR64)
|
||||
#error "PDP-10 does not support 64b addresses!"
|
||||
#endif
|
||||
|
||||
/* Digital Equipment Corporation's 36b family had six implementations:
|
||||
|
||||
name mips comments
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp11_defs.h: PDP-11 simulator definitions
|
||||
|
||||
Copyright (c) 1993-2008, Robert M Supnik
|
||||
Copyright (c) 1993-2010, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -26,6 +26,7 @@
|
|||
The author gratefully acknowledges the help of Max Burnet, Megan Gentry,
|
||||
and John Wilson in resolving questions about the PDP-11
|
||||
|
||||
22-May-10 RMS Added check for 64b definitions
|
||||
19-Nov-08 RMS Moved I/O support routines to I/O library
|
||||
16-May-08 RMS Added KE11A, DC11 support
|
||||
02-Feb-08 RMS Fixed DMA memory address limit test (found by John Dundas)
|
||||
|
@ -80,6 +81,10 @@
|
|||
#include "sim_defs.h" /* simulator defns */
|
||||
#include <setjmp.h>
|
||||
|
||||
#if defined(USE_INT64) || defined(USE_ADDR64)
|
||||
#error "PDP-11 does not support 64b values!"
|
||||
#endif
|
||||
|
||||
/* Architectural constants */
|
||||
|
||||
#define STKL_R 0340 /* stack limit */
|
||||
|
|
105
PDP11/pdp11_tq.c
105
PDP11/pdp11_tq.c
|
@ -1,6 +1,6 @@
|
|||
/* pdp11_tq.c: TMSCP tape controller simulator
|
||||
|
||||
Copyright (c) 2002-2008, Robert M Supnik
|
||||
Copyright (c) 2002-2011, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -25,6 +25,20 @@
|
|||
|
||||
tq TQK50 tape controller
|
||||
|
||||
14-Jan-11 MP Various fixes discovered while exploring Ultrix issue:
|
||||
- Set UNIT_SXC flag when a tape mark is encountered
|
||||
during forward motion read operations
|
||||
- Fixed logic which clears UNIT_SXC to check command
|
||||
modifier
|
||||
- Added CMF_WR flag to tq_cmf entry for OP_WTM
|
||||
- Made non-immediate rewind positioning operations
|
||||
take 2 seconds
|
||||
- Added UNIT_IDLE flag to tq units
|
||||
- Fixed debug output of tape file positions when they
|
||||
are 64b
|
||||
- Added more debug output after positioning operations.
|
||||
- Added textual display of the command being performed
|
||||
23-Dec-10 RMS Fixed comments about register addresses
|
||||
18-Jun-07 RMS Added UNIT_IDLE flag to timer thread
|
||||
16-Feb-06 RMS Revised for new magtape capacity checking
|
||||
31-Oct-05 RMS Fixed address width for large files
|
||||
|
@ -223,7 +237,6 @@ static struct drvtyp drv_tab[] = {
|
|||
|
||||
extern int32 int_req[IPL_HLVL];
|
||||
extern int32 tmr_poll, clk_tps;
|
||||
extern UNIT cpu_unit;
|
||||
extern FILE *sim_deb;
|
||||
extern uint32 sim_taddr_64;
|
||||
|
||||
|
@ -249,6 +262,7 @@ int32 tq_itime = 200; /* init time, except */
|
|||
int32 tq_itime4 = 10; /* stage 4 */
|
||||
int32 tq_qtime = 200; /* queue time */
|
||||
int32 tq_xtime = 500; /* transfer time */
|
||||
int32 tq_rwtime = 2000000; /* rewind time 2 sec (adjusted later) */
|
||||
int32 tq_typ = INIT_TYPE; /* device type */
|
||||
|
||||
/* Command table - legal modifiers (low 16b) and flags (high 16b) */
|
||||
|
@ -280,7 +294,7 @@ static uint32 tq_cmf[64] = {
|
|||
CMF_SEQ|CMF_RW|CMF_WR|MD_CDL|MD_CSE|MD_IMM| /* write */
|
||||
MD_CMP|MD_ERW|MD_SEC|MD_SER,
|
||||
0, /* 35 */
|
||||
CMF_SEQ|MD_CDL|MD_CSE|MD_IMM, /* wr tape mark */
|
||||
CMF_SEQ|CMF_WR|MD_CDL|MD_CSE|MD_IMM, /* wr tape mark */
|
||||
CMF_SEQ|MD_CDL|MD_CSE|MD_IMM|MD_OBC| /* reposition */
|
||||
MD_REV|MD_RWD|MD_DLE|
|
||||
MD_SCH|MD_SEC|MD_SER,
|
||||
|
@ -289,6 +303,37 @@ static uint32 tq_cmf[64] = {
|
|||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
static char *tq_cmdname[] = {
|
||||
"", /* 0 */
|
||||
"ABO", /* 1 b: abort */
|
||||
"GCS", /* 2 b: get command status */
|
||||
"GUS", /* 3 b: get unit status */
|
||||
"SCC", /* 4 b: set controller char */
|
||||
"","","", /* 5-7 */
|
||||
"AVL", /* 8 b: available */
|
||||
"ONL", /* 9 b: online */
|
||||
"SUC", /* 10 b: set unit char */
|
||||
"DAP", /* 11 b: det acc paths - nop */
|
||||
"","","","", /* 12-15 */
|
||||
"ACC", /* 16 b: access */
|
||||
"CCD", /* 17 d: compare - nop */
|
||||
"ERS", /* 18 b: erase */
|
||||
"FLU", /* 19 d: flush - nop */
|
||||
"","", /* 20-21 */
|
||||
"ERG", /* 22 t: erase gap */
|
||||
"","","","","","","","","", /* 23-31 */
|
||||
"CMP", /* 32 b: compare */
|
||||
"RD", /* 33 b: read */
|
||||
"WR", /* 34 b: write */
|
||||
"", /* 35 */
|
||||
"WTM", /* 36 t: write tape mark */
|
||||
"POS", /* 37 t: reposition */
|
||||
"","","","","","","","","", /* 38-46 */
|
||||
"FMT", /* 47 d: format */
|
||||
"","","","","","","","","","","","","","","","", /* 48-63 */
|
||||
"AVA", /* 64 b: unit now avail */
|
||||
};
|
||||
|
||||
/* Forward references */
|
||||
|
||||
DEVICE tq_dev;
|
||||
|
@ -369,12 +414,12 @@ DIB tq_dib = {
|
|||
};
|
||||
|
||||
UNIT tq_unit[] = {
|
||||
{ UDATA (&tq_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0), INIT_CAP },
|
||||
{ UDATA (&tq_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0), INIT_CAP },
|
||||
{ UDATA (&tq_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0), INIT_CAP },
|
||||
{ UDATA (&tq_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0), INIT_CAP },
|
||||
{ UDATA (&tq_tmrsvc, UNIT_DIS, 0) },
|
||||
{ UDATA (&tq_quesvc, UNIT_DIS, 0) }
|
||||
{ UDATA (&tq_svc, UNIT_IDLE|UNIT_ATTABLE|UNIT_DISABLE|UNIT_ROABLE, 0), INIT_CAP },
|
||||
{ UDATA (&tq_svc, UNIT_IDLE|UNIT_ATTABLE|UNIT_DISABLE|UNIT_ROABLE, 0), INIT_CAP },
|
||||
{ UDATA (&tq_svc, UNIT_IDLE|UNIT_ATTABLE|UNIT_DISABLE|UNIT_ROABLE, 0), INIT_CAP },
|
||||
{ UDATA (&tq_svc, UNIT_IDLE|UNIT_ATTABLE|UNIT_DISABLE|UNIT_ROABLE, 0), INIT_CAP },
|
||||
{ UDATA (&tq_tmrsvc, UNIT_IDLE|UNIT_DIS, 0) },
|
||||
{ UDATA (&tq_quesvc, UNIT_IDLE|UNIT_DIS, 0) }
|
||||
};
|
||||
|
||||
#define TQ_TIMER (TQ_NUMDR)
|
||||
|
@ -411,6 +456,7 @@ REG tq_reg[] = {
|
|||
{ DRDATA (I4TIME, tq_itime4, 24), PV_LEFT + REG_NZ },
|
||||
{ DRDATA (QTIME, tq_qtime, 24), PV_LEFT + REG_NZ },
|
||||
{ DRDATA (XTIME, tq_xtime, 24), PV_LEFT + REG_NZ },
|
||||
{ DRDATA (RWTIME, tq_rwtime, 32), PV_LEFT + REG_NZ },
|
||||
{ BRDATA (PKTS, tq_pkt, DEV_RDX, 16, TQ_NPKTS * (TQ_PKT_SIZE_W + 1)) },
|
||||
{ DRDATA (DEVTYPE, tq_typ, 2), REG_HRO },
|
||||
{ DRDATA (DEVCAP, drv_tab[TQU_TYPE].cap, T_ADDR_W), PV_LEFT | REG_HRO },
|
||||
|
@ -466,10 +512,10 @@ DEVICE tq_dev = {
|
|||
&tq_dib, DEV_DISABLE | DEV_UBUS | DEV_QBUS | DEV_DEBUG
|
||||
};
|
||||
|
||||
/* I/O dispatch routines, I/O addresses 17772150 - 17772152
|
||||
/* I/O dispatch routines, I/O addresses 17774500 - 17774502
|
||||
|
||||
17772150 IP read/write
|
||||
17772152 SA read/write
|
||||
17774500 IP read/write
|
||||
17774502 SA read/write
|
||||
*/
|
||||
|
||||
t_stat tq_rd (int32 *data, int32 PA, int32 access)
|
||||
|
@ -643,13 +689,16 @@ if ((pkt == 0) && tq_pip) { /* polling? */
|
|||
if (pkt) { /* got one? */
|
||||
if (DEBUG_PRS (tq_dev)) {
|
||||
UNIT *up = tq_getucb (tq_pkt[pkt].d[CMD_UN]);
|
||||
fprintf (sim_deb, ">>TQ: cmd=%04X, mod=%04X, unit=%d, ",
|
||||
tq_pkt[pkt].d[CMD_OPC], tq_pkt[pkt].d[CMD_MOD], tq_pkt[pkt].d[CMD_UN]);
|
||||
fprintf (sim_deb, ">>TQ: cmd=%04X(%3s), mod=%04X, unit=%d, ",
|
||||
tq_pkt[pkt].d[CMD_OPC], tq_cmdname[tq_pkt[pkt].d[CMD_OPC]&0x3f], tq_pkt[pkt].d[CMD_MOD], tq_pkt[pkt].d[CMD_UN]);
|
||||
fprintf (sim_deb, "bc=%04X%04X, ma=%04X%04X",
|
||||
tq_pkt[pkt].d[RW_BCH], tq_pkt[pkt].d[RW_BCL],
|
||||
tq_pkt[pkt].d[RW_BAH], tq_pkt[pkt].d[RW_BAL]);
|
||||
if (up)
|
||||
fprintf (sim_deb, ", pos=%d, obj=%d\n", up->pos, up->objp);
|
||||
if (up) {
|
||||
fprintf (sim_deb, ", pos=");
|
||||
fprint_val (sim_deb, up->pos, 10, T_ADDR_W, PV_LEFT);
|
||||
fprintf (sim_deb, ", obj=%d\n", up->objp);
|
||||
}
|
||||
else fprintf (sim_deb, "\n");
|
||||
fflush (sim_deb);
|
||||
}
|
||||
|
@ -734,7 +783,7 @@ else { /* valid cmd */
|
|||
}
|
||||
/* if (tq_cmf[cmd] & MD_CDL) /* clr cch lost? */
|
||||
/* uptr->flags = uptr->flags & ~UNIT_CDL; */
|
||||
if (tq_cmf[cmd] & MD_CSE) /* clr ser exc? */
|
||||
if ((mdf & MD_CSE) && (uptr->flags & UNIT_SXC)) /* clr ser exc? */
|
||||
uptr->flags = uptr->flags & ~UNIT_SXC;
|
||||
}
|
||||
switch (cmd) {
|
||||
|
@ -1066,7 +1115,12 @@ if (uptr = tq_getucb (lu)) { /* unit exist? */
|
|||
sts = tq_mot_valid (uptr, OP_POS); /* validity checks */
|
||||
if (sts == ST_SUC) { /* ok? */
|
||||
uptr->cpkt = pkt; /* op in progress */
|
||||
sim_activate (uptr, tq_xtime); /* activate */
|
||||
tq_rwtime = 2 * tmr_poll * clk_tps; /* 2 second rewind time */
|
||||
if ((tq_pkt[pkt].d[CMD_MOD] & MD_RWD) && /* rewind? */
|
||||
(!(tq_pkt[pkt].d[CMD_MOD] & MD_IMM))) /* !immediate? */
|
||||
sim_activate (uptr, tq_rwtime); /* use 2 sec rewind execute time */
|
||||
else /* otherwise */
|
||||
sim_activate (uptr, tq_xtime); /* use normal execute time */
|
||||
return OK; /* done */
|
||||
}
|
||||
}
|
||||
|
@ -1180,6 +1234,8 @@ switch (cmd) { /* case on command */
|
|||
return tq_mot_err (uptr, tbc); /* log, done */
|
||||
}
|
||||
if ((sts != ST_SUC) || (cmd == OP_ACC)) { /* error or access? */
|
||||
if (sts == ST_TMK)
|
||||
uptr->flags = uptr->flags | UNIT_SXC; /* set ser exc */
|
||||
PUTP32 (pkt, RW_BCL, 0); /* no bytes processed */
|
||||
break;
|
||||
}
|
||||
|
@ -1286,6 +1342,11 @@ switch (cmd) { /* case on command */
|
|||
}
|
||||
PUTP32 (pkt, POS_RCL, skrec); /* #rec skipped */
|
||||
PUTP32 (pkt, POS_TMCL, sktmk); /* #tmk skipped */
|
||||
if (DEBUG_PRS (tq_dev)) {
|
||||
fprintf (sim_deb, ">>TQ: Position Done: mdf=%04X, nrec=%04X, ntmk=%04X, skrec=%04X, sktmk=%04X\n",
|
||||
mdf, nrec, ntmk, skrec, sktmk);
|
||||
fflush (sim_deb);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1690,8 +1751,11 @@ if (DEBUG_PRS (tq_dev)) {
|
|||
UNIT *up = tq_getucb (tq_pkt[pkt].d[CMD_UN]);
|
||||
fprintf (sim_deb, ">>TQ: rsp=%04X, sts=%04X",
|
||||
tq_pkt[pkt].d[RSP_OPF], tq_pkt[pkt].d[RSP_STS]);
|
||||
if (up)
|
||||
fprintf (sim_deb, ", pos=%d, obj=%d\n", up->pos, up->objp);
|
||||
if (up) {
|
||||
fprintf (sim_deb, ", pos=");
|
||||
fprint_val (sim_deb, up->pos, 10, T_ADDR_W, PV_LEFT);
|
||||
fprintf (sim_deb, ", obj=%d\n", up->objp);
|
||||
}
|
||||
else fprintf (sim_deb, "\n");
|
||||
fflush (sim_deb);
|
||||
}
|
||||
|
@ -1816,6 +1880,7 @@ void tq_putr_unit (int32 pkt, UNIT *uptr, uint32 lu, t_bool all)
|
|||
{
|
||||
tq_pkt[pkt].d[ONL_MLUN] = lu; /* multi-unit */
|
||||
tq_pkt[pkt].d[ONL_UFL] = uptr->uf | TQ_WPH (uptr); /* unit flags */
|
||||
tq_pkt[pkt].d[ONL_UFL] |= tq_efl (uptr); /* end flags accordingly */
|
||||
tq_pkt[pkt].d[ONL_RSVL] = tq_pkt[pkt].d[ONL_RSVH] = 0; /* reserved */
|
||||
tq_pkt[pkt].d[ONL_UIDA] = lu; /* UID low */
|
||||
tq_pkt[pkt].d[ONL_UIDB] = 0;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp11_ts.c: TS11/TSV05 magnetic tape simulator
|
||||
|
||||
Copyright (c) 1993-2008, Robert M Supnik
|
||||
Copyright (c) 1993-2010, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -25,6 +25,8 @@
|
|||
|
||||
ts TS11/TSV05 magtape
|
||||
|
||||
22-May-10 RMS Fixed t_addr printouts for 64b big-endian systems
|
||||
(found by Mark Pizzolato)
|
||||
16-Feb-06 RMS Added tape capacity checking
|
||||
31-Oct-05 RMS Fixed address width for large files
|
||||
16-Aug-05 RMS Fixed C++ declaration and cast problems
|
||||
|
@ -733,9 +735,12 @@ if (!(cmdhdr & CMD_ACK)) { /* no acknowledge? */
|
|||
}
|
||||
fnc = GET_FNC (cmdhdr); /* get fnc+mode */
|
||||
mod = GET_MOD (cmdhdr);
|
||||
if (DEBUG_PRS (ts_dev))
|
||||
fprintf (sim_deb, ">>TS: cmd=%s, mod=%o, buf=%o, lnt=%d, pos=%d\n",
|
||||
fnc_name[fnc], mod, cmdadl, cmdlnt, ts_unit.pos);
|
||||
if (DEBUG_PRS (ts_dev)) {
|
||||
fprintf (sim_deb, ">>TS: cmd=%s, mod=%o, buf=%o, lnt=%d, pos=",
|
||||
fnc_name[fnc], mod, cmdadl, cmdlnt);
|
||||
fprint_val (sim_deb, ts_unit.pos, 10, T_ADDR_W, PV_LEFT);
|
||||
fprintf (sim_deb, "\n");
|
||||
}
|
||||
if ((fnc != FNC_WCHR) && (tssr & TSSR_NBA)) { /* ~wr chr & nba? */
|
||||
ts_endcmd (TC3, 0, 0); /* error */
|
||||
return SCPE_OK;
|
||||
|
@ -1016,9 +1021,12 @@ tssr = ts_updtssr (tssr | tc | TSSR_SSR | (tc? TSSR_SC: 0));
|
|||
if (cmdhdr & CMD_IE)
|
||||
SET_INT (TS);
|
||||
ts_ownm = 0; ts_ownc = 0;
|
||||
if (DEBUG_PRS (ts_dev))
|
||||
fprintf (sim_deb, ">>TS: sta=%o, tc=%o, rfc=%d, pos=%d\n",
|
||||
msgxs0, GET_TC (tssr), msgrfc, ts_unit.pos);
|
||||
if (DEBUG_PRS (ts_dev)) {
|
||||
fprintf (sim_deb, ">>TS: sta=%o, tc=%o, rfc=%d, pos=",
|
||||
msgxs0, GET_TC (tssr), msgrfc);
|
||||
fprint_val (sim_deb, ts_unit.pos, 10, T_ADDR_W, PV_LEFT);
|
||||
fprintf (sim_deb, "\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
944
PDP11/pdp11_xq.c
944
PDP11/pdp11_xq.c
File diff suppressed because it is too large
Load diff
187
PDP11/pdp11_xq.h
187
PDP11/pdp11_xq.h
|
@ -28,6 +28,14 @@
|
|||
|
||||
Modification history:
|
||||
|
||||
03-Mar-08 MP Added DELQA-T (aka DELQA Plus) device emulation support.
|
||||
06-Feb-08 MP Added dropped frame statistics to record when the receiver discards
|
||||
received packets due to the receiver being disabled, or due to the
|
||||
XQ device's packet receive queue being full. Also removed the
|
||||
filter statistic counter since there was no code which ever set it.
|
||||
29-Jan-08 MP Dynamically determine the timer polling rate based on the
|
||||
calibrated tmr_poll and clk_tps values of the simulator.
|
||||
23-Jan-08 MP Added debugging support to display packet headers and packet data
|
||||
07-Jul-05 RMS Removed extraneous externs
|
||||
20-Jan-04 DTH Added new sanity timer and system id timer
|
||||
19-Jan-04 DTH Added XQ_SERVICE_INTERVAL, poll
|
||||
|
@ -84,12 +92,11 @@ extern int32 int_req[IPL_HLVL];
|
|||
#define XQ_HW_SANITY_SECS 240 /* seconds before HW sanity timer expires */
|
||||
#define XQ_MAX_CONTROLLERS 2 /* maximum controllers allowed */
|
||||
|
||||
enum xq_type {XQ_T_DEQNA, XQ_T_DELQA};
|
||||
enum xq_type {XQ_T_DEQNA, XQ_T_DELQA, XQ_T_DELQA_PLUS};
|
||||
|
||||
struct xq_sanity {
|
||||
int enabled; /* sanity timer enabled? 2=HW, 1=SW, 0=off */
|
||||
int quarter_secs; /* sanity timer value in 1/4 seconds */
|
||||
int max; /* maximum timeout (based on poll) */
|
||||
int timer; /* countdown timer */
|
||||
};
|
||||
|
||||
|
@ -104,17 +111,132 @@ struct xq_setup {
|
|||
ETH_MAC macs[XQ_FILTER_MAX]; /* MAC addresses to respond to */
|
||||
};
|
||||
|
||||
struct xq_turbo_init_block { /* DELQA-T Initialization Block */
|
||||
uint16 mode;
|
||||
#define XQ_IN_MO_PRO 0x8000 /* Promiscuous Mode */
|
||||
#define XQ_IN_MO_INT 0x0040 /* Internal Loopback Mode */
|
||||
#define XQ_IN_MO_DRT 0x0020 /* Disable Retry */
|
||||
#define XQ_IN_MO_DTC 0x0008 /* Disable Transmit CRC */
|
||||
#define XQ_IN_MO_LOP 0x0004 /* Loopback */
|
||||
ETH_MAC phys; /* Physical MAC Address */
|
||||
ETH_MULTIHASH hash_filter; /* 64bit LANCE Hash Filter for Multicast Address selection */
|
||||
uint16 rdra_l;
|
||||
uint16 rdra_h;
|
||||
uint16 tdra_l;
|
||||
uint16 tdra_h;
|
||||
uint16 options;
|
||||
#define XQ_IN_OP_HIT 0x0002 /* Host Inactivity Timer Enable Flag */
|
||||
#define XQ_IN_OP_INT 0x0001 /* Interrupt Enable Flag*/
|
||||
uint16 vector; /* Interrupt Vector */
|
||||
uint16 hit_timeout; /* Host Inactivity Timer Timeout Value */
|
||||
uint8 bootpassword[6]; /* MOP Console Boot Password */
|
||||
};
|
||||
|
||||
/* DELQA-T Mode - Transmit Buffer Descriptor */
|
||||
struct transmit_buffer_descriptor {
|
||||
uint16 tmd0;
|
||||
#define XQ_TMD0_ERR1 0x4000 /* Error Summary. The OR of TMD1 (LC0, LCA, and RTR) */
|
||||
#define XQ_TMD0_MOR 0x1000 /* More than one retry on transmit */
|
||||
#define XQ_TMD0_ONE 0x0800 /* One retry on transmit */
|
||||
#define XQ_TMD0_DEF 0x0400 /* Deferral during transmit */
|
||||
uint16 tmd1;
|
||||
#define XQ_TMD1_LCO 0x1000 /* Late collision on transmit - packet not transmitted */
|
||||
#define XQ_TMD1_LCA 0x0800 /* Loss of carrier on transmit - packet not transmitted */
|
||||
#define XQ_TMD1_RTR 0x0400 /* Retry error on transmit - packet not transmitted */
|
||||
#define XQ_TMD1_TDR 0x03FF /* Time Domain Reflectometry value */
|
||||
uint16 tmd2;
|
||||
#define XQ_TMD2_ERR2 0x8000 /* Error Summary. The OR of TMD2 (BBL, CER, and MIS) */
|
||||
#define XQ_TMD2_BBL 0x4000 /* Babble error on transmit */
|
||||
#define XQ_TMD2_CER 0x2000 /* Collision error on transmit */
|
||||
#define XQ_TMD2_MIS 0x1000 /* Packet lost on receive */
|
||||
#define XQ_TMD2_EOR 0x0800 /* End Of Receive Ring Reached */
|
||||
#define XQ_TMD2_RON 0x0020 /* Receiver On */
|
||||
#define XQ_TMD2_TON 0x0010 /* Transmitter On */
|
||||
uint16 tmd3;
|
||||
#define XQ_TMD3_OWN 0x8000 /* Ownership field. 0 = DELQA-T, 1 = Host Driver */
|
||||
#define XQ_TMD3_FOT 0x4000 /* First Of Two flag. 1 = first in chained, 0 = no chain or last in chain */
|
||||
#define XQ_TMD3_BCT 0x0FFF /* Byte Count */
|
||||
uint16 ladr; /* Low 16bits of Buffer Address */
|
||||
uint16 hadr; /* Most significant bits of the Buffer Address */
|
||||
uint16 hostuse1;
|
||||
uint16 hostuse2;
|
||||
};
|
||||
#define XQ_TURBO_XM_BCNT 12 /* Transmit Buffer Descriptor Count */
|
||||
|
||||
struct receive_buffer_descriptor {
|
||||
uint16 rmd0;
|
||||
#define XQ_RMD0_ERR3 0x4000 /* Error Summary. The OR of FRA, CRC, OFL and BUF */
|
||||
#define XQ_RMD0_FRA 0x2000 /* Framing error on receive */
|
||||
#define XQ_RMD0_OFL 0x1000 /* Overflow error on receive (Giant packet) */
|
||||
#define XQ_RMD0_CRC 0x0800 /* CRC error on receive */
|
||||
#define XQ_RMD0_BUF 0x0400 /* Internal device buffer error. Part of Giant packet lost */
|
||||
#define XQ_RMD0_STP 0x0200 /* Start of Packet Flag */
|
||||
#define XQ_RMD0_ENP 0x0100 /* End of Packet Flag */
|
||||
uint16 rmd1;
|
||||
#define XQ_RMD1_MCNT 0x0FFF /* Message byte count (including CRC) */
|
||||
uint16 rmd2;
|
||||
#define XQ_RMD2_ERR4 0x8000 /* Error Summary. The OR of RMD2 (RBL, CER, and MIS) */
|
||||
#define XQ_RMD2_BBL 0x4000 /* Babble error on transmit */
|
||||
#define XQ_RMD2_CER 0x2000 /* Collision error on transmit */
|
||||
#define XQ_RMD2_MIS 0x1000 /* Packet lost on receive */
|
||||
#define XQ_RMD2_EOR 0x0800 /* End Of Receive Ring Reached */
|
||||
#define XQ_RMD2_RON 0x0020 /* Receiver On */
|
||||
#define XQ_RMD2_TON 0x0010 /* Transmitter On */
|
||||
uint16 rmd3;
|
||||
#define XQ_RMD3_OWN 0x8000 /* Ownership field. 0 = DELQA-T, 1 = Host Driver */
|
||||
uint16 ladr; /* Low 16bits of Buffer Address */
|
||||
uint16 hadr; /* Most significant bits of the Buffer Address */
|
||||
uint16 hostuse1;
|
||||
uint16 hostuse2;
|
||||
};
|
||||
#define XQ_TURBO_RC_BCNT 32 /* Receive Buffer Descriptor Count */
|
||||
|
||||
struct xq_stats {
|
||||
int recv; /* received packets */
|
||||
int filter; /* filtered packets */
|
||||
int dropped; /* received packets dropped */
|
||||
int xmit; /* transmitted packets */
|
||||
int fail; /* transmit failed */
|
||||
int runt; /* runts */
|
||||
int reset; /* reset count */
|
||||
int giant; /* oversize packets */
|
||||
int setup; /* setup packets */
|
||||
int loop; /* loopback packets */
|
||||
};
|
||||
|
||||
#pragma pack(2)
|
||||
struct xq_mop_counters {
|
||||
uint16 seconds; /* Seconds since last zeroed */
|
||||
uint32 b_rcvd; /* Bytes Received */
|
||||
uint32 b_xmit; /* Bytes Transmitted */
|
||||
uint32 p_rcvd; /* Packets Received */
|
||||
uint32 p_xmit; /* Packets Transmitted */
|
||||
uint32 mb_rcvd; /* Multicast Bytes Received */
|
||||
uint32 mp_rcvd; /* Multicast Packets Received */
|
||||
uint32 p_x_col1; /* Packets Transmitted Initially Deferred */
|
||||
uint32 p_x_col2; /* Packets Transmitted after 2 attempts */
|
||||
uint32 p_x_col3; /* Packets Transmitted after 3+ attempts */
|
||||
uint16 p_x_fail; /* Transmit Packets Aborted (Send Failure) */
|
||||
uint16 p_x_f_bitmap; /* Transmit Packets Aborted (Send Failure) Bitmap */
|
||||
#define XQ_XF_RTRY 0x0001 /* Excessive Collisions */
|
||||
#define XQ_XF_LCAR 0x0002 /* Loss of Carrier */
|
||||
#define XQ_XF_MLEN 0x0010 /* Data Block Too Long */
|
||||
#define XQ_XF_LCOL 0x0020 /* Late Collision */
|
||||
uint16 p_r_fail; /* Packets received with Error (Receive Failure) */
|
||||
uint16 p_r_f_bitmap; /* Packets received with Error (Receive Failure) Bitmap */
|
||||
#define XQ_RF_CRC 0x0001 /* Block Check Error */
|
||||
#define XQ_RF_FRAM 0x0002 /* Framing Error */
|
||||
#define XQ_RF_MLEN 0x0004 /* Message Length Error */
|
||||
uint16 h_dest_err; /* Host Counter - Unrecognized Frame Destination Error */
|
||||
uint16 r_p_lost_i; /* Receive Packet Lost: Internal Buffer Error */
|
||||
uint16 r_p_lost_s; /* Receive Packet Lost: System Buffer Error (Unavailable or Truncated) */
|
||||
uint16 h_no_buf; /* Host Counter - User Buffer Unavailable */
|
||||
uint32 mb_xmit; /* Multicast Bytes Tramsmitted */
|
||||
uint16 reserved1; /* */
|
||||
uint16 reserved2; /* */
|
||||
uint16 babble; /* Babble Counter */
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
struct xq_meb { /* MEB block */
|
||||
uint8 type;
|
||||
uint8 add_lo;
|
||||
|
@ -128,18 +250,36 @@ struct xq_device {
|
|||
/*+ initialized values - DO NOT MOVE */
|
||||
ETH_PCALLBACK rcallback; /* read callback routine */
|
||||
ETH_PCALLBACK wcallback; /* write callback routine */
|
||||
ETH_MAC mac; /* MAC address */
|
||||
ETH_MAC mac; /* Hardware MAC address */
|
||||
enum xq_type type; /* controller type */
|
||||
int poll; /* poll ethernet times/sec */
|
||||
enum xq_type mode; /* controller operating mode */
|
||||
uint16 poll; /* configured poll ethernet times/sec for receive */
|
||||
uint16 coalesce_latency; /* microseconds to hold-off interrupts when not polling */
|
||||
uint16 coalesce_latency_ticks; /* instructions in coalesce_latency microseconds */
|
||||
struct xq_sanity sanity; /* sanity timer information */
|
||||
/*- initialized values - DO NOT MOVE */
|
||||
|
||||
/* I/O register storage */
|
||||
uint16 addr[6];
|
||||
|
||||
uint16 rbdl[2];
|
||||
uint16 xbdl[2];
|
||||
uint16 var;
|
||||
uint16 csr;
|
||||
|
||||
uint16 srr; /* Status and Response Register - DELQA-T only */
|
||||
uint16 srqr; /* Synchronous Request Register - DELQA-T only */
|
||||
uint32 iba; /* Init Block Address Register - DELQA-T only */
|
||||
uint16 icr; /* Interrupt Request Register - DELQA-T only */
|
||||
uint16 pending_interrupt; /* Pending Interrupt - DELQA-T only */
|
||||
struct xq_turbo_init_block
|
||||
init;
|
||||
struct transmit_buffer_descriptor
|
||||
xring[XQ_TURBO_XM_BCNT]; /* Transmit Buffer Ring */
|
||||
uint32 tbindx; /* Transmit Buffer Ring Index */
|
||||
struct receive_buffer_descriptor
|
||||
rring[XQ_TURBO_RC_BCNT]; /* Receive Buffer Ring */
|
||||
uint32 rbindx; /* Receive Buffer Ring Index */
|
||||
|
||||
uint32 irq; /* interrupt request flag */
|
||||
|
||||
/* buffers, etc. */
|
||||
|
@ -151,11 +291,11 @@ struct xq_device {
|
|||
uint32 rbdl_ba;
|
||||
uint32 xbdl_ba;
|
||||
ETH_DEV* etherface;
|
||||
int receiving;
|
||||
ETH_PACK read_buffer;
|
||||
ETH_PACK write_buffer;
|
||||
ETH_QUE ReadQ;
|
||||
int idtmr; /* countdown for ID Timer */
|
||||
uint32 idtmr; /* countdown for ID Timer */
|
||||
uint32 must_poll; /* receiver must poll instead of counting on asynch polls */
|
||||
};
|
||||
|
||||
struct xq_controller {
|
||||
|
@ -207,6 +347,7 @@ typedef struct xq_controller CTLR;
|
|||
#define XQ_VEC_RO 0x5C02 /* Read-Only bits */
|
||||
#define XQ_VEC_RW 0xA3FD /* Read/Write bits */
|
||||
|
||||
/* DEQNA - DELQA Normal Mode Buffer Descriptors */
|
||||
#define XQ_DSC_V 0x8000 /* Valid bit */
|
||||
#define XQ_DSC_C 0x4000 /* Chain bit */
|
||||
#define XQ_DSC_E 0x2000 /* End of Message bit [Transmit only] */
|
||||
|
@ -214,11 +355,38 @@ typedef struct xq_controller CTLR;
|
|||
#define XQ_DSC_L 0x0080 /* Low Byte Termination bit [Transmit only] */
|
||||
#define XQ_DSC_H 0x0040 /* High Byte Start bit [Transmit only] */
|
||||
|
||||
/* DEQNA - DELQA Normal Mode Setup Packet Flags */
|
||||
#define XQ_SETUP_MC 0x0001 /* multicast bit */
|
||||
#define XQ_SETUP_PM 0x0002 /* promiscuous bit */
|
||||
#define XQ_SETUP_LD 0x000C /* led bits */
|
||||
#define XQ_SETUP_ST 0x0070 /* sanity timer bits */
|
||||
|
||||
/* DELQA-T Mode - Status and Response Register (SRR) */
|
||||
#define XQ_SRR_FES 0x8000 /* Fatal Error Summary [RO] */
|
||||
#define XQ_SRR_CHN 0x4000 /* Chaining Error [RO] */
|
||||
#define XQ_SRR_NXM 0x1000 /* Non-Existant Memory Error [RO] */
|
||||
#define XQ_SRR_PAR 0x0800 /* Parity Error (Qbus) [RO] */
|
||||
#define XQ_SRR_IME 0x0400 /* Internal Memory Error [RO] */
|
||||
#define XQ_SRR_TBL 0x0200 /* Transmit Buffer Too Long Error [RO] */
|
||||
#define XQ_SRR_RESP 0x0003 /* Synchronous Response Field [RO] */
|
||||
#define XQ_SRR_TRBO 0x0001 /* Select Turbo Response [RO] */
|
||||
#define XQ_SRR_STRT 0x0002 /* Start Device Response [RO] */
|
||||
#define XQ_SRR_STOP 0x0003 /* Stop Device Response [RO] */
|
||||
|
||||
/* DELQA-T Mode - Synchronous Request Register (SRQR) */
|
||||
#define XQ_SRQR_STRT 0x0002 /* Start Device Request [WO] */
|
||||
#define XQ_SRQR_STOP 0x0003 /* Stop Device Request [WO] */
|
||||
#define XQ_SRQR_RW 0x0003 /* Writable Bits in SRQR [WO] */
|
||||
|
||||
/* DELQA-T Mode - Asynchronous Request Register (ARQR) */
|
||||
#define XQ_ARQR_TRQ 0x8000 /* Transmit Request [WO] */
|
||||
#define XQ_ARQR_RRQ 0x0080 /* Receieve Request [WO] */
|
||||
#define XQ_ARQR_SR 0x0002 /* Software Reset Request [WO] */
|
||||
|
||||
/* DELQA-T Mode - Interrupt Control Register (ICR) */
|
||||
#define XQ_ICR_ENA 0x0001 /* Interrupt Enabled [WO] */
|
||||
|
||||
|
||||
/* debugging bitmaps */
|
||||
#define DBG_TRC 0x0001 /* trace routine calls */
|
||||
#define DBG_REG 0x0002 /* trace read/write registers */
|
||||
|
@ -227,7 +395,8 @@ typedef struct xq_controller CTLR;
|
|||
#define DBG_WRN 0x0010 /* display warnings */
|
||||
#define DBG_SAN 0x0020 /* display sanity timer info */
|
||||
#define DBG_SET 0x0040 /* display setup info */
|
||||
#define DBG_PCK 0x0080 /* display packets */
|
||||
#define DBG_PCK 0x0080 /* display packet headers */
|
||||
#define DBG_DAT 0x0100 /* display packet data */
|
||||
#define DBG_ETH 0x8000 /* debug ethernet device */
|
||||
|
||||
#endif /* _PDP11_XQ_H */
|
||||
|
|
144
PDP11/pdp11_xu.c
144
PDP11/pdp11_xu.c
|
@ -1,7 +1,7 @@
|
|||
/* pdp11_xu.c: DEUNA/DELUA ethernet controller simulator
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2003-2007, David T. Hittner
|
||||
Copyright (c) 2003-2011, David T. Hittner
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -30,7 +30,7 @@
|
|||
Digital DELUA Users Guide, Part# EK-DELUA-UG-002
|
||||
Digital DEUNA Users Guide, Part# EK-DEUNA-UG-001
|
||||
These manuals can be found online at:
|
||||
http://www.spies.com/~aek/pdf/dec/unibus
|
||||
http://www.bitsavers.org/pdf/dec/unibus
|
||||
|
||||
Testing performed:
|
||||
1) Receives/Transmits single packet under custom RSX driver
|
||||
|
@ -41,7 +41,13 @@
|
|||
DECNET - SET HOST in/out, COPY in/out
|
||||
TCP/IP - PING in/out; SET HOST/TELNET in/out, COPY/FTP in/out
|
||||
Clustering - Successfully clustered with AlphaVMS 8.2
|
||||
4) Runs VAX EVDWA diagnostic tests 1-10; tests 11-19 (M68000/ROM/RAM) fail
|
||||
4) VMS 4.7 on VAX780 summary:
|
||||
(Jan/2011: Win7 x64 host; MS VC++ 2008; SIMH v3.8-2 rc1 base; WinPcap 4.1)
|
||||
LAT - SET HOST/LAT in (no outbound exists)
|
||||
DECNET - SET HOST in/out, DIR in/out, COPY in/out
|
||||
TCP/IP - no kit available to test
|
||||
Clustering - not tested
|
||||
5) Runs VAX EVDWA diagnostic tests 1-10; tests 11-19 (M68000/ROM/RAM) fail
|
||||
|
||||
Known issues:
|
||||
1) Most auxiliary commands are not implemented yet.
|
||||
|
@ -56,6 +62,14 @@
|
|||
|
||||
Modification history:
|
||||
|
||||
12-Jan-11 DTH Added SHOW XU FILTERS modifier
|
||||
11-Jan-11 DTH Corrected SELFTEST command, enabling use by VMS 3.7, VMS 4.7, and Ultrix 1.1
|
||||
09-Dec-10 MP Added address conflict check during attach.
|
||||
06-Dec-10 MP Added loopback processing support
|
||||
30-Nov-10 MP Fixed the fact that no broadcast packets were received by the DEUNA
|
||||
15-Aug-08 MP Fixed transmitted packets to have the correct source MAC address.
|
||||
Fixed incorrect address filter setting calling eth_filter().
|
||||
23-Jan-08 MP Added debugging support to display packet headers and packet data
|
||||
18-Jun-07 RMS Added UNIT_IDLE flag
|
||||
03-May-07 DTH Added missing FC_RMAL command; cleared multicast on write
|
||||
29-Oct-06 RMS Synced poll and clock
|
||||
|
@ -112,6 +126,7 @@ void xu_clrint (CTLR* xu);
|
|||
void xu_process_receive(CTLR* xu);
|
||||
void xu_dump_rxring(CTLR* xu);
|
||||
void xu_dump_txring(CTLR* xu);
|
||||
t_stat xu_show_filters (FILE* st, UNIT* uptr, int32 val, void* desc);
|
||||
|
||||
DIB xua_dib = { IOBA_XU, IOLN_XU, &xu_rd, &xu_wr,
|
||||
1, IVCL (XU), VEC_XU, {&xu_int} };
|
||||
|
@ -143,6 +158,8 @@ MTAB xu_mod[] = {
|
|||
NULL, ð_show, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATS", "STATS",
|
||||
&xu_set_stats, &xu_show_stats, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "FILTERS", "FILTERS",
|
||||
NULL, &xu_show_filters, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 0, "TYPE", "TYPE={DEUNA|DELUA}",
|
||||
&xu_set_type, &xu_show_type, NULL },
|
||||
{ 0 },
|
||||
|
@ -156,6 +173,7 @@ DEBTAB xu_debug[] = {
|
|||
{"WARN", DBG_WRN},
|
||||
{"REG", DBG_REG},
|
||||
{"PACKET", DBG_PCK},
|
||||
{"DATA", DBG_DAT},
|
||||
{"ETH", DBG_ETH},
|
||||
{0}
|
||||
};
|
||||
|
@ -294,7 +312,7 @@ t_stat xu_set_stats (UNIT* uptr, int32 val, char* cptr, void* desc)
|
|||
|
||||
t_stat xu_show_stats (FILE* st, UNIT* uptr, int32 val, void* desc)
|
||||
{
|
||||
char* fmt = " %-24s%d\n";
|
||||
char* fmt = " %-26s%d\n";
|
||||
CTLR* xu = xu_unit2ctlr(uptr);
|
||||
struct xu_stats* stats = &xu->var->stats;
|
||||
|
||||
|
@ -308,6 +326,25 @@ t_stat xu_show_stats (FILE* st, UNIT* uptr, int32 val, void* desc)
|
|||
fprintf(st, fmt, "Recv dbytes(multicast):", stats->mrbytes);
|
||||
fprintf(st, fmt, "Xmit frames(multicast):", stats->mftrans);
|
||||
fprintf(st, fmt, "Xmit dbytes(multicast):", stats->mtbytes);
|
||||
fprintf(st, fmt, "Loopback forward Frames:", stats->loopf);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat xu_show_filters (FILE* st, UNIT* uptr, int32 val, void* desc)
|
||||
{
|
||||
CTLR* xu = xu_unit2ctlr(uptr);
|
||||
char buffer[20];
|
||||
int i;
|
||||
|
||||
fprintf(st, "Filters:\n");
|
||||
for (i=0; i<XU_FILTER_MAX; i++) {
|
||||
eth_mac_fmt((ETH_MAC*)xu->var->setup.macs[i], buffer);
|
||||
fprintf(st, " [%2d]: %s\n", i, buffer);
|
||||
}
|
||||
if (xu->var->setup.multicast)
|
||||
fprintf(st, "All Multicast Receive Mode\n");
|
||||
if (xu->var->setup.promiscuous)
|
||||
fprintf(st, "Promiscuous Receive Mode\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -359,13 +396,63 @@ void bit_stat16(uint16* stat, uint16 bits)
|
|||
*stat |= bits;
|
||||
}
|
||||
|
||||
t_stat xu_process_loopback(CTLR* xu, ETH_PACK* pack)
|
||||
{
|
||||
ETH_PACK response;
|
||||
ETH_MAC physical_address;
|
||||
t_stat status;
|
||||
int offset = 16 + (pack->msg[14] | (pack->msg[15] << 8));
|
||||
int function = pack->msg[offset] | (pack->msg[offset+1] << 8);
|
||||
|
||||
sim_debug(DBG_TRC, xu->dev, "xu_process_loopback()\n");
|
||||
|
||||
if (function != 2 /*forward*/)
|
||||
return SCPE_NOFNC;
|
||||
|
||||
/* create forward response packet */
|
||||
memcpy (&response, pack, sizeof(ETH_PACK));
|
||||
memcpy (physical_address, xu->var->setup.macs[0], sizeof(ETH_MAC));
|
||||
memcpy (&response.msg[0], &response.msg[offset+2], sizeof(ETH_MAC));
|
||||
memcpy (&response.msg[6], physical_address, sizeof(ETH_MAC));
|
||||
offset += 8;
|
||||
response.msg[14] = offset & 0xFF;
|
||||
response.msg[15] = (offset >> 8) & 0xFF;
|
||||
|
||||
/* send response packet */
|
||||
status = eth_write(xu->var->etherface, &response, NULL);
|
||||
++xu->var->stats.loopf;
|
||||
|
||||
if (DBG_PCK & xu->dev->dctrl)
|
||||
eth_packet_trace_ex(xu->var->etherface, response.msg, response.len, ((function == 1) ? "xu-loopbackreply" : "xu-loopbackforward"), DBG_DAT & xu->dev->dctrl, DBG_PCK);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
t_stat xu_process_local (CTLR* xu, ETH_PACK* pack)
|
||||
{
|
||||
/* returns SCPE_OK if local processing occurred,
|
||||
otherwise returns SCPE_NOFNC or some other code */
|
||||
int protocol;
|
||||
|
||||
sim_debug(DBG_TRC, xu->dev, "xu_process_local()\n");
|
||||
|
||||
protocol = pack->msg[12] | (pack->msg[13] << 8);
|
||||
switch (protocol) {
|
||||
case 0x0090: /* ethernet loopback */
|
||||
return xu_process_loopback(xu, pack);
|
||||
break;
|
||||
case 0x0260: /* MOP remote console */
|
||||
return SCPE_NOFNC; /* not implemented yet */
|
||||
break;
|
||||
}
|
||||
return SCPE_NOFNC;
|
||||
}
|
||||
|
||||
void xu_read_callback(CTLR* xu, int status)
|
||||
{
|
||||
if (DBG_PCK & xu->dev->dctrl)
|
||||
eth_packet_trace_ex(xu->var->etherface, xu->var->read_buffer.msg, xu->var->read_buffer.len, "xu-recvd", DBG_DAT & xu->dev->dctrl, DBG_PCK);
|
||||
|
||||
/* process any packets locally that can be */
|
||||
status = xu_process_local (xu, &xu->var->read_buffer);
|
||||
|
||||
|
@ -442,6 +529,8 @@ t_stat xu_system_id (CTLR* xu, const ETH_MAC dest, uint16 receipt_id)
|
|||
/* write system id */
|
||||
system_id.len = 60;
|
||||
status = eth_write(xu->var->etherface, &system_id, NULL);
|
||||
if (DBG_PCK & xu->dev->dctrl)
|
||||
eth_packet_trace_ex(xu->var->etherface, system_id.msg, system_id.len, "xu-systemid", DBG_DAT & xu->dev->dctrl, DBG_PCK);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -524,6 +613,7 @@ void xu_setclrint(CTLR* xu, int32 bits)
|
|||
t_stat xu_sw_reset (CTLR* xu)
|
||||
{
|
||||
t_stat status;
|
||||
int i;
|
||||
|
||||
sim_debug(DBG_TRC, xu->dev, "xu_sw_reset()\n");
|
||||
|
||||
|
@ -559,10 +649,12 @@ t_stat xu_sw_reset (CTLR* xu)
|
|||
|
||||
/* reset ethernet interface */
|
||||
memcpy (xu->var->setup.macs[0], xu->var->mac, sizeof(ETH_MAC));
|
||||
xu->var->setup.mac_count = 1;
|
||||
for (i=0; i<6; i++)
|
||||
xu->var->setup.macs[1][i] = 0xff; /* Broadcast Address */
|
||||
xu->var->setup.mac_count = 2;
|
||||
if (xu->var->etherface)
|
||||
status = eth_filter (xu->var->etherface, xu->var->setup.mac_count,
|
||||
&xu->var->mac, xu->var->setup.multicast,
|
||||
xu->var->setup.macs, xu->var->setup.multicast,
|
||||
xu->var->setup.promiscuous);
|
||||
|
||||
/* activate device if not disabled */
|
||||
|
@ -670,7 +762,7 @@ int32 xu_command(CTLR* xu)
|
|||
case FC_RMAL: /* read multicast address list */
|
||||
mtlen = (xu->var->pcb[2] & 0xFF00) >> 8;
|
||||
udbb = xu->var->pcb[1] | ((xu->var->pcb[2] & 03) << 16);
|
||||
wstatus = Map_WriteB(udbb, mtlen * 3, (uint8*) &xu->var->setup.macs[1]);
|
||||
wstatus = Map_WriteB(udbb, mtlen * 3, (uint8*) &xu->var->setup.macs[2]);
|
||||
break;
|
||||
|
||||
case FC_WMAL: /* write multicast address list */
|
||||
|
@ -680,14 +772,14 @@ sim_debug(DBG_TRC, xu->dev, "FC_WAL: mtlen=%d\n", mtlen);
|
|||
return PCSR0_PCEI;
|
||||
udbb = xu->var->pcb[1] | ((xu->var->pcb[2] & 03) << 16);
|
||||
/* clear existing multicast list */
|
||||
for (i=1; i<XU_FILTER_MAX; i++) {
|
||||
for (i=2; i<XU_FILTER_MAX; i++) {
|
||||
for (j=0; j<6; j++)
|
||||
xu->var->setup.macs[i][j] = 0;
|
||||
}
|
||||
/* get multicast list from host */
|
||||
rstatus = Map_ReadB(udbb, mtlen * 6, (uint8*) &xu->var->setup.macs[1]);
|
||||
rstatus = Map_ReadB(udbb, mtlen * 6, (uint8*) &xu->var->setup.macs[2]);
|
||||
if (rstatus == 0) {
|
||||
xu->var->setup.mac_count = mtlen + 1;
|
||||
xu->var->setup.mac_count = mtlen + 2;
|
||||
status = eth_filter (xu->var->etherface, xu->var->setup.mac_count,
|
||||
xu->var->setup.macs, xu->var->setup.multicast,
|
||||
xu->var->setup.promiscuous);
|
||||
|
@ -816,7 +908,7 @@ sim_debug(DBG_TRC, xu->dev, "FC_WMODE: mode=%04x\n", xu->var->mode);
|
|||
/* if promiscuous or multicast flags changed, change filter */
|
||||
if ((value ^ xu->var->mode) & (MODE_PROM | MODE_ENAL))
|
||||
status = eth_filter (xu->var->etherface, xu->var->setup.mac_count,
|
||||
&xu->var->mac, xu->var->setup.multicast,
|
||||
xu->var->setup.macs, xu->var->setup.multicast,
|
||||
xu->var->setup.promiscuous);
|
||||
break;
|
||||
|
||||
|
@ -1151,6 +1243,11 @@ void xu_process_transmit(CTLR* xu)
|
|||
runt = 1;
|
||||
}
|
||||
|
||||
/* As described in the DEUNA User Guide (Section 4.7), the DEUNA is responsible
|
||||
for inserting the appropriate source MAC address in the outgoing packet header,
|
||||
so we do that now. */
|
||||
memcpy(xu->var->write_buffer.msg+6, (uint8*)&xu->var->setup.macs[0], sizeof(ETH_MAC));
|
||||
|
||||
/* are we in internal loopback mode ? */
|
||||
if ((xu->var->mode & MODE_LOOP) && (xu->var->mode & MODE_INTL)) {
|
||||
/* just put packet in receive buffer */
|
||||
|
@ -1160,6 +1257,9 @@ void xu_process_transmit(CTLR* xu)
|
|||
wstatus = eth_write(xu->var->etherface, &xu->var->write_buffer, xu->var->wcallback);
|
||||
if (wstatus)
|
||||
xu->var->pcsr0 |= PCSR0_PCEI;
|
||||
else
|
||||
if (DBG_PCK & xu->dev->dctrl)
|
||||
eth_packet_trace_ex(xu->var->etherface, xu->var->write_buffer.msg, xu->var->write_buffer.len, "xu-write", DBG_DAT & xu->dev->dctrl, DBG_PCK);
|
||||
}
|
||||
|
||||
/* update transmit status in transmit buffer */
|
||||
|
@ -1263,7 +1363,14 @@ void xu_port_command (CTLR* xu)
|
|||
break;
|
||||
|
||||
case CMD_SELFTEST: /* SELFTEST */
|
||||
xu_sw_reset(xu);
|
||||
/*
|
||||
SELFTEST is a <=15-second self diagnostic test, setting various
|
||||
error flags and the DONE (DNI) flag when complete. For simulation
|
||||
purposes, signal completion immediately with no errors. This
|
||||
inexact behavior could be incompatible with any guest machine
|
||||
diagnostics that are expecting to be able to monitor the
|
||||
controller's progress through the diagnostic testing.
|
||||
*/
|
||||
xu->var->pcsr0 |= PCSR0_DNI;
|
||||
break;
|
||||
|
||||
|
@ -1348,7 +1455,7 @@ t_stat xu_rd(int32 *data, int32 PA, int32 access)
|
|||
*data = xu->var->pcsr3;
|
||||
break;
|
||||
}
|
||||
sim_debug(DBG_TRC, xu->dev, "xu_rd(), PCSR%d, data=%04x\n", reg, *data);
|
||||
sim_debug(DBG_REG, xu->dev, "xu_rd(), PCSR%d, data=%04x\n", reg, *data);
|
||||
if (PA & 1)
|
||||
sim_debug(DBG_WRN, xu->dev, "xu_rd(), Unexpected Odd address access of PCSR%d\n", reg);
|
||||
return SCPE_OK;
|
||||
|
@ -1375,7 +1482,7 @@ t_stat xu_wr(int32 data, int32 PA, int32 access)
|
|||
strcpy(desc, "Unknown");
|
||||
break;
|
||||
}
|
||||
sim_debug(DBG_TRC, xu->dev, "xu_wr(), PCSR%d, data=%08x, PA=%08x, access=%d[%s]\n", reg, data, PA, access, desc);
|
||||
sim_debug(DBG_REG, xu->dev, "xu_wr(), PCSR%d, data=%08x, PA=%08x, access=%d[%s]\n", reg, data, PA, access, desc);
|
||||
switch (reg) {
|
||||
case 00:
|
||||
/* Clear write-one-to-clear interrupt bits */
|
||||
|
@ -1458,6 +1565,15 @@ t_stat xu_attach(UNIT* uptr, char* cptr)
|
|||
xu->var->etherface = 0;
|
||||
return status;
|
||||
}
|
||||
if (SCPE_OK != eth_check_address_conflict (xu->var->etherface, &xu->var->mac)) {
|
||||
char buf[32];
|
||||
|
||||
eth_mac_fmt(&xu->var->mac, buf); /* format ethernet mac address */
|
||||
printf("%s: MAC Address Conflict on LAN for address %s\n", xu->dev->name, buf);
|
||||
if (sim_log) fprintf (sim_log, "%s: MAC Address Conflict on LAN for address %s\n", xu->dev->name, buf);
|
||||
eth_close(xu->var->etherface);
|
||||
return SCPE_NOATT;
|
||||
}
|
||||
uptr->filename = tptr;
|
||||
uptr->flags |= UNIT_ATT;
|
||||
eth_setcrc(xu->var->etherface, 1); /* enable CRC */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* pdp11_xu.h: DEUNA/DELUA ethernet controller information
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2003-2008, David T. Hittner
|
||||
Copyright (c) 2003-2005, David T. Hittner
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -28,6 +28,7 @@
|
|||
|
||||
Modification history:
|
||||
|
||||
23-Jan-08 MP Added debugging support to display packet headers and packet data
|
||||
08-Dec-05 DTH Added load_server, increased UDBSIZE for system ID parameters
|
||||
07-Jul-05 RMS Removed extraneous externs
|
||||
05-Jan-04 DTH Added network statistics
|
||||
|
@ -66,7 +67,7 @@ extern int32 int_req[IPL_HLVL];
|
|||
#include "sim_ether.h"
|
||||
|
||||
#define XU_QUE_MAX 500 /* message queue array */
|
||||
#define XU_FILTER_MAX 11 /* mac + 10 multicast addrs */
|
||||
#define XU_FILTER_MAX 12 /* mac + broadcast + 10 multicast addrs */
|
||||
#define XU_SERVICE_INTERVAL 100 /* times per second */
|
||||
#define XU_ID_TIMER_VAL 540 /* 9 min * 60 sec */
|
||||
#define UDBSIZE 200 /* max size of UDB (in words) */
|
||||
|
@ -107,6 +108,7 @@ struct xu_stats {
|
|||
uint16 txccf; /* transmit collision test failure */
|
||||
uint16 porterr; /* port driver errors */
|
||||
uint16 bablcnt; /* babble counter */
|
||||
uint32 loopf; /* loopback frames processed */
|
||||
};
|
||||
|
||||
struct xu_device {
|
||||
|
@ -300,7 +302,8 @@ typedef struct xu_controller CTLR;
|
|||
#define DBG_TRC 0x0001 /* trace routine calls */
|
||||
#define DBG_REG 0x0002 /* trace read/write registers */
|
||||
#define DBG_WRN 0x0004 /* display warnings */
|
||||
#define DBG_PCK 0x0080 /* display packets */
|
||||
#define DBG_PCK 0x0080 /* display packet headers */
|
||||
#define DBG_DAT 0x0100 /* display packet data */
|
||||
#define DBG_ETH 0x8000 /* debug ethernet device */
|
||||
|
||||
#endif /* _PDP11_XU_H */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp18b_defs.h: 18b PDP simulator definitions
|
||||
|
||||
Copyright (c) 1993-2008, Robert M Supnik
|
||||
Copyright (c) 1993-2010, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,7 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
22-May-10 RMS Added check for 64b definitions
|
||||
30-Oct-06 RMS Added infinite loop stop
|
||||
14-Jan-04 RMS Revised IO device call interface
|
||||
18-Oct-03 RMS Added DECtape off reel message
|
||||
|
@ -53,6 +54,10 @@
|
|||
|
||||
#include "sim_defs.h" /* simulator defns */
|
||||
|
||||
#if defined(USE_INT64) || defined(USE_ADDR64)
|
||||
#error "18b PDP's do not support 64b values!"
|
||||
#endif
|
||||
|
||||
/* Models: only one should be defined
|
||||
|
||||
model memory CPU options I/O options
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp8_clk.c: PDP-8 real-time clock simulator
|
||||
|
||||
Copyright (c) 1993-2008, Robert M Supnik
|
||||
Copyright (c) 1993-2011, 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"),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp8_cpu.c: PDP-8 CPU simulator
|
||||
|
||||
Copyright (c) 1993-2008, Robert M Supnik
|
||||
Copyright (c) 1993-2011, 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"),
|
||||
|
@ -27,13 +27,13 @@
|
|||
|
||||
28-Apr-07 RMS Removed clock initialization
|
||||
30-Oct-06 RMS Added idle and infinite loop detection
|
||||
30-Sep-06 RMS Fixed SC value after DVI overflow (found by Don North)
|
||||
22-Sep-05 RMS Fixed declarations (from Sterling Garwood)
|
||||
30-Sep-06 RMS Fixed SC value after DVI overflow (Don North)
|
||||
22-Sep-05 RMS Fixed declarations (Sterling Garwood)
|
||||
16-Aug-05 RMS Fixed C++ declaration and cast problems
|
||||
06-Nov-04 RMS Added =n to SHOW HISTORY
|
||||
31-Dec-03 RMS Fixed bug in set_cpu_hist
|
||||
13-Oct-03 RMS Added instruction history
|
||||
Added TSC8-75 support (from Bernhard Baehr)
|
||||
Added TSC8-75 support (Bernhard Baehr)
|
||||
12-Mar-03 RMS Added logical name support
|
||||
04-Oct-02 RMS Revamped device dispatching, added device number support
|
||||
06-Jan-02 RMS Added device enable/disable routines
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp8_ct.c: PDP-8 cassette tape simulator
|
||||
|
||||
Copyright (c) 2006-2008, Robert M Supnik
|
||||
Copyright (c) 2006-2011, 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"),
|
||||
|
@ -27,7 +27,7 @@
|
|||
|
||||
13-Aug-07 RMS Fixed handling of BEOT
|
||||
06-Aug-07 RMS Foward op at BOT skips initial file gap
|
||||
30-May-2007 RMS Fixed typo (from Norm Lastovica)
|
||||
30-May-2007 RMS Fixed typo (Norm Lastovica)
|
||||
|
||||
Magnetic tapes are represented as a series of variable records
|
||||
of the form:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp8_defs.h: PDP-8 simulator definitions
|
||||
|
||||
Copyright (c) 1993-2008, Robert M Supnik
|
||||
Copyright (c) 1993-2010, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,7 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
22-May-10 RMS Added check for 64b definitions
|
||||
21-Aug-07 RMS Added FPP8 support
|
||||
13-Dec-06 RMS Added TA8E support
|
||||
30-Oct-06 RMS Added infinite loop stop
|
||||
|
@ -46,6 +47,10 @@
|
|||
|
||||
#include "sim_defs.h" /* simulator defns */
|
||||
|
||||
#if defined(USE_INT64) || defined(USE_ADDR64)
|
||||
#error "PDP-8 does not support 64b values!"
|
||||
#endif
|
||||
|
||||
/* Simulator stop codes */
|
||||
|
||||
#define STOP_RSRV 1 /* must be 1 */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp8_df.c: DF32 fixed head disk simulator
|
||||
|
||||
Copyright (c) 1993-2008, Robert M Supnik
|
||||
Copyright (c) 1993-2011, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -25,8 +25,8 @@
|
|||
|
||||
df DF32 fixed head disk
|
||||
|
||||
15-May-06 RMS Fixed bug in autosize attach (reported by Dave Gesswein)
|
||||
07-Jan-06 RMS Fixed unaligned register access bug (found by Doug Carman)
|
||||
15-May-06 RMS Fixed bug in autosize attach (Dave Gesswein)
|
||||
07-Jan-06 RMS Fixed unaligned register access bug (Doug Carman)
|
||||
04-Jan-04 RMS Changed sim_fsize calling sequence
|
||||
26-Oct-03 RMS Cleaned up buffer copy code
|
||||
26-Jul-03 RMS Fixed bug in set size routine
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp8_dt.c: PDP-8 DECtape simulator
|
||||
|
||||
Copyright (c) 1993-2008, Robert M Supnik
|
||||
Copyright (c) 1993-2011, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -26,7 +26,7 @@
|
|||
dt TC08/TU56 DECtape
|
||||
|
||||
23-Jun-06 RMS Fixed switch conflict in ATTACH
|
||||
07-Jan-06 RMS Fixed unaligned register access bug (found by Doug Carman)
|
||||
07-Jan-06 RMS Fixed unaligned register access bug (Doug Carman)
|
||||
16-Aug-05 RMS Fixed C++ declaration and cast problems
|
||||
25-Jan-04 RMS Revised for device debug support
|
||||
09-Jan-04 RMS Changed sim_fsize calling sequence, added STOP_OFFR
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp8_fpp.c: PDP-8 floating point processor (FPP8A)
|
||||
|
||||
Copyright (c) 2007-2010, Robert M Supnik
|
||||
Copyright (c) 2007-2011, 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"),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp8_lp.c: PDP-8 line printer simulator
|
||||
|
||||
Copyright (c) 1993-2008, Robert M Supnik
|
||||
Copyright (c) 1993-2011, 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"),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp8_mt.c: PDP-8 magnetic tape simulator
|
||||
|
||||
Copyright (c) 1993-2008, Robert M Supnik
|
||||
Copyright (c) 1993-2011, 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"),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp8_pt.c: PDP-8 paper tape reader/punch simulator
|
||||
|
||||
Copyright (c) 1993-2008, Robert M Supnik
|
||||
Copyright (c) 1993-2011, 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"),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp8_rf.c: RF08 fixed head disk simulator
|
||||
|
||||
Copyright (c) 1993-2008, Robert M Supnik
|
||||
Copyright (c) 1993-2011, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -25,8 +25,8 @@
|
|||
|
||||
rf RF08 fixed head disk
|
||||
|
||||
15-May-06 RMS Fixed bug in autosize attach (reported by Dave Gesswein)
|
||||
07-Jan-06 RMS Fixed unaligned register access bug (found by Doug Carman)
|
||||
15-May-06 RMS Fixed bug in autosize attach (Dave Gesswein)
|
||||
07-Jan-06 RMS Fixed unaligned register access bug (Doug Carman)
|
||||
04-Jan-04 RMS Changed sim_fsize calling sequence
|
||||
26-Oct-03 RMS Cleaned up buffer copy code
|
||||
26-Jul-03 RMS Fixed bug in set size routine
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp8_rk.c: RK8E cartridge disk simulator
|
||||
|
||||
Copyright (c) 1993-2008, Robert M Supnik
|
||||
Copyright (c) 1993-2011, 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"),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp8_rl.c: RL8A cartridge disk simulator
|
||||
|
||||
Copyright (c) 1993-2008, Robert M Supnik
|
||||
Copyright (c) 1993-2011, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -25,7 +25,7 @@
|
|||
|
||||
rl RL8A cartridge disk
|
||||
|
||||
25-Oct-05 RMS Fixed IOT 61 decode bug (found by David Gesswein)
|
||||
25-Oct-05 RMS Fixed IOT 61 decode bug (David Gesswein)
|
||||
16-Aug-05 RMS Fixed C++ declaration and cast problems
|
||||
04-Jan-04 RMS Changed attach routine to use sim_fsize
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp8_rx.c: RX8E/RX01, RX28/RX02 floppy disk simulator
|
||||
|
||||
Copyright (c) 1993-2008, Robert M Supnik
|
||||
Copyright (c) 1993-2011, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -25,9 +25,9 @@
|
|||
|
||||
rx RX8E/RX01, RX28/RX02 floppy disk
|
||||
|
||||
15-May-06 RMS Fixed bug in autosize attach (reported by Dave Gesswein)
|
||||
15-May-06 RMS Fixed bug in autosize attach (Dave Gesswein)
|
||||
04-Jan-04 RMS Changed sim_fsize calling sequence
|
||||
05-Nov-03 RMS Fixed bug in RX28 read status (found by Charles Dickman)
|
||||
05-Nov-03 RMS Fixed bug in RX28 read status (Charles Dickman)
|
||||
26-Oct-03 RMS Cleaned up buffer copy code, fixed double density write
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
14-Mar-03 RMS Fixed variable size interaction with save/restore
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp8_sys.c: PDP-8 simulator interface
|
||||
|
||||
Copyright (c) 1993-2009, Robert M Supnik
|
||||
Copyright (c) 1993-2011, 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"),
|
||||
|
@ -24,7 +24,7 @@
|
|||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
24-Mar-09 RMS Added link to FPP
|
||||
24-Jun-08 RMS Fixed bug in new rim loader (found by Don North)
|
||||
24-Jun-08 RMS Fixed bug in new rim loader (Don North)
|
||||
24-May-08 RMS Fixed signed/unsigned declaration inconsistency
|
||||
03-Sep-07 RMS Added FPP8 support
|
||||
Rewrote rim and binary loaders
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp8_td.c: PDP-8 simple DECtape controller (TD8E) simulator
|
||||
|
||||
Copyright (c) 1993-2008, Robert M Supnik
|
||||
Copyright (c) 1993-2011, 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"),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp8_tsc.c: PDP-8 ETOS timesharing option board (TSC8-75)
|
||||
|
||||
Copyright (c) 2003-2008, Robert M Supnik
|
||||
Copyright (c) 2003-2011, 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"),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp8_tt.c: PDP-8 console terminal simulator
|
||||
|
||||
Copyright (c) 1993-2008, Robert M Supnik
|
||||
Copyright (c) 1993-2011, 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"),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp8_ttx.c: PDP-8 additional terminals simulator
|
||||
|
||||
Copyright (c) 1993-2008, Robert M Supnik
|
||||
Copyright (c) 1993-2011, 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"),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* sds_defs.h: SDS 940 simulator definitions
|
||||
|
||||
Copyright (c) 2001-2008, Robert M. Supnik
|
||||
Copyright (c) 2001-2010, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,7 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
22-May-10 RMS Added check for 64b definitions
|
||||
25-Apr-03 RMS Revised for extended file support
|
||||
*/
|
||||
|
||||
|
@ -31,6 +32,10 @@
|
|||
|
||||
#include "sim_defs.h" /* simulator defns */
|
||||
|
||||
#if defined(USE_INT64) || defined(USE_ADDR64)
|
||||
#error "SDS 940 does not support 64b values!"
|
||||
#endif
|
||||
|
||||
/* Simulator stop codes */
|
||||
|
||||
#define STOP_IONRDY 1 /* I/O dev not ready */
|
||||
|
|
|
@ -124,21 +124,21 @@
|
|||
|
||||
/* 780 microcode patch 37 - only test LR<23:0> for appropriate length */
|
||||
|
||||
#define ML_LR_TEST(r) if ((uint32)((r) & 0xFFFFFF) > 0x200000) RSVD_OPND_FAULT
|
||||
#define ML_LR_TEST(r) if (((uint32)((r) & 0xFFFFFF)) > 0x200000) RSVD_OPND_FAULT
|
||||
|
||||
/* 780 microcode patch 38 - only test PxBR<31>=1 and xBR<1:0> = 0 */
|
||||
/* 780 microcode patch 38 - only test PxBR<31>=1, PxBR<30> = 0, and xBR<1:0> = 0 */
|
||||
|
||||
#define ML_PXBR_TEST(r) if ((((r) & 0x80000000) == 0) || \
|
||||
((r) & 0x00000003)) RSVD_OPND_FAULT
|
||||
#define ML_SBR_TEST(r) if ((r) & 0x00000003) RSVD_OPND_FAULT
|
||||
#define ML_PXBR_TEST(r) if (((((uint32)(r)) & 0x80000000) == 0) || \
|
||||
((((uint32)(r)) & 0x40000003) != 0)) RSVD_OPND_FAULT
|
||||
#define ML_SBR_TEST(r) if ((((uint32)(r)) & 0xC0000003) != 0) RSVD_OPND_FAULT
|
||||
|
||||
/* 780 microcode patch 78 - only test xCBB<1:0> = 0 */
|
||||
|
||||
#define ML_PA_TEST(r) if ((r) & 0x00000003) RSVD_OPND_FAULT
|
||||
#define ML_PA_TEST(r) if ((((uint32)(r)) & 0x00000003) != 0) RSVD_OPND_FAULT
|
||||
|
||||
#define LP_AST_TEST(r) if ((r) > AST_MAX) RSVD_OPND_FAULT
|
||||
#define LP_MBZ84_TEST(r) if ((r) & 0xF8C00000) RSVD_OPND_FAULT
|
||||
#define LP_MBZ92_TEST(r) if ((r) & 0x7FC00000) RSVD_OPND_FAULT
|
||||
#define LP_MBZ84_TEST(r) if ((((uint32)(r)) & 0xF8C00000) != 0) RSVD_OPND_FAULT
|
||||
#define LP_MBZ92_TEST(r) if ((((uint32)(r)) & 0x7FC00000) != 0) RSVD_OPND_FAULT
|
||||
|
||||
/* Memory */
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* vax780_sbi.c: VAX 11/780 SBI
|
||||
|
||||
Copyright (c) 2004-2008, Robert M Supnik
|
||||
Copyright (c) 2004-2011, 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"),
|
||||
|
@ -27,9 +27,10 @@
|
|||
|
||||
sbi bus controller
|
||||
|
||||
21-Mar-2011 RMS Added autoreboot capability (from Mark Pizzalato)
|
||||
31-May-2008 RMS Fixed machine_check calling sequence (found by Peter Schorn)
|
||||
03-May-2006 RMS Fixed writes to ACCS
|
||||
28-May-08 RMS Inlined physical memory routines
|
||||
28-May-2008 RMS Inlined physical memory routines
|
||||
*/
|
||||
|
||||
#include "vax_defs.h"
|
||||
|
@ -100,6 +101,7 @@ uint32 sbi_sc = 0; /* SBI silo comparator *
|
|||
uint32 sbi_mt = 0; /* SBI maintenance */
|
||||
uint32 sbi_er = 0; /* SBI error status */
|
||||
uint32 sbi_tmo = 0; /* SBI timeout addr */
|
||||
char cpu_boot_cmd[CBUFSIZE] = { 0 }; /* boot command */
|
||||
|
||||
static t_stat (*nexusR[NEXUS_NUM])(int32 *dat, int32 ad, int32 md);
|
||||
static t_stat (*nexusW[NEXUS_NUM])(int32 dat, int32 ad, int32 md);
|
||||
|
@ -132,6 +134,8 @@ t_stat sbi_reset (DEVICE *dptr);
|
|||
void sbi_set_tmo (int32 pa);
|
||||
void uba_eval_int (void);
|
||||
t_stat vax780_boot (int32 flag, char *ptr);
|
||||
t_stat vax780_boot_parse (int32 flag, char *ptr);
|
||||
t_stat cpu_boot (int32 unitno, DEVICE *dptr);
|
||||
|
||||
extern t_stat vax780_fload (int flag, char *cptr);
|
||||
extern int32 intexc (int32 vec, int32 cc, int32 ipl, int ei);
|
||||
|
@ -175,6 +179,7 @@ REG sbi_reg[] = {
|
|||
{ HRDATA (SBIMT, sbi_mt, 32) },
|
||||
{ HRDATA (SBIER, sbi_er, 32) },
|
||||
{ HRDATA (SBITMO, sbi_tmo, 32) },
|
||||
{ BRDATA (BOOTCMD, cpu_boot_cmd, 16, 8, CBUFSIZE), REG_HRO },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
@ -587,11 +592,18 @@ sbi_er = sbi_er & ~SBIER_TMOW1C; /* clr SBIER<tmo> etc */
|
|||
return cc;
|
||||
}
|
||||
|
||||
/* Console entry */
|
||||
/* Console entry - only reached if CONHALT is set (AUTORESTART is set */
|
||||
|
||||
int32 con_halt (int32 code, int32 cc)
|
||||
{
|
||||
ABORT (STOP_HALT);
|
||||
if ((cpu_boot_cmd[0] == 0) || /* saved boot cmd? */
|
||||
(vax780_boot_parse (0, cpu_boot_cmd) != SCPE_OK) || /* reparse the boot cmd */
|
||||
(reset_all (0) != SCPE_OK) || /* reset the world */
|
||||
(cpu_boot (0, NULL) != SCPE_OK)) /* set up boot code */
|
||||
ABORT (STOP_BOOT); /* any error? */
|
||||
printf ("Rebooting...\n");
|
||||
if (sim_log)
|
||||
fprintf (sim_log, "Rebooting...\n");
|
||||
return cc;
|
||||
}
|
||||
|
||||
|
@ -604,6 +616,19 @@ return cc;
|
|||
|
||||
t_stat vax780_boot (int32 flag, char *ptr)
|
||||
{
|
||||
t_stat r;
|
||||
|
||||
r = vax780_boot_parse (flag, ptr); /* parse the boot cmd */
|
||||
if (r != SCPE_OK) /* error? */
|
||||
return r;
|
||||
strncpy (cpu_boot_cmd, ptr, CBUFSIZE); /* save for reboot */
|
||||
return run_cmd (flag, "CPU");
|
||||
}
|
||||
|
||||
/* Parse boot command, set up registers - also used on reset */
|
||||
|
||||
t_stat vax780_boot_parse (int32 flag, char *ptr)
|
||||
{
|
||||
char gbuf[CBUFSIZE];
|
||||
char *slptr, *regptr;
|
||||
int32 i, r5v, unitno;
|
||||
|
@ -649,7 +674,7 @@ for (i = 0; boot_tab[i].name != NULL; i++) {
|
|||
R[3] = unitno;
|
||||
R[4] = 0;
|
||||
R[5] = r5v;
|
||||
return run_cmd (flag, "CPU");
|
||||
return SCPE_OK;
|
||||
}
|
||||
}
|
||||
return SCPE_NOFNC;
|
||||
|
@ -662,8 +687,8 @@ t_stat cpu_boot (int32 unitno, DEVICE *dptr)
|
|||
t_stat r;
|
||||
|
||||
printf ("Loading boot code from vmb.exe\n");
|
||||
if (sim_log) fprintf (sim_log,
|
||||
"Loading boot code from vmb.exe\n");
|
||||
if (sim_log)
|
||||
fprintf (sim_log, "Loading boot code from vmb.exe\n");
|
||||
r = load_cmd (0, "-O vmb.exe 200");
|
||||
if (r != SCPE_OK)
|
||||
return r;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* vax780_stddev.c: VAX 11/780 standard I/O devices
|
||||
|
||||
Copyright (c) 1998-2008, Robert M Supnik
|
||||
Copyright (c) 1998-2011, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -29,6 +29,7 @@
|
|||
todr TODR clock
|
||||
tmr interval timer
|
||||
|
||||
21-Mar-11 RMS Added reboot capability
|
||||
17-Aug-08 RMS Resync TODR on any clock reset
|
||||
18-Jun-07 RMS Added UNIT_IDLE flag to console input, clock
|
||||
29-Oct-06 RMS Added clock coscheduler function
|
||||
|
@ -207,6 +208,8 @@ t_stat fl_wr_txdb (int32 data);
|
|||
t_bool fl_test_xfr (UNIT *uptr, t_bool wr);
|
||||
void fl_protocol_error (void);
|
||||
|
||||
extern int32 con_halt (int32 code, int32 cc);
|
||||
|
||||
/* TTI data structures
|
||||
|
||||
tti_dev TTI device descriptor
|
||||
|
@ -778,16 +781,20 @@ else {
|
|||
}
|
||||
else if (sel == TXDB_MISC) { /* misc function? */
|
||||
switch (data & MISC_MASK) { /* case on function */
|
||||
|
||||
case MISC_CLWS:
|
||||
comm_region[COMM_WRMS] = 0;
|
||||
|
||||
case MISC_CLCS:
|
||||
comm_region[COMM_CLDS] = 0;
|
||||
break;
|
||||
|
||||
case MISC_SWDN:
|
||||
ABORT (STOP_SWDN);
|
||||
break;
|
||||
|
||||
case MISC_BOOT:
|
||||
ABORT (STOP_BOOT);
|
||||
con_halt (0, 0); /* set up reboot */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
102
VAX/vax_cpu.c
102
VAX/vax_cpu.c
|
@ -1,6 +1,6 @@
|
|||
/* vax_cpu.c: VAX CPU
|
||||
|
||||
Copyright (c) 1998-2010, Robert M Supnik
|
||||
Copyright (c) 1998-2011, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -25,6 +25,7 @@
|
|||
|
||||
cpu VAX central processor
|
||||
|
||||
23-Mar-11 RMS Revised for new idle design (from Mark Pizzolato)
|
||||
24-Apr-10 RMS Added OLDVMS idle timer option
|
||||
Fixed bug in SET CPU IDLE
|
||||
21-May-08 RMS Removed inline support
|
||||
|
@ -175,8 +176,9 @@
|
|||
#define UNIT_CONH (1u << UNIT_V_CONH)
|
||||
#define UNIT_MSIZE (1u << UNIT_V_MSIZE)
|
||||
#define GET_CUR acc = ACC_MASK (PSL_GETCUR (PSL))
|
||||
#define VAX_IDLE_DFLT 1000
|
||||
#define OLD_IDLE_DFLT 200
|
||||
#define VAX_IDLE_VMS 0x1
|
||||
#define VAX_IDLE_ULT 0x2
|
||||
#define VAX_IDLE_QUAD 0x3
|
||||
|
||||
#define OPND_SIZE 16
|
||||
#define INST_SIZE 52
|
||||
|
@ -261,9 +263,8 @@ int32 cpu_astop = 0;
|
|||
int32 mchk_va, mchk_ref; /* mem ref param */
|
||||
int32 ibufl, ibufh; /* prefetch buf */
|
||||
int32 ibcnt, ppc; /* prefetch ctl */
|
||||
uint32 cpu_idle_ipl_mask = 0x8; /* idle if on IPL 3 */
|
||||
uint32 cpu_idle_type = 1; /* default to VMS */
|
||||
int32 cpu_idle_wait = VAX_IDLE_DFLT; /* for these cycles */
|
||||
uint32 cpu_idle_mask = VAX_IDLE_VMS; /* idle mask */
|
||||
uint32 cpu_idle_type = 1; /* default VMS */
|
||||
jmp_buf save_env;
|
||||
REG *pcq_r = NULL; /* PC queue reg ptr */
|
||||
int32 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
|
||||
|
@ -387,8 +388,8 @@ int32 cpu_get_vsw (int32 sw);
|
|||
SIM_INLINE int32 get_istr (int32 lnt, int32 acc);
|
||||
int32 ReadOcta (int32 va, int32 *opnd, int32 j, int32 acc);
|
||||
t_bool cpu_show_opnd (FILE *st, InstHistory *h, int32 line);
|
||||
int32 cpu_psl_ipl_idle (int32 newpsl);
|
||||
t_stat cpu_idle_svc (UNIT *uptr);
|
||||
void cpu_idle (void);
|
||||
|
||||
/* CPU data structures
|
||||
|
||||
|
@ -445,9 +446,8 @@ REG cpu_reg[] = {
|
|||
{ FLDATA (CRDERR, crd_err, 0) },
|
||||
{ FLDATA (MEMERR, mem_err, 0) },
|
||||
{ FLDATA (HLTPIN, hlt_pin, 0) },
|
||||
{ HRDATA (IDLE_IPL, cpu_idle_ipl_mask, 16), REG_HIDDEN },
|
||||
{ DRDATA (IDLE_TYPE, cpu_idle_type, 4), REG_HRO },
|
||||
{ DRDATA (IDLE_WAIT, cpu_idle_wait, 16), REG_HIDDEN },
|
||||
{ HRDATA (IDLE_MASK, cpu_idle_mask, 16), REG_HIDDEN },
|
||||
{ DRDATA (IDLE_INDX, cpu_idle_type, 4), REG_HRO },
|
||||
{ BRDATA (PCQ, pcq, 16, 32, PCQ_SIZE), REG_RO+REG_CIRC },
|
||||
{ HRDATA (PCQP, pcq_p, 6), REG_HRO },
|
||||
{ HRDATA (BADABO, badabo, 32), REG_HRO },
|
||||
|
@ -1571,6 +1571,16 @@ for ( ;; ) {
|
|||
|
||||
case TSTL:
|
||||
CC_IIZZ_L (op0); /* set cc's */
|
||||
if ((cc == CC_Z) &&
|
||||
((((PSL & PSL_IS) != 0) && /* on IS? */
|
||||
(PSL_GETIPL (PSL) == 0x1) && /* at IPL 1? */
|
||||
((cpu_idle_mask & VAX_IDLE_ULT) != 0))|| /* running Ultrix or friends? */
|
||||
((PSL_GETIPL (PSL) == 0x0) && /* at IPL 0? */
|
||||
((fault_PC & 0x80000000) != 0) && /* in system space? */
|
||||
((PC - fault_PC) == 6) && /* 6 byte instruction? */
|
||||
((fault_PC & 0x7fffffff) < 0x4000) && /* in low system space? */
|
||||
((cpu_idle_mask & VAX_IDLE_QUAD) != 0)))) /* running Quad or friends? */
|
||||
cpu_idle(); /* idle loop */
|
||||
break;
|
||||
|
||||
/* Single operand instructions with source, read/write - op src.mx
|
||||
|
@ -2109,14 +2119,20 @@ for ( ;; ) {
|
|||
|
||||
case BRB:
|
||||
BRANCHB (brdisp); /* branch */
|
||||
if ((PC == fault_PC) && (PSL_GETIPL (PSL) == 0x1F))
|
||||
ABORT (STOP_LOOP);
|
||||
if (PC == fault_PC) { /* to self? */
|
||||
if (PSL_GETIPL (PSL) == 0x1F) /* int locked out? */
|
||||
ABORT (STOP_LOOP); /* infinite loop */
|
||||
cpu_idle (); /* idle loop */
|
||||
}
|
||||
break;
|
||||
|
||||
case BRW:
|
||||
BRANCHW (brdisp); /* branch */
|
||||
if ((PC == fault_PC) && (PSL_GETIPL (PSL) == 0x1F))
|
||||
ABORT (STOP_LOOP);
|
||||
if (PC == fault_PC) { /* to self? */
|
||||
if (PSL_GETIPL (PSL) == 0x1F) /* int locked out? */
|
||||
ABORT (STOP_LOOP); /* infinite loop */
|
||||
cpu_idle (); /* idle loop */
|
||||
}
|
||||
break;
|
||||
|
||||
case BSBB:
|
||||
|
@ -2348,8 +2364,13 @@ for ( ;; ) {
|
|||
*/
|
||||
|
||||
case BBS:
|
||||
if (op_bb_n (opnd, acc)) /* br if bit set */
|
||||
if (op_bb_n (opnd, acc)) { /* br if bit set */
|
||||
BRANCHB (brdisp);
|
||||
if (((PSL & PSL_IS) != 0) && /* on IS? */
|
||||
(PSL_GETIPL (PSL) == 0x3) && /* at IPL 3? */
|
||||
((cpu_idle_mask & VAX_IDLE_VMS) != 0)) /* running VMS? */
|
||||
cpu_idle (); /* idle loop */
|
||||
}
|
||||
break;
|
||||
|
||||
case BBC:
|
||||
|
@ -3071,24 +3092,15 @@ opnd[j++] = Read (va + 12, L_LONG, acc);
|
|||
return j;
|
||||
}
|
||||
|
||||
/* Check new PSL IPL for idle start
|
||||
Checked only on exception or REI, not on MTPR #IPL,
|
||||
to allow for local locking within the idle loop */
|
||||
/* Schedule idle before the next instruction */
|
||||
|
||||
int32 cpu_psl_ipl_idle (int32 newpsl)
|
||||
void cpu_idle (void)
|
||||
{
|
||||
if (((newpsl ^ PSL) & PSL_IPL) != 0) {
|
||||
sim_cancel (&cpu_unit);
|
||||
if (sim_idle_enab && ((newpsl & PSL_CUR) == 0)) {
|
||||
uint32 newipl = PSL_GETIPL (newpsl);
|
||||
if (cpu_idle_ipl_mask & (1u << newipl))
|
||||
sim_activate (&cpu_unit, cpu_idle_wait);
|
||||
}
|
||||
}
|
||||
return newpsl;
|
||||
sim_activate_abs (&cpu_unit, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Idle timer has expired with no PSL change */
|
||||
/* Idle service */
|
||||
|
||||
t_stat cpu_idle_svc (UNIT *uptr)
|
||||
{
|
||||
|
@ -3108,15 +3120,17 @@ PSL = PSL_IS | PSL_IPL1F;
|
|||
SISR = 0;
|
||||
ASTLVL = 4;
|
||||
mapen = 0;
|
||||
if (M == NULL)
|
||||
FLUSH_ISTR; /* init I-stream */
|
||||
if (M == NULL) { /* first time init? */
|
||||
sim_brk_types = sim_brk_dflt = SWMASK ('E');
|
||||
pcq_r = find_reg ("PCQ", NULL, dptr);
|
||||
if (pcq_r == NULL)
|
||||
return SCPE_IERR;
|
||||
pcq_r->qptr = 0;
|
||||
M = (uint32 *) calloc (((uint32) MEMSIZE) >> 2, sizeof (uint32));
|
||||
if (M == NULL)
|
||||
return SCPE_MEM;
|
||||
pcq_r = find_reg ("PCQ", NULL, dptr);
|
||||
if (pcq_r)
|
||||
pcq_r->qptr = 0;
|
||||
else return SCPE_IERR;
|
||||
sim_brk_types = sim_brk_dflt = SWMASK ('E');
|
||||
}
|
||||
return build_dib_tab ();
|
||||
}
|
||||
|
||||
|
@ -3381,17 +3395,16 @@ return more;
|
|||
struct os_idle {
|
||||
char *name;
|
||||
uint32 mask;
|
||||
int32 value;
|
||||
};
|
||||
|
||||
static struct os_idle os_tab[] = {
|
||||
{ "VMS", 0x8, VAX_IDLE_DFLT },
|
||||
{ "NETBSD", 0x2, VAX_IDLE_DFLT },
|
||||
{ "ULTRIX", 0x2, VAX_IDLE_DFLT },
|
||||
{ "OPENBSD", 0x1, VAX_IDLE_DFLT },
|
||||
{ "32V", 0x1, VAX_IDLE_DFLT },
|
||||
{ "OLDVMS", 0xB, OLD_IDLE_DFLT },
|
||||
{ NULL, 0, 0 }
|
||||
{ "VMS", VAX_IDLE_VMS },
|
||||
{ "NETBSD", VAX_IDLE_ULT },
|
||||
{ "ULTRIX", VAX_IDLE_ULT },
|
||||
{ "OPENBSD", VAX_IDLE_QUAD },
|
||||
{ "32V", VAX_IDLE_QUAD },
|
||||
{ "ALL", VAX_IDLE_VMS|VAX_IDLE_ULT|VAX_IDLE_QUAD },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
/* Set and show idle */
|
||||
|
@ -3404,8 +3417,7 @@ if (cptr != NULL) {
|
|||
for (i = 0; os_tab[i].name != NULL; i++) {
|
||||
if (strcmp (os_tab[i].name, cptr) == 0) {
|
||||
cpu_idle_type = i + 1;
|
||||
cpu_idle_ipl_mask = os_tab[i].mask;
|
||||
cpu_idle_wait = os_tab[i].value;
|
||||
cpu_idle_mask = os_tab[i].mask;
|
||||
return sim_set_idle (uptr, val, NULL, desc);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* vax_cpu1.c: VAX complex instructions
|
||||
|
||||
Copyright (c) 1998-2008, Robert M Supnik
|
||||
Copyright (c) 1998-2011, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,7 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
23-Mar-11 RMS Revised idle design (from Mark Pizzolato)
|
||||
28-May-08 RMS Inlined physical memory routines
|
||||
29-Apr-07 RMS Separated base register access checks for 11/780
|
||||
10-May-06 RMS Added access check on system PTE for 11/780
|
||||
|
@ -109,7 +110,6 @@ extern t_bool chk_tb_ent (uint32 va);
|
|||
extern int32 ReadIPR (int32 rg);
|
||||
extern void WriteIPR (int32 rg, int32 val);
|
||||
extern t_bool BadCmPSL (int32 newpsl);
|
||||
extern int32 cpu_psl_ipl_idle (int32 newpsl);
|
||||
|
||||
extern jmp_buf save_env;
|
||||
|
||||
|
@ -1137,9 +1137,9 @@ else {
|
|||
}
|
||||
}
|
||||
if (ei > 0) /* if int, new IPL */
|
||||
PSL = cpu_psl_ipl_idle (newpsl | (ipl << PSL_V_IPL));
|
||||
else PSL = cpu_psl_ipl_idle (newpsl | /* exc, old IPL/1F */
|
||||
((newpc & 1)? PSL_IPL1F: (oldpsl & PSL_IPL)) | (oldcur << PSL_V_PRV));
|
||||
PSL = newpsl | (ipl << PSL_V_IPL);
|
||||
else PSL = newpsl | /* exc, old IPL/1F */
|
||||
((newpc & 1)? PSL_IPL1F: (oldpsl & PSL_IPL)) | (oldcur << PSL_V_PRV);
|
||||
if (DEBUG_PRI (cpu_dev, LOG_CPU_I))
|
||||
fprintf (sim_deb, ">>IEX: PC=%08x, PSL=%08x, SP=%08x, VEC=%08x, nPSL=%08x, nSP=%08x\n",
|
||||
PC, oldpsl, oldsp, vec, PSL, SP);
|
||||
|
@ -1249,7 +1249,7 @@ else STK[oldcur] = SP;
|
|||
if (DEBUG_PRI (cpu_dev, LOG_CPU_R))
|
||||
fprintf (sim_deb, ">>REI: PC=%08x, PSL=%08x, SP=%08x, nPC=%08x, nPSL=%08x, nSP=%08x\n",
|
||||
PC, PSL, SP - 8, newpc, newpsl, ((newpsl & IS)? IS: STK[newcur]));
|
||||
PSL = cpu_psl_ipl_idle ((PSL & PSL_TP) | (newpsl & ~CC_MASK)); /* set PSL */
|
||||
PSL = (PSL & PSL_TP) | (newpsl & ~CC_MASK); /* set PSL */
|
||||
if (PSL & PSL_IS) /* set new stack */
|
||||
SP = IS;
|
||||
else {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* vax_sys.c: VAX simulator interface
|
||||
|
||||
Copyright (c) 1998-2008, Robert M Supnik
|
||||
Copyright (c) 1998-2011, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,7 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
21-Mar-11 RMS Modified string for STOP_BOOT message
|
||||
19-Nov-08 RMS Moved bad block routine to I/O library
|
||||
03-Nov-05 RMS Added 780 stop codes
|
||||
04-Sep-05 RMS Fixed missing assignment (found by Peter Schorn)
|
||||
|
@ -100,7 +101,7 @@ const char *sim_stop_messages[] = {
|
|||
"Infinite loop",
|
||||
"Sanity timer expired",
|
||||
"Software done",
|
||||
"Reboot requested",
|
||||
"Reboot request failed",
|
||||
"Unknown error",
|
||||
"Unknown abort code"
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* vax_syscm.c: PDP-11 compatibility mode symbolic decode and parse
|
||||
|
||||
Copyright (c) 1993-2008, Robert M Supnik
|
||||
Copyright (c) 1993-2010, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,8 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
22-May-10 RMS Fixed t_addr printouts for 64b big-endian systems
|
||||
(found by Mark Pizzolato)
|
||||
12-Nov-06 RMS Fixed operand order in EIS instructions (found by W.F.J. Mueller)
|
||||
27-Sep-05 RMS Fixed warnings compiling with 64b addresses
|
||||
15-Sep-04 RMS Cloned from pdp11_sys.c
|
||||
|
@ -242,13 +244,13 @@ switch (mode) {
|
|||
case 6:
|
||||
if (reg != 7)
|
||||
fprintf (of, "%-X(%s)", nval, rname[reg]);
|
||||
else fprintf (of, "%-X", (nval + addr + 4) & 0177777);
|
||||
else fprintf (of, "%-X", (int32)((nval + addr + 4) & 0177777));
|
||||
break;
|
||||
|
||||
case 7:
|
||||
if (reg != 7)
|
||||
fprintf (of, "@%-X(%s)", nval, rname[reg]);
|
||||
else fprintf (of, "@%-X", (nval + addr + 4) & 0177777);
|
||||
else fprintf (of, "@%-X", (int32)((nval + addr + 4) & 0177777));
|
||||
break;
|
||||
} /* end case */
|
||||
|
||||
|
@ -326,7 +328,7 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
|
|||
case I_V_BR: /* cond branch */
|
||||
fprintf (of, "%s ", opcode[i]);
|
||||
brdisp = (l8b + l8b + ((l8b & 0200)? 0177002: 2)) & 0177777;
|
||||
fprintf (of, "%-X", (addr + brdisp) & 0177777);
|
||||
fprintf (of, "%-X", (int32)((addr + brdisp) & 0177777));
|
||||
break;
|
||||
|
||||
case I_V_8B: /* 8b */
|
||||
|
@ -336,7 +338,7 @@ for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
|
|||
case I_V_SOB: /* sob */
|
||||
fprintf (of, "%s %s,", opcode[i], rname[srcr]);
|
||||
brdisp = (dstm * 2) - 2;
|
||||
fprintf (of, "%-X", (addr - brdisp) & 0177777);
|
||||
fprintf (of, "%-X", (int32)((addr - brdisp) & 0177777));
|
||||
break;
|
||||
|
||||
case I_V_RSOP: /* rsop */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* vax_sysdev.c: VAX 3900 system-specific logic
|
||||
|
||||
Copyright (c) 1998-2008, Robert M Supnik
|
||||
Copyright (c) 1998-2011, 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"),
|
||||
|
@ -32,6 +32,7 @@
|
|||
cso console storage output
|
||||
sysd system devices (SSC miscellany)
|
||||
|
||||
23-Dec-10 RMS Added power clear call to boot routine (from Mark Pizzolato)
|
||||
25-Oct-05 RMS Automated CMCTL extended memory
|
||||
16-Aug-05 RMS Fixed C++ declaration and cast problems
|
||||
10-Mar-05 RMS Fixed bug in timer schedule routine (from Mark Hittinger)
|
||||
|
@ -275,6 +276,7 @@ extern void txcs_wr (int32 dat);
|
|||
extern void txdb_wr (int32 dat);
|
||||
extern void ioreset_wr (int32 dat);
|
||||
extern uint32 sim_os_msec();
|
||||
extern void cpu_idle (void);
|
||||
|
||||
/* ROM data structures
|
||||
|
||||
|
@ -1556,6 +1558,7 @@ if (*rom == 0) { /* no boot? */
|
|||
if (r != SCPE_OK)
|
||||
return r;
|
||||
}
|
||||
sysd_powerup ();
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
|
46
makefile
46
makefile
|
@ -9,12 +9,36 @@ ifeq ($(WIN32),)
|
|||
ifneq (,$(findstring darwin,$(OSTYPE)))
|
||||
OS_CCDEFS = -D_GNU_SOURCE
|
||||
else
|
||||
ifeq (librt,$(shell if test -e /usr/lib/librt.a; then echo librt; fi))
|
||||
OS_CCDEFS = -lrt -lm -D_GNU_SOURCE
|
||||
endif
|
||||
endif
|
||||
CC = gcc -std=c99 -U__STRICT_ANSI__ -g $(OS_CCDEFS) -I .
|
||||
ifeq ($(USE_NETWORK),)
|
||||
else
|
||||
OS_CCDEFS = -lm -D_GNU_SOURCE
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
ifeq (readline,$(shell if test -e /usr/lib/libreadline.a; then echo readline; fi))
|
||||
# Use Locally installed and available readline support
|
||||
ifeq (ncurses,$(shell if test -e /usr/lib/libncurses.a; then echo ncurses; fi))
|
||||
READLINE_CCDEFS = -DHAVE_READLINE -lreadline -lncurses
|
||||
else
|
||||
READLINE_CCDEFS = -DHAVE_READLINE -lreadline
|
||||
endif
|
||||
endif
|
||||
ifeq (pcap,$(shell if test -e /usr/lib/libpcap.a; then echo pcap; fi))
|
||||
# Use Locally installed and available pcap support
|
||||
NETWORK_CCDEFS = -DUSE_NETWORK -lpcap
|
||||
endif
|
||||
ifeq (tuntap,$(shell if test -e /usr/include/linux/if_tun.h; then echo tuntap; fi))
|
||||
# Provide support for Tap networking on Linux
|
||||
NETWORK_TAP_CCDEFS = -DUSE_TAP_NETWORK
|
||||
endif
|
||||
ifeq (bsdtuntap,$(shell if test -e /usr/include/net/if_tun.h; then echo bsdtuntap; fi))
|
||||
# Provide support for Tap networking
|
||||
NETWORK_TAP_CCDEFS = -DUSE_TAP_NETWORK -DUSE_BSDTUNTAP
|
||||
endif
|
||||
CC = gcc -std=c99 -U__STRICT_ANSI__ -g $(OS_CCDEFS) -I . $(READLINE_CCDEFS) $(NETWORK_CCDEFS) $(NETWORK_TAP_CCDEFS)
|
||||
ifneq ($(USE_NETWORK),)
|
||||
# Assume built from tcpdump.org sources with default install target
|
||||
NETWORK_OPT = -DUSE_NETWORK -isystem /usr/local/include /usr/local/lib/libpcap.a
|
||||
endif
|
||||
else
|
||||
|
@ -22,9 +46,8 @@ else
|
|||
LDFLAGS = -lm -lwsock32 -lwinmm
|
||||
CC = gcc -std=c99 -U__STRICT_ANSI__ -O2 -I.
|
||||
EXE = .exe
|
||||
ifeq ($(USE_NETWORK),)
|
||||
else
|
||||
NETWORK_OPT = -DUSE_NETWORK -lwpcap -lpacket
|
||||
ifneq ($(USE_NETWORK),)
|
||||
NETWORK_OPT = -DUSE_SHARED
|
||||
endif
|
||||
endif
|
||||
|
||||
|
@ -58,7 +81,7 @@ ECLIPSE = ${NOVAD}/eclipse_cpu.c ${NOVAD}/eclipse_tt.c ${NOVAD}/nova_sys.c \
|
|||
${NOVAD}/nova_dkp.c ${NOVAD}/nova_dsk.c ${NOVAD}/nova_lp.c \
|
||||
${NOVAD}/nova_mta.c ${NOVAD}/nova_plt.c ${NOVAD}/nova_pt.c \
|
||||
${NOVAD}/nova_clk.c ${NOVAD}/nova_tt1.c ${NOVAD}/nova_qty.c
|
||||
ECLIPSE_OPT = -I ${NOVAD} -DECLIPSE -DUSE_INT64
|
||||
ECLIPSE_OPT = -I ${NOVAD} -DECLIPSE
|
||||
|
||||
|
||||
PDP18BD = PDP18B
|
||||
|
@ -135,7 +158,7 @@ PDP8 = ${PDP8D}/pdp8_cpu.c ${PDP8D}/pdp8_clk.c ${PDP8D}/pdp8_df.c \
|
|||
PDP8_OPT = -I ${PDP8D}
|
||||
|
||||
|
||||
H316D = H316
|
||||
H316D = h316
|
||||
H316 = ${H316D}/h316_stddev.c ${H316D}/h316_lp.c ${H316D}/h316_cpu.c \
|
||||
${H316D}/h316_sys.c ${H316D}/h316_mt.c ${H316D}/h316_fhd.c \
|
||||
${H316D}/h316_dp.c
|
||||
|
@ -251,7 +274,7 @@ SDS = ${SDSD}/sds_cpu.c ${SDSD}/sds_drm.c ${SDSD}/sds_dsk.c ${SDSD}/sds_io.c \
|
|||
${SDSD}/sds_stddev.c ${SDSD}/sds_sys.c
|
||||
SDS_OPT = -I ${SDSD}
|
||||
|
||||
SWTPD = SWTP
|
||||
SWTPD = swtp
|
||||
SWTP = ${SWTPD}/swtp_cpu.c ${SWTPD}/swtp_dsk.c ${SWTPD}/swtp_sio.c \
|
||||
${SWTPD}/swtp_sys.c
|
||||
SWTP_OPT = -I ${SWTPD}
|
||||
|
@ -269,9 +292,10 @@ all : ${ALL}
|
|||
|
||||
clean :
|
||||
ifeq ($(WIN32),)
|
||||
${RM} ${BIN}*
|
||||
${RM} -r ${BIN}
|
||||
else
|
||||
if exist BIN\*.exe del /q BIN\*.exe
|
||||
if exist BIN rmdir BIN
|
||||
endif
|
||||
|
||||
#
|
||||
|
|
175
scp.c
175
scp.c
|
@ -1,6 +1,6 @@
|
|||
/* scp.c: simulator control program
|
||||
|
||||
Copyright (c) 1993-2009, Robert M Supnik
|
||||
Copyright (c) 1993-2011, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,11 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
13-Jan-11 MP Added "SHOW SHOW" and "SHOW <dev> SHOW" commands
|
||||
05-Jan-11 RMS Fixed bug in deposit stride for numeric input (John Dundas)
|
||||
23-Dec-10 RMS Clarified some help messages (Mark Pizzolato)
|
||||
08-Nov-10 RMS Fixed handling of DO with no arguments (Dave Bryan)
|
||||
22-May-10 RMS Added *nix READLINE support (Mark Pizzolato)
|
||||
08-Feb-09 RMS Fixed warnings in help printouts
|
||||
29-Dec-08 RMS Fixed implementation of MTAB_NC
|
||||
24-Nov-08 RMS Revised RESTORE unit logic for consistency
|
||||
|
@ -30,8 +35,8 @@
|
|||
17-Aug-08 RMS Revert RUN/BOOT to standard, rather than powerup, reset
|
||||
25-Jul-08 JDB DO cmd missing params now default to null string
|
||||
29-Jun-08 JDB DO cmd sub_args now allows "\\" to specify literal backslash
|
||||
31-Mar-08 RMS Fixed bug in local/global register search (found by Mark Pizzolato)
|
||||
Fixed bug in restore of RO units (from Mark Pizzolato)
|
||||
31-Mar-08 RMS Fixed bug in local/global register search (Mark Pizzolato)
|
||||
Fixed bug in restore of RO units (Mark Pizzolato)
|
||||
06-Feb-08 RMS Added SET/SHO/NO BR with default argument
|
||||
18-Jul-07 RMS Modified match_ext for VMS ext;version support
|
||||
28-Apr-07 RMS Modified sim_instr invocation to call sim_rtcn_init_all
|
||||
|
@ -47,52 +52,52 @@
|
|||
14-Feb-06 RMS Upgraded save file format to V3.5
|
||||
18-Jan-06 RMS Added fprint_stopped_gen
|
||||
Added breakpoint spaces
|
||||
Fixed unaligned register access (found by Doug Carman)
|
||||
22-Sep-05 RMS Fixed declarations (from Sterling Garwood)
|
||||
Fixed unaligned register access (Doug Carman)
|
||||
22-Sep-05 RMS Fixed declarations (Sterling Garwood)
|
||||
30-Aug-05 RMS Revised to trim trailing spaces on file names
|
||||
25-Aug-05 RMS Added variable default device support
|
||||
23-Aug-05 RMS Added Linux line history support
|
||||
16-Aug-05 RMS Fixed C++ declaration and cast problems
|
||||
01-May-05 RMS Revised syntax for SET DEBUG (from Dave Bryan)
|
||||
01-May-05 RMS Revised syntax for SET DEBUG (Dave Bryan)
|
||||
22-Mar-05 JDB Modified DO command to allow ten-level nesting
|
||||
18-Mar-05 RMS Moved DETACH tests into detach_unit (from Dave Bryan)
|
||||
18-Mar-05 RMS Moved DETACH tests into detach_unit (Dave Bryan)
|
||||
Revised interface to fprint_sym, fparse_sym
|
||||
07-Feb-05 RMS Added ASSERT command (from Dave Bryan)
|
||||
07-Feb-05 RMS Added ASSERT command (Dave Bryan)
|
||||
02-Feb-05 RMS Fixed bug in global register search
|
||||
26-Dec-04 RMS Qualified SAVE examine, RESTORE deposit with SIM_SW_REST
|
||||
10-Nov-04 JDB Fixed logging of errors from cmds in "do" file
|
||||
05-Nov-04 RMS Moved SET/SHOW DEBUG under CONSOLE hierarchy
|
||||
Renamed unit OFFLINE/ONLINE to DISABLED/ENABLED (from Dave Bryan)
|
||||
Revised to flush output files after simulation stop (from Dave Bryan)
|
||||
Renamed unit OFFLINE/ONLINE to DISABLED/ENABLED (Dave Bryan)
|
||||
Revised to flush output files after simulation stop (Dave Bryan)
|
||||
15-Oct-04 RMS Fixed HELP to suppress duplicate descriptions
|
||||
27-Sep-04 RMS Fixed comma-separation options in set (from David Bryan)
|
||||
27-Sep-04 RMS Fixed comma-separation options in set (David Bryan)
|
||||
09-Sep-04 RMS Added -p option for RESET
|
||||
13-Aug-04 RMS Qualified RESTORE detach with SIM_SW_REST
|
||||
17-Jul-04 RMS Added ECHO command (from Dave Bryan)
|
||||
17-Jul-04 RMS Added ECHO command (Dave Bryan)
|
||||
12-Jul-04 RMS Fixed problem ATTACHing to read only files
|
||||
(found by John Dundas)
|
||||
(John Dundas)
|
||||
28-May-04 RMS Added SET/SHOW CONSOLE
|
||||
14-Feb-04 RMS Updated SAVE/RESTORE (V3.2)
|
||||
RMS Added debug print routines (from Dave Hittner)
|
||||
RMS Added debug print routines (Dave Hittner)
|
||||
RMS Added sim_vm_parse_addr and sim_vm_fprint_addr
|
||||
RMS Added REG_VMAD support
|
||||
RMS Split out libraries
|
||||
RMS Moved logging function to SCP
|
||||
RMS Exposed step counter interface(s)
|
||||
RMS Fixed double logging of SHOW BREAK (found by Mark Pizzolato)
|
||||
RMS Fixed double logging of SHOW BREAK (Mark Pizzolato)
|
||||
RMS Fixed implementation of REG_VMIO
|
||||
RMS Added SET/SHOW DEBUG, SET/SHOW <device> DEBUG,
|
||||
SHOW <device> MODIFIERS, SHOW <device> RADIX
|
||||
RMS Changed sim_fsize to take uptr argument
|
||||
29-Dec-03 RMS Added Telnet console output stall support
|
||||
01-Nov-03 RMS Cleaned up implicit detach on attach/restore
|
||||
Fixed bug in command line read while logging (found by Mark Pizzolato)
|
||||
Fixed bug in command line read while logging (Mark Pizzolato)
|
||||
01-Sep-03 RMS Fixed end-of-file problem in dep, idep
|
||||
Fixed error on trailing spaces in dep, idep
|
||||
15-Jul-03 RMS Removed unnecessary test in reset_all
|
||||
15-Jun-03 RMS Added register flag REG_VMIO
|
||||
25-Apr-03 RMS Added extended address support (V3.0)
|
||||
Fixed bug in SAVE (found by Peter Schorn)
|
||||
Fixed bug in SAVE (Peter Schorn)
|
||||
Added u5, u6 fields
|
||||
Added logical name support
|
||||
03-Mar-03 RMS Added sim_fsize
|
||||
|
@ -100,36 +105,36 @@
|
|||
08-Feb-03 RMS Changed sim_os_sleep to void, match_ext to char*
|
||||
Added multiple actions, .ini file support
|
||||
Added multiple switch evaluations per line
|
||||
07-Feb-03 RMS Added VMS support for ! (from Mark Pizzolato)
|
||||
07-Feb-03 RMS Added VMS support for ! (Mark Pizzolato)
|
||||
01-Feb-03 RMS Added breakpoint table extension, actions
|
||||
14-Jan-03 RMS Added missing function prototypes
|
||||
10-Jan-03 RMS Added attach/restore flag, dynamic memory size support,
|
||||
case sensitive SET options
|
||||
22-Dec-02 RMS Added ! (OS command) feature (from Mark Pizzolato)
|
||||
22-Dec-02 RMS Added ! (OS command) feature (Mark Pizzolato)
|
||||
17-Dec-02 RMS Added get_ipaddr
|
||||
02-Dec-02 RMS Added EValuate command
|
||||
16-Nov-02 RMS Fixed bug in register name match algorithm
|
||||
13-Oct-02 RMS Fixed Borland compiler warnings (found by Hans Pufal)
|
||||
05-Oct-02 RMS Fixed bugs in set_logon, ssh_break (found by David Hittner)
|
||||
13-Oct-02 RMS Fixed Borland compiler warnings (Hans Pufal)
|
||||
05-Oct-02 RMS Fixed bugs in set_logon, ssh_break (David Hittner)
|
||||
Added support for fixed buffer devices
|
||||
Added support for Telnet console, removed VT support
|
||||
Added help <command>
|
||||
Added VMS file optimizations (from Robert Alan Byer)
|
||||
Added VMS file optimizations (Robert Alan Byer)
|
||||
Added quiet mode, DO with parameters, GUI interface,
|
||||
extensible commands (from Brian Knittel)
|
||||
extensible commands (Brian Knittel)
|
||||
Added device enable/disable commands
|
||||
14-Jul-02 RMS Fixed exit bug in do, added -v switch (from Brian Knittel)
|
||||
14-Jul-02 RMS Fixed exit bug in do, added -v switch (Brian Knittel)
|
||||
17-May-02 RMS Fixed bug in fxread/fxwrite error usage (found by
|
||||
Norm Lastovic)
|
||||
02-May-02 RMS Added VT emulation interface, changed {NO}LOG to SET {NO}LOG
|
||||
22-Apr-02 RMS Fixed laptop sleep problem in clock calibration, added
|
||||
magtape record length error (found by Jonathan Engdahl)
|
||||
magtape record length error (Jonathan Engdahl)
|
||||
26-Feb-02 RMS Fixed initialization bugs in do_cmd, get_aval
|
||||
(found by Brian Knittel)
|
||||
(Brian Knittel)
|
||||
10-Feb-02 RMS Fixed problem in clock calibration
|
||||
06-Jan-02 RMS Moved device enable/disable to simulators
|
||||
30-Dec-01 RMS Generalized timer packaged, added circular arrays
|
||||
19-Dec-01 RMS Fixed DO command bug (found by John Dundas)
|
||||
19-Dec-01 RMS Fixed DO command bug (John Dundas)
|
||||
07-Dec-01 RMS Implemented breakpoint package
|
||||
05-Dec-01 RMS Fixed bug in universal register logic
|
||||
03-Dec-01 RMS Added read-only units, extended SET/SHOW, universal registers
|
||||
|
@ -144,7 +149,7 @@
|
|||
Added special modifier print
|
||||
31-Aug-01 RMS Changed int64 to t_int64 for Windoze (V2.7)
|
||||
18-Jul-01 RMS Minor changes for Macintosh port
|
||||
12-Jun-01 RMS Fixed bug in big-endian I/O (found by Dave Conroy)
|
||||
12-Jun-01 RMS Fixed bug in big-endian I/O (Dave Conroy)
|
||||
27-May-01 RMS Added multiple console support
|
||||
16-May-01 RMS Added logging
|
||||
15-May-01 RMS Added features from Tim Litt
|
||||
|
@ -183,6 +188,11 @@
|
|||
#include <signal.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#if defined(HAVE_READLINE)
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
#endif
|
||||
|
||||
#define EX_D 0 /* deposit */
|
||||
#define EX_E 1 /* examine */
|
||||
#define EX_I 2 /* interactive */
|
||||
|
@ -279,11 +289,13 @@ t_stat show_config (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
|
|||
t_stat show_queue (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
|
||||
t_stat show_time (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
|
||||
t_stat show_mod_names (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
|
||||
t_stat show_show_commands (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
|
||||
t_stat show_log_names (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
|
||||
t_stat show_dev_radix (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
|
||||
t_stat show_dev_debug (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
|
||||
t_stat show_dev_logicals (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
|
||||
t_stat show_dev_modifiers (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
|
||||
t_stat show_dev_show_commands (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
|
||||
t_stat show_version (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
|
||||
t_stat show_break (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr);
|
||||
t_stat show_device (FILE *st, DEVICE *dptr, int32 flag);
|
||||
|
@ -322,6 +334,7 @@ void fprint_help (FILE *st);
|
|||
void fprint_stopped (FILE *st, t_stat r);
|
||||
void fprint_capac (FILE *st, DEVICE *dptr, UNIT *uptr);
|
||||
char *read_line (char *ptr, int32 size, FILE *stream);
|
||||
char *read_line_p (char *prompt, char *ptr, int32 size, FILE *stream);
|
||||
REG *find_reg_glob (char *ptr, char **optr, DEVICE **gdptr);
|
||||
char *sim_trim_endspc (char *cptr);
|
||||
|
||||
|
@ -393,7 +406,7 @@ static const char *sim_sa64 = "64b addresses";
|
|||
#else
|
||||
static const char *sim_sa64 = "32b addresses";
|
||||
#endif
|
||||
#if defined USE_NETWORK
|
||||
#if defined (USE_NETWORK) || defined (USE_SHARED)
|
||||
static const char *sim_snet = "Ethernet support";
|
||||
#else
|
||||
static const char *sim_snet = "no Ethernet";
|
||||
|
@ -539,17 +552,18 @@ static CTAB cmd_table[] = {
|
|||
"set <dev> DISABLED disable device\n"
|
||||
"set <dev> DEBUG{=arg} set device debug flags\n"
|
||||
"set <dev> NODEBUG={arg} clear device debug flags\n"
|
||||
"set <dev> arg{,arg...} set device parameters\n"
|
||||
"set <dev> arg{,arg...} set device parameters (see show modifiers)\n"
|
||||
"set <unit> ENABLED enable unit\n"
|
||||
"set <unit> DISABLED disable unit\n"
|
||||
"set <unit> arg{,arg...} set unit parameters\n"
|
||||
"set <unit> arg{,arg...} set unit parameters (see show modifiers)\n"
|
||||
},
|
||||
{ "SHOW", &show_cmd, 0,
|
||||
"sh{ow} br{eak} <list> show breakpoints\n"
|
||||
"sh{ow} con{figuration} show configuration\n"
|
||||
"sh{ow} cons{ole} {arg} show console options\n"
|
||||
"sh{ow} dev{ices} show devices\n"
|
||||
"sh{ow} m{odifiers} show modifiers\n"
|
||||
"sh{ow} m{odifiers} show modifiers for all devices\n"
|
||||
"sh{ow} s{how} show SHOW commands for all devices\n"
|
||||
"sh{ow} n{ames} show logical names\n"
|
||||
"sh{ow} q{ueue} show event queue\n"
|
||||
"sh{ow} ti{me} show simulated time\n"
|
||||
|
@ -558,7 +572,8 @@ static CTAB cmd_table[] = {
|
|||
"sh{ow} <dev> RADIX show device display radix\n"
|
||||
"sh{ow} <dev> DEBUG show device debug flags\n"
|
||||
"sh{ow} <dev> MODIFIERS show device modifiers\n"
|
||||
"sh{ow} <dev} NAMES show device logical name\n"
|
||||
"sh{ow} <dev> NAMES show device logical name\n"
|
||||
"sh{ow} <dev> SHOW show device SHOW commands\n"
|
||||
"sh{ow} <dev> {arg,...} show device parameters\n"
|
||||
"sh{ow} <unit> {arg,...} show unit parameters\n" },
|
||||
{ "DO", &do_cmd, 1,
|
||||
|
@ -669,12 +684,13 @@ else if (*argv[0]) { /* sim name arg? */
|
|||
}
|
||||
|
||||
while (stat != SCPE_EXIT) { /* in case exit */
|
||||
printf ("sim> "); /* prompt */
|
||||
if (cptr = sim_brk_getact (cbuf, CBUFSIZE)) /* pending action? */
|
||||
printf ("%s\n", cptr); /* echo */
|
||||
else if (sim_vm_read != NULL) /* sim routine? */
|
||||
printf ("sim> %s\n", cptr); /* echo */
|
||||
else if (sim_vm_read != NULL) { /* sim routine? */
|
||||
printf ("sim> "); /* prompt */
|
||||
cptr = (*sim_vm_read) (cbuf, CBUFSIZE, stdin);
|
||||
else cptr = read_line (cbuf, CBUFSIZE, stdin); /* read command line */
|
||||
}
|
||||
else cptr = read_line_p ("sim> ", cbuf, CBUFSIZE, stdin);/* read with prmopt*/
|
||||
if (cptr == NULL) /* ignore EOF */
|
||||
continue;
|
||||
if (*cptr == 0) /* ignore blank */
|
||||
|
@ -863,7 +879,7 @@ for (nargs = 0; nargs < 10; ) { /* extract arguments */
|
|||
}
|
||||
} /* end for */
|
||||
|
||||
if (nargs <= 0) /* need at least 1 */
|
||||
if ((nargs <= 0) || (do_arg [0] == NULL)) /* need at least 1 */
|
||||
return SCPE_2FARG;
|
||||
if ((fpin = fopen (do_arg[0], "r")) == NULL) { /* file failed to open? */
|
||||
if (flag == 0) /* cmd line file? */
|
||||
|
@ -1304,6 +1320,7 @@ static SHTAB show_glob_tab[] = {
|
|||
{ "TIME", &show_time, 0 },
|
||||
{ "MODIFIERS", &show_mod_names, 0 },
|
||||
{ "NAMES", &show_log_names, 0 },
|
||||
{ "SHOW", &show_show_commands, 0 },
|
||||
{ "VERSION", &show_version, 1 },
|
||||
{ "CONSOLE", &sim_show_console, 0 },
|
||||
{ "BREAK", &show_break, 0 },
|
||||
|
@ -1319,6 +1336,7 @@ static SHTAB show_dev_tab[] = {
|
|||
{ "DEBUG", &show_dev_debug, 0 },
|
||||
{ "MODIFIERS", &show_dev_modifiers, 0 },
|
||||
{ "NAMES", &show_dev_logicals, 0 },
|
||||
{ "SHOW", &show_dev_show_commands, 0 },
|
||||
{ NULL, NULL, 0 }
|
||||
};
|
||||
|
||||
|
@ -1634,7 +1652,7 @@ return SCPE_OK;
|
|||
|
||||
t_stat show_dev_modifiers (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr)
|
||||
{
|
||||
int any, enb;
|
||||
int32 any, enb;
|
||||
MTAB *mptr;
|
||||
DEBTAB *dep;
|
||||
|
||||
|
@ -1660,11 +1678,12 @@ if (!enb && (dptr->flags & DEV_DISABLE)) {
|
|||
fprintf (st, ", ENABLED, DISABLED");
|
||||
else fprintf (st, "%s\tENABLED, DISABLED", sim_dname (dptr));
|
||||
}
|
||||
if (any) fprintf (st, "\n");
|
||||
if (any)
|
||||
fprintf (st, "\n");
|
||||
if ((dptr->flags & DEV_DEBUG) && dptr->debflags) {
|
||||
fprintf (st, "%s\tDEBUG=", sim_dname (dptr));
|
||||
for (dep = dptr->debflags; dep->name != NULL; dep++)
|
||||
fprintf (st, "%s%s", ((dep == dptr->debflags) ? "" : ","), dep->name);
|
||||
fprintf (st, "%s%s", ((dep == dptr->debflags) ? "" : ";"), dep->name);
|
||||
fprintf (st, "\n");
|
||||
}
|
||||
return SCPE_OK;
|
||||
|
@ -1707,6 +1726,40 @@ if (flag && !((mptr->mask & MTAB_XTD) && (mptr->mask & MTAB_NMO)))
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Show show commands */
|
||||
|
||||
t_stat show_show_commands (FILE *st, DEVICE *dnotused, UNIT *unotused, int32 flag, char *cptr)
|
||||
{
|
||||
int32 i;
|
||||
DEVICE *dptr;
|
||||
|
||||
if (cptr && (*cptr != 0)) /* now eol? */
|
||||
return SCPE_2MARG;
|
||||
for (i = 0; (dptr = sim_devices[i]) != NULL; i++)
|
||||
show_dev_show_commands (st, dptr, NULL, flag, cptr);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat show_dev_show_commands (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr)
|
||||
{
|
||||
int32 any, enb;
|
||||
MTAB *mptr;
|
||||
|
||||
any = enb = 0;
|
||||
if (dptr->modifiers) {
|
||||
for (mptr = dptr->modifiers; mptr->mask != 0; mptr++) {
|
||||
if ((!mptr->disp) || (!mptr->pstring))
|
||||
continue;
|
||||
if (any++)
|
||||
fprintf (st, ", %s", mptr->pstring);
|
||||
else fprintf (st, "SHOW %s\t%s", sim_dname (dptr), mptr->pstring);
|
||||
}
|
||||
}
|
||||
if (any)
|
||||
fprintf (st, "\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Breakpoint commands */
|
||||
|
||||
t_stat brk_cmd (int32 flg, char *cptr)
|
||||
|
@ -3265,6 +3318,7 @@ if ((reason = parse_sym (cptr, addr, uptr, sim_eval, sim_switches)) > 0) {
|
|||
sim_eval[0] = get_uint (cptr, rdx, mask, &reason);
|
||||
if (reason != SCPE_OK)
|
||||
return reason;
|
||||
reason = dfltinc;
|
||||
}
|
||||
count = (1 - reason + (dptr->aincr - 1)) / dptr->aincr;
|
||||
|
||||
|
@ -3356,9 +3410,42 @@ return SCPE_OK;
|
|||
|
||||
char *read_line (char *cptr, int32 size, FILE *stream)
|
||||
{
|
||||
return read_line_p (NULL, cptr, size, stream);
|
||||
}
|
||||
|
||||
/* read_line_p read line with prompt
|
||||
|
||||
Inputs:
|
||||
prompt = pointer to prompt string
|
||||
cptr = pointer to buffer
|
||||
size = maximum size
|
||||
stream = pointer to input stream
|
||||
Outputs:
|
||||
optr = pointer to first non-blank character
|
||||
NULL if EOF
|
||||
*/
|
||||
|
||||
char *read_line_p (char *prompt, char *cptr, int32 size, FILE *stream)
|
||||
{
|
||||
char *tptr;
|
||||
|
||||
#if defined(HAVE_READLINE)
|
||||
if (prompt) { /* interactive? */
|
||||
char *tmpc = readline (prompt); /* get cmd line */
|
||||
if (tmpc == NULL) /* bad result? */
|
||||
cptr = NULL;
|
||||
else {
|
||||
strncpy (cptr, tmpc, size); /* copy result */
|
||||
free (tmpc) ; /* free temp */
|
||||
}
|
||||
}
|
||||
else cptr = fgets (cptr, size, stream); /* get cmd line */
|
||||
#else
|
||||
if (prompt) /* interactive? */
|
||||
printf ("%s", prompt); /* display prompt */
|
||||
cptr = fgets (cptr, size, stream); /* get cmd line */
|
||||
#endif
|
||||
|
||||
if (cptr == NULL) {
|
||||
clearerr (stream); /* clear error */
|
||||
return NULL; /* ignore EOF */
|
||||
|
@ -3372,12 +3459,14 @@ for (tptr = cptr; tptr < (cptr + size); tptr++) { /* remove cr or nl */
|
|||
}
|
||||
while (isspace (*cptr)) /* trim leading spc */
|
||||
cptr++;
|
||||
if (*cptr == ';') *cptr = 0; /* ignore comment */
|
||||
if (*cptr == ';') /* ignore comment */
|
||||
*cptr = 0;
|
||||
|
||||
#if defined (HAVE_READLINE)
|
||||
if (prompt)
|
||||
add_history (cptr);
|
||||
|
||||
#endif
|
||||
|
||||
return cptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* sim_console.c: simulator console I/O library
|
||||
|
||||
Copyright (c) 1993-2008, Robert M Supnik
|
||||
Copyright (c) 1993-2011, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,7 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
20-Jan-11 MP Added support for BREAK key on Windows
|
||||
30-Sep-06 RMS Fixed non-printable characters in KSR mode
|
||||
22-Jun-06 RMS Implemented SET/SHOW PCHAR
|
||||
31-May-06 JDB Fixed bug if SET CONSOLE DEBUG with no argument
|
||||
|
@ -662,17 +663,42 @@ return SCPE_OK;
|
|||
|
||||
#elif defined (_WIN32)
|
||||
|
||||
#include <conio.h>
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include <windows.h>
|
||||
#define RAW_MODE 0
|
||||
static HANDLE std_input;
|
||||
static HANDLE std_output;
|
||||
static DWORD saved_mode;
|
||||
|
||||
static BOOL WINAPI
|
||||
ControlHandler(DWORD dwCtrlType)
|
||||
{
|
||||
DWORD Mode;
|
||||
extern void int_handler (int sig);
|
||||
|
||||
switch (dwCtrlType)
|
||||
{
|
||||
case CTRL_BREAK_EVENT: // Use CTRL-Break or CTRL-C to simulate
|
||||
case CTRL_C_EVENT: // SERVICE_CONTROL_STOP in debug mode
|
||||
int_handler(0);
|
||||
return TRUE;
|
||||
case CTRL_CLOSE_EVENT: // Window is Closing
|
||||
case CTRL_LOGOFF_EVENT: // User is logging off
|
||||
if (!GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &Mode))
|
||||
return TRUE; // Not our User, so ignore
|
||||
case CTRL_SHUTDOWN_EVENT: // System is shutting down
|
||||
int_handler(0);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
t_stat sim_ttinit (void)
|
||||
{
|
||||
SetConsoleCtrlHandler( ControlHandler, TRUE );
|
||||
std_input = GetStdHandle (STD_INPUT_HANDLE);
|
||||
std_output = GetStdHandle (STD_OUTPUT_HANDLE);
|
||||
if ((std_input == INVALID_HANDLE_VALUE) ||
|
||||
!GetConsoleMode (std_input, &saved_mode))
|
||||
return SCPE_TTYERR;
|
||||
|
@ -710,24 +736,49 @@ return SCPE_OK;
|
|||
|
||||
t_stat sim_os_poll_kbd (void)
|
||||
{
|
||||
int c;
|
||||
int c = -1;
|
||||
DWORD nkbevents, nkbevent;
|
||||
INPUT_RECORD rec;
|
||||
extern int32 sim_switches;
|
||||
|
||||
if (!_kbhit ())
|
||||
if (!GetNumberOfConsoleInputEvents(std_input, &nkbevents))
|
||||
return SCPE_TTYERR;
|
||||
while (c == -1) {
|
||||
if (0 == nkbevents)
|
||||
return SCPE_OK;
|
||||
c = _getch ();
|
||||
if (!ReadConsoleInput(std_input, &rec, 1, &nkbevent))
|
||||
return SCPE_TTYERR;
|
||||
if (0 == nkbevent)
|
||||
return SCPE_OK;
|
||||
--nkbevents;
|
||||
if (rec.EventType == KEY_EVENT) {
|
||||
if (rec.Event.KeyEvent.bKeyDown) {
|
||||
if (0 == rec.Event.KeyEvent.uChar.UnicodeChar) { /* Special Character/Keys? */
|
||||
if (rec.Event.KeyEvent.wVirtualKeyCode == VK_PAUSE) /* Pause/Break Key */
|
||||
c = sim_brk_char | SCPE_BREAK;
|
||||
else
|
||||
if (rec.Event.KeyEvent.wVirtualKeyCode == '2') /* ^@ */
|
||||
c = 0; /* return NUL */
|
||||
} else
|
||||
c = rec.Event.KeyEvent.uChar.AsciiChar;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((c & 0177) == sim_del_char)
|
||||
c = 0177;
|
||||
if ((c & 0177) == sim_int_char)
|
||||
return SCPE_STOP;
|
||||
if (sim_brk_char && ((c & 0177) == sim_brk_char))
|
||||
if ((sim_brk_char && ((c & 0177) == sim_brk_char)) || (c & SCPE_BREAK))
|
||||
return SCPE_BREAK;
|
||||
return c | SCPE_KFLAG;
|
||||
}
|
||||
|
||||
t_stat sim_os_putchar (int32 c)
|
||||
{
|
||||
DWORD unused;
|
||||
|
||||
if (c != 0177)
|
||||
_putch (c);
|
||||
WriteConsoleA(std_output, &c, 1, &unused, NULL);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
|
1180
sim_console_old.c
Normal file
1180
sim_console_old.c
Normal file
File diff suppressed because it is too large
Load diff
1476
sim_ether.c
1476
sim_ether.c
File diff suppressed because it is too large
Load diff
75
sim_ether.h
75
sim_ether.h
|
@ -28,6 +28,14 @@
|
|||
|
||||
Modification history:
|
||||
|
||||
09-Dec-10 MP Added support to determine if network address conflicts exist
|
||||
07-Dec-10 MP Reworked DECnet self detection to the more general approach
|
||||
of loopback self when any Physical Address is being set.
|
||||
04-Dec-10 MP Changed eth_write to do nonblocking writes when
|
||||
USE_READER_THREAD is defined.
|
||||
07-Feb-08 MP Added eth_show_dev to display ethernet state
|
||||
28-Jan-08 MP Added eth_set_async
|
||||
23-Jan-08 MP Added eth_packet_trace_ex and ethq_destroy
|
||||
30-Nov-05 DTH Added CRC length to packet and more field comments
|
||||
04-Feb-04 DTH Added debugging information
|
||||
14-Jan-04 MP Generalized BSD support issues
|
||||
|
@ -64,7 +72,7 @@
|
|||
#define USE_SETNONBLOCK 1
|
||||
#endif
|
||||
|
||||
#if defined(__sun__) && defined(__i386__)
|
||||
#if (((defined(__sun__) && defined(__i386__)) || defined(__linux)) && !defined(DONT_USE_READER_THREAD))
|
||||
#define USE_READER_THREAD 1
|
||||
#endif
|
||||
|
||||
|
@ -108,13 +116,20 @@
|
|||
#define ETH_DEV_DESC_MAX 256 /* maximum device description size */
|
||||
#define ETH_MIN_PACKET 60 /* minimum ethernet packet size */
|
||||
#define ETH_MAX_PACKET 1514 /* maximum ethernet packet size */
|
||||
#define ETH_MAX_JUMBO_FRAME 16384 /* maximum ethernet jumbo frame size */
|
||||
#define ETH_MAX_DEVICE 10 /* maximum ethernet devices */
|
||||
#define ETH_CRC_SIZE 4 /* ethernet CRC size */
|
||||
#define ETH_FRAME_SIZE 1518 /* ethernet maximum frame size */
|
||||
#define ETH_FRAME_SIZE (ETH_MAX_PACKET+ETH_CRC_SIZE) /* ethernet maximum frame size */
|
||||
#define ETH_MIN_JUMBO_FRAME ETH_MAX_PACKET /* Threshold size for Jumbo Frame Processing */
|
||||
|
||||
#define DECNET_SELF_FRAME(dnet_mac, msg) \
|
||||
((memcmp(dnet_mac, msg , 6) == 0) && \
|
||||
(memcmp(dnet_mac, msg+6, 6) == 0))
|
||||
#define LOOPBACK_SELF_FRAME(phy_mac, msg) \
|
||||
((memcmp(phy_mac, msg , 6) == 0) && \
|
||||
(memcmp(phy_mac, msg+6, 6) == 0) && \
|
||||
((msg)[12] == 0x90) && ((msg)[13] == 0x00) && \
|
||||
((msg)[14] == 0x00) && ((msg)[15] == 0x00) && \
|
||||
((msg)[16] == 0x02) && ((msg)[17] == 0x00) && \
|
||||
(memcmp(phy_mac, msg+18, 6) == 0) && \
|
||||
((msg)[24] == 0x01) && ((msg)[25] == 0x00))
|
||||
|
||||
struct eth_packet {
|
||||
uint8 msg[ETH_FRAME_SIZE]; /* ethernet frame (message) */
|
||||
|
@ -147,6 +162,7 @@ struct eth_list {
|
|||
|
||||
typedef int ETH_BOOL;
|
||||
typedef unsigned char ETH_MAC[6];
|
||||
typedef unsigned char ETH_MULTIHASH[8];
|
||||
typedef struct eth_packet ETH_PACK;
|
||||
typedef void (*ETH_PCALLBACK)(int status);
|
||||
typedef struct eth_list ETH_LIST;
|
||||
|
@ -156,24 +172,45 @@ typedef struct eth_item ETH_ITEM;
|
|||
struct eth_device {
|
||||
char* name; /* name of ethernet device */
|
||||
void* handle; /* handle of implementation-specific device */
|
||||
int fd_handle; /* fd to kernel device (where needed) */
|
||||
int pcap_mode; /* Flag indicating if pcap API are being used to move packets */
|
||||
ETH_PCALLBACK read_callback; /* read callback function */
|
||||
ETH_PCALLBACK write_callback; /* write callback function */
|
||||
ETH_PACK* read_packet; /* read packet */
|
||||
ETH_PACK* write_packet; /* write packet */
|
||||
ETH_MAC filter_address[ETH_FILTER_MAX]; /* filtering addresses */
|
||||
int addr_count; /* count of filtering addresses */
|
||||
ETH_BOOL promiscuous; /* promiscuous mode flag */
|
||||
ETH_BOOL all_multicast; /* receive all multicast messages */
|
||||
int32 decnet_self_sent; /* loopback packets sent but not seen */
|
||||
ETH_MAC decnet_addr; /* decnet address of interface */
|
||||
ETH_BOOL hash_filter; /* filter using AUTODIN II multicast hash */
|
||||
ETH_MULTIHASH hash; /* AUTODIN II multicast hash */
|
||||
int32 loopback_self_sent; /* loopback packets sent but not seen */
|
||||
int32 loopback_self_sent_total; /* total loopback packets sent */
|
||||
int32 loopback_self_rcvd_total; /* total loopback packets seen */
|
||||
ETH_MAC physical_addr; /* physical address of interface */
|
||||
int32 have_host_nic_phy_addr; /* flag indicating that the host_nic_phy_hw_addr is valid */
|
||||
ETH_MAC host_nic_phy_hw_addr; /* MAC address of the attached NIC */
|
||||
uint32 jumbo_fragmented; /* Giant IPv4 Frames Fragmented */
|
||||
uint32 jumbo_dropped; /* Giant Frames Dropped */
|
||||
DEVICE* dptr; /* device ethernet is attached to */
|
||||
uint32 dbit; /* debugging bit */
|
||||
int reflections; /* packet reflections on interface */
|
||||
int need_crc; /* device needs CRC (Cyclic Redundancy Check) */
|
||||
#if defined (USE_READER_THREAD)
|
||||
int asynch_io; /* Asynchronous Interrupt scheduling enabled */
|
||||
int asynch_io_latency; /* instructions to delay pending interrupt */
|
||||
ETH_QUE read_queue;
|
||||
pthread_mutex_t lock;
|
||||
pthread_t reader_thread; /* Reader Thread Id */
|
||||
pthread_t writer_thread; /* Writer Thread Id */
|
||||
pthread_mutex_t writer_lock;
|
||||
pthread_cond_t writer_cond;
|
||||
struct write_request {
|
||||
struct write_request *next;
|
||||
ETH_PACK packet;
|
||||
} *write_requests;
|
||||
int write_queue_peak;
|
||||
struct write_request *write_buffers;
|
||||
t_stat write_status;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -186,18 +223,30 @@ t_stat eth_open (ETH_DEV* dev, char* name, /* open ethernet interfa
|
|||
t_stat eth_close (ETH_DEV* dev); /* close ethernet interface */
|
||||
t_stat eth_write (ETH_DEV* dev, ETH_PACK* packet, /* write sychronous packet; */
|
||||
ETH_PCALLBACK routine); /* callback when done */
|
||||
t_stat eth_read (ETH_DEV* dev, ETH_PACK* packet, /* read single packet; */
|
||||
int eth_read (ETH_DEV* dev, ETH_PACK* packet, /* read single packet; */
|
||||
ETH_PCALLBACK routine); /* callback when done*/
|
||||
t_stat eth_filter (ETH_DEV* dev, int addr_count, /* set filter on incoming packets */
|
||||
ETH_MAC* addresses,
|
||||
ETH_MAC* const addresses,
|
||||
ETH_BOOL all_multicast,
|
||||
ETH_BOOL promiscuous);
|
||||
t_stat eth_filter_hash (ETH_DEV* dev, int addr_count, /* set filter on incoming packets with AUTODIN II based hash */
|
||||
ETH_MAC* const addresses,
|
||||
ETH_BOOL all_multicast,
|
||||
ETH_BOOL promiscuous,
|
||||
ETH_MULTIHASH* const hash);
|
||||
t_stat eth_check_address_conflict (ETH_DEV* dev,
|
||||
ETH_MAC* const address);
|
||||
int eth_devices (int max, ETH_LIST* dev); /* get ethernet devices on host */
|
||||
void eth_setcrc (ETH_DEV* dev, int need_crc); /* enable/disable CRC mode */
|
||||
t_stat eth_set_async (ETH_DEV* dev, int latency); /* set read behavior to be async */
|
||||
t_stat eth_clr_async (ETH_DEV* dev); /* set read behavior to be not async */
|
||||
uint32 eth_crc32(uint32 crc, const void* vbuf, size_t len); /* Compute Ethernet Autodin II CRC for buffer */
|
||||
|
||||
void eth_packet_trace (ETH_DEV* dev, const uint8 *msg, int len, char* txt); /* trace ethernet packet */
|
||||
void eth_packet_trace (ETH_DEV* dev, const uint8 *msg, int len, char* txt); /* trace ethernet packet header+crc */
|
||||
void eth_packet_trace_ex (ETH_DEV* dev, const uint8 *msg, int len, char* txt, int detail, uint32 reason); /* trace ethernet packet */
|
||||
t_stat eth_show (FILE* st, UNIT* uptr, /* show ethernet devices */
|
||||
int32 val, void* desc);
|
||||
void eth_show_dev (FILE*st, ETH_DEV* dev); /* show ethernet device state */
|
||||
|
||||
void eth_mac_fmt (ETH_MAC* add, char* buffer); /* format ethernet mac address */
|
||||
t_stat eth_mac_scan (ETH_MAC* mac, char* strmac); /* scan string for mac, put in mac */
|
||||
|
@ -207,6 +256,10 @@ void ethq_clear (ETH_QUE* que); /* clear FIFO queue */
|
|||
void ethq_remove (ETH_QUE* que); /* remove item from FIFO queue */
|
||||
void ethq_insert (ETH_QUE* que, int32 type, /* insert item into FIFO queue */
|
||||
ETH_PACK* packet, int32 status);
|
||||
void ethq_insert_data(ETH_QUE* que, int32 type, /* insert item into FIFO queue */
|
||||
const uint8 *data, int used, int len,
|
||||
int crc_len, const uint8 *crc_data, int32 status);
|
||||
t_stat ethq_destroy(ETH_QUE* que); /* release FIFO queue */
|
||||
|
||||
|
||||
#endif /* _SIM_ETHER_H */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* sim_sock.c: OS-dependent socket routines
|
||||
|
||||
Copyright (c) 2001-2008, Robert M Supnik
|
||||
Copyright (c) 2001-2010, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,7 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
22-Jun-10 RMS Fixed types in sim_accept_conn (from Mark Pizzolato)
|
||||
19-Nov-05 RMS Added conditional for OpenBSD (from Federico G. Schwindt)
|
||||
16-Aug-05 RMS Fixed spurious SIGPIPE signal error in Unix
|
||||
14-Apr-05 RMS Added WSAEINPROGRESS test (from Tim Riker)
|
||||
|
@ -195,7 +196,8 @@ SOCKET sim_accept_conn (SOCKET master, uint32 *ipaddr)
|
|||
{
|
||||
int32 sta, err;
|
||||
#if defined (macintosh) || defined (__linux) || \
|
||||
defined (__APPLE__) || defined (__OpenBSD__)
|
||||
defined (__APPLE__) || defined (__OpenBSD__) || \
|
||||
defined(__NetBSD__) || defined(__FreeBSD__)
|
||||
socklen_t size;
|
||||
#elif defined (_WIN32) || defined (__EMX__) || \
|
||||
(defined (__ALPHA) && defined (__unix__))
|
||||
|
@ -216,7 +218,8 @@ if (newsock == INVALID_SOCKET) { /* error? */
|
|||
printf ("Sockets: accept error %d\n", err);
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
if (ipaddr != NULL) *ipaddr = ntohl (clientname.sin_addr.s_addr);
|
||||
if (ipaddr != NULL)
|
||||
*ipaddr = ntohl (clientname.sin_addr.s_addr);
|
||||
|
||||
sta = sim_setnonblock (newsock); /* set nonblocking */
|
||||
if (sta == SOCKET_ERROR) /* fcntl error? */
|
||||
|
|
22
sim_timer.c
22
sim_timer.c
|
@ -1,6 +1,6 @@
|
|||
/* sim_timer.c: simulator timer library
|
||||
|
||||
Copyright (c) 1993-2008, Robert M Supnik
|
||||
Copyright (c) 1993-2010, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,7 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
29-Dec-10 MP Fixed clock resolution determination for Unix platforms
|
||||
22-Sep-08 RMS Added "stability threshold" for idle routine
|
||||
27-May-08 RMS Fixed bug in Linux idle routines (from Walter Mueller)
|
||||
18-Jun-07 RMS Modified idle to exclude counted delays
|
||||
|
@ -298,19 +299,6 @@ return;
|
|||
|
||||
uint32 sim_os_ms_sleep_init (void)
|
||||
{
|
||||
#if defined (_POSIX_SOURCE) /* POSIX-compliant */
|
||||
|
||||
struct timespec treq;
|
||||
uint32 msec;
|
||||
|
||||
if (clock_getres (CLOCK_REALTIME, &treq) != 0)
|
||||
return 0;
|
||||
msec = (treq.tv_nsec + (NANOS_PER_MILLI - 1)) / NANOS_PER_MILLI;
|
||||
if (msec > SIM_IDLE_MAX) return 0;
|
||||
return msec;
|
||||
|
||||
#else /* others */
|
||||
|
||||
uint32 i, t1, t2, tot, tim;
|
||||
|
||||
for (i = 0, tot = 0; i < sleep1Samples; i++) {
|
||||
|
@ -320,13 +308,9 @@ for (i = 0, tot = 0; i < sleep1Samples; i++) {
|
|||
tot += (t2 - t1);
|
||||
}
|
||||
tim = (tot + (sleep1Samples - 1)) / sleep1Samples;
|
||||
if (tim == 0)
|
||||
tim = 1;
|
||||
else if (tim > SIM_IDLE_MAX)
|
||||
if (tim > SIM_IDLE_MAX)
|
||||
tim = 0;
|
||||
return tim;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32 sim_os_ms_sleep (unsigned int milliseconds)
|
||||
|
|
64
sim_tmxr.c
64
sim_tmxr.c
|
@ -1,6 +1,6 @@
|
|||
/* sim_tmxr.c: Telnet terminal multiplexor library
|
||||
|
||||
Copyright (c) 2001-2008, Robert M Supnik
|
||||
Copyright (c) 2001-2011, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -26,6 +26,7 @@
|
|||
Based on the original DZ11 simulator by Thord Nilson, as updated by
|
||||
Arthur Krewat.
|
||||
|
||||
16-Jan-11 MP Made option negotiation more reliable
|
||||
20-Nov-08 RMS Added three new standardized SHOW routines
|
||||
30-Sep-08 JDB Reverted tmxr_find_ldsc to original implementation
|
||||
27-May-08 JDB Added line connection order to tmxr_poll_conn,
|
||||
|
@ -86,12 +87,26 @@
|
|||
|
||||
/* Telnet protocol constants - negatives are for init'ing signed char data */
|
||||
|
||||
/* Commands */
|
||||
#define TN_IAC -1 /* protocol delim */
|
||||
#define TN_DONT -2 /* dont */
|
||||
#define TN_DO -3 /* do */
|
||||
#define TN_WONT -4 /* wont */
|
||||
#define TN_WILL -5 /* will */
|
||||
#define TN_SB -6 /* sub-option negotiation */
|
||||
#define TN_GA -7 /* go ahead */
|
||||
#define TN_EL -8 /* erase line */
|
||||
#define TN_EC -9 /* erase character */
|
||||
#define TN_AYT -10 /* are you there */
|
||||
#define TN_AO -11 /* abort output */
|
||||
#define TN_IP -12 /* interrupt process */
|
||||
#define TN_BRK -13 /* break */
|
||||
#define TN_DATAMK -14 /* data mark */
|
||||
#define TN_NOP -15 /* no operation */
|
||||
#define TN_SE -16 /* end sub-option negot */
|
||||
|
||||
/* Options */
|
||||
|
||||
#define TN_BIN 0 /* bin */
|
||||
#define TN_ECHO 1 /* echo */
|
||||
#define TN_SGA 3 /* sga */
|
||||
|
@ -108,6 +123,8 @@
|
|||
#define TNS_WONT 003 /* WONT seen */
|
||||
#define TNS_SKIP 004 /* skip next cmd */
|
||||
#define TNS_CRPAD 005 /* CR padding */
|
||||
#define TNS_DO 006 /* DO request pending rejection */
|
||||
|
||||
|
||||
void tmxr_rmvrc (TMLN *lp, int32 p);
|
||||
int32 tmxr_send_buffered_data (TMLN *lp);
|
||||
|
@ -139,6 +156,7 @@ TMLN *lp;
|
|||
int32 *op;
|
||||
int32 i, j;
|
||||
uint32 ipaddr;
|
||||
|
||||
static char mantra[] = {
|
||||
TN_IAC, TN_WILL, TN_LINE,
|
||||
TN_IAC, TN_WILL, TN_SGA,
|
||||
|
@ -178,7 +196,7 @@ if (newsock != INVALID_SOCKET) { /* got a live one? */
|
|||
lp->tsta = 0; /* init telnet state */
|
||||
lp->xmte = 1; /* enable transmit */
|
||||
lp->dstb = 0; /* default bin mode */
|
||||
sim_write_sock (newsock, mantra, 15);
|
||||
sim_write_sock (newsock, mantra, sizeof (mantra));
|
||||
tmxr_linemsg (lp, "\n\r\nConnected to the ");
|
||||
tmxr_linemsg (lp, sim_name);
|
||||
tmxr_linemsg (lp, " simulator ");
|
||||
|
@ -301,7 +319,7 @@ for (i = 0; i < mp->lines; i++) { /* loop thru lines */
|
|||
break;
|
||||
|
||||
case TNS_IAC: /* IAC prev */
|
||||
if ((tmp == TN_IAC) & !lp->dstb) { /* IAC + IAC, bin? */
|
||||
if (tmp == TN_IAC) { /* IAC + IAC */
|
||||
lp->tsta = TNS_NORM; /* treat as normal */
|
||||
j = j + 1; /* advance j */
|
||||
break; /* keep IAC */
|
||||
|
@ -313,11 +331,31 @@ for (i = 0; i < mp->lines; i++) { /* loop thru lines */
|
|||
j = j + 1; /* advance j */
|
||||
break;
|
||||
}
|
||||
if (tmp == TN_WILL) /* IAC + WILL? */
|
||||
switch (tmp) {
|
||||
case TN_WILL: /* IAC + WILL? */
|
||||
lp->tsta = TNS_WILL;
|
||||
else if (tmp == TN_WONT) /* IAC + WONT? */
|
||||
break;
|
||||
case TN_WONT: /* IAC + WONT? */
|
||||
lp->tsta = TNS_WONT;
|
||||
else lp->tsta = TNS_SKIP; /* IAC + other */
|
||||
break;
|
||||
case TN_DO: /* IAC + DO? */
|
||||
lp->tsta = TNS_DO;
|
||||
break;
|
||||
case TN_DONT: /* IAC + DONT? */
|
||||
lp->tsta = TNS_SKIP; /* IAC + other */
|
||||
break;
|
||||
case TN_GA: case TN_EL: /* IAC + other 2 byte types */
|
||||
case TN_EC: case TN_AYT:
|
||||
case TN_AO: case TN_IP:
|
||||
case TN_NOP:
|
||||
lp->tsta = TNS_NORM; /* ignore */
|
||||
break;
|
||||
case TN_SB: /* IAC + SB sub-opt negotiation */
|
||||
case TN_DATAMK: /* IAC + data mark */
|
||||
case TN_SE: /* IAC + SE sub-opt end */
|
||||
lp->tsta = TNS_NORM; /* ignore */
|
||||
break;
|
||||
}
|
||||
tmxr_rmvrc (lp, j); /* remove char */
|
||||
break;
|
||||
|
||||
|
@ -327,6 +365,9 @@ for (i = 0; i < mp->lines; i++) { /* loop thru lines */
|
|||
lp->dstb = 0;
|
||||
else lp->dstb = 1;
|
||||
}
|
||||
tmxr_rmvrc (lp, j); /* remove it */
|
||||
lp->tsta = TNS_NORM; /* next normal */
|
||||
break;
|
||||
|
||||
/* Negotiation with the HP terminal emulator "QCTerm" is not working.
|
||||
QCTerm says "WONT BIN" but sends bare CRs. RFC 854 says:
|
||||
|
@ -349,9 +390,18 @@ for (i = 0; i < mp->lines; i++) { /* loop thru lines */
|
|||
tmxr_rmvrc (lp, j); /* remove it */
|
||||
break;
|
||||
|
||||
case TNS_SKIP: default: /* skip char */
|
||||
case TNS_DO: /* pending DO request */
|
||||
if (tmp == TN_BIN) { /* reject all but binary mode */
|
||||
char accept[] = {TN_IAC, TN_WILL, TN_BIN};
|
||||
sim_write_sock (lp->conn, accept, sizeof(accept));
|
||||
}
|
||||
tmxr_rmvrc (lp, j); /* remove it */
|
||||
lp->tsta = TNS_NORM; /* next normal */
|
||||
break;
|
||||
|
||||
case TNS_SKIP: default: /* skip char */
|
||||
tmxr_rmvrc (lp, j); /* remove char */
|
||||
lp->tsta = TNS_NORM; /* next normal */
|
||||
break;
|
||||
} /* end case state */
|
||||
} /* end for char */
|
||||
|
|
998
sim_tmxr_old.c
Normal file
998
sim_tmxr_old.c
Normal file
|
@ -0,0 +1,998 @@
|
|||
/* sim_tmxr.c: Telnet terminal multiplexor library
|
||||
|
||||
Copyright (c) 2001-2008, 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.
|
||||
|
||||
Based on the original DZ11 simulator by Thord Nilson, as updated by
|
||||
Arthur Krewat.
|
||||
|
||||
20-Nov-08 RMS Added three new standardized SHOW routines
|
||||
30-Sep-08 JDB Reverted tmxr_find_ldsc to original implementation
|
||||
27-May-08 JDB Added line connection order to tmxr_poll_conn,
|
||||
added tmxr_set_lnorder and tmxr_show_lnorder
|
||||
14-May-08 JDB Print device and line to which connection was made
|
||||
11-Apr-07 JDB Worked around Telnet negotiation problem with QCTerm
|
||||
16-Aug-05 RMS Fixed C++ declaration and cast problems
|
||||
29-Jun-05 RMS Extended tmxr_dscln to support unit array devices
|
||||
Fixed bug in SET LOG/NOLOG
|
||||
04-Jan-04 RMS Changed TMXR ldsc to be pointer to linedesc array
|
||||
Added tmxr_linemsg, circular output pointers, logging
|
||||
(from Mark Pizzolato)
|
||||
29-Dec-03 RMS Added output stall support
|
||||
01-Nov-03 RMS Cleaned up attach routine
|
||||
09-Mar-03 RMS Fixed bug in SHOW CONN
|
||||
22-Dec-02 RMS Fixed bugs in IAC+IAC receive and transmit sequences
|
||||
Added support for received break (all from by Mark Pizzolato)
|
||||
Fixed bug in attach
|
||||
31-Oct-02 RMS Fixed bug in 8b (binary) support
|
||||
22-Aug-02 RMS Added tmxr_open_master, tmxr_close_master
|
||||
30-Dec-01 RMS Added tmxr_fstats, tmxr_dscln, renamed tmxr_fstatus
|
||||
03-Dec-01 RMS Changed tmxr_fconns for extended SET/SHOW
|
||||
20-Oct-01 RMS Fixed bugs in read logic (found by Thord Nilson).
|
||||
Added tmxr_rqln, tmxr_tqln
|
||||
|
||||
This library includes:
|
||||
|
||||
tmxr_poll_conn - poll for connection
|
||||
tmxr_reset_ln - reset line
|
||||
tmxr_getc_ln - get character for line
|
||||
tmxr_poll_rx - poll receive
|
||||
tmxr_putc_ln - put character for line
|
||||
tmxr_poll_tx - poll transmit
|
||||
tmxr_open_master - open master connection
|
||||
tmxr_close_master - close master connection
|
||||
tmxr_attach - attach terminal multiplexor
|
||||
tmxr_detach - detach terminal multiplexor
|
||||
tmxr_ex - (null) examine
|
||||
tmxr_dep - (null) deposit
|
||||
tmxr_msg - send message to socket
|
||||
tmxr_linemsg - send message to line
|
||||
tmxr_fconns - output connection status
|
||||
tmxr_fstats - output connection statistics
|
||||
tmxr_dscln - disconnect line (SET routine)
|
||||
tmxr_rqln - number of available characters for line
|
||||
tmxr_tqln - number of buffered characters for line
|
||||
tmxr_set_lnorder - set line connection order
|
||||
tmxr_show_lnorder - show line connection order
|
||||
|
||||
All routines are OS-independent.
|
||||
*/
|
||||
|
||||
#include "sim_defs.h"
|
||||
#include "sim_sock.h"
|
||||
#include "sim_tmxr.h"
|
||||
#include "scp.h"
|
||||
#include <ctype.h>
|
||||
|
||||
/* Telnet protocol constants - negatives are for init'ing signed char data */
|
||||
|
||||
#define TN_IAC -1 /* protocol delim */
|
||||
#define TN_DONT -2 /* dont */
|
||||
#define TN_DO -3 /* do */
|
||||
#define TN_WONT -4 /* wont */
|
||||
#define TN_WILL -5 /* will */
|
||||
#define TN_BRK -13 /* break */
|
||||
#define TN_BIN 0 /* bin */
|
||||
#define TN_ECHO 1 /* echo */
|
||||
#define TN_SGA 3 /* sga */
|
||||
#define TN_LINE 34 /* line mode */
|
||||
#define TN_CR 015 /* carriage return */
|
||||
#define TN_LF 012 /* line feed */
|
||||
#define TN_NUL 000 /* null */
|
||||
|
||||
/* Telnet line states */
|
||||
|
||||
#define TNS_NORM 000 /* normal */
|
||||
#define TNS_IAC 001 /* IAC seen */
|
||||
#define TNS_WILL 002 /* WILL seen */
|
||||
#define TNS_WONT 003 /* WONT seen */
|
||||
#define TNS_SKIP 004 /* skip next cmd */
|
||||
#define TNS_CRPAD 005 /* CR padding */
|
||||
|
||||
void tmxr_rmvrc (TMLN *lp, int32 p);
|
||||
int32 tmxr_send_buffered_data (TMLN *lp);
|
||||
TMLN *tmxr_find_ldsc (UNIT *uptr, int32 val, TMXR *mp);
|
||||
|
||||
extern int32 sim_switches;
|
||||
extern char sim_name[];
|
||||
extern FILE *sim_log;
|
||||
extern uint32 sim_os_msec (void);
|
||||
|
||||
/* Poll for new connection
|
||||
|
||||
Called from unit service routine to test for new connection
|
||||
|
||||
Inputs:
|
||||
*mp = pointer to terminal multiplexor descriptor
|
||||
Outputs:
|
||||
line number activated, -1 if none
|
||||
|
||||
If a connection order is defined for the descriptor, and the first value is
|
||||
not -1 (indicating default order), then the order array is used to find an
|
||||
open line. Otherwise, a search is made of all lines in numerical sequence.
|
||||
*/
|
||||
|
||||
int32 tmxr_poll_conn (TMXR *mp)
|
||||
{
|
||||
SOCKET newsock;
|
||||
TMLN *lp;
|
||||
int32 *op;
|
||||
int32 i, j;
|
||||
uint32 ipaddr;
|
||||
static char mantra[] = {
|
||||
TN_IAC, TN_WILL, TN_LINE,
|
||||
TN_IAC, TN_WILL, TN_SGA,
|
||||
TN_IAC, TN_WILL, TN_ECHO,
|
||||
TN_IAC, TN_WILL, TN_BIN,
|
||||
TN_IAC, TN_DO, TN_BIN
|
||||
};
|
||||
|
||||
newsock = sim_accept_conn (mp->master, &ipaddr); /* poll connect */
|
||||
if (newsock != INVALID_SOCKET) { /* got a live one? */
|
||||
op = mp->lnorder; /* get line connection order list pointer */
|
||||
i = mp->lines; /* play it safe in case lines == 0 */
|
||||
|
||||
for (j = 0; j < mp->lines; j++, i++) { /* find next avail line */
|
||||
if (op && (*op >= 0) && (*op < mp->lines)) /* order list present and valid? */
|
||||
i = *op++; /* get next line in list to try */
|
||||
else /* no list or not used or range error */
|
||||
i = j; /* get next sequential line */
|
||||
|
||||
lp = mp->ldsc + i; /* get pointer to line descriptor */
|
||||
if (lp->conn == 0) /* is the line available? */
|
||||
break; /* yes, so stop search */
|
||||
}
|
||||
|
||||
if (i >= mp->lines) { /* all busy? */
|
||||
tmxr_msg (newsock, "All connections busy\r\n");
|
||||
sim_close_sock (newsock, 0);
|
||||
}
|
||||
else {
|
||||
lp = mp->ldsc + i; /* get line desc */
|
||||
lp->conn = newsock; /* record connection */
|
||||
lp->ipad = ipaddr; /* ip address */
|
||||
lp->cnms = sim_os_msec (); /* time of conn */
|
||||
lp->rxbpr = lp->rxbpi = 0; /* init buf pointers */
|
||||
lp->txbpr = lp->txbpi = 0;
|
||||
lp->rxcnt = lp->txcnt = 0; /* init counters */
|
||||
lp->tsta = 0; /* init telnet state */
|
||||
lp->xmte = 1; /* enable transmit */
|
||||
lp->dstb = 0; /* default bin mode */
|
||||
sim_write_sock (newsock, mantra, 15);
|
||||
tmxr_linemsg (lp, "\n\r\nConnected to the ");
|
||||
tmxr_linemsg (lp, sim_name);
|
||||
tmxr_linemsg (lp, " simulator ");
|
||||
|
||||
if (mp->dptr) { /* device defined? */
|
||||
tmxr_linemsg (lp, sim_dname (mp->dptr)); /* report device name */
|
||||
tmxr_linemsg (lp, " device");
|
||||
|
||||
if (mp->lines > 1) { /* more than one line? */
|
||||
char line[20];
|
||||
|
||||
tmxr_linemsg (lp, ", line "); /* report the line number */
|
||||
sprintf (line, "%i", i);
|
||||
tmxr_linemsg (lp, line);
|
||||
}
|
||||
}
|
||||
|
||||
tmxr_linemsg (lp, "\r\n\n");
|
||||
|
||||
tmxr_poll_tx (mp); /* flush output */
|
||||
return i;
|
||||
}
|
||||
} /* end if newsock */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Reset line */
|
||||
|
||||
void tmxr_reset_ln (TMLN *lp)
|
||||
{
|
||||
if (lp->txlog) /* dump log */
|
||||
fflush (lp->txlog);
|
||||
tmxr_send_buffered_data (lp); /* send buffered data */
|
||||
sim_close_sock (lp->conn, 0); /* reset conn */
|
||||
lp->conn = lp->tsta = 0; /* reset state */
|
||||
lp->rxbpr = lp->rxbpi = 0;
|
||||
lp->txbpr = lp->txbpi = 0;
|
||||
lp->xmte = 1;
|
||||
lp->dstb = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get character from specific line
|
||||
|
||||
Inputs:
|
||||
*lp = pointer to terminal line descriptor
|
||||
Output:
|
||||
valid + char, 0 if line
|
||||
*/
|
||||
|
||||
int32 tmxr_getc_ln (TMLN *lp)
|
||||
{
|
||||
int32 j, val = 0;
|
||||
uint32 tmp;
|
||||
|
||||
if (lp->conn && lp->rcve) { /* conn & enb? */
|
||||
j = lp->rxbpi - lp->rxbpr; /* # input chrs */
|
||||
if (j) { /* any? */
|
||||
tmp = lp->rxb[lp->rxbpr]; /* get char */
|
||||
val = TMXR_VALID | (tmp & 0377); /* valid + chr */
|
||||
if (lp->rbr[lp->rxbpr]) /* break? */
|
||||
val = val | SCPE_BREAK;
|
||||
lp->rxbpr = lp->rxbpr + 1; /* adv pointer */
|
||||
}
|
||||
} /* end if conn */
|
||||
if (lp->rxbpi == lp->rxbpr) /* empty? zero ptrs */
|
||||
lp->rxbpi = lp->rxbpr = 0;
|
||||
return val;
|
||||
}
|
||||
|
||||
/* Poll for input
|
||||
|
||||
Inputs:
|
||||
*mp = pointer to terminal multiplexor descriptor
|
||||
Outputs: none
|
||||
*/
|
||||
|
||||
void tmxr_poll_rx (TMXR *mp)
|
||||
{
|
||||
int32 i, nbytes, j;
|
||||
TMLN *lp;
|
||||
|
||||
for (i = 0; i < mp->lines; i++) { /* loop thru lines */
|
||||
lp = mp->ldsc + i; /* get line desc */
|
||||
if (!lp->conn || !lp->rcve) /* skip if !conn */
|
||||
continue;
|
||||
|
||||
nbytes = 0;
|
||||
if (lp->rxbpi == 0) /* need input? */
|
||||
nbytes = sim_read_sock (lp->conn, /* yes, read */
|
||||
&(lp->rxb[lp->rxbpi]), /* leave spc for */
|
||||
TMXR_MAXBUF - TMXR_GUARD); /* Telnet cruft */
|
||||
else if (lp->tsta) /* in Telnet seq? */
|
||||
nbytes = sim_read_sock (lp->conn, /* yes, read to end */
|
||||
&(lp->rxb[lp->rxbpi]),
|
||||
TMXR_MAXBUF - lp->rxbpi);
|
||||
if (nbytes < 0) /* closed? reset ln */
|
||||
tmxr_reset_ln (lp);
|
||||
else if (nbytes > 0) { /* if data rcvd */
|
||||
j = lp->rxbpi; /* start of data */
|
||||
memset (&lp->rbr[j], 0, nbytes); /* clear status */
|
||||
lp->rxbpi = lp->rxbpi + nbytes; /* adv pointers */
|
||||
lp->rxcnt = lp->rxcnt + nbytes;
|
||||
|
||||
/* Examine new data, remove TELNET cruft before making input available */
|
||||
|
||||
for (; j < lp->rxbpi; ) { /* loop thru char */
|
||||
signed char tmp = lp->rxb[j]; /* get char */
|
||||
switch (lp->tsta) { /* case tlnt state */
|
||||
|
||||
case TNS_NORM: /* normal */
|
||||
if (tmp == TN_IAC) { /* IAC? */
|
||||
lp->tsta = TNS_IAC; /* change state */
|
||||
tmxr_rmvrc (lp, j); /* remove char */
|
||||
break;
|
||||
}
|
||||
if ((tmp == TN_CR) && lp->dstb) /* CR, no bin */
|
||||
lp->tsta = TNS_CRPAD; /* skip pad char */
|
||||
j = j + 1; /* advance j */
|
||||
break;
|
||||
|
||||
case TNS_IAC: /* IAC prev */
|
||||
if ((tmp == TN_IAC) & !lp->dstb) { /* IAC + IAC, bin? */
|
||||
lp->tsta = TNS_NORM; /* treat as normal */
|
||||
j = j + 1; /* advance j */
|
||||
break; /* keep IAC */
|
||||
}
|
||||
if (tmp == TN_BRK) { /* IAC + BRK? */
|
||||
lp->tsta = TNS_NORM; /* treat as normal */
|
||||
lp->rxb[j] = 0; /* char is null */
|
||||
lp->rbr[j] = 1; /* flag break */
|
||||
j = j + 1; /* advance j */
|
||||
break;
|
||||
}
|
||||
if (tmp == TN_WILL) /* IAC + WILL? */
|
||||
lp->tsta = TNS_WILL;
|
||||
else if (tmp == TN_WONT) /* IAC + WONT? */
|
||||
lp->tsta = TNS_WONT;
|
||||
else lp->tsta = TNS_SKIP; /* IAC + other */
|
||||
tmxr_rmvrc (lp, j); /* remove char */
|
||||
break;
|
||||
|
||||
case TNS_WILL: case TNS_WONT: /* IAC+WILL/WONT prev */
|
||||
if (tmp == TN_BIN) { /* BIN? */
|
||||
if (lp->tsta == TNS_WILL)
|
||||
lp->dstb = 0;
|
||||
else lp->dstb = 1;
|
||||
}
|
||||
|
||||
/* Negotiation with the HP terminal emulator "QCTerm" is not working.
|
||||
QCTerm says "WONT BIN" but sends bare CRs. RFC 854 says:
|
||||
|
||||
Note that "CR LF" or "CR NUL" is required in both directions
|
||||
(in the default ASCII mode), to preserve the symmetry of the
|
||||
NVT model. ...The protocol requires that a NUL be inserted
|
||||
following a CR not followed by a LF in the data stream.
|
||||
|
||||
Until full negotiation is implemented, we work around the problem
|
||||
by checking the character following the CR in non-BIN mode and
|
||||
strip it only if it is LF or NUL. This should not affect
|
||||
conforming clients.
|
||||
*/
|
||||
|
||||
case TNS_CRPAD: /* only LF or NUL should follow CR */
|
||||
lp->tsta = TNS_NORM; /* next normal */
|
||||
if ((tmp == TN_LF) || /* CR + LF ? */
|
||||
(tmp == TN_NUL)) /* CR + NUL? */
|
||||
tmxr_rmvrc (lp, j); /* remove it */
|
||||
break;
|
||||
|
||||
case TNS_SKIP: default: /* skip char */
|
||||
lp->tsta = TNS_NORM; /* next normal */
|
||||
tmxr_rmvrc (lp, j); /* remove char */
|
||||
break;
|
||||
} /* end case state */
|
||||
} /* end for char */
|
||||
} /* end else nbytes */
|
||||
} /* end for lines */
|
||||
for (i = 0; i < mp->lines; i++) { /* loop thru lines */
|
||||
lp = mp->ldsc + i; /* get line desc */
|
||||
if (lp->rxbpi == lp->rxbpr) /* if buf empty, */
|
||||
lp->rxbpi = lp->rxbpr = 0; /* reset pointers */
|
||||
} /* end for */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Return count of available characters for line */
|
||||
|
||||
int32 tmxr_rqln (TMLN *lp)
|
||||
{
|
||||
return (lp->rxbpi - lp->rxbpr);
|
||||
}
|
||||
|
||||
/* Remove character p (and matching status) from line l input buffer */
|
||||
|
||||
void tmxr_rmvrc (TMLN *lp, int32 p)
|
||||
{
|
||||
for ( ; p < lp->rxbpi; p++) {
|
||||
lp->rxb[p] = lp->rxb[p + 1];
|
||||
lp->rbr[p] = lp->rbr[p + 1];
|
||||
}
|
||||
lp->rxbpi = lp->rxbpi - 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Store character in line buffer
|
||||
|
||||
Inputs:
|
||||
*lp = pointer to line descriptor
|
||||
chr = characters
|
||||
Outputs:
|
||||
status = ok, connection lost, or stall
|
||||
*/
|
||||
|
||||
t_stat tmxr_putc_ln (TMLN *lp, int32 chr)
|
||||
{
|
||||
if (lp->txlog) /* log if available */
|
||||
fputc (chr, lp->txlog);
|
||||
if (lp->conn == 0) /* no conn? lost */
|
||||
return SCPE_LOST;
|
||||
if (tmxr_tqln (lp) < (TMXR_MAXBUF - 1)) { /* room for char (+ IAC)? */
|
||||
lp->txb[lp->txbpi] = (char) chr; /* buffer char */
|
||||
lp->txbpi = lp->txbpi + 1; /* adv pointer */
|
||||
if (lp->txbpi >= TMXR_MAXBUF) /* wrap? */
|
||||
lp->txbpi = 0;
|
||||
if ((char) chr == TN_IAC) { /* IAC? */
|
||||
lp->txb[lp->txbpi] = (char) chr; /* IAC + IAC */
|
||||
lp->txbpi = lp->txbpi + 1; /* adv pointer */
|
||||
if (lp->txbpi >= TMXR_MAXBUF) /* wrap? */
|
||||
lp->txbpi = 0;
|
||||
}
|
||||
if (tmxr_tqln (lp) > (TMXR_MAXBUF - TMXR_GUARD)) /* near full? */
|
||||
lp->xmte = 0; /* disable line */
|
||||
return SCPE_OK; /* char sent */
|
||||
}
|
||||
lp->xmte = 0; /* no room, dsbl line */
|
||||
return SCPE_STALL; /* char not sent */
|
||||
}
|
||||
|
||||
/* Poll for output
|
||||
|
||||
Inputs:
|
||||
*mp = pointer to terminal multiplexor descriptor
|
||||
Outputs:
|
||||
none
|
||||
*/
|
||||
|
||||
void tmxr_poll_tx (TMXR *mp)
|
||||
{
|
||||
int32 i, nbytes;
|
||||
TMLN *lp;
|
||||
|
||||
for (i = 0; i < mp->lines; i++) { /* loop thru lines */
|
||||
lp = mp->ldsc + i; /* get line desc */
|
||||
if (lp->conn == 0) /* skip if !conn */
|
||||
continue;
|
||||
nbytes = tmxr_send_buffered_data (lp); /* buffered bytes */
|
||||
if (nbytes == 0) /* buf empty? enab line */
|
||||
lp->xmte = 1;
|
||||
} /* end for */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Send buffered data across network
|
||||
|
||||
Inputs:
|
||||
*lp = pointer to line descriptor
|
||||
Outputs:
|
||||
returns number of bytes still buffered
|
||||
*/
|
||||
|
||||
int32 tmxr_send_buffered_data (TMLN *lp)
|
||||
{
|
||||
int32 nbytes, sbytes;
|
||||
|
||||
nbytes = tmxr_tqln(lp); /* avail bytes */
|
||||
if (nbytes) { /* >0? write */
|
||||
if (lp->txbpr < lp->txbpi) /* no wrap? */
|
||||
sbytes = sim_write_sock (lp->conn, /* write all data */
|
||||
&(lp->txb[lp->txbpr]), nbytes);
|
||||
else sbytes = sim_write_sock (lp->conn, /* write to end buf */
|
||||
&(lp->txb[lp->txbpr]), TMXR_MAXBUF - lp->txbpr);
|
||||
if (sbytes != SOCKET_ERROR) { /* ok? */
|
||||
lp->txbpr = (lp->txbpr + sbytes); /* update remove ptr */
|
||||
if (lp->txbpr >= TMXR_MAXBUF) /* wrap? */
|
||||
lp->txbpr = 0;
|
||||
lp->txcnt = lp->txcnt + sbytes; /* update counts */
|
||||
nbytes = nbytes - sbytes;
|
||||
}
|
||||
if (nbytes && (lp->txbpr == 0)) { /* more data and wrap? */
|
||||
sbytes = sim_write_sock (lp->conn, lp->txb, nbytes);
|
||||
if (sbytes != SOCKET_ERROR) { /* ok */
|
||||
lp->txbpr = (lp->txbpr + sbytes); /* update remove ptr */
|
||||
if (lp->txbpr >= TMXR_MAXBUF) /* wrap? */
|
||||
lp->txbpr = 0;
|
||||
lp->txcnt = lp->txcnt + sbytes; /* update counts */
|
||||
nbytes = nbytes - sbytes;
|
||||
}
|
||||
}
|
||||
} /* end if nbytes */
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
/* Return count of buffered characters for line */
|
||||
|
||||
int32 tmxr_tqln (TMLN *lp)
|
||||
{
|
||||
return (lp->txbpi - lp->txbpr + ((lp->txbpi < lp->txbpr)? TMXR_MAXBUF: 0));
|
||||
}
|
||||
|
||||
/* Open master socket */
|
||||
|
||||
t_stat tmxr_open_master (TMXR *mp, char *cptr)
|
||||
{
|
||||
int32 i, port;
|
||||
SOCKET sock;
|
||||
TMLN *lp;
|
||||
t_stat r;
|
||||
|
||||
port = (int32) get_uint (cptr, 10, 65535, &r); /* get port */
|
||||
if ((r != SCPE_OK) || (port == 0))
|
||||
return SCPE_ARG;
|
||||
sock = sim_master_sock (port); /* make master socket */
|
||||
if (sock == INVALID_SOCKET) /* open error */
|
||||
return SCPE_OPENERR;
|
||||
printf ("Listening on port %d (socket %d)\n", port, sock);
|
||||
if (sim_log)
|
||||
fprintf (sim_log, "Listening on port %d (socket %d)\n", port, sock);
|
||||
mp->port = port; /* save port */
|
||||
mp->master = sock; /* save master socket */
|
||||
for (i = 0; i < mp->lines; i++) { /* initialize lines */
|
||||
lp = mp->ldsc + i;
|
||||
lp->conn = lp->tsta = 0;
|
||||
lp->rxbpi = lp->rxbpr = 0;
|
||||
lp->txbpi = lp->txbpr = 0;
|
||||
lp->rxcnt = lp->txcnt = 0;
|
||||
lp->xmte = 1;
|
||||
lp->dstb = 0;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Attach unit to master socket */
|
||||
|
||||
t_stat tmxr_attach (TMXR *mp, UNIT *uptr, char *cptr)
|
||||
{
|
||||
char* tptr;
|
||||
t_stat r;
|
||||
|
||||
tptr = (char *) malloc (strlen (cptr) + 1); /* get string buf */
|
||||
if (tptr == NULL) /* no more mem? */
|
||||
return SCPE_MEM;
|
||||
r = tmxr_open_master (mp, cptr); /* open master socket */
|
||||
if (r != SCPE_OK) { /* error? */
|
||||
free (tptr); /* release buf */
|
||||
return SCPE_OPENERR;
|
||||
}
|
||||
strcpy (tptr, cptr); /* copy port */
|
||||
uptr->filename = tptr; /* save */
|
||||
uptr->flags = uptr->flags | UNIT_ATT; /* no more errors */
|
||||
|
||||
if (mp->dptr == NULL) /* has device been set? */
|
||||
mp->dptr = find_dev_from_unit (uptr); /* no, so set device now */
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Close master socket */
|
||||
|
||||
t_stat tmxr_close_master (TMXR *mp)
|
||||
{
|
||||
int32 i;
|
||||
TMLN *lp;
|
||||
|
||||
for (i = 0; i < mp->lines; i++) { /* loop thru conn */
|
||||
lp = mp->ldsc + i;
|
||||
if (lp->conn) {
|
||||
tmxr_linemsg (lp, "\r\nDisconnected from the ");
|
||||
tmxr_linemsg (lp, sim_name);
|
||||
tmxr_linemsg (lp, " simulator\r\n\n");
|
||||
tmxr_reset_ln (lp);
|
||||
} /* end if conn */
|
||||
} /* end for */
|
||||
sim_close_sock (mp->master, 1); /* close master socket */
|
||||
mp->master = 0;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Detach unit from master socket */
|
||||
|
||||
t_stat tmxr_detach (TMXR *mp, UNIT *uptr)
|
||||
{
|
||||
if (!(uptr->flags & UNIT_ATT)) /* attached? */
|
||||
return SCPE_OK;
|
||||
tmxr_close_master (mp); /* close master socket */
|
||||
free (uptr->filename); /* free port string */
|
||||
uptr->filename = NULL;
|
||||
uptr->flags = uptr->flags & ~UNIT_ATT; /* not attached */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Stub examine and deposit */
|
||||
|
||||
t_stat tmxr_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw)
|
||||
{
|
||||
return SCPE_NOFNC;
|
||||
}
|
||||
|
||||
t_stat tmxr_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw)
|
||||
{
|
||||
return SCPE_NOFNC;
|
||||
}
|
||||
|
||||
/* Output message to socket or line descriptor */
|
||||
|
||||
void tmxr_msg (SOCKET sock, char *msg)
|
||||
{
|
||||
if (sock)
|
||||
sim_write_sock (sock, msg, strlen (msg));
|
||||
return;
|
||||
}
|
||||
|
||||
void tmxr_linemsg (TMLN *lp, char *msg)
|
||||
{
|
||||
int32 len;
|
||||
|
||||
for (len = strlen (msg); len > 0; --len)
|
||||
tmxr_putc_ln (lp, *msg++);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Print connections - used only in named SHOW command */
|
||||
|
||||
void tmxr_fconns (FILE *st, TMLN *lp, int32 ln)
|
||||
{
|
||||
if (ln >= 0)
|
||||
fprintf (st, "line %d: ", ln);
|
||||
if (lp->conn) {
|
||||
int32 o1, o2, o3, o4, hr, mn, sc;
|
||||
uint32 ctime;
|
||||
|
||||
o1 = (lp->ipad >> 24) & 0xFF;
|
||||
o2 = (lp->ipad >> 16) & 0xFF;
|
||||
o3 = (lp->ipad >> 8) & 0xFF;
|
||||
o4 = (lp->ipad) & 0xFF;
|
||||
ctime = (sim_os_msec () - lp->cnms) / 1000;
|
||||
hr = ctime / 3600;
|
||||
mn = (ctime / 60) % 60;
|
||||
sc = ctime % 60;
|
||||
fprintf (st, "IP address %d.%d.%d.%d", o1, o2, o3, o4);
|
||||
if (ctime)
|
||||
fprintf (st, ", connected %02d:%02d:%02d\n", hr, mn, sc);
|
||||
}
|
||||
else fprintf (st, "line disconnected\n");
|
||||
if (lp->txlog)
|
||||
fprintf (st, "Logging to %s\n", lp->txlogname);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Print statistics - used only in named SHOW command */
|
||||
|
||||
void tmxr_fstats (FILE *st, TMLN *lp, int32 ln)
|
||||
{
|
||||
static const char *enab = "on";
|
||||
static const char *dsab = "off";
|
||||
|
||||
if (ln >= 0)
|
||||
fprintf (st, "line %d: ", ln);
|
||||
if (lp->conn) {
|
||||
fprintf (st, "input (%s) queued/total = %d/%d, ",
|
||||
(lp->rcve? enab: dsab),
|
||||
lp->rxbpi - lp->rxbpr, lp->rxcnt);
|
||||
fprintf (st, "output (%s) queued/total = %d/%d\n",
|
||||
(lp->xmte? enab: dsab),
|
||||
lp->txbpi - lp->txbpr, lp->txcnt);
|
||||
}
|
||||
else fprintf (st, "line disconnected\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Disconnect line */
|
||||
|
||||
t_stat tmxr_dscln (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
TMXR *mp = (TMXR *) desc;
|
||||
TMLN *lp;
|
||||
int32 ln;
|
||||
t_stat r;
|
||||
|
||||
if (mp == NULL)
|
||||
return SCPE_IERR;
|
||||
if (val) { /* = n form */
|
||||
if (cptr == NULL)
|
||||
return SCPE_ARG;
|
||||
ln = (int32) get_uint (cptr, 10, mp->lines - 1, &r);
|
||||
if (r != SCPE_OK)
|
||||
return SCPE_ARG;
|
||||
lp = mp->ldsc + ln;
|
||||
}
|
||||
else {
|
||||
lp = tmxr_find_ldsc (uptr, 0, mp);
|
||||
if (lp == NULL)
|
||||
return SCPE_IERR;
|
||||
}
|
||||
if (lp->conn) {
|
||||
tmxr_linemsg (lp, "\r\nOperator disconnected line\r\n\n");
|
||||
tmxr_reset_ln (lp);
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Enable logging for line */
|
||||
|
||||
t_stat tmxr_set_log (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
TMXR *mp = (TMXR *) desc;
|
||||
TMLN *lp;
|
||||
|
||||
if (cptr == NULL) /* no file name? */
|
||||
return SCPE_2FARG;
|
||||
lp = tmxr_find_ldsc (uptr, val, mp); /* find line desc */
|
||||
if (lp == NULL)
|
||||
return SCPE_IERR;
|
||||
if (lp->txlog) /* close existing log */
|
||||
tmxr_set_nolog (NULL, val, NULL, desc);
|
||||
lp->txlogname = (char *) calloc (CBUFSIZE, sizeof (char)); /* alloc namebuf */
|
||||
if (lp->txlogname == NULL) /* can't? */
|
||||
return SCPE_MEM;
|
||||
strncpy (lp->txlogname, cptr, CBUFSIZE); /* save file name */
|
||||
lp->txlog = fopen (cptr, "ab"); /* open log */
|
||||
if (lp->txlog == NULL) { /* error? */
|
||||
free (lp->txlogname); /* free buffer */
|
||||
return SCPE_OPENERR;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Disable logging for line */
|
||||
|
||||
t_stat tmxr_set_nolog (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
TMXR *mp = (TMXR *) desc;
|
||||
TMLN *lp;
|
||||
|
||||
if (cptr) /* no arguments */
|
||||
return SCPE_2MARG;
|
||||
lp = tmxr_find_ldsc (uptr, val, mp); /* find line desc */
|
||||
if (lp == NULL)
|
||||
return SCPE_IERR;
|
||||
if (lp->txlog) { /* logging? */
|
||||
fclose (lp->txlog); /* close log */
|
||||
free (lp->txlogname); /* free namebuf */
|
||||
lp->txlog = NULL;
|
||||
lp->txlogname = NULL;
|
||||
}
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Show logging status for line */
|
||||
|
||||
t_stat tmxr_show_log (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
TMXR *mp = (TMXR *) desc;
|
||||
TMLN *lp;
|
||||
|
||||
lp = tmxr_find_ldsc (uptr, val, mp); /* find line desc */
|
||||
if (lp == NULL)
|
||||
return SCPE_IERR;
|
||||
if (lp->txlog)
|
||||
fprintf (st, "logging to %s", lp->txlogname);
|
||||
else fprintf (st, "no logging");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Find line descriptor.
|
||||
|
||||
Note: This routine may be called with a UNIT that does not belong to the
|
||||
device indicated in the TMXR structure. That is, the multiplexer lines may
|
||||
belong to a device other than the one attached to the socket (the HP 2100 MUX
|
||||
device is one example). Therefore, we must look up the device from the unit
|
||||
at each call, rather than depending on the DPTR stored in the TMXR.
|
||||
*/
|
||||
|
||||
TMLN *tmxr_find_ldsc (UNIT *uptr, int32 val, TMXR *mp)
|
||||
{
|
||||
if (uptr) { /* called from SET? */
|
||||
DEVICE *dptr = find_dev_from_unit (uptr); /* find device */
|
||||
if (dptr == NULL) /* what?? */
|
||||
return NULL;
|
||||
val = (int32) (uptr - dptr->units); /* implicit line # */
|
||||
}
|
||||
if ((val < 0) || (val >= mp->lines)) /* invalid line? */
|
||||
return NULL;
|
||||
return mp->ldsc + val; /* line descriptor */
|
||||
}
|
||||
|
||||
/* Set the line connection order.
|
||||
|
||||
Example command for eight-line multiplexer:
|
||||
|
||||
SET <dev> LINEORDER=1;5;2-4;7
|
||||
|
||||
Resulting connection order: 1,5,2,3,4,7,0,6.
|
||||
|
||||
Parameters:
|
||||
- uptr = (not used)
|
||||
- val = (not used)
|
||||
- cptr = pointer to first character of range specification
|
||||
- desc = pointer to multiplexer's TMXR structure
|
||||
|
||||
On entry, cptr points to the value portion of the command string, which may
|
||||
be either a semicolon-separated list of line ranges or the keyword ALL.
|
||||
|
||||
If a line connection order array is not defined in the multiplexer
|
||||
descriptor, the command is rejected. If the specified range encompasses all
|
||||
of the lines, the first value of the connection order array is set to -1 to
|
||||
indicate sequential connection order. Otherwise, the line values in the
|
||||
array are set to the order specified by the command string. All values are
|
||||
populated, first with those explicitly specified in the command string, and
|
||||
then in ascending sequence with those not specified.
|
||||
|
||||
If an error occurs, the original line order is not disturbed.
|
||||
*/
|
||||
|
||||
t_stat tmxr_set_lnorder (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
TMXR *mp = (TMXR *) desc;
|
||||
char *tptr;
|
||||
t_addr low, high, max = (t_addr) mp->lines - 1;
|
||||
int32 *list;
|
||||
t_bool *set;
|
||||
uint32 line, idx = 0;
|
||||
t_stat result = SCPE_OK;
|
||||
|
||||
if (mp->lnorder == NULL) /* line connection order undefined? */
|
||||
return SCPE_NXPAR; /* "Non-existent parameter" error */
|
||||
|
||||
else if ((cptr == NULL) || (*cptr == '\0')) /* line range not supplied? */
|
||||
return SCPE_MISVAL; /* "Missing value" error */
|
||||
|
||||
list = (int32 *) calloc (mp->lines, sizeof (int32)); /* allocate new line order array */
|
||||
|
||||
if (list == NULL) /* allocation failed? */
|
||||
return SCPE_MEM; /* report it */
|
||||
|
||||
set = (t_bool *) calloc (mp->lines, sizeof (t_bool)); /* allocate line set tracking array */
|
||||
|
||||
if (set == NULL) { /* allocation failed? */
|
||||
free (list); /* free successful list allocation */
|
||||
return SCPE_MEM; /* report it */
|
||||
}
|
||||
|
||||
tptr = cptr + strlen (cptr); /* append a semicolon */
|
||||
*tptr++ = ';'; /* to the command string */
|
||||
*tptr = '\0'; /* to make parsing easier for get_range */
|
||||
|
||||
while (*cptr) { /* parse command string */
|
||||
cptr = get_range (NULL, cptr, &low, &high, 10, max, ';'); /* get a line range */
|
||||
|
||||
if (cptr == NULL) { /* parsing error? */
|
||||
result = SCPE_ARG; /* "Invalid argument" error */
|
||||
break;
|
||||
}
|
||||
|
||||
else if ((low > max) || (high > max)) { /* line out of range? */
|
||||
result = SCPE_SUB; /* "Subscript out of range" error */
|
||||
break;
|
||||
}
|
||||
|
||||
else if ((low == 0) && (high == max)) { /* entire line range specified? */
|
||||
list [0] = -1; /* set sequential order flag */
|
||||
idx = (uint32) max + 1; /* indicate no fill-in needed */
|
||||
break;
|
||||
}
|
||||
|
||||
else
|
||||
for (line = (uint32) low; line <= (uint32) high; line++) /* see if previously specified */
|
||||
if (set [line] == FALSE) { /* not already specified? */
|
||||
set [line] = TRUE; /* now it is */
|
||||
list [idx] = line; /* add line to connection order */
|
||||
idx = idx + 1; /* bump "specified" count */
|
||||
}
|
||||
}
|
||||
|
||||
if (result == SCPE_OK) { /* assignment successful? */
|
||||
if (idx <= max) /* any lines not specified? */
|
||||
for (line = 0; line <= max; line++) /* fill them in sequentially */
|
||||
if (set [line] == FALSE) { /* specified? */
|
||||
list [idx] = line; /* no, so add it */
|
||||
idx = idx + 1;
|
||||
}
|
||||
|
||||
memcpy (mp->lnorder, list, mp->lines * sizeof (int32)); /* copy working array to connection array */
|
||||
}
|
||||
|
||||
free (list); /* free list allocation */
|
||||
free (set); /* free set allocation */
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Show line connection order.
|
||||
|
||||
Parameters:
|
||||
- st = stream on which output is to be written
|
||||
- uptr = (not used)
|
||||
- val = (not used)
|
||||
- desc = pointer to multiplexer's TMXR structure
|
||||
|
||||
If a connection order array is not defined in the multiplexer descriptor, the
|
||||
command is rejected. If the first value of the connection order array is set
|
||||
to -1, then the connection order is sequential. Otherwise, the line values
|
||||
in the array are printed as a semicolon-separated list. Ranges are printed
|
||||
where possible to shorten the output.
|
||||
*/
|
||||
|
||||
t_stat tmxr_show_lnorder (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
int32 i, j, low, last;
|
||||
TMXR *mp = (TMXR *) desc;
|
||||
int32 *iptr = mp->lnorder;
|
||||
t_bool first = TRUE;
|
||||
|
||||
if (iptr == NULL) /* connection order undefined? */
|
||||
return SCPE_NXPAR; /* "Non-existent parameter" error */
|
||||
|
||||
if (*iptr < 0) /* sequential order indicated? */
|
||||
fprintf (st, "Order=0-%d\n", mp->lines - 1); /* print full line range */
|
||||
|
||||
else {
|
||||
low = last = *iptr++; /* set first line value */
|
||||
|
||||
for (j = 1; j <= mp->lines; j++) { /* print remaining lines in order list */
|
||||
if (j < mp->lines) /* more lines to process? */
|
||||
i = *iptr++; /* get next line in list */
|
||||
else /* final iteration */
|
||||
i = -1; /* get "tie-off" value */
|
||||
|
||||
if (i != last + 1) { /* end of a range? */
|
||||
if (first) { /* first line to print? */
|
||||
fputs ("Order=", st); /* print header */
|
||||
first = FALSE;
|
||||
}
|
||||
|
||||
else /* not first line printed */
|
||||
fputc (';', st); /* print separator */
|
||||
|
||||
if (low == last) /* range null? */
|
||||
fprintf (st, "%d", last); /* print single line value */
|
||||
|
||||
else /* range established */
|
||||
fprintf (st, "%d-%d", low, last); /* print start and end line */
|
||||
|
||||
low = i; /* start new range */
|
||||
}
|
||||
|
||||
last = i; /* note value for range check */
|
||||
}
|
||||
}
|
||||
|
||||
if (first == FALSE) /* sanity check for lines == 0 */
|
||||
fputc ('\n', st);
|
||||
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Show summary processor */
|
||||
|
||||
t_stat tmxr_show_summ (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
TMXR *mp = (TMXR *) desc;
|
||||
int32 i, t;
|
||||
|
||||
if (mp == NULL)
|
||||
return SCPE_IERR;
|
||||
for (i = t = 0; i < mp->lines; i++)
|
||||
t = t + (mp->ldsc[i].conn != 0);
|
||||
if (t == 1)
|
||||
fprintf (st, "1 connection");
|
||||
else fprintf (st, "%d connections", t);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Show conn/stat processor */
|
||||
|
||||
t_stat tmxr_show_cstat (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
TMXR *mp = (TMXR *) desc;
|
||||
int32 i, any;
|
||||
|
||||
if (mp == NULL)
|
||||
return SCPE_IERR;
|
||||
for (i = any = 0; i < mp->lines; i++) {
|
||||
if (mp->ldsc[i].conn) {
|
||||
any++;
|
||||
if (val)
|
||||
tmxr_fconns (st, &mp->ldsc[i], i);
|
||||
else tmxr_fstats (st, &mp->ldsc[i], i);
|
||||
}
|
||||
}
|
||||
if (any == 0)
|
||||
fprintf (st, (mp->lines == 1? "disconnected\n": "all disconnected\n"));
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Show number of lines */
|
||||
|
||||
t_stat tmxr_show_lines (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
TMXR *mp = (TMXR *) desc;
|
||||
|
||||
if (mp == NULL)
|
||||
return SCPE_IERR;
|
||||
fprintf (st, "lines=%d", mp->lines);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
Loading…
Add table
Reference in a new issue