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:
Bob Supnik 2011-03-23 14:39:00 -07:00 committed by Mark Pizzolato
parent 35eac703c3
commit a9fd3dd518
77 changed files with 12846 additions and 1522 deletions

View file

@ -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

View file

@ -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!
@ -83,30 +161,33 @@ Linux, {Free|Net|Open}BSD, OS/X, and Un*x notes:
Sim_Ether has been reworked to be more universal; because of this, you will
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.
for details.
----- 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)

View file

@ -63,10 +63,11 @@
#endif
/* Debug flags */
#define IN_MSG (1 << 0)
#define OUT_MSG (1 << 1)
#define CMD_MSG (1 << 2)
#define VERBOSE_MSG (1 << 3)
#define IN_MSG (1 << 0)
#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)
@ -160,11 +161,12 @@ extern int32 sim_interval;
/* Debug Flags */
static DEBTAB generic_dt[] = {
{ "IN", IN_MSG },
{ "OUT", OUT_MSG },
{ "CMD", CMD_MSG },
{ "VERBOSE", VERBOSE_MSG },
{ NULL, 0 }
{ "IN", IN_MSG },
{ "OUT", OUT_MSG },
{ "CMD", CMD_MSG },
{ "VERBOSE", VERBOSE_MSG },
{ "BUFFEREMPTY", BUFFER_EMPTY_MSG },
{ NULL, 0 }
};
/* SIMH pseudo device status registers */
@ -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 */
sio_unit.u3 = FALSE; /* indicate that no character is available */
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);
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 " IN(0x%03x) = 0x%02x%s" NLP, PCX, port, result, printable(buffer, result, TRUE));
else if ((io) && (sio_dev.dctrl & OUT_MSG))
printf("\tSIO_D: " ADDRESS_FORMAT " OUT(0x%03x) = 0x%02x%s" NLP, PCX, port, data, printable(buffer, data, FALSE));
return result;
}

View file

@ -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

View file

@ -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 */

View file

@ -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 */

View file

@ -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? */

View file

@ -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 */

View file

@ -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)

View file

@ -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 */
@ -215,8 +211,8 @@ switch (mod) { /* case on modifier */
break;
}
if (!(flag & MD_BIN) && /* BCD tape and */
((dbuf[0] & CHAR) == BCD_TAPMRK)) /* first char TMK? */
uptr->IND = 1; /* set indicator */
((dbuf[0] & CHAR) == BCD_TAPMRK)) /* first char TMK? */
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 */
}

View file

@ -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 */

View file

@ -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.

View file

@ -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? */
j++;
com_buf[j] = (com_buf[j] << 12) | /* pack data */
((t_uint64) (com_pkt[ent].data & 07777));
}
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) (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)
sim_putchar (c);
if (c == '\r')
sim_putchar ('\n');
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') /* 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 */
tmxr_putc_ln (&com_ldsc[ln], c);
if (c == '\r') /* add LF after CR */
tmxr_putc_ln (&com_ldsc[ln], '\n');
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,20 +819,18 @@ 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 ((coml_unit[ln].flags & UNIT_K35) && islower (c)) /* KSR-35 LC? */
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 */
*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 */
*c1 = '\n'; /* lf after cr */
return '\r';
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

File diff suppressed because it is too large Load diff

View file

@ -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) {

View file

@ -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;
@ -324,7 +333,7 @@ switch (addr) {
break;
case 00140: /* SLF */
if (cpu_model & I_9X) /* 709X only */
if (cpu_model & I_9X) /* 709X only */
SLT = 0;
break;
@ -339,10 +348,12 @@ switch (addr) {
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? */
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;
ch = GET_U_CH (addr); /* get channel */
if (ch_flags[ch] & CHF_BOT) /* BOT? */
@ -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
View 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

File diff suppressed because it is too large Load diff

View file

@ -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))

View file

@ -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;
@ -537,7 +537,7 @@ if (uptr->UST == (CHSL_WRS|CHSL_2ND)) { /* data write? */
xb[mt_bptr[ch]++] = by; /* put in buffer */
}
if (eorfl)
return mt_rec_end (uptr); /* EOR? write rec */
return mt_rec_end (uptr); /* EOR? write rec */
return SCPE_OK;
}
return SCPE_IERR;
@ -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
View 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;
}

