SIMH: Fix spelling errors in comments and strings
This commit is contained in:
parent
e7b2431f11
commit
0f6bcb9682
34 changed files with 1893 additions and 1893 deletions
|
@ -3,36 +3,36 @@ SIM_ASYNCH_IO
|
|||
Theory of operation.
|
||||
|
||||
Features.
|
||||
- Optional Use. Build with or without SIM_ASYNCH_IO defined and
|
||||
- Optional Use. Build with or without SIM_ASYNCH_IO defined and
|
||||
simulators will still build and perform correctly when run.
|
||||
Additionmally, a simulator built with SIM_ASYNCH_IO defined can
|
||||
dynamically disable and reenable asynchronous operation with
|
||||
Additionally, a simulator built with SIM_ASYNCH_IO defined can
|
||||
dynamically disable and reenable asynchronous operation with
|
||||
the scp commands SET NOASYNCH and SET ASYNCH respectively.
|
||||
- Consistent Save/Restore state. The state of a simulator saved
|
||||
- Consistent Save/Restore state. The state of a simulator saved
|
||||
on a simulator with (or without) Asynch support can be restored
|
||||
on any simulator of the same version with or without Asynch
|
||||
on any simulator of the same version with or without Asynch
|
||||
support.
|
||||
- Optimal behavior/performance with simulator running with or
|
||||
- Optimal behavior/performance with simulator running with or
|
||||
without CPU idling enabled.
|
||||
- Consistent minimum instruction scheduling delays when operating
|
||||
with or without SIM_ASYNCH_IO. When SIM_ASYNCH_IO is emabled,
|
||||
any operation which would have been scheduled to occurr in 'n'
|
||||
instructions will still occur (from the simulated computer's
|
||||
- Consistent minimum instruction scheduling delays when operating
|
||||
with or without SIM_ASYNCH_IO. When SIM_ASYNCH_IO is enabled,
|
||||
any operation which would have been scheduled to occur in 'n'
|
||||
instructions will still occur (from the simulated computer's
|
||||
point of view) at least 'n' instructions after it was initiated.
|
||||
|
||||
|
||||
Benefits.
|
||||
- Allows a simulator to execute simulated instructions concurrently
|
||||
- Allows a simulator to execute simulated instructions concurrently
|
||||
with I/O operations which may take numerous milliseconds to perform.
|
||||
- Allows a simulated device to potentially avoid polling for the
|
||||
arrival of data. Polling consumes host processor CPU cycles which
|
||||
may better be spent executing simulated instructions or letting
|
||||
other host processes run. Measurements made of available
|
||||
- Allows a simulated device to potentially avoid polling for the
|
||||
arrival of data. Polling consumes host processor CPU cycles which
|
||||
may better be spent executing simulated instructions or letting
|
||||
other host processes run. Measurements made of available
|
||||
instruction execution easily demonstrate the benefits of parallel
|
||||
instruction and I/O activities. A VAX simulator with a process
|
||||
running a disk intensive application in one process was able to
|
||||
run (in another process) 11 times the number of Dhrystone operations
|
||||
instruction and I/O activities. A VAX simulator with a process
|
||||
running a disk intensive application in one process was able to
|
||||
run (in another process) 11 times the number of Dhrystone operations
|
||||
with Asynch I/O enabled vs not enabled.
|
||||
- Allows simulator clock ticks to track wall clock was precisely as
|
||||
- Allows simulator clock ticks to track wall clock was precisely as
|
||||
possible under varying I/O load and activities.
|
||||
|
||||
SimH Libraries which provide Asynch I/O support:
|
||||
|
@ -44,7 +44,7 @@ SimH Libraries which provide Asynch I/O support:
|
|||
|
||||
Requirements to use:
|
||||
The Simulator's instruction loop needs to be modified to include a single
|
||||
line which checks for asynchronouzly arrived events. The vax_cpu.c
|
||||
line which checks for asynchronously arrived events. The vax_cpu.c
|
||||
module added the following line indicated by >>>:
|
||||
|
||||
/* Main instruction loop */
|
||||
|
@ -60,20 +60,20 @@ module added the following line indicated by >>>:
|
|||
SET_IRQL; /* update interrupts */
|
||||
}
|
||||
|
||||
A global variable (sim_asynch_latency) is used to indicate the "interrupt
|
||||
A global variable (sim_asynch_latency) is used to indicate the "interrupt
|
||||
dispatch latency". This variable is the number of nanoseconds between checks
|
||||
for completed asynchronous I/O. The default value is 4000 (4 usec) which
|
||||
corresponds reasonably with simulated hardware. This variable controls
|
||||
the computation of sim_asynch_inst_latency which is the number of simulated
|
||||
instructions in the sim_asynch_latency interval. We are trying to avoid
|
||||
checking for completed asynchronous I/O after every instruction since the
|
||||
checking for completed asynchronous I/O after every instruction since the
|
||||
actual checking every instruction can slow down execution. Periodic checks
|
||||
provide a balance which allows response similar to real hardware while also
|
||||
providing minimal impact on actual instruction execution. Meanwhile, if
|
||||
maximal response is desired, then the value of sim_asynch_latency can be
|
||||
provide a balance which allows response similar to real hardware while also
|
||||
providing minimal impact on actual instruction execution. Meanwhile, if
|
||||
maximal response is desired, then the value of sim_asynch_latency can be
|
||||
set sufficiently low to assure that sim_asynch_inst_latency computes to 1.
|
||||
The sim_asynch_inst_latency is dynamically updated once per second in the
|
||||
sim_rtcn_calb routine where clock to instruction execution is dynamically
|
||||
The sim_asynch_inst_latency is dynamically updated once per second in the
|
||||
sim_rtcn_calb routine where clock to instruction execution is dynamically
|
||||
determined. A simulator would usually add register definitions
|
||||
to enable viewing and setting of these variables via scp:
|
||||
|
||||
|
@ -91,60 +91,60 @@ Naming conventions:
|
|||
All of the routines implemented in sim_disk and sim_tape have been kept
|
||||
in place. All routines which perform I/O have a variant routine available
|
||||
with a "_a" appended to the the routine name with the addition of a single
|
||||
parameter which indicates the asynch completion callback routine. For
|
||||
parameter which indicates the asynch completion callback routine. For
|
||||
example there now exists the routines:
|
||||
t_stat sim_tape_rdrecf (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max);
|
||||
t_stat sim_tape_rdrecf_a (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max, TAPE_PCALLBACK callback);
|
||||
|
||||
The Purpose of the callback function is to record the I/O completion status
|
||||
and then to schedule the activation of the unit.
|
||||
and then to schedule the activation of the unit.
|
||||
|
||||
Considerations:
|
||||
Avoiding multiple concurrent users of the unit structure. While asynch
|
||||
I/O is pending on a Unit, the unit should not otherwise be on the event
|
||||
I/O is pending on a Unit, the unit should not otherwise be on the event
|
||||
queue. The I/O completion will cause the Unit to be scheduled to run
|
||||
immediately to actually dispatch control flow to the callback routine.
|
||||
The callback routine is always called in the same thread which is
|
||||
executing instructions. Since all simulator device data structures are
|
||||
only referenced from this thread there are no host multi-processor cache
|
||||
The callback routine is always called in the same thread which is
|
||||
executing instructions. Since all simulator device data structures are
|
||||
only referenced from this thread there are no host multi-processor cache
|
||||
coherency issues to be concerned about.
|
||||
|
||||
Arguments to the callback routine:
|
||||
UNIT *, and IO Status
|
||||
Requirements of the Callback routine.
|
||||
The callback routine must save the I/O completion status in a place
|
||||
which the next invocation of the unit service routine will reference
|
||||
which the next invocation of the unit service routine will reference
|
||||
and act on it. This allows device code to return error conditions
|
||||
back to scp in a consistent way without regard to how the callback
|
||||
back to scp in a consistent way without regard to how the callback
|
||||
routine (and the actual I/O) may have been executed. When the callback
|
||||
routine is called, it will already be on the simulator event queue with
|
||||
an event time which was specified when the unit was attached or via a
|
||||
an event time which was specified when the unit was attached or via a
|
||||
call to sim_disk_set_async. If no value has been specified then it
|
||||
will have been scheduled with a delay time of 0. If a different event
|
||||
firing time is desired, then the callback completion routine should
|
||||
will have been scheduled with a delay time of 0. If a different event
|
||||
firing time is desired, then the callback completion routine should
|
||||
call sim_activate_abs to schedule the event at the appropriate time.
|
||||
|
||||
Required change in device coding.
|
||||
Devices which wish to leverage the benefits of asynch I/O must rearrange
|
||||
the code which implements the unit service routine. This rearrangement
|
||||
usually entails breaking the activities into two phases. The first phase
|
||||
(I'll call the top half) involves performing whatever is needed to
|
||||
initiate a call to perform an I/O operation with a callback argument.
|
||||
(I'll call the top half) involves performing whatever is needed to
|
||||
initiate a call to perform an I/O operation with a callback argument.
|
||||
Control is then immediately returned to the scp event dispatcher.
|
||||
The callback routine needs to be coded to stash away the io completion
|
||||
The callback routine needs to be coded to stash away the io completion
|
||||
status and some indicator that an I/O has completed.
|
||||
The top/bottom half separation of the unit service routine would be
|
||||
coded to examine the I/O completion indicator and invoke the bottom half
|
||||
code upon completion. The bottom half code should clear the I/O
|
||||
completion indicator and then perform any activities which normally
|
||||
code upon completion. The bottom half code should clear the I/O
|
||||
completion indicator and then perform any activities which normally
|
||||
need to occur after the I/O completes. Care should be taken while
|
||||
performing these top/bottom half activities to return to the scp event
|
||||
dispatcher with either SCPE_OK or an appropriate error code when needed.
|
||||
The need to return error indications to the scp event dispatcher is why
|
||||
the bottom half activities can't simply be performed in the
|
||||
callback routine (the callback routine does not return a status).
|
||||
Care should also be taken to realize that local variables in the
|
||||
unit service routine will not directly survive between the separate
|
||||
dispatcher with either SCPE_OK or an appropriate error code when needed.
|
||||
The need to return error indications to the scp event dispatcher is why
|
||||
the bottom half activities can't simply be performed in the
|
||||
callback routine (the callback routine does not return a status).
|
||||
Care should also be taken to realize that local variables in the
|
||||
unit service routine will not directly survive between the separate
|
||||
top and bottom half calls to the unit service routine. If any such
|
||||
information must be referenced in both the top and bottom half code paths
|
||||
then it must either be recomputed prior to the top/bottom half check
|
||||
|
@ -162,65 +162,65 @@ more realistic delays to perform I/O operations.
|
|||
The pdp11_tq.c module has been refactored to leverage the asynch I/O
|
||||
features of the sim_tape library. The impact to this code to adopt the
|
||||
asynch I/O paradigm was very significant. This was due to the two facts:
|
||||
1) there are many different operations which can be requested of tape
|
||||
devices and 2) some of the tmscp operations required many separate
|
||||
1) there are many different operations which can be requested of tape
|
||||
devices and 2) some of the tmscp operations required many separate
|
||||
operations on the physical device layer to perform a single tmscp request.
|
||||
This issue was addressed by adding additional routines to the physical
|
||||
This issue was addressed by adding additional routines to the physical
|
||||
device layer (in sim_tape.c) which combined these multiple operations.
|
||||
This approach will dovetail well with a potential future addition of
|
||||
This approach will dovetail well with a potential future addition of
|
||||
operations on physical tapes as yet another supported tape format.
|
||||
|
||||
Programming Console and Multiplexer devices to leverage Asynch I/O to
|
||||
Programming Console and Multiplexer devices to leverage Asynch I/O to
|
||||
minimize 'unproductive' polling.
|
||||
|
||||
There are two goals for asynchronous Multiplexer I/O: 1) Minimize polling
|
||||
to only happen when data is available, not arbitrarily on every clock tick,
|
||||
and 2) to have polling actually happen as soon as data may be available.
|
||||
In most cases no effort is required to add Asynch I/O support to a
|
||||
multiplexer device emulation. If a device emulation takes the normal
|
||||
to only happen when data is available, not arbitrarily on every clock tick,
|
||||
and 2) to have polling actually happen as soon as data may be available.
|
||||
In most cases no effort is required to add Asynch I/O support to a
|
||||
multiplexer device emulation. If a device emulation takes the normal
|
||||
model of polling for arriving data on every simulated clock tick, then if
|
||||
Asynch I/O is enabled, the device will operate asynchronously and behave
|
||||
well. There is one restriction in this model. Specifically, the device
|
||||
emulation logic can't expect that there will be a particular number (clock
|
||||
tick rate maybe) of invocations of a unit service routine to perform polls
|
||||
in any interval of time (this is what we're trying to change, right?).
|
||||
Therefore presumptions about measuring time by counting polls is not
|
||||
valid. If a device needs to manage time related activities, then the
|
||||
device should create a separate unit which is dedicated to the timing
|
||||
activities and which explicitly schedules a different unit service routine
|
||||
for those activities as needed. Such scheduled polling should only be
|
||||
enabled when actual timing is required.
|
||||
Asynch I/O is enabled, the device will operate asynchronously and behave
|
||||
well. There is one restriction in this model. Specifically, the device
|
||||
emulation logic can't expect that there will be a particular number (clock
|
||||
tick rate maybe) of invocations of a unit service routine to perform polls
|
||||
in any interval of time (this is what we're trying to change, right?).
|
||||
Therefore presumptions about measuring time by counting polls is not
|
||||
valid. If a device needs to manage time related activities, then the
|
||||
device should create a separate unit which is dedicated to the timing
|
||||
activities and which explicitly schedules a different unit service routine
|
||||
for those activities as needed. Such scheduled polling should only be
|
||||
enabled when actual timing is required.
|
||||
|
||||
A device which is unprepared to operate asynchronously can specifically
|
||||
disable multiplexer Asynch I/O for that device by explicitly defining
|
||||
NO_ASYNCH_MUX at compile time. This can be defined at the top of a
|
||||
particular device emulation which isn't capable of asynch operation, or
|
||||
disable multiplexer Asynch I/O for that device by explicitly defining
|
||||
NO_ASYNCH_MUX at compile time. This can be defined at the top of a
|
||||
particular device emulation which isn't capable of asynch operation, or
|
||||
it can be defined globally on the compile command line for the simulator.
|
||||
Alternatively, if a specific Multiplexer device doesn't function correctly
|
||||
under the multiplexer asynchronous environment and it will never be
|
||||
revised to operate correctly, it may statically set the TMUF_NOASYNCH bit
|
||||
Alternatively, if a specific Multiplexer device doesn't function correctly
|
||||
under the multiplexer asynchronous environment and it will never be
|
||||
revised to operate correctly, it may statically set the TMUF_NOASYNCH bit
|
||||
in its unit flags field.
|
||||
|
||||
Some devices will need a small amount of extra coding to leverage the
|
||||
Multiplexer Asynch I/O capabilties. Devices which require extra coding
|
||||
Some devices will need a small amount of extra coding to leverage the
|
||||
Multiplexer Asynch I/O capabilities. Devices which require extra coding
|
||||
have one or more of the following characteristics:
|
||||
- they poll for input data on a different unit (or units) than the unit
|
||||
- they poll for input data on a different unit (or units) than the unit
|
||||
which was provided when tmxr_attach was called.
|
||||
- they poll for connections on a different unit than the unit which was
|
||||
provided when tmxr_attach was called.
|
||||
|
||||
The extra coding required for proper operation is to call
|
||||
tmxr_set_line_unit() to associate the appropriate input polling unit to
|
||||
The extra coding required for proper operation is to call
|
||||
tmxr_set_line_unit() to associate the appropriate input polling unit to
|
||||
the respective multiplexer line (ONLY if input polling is done by a unit
|
||||
different than the unit specified when the MUX was attached). If output
|
||||
different than the unit specified when the MUX was attached). If output
|
||||
polling is done on a different unit, then tmxr_set_line_output_unit()
|
||||
should be called to describe that fact.
|
||||
|
||||
Console I/O can operate asynchronously if the simulator notifies the
|
||||
tmxr/console subsystem which device unit is used by the simulator to poll
|
||||
for console input and output units. This is done by including sim_tmxr.h
|
||||
in the source module which contains the console input device definition
|
||||
and calling tmxr_set_console_units(). tmxr_set_console_units would usually
|
||||
Console I/O can operate asynchronously if the simulator notifies the
|
||||
tmxr/console subsystem which device unit is used by the simulator to poll
|
||||
for console input and output units. This is done by including sim_tmxr.h
|
||||
in the source module which contains the console input device definition
|
||||
and calling tmxr_set_console_units(). tmxr_set_console_units would usually
|
||||
be called in a device reset routine.
|
||||
|
||||
sim_tmxr consumers:
|
||||
|
@ -241,68 +241,68 @@ sim_tmxr consumers:
|
|||
- PDP-18b TT1 devices = 2, units = 1/16, lines = 16, flagbits = 0, Untested Asynch
|
||||
- SDS MUX devices = 2, units = 1/32, lines = 32, flagbits = 0, Untested Asynch
|
||||
- sim_console Good Asynch
|
||||
|
||||
Program Clock Devices to leverage Asynsh I/O
|
||||
|
||||
simh's concept of time is calibrated by counting the number of
|
||||
instructions which the simulator can execute in a given amount of wall
|
||||
clock time. Once this is determined, the appropriate value is continually
|
||||
recalibrated and used throughout a simulator to schedule device time
|
||||
related delays as needed. Historically, this was fine until modern
|
||||
Program Clock Devices to leverage Asynch I/O
|
||||
|
||||
simh's concept of time is calibrated by counting the number of
|
||||
instructions which the simulator can execute in a given amount of wall
|
||||
clock time. Once this is determined, the appropriate value is continually
|
||||
recalibrated and used throughout a simulator to schedule device time
|
||||
related delays as needed. Historically, this was fine until modern
|
||||
processors started having dynamically variable processor clock rates.
|
||||
On such host systems, the simulator's concept of time passing can vary
|
||||
On such host systems, the simulator's concept of time passing can vary
|
||||
drastically. This dynamic adjustment of the host system's execution rate
|
||||
may cause dramatic drifting of the simulated operating system's concept
|
||||
of time. Once all devices are disconnected from the calibrated clock's
|
||||
instruction count, the only concern for time in the simulated system is
|
||||
that it's clock tick be as accurate as possible. This has worked well
|
||||
in the past, however each simulator was burdened with providing code
|
||||
which facilitated managing the concept of the relationship between the
|
||||
number of instructions executed and the passage of wall clock time.
|
||||
To accomodate the needs of activities or events which should be measured
|
||||
against wall clock time (vs specific number of instructions executed),
|
||||
the simulator framework has been extended to specifically provide event
|
||||
scheduling based on elapsed wall time. A new API can be used by devices
|
||||
to schedule unit event delivery after the passage of a specific amount
|
||||
of wall clock time. The api sim_activate_after() provides this
|
||||
capability. This capability is not limited to being available ONLY when
|
||||
compiling with SIM_SYNCH_IO defined. When SIM_ASYNCH_IO is defined, this
|
||||
facility is implemented by a thread which drives the delivery of these
|
||||
events from the host system's clock ticks (interpolated as needed to
|
||||
accomodate hosts with relatively large clock ticks). When SIM_ASYNCH_IO
|
||||
is not defined, this facility is implemented using the traditional simh
|
||||
may cause dramatic drifting of the simulated operating system's concept
|
||||
of time. Once all devices are disconnected from the calibrated clock's
|
||||
instruction count, the only concern for time in the simulated system is
|
||||
that it's clock tick be as accurate as possible. This has worked well
|
||||
in the past, however each simulator was burdened with providing code
|
||||
which facilitated managing the concept of the relationship between the
|
||||
number of instructions executed and the passage of wall clock time.
|
||||
To accomodate the needs of activities or events which should be measured
|
||||
against wall clock time (vs specific number of instructions executed),
|
||||
the simulator framework has been extended to specifically provide event
|
||||
scheduling based on elapsed wall time. A new API can be used by devices
|
||||
to schedule unit event delivery after the passage of a specific amount
|
||||
of wall clock time. The api sim_activate_after() provides this
|
||||
capability. This capability is not limited to being available ONLY when
|
||||
compiling with SIM_SYNCH_IO defined. When SIM_ASYNCH_IO is defined, this
|
||||
facility is implemented by a thread which drives the delivery of these
|
||||
events from the host system's clock ticks (interpolated as needed to
|
||||
accomodate hosts with relatively large clock ticks). When SIM_ASYNCH_IO
|
||||
is not defined, this facility is implemented using the traditional simh
|
||||
calibrated clock approach. This new approach has been measured to provide
|
||||
clocks which drift far less than the drift realized in prior simh versions.
|
||||
Using the released simh v3.9-0 vax simulator with idling enabled, the clock
|
||||
drifted some 4 minutes in 35 minutes time (approximately 10%). The same OS
|
||||
disk also running with idling enabled booted for 4 hours had less that 5
|
||||
clocks which drift far less than the drift realized in prior simh versions.
|
||||
Using the released simh v3.9-0 vax simulator with idling enabled, the clock
|
||||
drifted some 4 minutes in 35 minutes time (approximately 10%). The same OS
|
||||
disk also running with idling enabled booted for 4 hours had less that 5
|
||||
seconds of clock drift (approximately 0.03%).
|
||||
|
||||
Co-Scheduling Clock and Multiplexer (or other devices)
|
||||
|
||||
Many simulator devices have needs to periodically executed with timing on the
|
||||
order of the simulated system's clock ticks. There are numerous reasons for
|
||||
this type of execution. Meanwhile, many of these events aren't particular
|
||||
this type of execution. Meanwhile, many of these events aren't particular
|
||||
about exactly when they execute as long as they execute frequently enough.
|
||||
Frequently executing events has the potential to interfere with a simulator's
|
||||
attempts to idle when the simulated system isn't actually doing useful work.
|
||||
|
||||
Interactions with attempts to 'co-schedule' multiplexer polling with clock
|
||||
ticks can cause strange simulator behaviors. These strange behaviors only
|
||||
ticks can cause strange simulator behaviors. These strange behaviors only
|
||||
happen under a combination of conditions:
|
||||
1) a multiplexer device is defined in the simulator configuration,
|
||||
2) the multiplexor device is NOT attached, and thus is not being managed by
|
||||
the asynchronous multiplexer support
|
||||
3) the multiplexer device schedules polling (co-scheduled) when not
|
||||
3) the multiplexer device schedules polling (co-scheduled) when not
|
||||
attached (such polling will never produce any input, so this is probably
|
||||
a bug).
|
||||
In prior simh versions support for clock co-scheduling was implmented
|
||||
In prior simh versions support for clock co-scheduling was implemented
|
||||
separately by each simulator, and usually was expressed by code of the form:
|
||||
sim_activate (uptr, clk_cosched (tmxr_poll));
|
||||
As a part of asynchronous timer support, the simulator framework has been
|
||||
As a part of asynchronous timer support, the simulator framework has been
|
||||
extended to generically provide clock co-scheduling support. The use of this
|
||||
new capability requires an initial call (usually in the clock device reset
|
||||
routing) of the form:
|
||||
new capability requires an initial call (usually in the clock device reset
|
||||
routing) of the form:
|
||||
sim_register_clock_unit (&clk_unit);
|
||||
Once the clock unit has been registered, co-scheduling is achieved by replacing
|
||||
the earlier sim_activate with the following:
|
||||
|
@ -311,8 +311,8 @@ the earlier sim_activate with the following:
|
|||
Run time requirements to use SIM_ASYNCH_IO.
|
||||
The Posix threads API (pthreads) is required for asynchronous execution.
|
||||
Most *nix platforms have these APIs available and on these platforms
|
||||
simh is typically built with these available since on these platforms,
|
||||
pthreads is required for simh networking support. Windows can also
|
||||
simh is typically built with these available since on these platforms,
|
||||
pthreads is required for simh networking support. Windows can also
|
||||
utilize the pthreads APIs if the compile and run time support for the
|
||||
win32Pthreads package has been installed on the build system.
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ This file contains information about the SIMH Ethernet package.
|
|||
-------------------------------------------------------------------------------
|
||||
|
||||
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
|
||||
DELQA-T (M7516-YM), DELQA (M7516) and DEQNA (M7504) Q-bus Ethernet cards
|
||||
for the SIMH emulator.
|
||||
|
||||
The XU emulator is a host-independent software emulation of Digital's DEUNA
|
||||
|
@ -25,29 +25,29 @@ most of the undesirable traffic. You will only see "excessive" traffic if you
|
|||
are on a direct or hub(repeater) segment.
|
||||
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
||||
Integrated Universal TUN/TAP support provides another solution for the above
|
||||
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,
|
||||
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 and OSX. Each of these
|
||||
platforms has some way to create a tap pseudo device (and possibly then to
|
||||
tested on include: Linux, FreeBSD, OpenBSD, NetBSD and OSX. Each of these
|
||||
platforms has some way to create a tap pseudo device (and possibly then to
|
||||
bridge it with a physical network interface).
|
||||
|
||||
The following steps were performed to get a working SIMH vax simulator
|
||||
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):
|
||||
|
@ -79,7 +79,7 @@ Linux (Ubuntu 10.04):
|
|||
/sbin/ifconfig tap0 0.0.0.0
|
||||
|
||||
# Run simulator and "attach xq tap:tap0"
|
||||
|
||||
|
||||
|
||||
Linux (Fedora Core 18, 20, CentOS, RedHat, etc.):
|
||||
yum install gcc
|
||||
|
@ -90,7 +90,7 @@ Linux (Centos 6.x):
|
|||
yum install gcc
|
||||
yum install libpcap-devel
|
||||
yum install uml_utilities
|
||||
|
||||
|
||||
OpenBSD (OpenBSD 4.6)
|
||||
|
||||
/sbin/ifconfig tun0 create
|
||||
|
@ -103,10 +103,10 @@ OpenBSD (OpenBSD 4.6)
|
|||
/sbin/brconfig bridge0 up
|
||||
|
||||
# Run simulator and "attach xq tap:tun0"
|
||||
|
||||
|
||||
FreeBSD (FreeBSD 11.3)
|
||||
|
||||
/sbin/sysctl net.link.tap.up_on_open=1
|
||||
/sbin/sysctl net.link.tap.up_on_open=1
|
||||
/sbin/ifconfig tap0 create
|
||||
/sbin/ifconfig tap0 up
|
||||
|
||||
|
@ -131,38 +131,38 @@ NetBSD (NetBSD 5.0.2)
|
|||
OSX (Snow Leopard)
|
||||
OSX Does NOT have native support for tun/tap interfaces. It also does not have native
|
||||
support for bridging.
|
||||
|
||||
Mattias Nissler has created tun/tap functionality available at http://tuntaposx,sourceforge.net/
|
||||
|
||||
|
||||
Mattias Nissler has created tun/tap functionality available at http://tuntaposx.sourceforge.net/
|
||||
|
||||
We'll punt on bridging for the sake of this example and move on to use a basic tap
|
||||
based internal network so a host and guest can communicate directly.
|
||||
|
||||
Download the install package from:
|
||||
|
||||
Download the install package from:
|
||||
http://sourceforge.net/projects/tuntaposx/files/tuntap/20111101/tuntap_20111101.tar.gz
|
||||
|
||||
|
||||
Expand the tarball to a directory.
|
||||
Invoke the package installer tuntap_20111101.pkg
|
||||
Click through the various prompts accepting things and eventually installing the package.
|
||||
|
||||
|
||||
# Build and Run simulator and:
|
||||
sim> attach xq tap:tap0
|
||||
sim> ! ifconfig tap0 192.168.6.1 netmask 255.255.255.0
|
||||
|
||||
Simulated system uses IP address 192.168.6.2 and host uses 192.168.6.1
|
||||
Simulated system uses IP address 192.168.6.2 and host uses 192.168.6.1
|
||||
and things work.
|
||||
You must run as root for this to work.
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
An alternative to direct pcap and tun/tap networking on *nix environments is
|
||||
An alternative to direct pcap and tun/tap networking on *nix environments is
|
||||
VDE (Virtual Distributed Ethernet).
|
||||
|
||||
Note 1: Using vde based networking is likely more flexible, but it isn't
|
||||
nearly as efficient. Host OS overhead will always be higher when
|
||||
vde networking is used as compared to native pcap and/or tun/tap
|
||||
Note 1: Using vde based networking is likely more flexible, but it isn't
|
||||
nearly as efficient. Host OS overhead will always be higher when
|
||||
vde networking is used as compared to native pcap and/or tun/tap
|
||||
networking.
|
||||
Note 2: Root access will likely be needed to configure or start the vde
|
||||
Note 2: Root access will likely be needed to configure or start the vde
|
||||
environment prior to starting a simulator which may use it.
|
||||
Note 3: Simulators running using VDE networking can run without root
|
||||
Note 3: Simulators running using VDE networking can run without root
|
||||
privilege.
|
||||
|
||||
Linux (Ubuntu 11.10):
|
||||
|
@ -172,44 +172,44 @@ Linux (Ubuntu 11.10):
|
|||
|
||||
vde_switch -s /tmp/switch1 -tap tap0 -m 666
|
||||
ifconfig tap0 192.168.6.1 netmask 255.255.255.0 up
|
||||
|
||||
|
||||
# Build and Run simulator and:
|
||||
sim> attach xq vde:/tmp/switch1 #simulator uses IP address 192.168.6.2
|
||||
|
||||
OSX:
|
||||
The macports package manager (http://www.macports.org) can be used to
|
||||
The macports package manager (http://www.macports.org) can be used to
|
||||
install the net/vde2 package.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Another alternative to direct pcap and tun/tap networking on all environments is
|
||||
Another alternative to direct pcap and tun/tap networking on all environments is
|
||||
NAT (SLiRP) networking. NAT networking is limited to only IP network protocols
|
||||
so DECnet, LAT and Clusting can't work on a NAT connected interface, but this may
|
||||
be the easiest solution for many folks.
|
||||
|
||||
sim> attach xq nat:
|
||||
|
||||
The simulator can use static IP addresses of 10.0.2.4 thru 10.0.2.14 with a
|
||||
|
||||
The simulator can use static IP addresses of 10.0.2.4 thru 10.0.2.14 with a
|
||||
netmask of 255.255.255.0 and a gateway of 10.0.2.2 and a nameserver of 10.0.2.3.
|
||||
If the simulated machine uses DHCP it will get the address 10.0.2.15. Various
|
||||
NAT based parameters can be configured on the attach command. HELP XQ ATTACH
|
||||
will provide useful information. Host to simulator connectivitiy can be
|
||||
achieved for a simulator which gets its IP address via DHCP with the following
|
||||
If the simulated machine uses DHCP it will get the address 10.0.2.15. Various
|
||||
NAT based parameters can be configured on the attach command. HELP XQ ATTACH
|
||||
will provide useful information. Host to simulator connectivity can be
|
||||
achieved for a simulator which gets its IP address via DHCP with the following
|
||||
command:
|
||||
|
||||
sim> attach xq nat:tcp=2323:10.0.2.15:23,tcp=2121:10.0.2.15:21
|
||||
|
||||
The host computer can telnet to localhost:2323 to reach the simulator via
|
||||
|
||||
The host computer can telnet to localhost:2323 to reach the simulator via
|
||||
telnet, etc.
|
||||
|
||||
Additionally NAT based networking is useful to allow host systems with WiFi
|
||||
Additionally NAT based networking is useful to allow host systems with WiFi
|
||||
networking to a) reach the simulated system and b) allow the simulated system
|
||||
to reach out to the Internet.
|
||||
|
||||
Note: As mentioned above, NAT networking is specifically capable of providing
|
||||
TCP/IP connectivity. Only expect TCP and UDP traffic to pass through
|
||||
the interface. Do not expect ICMP traffic (ping mostly) to traverse
|
||||
the NAT boundary. This restriction is a conseqence of host platform
|
||||
and network limitations regarding direct user mode code generating ICMP
|
||||
Note: As mentioned above, NAT networking is specifically capable of providing
|
||||
TCP/IP connectivity. Only expect TCP and UDP traffic to pass through
|
||||
the interface. Do not expect ICMP traffic (ping mostly) to traverse
|
||||
the NAT boundary. This restriction is a consequence of host platform
|
||||
and network limitations regarding direct user mode code generating ICMP
|
||||
packets.
|
||||
|
||||
|
||||
|
@ -217,34 +217,34 @@ Note: As mentioned above, NAT networking is specifically capable of providing
|
|||
|
||||
Windows notes:
|
||||
1. The Npcap package available from https://nmap.org/npcap is the preferred
|
||||
interface for Windows 7 onward since the original WinPCAP 4.1.3 package
|
||||
interface for Windows 7 onward since the original WinPCAP 4.1.3 package
|
||||
from https://www.winpcap.org/install/bin/WinPcap_4_1_3.exe is no longer
|
||||
developed or supported. These packages for windows simulate the libpcap
|
||||
package that is freely available for un*x systems.
|
||||
developed or supported. These packages for windows simulate the libpcap
|
||||
package that is freely available for un*x systems.
|
||||
|
||||
2. You must *install* the npcap or WinPCAP runtime package.
|
||||
|
||||
3. The first time the npcap/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 "npf" driver
|
||||
to autostart.
|
||||
Current Npcap and WinPcap installers provide an option to configure this
|
||||
3. The first time the npcap/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 "npf" driver
|
||||
to autostart.
|
||||
Current Npcap and WinPcap installers provide an option to configure this
|
||||
at installation time, so if that choice is made, then there is no need for
|
||||
administrator privileged to run simulators with network support.
|
||||
|
||||
|
||||
Building on Windows:
|
||||
You should be able to build with any of the free compiler environments
|
||||
available on the Windows platform. If you want to use the Visual C++
|
||||
Express 2008 or 2010 interactive development environments, read the file
|
||||
You should be able to build with any of the free compiler environments
|
||||
available on the Windows platform. If you want to use the Visual C++
|
||||
Express 2008 or 2010 interactive development environments, read the file
|
||||
".\Visual Studio Projects\0ReadMe_Projects.txt" for details about the
|
||||
required dependencies. Alternatively, you can build simh with networking
|
||||
support using the MinGW GCC compiler environment (32 bit) or the cygwin
|
||||
environment. Each of these Visual C++, MinGW and cygwin build environments
|
||||
require Npcap or WinPcap and Posix threading packages being available.
|
||||
These should be located in a directory structure parallel to the current
|
||||
support using the MinGW GCC compiler environment (32 bit) or the cygwin
|
||||
environment. Each of these Visual C++, MinGW and cygwin build environments
|
||||
require Npcap or WinPcap and Posix threading packages being available.
|
||||
These should be located in a directory structure parallel to the current
|
||||
simulator source directory.
|
||||
|
||||
|
||||
For Example, the directory structure should look like:
|
||||
|
||||
.../simh/simh-master/VAX/vax_cpu.c
|
||||
|
@ -261,16 +261,16 @@ Building on Windows:
|
|||
|
||||
|
||||
There are Windows batch files provided to initiate compiles using the MinGW
|
||||
compiler tool chain. These batch files are located in the same directory
|
||||
as this file and are called: build_mingw.bat, build_mingw_ether.bat, and
|
||||
build_mingw_noasync.bat. These batch files each presume that the MinGW
|
||||
compiler tool chain. These batch files are located in the same directory
|
||||
as this file and are called: build_mingw.bat, build_mingw_ether.bat, and
|
||||
build_mingw_noasync.bat. These batch files each presume that the MinGW
|
||||
toolchain is either in the current path or, if not that it is located at
|
||||
C:\MinGW\bin. These batch files merely invoke the MinGW make (GNU make)
|
||||
passing some specific arguments along with the optional arguments the batch
|
||||
passing some specific arguments along with the optional arguments the batch
|
||||
file is invoked with.
|
||||
|
||||
The current windows network built binaries will run on any system without
|
||||
regard to whether or not Npcap or WinPcap is installed, and will provide
|
||||
|
||||
The current windows network built binaries will run on any system without
|
||||
regard to whether or not Npcap or WinPcap is installed, and will provide
|
||||
Network functionality when Npcap or WinPcap is available.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
@ -282,19 +282,19 @@ 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. All current Linux
|
||||
distributions provide a libpcap-dev package which has the needed version
|
||||
of libpcap and the required components to build applications using it.
|
||||
If you are running an older Linux OS, you can download and build the required
|
||||
library from www.tcpdump.org - see the comments at the top of Sim_ether.c
|
||||
for details.
|
||||
of libpcap and the required components to build applications using it.
|
||||
If you are running an older Linux OS, you can download and build the required
|
||||
library from www.tcpdump.org - see the comments at the top of Sim_ether.c
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
Starting the "npf" driver at boot time means that simulators do
|
||||
not need to run with administrator privileges.
|
||||
b) For more recent Linux systems, The concepts leveraging "Filesystem
|
||||
|
@ -303,76 +303,76 @@ for details.
|
|||
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
|
||||
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
|
||||
Additional alternative methods for avoiding the 'run as root' requirement
|
||||
will be welcomed.
|
||||
|
||||
2. If you want to use TAP devices, and any surrounding system network/bridge
|
||||
setup must be done before running SIMH. However, once that is done
|
||||
setup must be done before running SIMH. However, once that is done
|
||||
(possibly at system boot time), using the TAP devices can be done without
|
||||
root privileges.
|
||||
|
||||
Building on Linux, {Free|Net|Open}BSD, OS/X, Solaris, other *nix:
|
||||
|
||||
1. Get/make/install the libpcap-dev package (or libpcap-devel) for your
|
||||
1. Get/make/install the libpcap-dev package (or libpcap-devel) for your
|
||||
operating system. Sources:
|
||||
All : http://www.tcpdump.org/
|
||||
Older versions of libpcap can be found, for various systems, at:
|
||||
Linux :
|
||||
Debian Based distributions:
|
||||
Linux :
|
||||
Debian Based distributions:
|
||||
# apt-get install libpcap-dev
|
||||
RedHat/Fedora Based distributions:
|
||||
# yum install libpcap-devel
|
||||
|
||||
OS/X : The libpcap components are installed as part of the Xcode
|
||||
developer package. Instructions to install Xcode on various
|
||||
OSX versions are available at:
|
||||
|
||||
OS/X : The libpcap components are installed as part of the Xcode
|
||||
developer package. Instructions to install Xcode on various
|
||||
OSX versions are available at:
|
||||
https://guide.macports.org/chunked/installing.xcode.html
|
||||
Be sure to install the command line tools which are installed
|
||||
with the command "xcode-select --install" in more recent
|
||||
with the command "xcode-select --install" in more recent
|
||||
versions of the Apple developer support.
|
||||
|
||||
|
||||
HP-UX : ftp://hpux.connect.org.uk/hpux/Networking/Admin/
|
||||
|
||||
NOTE: The 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.
|
||||
The OS provided libpcap-dev components will be prefereable
|
||||
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.
|
||||
The OS provided libpcap-dev components will be preferable
|
||||
to a package built from www.tcpdump.org sources. This is
|
||||
due to the fact that various OS supplied packages will
|
||||
depend on the OS supplied libpcap. The improper build or
|
||||
install of the www.tcpdump.org source package can conflict
|
||||
with the OS provided one and break the OS provided
|
||||
due to the fact that various OS supplied packages will
|
||||
depend on the OS supplied libpcap. The improper build or
|
||||
install of the www.tcpdump.org source package can conflict
|
||||
with the OS provided one and break the OS provided
|
||||
applications (i.e. tcpdump and/or wireshark) as well as
|
||||
not working correctly for use by simh.
|
||||
|
||||
2. If you install the vendor supplied libpcap-dev package then the simh
|
||||
makefile will automatically use the vendor supplied library without any
|
||||
additional arguments. If you have downloaded and built libpcap from
|
||||
makefile will automatically use the vendor supplied library without any
|
||||
additional arguments. If you have downloaded and built libpcap from
|
||||
www.tcpdump.org, then the existing makefile will detect that this is
|
||||
the case and try to use that.
|
||||
|
||||
3. The makefile defaults to building simulators with network support which
|
||||
dynamically load the libpcap library. This means that the same simulator
|
||||
binaries will run on any system whether or not libpcap is installed. If
|
||||
you want to force direct libpcap linking during a build you do so by
|
||||
typing 'make USE_NETWORK=1'. You must build with gcc to do this. There
|
||||
binaries will run on any system whether or not libpcap is installed. If
|
||||
you want to force direct libpcap linking during a build you do so by
|
||||
typing 'make USE_NETWORK=1'. You must build with gcc to do this. There
|
||||
is no observable benefit to statically linking against libpcap. Support
|
||||
for statically linking libpcap ia deprecated on all platforms except
|
||||
for statically linking libpcap is deprecated on all platforms except
|
||||
Linux and OS X where it has already been removed.
|
||||
|
||||
4. Some platforms (HP-UX in particular) may not have vendor supplied libpcap
|
||||
|
||||
4. Some platforms (HP-UX in particular) may not have vendor supplied libpcap
|
||||
components available and installed with the operating system. The packages
|
||||
which are available for this platform install include and library files in
|
||||
user specified locations. When building on these platforms the library
|
||||
which are available for this platform install include and library files in
|
||||
user specified locations. When building on these platforms the library
|
||||
path must be specified on the make command line. This can be done with:
|
||||
'make LPATH=/usr/lib:/usr/local/lib'
|
||||
|
||||
|
@ -380,7 +380,7 @@ Building on Linux, {Free|Net|Open}BSD, OS/X, Solaris, other *nix:
|
|||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
OpenVMS Alpha and OpenVMS Integrety (IA64) notes:
|
||||
OpenVMS Alpha and OpenVMS Integrity (IA64) notes:
|
||||
1. Ethernet support will only work on Alpha VMS 7.3-1 or later, which is
|
||||
when required VCI promiscuous mode support was added. Hobbyists can
|
||||
get the required version of VMS from the OpenVMS Alpha Hobbyist Kit 3.0.
|
||||
|
@ -413,13 +413,13 @@ OpenVMS Alpha and OpenVMS Integrety (IA64) notes:
|
|||
adapter prior trying to connect with SIMH, or the host may crash.
|
||||
The execlet is not written to create an I/O structure for the device.
|
||||
|
||||
Building on OpenVMS Alpha and OpenVMS Integrety (IA64):
|
||||
Building on OpenVMS Alpha and OpenVMS Integrity (IA64):
|
||||
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,
|
||||
VAX780, and PDP11. 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:
|
||||
|
||||
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.
|
||||
3. Build the simulator(s) with MMS or MMK:
|
||||
|
@ -441,7 +441,7 @@ Other testers have reported that RSX with DECNET and the NetBSD operating
|
|||
systems also work. RSTS/E v10.1 has preliminary support - RSTS/E boots and
|
||||
enables the XH (XQ) device - DECNET and LAT software have not been tested.
|
||||
|
||||
The XU module has been tested by a third party for basic packet functionality
|
||||
The XU module has been tested by a third party for basic packet functionality
|
||||
under a modified RSX11M environment. I am unable to test it in-house until
|
||||
someone can arrange to send me a disk image containing a stock RSTS/E or
|
||||
RSX11M+ system image that also contains DECNET, LAT, and/or TCP/IP software.
|
||||
|
@ -486,9 +486,9 @@ Dave
|
|||
===============================================================================
|
||||
Change Log
|
||||
===============================================================================
|
||||
|
||||
|
||||
01-Mar-12 AGN Added support for building using Cygwin on Windows
|
||||
01-Mar-12 MP Made host NIC address detection more robust on *nix platforms
|
||||
01-Mar-12 MP Made host NIC address detection more robust on *nix platforms
|
||||
and mad it work when compiling under Cygwin
|
||||
29-Feb-12 MP Fixed MAC Address Conflict detection support
|
||||
28-Feb-12 MP Fixed overrun bug in eth_devices which caused SEGFAULTs
|
||||
|
@ -498,95 +498,95 @@ Dave
|
|||
17-Nov-11 MP Added dynamic loading of libpcap on *nix platforms
|
||||
30-Oct-11 MP Added support for vde (Virtual Distributed Ethernet) networking
|
||||
29-Oct-11 MP Added support for integrated Tap networking interfaces on OSX
|
||||
17-Aug-11 RMS Fix from Sergey Oboguev relating to XU and XQ Auto Config and
|
||||
17-Aug-11 RMS Fix from Sergey Oboguev relating to XU and XQ Auto Config and
|
||||
vector assignments
|
||||
12-Aug-11 MP Cleaned up payload length determination
|
||||
Fixed race condition detecting reflections when threaded
|
||||
Fixed race condition detecting reflections when threaded
|
||||
reading and writing is enabled
|
||||
07-Jul-11 MB VMS Pcap (from Mike Burke)
|
||||
- Fixed Alpha issues
|
||||
- Added OpenVMS Integrety support
|
||||
- Added OpenVMS Integrity support
|
||||
20-Apr-11 MP Fixed save/restore behavior
|
||||
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
|
||||
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
|
||||
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).
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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)
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
@ -594,7 +594,7 @@ Dave
|
|||
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
|
||||
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
|
||||
|
@ -608,21 +608,21 @@ Dave
|
|||
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
|
||||
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
|
||||
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
|
||||
- Fixed bug when the simulated device doesn't need crc
|
||||
in packet data which is read.
|
||||
- Added call to pcap_setmintocopy to minimize packet
|
||||
- Added call to pcap_setmintocopy to minimize packet
|
||||
delivery latencies.
|
||||
- Added ethq_destroy and used it to avoid a memory leak in
|
||||
eth_close.
|
||||
|
@ -632,8 +632,8 @@ Dave
|
|||
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
|
||||
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
|
||||
|
@ -719,7 +719,7 @@ Dave
|
|||
1. Added VMScluster support (thanks to Mark Pizzolato)
|
||||
2. Verified VAX remote boot functionality (>>>B XQA0)
|
||||
3. Added major performance enhancements (thanks to Mark Pizzolato again)
|
||||
4. Changed _DEBUG tracers to XQ_DEBUG and ETH_DEBUG
|
||||
4. Changed _DEBUG tracers to XQ_DEBUG and ETH_DEBUG
|
||||
5. Added local packet processing
|
||||
6. Added system id broadcast
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ if (NOT CMAKE_CONFIGURATION_TYPES)
|
|||
endif ()
|
||||
|
||||
# SIMH_SYSTEM_ID: Roughly analogous to the autoconf system triple. Used (almost exclusively)
|
||||
# as part of the depedencies' top-level directory name.
|
||||
# as part of the dependencies' top-level directory name.
|
||||
set(SIMH_SYSTEM_ID ${CMAKE_SYSTEM_NAME})
|
||||
string(REPLACE "." ";" version_list ${CMAKE_SYSTEM_VERSION})
|
||||
list(GET version_list 0 version_major)
|
||||
|
@ -163,9 +163,9 @@ if (NOT DEFINED MAC_UNIVERSAL)
|
|||
else ()
|
||||
set(MAC_UNIVERSAL_OPTVAL ${MAC_UNIVERSAL})
|
||||
if (MAC_UNIVERSAL_OPTVAL)
|
||||
message(STATUS "macOS unversal binaries WILL BE BUILT.")
|
||||
message(STATUS "macOS universal binaries WILL BE BUILT.")
|
||||
else ()
|
||||
message(STATUS "macOS unversal binaries NOT WILL BE BUILT.")
|
||||
message(STATUS "macOS universal binaries NOT WILL BE BUILT.")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
|
@ -247,7 +247,7 @@ set(DEP_CMAKE_ARGS "-Wno-dev" "--no-warn-unused-cli")
|
|||
if (NOT (USING_VCPKG OR NO_DEP_BUILD) AND NOT EXISTS ${SIMH_DEP_TOPDIR})
|
||||
message(STATUS "Creating dependency library directory hierarchy")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${SIMH_DEP_TOPDIR} ${SIMH_DEP_TOPDIR}/include ${SIMH_DEP_TOPDIR}/lib
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${SIMH_DEP_TOPDIR} ${SIMH_DEP_TOPDIR}/include ${SIMH_DEP_TOPDIR}/lib
|
||||
${SIMH_DEP_TOPDIR}/bin
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
)
|
||||
|
@ -297,7 +297,7 @@ include(platform-quirks)
|
|||
|
||||
# Find packages, arrange for dependency download/compile/install:
|
||||
#
|
||||
# SIMH_BUILD_DEPS is the list of the dependecies' names, for pretty-printing.
|
||||
# SIMH_BUILD_DEPS is the list of the dependencies' names, for pretty-printing.
|
||||
# SIMH_DEP_TARGETS is the list of dependency targets' names that we'll actually build.
|
||||
|
||||
set(SIMH_BUILD_DEPS)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
- [Why CMake?](#why-cmake)
|
||||
- [Before You Begin Building...](#before-you-begin-building)
|
||||
- [Toolchains and Tools](#toolchains-and-tools)
|
||||
- [Ninja: "failed recompaction: Permission denied"](#ninja-file-recompation-permission-denied)
|
||||
- [Ninja: "failed recompaction: Permission denied"](#ninja-file-recompaction-permission-denied)
|
||||
- [Windows XP-compatible/Server 2003 binaries](#windows-xp-compatibleserver-2003-binaries)
|
||||
- [Feature Libraries](#feature-libraries)
|
||||
- [Linux, macOS and MinGW-w64](#linux-macos-and-mingw-w64)
|
||||
|
@ -43,7 +43,7 @@ framework. A sample of the supported build environments include:
|
|||
- Unix Makefiles
|
||||
- [MinGW Makefiles][mingw64]
|
||||
- [Ninja][ninja]
|
||||
- macOS XCode
|
||||
- macOS Xcode
|
||||
- MS Visual Studio solutions (2015, 2017, 2019, 2022)
|
||||
- IDE build wrappers ([Sublime Text][sublime] and [CodeBlocks][codeblocks])
|
||||
|
||||
|
@ -189,7 +189,7 @@ to select a 32-bit target architecture and the `v141_xp` toolkit.
|
|||
|
||||
_VS2022_: Install the `v141_xp` tools
|
||||
|
||||
Start the Visual Studio Installler, whether this is a new VS2022 install or
|
||||
Start the Visual Studio Installer, whether this is a new VS2022 install or
|
||||
modifying an existing installation.
|
||||
|
||||
- New install
|
||||
|
@ -219,7 +219,7 @@ the [command line](#cmake-command-line) or [via the IDE](#xp-compatible-build-vi
|
|||
|
||||
_VS2019_: Install the `v141_xp` tools.
|
||||
|
||||
Start the Visual Studio Installler, whether this is a new VS2019 install or
|
||||
Start the Visual Studio Installer, whether this is a new VS2019 install or
|
||||
modifying an existing installation.
|
||||
|
||||
- New installation: Follow the VS 2022 "New install" instructions. The steps are
|
||||
|
@ -373,7 +373,7 @@ Setup and Usage:
|
|||
PS C:\...\vcpkg> cd ..\open-simh
|
||||
PS C:\...\open-simh>
|
||||
```
|
||||
Then set the `VCPKG_ROOT` environment variable to the `vcpkg` installaton directory.
|
||||
Then set the `VCPKG_ROOT` environment variable to the `vcpkg` installation directory.
|
||||
|
||||
[^1]: `vcpkg` does not support the `v141_xp` toolkit required to compile Windows
|
||||
XP binaries. Windows XP is a target platform that SIMH can hopefully deprecate
|
||||
|
@ -1033,11 +1033,11 @@ within the IDE. The walkthrough provides directions for VS 2022 and VS 2019.
|
|||
`x64-Release` configuration. And wait for reconfiguration to finish (again.)
|
||||
|
||||
5. Select `Build All` from the `Build` menu, or equivalently chord `Ctrl-Shift-B`
|
||||
on the keyboard, to start the dependecy feature library superbuild.
|
||||
on the keyboard, to start the dependency feature library superbuild.
|
||||
|
||||
- When all dependency feature libraries have been built, the build process
|
||||
__will__ unexpectedly terminate with a _"failed recompaction: Permission
|
||||
denied"_ error (see [this `ninja` note](#ninja-file-recompation-permission-denied).)
|
||||
denied"_ error (see [this `ninja` note](#ninja-file-recompaction-permission-denied).)
|
||||
|
||||
Choose `Delete Cache and Reconfigure` from the `Project` menu. This will
|
||||
cause CMake to reconfigure the project and detect the dependency feature
|
||||
|
@ -1141,7 +1141,7 @@ add_simulator(3b2
|
|||
TEST 3b2)
|
||||
```
|
||||
|
||||
`add_simulator` is relatively self explanitory:
|
||||
`add_simulator` is relatively self explanatory:
|
||||
|
||||
- The first argument is the simulator's executable name: `3b2`. This generates
|
||||
an executable named `3b2` on Unix platforms or `3b2.exe` on Windows.
|
||||
|
|
|
@ -99,7 +99,7 @@
|
|||
|
||||
#### CDC 1700 simulator from John Forecast
|
||||
|
||||
#### Hans-Åke Lund has implemented an SCELBI (SCientic-ELectronics-BIology) simulator.
|
||||
#### Hans-Åke Lund has implemented an SCELBI (SCientific-ELectronics-BIology) simulator.
|
||||
|
||||
#### IBM 650 simulator from Roberto Sancho Villa
|
||||
|
||||
|
@ -351,7 +351,7 @@ The EXPECT command now exists to provide a means of reacting to simulator output
|
|||
|
||||
#### Help
|
||||
|
||||
The built-in help system provides a heirarchical oriented help command interface.
|
||||
The built-in help system provides a hierarchical oriented help command interface.
|
||||
In addition, there is explicit support for per device help:
|
||||
|
||||
HELP dev
|
||||
|
@ -600,7 +600,7 @@ This link will return a file called simh-vms-pcap.zip which should be unpacked a
|
|||
$ unzip -a simh-vms-pcap.zip
|
||||
$ rename [.simh-vms-pcap]pcap-vms.dir []
|
||||
|
||||
The PCAP-VMS components are presumed (by the descript.mms file) to be
|
||||
The PCAP-VMS components are presumed (by the descrip.mms file) to be
|
||||
located in a directory at the same level as the directory containing the
|
||||
simh source files. For example, if these exist here:
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
:: If this procedure is not invoked from a Developer command prompt
|
||||
:: then the VS2008 tools are preferred if VS2008 is installed,
|
||||
:: otherwise the installed Visual Studio tools will be used
|
||||
:: prefering newer Visual Studio versions over older ones.
|
||||
:: preferring newer Visual Studio versions over older ones.
|
||||
::
|
||||
:: If this procedure is invoked from a Developer command prompt
|
||||
:: then the tool chain provided with the command prompt is used
|
||||
|
|
64
descrip.mms
64
descrip.mms
|
@ -10,7 +10,7 @@
|
|||
# HP C V7.3-009-48GBT (AXP), HP C V7.2-001 (IA64) and v6.4-005(VAX).
|
||||
#
|
||||
# Notes: On VAX, the PDP-10, Eclipse, IBM 7094 and BESM6 simulators will
|
||||
# not be built due to the fact that INT64 is required for these
|
||||
# not be built due to the fact that INT64 is required for these
|
||||
# simulators.
|
||||
#
|
||||
# This build script will accept the following build options.
|
||||
|
@ -25,9 +25,9 @@
|
|||
# ECLIPSE Just Build The Data General Eclipse.
|
||||
# GRI Just Build The GRI Corporation GRI-909.
|
||||
# LGP Just Build The Royal-McBee LGP-30.
|
||||
# H316 Just Build The Honewell 316/516.
|
||||
# HP2100 Just Build The Hewlett-Packard HP-2100.
|
||||
# HP3000 Just Build The Hewlett-Packard HP-3000.
|
||||
# H316 Just Build The Honeywell 316/516.
|
||||
# HP2100 Just Build The Hewlett-Packard HP-2100.
|
||||
# HP3000 Just Build The Hewlett-Packard HP-3000.
|
||||
# I1401 Just Build The IBM 1401.
|
||||
# I1620 Just Build The IBM 1620.
|
||||
# I7094 Just Build The IBM 7094.
|
||||
|
@ -75,22 +75,22 @@
|
|||
# VAX8600 Just Build The DEC VAX8600.
|
||||
# CLEAN Will Clean Files Back To Base Kit.
|
||||
#
|
||||
# To build with debugging enabled (which will also enable traceback
|
||||
# To build with debugging enabled (which will also enable traceback
|
||||
# information) use..
|
||||
#
|
||||
# MMK/MACRO=(DEBUG=1)
|
||||
#
|
||||
# This will produce an executable named {Simulator}-{I64|VAX|AXP}-DBG.EXE
|
||||
#
|
||||
# To build on older Alpha VMS platforms, SIM_ASYNCH_IO must be disabled.
|
||||
# To build on older Alpha VMS platforms, SIM_ASYNCH_IO must be disabled.
|
||||
# use..
|
||||
#
|
||||
# MMK/MACRO=(NOASYNCH=1)
|
||||
#
|
||||
# On AXP and IA64 the VMS PCAP components are built and used to provide
|
||||
# On AXP and IA64 the VMS PCAP components are built and used to provide
|
||||
# network support for the VAX and PDP11 simulators.
|
||||
#
|
||||
# The AXP PCAP components can only be built using a version of the
|
||||
# The AXP PCAP components can only be built using a version of the
|
||||
# DEC/Compaq/HP Compiler version V6.5-001 or later. To build using an
|
||||
# older compiler, networking support must be disabled. Use...
|
||||
#
|
||||
|
@ -716,7 +716,7 @@ S3_OPTIONS = /INCL=($(SIMH_DIR),$(S3_DIR))/DEF=($(CC_DEFS))
|
|||
#
|
||||
SDS_DIR = SYS$DISK:[.SDS]
|
||||
SDS_LIB = $(LIB_DIR)SDS-$(ARCH).OLB
|
||||
SDS_SOURCE = $(SDS_DIR)SDS_CPU.C,$(SDS_DIR)SDS_DRM.C,$(SDS_DIR)SDS_DSK.C,\
|
||||
SDS_SOURCE = $(SDS_DIR)SDS_CPU.C,$(SDS_DIR)SDS_DRM.C,$(SDS_DIR)SDS_DSK.C,\
|
||||
$(SDS_DIR)SDS_IO.C,$(SDS_DIR)SDS_LP.C,$(SDS_DIR)SDS_MT.C,\
|
||||
$(SDS_DIR)SDS_MUX.C,$(SDS_DIR)SDS_RAD.C,$(SDS_DIR)SDS_STDDEV.C,\
|
||||
$(SDS_DIR)SDS_SYS.C,$(SDS_DIR)SDS_CR.C,$(SDS_DIR)SDS_CP.C
|
||||
|
@ -1431,7 +1431,7 @@ ALL : ALTAIR GRI H316 HP2100 I1401 I1620 IBM1130 ID16 ID32 \
|
|||
$! No further actions necessary
|
||||
.ENDIF
|
||||
|
||||
CLEAN :
|
||||
CLEAN :
|
||||
$!
|
||||
$! Clean out all targets and building Remnants
|
||||
$!
|
||||
|
@ -1578,7 +1578,7 @@ $(ECLIPSE_LIB) : $(ECLIPSE_SOURCE)
|
|||
#
|
||||
# We Are On VAX And Due To The Use of INT64 We Can't Build It.
|
||||
#
|
||||
$(ECLIPSE_LIB) :
|
||||
$(ECLIPSE_LIB) :
|
||||
$! Due To The Use Of INT64 We Can't Build The
|
||||
$! $(MMS$TARGET) Library On VAX.
|
||||
.ENDIF
|
||||
|
@ -1832,19 +1832,19 @@ $(KI10_LIB) : $(KI10_SOURCE)
|
|||
#
|
||||
# We Are On VAX And Due To The Use of INT64 We Can't Build It.
|
||||
#
|
||||
$(PDP10_LIB) :
|
||||
$(PDP10_LIB) :
|
||||
$! Due To The Use Of INT64 We Can't Build The
|
||||
$! $(MMS$TARGET) Library On VAX.
|
||||
|
||||
$(PDP6_LIB) :
|
||||
$(PDP6_LIB) :
|
||||
$! Due To The Use Of INT64 We Can't Build The
|
||||
$! $(MMS$TARGET) Library On VAX.
|
||||
|
||||
$(KA10_LIB) :
|
||||
$(KA10_LIB) :
|
||||
$! Due To The Use Of INT64 We Can't Build The
|
||||
$! $(MMS$TARGET) Library On VAX.
|
||||
|
||||
$(KI10_LIB) :
|
||||
$(KI10_LIB) :
|
||||
$! Due To The Use Of INT64 We Can't Build The
|
||||
$! $(MMS$TARGET) Library On VAX.
|
||||
.ENDIF
|
||||
|
@ -1955,7 +1955,7 @@ $(BESM6_LIB) : $(BESM6_SOURCE)
|
|||
#
|
||||
# We Are On VAX And Due To The Use of INT64 We Can't Build It.
|
||||
#
|
||||
$(BESM6_LIB) :
|
||||
$(BESM6_LIB) :
|
||||
$! Due To The Use Of INT64 We Can't Build The
|
||||
$! $(MMS$TARGET) Library On VAX.
|
||||
.ENDIF
|
||||
|
@ -1978,7 +1978,7 @@ $(B5500_LIB) : $(B5500_SOURCE)
|
|||
#
|
||||
# We Are On VAX And Due To The Use of INT64 We Can't Build It.
|
||||
#
|
||||
$(B5500_LIB) :
|
||||
$(B5500_LIB) :
|
||||
$! Due To The Use Of INT64 We Can't Build The
|
||||
$! $(MMS$TARGET) Library On VAX.
|
||||
.ENDIF
|
||||
|
@ -2001,7 +2001,7 @@ $(CDC1700_LIB) : $(CDC1700_SOURCE)
|
|||
#
|
||||
# We Are On VAX And Due To The Use of INT64 We Can't Build It.
|
||||
#
|
||||
$(CDC1700_LIB) :
|
||||
$(CDC1700_LIB) :
|
||||
$! Due To The Use Of INT64 We Can't Build The
|
||||
$! $(MMS$TARGET) Library On VAX.
|
||||
.ENDIF
|
||||
|
@ -2499,7 +2499,7 @@ $(I7094_LIB) : $(I7094_SOURCE)
|
|||
#
|
||||
# We Are On VAX And Due To The Use of INT64 We Can't Build It.
|
||||
#
|
||||
$(I7094_LIB) :
|
||||
$(I7094_LIB) :
|
||||
$! Due To The Use Of INT64 We Can't Build The
|
||||
$! $(MMS$TARGET) Library On VAX.
|
||||
.ENDIF
|
||||
|
@ -2519,7 +2519,7 @@ ATT3B2 : $(BIN_DIR)ATT3B2-$(ARCH).EXE
|
|||
# Else We Are On VAX And Tell The User We Can't Build On VAX
|
||||
# Due To The Use Of INT64.
|
||||
#
|
||||
ATT3B2 :
|
||||
ATT3B2 :
|
||||
$! Sorry, Can't Build $(BIN_DIR)ATT3B2-$(ARCH).EXE Simulator
|
||||
$! Because It Requires The Use Of INT64.
|
||||
.ENDIF
|
||||
|
@ -2557,7 +2557,7 @@ ALTAIRZ80 : $(BIN_DIR)ALTAIRZ80-$(ARCH).EXE
|
|||
# Else We Are On VAX And Tell The User We Can't Build On VAX
|
||||
# Due To The Use Of INT64.
|
||||
#
|
||||
ALTAIRZ80 :
|
||||
ALTAIRZ80 :
|
||||
$! Sorry, Can't Build $(BIN_DIR)ALTAIRZ80-$(ARCH).EXE Simulator
|
||||
$! Because It Requires The Use Of INT64.
|
||||
.ENDIF
|
||||
|
@ -2583,7 +2583,7 @@ ECLIPSE : $(BIN_DIR)ECLIPSE-$(ARCH).EXE
|
|||
# Else We Are On VAX And Tell The User We Can't Build On VAX
|
||||
# Due To The Use Of INT64.
|
||||
#
|
||||
ECLIPSE :
|
||||
ECLIPSE :
|
||||
$! Sorry, Can't Build $(BIN_DIR)ECLIPSE-$(ARCH).EXE Simulator
|
||||
$! Because It Requires The Use Of INT64.
|
||||
.ENDIF
|
||||
|
@ -2847,19 +2847,19 @@ $(BIN_DIR)PDP10-KI-$(ARCH).EXE : $(SIMH_MAIN) $(SIMH_NONET_LIB) $(PCAP_LIBD) $(K
|
|||
# Else We Are On VAX And Tell The User We Can't Build On VAX
|
||||
# Due To The Use Of INT64.
|
||||
#
|
||||
PDP10 :
|
||||
PDP10 :
|
||||
$! Sorry, Can't Build $(BIN_DIR)PDP10-$(ARCH).EXE Simulator
|
||||
$! Because It Requires The Use Of INT64.
|
||||
|
||||
PDP6 :
|
||||
PDP6 :
|
||||
$! Sorry, Can't Build $(BIN_DIR)PDP6-$(ARCH).EXE Simulator
|
||||
$! Because It Requires The Use Of INT64.
|
||||
|
||||
PDP10-KA :
|
||||
PDP10-KA :
|
||||
$! Sorry, Can't Build $(BIN_DIR)PDP10-KA-$(ARCH).EXE Simulator
|
||||
$! Because It Requires The Use Of INT64.
|
||||
|
||||
PDP10-KI :
|
||||
PDP10-KI :
|
||||
$! Sorry, Can't Build $(BIN_DIR)PDP10-KI-$(ARCH).EXE Simulator
|
||||
$! Because It Requires The Use Of INT64.
|
||||
.ENDIF
|
||||
|
@ -2968,7 +2968,7 @@ $(BIN_DIR)BESM6-$(ARCH).EXE : $(SIMH_MAIN) $(SIMH_NONET_LIB) $(BESM6_LIB)
|
|||
# Else We Are On VAX And Tell The User We Can't Build On VAX
|
||||
# Due To The Use Of INT64.
|
||||
#
|
||||
BESM6 :
|
||||
BESM6 :
|
||||
$! Sorry, Can't Build $(BIN_DIR)BESM6-$(ARCH).EXE Simulator
|
||||
$! Because It Requires The Use Of INT64.
|
||||
.ENDIF
|
||||
|
@ -2994,7 +2994,7 @@ $(BIN_DIR)B5500-$(ARCH).EXE : $(SIMH_MAIN) $(SIMH_NONET_LIB) $(B5500_LIB)
|
|||
# Else We Are On VAX And Tell The User We Can't Build On VAX
|
||||
# Due To The Use Of INT64.
|
||||
#
|
||||
B5500 :
|
||||
B5500 :
|
||||
$! Sorry, Can't Build $(BIN_DIR)B5500-$(ARCH).EXE Simulator
|
||||
$! Because It Requires The Use Of INT64.
|
||||
.ENDIF
|
||||
|
@ -3020,7 +3020,7 @@ $(BIN_DIR)CDC1700-$(ARCH).EXE : $(SIMH_MAIN) $(SIMH_NONET_LIB) $(CDC1700_LIB)
|
|||
# Else We Are On VAX And Tell The User We Can't Build On VAX
|
||||
# Due To The Use Of INT64.
|
||||
#
|
||||
CDC1700 :
|
||||
CDC1700 :
|
||||
$! Sorry, Can't Build $(BIN_DIR)CDC1700-$(ARCH).EXE Simulator
|
||||
$! Because It Requires The Use Of INT64.
|
||||
.ENDIF
|
||||
|
@ -3363,7 +3363,7 @@ $(BIN_DIR)I7094-$(ARCH).EXE : $(SIMH_MAIN) $(SIMH_NONET_LIB) $(I7094_LIB)
|
|||
# Else We Are On VAX And Tell The User We Can't Build On VAX
|
||||
# Due To The Use Of INT64.
|
||||
#
|
||||
I7094 :
|
||||
I7094 :
|
||||
$! Sorry, Can't Build $(BIN_DIR)I7094-$(ARCH).EXE Simulator
|
||||
$! Because It Requires The Use Of INT64.
|
||||
.ENDIF
|
||||
|
@ -3375,9 +3375,9 @@ $(PCAP_VCI) : $(PCAP_VCMDIR)PCAPVCM.EXE
|
|||
$!
|
||||
$! Installing the PCAP VCI Execlet in SYS$LOADABLE_IMAGES
|
||||
$!
|
||||
$ COPY $(PCAP_VCMDIR)PCAPVCM.EXE SYS$COMMON:[SYS$LDR]PCAPVCM.EXE
|
||||
$ COPY $(PCAP_VCMDIR)PCAPVCM.EXE SYS$COMMON:[SYS$LDR]PCAPVCM.EXE
|
||||
|
||||
$(PCAP_VCMDIR)PCAPVCM.EXE : $(PCAP_VCM_SOURCES)
|
||||
$(PCAP_VCMDIR)PCAPVCM.EXE : $(PCAP_VCM_SOURCES)
|
||||
$!
|
||||
$! Building The PCAP VCI Execlet
|
||||
$!
|
||||
|
|
6
helpx
6
helpx
|
@ -226,7 +226,7 @@ while( <STDIN> ) {
|
|||
next;
|
||||
} elsif ($tok eq 'word' && $val =~ /^fprint_(set|show|reg)_help(?:_ex)?$/) {
|
||||
my %alt = ( set => "\$Set commands",
|
||||
show => "\$Show commmands",
|
||||
show => "\$Show commands",
|
||||
reg => "\$Registers" );
|
||||
$b .= "/* Use \"$alt{$1}\" topic instead:\n";
|
||||
do {
|
||||
|
@ -272,7 +272,7 @@ while( <STDIN> ) {
|
|||
" The SET commands for the device will automagically display above\n"
|
||||
" this line. Add any special notes.\n"
|
||||
"2 OSNAME1\n"
|
||||
" Operating System-specif configuration details\n"
|
||||
" Operating System-specific configuration details\n"
|
||||
" If the device needs special configuration for a particular OS, a subtopic\n"
|
||||
" for each such OS goes here.\n"
|
||||
"2 Files\n"
|
||||
|
@ -299,7 +299,7 @@ while( <STDIN> ) {
|
|||
"1 Related Devices\n"
|
||||
" If devices are configured or used together, list the other devices here.\n"
|
||||
" E.G. The DEC KMC/DUP are two hardware devices that are closely related;\n"
|
||||
" The KMC controlls the DUP on behalf of the OS.\n"
|
||||
" The KMC controls the DUP on behalf of the OS.\n"
|
||||
|
||||
/* **** Your converted help text starts hare **** */
|
||||
|
||||
|
|
142
makefile
142
makefile
|
@ -19,21 +19,21 @@
|
|||
# In general, the logic below will detect and build with the available
|
||||
# features which the host build environment provides.
|
||||
#
|
||||
# Dynamic loading of libpcap is the preferred default behavior if pcap.h
|
||||
# Dynamic loading of libpcap is the preferred default behavior if pcap.h
|
||||
# is available at build time. Support to statically linking against libpcap
|
||||
# is deprecated and may be removed in the future. Static linking against
|
||||
# libpcap can be enabled if GNU make is invoked with USE_NETWORK=1 on the
|
||||
# is deprecated and may be removed in the future. Static linking against
|
||||
# libpcap can be enabled if GNU make is invoked with USE_NETWORK=1 on the
|
||||
# command line.
|
||||
#
|
||||
# Some platforms may not have vendor supplied libpcap available. HP-UX is
|
||||
# Some platforms may not have vendor supplied libpcap available. HP-UX is
|
||||
# one such example. The packages which are available for this platform
|
||||
# install include files and libraries in user specified directories. In
|
||||
# order for this makefile to locate where these components may have been
|
||||
# installed, gmake should be invoked with LPATH=/usr/lib:/usr/local/lib
|
||||
# install include files and libraries in user specified directories. In
|
||||
# order for this makefile to locate where these components may have been
|
||||
# installed, gmake should be invoked with LPATH=/usr/lib:/usr/local/lib
|
||||
# defined (adjusted as needed depending on where they may be installed).
|
||||
#
|
||||
# In the unlikely event that someone wants to build network capable
|
||||
# simulators without networking support, invoking GNU make with
|
||||
# In the unlikely event that someone wants to build network capable
|
||||
# simulators without networking support, invoking GNU make with
|
||||
# NONETWORK=1 on the command line will do the trick.
|
||||
#
|
||||
# By default, video support is enabled if the SDL2 development
|
||||
|
@ -44,49 +44,49 @@
|
|||
# If debugging is desired, then GNU make can be invoked with
|
||||
# DEBUG=1 on the command line.
|
||||
#
|
||||
# When building compiler optimized binaries with the gcc or clang
|
||||
# compilers, invoking GNU make with LTO=1 on the command line will
|
||||
# cause the build to use Link Time Optimization to maximally optimize
|
||||
# the results. Link Time Optimization can report errors which aren't
|
||||
# otherwise detected and will also take significantly longer to
|
||||
# When building compiler optimized binaries with the gcc or clang
|
||||
# compilers, invoking GNU make with LTO=1 on the command line will
|
||||
# cause the build to use Link Time Optimization to maximally optimize
|
||||
# the results. Link Time Optimization can report errors which aren't
|
||||
# otherwise detected and will also take significantly longer to
|
||||
# complete. Additionally, non debug builds default to build with an
|
||||
# optimization level of -O2. This optimization level can be changed
|
||||
# by invoking GNU OPTIMIZE=-O3 (or whatever optimize value you want)
|
||||
# optimization level of -O2. This optimization level can be changed
|
||||
# by invoking GNU OPTIMIZE=-O3 (or whatever optimize value you want)
|
||||
# on the command line if desired.
|
||||
#
|
||||
# The default setup will fail simulator build(s) if the compile
|
||||
# produces any warnings. These should be cleaned up before new
|
||||
# or changd code is accepted into the code base. This option
|
||||
# The default setup will fail simulator build(s) if the compile
|
||||
# produces any warnings. These should be cleaned up before new
|
||||
# or changed code is accepted into the code base. This option
|
||||
# can be overridden if GNU make is invoked with WARNINGS=ALLOWED
|
||||
# on the command line.
|
||||
#
|
||||
# The default build will run per simulator tests if they are
|
||||
# available. If building without running tests is desired,
|
||||
# then GNU make should be invoked with TESTS=0 on the command
|
||||
# The default build will run per simulator tests if they are
|
||||
# available. If building without running tests is desired,
|
||||
# then GNU make should be invoked with TESTS=0 on the command
|
||||
# line.
|
||||
#
|
||||
# Default test execution will produce summary output. Detailed
|
||||
# test output can be produced if GNU make is invoked with
|
||||
# test output can be produced if GNU make is invoked with
|
||||
# TEST_ARG=-v on the command line.
|
||||
#
|
||||
# simh project support is provided for simulators that are built with
|
||||
# dependent packages provided with the or by the operating system
|
||||
# distribution OR for platforms where that isn't directly available
|
||||
# (OS X/macOS) by packages from specific package management systems (MacPorts
|
||||
# or Homebrew). Users wanting to build simulators with locally built
|
||||
# dependent packages or packages provided by an unsupported package
|
||||
# management system may be able to override where this procedure looks
|
||||
# for include files and/or libraries. Overrides can be specified by define
|
||||
# exported environment variables or GNU make command line arguments which
|
||||
# specify INCLUDES and/or LIBRARIES.
|
||||
# simh project support is provided for simulators that are built with
|
||||
# dependent packages provided with the or by the operating system
|
||||
# distribution OR for platforms where that isn't directly available
|
||||
# (OS X/macOS) by packages from specific package management systems (MacPorts
|
||||
# or Homebrew). Users wanting to build simulators with locally built
|
||||
# dependent packages or packages provided by an unsupported package
|
||||
# management system may be able to override where this procedure looks
|
||||
# for include files and/or libraries. Overrides can be specified by define
|
||||
# exported environment variables or GNU make command line arguments which
|
||||
# specify INCLUDES and/or LIBRARIES.
|
||||
# Each of these, if specified, must be the complete list include directories
|
||||
# or library directories that should be used with each element separated by
|
||||
# or library directories that should be used with each element separated by
|
||||
# colons. (i.e. INCLUDES=/usr/include/:/usr/local/include/:...)
|
||||
# If this doesn't work for you and/or you're interested in using a different
|
||||
# If this doesn't work for you and/or you're interested in using a different
|
||||
# ToolChain, you're free to solve this problem on your own. Good Luck.
|
||||
#
|
||||
# Some environments may have the LLVM (clang) compiler installed as
|
||||
# an alternate to gcc. If you want to build with the clang compiler,
|
||||
# an alternate to gcc. If you want to build with the clang compiler,
|
||||
# invoke make with GCC=clang.
|
||||
#
|
||||
# Internal ROM support can be disabled if GNU make is invoked with
|
||||
|
@ -362,7 +362,7 @@ ifeq (${WIN32},) #*nix Environments (&& cygwin)
|
|||
$(shell git log -1 --pretty="SIM_GIT_COMMIT_ID %H$(GIT_EXTRA_FILES)%nSIM_GIT_COMMIT_TIME $(isodate)" >.git-commit-id)
|
||||
endif
|
||||
endif
|
||||
LTO_EXCLUDE_VERSIONS =
|
||||
LTO_EXCLUDE_VERSIONS =
|
||||
PCAPLIB = pcap
|
||||
ifeq (agcc,$(findstring agcc,${GCC})) # Android target build?
|
||||
OS_CCDEFS += -D_GNU_SOURCE
|
||||
|
@ -585,16 +585,16 @@ ifeq (${WIN32},) #*nix Environments (&& cygwin)
|
|||
LIBEXTSAVE := ${LIBEXT}
|
||||
LIBEXT = a
|
||||
ifneq (,$(call find_lib,pthread))
|
||||
AIO_CCDEFS += -DUSE_READER_THREAD -DSIM_ASYNCH_IO
|
||||
AIO_CCDEFS += -DUSE_READER_THREAD -DSIM_ASYNCH_IO
|
||||
OS_LDFLAGS += -lpthread
|
||||
$(info using libpthread: $(call find_lib,pthread) $(call find_include,pthread))
|
||||
else
|
||||
ifneq (,$(findstring Haiku,$(OSTYPE)))
|
||||
AIO_CCDEFS += -DUSE_READER_THREAD -DSIM_ASYNCH_IO
|
||||
AIO_CCDEFS += -DUSE_READER_THREAD -DSIM_ASYNCH_IO
|
||||
$(info using libpthread: $(call find_include,pthread))
|
||||
else
|
||||
ifeq (Darwin,$(OSTYPE))
|
||||
AIO_CCDEFS += -DUSE_READER_THREAD -DSIM_ASYNCH_IO
|
||||
AIO_CCDEFS += -DUSE_READER_THREAD -DSIM_ASYNCH_IO
|
||||
OS_LDFLAGS += -lpthread
|
||||
$(info using macOS libpthread: $(call find_include,pthread))
|
||||
endif
|
||||
|
@ -688,7 +688,7 @@ ifeq (${WIN32},) #*nix Environments (&& cygwin)
|
|||
OS_CCDEFS += -DHAVE_GLOB
|
||||
else
|
||||
ifneq (,$(call find_include,fnmatch))
|
||||
OS_CCDEFS += -DHAVE_FNMATCH
|
||||
OS_CCDEFS += -DHAVE_FNMATCH
|
||||
endif
|
||||
endif
|
||||
ifneq (,$(call find_include,sys/mman))
|
||||
|
@ -1285,8 +1285,8 @@ else
|
|||
$(info ***********************************************************************)
|
||||
$(error .)
|
||||
else
|
||||
$(info ** date. For the most functional and stable features you shoud **)
|
||||
$(info ** Download the file: **)
|
||||
$(info ** date. For the most functional and stable features you should **)
|
||||
$(info ** download the file: **)
|
||||
$(info ** https://github.com/simh/windows-build/archive/windows-build.zip **)
|
||||
$(info ** Extract the windows-build-windows-build folder it contains to **)
|
||||
$(info ** $(abspath ..\) **)
|
||||
|
@ -1332,7 +1332,7 @@ else
|
|||
else
|
||||
CFLAGS_O := $(OPTIMIZE)
|
||||
endif
|
||||
LDFLAGS_O =
|
||||
LDFLAGS_O =
|
||||
GCC_MAJOR_VERSION = $(firstword $(subst ., ,$(GCC_VERSION)))
|
||||
ifneq (3,$(GCC_MAJOR_VERSION))
|
||||
ifeq (,$(GCC_OPTIMIZERS_CMD))
|
||||
|
@ -1743,7 +1743,7 @@ H316D = ${SIMHD}/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 ${H316D}/h316_rtc.c ${H316D}/h316_imp.c \
|
||||
${H316D}/h316_hi.c ${H316D}/h316_mi.c ${H316D}/h316_udp.c
|
||||
${H316D}/h316_hi.c ${H316D}/h316_mi.c ${H316D}/h316_udp.c
|
||||
H316_OPT = -I ${H316D} -D VM_IMPTIP
|
||||
|
||||
|
||||
|
@ -1795,7 +1795,7 @@ I7090 = ${I7000D}/i7090_cpu.c ${I7000D}/i7090_sys.c ${I7000D}/i7090_chan.c \
|
|||
${I7000D}/i7090_cdr.c ${I7000D}/i7090_cdp.c ${I7000D}/i7090_lpr.c \
|
||||
${I7000D}/i7000_chan.c ${I7000D}/i7000_mt.c ${I7000D}/i7090_drum.c \
|
||||
${I7000D}/i7090_hdrum.c ${I7000D}/i7000_chron.c ${I7000D}/i7000_dsk.c \
|
||||
${I7000D}/i7000_com.c ${I7000D}/i7000_ht.c
|
||||
${I7000D}/i7000_com.c ${I7000D}/i7000_ht.c
|
||||
I7090_OPT = -I $(I7000D) -DUSE_INT64 -DI7090 -DUSE_SIM_CARD
|
||||
|
||||
I7080D = ${SIMHD}/I7000
|
||||
|
@ -1803,7 +1803,7 @@ I7080 = ${I7000D}/i7080_cpu.c ${I7000D}/i7080_sys.c ${I7000D}/i7080_chan.c \
|
|||
${I7000D}/i7080_drum.c ${I7000D}/i7000_cdp.c ${I7000D}/i7000_cdr.c \
|
||||
${I7000D}/i7000_con.c ${I7000D}/i7000_chan.c ${I7000D}/i7000_lpr.c \
|
||||
${I7000D}/i7000_mt.c ${I7000D}/i7000_chron.c ${I7000D}/i7000_dsk.c \
|
||||
${I7000D}/i7000_com.c ${I7000D}/i7000_ht.c
|
||||
${I7000D}/i7000_com.c ${I7000D}/i7000_ht.c
|
||||
I7080_OPT = -I $(I7000D) -DI7080 -DUSE_SIM_CARD
|
||||
|
||||
I7070D = ${SIMHD}/I7000
|
||||
|
@ -1811,7 +1811,7 @@ I7070 = ${I7000D}/i7070_cpu.c ${I7000D}/i7070_sys.c ${I7000D}/i7070_chan.c \
|
|||
${I7000D}/i7000_cdp.c ${I7000D}/i7000_cdr.c ${I7000D}/i7000_con.c \
|
||||
${I7000D}/i7000_chan.c ${I7000D}/i7000_lpr.c ${I7000D}/i7000_mt.c \
|
||||
${I7000D}/i7000_chron.c ${I7000D}/i7000_dsk.c ${I7000D}/i7000_com.c \
|
||||
${I7000D}/i7000_ht.c
|
||||
${I7000D}/i7000_ht.c
|
||||
I7070_OPT = -I $(I7000D) -DUSE_INT64 -DI7070 -DUSE_SIM_CARD
|
||||
|
||||
I7010D = ${SIMHD}/I7000
|
||||
|
@ -1819,20 +1819,20 @@ I7010 = ${I7000D}/i7010_cpu.c ${I7000D}/i7010_sys.c ${I7000D}/i7010_chan.c \
|
|||
${I7000D}/i7000_cdp.c ${I7000D}/i7000_cdr.c ${I7000D}/i7000_con.c \
|
||||
${I7000D}/i7000_chan.c ${I7000D}/i7000_lpr.c ${I7000D}/i7000_mt.c \
|
||||
${I7000D}/i7000_chron.c ${I7000D}/i7000_dsk.c ${I7000D}/i7000_com.c \
|
||||
${I7000D}/i7000_ht.c
|
||||
${I7000D}/i7000_ht.c
|
||||
I7010_OPT = -I $(I7010D) -DI7010 -DUSE_SIM_CARD
|
||||
|
||||
I704D = ${SIMHD}/I7000
|
||||
I704 = ${I7000D}/i7090_cpu.c ${I7000D}/i7090_sys.c ${I7000D}/i7090_chan.c \
|
||||
${I7000D}/i7090_cdr.c ${I7000D}/i7090_cdp.c ${I7000D}/i7090_lpr.c \
|
||||
${I7000D}/i7000_mt.c ${I7000D}/i7090_drum.c ${I7000D}/i7000_chan.c
|
||||
${I7000D}/i7000_mt.c ${I7000D}/i7090_drum.c ${I7000D}/i7000_chan.c
|
||||
I704_OPT = -I $(I7000D) -DUSE_INT64 -DI704 -DUSE_SIM_CARD
|
||||
|
||||
|
||||
I701D = ${SIMHD}/I7000
|
||||
I701 = ${I7000D}/i701_cpu.c ${I7000D}/i701_sys.c ${I7000D}/i701_chan.c \
|
||||
${I7000D}/i7090_cdr.c ${I7000D}/i7090_cdp.c ${I7000D}/i7090_lpr.c \
|
||||
${I7000D}/i7000_mt.c ${I7000D}/i7090_drum.c ${I7000D}/i7000_chan.c
|
||||
${I7000D}/i7000_mt.c ${I7000D}/i7090_drum.c ${I7000D}/i7000_chan.c
|
||||
I701_OPT = -I $(I7000D) -DUSE_INT64 -DI701 -DUSE_SIM_CARD
|
||||
|
||||
|
||||
|
@ -1860,8 +1860,8 @@ IBM1130 = ${IBM1130D}/ibm1130_cpu.c ${IBM1130D}/ibm1130_cr.c \
|
|||
${IBM1130D}/ibm1130_t2741.c
|
||||
IBM1130_OPT = -I ${IBM1130D}
|
||||
ifneq (${WIN32},)
|
||||
IBM1130_OPT += -DGUI_SUPPORT -lgdi32 ${BIN}ibm1130.o
|
||||
endif
|
||||
IBM1130_OPT += -DGUI_SUPPORT -lgdi32 ${BIN}ibm1130.o
|
||||
endif
|
||||
|
||||
|
||||
ID16D = ${SIMHD}/Interdata
|
||||
|
@ -1983,7 +1983,7 @@ INTEL_PARTS = \
|
|||
${INTELSYSC}/multibus.c \
|
||||
${INTELSYSC}/mem.c \
|
||||
${INTELSYSC}/sys.c \
|
||||
${INTELSYSC}/zx200a.c
|
||||
${INTELSYSC}/zx200a.c
|
||||
|
||||
|
||||
INTEL_MDSD = ${INTELSYSD}/Intel-MDS
|
||||
|
@ -2008,7 +2008,7 @@ IBMPCXT = ${IBMPCXTC}/i8088.c ${IBMPCXTD}/ibmpcxt_sys.c \
|
|||
${IBMPCXTC}/i8253.c ${IBMPCXTC}/i8259.c \
|
||||
${IBMPCXTC}/i8255.c ${IBMPCXTD}/ibmpcxt.c \
|
||||
${IBMPCXTC}/pceprom.c ${IBMPCXTC}/pcram8.c \
|
||||
${IBMPCXTC}/pcbus.c ${IBMPCXTC}/i8237.c
|
||||
${IBMPCXTC}/pcbus.c ${IBMPCXTC}/i8237.c
|
||||
IBMPCXT_OPT = -I ${IBMPCXTD}
|
||||
|
||||
|
||||
|
@ -2044,7 +2044,7 @@ BESM6_OPT = -I ${BESM6D} -DUSE_INT64 $(BESM6_PANEL_OPT)
|
|||
|
||||
PDP6D = ${SIMHD}/PDP10
|
||||
ifneq (,${DISPLAY_OPT})
|
||||
PDP6_DISPLAY_OPT =
|
||||
PDP6_DISPLAY_OPT =
|
||||
endif
|
||||
PDP6 = ${PDP6D}/kx10_cpu.c ${PDP6D}/kx10_sys.c ${PDP6D}/kx10_cty.c \
|
||||
${PDP6D}/kx10_lp.c ${PDP6D}/kx10_pt.c ${PDP6D}/kx10_cr.c \
|
||||
|
@ -2057,7 +2057,7 @@ PDP6_OPT = -DPDP6=1 -DUSE_INT64 -I ${PDP6D} -DUSE_SIM_CARD ${DISPLAY_OPT} ${PDP6
|
|||
|
||||
KA10D = ${SIMHD}/PDP10
|
||||
ifneq (,${DISPLAY_OPT})
|
||||
KA10_DISPLAY_OPT =
|
||||
KA10_DISPLAY_OPT =
|
||||
endif
|
||||
KA10 = ${KA10D}/kx10_cpu.c ${KA10D}/kx10_sys.c ${KA10D}/kx10_df.c \
|
||||
${KA10D}/kx10_dp.c ${KA10D}/kx10_mt.c ${KA10D}/kx10_cty.c \
|
||||
|
@ -2084,7 +2084,7 @@ endif
|
|||
|
||||
KI10D = ${SIMHD}/PDP10
|
||||
ifneq (,${DISPLAY_OPT})
|
||||
KI10_DISPLAY_OPT =
|
||||
KI10_DISPLAY_OPT =
|
||||
endif
|
||||
KI10 = ${KI10D}/kx10_cpu.c ${KI10D}/kx10_sys.c ${KI10D}/kx10_df.c \
|
||||
${KI10D}/kx10_dp.c ${KI10D}/kx10_mt.c ${KI10D}/kx10_cty.c \
|
||||
|
@ -2191,12 +2191,12 @@ SAGE = ${SAGED}/sage_cpu.c ${SAGED}/sage_sys.c ${SAGED}/sage_stddev.c \
|
|||
${SAGED}/sage_cons.c ${SAGED}/sage_fd.c ${SAGED}/sage_lp.c \
|
||||
${SAGED}/m68k_cpu.c ${SAGED}/m68k_mem.c ${SAGED}/m68k_scp.c \
|
||||
${SAGED}/m68k_parse.tab.c ${SAGED}/m68k_sys.c \
|
||||
${SAGED}/i8251.c ${SAGED}/i8253.c ${SAGED}/i8255.c ${SAGED}/i8259.c ${SAGED}/i8272.c
|
||||
${SAGED}/i8251.c ${SAGED}/i8253.c ${SAGED}/i8255.c ${SAGED}/i8259.c ${SAGED}/i8272.c
|
||||
SAGE_OPT = -I ${SAGED} -DHAVE_INT64
|
||||
|
||||
PDQ3D = ${SIMHD}/PDQ-3
|
||||
PDQ3 = ${PDQ3D}/pdq3_cpu.c ${PDQ3D}/pdq3_sys.c ${PDQ3D}/pdq3_stddev.c \
|
||||
${PDQ3D}/pdq3_mem.c ${PDQ3D}/pdq3_debug.c ${PDQ3D}/pdq3_fdc.c
|
||||
${PDQ3D}/pdq3_mem.c ${PDQ3D}/pdq3_debug.c ${PDQ3D}/pdq3_fdc.c
|
||||
PDQ3_OPT = -I ${PDQ3D}
|
||||
|
||||
#
|
||||
|
@ -2213,7 +2213,7 @@ ALL = pdp1 pdp4 pdp7 pdp8 pdp9 pdp15 pdp11 pdp10 \
|
|||
swtp6800mp-a swtp6800mp-a2 tx-0 ssem b5500 intel-mds \
|
||||
scelbi 3b2 3b2-700 i701 i704 i7010 i7070 i7080 i7090 \
|
||||
sigma uc15 pdp10-ka pdp10-ki pdp10-kl pdp10-ks pdp6 i650 \
|
||||
imlac tt2500 sel32
|
||||
imlac tt2500 sel32
|
||||
|
||||
all : ${ALL}
|
||||
|
||||
|
@ -2228,7 +2228,7 @@ else
|
|||
if exist BIN rmdir /s /q BIN
|
||||
endif
|
||||
|
||||
${BUILD_ROMS} :
|
||||
${BUILD_ROMS} :
|
||||
${MKDIRBIN}
|
||||
ifeq (${WIN32},)
|
||||
@if ${TEST} \( ! -e $@ \) -o \( sim_BuildROMs.c -nt $@ \) ; then ${CC} sim_BuildROMs.c ${CC_OUTSPEC}; fi
|
||||
|
@ -2864,7 +2864,7 @@ endif
|
|||
|
||||
b5500 : ${BIN}b5500${EXE}
|
||||
|
||||
${BIN}b5500${EXE} : ${B5500} ${SIM}
|
||||
${BIN}b5500${EXE} : ${B5500} ${SIM}
|
||||
${MKDIRBIN}
|
||||
${CC} ${B5500} ${SIM} ${B5500_OPT} ${CC_OUTSPEC} ${LDFLAGS}
|
||||
ifneq (,$(call find_test,${B5500D},b5500))
|
||||
|
@ -2874,7 +2874,7 @@ endif
|
|||
3b2-400 : 3b2
|
||||
|
||||
3b2 : ${BIN}3b2${EXE}
|
||||
|
||||
|
||||
${BIN}3b2${EXE} : ${ATT3B2M400} ${SIM}
|
||||
${MKDIRBIN}
|
||||
${CC} ${ATT3B2M400} ${SIM} ${ATT3B2M400_OPT} ${CC_OUTSPEC} ${LDFLAGS}
|
||||
|
@ -2898,7 +2898,7 @@ endif
|
|||
|
||||
i7090 : ${BIN}i7090${EXE}
|
||||
|
||||
${BIN}i7090${EXE} : ${I7090} ${SIM}
|
||||
${BIN}i7090${EXE} : ${I7090} ${SIM}
|
||||
${MKDIRBIN}
|
||||
${CC} ${I7090} ${SIM} ${I7090_OPT} ${CC_OUTSPEC} ${LDFLAGS}
|
||||
ifneq (,$(call find_test,${I7000D},i7090))
|
||||
|
@ -2907,7 +2907,7 @@ endif
|
|||
|
||||
i7080 : ${BIN}i7080${EXE}
|
||||
|
||||
${BIN}i7080${EXE} : ${I7080} ${SIM}
|
||||
${BIN}i7080${EXE} : ${I7080} ${SIM}
|
||||
${MKDIRBIN}
|
||||
${CC} ${I7080} ${SIM} ${I7080_OPT} ${CC_OUTSPEC} ${LDFLAGS}
|
||||
ifneq (,$(call find_test,${I7080D},i7080))
|
||||
|
@ -2916,7 +2916,7 @@ endif
|
|||
|
||||
i7070 : ${BIN}i7070${EXE}
|
||||
|
||||
${BIN}i7070${EXE} : ${I7070} ${SIM}
|
||||
${BIN}i7070${EXE} : ${I7070} ${SIM}
|
||||
${MKDIRBIN}
|
||||
${CC} ${I7070} ${SIM} ${I7070_OPT} ${CC_OUTSPEC} ${LDFLAGS}
|
||||
ifneq (,$(call find_test,${I7070D},i7070))
|
||||
|
@ -2925,7 +2925,7 @@ endif
|
|||
|
||||
i7010 : ${BIN}i7010${EXE}
|
||||
|
||||
${BIN}i7010${EXE} : ${I7010} ${SIM}
|
||||
${BIN}i7010${EXE} : ${I7010} ${SIM}
|
||||
${MKDIRBIN}
|
||||
${CC} ${I7010} ${SIM} ${I7010_OPT} ${CC_OUTSPEC} ${LDFLAGS}
|
||||
ifneq (,$(call find_test,${I7010D},i7010))
|
||||
|
@ -2934,7 +2934,7 @@ endif
|
|||
|
||||
i704 : ${BIN}i704${EXE}
|
||||
|
||||
${BIN}i704${EXE} : ${I704} ${SIM}
|
||||
${BIN}i704${EXE} : ${I704} ${SIM}
|
||||
${MKDIRBIN}
|
||||
${CC} ${I704} ${SIM} ${I704_OPT} ${CC_OUTSPEC} ${LDFLAGS}
|
||||
ifneq (,$(call find_test,${I704D},i704))
|
||||
|
@ -2943,7 +2943,7 @@ endif
|
|||
|
||||
i701 : ${BIN}i701${EXE}
|
||||
|
||||
${BIN}i701${EXE} : ${I701} ${SIM}
|
||||
${BIN}i701${EXE} : ${I701} ${SIM}
|
||||
${MKDIRBIN}
|
||||
${CC} ${I701} ${SIM} ${I701_OPT} ${CC_OUTSPEC} ${LDFLAGS}
|
||||
ifneq (,$(call find_test,${I701D},i701))
|
||||
|
@ -2952,7 +2952,7 @@ endif
|
|||
|
||||
i650 : ${BIN}i650${EXE}
|
||||
|
||||
${BIN}i650${EXE} : ${I650} ${SIM}
|
||||
${BIN}i650${EXE} : ${I650} ${SIM}
|
||||
${MKDIRBIN}
|
||||
${CC} ${I650} ${SIM} ${I650_OPT} ${CC_OUTSPEC} ${LDFLAGS}
|
||||
ifneq (,$(call find_test,${I650D},i650))
|
||||
|
|
10
scp.h
10
scp.h
|
@ -23,7 +23,7 @@
|
|||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
05-Dec-10 MP Added macro invocation of sim_debug
|
||||
05-Dec-10 MP Added macro invocation of sim_debug
|
||||
09-Aug-06 JDB Added assign_device and deassign_device
|
||||
14-Jul-06 RMS Added sim_activate_abs
|
||||
06-Jan-06 RMS Added fprint_stopped_gen
|
||||
|
@ -253,7 +253,7 @@ void sim_perror (const char *msg);
|
|||
t_stat sim_call_argv (int (*main_like)(int argc, char *argv[]), const char *cptr);
|
||||
t_stat sim_messagef (t_stat stat, const char *fmt, ...) GCC_FMT_ATTR(2, 3);
|
||||
void sim_data_trace(DEVICE *dptr, UNIT *uptr, const uint8 *data, const char *position, size_t len, const char *txt, uint32 reason);
|
||||
void sim_debug_bits_hdr (uint32 dbits, DEVICE* dptr, const char *header,
|
||||
void sim_debug_bits_hdr (uint32 dbits, DEVICE* dptr, const char *header,
|
||||
BITFIELD* bitdefs, uint32 before, uint32 after, int terminate);
|
||||
void sim_debug_bits (uint32 dbits, DEVICE* dptr, BITFIELD* bitdefs,
|
||||
uint32 before, uint32 after, int terminate);
|
||||
|
@ -357,13 +357,13 @@ extern t_stat parse_sym (CONST char *cptr, t_addr addr, UNIT *uptr, t_value *val
|
|||
int32 sw);
|
||||
|
||||
/* The per-simulator init routine is a weak global that defaults to NULL
|
||||
The other per-simulator pointers can be overrriden by the init routine
|
||||
The other per-simulator pointers can be overridden by the init routine
|
||||
|
||||
extern void (*sim_vm_init) (void);
|
||||
|
||||
This routine is no longer invoked this way since it doesn't work reliably
|
||||
on all simh supported compile environments. A simulator that needs these
|
||||
initializations can perform them in the CPU device reset routine which will
|
||||
on all simh supported compile environments. A simulator that needs these
|
||||
initializations can perform them in the CPU device reset routine which will
|
||||
always be called before anything else can be processed.
|
||||
|
||||
*/
|
||||
|
|
20
scp_help.h
20
scp_help.h
|
@ -84,7 +84,7 @@
|
|||
* For these cases, ?#, where # is a 1-based parameter number, can be used
|
||||
* to selectively include a topic. If the specified parameter is TRUE
|
||||
* (a string with the value "T", "t" or '1'), the topic will be visible.
|
||||
* If the parameter is FALSE (NULL, or a string with any other value),
|
||||
* If the parameter is FALSE (NULL, or a string with any other value),
|
||||
* the topic will not be visible.
|
||||
*
|
||||
* If it can be determined at compile time whether the topic in question
|
||||
|
@ -95,7 +95,7 @@
|
|||
* Guidelines:
|
||||
* Help should be concise and easy to understand.
|
||||
*
|
||||
* The main topic should be short - less than a sceenful when presented with the
|
||||
* The main topic should be short - less than a screenful when presented with the
|
||||
* subtopic list.
|
||||
*
|
||||
* Keep line lengths to 76 columns or less.
|
||||
|
@ -107,7 +107,7 @@
|
|||
* Hardware Description - The details of the hardware. Feeds & speeds are OK here.
|
||||
* Models - If the device was offered in distinct models, a subtopic for each.
|
||||
* Registers - Register descriptions
|
||||
*
|
||||
*
|
||||
* Configuration - How to configure the device under SimH. SET commands.
|
||||
* Operating System - If the device needs special configuration for a particular
|
||||
* OS, a subtopic for each such OS goes here.
|
||||
|
@ -126,7 +126,7 @@
|
|||
*
|
||||
* Related Devices - If devices are configured or used together, list the other devices here.
|
||||
* E.G. The DEC KMC/DUP are two hardware devices that are closely related;
|
||||
* The KMC controlls the DUP on behalf of the OS.
|
||||
* The KMC controls the DUP on behalf of the OS.
|
||||
*
|
||||
* This text can be created by any convenient means. It can be mechanically extracted from the device
|
||||
* source, read from a file, or simply entered as a string in the help routine. To facilitate the latter,
|
||||
|
@ -151,7 +151,7 @@
|
|||
* UNIT *uptr, int flag, const char *help, char *cptr, ...)
|
||||
*
|
||||
* If you need to pass the variable argument list from another routine, use:
|
||||
*
|
||||
*
|
||||
* t_stat scp_vhelp (FILE *st, DEVICE *dptr,
|
||||
* UNIT *uptr, int flag, const char *help, char *cptr, va_list ap)
|
||||
*
|
||||
|
@ -175,12 +175,12 @@
|
|||
* to a string.)
|
||||
*
|
||||
* Lines beginning with ';' will be ignored.
|
||||
*
|
||||
*
|
||||
* Here is a worked-out example:
|
||||
*
|
||||
;****************************************************************************
|
||||
The Whizbang 100 is a DMA line printer controller used on the Whizbang 1000
|
||||
and Gurgle 1200 processor familes of the Obsolete Hardware Corporation.
|
||||
and Gurgle 1200 processor families of the Obsolete Hardware Corporation.
|
||||
1 Hardware Description
|
||||
The Whizbang 100 is specified to operate "any printer you and a friend can
|
||||
lift", and speeds up to 0.5 C.
|
||||
|
@ -205,7 +205,7 @@
|
|||
Bit 2 ejects the operator
|
||||
Bit 3 enables interrupts
|
||||
3 Print data register
|
||||
The print data register is thiry-seven bits wide, and accepts data in
|
||||
The print data register is thirty-seven bits wide, and accepts data in
|
||||
elephantcode, the precursor to Unicode. Paper advance is accomplished
|
||||
with the Rocket Return and Page Trampoline characters.
|
||||
1 Configuration
|
||||
|
@ -217,7 +217,7 @@
|
|||
+ SET WHIZBANG CODESET ASCII
|
||||
+ SET WHIZBANG CODESET ELEPHANTCODE
|
||||
|
||||
The VFU (carriage control tape) is specifed with
|
||||
The VFU (carriage control tape) is specified with
|
||||
+ SET WHIZBANG TAPE vfufile
|
||||
2 WOS
|
||||
Under WOS, the device will only work at LooneyBus slot 9
|
||||
|
@ -231,7 +231,7 @@
|
|||
2 Examples
|
||||
TBS
|
||||
1 Operation
|
||||
Specify the host file to receive output using the
|
||||
Specify the host file to receive output using the
|
||||
+ATTACH WHIZBANG filespec
|
||||
command.
|
||||
1 Monitoring
|
||||
|
|
22
sim_card.c
22
sim_card.c
|
@ -22,7 +22,7 @@
|
|||
This is the standard card reader.
|
||||
This is the standard card punch.
|
||||
|
||||
Input formats are accepted in a variaty of formats:
|
||||
Input formats are accepted in a variety of formats:
|
||||
Standard ASCII: one record per line.
|
||||
returns are ignored.
|
||||
tabs are expanded to modules 8 characters.
|
||||
|
@ -44,7 +44,7 @@
|
|||
Bits 5-0 are character.
|
||||
|
||||
CBN Format:
|
||||
Each record 160 charaters.
|
||||
Each record 160 characters.
|
||||
First char has bit 7 set. Rest set to 0.
|
||||
Bit 6 is odd parity.
|
||||
Bit 5-0 of first character are top 6 bits
|
||||
|
@ -60,7 +60,7 @@
|
|||
is not enough octal numbers to span a full card the remainder of the
|
||||
card will not be punched.
|
||||
|
||||
Also ~eor, will generate a 7/8/9 punch card. An ~eof will gernerate a
|
||||
Also ~eor, will generate a 7/8/9 punch card. An ~eof will generate a
|
||||
6/7/9 punch card, and a ~eoi will generate a 6/7/8/9 punch.
|
||||
|
||||
A single line of ~ will set the EOF flag when that card is read.
|
||||
|
@ -252,7 +252,7 @@ static const uint16 ascii_to_dec_029[128] = {
|
|||
|
||||
#if SIMH_EVER_USES_THIS
|
||||
/* This is a static const that isn't referenced in this code.
|
||||
* Kept for historical refernce.
|
||||
* Kept for historical reference.
|
||||
*/
|
||||
static const uint16 ascii_to_hol_ebcdic[128] = {
|
||||
/* Control */
|
||||
|
@ -434,7 +434,7 @@ static struct card_formats fmts[] = {
|
|||
|
||||
/* Conversion routines */
|
||||
|
||||
/* Convert BCD character into hollerith code */
|
||||
/* Convert BCD character into Hollerith code */
|
||||
uint16
|
||||
sim_bcd_to_hol(uint8 bcd) {
|
||||
uint16 hol;
|
||||
|
@ -479,7 +479,7 @@ sim_bcd_to_hol(uint8 bcd) {
|
|||
return hol;
|
||||
}
|
||||
|
||||
/* Returns the BCD of the hollerith code or 0x7f if error */
|
||||
/* Returns the BCD of the Hollerith code or 0x7f if error */
|
||||
uint8
|
||||
sim_hol_to_bcd(uint16 hol) {
|
||||
uint8 bcd;
|
||||
|
@ -529,7 +529,7 @@ sim_hol_to_bcd(uint16 hol) {
|
|||
return bcd;
|
||||
}
|
||||
|
||||
/* Convert EBCDIC character into hollerith code */
|
||||
/* Convert EBCDIC character into Hollerith code */
|
||||
uint16
|
||||
sim_ebcdic_to_hol(uint8 ebcdic) {
|
||||
return ebcdic_to_hol[ebcdic];
|
||||
|
@ -537,7 +537,7 @@ sim_ebcdic_to_hol(uint8 ebcdic) {
|
|||
|
||||
|
||||
|
||||
/* Returns the BCD of the hollerith code or 0x7f if error */
|
||||
/* Returns the BCD of the Hollerith code or 0x7f if error */
|
||||
uint16
|
||||
sim_hol_to_ebcdic(uint16 hol) {
|
||||
return hol_to_ebcdic[hol];
|
||||
|
@ -987,7 +987,7 @@ _sim_read_deck(UNIT * uptr, int eof)
|
|||
|
||||
buf.len = 0;
|
||||
buf.size = 0;
|
||||
buf.buffer[0] = 0; /* Initialize bufer to empty */
|
||||
buf.buffer[0] = 0; /* Initialize buffer to empty */
|
||||
|
||||
/* Slurp up current file */
|
||||
do {
|
||||
|
@ -1014,7 +1014,7 @@ _sim_read_deck(UNIT * uptr, int eof)
|
|||
sim_uname(uptr), uptr->filename, sim_error_text(r), cards);
|
||||
}
|
||||
data->hopper_cards++;
|
||||
/* Move data to start at begining of buffer */
|
||||
/* Move data to start at beginning of buffer */
|
||||
/* Data is moved down to simplify the decoding of one card */
|
||||
l = buf.len - buf.size;
|
||||
j = buf.size;
|
||||
|
@ -1059,7 +1059,7 @@ sim_punch_card(UNIT * uptr, uint16 image[80])
|
|||
/* Convert word record into column image */
|
||||
/* Check output type, if auto or text, try and convert record to bcd first */
|
||||
/* If failed and text report error and dump what we have */
|
||||
/* Else if binary or not convertable, dump as image */
|
||||
/* Else if binary or not convertible, dump as image */
|
||||
|
||||
/* Try to convert to text */
|
||||
uint8 out[512];
|
||||
|
|
12
sim_card.h
12
sim_card.h
|
@ -22,7 +22,7 @@
|
|||
This is the standard card reader.
|
||||
This is the standard card punch.
|
||||
|
||||
Input formats are accepted in a variaty of formats:
|
||||
Input formats are accepted in a variety of formats:
|
||||
Standard ASCII: one record per line.
|
||||
returns are ignored.
|
||||
tabs are expanded to modules 8 characters.
|
||||
|
@ -44,7 +44,7 @@
|
|||
Bits 5-0 are character.
|
||||
|
||||
CBN Format:
|
||||
Each record 160 charaters.
|
||||
Each record 160 characters.
|
||||
First char has bit 7 set. Rest set to 0.
|
||||
Bit 6 is odd parity.
|
||||
Bit 5-0 of first character are top 6 bits
|
||||
|
@ -60,14 +60,14 @@
|
|||
|
||||
|
||||
ASCII mode recognizes some additional forms of input which allows the
|
||||
intermixing of binary cards with text cards.
|
||||
intermixing of binary cards with text cards.
|
||||
|
||||
Lines beginning with ~raw are taken as a number of 4 digit octal values
|
||||
with represent each column of the card from 12 row down to 9 row. If there
|
||||
is not enough octal numbers to span a full card the remainder of the
|
||||
is not enough octal numbers to span a full card the remainder of the
|
||||
card will not be punched.
|
||||
|
||||
Also ~eor, will generate a 7/8/9 punch card. An ~eof will gernerate a
|
||||
Also ~eor, will generate a 7/8/9 punch card. An ~eof will generate a
|
||||
6/7/9 punch card, and a ~eoi will generate a 6/7/8/9 punch.
|
||||
|
||||
A single line of ~ will set the EOF flag when that card is read.
|
||||
|
@ -110,7 +110,7 @@ typedef int t_cdstat;
|
|||
#define CDSE_OK 0 /* Good */
|
||||
#define CDSE_EOF 1 /* End of File */
|
||||
#define CDSE_EMPTY 2 /* Input Hopper Empty */
|
||||
#define CDSE_ERROR 3 /* Error Card Read */
|
||||
#define CDSE_ERROR 3 /* Error Card Read */
|
||||
|
||||
/* Generic routines. */
|
||||
|
||||
|
|
120
sim_console.c
120
sim_console.c
|
@ -34,33 +34,33 @@
|
|||
10-Nov-14 JDB Added -N option to SET CONSOLE LOG and SET CONSOLE DEBUG
|
||||
02-Jan-14 RMS Added tab stop routines
|
||||
18-Mar-12 RMS Removed unused reference to sim_switches (Dave Bryan)
|
||||
07-Dec-11 MP Added sim_ttisatty to support reasonable behaviour (i.e.
|
||||
07-Dec-11 MP Added sim_ttisatty to support reasonable behaviour (i.e.
|
||||
avoid in infinite loop) in the main command input
|
||||
loop when EOF is detected and input is coming from
|
||||
loop when EOF is detected and input is coming from
|
||||
a file (or a null device: /dev/null or NUL:) This may
|
||||
happen when a simulator is running in a background
|
||||
happen when a simulator is running in a background
|
||||
process.
|
||||
17-Apr-11 MP Cleaned up to support running in a background/detached
|
||||
process
|
||||
20-Jan-11 MP Fixed support for BREAK key on Windows to account
|
||||
20-Jan-11 MP Fixed support for BREAK key on Windows to account
|
||||
for/ignore other keyboard Meta characters.
|
||||
18-Jan-11 MP Added log file reference count support
|
||||
17-Jan-11 MP Added support for a "Buffered" behaviors which include:
|
||||
- If Buffering is enabled and Telnet is enabled, a
|
||||
telnet connection is not required for simulator
|
||||
telnet connection is not required for simulator
|
||||
operation (instruction execution).
|
||||
- If Buffering is enabled, all console output is
|
||||
- If Buffering is enabled, all console output is
|
||||
written to the buffer at all times (deleting the
|
||||
oldest buffer contents on overflow).
|
||||
- when a connection is established on the console
|
||||
- when a connection is established on the console
|
||||
telnet port, the whole contents of the Buffer is
|
||||
presented on the telnet session and connection
|
||||
presented on the telnet session and connection
|
||||
will then proceed as if the connection had always
|
||||
been there.
|
||||
This concept allows a simulator to run in the background
|
||||
and when needed a console session to be established.
|
||||
The "when needed" case usually will be interested in
|
||||
what already happened before looking to address what
|
||||
and when needed a console session to be established.
|
||||
The "when needed" case usually will be interested in
|
||||
what already happened before looking to address what
|
||||
to do, hence the buffer contents being presented.
|
||||
28-Dec-10 MP Added support for BREAK key on Windows
|
||||
30-Sep-06 RMS Fixed non-printable characters in KSR mode
|
||||
|
@ -94,7 +94,7 @@
|
|||
25-Jan-97 RMS Added POSIX terminal I/O support
|
||||
02-Jan-97 RMS Fixed bug in sim_poll_kbd
|
||||
|
||||
This module implements the following routines to support terminal and
|
||||
This module implements the following routines to support terminal and
|
||||
Remote Console I/O:
|
||||
|
||||
sim_poll_kbd poll for keyboard input
|
||||
|
@ -158,7 +158,7 @@
|
|||
#define MIN(a,b) (((a) <= (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
/* Forward Declaraations of Platform specific routines */
|
||||
/* Forward declarations of platform specific routines */
|
||||
|
||||
static t_stat sim_os_poll_kbd (void);
|
||||
static t_bool sim_os_poll_kbd_ready (int ms_timeout);
|
||||
|
@ -257,9 +257,9 @@ return "Console telnet support";
|
|||
}
|
||||
|
||||
DEVICE sim_con_telnet = {
|
||||
"CON-TELNET", sim_con_units, sim_con_reg, sim_con_mod,
|
||||
2, 0, 0, 0, 0, 0,
|
||||
NULL, NULL, sim_con_reset, NULL, sim_con_attach, sim_con_detach,
|
||||
"CON-TELNET", sim_con_units, sim_con_reg, sim_con_mod,
|
||||
2, 0, 0, 0, 0, 0,
|
||||
NULL, NULL, sim_con_reset, NULL, sim_con_attach, sim_con_detach,
|
||||
NULL, DEV_DEBUG | DEV_NOSAVE, 0, sim_con_debug,
|
||||
NULL, NULL, NULL, NULL, NULL, sim_con_telnet_description};
|
||||
TMLN sim_con_ldsc = { 0 }; /* console line descr */
|
||||
|
@ -325,7 +325,7 @@ static t_stat sim_con_detach (UNIT *uptr)
|
|||
return sim_set_notelnet (0, NULL);
|
||||
}
|
||||
|
||||
/* Forward declaratations */
|
||||
/* Forward declarations */
|
||||
|
||||
static t_stat sim_os_fd_isatty (int fd);
|
||||
|
||||
|
@ -505,9 +505,9 @@ return "Remote Console Facility";
|
|||
}
|
||||
|
||||
DEVICE sim_remote_console = {
|
||||
"REM-CON", NULL, NULL, sim_rem_con_mod,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
NULL, NULL, sim_rem_con_reset, NULL, NULL, NULL,
|
||||
"REM-CON", NULL, NULL, sim_rem_con_mod,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
NULL, NULL, sim_rem_con_reset, NULL, NULL, NULL,
|
||||
NULL, DEV_DEBUG | DEV_NOSAVE, 0, sim_rem_con_debug,
|
||||
NULL, NULL, NULL, NULL, NULL, sim_rem_con_description};
|
||||
|
||||
|
@ -711,7 +711,7 @@ if (c >= 0) { /* poll connect */
|
|||
tmxr_linemsgf (lp, "%s Remote Console\r\n"
|
||||
"Enter single commands or to enter multiple command mode enter the %s character\r"
|
||||
"%s",
|
||||
sim_name, wru_name,
|
||||
sim_name, wru_name,
|
||||
((sim_rem_master_mode && (c == 0)) ? "" : "\nSimulator Running..."));
|
||||
if (sim_rem_master_mode && (c == 0)) /* Master Mode session? */
|
||||
rem->single_mode = FALSE; /* start in multi-command mode */
|
||||
|
@ -878,7 +878,7 @@ return SCPE_OK;
|
|||
static t_stat _sim_rem_message (const char *cmd, t_stat stat)
|
||||
{
|
||||
CTAB *cmdp = NULL;
|
||||
t_stat stat_nomessage = stat & SCPE_NOMESSAGE; /* extract possible message supression flag */
|
||||
t_stat stat_nomessage = stat & SCPE_NOMESSAGE; /* extract possible message suppression flag */
|
||||
|
||||
cmdp = find_cmd (cmd);
|
||||
stat = SCPE_BARE_STATUS(stat); /* remove possible flag */
|
||||
|
@ -906,7 +906,7 @@ if ((!sim_oline) && (sim_log)) {
|
|||
tmxr_linemsgf (lp, "%s", cbuf);
|
||||
}
|
||||
sim_oline = NULL;
|
||||
if ((rem->act == NULL) &&
|
||||
if ((rem->act == NULL) &&
|
||||
(!tmxr_input_pending_ln (lp))) {
|
||||
size_t unwritten;
|
||||
|
||||
|
@ -1001,7 +1001,7 @@ if ((ep != NULL) && (*ep != ';')) { /* if a quoted string is present
|
|||
if (ep [0] == '\\' && ep [1] == quote) /* if an escaped quote sequence follows */
|
||||
ep = ep + 2; /* then skip over the pair */
|
||||
else /* otherwise */
|
||||
ep = ep + 1; /* skip the non-quote character */
|
||||
ep = ep + 1; /* skip the non-quote character */
|
||||
ep = strchr (ep, ';'); /* the next semicolon is outside the quotes if it exists */
|
||||
}
|
||||
|
||||
|
@ -1019,7 +1019,7 @@ else {
|
|||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
Parse and setup Remote Console REPEAT command:
|
||||
REPEAT EVERY nnn USECS Command {; command...}
|
||||
*/
|
||||
|
@ -1100,7 +1100,7 @@ return stat;
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
/*
|
||||
Parse and setup Remote Console REPEAT command:
|
||||
COLLECT nnn SAMPLES EVERY nnn CYCLES reg{,reg...}
|
||||
*/
|
||||
|
@ -1396,8 +1396,8 @@ CTAB *basecmdp = NULL;
|
|||
uint32 read_start_time = 0;
|
||||
|
||||
tmxr_poll_rx (&sim_rem_con_tmxr); /* poll input */
|
||||
for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
|
||||
(i < sim_rem_con_tmxr.lines) && (!active_command);
|
||||
for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
|
||||
(i < sim_rem_con_tmxr.lines) && (!active_command);
|
||||
i++) {
|
||||
REMOTE *rem = &sim_rem_consoles[i];
|
||||
t_bool master_session = (sim_rem_master_mode && (i == 0));
|
||||
|
@ -1553,7 +1553,7 @@ for (i=(was_active_command ? sim_rem_cmd_active_line : 0);
|
|||
c = tmxr_getc_ln (lp);
|
||||
if (!(TMXR_VALID & c)) {
|
||||
tmxr_send_buffered_data (lp); /* flush any buffered data */
|
||||
if (!master_session &&
|
||||
if (!master_session &&
|
||||
rem->read_timeout &&
|
||||
((sim_os_msec() - read_start_time)/1000 >= rem->read_timeout)) {
|
||||
while (rem->buf_ptr > 0) { /* Erase current input line */
|
||||
|
@ -1879,7 +1879,7 @@ if (sim_rem_cmd_active_line != -1) {
|
|||
return SCPE_REMOTE; /* force sim_instr() to exit to process command */
|
||||
}
|
||||
else
|
||||
sim_activate_after(uptr, 100000); /* check again in 100 milliaeconds */
|
||||
sim_activate_after(uptr, 100000); /* check again in 100 milliseconds */
|
||||
if (sim_rem_master_was_enabled && !sim_rem_master_mode) { /* Transitioning out of master mode? */
|
||||
lp = &sim_rem_con_tmxr.ldsc[0];
|
||||
tmxr_linemsgf (lp, "Non Master Mode Session..."); /* report transition */
|
||||
|
@ -2059,7 +2059,7 @@ return sim_rem_master_mode && /* maste
|
|||
/* In master mode, commands are subsequently processed from the
|
||||
primary/initial (master mode) remote console session. Commands
|
||||
are processed from that source until that source disables master
|
||||
mode or the simulator exits
|
||||
mode or the simulator exits
|
||||
*/
|
||||
|
||||
static t_stat sim_set_rem_master (int32 flag, CONST char *cptr)
|
||||
|
@ -2092,7 +2092,7 @@ if (sim_rem_master_mode) {
|
|||
sim_activate (rem_con_data_unit, -1);
|
||||
stat = run_cmd (RU_GO, "");
|
||||
if (stat != SCPE_TTMO) {
|
||||
stat_nomessage = stat & SCPE_NOMESSAGE; /* extract possible message supression flag */
|
||||
stat_nomessage = stat & SCPE_NOMESSAGE; /* extract possible message suppression flag */
|
||||
stat = _sim_rem_message ("RUN", stat);
|
||||
}
|
||||
brk_action = sim_brk_replace_act (NULL);
|
||||
|
@ -2203,7 +2203,7 @@ if (sim_devices[0]->dradix == 16)
|
|||
else
|
||||
fprintf (st, "pchar mask = %o", sim_tt_pchar);
|
||||
if (sim_tt_pchar) {
|
||||
static const char *pchars[] = {"NUL(^@)", "SOH(^A)", "STX(^B)", "ETX(^C)", "EOT(^D)", "ENQ(^E)", "ACK(^F)", "BEL(^G)",
|
||||
static const char *pchars[] = {"NUL(^@)", "SOH(^A)", "STX(^B)", "ETX(^C)", "EOT(^D)", "ENQ(^E)", "ACK(^F)", "BEL(^G)",
|
||||
"BS(^H)" , "HT(^I)", "LF(^J)", "VT(^K)", "FF(^L)", "CR(^M)", "SO(^N)", "SI(^O)",
|
||||
"DLE(^P)", "DC1(^Q)", "DC2(^R)", "DC3(^S)", "DC4(^T)", "NAK(^U)", "SYN(^V)", "ETB(^W)",
|
||||
"CAN(^X)", "EM(^Y)", "SUB(^Z)", "ESC", "FS", "GS", "RS", "US"};
|
||||
|
@ -2258,14 +2258,14 @@ cptr = get_glyph_nc (cptr, gbuf, 0); /* get file name */
|
|||
if (*cptr != 0) /* now eol? */
|
||||
return SCPE_2MARG;
|
||||
sim_set_logoff (0, NULL); /* close cur log */
|
||||
r = sim_open_logfile (gbuf, (sim_switches & SWMASK ('B')) == SWMASK ('B'),
|
||||
r = sim_open_logfile (gbuf, (sim_switches & SWMASK ('B')) == SWMASK ('B'),
|
||||
&sim_log, &sim_log_ref); /* open log */
|
||||
if (r != SCPE_OK) /* error? */
|
||||
return r;
|
||||
if ((!sim_quiet) && (!(sim_switches & SWMASK ('Q'))))
|
||||
fprintf (stdout, "Logging to file \"%s\"\n",
|
||||
fprintf (stdout, "Logging to file \"%s\"\n",
|
||||
sim_logfile_name (sim_log, sim_log_ref));
|
||||
fprintf (sim_log, "Logging to file \"%s\"\n",
|
||||
fprintf (sim_log, "Logging to file \"%s\"\n",
|
||||
sim_logfile_name (sim_log, sim_log_ref)); /* start of log */
|
||||
time(&now);
|
||||
if ((!sim_quiet) && (!(sim_switches & SWMASK ('Q'))))
|
||||
|
@ -2296,7 +2296,7 @@ t_stat sim_show_log (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, CONST char
|
|||
if (cptr && (*cptr != 0))
|
||||
return SCPE_2MARG;
|
||||
if (sim_log)
|
||||
fprintf (st, "Logging enabled to \"%s\"\n",
|
||||
fprintf (st, "Logging enabled to \"%s\"\n",
|
||||
sim_logfile_name (sim_log, sim_log_ref));
|
||||
else
|
||||
fprintf (st, "Logging disabled\n");
|
||||
|
@ -2309,9 +2309,9 @@ int32 sim_set_deb_switches (int32 switches)
|
|||
{
|
||||
int32 old_deb_switches = sim_deb_switches;
|
||||
|
||||
sim_deb_switches = switches &
|
||||
(SWMASK ('R') | SWMASK ('P') |
|
||||
SWMASK ('T') | SWMASK ('A') |
|
||||
sim_deb_switches = switches &
|
||||
(SWMASK ('R') | SWMASK ('P') |
|
||||
SWMASK ('T') | SWMASK ('A') |
|
||||
SWMASK ('F') | SWMASK ('N') |
|
||||
SWMASK ('B') | SWMASK ('E') |
|
||||
SWMASK ('D') ); /* save debug switches */
|
||||
|
@ -2370,7 +2370,7 @@ if (sim_deb_switches & SWMASK ('F'))
|
|||
if (sim_deb_switches & SWMASK ('E'))
|
||||
sim_messagef (SCPE_OK, " Debug messages containing blob data in EBCDIC will display in readable form\n");
|
||||
if (sim_deb_switches & SWMASK ('B'))
|
||||
sim_messagef (SCPE_OK, " Debug messages will be written to a %u MB circular memory buffer\n",
|
||||
sim_messagef (SCPE_OK, " Debug messages will be written to a %u MB circular memory buffer\n",
|
||||
(unsigned int)buffer_size);
|
||||
time(&now);
|
||||
if (!sim_quiet) {
|
||||
|
@ -2432,7 +2432,7 @@ int32 i;
|
|||
if (cptr && (*cptr != 0))
|
||||
return SCPE_2MARG;
|
||||
if (sim_deb) {
|
||||
fprintf (st, "Debug output enabled to \"%s\"\n",
|
||||
fprintf (st, "Debug output enabled to \"%s\"\n",
|
||||
sim_logfile_name (sim_deb, sim_deb_ref));
|
||||
if (sim_deb_switches & SWMASK ('P'))
|
||||
fprintf (st, " Debug messages contain current PC value\n");
|
||||
|
@ -2536,7 +2536,7 @@ t_stat sim_show_telnet (FILE *st, DEVICE *dunused, UNIT *uunused, int32 flag, CO
|
|||
{
|
||||
if (cptr && (*cptr != 0))
|
||||
return SCPE_2MARG;
|
||||
if ((sim_con_tmxr.master == 0) &&
|
||||
if ((sim_con_tmxr.master == 0) &&
|
||||
(sim_con_ldsc.serport == 0))
|
||||
fprintf (st, "Connected to console window\n");
|
||||
else {
|
||||
|
@ -2544,7 +2544,7 @@ else {
|
|||
fprintf (st, "Connected to ");
|
||||
tmxr_fconns (st, &sim_con_ldsc, -1);
|
||||
}
|
||||
else
|
||||
else
|
||||
if (sim_con_ldsc.sock == 0)
|
||||
fprintf (st, "Listening on port %s\n", sim_con_tmxr.port);
|
||||
else {
|
||||
|
@ -2790,7 +2790,7 @@ if (!ref)
|
|||
return ref->name;
|
||||
}
|
||||
|
||||
/* Check connection before executing
|
||||
/* Check connection before executing
|
||||
(including a remote console which may be required in master mode) */
|
||||
|
||||
t_stat sim_check_console (int32 sec)
|
||||
|
@ -2827,7 +2827,7 @@ if (trys == sec) {
|
|||
return SCPE_TTMO; /* timed out */
|
||||
}
|
||||
if (sim_con_ldsc.serport)
|
||||
if (tmxr_poll_conn (&sim_con_tmxr) >= 0)
|
||||
if (tmxr_poll_conn (&sim_con_tmxr) >= 0)
|
||||
sim_con_ldsc.rcve = 1; /* rcv enabled */
|
||||
if ((sim_con_tmxr.master == 0) || /* serial console or not Telnet? done */
|
||||
(sim_con_ldsc.serport))
|
||||
|
@ -2931,7 +2931,7 @@ if (!sim_rem_master_mode) {
|
|||
}
|
||||
}
|
||||
tmxr_poll_rx (&sim_con_tmxr); /* poll for input */
|
||||
if ((c = (t_stat)tmxr_getc_ln (&sim_con_ldsc))) { /* any char? */
|
||||
if ((c = (t_stat)tmxr_getc_ln (&sim_con_ldsc))) { /* any char? */
|
||||
sim_debug (DBG_RCV, &sim_con_telnet, "sim_poll_kbd() tmxr_getc_ln() returning: '%c' (0x%02X)\n", sim_isprint (c & 0xFF) ? c & 0xFF : '.', c);
|
||||
return (c & (SCPE_BREAK | 0377)) | SCPE_KFLAG;
|
||||
}
|
||||
|
@ -3128,7 +3128,7 @@ if ((md == TTUF_MODE_UC) && (par_mode == TTUF_PAR_MARK))
|
|||
fprintf (st, "KSR (UC, MARK parity)");
|
||||
else
|
||||
fprintf (st, "%s", modes[md]);
|
||||
if ((md != TTUF_MODE_8B) &&
|
||||
if ((md != TTUF_MODE_8B) &&
|
||||
((md != TTUF_MODE_UC) || (par_mode != TTUF_PAR_MARK))) {
|
||||
if (par_mode != 0)
|
||||
fprintf (st, ", %s parity", parity[par_mode]);
|
||||
|
@ -3153,8 +3153,8 @@ _console_poll(void *arg)
|
|||
int wait_count = 0;
|
||||
DEVICE *d;
|
||||
|
||||
/* Boost Priority for this I/O thread vs the CPU instruction execution
|
||||
thread which, in general, won't be readily yielding the processor when
|
||||
/* Boost Priority for this I/O thread vs the CPU instruction execution
|
||||
thread which, in general, won't be readily yielding the processor when
|
||||
this thread needs to run */
|
||||
sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL);
|
||||
|
||||
|
@ -3496,11 +3496,11 @@ static DWORD saved_error_mode;
|
|||
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
|
||||
#endif
|
||||
|
||||
/* Note: This routine catches all the potential events which some aspect
|
||||
of the windows system can generate. The CTRL_C_EVENT won't be
|
||||
generated by a user typing in a console session since that
|
||||
/* Note: This routine catches all the potential events which some aspect
|
||||
of the windows system can generate. The CTRL_C_EVENT won't be
|
||||
generated by a user typing in a console session since that
|
||||
session is in RAW mode. In general, Ctrl-C on a simulator's
|
||||
console terminal is a useful character to be passed to the
|
||||
console terminal is a useful character to be passed to the
|
||||
simulator. This code does nothing to disable or affect that. */
|
||||
|
||||
#include <signal.h>
|
||||
|
@ -3513,7 +3513,7 @@ ControlHandler(DWORD dwCtrlType)
|
|||
|
||||
switch (dwCtrlType)
|
||||
{
|
||||
case CTRL_BREAK_EVENT: // Use CTRL-Break or CTRL-C to simulate
|
||||
case CTRL_BREAK_EVENT: // Use CTRL-Break or CTRL-C to simulate
|
||||
case CTRL_C_EVENT: // SERVICE_CONTROL_STOP in debug mode
|
||||
int_handler(SIGINT);
|
||||
return TRUE;
|
||||
|
@ -3927,11 +3927,11 @@ static t_stat sim_os_ttinit (void)
|
|||
sim_debug (DBG_TRC, &sim_con_telnet, "sim_os_ttinit()\n");
|
||||
|
||||
cmdfl = fcntl (fileno (stdin), F_GETFL, 0); /* get old flags and status */
|
||||
/*
|
||||
/*
|
||||
* make sure systems with broken termios (that don't honor
|
||||
* VMIN=0 and VTIME=0) actually implement non blocking reads.
|
||||
* This will have no negative effect on other systems since
|
||||
* this is turned on and off depending on whether simulation
|
||||
* VMIN=0 and VTIME=0) actually implement non blocking reads.
|
||||
* This will have no negative effect on other systems since
|
||||
* this is turned on and off depending on whether simulation
|
||||
* is running or not.
|
||||
*/
|
||||
runfl = cmdfl | O_NONBLOCK;
|
||||
|
@ -4130,7 +4130,7 @@ else {
|
|||
|
||||
mbuf2 = (char *)malloc (3 + strlen(cptr));
|
||||
sprintf (mbuf2, "%s%s%s", (sim_switches & SWMASK ('A')) ? "\n" : "",
|
||||
mbuf,
|
||||
mbuf,
|
||||
(sim_switches & SWMASK ('I')) ? "" : "\n");
|
||||
free (mbuf);
|
||||
mbuf = sim_encode_quoted_string ((uint8 *)mbuf2, strlen (mbuf2));
|
||||
|
|
|
@ -212,7 +212,7 @@ extern "C" {
|
|||
|
||||
/* Length specific integer declarations */
|
||||
|
||||
/* Handle the special/unusual cases first with everything else leveraging stdints.h */
|
||||
/* Handle the special/unusual cases first with everything else leveraging stdint.h */
|
||||
#if defined (VMS)
|
||||
#include <ints.h>
|
||||
#elif defined(_MSC_VER) && (_MSC_VER < 1600)
|
||||
|
@ -224,7 +224,7 @@ typedef unsigned __int16 uint16;
|
|||
typedef unsigned __int32 uint32;
|
||||
#else
|
||||
/* All modern/standard compiler environments */
|
||||
/* any other environment needa a special case above */
|
||||
/* any other environment needs a special case above */
|
||||
#include <stdint.h>
|
||||
typedef int8_t int8;
|
||||
typedef int16_t int16;
|
||||
|
@ -435,7 +435,7 @@ typedef uint32 t_addr;
|
|||
#define SCPE_MAX_ERR (SCPE_BASE + 51) /* Maximum SCPE Error Value */
|
||||
#define SCPE_KFLAG 0x10000000 /* tti data flag */
|
||||
#define SCPE_BREAK 0x20000000 /* tti break flag */
|
||||
#define SCPE_NOMESSAGE 0x40000000 /* message display supression flag */
|
||||
#define SCPE_NOMESSAGE 0x40000000 /* message display suppression flag */
|
||||
#define SCPE_BARE_STATUS(stat) ((stat) & ~(SCPE_NOMESSAGE|SCPE_KFLAG|SCPE_BREAK))
|
||||
|
||||
/* Print value format codes */
|
||||
|
|
166
sim_disk.c
166
sim_disk.c
|
@ -28,7 +28,7 @@
|
|||
This is the place which hides processing of various disk formats,
|
||||
as well as OS-specific direct hardware access.
|
||||
|
||||
25-Jan-11 MP Initial Implemementation
|
||||
25-Jan-11 MP Initial Implementation
|
||||
|
||||
Public routines:
|
||||
|
||||
|
@ -276,8 +276,8 @@ return NULL;
|
|||
processing events for any unit. It is only called when an asynchronous
|
||||
thread has called sim_activate() to activate a unit. The job of this
|
||||
routine is to put the unit in proper condition to digest what may have
|
||||
occurred in the asynchrconous thread.
|
||||
|
||||
occurred in the asynchronous thread.
|
||||
|
||||
Since disk processing only handles a single I/O at a time to a
|
||||
particular disk device (due to using stdio for the SimH Disk format
|
||||
and stdio doesn't have an atomic seek+(read|write) operation),
|
||||
|
@ -487,7 +487,7 @@ switch (DK_GET_FMT (uptr)) { /* case on format */
|
|||
sim_switches = 0;
|
||||
sim_quiet = 1;
|
||||
strcpy (path, uptr->filename);
|
||||
sim_disk_attach (uptr, path, ctx->sector_size, ctx->xfer_element_size,
|
||||
sim_disk_attach (uptr, path, ctx->sector_size, ctx->xfer_element_size,
|
||||
FALSE, ctx->dbit, NULL, 0, 0);
|
||||
sim_quiet = saved_quiet;
|
||||
sim_switches = saved_switches;
|
||||
|
@ -524,7 +524,7 @@ DEVICE *dptr;
|
|||
uint32 dev, unit, count = 0;
|
||||
|
||||
if (flag == sim_disk_no_autosize)
|
||||
return sim_messagef (SCPE_ARG, "Autosizing is already %sabled!\n",
|
||||
return sim_messagef (SCPE_ARG, "Autosizing is already %sabled!\n",
|
||||
sim_disk_no_autosize ? "dis" : "en");
|
||||
for (dev = 0; (dptr = sim_devices[dev]) != NULL; dev++) {
|
||||
if ((DEV_TYPE (dptr) != DEV_DISK) ||
|
||||
|
@ -665,7 +665,7 @@ while (tbc) {
|
|||
if (i < tbc) /* fill */
|
||||
memset (&buf[i], 0, tbc-i);
|
||||
if ((i == 0) && /* Reading at or past EOF? */
|
||||
feof (uptr->fileref))
|
||||
feof (uptr->fileref))
|
||||
i = tbc; /* return 0's which have already been filled in buffer */
|
||||
sectbytes = (i / ctx->sector_size) * ctx->sector_size;
|
||||
if (i > sectbytes)
|
||||
|
@ -871,7 +871,7 @@ if (f == DKUF_F_RAW) {
|
|||
if (tbuf == NULL)
|
||||
return SCPE_MEM;
|
||||
/* Partial Sector writes require a read-modify-write sequence for the partial sectors */
|
||||
if (soffset)
|
||||
if (soffset)
|
||||
sim_os_disk_read (uptr, ssaddr, tbuf, NULL, ctx->storage_sector_size);
|
||||
sim_os_disk_read (uptr, sladdr, tbuf + (size_t)(sladdr - ssaddr), NULL, ctx->storage_sector_size);
|
||||
sim_buf_copy_swapped (tbuf + soffset,
|
||||
|
@ -982,13 +982,13 @@ static t_stat _sim_disk_rdsect_interleave (UNIT *uptr, t_lba lba, uint8 *buf, t_
|
|||
struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx;
|
||||
t_lba sectno = lba, psa;
|
||||
t_stat status;
|
||||
|
||||
|
||||
if (sectsread)
|
||||
*sectsread = 0;
|
||||
|
||||
do {
|
||||
uint16 i, track, sector;
|
||||
|
||||
|
||||
/*
|
||||
* Map an LBA address into a physical sector address
|
||||
*/
|
||||
|
@ -1141,7 +1141,7 @@ typedef struct _ODS2_FileHeader
|
|||
|
||||
typedef union _ODS2_Retreval
|
||||
{
|
||||
struct
|
||||
struct
|
||||
{
|
||||
unsigned fm2___fill : 14; /* type specific data */
|
||||
unsigned fm2_v_format : 2; /* format type code */
|
||||
|
@ -1278,31 +1278,31 @@ if ((_DEC_rdsect (uptr, 512 / ctx->sector_size, (uint8 *)&Home, §s_read, siz
|
|||
goto Return_Cleanup;
|
||||
CheckSum1 = ODSChecksum (&Home, (uint16)((((char *)&Home.hm2_w_checksum1)-((char *)&Home.hm2_l_homelbn))/2));
|
||||
CheckSum2 = ODSChecksum (&Home, (uint16)((((char *)&Home.hm2_w_checksum2)-((char *)&Home.hm2_l_homelbn))/2));
|
||||
if ((Home.hm2_l_homelbn == 0) ||
|
||||
(Home.hm2_l_alhomelbn == 0) ||
|
||||
(Home.hm2_l_altidxlbn == 0) ||
|
||||
((Home.hm2_b_struclev != 2) && (Home.hm2_b_struclev != 5)) ||
|
||||
(Home.hm2_b_strucver == 0) ||
|
||||
(Home.hm2_w_cluster == 0) ||
|
||||
(Home.hm2_w_homevbn == 0) ||
|
||||
(Home.hm2_w_alhomevbn == 0) ||
|
||||
(Home.hm2_w_ibmapvbn == 0) ||
|
||||
(Home.hm2_l_ibmaplbn == 0) ||
|
||||
(Home.hm2_w_resfiles >= Home.hm2_l_maxfiles) ||
|
||||
(Home.hm2_w_ibmapsize == 0) ||
|
||||
(Home.hm2_w_resfiles < 5) ||
|
||||
if ((Home.hm2_l_homelbn == 0) ||
|
||||
(Home.hm2_l_alhomelbn == 0) ||
|
||||
(Home.hm2_l_altidxlbn == 0) ||
|
||||
((Home.hm2_b_struclev != 2) && (Home.hm2_b_struclev != 5)) ||
|
||||
(Home.hm2_b_strucver == 0) ||
|
||||
(Home.hm2_w_cluster == 0) ||
|
||||
(Home.hm2_w_homevbn == 0) ||
|
||||
(Home.hm2_w_alhomevbn == 0) ||
|
||||
(Home.hm2_w_ibmapvbn == 0) ||
|
||||
(Home.hm2_l_ibmaplbn == 0) ||
|
||||
(Home.hm2_w_resfiles >= Home.hm2_l_maxfiles) ||
|
||||
(Home.hm2_w_ibmapsize == 0) ||
|
||||
(Home.hm2_w_resfiles < 5) ||
|
||||
(Home.hm2_w_checksum1 != CheckSum1) ||
|
||||
(Home.hm2_w_checksum2 != CheckSum2))
|
||||
goto Return_Cleanup;
|
||||
if ((_DEC_rdsect (uptr, (Home.hm2_l_ibmaplbn+Home.hm2_w_ibmapsize+1) * (512 / ctx->sector_size),
|
||||
(uint8 *)&Header, §s_read, sizeof (Header) / ctx->sector_size, physsectsz)) ||
|
||||
if ((_DEC_rdsect (uptr, (Home.hm2_l_ibmaplbn+Home.hm2_w_ibmapsize+1) * (512 / ctx->sector_size),
|
||||
(uint8 *)&Header, §s_read, sizeof (Header) / ctx->sector_size, physsectsz)) ||
|
||||
(sects_read != (sizeof (Header) / ctx->sector_size)))
|
||||
goto Return_Cleanup;
|
||||
CheckSum1 = ODSChecksum (&Header, 255);
|
||||
if (CheckSum1 != *(((uint16 *)&Header)+255)) /* Verify Checksum on BITMAP.SYS file header */
|
||||
goto Return_Cleanup;
|
||||
Retr = (ODS2_Retreval *)(((uint16*)(&Header))+Header.fh2_b_mpoffset);
|
||||
/* The BitMap File has a single extent, which may be preceeded by a placement descriptor */
|
||||
/* The BitMap File has a single extent, which may be preceded by a placement descriptor */
|
||||
if (Retr->fm2_r_word0_bits.fm2_v_format == 0)
|
||||
Retr = (ODS2_Retreval *)(((uint16 *)Retr)+1); /* skip placement descriptor */
|
||||
switch (Retr->fm2_r_word0_bits.fm2_v_format)
|
||||
|
@ -1324,12 +1324,12 @@ if ((_DEC_rdsect (uptr, ScbLbn * (512 / ctx->sector_size), (uint8 *)&Scb, §s
|
|||
CheckSum1 = ODSChecksum (&Scb, 255);
|
||||
if (CheckSum1 != *(((uint16 *)&Scb)+255)) /* Verify Checksum on Storage Control Block */
|
||||
goto Return_Cleanup;
|
||||
if ((Scb.scb_w_cluster != Home.hm2_w_cluster) ||
|
||||
if ((Scb.scb_w_cluster != Home.hm2_w_cluster) ||
|
||||
(Scb.scb_b_strucver != Home.hm2_b_strucver) ||
|
||||
(Scb.scb_b_struclev != Home.hm2_b_struclev))
|
||||
goto Return_Cleanup;
|
||||
sim_messagef (SCPE_OK, "%s: '%s' Contains ODS%d File system\n", sim_uname (uptr), uptr->filename, Home.hm2_b_struclev);
|
||||
sim_messagef (SCPE_OK, "%s: Volume Name: %12.12s Format: %12.12s Sectors In Volume: %u\n",
|
||||
sim_messagef (SCPE_OK, "%s: Volume Name: %12.12s Format: %12.12s Sectors In Volume: %u\n",
|
||||
sim_uname (uptr), Home.hm2_t_volname, Home.hm2_t_format, Scb.scb_l_volsize);
|
||||
ret_val = ((t_offset)Scb.scb_l_volsize) * 512;
|
||||
|
||||
|
@ -1365,12 +1365,12 @@ if ((_DEC_rdsect (uptr, 512 / ctx->sector_size, (uint8 *)&Home, §s_read, siz
|
|||
goto Return_Cleanup;
|
||||
CheckSum1 = ODSChecksum (&Home, (uint16)((((char *)&Home.hm1_w_checksum1)-((char *)&Home.hm1_w_ibmapsize))/2));
|
||||
CheckSum2 = ODSChecksum (&Home, (uint16)((((char *)&Home.hm1_w_checksum2)-((char *)&Home.hm1_w_ibmapsize))/2));
|
||||
if ((Home.hm1_w_ibmapsize == 0) ||
|
||||
(Home.hm1_l_ibmaplbn == 0) ||
|
||||
(Home.hm1_w_maxfiles == 0) ||
|
||||
(Home.hm1_w_cluster != 1) ||
|
||||
((Home.hm1_w_structlev != HM1_C_LEVEL1) && (Home.hm1_w_structlev != HM1_C_LEVEL2)) ||
|
||||
(Home.hm1_l_ibmaplbn == 0) ||
|
||||
if ((Home.hm1_w_ibmapsize == 0) ||
|
||||
(Home.hm1_l_ibmaplbn == 0) ||
|
||||
(Home.hm1_w_maxfiles == 0) ||
|
||||
(Home.hm1_w_cluster != 1) ||
|
||||
((Home.hm1_w_structlev != HM1_C_LEVEL1) && (Home.hm1_w_structlev != HM1_C_LEVEL2)) ||
|
||||
(Home.hm1_l_ibmaplbn == 0) ||
|
||||
(Home.hm1_w_checksum1 != CheckSum1) ||
|
||||
(Home.hm1_w_checksum2 != CheckSum2))
|
||||
goto Return_Cleanup;
|
||||
|
@ -1392,7 +1392,7 @@ if (Scb->scb_b_bitmapblks < 127)
|
|||
else
|
||||
ret_val = (((t_offset)Scb->scb_r_blocks[0].scb_w_freeblks << 16) + Scb->scb_r_blocks[0].scb_w_freeptr) * 512;
|
||||
sim_messagef (SCPE_OK, "%s: '%s' Contains an ODS1 File system\n", sim_uname (uptr), uptr->filename);
|
||||
sim_messagef (SCPE_OK, "%s: Volume Name: %12.12s Format: %12.12s Sectors In Volume: %u\n",
|
||||
sim_messagef (SCPE_OK, "%s: Volume Name: %12.12s Format: %12.12s Sectors In Volume: %u\n",
|
||||
sim_uname (uptr), Home.hm1_t_volname, Home.hm1_t_format, (uint32)(ret_val / 512));
|
||||
Return_Cleanup:
|
||||
uptr->capac = saved_capac;
|
||||
|
@ -1434,7 +1434,7 @@ if ((_DEC_rdsect (uptr, 31 * (512 / ctx->sector_size), sector_buf, §s_read,
|
|||
(sects_read != (512 / ctx->sector_size)))
|
||||
goto Return_Cleanup;
|
||||
|
||||
if ((Label->pt_magic != PT_MAGIC) ||
|
||||
if ((Label->pt_magic != PT_MAGIC) ||
|
||||
(Label->pt_valid != PT_VALID))
|
||||
goto Return_Cleanup;
|
||||
|
||||
|
@ -1524,7 +1524,7 @@ saved_capac = uptr->capac;
|
|||
uptr->capac = temp_capac;
|
||||
|
||||
while (sim_disk_rdsect(uptr, (t_lba)(sectfactor * cur_pos / sizeof (*Desc)), (uint8 *)Desc, §sread, sectfactor) == DKSE_OK) {
|
||||
if ((sectsread != sectfactor) ||
|
||||
if ((sectsread != sectfactor) ||
|
||||
(Desc->Version != 1) ||
|
||||
(0 != memcmp (Desc->Identifier, "CD001", sizeof (Desc->Identifier))))
|
||||
break;
|
||||
|
@ -2027,7 +2027,7 @@ for (context.dcshift = 0; context.dcshift < 8; context.dcshift++) {
|
|||
}
|
||||
|
||||
sim_messagef(SCPE_OK, "%s: '%s' Contains a RSTS File system\n", sim_uname (uptr), uptr->filename);
|
||||
sim_messagef(SCPE_OK, "%s: Pack ID: %6.6s Revision Level: %3s Pack Clustersize: %d\n",
|
||||
sim_messagef(SCPE_OK, "%s: Pack ID: %6.6s Revision Level: %3s Pack Clustersize: %d\n",
|
||||
sim_uname (uptr), context.packid, fmt, context.pcs);
|
||||
sim_messagef(SCPE_OK, "%s: Last Unallocated Sector In File System: %u\n", sim_uname (uptr), (uint32)((ret_val / 512) - 1));
|
||||
goto cleanup_done;
|
||||
|
@ -2120,7 +2120,7 @@ if (strncmp((char *)&home->hb_b_sysid, HB_C_SYSID, strlen(HB_C_SYSID)) == 0) {
|
|||
|
||||
if (strncmp((char *)&home->hb_b_sysid, HB_C_VMSSYSID, strlen(HB_C_VMSSYSID)) == 0)
|
||||
return RT11_SINGLEPART;
|
||||
|
||||
|
||||
return RT11_NOPART;
|
||||
}
|
||||
|
||||
|
@ -2156,7 +2156,7 @@ for (part = 0; part < RT11_MAXPARTITIONS; part++) {
|
|||
*/
|
||||
if ((part != 0) && (physsectsz != 0))
|
||||
break;
|
||||
|
||||
|
||||
base = part << 16;
|
||||
|
||||
if (_DEC_rdsect(uptr, (base + RT11_HOME) * (512 / ctx->sector_size), (uint8 *)&Home, §s_read, 512 / ctx->sector_size, physsectsz) ||
|
||||
|
@ -2293,22 +2293,22 @@ for (i = 0; checks[i] != NULL; i++)
|
|||
if ((ret_val = checks[i] (uptr, 0, readonly)) != (t_offset)-1) {
|
||||
/* ISO files that haven't already been determined to be ISO 9660
|
||||
* which contain a known file system are also marked read-only
|
||||
* now. This fits early DEC distribution CDs that were created
|
||||
* now. This fits early DEC distribution CDs that were created
|
||||
* before ISO 9660 was standardized and operating support was added.
|
||||
*/
|
||||
if ((readonly != NULL) &&
|
||||
if ((readonly != NULL) &&
|
||||
(*readonly == FALSE) &&
|
||||
(NULL != match_ext (uptr->filename, "ISO")))
|
||||
*readonly = TRUE;
|
||||
return ret_val;
|
||||
}
|
||||
/*
|
||||
* The only known interleaved disk devices have either 256 byte
|
||||
* or 128 byte sector sizes. If additional interleaved file
|
||||
/*
|
||||
* The only known interleaved disk devices have either 256 byte
|
||||
* or 128 byte sector sizes. If additional interleaved file
|
||||
* system scenarios with different sector sizes come up they
|
||||
* should be added here.
|
||||
*/
|
||||
|
||||
|
||||
for (i = 0; checks[i] != NULL; i++) {
|
||||
ctx->sector_size = 256;
|
||||
if ((ret_val = checks[i] (uptr, ctx->sector_size, readonly)) != (t_offset)-1)
|
||||
|
@ -2318,7 +2318,7 @@ for (i = 0; checks[i] != NULL; i++) {
|
|||
break;
|
||||
}
|
||||
if ((ret_val != (t_offset)-1) && (ctx->sector_size != saved_sector_size ))
|
||||
sim_messagef (SCPE_OK, "%s: with an unexpected sector size of %u bytes instead of %u bytes\n",
|
||||
sim_messagef (SCPE_OK, "%s: with an unexpected sector size of %u bytes instead of %u bytes\n",
|
||||
sim_uname (uptr), ctx->sector_size, saved_sector_size);
|
||||
ctx->sector_size = saved_sector_size;
|
||||
return ret_val;
|
||||
|
@ -2395,7 +2395,7 @@ if (f) {
|
|||
}
|
||||
else {
|
||||
/* We've got a valid footer, but it may need to be corrected */
|
||||
if ((NtoHl (f->TransferElementSize) == 1) &&
|
||||
if ((NtoHl (f->TransferElementSize) == 1) &&
|
||||
(0 == memcmp (f->DriveType, "RZ", 2))) {
|
||||
f->TransferElementSize = NtoHl (2);
|
||||
f->Checksum = NtoHl (eth_crc32 (0, f, sizeof (*f) - sizeof (f->Checksum)));
|
||||
|
@ -2415,12 +2415,12 @@ if (f) {
|
|||
" AccessFormat: %u\n"
|
||||
" CreationTime: %s",
|
||||
sim_uname (uptr), uptr->filename,
|
||||
f->CreatingSimulator, f->DriveType, NtoHl(f->SectorSize), NtoHl (f->SectorCount),
|
||||
f->CreatingSimulator, f->DriveType, NtoHl(f->SectorSize), NtoHl (f->SectorCount),
|
||||
NtoHl (f->TransferElementSize), f->FooterVersion, f->AccessFormat, f->CreationTime);
|
||||
if (f->DeviceName[0] != '\0')
|
||||
sim_debug_unit (ctx->dbit, uptr,
|
||||
sim_debug_unit (ctx->dbit, uptr,
|
||||
" DeviceName: %s\n", (char *)f->DeviceName);
|
||||
sim_debug_unit (ctx->dbit, uptr,
|
||||
sim_debug_unit (ctx->dbit, uptr,
|
||||
" HighwaterSector: %u\n", (uint32)(ctx->highwater/ctx->sector_size));
|
||||
}
|
||||
}
|
||||
|
@ -2677,7 +2677,7 @@ if (sim_switches & SWMASK ('C')) { /* create new disk conta
|
|||
}
|
||||
sim_messagef (SCPE_OK, "Copying %u sectors each %u bytes in size\n", (uint32)total_sectors, (uint32)sector_size);
|
||||
if (source_capac > target_capac) {
|
||||
sim_messagef (SCPE_OK, "The source container is %u sectors larger than the destination disk container\n",
|
||||
sim_messagef (SCPE_OK, "The source container is %u sectors larger than the destination disk container\n",
|
||||
(t_lba)(((source_capac - target_capac)*capac_factor)/(sector_size/((dptr->flags & DEV_SECTORS) ? 512 : 1))));
|
||||
sim_messagef (SCPE_OK, "these additional sectors will be unavailable on the target drive\n");
|
||||
}
|
||||
|
@ -2739,7 +2739,7 @@ if (sim_switches & SWMASK ('C')) { /* create new disk conta
|
|||
uptr->fileref = save_unit_fileref;
|
||||
uptr->flags = saved_unit_flags;
|
||||
if (r == SCPE_OK) {
|
||||
if ((sects_read != verify_read) ||
|
||||
if ((sects_read != verify_read) ||
|
||||
(0 != memcmp (copy_buf, verify_buf, verify_read*sector_size)))
|
||||
r = SCPE_IOERR;
|
||||
}
|
||||
|
@ -2967,7 +2967,7 @@ if ((DK_GET_FMT (uptr) == DKUF_F_VHD) || (ctx->footer)) {
|
|||
if ((container_sector_size != 0) && (sector_size != container_sector_size))
|
||||
r = sim_messagef (SCPE_OPENERR, "%s: Incompatible Container Sector Size %d\n", sim_uname (uptr), container_sector_size);
|
||||
else {
|
||||
if (dontchangecapac &&
|
||||
if (dontchangecapac &&
|
||||
((((t_lba)(ctx->container_size/sector_size) > current_unit_sectors)) ||
|
||||
((container_sectors != 0) && (container_sectors != current_unit_sectors)))) {
|
||||
r = sim_messagef (SCPE_OK, "%s: Container has %u sectors, drive has: %u sectors\n", sim_uname (uptr), container_sectors, current_unit_sectors);
|
||||
|
@ -3034,7 +3034,7 @@ if ((created) && (!copied)) {
|
|||
t_lba lba;
|
||||
t_lba total_lbas = (t_lba)((((t_offset)uptr->capac)*ctx->capac_factor*((dptr->flags & DEV_SECTORS) ? 512 : 1))/ctx->sector_size);
|
||||
|
||||
for (lba = 0; (r == SCPE_OK) && (lba < total_lbas); lba += 128) {
|
||||
for (lba = 0; (r == SCPE_OK) && (lba < total_lbas); lba += 128) {
|
||||
t_seccnt sectors = ((lba + 128) <= total_lbas) ? 128 : total_lbas - lba;
|
||||
|
||||
r = sim_disk_wrsect (uptr, lba, secbuf, NULL, sectors);
|
||||
|
@ -3077,7 +3077,7 @@ if ((created) && (!copied)) {
|
|||
free (init_buf);
|
||||
sim_disk_detach (uptr); /* report error now */
|
||||
(void)remove (cptr); /* remove the created file */
|
||||
return sim_messagef (SCPE_OPENERR, "Error initializing each sector with its address: %s\n",
|
||||
return sim_messagef (SCPE_OPENERR, "Error initializing each sector with its address: %s\n",
|
||||
(r == SCPE_OK) ? sim_error_text (r) : "sectors written not what was requested");
|
||||
}
|
||||
sim_messagef (SCPE_OK, "%s: Initialized To Sector Address %u/%u sectors. %d%% complete.\r", sim_uname (uptr), (uint32)(lba + sects_written), (uint32)total_sectors, (int)((((float)lba)*100)/total_sectors));
|
||||
|
@ -3109,7 +3109,7 @@ if (sim_switches & SWMASK ('K')) {
|
|||
r = sim_disk_rdsect (uptr, lba, verify_buf, §s_verify, sects);
|
||||
if (r == SCPE_OK) {
|
||||
if (sects != sects_verify)
|
||||
sim_printf ("\n%s: Verification Error when reading lbn %d(0x%X) of %d(0x%X) Requested %u sectors, read %u sectors.\n",
|
||||
sim_printf ("\n%s: Verification Error when reading lbn %d(0x%X) of %d(0x%X) Requested %u sectors, read %u sectors.\n",
|
||||
sim_uname (uptr), (int)lba, (int)lba, (int)total_sectors, (int)total_sectors, sects, sects_verify);
|
||||
for (sect = 0; sect < sects_verify; sect++) {
|
||||
t_lba offset;
|
||||
|
@ -3181,7 +3181,7 @@ if (container_size && (container_size != (t_offset)-1)) {
|
|||
uptr->capac = (t_addr)(filesystem_size/(ctx->capac_factor*((dptr->flags & DEV_SECTORS) ? ctx->sector_size : 1)));
|
||||
capac1 = strdup (sprint_capac (dptr, uptr));
|
||||
uptr->capac = saved_capac;
|
||||
r = sim_messagef (r, "%s: The file system on the disk %s is larger than simulated device (%s > %s)\n",
|
||||
r = sim_messagef (r, "%s: The file system on the disk %s is larger than simulated device (%s > %s)\n",
|
||||
sim_uname (uptr), cptr, capac1, sprint_capac (dptr, uptr));
|
||||
free (capac1);
|
||||
sim_disk_detach (uptr);
|
||||
|
@ -3200,7 +3200,7 @@ if (container_size && (container_size != (t_offset)-1)) {
|
|||
uptr->capac = (t_addr)(container_size/(ctx->capac_factor*((dptr->flags & DEV_SECTORS) ? ctx->sector_size : 1)));
|
||||
capac1 = strdup (sprint_capac (dptr, uptr));
|
||||
uptr->capac = saved_capac;
|
||||
r = sim_messagef (r, "%s: The disk container '%s' is larger than simulated device (%s > %s)\n",
|
||||
r = sim_messagef (r, "%s: The disk container '%s' is larger than simulated device (%s > %s)\n",
|
||||
sim_uname (uptr), cptr, capac1, sprint_capac (dptr, uptr));
|
||||
free (capac1);
|
||||
sim_disk_detach (uptr);
|
||||
|
@ -3217,7 +3217,7 @@ if (container_size && (container_size != (t_offset)-1)) {
|
|||
uptr->capac = (t_addr)(filesystem_size/(ctx->capac_factor*((dptr->flags & DEV_SECTORS) ? ctx->sector_size : 1)));
|
||||
capac1 = strdup (sprint_capac (dptr, uptr));
|
||||
uptr->capac = saved_capac;
|
||||
r = sim_messagef (r, "%s: The file system on the %s disk container is larger than simulated device (%s > %s)\n",
|
||||
r = sim_messagef (r, "%s: The file system on the %s disk container is larger than simulated device (%s > %s)\n",
|
||||
sim_uname (uptr), cptr, capac1, sprint_capac (dptr, uptr));
|
||||
free (capac1);
|
||||
sim_disk_detach (uptr);
|
||||
|
@ -3236,7 +3236,7 @@ if (container_size && (container_size != (t_offset)-1)) {
|
|||
uptr->capac = (t_addr)(container_size/(ctx->capac_factor*((dptr->flags & DEV_SECTORS) ? ctx->sector_size : 1)));
|
||||
capac1 = strdup (sprint_capac (dptr, uptr));
|
||||
uptr->capac = saved_capac;
|
||||
r = sim_messagef (r, "%s: non expandable %s%sdisk container '%s' is smaller than simulated device (%s < %s)\n",
|
||||
r = sim_messagef (r, "%s: non expandable %s%sdisk container '%s' is smaller than simulated device (%s < %s)\n",
|
||||
sim_uname (uptr), container_dtype, (*container_dtype != '\0') ? " " : "", cptr, capac1, sprint_capac (dptr, uptr));
|
||||
free (capac1);
|
||||
sim_disk_detach (uptr);
|
||||
|
@ -3259,8 +3259,8 @@ if (container_size && (container_size != (t_offset)-1)) {
|
|||
container_dtype = ctx->footer ? (const char *)ctx->footer->DriveType : "";
|
||||
sim_switches = saved_switches;
|
||||
if (r == SCPE_OK)
|
||||
r = sim_messagef (SCPE_OK, "%s: %s%sdisk container '%s' is larger than simulated device (%s > %s) Read Only Forced\n",
|
||||
sim_uname (uptr), container_dtype, (*container_dtype != '\0') ? " " : "", cptr,
|
||||
r = sim_messagef (SCPE_OK, "%s: %s%sdisk container '%s' is larger than simulated device (%s > %s) Read Only Forced\n",
|
||||
sim_uname (uptr), container_dtype, (*container_dtype != '\0') ? " " : "", cptr,
|
||||
capac1, sprint_capac (dptr, uptr));
|
||||
free (capac1);
|
||||
return r;
|
||||
|
@ -3317,9 +3317,9 @@ if (uptr->flags & UNIT_BUFABLE) { /* buffer in memory? */
|
|||
t_stat r = SCPE_OK;
|
||||
|
||||
if (uptr->flags & UNIT_MUSTBUF) { /* dyn alloc? */
|
||||
uptr->filebuf = calloc ((size_t)(ctx->container_size / ctx->xfer_element_size),
|
||||
uptr->filebuf = calloc ((size_t)(ctx->container_size / ctx->xfer_element_size),
|
||||
ctx->xfer_element_size); /* allocate */
|
||||
uptr->filebuf2 = calloc ((size_t)(ctx->container_size / ctx->xfer_element_size),
|
||||
uptr->filebuf2 = calloc ((size_t)(ctx->container_size / ctx->xfer_element_size),
|
||||
ctx->xfer_element_size); /* allocate copy */
|
||||
if ((uptr->filebuf == NULL) || /* either failed? */
|
||||
(uptr->filebuf2 == NULL)) {
|
||||
|
@ -3379,7 +3379,7 @@ if (NULL == find_dev_from_unit (uptr))
|
|||
if ((uptr->flags & UNIT_BUF) && (uptr->filebuf)) {
|
||||
uint32 cap = (uptr->hwmark + uptr->dptr->aincr - 1) / uptr->dptr->aincr;
|
||||
|
||||
if (((uptr->flags & UNIT_RO) == 0) &&
|
||||
if (((uptr->flags & UNIT_RO) == 0) &&
|
||||
(memcmp (uptr->filebuf, uptr->filebuf2, (size_t)ctx->container_size) != 0)) {
|
||||
sim_messagef (SCPE_OK, "%s: writing buffer to file: %s\n", sim_uname (uptr), uptr->filename);
|
||||
sim_disk_wrsect (uptr, 0, (uint8 *)uptr->filebuf, NULL, (cap + ctx->sector_size - 1) / ctx->sector_size);
|
||||
|
@ -3667,9 +3667,9 @@ return SCPE_OK;
|
|||
/* Factory bad block table creation routine
|
||||
|
||||
This routine writes a DEC standard 144 compliant bad block table on the
|
||||
last track of the specified unit as described in:
|
||||
last track of the specified unit as described in:
|
||||
EL-00144_B_DEC_STD_144_Disk_Standard_for_Recording_and_Handling_Bad_Sectors_Nov76.pdf
|
||||
The bad block table consists of 10 repetitions of the same table,
|
||||
The bad block table consists of 10 repetitions of the same table,
|
||||
formatted as follows:
|
||||
|
||||
words 0-1 pack id number
|
||||
|
@ -3948,9 +3948,9 @@ if (strchr (openmode, 'r'))
|
|||
DesiredAccess |= GENERIC_READ;
|
||||
if (strchr (openmode, 'w') || strchr (openmode, '+'))
|
||||
DesiredAccess |= GENERIC_WRITE;
|
||||
/* SCP Command Line parsing replaces \\ with \ presuming this is an
|
||||
escape sequence. This only affecdts RAW device names and UNC paths.
|
||||
We handle the RAW device name case here by prepending paths beginning
|
||||
/* SCP Command Line parsing replaces \\ with \ presuming this is an
|
||||
escape sequence. This only affects RAW device names and UNC paths.
|
||||
We handle the RAW device name case here by prepending paths beginning
|
||||
with \.\ with an extra \. */
|
||||
if ((!memcmp ("\\.\\", rawdevicename, 3)) ||
|
||||
(!memcmp ("/./", rawdevicename, 3))) {
|
||||
|
@ -3962,7 +3962,7 @@ else
|
|||
Handle = CreateFileA (tmpname, DesiredAccess, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS|FILE_FLAG_WRITE_THROUGH, NULL);
|
||||
free (tmpname);
|
||||
if (Handle != INVALID_HANDLE_VALUE) {
|
||||
if ((sim_os_disk_info_raw ((FILE *)Handle, NULL, NULL, &is_cdrom)) ||
|
||||
if ((sim_os_disk_info_raw ((FILE *)Handle, NULL, NULL, &is_cdrom)) ||
|
||||
((DesiredAccess & GENERIC_WRITE) && is_cdrom)) {
|
||||
CloseHandle (Handle);
|
||||
errno = EACCES;
|
||||
|
@ -5411,7 +5411,7 @@ static FILE *sim_vhd_disk_open (const char *szVHDPath, const char *DesiredAccess
|
|||
0);
|
||||
if (Status)
|
||||
goto Cleanup_Return;
|
||||
if ((0 != memcmp (hVHD->Dynamic.ParentUniqueID, ParentFooter.UniqueID, sizeof (ParentFooter.UniqueID))) ||
|
||||
if ((0 != memcmp (hVHD->Dynamic.ParentUniqueID, ParentFooter.UniqueID, sizeof (ParentFooter.UniqueID))) ||
|
||||
(ParentModifiedTimeStamp != hVHD->Dynamic.ParentTimeStamp)) {
|
||||
if (sim_switches & SWMASK ('O')) { /* OVERRIDE consistency checks? */
|
||||
if ((sim_switches & SWMASK ('U')) && /* FIX (UPDATE) consistency checks AND */
|
||||
|
@ -6161,7 +6161,7 @@ if (NtoHl (hVHD->Footer.DiskType) == VHD_DT_Fixed) {
|
|||
}
|
||||
/* We are now dealing with a Dynamically expanding or differencing disk */
|
||||
DynamicBlockSize = NtoHl (hVHD->Dynamic.BlockSize);
|
||||
if ((DynamicBlockSize == 0) ||
|
||||
if ((DynamicBlockSize == 0) ||
|
||||
((DynamicBlockSize & (DynamicBlockSize - 1)) != 0)) {
|
||||
errno = ERANGE;
|
||||
return SCPE_IOERR;
|
||||
|
@ -6292,7 +6292,7 @@ if (NtoHl(hVHD->Footer.DiskType) == VHD_DT_Fixed) {
|
|||
}
|
||||
/* We are now dealing with a Dynamically expanding or differencing disk */
|
||||
DynamicBlockSize = NtoHl (hVHD->Dynamic.BlockSize);
|
||||
if ((DynamicBlockSize == 0) ||
|
||||
if ((DynamicBlockSize == 0) ||
|
||||
((DynamicBlockSize & (DynamicBlockSize - 1)) != 0)) {
|
||||
errno = ERANGE;
|
||||
return SCPE_IOERR;
|
||||
|
@ -6381,9 +6381,9 @@ while (BytesToWrite && (r == SCPE_OK)) {
|
|||
goto Fatal_IO_Error;
|
||||
/* Since a large VHD can have a pretty large BAT, and we've only changed one longword bat entry
|
||||
in the current BAT, we write just the aligned sector which contains the updated BAT entry */
|
||||
BATUpdateBufferAddress = (uint8 *)hVHD->BAT - (size_t)NtoHll(hVHD->Dynamic.TableOffset) +
|
||||
BATUpdateBufferAddress = (uint8 *)hVHD->BAT - (size_t)NtoHll(hVHD->Dynamic.TableOffset) +
|
||||
(size_t)((((size_t)&hVHD->BAT[BlockNumber]) - (size_t)hVHD->BAT + (size_t)NtoHll(hVHD->Dynamic.TableOffset)) & ~(VHD_DATA_BLOCK_ALIGNMENT-1));
|
||||
/* If the starting of the BAT isn't on a VHD_DATA_BLOCK_ALIGNMENT boundary and we've just updated
|
||||
/* If the starting of the BAT isn't on a VHD_DATA_BLOCK_ALIGNMENT boundary and we've just updated
|
||||
a BAT entry early in the array, the buffer computed address might be before the start of the
|
||||
BAT table. If so, only write the BAT data needed */
|
||||
if (BATUpdateBufferAddress < (uint8 *)hVHD->BAT) {
|
||||
|
@ -6537,7 +6537,7 @@ for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */
|
|||
return TRUE; /* can't stat assume attached */
|
||||
}
|
||||
free (fullpath);
|
||||
if ((statb.st_dev != filestat.st_dev) ||
|
||||
if ((statb.st_dev != filestat.st_dev) ||
|
||||
(statb.st_ino != filestat.st_ino) ||
|
||||
(statb.st_mode != filestat.st_mode) ||
|
||||
(statb.st_nlink != filestat.st_nlink) ||
|
||||
|
@ -6556,7 +6556,7 @@ free (fullname);
|
|||
return FALSE; /* Not attached */
|
||||
}
|
||||
|
||||
static void sim_disk_info_entry (const char *directory,
|
||||
static void sim_disk_info_entry (const char *directory,
|
||||
const char *filename,
|
||||
t_offset FileSize,
|
||||
const struct stat *filestat,
|
||||
|
@ -6597,14 +6597,14 @@ if (info->flag) { /* zap type */
|
|||
if ((container_size != (t_offset)-1) && (container_size > (t_offset)sizeof (*f)) &&
|
||||
(sim_fseeko (container, container_size - sizeof (*f), SEEK_SET) == 0) &&
|
||||
(sizeof (*f) == sim_fread (f, 1, sizeof (*f), container))) {
|
||||
if ((memcmp (f->Signature, "simh", 4) == 0) &&
|
||||
if ((memcmp (f->Signature, "simh", 4) == 0) &&
|
||||
(f->Checksum == NtoHl (eth_crc32 (0, f, sizeof (*f) - sizeof (f->Checksum))))) {
|
||||
uint8 *sector_data;
|
||||
uint8 *zero_sector;
|
||||
size_t sector_size = NtoHl (f->SectorSize);
|
||||
t_offset highwater = (((t_offset)NtoHl (f->Highwater[0])) << 32) | ((t_offset)NtoHl (f->Highwater[1]));
|
||||
|
||||
if (sector_size > 16384) /* arbitray upper limit */
|
||||
if (sector_size > 16384) /* arbitrary upper limit */
|
||||
sector_size = 16384;
|
||||
/* determine whole sectors in original container size */
|
||||
/* By default we chop off the disk footer and trailing */
|
||||
|
@ -6686,7 +6686,7 @@ if (info->flag == 0) {
|
|||
" AccessFormat: %s\n"
|
||||
" CreationTime: %s",
|
||||
uptr->filename,
|
||||
f->CreatingSimulator, f->DriveType, NtoHl(f->SectorSize), NtoHl (f->SectorCount),
|
||||
f->CreatingSimulator, f->DriveType, NtoHl(f->SectorSize), NtoHl (f->SectorCount),
|
||||
NtoHl (f->TransferElementSize), fmts[f->AccessFormat].name, f->CreationTime);
|
||||
if (f->DeviceName[0] != '\0')
|
||||
sim_printf (" DeviceName: %s\n", (char *)f->DeviceName);
|
||||
|
@ -6824,7 +6824,7 @@ if (!(uptr->flags & UNIT_RO)) { /* Only test drives open Read/Write - Read Only
|
|||
|
||||
for (i = 0; i < uint32s_per_sector; i++)
|
||||
if (c->data[i + sector_to_check * uint32s_per_sector] != (lba + sector_to_check)) {
|
||||
sim_printf ("Sector %u(0x%X) has unexpected data at offset 0x%X: 0x%08X\n",
|
||||
sim_printf ("Sector %u(0x%X) has unexpected data at offset 0x%X: 0x%08X\n",
|
||||
lba + sector_to_check, lba + sector_to_check, i, c->data[i + sector_to_check * uint32s_per_sector]);
|
||||
unexpected_data = TRUE;
|
||||
break;
|
||||
|
|
24
sim_disk.h
24
sim_disk.h
|
@ -19,12 +19,12 @@
|
|||
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 names of Robert M Supnik and
|
||||
Except as contained in this notice, the names of Robert M Supnik and
|
||||
Mark Pizzolato shall not be used in advertising or otherwise to promote
|
||||
the sale, use or other dealings in this Software without prior written
|
||||
the sale, use or other dealings in this Software without prior written
|
||||
authorization from Robert M Supnik and Mark Pizzolato.
|
||||
|
||||
25-Jan-11 MP Initial Implemementation
|
||||
25-Jan-11 MP Initial Implementation
|
||||
*/
|
||||
|
||||
#ifndef SIM_DISK_H_
|
||||
|
@ -70,19 +70,19 @@ typedef void (*DISK_PCALLBACK)(UNIT *unit, t_stat status);
|
|||
/* Prototypes */
|
||||
|
||||
t_stat sim_disk_init (void);
|
||||
t_stat sim_disk_attach (UNIT *uptr,
|
||||
const char *cptr,
|
||||
t_stat sim_disk_attach (UNIT *uptr,
|
||||
const char *cptr,
|
||||
size_t memory_sector_size, /* memory footprint of sector data */
|
||||
size_t xfer_element_size,
|
||||
size_t xfer_element_size,
|
||||
t_bool dontchangecapac, /* if false just change uptr->capac as needed */
|
||||
uint32 debugbit, /* debug bit */
|
||||
const char *drivetype, /* drive type */
|
||||
uint32 pdp11_tracksize, /* BAD144 track */
|
||||
int completion_delay); /* Minimum Delay for asynch I/O completion */
|
||||
t_stat sim_disk_attach_ex (UNIT *uptr,
|
||||
const char *cptr,
|
||||
t_stat sim_disk_attach_ex (UNIT *uptr,
|
||||
const char *cptr,
|
||||
size_t memory_sector_size, /* memory footprint of sector data */
|
||||
size_t xfer_element_size,
|
||||
size_t xfer_element_size,
|
||||
t_bool dontchangecapac, /* if false just change uptr->capac as needed */
|
||||
uint32 dbit, /* debug bit */
|
||||
const char *dtype, /* drive type */
|
||||
|
@ -90,10 +90,10 @@ t_stat sim_disk_attach_ex (UNIT *uptr,
|
|||
int completion_delay, /* Minimum Delay for asynch I/O completion */
|
||||
const char **drivetypes); /* list of drive types (from smallest to largest) */
|
||||
/* to try and fit the container/file system into */
|
||||
t_stat sim_disk_attach_ex2 (UNIT *uptr,
|
||||
const char *cptr,
|
||||
t_stat sim_disk_attach_ex2 (UNIT *uptr,
|
||||
const char *cptr,
|
||||
size_t memory_sector_size, /* memory footprint of sector data */
|
||||
size_t xfer_element_size,
|
||||
size_t xfer_element_size,
|
||||
t_bool dontchangecapac, /* if false just change uptr->capac as needed */
|
||||
uint32 dbit, /* debug bit */
|
||||
const char *dtype, /* drive type */
|
||||
|
|
468
sim_ether.c
468
sim_ether.c
|
@ -66,27 +66,27 @@
|
|||
HP/UX ??
|
||||
Compaq Tru64 Unix ??
|
||||
VMS Alpha/Itanium VMS only, needs VMS libpcap
|
||||
|
||||
WinPcap is no longer developed or supported by was available from:
|
||||
|
||||
WinPcap is no longer developed or supported by was available from:
|
||||
http://winpcap.polito.it/
|
||||
Npcap is a complete replacement for systems running Windows7 and later
|
||||
and is available from:
|
||||
https://nmap.org/npcap
|
||||
libpcap for VMS is available from:
|
||||
libpcap for VMS is available from:
|
||||
http://simh.trailing-edge.com/sources/vms-pcap.zip
|
||||
libpcap for other Unix platforms is available at:
|
||||
NOTE: As of the release of this version of sim_ether.c ALL current
|
||||
*nix platforms ship with a sufficiently new version of
|
||||
libpcap for other Unix platforms is available at:
|
||||
NOTE: As of the release of this version of sim_ether.c ALL current
|
||||
*nix platforms ship with a sufficiently new version of
|
||||
libpcap, and ALL provide a libpcap-dev package for developing
|
||||
libpcap based applications. The OS vendor supplied version
|
||||
of libpcap AND the libpcap-dev components are preferred for
|
||||
proper operation of both simh AND other applications on the
|
||||
proper operation of both simh AND other applications on the
|
||||
host system which use libpcap.
|
||||
Current Version: http://www.tcpdump.org/daily/libpcap-current.tar.gz
|
||||
Released Version: http://www.tcpdump.org/release/
|
||||
|
||||
When absolutely necessary (see NOTE above about vendor supplied
|
||||
libpcap), we've gotten the tarball, unpacked, built and installed
|
||||
When absolutely necessary (see NOTE above about vendor supplied
|
||||
libpcap), we've gotten the tarball, unpacked, built and installed
|
||||
it with:
|
||||
gzip -dc libpcap-current.tar.gz | tar xvf -
|
||||
cd libpcap-directory-name
|
||||
|
@ -95,74 +95,74 @@
|
|||
make install
|
||||
Note: The "make install" step generally will have to be done as root.
|
||||
This will install libpcap in /usr/local/lib and /usr/local/include
|
||||
The current simh makefile will do the right thing to locate and
|
||||
The current simh makefile will do the right thing to locate and
|
||||
reference the OS provided libpcap or the one just installed.
|
||||
|
||||
|
||||
Note: Building for the platforms indicated above, with the indicated libpcap,
|
||||
should automatically leverage the appropriate mechanisms contained here.
|
||||
Things are structured so that it is likely to work for any other as yet
|
||||
untested platform. If it works for you, please let the author know so we
|
||||
can update the table above. If it doesn't work, then the following #define
|
||||
Note: Building for the platforms indicated above, with the indicated libpcap,
|
||||
should automatically leverage the appropriate mechanisms contained here.
|
||||
Things are structured so that it is likely to work for any other as yet
|
||||
untested platform. If it works for you, please let the author know so we
|
||||
can update the table above. If it doesn't work, then the following #define
|
||||
variables can influence the operation on an untested platform.
|
||||
|
||||
USE_BPF - Determines if this code leverages a libpcap/WinPcap
|
||||
provided bpf packet filtering facility. All tested
|
||||
environments have bpf facilities that work the way we
|
||||
need them to. However a new one might not. undefine
|
||||
USE_BPF - Determines if this code leverages a libpcap/WinPcap
|
||||
provided bpf packet filtering facility. All tested
|
||||
environments have bpf facilities that work the way we
|
||||
need them to. However a new one might not. undefine
|
||||
this variable to let this code do its own filtering.
|
||||
USE_SETNONBLOCK - Specifies whether the libpcap environment's non-blocking
|
||||
semantics are to be leveraged. This helps to manage the
|
||||
varying behaviours of the kernel packet facilities
|
||||
USE_SETNONBLOCK - Specifies whether the libpcap environment's non-blocking
|
||||
semantics are to be leveraged. This helps to manage the
|
||||
varying behaviours of the kernel packet facilities
|
||||
leveraged by libpcap.
|
||||
USE_READER_THREAD - Specifies that packet reading should be done in the
|
||||
context of a separate thread. The Posix threading
|
||||
USE_READER_THREAD - Specifies that packet reading should be done in the
|
||||
context of a separate thread. The Posix threading
|
||||
APIs are used. This option is less efficient than the
|
||||
default non-threaded approach, but it exists since some
|
||||
platforms don't want to work with nonblocking libpcap
|
||||
semantics. OpenBSD and NetBSD either don't have pthread
|
||||
APIs available, or they are too buggy to be useful.
|
||||
Using the threaded approach may require special compile
|
||||
and/or link time switches (i.e. -lpthread or -pthread,
|
||||
etc.) Consult the documentation for your platform as
|
||||
default non-threaded approach, but it exists since some
|
||||
platforms don't want to work with nonblocking libpcap
|
||||
semantics. OpenBSD and NetBSD either don't have pthread
|
||||
APIs available, or they are too buggy to be useful.
|
||||
Using the threaded approach may require special compile
|
||||
and/or link time switches (i.e. -lpthread or -pthread,
|
||||
etc.) Consult the documentation for your platform as
|
||||
needed. Although this may be 'less efficient' than the
|
||||
non-threaded approach, the efficiency is an overall system
|
||||
efficiency not necessarily a simulator efficiency. This
|
||||
means that work is removed from the thread executing
|
||||
efficiency not necessarily a simulator efficiency. This
|
||||
means that work is removed from the thread executing
|
||||
simulated instructions so the simulated system will most
|
||||
likely run faster (given that modern host CPUs are
|
||||
likely run faster (given that modern host CPUs are
|
||||
multi-core and have someplace to do this work in parallel).
|
||||
MUST_DO_SELECT - Specifies that, when USE_READER_THREAD is active,
|
||||
select() should be used to determine when available
|
||||
packets are ready for reading. Otherwise, we depend
|
||||
on the libpcap/kernel packet timeout specified on
|
||||
pcap_open_live. If USE_READER_THREAD is not set, then
|
||||
MUST_DO_SELECT - Specifies that, when USE_READER_THREAD is active,
|
||||
select() should be used to determine when available
|
||||
packets are ready for reading. Otherwise, we depend
|
||||
on the libpcap/kernel packet timeout specified on
|
||||
pcap_open_live. If USE_READER_THREAD is not set, then
|
||||
MUST_DO_SELECT is irrelevant
|
||||
HAVE_TAP_NETWORK - Specifies that support for tap networking should be
|
||||
HAVE_TAP_NETWORK - Specifies that support for tap networking should be
|
||||
included. This can be leveraged, along with OS bridging
|
||||
capabilities to share a single LAN interface. This
|
||||
capabilities to share a single LAN interface. This
|
||||
allows device names of the form tap:tap0 to be specified
|
||||
at open time. This functionality is only useful/needed
|
||||
on *nix platforms since native sharing of Windows NIC
|
||||
at open time. This functionality is only useful/needed
|
||||
on *nix platforms since native sharing of Windows NIC
|
||||
devices works with no external magic.
|
||||
HAVE_VDE_NETWORK - Specifies that support for vde networking should be
|
||||
HAVE_VDE_NETWORK - Specifies that support for vde networking should be
|
||||
included. This can be leveraged, along with OS bridging
|
||||
capabilities to share a single LAN interface. It also
|
||||
can allow a simulator to have useful networking
|
||||
functionality when running without root access. This
|
||||
allows device names of the form vde:/tmp/switch to be
|
||||
specified at open time. This functionality is only
|
||||
available on *nix platforms since the vde api isn't
|
||||
can allow a simulator to have useful networking
|
||||
functionality when running without root access. This
|
||||
allows device names of the form vde:/tmp/switch to be
|
||||
specified at open time. This functionality is only
|
||||
available on *nix platforms since the vde api isn't
|
||||
available on Windows.
|
||||
HAVE_SLIRP_NETWORK- Specifies that support for SLiRP networking should be
|
||||
included. This can be leveraged to provide User Mode
|
||||
HAVE_SLIRP_NETWORK- Specifies that support for SLiRP networking should be
|
||||
included. This can be leveraged to provide User Mode
|
||||
IP NAT connectivity for simulators.
|
||||
|
||||
NEED_PCAP_SENDPACKET
|
||||
- Specifies that you are using an older version of libpcap
|
||||
which doesn't provide a pcap_sendpacket API.
|
||||
|
||||
NOTE: Changing these defines is done in either sim_ether.h OR on the global
|
||||
NOTE: Changing these defines is done in either sim_ether.h OR on the global
|
||||
compiler command line which builds all of the modules included in a
|
||||
simulator.
|
||||
|
||||
|
@ -171,9 +171,9 @@
|
|||
Modification history:
|
||||
|
||||
30-Mar-12 MP Added host NIC address determination on supported VMS platforms
|
||||
01-Mar-12 MP Made host NIC address determination on *nix platforms more
|
||||
01-Mar-12 MP Made host NIC address determination on *nix platforms more
|
||||
robust.
|
||||
01-Mar-12 MP Added host NIC address determination work when building
|
||||
01-Mar-12 MP Added host NIC address determination work when building
|
||||
under Cygwin
|
||||
01-Mar-12 AGN Add conditionals for Cygwin dynamic loading of wpcap.dll
|
||||
01-Mar-12 AGN Specify the full /usr/lib for dlopen under Apple Mac OS X.
|
||||
|
@ -181,78 +181,78 @@
|
|||
30-Oct-11 MP Added support for vde (Virtual Distributed Ethernet) networking
|
||||
29-Oct-11 MP Added support for integrated Tap networking interfaces on OSX
|
||||
12-Aug-11 MP Cleaned up payload length determination
|
||||
Fixed race condition detecting reflections when threaded
|
||||
Fixed race condition detecting reflections when threaded
|
||||
reading and writing is enabled
|
||||
18-Apr-11 MP Fixed race condition with self loopback packets in
|
||||
18-Apr-11 MP Fixed race condition with self loopback packets in
|
||||
multithreaded environments
|
||||
09-Jan-11 MP Fixed missing crc data when USE_READER_THREAD is defined and
|
||||
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
|
||||
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).
|
||||
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 a Physical Address is being set.
|
||||
04-Dec-10 MP Changed eth_write to do nonblocking writes when
|
||||
04-Dec-10 MP Changed eth_write to do nonblocking writes when
|
||||
USE_READER_THREAD is defined.
|
||||
20-Aug-10 TVO Fix for Mac OSX 10.6
|
||||
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
|
||||
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
|
||||
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 fregment and/or segment outgoing
|
||||
network traffic. Additionally a simulated network device can
|
||||
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 fixup IP header checksums to accomodate
|
||||
21-May-10 MP Added functionality to fixup IP header checksums to accomodate
|
||||
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 hoat to
|
||||
the guest we're supporting. In general this will be a relatively
|
||||
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 hoat to the guest. In order to make the
|
||||
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
|
||||
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
|
||||
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
|
||||
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 they physical layer
|
||||
is responsible for interfacing to they physical layer
|
||||
devices, AND it belongs here to get CRC processing right.
|
||||
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
|
||||
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
|
||||
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
|
||||
- Fixed bug when the simulated device doesn't need crc
|
||||
in packet data which is read.
|
||||
- Added call to pcap_setmintocopy to minimize packet
|
||||
- Added call to pcap_setmintocopy to minimize packet
|
||||
delivery latencies.
|
||||
- Added ethq_destroy and used it to avoid a memory leak in
|
||||
eth_close.
|
||||
|
@ -262,8 +262,8 @@
|
|||
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.
|
||||
Fixedup #ifdef's relating to USE_SHARED so that setting
|
||||
USE_SHARED or USE_NETWORK will build a working network
|
||||
Fixedup #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
|
||||
|
@ -286,10 +286,10 @@
|
|||
25-Mar-04 MP Revised comments and minor #defines to deal with updated
|
||||
libpcap which now provides pcap_sendpacket on all platforms.
|
||||
04-Feb-04 MP Returned success/fail status from eth_write to support
|
||||
determining if the current libpcap connection can successfully
|
||||
determining if the current libpcap connection can successfully
|
||||
write packets.
|
||||
Added threaded approach to reading packets since
|
||||
this works better on some platforms (solaris intel) than the
|
||||
this works better on some platforms (solaris intel) than the
|
||||
inconsistently implemented non-blocking read approach.
|
||||
04-Feb-04 DTH Converted ETH_DEBUG to sim_debug
|
||||
13-Jan-04 MP tested and fixed on OpenBSD, NetBS and FreeBSD.
|
||||
|
@ -323,7 +323,7 @@
|
|||
work on Red Hat 6.2-sparc and Debian 3.0r1-sparc.
|
||||
03-Mar-03 MP Changed logging to be consistent on stdout and sim_log
|
||||
01-Feb-03 MP Changed type of local variables in eth_packet_trace to
|
||||
conform to the interface needs of eth_mac_fmt wich produces
|
||||
conform to the interface needs of eth_mac_fmt which produces
|
||||
char data instead of unsigned char data. Suggested by the
|
||||
DECC compiler.
|
||||
15-Jan-03 DTH Corrected PacketGetAdapterNames parameter2 datatype
|
||||
|
@ -364,7 +364,7 @@
|
|||
24-Sep-02 DTH Finished eth_devices, eth_getname
|
||||
18-Sep-02 DTH Callbacks implemented
|
||||
13-Sep-02 DTH Basic packet read/write written
|
||||
20-Aug-02 DTH Created Sim_Ether for O/S independant ethernet implementation
|
||||
20-Aug-02 DTH Created Sim_Ether for O/S independent ethernet implementation
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
|
@ -388,7 +388,7 @@ static void eth_get_nic_hw_addr(ETH_DEV* dev, const char *devname, int set_on);
|
|||
static const unsigned char framer_oui[3] = { 0xaa, 0x00, 0x03 };
|
||||
|
||||
/*============================================================================*/
|
||||
/* OS-independant ethernet routines */
|
||||
/* OS-independent ethernet routines */
|
||||
/*============================================================================*/
|
||||
|
||||
t_stat eth_mac_scan (ETH_MAC* mac, const char* strmac)
|
||||
|
@ -459,7 +459,7 @@ t_stat eth_mac_scan_ex (ETH_MAC* mac, const char* strmac, UNIT *uptr)
|
|||
return sim_messagef (SCPE_ARG, "Invalid MAC address byte value: %02X\n", a[i]);
|
||||
else {
|
||||
uint32 mask, shift;
|
||||
|
||||
|
||||
state.base_mac[i] = a[i];
|
||||
if (((i + 1) << 3) < state.bits)
|
||||
shift = 0;
|
||||
|
@ -945,7 +945,7 @@ t_stat eth_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const cha
|
|||
fprintf (st, "This simulator was not built with ethernet device support\n");
|
||||
return SCPE_OK;
|
||||
}
|
||||
t_stat eth_check_address_conflict (ETH_DEV* dev,
|
||||
t_stat eth_check_address_conflict (ETH_DEV* dev,
|
||||
ETH_MAC* const mac)
|
||||
{return SCPE_NOFNC;}
|
||||
t_stat eth_set_throttle (ETH_DEV* dev, uint32 time, uint32 burst, uint32 delay)
|
||||
|
@ -965,7 +965,7 @@ t_stat eth_filter_hash (ETH_DEV* dev, int addr_count, ETH_MAC* const addresses,
|
|||
ETH_BOOL all_multicast, ETH_BOOL promiscuous, ETH_MULTIHASH* const hash)
|
||||
{return SCPE_NOFNC;}
|
||||
t_stat eth_filter_hash_ex(ETH_DEV* dev, int addr_count, ETH_MAC* const addresses,
|
||||
ETH_BOOL all_multicast, ETH_BOOL promiscuous,
|
||||
ETH_BOOL all_multicast, ETH_BOOL promiscuous,
|
||||
ETH_BOOL match_broadcast, ETH_MULTIHASH* const hash)
|
||||
{return SCPE_NOFNC;}
|
||||
const char *eth_version (void)
|
||||
|
@ -1033,8 +1033,8 @@ typedef void * pcap_t; /* Pseudo Type to avoid compiler errors */
|
|||
#endif /* HAVE_PCAP_NETWORK */
|
||||
|
||||
/*
|
||||
The libpcap provided API pcap_findalldevs() on most platforms, will
|
||||
leverage the getifaddrs() API if it is available in preference to
|
||||
The libpcap provided API pcap_findalldevs() on most platforms, will
|
||||
leverage the getifaddrs() API if it is available in preference to
|
||||
alternate platform specific methods of determining the interface list.
|
||||
|
||||
A limitation of getifaddrs() is that it returns only interfaces which
|
||||
|
@ -1042,11 +1042,11 @@ typedef void * pcap_t; /* Pseudo Type to avoid compiler errors */
|
|||
interfaces that we are interested in since a host may have dedicated
|
||||
interfaces for a simulator, which is otherwise unused by the host.
|
||||
|
||||
One could hand craft the the build of libpcap to specifically use
|
||||
alternate methods to implement pcap_findalldevs(). However, this can
|
||||
One could hand craft the the build of libpcap to specifically use
|
||||
alternate methods to implement pcap_findalldevs(). However, this can
|
||||
get tricky, and would then result in a sort of deviant libpcap.
|
||||
|
||||
This routine exists to allow platform specific code to validate and/or
|
||||
This routine exists to allow platform specific code to validate and/or
|
||||
extend the set of available interfaces to include any that are not
|
||||
returned by pcap_findalldevs.
|
||||
|
||||
|
@ -1098,7 +1098,7 @@ for (i=0; i<used; i++) {
|
|||
continue;
|
||||
reglen = sizeof(regval);
|
||||
|
||||
/* look for user-defined adapter name, bail if not found */
|
||||
/* look for user-defined adapter name, bail if not found */
|
||||
/* same comment about Windows XP x64 (above) using RegQueryValueEx */
|
||||
if ((status = RegQueryValueExA (reghnd, "Name", NULL, ®type, regval, ®len)) != ERROR_SUCCESS) {
|
||||
RegCloseKey (reghnd);
|
||||
|
@ -1210,9 +1210,9 @@ return used;
|
|||
|
||||
#ifdef HAVE_TAP_NETWORK
|
||||
#if defined(__linux) || defined(__linux__)
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/if.h>
|
||||
#include <linux/if_tun.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/if.h>
|
||||
#include <linux/if_tun.h>
|
||||
#elif defined(HAVE_BSDTUNTAP)
|
||||
#include <sys/types.h>
|
||||
#include <net/if_types.h>
|
||||
|
@ -1577,9 +1577,9 @@ struct _PACKET_OID_DATA {
|
|||
uint32 Oid; ///< OID code. See the Microsoft DDK documentation or the file ntddndis.h
|
||||
///< for a complete list of valid codes.
|
||||
uint32 Length; ///< Length of the data field
|
||||
uint8 Data[1]; ///< variable-lenght field that contains the information passed to or received
|
||||
uint8 Data[1]; ///< variable-length field that contains the information passed to or received
|
||||
///< from the adapter.
|
||||
};
|
||||
};
|
||||
typedef struct _PACKET_OID_DATA PACKET_OID_DATA, *PPACKET_OID_DATA;
|
||||
typedef void **LPADAPTER;
|
||||
#define OID_802_3_CURRENT_ADDRESS 0x01010102 /* Extracted from ntddndis.h */
|
||||
|
@ -1611,7 +1611,7 @@ static int pcap_mac_if_win32(const char *AdapterName, unsigned char MACAddress[6
|
|||
p_PacketCloseAdapter = (void (*)(LPADAPTER lpAdapter))dlsym(hDll, "PacketCloseAdapter");
|
||||
p_PacketRequest = (int (*)(LPADAPTER AdapterObject,BOOLEAN Set,PPACKET_OID_DATA OidData))dlsym(hDll, "PacketRequest");
|
||||
#endif
|
||||
|
||||
|
||||
/* Open the selected adapter */
|
||||
|
||||
lpAdapter = p_PacketOpenAdapter(AdapterName);
|
||||
|
@ -1625,7 +1625,7 @@ static int pcap_mac_if_win32(const char *AdapterName, unsigned char MACAddress[6
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* Allocate a buffer to get the MAC adress */
|
||||
/* Allocate a buffer to get the MAC address */
|
||||
|
||||
OidData = (PACKET_OID_DATA *)malloc(6 + sizeof(PACKET_OID_DATA));
|
||||
if (OidData == NULL) {
|
||||
|
@ -1720,13 +1720,13 @@ static int pcap_mac_if_vms(const char *AdapterName, unsigned char MACAddress[6])
|
|||
Device.dsc$w_length = strlen(VMS_Device);
|
||||
if (!$VMS_STATUS_SUCCESS( sys$assign (&Device, &chan, 0, 0, 0) ))
|
||||
return -1;
|
||||
status = sys$qiow (0, chan, IO$_SETMODE|IO$M_CTRL|IO$M_STARTUP, &iosb, 0, 0,
|
||||
status = sys$qiow (0, chan, IO$_SETMODE|IO$M_CTRL|IO$M_STARTUP, &iosb, 0, 0,
|
||||
0, &setupdesc, 0, 0, 0, 0);
|
||||
if ((!$VMS_STATUS_SUCCESS(status)) || (!$VMS_STATUS_SUCCESS(iosb[0]))) {
|
||||
sys$dassgn(chan);
|
||||
return -1;
|
||||
}
|
||||
status = sys$qiow (0, chan, IO$_SENSEMODE|IO$M_CTRL, &iosb, 0, 0,
|
||||
status = sys$qiow (0, chan, IO$_SENSEMODE|IO$M_CTRL, &iosb, 0, 0,
|
||||
0, &chardesc, 0, 0, 0, 0);
|
||||
sys$dassgn(chan);
|
||||
if ((!$VMS_STATUS_SUCCESS(status)) || (!$VMS_STATUS_SUCCESS(iosb[0])))
|
||||
|
@ -1779,7 +1779,7 @@ static void eth_get_nic_hw_addr(ETH_DEV* dev, const char *devname, int set_on)
|
|||
char tool[CBUFSIZE];
|
||||
const char *turnon[] = {
|
||||
"ip link set dev %.*s up 2>/dev/null",
|
||||
"ifconfig %.*s up 2>/dev/null",
|
||||
"ifconfig %.*s up 2>/dev/null",
|
||||
NULL};
|
||||
const char *patterns[] = {
|
||||
"ip link show %.*s 2>/dev/null | grep [0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]",
|
||||
|
@ -1967,8 +1967,8 @@ switch (dev->eth_api) {
|
|||
|
||||
sim_debug(dev->dbit, dev->dptr, "Reader Thread Starting\n");
|
||||
|
||||
/* Boost Priority for this I/O thread vs the CPU instruction execution
|
||||
thread which, in general, won't be readily yielding the processor
|
||||
/* Boost Priority for this I/O thread vs the CPU instruction execution
|
||||
thread which, in general, won't be readily yielding the processor
|
||||
when this thread needs to run */
|
||||
sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL);
|
||||
|
||||
|
@ -1991,7 +1991,7 @@ while (dev->handle) {
|
|||
{
|
||||
fd_set setl;
|
||||
struct timeval timeout;
|
||||
|
||||
|
||||
FD_ZERO(&setl);
|
||||
FD_SET(select_fd, &setl);
|
||||
timeout.tv_sec = 0;
|
||||
|
@ -2001,7 +2001,7 @@ while (dev->handle) {
|
|||
}
|
||||
else
|
||||
sel_ret = 1;
|
||||
if (sel_ret < 0 && errno != EINTR)
|
||||
if (sel_ret < 0 && errno != EINTR)
|
||||
break;
|
||||
}
|
||||
if (sel_ret > 0) {
|
||||
|
@ -2128,8 +2128,8 @@ _eth_writer(void *arg)
|
|||
ETH_DEV* volatile dev = (ETH_DEV*)arg;
|
||||
ETH_WRITE_REQUEST *request = NULL;
|
||||
|
||||
/* Boost Priority for this I/O thread vs the CPU instruction execution
|
||||
thread which in general won't be readily yielding the processor when
|
||||
/* Boost Priority for this I/O thread vs the CPU instruction execution
|
||||
thread which in general won't be readily yielding the processor when
|
||||
this thread needs to run */
|
||||
sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL);
|
||||
|
||||
|
@ -2177,9 +2177,9 @@ return NULL;
|
|||
}
|
||||
#endif
|
||||
|
||||
/* eth_set_async
|
||||
/* eth_set_async
|
||||
*
|
||||
* Turn on reciever processing which can be either asynchronous or polled
|
||||
* Turn on receiver processing which can be either asynchronous or polled
|
||||
*/
|
||||
t_stat eth_set_async (ETH_DEV *dev, int latency)
|
||||
{
|
||||
|
@ -2203,9 +2203,9 @@ if (wakeup_needed) {
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* eth_clr_async
|
||||
/* eth_clr_async
|
||||
*
|
||||
* Turn off reciever processing
|
||||
* Turn off receiver processing
|
||||
*/
|
||||
t_stat eth_clr_async (ETH_DEV *dev)
|
||||
{
|
||||
|
@ -2345,7 +2345,7 @@ else { /* !tap: */
|
|||
#if defined(HAVE_VDE_NETWORK)
|
||||
char vdeswitch_s[CBUFSIZE]; /* VDE switch name */
|
||||
char vdeport_s[CBUFSIZE]; /* VDE switch port (optional), numeric */
|
||||
|
||||
|
||||
struct vde_open_args voa;
|
||||
const char *devname = savname + 4;
|
||||
|
||||
|
@ -2616,7 +2616,7 @@ if (1) {
|
|||
}
|
||||
#endif /* defined (USE_READER_THREAD */
|
||||
_eth_add_to_open_list (dev);
|
||||
/*
|
||||
/*
|
||||
* install a total filter on a newly opened interface and let the device
|
||||
* simulator install an appropriate filter that reflects the device's
|
||||
* configuration.
|
||||
|
@ -2761,7 +2761,7 @@ if (!rand_initialized)
|
|||
return (rand() & 0xFF);
|
||||
}
|
||||
|
||||
t_stat eth_check_address_conflict_ex (ETH_DEV* dev,
|
||||
t_stat eth_check_address_conflict_ex (ETH_DEV* dev,
|
||||
ETH_MAC* const mac,
|
||||
int *reflections,
|
||||
t_bool silent)
|
||||
|
@ -2779,68 +2779,68 @@ eth_mac_fmt(mac, mac_string);
|
|||
sim_debug(dev->dbit, dev->dptr, "Determining Address Conflict for MAC address: %s\n", mac_string);
|
||||
|
||||
/* 00:00:00:00:00:00 or any address with a multi-cast address is invalid */
|
||||
if ((((*mac)[0] == 0) && ((*mac)[1] == 0) && ((*mac)[2] == 0) &&
|
||||
if ((((*mac)[0] == 0) && ((*mac)[1] == 0) && ((*mac)[2] == 0) &&
|
||||
((*mac)[3] == 0) && ((*mac)[4] == 0) && ((*mac)[5] == 0)) ||
|
||||
((*mac)[0] & 1)) {
|
||||
return sim_messagef (SCPE_ARG, "%s: Invalid NIC MAC Address: %s\n", sim_dname(dev->dptr), mac_string);
|
||||
}
|
||||
|
||||
/* The process of checking address conflicts is used in two ways:
|
||||
1) to determine the behavior of the currently running packet
|
||||
delivery facility regarding whether it may receive copies
|
||||
of every packet sent (and how many).
|
||||
2) to verify if a MAC address which this facility is planning
|
||||
to use as the source address of packets is already in use
|
||||
by some other node on the local network
|
||||
Case #1, doesn't require (and explicitly doesn't want) any
|
||||
interaction or response from other systems on the LAN so
|
||||
therefore no considerations regarding switch packet forwarding
|
||||
are important. Meanwhile, Case #2 does require responses from
|
||||
other components on the LAN to provide useful functionality.
|
||||
The original designers of this mechanism did this when essentially
|
||||
all LANs were single collision domains (i.e. ALL nodes which might
|
||||
1) to determine the behavior of the currently running packet
|
||||
delivery facility regarding whether it may receive copies
|
||||
of every packet sent (and how many).
|
||||
2) to verify if a MAC address which this facility is planning
|
||||
to use as the source address of packets is already in use
|
||||
by some other node on the local network
|
||||
Case #1, doesn't require (and explicitly doesn't want) any
|
||||
interaction or response from other systems on the LAN so
|
||||
therefore no considerations regarding switch packet forwarding
|
||||
are important. Meanwhile, Case #2 does require responses from
|
||||
other components on the LAN to provide useful functionality.
|
||||
The original designers of this mechanism did this when essentially
|
||||
all LANs were single collision domains (i.e. ALL nodes which might
|
||||
be affected by an address conflict were physically present on a single
|
||||
Ethernet cable which might have been extended by a couple of repeaters).
|
||||
Since that time, essentially no networks are single collision domains.
|
||||
Thick and thinwire Ethernet cables don't exist and very few networks
|
||||
even have hubs. Today, essentially all LANs are deployed using one
|
||||
or more layers of network switches. In a switched LAN environment, the
|
||||
switches on the LAN "learn" which ports on the LAN source traffic from
|
||||
which MAC addresses and then forward traffic destined for particular
|
||||
Since that time, essentially no networks are single collision domains.
|
||||
Thick and thinwire Ethernet cables don't exist and very few networks
|
||||
even have hubs. Today, essentially all LANs are deployed using one
|
||||
or more layers of network switches. In a switched LAN environment, the
|
||||
switches on the LAN "learn" which ports on the LAN source traffic from
|
||||
which MAC addresses and then forward traffic destined for particular
|
||||
MAC address to the appropriate ports. If a particular MAC address is
|
||||
already in use somewhere on the LAN, then the switches "know" where
|
||||
it is. The host based test using the loopback protocol is poorly
|
||||
already in use somewhere on the LAN, then the switches "know" where
|
||||
it is. The host based test using the loopback protocol is poorly
|
||||
designed to detect this condition. This test is performed by the host
|
||||
first changing the device's Physical MAC address to the address which
|
||||
is to be tested, and then sending a loopback packet FROM AND TO this
|
||||
MAC address with a loopback reply to be sent by a system which may be
|
||||
currently using the MAC address. If no reply is received, then the
|
||||
currently using the MAC address. If no reply is received, then the
|
||||
MAC address is presumed to be unused. The sending of this packet will
|
||||
result in its delivery to the right system since the switch port/MAC
|
||||
address tables know where to deliver packets destined to this MAC
|
||||
address, however the response it generates won't be delivered to the
|
||||
system performing the test since the switches on the LAN won't know
|
||||
about the local port being the right target for packets with this MAC
|
||||
address. A better test design to detect these conflicts would be for
|
||||
address tables know where to deliver packets destined to this MAC
|
||||
address, however the response it generates won't be delivered to the
|
||||
system performing the test since the switches on the LAN won't know
|
||||
about the local port being the right target for packets with this MAC
|
||||
address. A better test design to detect these conflicts would be for
|
||||
the testing system to send a loopback packet FROM the current physical
|
||||
MAC address (BEFORE changing it) TO the MAC address being tested with
|
||||
the loopback response coming to the current physical MAC address of
|
||||
MAC address (BEFORE changing it) TO the MAC address being tested with
|
||||
the loopback response coming to the current physical MAC address of
|
||||
the device. If a response is received, then the address is in use and
|
||||
the attempt to change the device's MAC address should fail. Since we
|
||||
the attempt to change the device's MAC address should fail. Since we
|
||||
can't change the software running in these simulators to implement this
|
||||
better conflict detection approach, we can still "do the right thing"
|
||||
in the sim_ether layer. We're already handling the loopback test
|
||||
packets specially since we always had to avoid receiving the packets
|
||||
which were being sent, but needed to allow for the incoming loopback
|
||||
better conflict detection approach, we can still "do the right thing"
|
||||
in the sim_ether layer. We're already handling the loopback test
|
||||
packets specially since we always had to avoid receiving the packets
|
||||
which were being sent, but needed to allow for the incoming loopback
|
||||
packets to be properly dealt with. We can extend this current special
|
||||
handling to change outgoing "loopback to self" packets to have source
|
||||
handling to change outgoing "loopback to self" packets to have source
|
||||
AND loopback destination addresses in the packets to be the host NIC's
|
||||
physical address. The switch network will already know the correct
|
||||
MAC/port relationship for the host NIC's physical address, so loopback
|
||||
physical address. The switch network will already know the correct
|
||||
MAC/port relationship for the host NIC's physical address, so loopback
|
||||
response packets will be delivered as needed.
|
||||
|
||||
Code in _eth_write and _eth_callback provide the special handling to
|
||||
perform the described loopback packet adjustments, and code in
|
||||
Code in _eth_write and _eth_callback provide the special handling to
|
||||
perform the described loopback packet adjustments, and code in
|
||||
eth_filter_hash makes sure that the loopback response packets are received.
|
||||
|
||||
*/
|
||||
|
@ -2905,7 +2905,7 @@ if (reflections)
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
t_stat eth_check_address_conflict (ETH_DEV* dev,
|
||||
t_stat eth_check_address_conflict (ETH_DEV* dev,
|
||||
ETH_MAC* const mac)
|
||||
{
|
||||
char mac_string[32];
|
||||
|
@ -2983,13 +2983,13 @@ dev->error_needs_reset = (((dev->transmit_packet_errors + dev->receive_packet_er
|
|||
#endif
|
||||
/* Limit errors to 1 per second (per invoking thread (reader and writer)) */
|
||||
sim_os_sleep (1);
|
||||
/*
|
||||
/*
|
||||
When all of the threads which can reference this ETH_DEV object are
|
||||
simultaneously waiting in this routine, we have the potential to close
|
||||
and reopen the network connection.
|
||||
We do this after ETH_ERROR_REOPEN_THRESHOLD total errors have occurred.
|
||||
In practice could be as frequently as once every ETH_ERROR_REOPEN_THRESHOLD/2
|
||||
seconds, but normally would be about once every 1.5*ETH_ERROR_REOPEN_THRESHOLD
|
||||
We do this after ETH_ERROR_REOPEN_THRESHOLD total errors have occurred.
|
||||
In practice could be as frequently as once every ETH_ERROR_REOPEN_THRESHOLD/2
|
||||
seconds, but normally would be about once every 1.5*ETH_ERROR_REOPEN_THRESHOLD
|
||||
seconds (ONLY when the error condition exists).
|
||||
*/
|
||||
#ifdef USE_READER_THREAD
|
||||
|
@ -3128,7 +3128,7 @@ int write_queue_size = 1;
|
|||
/* make sure device exists */
|
||||
if ((!dev) || (dev->eth_api == ETH_API_NONE)) return SCPE_UNATT;
|
||||
|
||||
if (packet->len > sizeof (packet->msg)) /* packet ovesized? */
|
||||
if (packet->len > sizeof (packet->msg)) /* packet oversized? */
|
||||
return SCPE_IERR; /* that's no good! */
|
||||
|
||||
/* Get a buffer */
|
||||
|
@ -3199,26 +3199,26 @@ for (i=0; i<count; ++i) {
|
|||
int key = 0x3f & (eth_crc32(0, MultiCastList[i], 6) >> 26);
|
||||
|
||||
key ^= 0x3F;
|
||||
printf("MAC: %02X:%02X:%02X:%02X:%02X:%02X Key: %X, Byte: %X, Val: %X\n",
|
||||
MultiCastList[i][0], MultiCastList[i][1], MultiCastList[i][2], MultiCastList[i][3], MultiCastList[i][4], MultiCastList[i][5],
|
||||
printf("MAC: %02X:%02X:%02X:%02X:%02X:%02X Key: %X, Byte: %X, Val: %X\n",
|
||||
MultiCastList[i][0], MultiCastList[i][1], MultiCastList[i][2], MultiCastList[i][3], MultiCastList[i][4], MultiCastList[i][5],
|
||||
key, key>>3, (1 << (key&0x7)));
|
||||
lhash[key>>3] |= (1 << (key&0x7));
|
||||
}
|
||||
if (memcmp(hash, lhash, sizeof(lhash))) {
|
||||
printf("Inconsistent Computed Hash:\n");
|
||||
printf("Should be: %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
||||
hash[0], hash[1], hash[2], hash[3],
|
||||
printf("Should be: %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
||||
hash[0], hash[1], hash[2], hash[3],
|
||||
hash[4], hash[5], hash[6], hash[7]);
|
||||
printf("Was: %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
||||
lhash[0], lhash[1], lhash[2], lhash[3],
|
||||
printf("Was: %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
||||
lhash[0], lhash[1], lhash[2], lhash[3],
|
||||
lhash[4], lhash[5], lhash[6], lhash[7]);
|
||||
}
|
||||
else {
|
||||
printf("Should be: %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
||||
hash[0], hash[1], hash[2], hash[3],
|
||||
printf("Should be: %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
||||
hash[0], hash[1], hash[2], hash[3],
|
||||
hash[4], hash[5], hash[6], hash[7]);
|
||||
printf("Was: %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
||||
lhash[0], lhash[1], lhash[2], lhash[3],
|
||||
printf("Was: %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
||||
lhash[0], lhash[1], lhash[2], lhash[3],
|
||||
lhash[4], lhash[5], lhash[6], lhash[7]);
|
||||
}
|
||||
return 0;
|
||||
|
@ -3310,11 +3310,11 @@ struct TCPHeader {
|
|||
#define IPPROTO_ICMP 1 /* control message protocol */
|
||||
#endif
|
||||
|
||||
static uint16
|
||||
ip_checksum(uint16 *buffer, int size)
|
||||
static uint16
|
||||
ip_checksum(uint16 *buffer, int size)
|
||||
{
|
||||
unsigned long cksum = 0;
|
||||
|
||||
|
||||
/* Sum all the words together, adding the final byte if size is odd */
|
||||
while (size > 1) {
|
||||
cksum += *buffer++;
|
||||
|
@ -3332,16 +3332,16 @@ if (size) {
|
|||
/* Do a little shuffling */
|
||||
cksum = (cksum >> 16) + (cksum & 0xffff);
|
||||
cksum += (cksum >> 16);
|
||||
|
||||
|
||||
/* Return the bitwise complement of the resulting mishmash */
|
||||
return (uint16)(~cksum);
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* src_addr and dest_addr are presented in network byte order
|
||||
*/
|
||||
|
||||
static uint16
|
||||
static uint16
|
||||
pseudo_checksum(uint16 len, uint16 proto, void *nsrc_addr, void *ndest_addr, uint8 *buff)
|
||||
{
|
||||
uint32 sum;
|
||||
|
@ -3351,7 +3351,7 @@ uint16 *dest_addr = (uint16 *)ndest_addr;
|
|||
/* Sum the data first */
|
||||
sum = 0xffff&(~ip_checksum((uint16 *)buff, len));
|
||||
|
||||
/* add the pseudo header which contains the IP source and
|
||||
/* add the pseudo header which contains the IP source and
|
||||
destination addresses already in network byte order */
|
||||
sum += src_addr[0];
|
||||
sum += src_addr[1];
|
||||
|
@ -3363,7 +3363,7 @@ sum = sum + htons(proto) + htons(len);
|
|||
/* Do a little shuffling */
|
||||
sum = (sum >> 16) + (sum & 0xffff);
|
||||
sum += (sum >> 16);
|
||||
|
||||
|
||||
/* Return the bitwise complement of the resulting mishmash */
|
||||
return (uint16)(~sum);
|
||||
}
|
||||
|
@ -3434,7 +3434,7 @@ switch (IP->proto) {
|
|||
/* We don't do anything with the TCP checksum since we're going to resegment the TCP data below */
|
||||
break;
|
||||
default:
|
||||
++dev->jumbo_dropped; /* We onlt handle UDP, ICMP and TCP jumbo frames others are dropped */
|
||||
++dev->jumbo_dropped; /* We only handle UDP, ICMP and TCP jumbo frames others are dropped */
|
||||
return;
|
||||
}
|
||||
/* Reasonable Checksums are now in the jumbo packet, but we've got to actually */
|
||||
|
@ -3450,8 +3450,8 @@ switch (IP->proto) {
|
|||
case IPPROTO_UDP:
|
||||
case IPPROTO_ICMP:
|
||||
++dev->jumbo_fragmented;
|
||||
/* When we're performing LSO (Large Send Offload), we're given a
|
||||
'template' header which may not include a value being populated
|
||||
/* When we're performing LSO (Large Send Offload), we're given a
|
||||
'template' header which may not include a value being populated
|
||||
in the IP header length (which is only 16 bits).
|
||||
We process as payload everything which isn't known header data. */
|
||||
payload_len = (uint16)(len - (14 + IP_HLEN(IP)));
|
||||
|
@ -3477,8 +3477,8 @@ switch (IP->proto) {
|
|||
(i.e. we can use Wireshark to verify packet contents)
|
||||
we don't want to do this all the time for 2 reasons:
|
||||
1) sending through pcap involves kernel transitions and
|
||||
2) if the current system reflects sent packets, the
|
||||
recieving side will receive and process 2 copies of
|
||||
2) if the current system reflects sent packets, the
|
||||
receiving side will receive and process 2 copies of
|
||||
any packets sent this way. */
|
||||
ETH_PACK pkt;
|
||||
|
||||
|
@ -3504,8 +3504,8 @@ switch (IP->proto) {
|
|||
eth_packet_trace_ex (dev, ((u_char *)IP)-14, len, "Fragmenting Jumbo TCP segment", 1, dev->dbit);
|
||||
TCP = (struct TCPHeader *)(((char *)IP)+IP_HLEN(IP));
|
||||
orig_tcp_flags = ntohs(TCP->data_offset_and_flags);
|
||||
/* When we're performing LSO (Large Send Offload), we're given a
|
||||
'template' header which may not include a value being populated
|
||||
/* When we're performing LSO (Large Send Offload), we're given a
|
||||
'template' header which may not include a value being populated
|
||||
in the IP header length (which is only 16 bits).
|
||||
We process as payload everything which isn't known header data. */
|
||||
payload_len = (uint16)(len - (14 + IP_HLEN(IP) + TCP_DATA_OFFSET(TCP)));
|
||||
|
@ -3531,8 +3531,8 @@ switch (IP->proto) {
|
|||
(i.e. we can use Wireshark to verify packet contents)
|
||||
we don't want to do this all the time for 2 reasons:
|
||||
1) sending through pcap involves kernel transitions and
|
||||
2) if the current system reflects sent packets, the
|
||||
recieving side will receive and process 2 copies of
|
||||
2) if the current system reflects sent packets, the
|
||||
receiving side will receive and process 2 copies of
|
||||
any packets sent this way. */
|
||||
ETH_PACK pkt;
|
||||
|
||||
|
@ -3638,16 +3638,16 @@ function = data[offset] | (data[offset+1] << 8);
|
|||
if (function != 2) /*forward*/
|
||||
return 0;
|
||||
|
||||
/* The only packets we should be responding to are ones which
|
||||
we received due to them being directed to our physical MAC address,
|
||||
OR the Broadcast address OR to a Multicast address we're listening to
|
||||
(we may receive others if we're in promiscuous mode, but shouldn't
|
||||
/* The only packets we should be responding to are ones which
|
||||
we received due to them being directed to our physical MAC address,
|
||||
OR the Broadcast address OR to a Multicast address we're listening to
|
||||
(we may receive others if we're in promiscuous mode, but shouldn't
|
||||
respond to them) */
|
||||
if ((0 == (data[0]&1)) && /* Multicast or Broadcast */
|
||||
(0 != memcmp(dev->filter_address[0], data, sizeof(ETH_MAC))))
|
||||
return 0;
|
||||
|
||||
/* Attempts to forward to multicast or broadcast addresses are explicitly
|
||||
/* Attempts to forward to multicast or broadcast addresses are explicitly
|
||||
ignored by consuming the packet and doing nothing else */
|
||||
if (data[offset+2]&1)
|
||||
return 1;
|
||||
|
@ -3771,7 +3771,7 @@ if (bpf_used ? to_me : (to_me && !from_me)) {
|
|||
return;
|
||||
}
|
||||
if (_eth_process_loopback(dev, data, header->len))
|
||||
return;
|
||||
return;
|
||||
#if defined (USE_READER_THREAD)
|
||||
if (1) {
|
||||
int crc_len = 0;
|
||||
|
@ -3791,7 +3791,7 @@ if (bpf_used ? to_me : (to_me && !from_me)) {
|
|||
/* but were presumed to be traversing a NIC which was going to handle that task */
|
||||
/* This must be done before any needed CRC calculation */
|
||||
_eth_fix_ip_xsum_offload(dev, (const u_char*)data, len);
|
||||
|
||||
|
||||
if (dev->need_crc)
|
||||
crc_len = eth_get_packet_crc32_data(data, len, crc_data);
|
||||
|
||||
|
@ -3948,7 +3948,7 @@ if (status < 0) {
|
|||
status = 1;
|
||||
ethq_remove(&dev->read_queue);
|
||||
}
|
||||
pthread_mutex_unlock (&dev->lock);
|
||||
pthread_mutex_unlock (&dev->lock);
|
||||
if ((status) && (routine))
|
||||
routine(0);
|
||||
#endif
|
||||
|
@ -3957,7 +3957,7 @@ return status;
|
|||
}
|
||||
|
||||
t_stat eth_bpf_filter (ETH_DEV* dev, int addr_count, ETH_MAC* const filter_address,
|
||||
ETH_BOOL all_multicast, ETH_BOOL promiscuous,
|
||||
ETH_BOOL all_multicast, ETH_BOOL promiscuous,
|
||||
int reflections,
|
||||
ETH_MAC* physical_addr,
|
||||
ETH_MAC* host_nic_phy_hw_addr,
|
||||
|
@ -3986,9 +3986,9 @@ if (!promiscuous) {
|
|||
sprintf(&buf[strlen(buf)], ")");
|
||||
}
|
||||
|
||||
/* construct source filters - this prevents packets from being reflected back
|
||||
/* construct source filters - this prevents packets from being reflected back
|
||||
by systems where WinPcap and libpcap cause packet reflections. Note that
|
||||
some systems do not reflect packets at all. This *assumes* that the
|
||||
some systems do not reflect packets at all. This *assumes* that the
|
||||
simulated NIC will not send out packets with multicast source fields. */
|
||||
if ((addr_count > 0) && (reflections > 0)) {
|
||||
if (strlen(buf) > 0)
|
||||
|
@ -4013,22 +4013,22 @@ if ((addr_count > 0) && (reflections > 0)) {
|
|||
}
|
||||
if (strlen(buf) > 0)
|
||||
sprintf(&buf[strlen(buf)], ")");
|
||||
/* When changing the Physical Address on a LAN interface, VMS sends out a
|
||||
loopback packet with the source and destination addresses set to the same
|
||||
/* When changing the Physical Address on a LAN interface, VMS sends out a
|
||||
loopback packet with the source and destination addresses set to the same
|
||||
value as the Physical Address which is being setup. This packet is
|
||||
designed to find and help diagnose MAC address conflicts (which also
|
||||
include DECnet address conflicts). Normally, this packet would not be
|
||||
seen by the sender, only by the other machine that has the same Physical
|
||||
Address (or possibly DECnet address). If the ethernet subsystem is
|
||||
reflecting packets, the network startup will fail to start if it sees the
|
||||
reflected packet, since it thinks another system is using this Physical
|
||||
Address (or DECnet address). We have to let these packets through, so
|
||||
designed to find and help diagnose MAC address conflicts (which also
|
||||
include DECnet address conflicts). Normally, this packet would not be
|
||||
seen by the sender, only by the other machine that has the same Physical
|
||||
Address (or possibly DECnet address). If the ethernet subsystem is
|
||||
reflecting packets, the network startup will fail to start if it sees the
|
||||
reflected packet, since it thinks another system is using this Physical
|
||||
Address (or DECnet address). We have to let these packets through, so
|
||||
that if another machine has the same Physical Address (or DECnet address)
|
||||
that we can detect it. Both eth_write() and _eth_callback() help by
|
||||
that we can detect it. Both eth_write() and _eth_callback() help by
|
||||
checking the reflection count - eth_write() adds the reflection count to
|
||||
dev->loopback_self_sent, and _eth_callback() check the value - if the
|
||||
dev->loopback_self_sent count is zero, then the packet has come from
|
||||
another machine with the same address, and needs to be passed on to the
|
||||
dev->loopback_self_sent count is zero, then the packet has come from
|
||||
another machine with the same address, and needs to be passed on to the
|
||||
simulated machine. */
|
||||
/* check for physical address in filters */
|
||||
if ((!promiscuous) && (addr_count) && (reflections > 0)) {
|
||||
|
@ -4051,22 +4051,22 @@ return SCPE_OK;
|
|||
t_stat eth_filter(ETH_DEV* dev, int addr_count, ETH_MAC* const addresses,
|
||||
ETH_BOOL all_multicast, ETH_BOOL promiscuous)
|
||||
{
|
||||
return eth_filter_hash_ex(dev, addr_count, addresses,
|
||||
return eth_filter_hash_ex(dev, addr_count, addresses,
|
||||
all_multicast, promiscuous, FALSE,
|
||||
NULL);
|
||||
}
|
||||
|
||||
t_stat eth_filter_hash(ETH_DEV* dev, int addr_count, ETH_MAC* const addresses,
|
||||
ETH_BOOL all_multicast, ETH_BOOL promiscuous,
|
||||
ETH_BOOL all_multicast, ETH_BOOL promiscuous,
|
||||
ETH_MULTIHASH* const hash)
|
||||
{
|
||||
return eth_filter_hash_ex(dev, addr_count, addresses,
|
||||
return eth_filter_hash_ex(dev, addr_count, addresses,
|
||||
all_multicast, promiscuous, TRUE,
|
||||
hash);
|
||||
}
|
||||
|
||||
t_stat eth_filter_hash_ex(ETH_DEV* dev, int addr_count, ETH_MAC* const addresses,
|
||||
ETH_BOOL all_multicast, ETH_BOOL promiscuous,
|
||||
ETH_BOOL all_multicast, ETH_BOOL promiscuous,
|
||||
ETH_BOOL match_broadcast, ETH_MULTIHASH* const hash)
|
||||
{
|
||||
int i;
|
||||
|
@ -4084,7 +4084,7 @@ if (!dev) return SCPE_UNATT;
|
|||
if ((addr_count < 0) || ((addr_count + (match_broadcast ? 1 : 0)) > ETH_FILTER_MAX))
|
||||
return SCPE_ARG;
|
||||
else
|
||||
if (!addresses && (addr_count != 0))
|
||||
if (!addresses && (addr_count != 0))
|
||||
return SCPE_ARG;
|
||||
|
||||
/* test reflections. This is done early in this routine since eth_reflect */
|
||||
|
@ -4111,7 +4111,7 @@ dev->hash_filter = (hash != NULL);
|
|||
if (hash) {
|
||||
memcpy(dev->hash, hash, sizeof(*hash));
|
||||
sim_debug(dev->dbit, dev->dptr, "Multicast Hash: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n",
|
||||
dev->hash[0], dev->hash[1], dev->hash[2], dev->hash[3],
|
||||
dev->hash[0], dev->hash[1], dev->hash[2], dev->hash[3],
|
||||
dev->hash[4], dev->hash[5], dev->hash[6], dev->hash[7]);
|
||||
}
|
||||
|
||||
|
@ -4151,14 +4151,14 @@ for (i = 0; i < addr_count; i++) {
|
|||
#endif
|
||||
|
||||
/* setup BPF filters and other fields to minimize packet delivery */
|
||||
eth_bpf_filter (dev, dev->addr_count, dev->filter_address,
|
||||
dev->all_multicast, dev->promiscuous,
|
||||
dev->reflections, &dev->physical_addr,
|
||||
eth_bpf_filter (dev, dev->addr_count, dev->filter_address,
|
||||
dev->all_multicast, dev->promiscuous,
|
||||
dev->reflections, &dev->physical_addr,
|
||||
dev->have_host_nic_phy_addr ? &dev->host_nic_phy_hw_addr: NULL,
|
||||
(dev->hash_filter ? &dev->hash : NULL), buf);
|
||||
|
||||
/* get netmask, which is a required argument for compiling. The value,
|
||||
in our case isn't actually interesting since the filters we generate
|
||||
/* get netmask, which is a required argument for compiling. The value,
|
||||
in our case isn't actually interesting since the filters we generate
|
||||
aren't referencing IP fields, networks or values */
|
||||
|
||||
#ifdef USE_BPF
|
||||
|
@ -4188,7 +4188,7 @@ if (dev->eth_api == ETH_API_PCAP) {
|
|||
sim_printf ("Eth: Promiscuous\n");
|
||||
if (dev->hash_filter)
|
||||
sim_printf ("Eth: Multicast Hash: %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X\n",
|
||||
dev->hash[0], dev->hash[1], dev->hash[2], dev->hash[3],
|
||||
dev->hash[0], dev->hash[1], dev->hash[2], dev->hash[3],
|
||||
dev->hash[4], dev->hash[5], dev->hash[6], dev->hash[7]);
|
||||
if (dev->have_host_nic_phy_addr) {
|
||||
eth_mac_fmt(&dev->host_nic_phy_hw_addr, mac);
|
||||
|
@ -4433,9 +4433,9 @@ for (eth_num=0; eth_num<eth_device_count; eth_num++) {
|
|||
char errbuf[PCAP_ERRBUF_SIZE];
|
||||
|
||||
++bpf_count;
|
||||
r = eth_bpf_filter (&dev, addr_count, &filter_address[0],
|
||||
all_multicast, promiscuous, reflections,
|
||||
&filter_address[0],
|
||||
r = eth_bpf_filter (&dev, addr_count, &filter_address[0],
|
||||
all_multicast, promiscuous, reflections,
|
||||
&filter_address[0],
|
||||
host_phy_addr_list[host_phy_addr_listindex],
|
||||
hash_list[hash_listindex],
|
||||
buf);
|
||||
|
|
20
sim_ether.h
20
sim_ether.h
|
@ -31,12 +31,12 @@
|
|||
01-Mar-12 AGN Cygwin doesn't have non-blocking pcap I/O pcap (it uses WinPcap)
|
||||
17-Nov-11 MP Added dynamic loading of libpcap on *nix platforms
|
||||
30-Oct-11 MP Added support for vde (Virtual Distributed Ethernet) networking
|
||||
18-Apr-11 MP Fixed race condition with self loopback packets in
|
||||
18-Apr-11 MP Fixed race condition with self loopback packets in
|
||||
multithreaded environments
|
||||
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
|
||||
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
|
||||
|
@ -52,7 +52,7 @@
|
|||
14-Nov-03 DTH Added #ifdef DECNET_FIX for problematic duplicate detection code
|
||||
07-Jun-03 MP Added WIN32 support for DECNET duplicate address detection.
|
||||
05-Jun-03 DTH Added used to struct eth_packet
|
||||
01-Feb-03 MP Changed some uint8 strings to char* to reflect usage
|
||||
01-Feb-03 MP Changed some uint8 strings to char* to reflect usage
|
||||
22-Oct-02 DTH Added all_multicast and promiscuous support
|
||||
21-Oct-02 DTH Corrected copyright again
|
||||
16-Oct-02 DTH Fixed copyright
|
||||
|
@ -82,7 +82,7 @@ extern "C" {
|
|||
#define USE_SETNONBLOCK 1
|
||||
#endif
|
||||
|
||||
/* cygwin dowsn't have the right features to use the threaded network I/O */
|
||||
/* cygwin doesn't have the right features to use the threaded network I/O */
|
||||
#if defined(__CYGWIN__) || defined(__ZAURUS__) // psco added check for Zaurus platform
|
||||
#define DONT_USE_READER_THREAD
|
||||
#endif
|
||||
|
@ -135,9 +135,9 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
/*
|
||||
USE_BPF is defined to let this code leverage the libpcap/OS kernel provided
|
||||
BPF packet filtering. This generally will enhance performance. It may not
|
||||
be available in some environments and/or it may not work correctly, so
|
||||
USE_BPF is defined to let this code leverage the libpcap/OS kernel provided
|
||||
BPF packet filtering. This generally will enhance performance. It may not
|
||||
be available in some environments and/or it may not work correctly, so
|
||||
undefining this will still provide working code here.
|
||||
*/
|
||||
#if defined(HAVE_PCAP_NETWORK)
|
||||
|
@ -335,7 +335,7 @@ t_stat eth_open (ETH_DEV* dev, const char* name, /* open ethernet interfa
|
|||
DEVICE* dptr, uint32 dbit);
|
||||
t_stat eth_close (ETH_DEV* dev); /* close ethernet interface */
|
||||
t_stat eth_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
|
||||
t_stat eth_write (ETH_DEV* dev, ETH_PACK* packet, /* write sychronous packet; */
|
||||
t_stat eth_write (ETH_DEV* dev, ETH_PACK* packet, /* write synchronous packet; */
|
||||
ETH_PCALLBACK routine); /* callback when done */
|
||||
int eth_read (ETH_DEV* dev, ETH_PACK* packet, /* read single packet; */
|
||||
ETH_PCALLBACK routine); /* callback when done*/
|
||||
|
@ -354,7 +354,7 @@ t_stat eth_filter_hash_ex (ETH_DEV* dev, int addr_count,/* set filter on incomin
|
|||
ETH_BOOL promiscuous,
|
||||
ETH_BOOL match_broadcast,
|
||||
ETH_MULTIHASH* const hash); /* AUTODIN II based 8 byte imperfect hash */
|
||||
t_stat eth_check_address_conflict (ETH_DEV* dev,
|
||||
t_stat eth_check_address_conflict (ETH_DEV* dev,
|
||||
ETH_MAC* const address);
|
||||
const char *eth_version (void); /* Version of dynamically loaded library (pcap) */
|
||||
void eth_setcrc (ETH_DEV* dev, int need_crc); /* enable/disable CRC mode */
|
||||
|
@ -383,7 +383,7 @@ void ethq_remove (ETH_QUE* que); /* remove item from FIFO
|
|||
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, size_t len,
|
||||
const uint8 *data, int used, size_t len,
|
||||
size_t crc_len, const uint8 *crc_data, int32 status);
|
||||
t_stat ethq_destroy(ETH_QUE* que); /* release FIFO queue */
|
||||
const char *eth_capabilities(void);
|
||||
|
|
22
sim_fio.c
22
sim_fio.c
|
@ -136,7 +136,7 @@ unsigned char by, *sptr, *dptr;
|
|||
if (sim_end || (count == 0) || (size == sizeof (char)))
|
||||
return;
|
||||
for (j = 0, dptr = sptr = (unsigned char *) bptr; /* loop on items */
|
||||
j < count; j++) {
|
||||
j < count; j++) {
|
||||
for (k = (int32)(size - 1); k >= (((int32) size + 1) / 2); k--) {
|
||||
by = *sptr; /* swap end-for-end */
|
||||
*sptr++ = *(dptr + k);
|
||||
|
@ -359,7 +359,7 @@ if (NULL == _sim_expand_homedir (path, pathbuf, sizeof (pathbuf)))
|
|||
return rmdir (pathbuf);
|
||||
}
|
||||
|
||||
static void _sim_filelist_entry (const char *directory,
|
||||
static void _sim_filelist_entry (const char *directory,
|
||||
const char *filename,
|
||||
t_offset FileSize,
|
||||
const struct stat *filestat,
|
||||
|
@ -503,9 +503,9 @@ return (t_offset)(ftello64 (st));
|
|||
|
||||
/* Apple OS/X */
|
||||
|
||||
#if defined (__APPLE__) || defined (__FreeBSD__) || defined(__NetBSD__) || defined (__OpenBSD__) || defined (__CYGWIN__)
|
||||
#if defined (__APPLE__) || defined (__FreeBSD__) || defined(__NetBSD__) || defined (__OpenBSD__) || defined (__CYGWIN__)
|
||||
#define S_SIM_IO_FSEEK_EXT_ 1
|
||||
int sim_fseeko (FILE *st, t_offset xpos, int origin)
|
||||
int sim_fseeko (FILE *st, t_offset xpos, int origin)
|
||||
{
|
||||
return fseeko (st, (off_t)xpos, origin);
|
||||
}
|
||||
|
@ -576,7 +576,7 @@ static void _time_t_to_filetime (time_t ttime, FILETIME *filetime)
|
|||
{
|
||||
t_uint64 time64;
|
||||
|
||||
time64 = 134774; /* Days betwen Jan 1, 1601 and Jan 1, 1970 */
|
||||
time64 = 134774; /* Days between Jan 1, 1601 and Jan 1, 1970 */
|
||||
time64 *= 24; /* Hours */
|
||||
time64 *= 3600; /* Seconds */
|
||||
time64 += (t_uint64)ttime; /* include time_t seconds */
|
||||
|
@ -674,7 +674,7 @@ if (AlreadyExists) {
|
|||
else
|
||||
*((DWORD *)((*shmem)->shm_base)) = (DWORD)size; /* Save Size in first page */
|
||||
|
||||
*addr = ((char *)(*shmem)->shm_base + SysInfo.dwPageSize); /* Point to the second paget for data */
|
||||
*addr = ((char *)(*shmem)->shm_base + SysInfo.dwPageSize); /* Point to the second page for data */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -936,8 +936,8 @@ return FALSE;
|
|||
#endif /* defined (_WIN32) */
|
||||
|
||||
#if defined(__VAX)
|
||||
/*
|
||||
* We privide a 'basic' snprintf, which 'might' overrun a buffer, but
|
||||
/*
|
||||
* We provide a 'basic' snprintf, which 'might' overrun a buffer, but
|
||||
* the actual use cases don't on other platforms and none of the callers
|
||||
* care about the function return value.
|
||||
*/
|
||||
|
@ -977,7 +977,7 @@ return getcwd (buf, buf_size);
|
|||
* %~pnI% - expands filepath value to a path and name only
|
||||
* %~nxI% - expands filepath value to a file name and extension only
|
||||
*
|
||||
* In the above example above %I% can be replaced by other
|
||||
* In the above example above %I% can be replaced by other
|
||||
* environment variables or numeric parameters to a DO command
|
||||
* invocation.
|
||||
*/
|
||||
|
@ -1001,7 +1001,7 @@ filepath = namebuf;
|
|||
|
||||
/* Check for full or current directory relative path */
|
||||
if ((filepath[1] == ':') ||
|
||||
(filepath[0] == '/') ||
|
||||
(filepath[0] == '/') ||
|
||||
(filepath[0] == '\\')){
|
||||
tot_len = 1 + strlen (filepath);
|
||||
fullpath = (char *)malloc (tot_len);
|
||||
|
@ -1155,7 +1155,7 @@ if ((hFind = FindFirstFileA (cptr, &File)) != INVALID_HANDLE_VALUE) {
|
|||
c = strrchr (DirName, '\\');
|
||||
*c = '\0'; /* Truncate to just directory path */
|
||||
if (!pathsep || /* Separator wasn't mentioned? */
|
||||
(slash && (0 == strcmp (slash, "/*"))))
|
||||
(slash && (0 == strcmp (slash, "/*"))))
|
||||
pathsep = "\\"; /* Default to Windows backslash */
|
||||
if (*pathsep == '/') { /* If slash separator? */
|
||||
while ((c = strchr (DirName, '\\')))
|
||||
|
|
108
sim_frontpanel.c
108
sim_frontpanel.c
|
@ -28,15 +28,15 @@
|
|||
03-Apr-15 MP Added logic to pass simulator startup messages in
|
||||
panel error text if the connection to the simulator
|
||||
shuts down while it is starting.
|
||||
04-Apr-15 MP Added mount and dismount routines to connect and
|
||||
04-Apr-15 MP Added mount and dismount routines to connect and
|
||||
disconnect removable media
|
||||
|
||||
This module provides interface between a front panel application and a simh
|
||||
simulator. Facilities provide ways to gather information from and to
|
||||
simulator. Facilities provide ways to gather information from and to
|
||||
observe and control the state of a simulator.
|
||||
|
||||
The details of the 'wire protocol' are internal to the API interfaces
|
||||
provided here and described in sim_frontpanel.h. These details are subject
|
||||
The details of the 'wire protocol' are internal to the API interfaces
|
||||
provided here and described in sim_frontpanel.h. These details are subject
|
||||
to change from one sim_frontpanel version to the next, while all efforts
|
||||
will be made to retain any prior sim_frontpanel API interfaces.
|
||||
|
||||
|
@ -189,19 +189,19 @@ struct PANEL {
|
|||
*
|
||||
* Mutex: Role:
|
||||
* io_lock Serialize access to panel state variables
|
||||
* acquired and released in application threads:
|
||||
* acquired and released in application threads:
|
||||
* _panel_register_query_string,
|
||||
* _panel_establish_register_bits_collection,
|
||||
* _panel_sendf
|
||||
* acquired and released in internal threads:
|
||||
* acquired and released in internal threads:
|
||||
* _panel_callback
|
||||
* _panel_reader
|
||||
* io_send_lock Serializes writes to a panel's sockets so that complete
|
||||
* command/request data can be delivered before another
|
||||
* io_send_lock Serializes writes to a panel's sockets so that complete
|
||||
* command/request data can be delivered before another
|
||||
* thread attempts to write to the socket.
|
||||
* acquired and released in: _panel_send
|
||||
* io_command_lock To serialize frontpanel application command requests
|
||||
* acquired and released in: _panel_get_registers,
|
||||
* acquired and released in: _panel_get_registers,
|
||||
* _panel_sendf_completion
|
||||
*
|
||||
* Condition Var: Sync Mutex: Purpose & Duration:
|
||||
|
@ -291,8 +291,8 @@ while (p && p->Debug && (dbits & p->debug)) {
|
|||
|
||||
clock_gettime(CLOCK_REALTIME, &time_now);
|
||||
sprintf (timestamp, "%lld.%03d ", (long long)(time_now.tv_sec), (int)(time_now.tv_nsec/1000000));
|
||||
sprintf (threadname, "%s:%s ", p->parent ? p->device_name : "CPU", (pthread_getspecific (panel_thread_id)) ? (char *)pthread_getspecific (panel_thread_id) : "");
|
||||
|
||||
sprintf (threadname, "%s:%s ", p->parent ? p->device_name : "CPU", (pthread_getspecific (panel_thread_id)) ? (char *)pthread_getspecific (panel_thread_id) : "");
|
||||
|
||||
obuf[obufsize - 1] = '\0';
|
||||
len = vsnprintf (obuf, obufsize - 1, fmt, arglist);
|
||||
if (len < 0)
|
||||
|
@ -620,7 +620,7 @@ for (i=0; i<panel->reg_count; i++) {
|
|||
}
|
||||
}
|
||||
pthread_mutex_unlock (&panel->io_lock);
|
||||
if (_panel_sendf (panel, &cmd_stat, &response, "%s%u%s%u%s%u%s%s\r", register_collect_prefix, panel->sample_depth,
|
||||
if (_panel_sendf (panel, &cmd_stat, &response, "%s%u%s%u%s%u%s%s\r", register_collect_prefix, panel->sample_depth,
|
||||
register_collect_mid1, panel->sample_frequency,
|
||||
register_collect_mid2, panel->sample_dither_pct,
|
||||
register_collect_mid3, buf)) {
|
||||
|
@ -669,7 +669,7 @@ int i;
|
|||
for (i=0; i<panel_count; i++) {
|
||||
if (panels[i] == p) {
|
||||
int j;
|
||||
for (j=i+1; j<panel_count; j++)
|
||||
for (j=i+1; j<panel_count; j++)
|
||||
panels[j-1] = panels[j];
|
||||
--panel_count;
|
||||
if (panel_count == 0) {
|
||||
|
@ -869,7 +869,7 @@ if (!simulator_panel) {
|
|||
close (0); close (1); close (2); /* make sure not to pass the open standard handles */
|
||||
if (dup (dup (open ("/dev/null", O_RDWR)))) {}; /* open standard handles to /dev/null */
|
||||
if (execlp (sim_path, sim_path, p->temp_config, NULL, NULL)) {
|
||||
perror ("execl");
|
||||
perror ("execlp");
|
||||
exit(errno);
|
||||
}
|
||||
}
|
||||
|
@ -1160,7 +1160,7 @@ if ((bit_count != 0) && (panel->sample_depth == 0)) {
|
|||
sim_panel_set_error (NULL, "sim_panel_set_sampling_parameters() must be called first");
|
||||
return -1;
|
||||
}
|
||||
regs = (REG *)_panel_malloc ((1 + panel->reg_count)*sizeof(*regs));
|
||||
regs = (REG *)_panel_malloc ((1 + panel->reg_count)*sizeof(*regs));
|
||||
if (regs == NULL)
|
||||
return sim_panel_set_error (panel, "_panel_add_register(): Out of Memory\n");
|
||||
pthread_mutex_lock (&panel->io_lock);
|
||||
|
@ -1216,8 +1216,8 @@ for (i=0; i<panel->reg_count; i++) {
|
|||
}
|
||||
sprintf (t1, "%s %s", regs[i].device_name ? regs[i].device_name : "", regs[i].name);
|
||||
sprintf (t2, "%s %s", reg->device_name ? reg->device_name : "", reg->name);
|
||||
if ((!strcmp (t1, t2)) &&
|
||||
(reg->indirect == regs[i].indirect) &&
|
||||
if ((!strcmp (t1, t2)) &&
|
||||
(reg->indirect == regs[i].indirect) &&
|
||||
((reg->bits == NULL) == (regs[i].bits == NULL))) {
|
||||
pthread_mutex_unlock (&panel->io_lock);
|
||||
sim_panel_set_error (NULL, "Duplicate Register Declaration");
|
||||
|
@ -1379,9 +1379,9 @@ return _panel_get_registers (panel, (panel->State == Halt), simulation_time);
|
|||
}
|
||||
|
||||
int
|
||||
sim_panel_set_display_callback_interval (PANEL *panel,
|
||||
PANEL_DISPLAY_PCALLBACK callback,
|
||||
void *context,
|
||||
sim_panel_set_display_callback_interval (PANEL *panel,
|
||||
PANEL_DISPLAY_PCALLBACK callback,
|
||||
void *context,
|
||||
int usecs_between_callbacks)
|
||||
{
|
||||
if (!panel) {
|
||||
|
@ -1707,7 +1707,7 @@ return 0;
|
|||
*/
|
||||
|
||||
int
|
||||
sim_panel_gen_examine (PANEL *panel,
|
||||
sim_panel_gen_examine (PANEL *panel,
|
||||
const char *name_or_addr,
|
||||
size_t size,
|
||||
void *value)
|
||||
|
@ -1755,7 +1755,7 @@ return 0;
|
|||
*/
|
||||
|
||||
int
|
||||
sim_panel_get_history (PANEL *panel,
|
||||
sim_panel_get_history (PANEL *panel,
|
||||
int count,
|
||||
size_t size,
|
||||
char *buffer)
|
||||
|
@ -1781,7 +1781,7 @@ return 0;
|
|||
}
|
||||
|
||||
int
|
||||
sim_panel_device_debug_mode (PANEL *panel,
|
||||
sim_panel_device_debug_mode (PANEL *panel,
|
||||
const char *device,
|
||||
int set_unset,
|
||||
const char *mode_bits)
|
||||
|
@ -1796,17 +1796,17 @@ if (!panel || (panel->State == Error)) {
|
|||
if ((device != NULL) &&
|
||||
((_panel_sendf (panel, &cmd_stat, &response, "SHOW %s", device) ||
|
||||
(cmd_stat)))) {
|
||||
sim_panel_set_error (NULL, "Can't %s Debug Mode: '%s' on Device '%s': %s",
|
||||
sim_panel_set_error (NULL, "Can't %s Debug Mode: '%s' on Device '%s': %s",
|
||||
set_unset ? "Enable" : "Disable", mode_bits ? mode_bits : "", device, response);
|
||||
free (response);
|
||||
return -1;
|
||||
}
|
||||
free (response);
|
||||
response = NULL;
|
||||
if (_panel_sendf (panel, &cmd_stat, &response, "%sDEBUG %s %s",
|
||||
if (_panel_sendf (panel, &cmd_stat, &response, "%sDEBUG %s %s",
|
||||
set_unset ? "" : "NO", device ? device : "", mode_bits ? mode_bits : "") ||
|
||||
(cmd_stat)) {
|
||||
sim_panel_set_error (NULL, "Can't %s Debug Mode: '%s' on Device '%s': %s",
|
||||
sim_panel_set_error (NULL, "Can't %s Debug Mode: '%s' on Device '%s': %s",
|
||||
set_unset ? "Enable" : "Disable", mode_bits ? mode_bits : "", device, response);
|
||||
free (response);
|
||||
return -1;
|
||||
|
@ -1822,12 +1822,12 @@ return 0;
|
|||
name_or_addr the name the simulator knows this register by
|
||||
size the size (in local storage) of the buffer which
|
||||
contains the data to be deposited into the simulator
|
||||
value a pointer to the buffer which contains the data to
|
||||
value a pointer to the buffer which contains the data to
|
||||
be deposited into the simulator
|
||||
*/
|
||||
|
||||
int
|
||||
sim_panel_gen_deposit (PANEL *panel,
|
||||
sim_panel_gen_deposit (PANEL *panel,
|
||||
const char *name_or_addr,
|
||||
size_t size,
|
||||
const void *value)
|
||||
|
@ -1856,7 +1856,7 @@ return 0;
|
|||
|
||||
sim_panel_mem_examine
|
||||
|
||||
addr_size the size (in local storage) of the buffer which
|
||||
addr_size the size (in local storage) of the buffer which
|
||||
contains the memory address of the data to be examined
|
||||
in the simulator
|
||||
addr a pointer to the buffer containing the memory address
|
||||
|
@ -1868,7 +1868,7 @@ return 0;
|
|||
*/
|
||||
|
||||
int
|
||||
sim_panel_mem_examine (PANEL *panel,
|
||||
sim_panel_mem_examine (PANEL *panel,
|
||||
size_t addr_size,
|
||||
const void *addr,
|
||||
size_t value_size,
|
||||
|
@ -1913,7 +1913,7 @@ return 0;
|
|||
|
||||
sim_panel_mem_deposit
|
||||
|
||||
addr_size the size (in local storage) of the buffer which
|
||||
addr_size the size (in local storage) of the buffer which
|
||||
contains the memory address of the data to be deposited
|
||||
into the simulator
|
||||
addr a pointer to the buffer containing the memory address
|
||||
|
@ -1925,7 +1925,7 @@ return 0;
|
|||
*/
|
||||
|
||||
int
|
||||
sim_panel_mem_deposit (PANEL *panel,
|
||||
sim_panel_mem_deposit (PANEL *panel,
|
||||
size_t addr_size,
|
||||
const void *addr,
|
||||
size_t value_size,
|
||||
|
@ -1959,17 +1959,17 @@ return 0;
|
|||
|
||||
sim_panel_mem_deposit_instruction
|
||||
|
||||
addr_size the size (in local storage) of the buffer which
|
||||
addr_size the size (in local storage) of the buffer which
|
||||
contains the memory address of the data to be deposited
|
||||
into the simulator
|
||||
addr a pointer to the buffer containing the memory address
|
||||
of the data to be deposited into the simulator
|
||||
instruction a pointer to the buffer that contains the mnemonic
|
||||
instruction a pointer to the buffer that contains the mnemonic
|
||||
instruction to be deposited at the indicated address
|
||||
*/
|
||||
|
||||
int
|
||||
sim_panel_mem_deposit_instruction (PANEL *panel,
|
||||
sim_panel_mem_deposit_instruction (PANEL *panel,
|
||||
size_t addr_size,
|
||||
const void *addr,
|
||||
const char *instruction)
|
||||
|
@ -1999,8 +1999,8 @@ return 0;
|
|||
|
||||
name the name of a simulator register or a memory address
|
||||
which is to receive a new value
|
||||
value the new value in character string form. The string
|
||||
must be in the native/natural radix that the simulator
|
||||
value the new value in character string form. The string
|
||||
must be in the native/natural radix that the simulator
|
||||
uses when referencing that register
|
||||
|
||||
*/
|
||||
|
@ -2118,8 +2118,8 @@ int buf_data = 0;
|
|||
int processing_register_output = 0;
|
||||
int io_wait_done = 0;
|
||||
|
||||
/*
|
||||
Boost Priority for this response processing thread to quickly digest
|
||||
/*
|
||||
Boost Priority for this response processing thread to quickly digest
|
||||
arriving data.
|
||||
*/
|
||||
pthread_getschedparam (pthread_self(), &sched_policy, &sched_priority);
|
||||
|
@ -2201,13 +2201,13 @@ while ((p->sock != INVALID_SOCKET) &&
|
|||
++s;
|
||||
continue; /* process next line */
|
||||
}
|
||||
if ((*s == '}') &&
|
||||
if ((*s == '}') &&
|
||||
(3 == sscanf (s, "}%s %s %s", smp_dev, smp_reg, smp_ind))) { /* Register bit Sample Data? */
|
||||
r = NULL;
|
||||
for (i=0; i<p->reg_count; i++) {
|
||||
if (p->regs[i].bits == NULL)
|
||||
continue;
|
||||
if ((!strcmp (smp_reg, p->regs[i].name)) &&
|
||||
if ((!strcmp (smp_reg, p->regs[i].name)) &&
|
||||
((!p->device_name) || (!strcmp (smp_dev, p->device_name)))) {
|
||||
r = &p->regs[i];
|
||||
break;
|
||||
|
@ -2283,7 +2283,7 @@ while ((p->sock != INVALID_SOCKET) &&
|
|||
|
||||
if (end)
|
||||
end_index = (size_t)atoi (end + 1);
|
||||
if (strcmp (e, " same as above"))
|
||||
if (strcmp (e, " same as above"))
|
||||
p->array_element_data = strtoull (e, NULL, 16);
|
||||
while (array_index <= end_index) {
|
||||
if (little_endian)
|
||||
|
@ -2319,14 +2319,14 @@ while ((p->sock != INVALID_SOCKET) &&
|
|||
p->io_response[p->io_response_data] = '\0';
|
||||
goto Start_Next_Line;
|
||||
}
|
||||
if ((strlen (s) > strlen (sim_prompt)) &&
|
||||
if ((strlen (s) > strlen (sim_prompt)) &&
|
||||
((!strcmp (s + strlen (sim_prompt), register_repeat_start)) ||
|
||||
(!strcmp (s + strlen (sim_prompt), register_get_start)))) {
|
||||
_panel_debug (p, DBG_RCV, "*Repeat/Register Block Starting", NULL, 0);
|
||||
processing_register_output = 1;
|
||||
goto Start_Next_Line;
|
||||
}
|
||||
if ((strlen (s) > strlen (sim_prompt)) &&
|
||||
if ((strlen (s) > strlen (sim_prompt)) &&
|
||||
(!strcmp (s + strlen (sim_prompt), register_get_end))) {
|
||||
_panel_debug (p, DBG_RCV, "*Register Block Complete", NULL, 0);
|
||||
p->io_waiting = 0;
|
||||
|
@ -2359,8 +2359,8 @@ while ((p->sock != INVALID_SOCKET) &&
|
|||
p->io_response_data += strlen(s);
|
||||
strcpy (p->io_response + p->io_response_data, "\r\n");
|
||||
p->io_response_data += 2;
|
||||
if ((!p->parent) &&
|
||||
(p->completion_string) &&
|
||||
if ((!p->parent) &&
|
||||
(p->completion_string) &&
|
||||
(!memcmp (s, p->completion_string, strlen (p->completion_string)))) {
|
||||
_panel_debug (p, DBG_RCV, "Match with potentially coalesced additional data: '%s'", NULL, 0, p->completion_string);
|
||||
if (eol < &buf[buf_data])
|
||||
|
@ -2376,8 +2376,8 @@ Start_Next_Line:
|
|||
buf_data = strlen (buf);
|
||||
if (buf_data)
|
||||
_panel_debug (p, DBG_RSP, "Remnant Buffer Contents: '%s'", NULL, 0, buf);
|
||||
if ((!p->parent) &&
|
||||
(p->completion_string) &&
|
||||
if ((!p->parent) &&
|
||||
(p->completion_string) &&
|
||||
(!memcmp (buf, p->completion_string, strlen (p->completion_string)))) {
|
||||
_panel_debug (p, DBG_RCV, "*Received Command Complete - Match: '%s'", NULL, 0, p->completion_string);
|
||||
io_wait_done = 1;
|
||||
|
@ -2448,8 +2448,8 @@ size_t buf_data = 0;
|
|||
unsigned int callback_count = 0;
|
||||
int cmd_stat;
|
||||
|
||||
/*
|
||||
Boost Priority for timer thread so it doesn't compete
|
||||
/*
|
||||
Boost Priority for timer thread so it doesn't compete
|
||||
with compute bound activities.
|
||||
*/
|
||||
pthread_getschedparam (pthread_self(), &sched_policy, &sched_priority);
|
||||
|
@ -2464,7 +2464,7 @@ pthread_mutex_unlock (&p->io_lock);
|
|||
pthread_cond_signal (&p->startup_done); /* Signal we're ready to go */
|
||||
msleep (100);
|
||||
pthread_mutex_lock (&p->io_lock);
|
||||
while ((p->sock != INVALID_SOCKET) &&
|
||||
while ((p->sock != INVALID_SOCKET) &&
|
||||
(p->usecs_between_callbacks) &&
|
||||
(p->State != Error)) {
|
||||
int interval = p->usecs_between_callbacks;
|
||||
|
@ -2501,9 +2501,9 @@ while ((p->sock != INVALID_SOCKET) &&
|
|||
buf_data -= (c - buf) + strlen (register_get_start);
|
||||
c += strlen (register_get_start);
|
||||
}
|
||||
sprintf (repeat, "%s%d%s%s%*.*s", register_repeat_prefix,
|
||||
p->usecs_between_callbacks,
|
||||
register_repeat_units,
|
||||
sprintf (repeat, "%s%d%s%s%*.*s", register_repeat_prefix,
|
||||
p->usecs_between_callbacks,
|
||||
register_repeat_units,
|
||||
register_repeat_start,
|
||||
(int)buf_data, (int)buf_data, c);
|
||||
pthread_mutex_unlock (&p->io_lock);
|
||||
|
|
172
sim_frontpanel.h
172
sim_frontpanel.h
|
@ -28,18 +28,18 @@
|
|||
03-Apr-15 MP Added logic to pass simulator startup messages in
|
||||
panel error text if the connection to the simulator
|
||||
shuts down while it is starting.
|
||||
04-Apr-15 MP Added mount and dismount routines to connect and
|
||||
04-Apr-15 MP Added mount and dismount routines to connect and
|
||||
disconnect removable media
|
||||
|
||||
This module defines interface between a front panel application and a simh
|
||||
simulator. Facilities provide ways to gather information from and to
|
||||
simulator. Facilities provide ways to gather information from and to
|
||||
observe and control the state of a simulator.
|
||||
|
||||
Any application which wants to use this API needs to:
|
||||
1) include this file in the application code
|
||||
2) compile sim_frontpanel.c and sim_sock.c from the top level directory
|
||||
2) compile sim_frontpanel.c and sim_sock.c from the top level directory
|
||||
of the simh source.
|
||||
3) link the sim_frontpanel and sim_sock object modules and libpthreads
|
||||
3) link the sim_frontpanel and sim_sock object modules and libpthreads
|
||||
into the application.
|
||||
4) Use a simh simulator built from the same version of simh that the
|
||||
sim_frontpanel and sim_sock modules came from.
|
||||
|
@ -60,21 +60,21 @@ extern "C" {
|
|||
|
||||
/**
|
||||
|
||||
sim_panel_start_simulator A starts a simulator with a particular
|
||||
sim_panel_start_simulator A starts a simulator with a particular
|
||||
configuration
|
||||
|
||||
sim_path the path to the simulator binary
|
||||
sim_config the configuration to run the simulator with
|
||||
device_panel_count the number of sub panels for connected devices
|
||||
|
||||
Note 1: - The path specified must be either a fully specified path or
|
||||
Note 1: - The path specified must be either a fully specified path or
|
||||
it could be merely the simulator name if the simulator binary
|
||||
is located in the current PATH.
|
||||
- The simulator binary must be built from the same version
|
||||
simh source code that the frontpanel API was acquired fron
|
||||
(the API and the simh framework must speak the same language)
|
||||
- The simulator binary must be built from the same version
|
||||
simh source code that the frontpanel API was acquired from
|
||||
(the API and the simh framework must speak the same language)
|
||||
|
||||
Note 2: - Configuration file specified should contain device setup
|
||||
Note 2: - Configuration file specified should contain device setup
|
||||
statements (enable, disable, CPU types and attach commands).
|
||||
It should not start a simulator running.
|
||||
*/
|
||||
|
@ -94,7 +94,7 @@ sim_panel_start_simulator_debug (const char *sim_path,
|
|||
|
||||
/**
|
||||
|
||||
sim_panel_add_device_panel - creates a sub panel associated
|
||||
sim_panel_add_device_panel - creates a sub panel associated
|
||||
with a specific simulator panel
|
||||
|
||||
simulator_panel the simulator panel to connect to
|
||||
|
@ -109,7 +109,7 @@ sim_panel_add_device_panel (PANEL *simulator_panel,
|
|||
|
||||
sim_panel_destroy to shutdown a panel or sub panel.
|
||||
|
||||
Note: destroying a simulator panel will also destroy any
|
||||
Note: destroying a simulator panel will also destroy any
|
||||
related sub panels
|
||||
*/
|
||||
|
||||
|
@ -118,18 +118,18 @@ sim_panel_destroy (PANEL *panel);
|
|||
|
||||
/**
|
||||
|
||||
The frontpanel API exposes the state of a simulator via access to
|
||||
The frontpanel API exposes the state of a simulator via access to
|
||||
simh register variables that the simulator and its devices define.
|
||||
These registers certainly include any architecturally described
|
||||
These registers certainly include any architecturally described
|
||||
registers (PC, PSL, SP, etc.), but also include anything else
|
||||
the simulator uses as internal state to implement the running
|
||||
the simulator uses as internal state to implement the running
|
||||
simulator.
|
||||
|
||||
The registers that a particular frontpanel application mught need
|
||||
access to are specified by the application when it calls:
|
||||
|
||||
The registers that a particular frontpanel application might need
|
||||
access to are specified by the application when it calls:
|
||||
|
||||
sim_panel_add_register
|
||||
sim_panel_add_register_bits
|
||||
sim_panel_add_register_bits
|
||||
sim_panel_add_register_array
|
||||
and
|
||||
sim_panel_add_register_indirect
|
||||
|
@ -142,13 +142,13 @@ and
|
|||
element_count number of elements in the register array
|
||||
size the size (in local storage) of the buffer which will
|
||||
receive the data in the simulator's register
|
||||
addr a pointer to the location of the buffer which will
|
||||
addr a pointer to the location of the buffer which will
|
||||
be loaded with the data in the simulator's register
|
||||
bit_width the number of values to populate in the bits array
|
||||
bits an array of integers which is bit_width long that
|
||||
bits an array of integers which is bit_width long that
|
||||
will receive each bit's current accumulated value.
|
||||
The accumulated value will range from 0 thru the
|
||||
the sample_depth specified when calling
|
||||
The accumulated value will range from 0 thru the
|
||||
the sample_depth specified when calling
|
||||
sim_panel_set_sampling_parameters().
|
||||
*/
|
||||
|
||||
|
@ -190,58 +190,58 @@ sim_panel_add_register_indirect_bits (PANEL *panel,
|
|||
|
||||
/**
|
||||
|
||||
A panel application has a choice of two different methods of getting
|
||||
A panel application has a choice of two different methods of getting
|
||||
the values contained in the set of registers it has declared interest in via
|
||||
the sim_panel_add_register APIs.
|
||||
|
||||
|
||||
1) The values can be polled (whenever it is desired) by calling
|
||||
sim_panel_get_registers().
|
||||
2) The panel can call sim_panel_set_display_callback_interval() to
|
||||
specify a callback routine and a periodic rate that the callback
|
||||
routine should be called. The panel API will make a best effort
|
||||
2) The panel can call sim_panel_set_display_callback_interval() to
|
||||
specify a callback routine and a periodic rate that the callback
|
||||
routine should be called. The panel API will make a best effort
|
||||
to deliver the current register state at the desired rate.
|
||||
|
||||
|
||||
Note 1: The buffers described in a panel's register set will be
|
||||
dynamically revised as soon as data is available from the
|
||||
simulator. The callback routine merely serves as a notification
|
||||
Note 1: The buffers described in a panel's register set will be
|
||||
dynamically revised as soon as data is available from the
|
||||
simulator. The callback routine merely serves as a notification
|
||||
that a complete register set has arrived.
|
||||
Note 2: The callback routine should, in general, not run for a long time
|
||||
or frontpanel interactions with the simulator may be disrupted.
|
||||
Setting a flag, signaling an event or posting a message are
|
||||
or frontpanel interactions with the simulator may be disrupted.
|
||||
Setting a flag, signaling an event or posting a message are
|
||||
reasonable activities to perform in a callback routine.
|
||||
*/
|
||||
|
||||
int
|
||||
sim_panel_get_registers (PANEL *panel, unsigned long long *simulation_time);
|
||||
|
||||
typedef void (*PANEL_DISPLAY_PCALLBACK)(PANEL *panel,
|
||||
typedef void (*PANEL_DISPLAY_PCALLBACK)(PANEL *panel,
|
||||
unsigned long long simulation_time,
|
||||
void *context);
|
||||
|
||||
int
|
||||
sim_panel_set_display_callback_interval (PANEL *panel,
|
||||
PANEL_DISPLAY_PCALLBACK callback,
|
||||
void *context,
|
||||
sim_panel_set_display_callback_interval (PANEL *panel,
|
||||
PANEL_DISPLAY_PCALLBACK callback,
|
||||
void *context,
|
||||
int usecs_between_callbacks);
|
||||
|
||||
/**
|
||||
|
||||
When a front panel application wants to get averaged bit sample
|
||||
values, it must first declare the sampling parameters that will
|
||||
be used while collecting the bit values. The dithering
|
||||
be used while collecting the bit values. The dithering
|
||||
percentage must be 25% or less and when non 0 causes the sample
|
||||
frequency to vary by plus or minus a random percentage value up
|
||||
frequency to vary by plus or minus a random percentage value up
|
||||
to the specified value.
|
||||
|
||||
sim_panel_set_sampling_parameters
|
||||
sim_panel_set_sampling_parameters_ex
|
||||
sim_panel_set_sampling_parameters
|
||||
sim_panel_set_sampling_parameters_ex
|
||||
|
||||
sample_frequency cycles/instructions between sample captures
|
||||
sample_dither_pct percentage of sample_frequency to vary randomly
|
||||
sample_depth how many samples to accumulate in the rolling
|
||||
average for each bit sample. Returned bit
|
||||
sample values will range from 0 thru this
|
||||
sample values will range from 0 thru this
|
||||
value.
|
||||
*/
|
||||
|
||||
|
@ -258,13 +258,13 @@ sim_panel_set_sampling_parameters (PANEL *panel,
|
|||
/**
|
||||
|
||||
When a front panel application needs to change the running
|
||||
state of a simulator one of the following routines should
|
||||
be called:
|
||||
|
||||
state of a simulator one of the following routines should
|
||||
be called:
|
||||
|
||||
sim_panel_exec_halt - Stop instruction execution
|
||||
sim_panel_exec_boot - Boot a simulator from a specific device
|
||||
sim_panel_exec_run - Start/Resume a simulator running instructions
|
||||
sim_panel_exec_start - Start a simulator running instructions
|
||||
sim_panel_exec_start - Start a simulator running instructions
|
||||
after resetting all devices
|
||||
sim_panel_exec_step - Have a simulator execute a single step
|
||||
*/
|
||||
|
@ -290,7 +290,7 @@ sim_panel_exec_step (PANEL *panel);
|
|||
A simulator often displays some useful information as it stops
|
||||
executing instructions.
|
||||
|
||||
sim_panel_halt_text - Returns the simulator output immediately prior
|
||||
sim_panel_halt_text - Returns the simulator output immediately prior
|
||||
to the most recent transition to the Halt state.
|
||||
*/
|
||||
|
||||
|
@ -299,20 +299,20 @@ sim_panel_halt_text (PANEL *panel);
|
|||
|
||||
/**
|
||||
|
||||
When a front panel application wants to describe conditions that
|
||||
When a front panel application wants to describe conditions that
|
||||
should stop instruction execution an execution or an output
|
||||
breakpoint should be used. To established or clear a breakpoint,
|
||||
one of the following routines should be called:
|
||||
|
||||
breakpoint should be used. To established or clear a breakpoint,
|
||||
one of the following routines should be called:
|
||||
|
||||
sim_panel_break_set - Establish a simulation breakpoint
|
||||
sim_panel_break_clear - Cancel/Delete a previously defined
|
||||
breakpoint
|
||||
sim_panel_break_output_set - Establish a simulator output
|
||||
sim_panel_break_output_set - Establish a simulator output
|
||||
breakpoint
|
||||
sim_panel_break_output_clear - Cancel/Delete a previously defined
|
||||
output breakpoint
|
||||
|
||||
Note: Any breakpoint switches/flags must be located at the
|
||||
|
||||
Note: Any breakpoint switches/flags must be located at the
|
||||
beginning of the condition string
|
||||
*/
|
||||
|
||||
|
@ -332,16 +332,16 @@ sim_panel_break_output_clear (PANEL *panel, const char *condition);
|
|||
/**
|
||||
|
||||
When a front panel application needs to change or access
|
||||
memory or a register one of the following routines should
|
||||
be called:
|
||||
|
||||
memory or a register one of the following routines should
|
||||
be called:
|
||||
|
||||
sim_panel_gen_examine - Examine register or memory
|
||||
sim_panel_gen_deposit - Deposit to register or memory
|
||||
sim_panel_mem_examine - Examine memory location
|
||||
sim_panel_mem_deposit - Deposit to memory location
|
||||
sim_panel_mem_deposit_instruction - Deposit instruction to memory
|
||||
sim_panel_mem_deposit_instruction - Deposit instruction to memory
|
||||
location
|
||||
sim_panel_set_register_value - Deposit to a register or memory
|
||||
sim_panel_set_register_value - Deposit to a register or memory
|
||||
location
|
||||
*/
|
||||
|
||||
|
@ -358,7 +358,7 @@ sim_panel_break_output_clear (PANEL *panel, const char *condition);
|
|||
*/
|
||||
|
||||
int
|
||||
sim_panel_gen_examine (PANEL *panel,
|
||||
sim_panel_gen_examine (PANEL *panel,
|
||||
const char *name_or_addr,
|
||||
size_t size,
|
||||
void *value);
|
||||
|
@ -370,12 +370,12 @@ sim_panel_gen_examine (PANEL *panel,
|
|||
name_or_addr the name the simulator knows this register by
|
||||
size the size (in local storage) of the buffer which
|
||||
contains the data to be deposited into the simulator
|
||||
value a pointer to the buffer which contains the data to
|
||||
value a pointer to the buffer which contains the data to
|
||||
be deposited into the simulator
|
||||
*/
|
||||
|
||||
int
|
||||
sim_panel_gen_deposit (PANEL *panel,
|
||||
sim_panel_gen_deposit (PANEL *panel,
|
||||
const char *name_or_addr,
|
||||
size_t size,
|
||||
const void *value);
|
||||
|
@ -384,7 +384,7 @@ sim_panel_gen_deposit (PANEL *panel,
|
|||
|
||||
sim_panel_mem_examine
|
||||
|
||||
addr_size the size (in local storage) of the buffer which
|
||||
addr_size the size (in local storage) of the buffer which
|
||||
contains the memory address of the data to be examined
|
||||
in the simulator
|
||||
addr a pointer to the buffer containing the memory address
|
||||
|
@ -396,7 +396,7 @@ sim_panel_gen_deposit (PANEL *panel,
|
|||
*/
|
||||
|
||||
int
|
||||
sim_panel_mem_examine (PANEL *panel,
|
||||
sim_panel_mem_examine (PANEL *panel,
|
||||
size_t addr_size,
|
||||
const void *addr,
|
||||
size_t value_size,
|
||||
|
@ -406,7 +406,7 @@ sim_panel_mem_examine (PANEL *panel,
|
|||
|
||||
sim_panel_mem_deposit
|
||||
|
||||
addr_size the size (in local storage) of the buffer which
|
||||
addr_size the size (in local storage) of the buffer which
|
||||
contains the memory address of the data to be deposited
|
||||
into the simulator
|
||||
addr a pointer to the buffer containing the memory address
|
||||
|
@ -418,7 +418,7 @@ sim_panel_mem_examine (PANEL *panel,
|
|||
*/
|
||||
|
||||
int
|
||||
sim_panel_mem_deposit (PANEL *panel,
|
||||
sim_panel_mem_deposit (PANEL *panel,
|
||||
size_t addr_size,
|
||||
const void *addr,
|
||||
size_t value_size,
|
||||
|
@ -428,17 +428,17 @@ sim_panel_mem_deposit (PANEL *panel,
|
|||
|
||||
sim_panel_mem_deposit_instruction
|
||||
|
||||
addr_size the size (in local storage) of the buffer which
|
||||
addr_size the size (in local storage) of the buffer which
|
||||
contains the memory address of the data to be deposited
|
||||
into the simulator
|
||||
addr a pointer to the buffer containing the memory address
|
||||
of the data to be deposited into the simulator
|
||||
instruction a pointer to the buffer that contains the mnemonic
|
||||
instruction a pointer to the buffer that contains the mnemonic
|
||||
instruction to be deposited at the indicated address
|
||||
*/
|
||||
|
||||
int
|
||||
sim_panel_mem_deposit_instruction (PANEL *panel,
|
||||
sim_panel_mem_deposit_instruction (PANEL *panel,
|
||||
size_t addr_size,
|
||||
const void *addr,
|
||||
const char *instruction);
|
||||
|
@ -449,8 +449,8 @@ sim_panel_mem_deposit_instruction (PANEL *panel,
|
|||
|
||||
name the name of a simulator register or a memory address
|
||||
which is to receive a new value
|
||||
value the new value in character string form. The string
|
||||
must be in the native/natural radix that the simulator
|
||||
value the new value in character string form. The string
|
||||
must be in the native/natural radix that the simulator
|
||||
uses when referencing that register
|
||||
*/
|
||||
int
|
||||
|
@ -461,9 +461,9 @@ sim_panel_set_register_value (PANEL *panel,
|
|||
/**
|
||||
|
||||
A front panel application might want to have access to the
|
||||
instruction execution history that a simulator may be capable
|
||||
instruction execution history that a simulator may be capable
|
||||
of providing. If this functionality is desired, enabling of
|
||||
recording instruction history should be explicitly enabled
|
||||
recording instruction history should be explicitly enabled
|
||||
in the sim_config file that the simulator is started with.
|
||||
*/
|
||||
|
||||
|
@ -479,7 +479,7 @@ sim_panel_set_register_value (PANEL *panel,
|
|||
*/
|
||||
|
||||
int
|
||||
sim_panel_get_history (PANEL *panel,
|
||||
sim_panel_get_history (PANEL *panel,
|
||||
int count,
|
||||
size_t size,
|
||||
char *buffer);
|
||||
|
@ -488,7 +488,7 @@ sim_panel_get_history (PANEL *panel,
|
|||
/**
|
||||
|
||||
A front panel application might want some details of simulator
|
||||
and/or device behavior that is provided by a particular simulator
|
||||
and/or device behavior that is provided by a particular simulator
|
||||
via debug information. Debugging for particular device(s)
|
||||
and/or simulator debug settings can be controlled via the
|
||||
sim_panel_device_debug_mode API.
|
||||
|
@ -499,15 +499,15 @@ sim_panel_get_history (PANEL *panel,
|
|||
sim_panel_device_debug_mode
|
||||
|
||||
device the device whose debug mode is to change
|
||||
set_untset 1 to set debug flags, 0 to clear debug flags
|
||||
mode_bits character string with different debug mode bits
|
||||
set_unset 1 to set debug flags, 0 to clear debug flags
|
||||
mode_bits character string with different debug mode bits
|
||||
to enable or disable. An empty string will
|
||||
enable or disable all mode bits for the specified
|
||||
enable or disable all mode bits for the specified
|
||||
device
|
||||
*/
|
||||
|
||||
int
|
||||
sim_panel_device_debug_mode (PANEL *panel,
|
||||
sim_panel_device_debug_mode (PANEL *panel,
|
||||
const char *device,
|
||||
int set_unset,
|
||||
const char *mode_bits);
|
||||
|
@ -516,11 +516,11 @@ sim_panel_device_debug_mode (PANEL *panel,
|
|||
/**
|
||||
|
||||
When a front panel application needs to change the media
|
||||
in a simulated removable media device one of the following
|
||||
in a simulated removable media device one of the following
|
||||
routines should be called:
|
||||
|
||||
sim_panel_mount - mounts the indicated media file on a device
|
||||
sim_panel_dismount - dismounts the currently mounted media file
|
||||
sim_panel_dismount - dismounts the currently mounted media file
|
||||
from a device
|
||||
*/
|
||||
|
||||
|
@ -564,13 +564,13 @@ sim_panel_get_state (PANEL *panel);
|
|||
|
||||
/**
|
||||
|
||||
All API routines which return an int return 0 for
|
||||
success and -1 for an error.
|
||||
All API routines which return an int return 0 for
|
||||
success and -1 for an error.
|
||||
|
||||
An API which returns an error (-1), will not change the panel state
|
||||
except to possibly set the panel state to Error if the panel
|
||||
condition is no longer useful.
|
||||
|
||||
|
||||
sim_panel_get_error - the details of the most recent error
|
||||
sim_panel_clear_error - clears the error buffer
|
||||
*/
|
||||
|
@ -580,8 +580,8 @@ void sim_panel_clear_error (void);
|
|||
|
||||
/**
|
||||
|
||||
The panek<->simulator wire protocol can be traced if protocol problems arise.
|
||||
|
||||
The panel<->simulator wire protocol can be traced if protocol problems arise.
|
||||
|
||||
sim_panel_set_debug_mode - Specifies the debug detail to be recorded
|
||||
sim_panel_flush_debug - Flushes debug output to disk
|
||||
sim_panel_debug - Write message to the debug file
|
||||
|
|
|
@ -156,7 +156,7 @@ static t_stat diskParse(DISK_INFO *myDisk, uint32 isVerbose)
|
|||
sim_debug(myDisk->debugmask, myDisk->device, "start of track %d at file offset %ld\n", myDisk->ntracks, ftell(myDisk->file));
|
||||
|
||||
hdrBytes = sim_fread(&imd, 1, 5, myDisk->file);
|
||||
|
||||
|
||||
if ((hdrBytes == 0) && feof(myDisk->file))
|
||||
break; /* detected end of IMD file */
|
||||
|
||||
|
@ -672,7 +672,7 @@ t_stat sectWrite(DISK_INFO *myDisk,
|
|||
* does not involve changing the disk image size.)
|
||||
*
|
||||
* Any existing data on the disk image will be destroyed when Track 0, Head 0 is formatted.
|
||||
* At that time, the IMD file is truncated. So for the trackWrite to be used to sucessfully
|
||||
* At that time, the IMD file is truncated. So for the trackWrite to be used to successfully
|
||||
* format a disk image, then format program must format tracks starting with Cyl 0, Head 0,
|
||||
* and proceed sequentially through all tracks/heads on the disk.
|
||||
*
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* sim_printf_fmts.h
|
||||
*
|
||||
* Cross-platform printf() formats for simh data types. Refactored out to
|
||||
* this header so that these formats are avaiable to more than SCP.
|
||||
* this header so that these formats are available to more than SCP.
|
||||
*
|
||||
* Author: B. Scott Michel
|
||||
*
|
||||
|
|
106
sim_rev.h
106
sim_rev.h
|
@ -45,8 +45,8 @@
|
|||
#endif
|
||||
|
||||
/*
|
||||
SIM__GIT_COMMMIT_ID is undefined when working with an
|
||||
archive (zip file or tar ball). Use Git keyword subsitution
|
||||
SIM__GIT_COMMMIT_ID is undefined when working with an
|
||||
archive (zip file or tar ball). Use Git keyword substitution
|
||||
to record the archive's commit id via the .gitattributes
|
||||
"export-subst".
|
||||
*/
|
||||
|
@ -55,9 +55,9 @@
|
|||
|
||||
/*
|
||||
The comment section below reflects the manual editing process which was in place
|
||||
prior to the use of the git source control system on at https://gihub.com/simh/simh
|
||||
prior to the use of the git source control system on at https://github.com/simh/simh
|
||||
|
||||
Details about all future fixes will be visible in the source control system's
|
||||
Details about all future fixes will be visible in the source control system's
|
||||
history.
|
||||
|
||||
*/
|
||||
|
@ -86,7 +86,7 @@ patch date module(s) and fix(es)
|
|||
connected LANs
|
||||
|
||||
sim_tmxr.c:
|
||||
- made telnet option negotiation more reliable, VAX simulator now
|
||||
- made telnet option negotiation more reliable, VAX simulator now
|
||||
works with PuTTY as console (Mark Pizzolato)
|
||||
|
||||
h316_cpu.c:
|
||||
|
@ -147,7 +147,7 @@ patch date module(s) and fix(es)
|
|||
|
||||
hp2100_dp.c (Dave Bryan):
|
||||
- Added CNTLR_TYPE cast to dp_settype
|
||||
|
||||
|
||||
hp2100_ds.c (Dave Bryan):
|
||||
- Rewritten to use the MAC/ICD disc controller library
|
||||
- ioIOO now notifies controller service of parameter output
|
||||
|
@ -178,21 +178,21 @@ patch date module(s) and fix(es)
|
|||
|
||||
hp2100_ms.c (Dave Bryan):
|
||||
- Added CNTLR_TYPE cast to ms_settype
|
||||
|
||||
|
||||
hp2100_mt.c (Dave Bryan):
|
||||
- Removed redundant MTAB_VUN from "format" MTAB entry
|
||||
- Fixed command scanning error in mtcio ioIOO handler
|
||||
|
||||
hp2100_stddev.c (Dave Bryan):
|
||||
- Add TBG as a logical name for the CLK device
|
||||
|
||||
|
||||
hp2100_sys.c (Dave Bryan):
|
||||
- Deprecated DEVNO in favor of SC
|
||||
- Added hp_setsc, hp_showsc functions to support SC modifier
|
||||
- Added DA and dummy DC devices
|
||||
- DMA channels renamed from 0,1 to 1,2 to match documentation
|
||||
- Changed DIB access for revised signal model
|
||||
|
||||
|
||||
hp_disclib.c, hp_disclib.h (Dave Bryan)
|
||||
- Created MAC/ICD disc controller library
|
||||
|
||||
|
@ -229,7 +229,7 @@ patch date module(s) and fix(es)
|
|||
- fixed misuse of & instead of && in Ea_ch (Michael Bloom)
|
||||
|
||||
pdp1_stddev.c:
|
||||
- fixed unitialized variable in tty output service (Michael Bloom)
|
||||
- fixed uninitialized variable in tty output service (Michael Bloom)
|
||||
|
||||
pdp10_fe.c:
|
||||
- revised to use clock coscheduling
|
||||
|
@ -241,7 +241,7 @@ patch date module(s) and fix(es)
|
|||
- fixed Qbus interrupts to treat all IO devices (except clock) as BR4
|
||||
- fixed order of int_internal (Jordi Guillaumes i Pons)
|
||||
|
||||
ppd11_rf.c
|
||||
pdp11_rf.c
|
||||
- fixed bug in updating mem addr extension (Peter Schorn)
|
||||
|
||||
pdp11_rk.c:
|
||||
|
@ -254,7 +254,7 @@ patch date module(s) and fix(es)
|
|||
- added RD32 support
|
||||
|
||||
pdp11_tq.c: (Mark Pizzolato)
|
||||
- set UNIT_SXC flag when a tape mark is encountered
|
||||
- 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
|
||||
|
@ -264,7 +264,7 @@ patch date module(s) and fix(es)
|
|||
- added more debug output after positioning operations
|
||||
- added textual display of the command being performed
|
||||
- fixed comments about register addresses
|
||||
|
||||
|
||||
pdp11_ts.c:
|
||||
- fixed t_addr printouts for 64b big-endian systems (Mark Pizzolato)
|
||||
|
||||
|
@ -278,34 +278,34 @@ patch date module(s) and fix(es)
|
|||
|
||||
pdp11_xq.c: (Mark Pizzolato)
|
||||
- Fixed missing information from save/restore which
|
||||
caused operations to not complete correctly after
|
||||
caused operations to not complete correctly after
|
||||
a restore until the OS reset the controller.
|
||||
- Added address conflict check during attach.
|
||||
- Fixed loopback processing to correctly handle forward packets.
|
||||
- Fixed interrupt dispatch issue which caused delivered packets
|
||||
- Fixed interrupt dispatch issue which caused delivered packets
|
||||
(in and out) to sometimes not interrupt the CPU after processing.
|
||||
- Fixed the SCP visibile SA registers to always display the
|
||||
- Fixed the SCP visible SA registers to always display the
|
||||
ROM mac address, even after it is changed by SET XQ MAC=.
|
||||
- Added changes so that the Console DELQA diagnostic (>>>TEST 82)
|
||||
- Added changes so that the Console DELQA diagnostic (>>>TEST 82)
|
||||
will succeed.
|
||||
- Added DELQA-T (aka DELQA Plus) device emulation support.
|
||||
- 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
|
||||
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.
|
||||
- Added the ability to Coalesce received packet interrupts. This
|
||||
is enabled by SET XQ POLL=DELAY=nnn where nnn is a number of
|
||||
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.
|
||||
- Added SET XQ POLL=DISABLE (aka SET XQ POLL=0) to operate without
|
||||
- Added SET XQ POLL=DISABLE (aka SET XQ POLL=0) to operate without
|
||||
polling for packet read completion.
|
||||
- Changed the sanity and id timer mechanisms to use a separate timer
|
||||
unit so that transmit and recieve activities can be dealt with
|
||||
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
|
||||
Dynamically determine the timer polling rate based on the
|
||||
calibrated tmr_poll and clk_tps values of the simulator.
|
||||
- Enabled the SET XQ POLL to be meaningful if the simulator currently
|
||||
doesn't support idling.
|
||||
|
@ -313,7 +313,7 @@ patch date module(s) and fix(es)
|
|||
all debug output goes to the same place.
|
||||
- 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
|
||||
service time. This must have been inadvertently commented out
|
||||
while other things were being tested.
|
||||
|
||||
pdp11_xu.c: (Mark Pizzolato)
|
||||
|
@ -328,7 +328,7 @@ patch date module(s) and fix(es)
|
|||
pdp18b_stddev.c:
|
||||
- added clock coscheduling
|
||||
- revised TTI to use clock coscheduling and to fix perpetual CAF bug
|
||||
|
||||
|
||||
pdp18b_ttx.c:
|
||||
- revised to use clock coscheduling
|
||||
|
||||
|
@ -342,7 +342,7 @@ patch date module(s) and fix(es)
|
|||
- revised to use clock coscheduling and to fix perpetual CAF bug
|
||||
|
||||
pdp8_ttx.c:
|
||||
- revised to use clock cosheduling
|
||||
- revised to use clock coscheduling
|
||||
|
||||
pdp8_sys.c:
|
||||
- added link to FPP
|
||||
|
@ -401,7 +401,7 @@ patch date module(s) and fix(es)
|
|||
- decommitted MTAB_VAL
|
||||
- fixed implementation of MTAB_NC
|
||||
- fixed warnings in help printouts
|
||||
- fixed "SHOW DEVICE" with only one enabled unit (Dave Bryan)
|
||||
- fixed "SHOW DEVICE" with only one enabled unit (Dave Bryan)
|
||||
|
||||
sim_tape.c:
|
||||
- fixed signed/unsigned warning in sim_tape_set_fmt (Dave Bryan)
|
||||
|
@ -423,7 +423,7 @@ patch date module(s) and fix(es)
|
|||
- Moved non-existent memory checks to WritePW
|
||||
- Fixed mp_dms_jmp to accept lower bound, check write protection
|
||||
- Corrected DMS violation register set conditions
|
||||
- Refefined ABORT to pass address, moved def to hp2100_cpu.h
|
||||
- Redefined ABORT to pass address, moved def to hp2100_cpu.h
|
||||
- Combined dms and dms_io routines
|
||||
- JSB to 0/1 with W5 out and fence = 0 erroneously causes MP abort
|
||||
- Unified I/O slot dispatch by adding DIBs for CPU, MP, and DMA
|
||||
|
@ -449,7 +449,7 @@ patch date module(s) and fix(es)
|
|||
- Updated mp_dms_jmp calling sequence
|
||||
- Fixed DJP, SJP, and UJP jump target validation
|
||||
- RVA/B conditionally updates dms_vr before returning value
|
||||
|
||||
|
||||
hp2100_cpu3.c (Dave Bryan):
|
||||
- Moved microcode function prototypes to hp2100_cpu1.h
|
||||
- Removed option-present tests (now in UIG dispatchers)
|
||||
|
@ -506,7 +506,7 @@ patch date module(s) and fix(es)
|
|||
hp2100_mt.c (Dave Bryan):
|
||||
- Fixed missing flag after CLR command
|
||||
- Moved write enable and format commands from MTD to MTC
|
||||
|
||||
|
||||
hp2100_mux.c (Dave Bryan):
|
||||
- SHOW MUX CONN/STAT with SET MUX DIAG is no longer disallowed
|
||||
- Changed Telnet poll to connect immediately after reset or attach
|
||||
|
@ -744,7 +744,7 @@ patch date module(s) and fix(es)
|
|||
- fixed declarations (Mark Pizzolato)
|
||||
|
||||
|
||||
V3.7 revision history
|
||||
V3.7 revision history
|
||||
|
||||
3 02-Sep-07 scp.c:
|
||||
- fixed bug in SET THROTTLE command
|
||||
|
@ -771,7 +771,7 @@ patch date module(s) and fix(es)
|
|||
|
||||
sim_timer.c:
|
||||
- fixed idle timer event selection algorithm
|
||||
|
||||
|
||||
h316_lp.c:
|
||||
- fixed loss of last print line (Theo Engel)
|
||||
|
||||
|
@ -827,7 +827,7 @@ patch date module(s) and fix(es)
|
|||
- fixed to set "mux_rchp" when a line break is received
|
||||
- fixed incorrect "odd_par" table values
|
||||
- reversed test in "RCV_PAR" to return "LIL_PAR" on odd parity
|
||||
- rixed mux reset (ioCRS) to clear port parameters
|
||||
- fixed mux reset (ioCRS) to clear port parameters
|
||||
- fixed to use PUT_DCH instead of PUT_CCH for data channel status
|
||||
- added DIAG/TERM modifiers to implement diagnostic mode
|
||||
|
||||
|
@ -1016,7 +1016,7 @@ patch date module(s) and fix(es)
|
|||
- fixed operand order in EIS instructions (W.F.J. Mueller)
|
||||
|
||||
|
||||
V3.6 revision history
|
||||
V3.6 revision history
|
||||
|
||||
1 25-Jul-06 sim_console.c:
|
||||
- implemented SET/SHOW PCHAR
|
||||
|
@ -1167,7 +1167,7 @@ patch date module(s) and fix(es)
|
|||
- fixed POLYD, POLYG to not exit prematurely if arg = 0
|
||||
- fixed POLYD, POLYG to do full 64b multiply
|
||||
- fixed POLYF, POLYD, POLYG to remove truncation on add
|
||||
- fixed POLYF, POLYD, POLYG to mask mul reslt to 31b/63b/63b
|
||||
- fixed POLYF, POLYD, POLYG to mask mul result to 31b/63b/63b
|
||||
- fixed fp add routine to test for zero via fraction
|
||||
to support "denormal" argument from POLYF, POLYD, POLYG
|
||||
- fixed bug in 32b floating multiply routine
|
||||
|
@ -1183,14 +1183,14 @@ patch date module(s) and fix(es)
|
|||
- fixed ACBH to set cc's on result
|
||||
- fixed POLYH to set R3 correctly
|
||||
- fixed POLYH to not exit prematurely if arg = 0
|
||||
- fixed POLYH to mask mul reslt to 127b
|
||||
- fixed POLYH to mask mul result to 127b
|
||||
- fixed fp add routine to test for zero via fraction
|
||||
to support "denormal" argument from POLYH
|
||||
- fixed EMODH to concatenate 15b of 16b extension
|
||||
- fixed bug in reported VA on faulting cross-page write
|
||||
|
||||
|
||||
V3.5 revision history
|
||||
V3.5 revision history
|
||||
|
||||
patch date module(s) and fix(es)
|
||||
|
||||
|
@ -1326,7 +1326,7 @@ patch date module(s) and fix(es)
|
|||
|
||||
vax_io.c: revised autoconfiguration algorithm and interface
|
||||
|
||||
V3.4 revision history
|
||||
V3.4 revision history
|
||||
|
||||
0 01-May-04 scp.c:
|
||||
- fixed ASSERT code
|
||||
|
@ -1364,7 +1364,7 @@ patch date module(s) and fix(es)
|
|||
|
||||
pdp11_tu.c: fixed error reporting
|
||||
|
||||
V3.3 revision history
|
||||
V3.3 revision history
|
||||
|
||||
2 08-Mar-05 scp.c: added ASSERT command (Dave Bryan)
|
||||
|
||||
|
@ -1546,7 +1546,7 @@ patch date module(s) and fix(es)
|
|||
- TMK is cleared by new motion command, not DCLR
|
||||
- DONE is set on data transfers, ATA on non data transfers
|
||||
|
||||
pdp11_defs.h:
|
||||
pdp11_defs.h:
|
||||
- revised Unibus/Qbus DMA API's
|
||||
- added CPU type and options flags
|
||||
|
||||
|
@ -1582,7 +1582,7 @@ patch date module(s) and fix(es)
|
|||
vax_defs.h:
|
||||
- added octaword, compatibility mode support
|
||||
|
||||
vax_moddefs.h:
|
||||
vax_moddefs.h:
|
||||
- revised Unibus/Qbus DMA API's
|
||||
|
||||
vax_cpu.c:
|
||||
|
@ -1616,7 +1616,7 @@ patch date module(s) and fix(es)
|
|||
- split from vax_sys.c
|
||||
- removed PTR, PTP
|
||||
|
||||
V3.2 revision history
|
||||
V3.2 revision history
|
||||
|
||||
3 03-Sep-04 scp.c:
|
||||
- added ECHO command (Dave Bryan)
|
||||
|
@ -1701,7 +1701,7 @@ patch date module(s) and fix(es)
|
|||
- revised SR values to preserve SR<5:3>
|
||||
|
||||
hp2100_lps.c, hp2100_lpt.c: fixed timing
|
||||
|
||||
|
||||
hp2100_dp.c: fixed interpretation of SR<0>
|
||||
|
||||
hp2100_dr.c: revised boot code to use IBL algorithm
|
||||
|
@ -1868,7 +1868,7 @@ patch date module(s) and fix(es)
|
|||
|
||||
pdp1_drm.c:
|
||||
- added parallel drum support
|
||||
- fixed bug in serial drum instructin decoding
|
||||
- fixed bug in serial drum instruction decoding
|
||||
|
||||
pdp1_sys.c: added parallel drum support, mnemonics
|
||||
|
||||
|
@ -1893,7 +1893,7 @@ patch date module(s) and fix(es)
|
|||
pdp11_xq.c (Dave Hittner, Mark Pizzolato):
|
||||
- fixed second controller interrupts
|
||||
- fixed bugs in multicast and promiscuous setup
|
||||
|
||||
|
||||
pdp18b_cpu.c:
|
||||
- added instruction history
|
||||
- fixed PDP-4,-7,-9 autoincrement bug
|
||||
|
@ -1928,7 +1928,7 @@ patch date module(s) and fix(es)
|
|||
- revised instruction decoding
|
||||
- added instruction history
|
||||
|
||||
V3.0 revision history
|
||||
V3.0 revision history
|
||||
|
||||
2 15-Sep-03 scp.c:
|
||||
- fixed end-of-file problem in dep, idep
|
||||
|
@ -1940,7 +1940,7 @@ patch date module(s) and fix(es)
|
|||
- added address switch functionality to PTR BOOT
|
||||
|
||||
pdp1_sys.c: added multibank capability to LOAD
|
||||
|
||||
|
||||
pdp18b_cpu.c:
|
||||
- fixed priorities in PDP-15 API (PI between 3 and 4)
|
||||
- fixed sign handling in PDP-15 unsigned mul/div
|
||||
|
@ -2429,7 +2429,7 @@ patch date module(s) and fix(es)
|
|||
pdp11_cpu.c: fixed bugs (John Dundas)
|
||||
- added special case for PS<15:12> = 1111 to MFPI
|
||||
- removed special case from MTPI
|
||||
- added masking of relocation adds
|
||||
- added masking of relocation adds
|
||||
|
||||
i1401_cpu.c:
|
||||
- added multiply/divide
|
||||
|
@ -2446,7 +2446,7 @@ patch date module(s) and fix(es)
|
|||
- changed LOG/NOLOG to SET LOG/NOLOG
|
||||
- added SHOW LOG
|
||||
- added SET VT/NOVT and SHOW VT for VT emulation
|
||||
|
||||
|
||||
sim_sock.h: changed VMS stropt.h include to ioctl.h
|
||||
|
||||
vax_cpu.c
|
||||
|
@ -2455,12 +2455,12 @@ patch date module(s) and fix(es)
|
|||
- fixed register logging in autoincrement indexed
|
||||
|
||||
vax_stddev.c: added TODR powerup routine
|
||||
|
||||
|
||||
vax_cpu1.c: fixed exception flows to clear trap request
|
||||
|
||||
7 30-Apr-02 scp.c: fixed bug in clock calibration when (real) clock
|
||||
jumps forward due too far (Jonathan Engdahl)
|
||||
|
||||
|
||||
pdp11_cpu.c: fixed bugs, added features (John Dundas
|
||||
and Wolfgang Helbig)
|
||||
- added HTRAP and BPOK to maintenance register
|
||||
|
@ -2469,7 +2469,7 @@ patch date module(s) and fix(es)
|
|||
- fixed RTS SP, don't increment restored SP
|
||||
- fixed TSTSET, write dst | 1 rather than prev R0 | 1
|
||||
- fixed DIV, set N=0,Z=1 on div by zero (J11, 11/70)
|
||||
- fixed DIV, set set N=Z=0 on overfow (J11, 11/70)
|
||||
- fixed DIV, set set N=Z=0 on overflow (J11, 11/70)
|
||||
- fixed ASH, ASHC, count = -32 used implementation-
|
||||
dependent 32 bit right shift
|
||||
- fixed illegal instruction test to detect 000010
|
||||
|
@ -2600,7 +2600,7 @@ patch date module(s) and fix(es)
|
|||
- cleaned up volatile state for GNU C longjmp
|
||||
|
||||
pdp11_cpu.c: cleaned up declarations
|
||||
|
||||
|
||||
pdp11_rq.c: added RA-class disks
|
||||
|
||||
4 17-Dec-01 pdp11_rq.c: added delayed processing of packets
|
||||
|
|
14
sim_scsi.c
14
sim_scsi.c
|
@ -71,7 +71,7 @@
|
|||
#define KEY_ILLREQ 5 /* illegal request */
|
||||
#define KEY_PROT 7 /* data protect */
|
||||
#define KEY_BLANK 8 /* blank check */
|
||||
#define KEY_M_ILI 0x20 /* incorrent length indicator */
|
||||
#define KEY_M_ILI 0x20 /* incorrect length indicator */
|
||||
|
||||
/* Additional sense codes */
|
||||
|
||||
|
@ -380,7 +380,7 @@ scsi_debug_cmd (bus, "Test Unit Ready\n");
|
|||
|
||||
if (uptr->flags & UNIT_ATT) /* attached? */
|
||||
scsi_status (bus, STS_OK, KEY_OK, ASC_OK); /* unit is ready */
|
||||
else
|
||||
else
|
||||
scsi_status (bus, STS_CHK, KEY_NOTRDY, ASC_NOMEDIA); /* no media present */
|
||||
}
|
||||
|
||||
|
@ -428,11 +428,11 @@ else {
|
|||
}
|
||||
#endif
|
||||
if (dev->removeable)
|
||||
bus->buf[bus->buf_b++] = 0x80; /* removeable */
|
||||
bus->buf[bus->buf_b++] = 0x80; /* removable */
|
||||
else
|
||||
bus->buf[bus->buf_b++] = 0; /* fixed */
|
||||
bus->buf[bus->buf_b++] = dev->scsiver; /* versions */
|
||||
bus->buf[bus->buf_b++] = dev->scsiver; /* respose data format */
|
||||
bus->buf[bus->buf_b++] = dev->scsiver; /* response data format */
|
||||
bus->buf[bus->buf_b++] = 31; /* additional length */
|
||||
bus->buf[bus->buf_b++] = 0; /* reserved */
|
||||
bus->buf[bus->buf_b++] = 0; /* reserved */
|
||||
|
@ -639,7 +639,7 @@ if ((pc == 0x4) || (pc == 0x3F)) {
|
|||
bus->buf[bus->buf_b++] = 0x4; /* landing zone cyl (15:8) */
|
||||
bus->buf[bus->buf_b++] = 0; /* landing zone cyl (7:0) */
|
||||
bus->buf[bus->buf_b++] = 0; /* reserved, RPL */
|
||||
bus->buf[bus->buf_b++] = 0; /* rotational offet */
|
||||
bus->buf[bus->buf_b++] = 0; /* rotational offset */
|
||||
bus->buf[bus->buf_b++] = 0; /* reserved */
|
||||
bus->buf[bus->buf_b++] = 0x1C; /* medium rotation rate (15:8) */
|
||||
bus->buf[bus->buf_b++] = 0x20; /* medium rotation rate (7:0) */
|
||||
|
@ -1189,7 +1189,7 @@ for (i = 0; i < sects; i++) {
|
|||
r = sim_tape_wrtmk (uptr);
|
||||
if (r != MTSE_OK) break;
|
||||
}
|
||||
|
||||
|
||||
scsi_tape_status (bus, r);
|
||||
bus->buf[bus->buf_b++] = bus->status; /* status code */
|
||||
scsi_set_phase (bus, SCSI_STS); /* status phase next */
|
||||
|
@ -1782,7 +1782,7 @@ t_stat scsi_attach (UNIT *uptr, CONST char *cptr)
|
|||
return scsi_attach_ex (uptr, cptr, NULL);
|
||||
}
|
||||
|
||||
/* Dettach device */
|
||||
/* Detach device */
|
||||
|
||||
t_stat scsi_detach (UNIT *uptr)
|
||||
{
|
||||
|
|
56
sim_serial.c
56
sim_serial.c
|
@ -74,12 +74,12 @@
|
|||
sim_control_serial (SERHANDLE port, int32 bits_to_set, int32 bits_to_clear, int32 *incoming_bits)
|
||||
-------------------------------------------------------------------------------------------------
|
||||
|
||||
The DTR and RTS line of the serial port is set or cleared as indicated in
|
||||
the respective bits_to_set or bits_to_clear parameters. If the
|
||||
incoming_bits parameter is not NULL, then the modem status bits DCD, RNG,
|
||||
The DTR and RTS line of the serial port is set or cleared as indicated in
|
||||
the respective bits_to_set or bits_to_clear parameters. If the
|
||||
incoming_bits parameter is not NULL, then the modem status bits DCD, RNG,
|
||||
DSR and CTS are returned.
|
||||
|
||||
If unreasonable or nonsense bits_to_set or bits_to_clear bits are
|
||||
If unreasonable or nonsense bits_to_set or bits_to_clear bits are
|
||||
specified, then the return status is SCPE_ARG;
|
||||
If an error occurs, SCPE_IOERR is returned.
|
||||
|
||||
|
@ -233,8 +233,8 @@ static int sim_serial_devices (int max, SERIAL_LIST *list)
|
|||
{
|
||||
int i, j, ports = sim_serial_os_devices(max, list);
|
||||
|
||||
/* Open ports may not show up in the list returned by sim_serial_os_devices
|
||||
so we add the open ports to the list removing duplicates before sorting
|
||||
/* Open ports may not show up in the list returned by sim_serial_os_devices
|
||||
so we add the open ports to the list removing duplicates before sorting
|
||||
the resulting list */
|
||||
|
||||
for (i=0; i<serial_open_device_count; ++i) {
|
||||
|
@ -500,9 +500,9 @@ return r;
|
|||
|
||||
/* Enumerate the available serial ports.
|
||||
|
||||
The serial port names are extracted from the appropriate place in the
|
||||
The serial port names are extracted from the appropriate place in the
|
||||
windows registry (HKLM\HARDWARE\DEVICEMAP\SERIALCOMM\). The resulting
|
||||
list is sorted alphabetically by device name (COMn). The device description
|
||||
list is sorted alphabetically by device name (COMn). The device description
|
||||
is set to the OS internal name for the COM device.
|
||||
|
||||
*/
|
||||
|
@ -536,7 +536,7 @@ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM", 0, KEY_
|
|||
else
|
||||
break;
|
||||
}
|
||||
/* Besure to clear the working entry before trying again */
|
||||
/* Be sure to clear the working entry before trying again */
|
||||
memset(list[ports].name, 0, sizeof(list[ports].name));
|
||||
memset(list[ports].desc, 0, sizeof(list[ports].desc));
|
||||
dwValueNameSize = sizeof(list[ports].desc);
|
||||
|
@ -775,12 +775,12 @@ return SCPE_OK; /* return success status
|
|||
|
||||
/* Control a serial port.
|
||||
|
||||
The DTR and RTS line of the serial port is set or cleared as indicated in
|
||||
the respective bits_to_set or bits_to_clear parameters. If the
|
||||
incoming_bits parameter is not NULL, then the modem status bits DCD, RNG,
|
||||
The DTR and RTS line of the serial port is set or cleared as indicated in
|
||||
the respective bits_to_set or bits_to_clear parameters. If the
|
||||
incoming_bits parameter is not NULL, then the modem status bits DCD, RNG,
|
||||
DSR and CTS are returned.
|
||||
|
||||
If unreasonable or nonsense bits_to_set or bits_to_clear bits are
|
||||
If unreasonable or nonsense bits_to_set or bits_to_clear bits are
|
||||
specified, then the return status is SCPE_ARG;
|
||||
If an error occurs, SCPE_IOERR is returned.
|
||||
*/
|
||||
|
@ -939,8 +939,8 @@ struct SERPORT {
|
|||
|
||||
The serial port names generated by attempting to open /dev/ttyS0 thru
|
||||
/dev/ttyS63 and /dev/ttyUSB0 thru /dev/ttyUSB63 and /dev/tty.serial0
|
||||
thru /dev/tty.serial63. Ones we can open and are ttys (as determined
|
||||
by isatty()) are added to the list. The list is sorted alphabetically
|
||||
thru /dev/tty.serial63. Ones we can open and are ttys (as determined
|
||||
by isatty()) are added to the list. The list is sorted alphabetically
|
||||
by device name.
|
||||
|
||||
*/
|
||||
|
@ -1002,7 +1002,7 @@ for (i=0; (ports < max) && (i < 64); ++i) {
|
|||
static char *serial_unix_serial_names[] = { "S", "U", "USB", ".serial", ".usbserial", NULL};
|
||||
char **sp;
|
||||
|
||||
for (sp = serial_unix_serial_names; *sp; sp++) {
|
||||
for (sp = serial_unix_serial_names; *sp; sp++) {
|
||||
for (i=0; (ports < max) && (i <= 64); ++i) {
|
||||
if (i < 64)
|
||||
snprintf (list[ports].name, sizeof (list[ports].name), "/dev/tty%s%d", *sp, i);
|
||||
|
@ -1224,12 +1224,12 @@ return SCPE_OK; /* configuration set suc
|
|||
|
||||
/* Control a serial port.
|
||||
|
||||
The DTR and RTS line of the serial port is set or cleared as indicated in
|
||||
the respective bits_to_set or bits_to_clear parameters. If the
|
||||
incoming_bits parameter is not NULL, then the modem status bits DCD, RNG,
|
||||
The DTR and RTS line of the serial port is set or cleared as indicated in
|
||||
the respective bits_to_set or bits_to_clear parameters. If the
|
||||
incoming_bits parameter is not NULL, then the modem status bits DCD, RNG,
|
||||
DSR and CTS are returned.
|
||||
|
||||
If unreasonable or nonsense bits_to_set or bits_to_clear bits are
|
||||
If unreasonable or nonsense bits_to_set or bits_to_clear bits are
|
||||
specified, then the return status is SCPE_ARG;
|
||||
If an error occurs, SCPE_IOERR is returned.
|
||||
*/
|
||||
|
@ -1432,7 +1432,7 @@ struct SERPORT {
|
|||
|
||||
The serial port names generated by attempting to open /dev/ttyS0 thru
|
||||
/dev/ttyS53 and /dev/ttyUSB0 thru /dev/ttyUSB0. Ones we can open and
|
||||
are ttys (as determined by isatty()) are added to the list. The list
|
||||
are ttys (as determined by isatty()) are added to the list. The list
|
||||
is sorted alphabetically by device name.
|
||||
|
||||
*/
|
||||
|
@ -1539,10 +1539,10 @@ SERHANDLE port;
|
|||
|
||||
devnam.dsc$w_length = strlen (devnam.dsc$a_pointer);
|
||||
status = sys$assign (&devnam, &chan, 0, 0);
|
||||
if (status != SS$_NORMAL)
|
||||
if (status != SS$_NORMAL)
|
||||
return INVALID_HANDLE;
|
||||
status = sys$getdviw (0, chan, NULL, items, &iosb, NULL, 0, NULL);
|
||||
if ((status != SS$_NORMAL) ||
|
||||
if ((status != SS$_NORMAL) ||
|
||||
(iosb.status != SS$_NORMAL) ||
|
||||
(devclass != DC$_TERM)) {
|
||||
sys$dassgn (chan);
|
||||
|
@ -1671,12 +1671,12 @@ return SCPE_OK; /* configuration set suc
|
|||
|
||||
/* Control a serial port.
|
||||
|
||||
The DTR and RTS line of the serial port is set or cleared as indicated in
|
||||
the respective bits_to_set or bits_to_clear parameters. If the
|
||||
incoming_bits parameter is not NULL, then the modem status bits DCD, RNG,
|
||||
The DTR and RTS line of the serial port is set or cleared as indicated in
|
||||
the respective bits_to_set or bits_to_clear parameters. If the
|
||||
incoming_bits parameter is not NULL, then the modem status bits DCD, RNG,
|
||||
DSR and CTS are returned.
|
||||
|
||||
If unreasonable or nonsense bits_to_set or bits_to_clear bits are
|
||||
If unreasonable or nonsense bits_to_set or bits_to_clear bits are
|
||||
specified, then the return status is SCPE_ARG;
|
||||
If an error occurs, SCPE_IOERR is returned.
|
||||
*/
|
||||
|
@ -1770,7 +1770,7 @@ if (status != SS$_NORMAL) {
|
|||
}
|
||||
if (sense.sense_count == 0) /* no characters available? */
|
||||
return 0; /* return 0 to indicate */
|
||||
status = sys$qiow (0, port->port, IO$_READLBLK | IO$M_NOECHO | IO$M_NOFILTR | IO$M_TIMED | IO$M_TRMNOECHO,
|
||||
status = sys$qiow (0, port->port, IO$_READLBLK | IO$M_NOECHO | IO$M_NOFILTR | IO$M_TIMED | IO$M_TRMNOECHO,
|
||||
&iosb, 0, 0, buffer, (count < sense.sense_count) ? count : sense.sense_count, 0, term, 0, 0);
|
||||
if (status == SS$_NORMAL)
|
||||
status = iosb.status;
|
||||
|
|
12
sim_sock.h
12
sim_sock.h
|
@ -23,10 +23,10 @@
|
|||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
15-Oct-12 MP Added definitions needed to detect possible tcp
|
||||
15-Oct-12 MP Added definitions needed to detect possible tcp
|
||||
connect failures
|
||||
25-Sep-12 MP Reworked for RFC3493 interfaces supporting IPv6 and IPv4
|
||||
04-Jun-08 RMS Addes sim_create_sock, for IBM 1130
|
||||
04-Jun-08 RMS Added sim_create_sock, for IBM 1130
|
||||
14-Apr-05 RMS Added WSAEINPROGRESS (from Tim Riker)
|
||||
20-Aug-04 HV Added missing definition for OS/2 (from Holger Veit)
|
||||
22-Oct-03 MP Changed WIN32 winsock include to use winsock2.h to
|
||||
|
@ -69,7 +69,7 @@ extern "C" {
|
|||
|
||||
#define WSAGetLastError() errno /* Windows macros */
|
||||
#define WSASetLastError(err) errno = err
|
||||
#define closesocket close
|
||||
#define closesocket close
|
||||
#define SOCKET int
|
||||
#if defined(__hpux)
|
||||
#define WSAEWOULDBLOCK EAGAIN
|
||||
|
@ -111,10 +111,10 @@ extern "C" {
|
|||
#define sim_printf printf
|
||||
#endif
|
||||
|
||||
int sim_parse_addr (const char *cptr, char *host, size_t hostlen, const char *default_host,
|
||||
char *port, size_t port_len, const char *default_port,
|
||||
int sim_parse_addr (const char *cptr, char *host, size_t hostlen, const char *default_host,
|
||||
char *port, size_t port_len, const char *default_port,
|
||||
const char *validate_addr);
|
||||
int sim_parse_addr_ex (const char *cptr, char *host, size_t hostlen, const char *default_host,
|
||||
int sim_parse_addr_ex (const char *cptr, char *host, size_t hostlen, const char *default_host,
|
||||
char *port, size_t port_len, char *localport, size_t local_port_len, const char *default_port);
|
||||
int sim_addr_acl_check (const char *validate_addr, const char *acl);
|
||||
#define SIM_SOCK_OPT_REUSEADDR 0x0001
|
||||
|
|
160
sim_tape.c
160
sim_tape.c
|
@ -35,8 +35,8 @@
|
|||
sim_tape_sprecsr - skip records rev
|
||||
sim_tape_spfiler - skip files rev
|
||||
sim_tape_position - general purpose position
|
||||
These routines correspond to natural tape operations
|
||||
and will align better when physical tape support is
|
||||
These routines correspond to natural tape operations
|
||||
and will align better when physical tape support is
|
||||
included here.
|
||||
08-Jun-08 JDB Fixed signed/unsigned warning in sim_tape_set_fmt
|
||||
23-Jan-07 JDB Fixed backspace over gap at BOT
|
||||
|
@ -71,7 +71,7 @@
|
|||
sim_tape_errecf erase record forward
|
||||
sim_tape_errecr erase record reverse
|
||||
sim_tape_sprecsf space records forward
|
||||
sim_tape_spfilef space files forward
|
||||
sim_tape_spfilef space files forward
|
||||
sim_tape_sprecsr space records reverse
|
||||
sim_tape_spfiler space files reverse
|
||||
sim_tape_position generalized position
|
||||
|
@ -229,8 +229,8 @@ _tape_io(void *arg)
|
|||
UNIT* volatile uptr = (UNIT*)arg;
|
||||
struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
|
||||
|
||||
/* Boost Priority for this I/O thread vs the CPU instruction execution
|
||||
thread which in general won't be readily yielding the processor when
|
||||
/* Boost Priority for this I/O thread vs the CPU instruction execution
|
||||
thread which in general won't be readily yielding the processor when
|
||||
this thread needs to run */
|
||||
sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL);
|
||||
|
||||
|
@ -308,14 +308,14 @@ struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* This routine is called in the context of the main simulator thread before
|
||||
processing events for any unit. It is only called when an asynchronous
|
||||
thread has called sim_activate() to activate a unit. The job of this
|
||||
/* This routine is called in the context of the main simulator thread before
|
||||
processing events for any unit. It is only called when an asynchronous
|
||||
thread has called sim_activate() to activate a unit. The job of this
|
||||
routine is to put the unit in proper condition to digest what may have
|
||||
occurred in the asynchronous thread.
|
||||
|
||||
Since tape processing only handles a single I/O at a time to a
|
||||
particular tape device, we have the opportunity to possibly detect
|
||||
|
||||
Since tape processing only handles a single I/O at a time to a
|
||||
particular tape device, we have the opportunity to possibly detect
|
||||
improper attempts to issue multiple concurrent I/O requests. */
|
||||
static void _tape_completion_dispatch (UNIT *uptr)
|
||||
{
|
||||
|
@ -453,30 +453,30 @@ typedef struct MEMORY_TAPE {
|
|||
VOL1 vol1;
|
||||
} MEMORY_TAPE;
|
||||
|
||||
const char HDR3_RMS_STREAM[] = "HDR3020002040000"
|
||||
"0000000100000000"
|
||||
"0000000002000000"
|
||||
"0000000000000000"
|
||||
const char HDR3_RMS_STREAM[] = "HDR3020002040000"
|
||||
"0000000100000000"
|
||||
"0000000002000000"
|
||||
"0000000000000000"
|
||||
"0000 ";
|
||||
const char HDR3_RMS_STMLF[] = "HDR3020002050000"
|
||||
"0000000100000000"
|
||||
"0000000002000000"
|
||||
"0000000000000000"
|
||||
const char HDR3_RMS_STMLF[] = "HDR3020002050000"
|
||||
"0000000100000000"
|
||||
"0000000002000000"
|
||||
"0000000000000000"
|
||||
"0000 ";
|
||||
const char HDR3_RMS_FIXED[] = "HDR3020000010000"
|
||||
"0000000100000000"
|
||||
"0000000002000000"
|
||||
"0000000000000000"
|
||||
const char HDR3_RMS_FIXED[] = "HDR3020000010000"
|
||||
"0000000100000000"
|
||||
"0000000002000000"
|
||||
"0000000000000000"
|
||||
"0000 ";
|
||||
const char HDR3_RMS_VARRSX[] = "HDR300000A020000"
|
||||
"0000000100000000"
|
||||
"0000000000000000"
|
||||
"0000000000000000"
|
||||
const char HDR3_RMS_VARRSX[] = "HDR300000A020000"
|
||||
"0000000100000000"
|
||||
"0000000000000000"
|
||||
"0000000000000000"
|
||||
"0000 ";
|
||||
const char HDR3_RMS_FIXRSX[] = "HDR3020008010000"
|
||||
"0000000100000000"
|
||||
"0000000000000000"
|
||||
"0000000000000000"
|
||||
const char HDR3_RMS_FIXRSX[] = "HDR3020008010000"
|
||||
"0000000100000000"
|
||||
"0000000000000000"
|
||||
"0000000000000000"
|
||||
"0000 ";
|
||||
|
||||
static struct ansi_tape_parameters {
|
||||
|
@ -508,7 +508,7 @@ static struct ansi_tape_parameters {
|
|||
static MEMORY_TAPE *ansi_create_tape (const char *label, size_t block_size, uint32 ansi_type);
|
||||
static MEMORY_TAPE *memory_create_tape (void);
|
||||
static void memory_free_tape (void *vtape);
|
||||
static void sim_tape_add_ansi_entry (const char *directory,
|
||||
static void sim_tape_add_ansi_entry (const char *directory,
|
||||
const char *filename,
|
||||
t_offset FileSize,
|
||||
const struct stat *filestat,
|
||||
|
@ -596,7 +596,7 @@ return SCPE_OK;
|
|||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
This routine is called when the simulator stops and any time
|
||||
the asynch mode is changed (enabled or disabled)
|
||||
*/
|
||||
|
@ -781,7 +781,7 @@ switch (MT_GET_FMT (uptr)) {
|
|||
if (uptr->recsize == 0)
|
||||
uptr->recsize = 512;
|
||||
if ((statb.st_size % uptr->recsize) != 0) {
|
||||
r = sim_messagef (SCPE_ARG, "Binary file data is not a multiple of the specifyed record size (%d)\n", (int)uptr->recsize);
|
||||
r = sim_messagef (SCPE_ARG, "Binary file data is not a multiple of the specified record size (%d)\n", (int)uptr->recsize);
|
||||
fclose (f);
|
||||
break;
|
||||
}
|
||||
|
@ -810,11 +810,11 @@ switch (MT_GET_FMT (uptr)) {
|
|||
tape->block_size = uptr->recsize;
|
||||
block = (uint8 *)calloc (1, tape->block_size + 3);
|
||||
while (!feof (f) && !error) {
|
||||
/* fgest() read size is int, cast accordingly. */
|
||||
/* fgets() read size is int, cast accordingly. */
|
||||
if (fgets ((char *)block, (int) (tape->block_size + 3), f)) {
|
||||
size_t len = strlen ((char *)block);
|
||||
|
||||
while ((len > 0) &&
|
||||
while ((len > 0) &&
|
||||
((block[len - 1] == '\r') || (block[len - 1] == '\n')))
|
||||
--len;
|
||||
memset (block + len, ' ', tape->block_size - len);
|
||||
|
@ -891,7 +891,7 @@ switch (MT_GET_FMT (uptr)) {
|
|||
if (uptr->recsize == 0)
|
||||
uptr->recsize = TAR_DFLT_RECSIZE; /* Apply default block size */
|
||||
if ((uptr->recsize % 512) != 0)
|
||||
return sim_messagef (SCPE_ARG, "TAR format block size of %" SIZE_T_FMT "u is not a multiple of 512\n", uptr->recsize);
|
||||
return sim_messagef (SCPE_ARG, "TAR format block size of %" SIZE_T_FMT "u is not a multiple of 512\n", uptr->recsize);
|
||||
sim_switches |= SWMASK ('E'); /* The TAR file must exist */
|
||||
/* fall through */
|
||||
default:
|
||||
|
@ -1083,7 +1083,7 @@ fprintf (st, " accessible directly as files on the tape.\n\n");
|
|||
fprintf (st, " FIXED format will present the contents of a file (text or binary) as\n");
|
||||
fprintf (st, " fixed sized records/blocks with ascii text data optionally converted\n");
|
||||
fprintf (st, " to EBCDIC.\n\n");
|
||||
fprintf (st, " DOS11 format will present the contents of a file preceeded by a DOS11\n");
|
||||
fprintf (st, " DOS11 format will present the contents of a file preceded by a DOS11\n");
|
||||
fprintf (st, " 14-byte header. All files will be owned by [1,1], have a default\n");
|
||||
fprintf (st, " protection of <233> and a date in the range 1972 - 1999 with the\n");
|
||||
fprintf (st, " month/day layout as the current year. The file name on the tape\n");
|
||||
|
@ -1239,7 +1239,7 @@ MT_CLR_PNU (uptr); /* clear the position-no
|
|||
if ((uptr->flags & UNIT_ATT) == 0) /* if the unit is not attached */
|
||||
return MTSE_UNATT; /* then quit with an error */
|
||||
|
||||
if ((uptr->tape_eom > 0) &&
|
||||
if ((uptr->tape_eom > 0) &&
|
||||
(uptr->pos >= uptr->tape_eom)) {
|
||||
MT_SET_PNU (uptr); /* then set position not updated */
|
||||
return MTSE_EOM; /* and quit with I/O error status */
|
||||
|
@ -1402,7 +1402,7 @@ switch (f) { /* otherwise the read method
|
|||
}
|
||||
else {
|
||||
if ((feof (uptr->fileref)) || /* eof? */
|
||||
((tpcbc == TPC_EOM) &&
|
||||
((tpcbc == TPC_EOM) &&
|
||||
(sim_fsize (uptr->fileref) == (uint32)sim_ftell (uptr->fileref)))) {
|
||||
MT_SET_PNU (uptr); /* pos not upd */
|
||||
status = MTSE_EOM;
|
||||
|
@ -1483,7 +1483,7 @@ switch (f) { /* otherwise the read method
|
|||
saved_pos = (t_addr)sim_ftell (uptr->fileref);/* save record data address */
|
||||
(void)sim_tape_seek (uptr, uptr->pos); /* for read */
|
||||
rdcnt = sim_fread (&awshdr, sizeof (t_awslnt), 3, uptr->fileref);
|
||||
if ((rdcnt == 3) &&
|
||||
if ((rdcnt == 3) &&
|
||||
((awshdr.prelen != *bc) || ((awshdr.rectyp != AWS_REC) && (awshdr.rectyp != AWS_TMK)))) {
|
||||
status = MTSE_INVRL;
|
||||
uptr->tape_eom = uptr->pos;
|
||||
|
@ -1499,7 +1499,7 @@ switch (f) { /* otherwise the read method
|
|||
*bc = (t_mtrlnt)uptr->recsize; /* TAR record size */
|
||||
else
|
||||
*bc = (t_mtrlnt)(uptr->hwmark - uptr->pos); /* TAR remnant last record */
|
||||
(void)sim_tape_seek (uptr, uptr->pos);
|
||||
(void)sim_tape_seek (uptr, uptr->pos);
|
||||
uptr->pos += *bc;
|
||||
MT_CLR_INMRK (uptr);
|
||||
}
|
||||
|
@ -1798,8 +1798,8 @@ switch (f) { /* otherwise the read me
|
|||
status = MTSE_EOM;
|
||||
break;
|
||||
}
|
||||
if ((rdcnt != 3) ||
|
||||
((awshdr.rectyp != AWS_REC) &&
|
||||
if ((rdcnt != 3) ||
|
||||
((awshdr.rectyp != AWS_REC) &&
|
||||
(awshdr.rectyp != AWS_TMK))) {
|
||||
status = MTSE_INVRL;
|
||||
}
|
||||
|
@ -1810,8 +1810,8 @@ switch (f) { /* otherwise the read me
|
|||
if (awshdr.prelen == 0)
|
||||
status = MTSE_TMK;
|
||||
else {
|
||||
if ((uptr->tape_eom > 0) &&
|
||||
(uptr->pos >= uptr->tape_eom) &&
|
||||
if ((uptr->tape_eom > 0) &&
|
||||
(uptr->pos >= uptr->tape_eom) &&
|
||||
(awshdr.rectyp == AWS_TMK)) {
|
||||
status = MTSE_TMK;
|
||||
*bc = 0; /* save rec lnt */
|
||||
|
@ -1847,7 +1847,7 @@ switch (f) { /* otherwise the read me
|
|||
*bc = (t_mtrlnt)uptr->recsize;
|
||||
if (*bc) {
|
||||
uptr->pos -= *bc;
|
||||
(void)sim_tape_seek (uptr, uptr->pos);
|
||||
(void)sim_tape_seek (uptr, uptr->pos);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -2139,7 +2139,7 @@ if (ferror (uptr->fileref)) { /* error? */
|
|||
MT_SET_PNU (uptr); /* pos not upd */
|
||||
return sim_tape_ioerr (uptr);
|
||||
}
|
||||
if ((!sim_tape_bot (uptr)) &&
|
||||
if ((!sim_tape_bot (uptr)) &&
|
||||
(((feof (uptr->fileref)) && (rdcnt < 3)) || /* eof? */
|
||||
((awshdr.rectyp != AWS_REC) && (awshdr.rectyp != AWS_TMK)))) {
|
||||
MT_SET_PNU (uptr); /* pos not upd */
|
||||
|
@ -2870,7 +2870,7 @@ if (ctx == NULL) /* if not properly attac
|
|||
return sim_messagef (SCPE_IERR, "Bad Attach\n"); /* that's a problem */
|
||||
sim_debug_unit (ctx->dbit, uptr, "sim_tape_sprecsf(unit=%d, count=%d)\n", (int)(uptr-ctx->dptr->units), count);
|
||||
|
||||
while (*skipped < count) { /* loopo */
|
||||
while (*skipped < count) { /* loop */
|
||||
st = sim_tape_sprecf (uptr, &tbc); /* spc rec */
|
||||
if (st != MTSE_OK)
|
||||
return st;
|
||||
|
@ -2967,7 +2967,7 @@ if (ctx == NULL) /* if not properly attac
|
|||
return sim_messagef (SCPE_IERR, "Bad Attach\n"); /* that's a problem */
|
||||
sim_debug_unit (ctx->dbit, uptr, "sim_tape_sprecsr(unit=%d, count=%d)\n", (int)(uptr-ctx->dptr->units), count);
|
||||
|
||||
while (*skipped < count) { /* loopo */
|
||||
while (*skipped < count) { /* loop */
|
||||
st = sim_tape_sprecr (uptr, &tbc); /* spc rec rev */
|
||||
if (st != MTSE_OK)
|
||||
return st;
|
||||
|
@ -3028,7 +3028,7 @@ if (check_leot) {
|
|||
}
|
||||
*skipped = 0;
|
||||
*recsskipped = 0;
|
||||
while (*skipped < count) { /* loopo */
|
||||
while (*skipped < count) { /* loop */
|
||||
while (1) {
|
||||
st = sim_tape_sprecsf (uptr, 0x1ffffff, &filerecsskipped);/* spc recs */
|
||||
*recsskipped += filerecsskipped;
|
||||
|
@ -3134,7 +3134,7 @@ if (ctx == NULL) /* if not properly attac
|
|||
return sim_messagef (SCPE_IERR, "Bad Attach\n"); /* that's a problem */
|
||||
sim_debug_unit (ctx->dbit, uptr, "sim_tape_spfilebyrecr(unit=%d, count=%d)\n", (int)(uptr-ctx->dptr->units), count);
|
||||
|
||||
while (*skipped < count) { /* loopo */
|
||||
while (*skipped < count) { /* loop */
|
||||
while (1) {
|
||||
st = sim_tape_sprecsr (uptr, 0x1ffffff, &filerecsskipped);/* spc recs rev */
|
||||
*recsskipped += filerecsskipped;
|
||||
|
@ -3250,7 +3250,7 @@ if (flags & MTPOS_M_OBJ) {
|
|||
uint32 skipped;
|
||||
uint32 objsremaining = objs;
|
||||
|
||||
while (*objectsskipped < objs) { /* loopo */
|
||||
while (*objectsskipped < objs) { /* loop */
|
||||
if (flags & MTPOS_M_REV) /* reverse? */
|
||||
r = sim_tape_sprecsr (uptr, objsremaining, &skipped);
|
||||
else
|
||||
|
@ -3445,18 +3445,18 @@ for (i=0; i<65535; i++) {
|
|||
sim_debug_unit (MTSE_DBG_STR, uptr, "tpc_map: summary - %u %d byte record%s\n", countmap[i], (int)i, (countmap[i] > 1) ? "s" : "");
|
||||
}
|
||||
}
|
||||
if (((last_bc != TPC_EOM) &&
|
||||
if (((last_bc != TPC_EOM) &&
|
||||
(tpos > tape_size) &&
|
||||
(!had_double_tape_mark)) ||
|
||||
(!had_double_tape_mark) ||
|
||||
((objc == countmap[0]) &&
|
||||
((objc == countmap[0]) &&
|
||||
(countmap[0] != 2))) { /* Unreasonable format? */
|
||||
if (last_bc != TPC_EOM)
|
||||
sim_debug_unit (MTSE_DBG_STR, uptr, "tpc_map: ERROR unexpected EOT byte count: %d\n", last_bc);
|
||||
if (tpos > tape_size)
|
||||
sim_debug_unit (MTSE_DBG_STR, uptr, "tpc_map: ERROR next record position %" T_ADDR_FMT "u beyond EOT: %" T_ADDR_FMT "u\n", tpos, tape_size);
|
||||
if (objc == countmap[0])
|
||||
sim_debug_unit (MTSE_DBG_STR, uptr, "tpc_map: ERROR tape cnly contains tape marks\n");
|
||||
sim_debug_unit (MTSE_DBG_STR, uptr, "tpc_map: ERROR tape only contains tape marks\n");
|
||||
free (countmap);
|
||||
free (recbuf);
|
||||
return 0;
|
||||
|
@ -3582,7 +3582,7 @@ while (r == SCPE_OK) {
|
|||
break;
|
||||
}
|
||||
if (0 != memcmp (buf_f, buf_r, bc_f)) {
|
||||
sim_printf ("%d byte record contents differ when read forward amd backwards start from position %" T_ADDR_FMT "u\n", bc_f, pos_f);
|
||||
sim_printf ("%d byte record contents differ when read forward and backwards start from position %" T_ADDR_FMT "u\n", bc_f, pos_f);
|
||||
r = MTSE_RECE;
|
||||
break;
|
||||
}
|
||||
|
@ -3817,11 +3817,11 @@ return SCPE_OK;
|
|||
|
||||
/* list supported densities
|
||||
|
||||
translates the mask of supported densities to a string list in the form:
|
||||
|
||||
translates the mask of supported densities to a string list in the form:
|
||||
|
||||
"(800|1600|6250)"
|
||||
|
||||
this string may be useful to construct a MTAB help string for a
|
||||
this string may be useful to construct a MTAB help string for a
|
||||
SET <unit> DENSITY= command.
|
||||
|
||||
*/
|
||||
|
@ -4076,7 +4076,7 @@ tpclnt = 0xffff;
|
|||
(void)sim_fwrite (&mtrlnt, sizeof (mtrlnt), 1, fE11);
|
||||
(void)sim_fwrite (&tpclnt, sizeof (tpclnt), 1, fTPC);
|
||||
(void)sim_fwrite (buf, 1, 1, fP7B);
|
||||
/* Write an unmatched record delimiter (aka garbage) at
|
||||
/* Write an unmatched record delimiter (aka garbage) at
|
||||
the end of the SIMH, E11 and AWS files */
|
||||
mtrlnt = 25;
|
||||
(void)sim_fwrite (&mtrlnt, sizeof (mtrlnt), 1, fSIMH);
|
||||
|
@ -4220,23 +4220,23 @@ if ((SCPE_ARG != (stat = sim_tape_density_supported (buf, sizeof (buf), valid_bi
|
|||
(strcmp (buf, "")))
|
||||
return stat;
|
||||
valid_bits = MT_556_VALID;
|
||||
if ((SCPE_OK != (stat = sim_tape_density_supported (buf, sizeof (buf), valid_bits))) ||
|
||||
if ((SCPE_OK != (stat = sim_tape_density_supported (buf, sizeof (buf), valid_bits))) ||
|
||||
(strcmp (buf, "556")))
|
||||
return sim_messagef (SCPE_ARG, "stat was: %s, got string: %s\n", sim_error_text (stat), buf);
|
||||
valid_bits = MT_800_VALID | MT_1600_VALID;
|
||||
if ((SCPE_OK != (stat = sim_tape_density_supported (buf, sizeof (buf), valid_bits))) ||
|
||||
if ((SCPE_OK != (stat = sim_tape_density_supported (buf, sizeof (buf), valid_bits))) ||
|
||||
(strcmp (buf, "{800|1600}")))
|
||||
return sim_messagef (SCPE_ARG, "stat was: %s, got string: %s\n", sim_error_text (stat), buf);
|
||||
valid_bits = MT_800_VALID | MT_1600_VALID | MT_6250_VALID;
|
||||
if ((SCPE_OK != (stat = sim_tape_density_supported (buf, sizeof (buf), valid_bits))) ||
|
||||
if ((SCPE_OK != (stat = sim_tape_density_supported (buf, sizeof (buf), valid_bits))) ||
|
||||
(strcmp (buf, "{800|1600|6250}")))
|
||||
return sim_messagef (SCPE_ARG, "stat was: %s, got string: %s\n", sim_error_text (stat), buf);
|
||||
valid_bits = MT_200_VALID | MT_800_VALID | MT_1600_VALID | MT_6250_VALID;
|
||||
if ((SCPE_OK != (stat = sim_tape_density_supported (buf, sizeof (buf), valid_bits))) ||
|
||||
if ((SCPE_OK != (stat = sim_tape_density_supported (buf, sizeof (buf), valid_bits))) ||
|
||||
(strcmp (buf, "{200|800|1600|6250}")))
|
||||
return sim_messagef (SCPE_ARG, "stat was: %s, got string: %s\n", sim_error_text (stat), buf);
|
||||
valid_bits = MT_NONE_VALID | MT_800_VALID | MT_1600_VALID | MT_6250_VALID;
|
||||
if ((SCPE_OK != (stat = sim_tape_density_supported (buf, sizeof (buf), valid_bits))) ||
|
||||
if ((SCPE_OK != (stat = sim_tape_density_supported (buf, sizeof (buf), valid_bits))) ||
|
||||
(strcmp (buf, "{0|800|1600|6250}")))
|
||||
return sim_messagef (SCPE_ARG, "stat was: %s, got string: %s\n", sim_error_text (stat), buf);
|
||||
return SCPE_OK;
|
||||
|
@ -4299,7 +4299,7 @@ for (t = classify_tests; t->testname != NULL; t++) {
|
|||
tape_classify_file_contents (f, &mrs, &lf_lines, &crlf_lines);
|
||||
fclose (f);
|
||||
if ((mrs != t->expected_mrs) || (lf_lines != t->expected_lf_lines) || (crlf_lines != t->expected_crlf_lines))
|
||||
return sim_messagef (SCPE_ARG, "%s was unexpectedly reported to having MRS=%d, lf_lines=%s, crlf_lines=%s\n",
|
||||
return sim_messagef (SCPE_ARG, "%s was unexpectedly reported to having MRS=%d, lf_lines=%s, crlf_lines=%s\n",
|
||||
t->testname, (int)mrs, lf_lines ? "true" : "false", crlf_lines ? "true" : "false");
|
||||
if (t->success_attach_args) {
|
||||
char args[CBUFSIZE*2];
|
||||
|
@ -4414,17 +4414,17 @@ static void ansi_date (time_t datetime, char date[6], t_bool y2k_date_bug)
|
|||
|
||||
lt = localtime (&datetime);
|
||||
if (y2k_date_bug)
|
||||
sprintf (buf, " %c%c%03d", '0' + (lt->tm_year / 10),
|
||||
'0' + (lt->tm_year % 10),
|
||||
sprintf (buf, " %c%c%03d", '0' + (lt->tm_year / 10),
|
||||
'0' + (lt->tm_year % 10),
|
||||
lt->tm_yday + 1);
|
||||
else
|
||||
sprintf (buf, "%c%02d%03d", (lt->tm_year < 100) ? ' ' : '0' + (lt->tm_year/100 - 1),
|
||||
lt->tm_year % 100,
|
||||
sprintf (buf, "%c%02d%03d", (lt->tm_year < 100) ? ' ' : '0' + (lt->tm_year/100 - 1),
|
||||
lt->tm_year % 100,
|
||||
lt->tm_yday + 1);
|
||||
memcpy (date, buf, 6);
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* This isn't quite ANSI 'a' since several ANSI allowed characters
|
||||
* are either illegal file names on many DEC systems or are confusing
|
||||
* to OS file name parsers.
|
||||
|
@ -4479,7 +4479,7 @@ static void ansi_make_HDR1 (HDR1 *hdr1, VOL1 *vol, HDR4 *hdr4, const char *filen
|
|||
fn = fn_cpy;
|
||||
ext = strrchr (fn_cpy, '.');
|
||||
if (ext) {
|
||||
while (((c = strchr (fn_cpy, '.')) != NULL) &&
|
||||
while (((c = strchr (fn_cpy, '.')) != NULL) &&
|
||||
(c != ext))
|
||||
*c = '_'; /* translate extra .'s to _ */
|
||||
}
|
||||
|
@ -4565,7 +4565,7 @@ static void ansi_fill_text_buffer (FILE *f, char *buf, size_t buf_size, size_t r
|
|||
move_size = rec_size;
|
||||
else
|
||||
move_size = buf_size - offset;
|
||||
/* We've got a line that stradles a block boundary */
|
||||
/* We've got a line that straddles a block boundary */
|
||||
memcpy (buf + offset, tmp, move_size);
|
||||
offset += move_size;
|
||||
if (offset == buf_size) {
|
||||
|
@ -4798,7 +4798,7 @@ else {
|
|||
if (data_read > 0)
|
||||
error = memory_tape_add_block (tape, block, data_read);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose (f);
|
||||
free (block);
|
||||
|
@ -4953,7 +4953,7 @@ else { /* Text file */
|
|||
1 - ansi->skip_lf_line_endings);
|
||||
/* max_record_size must fit in the 4-character ANSI RCW */
|
||||
if (max_record_size > 9999) {
|
||||
size_t max_allowed = 9999 - 4 -
|
||||
size_t max_allowed = 9999 - 4 -
|
||||
(crlf_line_endings ? 2 - ansi->skip_crlf_line_endings :
|
||||
1 - ansi->skip_lf_line_endings);
|
||||
sim_messagef (SCPE_ARG, "Text file: %s has lines longer (%d) than %s format allows (%d)\n",
|
||||
|
@ -5002,15 +5002,15 @@ while (!feof (f) && !error) {
|
|||
size_t data_read = tape->block_size;
|
||||
|
||||
if (lf_line_endings || crlf_line_endings) /* Text file? */
|
||||
ansi_fill_text_buffer (f, (char *)block, tape->block_size,
|
||||
crlf_line_endings ? ansi->skip_crlf_line_endings : ansi->skip_lf_line_endings,
|
||||
ansi_fill_text_buffer (f, (char *)block, tape->block_size,
|
||||
crlf_line_endings ? ansi->skip_crlf_line_endings : ansi->skip_lf_line_endings,
|
||||
ansi->fixed_text);
|
||||
|
||||
else { /* Binary file */
|
||||
size_t runt = 0;
|
||||
|
||||
data_read = fread (block, 1, tape->block_size, f);
|
||||
if (max_record_size > 0) /* always will be true but XCode thinks otherwise */
|
||||
if (max_record_size > 0) /* always will be true but Xcode thinks otherwise */
|
||||
runt = data_read % max_record_size; /* data_read (=0) % anypositivenumber == 0 */
|
||||
/* Pad short records with zeros */
|
||||
if (runt > 0) {
|
||||
|
@ -5049,7 +5049,7 @@ if (sim_switches & SWMASK ('V'))
|
|||
return error;
|
||||
}
|
||||
|
||||
static void sim_tape_add_ansi_entry (const char *directory,
|
||||
static void sim_tape_add_ansi_entry (const char *directory,
|
||||
const char *filename,
|
||||
t_offset FileSize,
|
||||
const struct stat *filestat,
|
||||
|
|
272
sim_timer.c
272
sim_timer.c
|
@ -32,23 +32,23 @@
|
|||
- Sleep for the observed clock tick size while throttling
|
||||
- Recompute the throttling wait once every 10 seconds
|
||||
to account for varying instruction mixes during
|
||||
different phases of a simulator execution or to
|
||||
accommodate the presence of other load on the host
|
||||
different phases of a simulator execution or to
|
||||
accommodate the presence of other load on the host
|
||||
system.
|
||||
- Each of the pre-existing throttling modes (Kcps,
|
||||
Mcps, and %) all compute the appropriate throttling
|
||||
- Each of the pre-existing throttling modes (Kcps,
|
||||
Mcps, and %) all compute the appropriate throttling
|
||||
interval dynamically. These dynamic computations
|
||||
assume that 100% of the host CPU is dedicated to
|
||||
assume that 100% of the host CPU is dedicated to
|
||||
the current simulator during this computation.
|
||||
This assumption may not always be true and under
|
||||
certain conditions may never provide a way to
|
||||
correctly determine the appropriate throttling
|
||||
This assumption may not always be true and under
|
||||
certain conditions may never provide a way to
|
||||
correctly determine the appropriate throttling
|
||||
wait. An additional throttling mode has been added
|
||||
which allows the simulator operator to explicitly
|
||||
state the desired throttling wait parameters.
|
||||
These are specified by:
|
||||
These are specified by:
|
||||
SET THROT insts/delay
|
||||
where 'insts' is the number of instructions to
|
||||
where 'insts' is the number of instructions to
|
||||
execute before sleeping for 'delay' milliseconds.
|
||||
22-Apr-11 MP Fixed Asynch I/O support to reasonably account cycles
|
||||
when an idle wait is terminated by an external event
|
||||
|
@ -286,8 +286,8 @@ return sim_os_sleep_min_ms;
|
|||
|
||||
#if defined(MS_MIN_GRANULARITY) && (MS_MIN_GRANULARITY != 1)
|
||||
|
||||
#define sim_idle_ms_sleep real_sim_idle_ms_sleep
|
||||
#define sim_os_msec real_sim_os_msec
|
||||
#define sim_idle_ms_sleep real_sim_idle_ms_sleep
|
||||
#define sim_os_msec real_sim_os_msec
|
||||
#define sim_os_ms_sleep real_sim_os_ms_sleep
|
||||
|
||||
#endif /* defined(MS_MIN_GRANULARITY) && (MS_MIN_GRANULARITY != 1) */
|
||||
|
@ -783,7 +783,7 @@ return sim_rtcn_init_unit_ticks (uptr, time, tmr, 0);
|
|||
int32 sim_rtcn_init_unit_ticks (UNIT *uptr, int32 time, int32 tmr, int32 ticksper)
|
||||
{
|
||||
RTC *rtc;
|
||||
|
||||
|
||||
if (time == 0)
|
||||
time = 1;
|
||||
if (tmr == SIM_INTERNAL_CLK)
|
||||
|
@ -864,8 +864,8 @@ if (rtc->hz != ticksper) { /* changing tick rate? */
|
|||
|
||||
if (rtc->hz == 0)
|
||||
rtc->clock_tick_start_time = sim_timenow_double ();
|
||||
if ((rtc->last_hz != 0) &&
|
||||
(rtc->last_hz != ticksper) &&
|
||||
if ((rtc->last_hz != 0) &&
|
||||
(rtc->last_hz != ticksper) &&
|
||||
(ticksper != 0))
|
||||
rtc->currd = (int32)(sim_timer_inst_per_sec () / ticksper);
|
||||
rtc->last_hz = rtc->hz;
|
||||
|
@ -912,9 +912,9 @@ if (sim_calb_tmr != tmr) {
|
|||
return rtc->currd;
|
||||
}
|
||||
new_rtime = sim_os_msec (); /* wall time */
|
||||
if (!sim_signaled_int_char &&
|
||||
if (!sim_signaled_int_char &&
|
||||
((new_rtime - sim_last_poll_kbd_time) > 500)) {
|
||||
sim_debug (DBG_CAL, &sim_timer_dev, "sim_rtcn_calb(tmr=%d) gratuitious keyboard poll after %d msecs\n", tmr, (int)(new_rtime - sim_last_poll_kbd_time));
|
||||
sim_debug (DBG_CAL, &sim_timer_dev, "sim_rtcn_calb(tmr=%d) gratuitous keyboard poll after %d msecs\n", tmr, (int)(new_rtime - sim_last_poll_kbd_time));
|
||||
(void)sim_poll_kbd ();
|
||||
}
|
||||
++rtc->calibrations; /* count calibrations */
|
||||
|
@ -989,7 +989,7 @@ if (sim_asynch_timer || (catchup_ticks_curr > 0)) {
|
|||
}
|
||||
rtc->based = rtc->currd = new_currd;
|
||||
rtc->gtime = new_gtime; /* save instruction time */
|
||||
sim_debug (DBG_CAL, &sim_timer_dev, "sim_rtcn_calb(%s tmr=%d, tickper=%d) catchups=%u, idle=%d%% result: %d\n",
|
||||
sim_debug (DBG_CAL, &sim_timer_dev, "sim_rtcn_calb(%s tmr=%d, tickper=%d) catchups=%u, idle=%d%% result: %d\n",
|
||||
sim_asynch_timer ? "asynch" : "catchup", tmr, ticksper, catchup_ticks_curr, last_idle_pct, rtc->currd);
|
||||
return rtc->currd; /* calibrated result */
|
||||
}
|
||||
|
@ -1016,7 +1016,7 @@ if (rtc->based <= 0) /* never negative or zero! *
|
|||
rtc->based = 1;
|
||||
if (rtc->currd <= 0) /* never negative or zero! */
|
||||
rtc->currd = 1;
|
||||
sim_debug (DBG_CAL, &sim_timer_dev, "sim_rtcn_calb(tmr=%d, tickper=%d) (delta_rtime=%d, delta_vtime=%d, base=%d, nxintv=%u, catchups=%u, idle=%d%%, result: %d)\n",
|
||||
sim_debug (DBG_CAL, &sim_timer_dev, "sim_rtcn_calb(tmr=%d, tickper=%d) (delta_rtime=%d, delta_vtime=%d, base=%d, nxintv=%u, catchups=%u, idle=%d%%, result: %d)\n",
|
||||
tmr, ticksper, (int)delta_rtime, (int)delta_vtime, rtc->based, rtc->nxintv, catchup_ticks_curr, last_idle_pct, rtc->currd);
|
||||
/* Adjust calibration for other timers which depend on this timer's calibration */
|
||||
for (itmr=0; itmr<=SIM_NTIMERS; itmr++) {
|
||||
|
@ -1025,7 +1025,7 @@ for (itmr=0; itmr<=SIM_NTIMERS; itmr++) {
|
|||
if ((itmr != tmr) && (irtc->hz != 0))
|
||||
irtc->currd = (rtc->currd * ticksper) / irtc->hz;
|
||||
}
|
||||
AIO_SET_INTERRUPT_LATENCY(rtc->currd * ticksper); /* set interrrupt latency */
|
||||
AIO_SET_INTERRUPT_LATENCY(rtc->currd * ticksper); /* set interrupt latency */
|
||||
return rtc->currd;
|
||||
}
|
||||
|
||||
|
@ -1077,7 +1077,7 @@ sim_stop_time = clock_last = clock_start = sim_os_msec ();
|
|||
sim_os_clock_resoluton_ms = 1000;
|
||||
do {
|
||||
uint32 clock_diff;
|
||||
|
||||
|
||||
clock_now = sim_os_msec ();
|
||||
clock_diff = clock_now - clock_last;
|
||||
if ((clock_diff > 0) && (clock_diff < sim_os_clock_resoluton_ms))
|
||||
|
@ -1127,8 +1127,8 @@ if (sim_idle_enab) {
|
|||
if (sim_throt_type != SIM_THROT_NONE) {
|
||||
sim_show_throt (st, NULL, uptr, val, desc);
|
||||
}
|
||||
fprintf (st, "Calibrated Timer: %s\n", (calb_tmr == -1) ? "Undetermined" :
|
||||
((calb_tmr == SIM_NTIMERS) ? "Internal Timer" :
|
||||
fprintf (st, "Calibrated Timer: %s\n", (calb_tmr == -1) ? "Undetermined" :
|
||||
((calb_tmr == SIM_NTIMERS) ? "Internal Timer" :
|
||||
(rtcs[calb_tmr].clock_unit ? sim_uname(rtcs[calb_tmr].clock_unit) : "")));
|
||||
if (calb_tmr == SIM_NTIMERS)
|
||||
fprintf (st, "Catchup Ticks: %s\n", sim_catchup_ticks ? "Enabled" : "Disabled");
|
||||
|
@ -1153,12 +1153,12 @@ for (tmr=clocks=0; tmr<=SIM_NTIMERS; ++tmr) {
|
|||
|
||||
if (0 == rtc->initd)
|
||||
continue;
|
||||
|
||||
|
||||
if (rtc->clock_unit) {
|
||||
++clocks;
|
||||
fprintf (st, "%s clock device is %s%s%s\n", sim_name,
|
||||
(tmr == SIM_NTIMERS) ? "Internal Calibrated Timer(" : "",
|
||||
sim_uname(rtc->clock_unit),
|
||||
fprintf (st, "%s clock device is %s%s%s\n", sim_name,
|
||||
(tmr == SIM_NTIMERS) ? "Internal Calibrated Timer(" : "",
|
||||
sim_uname(rtc->clock_unit),
|
||||
(tmr == SIM_NTIMERS) ? ")" : "");
|
||||
}
|
||||
|
||||
|
@ -1478,30 +1478,30 @@ return "Throttle facility";
|
|||
|
||||
|
||||
DEVICE sim_timer_dev = {
|
||||
"INT-CLOCK", sim_timer_units, sim_timer_reg, sim_timer_mod,
|
||||
SIM_NTIMERS+1, 0, 0, 0, 0, 0,
|
||||
NULL, NULL, &sim_timer_clock_reset, NULL, NULL, NULL,
|
||||
NULL, DEV_DEBUG | DEV_NOSAVE, 0,
|
||||
"INT-CLOCK", sim_timer_units, sim_timer_reg, sim_timer_mod,
|
||||
SIM_NTIMERS+1, 0, 0, 0, 0, 0,
|
||||
NULL, NULL, &sim_timer_clock_reset, NULL, NULL, NULL,
|
||||
NULL, DEV_DEBUG | DEV_NOSAVE, 0,
|
||||
sim_timer_debug};
|
||||
|
||||
DEVICE sim_int_timer_dev = {
|
||||
"INT-TIMER", &sim_internal_timer_unit, NULL, NULL,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
"INT-TIMER", &sim_internal_timer_unit, NULL, NULL,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, DEV_NOSAVE};
|
||||
|
||||
DEVICE sim_stop_dev = {
|
||||
"INT-STOP", &sim_stop_unit, NULL, NULL,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, DEV_NOSAVE, 0,
|
||||
"INT-STOP", &sim_stop_unit, NULL, NULL,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, DEV_NOSAVE, 0,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
sim_int_stop_description};
|
||||
|
||||
DEVICE sim_throttle_dev = {
|
||||
"INT-THROTTLE", &sim_throttle_unit, sim_throttle_reg, NULL,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, DEV_NOSAVE};
|
||||
|
||||
/* SET CLOCK command */
|
||||
|
@ -1569,35 +1569,35 @@ if ((!sim_idle_enab) || /* idling disabled */
|
|||
((sim_clock_queue != QUEUE_LIST_END) && /* or clock queue not empty */
|
||||
((sim_clock_queue->flags & UNIT_IDLE) == 0))|| /* and event not idle-able? */
|
||||
(rtc->elapsed < sim_idle_stable)) { /* or calibrated timer not stable? */
|
||||
sim_debug (DBG_IDL, &sim_timer_dev, "Can't idle: %s - elapsed: %d and %d/%d\n", !sim_idle_enab ? "idle disabled" :
|
||||
((rtc->elapsed < sim_idle_stable) ? "not stable" :
|
||||
((sim_clock_queue != QUEUE_LIST_END) ? sim_uname (sim_clock_queue) :
|
||||
sim_debug (DBG_IDL, &sim_timer_dev, "Can't idle: %s - elapsed: %d and %d/%d\n", !sim_idle_enab ? "idle disabled" :
|
||||
((rtc->elapsed < sim_idle_stable) ? "not stable" :
|
||||
((sim_clock_queue != QUEUE_LIST_END) ? sim_uname (sim_clock_queue) :
|
||||
"")), rtc->elapsed, rtc->ticks, rtc->hz);
|
||||
sim_interval -= sin_cyc;
|
||||
return FALSE;
|
||||
}
|
||||
/*
|
||||
When a simulator is in an instruction path (or under other conditions
|
||||
which would indicate idling), the countdown of sim_interval may not
|
||||
be happening at a pace which is consistent with the rate it happens
|
||||
when not in the 'idle capable' state. The consequence of this is that
|
||||
the clock calibration may produce calibrated results which vary much
|
||||
more than they do when not in the idle able state. Sim_idle also uses
|
||||
When a simulator is in an instruction path (or under other conditions
|
||||
which would indicate idling), the countdown of sim_interval may not
|
||||
be happening at a pace which is consistent with the rate it happens
|
||||
when not in the 'idle capable' state. The consequence of this is that
|
||||
the clock calibration may produce calibrated results which vary much
|
||||
more than they do when not in the idle able state. Sim_idle also uses
|
||||
the calibrated tick size to approximate an adjustment to sim_interval
|
||||
to reflect the number of instructions which would have executed during
|
||||
the actual idle time, so consistent calibrated numbers produce better
|
||||
adjustments.
|
||||
|
||||
to reflect the number of instructions which would have executed during
|
||||
the actual idle time, so consistent calibrated numbers produce better
|
||||
adjustments.
|
||||
|
||||
To negate this effect, we accumulate the time actually idled here.
|
||||
sim_rtcn_calb compares the accumulated idle time during the most recent
|
||||
sim_rtcn_calb compares the accumulated idle time during the most recent
|
||||
second and if it exceeds the percentage defined by sim_idle_calib_pct
|
||||
calibration is suppressed. Thus recalibration only happens if things
|
||||
calibration is suppressed. Thus recalibration only happens if things
|
||||
didn't idle too much.
|
||||
|
||||
we also check check sim_idle_enab above so that all simulators can avoid
|
||||
directly checking sim_idle_enab before calling sim_idle so that all of
|
||||
the bookkeeping on sim_idle_idled is done here in sim_timer where it
|
||||
means something, while not idling when it isn't enabled.
|
||||
directly checking sim_idle_enab before calling sim_idle so that all of
|
||||
the bookkeeping on sim_idle_idled is done here in sim_timer where it
|
||||
means something, while not idling when it isn't enabled.
|
||||
*/
|
||||
sim_debug (DBG_TRC, &sim_timer_dev, "sim_idle(tmr=%d, sin_cyc=%d)\n", tmr, sin_cyc);
|
||||
if (sim_idle_cyc_ms == 0) {
|
||||
|
@ -1641,7 +1641,7 @@ act_cyc = act_ms * sim_idle_cyc_ms;
|
|||
if (cyc_since_idle > sim_idle_cyc_sleep)
|
||||
act_cyc -= sim_idle_cyc_sleep / 2; /* account for half an interval's worth of cycles */
|
||||
else
|
||||
act_cyc -= (int32)cyc_since_idle; /* acount for cycles executed */
|
||||
act_cyc -= (int32)cyc_since_idle; /* account for cycles executed */
|
||||
sim_interval = sim_interval - act_cyc; /* count down sim_interval to reflect idle period */
|
||||
sim_idle_end_time = sim_gtime(); /* save idle completed time */
|
||||
if (sim_clock_queue == QUEUE_LIST_END)
|
||||
|
@ -1723,7 +1723,7 @@ else {
|
|||
if ((*tptr != '\0') || (val == 0))
|
||||
return sim_messagef (SCPE_ARG, "Invalid throttle delay specifier: %s\n", cptr);
|
||||
}
|
||||
if (c == 'M')
|
||||
if (c == 'M')
|
||||
sim_throt_type = SIM_THROT_MCYC;
|
||||
else if (c == 'K')
|
||||
sim_throt_type = SIM_THROT_KCYC;
|
||||
|
@ -1860,7 +1860,7 @@ switch (sim_throt_state) {
|
|||
}
|
||||
sim_debug (DBG_THR, &sim_timer_dev, "sim_throt_svc(INIT) Computing Throttling values based on the last second's execution rate\n");
|
||||
sim_throt_state = SIM_THROT_STATE_TIME;
|
||||
if (sim_throt_peak_cps < (double)(rtc->hz * rtc->currd))
|
||||
if (sim_throt_peak_cps < (double)(rtc->hz * rtc->currd))
|
||||
sim_throt_peak_cps = (double)rtc->hz * rtc->currd;
|
||||
return sim_throt_svc (uptr);
|
||||
}
|
||||
|
@ -1902,11 +1902,11 @@ switch (sim_throt_state) {
|
|||
sim_set_throt (0, NULL); /* disable throttling */
|
||||
return SCPE_OK;
|
||||
}
|
||||
sim_debug (DBG_THR, &sim_timer_dev, "sim_throt_svc() Not enough time. %d ms executing %.f %s.\n",
|
||||
sim_debug (DBG_THR, &sim_timer_dev, "sim_throt_svc() Not enough time. %d ms executing %.f %s.\n",
|
||||
(int)delta_ms, delta_inst, sim_vm_interval_units);
|
||||
sim_throt_wait = (int32)(delta_inst * SIM_THROT_WMUL);
|
||||
sim_throt_inst_start = sim_gtime();
|
||||
sim_idle_ms_sleep (sim_idle_rate_ms); /* start on a tick boundart to calibrate */
|
||||
sim_idle_ms_sleep (sim_idle_rate_ms); /* start on a tick boundary to calibrate */
|
||||
sim_throt_ms_start = sim_os_msec ();
|
||||
}
|
||||
else { /* long enough */
|
||||
|
@ -1920,11 +1920,11 @@ switch (sim_throt_state) {
|
|||
d_cps = (sim_throt_peak_cps * sim_throt_val) / 100.0;
|
||||
if (d_cps >= a_cps) {
|
||||
/* the initial throttling calibration measures a slower cps rate than the desired cps rate, */
|
||||
sim_debug (DBG_THR, &sim_timer_dev, "sim_throt_svc() CPU too slow. Values a_cps = %f, d_cps = %f\n",
|
||||
sim_debug (DBG_THR, &sim_timer_dev, "sim_throt_svc() CPU too slow. Values a_cps = %f, d_cps = %f\n",
|
||||
a_cps, d_cps);
|
||||
/* if the measured rate is well below the measured peak rate? */
|
||||
if (sim_throt_peak_cps >= (2.0 * d_cps)) {
|
||||
/* distrust the measured rate and instead use half the peak rate as measured
|
||||
/* distrust the measured rate and instead use half the peak rate as measured
|
||||
cps rate. */
|
||||
sim_printf ("*********** WARNING ***********\n");
|
||||
sim_printf ("Host CPU could be too slow to simulate %s %s per second\n", sim_fmt_numeric(d_cps), sim_vm_interval_units);
|
||||
|
@ -1953,13 +1953,13 @@ switch (sim_throt_state) {
|
|||
if (sim_throt_wait >= SIM_THROT_WMIN) /* long enough? */
|
||||
break;
|
||||
sim_throt_sleep_time += sim_os_sleep_inc_ms;
|
||||
sim_debug (DBG_THR, &sim_timer_dev, "sim_throt_svc() Wait too small, increasing sleep time to %d ms. Values a_cps = %f, d_cps = %f, wait = %d\n",
|
||||
sim_debug (DBG_THR, &sim_timer_dev, "sim_throt_svc() Wait too small, increasing sleep time to %d ms. Values a_cps = %f, d_cps = %f, wait = %d\n",
|
||||
sim_throt_sleep_time, a_cps, d_cps, sim_throt_wait);
|
||||
}
|
||||
sim_throt_ms_start = sim_throt_ms_stop;
|
||||
sim_throt_inst_start = sim_gtime();
|
||||
sim_throt_state = SIM_THROT_STATE_THROTTLE;
|
||||
sim_debug (DBG_THR, &sim_timer_dev, "sim_throt_svc() Throttle values a_cps = %f, d_cps = %f, wait = %d, sleep = %d ms\n",
|
||||
sim_debug (DBG_THR, &sim_timer_dev, "sim_throt_svc() Throttle values a_cps = %f, d_cps = %f, wait = %d, sleep = %d ms\n",
|
||||
a_cps, d_cps, sim_throt_wait, sim_throt_sleep_time);
|
||||
sim_throt_cps = d_cps; /* save the desired rate */
|
||||
_sim_timer_adjust_cal(); /* adjust timer calibrations */
|
||||
|
@ -1982,11 +1982,11 @@ switch (sim_throt_state) {
|
|||
else
|
||||
d_cps = (sim_throt_peak_cps * sim_throt_val) / 100.0;
|
||||
if (fabs(100.0 * (d_cps - a_cps) / d_cps) > (double)sim_throt_drift_pct) {
|
||||
sim_debug (DBG_THR, &sim_timer_dev, "sim_throt_svc() Recalibrating throttle based on values a_cps = %f, d_cps = %f deviating by %.2f%% from the desired value\n",
|
||||
sim_debug (DBG_THR, &sim_timer_dev, "sim_throt_svc() Recalibrating throttle based on values a_cps = %f, d_cps = %f deviating by %.2f%% from the desired value\n",
|
||||
a_cps, d_cps, fabs(100.0 * (d_cps - a_cps) / d_cps));
|
||||
if ((a_cps > d_cps) && /* too fast? */
|
||||
((100.0 * (a_cps - d_cps) / d_cps) > (100 - sim_throt_drift_pct))) {
|
||||
sim_debug (DBG_THR, &sim_timer_dev, "sim_throt_svc() Restarting calibrating throttle going too fast: a_cps = %f, d_cps = %f deviating by %.2f%% from the desired value\n",
|
||||
sim_debug (DBG_THR, &sim_timer_dev, "sim_throt_svc() Restarting calibrating throttle going too fast: a_cps = %f, d_cps = %f deviating by %.2f%% from the desired value\n",
|
||||
a_cps, d_cps, fabs(100.0 * (d_cps - a_cps) / d_cps));
|
||||
while (1) {
|
||||
sim_throt_wait = (int32) /* cycles between sleeps */
|
||||
|
@ -1995,16 +1995,16 @@ switch (sim_throt_state) {
|
|||
if (sim_throt_wait >= SIM_THROT_WMIN)/* long enough? */
|
||||
break;
|
||||
sim_throt_sleep_time += sim_os_sleep_inc_ms;
|
||||
sim_debug (DBG_THR, &sim_timer_dev, "sim_throt_svc() Wait too small, increasing sleep time to %d ms. Values a_cps = %f, d_cps = %f, wait = %d\n",
|
||||
sim_debug (DBG_THR, &sim_timer_dev, "sim_throt_svc() Wait too small, increasing sleep time to %d ms. Values a_cps = %f, d_cps = %f, wait = %d\n",
|
||||
sim_throt_sleep_time, sim_throt_peak_cps, d_cps, sim_throt_wait);
|
||||
}
|
||||
}
|
||||
else { /* slow or within reasonable range */
|
||||
sim_debug (DBG_THR, &sim_timer_dev, "sim_throt_svc() Adjusting wait before sleep interval by %d\n",
|
||||
sim_debug (DBG_THR, &sim_timer_dev, "sim_throt_svc() Adjusting wait before sleep interval by %d\n",
|
||||
(int32)(((d_cps - a_cps) * (double)sim_throt_wait) / d_cps));
|
||||
sim_throt_wait += (int32)(((d_cps - a_cps) * (double)sim_throt_wait) / d_cps);
|
||||
}
|
||||
sim_debug (DBG_THR, &sim_timer_dev, "sim_throt_svc() Throttle values a_cps = %f, d_cps = %f, wait = %d, sleep = %d ms\n",
|
||||
sim_debug (DBG_THR, &sim_timer_dev, "sim_throt_svc() Throttle values a_cps = %f, d_cps = %f, wait = %d, sleep = %d ms\n",
|
||||
a_cps, d_cps, sim_throt_wait, sim_throt_sleep_time);
|
||||
sim_throt_cps = d_cps; /* save the desired rate */
|
||||
sim_throt_ms_start = sim_os_msec ();
|
||||
|
@ -2013,7 +2013,7 @@ switch (sim_throt_state) {
|
|||
}
|
||||
else { /* record instruction rate */
|
||||
sim_throt_cps = (int32)a_cps;
|
||||
sim_debug (DBG_THR, &sim_timer_dev, "sim_throt_svc() Recalibrating Special %d/%u Cycles Per Second of %f\n",
|
||||
sim_debug (DBG_THR, &sim_timer_dev, "sim_throt_svc() Recalibrating Special %d/%u Cycles Per Second of %f\n",
|
||||
sim_throt_wait, sim_throt_sleep_time, sim_throt_cps);
|
||||
sim_throt_inst_start = sim_gtime();
|
||||
sim_throt_ms_start = sim_os_msec ();
|
||||
|
@ -2050,7 +2050,7 @@ static void _sim_timer_adjust_cal(void)
|
|||
}
|
||||
}
|
||||
|
||||
/* Clock assist activites */
|
||||
/* Clock assist activities */
|
||||
t_stat sim_timer_tick_svc (UNIT *uptr)
|
||||
{
|
||||
int32 tmr = (int32)(uptr-sim_timer_units);
|
||||
|
@ -2060,11 +2060,11 @@ RTC *rtc = &rtcs[tmr];
|
|||
rtc->clock_ticks += 1;
|
||||
rtc->calib_tick_time += rtc->clock_tick_size;
|
||||
/*
|
||||
* Some devices may depend on executing during the same instruction or
|
||||
* immediately after the clock tick event. To satisfy this, we directly
|
||||
* Some devices may depend on executing during the same instruction or
|
||||
* immediately after the clock tick event. To satisfy this, we directly
|
||||
* run the clock event here and if it completes successfully, schedule any
|
||||
* currently coschedule units to run now. Ticks should never return a
|
||||
* non-success status, while co-schedule activities might, so they are
|
||||
* currently coschedule units to run now. Ticks should never return a
|
||||
* non-success status, while co-schedule activities might, so they are
|
||||
* queued to run from sim_process_event
|
||||
*/
|
||||
sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_tick_svc(tmr=%d) - scheduling %s - cosched interval: %d\n", tmr, sim_uname (rtc->clock_unit), rtc->cosched_interval);
|
||||
|
@ -2074,7 +2074,7 @@ stat = rtc->clock_unit->action (rtc->clock_unit);
|
|||
--rtc->cosched_interval; /* Countdown ticks */
|
||||
if (rtc->clock_cosched_queue != QUEUE_LIST_END)
|
||||
rtc->clock_cosched_queue->time = rtc->cosched_interval;
|
||||
if ((stat == SCPE_OK) &&
|
||||
if ((stat == SCPE_OK) &&
|
||||
(rtc->cosched_interval <= 0) &&
|
||||
(rtc->clock_cosched_queue != QUEUE_LIST_END)) {
|
||||
UNIT *sptr = rtc->clock_cosched_queue;
|
||||
|
@ -2150,7 +2150,7 @@ if (now)
|
|||
return ts_now.tv_sec;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* If the host system has a relatively large clock tick (as compared to
|
||||
* the desired simulated hz) ticks will naturally be scheduled late and
|
||||
* these delays will accumulate. The net result will be unreasonably
|
||||
|
@ -2163,15 +2163,15 @@ return ts_now.tv_sec;
|
|||
* We accomodate these problems and make up for lost ticks by injecting
|
||||
* catch-up ticks to the simulator.
|
||||
*
|
||||
* When necessary, catch-up ticks are scheduled to run under one
|
||||
* When necessary, catch-up ticks are scheduled to run under one
|
||||
* of two conditions:
|
||||
* 1) after indicated number of instructions in a call by the simulator
|
||||
* to sim_rtcn_tick_ack. sim_rtcn_tick_ack exists to provide a
|
||||
* mechanism to inform the simh timer facilities when the simulated
|
||||
* to sim_rtcn_tick_ack. sim_rtcn_tick_ack exists to provide a
|
||||
* mechanism to inform the simh timer facilities when the simulated
|
||||
* system has accepted the most recent clock tick interrupt.
|
||||
* 2) immediately when the simulator calls sim_idle
|
||||
*
|
||||
* catchup ticks are only scheduled (eligible to happen) under these
|
||||
* catchup ticks are only scheduled (eligible to happen) under these
|
||||
* conditions after at least one tick has been acknowledged.
|
||||
*
|
||||
* The clock tick UNIT that will be scheduled to run for catchup ticks
|
||||
|
@ -2229,7 +2229,7 @@ if ((!rtc->clock_catchup_eligible) && /* not eligible yet? */
|
|||
sim_debug (DBG_QUE, &sim_timer_dev, "_rtcn_tick_catchup_check() - Enabling catchup ticks for %s\n", sim_uname (rtc->clock_unit));
|
||||
bReturn = TRUE;
|
||||
}
|
||||
if ((rtc->hz > 0) &&
|
||||
if ((rtc->hz > 0) &&
|
||||
rtc->clock_catchup_eligible)
|
||||
{
|
||||
double tnow = sim_timenow_double();
|
||||
|
@ -2295,8 +2295,8 @@ _timer_thread(void *arg)
|
|||
int sched_policy;
|
||||
struct sched_param sched_priority;
|
||||
|
||||
/* Boost Priority for this I/O thread vs the CPU instruction execution
|
||||
thread which, in general, won't be readily yielding the processor when
|
||||
/* Boost Priority for this I/O thread vs the CPU instruction execution
|
||||
thread which, in general, won't be readily yielding the processor when
|
||||
this thread needs to run */
|
||||
pthread_getschedparam (pthread_self(), &sched_policy, &sched_priority);
|
||||
++sched_priority.sched_priority;
|
||||
|
@ -2317,7 +2317,7 @@ while (sim_asynch_timer && sim_is_running) {
|
|||
|
||||
if (sim_wallclock_entry) { /* something to insert in queue? */
|
||||
|
||||
sim_debug (DBG_TIM, &sim_timer_dev, "_timer_thread() - timing %s for %s\n",
|
||||
sim_debug (DBG_TIM, &sim_timer_dev, "_timer_thread() - timing %s for %s\n",
|
||||
sim_uname(sim_wallclock_entry), sim_fmt_secs (sim_wallclock_entry->a_usec_delay/1000000.0));
|
||||
|
||||
uptr = sim_wallclock_entry;
|
||||
|
@ -2356,7 +2356,7 @@ while (sim_asynch_timer && sim_is_running) {
|
|||
sim_debug (DBG_TIM, &sim_timer_dev, "_timer_thread() - waiting forever\n");
|
||||
else
|
||||
sim_debug (DBG_TIM, &sim_timer_dev, "_timer_thread() - waiting for %.0f usecs until %.6f for %s\n", wait_usec, sim_wallclock_queue->a_due_time, sim_uname(sim_wallclock_queue));
|
||||
if ((wait_usec <= 0.0) ||
|
||||
if ((wait_usec <= 0.0) ||
|
||||
(0 != pthread_cond_timedwait (&sim_timer_wake, &sim_timer_lock, &due_time))) {
|
||||
|
||||
if (sim_wallclock_queue == QUEUE_LIST_END) /* queue empty? */
|
||||
|
@ -2372,7 +2372,7 @@ while (sim_asynch_timer && sim_is_running) {
|
|||
inst_delay = 0;
|
||||
else
|
||||
inst_delay = (int32)(inst_per_sec*(_timespec_to_double(&due_time)-_timespec_to_double(&stop_time)));
|
||||
sim_debug (DBG_TIM, &sim_timer_dev, "_timer_thread() - slept %.0fms - activating(%s,%d)\n",
|
||||
sim_debug (DBG_TIM, &sim_timer_dev, "_timer_thread() - slept %.0fms - activating(%s,%d)\n",
|
||||
1000.0*(_timespec_to_double (&stop_time)-_timespec_to_double (&start_time)), sim_uname(uptr), inst_delay);
|
||||
sim_activate (uptr, inst_delay);
|
||||
}
|
||||
|
@ -2390,17 +2390,17 @@ return NULL;
|
|||
#endif /* defined(SIM_ASYNCH_CLOCKS) */
|
||||
|
||||
/*
|
||||
In the event that there are no active calibrated clock devices,
|
||||
no instruction rate calibration will be performed. This is more
|
||||
likely on simpler simulators which don't have a full spectrum of
|
||||
standard devices or possibly when a clock device exists but its
|
||||
In the event that there are no active calibrated clock devices,
|
||||
no instruction rate calibration will be performed. This is more
|
||||
likely on simpler simulators which don't have a full spectrum of
|
||||
standard devices or possibly when a clock device exists but its
|
||||
use is optional.
|
||||
|
||||
Additonally, when a host system has a natural clock tick (
|
||||
or minimal sleep time) which is greater than the tick size that
|
||||
a simulator wants to run a clock at, we run this clock at the
|
||||
Additionally, when a host system has a natural clock tick (
|
||||
or minimal sleep time) which is greater than the tick size that
|
||||
a simulator wants to run a clock at, we run this clock at the
|
||||
rate implied by the host system's minimal sleep time or 50Hz.
|
||||
|
||||
|
||||
To solve this we merely run an internal clock at 100Hz.
|
||||
*/
|
||||
|
||||
|
@ -2412,22 +2412,22 @@ sim_activate_after (uptr, 1000000/sim_int_clk_tps); /* reactivate unit */
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
This routine exists to assure that there is a single reliably calibrated
|
||||
clock properly counting instruction execution relative to time. The best
|
||||
way to assure reliable calibration is to use a clock which ticks no
|
||||
faster than the host system's clock. This is optimal so that accurate
|
||||
time measurements are taken. If the simulated system doesn't have a
|
||||
clock with an appropriate tick rate, an internal clock is run that meets
|
||||
/*
|
||||
This routine exists to assure that there is a single reliably calibrated
|
||||
clock properly counting instruction execution relative to time. The best
|
||||
way to assure reliable calibration is to use a clock which ticks no
|
||||
faster than the host system's clock. This is optimal so that accurate
|
||||
time measurements are taken. If the simulated system doesn't have a
|
||||
clock with an appropriate tick rate, an internal clock is run that meets
|
||||
this requirement, OR when asynch clocks are enabled, the internal clock
|
||||
is always run.
|
||||
|
||||
Some simulators have clocks that have dynamically programmable tick
|
||||
rates. Such a clock is only a reliable candidate to be the calibrated
|
||||
clock if it uses a single tick rate rather than changing the tick rate
|
||||
Some simulators have clocks that have dynamically programmable tick
|
||||
rates. Such a clock is only a reliable candidate to be the calibrated
|
||||
clock if it uses a single tick rate rather than changing the tick rate
|
||||
on the fly. Generally most systems like this, under normal conditions
|
||||
don't change their tick rates unless they're running something that is
|
||||
examining the behavior of the clock system (like a diagnostic). Under
|
||||
examining the behavior of the clock system (like a diagnostic). Under
|
||||
these conditions this clock is removed from the potential selection as
|
||||
"the" calibrated clock all others are relative to and if necessary, an
|
||||
internal calibrated clock is selected.
|
||||
|
@ -2486,7 +2486,7 @@ if (tmr == SIM_NTIMERS) { /* None found? */
|
|||
}
|
||||
return;
|
||||
}
|
||||
if ((tmr == newtmr) &&
|
||||
if ((tmr == newtmr) &&
|
||||
(sim_calb_tmr == newtmr)) /* already set? */
|
||||
return;
|
||||
if (sim_calb_tmr == SIM_NTIMERS) { /* was old the internal timer? */
|
||||
|
@ -2567,7 +2567,7 @@ if (sim_calb_tmr == -1) {
|
|||
}
|
||||
else {
|
||||
if (sim_calb_tmr == SIM_NTIMERS) {
|
||||
sim_debug (DBG_CAL, &sim_timer_dev, "sim_start_timer_services() - restarting internal timer after %d %s\n",
|
||||
sim_debug (DBG_CAL, &sim_timer_dev, "sim_start_timer_services() - restarting internal timer after %d %s\n",
|
||||
sim_internal_timer_time, sim_vm_interval_units);
|
||||
sim_activate (&SIM_INTERNAL_UNIT, sim_internal_timer_time);
|
||||
}
|
||||
|
@ -2730,7 +2730,7 @@ for (tmr=0; tmr<=SIM_NTIMERS; tmr++) {
|
|||
if (sim_is_active (uptr)) /* already active? */
|
||||
return SCPE_OK;
|
||||
if (usec_delay < 0.0) {
|
||||
sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - surprising usec value\n",
|
||||
sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - surprising usec value\n",
|
||||
sim_uname(uptr), usec_delay);
|
||||
}
|
||||
if ((sim_is_running) || (tmr <= SIM_NTIMERS))
|
||||
|
@ -2739,7 +2739,7 @@ else { /* defer non timer wallclock activat
|
|||
uptr->usecs_remaining = usec_delay;
|
||||
usec_delay = 0;
|
||||
}
|
||||
/*
|
||||
/*
|
||||
* Handle long delays by aligning with the calibrated timer's calibration
|
||||
* activities. Delays which would expire prior to the next calibration
|
||||
* are specifically scheduled directly based on the the current instruction
|
||||
|
@ -2769,9 +2769,9 @@ if (sim_calb_tmr != -1) {
|
|||
if (inst_delay_d > (double)inst_til_calib) { /* long wait? */
|
||||
stat = sim_clock_coschedule_tmr (uptr, sim_calb_tmr, ticks_til_calib - 1);
|
||||
uptr->usecs_remaining = (stat == SCPE_OK) ? usec_delay - usecs_til_calib : 0.0;
|
||||
sim_debug (DBG_TIM, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - coscheduling with with calibrated timer(%d), ticks=%d, usecs_remaining=%.0f usecs, inst_til_tick=%d, ticks_til_calib=%d, usecs_til_calib=%u\n",
|
||||
sim_debug (DBG_TIM, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - coscheduling with with calibrated timer(%d), ticks=%d, usecs_remaining=%.0f usecs, inst_til_tick=%d, ticks_til_calib=%d, usecs_til_calib=%u\n",
|
||||
sim_uname(uptr), usec_delay, sim_calb_tmr, ticks_til_calib, uptr->usecs_remaining, inst_til_tick, ticks_til_calib, usecs_til_calib);
|
||||
sim_debug (DBG_CHK, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - result = %.0f usecs, %.0f usecs\n",
|
||||
sim_debug (DBG_CHK, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - result = %.0f usecs, %.0f usecs\n",
|
||||
sim_uname(uptr), usec_delay, sim_timer_activate_time_usecs (ouptr), sim_timer_activate_time_usecs (uptr));
|
||||
return stat;
|
||||
}
|
||||
|
@ -2781,16 +2781,16 @@ if (sim_calb_tmr != -1) {
|
|||
|
||||
stat = sim_clock_coschedule_tmr (uptr, sim_calb_tmr, 0);
|
||||
uptr->usecs_remaining = (stat == SCPE_OK) ? usec_delay - usecs_til_tick : 0.0;
|
||||
sim_debug (DBG_TIM, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - coscheduling with with calibrated timer(%d), ticks=%d, usecs_remaining=%.0f usecs, inst_til_tick=%d, usecs_til_tick=%.0f\n",
|
||||
sim_debug (DBG_TIM, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - coscheduling with with calibrated timer(%d), ticks=%d, usecs_remaining=%.0f usecs, inst_til_tick=%d, usecs_til_tick=%.0f\n",
|
||||
sim_uname(uptr), usec_delay, sim_calb_tmr, 0, uptr->usecs_remaining, inst_til_tick, usecs_til_tick);
|
||||
sim_debug (DBG_CHK, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - result = %.0f usecs, %.0f usecs\n",
|
||||
sim_debug (DBG_CHK, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - result = %.0f usecs, %.0f usecs\n",
|
||||
sim_uname(uptr), usec_delay, sim_timer_activate_time_usecs (ouptr), sim_timer_activate_time_usecs (uptr));
|
||||
return stat;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
/*
|
||||
* We're here to schedule if:
|
||||
* No Calibrated Timer, OR
|
||||
* Scheduling the Calibrated Timer OR
|
||||
|
@ -2798,8 +2798,8 @@ if (sim_calb_tmr != -1) {
|
|||
*/
|
||||
/*
|
||||
* Bound delay to avoid overflow.
|
||||
* Long delays are usually canceled before they expire, however bounding the
|
||||
* delay will cause sim_activate_time to return inconsistent results when
|
||||
* Long delays are usually canceled before they expire, however bounding the
|
||||
* delay will cause sim_activate_time to return inconsistent results when
|
||||
* truncation has happened.
|
||||
*/
|
||||
if (inst_delay_d > (double)0x7fffffff)
|
||||
|
@ -2823,7 +2823,7 @@ if ((sim_asynch_timer) &&
|
|||
rtc->clock_unit->a_is_active = &_sim_wallclock_is_active;
|
||||
}
|
||||
|
||||
sim_debug (DBG_TIM, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - queueing wallclock addition at %.6f\n",
|
||||
sim_debug (DBG_TIM, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - queueing wallclock addition at %.6f\n",
|
||||
sim_uname(uptr), usec_delay, uptr->a_due_time);
|
||||
|
||||
pthread_mutex_lock (&sim_timer_lock);
|
||||
|
@ -2836,7 +2836,7 @@ if ((sim_asynch_timer) &&
|
|||
uptr->a_next = QUEUE_LIST_END; /* Temporarily mark as active */
|
||||
if (sim_timer_thread_running) {
|
||||
while (sim_wallclock_entry) { /* wait for any prior entry has been digested */
|
||||
sim_debug (DBG_TIM, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - queue insert entry %s busy waiting for 1ms\n",
|
||||
sim_debug (DBG_TIM, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - queue insert entry %s busy waiting for 1ms\n",
|
||||
sim_uname(uptr), usec_delay, sim_uname(sim_wallclock_entry));
|
||||
pthread_mutex_unlock (&sim_timer_lock);
|
||||
sim_os_ms_sleep (1);
|
||||
|
@ -2857,9 +2857,9 @@ if ((sim_asynch_timer) &&
|
|||
}
|
||||
#endif
|
||||
stat = _sim_activate (uptr, inst_delay); /* queue it now */
|
||||
sim_debug (DBG_TIM, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - queue addition at %d - remnant: %.0f\n",
|
||||
sim_debug (DBG_TIM, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - queue addition at %d - remnant: %.0f\n",
|
||||
sim_uname(uptr), usec_delay, inst_delay, uptr->usecs_remaining);
|
||||
sim_debug (DBG_CHK, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - result = %.0f usecs, %.0f usecs\n",
|
||||
sim_debug (DBG_CHK, &sim_timer_dev, "sim_timer_activate_after(%s, %.0f usecs) - result = %.0f usecs, %.0f usecs\n",
|
||||
sim_uname(uptr), usec_delay, sim_timer_activate_time_usecs (ouptr), sim_timer_activate_time_usecs (uptr));
|
||||
return stat;
|
||||
}
|
||||
|
@ -2900,7 +2900,7 @@ if (rtc->clock_unit == NULL)
|
|||
rtc->clock_cosched_queue = QUEUE_LIST_END;
|
||||
rtc->clock_unit = uptr;
|
||||
uptr->dynflags |= UNIT_TMR_UNIT;
|
||||
rtc->timer_unit->flags = ((tmr == SIM_NTIMERS) ? 0 : UNIT_DIS) |
|
||||
rtc->timer_unit->flags = ((tmr == SIM_NTIMERS) ? 0 : UNIT_DIS) |
|
||||
(rtc->clock_unit ? UNIT_IDLE : 0);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -3213,7 +3213,7 @@ for (tmr=0; tmr<=SIM_NTIMERS; tmr++) {
|
|||
return _sim_activate_time (&sim_timer_units[tmr]);
|
||||
}
|
||||
}
|
||||
return -1; /* Not found. */
|
||||
return -1; /* Not found. */
|
||||
}
|
||||
|
||||
double sim_timer_activate_time_usecs (UNIT *uptr)
|
||||
|
@ -3305,7 +3305,7 @@ for (tmr=0; tmr<=SIM_NTIMERS; tmr++) {
|
|||
}
|
||||
result = uptr->usecs_remaining + (1000000.0 * (sim_activate_time (uptr) - 1)) / sim_timer_inst_per_sec ();
|
||||
sim_debug (DBG_QUE, &sim_timer_dev, "sim_timer_activate_time_usecs(%s) clock - %.0f usecs, inst_per_sec=%.0f, usecs_remaining=%.0f\n", sim_uname (uptr), result, sim_timer_inst_per_sec (), uptr->usecs_remaining);
|
||||
return result; /* Not found. */
|
||||
return result; /* Not found. */
|
||||
}
|
||||
|
||||
/* read only memory delayed support
|
||||
|
@ -3314,10 +3314,10 @@ return result; /* Not found. */
|
|||
time to meet timing assumptions in the code being executed.
|
||||
|
||||
The default calibration determines a way to limit activities
|
||||
to 1Mhz for each call to sim_rom_read_with_delay(). If a
|
||||
simulator needs a different delay factor, the 1 Mhz initial
|
||||
value can be queried with sim_get_rom_delay_factor() and the
|
||||
result can be adjusted as nessary and the operating delay
|
||||
to 1Mhz for each call to sim_rom_read_with_delay(). If a
|
||||
simulator needs a different delay factor, the 1 MHz initial
|
||||
value can be queried with sim_get_rom_delay_factor() and the
|
||||
result can be adjusted as necessary and the operating delay
|
||||
can be set with sim_set_rom_delay_factor().
|
||||
*/
|
||||
|
||||
|
@ -3341,7 +3341,7 @@ return val + rom_loopval;
|
|||
SIM_NOINLINE uint32 sim_get_rom_delay_factor (void)
|
||||
{
|
||||
/* Calibrate the loop delay factor at startup.
|
||||
Do this 4 times and use the largest value computed.
|
||||
Do this 4 times and use the largest value computed.
|
||||
The goal here is to come up with a delay factor which will throttle
|
||||
a 6 byte delay loop running from ROM address space to execute
|
||||
1 instruction per usec */
|
||||
|
@ -3361,7 +3361,7 @@ if (sim_rom_delay == 0) {
|
|||
|
||||
for (i = 0; i < c; i++)
|
||||
rom_loopval |= (rom_loopval + ts) ^ _rom_swapb (_rom_swapb (rom_loopval + ts));
|
||||
te = sim_os_msec ();
|
||||
te = sim_os_msec ();
|
||||
if ((te - ts) < 50) /* sample big enough? */
|
||||
continue;
|
||||
if (sim_rom_delay < (rom_loopval + (c / (te - ts) / 1000) + 1))
|
||||
|
@ -3385,9 +3385,9 @@ sim_rom_delay = delay;
|
|||
*
|
||||
* The point of this routine is to run a bunch of simulator provided
|
||||
* instructions that don't do anything, but run in an effective loop.
|
||||
* That loop is run for some 5 million instructions and based on
|
||||
* That loop is run for some 5 million instructions and based on
|
||||
* the time those 5 million instructions take to execute the effective
|
||||
* execution rate. That rate is used to avoid the initial 3 to 5
|
||||
* execution rate. That rate is used to avoid the initial 3 to 5
|
||||
* seconds that normal clock calibration takes.
|
||||
*
|
||||
*/
|
||||
|
@ -3434,7 +3434,7 @@ sim_inst_per_sec_last = sim_precalibrate_ips;
|
|||
sim_idle_stable = 0;
|
||||
}
|
||||
|
||||
double
|
||||
double
|
||||
sim_host_speed_factor (void)
|
||||
{
|
||||
if (sim_precalibrate_ips > sim_vm_initial_ips)
|
||||
|
|
504
sim_tmxr.c
504
sim_tmxr.c
File diff suppressed because it is too large
Load diff
|
@ -26,7 +26,7 @@
|
|||
Based on the original DZ11 simulator by Thord Nilson, as updated by
|
||||
Arthur Krewat.
|
||||
|
||||
10-Oct-12 MP Added extended attach support for serial, per line
|
||||
10-Oct-12 MP Added extended attach support for serial, per line
|
||||
listener and outgoing connections
|
||||
17-Jan-11 MP Added buffered line capabilities
|
||||
20-Nov-08 RMS Added three new standardized SHOW routines
|
||||
|
@ -96,7 +96,7 @@ typedef struct SERPORT *SERHANDLE;
|
|||
#define TMUF_NOASYNCH (1u << TMUF_V_NOASYNCH) /* This flag can be defined */
|
||||
/* statically in a unit's flag field */
|
||||
/* This will disable the unit from */
|
||||
/* supporting asynchronmous mux behaviors */
|
||||
/* supporting asynchronous mux behaviors */
|
||||
/* Receive line speed limits */
|
||||
|
||||
#define TMLN_SPD_50_BPS 200000 /* usec per character */
|
||||
|
@ -125,7 +125,7 @@ typedef struct SERPORT *SERHANDLE;
|
|||
#define TMLN_SPD_115200_BPS 86 /* usec per character */
|
||||
|
||||
/* Internal struct */
|
||||
struct framer_data;
|
||||
struct framer_data;
|
||||
|
||||
typedef struct tmln TMLN;
|
||||
typedef struct tmxr TMXR;
|
||||
|
@ -356,7 +356,7 @@ t_stat tmxr_add_debug (DEVICE *dptr);
|
|||
#define sim_activate_abs tmxr_activate_abs
|
||||
#define sim_activate_after tmxr_activate_after
|
||||
#define sim_activate_after_abs tmxr_activate_after_abs
|
||||
#define sim_clock_coschedule tmxr_clock_coschedule
|
||||
#define sim_clock_coschedule tmxr_clock_coschedule
|
||||
#define sim_clock_coschedule_abs tmxr_clock_coschedule_abs
|
||||
#define sim_clock_coschedule_tmr tmxr_clock_coschedule_tmr
|
||||
#define sim_clock_coschedule_tmr_abs tmxr_clock_coschedule_tmr_abs
|
||||
|
|
94
sim_video.c
94
sim_video.c
|
@ -104,20 +104,20 @@ char vid_release_key[64] = "Ctrl-Right-Shift";
|
|||
#include <SDL.h>
|
||||
#include <SDL_thread.h>
|
||||
|
||||
static const char *key_names[] =
|
||||
{"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12",
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
|
||||
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
|
||||
"K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
|
||||
"U", "V", "W", "X", "Y", "Z",
|
||||
"BACKQUOTE", "MINUS", "EQUALS", "LEFT_BRACKET", "RIGHT_BRACKET",
|
||||
"SEMICOLON", "SINGLE_QUOTE", "BACKSLASH", "LEFT_BACKSLASH", "COMMA",
|
||||
"PERIOD", "SLASH", "PRINT", "SCRL_LOCK", "PAUSE", "ESC", "BACKSPACE",
|
||||
"TAB", "ENTER", "SPACE", "INSERT", "DELETE", "HOME", "END", "PAGE_UP",
|
||||
"PAGE_DOWN", "UP", "DOWN", "LEFT", "RIGHT", "CAPS_LOCK", "NUM_LOCK",
|
||||
"ALT_L", "ALT_R", "CTRL_L", "CTRL_R", "SHIFT_L", "SHIFT_R",
|
||||
"WIN_L", "WIN_R", "MENU", "KP_ADD", "KP_SUBTRACT", "KP_END", "KP_DOWN",
|
||||
"KP_PAGE_DOWN", "KP_LEFT", "KP_RIGHT", "KP_HOME", "KP_UP", "KP_PAGE_UP",
|
||||
static const char *key_names[] =
|
||||
{"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12",
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
|
||||
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
|
||||
"K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
|
||||
"U", "V", "W", "X", "Y", "Z",
|
||||
"BACKQUOTE", "MINUS", "EQUALS", "LEFT_BRACKET", "RIGHT_BRACKET",
|
||||
"SEMICOLON", "SINGLE_QUOTE", "BACKSLASH", "LEFT_BACKSLASH", "COMMA",
|
||||
"PERIOD", "SLASH", "PRINT", "SCRL_LOCK", "PAUSE", "ESC", "BACKSPACE",
|
||||
"TAB", "ENTER", "SPACE", "INSERT", "DELETE", "HOME", "END", "PAGE_UP",
|
||||
"PAGE_DOWN", "UP", "DOWN", "LEFT", "RIGHT", "CAPS_LOCK", "NUM_LOCK",
|
||||
"ALT_L", "ALT_R", "CTRL_L", "CTRL_R", "SHIFT_L", "SHIFT_R",
|
||||
"WIN_L", "WIN_R", "MENU", "KP_ADD", "KP_SUBTRACT", "KP_END", "KP_DOWN",
|
||||
"KP_PAGE_DOWN", "KP_LEFT", "KP_RIGHT", "KP_HOME", "KP_UP", "KP_PAGE_UP",
|
||||
"KP_INSERT", "KP_DELETE", "KP_5", "KP_ENTER", "KP_MULTIPLY", "KP_DIVIDE"
|
||||
};
|
||||
|
||||
|
@ -170,7 +170,7 @@ static char tmp_key_name[40];
|
|||
#define amask 0xFF000000
|
||||
#endif
|
||||
|
||||
/* libpng callbacks */
|
||||
/* libpng callbacks */
|
||||
static void png_error_SDL(png_structp ctx, png_const_charp str)
|
||||
{
|
||||
SDL_SetError("libpng: %s\n", str);
|
||||
|
@ -181,12 +181,12 @@ static void png_write_SDL(png_structp png_ptr, png_bytep data, png_size_t length
|
|||
SDL_RWwrite(rw, data, sizeof(png_byte), length);
|
||||
}
|
||||
|
||||
static SDL_Surface *SDL_PNGFormatAlpha(SDL_Surface *src)
|
||||
static SDL_Surface *SDL_PNGFormatAlpha(SDL_Surface *src)
|
||||
{
|
||||
SDL_Surface *surf;
|
||||
SDL_Rect rect = { 0 };
|
||||
|
||||
/* NO-OP for images < 32bpp and 32bpp images that already have Alpha channel */
|
||||
/* NO-OP for images < 32bpp and 32bpp images that already have Alpha channel */
|
||||
if (src->format->BitsPerPixel <= 24 || src->format->Amask) {
|
||||
src->refcount++;
|
||||
return src;
|
||||
|
@ -202,7 +202,7 @@ static SDL_Surface *SDL_PNGFormatAlpha(SDL_Surface *src)
|
|||
return surf;
|
||||
}
|
||||
|
||||
static int SDL_SavePNG_RW(SDL_Surface *surface, SDL_RWops *dst, int freedst)
|
||||
static int SDL_SavePNG_RW(SDL_Surface *surface, SDL_RWops *dst, int freedst)
|
||||
{
|
||||
png_structp png_ptr;
|
||||
png_infop info_ptr;
|
||||
|
@ -225,7 +225,7 @@ static int SDL_SavePNG_RW(SDL_Surface *surface, SDL_RWops *dst, int freedst)
|
|||
return (ERROR);
|
||||
}
|
||||
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, png_error_SDL, NULL); /* err_ptr, err_fn, warn_fn */
|
||||
if (!png_ptr)
|
||||
if (!png_ptr)
|
||||
{
|
||||
SDL_SetError("Unable to png_create_write_struct on %s\n", PNG_LIBPNG_VER_STRING);
|
||||
if (freedst) SDL_RWclose(dst);
|
||||
|
@ -300,19 +300,19 @@ static int SDL_SavePNG_RW(SDL_Surface *surface, SDL_RWops *dst, int freedst)
|
|||
}
|
||||
#endif /* defined(HAVE_LIBPNG) */
|
||||
|
||||
/*
|
||||
Some platforms (OS X), require that ALL input event processing be
|
||||
/*
|
||||
Some platforms (OS X), require that ALL input event processing be
|
||||
performed by the main thread of the process.
|
||||
|
||||
To satisfy this requirement, we leverage the SDL_MAIN functionality
|
||||
To satisfy this requirement, we leverage the SDL_MAIN functionality
|
||||
which does:
|
||||
|
||||
|
||||
#defines main SDL_main
|
||||
|
||||
and we define the main() entry point here. Locally, we run the
|
||||
|
||||
and we define the main() entry point here. Locally, we run the
|
||||
application's SDL_main in a separate thread, and while that thread
|
||||
is running, the main thread performs event handling and dispatch.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#define EVENT_REDRAW 1 /* redraw event for SDL */
|
||||
|
@ -641,7 +641,7 @@ int i, n;
|
|||
if (vid_gamepad_inited++)
|
||||
return;
|
||||
|
||||
/* Chech that the SDL_GameControllerFromInstanceID function is
|
||||
/* Check that the SDL_GameControllerFromInstanceID function is
|
||||
available at run time. */
|
||||
SDL_GetVersion(&ver);
|
||||
vid_gamepad_ok = (ver.major > 2 ||
|
||||
|
@ -999,7 +999,7 @@ if (vptr->vid_flags & SIM_VID_INPUTCAPTURED)
|
|||
|
||||
if ((x_delta) || (y_delta)) {
|
||||
sim_debug (SIM_VID_DBG_CURSOR, vptr->vid_dev, "vid_set_cursor_position(%d, %d) - Cursor position changed\n", x, y);
|
||||
/* Any queued mouse motion events need to have their relative
|
||||
/* Any queued mouse motion events need to have their relative
|
||||
positions adjusted since they were queued based on different info. */
|
||||
if (SDL_SemWait (vid_mouse_events.sem) == 0) {
|
||||
int32 i;
|
||||
|
@ -1452,9 +1452,9 @@ if (vptr->vid_mouse_captured) {
|
|||
|
||||
if (!KeyStates)
|
||||
KeyStates = SDL_GetKeyboardState(&numkeys);
|
||||
if ((vptr->vid_flags & SIM_VID_INPUTCAPTURED) &&
|
||||
(event->state == SDL_PRESSED) &&
|
||||
KeyStates[SDL_SCANCODE_RSHIFT] &&
|
||||
if ((vptr->vid_flags & SIM_VID_INPUTCAPTURED) &&
|
||||
(event->state == SDL_PRESSED) &&
|
||||
KeyStates[SDL_SCANCODE_RSHIFT] &&
|
||||
(KeyStates[SDL_SCANCODE_LCTRL] || KeyStates[SDL_SCANCODE_RCTRL])) {
|
||||
sim_debug (SIM_VID_DBG_KEY, vptr->vid_dev, "vid_key() - Cursor Release\n");
|
||||
if (SDL_SetRelativeMouseMode(SDL_FALSE) < 0) /* release cursor, show cursor */
|
||||
|
@ -1512,7 +1512,7 @@ if (!sim_is_running)
|
|||
return;
|
||||
if (!vptr->vid_cursor_visible)
|
||||
return;
|
||||
sim_debug (SIM_VID_DBG_MOUSE, vptr->vid_dev, "Mouse Move Event: pos:(%d,%d) rel:(%d,%d) buttons:(%d,%d,%d)\n",
|
||||
sim_debug (SIM_VID_DBG_MOUSE, vptr->vid_dev, "Mouse Move Event: pos:(%d,%d) rel:(%d,%d) buttons:(%d,%d,%d)\n",
|
||||
event->x, event->y, event->xrel, event->yrel, (event->state & SDL_BUTTON(SDL_BUTTON_LEFT)) ? 1 : 0, (event->state & SDL_BUTTON(SDL_BUTTON_MIDDLE)) ? 1 : 0, (event->state & SDL_BUTTON(SDL_BUTTON_RIGHT)) ? 1 : 0);
|
||||
while (SDL_PeepEvents (&dummy_event, 1, SDL_GETEVENT, SDL_MOUSEMOTION, SDL_MOUSEMOTION)) {
|
||||
/* Coalesce motion activity to avoid thrashing */
|
||||
|
@ -1521,7 +1521,7 @@ while (SDL_PeepEvents (&dummy_event, 1, SDL_GETEVENT, SDL_MOUSEMOTION, SDL_MOUSE
|
|||
event->x = dev->x;
|
||||
event->y = dev->y;
|
||||
event->state = dev->state;
|
||||
sim_debug (SIM_VID_DBG_MOUSE, vptr->vid_dev, "Mouse Move Event: Additional Event Coalesced:pos:(%d,%d) rel:(%d,%d) buttons:(%d,%d,%d)\n",
|
||||
sim_debug (SIM_VID_DBG_MOUSE, vptr->vid_dev, "Mouse Move Event: Additional Event Coalesced:pos:(%d,%d) rel:(%d,%d) buttons:(%d,%d,%d)\n",
|
||||
dev->x, dev->y, dev->xrel, dev->yrel, (dev->state & SDL_BUTTON(SDL_BUTTON_LEFT)) ? 1 : 0, (dev->state & SDL_BUTTON(SDL_BUTTON_MIDDLE)) ? 1 : 0, (dev->state & SDL_BUTTON(SDL_BUTTON_RIGHT)) ? 1 : 0);
|
||||
};
|
||||
if (SDL_SemWait (vid_mouse_events.sem) == 0) {
|
||||
|
@ -1532,7 +1532,7 @@ if (SDL_SemWait (vid_mouse_events.sem) == 0) {
|
|||
vid_mouse_b1 = (event->state & SDL_BUTTON(SDL_BUTTON_LEFT)) ? TRUE : FALSE;
|
||||
vid_mouse_b2 = (event->state & SDL_BUTTON(SDL_BUTTON_MIDDLE)) ? TRUE : FALSE;
|
||||
vid_mouse_b3 = (event->state & SDL_BUTTON(SDL_BUTTON_RIGHT)) ? TRUE : FALSE;
|
||||
sim_debug (SIM_VID_DBG_MOUSE, vptr->vid_dev, "Mouse Move Event: pos:(%d,%d) rel:(%d,%d) buttons:(%d,%d,%d) - Count: %d vid_cursor:(%d,%d)\n",
|
||||
sim_debug (SIM_VID_DBG_MOUSE, vptr->vid_dev, "Mouse Move Event: pos:(%d,%d) rel:(%d,%d) buttons:(%d,%d,%d) - Count: %d vid_cursor:(%d,%d)\n",
|
||||
event->x, event->y, event->xrel, event->yrel, (event->state & SDL_BUTTON(SDL_BUTTON_LEFT)) ? 1 : 0, (event->state & SDL_BUTTON(SDL_BUTTON_MIDDLE)) ? 1 : 0, (event->state & SDL_BUTTON(SDL_BUTTON_RIGHT)) ? 1 : 0, vid_mouse_events.count, vid_cursor_x, vid_cursor_y);
|
||||
if (vid_mouse_events.count < MAX_EVENTS) {
|
||||
SIM_MOUSE_EVENT *tail = &vid_mouse_events.events[(vid_mouse_events.tail+MAX_EVENTS-1)%MAX_EVENTS];
|
||||
|
@ -1547,13 +1547,13 @@ if (SDL_SemWait (vid_mouse_events.sem) == 0) {
|
|||
ev.y_pos = event->y;
|
||||
if ((vid_mouse_events.count > 0) && /* Is there a tail event? */
|
||||
(ev.b1_state == tail->b1_state) && /* With the same button state? */
|
||||
(ev.b2_state == tail->b2_state) &&
|
||||
(ev.b2_state == tail->b2_state) &&
|
||||
(ev.b3_state == tail->b3_state)) { /* Merge the motion */
|
||||
tail->x_rel += ev.x_rel;
|
||||
tail->y_rel += ev.y_rel;
|
||||
tail->x_pos = ev.x_pos;
|
||||
tail->y_pos = ev.y_pos;
|
||||
sim_debug (SIM_VID_DBG_MOUSE, vptr->vid_dev, "Mouse Move Event: Coalesced into pending event: (%d,%d)\n",
|
||||
sim_debug (SIM_VID_DBG_MOUSE, vptr->vid_dev, "Mouse Move Event: Coalesced into pending event: (%d,%d)\n",
|
||||
tail->x_rel, tail->y_rel);
|
||||
}
|
||||
else { /* Add a new event */
|
||||
|
@ -1757,7 +1757,7 @@ void vid_update_cursor (VID_DISPLAY *vptr, SDL_Cursor *cursor, t_bool visible)
|
|||
{
|
||||
if (!cursor)
|
||||
return;
|
||||
sim_debug (SIM_VID_DBG_VIDEO, vptr->vid_dev, "Cursor Update Event: Previously %s, Now %s, New Cursor object at: %p, Old Cursor object at: %p\n",
|
||||
sim_debug (SIM_VID_DBG_VIDEO, vptr->vid_dev, "Cursor Update Event: Previously %s, Now %s, New Cursor object at: %p, Old Cursor object at: %p\n",
|
||||
SDL_ShowCursor(-1) ? "visible" : "invisible", visible ? "visible" : "invisible", cursor, vptr->vid_cursor);
|
||||
SDL_SetCursor (cursor);
|
||||
if ((vptr->vid_window == SDL_GetMouseFocus ()) && visible)
|
||||
|
@ -1794,7 +1794,7 @@ SDL_UnlockMutex (vptr->vid_draw_mutex);
|
|||
|
||||
if (vptr->vid_blending) {
|
||||
SDL_UpdateTexture(vptr->vid_texture, vid_dst, buf, vid_dst->w*sizeof(*buf));
|
||||
SDL_RenderCopy (vptr->vid_renderer, vptr->vid_texture, vid_dst, vid_dst);
|
||||
SDL_RenderCopy (vptr->vid_renderer, vptr->vid_texture, vid_dst, vid_dst);
|
||||
}
|
||||
else
|
||||
if (SDL_UpdateTexture(vptr->vid_texture, vid_dst, buf, vid_dst->w*sizeof(*buf)))
|
||||
|
@ -2282,10 +2282,10 @@ SDLVersion[sizeof (SDLVersion) - 1] = '\0';
|
|||
if ((compiled.major == running.major) &&
|
||||
(compiled.minor == running.minor) &&
|
||||
(compiled.patch == running.patch))
|
||||
snprintf(SDLVersion, sizeof (SDLVersion) - 1, "SDL Version %d.%d.%d",
|
||||
snprintf(SDLVersion, sizeof (SDLVersion) - 1, "SDL Version %d.%d.%d",
|
||||
compiled.major, compiled.minor, compiled.patch);
|
||||
else
|
||||
snprintf(SDLVersion, sizeof (SDLVersion) - 1, "SDL Version (Compiled: %d.%d.%d, Runtime: %d.%d.%d)",
|
||||
snprintf(SDLVersion, sizeof (SDLVersion) - 1, "SDL Version (Compiled: %d.%d.%d, Runtime: %d.%d.%d)",
|
||||
compiled.major, compiled.minor, compiled.patch,
|
||||
running.major, running.minor, running.patch);
|
||||
#if defined (HAVE_LIBPNG)
|
||||
|
@ -2293,19 +2293,19 @@ if (1) {
|
|||
png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
|
||||
if (strcmp (PNG_LIBPNG_VER_STRING, png_get_libpng_ver (png)))
|
||||
snprintf(&SDLVersion[strlen (SDLVersion)], sizeof (SDLVersion) - (strlen (SDLVersion) + 1),
|
||||
", PNG Version (Compiled: %s, Runtime: %s)",
|
||||
snprintf(&SDLVersion[strlen (SDLVersion)], sizeof (SDLVersion) - (strlen (SDLVersion) + 1),
|
||||
", PNG Version (Compiled: %s, Runtime: %s)",
|
||||
PNG_LIBPNG_VER_STRING, png_get_libpng_ver (png));
|
||||
else
|
||||
snprintf(&SDLVersion[strlen (SDLVersion)], sizeof (SDLVersion) - (strlen (SDLVersion) + 1),
|
||||
snprintf(&SDLVersion[strlen (SDLVersion)], sizeof (SDLVersion) - (strlen (SDLVersion) + 1),
|
||||
", PNG Version %s", PNG_LIBPNG_VER_STRING);
|
||||
png_destroy_read_struct(&png, NULL, NULL);
|
||||
#if defined (ZLIB_VERSION)
|
||||
if (strcmp (ZLIB_VERSION, zlibVersion ()))
|
||||
snprintf(&SDLVersion[strlen (SDLVersion)], sizeof (SDLVersion) - (strlen (SDLVersion) + 1),
|
||||
snprintf(&SDLVersion[strlen (SDLVersion)], sizeof (SDLVersion) - (strlen (SDLVersion) + 1),
|
||||
", zlib: (Compiled: %s, Runtime: %s)", ZLIB_VERSION, zlibVersion ());
|
||||
else
|
||||
snprintf(&SDLVersion[strlen (SDLVersion)], sizeof (SDLVersion) - (strlen (SDLVersion) + 1),
|
||||
snprintf(&SDLVersion[strlen (SDLVersion)], sizeof (SDLVersion) - (strlen (SDLVersion) + 1),
|
||||
", zlib: %s", ZLIB_VERSION);
|
||||
#endif
|
||||
}
|
||||
|
@ -2654,7 +2654,7 @@ char *extension = strrchr ((char *)_screenshot_filename, '.');
|
|||
if (name == NULL) {
|
||||
_screenshot_stat = SCPE_NXM;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (extension)
|
||||
n = extension - _screenshot_filename;
|
||||
else {
|
||||
|
@ -2778,7 +2778,7 @@ while (SDL_PushEvent (&user_event) < 0)
|
|||
#else
|
||||
vid_beep_event ();
|
||||
#endif
|
||||
SDL_Delay (vid_beep_duration + 100);/* Wait for sound to finnish */
|
||||
SDL_Delay (vid_beep_duration + 100);/* Wait for sound to finish */
|
||||
}
|
||||
|
||||
#else /* !(defined(USE_SIM_VIDEO) && defined(HAVE_LIBSDL)) */
|
||||
|
|
Loading…
Add table
Reference in a new issue