Merged in new ethernet code to potentially leverage AsynchIO

This commit is contained in:
Mark Pizzolato 2011-04-15 08:53:01 -07:00
parent a1930c9b05
commit eb514e2a8d
7 changed files with 3081 additions and 605 deletions

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)

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

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