View file

@ -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
View 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];
}

View file

@ -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 */

View file

@ -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 */

View file

@ -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 */

View file

@ -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 */

View file

@ -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

View file

@ -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 */

View file

@ -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) {
@ -847,19 +896,19 @@ uint32 sts;
UNIT *uptr;
if (uptr = tq_getucb (lu)) { /* unit exist? */
if (uptr->flags & UNIT_SXC) /* ser exc pending? */
if (uptr->flags & UNIT_SXC) /* ser exc pending? */
sts = ST_SXC;
else {
uptr->flags = uptr->flags & ~(UNIT_ONL | UNIT_TMK | UNIT_POL);
sim_tape_rewind (uptr); /* rewind */
uptr->uf = uptr->objp = 0; /* clr flags */
if (uptr->flags & UNIT_ATT) { /* attached? */
sts = ST_SUC; /* success */
if (mdf & MD_UNL) /* unload? */
else {
uptr->flags = uptr->flags & ~(UNIT_ONL | UNIT_TMK | UNIT_POL);
sim_tape_rewind (uptr); /* rewind */
uptr->uf = uptr->objp = 0; /* clr flags */
if (uptr->flags & UNIT_ATT) { /* attached? */
sts = ST_SUC; /* success */
if (mdf & MD_UNL) /* unload? */
tq_detach (uptr);
}
else sts = ST_OFL | SB_OFL_NV; /* no, offline */
}
}
else sts = ST_OFL | SB_OFL_NV; /* no, offline */
}
}
else sts = ST_OFL; /* offline */
tq_putr (pkt, OP_AVL | OP_END, tq_efl (uptr), sts, AVL_LNT, UQ_TYP_SEQ);
@ -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;

View file

@ -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;
}

File diff suppressed because it is too large Load diff

View file

@ -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 */

View file

@ -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, &eth_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,20 +312,39 @@ 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;
fprintf(st, "Ethernet statistics:\n");
fprintf(st, fmt, "Seconds since cleared:", stats->secs);
fprintf(st, fmt, "Recv frames:", stats->frecv);
fprintf(st, fmt, "Recv dbytes:", stats->rbytes);
fprintf(st, fmt, "Xmit frames:", stats->ftrans);
fprintf(st, fmt, "Xmit dbytes:", stats->tbytes);
fprintf(st, fmt, "Recv frames(multicast):", stats->mfrecv);
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, "Seconds since cleared:", stats->secs);
fprintf(st, fmt, "Recv frames:", stats->frecv);
fprintf(st, fmt, "Recv dbytes:", stats->rbytes);
fprintf(st, fmt, "Xmit frames:", stats->ftrans);
fprintf(st, fmt, "Xmit dbytes:", stats->tbytes);
fprintf(st, fmt, "Recv frames(multicast):", stats->mfrecv);
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)
{
return SCPE_NOFNC; /* not implemented yet */
/* 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,24 +762,24 @@ 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]);
break;
wstatus = Map_WriteB(udbb, mtlen * 3, (uint8*) &xu->var->setup.macs[2]);
break;
case FC_WMAL: /* write multicast address list */
mtlen = (xu->var->pcb[2] & 0xFF00) >> 8;
sim_debug(DBG_TRC, xu->dev, "FC_WAL: mtlen=%d\n", mtlen);
sim_debug(DBG_TRC, xu->dev, "FC_WAL: mtlen=%d\n", mtlen);
if (mtlen > 10)
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 (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]);
/* clear existing multicast list */
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[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);
@ -807,7 +899,7 @@ sim_debug(DBG_TRC, xu->dev, "FC_WAL: mtlen=%d\n", mtlen);
case FC_WMODE: /* write mode register */
value = xu->var->mode;
xu->var->mode = xu->var->pcb[1];
sim_debug(DBG_TRC, xu->dev, "FC_WMODE: mode=%04x\n", xu->var->mode);
sim_debug(DBG_TRC, xu->dev, "FC_WMODE: mode=%04x\n", xu->var->mode);
/* set promiscuous and multicast flags */
xu->var->setup.promiscuous = (xu->var->mode & MODE_PROM) ? 1 : 0;
@ -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 */

View file

@ -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 */

View file

@ -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

View file

@ -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"),

View file

@ -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

View file

@ -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:

View file

@ -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 */

View file

@ -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

View file

@ -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

View file

@ -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"),

View file

@ -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"),

View file

@ -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"),

View file

@ -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"),

View file

@ -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

View file

@ -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"),

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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"),

View file

@ -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"),

View file

@ -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"),

View file

@ -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"),

View file

@ -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 */

View file

@ -227,7 +227,7 @@ switch (fnc) { /* case function */
}
else if ((t == 03610) && sim_is_active (uptr) &&/* skip rec? */
((mt_inst & DEV_OUT) == 0))
mt_skip = 1; /* set flag */
mt_skip = 1; /* set flag */
else CRETINS;
break;

View file

@ -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 */

View file

@ -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 }
};
@ -246,7 +251,7 @@ if ((ipl < IPL_TTINT) && (tti_int || tto_int)) /* console int */
if (ipl >= IPL_SMAX) /* ipl >= sw max? */
return 0;
if ((t = SISR & sw_int_mask[ipl]) == 0)
return 0; /* eligible req */
return 0; /* eligible req */
for (i = IPL_SMAX; i > ipl; i--) { /* check swre int */
if ((t >> i) & 1) /* req != 0? int */
return i;
@ -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;

View file

@ -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;
}
}

View file

@ -619,7 +619,7 @@ for (i = 0; i < bc; i = i + pbc) { /* loop by pages */
if (!uba_map_addr (ba + i, &ma)) /* page inv or NXM? */
return (bc - i);
pbc = VA_PAGSIZE - VA_GETOFF (ma); /* left in page */
if (pbc > (bc - i)) /* limit to rem xfr */
if (pbc > (bc - i)) /* limit to rem xfr */
pbc = bc - i;
if (DEBUG_PRI (uba_dev, UBA_DEB_XFR))
fprintf (sim_deb, ">>UBA: 8b read, ma = %X, bc = %X\n", ma, pbc);

View file

@ -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)
M = (uint32 *) calloc (((uint32) MEMSIZE) >> 2, sizeof (uint32));
if (M == NULL)
return SCPE_MEM;
pcq_r = find_reg ("PCQ", NULL, dptr);
if (pcq_r)
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;
else return SCPE_IERR;
sim_brk_types = sim_brk_dflt = SWMASK ('E');
M = (uint32 *) calloc (((uint32) MEMSIZE) >> 2, sizeof (uint32));
if (M == NULL)
return SCPE_MEM;
}
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);
}
}

View file

@ -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 {

View file

@ -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"
};

View file

@ -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 */

View file

@ -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;
}

View file

@ -9,12 +9,36 @@ ifeq ($(WIN32),)
ifneq (,$(findstring darwin,$(OSTYPE)))
OS_CCDEFS = -D_GNU_SOURCE
else
OS_CCDEFS = -lrt -lm -D_GNU_SOURCE
ifeq (librt,$(shell if test -e /usr/lib/librt.a; then echo librt; fi))
OS_CCDEFS = -lrt -lm -D_GNU_SOURCE
else
OS_CCDEFS = -lm -D_GNU_SOURCE
endif
endif
endif
CC = gcc -std=c99 -U__STRICT_ANSI__ -g $(OS_CCDEFS) -I .
ifeq ($(USE_NETWORK),)
else
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
#

177
scp.c
View file

@ -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)
add_history (cptr);
if (prompt)
add_history (cptr);
#endif
return cptr;
}

View file

@ -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 ())
return SCPE_OK;
c = _getch ();
if (!GetNumberOfConsoleInputEvents(std_input, &nkbevents))
return SCPE_TTYERR;
while (c == -1) {
if (0 == nkbevents)
return SCPE_OK;
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

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -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) */
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 */

508
sim_rev.h

File diff suppressed because it is too large Load diff

View file

@ -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,9 +196,10 @@ 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__) ||\
#elif defined (_WIN32) || defined (__EMX__) || \
(defined (__ALPHA) && defined (__unix__))
int size;
#else
@ -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? */

View file

@ -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)

View file

@ -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
View 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;
}