Notes For V2.10-4
1. New Features in 2.10-4 1.1 SCP and Libraries - Added .ini startup file capability (suggested by Hans Pufal). - Added multiple switch evaluation points (suggested by Hans Pufal). - Added multiple command per action. - Added new library, sim_tape.c, for magtape emulation. 1.2 PDP-11 - Added user-defined disk capacity to RQ. - Addec choice of controllers to TQ. - Added user-defined tape capacity to TQ. 1.3 Interdata - Added SHOW SELCH n command to display selector channel state. 1.4 Line Frequency Clocks (H316, Interdata, Nova, PDP-8, PDP-11, PDP-18B, SDS) - Added SET <device> {50HZ/60HZ}, to set the line frequency. 1.5 DEC Console Input (PDP-8, PDP-11, PDP-18B, VAX) - Added SET TTI CTRL-C, to generate ^C from SIMH prompt (^C crashes simulators compiled with Windows Visual C++). 1.6 Magtapes - Revised to use magtape library for consistency. 2. Bugs Fixed in 2.10-4 - SCP: fixed bug in multiword deposits to files - Interdata disks: fixed bug in cylinder overflow on writes - Interdata tape: fixed bug, read error did not stop selector channel - Interdata precision clock: improved autocalibrate algorithm for UNIX V7. - Nova fixed head disk: fixed autosize algorithm. - PDP-11 RQ and TQ: fixed bugs in queue process and in vector calculation for VAXen. - PDP-11 TQ: fixed overly strict implementation of illegal modifiers check. - PDP-11 RY: fixed autosize algorithm. - PDP-18B CPU: fixed three EAE bugs (found by Hans Pufal). - PDP-18B MT: fixed bugs in interrupt handling, BOT error handling. - PDP-18B RF: removed extra bit from disk address, fixed autosize algorithm. - PDP-18B SYS: fixed bug in FMTASC usage (found by Hans Pufal). - PDP-8 MT: fixed bug in BOT error handling. - PDP-8 DF, RF, RX: fixed autosize algorithm. 3. New Features in 2.10 vs prior releases 3.1 SCP and Libraries - The VT emulation package has been replaced by the capability to remote the console to a Telnet session. Telnet clients typically have more complete and robust VT100 emulation. - Simulated devices may now have statically allocated buffers, in addition to dynamically allocated buffers or disk-based data stores. - The DO command now takes substitutable arguments (max 9). In command files, %n represents substitutable argument n. - The initial command line is now interpreted as the command name and substitutable arguments for a DO command. This is backward compatible to prior versions. - The initial command line parses switches. -Q is interpreted as quiet mode; informational messages are suppressed. - The HELP command now takes an optional argument. HELP <cmd> types help on the specified command. - Hooks have been added for implementing GUI-based consoles, as well as simulator-specific command extensions. A few internal data structures and definitions have changed. - Two new routines (tmxr_open_master, tmxr_close_master) have been added to sim_tmxr.c. The calling sequence for sim_accept_conn has been changed in sim_sock.c. - The calling sequence for the VM boot routine has been modified to add an additional parameter. - SAVE now saves, and GET now restores, controller and unit flags. - Library sim_ether.c has been added for Ethernet support. - The EVAL command will evaluate a symbolic type-in and display it in numeric form. - The ! command (with no arguments) will launch the host operating system command shell. The ! command (with an argument) executes the argument as a host operating system command. (Code from Mark Pizzolato) - Telnet sessions now recognize BREAK. How a BREAK is transmitted dependent on the particular Telnet client. (Code from Mark Pizzolato) - The sockets library includes code for active connections as well as listening connections. - The RESTORE command will restore saved memory size, if the simulator supports dynamic memory resizing. - Added dynamic extension of the breakpoint table. - Added breakpoint actions. - Added VMS support for ! (from Mark Pizzolato). 3.2 VAX - Non-volatile RAM (NVR) can behave either like a memory or like a disk-based peripheral. If unattached, it behaves like memory and is saved and restored by SAVE and RESTORE, respectively. If attached, its contents are loaded from disk by ATTACH and written back to disk at DETACH and EXIT. - SHOW <device> VECTOR displays the device's interrupt vector. A few devices allow the vector to be changed with SET <device> VECTOR=nnn. - SHOW CPU IOSPACE displays the I/O space address map. - The TK50 (TMSCP tape) has been added. - The DEQNA/DELQA (Qbus Ethernet controllers) have been added. - Autoconfiguration support has been added. - The paper tape reader has been removed from vax_stddev.c and now references a common implementation file, dec_pt.h. - Examine and deposit switches now work on all devices, not just the CPU. - Device address conflicts are not detected until simulation starts. - If the VAX console is attached to a Telnet session, BREAK is interpreted as console halt. - The SET/SHOW HISTORY commands enable and display a history of the most recently executed instructions. (Code from Mark Pizzolato) 3.3 PDP-11 - SHOW <device> VECTOR displays the device's interrupt vector. Most devices allow the vector to be changed with SET <device> VECTOR=nnn. - SHOW CPU IOSPACE displays the I/O space address map. - The TK50 (TMSCP tape), RK611/RK06/RK07 (cartridge disk), RX211 (double density floppy), and KW11P programmable clock have been added. - The DEQNA/DELQA (Qbus Ethernet controllers) have been added. - Autoconfiguration support has been added. - The paper tape reader has been removed from pdp11_stddev.c and now references a common implementation file, dec_pt.h. - Device bootstraps now use the actual CSR specified by the SET ADDRESS command, rather than just the default CSR. Note that PDP-11 operating systems may NOT support booting with non-standard addresses. - Specifying more than 256KB of memory, or changing the bus configuration, causes all peripherals that are not compatible with the current bus configuration to be disabled. - Device address conflicts are not detected until simulation starts. - The PDP-11 implements a stub DEUNA/DELUA (XU). The real XU module will be included in a later release. 3.4 PDP-10 - SHOW <device> VECTOR displays the device's interrupt vector. A few devices allow the vector to be changed with SET <device> VECTOR=nnn. - SHOW CPU IOSPACE displays the I/O space address map. - The RX211 (double density floppy) has been added; it is off by default. - The paper tape now references a common implementation file, dec_pt.h. - Device address conflicts are not detected until simulation starts. - The PDP-10 implements a stub DEUNA/DELUA (XU). The real XU module will be included in a later release. 3.5 PDP-1 - DECtape (then known as MicroTape) support has been added. - The line printer and DECtape can be disabled and enabled. - The PDP-1 supports the Type 24 serial drum (based on recently discovered documents). 3.6 18b PDP's - The PDP-4 supports the Type 24 serial drum (based on recently discovered documents). - Added RB09 fixed head disk for the PDP-9. - Added LP09 line printer for the PDP-9 and PDP-15. - Added variable size support and autosizing to the RF15/RF09. 3.7 PDP-8 - The RX28 (double density floppy) has been added as an option to the existing RX8E controller. - SHOW <device> DEVNO displays the device's device number. Most devices allow the device number to be changed with SET <device> DEVNO=nnn. - Device number conflicts are not detected until simulation starts. - Added variable size support and autosizing to the DF32 and RF08. 3.8 Nova - Added variable size support and autosizing to the Novadisk. 3.9 AltairZ80 - A hard drive has been added for increased storage. - Several bugs have been fixed. 3.10 HP 2100 - The 12845A has been added and made the default line printer (LPT). The 12653A has been renamed LPS and is off by default. It also supports the diagnostic functions needed to run the DCPC and DMS diagnostics. - The 12557A/13210A disk defaults to the 13210A (7900/7901). - The 12559A magtape is off by default. - New CPU options (EAU/NOEAU) enable/disable the extended arithmetic instructions for the 2116. These instructions are standard on the 2100 and 21MX. - New CPU options (MPR/NOMPR) enable/disable memory protect for the 2100 and 21MX. - New CPU options (DMS/NODMS) enable/disable the dynamic mapping instructions for the 21MX. - The 12539 timebase generator autocalibrates. - The IOP microinstruction set is supported for the 21MX as well as the 2100. - The HP2100 supports the Access Interprocessor Link (IPL). 3.11 Simulated Magtapes - Simulated magtapes recognize end of file and the marker 0xFFFFFFFF as end of medium. Only the TMSCP tape simulator can generate an end of medium marker. - The error handling in simulated magtapes was overhauled to be consistent through all simulators. 3.12 Simulated DECtapes - Added support for RT11 image file format (256 x 16b) to DECtapes. 3.13 Terminals Multiplexors - BREAK detection was added to the HP, DEC, and Interdata terminal multiplexors. 4. Bugs Fixed in 2.10 vs prior releases - TS11/TSV05 was not simulating the XS0_MOT bit, causing failures under VMS. In addition, two of the CTL options were coded interchanged. - IBM 1401 tape was not setting a word mark under group mark for load mode reads. This caused the diagnostics to crash. - SCP bugs in ssh_break and set_logon were fixed (found by Dave Hittner). - Numerous bugs in the HP 2100 extended arithmetic, floating point, 21MX, DMS, and IOP instructions were fixed. Bugs were also fixed in the memory protect and DMS functions. The moving head disks (DP, DQ) were revised to simulate the hardware more accurately. Missing functions in DQ (address skip, read address) were added. - PDP-10 tape wouldn't boot, and then wouldn't read (reported by Michael Thompson and Harris Newman, respectively) - PDP-1 typewriter is half duplex, with only one shift state for both input and output (found by Derek Peschel) - PDP-11 console must default to 7b for early UNIX compatibility. - PDP-11/VAX TMSCP emulator was using the wrong packet length for read/write end packets. - Telnet IAC+IAC processing was fixed, both for input and output (found by Mark Pizzolato). - PDP-11/VAX Ethernet setting flag bits wrong for chained descriptors (found by Mark Pizzolato). - 18b PDP RF15/RF09: fixed IOT decoding and address wraparound logic (found by Hans Pufal). - 18b PDP RP15: fixed IOT decoding and command initiation. - HP2100 IPL: changed to full duplex (found by Mike Gemeny). - HP2100 CPU: fixed last cycle bug in DMA outpout (found by Mike Gemeny). - Interdata 16b CPU: fixed bug in SETM, SETMR (found by Mark Pizzolato). 5. General Notes WARNING: The build procedures have changed. There is only one UNIX makefile. To compile without Ethernet support, simply type gmake {target|all} To compile with Ethernet support, type gmake USE_NETWORK=1 {target|all} The Mingw batch files require Mingw release 2 and invoke the Unix makefile. There are still separate batch files for compilation with or without Ethernet support. WARNING: V2.10 has reorganized and renamed some of the definition files for the PDP-10, PDP-11, and VAX. Be sure to delete all previous source files before you unpack the Zip archive, or unpack it into a new directory structure. WARNING: V2.10 has a new, more comprehensive save file format. Restoring save files from previous releases will cause 'invalid register' errors and loss of CPU option flags, device enable/ disable flags, unit online/offline flags, and unit writelock flags. WARNING: If you are using Visual Studio .NET through the IDE, be sure to turn off the /Wp64 flag in the project settings, or dozens of spurious errors will be generated. WARNING: Compiling Ethernet support under Windows requires extra steps; see the Ethernet readme file. Ethernet support is currently available only for Windows, Linux, NetBSD, and OpenBSD.
This commit is contained in:
parent
f20f5c629d
commit
43385c9616
72 changed files with 3065 additions and 2189 deletions
|
@ -1,37 +1,59 @@
|
||||||
Notes For V2.10-3
|
Notes For V2.10-4
|
||||||
|
|
||||||
1. New Features in 2.10-3
|
1. New Features in 2.10-4
|
||||||
|
|
||||||
1.1 SCP and Libraries
|
1.1 SCP and Libraries
|
||||||
|
|
||||||
- Added dynamic extension of the breakpoint table.
|
- Added .ini startup file capability (suggested by Hans Pufal).
|
||||||
- Added breakpoint actions.
|
- Added multiple switch evaluation points (suggested by Hans Pufal).
|
||||||
- Added VMS support for ! (from Mark Pizzolato).
|
- Added multiple command per action.
|
||||||
|
- Added new library, sim_tape.c, for magtape emulation.
|
||||||
|
|
||||||
1.2 18b PDP's
|
1.2 PDP-11
|
||||||
|
|
||||||
- Added RB09 fixed head disk for the PDP-9.
|
- Added user-defined disk capacity to RQ.
|
||||||
- Added LP09 line printer for the PDP-9 and PDP-15.
|
- Addec choice of controllers to TQ.
|
||||||
- Added variable size support and autosizing to the RF15/RF09.
|
- Added user-defined tape capacity to TQ.
|
||||||
|
|
||||||
1.3 PDP-8
|
1.3 Interdata
|
||||||
|
|
||||||
- Added variable size support and autosizing to the DF32 and RF08.
|
- Added SHOW SELCH n command to display selector channel state.
|
||||||
|
|
||||||
1.4 Nova
|
1.4 Line Frequency Clocks (H316, Interdata, Nova, PDP-8, PDP-11,
|
||||||
|
PDP-18B, SDS)
|
||||||
|
|
||||||
- Added variable size support and autosizing to the Novadisk.
|
- Added SET <device> {50HZ/60HZ}, to set the line frequency.
|
||||||
|
|
||||||
2. Bugs Fixed in 2.10-3
|
1.5 DEC Console Input (PDP-8, PDP-11, PDP-18B, VAX)
|
||||||
|
|
||||||
- 18b PDP RF15/RF09: fixed IOT decoding and address wraparound
|
- Added SET TTI CTRL-C, to generate ^C from SIMH prompt (^C
|
||||||
logic (found by Hans Pufal).
|
crashes simulators compiled with Windows Visual C++).
|
||||||
- 18b PDP RP15: fixed IOT decoding and command initiation.
|
|
||||||
- HP2100 IPL: changed to full duplex (found by Mike Gemeny).
|
1.6 Magtapes
|
||||||
- HP2100 CPU: fixed last cycle bug in DMA outpout (found by Mike
|
|
||||||
Gemeny).
|
- Revised to use magtape library for consistency.
|
||||||
- Interdata 16b CPU: fixed bug in SETM, SETMR (found by Mark
|
|
||||||
Pizzolato).
|
2. Bugs Fixed in 2.10-4
|
||||||
|
|
||||||
|
- SCP: fixed bug in multiword deposits to files
|
||||||
|
- Interdata disks: fixed bug in cylinder overflow on writes
|
||||||
|
- Interdata tape: fixed bug, read error did not stop selector
|
||||||
|
channel
|
||||||
|
- Interdata precision clock: improved autocalibrate algorithm
|
||||||
|
for UNIX V7.
|
||||||
|
- Nova fixed head disk: fixed autosize algorithm.
|
||||||
|
- PDP-11 RQ and TQ: fixed bugs in queue process and in vector
|
||||||
|
calculation for VAXen.
|
||||||
|
- PDP-11 TQ: fixed overly strict implementation of illegal
|
||||||
|
modifiers check.
|
||||||
|
- PDP-11 RY: fixed autosize algorithm.
|
||||||
|
- PDP-18B CPU: fixed three EAE bugs (found by Hans Pufal).
|
||||||
|
- PDP-18B MT: fixed bugs in interrupt handling, BOT error handling.
|
||||||
|
- PDP-18B RF: removed extra bit from disk address, fixed autosize
|
||||||
|
algorithm.
|
||||||
|
- PDP-18B SYS: fixed bug in FMTASC usage (found by Hans Pufal).
|
||||||
|
- PDP-8 MT: fixed bug in BOT error handling.
|
||||||
|
- PDP-8 DF, RF, RX: fixed autosize algorithm.
|
||||||
|
|
||||||
3. New Features in 2.10 vs prior releases
|
3. New Features in 2.10 vs prior releases
|
||||||
|
|
||||||
|
@ -75,6 +97,9 @@ Notes For V2.10-3
|
||||||
well as listening connections.
|
well as listening connections.
|
||||||
- The RESTORE command will restore saved memory size, if the
|
- The RESTORE command will restore saved memory size, if the
|
||||||
simulator supports dynamic memory resizing.
|
simulator supports dynamic memory resizing.
|
||||||
|
- Added dynamic extension of the breakpoint table.
|
||||||
|
- Added breakpoint actions.
|
||||||
|
- Added VMS support for ! (from Mark Pizzolato).
|
||||||
|
|
||||||
3.2 VAX
|
3.2 VAX
|
||||||
|
|
||||||
|
@ -150,6 +175,9 @@ Notes For V2.10-3
|
||||||
|
|
||||||
- The PDP-4 supports the Type 24 serial drum (based on recently
|
- The PDP-4 supports the Type 24 serial drum (based on recently
|
||||||
discovered documents).
|
discovered documents).
|
||||||
|
- Added RB09 fixed head disk for the PDP-9.
|
||||||
|
- Added LP09 line printer for the PDP-9 and PDP-15.
|
||||||
|
- Added variable size support and autosizing to the RF15/RF09.
|
||||||
|
|
||||||
3.7 PDP-8
|
3.7 PDP-8
|
||||||
|
|
||||||
|
@ -159,13 +187,18 @@ Notes For V2.10-3
|
||||||
devices allow the device number to be changed with SET <device>
|
devices allow the device number to be changed with SET <device>
|
||||||
DEVNO=nnn.
|
DEVNO=nnn.
|
||||||
- Device number conflicts are not detected until simulation starts.
|
- Device number conflicts are not detected until simulation starts.
|
||||||
|
- Added variable size support and autosizing to the DF32 and RF08.
|
||||||
|
|
||||||
3.8 AltairZ80
|
3.8 Nova
|
||||||
|
|
||||||
|
- Added variable size support and autosizing to the Novadisk.
|
||||||
|
|
||||||
|
3.9 AltairZ80
|
||||||
|
|
||||||
- A hard drive has been added for increased storage.
|
- A hard drive has been added for increased storage.
|
||||||
- Several bugs have been fixed.
|
- Several bugs have been fixed.
|
||||||
|
|
||||||
3.9 HP 2100
|
3.10 HP 2100
|
||||||
|
|
||||||
- The 12845A has been added and made the default line printer (LPT).
|
- The 12845A has been added and made the default line printer (LPT).
|
||||||
The 12653A has been renamed LPS and is off by default. It also
|
The 12653A has been renamed LPS and is off by default. It also
|
||||||
|
@ -185,7 +218,7 @@ Notes For V2.10-3
|
||||||
as the 2100.
|
as the 2100.
|
||||||
- The HP2100 supports the Access Interprocessor Link (IPL).
|
- The HP2100 supports the Access Interprocessor Link (IPL).
|
||||||
|
|
||||||
3.10 Simulated Magtapes
|
3.11 Simulated Magtapes
|
||||||
|
|
||||||
- Simulated magtapes recognize end of file and the marker
|
- Simulated magtapes recognize end of file and the marker
|
||||||
0xFFFFFFFF as end of medium. Only the TMSCP tape simulator
|
0xFFFFFFFF as end of medium. Only the TMSCP tape simulator
|
||||||
|
@ -193,11 +226,11 @@ Notes For V2.10-3
|
||||||
- The error handling in simulated magtapes was overhauled to be
|
- The error handling in simulated magtapes was overhauled to be
|
||||||
consistent through all simulators.
|
consistent through all simulators.
|
||||||
|
|
||||||
3.11 Simulated DECtapes
|
3.12 Simulated DECtapes
|
||||||
|
|
||||||
- Added support for RT11 image file format (256 x 16b) to DECtapes.
|
- Added support for RT11 image file format (256 x 16b) to DECtapes.
|
||||||
|
|
||||||
3.12 Terminals Multiplexors
|
3.13 Terminals Multiplexors
|
||||||
|
|
||||||
- BREAK detection was added to the HP, DEC, and Interdata terminal
|
- BREAK detection was added to the HP, DEC, and Interdata terminal
|
||||||
multiplexors.
|
multiplexors.
|
||||||
|
@ -227,6 +260,15 @@ Notes For V2.10-3
|
||||||
(found by Mark Pizzolato).
|
(found by Mark Pizzolato).
|
||||||
- PDP-11/VAX Ethernet setting flag bits wrong for chained
|
- PDP-11/VAX Ethernet setting flag bits wrong for chained
|
||||||
descriptors (found by Mark Pizzolato).
|
descriptors (found by Mark Pizzolato).
|
||||||
|
- 18b PDP RF15/RF09: fixed IOT decoding and address wraparound
|
||||||
|
logic (found by Hans Pufal).
|
||||||
|
- 18b PDP RP15: fixed IOT decoding and command initiation.
|
||||||
|
- HP2100 IPL: changed to full duplex (found by Mike Gemeny).
|
||||||
|
- HP2100 CPU: fixed last cycle bug in DMA outpout (found by Mike
|
||||||
|
Gemeny).
|
||||||
|
- Interdata 16b CPU: fixed bug in SETM, SETMR (found by Mark
|
||||||
|
Pizzolato).
|
||||||
|
|
||||||
|
|
||||||
5. General Notes
|
5. General Notes
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
To: Users
|
To: Users
|
||||||
From: Bob Supnik
|
From: Bob Supnik
|
||||||
Subj: H316 Simulator Usage
|
Subj: H316 Simulator Usage
|
||||||
Date: 15-Nov-2002
|
Date: 15-Mar-2003
|
||||||
|
|
||||||
COPYRIGHT NOTICE
|
COPYRIGHT NOTICE
|
||||||
|
|
||||||
The following copyright notice applies to both the SIMH source and binary:
|
The following copyright notice applies to both the SIMH source and binary:
|
||||||
|
|
||||||
Original code published in 1993-2002, written by Robert M Supnik
|
Original code published in 1993-2003, written by Robert M Supnik
|
||||||
Copyright (c) 1993-2002, Robert M Supnik
|
Copyright (c) 1993-2003, Robert M Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -211,7 +211,14 @@ simulator console window. It implements these registers:
|
||||||
|
|
||||||
2.2.4 316/516-12 Real Time Clock (CLK)
|
2.2.4 316/516-12 Real Time Clock (CLK)
|
||||||
|
|
||||||
The real time clock (CLK) implements these registers:
|
The real time clock (CLK) frequency can be adjusted as follows:
|
||||||
|
|
||||||
|
SET CLK 60HZ set frequency to 60Hz
|
||||||
|
SET CLK 50HZ set frequency to 50Hz
|
||||||
|
|
||||||
|
The default is 60Hz.
|
||||||
|
|
||||||
|
The clock implements these registers:
|
||||||
|
|
||||||
name size comments
|
name size comments
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* h316_stddev.c: Honeywell 316/516 standard devices
|
/* h316_stddev.c: Honeywell 316/516 standard devices
|
||||||
|
|
||||||
Copyright (c) 1999-2002, Robert M. Supnik
|
Copyright (c) 1999-2003, Robert M. Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -28,6 +28,7 @@
|
||||||
tty 316/516-33 teleprinter
|
tty 316/516-33 teleprinter
|
||||||
clk/options 316/516-12 real time clocks/internal options
|
clk/options 316/516-12 real time clocks/internal options
|
||||||
|
|
||||||
|
01-Mar-03 RMS Added SET/SHOW CLK FREQ support
|
||||||
22-Dec-02 RMS Added break support
|
22-Dec-02 RMS Added break support
|
||||||
01-Nov-02 RMS Added 7b/8b support to terminal
|
01-Nov-02 RMS Added 7b/8b support to terminal
|
||||||
30-May-02 RMS Widened POS to 32b
|
30-May-02 RMS Widened POS to 32b
|
||||||
|
@ -67,6 +68,8 @@ t_stat tty_reset (DEVICE *dptr);
|
||||||
t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
t_stat clk_svc (UNIT *uptr);
|
t_stat clk_svc (UNIT *uptr);
|
||||||
t_stat clk_reset (DEVICE *dptr);
|
t_stat clk_reset (DEVICE *dptr);
|
||||||
|
t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
|
|
||||||
/* PTR data structures
|
/* PTR data structures
|
||||||
|
|
||||||
|
@ -177,11 +180,20 @@ REG clk_reg[] = {
|
||||||
{ FLDATA (READY, dev_ready, INT_V_CLK) },
|
{ FLDATA (READY, dev_ready, INT_V_CLK) },
|
||||||
{ FLDATA (ENABLE, dev_enable, INT_V_CLK) },
|
{ FLDATA (ENABLE, dev_enable, INT_V_CLK) },
|
||||||
{ DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT },
|
{ DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT },
|
||||||
{ DRDATA (TPS, clk_tps, 8), REG_NZ + PV_LEFT },
|
{ DRDATA (TPS, clk_tps, 8), PV_LEFT + REG_HRO },
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
|
MTAB clk_mod[] = {
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 50, NULL, "50HZ",
|
||||||
|
&clk_set_freq, NULL, NULL },
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 60, NULL, "60HZ",
|
||||||
|
&clk_set_freq, NULL, NULL },
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 0, "FREQUENCY", NULL,
|
||||||
|
NULL, &clk_show_freq, NULL },
|
||||||
|
{ 0 } };
|
||||||
|
|
||||||
DEVICE clk_dev = {
|
DEVICE clk_dev = {
|
||||||
"CLK", &clk_unit, clk_reg, NULL,
|
"CLK", &clk_unit, clk_reg, clk_mod,
|
||||||
1, 0, 0, 0, 0, 0,
|
1, 0, 0, 0, 0, 0,
|
||||||
NULL, NULL, &clk_reset,
|
NULL, NULL, &clk_reset,
|
||||||
NULL, NULL, NULL };
|
NULL, NULL, NULL };
|
||||||
|
@ -506,3 +518,21 @@ CLR_ENABLE (INT_CLK);
|
||||||
sim_cancel (&clk_unit); /* deactivate unit */
|
sim_cancel (&clk_unit); /* deactivate unit */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set frequency */
|
||||||
|
|
||||||
|
t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
if (cptr) return SCPE_ARG;
|
||||||
|
if ((val != 50) && (val != 60)) return SCPE_IERR;
|
||||||
|
clk_tps = val;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Show frequency */
|
||||||
|
|
||||||
|
t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
|
{
|
||||||
|
fprintf (st, (clk_tps == 50)? "50Hz": "60Hz");
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
|
@ -159,11 +159,12 @@ Peripherals
|
||||||
12965 2883/2884 disk passed 12965 manual no
|
12965 2883/2884 disk passed 12965 manual no
|
||||||
12559 3030 magtape not run no documentation
|
12559 3030 magtape not run no documentation
|
||||||
13181 7970B magtape partial in 21MX CE no
|
13181 7970B magtape partial in 21MX CE no
|
||||||
|
- initial s = 102030
|
||||||
- set MSC CTIME to 180000
|
- set MSC CTIME to 180000
|
||||||
- do not change MSC XTIME
|
- do not change MSC XTIME
|
||||||
- attach scratch tapes to units 0,1
|
- attach scratch tapes to units 0,1
|
||||||
- set s = 2000 (suppress CRC/LRC)
|
- set s = 1201 (suppress CRC/LRC)
|
||||||
- run with test select a = 37737, b = 7767
|
- run with test select a = 37757, b = 7767
|
||||||
- tests 4, 14, 15 are timing dependent
|
- tests 4, 14, 15 are timing dependent
|
||||||
- test 19 uses non-supported read rev
|
- test 19 uses non-supported read rev
|
||||||
13183 7970E magtape not run in 21MX CE no
|
13183 7970E magtape not run in 21MX CE no
|
||||||
|
|
|
@ -51,16 +51,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "hp2100_defs.h"
|
#include "hp2100_defs.h"
|
||||||
|
#include "sim_tape.h"
|
||||||
|
|
||||||
#define MS_NUMDR 4 /* number of drives */
|
#define MS_NUMDR 4 /* number of drives */
|
||||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
|
||||||
#define UNIT_V_PNU (UNIT_V_UF + 1) /* pos not updated */
|
|
||||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
|
||||||
#define UNIT_PNU (1 << UNIT_V_PNU)
|
|
||||||
#define DB_N_SIZE 16 /* max data buf */
|
#define DB_N_SIZE 16 /* max data buf */
|
||||||
#define DBSIZE (1 << DB_N_SIZE) /* max data cmd */
|
#define DBSIZE (1 << DB_N_SIZE) /* max data cmd */
|
||||||
#define DBMASK (DBSIZE - 1)
|
|
||||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
|
||||||
#define FNC u3 /* function */
|
#define FNC u3 /* function */
|
||||||
#define UST u4 /* unit status */
|
#define UST u4 /* unit status */
|
||||||
|
|
||||||
|
@ -138,12 +133,7 @@ t_stat msc_reset (DEVICE *dptr);
|
||||||
t_stat msc_attach (UNIT *uptr, char *cptr);
|
t_stat msc_attach (UNIT *uptr, char *cptr);
|
||||||
t_stat msc_detach (UNIT *uptr);
|
t_stat msc_detach (UNIT *uptr);
|
||||||
t_stat msc_boot (int32 unitno, DEVICE *dptr);
|
t_stat msc_boot (int32 unitno, DEVICE *dptr);
|
||||||
t_stat msc_vlock (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat ms_map_err (UNIT *uptr, t_stat st);
|
||||||
t_bool ms_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
|
||||||
t_bool ms_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
|
||||||
t_bool ms_forwsp (UNIT *uptr, int32 *err);
|
|
||||||
t_bool ms_backsp (UNIT *uptr, int32 *err);
|
|
||||||
int32 ms_wrtrec (UNIT *uptr, t_mtrlnt lnt);
|
|
||||||
t_stat ms_settype (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat ms_settype (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
t_stat ms_showtype (FILE *st, UNIT *uptr, int32 val, void *desc);
|
t_stat ms_showtype (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
|
|
||||||
|
@ -223,8 +213,8 @@ REG msc_reg[] = {
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
MTAB msc_mod[] = {
|
MTAB msc_mod[] = {
|
||||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", &msc_vlock },
|
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", &msc_vlock },
|
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
|
||||||
{ MTAB_XTD | MTAB_VDV, 0, NULL, "13181A",
|
{ MTAB_XTD | MTAB_VDV, 0, NULL, "13181A",
|
||||||
&ms_settype, NULL, NULL },
|
&ms_settype, NULL, NULL },
|
||||||
{ MTAB_XTD | MTAB_VDV, 1, NULL, "13183A",
|
{ MTAB_XTD | MTAB_VDV, 1, NULL, "13183A",
|
||||||
|
@ -285,6 +275,7 @@ return dat;
|
||||||
int32 mscio (int32 inst, int32 IR, int32 dat)
|
int32 mscio (int32 inst, int32 IR, int32 dat)
|
||||||
{
|
{
|
||||||
int32 i, devc, devd;
|
int32 i, devc, devd;
|
||||||
|
t_stat st;
|
||||||
UNIT *uptr = msc_dev.units + msc_usl;
|
UNIT *uptr = msc_dev.units + msc_usl;
|
||||||
static const uint8 map_sel[16] = {
|
static const uint8 map_sel[16] = {
|
||||||
0, 0, 1, 1, 2, 2, 2, 2,
|
0, 0, 1, 1, 2, 2, 2, 2,
|
||||||
|
@ -314,7 +305,7 @@ case ioOTX: /* output */
|
||||||
uptr = msc_dev.units + msc_usl; }
|
uptr = msc_dev.units + msc_usl; }
|
||||||
if (((dat & FNF_MOT) && sim_is_active (uptr)) ||
|
if (((dat & FNF_MOT) && sim_is_active (uptr)) ||
|
||||||
((dat & FNF_REV) && (uptr->UST & STA_BOT)) ||
|
((dat & FNF_REV) && (uptr->UST & STA_BOT)) ||
|
||||||
((dat & FNF_WRT) && (uptr->flags & UNIT_WPRT)))
|
((dat & FNF_WRT) && sim_tape_wrp (uptr)))
|
||||||
msc_sta = msc_sta | STA_REJ; /* reject? */
|
msc_sta = msc_sta | STA_REJ; /* reject? */
|
||||||
break;
|
break;
|
||||||
case ioLIX: /* load */
|
case ioLIX: /* load */
|
||||||
|
@ -324,7 +315,7 @@ case ioMIX: /* merge */
|
||||||
if (uptr->flags & UNIT_ATT) { /* online? */
|
if (uptr->flags & UNIT_ATT) { /* online? */
|
||||||
if (sim_is_active (uptr)) /* busy */
|
if (sim_is_active (uptr)) /* busy */
|
||||||
dat = dat | STA_TBSY;
|
dat = dat | STA_TBSY;
|
||||||
if (uptr->flags & UNIT_WPRT) /* write prot? */
|
if (sim_tape_wrp (uptr)) /* write prot? */
|
||||||
dat = dat | STA_WLK; }
|
dat = dat | STA_WLK; }
|
||||||
else dat = dat | STA_TBSY | STA_LOCAL;
|
else dat = dat | STA_TBSY | STA_LOCAL;
|
||||||
if (ms_ctype) dat = dat | STA_PE | /* 13183A? */
|
if (ms_ctype) dat = dat | STA_PE | /* 13183A? */
|
||||||
|
@ -336,8 +327,9 @@ case ioCTL: /* control clear/set */
|
||||||
if ((msc_buf & 0377) == FNC_CLR) { /* clear? */
|
if ((msc_buf & 0377) == FNC_CLR) { /* clear? */
|
||||||
for (i = 0; i < MS_NUMDR; i++) { /* loop thru units */
|
for (i = 0; i < MS_NUMDR; i++) { /* loop thru units */
|
||||||
if (sim_is_active (&msc_unit[i]) && /* write in prog? */
|
if (sim_is_active (&msc_unit[i]) && /* write in prog? */
|
||||||
(msc_unit[i].FNC == FNC_WC) && (ms_ptr > 0))
|
(msc_unit[i].FNC == FNC_WC) && (ms_ptr > 0)) {
|
||||||
ms_wrtrec (uptr, ms_ptr | MTR_ERF);
|
if (st = sim_tape_wrrecf (uptr, msxb, ms_ptr | MTR_ERF))
|
||||||
|
ms_map_err (uptr, st); }
|
||||||
if ((msc_unit[i].UST & STA_REW) == 0)
|
if ((msc_unit[i].UST & STA_REW) == 0)
|
||||||
sim_cancel (&msc_unit[i]); } /* stop if now rew */
|
sim_cancel (&msc_unit[i]); } /* stop if now rew */
|
||||||
clrCTL (devc); /* init device */
|
clrCTL (devc); /* init device */
|
||||||
|
@ -371,10 +363,10 @@ return dat;
|
||||||
|
|
||||||
t_stat msc_svc (UNIT *uptr)
|
t_stat msc_svc (UNIT *uptr)
|
||||||
{
|
{
|
||||||
int32 devc, devd, err, pnu;
|
int32 devc, devd;
|
||||||
static t_mtrlnt i, bceof = { MTR_TMK };
|
t_mtrlnt tbc;
|
||||||
|
t_stat st, r = SCPE_OK;
|
||||||
|
|
||||||
err = 0; /* assume no errors */
|
|
||||||
devc = msc_dib.devno; /* get device nos */
|
devc = msc_dib.devno; /* get device nos */
|
||||||
devd = msd_dib.devno;
|
devd = msd_dib.devno;
|
||||||
|
|
||||||
|
@ -383,14 +375,11 @@ if ((uptr->flags & UNIT_ATT) == 0) { /* offline? */
|
||||||
setFLG (devc); /* set cch flg */
|
setFLG (devc); /* set cch flg */
|
||||||
return IORETURN (msc_stopioe, SCPE_UNATT); }
|
return IORETURN (msc_stopioe, SCPE_UNATT); }
|
||||||
|
|
||||||
pnu = MT_TST_PNU (uptr); /* get pos not upd */
|
|
||||||
MT_CLR_PNU (uptr); /* and clear */
|
|
||||||
|
|
||||||
switch (uptr->FNC) { /* case on function */
|
switch (uptr->FNC) { /* case on function */
|
||||||
case FNC_REW: /* rewind */
|
case FNC_REW: /* rewind */
|
||||||
case FNC_RWS: /* rewind offline */
|
case FNC_RWS: /* rewind offline */
|
||||||
if (uptr->UST & STA_REW) { /* rewind in prog? */
|
if (uptr->UST & STA_REW) { /* rewind in prog? */
|
||||||
uptr->pos = 0; /* done */
|
sim_tape_rewind (uptr); /* done */
|
||||||
uptr->UST = STA_BOT; /* set BOT status */
|
uptr->UST = STA_BOT; /* set BOT status */
|
||||||
if (uptr->FNC & FNF_OFL) detach_unit (uptr);
|
if (uptr->FNC & FNF_OFL) detach_unit (uptr);
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
|
@ -400,32 +389,40 @@ case FNC_RWS: /* rewind offline */
|
||||||
|
|
||||||
case FNC_GFM: /* gap file mark */
|
case FNC_GFM: /* gap file mark */
|
||||||
case FNC_WFM: /* write file mark */
|
case FNC_WFM: /* write file mark */
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
|
||||||
fxwrite (&bceof, sizeof (t_mtrlnt), 1, uptr->fileref);
|
r = ms_map_err (uptr, st); /* map error */
|
||||||
msc_sta = STA_EOF; /* set EOF status */
|
msc_sta = STA_EOF; /* set EOF status */
|
||||||
if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr);
|
|
||||||
else uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* update tape pos */
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FNC_GAP: /* erase gap */
|
case FNC_GAP: /* erase gap */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FNC_FSF:
|
case FNC_FSR: /* space forward */
|
||||||
while (ms_forwsp (uptr, &err)) ; /* spc until EOF/EOT */
|
if (st = sim_tape_sprecf (uptr, &tbc)) /* space rec fwd, err? */
|
||||||
|
r = ms_map_err (uptr, st); /* map error */
|
||||||
|
if (tbc & 1) msc_sta = msc_sta | STA_ODD;
|
||||||
|
else msc_sta = msc_sta & ~STA_ODD;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FNC_FSR: /* space forward */
|
case FNC_BSR:
|
||||||
ms_forwsp (uptr, &err);
|
if (st = sim_tape_sprecr (uptr, &tbc)) /* space rec rev, err? */
|
||||||
|
r = ms_map_err (uptr, st); /* map error */
|
||||||
|
if (tbc & 1) msc_sta = msc_sta | STA_ODD;
|
||||||
|
else msc_sta = msc_sta & ~STA_ODD;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FNC_FSF:
|
||||||
|
while ((st = sim_tape_sprecf (uptr, &tbc)) == MTSE_OK) ;
|
||||||
|
if (st == MTSE_TMK) /* stopped by tmk? */
|
||||||
|
msc_sta = msc_sta | STA_EOF | STA_ODD; /* normal status */
|
||||||
|
else r = ms_map_err (uptr, st); /* map error */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FNC_BSF:
|
case FNC_BSF:
|
||||||
while (ms_backsp (uptr, &err)) ; /* spc until EOF/BOT */
|
while ((st = sim_tape_sprecr (uptr, &tbc)) == MTSE_OK) ;
|
||||||
break;
|
if (st == MTSE_TMK) /* stopped by tmk? */
|
||||||
|
msc_sta = msc_sta | STA_EOF | STA_ODD; /* normal status */
|
||||||
case FNC_BSR: /* space reverse */
|
else r = ms_map_err (uptr, st); /* map error */
|
||||||
if (!pnu) { /* position ok? */
|
|
||||||
ms_backsp (uptr, &err); /* backspace */
|
|
||||||
if (msc_sta & STA_ODD) msc_sta = msc_sta | STA_PAR; }
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Unit service, continued */
|
/* Unit service, continued */
|
||||||
|
@ -434,21 +431,16 @@ case FNC_RFF: /* diagnostic read */
|
||||||
case FNC_RC: /* read */
|
case FNC_RC: /* read */
|
||||||
if (msc_1st) { /* first svc? */
|
if (msc_1st) { /* first svc? */
|
||||||
msc_1st = ms_ptr = 0; /* clr 1st flop */
|
msc_1st = ms_ptr = 0; /* clr 1st flop */
|
||||||
if (ms_rdlntf (uptr, &ms_max, &err)) { /* read rec lnt */
|
st = sim_tape_rdrecf (uptr, msxb, &ms_max, DBSIZE); /* read rec */
|
||||||
if (!err) { /* tmk or eom? */
|
if (st == MTSE_RECE) msc_sta = msc_sta | STA_PAR; /* rec in err? */
|
||||||
|
else if (st != MTSE_OK) { /* other error? */
|
||||||
|
r = ms_map_err (uptr, st); /* map error */
|
||||||
|
if (r == SCPE_OK) { /* recoverable? */
|
||||||
sim_activate (uptr, msc_gtime); /* sched IRG */
|
sim_activate (uptr, msc_gtime); /* sched IRG */
|
||||||
uptr->FNC = 0; /* NOP func */
|
uptr->FNC = 0; /* NOP func */
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
break; } /* err, done */
|
break; } /* err, done */
|
||||||
if (ms_max > DBSIZE) return SCPE_MTRLNT; /* record too long? */
|
}
|
||||||
i = fxread (msxb, sizeof (int8), ms_max, uptr->fileref);
|
|
||||||
if (err = ferror (uptr->fileref)) { /* error? */
|
|
||||||
msc_sta = msc_sta | STA_PAR; /* set flag */
|
|
||||||
MT_SET_PNU (uptr); /* pos not upd */
|
|
||||||
break; }
|
|
||||||
for ( ; i < ms_max; i++) msxb[i] = 0; /* fill with 0's */
|
|
||||||
uptr->pos = uptr->pos + ((ms_max + 1) & ~1) +
|
|
||||||
(2 * sizeof (t_mtrlnt)); } /* update position */
|
|
||||||
if (ms_ptr < ms_max) { /* more chars? */
|
if (ms_ptr < ms_max) { /* more chars? */
|
||||||
if (FLG (devd)) msc_sta = msc_sta | STA_TIM | STA_PAR;
|
if (FLG (devd)) msc_sta = msc_sta | STA_TIM | STA_PAR;
|
||||||
msd_buf = ((uint16) msxb[ms_ptr] << 8) | msxb[ms_ptr + 1];
|
msd_buf = ((uint16) msxb[ms_ptr] << 8) | msxb[ms_ptr + 1];
|
||||||
|
@ -475,7 +467,9 @@ case FNC_WC: /* write */
|
||||||
sim_activate (uptr, msc_xtime); /* re-activate */
|
sim_activate (uptr, msc_xtime); /* re-activate */
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
if (ms_ptr) { /* any data? write */
|
if (ms_ptr) { /* any data? write */
|
||||||
if (err = ms_wrtrec (uptr, ms_ptr)) break; }
|
if (st = sim_tape_wrrecf (uptr, msxb, ms_ptr)) { /* write, err? */
|
||||||
|
r = ms_map_err (uptr, st); /* map error */
|
||||||
|
break; } }
|
||||||
sim_activate (uptr, msc_gtime); /* sched IRG */
|
sim_activate (uptr, msc_gtime); /* sched IRG */
|
||||||
uptr->FNC = 0; /* NOP func */
|
uptr->FNC = 0; /* NOP func */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -485,94 +479,40 @@ default: /* unknown */
|
||||||
|
|
||||||
setFLG (devc); /* set cch flg */
|
setFLG (devc); /* set cch flg */
|
||||||
msc_sta = msc_sta & ~STA_BUSY; /* update status */
|
msc_sta = msc_sta & ~STA_BUSY; /* update status */
|
||||||
if (err != 0) { /* I/O error */
|
|
||||||
perror ("MT I/O error");
|
|
||||||
clearerr (uptr->fileref);
|
|
||||||
if (msc_stopioe) return SCPE_IOERR; }
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tape motion routines */
|
/* Map tape error status */
|
||||||
|
|
||||||
t_bool ms_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
t_stat ms_map_err (UNIT *uptr, t_stat st)
|
||||||
{
|
{
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* position */
|
switch (st) {
|
||||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref); /* get bc */
|
case MTSE_FMT: /* illegal fmt */
|
||||||
if ((*err = ferror (uptr->fileref)) || /* error or eom? */
|
case MTSE_UNATT: /* unattached */
|
||||||
feof (uptr->fileref) || (*tbc == MTR_EOM)) {
|
msc_sta = msc_sta | STA_REJ; /* reject */
|
||||||
msc_sta = msc_sta | STA_PAR; /* error */
|
case MTSE_OK: /* no error */
|
||||||
MT_SET_PNU (uptr); /* pos not upd */
|
return SCPE_IERR; /* never get here! */
|
||||||
return TRUE; }
|
case MTSE_TMK: /* end of file */
|
||||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
|
||||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt);
|
|
||||||
msc_sta = msc_sta | STA_EOF | STA_ODD; /* eof (also sets odd) */
|
msc_sta = msc_sta | STA_EOF | STA_ODD; /* eof (also sets odd) */
|
||||||
return TRUE; }
|
break;
|
||||||
if (MTRF (*tbc)) msc_sta = msc_sta | STA_PAR; /* error in rec? */
|
case MTSE_INVRL: /* invalid rec lnt */
|
||||||
*tbc = MTRL (*tbc); /* clear err flag */
|
msc_sta = msc_sta | STA_PAR;
|
||||||
if (*tbc & 1) msc_sta = msc_sta | STA_ODD;
|
return SCPE_MTRLNT;
|
||||||
else msc_sta = msc_sta & ~STA_ODD;
|
case MTSE_IOERR: /* IO error */
|
||||||
return FALSE;
|
msc_sta = msc_sta | STA_PAR; /* error */
|
||||||
}
|
if (msc_stopioe) return SCPE_IOERR;
|
||||||
|
break;
|
||||||
t_bool ms_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
case MTSE_RECE: /* record in error */
|
||||||
{
|
case MTSE_EOM: /* end of medium */
|
||||||
if (uptr->pos < sizeof (t_mtrlnt)) { /* at bot? */
|
msc_sta = msc_sta | STA_PAR; /* error */
|
||||||
|
break;
|
||||||
|
case MTSE_BOT: /* reverse into BOT */
|
||||||
uptr->UST = STA_BOT; /* set status */
|
uptr->UST = STA_BOT; /* set status */
|
||||||
return TRUE; } /* error */
|
break;
|
||||||
fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET);
|
case MTSE_WRP: /* write protect */
|
||||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref); /* get bc */
|
msc_sta = msc_sta | STA_REJ; /* reject */
|
||||||
if ((*err = ferror (uptr->fileref)) || /* error or eof? */
|
break; }
|
||||||
feof (uptr->fileref)) {
|
return SCPE_OK;
|
||||||
msc_sta = msc_sta | STA_PAR; /* error */
|
|
||||||
return TRUE; }
|
|
||||||
if (*tbc == MTR_EOM) { /* eom? */
|
|
||||||
msc_sta = msc_sta | STA_PAR; /* error */
|
|
||||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over eom */
|
|
||||||
return TRUE; }
|
|
||||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
|
||||||
msc_sta = msc_sta | STA_EOF; /* eof */
|
|
||||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over tmk */
|
|
||||||
return TRUE; }
|
|
||||||
if (MTRF (*tbc)) msc_sta = msc_sta | STA_PAR; /* error in rec? */
|
|
||||||
*tbc = MTRL (*tbc); /* clear err flag */
|
|
||||||
if (*tbc & 1) msc_sta = msc_sta | STA_ODD;
|
|
||||||
else msc_sta = msc_sta & ~STA_ODD;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
t_bool ms_forwsp (UNIT *uptr, int32 *err)
|
|
||||||
{
|
|
||||||
t_mtrlnt tbc;
|
|
||||||
|
|
||||||
if (ms_rdlntf (uptr, &tbc, err)) return FALSE; /* read rec lnt, err? */
|
|
||||||
uptr->pos = uptr->pos + ((tbc + 1) & ~1) + /* incr tape position */
|
|
||||||
(2 * sizeof (t_mtrlnt));
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
t_bool ms_backsp (UNIT *uptr, int32 *err)
|
|
||||||
{
|
|
||||||
t_mtrlnt tbc;
|
|
||||||
|
|
||||||
if (ms_rdlntr (uptr, &tbc, err)) return FALSE; /* read rec lnt, err? */
|
|
||||||
uptr->pos = uptr->pos - ((MTRL (tbc) + 1) & ~1) - /* decr tape position */
|
|
||||||
(2 * sizeof (t_mtrlnt));
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 ms_wrtrec (UNIT *uptr, t_mtrlnt lnt)
|
|
||||||
{
|
|
||||||
int32 elnt = MTRL ((lnt + 1) & ~1); /* even lnt, no err */
|
|
||||||
|
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* seek to record */
|
|
||||||
fxwrite (&lnt, sizeof (t_mtrlnt), 1, uptr->fileref); /* write rec lnt */
|
|
||||||
fxwrite (msxb, sizeof (int8), elnt, uptr->fileref); /* write data */
|
|
||||||
fxwrite (&lnt, sizeof (t_mtrlnt), 1, uptr->fileref); /* write rec lnt */
|
|
||||||
if (ferror (uptr->fileref)) { /* error? */
|
|
||||||
MT_SET_PNU (uptr); /* pos not updated */
|
|
||||||
return 1; }
|
|
||||||
else uptr->pos = uptr->pos + elnt + (2 * sizeof (t_mtrlnt)); /* no, upd pos */
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset routine */
|
/* Reset routine */
|
||||||
|
@ -592,7 +532,7 @@ msc_dib.flg = msd_dib.flg = 1; /* set flg */
|
||||||
msc_dib.fbf = msd_dib.fbf = 1; /* set fbf */
|
msc_dib.fbf = msd_dib.fbf = 1; /* set fbf */
|
||||||
for (i = 0; i < MS_NUMDR; i++) {
|
for (i = 0; i < MS_NUMDR; i++) {
|
||||||
uptr = msc_dev.units + i;
|
uptr = msc_dev.units + i;
|
||||||
MT_CLR_PNU (uptr);
|
sim_tape_reset (uptr);
|
||||||
sim_cancel (uptr);
|
sim_cancel (uptr);
|
||||||
uptr->UST = 0; }
|
uptr->UST = 0; }
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -604,9 +544,8 @@ t_stat msc_attach (UNIT *uptr, char *cptr)
|
||||||
{
|
{
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
r = attach_unit (uptr, cptr); /* attach unit */
|
r = sim_tape_attach (uptr, cptr); /* attach unit */
|
||||||
if (r != SCPE_OK) return r; /* update status */
|
if (r != SCPE_OK) return r; /* update status */
|
||||||
MT_CLR_PNU (uptr);
|
|
||||||
uptr->UST = STA_BOT;
|
uptr->UST = STA_BOT;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -616,16 +555,7 @@ return r;
|
||||||
t_stat msc_detach (UNIT* uptr)
|
t_stat msc_detach (UNIT* uptr)
|
||||||
{
|
{
|
||||||
uptr->UST = 0; /* update status */
|
uptr->UST = 0; /* update status */
|
||||||
MT_CLR_PNU (uptr);
|
return sim_tape_detach (uptr); /* detach unit */
|
||||||
return detach_unit (uptr); /* detach unit */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write lock/enable routine */
|
|
||||||
|
|
||||||
t_stat msc_vlock (UNIT *uptr, int32 val, char *cptr, void *desc)
|
|
||||||
{
|
|
||||||
if (val && (uptr->flags & UNIT_ATT)) return SCPE_ARG;
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set controller type */
|
/* Set controller type */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* hp2100_mt.c: HP 2100 12559A magnetic tape simulator
|
/* hp2100_mt.c: HP 2100 12559A magnetic tape simulator
|
||||||
|
|
||||||
Copyright (c) 1993-2002, Robert M. Supnik
|
Copyright (c) 1993-2003, Robert M. Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
mt 12559A 3030 nine track magnetic tape
|
mt 12559A 3030 nine track magnetic tape
|
||||||
|
|
||||||
|
28-Feb-03 RMS Revised for magtape library
|
||||||
30-Sep-02 RMS Revamped error handling
|
30-Sep-02 RMS Revamped error handling
|
||||||
28-Aug-02 RMS Added end of medium support
|
28-Aug-02 RMS Added end of medium support
|
||||||
30-May-02 RMS Widened POS to 32b
|
30-May-02 RMS Widened POS to 32b
|
||||||
|
@ -54,15 +55,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "hp2100_defs.h"
|
#include "hp2100_defs.h"
|
||||||
|
#include "sim_tape.h"
|
||||||
|
|
||||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
|
||||||
#define UNIT_V_PNU (UNIT_V_UF + 1) /* pos not updated */
|
|
||||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
|
||||||
#define UNIT_PNU (1 << UNIT_V_PNU)
|
|
||||||
#define DB_V_SIZE 16 /* max data buf */
|
#define DB_V_SIZE 16 /* max data buf */
|
||||||
#define DBSIZE (1 << DB_V_SIZE) /* max data cmd */
|
#define DBSIZE (1 << DB_V_SIZE) /* max data cmd */
|
||||||
#define DBMASK (DBSIZE - 1)
|
|
||||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
|
||||||
|
|
||||||
/* Command - mtc_fnc */
|
/* Command - mtc_fnc */
|
||||||
|
|
||||||
|
@ -108,12 +104,9 @@ int32 mtdio (int32 inst, int32 IR, int32 dat);
|
||||||
int32 mtcio (int32 inst, int32 IR, int32 dat);
|
int32 mtcio (int32 inst, int32 IR, int32 dat);
|
||||||
t_stat mtc_svc (UNIT *uptr);
|
t_stat mtc_svc (UNIT *uptr);
|
||||||
t_stat mtc_reset (DEVICE *dptr);
|
t_stat mtc_reset (DEVICE *dptr);
|
||||||
t_stat mtc_vlock (UNIT *uptr, int32 val, char *cptr, void *desc);
|
|
||||||
t_stat mtc_attach (UNIT *uptr, char *cptr);
|
t_stat mtc_attach (UNIT *uptr, char *cptr);
|
||||||
t_stat mtc_detach (UNIT *uptr);
|
t_stat mtc_detach (UNIT *uptr);
|
||||||
t_bool mt_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
t_stat mt_map_err (UNIT *uptr, t_stat st);
|
||||||
t_bool mt_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
|
||||||
int32 mt_wrtrec (UNIT *uptr, t_mtrlnt lnt);
|
|
||||||
|
|
||||||
/* MTD data structures
|
/* MTD data structures
|
||||||
|
|
||||||
|
@ -143,6 +136,8 @@ REG mtd_reg[] = {
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
MTAB mtd_mod[] = {
|
MTAB mtd_mod[] = {
|
||||||
|
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||||
|
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
|
||||||
{ MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO",
|
{ MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO",
|
||||||
&hp_setdev, &hp_showdev, &mtd_dev },
|
&hp_setdev, &hp_showdev, &mtd_dev },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
@ -183,8 +178,6 @@ REG mtc_reg[] = {
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
MTAB mtc_mod[] = {
|
MTAB mtc_mod[] = {
|
||||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", &mtc_vlock },
|
|
||||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", &mtc_vlock },
|
|
||||||
{ MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO",
|
{ MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO",
|
||||||
&hp_setdev, &hp_showdev, &mtd_dev },
|
&hp_setdev, &hp_showdev, &mtd_dev },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
@ -234,6 +227,7 @@ return dat;
|
||||||
int32 mtcio (int32 inst, int32 IR, int32 dat)
|
int32 mtcio (int32 inst, int32 IR, int32 dat)
|
||||||
{
|
{
|
||||||
int32 i, devc, devd, valid;
|
int32 i, devc, devd, valid;
|
||||||
|
t_stat st;
|
||||||
|
|
||||||
devc = IR & I_DEVMASK; /* get device no */
|
devc = IR & I_DEVMASK; /* get device no */
|
||||||
devd = devc - 1;
|
devd = devc - 1;
|
||||||
|
@ -252,8 +246,9 @@ case ioOTX: /* output */
|
||||||
mtc_sta = mtc_sta & ~STA_REJ; /* clear reject */
|
mtc_sta = mtc_sta & ~STA_REJ; /* clear reject */
|
||||||
if (dat == FNC_CLR) { /* clear? */
|
if (dat == FNC_CLR) { /* clear? */
|
||||||
if (sim_is_active (&mtc_unit) && /* write in prog? */
|
if (sim_is_active (&mtc_unit) && /* write in prog? */
|
||||||
(mtc_fnc == FNC_WC) && (mt_ptr > 0)) /* yes, bad rec */
|
(mtc_fnc == FNC_WC) && (mt_ptr > 0)) { /* yes, bad rec */
|
||||||
mt_wrtrec (&mtc_unit, mt_ptr | MTR_ERF);
|
if (st = sim_tape_wrrecf (&mtc_unit, mtxb, mt_ptr | MTR_ERF))
|
||||||
|
mt_map_err (&mtc_unit, st); }
|
||||||
if (((mtc_fnc == FNC_REW) || (mtc_fnc == FNC_RWS)) &&
|
if (((mtc_fnc == FNC_REW) || (mtc_fnc == FNC_RWS)) &&
|
||||||
sim_is_active (&mtc_unit)) sim_cancel (&mtc_unit);
|
sim_is_active (&mtc_unit)) sim_cancel (&mtc_unit);
|
||||||
mtc_1st = mtc_dtf = 0;
|
mtc_1st = mtc_dtf = 0;
|
||||||
|
@ -267,7 +262,7 @@ case ioOTX: /* output */
|
||||||
if (dat == mtc_cmd[i]) valid = 1;
|
if (dat == mtc_cmd[i]) valid = 1;
|
||||||
if (!valid || sim_is_active (&mtc_unit) || /* is cmd valid? */
|
if (!valid || sim_is_active (&mtc_unit) || /* is cmd valid? */
|
||||||
((mtc_sta & STA_BOT) && (dat == FNC_BSR)) ||
|
((mtc_sta & STA_BOT) && (dat == FNC_BSR)) ||
|
||||||
((mtc_unit.flags & UNIT_WPRT) &&
|
(sim_tape_wrp (&mtc_unit) &&
|
||||||
((dat == FNC_WC) || (dat == FNC_GAP) || (dat == FNC_WFM))))
|
((dat == FNC_WC) || (dat == FNC_GAP) || (dat == FNC_WFM))))
|
||||||
mtc_sta = mtc_sta | STA_REJ;
|
mtc_sta = mtc_sta | STA_REJ;
|
||||||
else {
|
else {
|
||||||
|
@ -286,7 +281,7 @@ case ioMIX: /* merge */
|
||||||
dat = dat | (mtc_sta & ~(STA_LOCAL | STA_WLK | STA_BUSY));
|
dat = dat | (mtc_sta & ~(STA_LOCAL | STA_WLK | STA_BUSY));
|
||||||
if (mtc_unit.flags & UNIT_ATT) { /* construct status */
|
if (mtc_unit.flags & UNIT_ATT) { /* construct status */
|
||||||
if (sim_is_active (&mtc_unit)) dat = dat | STA_BUSY;
|
if (sim_is_active (&mtc_unit)) dat = dat | STA_BUSY;
|
||||||
if (mtc_unit.flags & UNIT_WPRT) dat = dat | STA_WLK; }
|
if (sim_tape_wrp (&mtc_unit)) dat = dat | STA_WLK; }
|
||||||
else dat = dat | STA_BUSY | STA_LOCAL;
|
else dat = dat | STA_BUSY | STA_LOCAL;
|
||||||
break;
|
break;
|
||||||
case ioCTL: /* control clear/set */
|
case ioCTL: /* control clear/set */
|
||||||
|
@ -309,10 +304,10 @@ return dat;
|
||||||
|
|
||||||
t_stat mtc_svc (UNIT *uptr)
|
t_stat mtc_svc (UNIT *uptr)
|
||||||
{
|
{
|
||||||
int32 devc, devd, err, pnu;
|
int32 devc, devd;
|
||||||
static t_mtrlnt i, bceof = { MTR_TMK };
|
t_mtrlnt tbc;
|
||||||
|
t_stat st, r = SCPE_OK;
|
||||||
|
|
||||||
err = 0; /* assume no errors */
|
|
||||||
devc = mtc_dib.devno; /* get device nos */
|
devc = mtc_dib.devno; /* get device nos */
|
||||||
devd = mtd_dib.devno;
|
devd = mtd_dib.devno;
|
||||||
if ((mtc_unit.flags & UNIT_ATT) == 0) { /* offline? */
|
if ((mtc_unit.flags & UNIT_ATT) == 0) { /* offline? */
|
||||||
|
@ -320,66 +315,54 @@ if ((mtc_unit.flags & UNIT_ATT) == 0) { /* offline? */
|
||||||
setFLG (devc); /* set cch flg */
|
setFLG (devc); /* set cch flg */
|
||||||
return IORETURN (mtc_stopioe, SCPE_UNATT); }
|
return IORETURN (mtc_stopioe, SCPE_UNATT); }
|
||||||
|
|
||||||
pnu = MT_TST_PNU (uptr); /* get pos not upd */
|
|
||||||
MT_CLR_PNU (uptr); /* and clear */
|
|
||||||
switch (mtc_fnc) { /* case on function */
|
switch (mtc_fnc) { /* case on function */
|
||||||
|
|
||||||
case FNC_REW: /* rewind */
|
case FNC_REW: /* rewind */
|
||||||
mtc_unit.pos = 0; /* BOT */
|
sim_tape_rewind (uptr); /* BOT */
|
||||||
mtc_sta = STA_BOT; /* update status */
|
mtc_sta = STA_BOT; /* update status */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FNC_RWS: /* rewind and offline */
|
case FNC_RWS: /* rewind and offline */
|
||||||
mtc_unit.pos = 0; /* clear position */
|
sim_tape_rewind (uptr); /* clear position */
|
||||||
return detach_unit (uptr); /* don't set cch flg */
|
return sim_tape_detach (uptr); /* don't set cch flg */
|
||||||
|
|
||||||
case FNC_WFM: /* write file mark */
|
case FNC_WFM: /* write file mark */
|
||||||
fseek (mtc_unit.fileref, mtc_unit.pos, SEEK_SET);
|
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
|
||||||
fxwrite (&bceof, sizeof (t_mtrlnt), 1, mtc_unit.fileref);
|
r = mt_map_err (uptr, st); /* map error */
|
||||||
mtc_sta = STA_EOF; /* set EOF status */
|
mtc_sta = STA_EOF; /* set EOF status */
|
||||||
if (err = ferror (mtc_unit.fileref)) MT_SET_PNU (uptr);
|
|
||||||
else mtc_unit.pos = mtc_unit.pos + sizeof (t_mtrlnt); /* update tape pos */
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FNC_GAP: /* erase gap */
|
case FNC_GAP: /* erase gap */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FNC_FSR: /* space forward */
|
case FNC_FSR: /* space forward */
|
||||||
if (mt_rdlntf (uptr, &mt_max, &err)) break; /* read rec lnt, err? */
|
if (st = sim_tape_sprecf (uptr, &tbc)) /* space rec fwd, err? */
|
||||||
mtc_unit.pos = mtc_unit.pos + ((mt_max + 1) & ~1) +
|
r = mt_map_err (uptr, st); /* map error */
|
||||||
(2 * sizeof (t_mtrlnt)); /* update position */
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FNC_BSR: /* space reverse */
|
case FNC_BSR: /* space reverse */
|
||||||
if (pnu) break; /* pnu? do nothing */
|
if (st = sim_tape_sprecr (uptr, &tbc)) /* space rec rev, err? */
|
||||||
if (mt_rdlntr (uptr, &mt_max, &err)) break; /* read rec lnt, err? */
|
r = mt_map_err (uptr, st); /* map error */
|
||||||
mtc_unit.pos = mtc_unit.pos - ((mt_max + 1) & ~1) -
|
|
||||||
(2 * sizeof (t_mtrlnt)); /* update position */
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Unit service, continued */
|
/* Unit service, continued */
|
||||||
|
|
||||||
case FNC_RC: /* read */
|
case FNC_RC: /* read */
|
||||||
if (mtc_1st) { /* first svc? */
|
if (mtc_1st) { /* first svc? */
|
||||||
mtc_1st = 0; /* clr 1st flop */
|
mtc_1st = mt_ptr = 0; /* clr 1st flop */
|
||||||
if (mt_rdlntf (uptr, &mt_max, &err)) { /* read rec lnt */
|
st = sim_tape_rdrecf (uptr, mtxb, &mt_max, DBSIZE); /* read rec */
|
||||||
if (!err) { /* tmk or eom? */
|
if (st == MTSE_RECE) mtc_sta = mtc_sta | STA_PAR; /* rec in err? */
|
||||||
|
else if (st != MTSE_OK) { /* other error? */
|
||||||
|
r = mt_map_err (uptr, st); /* map error */
|
||||||
|
if (r == SCPE_OK) { /* recoverable? */
|
||||||
sim_activate (uptr, mtc_gtime); /* sched IRG */
|
sim_activate (uptr, mtc_gtime); /* sched IRG */
|
||||||
mtc_fnc = 0; /* NOP func */
|
mtc_fnc = 0; /* NOP func */
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
break; } /* error, done */
|
break; } /* non-recov, done */
|
||||||
if (mt_max > DBSIZE) return SCPE_MTRLNT; /* record too long? */
|
|
||||||
if (mt_max < 12) { /* record too short? */
|
if (mt_max < 12) { /* record too short? */
|
||||||
mtc_sta = mtc_sta | STA_PAR; /* set flag */
|
mtc_sta = mtc_sta | STA_PAR; /* set flag */
|
||||||
break; }
|
break; }
|
||||||
i = fxread (mtxb, sizeof (int8), mt_max, mtc_unit.fileref);
|
}
|
||||||
for ( ; i < mt_max; i++) mtxb[i] = 0; /* fill with 0's */
|
|
||||||
if (err = ferror (mtc_unit.fileref)) { /* error? */
|
|
||||||
mtc_sta = mtc_sta | STA_PAR; /* set flag */
|
|
||||||
MT_SET_PNU (uptr); /* pos not upd */
|
|
||||||
break; }
|
|
||||||
mtc_unit.pos = mtc_unit.pos + ((mt_max + 1) & ~1) +
|
|
||||||
(2 * sizeof (t_mtrlnt)); } /* update position */
|
|
||||||
if (mt_ptr < mt_max) { /* more chars? */
|
if (mt_ptr < mt_max) { /* more chars? */
|
||||||
if (FLG (devd)) mtc_sta = mtc_sta | STA_TIM;
|
if (FLG (devd)) mtc_sta = mtc_sta | STA_TIM;
|
||||||
mtc_unit.buf = mtxb[mt_ptr++]; /* fetch next */
|
mtc_unit.buf = mtxb[mt_ptr++]; /* fetch next */
|
||||||
|
@ -402,7 +385,9 @@ case FNC_WC: /* write */
|
||||||
sim_activate (uptr, mtc_xtime); /* re-activate */
|
sim_activate (uptr, mtc_xtime); /* re-activate */
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
if (mt_ptr) { /* write buffer */
|
if (mt_ptr) { /* write buffer */
|
||||||
if (err = mt_wrtrec (uptr, mt_ptr)) break; }
|
if (st = sim_tape_wrrecf (uptr, mtxb, mt_ptr)) { /* write, err? */
|
||||||
|
r = mt_map_err (uptr, st); /* map error */
|
||||||
|
break; } } /* done */
|
||||||
sim_activate (uptr, mtc_gtime); /* schedule gap */
|
sim_activate (uptr, mtc_gtime); /* schedule gap */
|
||||||
mtc_fnc = 0; /* nop */
|
mtc_fnc = 0; /* nop */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -412,70 +397,40 @@ default: /* unknown */
|
||||||
|
|
||||||
setFLG (devc); /* set cch flg */
|
setFLG (devc); /* set cch flg */
|
||||||
mtc_sta = mtc_sta & ~STA_BUSY; /* not busy */
|
mtc_sta = mtc_sta & ~STA_BUSY; /* not busy */
|
||||||
if (err != 0) { /* I/O error */
|
|
||||||
perror ("MT I/O error");
|
|
||||||
clearerr (mtc_unit.fileref);
|
|
||||||
if (mtc_stopioe) return SCPE_IOERR; }
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tape motion routines */
|
/* Map tape error status */
|
||||||
|
|
||||||
t_bool mt_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
t_stat mt_map_err (UNIT *uptr, t_stat st)
|
||||||
{
|
{
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* position */
|
switch (st) {
|
||||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref); /* get bc */
|
case MTSE_FMT: /* illegal fmt */
|
||||||
if ((*err = ferror (uptr->fileref)) || /* error or eom? */
|
case MTSE_UNATT: /* unattached */
|
||||||
feof (uptr->fileref) || (*tbc == MTR_EOM)) {
|
mtc_sta = mtc_sta | STA_REJ; /* reject */
|
||||||
mtc_sta = mtc_sta | STA_PAR; /* error */
|
case MTSE_OK: /* no error */
|
||||||
MT_SET_PNU (uptr); /* pos not upd */
|
return SCPE_IERR; /* never get here! */
|
||||||
return TRUE; }
|
case MTSE_TMK: /* end of file */
|
||||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
|
||||||
mtc_sta = mtc_sta | STA_EOF; /* eof */
|
mtc_sta = mtc_sta | STA_EOF; /* eof */
|
||||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* spc over tmk */
|
break;
|
||||||
return TRUE; }
|
case MTSE_IOERR: /* IO error */
|
||||||
if (MTRF (*tbc)) mtc_sta = mtc_sta | STA_PAR; /* error in rec? */
|
|
||||||
*tbc = MTRL (*tbc); /* clear err flag */
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
t_bool mt_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
|
||||||
{
|
|
||||||
if (uptr->pos < sizeof (t_mtrlnt)) { /* no data to read? */
|
|
||||||
mtc_sta = mtc_sta | STA_BOT; /* update status */
|
|
||||||
return TRUE; }
|
|
||||||
fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET);
|
|
||||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref); /* get bc */
|
|
||||||
if ((*err = ferror (uptr->fileref)) || /* error or eof? */
|
|
||||||
feof (uptr->fileref)) {
|
|
||||||
mtc_sta = mtc_sta | STA_PAR; /* error */
|
mtc_sta = mtc_sta | STA_PAR; /* error */
|
||||||
return TRUE; }
|
if (mtc_stopioe) return SCPE_IOERR;
|
||||||
if (*tbc == MTR_EOM) { /* eom? */
|
break;
|
||||||
|
case MTSE_INVRL: /* invalid rec lnt */
|
||||||
|
mtc_sta = mtc_sta | STA_PAR;
|
||||||
|
return SCPE_MTRLNT;
|
||||||
|
case MTSE_RECE: /* record in error */
|
||||||
|
case MTSE_EOM: /* end of medium */
|
||||||
mtc_sta = mtc_sta | STA_PAR; /* error */
|
mtc_sta = mtc_sta | STA_PAR; /* error */
|
||||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over eom */
|
break;
|
||||||
return TRUE; }
|
case MTSE_BOT: /* reverse into BOT */
|
||||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
mtc_sta = mtc_sta | STA_BOT; /* set status */
|
||||||
mtc_sta = mtc_sta | STA_EOF; /* eof */
|
break;
|
||||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over tmk */
|
case MTSE_WRP: /* write protect */
|
||||||
return TRUE; }
|
mtc_sta = mtc_sta | STA_REJ; /* reject */
|
||||||
if (MTRF (*tbc)) mtc_sta = mtc_sta | STA_PAR; /* error in rec? */
|
break; }
|
||||||
*tbc = MTRL (*tbc); /* clear err flag */
|
return SCPE_OK;
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 mt_wrtrec (UNIT *uptr, t_mtrlnt lnt)
|
|
||||||
{
|
|
||||||
int32 elnt = MTRL ((lnt + 1) & ~1); /* even lnt, no err */
|
|
||||||
|
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* seek to record */
|
|
||||||
fxwrite (&lnt, sizeof (t_mtrlnt), 1, uptr->fileref); /* write rec lnt */
|
|
||||||
fxwrite (mtxb, sizeof (int8), elnt, uptr->fileref); /* write data */
|
|
||||||
fxwrite (&lnt, sizeof (t_mtrlnt), 1, uptr->fileref); /* write rec lnt */
|
|
||||||
if (ferror (uptr->fileref)) { /* error? */
|
|
||||||
MT_SET_PNU (uptr); /* pos not updated */
|
|
||||||
return 1; }
|
|
||||||
else uptr->pos = uptr->pos + elnt + (2 * sizeof (t_mtrlnt)); /* no, upd pos */
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset routine */
|
/* Reset routine */
|
||||||
|
@ -490,9 +445,10 @@ mtc_dib.ctl = mtd_dib.ctl = 0; /* clear ctl */
|
||||||
mtc_dib.flg = mtd_dib.flg = 0; /* clear flg */
|
mtc_dib.flg = mtd_dib.flg = 0; /* clear flg */
|
||||||
mtc_dib.fbf = mtd_dib.fbf = 0; /* clear fbf */
|
mtc_dib.fbf = mtd_dib.fbf = 0; /* clear fbf */
|
||||||
sim_cancel (&mtc_unit); /* cancel activity */
|
sim_cancel (&mtc_unit); /* cancel activity */
|
||||||
mtc_unit.flags = mtc_unit.flags & ~UNIT_PNU; /* clear pos flag */
|
sim_tape_reset (&mtc_unit);
|
||||||
if (mtc_unit.flags & UNIT_ATT) mtc_sta = ((mtc_unit.pos)? 0: STA_BOT) |
|
if (mtc_unit.flags & UNIT_ATT) mtc_sta =
|
||||||
((mtc_unit.flags & UNIT_WPRT)? STA_WLK: 0);
|
(sim_tape_bot (&mtc_unit)? STA_BOT: 0) |
|
||||||
|
(sim_tape_wrp (&mtc_unit)? STA_WLK: 0);
|
||||||
else mtc_sta = STA_LOCAL | STA_BUSY;
|
else mtc_sta = STA_LOCAL | STA_BUSY;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -503,9 +459,8 @@ t_stat mtc_attach (UNIT *uptr, char *cptr)
|
||||||
{
|
{
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
r = attach_unit (uptr, cptr); /* attach unit */
|
r = sim_tape_attach (uptr, cptr); /* attach unit */
|
||||||
if (r != SCPE_OK) return r; /* update status */
|
if (r != SCPE_OK) return r; /* update status */
|
||||||
MT_CLR_PNU (uptr);
|
|
||||||
mtc_sta = STA_BOT;
|
mtc_sta = STA_BOT;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -515,14 +470,5 @@ return r;
|
||||||
t_stat mtc_detach (UNIT* uptr)
|
t_stat mtc_detach (UNIT* uptr)
|
||||||
{
|
{
|
||||||
mtc_sta = 0; /* update status */
|
mtc_sta = 0; /* update status */
|
||||||
MT_CLR_PNU (uptr);
|
return sim_tape_detach (uptr); /* detach unit */
|
||||||
return detach_unit (uptr); /* detach unit */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write lock/enable routine */
|
|
||||||
|
|
||||||
t_stat mtc_vlock (UNIT *uptr, int32 val, char *cptr, void *desc)
|
|
||||||
{
|
|
||||||
if (val && (uptr->flags & UNIT_ATT)) return SCPE_ARG;
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
}
|
||||||
|
|
142
I1401/i1401_mt.c
142
I1401/i1401_mt.c
|
@ -1,6 +1,6 @@
|
||||||
/* i1401_mt.c: IBM 1401 magnetic tape simulator
|
/* i1401_mt.c: IBM 1401 magnetic tape simulator
|
||||||
|
|
||||||
Copyright (c) 1993-2002, Robert M. Supnik
|
Copyright (c) 1993-2003, Robert M. Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
mt 7-track magtape
|
mt 7-track magtape
|
||||||
|
|
||||||
|
28-Feb-03 RMS Modified for magtape library
|
||||||
31-Oct-02 RMS Added error record handling
|
31-Oct-02 RMS Added error record handling
|
||||||
10-Oct-02 RMS Fixed end-of-record on load read writes WM plus GM
|
10-Oct-02 RMS Fixed end-of-record on load read writes WM plus GM
|
||||||
30-Sep-02 RMS Revamped error handling
|
30-Sep-02 RMS Revamped error handling
|
||||||
|
@ -59,13 +60,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "i1401_defs.h"
|
#include "i1401_defs.h"
|
||||||
|
#include "sim_tape.h"
|
||||||
|
|
||||||
#define MT_NUMDR 7 /* #drives */
|
#define MT_NUMDR 7 /* #drives */
|
||||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
|
||||||
#define UNIT_V_PNU (UNIT_V_UF + 1) /* pos not upd */
|
|
||||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
|
||||||
#define UNIT_PNU (1 << UNIT_V_PNU)
|
|
||||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
|
||||||
#define MT_MAXFR (MAXMEMSIZE * 2) /* max transfer */
|
#define MT_MAXFR (MAXMEMSIZE * 2) /* max transfer */
|
||||||
|
|
||||||
extern uint8 M[]; /* memory */
|
extern uint8 M[]; /* memory */
|
||||||
|
@ -75,7 +72,7 @@ extern UNIT cpu_unit;
|
||||||
uint8 dbuf[MT_MAXFR]; /* tape buffer */
|
uint8 dbuf[MT_MAXFR]; /* tape buffer */
|
||||||
t_stat mt_reset (DEVICE *dptr);
|
t_stat mt_reset (DEVICE *dptr);
|
||||||
t_stat mt_boot (int32 unitno, DEVICE *dptr);
|
t_stat mt_boot (int32 unitno, DEVICE *dptr);
|
||||||
t_stat mt_attach (UNIT *uptr, char *cptr);
|
t_stat mt_map_status (t_stat st);
|
||||||
UNIT *get_unit (int32 unit);
|
UNIT *get_unit (int32 unit);
|
||||||
|
|
||||||
/* MT data structures
|
/* MT data structures
|
||||||
|
@ -113,15 +110,15 @@ REG mt_reg[] = {
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
MTAB mt_mod[] = {
|
MTAB mt_mod[] = {
|
||||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
|
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
|
||||||
DEVICE mt_dev = {
|
DEVICE mt_dev = {
|
||||||
"MT", mt_unit, mt_reg, mt_mod,
|
"MT", mt_unit, mt_reg, mt_mod,
|
||||||
MT_NUMDR, 10, 31, 1, 8, 8,
|
MT_NUMDR, 10, 31, 1, 8, 8,
|
||||||
NULL, NULL, &mt_reset,
|
NULL, NULL, &mt_reset,
|
||||||
&mt_boot, &mt_attach, NULL };
|
&mt_boot, &sim_tape_attach, &sim_tape_detach };
|
||||||
|
|
||||||
/* Function routine
|
/* Function routine
|
||||||
|
|
||||||
|
@ -134,59 +131,38 @@ DEVICE mt_dev = {
|
||||||
|
|
||||||
t_stat mt_func (int32 unit, int32 mod)
|
t_stat mt_func (int32 unit, int32 mod)
|
||||||
{
|
{
|
||||||
int32 err, pnu;
|
|
||||||
t_mtrlnt tbc;
|
t_mtrlnt tbc;
|
||||||
UNIT *uptr;
|
UNIT *uptr;
|
||||||
static t_mtrlnt bceof = { MTR_TMK };
|
t_stat st;
|
||||||
|
|
||||||
if ((uptr = get_unit (unit)) == NULL) return STOP_INVMTU; /* valid unit? */
|
if ((uptr = get_unit (unit)) == NULL) return STOP_INVMTU; /* valid unit? */
|
||||||
pnu = MT_TST_PNU (uptr); /* get pos not upd */
|
|
||||||
MT_CLR_PNU (uptr); /* and clear */
|
|
||||||
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */
|
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */
|
||||||
switch (mod) { /* case on modifier */
|
switch (mod) { /* case on modifier */
|
||||||
case BCD_B: /* backspace */
|
case BCD_B: /* backspace */
|
||||||
ind[IN_END] = 0; /* clear end of reel */
|
ind[IN_END] = 0; /* clear end of file */
|
||||||
if (pnu || (uptr->pos < sizeof (t_mtrlnt))) /* bot or pnu? */
|
st = sim_tape_sprecr (uptr, &tbc); /* space rev */
|
||||||
return SCPE_OK;
|
|
||||||
fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET);
|
|
||||||
fxread (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
|
||||||
if ((err = ferror (uptr->fileref)) || /* err or eof? */
|
|
||||||
feof (uptr->fileref)) break;
|
|
||||||
if ((tbc == MTR_TMK) || (tbc == MTR_EOM)) /* tmk or eom? */
|
|
||||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt);
|
|
||||||
else uptr->pos = uptr->pos - ((MTRL (tbc) + 1) & ~1) -
|
|
||||||
(2 * sizeof (t_mtrlnt));
|
|
||||||
break; /* end case */
|
break; /* end case */
|
||||||
|
|
||||||
case BCD_E: /* erase = nop */
|
case BCD_E: /* erase = nop */
|
||||||
if (uptr->flags & UNIT_WPRT) return STOP_MTL;
|
if (sim_tape_wrp (uptr)) return STOP_MTL;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
|
||||||
case BCD_M: /* write tapemark */
|
case BCD_M: /* write tapemark */
|
||||||
if (uptr->flags & UNIT_WPRT) return STOP_MTL;
|
st = sim_tape_wrtmk (uptr); /* write tmk */
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
|
||||||
fxwrite (&bceof, sizeof (t_mtrlnt), 1, uptr->fileref);
|
|
||||||
if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr); /* error */
|
|
||||||
else uptr->pos = uptr->pos + sizeof (t_mtrlnt);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BCD_R: /* rewind */
|
case BCD_R: /* rewind */
|
||||||
uptr->pos = 0; /* update position */
|
sim_tape_rewind (uptr); /* update position */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
|
||||||
case BCD_U: /* unload */
|
case BCD_U: /* unload */
|
||||||
uptr->pos = 0; /* update position */
|
sim_tape_rewind (uptr); /* update position */
|
||||||
return detach_unit (uptr); /* detach */
|
return detach_unit (uptr); /* detach */
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return STOP_INVM; }
|
return STOP_INVM; }
|
||||||
|
|
||||||
if (err != 0) { /* I/O error */
|
return mt_map_status (st);
|
||||||
perror ("MT I/O error");
|
|
||||||
clearerr (uptr->fileref);
|
|
||||||
ind[IN_TAP] = 1; /* set indicator */
|
|
||||||
if (iochk) return SCPE_IOERR; }
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read and write routines
|
/* Read and write routines
|
||||||
|
@ -201,37 +177,21 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat mt_io (int32 unit, int32 flag, int32 mod)
|
t_stat mt_io (int32 unit, int32 flag, int32 mod)
|
||||||
{
|
{
|
||||||
int32 err, t, wm_seen;
|
int32 t, wm_seen;
|
||||||
t_mtrlnt i, tbc, ebc;
|
t_mtrlnt i, tbc;
|
||||||
|
t_stat st;
|
||||||
UNIT *uptr;
|
UNIT *uptr;
|
||||||
|
|
||||||
if ((uptr = get_unit (unit)) == NULL) return STOP_INVMTU; /* valid unit? */
|
if ((uptr = get_unit (unit)) == NULL) return STOP_INVMTU; /* valid unit? */
|
||||||
uptr->flags = uptr->flags & ~UNIT_PNU; /* clr pos not upd */
|
|
||||||
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */
|
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */
|
||||||
|
|
||||||
switch (mod) {
|
switch (mod) {
|
||||||
case BCD_R: /* read */
|
case BCD_R: /* read */
|
||||||
ind[IN_TAP] = ind[IN_END] = 0; /* clear error */
|
ind[IN_TAP] = ind[IN_END] = 0; /* clear error */
|
||||||
wm_seen = 0; /* no word mk seen */
|
wm_seen = 0; /* no word mk seen */
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
st = sim_tape_rdrecf (uptr, dbuf, &tbc, MT_MAXFR); /* read rec */
|
||||||
fxread (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
if (st == MTSE_RECE) ind[IN_TAP] = 1; /* rec in error? */
|
||||||
if (err = ferror (uptr->fileref)) break; /* error? */
|
else if (st != MTSE_OK) break; /* stop on error */
|
||||||
if (feof (uptr->fileref) || (tbc == MTR_EOM)) { /* eom or eof? */
|
|
||||||
ind[IN_TAP] = 1; /* pretend error */
|
|
||||||
MT_SET_PNU (uptr); /* pos not upd */
|
|
||||||
break; }
|
|
||||||
if (tbc == MTR_TMK) { /* tape mark? */
|
|
||||||
ind[IN_END] = 1; /* set end mark */
|
|
||||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt);
|
|
||||||
break; }
|
|
||||||
if (MTRF (tbc)) ind[IN_TAP] = 1; /* error? set flag */
|
|
||||||
tbc = MTRL (tbc); /* clear error flag */
|
|
||||||
if (tbc > MT_MAXFR) return SCPE_MTRLNT; /* record too long? */
|
|
||||||
i = fxread (dbuf, sizeof (int8), tbc, uptr->fileref);
|
|
||||||
if (err = ferror (uptr->fileref)) break; /* I/O error? */
|
|
||||||
for ( ; i < tbc; i++) dbuf[i] = 0; /* fill with 0's */
|
|
||||||
uptr->pos = uptr->pos + ((tbc + 1) & ~1) +
|
|
||||||
(2 * sizeof (t_mtrlnt));
|
|
||||||
for (i = 0; i < tbc; i++) { /* loop thru buf */
|
for (i = 0; i < tbc; i++) { /* loop thru buf */
|
||||||
if (M[BS] == (BCD_GRPMRK + WM)) { /* GWM in memory? */
|
if (M[BS] == (BCD_GRPMRK + WM)) { /* GWM in memory? */
|
||||||
BS++; /* incr BS */
|
BS++; /* incr BS */
|
||||||
|
@ -260,7 +220,7 @@ case BCD_R: /* read */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BCD_W:
|
case BCD_W:
|
||||||
if (uptr->flags & UNIT_WPRT) return STOP_MTL; /* locked? */
|
if (uptr->flags & MTUF_WRP) return STOP_MTL; /* locked? */
|
||||||
if (M[BS] == (BCD_GRPMRK + WM)) return STOP_MTZ; /* eor? */
|
if (M[BS] == (BCD_GRPMRK + WM)) return STOP_MTZ; /* eor? */
|
||||||
ind[IN_TAP] = ind[IN_END] = 0; /* clear error */
|
ind[IN_TAP] = ind[IN_END] = 0; /* clear error */
|
||||||
for (tbc = 0; (t = M[BS++]) != (BCD_GRPMRK + WM); ) {
|
for (tbc = 0; (t = M[BS++]) != (BCD_GRPMRK + WM); ) {
|
||||||
|
@ -271,13 +231,7 @@ case BCD_W:
|
||||||
if (ADDR_ERR (BS)) { /* check next BS */
|
if (ADDR_ERR (BS)) { /* check next BS */
|
||||||
BS = BA | (BS % MAXMEMSIZE);
|
BS = BA | (BS % MAXMEMSIZE);
|
||||||
return STOP_WRAP; } }
|
return STOP_WRAP; } }
|
||||||
ebc = (tbc + 1) & ~1; /* force even */
|
st = sim_tape_wrrecf (uptr, dbuf, tbc); /* write record */
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
|
||||||
fxwrite (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
|
||||||
fxwrite (dbuf, sizeof (int8), ebc, uptr->fileref);
|
|
||||||
fxwrite (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
|
||||||
if (err = ferror (uptr->fileref)) break; /* I/O error? */
|
|
||||||
uptr->pos = uptr->pos + ebc + (2 * sizeof (t_mtrlnt));
|
|
||||||
if (ADDR_ERR (BS)) { /* check final BS */
|
if (ADDR_ERR (BS)) { /* check final BS */
|
||||||
BS = BA | (BS % MAXMEMSIZE);
|
BS = BA | (BS % MAXMEMSIZE);
|
||||||
return STOP_WRAP; }
|
return STOP_WRAP; }
|
||||||
|
@ -285,13 +239,7 @@ case BCD_W:
|
||||||
default:
|
default:
|
||||||
return STOP_INVM; }
|
return STOP_INVM; }
|
||||||
|
|
||||||
if (err != 0) { /* I/O error? */
|
return mt_map_status (st);
|
||||||
perror ("MT I/O error");
|
|
||||||
clearerr (uptr->fileref);
|
|
||||||
MT_SET_PNU (uptr); /* pos not upd */
|
|
||||||
ind[IN_TAP] = 1; /* flag error */
|
|
||||||
if (iochk) return SCPE_IOERR; }
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get unit pointer from unit number */
|
/* Get unit pointer from unit number */
|
||||||
|
@ -299,7 +247,37 @@ return SCPE_OK;
|
||||||
UNIT *get_unit (int32 unit)
|
UNIT *get_unit (int32 unit)
|
||||||
{
|
{
|
||||||
if ((unit <= 0) || (unit >= MT_NUMDR)) return NULL;
|
if ((unit <= 0) || (unit >= MT_NUMDR)) return NULL;
|
||||||
else return mt_dev.units + unit;
|
return mt_dev.units + unit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Map tape status */
|
||||||
|
|
||||||
|
t_stat mt_map_status (t_stat st)
|
||||||
|
{
|
||||||
|
switch (st) {
|
||||||
|
case MTSE_OK: /* no error */
|
||||||
|
case MTSE_BOT: /* reverse into BOT */
|
||||||
|
break;
|
||||||
|
case MTSE_FMT: /* illegal fmt */
|
||||||
|
return SCPE_IERR;
|
||||||
|
case MTSE_UNATT: /* not attached */
|
||||||
|
return SCPE_UNATT;
|
||||||
|
case MTSE_INVRL: /* invalid rec lnt */
|
||||||
|
return SCPE_MTRLNT;
|
||||||
|
case MTSE_TMK: /* end of file */
|
||||||
|
ind[IN_END] = 1; /* set end mark */
|
||||||
|
break;
|
||||||
|
case MTSE_IOERR: /* IO error */
|
||||||
|
ind[IN_TAP] = 1; /* set error */
|
||||||
|
if (iochk) return SCPE_IOERR;
|
||||||
|
break;
|
||||||
|
case MTSE_RECE: /* record in error */
|
||||||
|
case MTSE_EOM: /* end of medium */
|
||||||
|
ind[IN_TAP] = 1; /* set error */
|
||||||
|
break;
|
||||||
|
case MTSE_WRP: /* write protect */
|
||||||
|
return STOP_MTL; }
|
||||||
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset routine */
|
/* Reset routine */
|
||||||
|
@ -315,21 +293,13 @@ ind[IN_END] = ind[IN_TAP] = 0; /* clear indicators */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Attach routine */
|
|
||||||
|
|
||||||
t_stat mt_attach (UNIT *uptr, char *cptr)
|
|
||||||
{
|
|
||||||
MT_CLR_PNU (uptr);
|
|
||||||
return attach_unit (uptr, cptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Bootstrap routine */
|
/* Bootstrap routine */
|
||||||
|
|
||||||
t_stat mt_boot (int32 unitno, DEVICE *dptr)
|
t_stat mt_boot (int32 unitno, DEVICE *dptr)
|
||||||
{
|
{
|
||||||
extern int32 saved_IS;
|
extern int32 saved_IS;
|
||||||
|
|
||||||
mt_unit[unitno].pos = 0; /* force rewind */
|
sim_tape_rewind (&mt_unit[unitno]); /* force rewind */
|
||||||
BS = 1; /* set BS = 001 */
|
BS = 1; /* set BS = 001 */
|
||||||
mt_io (unitno, MD_WM, BCD_R); /* LDA %U1 001 R */
|
mt_io (unitno, MD_WM, BCD_R); /* LDA %U1 001 R */
|
||||||
saved_IS = 1;
|
saved_IS = 1;
|
||||||
|
|
|
@ -303,23 +303,27 @@ static uint8 dboot_rom[] = {
|
||||||
|
|
||||||
struct dboot_id {
|
struct dboot_id {
|
||||||
char *name;
|
char *name;
|
||||||
|
uint32 sw;
|
||||||
uint32 cap;
|
uint32 cap;
|
||||||
uint32 dtype;
|
uint32 dtype;
|
||||||
uint32 offset;
|
uint32 offset;
|
||||||
|
uint32 adder;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct dboot_id dboot_tab[] = {
|
static struct dboot_id dboot_tab[] = {
|
||||||
{ "DP", 2, 0x31, o_DP0 },
|
{ "DP", 0, 2, 0x31, o_DP0, 0 },
|
||||||
{ "DP", 9, 0x33, o_DP0 },
|
{ "DP", SWMASK ('F'), 9, 0x32, o_DP0, o_DPF },
|
||||||
{ "DM", 64, 0x35, o_ID0 },
|
{ "DP", 0, 9, 0x33, o_DP0, 0 },
|
||||||
{ "DM", 244, 0x36, o_ID0 },
|
{ "DM", 0, 64, 0x35, o_ID0, 0 },
|
||||||
|
{ "DM", 0, 244, 0x36, o_ID0, 0 },
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
t_stat id_dboot (int32 u, DEVICE *dptr)
|
t_stat id_dboot (int32 u, DEVICE *dptr)
|
||||||
{
|
{
|
||||||
extern DIB pt_dib, sch_dib;
|
extern DIB pt_dib, sch_dib;
|
||||||
extern uint32 PC;
|
extern uint32 PC;
|
||||||
uint32 i, typ, ctlno, off, cap, sch_dev;
|
extern int32 sim_switches;
|
||||||
|
uint32 i, typ, ctlno, off, add, cap, sch_dev;
|
||||||
UNIT *uptr;
|
UNIT *uptr;
|
||||||
|
|
||||||
DIB *ddib = (DIB *) dptr->ctxt; /* get disk DIB */
|
DIB *ddib = (DIB *) dptr->ctxt; /* get disk DIB */
|
||||||
|
@ -331,13 +335,15 @@ for (i = typ = 0; dboot_tab[i].name != NULL; i++) {
|
||||||
if ((strcmp (dboot_tab[i].name, dptr->name) == 0) &&
|
if ((strcmp (dboot_tab[i].name, dptr->name) == 0) &&
|
||||||
(dboot_tab[i].cap == cap)) {
|
(dboot_tab[i].cap == cap)) {
|
||||||
typ = dboot_tab[i].dtype;
|
typ = dboot_tab[i].dtype;
|
||||||
off = dboot_tab[i].offset; } }
|
off = dboot_tab[i].offset;
|
||||||
|
add = dboot_tab[i].adder;
|
||||||
|
break; } }
|
||||||
if (typ == 0) return SCPE_NOFNC;
|
if (typ == 0) return SCPE_NOFNC;
|
||||||
|
|
||||||
IOWriteBlk (DBOOT_BEG, DBOOT_LEN, dboot_rom); /* copy boot */
|
IOWriteBlk (DBOOT_BEG, DBOOT_LEN, dboot_rom); /* copy boot */
|
||||||
IOWriteB (AL_DEV, pt_dib.dno); /* bin input dev */
|
IOWriteB (AL_DEV, pt_dib.dno); /* bin input dev */
|
||||||
IOWriteB (AL_IOC, 0x99);
|
IOWriteB (AL_IOC, 0x99);
|
||||||
IOWriteB (AL_DSKU, ctlno + ((u + 1) * off)); /* disk param */
|
IOWriteB (AL_DSKU, ctlno + ((u + 1) * off) + add); /* disk param */
|
||||||
IOWriteB (AL_DSKT, typ);
|
IOWriteB (AL_DSKT, typ);
|
||||||
IOWriteB (AL_DSKC, ctlno);
|
IOWriteB (AL_DSKC, ctlno);
|
||||||
IOWriteB (AL_SCH, sch_dev);
|
IOWriteB (AL_SCH, sch_dev);
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
Except as contained in this notice, the name of Robert M Supnik shall not
|
Except as contained in this notice, the name of Robert M Supnik shall not
|
||||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
27-Feb-03 RMS Added relative addressing support
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "id_defs.h"
|
#include "id_defs.h"
|
||||||
|
@ -42,8 +44,8 @@ extern UNIT cpu_unit;
|
||||||
extern REG cpu_reg[];
|
extern REG cpu_reg[];
|
||||||
extern uint16 *M;
|
extern uint16 *M;
|
||||||
|
|
||||||
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val);
|
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val, t_bool cf);
|
||||||
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val);
|
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val, t_bool cf);
|
||||||
extern t_stat lp_load (FILE *fileref, char *cptr, char *fnam);
|
extern t_stat lp_load (FILE *fileref, char *cptr, char *fnam);
|
||||||
extern pt_dump (FILE *of, char *cptr, char *fnam);
|
extern pt_dump (FILE *of, char *cptr, char *fnam);
|
||||||
|
|
||||||
|
@ -297,7 +299,7 @@ if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */
|
||||||
return -(vp - 1); } /* return # chars */
|
return -(vp - 1); } /* return # chars */
|
||||||
|
|
||||||
if (sw & SWMASK ('M')) { /* inst format? */
|
if (sw & SWMASK ('M')) { /* inst format? */
|
||||||
r = fprint_sym_m (of, addr, val); /* decode inst */
|
r = fprint_sym_m (of, addr, val, uptr == &cpu_unit); /* decode inst */
|
||||||
if (r <= 0) return r; }
|
if (r <= 0) return r; }
|
||||||
|
|
||||||
GETNUM (num, lnt); /* get number */
|
GETNUM (num, lnt); /* get number */
|
||||||
|
@ -311,14 +313,15 @@ return -(vp - 1);
|
||||||
of = output stream
|
of = output stream
|
||||||
addr = current PC
|
addr = current PC
|
||||||
*val = values to decode
|
*val = values to decode
|
||||||
|
cf = true if decoding for CPU
|
||||||
Outputs:
|
Outputs:
|
||||||
return = if >= 0, error code
|
return = if >= 0, error code
|
||||||
if < 0, number of extra bytes retired
|
if < 0, number of extra bytes retired
|
||||||
*/
|
*/
|
||||||
|
|
||||||
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val)
|
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val, t_bool cf)
|
||||||
{
|
{
|
||||||
uint32 i, j, k, inst, r1, r2, ea, tgt, vp;
|
uint32 i, j, k, inst, r1, r2, ea, vp;
|
||||||
|
|
||||||
vp = 0;
|
vp = 0;
|
||||||
GETNUM (inst, 2); /* first 16b */
|
GETNUM (inst, 2); /* first 16b */
|
||||||
|
@ -328,39 +331,38 @@ for (i = 0; opcode[i] != NULL; i++) { /* loop thru ops */
|
||||||
if ((opc_val[i] & 0xFFFF) == (inst & masks[j])) { /* match? */
|
if ((opc_val[i] & 0xFFFF) == (inst & masks[j])) { /* match? */
|
||||||
r1 = (inst >> 4) & 0xF;
|
r1 = (inst >> 4) & 0xF;
|
||||||
r2 = inst & 0xF;
|
r2 = inst & 0xF;
|
||||||
|
fprintf (of, "%s ", opcode[i]); /* print opcode */
|
||||||
switch (j) { /* case on class */
|
switch (j) { /* case on class */
|
||||||
case I_V_MR: /* mask-register */
|
case I_V_MR: /* mask-register */
|
||||||
fprintf (of, "%s %-X,R%d", opcode[i], r1, r2);
|
fprintf (of, "%-X,R%d", r1, r2);
|
||||||
return -1;
|
return -1;
|
||||||
case I_V_RR: /* register-register */
|
case I_V_RR: /* register-register */
|
||||||
case I_V_FF: /* floating-floating */
|
case I_V_FF: /* floating-floating */
|
||||||
fprintf (of, "%s R%d,R%d", opcode[i], r1, r2);
|
fprintf (of, "R%d,R%d", r1, r2);
|
||||||
return -1;
|
return -1;
|
||||||
case I_V_SI: /* short immediate */
|
case I_V_SI: /* short immediate */
|
||||||
fprintf (of, "%s R%d,%-X", opcode[i], r1, r2);
|
fprintf (of, "R%d,%-X", r1, r2);
|
||||||
return -1;
|
return -1;
|
||||||
case I_V_SB: /* short branch */
|
case I_V_SB: /* short branch */
|
||||||
if (inst & MSK_SBF) tgt = addr + r2 + r2;
|
fprintf (of, "%-X,", r1);
|
||||||
else tgt = addr - r2 - r2;
|
|
||||||
fprintf (of, "%s %-X,%-X", opcode[i], r1, tgt);
|
|
||||||
return -1;
|
|
||||||
case I_V_SX: /* ext short branch */
|
case I_V_SX: /* ext short branch */
|
||||||
if (inst & MSK_SBF) tgt = addr + r2 + r2;
|
if (cf) fprintf (of, "%-X", ((inst & MSK_SBF)?
|
||||||
else tgt = addr - r2 - r2;
|
(addr + r2 + r2): (addr - r2 - r2)));
|
||||||
fprintf (of, "%s %-X", opcode[i], tgt);
|
else fprintf (of, ((inst & MSK_SBF)?
|
||||||
|
".+%-X": ".-%X"), r2 + r2);
|
||||||
return -1;
|
return -1;
|
||||||
case I_V_R: /* register */
|
case I_V_R: /* register */
|
||||||
fprintf (of, "%s R%d", opcode[i], r2);
|
fprintf (of, "R%d", r2);
|
||||||
return -1;
|
return -1;
|
||||||
case I_V_MX: /* mask-memory */
|
case I_V_MX: /* mask-memory */
|
||||||
fprintf (of, "%s %-X,%-X", opcode[i], r1, ea);
|
fprintf (of, "%-X,%-X", r1, ea);
|
||||||
break;
|
break;
|
||||||
case I_V_RX: /* register-memory */
|
case I_V_RX: /* register-memory */
|
||||||
case I_V_FX: /* floating-memory */
|
case I_V_FX: /* floating-memory */
|
||||||
fprintf (of, "%s R%d,%-X", opcode[i], r1, ea);
|
fprintf (of, "R%d,%-X", r1, ea);
|
||||||
break;
|
break;
|
||||||
case I_V_X: /* memory */
|
case I_V_X: /* memory */
|
||||||
fprintf (of, "%s %-X", opcode[i], ea);
|
fprintf (of, "%-X", ea);
|
||||||
break; } /* end case */
|
break; } /* end case */
|
||||||
if (r2) fprintf (of, "(R%d)", r2);
|
if (r2) fprintf (of, "(R%d)", r2);
|
||||||
return -3; } /* end if */
|
return -3; } /* end if */
|
||||||
|
@ -398,6 +400,41 @@ if ((rtype == R_F) && (reg & 1)) return -1;
|
||||||
*optr = cptr + 1;
|
*optr = cptr + 1;
|
||||||
return reg;
|
return reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Address
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
*cptr = pointer to input string
|
||||||
|
**tptr = pointer to moved pointer
|
||||||
|
*ea = effective address
|
||||||
|
*rel = relative flag
|
||||||
|
addr = base address
|
||||||
|
cf = true if parsing for CPU
|
||||||
|
Outputs:
|
||||||
|
status = SCPE_OK if ok, else error code
|
||||||
|
*/
|
||||||
|
|
||||||
|
t_stat get_addr (char *cptr, char **tptr, t_addr *ea, t_bool *rel,
|
||||||
|
t_addr addr, t_bool cf)
|
||||||
|
{
|
||||||
|
int32 sign = 1;
|
||||||
|
|
||||||
|
*ea = 0;
|
||||||
|
if (*cptr == '.') { /* relative? */
|
||||||
|
*rel = TRUE;
|
||||||
|
cptr++;
|
||||||
|
if (cf) *ea = addr;
|
||||||
|
if (*cptr == '+') cptr++; /* .+? */
|
||||||
|
else if (*cptr == '-') { /* .-? */
|
||||||
|
sign = -1;
|
||||||
|
cptr++; }
|
||||||
|
else return SCPE_OK; }
|
||||||
|
else *rel = FALSE;
|
||||||
|
errno = 0;
|
||||||
|
*ea = *ea + (sign * ((int32) strtoul (cptr, tptr, 16)));
|
||||||
|
if (errno || (cptr == *tptr)) return SCPE_ARG;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
#define PUTNUM(d,n) for (k = n; k > 0; k--) \
|
#define PUTNUM(d,n) for (k = n; k > 0; k--) \
|
||||||
val[vp++] = (d >> ((k - 1) * 8)) & 0xFF
|
val[vp++] = (d >> ((k - 1) * 8)) & 0xFF
|
||||||
|
@ -431,9 +468,8 @@ if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */
|
||||||
val[vp++] = *cptr++; }
|
val[vp++] = *cptr++; }
|
||||||
return -(vp - 1); } /* return # chars */
|
return -(vp - 1); } /* return # chars */
|
||||||
|
|
||||||
if (uptr == &cpu_unit) { /* cpu only */
|
r = parse_sym_m (cptr, addr, val, uptr == &cpu_unit); /* try to parse inst */
|
||||||
r = parse_sym_m (cptr, addr, val); /* try to parse inst */
|
if (r <= 0) return r;
|
||||||
if (r <= 0) return r; }
|
|
||||||
|
|
||||||
num = (int32) get_uint (cptr, rdx, maxv[lnt], &r); /* get number */
|
num = (int32) get_uint (cptr, rdx, maxv[lnt], &r); /* get number */
|
||||||
if (r != SCPE_OK) return r;
|
if (r != SCPE_OK) return r;
|
||||||
|
@ -447,15 +483,17 @@ return -(lnt - 1);
|
||||||
*cptr = pointer to input string
|
*cptr = pointer to input string
|
||||||
addr = current PC
|
addr = current PC
|
||||||
*val = pointer to output values
|
*val = pointer to output values
|
||||||
|
cf = true if parsing for CPU
|
||||||
Outputs:
|
Outputs:
|
||||||
status = > 0 error code
|
status = > 0 error code
|
||||||
<= 0 -number of extra words
|
<= 0 -number of extra words
|
||||||
*/
|
*/
|
||||||
|
|
||||||
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val)
|
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val, t_bool cf)
|
||||||
{
|
{
|
||||||
uint32 i, j, k, t, df, db, inst, ea, vp;
|
uint32 i, j, k, t, df, db, inst, vp;
|
||||||
int32 r1, r2;
|
int32 st, r1, r2;
|
||||||
|
t_bool rel;
|
||||||
t_stat r;
|
t_stat r;
|
||||||
char *tptr, gbuf[CBUFSIZE];
|
char *tptr, gbuf[CBUFSIZE];
|
||||||
|
|
||||||
|
@ -488,9 +526,9 @@ case I_V_R: /* register */
|
||||||
case I_V_FX: /* float-memory */
|
case I_V_FX: /* float-memory */
|
||||||
case I_V_MX: case I_V_RX: /* mask/reg-mem */
|
case I_V_MX: case I_V_RX: /* mask/reg-mem */
|
||||||
case I_V_X: /* memory */
|
case I_V_X: /* memory */
|
||||||
errno = 0;
|
r = get_addr (gbuf, &tptr, &t, &rel, addr, cf); /* get addr */
|
||||||
ea = strtoul (gbuf, &tptr, 16); /* get address */
|
if ((r != SCPE_OK) || (t > PAMASK16) ||
|
||||||
if (errno || (gbuf == tptr)) return SCPE_ARG; /* error? */
|
(!cf && rel)) return SCPE_ARG;
|
||||||
if (*tptr == '(') { /* index? */
|
if (*tptr == '(') { /* index? */
|
||||||
if ((r2 = get_reg (tptr + 1, &tptr, R_R)) < 0)
|
if ((r2 = get_reg (tptr + 1, &tptr, R_R)) < 0)
|
||||||
return SCPE_ARG;
|
return SCPE_ARG;
|
||||||
|
@ -498,23 +536,34 @@ case I_V_X: /* memory */
|
||||||
inst = inst | r2; } /* or in R2 */
|
inst = inst | r2; } /* or in R2 */
|
||||||
if (*tptr != 0) return SCPE_ARG;
|
if (*tptr != 0) return SCPE_ARG;
|
||||||
PUTNUM (inst, 2);
|
PUTNUM (inst, 2);
|
||||||
PUTNUM (ea, 2);
|
PUTNUM (t, 2);
|
||||||
return -3;
|
return -3;
|
||||||
|
|
||||||
case I_V_SB: case I_V_SX: /* short branches */
|
case I_V_SB: case I_V_SX: /* short branches */
|
||||||
t = get_uint (gbuf, 16, DMASK16, &r); /* get addr */
|
r = get_addr (gbuf, &tptr, &t, &rel, addr, cf); /* get addr */
|
||||||
if ((r != SCPE_OK) || (t & 1)) return r; /* error if odd */
|
if ((r != SCPE_OK) || (t & 1) || *tptr) /* error if odd */
|
||||||
|
return SCPE_ARG;
|
||||||
|
st = t; /* signed version */
|
||||||
|
if (cf) { /* for CPU? */
|
||||||
db = (addr - t) & 0x1F; /* back displ */
|
db = (addr - t) & 0x1F; /* back displ */
|
||||||
df = (t - addr) & 0x1F; /* fwd displ */
|
df = (t - addr) & 0x1F; /* fwd displ */
|
||||||
if ((t == ((addr - db) & VAMASK16)) && /* back work and */
|
if ((t == ((addr - db) & VAMASK16)) && /* back work and */
|
||||||
((j == I_V_SX) || !(inst & MSK_SBF))) { /* ext or back br? */
|
((j == I_V_SX) || !(inst & MSK_SBF))) /* ext or back br? */
|
||||||
inst = inst | (db >> 1); /* or in back displ */
|
inst = inst | (db >> 1); /* or in back displ */
|
||||||
break; }
|
else if ((t == ((addr + df) & VAMASK16)) && /* fwd work and */
|
||||||
if ((t == ((addr + df) & VAMASK16)) && /* fwd work and */
|
((j == I_V_SX) || (inst & MSK_SBF))) /* ext or fwd br? */
|
||||||
((j == I_V_SX) || (inst & MSK_SBF))) { /* ext or fwd br? */
|
|
||||||
inst = inst | (df >> 1) | MSK_SBF; /* or in fwd displ */
|
inst = inst | (df >> 1) | MSK_SBF; /* or in fwd displ */
|
||||||
break; }
|
else return SCPE_ARG; }
|
||||||
return SCPE_ARG; } /* end case */
|
else if (rel) { /* periph, must be rel */
|
||||||
|
if ((st <= 0) && (st >= -0x1F) && /* relative back? */
|
||||||
|
((j == I_V_SX) || !(inst & MSK_SBF)))
|
||||||
|
inst = inst | ((-st & 0x1F) >> 1);
|
||||||
|
else if ((st >= 0) && (st < 0x1F) && /* relative fwd? */
|
||||||
|
((j == I_V_SX) || (inst & MSK_SBF)))
|
||||||
|
inst = inst | ((t & 0x1F) >> 1);
|
||||||
|
else return SCPE_ARG; }
|
||||||
|
else return SCPE_ARG; /* periph & ~rel, err */
|
||||||
|
} /* end case */
|
||||||
|
|
||||||
PUTNUM (inst, 2);
|
PUTNUM (inst, 2);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* id32_cpu.c: Interdata 32b CPU simulator
|
/* id32_cpu.c: Interdata 32b CPU simulator
|
||||||
|
|
||||||
Copyright (c) 2000-2002, Robert M. Supnik
|
Copyright (c) 2000-2003, Robert M. Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -740,7 +740,7 @@ case 0x63: /* LRA - RX */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x40: /* STH - RX */
|
case 0x40: /* STH - RX */
|
||||||
WriteH (ea, R[r1] & DMASK16, VW); /* store register */
|
WriteH (ea, R[r1], VW); /* store register */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x50: /* ST - RX */
|
case 0x50: /* ST - RX */
|
||||||
|
@ -775,7 +775,7 @@ case 0x92: /* STBR - NO */
|
||||||
R[r2] = (R[r2] & ~DMASK8) | (R[r1] & DMASK8); /* store byte */
|
R[r2] = (R[r2] & ~DMASK8) | (R[r1] & DMASK8); /* store byte */
|
||||||
break;
|
break;
|
||||||
case 0xD2: /* STB - RX */
|
case 0xD2: /* STB - RX */
|
||||||
WriteB (ea, R[r1] & DMASK8, VW); /* store byte */
|
WriteB (ea, R[r1], VW); /* store byte */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x34: /* EXHR - NO */
|
case 0x34: /* EXHR - NO */
|
||||||
|
@ -1291,7 +1291,7 @@ case 0xE3: /* SCP - RX */
|
||||||
else WriteB ((bufa + sr) & VAMASK, R[r1], VW); /* read, R1 to mem */
|
else WriteB ((bufa + sr) & VAMASK, R[r1], VW); /* read, R1 to mem */
|
||||||
sr = sr + 1; /* inc count */
|
sr = sr + 1; /* inc count */
|
||||||
CC_GL_32 (sr & DMASK32); /* set cc's */
|
CC_GL_32 (sr & DMASK32); /* set cc's */
|
||||||
WriteH (t & VAMASK, sr & DMASK16, VW); /* rewrite */
|
WriteH (t & VAMASK, sr, VW); /* rewrite */
|
||||||
if ((sr > 0) && !(opnd & CCW32_FST)) /* buf switch? */
|
if ((sr > 0) && !(opnd & CCW32_FST)) /* buf switch? */
|
||||||
WriteH (ea, opnd ^ CCW32_B1, VW); /* flip CCW bit */
|
WriteH (ea, opnd ^ CCW32_B1, VW); /* flip CCW bit */
|
||||||
} /* end if */
|
} /* end if */
|
||||||
|
@ -1603,7 +1603,7 @@ slt = (t >> 16) & DMASK16; /* # slots */
|
||||||
usd = t & DMASK16; /* # used */
|
usd = t & DMASK16; /* # used */
|
||||||
if (usd == 0) return CC_V; /* empty? */
|
if (usd == 0) return CC_V; /* empty? */
|
||||||
usd = usd - 1; /* dec used */
|
usd = usd - 1; /* dec used */
|
||||||
WriteH (ea + Q32_USD, usd & DMASK16, VW); /* rewrite */
|
WriteH (ea + Q32_USD, usd, VW); /* rewrite */
|
||||||
if (flg) { /* RBL? */
|
if (flg) { /* RBL? */
|
||||||
rda = ReadH ((ea + Q32_BOT) & VAMASK, VR); /* get bottom */
|
rda = ReadH ((ea + Q32_BOT) & VAMASK, VR); /* get bottom */
|
||||||
if (rda == 0) rda = (slt - 1) & DMASK16; /* wrap if necc */
|
if (rda == 0) rda = (slt - 1) & DMASK16; /* wrap if necc */
|
||||||
|
@ -1673,7 +1673,7 @@ if (ccw & CCW32_FST) { /* fast mode? */
|
||||||
t = dev_tab[dev] (dev, IO_RD, 0); /* get byte */
|
t = dev_tab[dev] (dev, IO_RD, 0); /* get byte */
|
||||||
WriteB (addr, t, VW); } /* write to mem */
|
WriteB (addr, t, VW); } /* write to mem */
|
||||||
bufc = bufc + 1; } /* adv buf cnt */
|
bufc = bufc + 1; } /* adv buf cnt */
|
||||||
WriteH (ccwa + CCB32_B0C, bufc & DMASK16, VW);/* rewrite cnt */
|
WriteH (ccwa + CCB32_B0C, bufc, VW); /* rewrite cnt */
|
||||||
if (bufc > 0) {
|
if (bufc > 0) {
|
||||||
PC = ReadH (ccwa + CCB32_SUB, VR); /* get subr */
|
PC = ReadH (ccwa + CCB32_SUB, VR); /* get subr */
|
||||||
return CC_G; } /* CC = G */
|
return CC_G; } /* CC = G */
|
||||||
|
@ -1709,7 +1709,7 @@ else { /* slow mode */
|
||||||
PC = t << 1; /* change PC */
|
PC = t << 1; /* change PC */
|
||||||
R[3] = by; /* untrans char */
|
R[3] = by; /* untrans char */
|
||||||
return 0; } /* CC = 0 */
|
return 0; } /* CC = 0 */
|
||||||
WriteB (addr, t & DMASK8, VW); } /* wr trans */
|
WriteB (addr, t, VW); } /* wr trans */
|
||||||
else WriteB (addr, by, VW); } /* wr orig */
|
else WriteB (addr, by, VW); } /* wr orig */
|
||||||
t = ReadH (ccwa + CCB32_CHK, VR); /* get check wd */
|
t = ReadH (ccwa + CCB32_CHK, VR); /* get check wd */
|
||||||
t = t ^ by; /* start LRC */
|
t = t ^ by; /* start LRC */
|
||||||
|
@ -1719,7 +1719,7 @@ else { /* slow mode */
|
||||||
else t = t >> 1; } }
|
else t = t >> 1; } }
|
||||||
WriteH (ccwa + CCB32_CHK, t, VW); /* rewrite chk wd */
|
WriteH (ccwa + CCB32_CHK, t, VW); /* rewrite chk wd */
|
||||||
bufc = bufc + 1; /* adv buf cnt */
|
bufc = bufc + 1; /* adv buf cnt */
|
||||||
WriteH (ccwb, bufc & DMASK16, VW); /* rewrite cnt */
|
WriteH (ccwb, bufc, VW); /* rewrite cnt */
|
||||||
if (bufc > 0) { /* cnt pos? */
|
if (bufc > 0) { /* cnt pos? */
|
||||||
ccw = ccw ^ CCW32_B1; /* flip buf */
|
ccw = ccw ^ CCW32_B1; /* flip buf */
|
||||||
WriteH (ccwa, ccw, VW); /* rewrite */
|
WriteH (ccwa, ccw, VW); /* rewrite */
|
||||||
|
@ -1826,10 +1826,10 @@ uint32 val;
|
||||||
uint32 sc = (3 - (loc & 3)) << 3;
|
uint32 sc = (3 - (loc & 3)) << 3;
|
||||||
|
|
||||||
if ((PSW & PSW_REL) == 0) { /* reloc off? */
|
if ((PSW & PSW_REL) == 0) { /* reloc off? */
|
||||||
val = M[loc >> 2]; /* get mem word */
|
|
||||||
if ((loc & ~03) == MAC_STA) { /* MAC status? */
|
if ((loc & ~03) == MAC_STA) { /* MAC status? */
|
||||||
val = mac_sta; /* read it */
|
val = mac_sta; /* read it */
|
||||||
qevent = qevent & ~EV_MAC; } } /* clr MAC intr */
|
qevent = qevent & ~EV_MAC; } /* clr MAC intr */
|
||||||
|
else val = M[loc >> 2]; } /* get mem word */
|
||||||
else if (rel == 0) val = M[loc >> 2]; /* phys ref? */
|
else if (rel == 0) val = M[loc >> 2]; /* phys ref? */
|
||||||
else { uint32 pa = Reloc (loc, rel); /* relocate */
|
else { uint32 pa = Reloc (loc, rel); /* relocate */
|
||||||
val = M[pa >> 2]; }
|
val = M[pa >> 2]; }
|
||||||
|
@ -1841,10 +1841,10 @@ uint32 ReadH (uint32 loc, uint32 rel)
|
||||||
uint32 val;
|
uint32 val;
|
||||||
|
|
||||||
if ((PSW & PSW_REL) == 0) { /* reloc off? */
|
if ((PSW & PSW_REL) == 0) { /* reloc off? */
|
||||||
val = M[loc >> 2]; /* get mem word */
|
|
||||||
if ((loc & ~03) == MAC_STA) { /* MAC status? */
|
if ((loc & ~03) == MAC_STA) { /* MAC status? */
|
||||||
val = mac_sta; /* read it */
|
val = mac_sta; /* read it */
|
||||||
qevent = qevent & ~EV_MAC; } } /* clr MAC intr */
|
qevent = qevent & ~EV_MAC; } /* clr MAC intr */
|
||||||
|
else val = M[loc >> 2]; } /* get mem word */
|
||||||
else if (rel == 0) val = M[loc >> 2]; /* phys ref? */
|
else if (rel == 0) val = M[loc >> 2]; /* phys ref? */
|
||||||
else { uint32 pa = Reloc (loc, rel); /* relocate */
|
else { uint32 pa = Reloc (loc, rel); /* relocate */
|
||||||
val = M[pa >> 2]; }
|
val = M[pa >> 2]; }
|
||||||
|
@ -1856,10 +1856,10 @@ uint32 ReadF (uint32 loc, uint32 rel)
|
||||||
uint32 val;
|
uint32 val;
|
||||||
|
|
||||||
if ((PSW & PSW_REL) == 0) { /* reloc off? */
|
if ((PSW & PSW_REL) == 0) { /* reloc off? */
|
||||||
val = M[loc >> 2]; /* get mem word */
|
|
||||||
if ((loc & ~03) == MAC_STA) { /* MAC status? */
|
if ((loc & ~03) == MAC_STA) { /* MAC status? */
|
||||||
val = mac_sta; /* read it */
|
val = mac_sta; /* read it */
|
||||||
qevent = qevent & ~EV_MAC; } } /* clr MAC intr */
|
qevent = qevent & ~EV_MAC; } /* clr MAC intr */
|
||||||
|
else val = M[loc >> 2]; } /* get mem word */
|
||||||
else if (rel == 0) val = M[loc >> 2]; /* phys ref? */
|
else if (rel == 0) val = M[loc >> 2]; /* phys ref? */
|
||||||
else { uint32 pa = Reloc (loc, rel); /* relocate */
|
else { uint32 pa = Reloc (loc, rel); /* relocate */
|
||||||
val = M[pa >> 2]; }
|
val = M[pa >> 2]; }
|
||||||
|
@ -1911,6 +1911,7 @@ void WriteF (uint32 loc, uint32 val, uint32 rel)
|
||||||
{
|
{
|
||||||
uint32 pa = loc;
|
uint32 pa = loc;
|
||||||
|
|
||||||
|
val = val & DMASK32;
|
||||||
if (loc & 2) {
|
if (loc & 2) {
|
||||||
WriteH (loc & VAMASK, (val >> 16) & DMASK16, rel);
|
WriteH (loc & VAMASK, (val >> 16) & DMASK16, rel);
|
||||||
WriteH ((loc + 2) & VAMASK, val & DMASK16, rel);
|
WriteH ((loc + 2) & VAMASK, val & DMASK16, rel);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* id32_dboot.c: Interdata 32b simulator disk bootstrap
|
/* id32_dboot.c: Interdata 32b simulator disk bootstrap
|
||||||
|
|
||||||
Copyright (c) 2000-2002, Robert M. Supnik
|
Copyright (c) 2000-2003, Robert M. Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -22,6 +22,8 @@
|
||||||
Except as contained in this notice, the name of Robert M Supnik shall not
|
Except as contained in this notice, the name of Robert M Supnik shall not
|
||||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
17-Feb-03 RMS Fixed for UNIX bootstrap, upper platter bootstrap
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "id_defs.h"
|
#include "id_defs.h"
|
||||||
|
@ -140,7 +142,7 @@ static uint8 dboot_rom[] = {
|
||||||
0x11, 0xa5,
|
0x11, 0xa5,
|
||||||
0x06, 0xba,
|
0x06, 0xba,
|
||||||
0x98, 0x49,
|
0x98, 0x49,
|
||||||
0xde, 0x4d, 0x03, 0x28,
|
0xde, 0x4d, 0x03, 0x2b,
|
||||||
0x9d, 0x3f,
|
0x9d, 0x3f,
|
||||||
0x22, 0x21,
|
0x22, 0x21,
|
||||||
0x9d, 0x4f,
|
0x9d, 0x4f,
|
||||||
|
@ -265,23 +267,27 @@ static uint8 dboot_rom[] = {
|
||||||
|
|
||||||
struct dboot_id {
|
struct dboot_id {
|
||||||
char *name;
|
char *name;
|
||||||
|
uint32 sw;
|
||||||
uint32 cap;
|
uint32 cap;
|
||||||
uint32 dtype;
|
uint32 dtype;
|
||||||
uint32 offset;
|
uint32 offset;
|
||||||
|
uint32 adder;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct dboot_id dboot_tab[] = {
|
static struct dboot_id dboot_tab[] = {
|
||||||
{ "DP", 2, 0x31, o_DP0 },
|
{ "DP", 0, 2, 0x31, o_DP0, 0 },
|
||||||
{ "DP", 9, 0x33, o_DP0 },
|
{ "DP", SWMASK ('F'), 9, 0x32, o_DP0, o_DPF },
|
||||||
{ "DM", 64, 0x35, o_ID0 },
|
{ "DP", 0, 9, 0x33, o_DP0, 0 },
|
||||||
{ "DM", 244, 0x36, o_ID0 },
|
{ "DM", 0, 64, 0x35, o_ID0, 0 },
|
||||||
|
{ "DM", 0, 244, 0x36, o_ID0, 0 },
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
t_stat id_dboot (int32 u, DEVICE *dptr)
|
t_stat id_dboot (int32 u, DEVICE *dptr)
|
||||||
{
|
{
|
||||||
extern DIB pt_dib, sch_dib;
|
extern DIB ttp_dib, sch_dib;
|
||||||
extern uint32 PC;
|
extern uint32 PC;
|
||||||
uint32 i, typ, ctlno, off, cap, sch_dev;
|
extern int32 sim_switches;
|
||||||
|
uint32 i, typ, ctlno, off, add, cap, sch_dev;
|
||||||
UNIT *uptr;
|
UNIT *uptr;
|
||||||
|
|
||||||
DIB *ddib = (DIB *) dptr->ctxt; /* get disk DIB */
|
DIB *ddib = (DIB *) dptr->ctxt; /* get disk DIB */
|
||||||
|
@ -291,17 +297,20 @@ uptr = dptr->units + u; /* get capacity */
|
||||||
cap = uptr->capac >> 20;
|
cap = uptr->capac >> 20;
|
||||||
for (i = typ = 0; dboot_tab[i].name != NULL; i++) {
|
for (i = typ = 0; dboot_tab[i].name != NULL; i++) {
|
||||||
if ((strcmp (dboot_tab[i].name, dptr->name) == 0) &&
|
if ((strcmp (dboot_tab[i].name, dptr->name) == 0) &&
|
||||||
|
((dboot_tab[i].sw == 0) || (dboot_tab[i].sw & sim_switches)) &&
|
||||||
(dboot_tab[i].cap == cap)) {
|
(dboot_tab[i].cap == cap)) {
|
||||||
typ = dboot_tab[i].dtype;
|
typ = dboot_tab[i].dtype;
|
||||||
off = dboot_tab[i].offset; } }
|
off = dboot_tab[i].offset;
|
||||||
|
add = dboot_tab[i].adder;
|
||||||
|
break; } }
|
||||||
if (typ == 0) return SCPE_NOFNC;
|
if (typ == 0) return SCPE_NOFNC;
|
||||||
|
|
||||||
IOWriteBlk (DBOOT_BEG, DBOOT_LEN, dboot_rom); /* copy boot */
|
IOWriteBlk (DBOOT_BEG, DBOOT_LEN, dboot_rom); /* copy boot */
|
||||||
IOWriteB (AL_DEV, pt_dib.dno); /* bin input dev */
|
IOWriteB (AL_DEV, ttp_dib.dno); /* bin input dev */
|
||||||
IOWriteB (AL_IOC, 0x99);
|
IOWriteB (AL_IOC, 0xa3);
|
||||||
IOWriteB (AL_DSKU, ctlno + ((u + 1) * off)); /* disk param */
|
IOWriteB (AL_DSKU, ctlno + ((u + 1) * off) + add); /* disk dev addr */
|
||||||
IOWriteB (AL_DSKT, typ);
|
IOWriteB (AL_DSKT, typ); /* disk type */
|
||||||
IOWriteB (AL_DSKC, ctlno);
|
IOWriteB (AL_DSKC, ctlno); /* disk ctl addr */
|
||||||
IOWriteB (AL_SCH, sch_dev);
|
IOWriteB (AL_SCH, sch_dev);
|
||||||
PC = DBOOT_START;
|
PC = DBOOT_START;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
27-Feb-03 RMS Added relative addressing support
|
||||||
23-Dec-01 RMS Cloned from ID4 sources
|
23-Dec-01 RMS Cloned from ID4 sources
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -30,7 +31,7 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
#define MSK_SBF 0x0100
|
#define MSK_SBF 0x0100
|
||||||
#define SEXT15(x) (((x) & 0x4000)? ((x) | 0xFFFF8000): ((x) & 0x7FFF))
|
#define SEXT15(x) (((x) & 0x4000)? ((x) | ~0x3FFF): ((x) & 0x3FFF))
|
||||||
|
|
||||||
extern DEVICE cpu_dev;
|
extern DEVICE cpu_dev;
|
||||||
extern DEVICE sch_dev;
|
extern DEVICE sch_dev;
|
||||||
|
@ -45,8 +46,8 @@ extern UNIT cpu_unit;
|
||||||
extern REG cpu_reg[];
|
extern REG cpu_reg[];
|
||||||
extern uint32 *M;
|
extern uint32 *M;
|
||||||
|
|
||||||
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val);
|
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val, t_bool cf);
|
||||||
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val);
|
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val, t_bool cf);
|
||||||
extern t_stat lp_load (FILE *fileref, char *cptr, char *fnam);
|
extern t_stat lp_load (FILE *fileref, char *cptr, char *fnam);
|
||||||
extern pt_dump (FILE *of, char *cptr, char *fnam);
|
extern pt_dump (FILE *of, char *cptr, char *fnam);
|
||||||
|
|
||||||
|
@ -286,7 +287,8 @@ static const uint32 opc_val[] = {
|
||||||
|
|
||||||
/* Print an RX specifier */
|
/* Print an RX specifier */
|
||||||
|
|
||||||
t_stat fprint_addr (FILE *of, t_addr addr, uint32 rx, uint32 ea1, uint32 ea2)
|
t_stat fprint_addr (FILE *of, t_addr addr, uint32 rx, uint32 ea1,
|
||||||
|
uint32 ea2, t_bool cf)
|
||||||
{
|
{
|
||||||
uint32 rx2;
|
uint32 rx2;
|
||||||
|
|
||||||
|
@ -295,8 +297,13 @@ if ((ea1 & 0xC000) == 0) { /* RX1 */
|
||||||
if (rx) fprintf (of, "(R%d)", rx);
|
if (rx) fprintf (of, "(R%d)", rx);
|
||||||
return -3; }
|
return -3; }
|
||||||
if (ea1 & 0x8000) { /* RX2 */
|
if (ea1 & 0x8000) { /* RX2 */
|
||||||
|
if (cf) { /* for CPU? */
|
||||||
ea1 = addr + 4 + SEXT15 (ea1);
|
ea1 = addr + 4 + SEXT15 (ea1);
|
||||||
fprintf (of, "%-X", ea1 & VAMASK32);
|
fprintf (of, "%-X", ea1 & VAMASK32); }
|
||||||
|
else { /* for dev */
|
||||||
|
int32 disp = SEXT15 (ea1); /* get disp */
|
||||||
|
if (disp >= -4) fprintf (of, ".+%-X", disp + 4);
|
||||||
|
else fprintf (of, ".-%-X", -4 - disp); }
|
||||||
if (rx) fprintf (of, "(R%d)", rx);
|
if (rx) fprintf (of, "(R%d)", rx);
|
||||||
return -3; }
|
return -3; }
|
||||||
rx2 = (ea1 >> 8) & 0xF;
|
rx2 = (ea1 >> 8) & 0xF;
|
||||||
|
@ -351,7 +358,7 @@ if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */
|
||||||
return -(vp - 1); } /* return # chars */
|
return -(vp - 1); } /* return # chars */
|
||||||
|
|
||||||
if (sw & SWMASK ('M')) { /* inst format? */
|
if (sw & SWMASK ('M')) { /* inst format? */
|
||||||
r = fprint_sym_m (of, addr, val); /* decode inst */
|
r = fprint_sym_m (of, addr, val, uptr == &cpu_unit); /* decode inst */
|
||||||
if (r <= 0) return r; /* success? */
|
if (r <= 0) return r; /* success? */
|
||||||
lnt = 2; } /* no, skip 16b */
|
lnt = 2; } /* no, skip 16b */
|
||||||
|
|
||||||
|
@ -366,14 +373,15 @@ return -(vp - 1);
|
||||||
of = output stream
|
of = output stream
|
||||||
addr = current PC
|
addr = current PC
|
||||||
*val = values to decode
|
*val = values to decode
|
||||||
|
cf = true if parsing for CPU
|
||||||
Outputs:
|
Outputs:
|
||||||
return = if >= 0, error code
|
return = if >= 0, error code
|
||||||
if < 0, number of extra bytes retired
|
if < 0, number of extra bytes retired
|
||||||
*/
|
*/
|
||||||
|
|
||||||
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val)
|
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val, t_bool cf)
|
||||||
{
|
{
|
||||||
uint32 i, j, k, inst, r1, r2, ea1, ea2, tgt, vp;
|
uint32 i, j, k, inst, r1, r2, ea1, ea2, vp;
|
||||||
|
|
||||||
vp = 0;
|
vp = 0;
|
||||||
GETNUM (inst,2); /* high 16b */
|
GETNUM (inst,2); /* high 16b */
|
||||||
|
@ -384,49 +392,45 @@ for (i = 0; opc_val[i] != 0xFFFF; i++) { /* loop thru ops */
|
||||||
if ((opc_val[i] & 0xFFFF) == (inst & masks[j])) { /* match? */
|
if ((opc_val[i] & 0xFFFF) == (inst & masks[j])) { /* match? */
|
||||||
r1 = (inst >> 4) & 0xF;
|
r1 = (inst >> 4) & 0xF;
|
||||||
r2 = inst & 0xF;
|
r2 = inst & 0xF;
|
||||||
|
fprintf (of, "%s ", opcode[i]); /* print opcode */
|
||||||
switch (j) { /* case on class */
|
switch (j) { /* case on class */
|
||||||
case I_V_MR: /* mask-register */
|
case I_V_MR: /* mask-register */
|
||||||
fprintf (of, "%s %-X,R%d", opcode[i], r1, r2);
|
fprintf (of, "%-X,R%d", r1, r2);
|
||||||
return -1;
|
return -1;
|
||||||
case I_V_RR: /* register-register */
|
case I_V_RR: /* register-register */
|
||||||
case I_V_FF: /* floating-floating */
|
case I_V_FF: /* floating-floating */
|
||||||
fprintf (of, "%s R%d,R%d", opcode[i], r1, r2);
|
fprintf (of, "R%d,R%d", r1, r2);
|
||||||
return -1;
|
return -1;
|
||||||
case I_V_SI: /* short immediate */
|
case I_V_SI: /* short immediate */
|
||||||
fprintf (of, "%s R%d,%-X", opcode[i], r1, r2);
|
fprintf (of, "R%d,%-X", r1, r2);
|
||||||
return -1;
|
return -1;
|
||||||
case I_V_SB: /* short branch */
|
case I_V_SB: /* short branch */
|
||||||
if (inst & MSK_SBF) tgt = addr + r2 + r2;
|
fprintf (of, "%-X,", r1);
|
||||||
else tgt = addr - r2 - r2;
|
|
||||||
fprintf (of, "%s %-X,%-X", opcode[i], r1, tgt);
|
|
||||||
return -1;
|
|
||||||
case I_V_SX: /* ext short branch */
|
case I_V_SX: /* ext short branch */
|
||||||
if (inst & MSK_SBF) tgt = addr + r2 + r2;
|
if (cf) fprintf (of, "%-X", ((inst & MSK_SBF)?
|
||||||
else tgt = addr - r2 - r2;
|
(addr + r2 + r2): (addr - r2 - r2)));
|
||||||
fprintf (of, "%s %-X", opcode[i], tgt);
|
else fprintf (of, ((inst & MSK_SBF)?
|
||||||
|
".+%-X": ".-%X"), r2 + r2);
|
||||||
return -1;
|
return -1;
|
||||||
case I_V_R: /* register */
|
case I_V_R: /* register */
|
||||||
fprintf (of, "%s R%d", opcode[i], r2);
|
fprintf (of, "R%d", r2);
|
||||||
return -1;
|
return -1;
|
||||||
case I_V_RI: /* reg-immed */
|
case I_V_RI: /* reg-immed */
|
||||||
fprintf (of, "%s R%d,%-X", opcode[i], r1, ea1);
|
fprintf (of, "R%d,%-X", r1, ea1);
|
||||||
if (r2) fprintf (of, "(R%d)", r2);
|
if (r2) fprintf (of, "(R%d)", r2);
|
||||||
return -3;
|
return -3;
|
||||||
case I_V_RF: /* reg-full imm */
|
case I_V_RF: /* reg-full imm */
|
||||||
fprintf (of, "%s R%d,%-X", opcode[i], r1,
|
fprintf (of, "R%d,%-X", r1, (ea1 << 16) | ea2);
|
||||||
(ea1 << 16) | ea2);
|
|
||||||
if (r2) fprintf (of, "(R%d)", r2);
|
if (r2) fprintf (of, "(R%d)", r2);
|
||||||
return -5;
|
return -5;
|
||||||
case I_V_MX: /* mask-memory */
|
case I_V_MX: /* mask-memory */
|
||||||
fprintf (of, "%s %-X,", opcode[i], r1);
|
fprintf (of, "%-X,", r1);
|
||||||
return fprint_addr (of, addr, r2, ea1, ea2);
|
return fprint_addr (of, addr, r2, ea1, ea2, cf);
|
||||||
case I_V_RX: /* register-memory */
|
case I_V_RX: /* register-memory */
|
||||||
case I_V_FX: /* floating-memory */
|
case I_V_FX: /* floating-memory */
|
||||||
fprintf (of, "%s R%d,", opcode[i], r1);
|
fprintf (of, "R%d,", r1);
|
||||||
return fprint_addr (of, addr, r2, ea1, ea2);
|
|
||||||
case I_V_X: /* memory */
|
case I_V_X: /* memory */
|
||||||
fprintf (of, "%s ", opcode[i]);
|
return fprint_addr (of, addr, r2, ea1, ea2, cf); }
|
||||||
return fprint_addr (of, addr, r2, ea1, ea2); }
|
|
||||||
return SCPE_IERR; } /* end if */
|
return SCPE_IERR; } /* end if */
|
||||||
} /* end for */
|
} /* end for */
|
||||||
return SCPE_ARG; /* no match */
|
return SCPE_ARG; /* no match */
|
||||||
|
@ -490,6 +494,41 @@ if (*tptr == '(') { /* index? */
|
||||||
if (*tptr != 0) return SCPE_ARG;
|
if (*tptr != 0) return SCPE_ARG;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Address
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
*cptr = pointer to input string
|
||||||
|
**tptr = pointer to moved pointer
|
||||||
|
*ea = effective address
|
||||||
|
*rel = relative flag
|
||||||
|
addr = base address
|
||||||
|
cf = true if parsing for CPU
|
||||||
|
Outputs:
|
||||||
|
status = SCPE_OK if ok, else error code
|
||||||
|
*/
|
||||||
|
|
||||||
|
t_stat get_addr (char *cptr, char **tptr, t_addr *ea, t_bool *rel,
|
||||||
|
t_addr addr, t_bool cf)
|
||||||
|
{
|
||||||
|
int32 sign = 1;
|
||||||
|
|
||||||
|
*ea = 0;
|
||||||
|
if (*cptr == '.') { /* relative? */
|
||||||
|
*rel = TRUE;
|
||||||
|
cptr++;
|
||||||
|
if (cf) *ea = addr;
|
||||||
|
if (*cptr == '+') cptr++; /* .+? */
|
||||||
|
else if (*cptr == '-') { /* .-? */
|
||||||
|
sign = -1;
|
||||||
|
cptr++; }
|
||||||
|
else return SCPE_OK; }
|
||||||
|
else *rel = FALSE;
|
||||||
|
errno = 0;
|
||||||
|
*ea = *ea + (sign * ((int32) strtoul (cptr, tptr, 16)));
|
||||||
|
if (errno || (cptr == *tptr)) return SCPE_ARG;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
#define PUTNUM(d,n) for (k = n; k > 0; k--) \
|
#define PUTNUM(d,n) for (k = n; k > 0; k--) \
|
||||||
val[vp++] = (d >> ((k - 1) * 8)) & 0xFF
|
val[vp++] = (d >> ((k - 1) * 8)) & 0xFF
|
||||||
|
@ -523,9 +562,8 @@ if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */
|
||||||
val[vp++] = *cptr++; }
|
val[vp++] = *cptr++; }
|
||||||
return -(vp - 1); } /* return # chars */
|
return -(vp - 1); } /* return # chars */
|
||||||
|
|
||||||
if (uptr == &cpu_unit) { /* cpu only */
|
r = parse_sym_m (cptr, addr, val, uptr == &cpu_unit); /* try to parse */
|
||||||
r = parse_sym_m (cptr, addr, val); /* try to parse inst */
|
if (r <= 0) return r;
|
||||||
if (r <= 0) return r; }
|
|
||||||
|
|
||||||
num = (int32) get_uint (cptr, rdx, maxv[lnt], &r); /* get number */
|
num = (int32) get_uint (cptr, rdx, maxv[lnt], &r); /* get number */
|
||||||
if (r != SCPE_OK) return r;
|
if (r != SCPE_OK) return r;
|
||||||
|
@ -539,16 +577,18 @@ return -(lnt - 1);
|
||||||
*cptr = pointer to input string
|
*cptr = pointer to input string
|
||||||
addr = current PC
|
addr = current PC
|
||||||
*val = pointer to output values
|
*val = pointer to output values
|
||||||
|
cf = true if parsing for CPU
|
||||||
Outputs:
|
Outputs:
|
||||||
status = > 0 error code
|
status = > 0 error code
|
||||||
<= 0 -number of extra words
|
<= 0 -number of extra words
|
||||||
*/
|
*/
|
||||||
|
|
||||||
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val)
|
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val, t_bool cf)
|
||||||
{
|
{
|
||||||
uint32 i, j, k, t, df, db, inst, ea, vp;
|
uint32 i, j, k, df, db, t, inst, vp;
|
||||||
int32 st, r1, r2, rx2;
|
int32 st, r1, r2, rx2;
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
t_bool rel;
|
||||||
char *tptr, gbuf[CBUFSIZE];
|
char *tptr, gbuf[CBUFSIZE];
|
||||||
|
|
||||||
vp = 0;
|
vp = 0;
|
||||||
|
@ -580,9 +620,8 @@ case I_V_R: /* register */
|
||||||
case I_V_FX: /* float-memory */
|
case I_V_FX: /* float-memory */
|
||||||
case I_V_MX: case I_V_RX: /* mask/reg-memory */
|
case I_V_MX: case I_V_RX: /* mask/reg-memory */
|
||||||
case I_V_X: /* memory */
|
case I_V_X: /* memory */
|
||||||
errno = 0;
|
r = get_addr (gbuf, &tptr, &t, &rel, addr, cf); /* get addr */
|
||||||
ea = strtoul (gbuf, &tptr, 16); /* get address */
|
if (r != SCPE_OK) return SCPE_ARG; /* error? */
|
||||||
if (errno || (gbuf == tptr)) return SCPE_ARG; /* error? */
|
|
||||||
rx2 = 0; /* assume no 2nd */
|
rx2 = 0; /* assume no 2nd */
|
||||||
if (*tptr == '(') { /* index? */
|
if (*tptr == '(') { /* index? */
|
||||||
if ((r2 = get_reg (tptr + 1, &tptr, R_R)) < 0)
|
if ((r2 = get_reg (tptr + 1, &tptr, R_R)) < 0)
|
||||||
|
@ -594,47 +633,65 @@ case I_V_X: /* memory */
|
||||||
if (*tptr++ != ')') return SCPE_ARG; } /* all done? */
|
if (*tptr++ != ')') return SCPE_ARG; } /* all done? */
|
||||||
if (*tptr != 0) return SCPE_ARG;
|
if (*tptr != 0) return SCPE_ARG;
|
||||||
PUTNUM (inst, 2); /* store inst */
|
PUTNUM (inst, 2); /* store inst */
|
||||||
if (rx2 == 0) { /* no 2nd? */
|
if (!cf && rel) { /* periph, rel */
|
||||||
if (ea < 0x4000) { /* RX1? */
|
st = t - 4; /* displ */
|
||||||
PUTNUM (ea, 2); /* store ea */
|
if (rx2 || (st > 0x3FFF) || (st < -0x4000)) /* rx2 or too big? */
|
||||||
|
return SCPE_ARG;
|
||||||
|
t = (st & 0x7FFF) | 0x8000;
|
||||||
|
PUTNUM (t, 2); /* store displ */
|
||||||
return -3; }
|
return -3; }
|
||||||
st = (ea - (addr + 4)); /* displ */
|
if (rx2 == 0) { /* no 2nd? */
|
||||||
if ((st <= 0x3FFF) && (st >= -0x4000)) { /* RX2? */
|
if (t < 0x4000) { /* RX1? */
|
||||||
|
PUTNUM (t, 2); /* store ea */
|
||||||
|
return -3; }
|
||||||
|
st = (t - (addr + 4)); /* displ */
|
||||||
|
if (cf && (st <= 0x3FFF) && (st >= -0x4000)) { /* RX2? CPU only */
|
||||||
t = (st & 0x7FFF) | 0x8000;
|
t = (st & 0x7FFF) | 0x8000;
|
||||||
PUTNUM (t, 2); /* store displ */
|
PUTNUM (t, 2); /* store displ */
|
||||||
return -3; } }
|
return -3; } }
|
||||||
ea = (ea & VAMASK32) | 0x40000000 | (rx2 << 24);
|
t = (t & VAMASK32) | 0x40000000 | (rx2 << 24);
|
||||||
PUTNUM (ea, 4); /* RX3 */
|
PUTNUM (t, 4); /* RX3 */
|
||||||
return -5;
|
return -5;
|
||||||
|
|
||||||
case I_V_RI: /* 16b immediate */
|
case I_V_RI: /* 16b immediate */
|
||||||
r = get_imm (gbuf, &ea, &inst, DMASK16); /* process imm */
|
r = get_imm (gbuf, &t, &inst, DMASK16); /* process imm */
|
||||||
if (r != SCPE_OK) return r;
|
if (r != SCPE_OK) return r;
|
||||||
PUTNUM (inst, 2); /* store inst */
|
PUTNUM (inst, 2); /* store inst */
|
||||||
PUTNUM (ea, 2); /* store 16b imm */
|
PUTNUM (t, 2); /* store 16b imm */
|
||||||
return -3;
|
return -3;
|
||||||
|
|
||||||
case I_V_RF:
|
case I_V_RF:
|
||||||
r = get_imm (gbuf, &ea, &inst, DMASK32); /* process imm */
|
r = get_imm (gbuf, &t, &inst, DMASK32); /* process imm */
|
||||||
if (r != SCPE_OK) return r;
|
if (r != SCPE_OK) return r;
|
||||||
PUTNUM (inst, 2); /* store inst */
|
PUTNUM (inst, 2); /* store inst */
|
||||||
PUTNUM (ea, 4); /* store 32b imm */
|
PUTNUM (t, 4); /* store 32b imm */
|
||||||
return -5;
|
return -5;
|
||||||
|
|
||||||
case I_V_SB: case I_V_SX: /* short branches */
|
case I_V_SB: case I_V_SX: /* short branches */
|
||||||
t = get_uint (gbuf, 16, DMASK16, &r); /* get addr */
|
r = get_addr (gbuf, &tptr, &t, &rel, addr, cf); /* get addr */
|
||||||
if ((r != SCPE_OK) || (t & 1)) return r; /* error if odd */
|
if ((r != SCPE_OK) || (t & 1) || *tptr) /* error if odd */
|
||||||
|
return SCPE_ARG;
|
||||||
|
st = t; /* signed version */
|
||||||
|
if (cf) { /* for CPU? */
|
||||||
db = (addr - t) & 0x1F; /* back displ */
|
db = (addr - t) & 0x1F; /* back displ */
|
||||||
df = (t - addr) & 0x1F; /* fwd displ */
|
df = (t - addr) & 0x1F; /* fwd displ */
|
||||||
if ((t == ((addr - db) & VAMASK16)) && /* back work and */
|
if ((t == ((addr - db) & VAMASK16)) && /* back work and */
|
||||||
((j == I_V_SX) || !(inst & MSK_SBF))) { /* ext or back br? */
|
((j == I_V_SX) || !(inst & MSK_SBF))) /* ext or back br? */
|
||||||
inst = inst | (db >> 1); /* or in back displ */
|
inst = inst | (db >> 1); /* or in back displ */
|
||||||
break; }
|
else if ((t == ((addr + df) & VAMASK16)) && /* fwd work and */
|
||||||
if ((t == ((addr + df) & VAMASK16)) && /* fwd work and */
|
((j == I_V_SX) || (inst & MSK_SBF))) /* ext or fwd br? */
|
||||||
((j == I_V_SX) || (inst & MSK_SBF))) { /* ext or fwd br? */
|
|
||||||
inst = inst | (df >> 1) | MSK_SBF; /* or in fwd displ */
|
inst = inst | (df >> 1) | MSK_SBF; /* or in fwd displ */
|
||||||
break; }
|
else return SCPE_ARG; }
|
||||||
return SCPE_ARG; } /* end case */
|
else if (rel) { /* periph, must be rel */
|
||||||
|
if ((st <= 0) && (st >= -0x1F) && /* relative back? */
|
||||||
|
((j == I_V_SX) || !(inst & MSK_SBF)))
|
||||||
|
inst = inst | ((-st & 0x1F) >> 1);
|
||||||
|
else if ((st >= 0) && (st < 0x1F) && /* relative fwd? */
|
||||||
|
((j == I_V_SX) || (inst & MSK_SBF)))
|
||||||
|
inst = inst | ((t & 0x1F) >> 1);
|
||||||
|
else return SCPE_ARG; }
|
||||||
|
else return SCPE_ARG; /* periph & ~rel, err */
|
||||||
|
} /* end case */
|
||||||
|
|
||||||
PUTNUM (inst, 2);
|
PUTNUM (inst, 2);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
The author gratefully acknowledges the help of Carl Friend and Al Kossow,
|
The author gratefully acknowledges the help of Carl Friend and Al Kossow,
|
||||||
who provided key documents about the Interdata product line.
|
who provided key documents about the Interdata product line.
|
||||||
|
|
||||||
|
28-Feb-03 RMS Changed magtape device default to 0x85
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "sim_defs.h" /* simulator defns */
|
#include "sim_defs.h" /* simulator defns */
|
||||||
|
@ -260,12 +262,12 @@ typedef struct interdib DIB;
|
||||||
#define d_LPT 0x62 /* line printer */
|
#define d_LPT 0x62 /* line printer */
|
||||||
#define d_PIC 0x6C /* interval timer */
|
#define d_PIC 0x6C /* interval timer */
|
||||||
#define d_LFC 0x6D /* line freq clk */
|
#define d_LFC 0x6D /* line freq clk */
|
||||||
|
#define d_MT 0x85 /* magtape */
|
||||||
|
#define o_MT0 0x10
|
||||||
#define d_DPC 0xB6 /* disk controller */
|
#define d_DPC 0xB6 /* disk controller */
|
||||||
#define o_DP0 0x10
|
#define o_DP0 0x10
|
||||||
#define o_DPF 0x01 /* offset to fixed */
|
#define o_DPF 0x01 /* offset to fixed */
|
||||||
#define d_FD 0xC1 /* floppy disk */
|
#define d_FD 0xC1 /* floppy disk */
|
||||||
#define d_MT 0xC5 /* magtape */
|
|
||||||
#define o_MT0 0x10
|
|
||||||
#define d_SCH 0xF0 /* selector chan */
|
#define d_SCH 0xF0 /* selector chan */
|
||||||
#define d_IDC 0xFB /* MSM disk ctrl */
|
#define d_IDC 0xFB /* MSM disk ctrl */
|
||||||
#define o_ID0 0x01
|
#define o_ID0 0x01
|
||||||
|
|
|
@ -561,8 +561,8 @@ END OF TEST
|
||||||
---
|
---
|
||||||
Common magtape diagnostic
|
Common magtape diagnostic
|
||||||
|
|
||||||
sim> set mt dev=85 ; 800 bpi default
|
|
||||||
sim> att -e pt0 diag.bin
|
sim> att -e pt0 diag.bin
|
||||||
|
sim> att mt foo.tap
|
||||||
sim> br c4
|
sim> br c4
|
||||||
sim> boot pt0
|
sim> boot pt0
|
||||||
|
|
||||||
|
@ -577,9 +577,6 @@ COMMON MAGNETIC TAPE TEST PROGRAM 06-172R02
|
||||||
*MODE 0 ; prog i/o and selch
|
*MODE 0 ; prog i/o and selch
|
||||||
*RUN
|
*RUN
|
||||||
|
|
||||||
*MODE 0
|
|
||||||
*RUN
|
|
||||||
|
|
||||||
TEST 00
|
TEST 00
|
||||||
NO ERROR
|
NO ERROR
|
||||||
TEST 01
|
TEST 01
|
||||||
|
@ -880,7 +877,7 @@ Bugs found
|
||||||
65. PIC, LFC: ric reloaded from output buffer on count overflow
|
65. PIC, LFC: ric reloaded from output buffer on count overflow
|
||||||
66. PIC, LFC: added diagnostic mode, revised use of count vs timer
|
66. PIC, LFC: added diagnostic mode, revised use of count vs timer
|
||||||
67. DP: track increment algorithm incorrect
|
67. DP: track increment algorithm incorrect
|
||||||
68. DP,IDC: incorrectly setting overrun for less than full sector reads
|
68. DP, IDC: incorrectly setting overrun for less than full sector reads
|
||||||
69. DP: should interrupt on detach (offline)
|
69. DP: should interrupt on detach (offline)
|
||||||
70. FD: high water mark not updated on write
|
70. FD: high water mark not updated on write
|
||||||
71. FD: deleted data not implemented, required for diagnostic
|
71. FD: deleted data not implemented, required for diagnostic
|
||||||
|
@ -905,4 +902,6 @@ Bugs found
|
||||||
90. IDC: drive command 0x30 is an instant NOP
|
90. IDC: drive command 0x30 is an instant NOP
|
||||||
91. IDC: set cylinder with invalid cylinder sets SKI
|
91. IDC: set cylinder with invalid cylinder sets SKI
|
||||||
92. IDC: read with invalid head sets ACF, not DTE
|
92. IDC: read with invalid head sets ACF, not DTE
|
||||||
|
93. DP, IDC: write with cylinder overflow advanced selch pointer
|
||||||
|
94. MT: read error must stop selector channel (if active)
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
To: Users
|
To: Users
|
||||||
From: Bob Supnik
|
From: Bob Supnik
|
||||||
Subj: Interdata 16b/32b Simulator Usage
|
Subj: Interdata 16b/32b Simulator Usage
|
||||||
Date: 15-Jan-2003
|
Date: 15-Mar-2003
|
||||||
|
|
||||||
COPYRIGHT NOTICE
|
COPYRIGHT NOTICE
|
||||||
|
|
||||||
The following copyright notice applies to both the SIMH source and binary:
|
The following copyright notice applies to both the SIMH source and binary:
|
||||||
|
|
||||||
Original code published in 1993-2002, written by Robert M Supnik
|
Original code published in 1993-2003, written by Robert M Supnik
|
||||||
Copyright (c) 1993-2003, Robert M Supnik
|
Copyright (c) 1993-2003, Robert M Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
@ -91,7 +91,7 @@ DP 2.5MB/10MB cartridge disk
|
||||||
DM mass storage module (MSM)/intelligent (IDC) disk controller
|
DM mass storage module (MSM)/intelligent (IDC) disk controller
|
||||||
MT magnetic tape
|
MT magnetic tape
|
||||||
PAS programmable asynchronous line controller
|
PAS programmable asynchronous line controller
|
||||||
PASL programmable asyhchronous lines, up to 32
|
PASL programmable asynchronous lines, up to 32
|
||||||
|
|
||||||
The Interdata simulator implements two unique stop conditions:
|
The Interdata simulator implements two unique stop conditions:
|
||||||
|
|
||||||
|
@ -268,6 +268,10 @@ channels can be changed with the command:
|
||||||
|
|
||||||
SET SELCH CHANNELS=num
|
SET SELCH CHANNELS=num
|
||||||
|
|
||||||
|
All the state for a selector channel can be displayed with the command:
|
||||||
|
|
||||||
|
SHOW SELCH num
|
||||||
|
|
||||||
The selector channels implement these registers:
|
The selector channels implement these registers:
|
||||||
|
|
||||||
name size comments
|
name size comments
|
||||||
|
@ -398,7 +402,7 @@ UC, 7B, or 8B. In UC mode, lower case input and output characters
|
||||||
are automatically converted to upper case. In 7B mode, input and
|
are automatically converted to upper case. In 7B mode, input and
|
||||||
output characters are masked to 7 bits. In 8B mode, characters
|
output characters are masked to 7 bits. In 8B mode, characters
|
||||||
are not modified. Changing the mode of either unit changes both.
|
are not modified. Changing the mode of either unit changes both.
|
||||||
The default mode is UC.
|
The default mode is 7B.
|
||||||
|
|
||||||
To simulate pressing the break key, stop the simulator and use
|
To simulate pressing the break key, stop the simulator and use
|
||||||
the command:
|
the command:
|
||||||
|
@ -412,6 +416,8 @@ The PASLA console interface implements these registers:
|
||||||
|
|
||||||
name size comments
|
name size comments
|
||||||
|
|
||||||
|
CMD 16 command register
|
||||||
|
STA 8 status register
|
||||||
KBUF 8 input buffer
|
KBUF 8 input buffer
|
||||||
KPOS 32 number of characters input
|
KPOS 32 number of characters input
|
||||||
KTIME 24 input polling interval
|
KTIME 24 input polling interval
|
||||||
|
@ -480,7 +486,14 @@ Error handling is as follows:
|
||||||
|
|
||||||
2.4.5 Line Frequency Clock (LFC)
|
2.4.5 Line Frequency Clock (LFC)
|
||||||
|
|
||||||
The line frequency clock (LFC) implements these registers:
|
The line frequency clock (LFC) frequency can be adjusted as follows:
|
||||||
|
|
||||||
|
SET LFC 60HZ set frequency to 60Hz
|
||||||
|
SET LFC 50HZ set frequency to 50Hz
|
||||||
|
|
||||||
|
The default is 60Hz.
|
||||||
|
|
||||||
|
The line frequency clock implements these registers:
|
||||||
|
|
||||||
name size comments
|
name size comments
|
||||||
|
|
||||||
|
@ -488,10 +501,9 @@ The line frequency clock (LFC) implements these registers:
|
||||||
IENB 1 clock interrupt enable
|
IENB 1 clock interrupt enable
|
||||||
IARM 1 clock interrupt armed
|
IARM 1 clock interrupt armed
|
||||||
TIME 24 clock frequency
|
TIME 24 clock frequency
|
||||||
TPS 8 ticks per second (120 or 100)
|
|
||||||
|
|
||||||
The real-time clock autocalibrates; the clock interval is adjusted up or
|
The line frequency clock autocalibrates; the clock interval is adjusted
|
||||||
down so that the clock tracks actual elapsed time.
|
up or down so that the clock tracks actual elapsed time.
|
||||||
|
|
||||||
2.4.6 Programmable Interval Clock (PIC)
|
2.4.6 Programmable Interval Clock (PIC)
|
||||||
|
|
||||||
|
@ -509,8 +521,9 @@ The programmable interval clock (PIC) implements these registers:
|
||||||
IENB 1 clock interrupt enable
|
IENB 1 clock interrupt enable
|
||||||
IARM 1 clock interrupt armed
|
IARM 1 clock interrupt armed
|
||||||
|
|
||||||
If the interval requested is longer than 1 msec, the programmable clock
|
If the interval requested is longer than 1 msec, and a multiple of
|
||||||
auto-calibrates; if not, it simply counts instructions.
|
1 msec, the programmable clock auto-calibrates; if not, it simply
|
||||||
|
counts instructions.
|
||||||
|
|
||||||
2.4.7 Floppy Disk Controller (FD)
|
2.4.7 Floppy Disk Controller (FD)
|
||||||
|
|
||||||
|
@ -634,7 +647,8 @@ block 0, and uses that to locate the volume directory. It then searches
|
||||||
the directory for a filename of the form OS16xxxx.hhh or OS32xxxx.hhh,
|
the directory for a filename of the form OS16xxxx.hhh or OS32xxxx.hhh,
|
||||||
where the xxxx is ignored and hhh is the ASCII form of the extension from
|
where the xxxx is ignored and hhh is the ASCII form of the extension from
|
||||||
locations 7E:7F. The 32b bootstrap can also boot Wollongong UNIX; locations
|
locations 7E:7F. The 32b bootstrap can also boot Wollongong UNIX; locations
|
||||||
7E:7F must be 0.
|
7E:7F must be 0. The bootstrap normally boots from the first (removable)
|
||||||
|
platter in a 5440; to boot from the second (fixed) platter, use BOOT -F.
|
||||||
|
|
||||||
All drives have 256 8b bytes per sector. The other disk parameters are:
|
All drives have 256 8b bytes per sector. The other disk parameters are:
|
||||||
|
|
||||||
|
@ -877,7 +891,9 @@ number, optionally preceded by R, between 1 and F (15).
|
||||||
Instruction input uses standard Interdata assembler syntax. There are
|
Instruction input uses standard Interdata assembler syntax. There are
|
||||||
nine instruction classes: short branch, extended short branch, short
|
nine instruction classes: short branch, extended short branch, short
|
||||||
immediate, 16b immediate, 32b immediate, register, register-register,
|
immediate, 16b immediate, 32b immediate, register, register-register,
|
||||||
memory, and register-memory.
|
memory, and register-memory. Addresses, where required, can be
|
||||||
|
specified as either absolute numbers or relative to the current
|
||||||
|
location (.+n or .-n).
|
||||||
|
|
||||||
Short branch instructions have the format
|
Short branch instructions have the format
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* id_dp.c: Interdata 2.5MB/10MB cartridge disk simulator
|
/* id_dp.c: Interdata 2.5MB/10MB cartridge disk simulator
|
||||||
|
|
||||||
Copyright (c) 2001-2002, Robert M. Supnik
|
Copyright (c) 2001-2003, Robert M. Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -24,6 +24,8 @@
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
dp M46-421 2.5MB/10MB cartridge disk
|
dp M46-421 2.5MB/10MB cartridge disk
|
||||||
|
|
||||||
|
16-Feb-03 RMS Fixed read to test transfer ok before selch operation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "id_defs.h"
|
#include "id_defs.h"
|
||||||
|
@ -133,6 +135,7 @@ static struct drvtyp drv_tab[] = {
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
|
||||||
extern uint32 int_req[INTSZ], int_enb[INTSZ];
|
extern uint32 int_req[INTSZ], int_enb[INTSZ];
|
||||||
|
extern FILE *sim_log;
|
||||||
|
|
||||||
uint8 dpxb[DP_NUMBY]; /* xfer buffer */
|
uint8 dpxb[DP_NUMBY]; /* xfer buffer */
|
||||||
uint32 dp_bptr = 0; /* buffer ptr */
|
uint32 dp_bptr = 0; /* buffer ptr */
|
||||||
|
@ -148,6 +151,7 @@ uint32 dpd_arm[DP_NUMDR] = { 0 }; /* drives armed */
|
||||||
int32 dp_stime = 100; /* seek latency */
|
int32 dp_stime = 100; /* seek latency */
|
||||||
int32 dp_rtime = 100; /* rotate latency */
|
int32 dp_rtime = 100; /* rotate latency */
|
||||||
int32 dp_wtime = 1; /* word time */
|
int32 dp_wtime = 1; /* word time */
|
||||||
|
int32 dp_log = 0; /* debug log */
|
||||||
uint8 dp_tplte[(2 * DP_NUMDR) + 2]; /* fix/rmv + ctrl + end */
|
uint8 dp_tplte[(2 * DP_NUMDR) + 2]; /* fix/rmv + ctrl + end */
|
||||||
|
|
||||||
DEVICE dp_dev;
|
DEVICE dp_dev;
|
||||||
|
@ -208,6 +212,7 @@ REG dp_reg[] = {
|
||||||
DP_NUMDR, REG_RO) },
|
DP_NUMDR, REG_RO) },
|
||||||
{ URDATA (CAPAC, dp_unit[0].capac, 10, 31, 0,
|
{ URDATA (CAPAC, dp_unit[0].capac, 10, 31, 0,
|
||||||
DP_NUMDR, PV_LEFT | REG_HRO) },
|
DP_NUMDR, PV_LEFT | REG_HRO) },
|
||||||
|
{ FLDATA (LOG, dp_log, 0), REG_HIDDEN },
|
||||||
{ HRDATA (DEVNO, dp_dib.dno, 8), REG_HRO },
|
{ HRDATA (DEVNO, dp_dib.dno, 8), REG_HRO },
|
||||||
{ HRDATA (SELCH, dp_dib.sch, 2), REG_HRO },
|
{ HRDATA (SELCH, dp_dib.sch, 2), REG_HRO },
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
@ -260,6 +265,8 @@ case IO_RD: /* read data */
|
||||||
else dp_sta = dp_sta | STA_BSY; /* xfr? set busy */
|
else dp_sta = dp_sta | STA_BSY; /* xfr? set busy */
|
||||||
return dp_db; /* return data */
|
return dp_db; /* return data */
|
||||||
case IO_WD: /* write data */
|
case IO_WD: /* write data */
|
||||||
|
if (sim_log && dp_log) fprintf (sim_log,
|
||||||
|
">>DPC WD = %02X, STA = %02X\n", dat, dp_sta);
|
||||||
if (dp_sta & STC_IDL) dp_hdsc = dat & HS_MASK; /* idle? hdsc */
|
if (dp_sta & STC_IDL) dp_hdsc = dat & HS_MASK; /* idle? hdsc */
|
||||||
else { /* data xfer */
|
else { /* data xfer */
|
||||||
dp_sta = dp_sta | STA_BSY; /* set busy */
|
dp_sta = dp_sta | STA_BSY; /* set busy */
|
||||||
|
@ -270,6 +277,8 @@ case IO_SS: /* status */
|
||||||
if (t & SETC_EX) t = t | STA_EX; /* test for EX */
|
if (t & SETC_EX) t = t | STA_EX; /* test for EX */
|
||||||
return t;
|
return t;
|
||||||
case IO_OC: /* command */
|
case IO_OC: /* command */
|
||||||
|
if (sim_log && dp_log) fprintf (sim_log,
|
||||||
|
">>DPC OC = %02X, STA = %02X\n", dat, dp_sta);
|
||||||
f = dat & CMC_MASK; /* get cmd */
|
f = dat & CMC_MASK; /* get cmd */
|
||||||
if (f & CMC_CLR) { /* clear? */
|
if (f & CMC_CLR) { /* clear? */
|
||||||
dp_reset (&dp_dev); /* reset world */
|
dp_reset (&dp_dev); /* reset world */
|
||||||
|
@ -305,6 +314,8 @@ case IO_ADR: /* select */
|
||||||
if (dp_sta & STC_IDL) dp_svun = dev; /* idle? save unit */
|
if (dp_sta & STC_IDL) dp_svun = dev; /* idle? save unit */
|
||||||
return BY; /* byte only */
|
return BY; /* byte only */
|
||||||
case IO_WD: /* write data */
|
case IO_WD: /* write data */
|
||||||
|
if (sim_log && dp_log) fprintf (sim_log,
|
||||||
|
">>DP%d WD = %02X, STA = %02X\n", u, dat, dp_sta);
|
||||||
if (GET_DTYPE (uptr->flags) == TYPE_2315) /* 2.5MB drive? */
|
if (GET_DTYPE (uptr->flags) == TYPE_2315) /* 2.5MB drive? */
|
||||||
dp_cyl = dat & 0xFF; /* cyl is 8b */
|
dp_cyl = dat & 0xFF; /* cyl is 8b */
|
||||||
else dp_cyl = ((dp_cyl << 8) | dat) & DMASK16; /* insert byte */
|
else dp_cyl = ((dp_cyl << 8) | dat) & DMASK16; /* insert byte */
|
||||||
|
@ -318,6 +329,8 @@ case IO_SS: /* status */
|
||||||
if (t & SETD_EX) t = t | STA_EX; /* test for ex */
|
if (t & SETD_EX) t = t | STA_EX; /* test for ex */
|
||||||
return t;
|
return t;
|
||||||
case IO_OC: /* command */
|
case IO_OC: /* command */
|
||||||
|
if (sim_log && dp_log) fprintf (sim_log,
|
||||||
|
">>DP%d OC = %02X, STA = %02X\n", u, dat, dp_sta);
|
||||||
dpd_arm[u] = int_chg (v_DPC + u + 1, dat, dpd_arm[u]);
|
dpd_arm[u] = int_chg (v_DPC + u + 1, dat, dpd_arm[u]);
|
||||||
if (dat & CMD_SK) t = dp_cyl; /* seek? get cyl */
|
if (dat & CMD_SK) t = dp_cyl; /* seek? get cyl */
|
||||||
else if (dat & CMD_RST) t = 0; /* rest? cyl 0 */
|
else if (dat & CMD_RST) t = 0; /* rest? cyl 0 */
|
||||||
|
@ -378,9 +391,9 @@ case CMC_RD: /* read */
|
||||||
|
|
||||||
case CMC_WR: /* write */
|
case CMC_WR: /* write */
|
||||||
if (sch_actv (dp_dib.sch, dp_dib.dno)) { /* sch transfer? */
|
if (sch_actv (dp_dib.sch, dp_dib.dno)) { /* sch transfer? */
|
||||||
|
if (dp_dter (uptr, dp_1st)) return SCPE_OK; /* check xfr err */
|
||||||
dp_bptr = sch_rdmem (dp_dib.sch, dpxb, DP_NUMBY); /* read from mem */
|
dp_bptr = sch_rdmem (dp_dib.sch, dpxb, DP_NUMBY); /* read from mem */
|
||||||
dp_db = dpxb[dp_bptr - 1]; /* last byte */
|
dp_db = dpxb[dp_bptr - 1]; /* last byte */
|
||||||
if (dp_dter (uptr, dp_1st)) return SCPE_OK; /* check xfr err */
|
|
||||||
if (r = dp_wds (uptr)) return r; /* write sec, err? */
|
if (r = dp_wds (uptr)) return r; /* write sec, err? */
|
||||||
dp_1st = 0;
|
dp_1st = 0;
|
||||||
if (sch_actv (dp_dib.sch, dp_dib.dno)) { /* more to do? */
|
if (sch_actv (dp_dib.sch, dp_dib.dno)) { /* more to do? */
|
||||||
|
@ -440,8 +453,10 @@ if (((uptr->flags & UNIT_ATT) == 0) || /* not attached? */
|
||||||
hd = GET_SRF (dp_hdsc); /* get head */
|
hd = GET_SRF (dp_hdsc); /* get head */
|
||||||
sc = GET_SEC (dp_hdsc); /* get sector */
|
sc = GET_SEC (dp_hdsc); /* get sector */
|
||||||
if (dp_cyl != (uint32) uptr->CYL) { /* wrong cylinder? */
|
if (dp_cyl != (uint32) uptr->CYL) { /* wrong cylinder? */
|
||||||
|
if (dp_cyl == 0) uptr->CYL = 0;
|
||||||
|
else {
|
||||||
dp_done (STC_ACF); /* error, done */
|
dp_done (STC_ACF); /* error, done */
|
||||||
return TRUE; }
|
return TRUE; } }
|
||||||
if (sc >= DP_NUMSC) { /* bad sector? */
|
if (sc >= DP_NUMSC) { /* bad sector? */
|
||||||
dp_done (STC_OVR); /* error, done */
|
dp_done (STC_OVR); /* error, done */
|
||||||
return TRUE; }
|
return TRUE; }
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* id_idc.c: Interdata MSM/IDC disk controller simulator
|
/* id_idc.c: Interdata MSM/IDC disk controller simulator
|
||||||
|
|
||||||
Copyright (c) 2001-2002, Robert M. Supnik
|
Copyright (c) 2001-2003, Robert M. Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
idc MSM/IDC disk controller
|
idc MSM/IDC disk controller
|
||||||
|
|
||||||
|
16-Feb-03 RMS Fixed read to test transfer ok before selch operation
|
||||||
|
|
||||||
Note: define flag ID_IDC to enable the extra functions of the intelligent
|
Note: define flag ID_IDC to enable the extra functions of the intelligent
|
||||||
disk controller
|
disk controller
|
||||||
*/
|
*/
|
||||||
|
@ -491,7 +493,6 @@ case CMC_RUNC: /* read uncorr */
|
||||||
case CMC_RD: /* read */
|
case CMC_RD: /* read */
|
||||||
if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* sch transfer? */
|
if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* sch transfer? */
|
||||||
if (idc_dter (uptr, idc_1st)) return SCPE_OK; /* dte? done */
|
if (idc_dter (uptr, idc_1st)) return SCPE_OK; /* dte? done */
|
||||||
/* fseek done */
|
|
||||||
if (r = idc_rds (uptr)) return r; /* read sec, err? */
|
if (r = idc_rds (uptr)) return r; /* read sec, err? */
|
||||||
idc_1st = 0;
|
idc_1st = 0;
|
||||||
t = sch_wrmem (idc_dib.sch, idcxb, IDC_NUMBY); /* write mem */
|
t = sch_wrmem (idc_dib.sch, idcxb, IDC_NUMBY); /* write mem */
|
||||||
|
@ -504,9 +505,9 @@ case CMC_RD: /* read */
|
||||||
|
|
||||||
case CMC_WR: /* write */
|
case CMC_WR: /* write */
|
||||||
if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* sch transfer? */
|
if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* sch transfer? */
|
||||||
|
if (idc_dter (uptr, idc_1st)) return SCPE_OK; /* dte? done */
|
||||||
idc_bptr = sch_rdmem (idc_dib.sch, idcxb, IDC_NUMBY); /* read mem */
|
idc_bptr = sch_rdmem (idc_dib.sch, idcxb, IDC_NUMBY); /* read mem */
|
||||||
idc_db = idcxb[idc_bptr - 1]; /* last byte */
|
idc_db = idcxb[idc_bptr - 1]; /* last byte */
|
||||||
if (idc_dter (uptr, idc_1st)) return SCPE_OK; /* dte? done */
|
|
||||||
if (r = idc_wds (uptr)) return r; /* write sec, err? */
|
if (r = idc_wds (uptr)) return r; /* write sec, err? */
|
||||||
idc_1st = 0;
|
idc_1st = 0;
|
||||||
if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* more to do? */
|
if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* more to do? */
|
||||||
|
|
|
@ -35,8 +35,7 @@
|
||||||
Interdata I/O uses the following interconnected tables:
|
Interdata I/O uses the following interconnected tables:
|
||||||
|
|
||||||
dev_tab[dev] Indexed by device number, points to the I/O instruction
|
dev_tab[dev] Indexed by device number, points to the I/O instruction
|
||||||
processing routine for the device. Initialized in the
|
processing routine for the device.
|
||||||
device reset routine.
|
|
||||||
|
|
||||||
sch_tab[dev] Indexed by device number, if non-zero, the number + 1
|
sch_tab[dev] Indexed by device number, if non-zero, the number + 1
|
||||||
of the selector channel used by the device.
|
of the selector channel used by the device.
|
||||||
|
@ -81,7 +80,8 @@ uint8 sch_tplte[SCH_NUMCH + 1]; /* dnum template */
|
||||||
uint32 sch (uint32 dev, uint32 op, uint32 dat);
|
uint32 sch (uint32 dev, uint32 op, uint32 dat);
|
||||||
void sch_ini (t_bool dtpl);
|
void sch_ini (t_bool dtpl);
|
||||||
t_stat sch_reset (DEVICE *dptr);
|
t_stat sch_reset (DEVICE *dptr);
|
||||||
t_stat sch_vchan (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat sch_set_nchan (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat sch_show_reg (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
|
|
||||||
/* Selector channel data structures
|
/* Selector channel data structures
|
||||||
|
|
||||||
|
@ -110,7 +110,15 @@ REG sch_reg[] = {
|
||||||
|
|
||||||
MTAB sch_mod[] = {
|
MTAB sch_mod[] = {
|
||||||
{ MTAB_XTD|MTAB_VDV|MTAB_VAL, 0, "channels", "CHANNELS",
|
{ MTAB_XTD|MTAB_VDV|MTAB_VAL, 0, "channels", "CHANNELS",
|
||||||
&sch_vchan, NULL, &sch_reg[0] },
|
&sch_set_nchan, NULL, &sch_reg[0] },
|
||||||
|
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "0", NULL,
|
||||||
|
NULL, &sch_show_reg, NULL },
|
||||||
|
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "1", NULL,
|
||||||
|
NULL, &sch_show_reg, NULL },
|
||||||
|
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 2, "2", NULL,
|
||||||
|
NULL, &sch_show_reg, NULL },
|
||||||
|
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 3, "3", NULL,
|
||||||
|
NULL, &sch_show_reg, NULL },
|
||||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||||
&set_dev, &show_dev, &sch_dib },
|
&set_dev, &show_dev, &sch_dib },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
@ -298,7 +306,7 @@ return SCPE_OK;
|
||||||
|
|
||||||
/* Set number of channels */
|
/* Set number of channels */
|
||||||
|
|
||||||
t_stat sch_vchan (UNIT *uptr, int32 val, char *cptr, void *desc)
|
t_stat sch_set_nchan (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
{
|
{
|
||||||
DEVICE *dptr;
|
DEVICE *dptr;
|
||||||
DIB *dibp;
|
DIB *dibp;
|
||||||
|
@ -323,6 +331,21 @@ sch_reset_ch (sch_max); /* reset chan */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Show channel registers */
|
||||||
|
|
||||||
|
t_stat sch_show_reg (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
|
{
|
||||||
|
if (val < 0) return SCPE_IERR;
|
||||||
|
if (val >= (int32) sch_max) fprintf (st, "Channel %d disabled\n", val);
|
||||||
|
else { fprintf (st, "SA: %05X\n", sch_sa[val]);
|
||||||
|
fprintf (st, "EA: %05X\n", sch_ea[val]);
|
||||||
|
fprintf (st, "CMD: %02X\n", sch_cmd[val]);
|
||||||
|
fprintf (st, "DEV: %02X\n", sch_sdv[val]);
|
||||||
|
fprintf (st, "RDP: %X\n", sch_rdp[val]);
|
||||||
|
fprintf (st, "WDC: %X\n", sch_wdc[val]); }
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialize template */
|
/* Initialize template */
|
||||||
|
|
||||||
void sch_ini (t_bool dtpl)
|
void sch_ini (t_bool dtpl)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* id_mt.c: Interdata magnetic tape simulator
|
/* id_mt.c: Interdata magnetic tape simulator
|
||||||
|
|
||||||
Copyright (c) 2001-2002, Robert M Supnik
|
Copyright (c) 2001-2003, Robert M Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,9 @@
|
||||||
|
|
||||||
mt M46-494 dual density 9-track magtape controller
|
mt M46-494 dual density 9-track magtape controller
|
||||||
|
|
||||||
|
28-Feb-03 RMS Revised for magtape library
|
||||||
|
20-Feb-03 RMS Fixed read to stop selch on error
|
||||||
|
|
||||||
Magnetic tapes are represented as a series of variable 8b records
|
Magnetic tapes are represented as a series of variable 8b records
|
||||||
of the form:
|
of the form:
|
||||||
|
|
||||||
|
@ -42,15 +45,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "id_defs.h"
|
#include "id_defs.h"
|
||||||
|
#include "sim_tape.h"
|
||||||
|
|
||||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
|
||||||
#define UNIT_V_PNU (UNIT_V_UF + 1) /* pos not updated */
|
|
||||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
|
||||||
#define UNIT_PNU (1 << UNIT_V_PNU)
|
|
||||||
#define UST u3 /* unit status */
|
#define UST u3 /* unit status */
|
||||||
#define UCMD u4 /* unit command */
|
#define UCMD u4 /* unit command */
|
||||||
#define MT_MAXFR (1 << 16) /* max transfer */
|
#define MT_MAXFR (1 << 16) /* max transfer */
|
||||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
|
||||||
|
|
||||||
/* Command - in UCMD */
|
/* Command - in UCMD */
|
||||||
|
|
||||||
|
@ -98,15 +97,12 @@ static const uint8 bad_cmd[64] = {
|
||||||
|
|
||||||
DEVICE mt_dev;
|
DEVICE mt_dev;
|
||||||
uint32 mt (uint32 dev, uint32 op, uint32 dat);
|
uint32 mt (uint32 dev, uint32 op, uint32 dat);
|
||||||
t_bool mt_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
|
||||||
t_bool mt_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
|
||||||
t_bool mt_forwsp (UNIT *uptr, int32 *err);
|
|
||||||
t_bool mt_backsp (UNIT *uptr, int32 *err);
|
|
||||||
t_stat mt_svc (UNIT *uptr);
|
t_stat mt_svc (UNIT *uptr);
|
||||||
t_stat mt_reset (DEVICE *dptr);
|
t_stat mt_reset (DEVICE *dptr);
|
||||||
t_stat mt_attach (UNIT *uptr, char *cptr);
|
t_stat mt_attach (UNIT *uptr, char *cptr);
|
||||||
t_stat mt_detach (UNIT *uptr);
|
t_stat mt_detach (UNIT *uptr);
|
||||||
t_stat mt_boot (int32 unitno, DEVICE *dptr);
|
t_stat mt_boot (int32 unitno, DEVICE *dptr);
|
||||||
|
t_stat mt_map_err (UNIT *uptr, t_stat st);
|
||||||
|
|
||||||
/* MT data structures
|
/* MT data structures
|
||||||
|
|
||||||
|
@ -146,8 +142,8 @@ REG mt_reg[] = {
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
MTAB mt_mod[] = {
|
MTAB mt_mod[] = {
|
||||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
|
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
|
||||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||||
&set_dev, &show_dev, NULL },
|
&set_dev, &show_dev, NULL },
|
||||||
{ MTAB_XTD|MTAB_VDV, 0, "SELCH", "SELCH",
|
{ MTAB_XTD|MTAB_VDV, 0, "SELCH", "SELCH",
|
||||||
|
@ -200,7 +196,7 @@ case IO_OC: /* command */
|
||||||
if (((uptr->flags & UNIT_ATT) == 0) || /* ignore if unatt */
|
if (((uptr->flags & UNIT_ATT) == 0) || /* ignore if unatt */
|
||||||
bad_cmd[f] || /* or bad cmd */
|
bad_cmd[f] || /* or bad cmd */
|
||||||
(((f == MTC_WR) || (f == MTC_WEOF)) && /* or write */
|
(((f == MTC_WR) || (f == MTC_WEOF)) && /* or write */
|
||||||
(uptr->flags & UNIT_WPRT))) break; /* and protected */
|
sim_tape_wrp (uptr))) break; /* and protected */
|
||||||
for (i = 0; i < MT_NUMDR; i++) { /* check other drvs */
|
for (i = 0; i < MT_NUMDR; i++) { /* check other drvs */
|
||||||
if (sim_is_active (&mt_unit[i]) && /* active? */
|
if (sim_is_active (&mt_unit[i]) && /* active? */
|
||||||
(mt_unit[i].UCMD != MTC_REW)) { /* not rewind? */
|
(mt_unit[i].UCMD != MTC_REW)) { /* not rewind? */
|
||||||
|
@ -238,16 +234,11 @@ return 0;
|
||||||
|
|
||||||
t_stat mt_svc (UNIT *uptr)
|
t_stat mt_svc (UNIT *uptr)
|
||||||
{
|
{
|
||||||
uint32 i, pnu;
|
uint32 i;
|
||||||
int32 err;
|
|
||||||
int32 u = uptr - mt_dev.units;
|
int32 u = uptr - mt_dev.units;
|
||||||
uint32 dev = mt_dib.dno + (u * o_MT0);
|
uint32 dev = mt_dib.dno + (u * o_MT0);
|
||||||
t_mtrlnt tbc;
|
t_mtrlnt tbc;
|
||||||
static t_mtrlnt bceof = { 0 };
|
t_stat st, r = SCPE_OK;
|
||||||
|
|
||||||
err = 0;
|
|
||||||
pnu = MT_TST_PNU (uptr); /* get pos not upd */
|
|
||||||
MT_CLR_PNU (uptr); /* and clear */
|
|
||||||
|
|
||||||
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
|
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
|
||||||
uptr->UCMD = 0; /* clr cmd */
|
uptr->UCMD = 0; /* clr cmd */
|
||||||
|
@ -274,8 +265,8 @@ if (uptr->UCMD & MTC_STOP1) { /* stop, gen EOM? */
|
||||||
switch (uptr->UCMD) { /* case on function */
|
switch (uptr->UCMD) { /* case on function */
|
||||||
|
|
||||||
case MTC_REW: /* rewind */
|
case MTC_REW: /* rewind */
|
||||||
|
sim_tape_rewind (uptr); /* reposition */
|
||||||
uptr->UCMD = 0; /* clr cmd */
|
uptr->UCMD = 0; /* clr cmd */
|
||||||
uptr->pos = 0; /* update position */
|
|
||||||
uptr->UST = STA_NMTN | STA_EOT; /* update status */
|
uptr->UST = STA_NMTN | STA_EOT; /* update status */
|
||||||
mt_sta = mt_sta & ~STA_BSY; /* don't set EOM */
|
mt_sta = mt_sta & ~STA_BSY; /* don't set EOM */
|
||||||
if (mt_arm[u]) SET_INT (v_MT + u); /* interrupt */
|
if (mt_arm[u]) SET_INT (v_MT + u); /* interrupt */
|
||||||
|
@ -293,16 +284,15 @@ case MTC_REW: /* rewind */
|
||||||
|
|
||||||
case MTC_RD: /* read */
|
case MTC_RD: /* read */
|
||||||
if (mt_blnt == 0) { /* first time? */
|
if (mt_blnt == 0) { /* first time? */
|
||||||
if (mt_rdlntf (uptr, &tbc, &err)) break; /* read rec lnt, err? */
|
st = sim_tape_rdrecf (uptr, mtxb, &tbc, MT_MAXFR); /* read rec */
|
||||||
mt_blnt = tbc; /* set buf lnt */
|
if (st == MTSE_RECE) mt_sta = mt_sta | STA_ERR; /* rec in err? */
|
||||||
if (tbc > MT_MAXFR) return SCPE_MTRLNT; /* record too long? */
|
else if (st != SCPE_OK) { /* other error? */
|
||||||
i = fxread (mtxb, sizeof (uint8), mt_blnt, uptr->fileref);
|
r = mt_map_err (uptr, st); /* map error */
|
||||||
if (err = ferror (uptr->fileref)) { /* error? */
|
if (sch_actv (mt_dib.sch, dev)) /* if sch, stop */
|
||||||
MT_SET_PNU (uptr); /* pos not upd */
|
sch_stop (mt_dib.sch);
|
||||||
break; }
|
break; }
|
||||||
for ( ; i < mt_blnt; i++) mtxb[i] = 0; /* fill with 0's */
|
mt_blnt = tbc; /* set buf lnt */
|
||||||
uptr->pos = uptr->pos + ((tbc + 1) & ~1) /* upd pos */
|
}
|
||||||
+ (2 * sizeof (t_mtrlnt)); }
|
|
||||||
|
|
||||||
if (sch_actv (mt_dib.sch, dev)) { /* sch active? */
|
if (sch_actv (mt_dib.sch, dev)) { /* sch active? */
|
||||||
i = sch_wrmem (mt_dib.sch, mtxb, mt_blnt); /* store rec in mem */
|
i = sch_wrmem (mt_dib.sch, mtxb, mt_blnt); /* store rec in mem */
|
||||||
|
@ -334,114 +324,77 @@ case MTC_WR: /* write */
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
|
|
||||||
if (mt_bptr) { /* any chars? */
|
if (mt_bptr) { /* any chars? */
|
||||||
int32 ebc = (mt_bptr + 1) & ~1; /* force even */
|
if (st = sim_tape_wrrecf (uptr, mtxb, mt_bptr)) /* write, err? */
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
r = mt_map_err (uptr, st); } /* map error */
|
||||||
fxwrite (&mt_bptr, sizeof (t_mtrlnt), 1, uptr->fileref);
|
|
||||||
fxwrite (mtxb, sizeof (uint8), ebc, uptr->fileref);
|
|
||||||
fxwrite (&mt_bptr, sizeof (t_mtrlnt), 1, uptr->fileref);
|
|
||||||
if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr);
|
|
||||||
else uptr->pos = uptr->pos + ebc + (2 * sizeof (t_mtrlnt)); }
|
|
||||||
break; /* record done */
|
break; /* record done */
|
||||||
|
|
||||||
/* Unit service, continued */
|
/* Unit service, continued */
|
||||||
|
|
||||||
case MTC_WEOF: /* write eof */
|
case MTC_WEOF: /* write eof */
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set pos */
|
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
|
||||||
fxwrite (&bceof, sizeof (t_mtrlnt), 1, uptr->fileref);
|
r = mt_map_err (uptr, st); /* map error */
|
||||||
if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr);
|
|
||||||
else uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* update pos */
|
|
||||||
mt_sta = mt_sta | STA_EOF; /* set eof */
|
mt_sta = mt_sta | STA_EOF; /* set eof */
|
||||||
if (mt_arm[u]) SET_INT (v_MT + u); /* interrupt */
|
if (mt_arm[u]) SET_INT (v_MT + u); /* interrupt */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MTC_SKFF: /* skip file fwd */
|
case MTC_SKFF: /* skip file fwd */
|
||||||
while (mt_forwsp (uptr, &err)) ; /* spc until EOF/EOT */
|
while ((st = sim_tape_sprecf (uptr, &tbc)) == MTSE_OK) ;
|
||||||
|
if (st == MTSE_TMK) { /* stopped by tmk? */
|
||||||
|
mt_sta = mt_sta | STA_EOF; /* set eof */
|
||||||
|
if (mt_arm[u]) SET_INT (v_MT + u); } /* set intr */
|
||||||
|
else r = mt_map_err (uptr, st); /* map error */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MTC_SKFR: /* skip file rev */
|
case MTC_SKFR: /* skip file rev */
|
||||||
while (mt_backsp (uptr, &err)) ; /* spc until EOF/BOT */
|
while ((st = sim_tape_sprecr (uptr, &tbc)) == MTSE_OK) ;
|
||||||
|
if (st == MTSE_TMK) { /* stopped by tmk? */
|
||||||
|
mt_sta = mt_sta | STA_EOF; /* set eof */
|
||||||
|
if (mt_arm[u]) SET_INT (v_MT + u); } /* set intr */
|
||||||
|
else r = mt_map_err (uptr, st); /* map error */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MTC_SPCR: /* backspace */
|
case MTC_SPCR: /* backspace */
|
||||||
if (!pnu) mt_backsp (uptr, &err); /* if pos not upd */
|
if (st = sim_tape_sprecr (uptr, &tbc)) /* skip rec rev, err? */
|
||||||
|
r = mt_map_err (uptr, st); /* map error */
|
||||||
break; } /* end case */
|
break; } /* end case */
|
||||||
|
|
||||||
if (err != 0) { /* I/O error */
|
|
||||||
mt_sta = mt_sta | STA_ERR;
|
|
||||||
perror ("MT I/O error");
|
|
||||||
clearerr (uptr->fileref);
|
|
||||||
if (mt_stopioe) return SCPE_IOERR; }
|
|
||||||
uptr->UCMD = uptr->UCMD | MTC_STOP1; /* set stop stage 1 */
|
uptr->UCMD = uptr->UCMD | MTC_STOP1; /* set stop stage 1 */
|
||||||
sim_activate (uptr, mt_rtime); /* schedule */
|
sim_activate (uptr, mt_rtime); /* schedule */
|
||||||
return SCPE_OK;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tape motion routines */
|
/* Map tape error status */
|
||||||
|
|
||||||
t_bool mt_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
t_stat mt_map_err (UNIT *uptr, t_stat st)
|
||||||
{
|
{
|
||||||
int32 u = uptr - mt_dev.units;
|
int32 u = uptr - mt_dev.units;
|
||||||
|
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* position */
|
switch (st) {
|
||||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref); /* get bc */
|
case MTSE_FMT: /* illegal fmt */
|
||||||
if ((*err = ferror (uptr->fileref)) || /* err or eom? */
|
case MTSE_UNATT: /* not attached */
|
||||||
feof (uptr->fileref) || (*tbc == MTR_EOM)) {
|
mt_sta = mt_sta | STA_ERR;
|
||||||
mt_sta = mt_sta | STA_ERR; /* set err */
|
case MTSE_OK: /* no error */
|
||||||
MT_SET_PNU (uptr); /* pos not upd */
|
return SCPE_IERR;
|
||||||
return TRUE; }
|
case MTSE_TMK: /* end of file */
|
||||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
|
||||||
mt_sta = mt_sta | STA_EOF; /* set eof */
|
mt_sta = mt_sta | STA_EOF; /* set eof */
|
||||||
if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */
|
if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */
|
||||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* update pos */
|
break;
|
||||||
return TRUE; }
|
case MTSE_IOERR: /* IO error */
|
||||||
*tbc = MTRL (*tbc);
|
mt_sta = mt_sta | STA_ERR; /* set err */
|
||||||
return FALSE;
|
if (mt_stopioe) return SCPE_IOERR;
|
||||||
}
|
break;
|
||||||
|
case MTSE_INVRL: /* invalid rec lnt */
|
||||||
t_bool mt_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
mt_sta = mt_sta | STA_ERR;
|
||||||
{
|
return SCPE_MTRLNT;
|
||||||
int32 u = uptr - mt_dev.units;
|
case MTSE_WRP: /* write protect */
|
||||||
|
case MTSE_RECE: /* record in error */
|
||||||
if (uptr->pos < sizeof (t_mtrlnt)) { /* at bot? */
|
case MTSE_EOM: /* end of medium */
|
||||||
|
mt_sta = mt_sta | STA_ERR; /* set err */
|
||||||
|
break;
|
||||||
|
case MTSE_BOT: /* reverse into BOT */
|
||||||
uptr->UST = uptr->UST | STA_EOT; /* set err */
|
uptr->UST = uptr->UST | STA_EOT; /* set err */
|
||||||
return TRUE; }
|
break; } /* end switch */
|
||||||
fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET);
|
return SCPE_OK;
|
||||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref); /* get bc */
|
|
||||||
if ((*err = ferror (uptr->fileref)) || /* err or eof? */
|
|
||||||
feof (uptr->fileref)) {
|
|
||||||
mt_sta = mt_sta | STA_ERR; /* set err */
|
|
||||||
return TRUE; }
|
|
||||||
if (*tbc == MTR_EOM) { /* eom? */
|
|
||||||
mt_sta = mt_sta | STA_ERR; /* set err */
|
|
||||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* update pos */
|
|
||||||
return TRUE; }
|
|
||||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
|
||||||
mt_sta = mt_sta | STA_EOF; /* set eof */
|
|
||||||
if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */
|
|
||||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* update pos */
|
|
||||||
return TRUE; }
|
|
||||||
*tbc = MTRL (*tbc);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
t_bool mt_forwsp (UNIT *uptr, int32 *err)
|
|
||||||
{
|
|
||||||
t_mtrlnt tbc;
|
|
||||||
|
|
||||||
if (mt_rdlntf (uptr, &tbc, err)) return FALSE; /* read rec lnt, err? */
|
|
||||||
uptr->pos = uptr->pos + ((tbc + 1) & ~1) + /* space to next rec */
|
|
||||||
(2 * sizeof (t_mtrlnt));
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
t_bool mt_backsp (UNIT *uptr, int32 *err)
|
|
||||||
{
|
|
||||||
t_mtrlnt tbc;
|
|
||||||
|
|
||||||
if (mt_rdlntr (uptr, &tbc, err)) return FALSE; /* read rec lnt, err? */
|
|
||||||
uptr->pos = uptr->pos - ((tbc + 1) & ~1) - /* space to prv rec */
|
|
||||||
(2 * sizeof (t_mtrlnt));
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset routine */
|
/* Reset routine */
|
||||||
|
@ -459,7 +412,7 @@ for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */
|
||||||
CLR_ENB (v_MT + u); /* disable int */
|
CLR_ENB (v_MT + u); /* disable int */
|
||||||
mt_arm[u] = 0; /* disarm int */
|
mt_arm[u] = 0; /* disarm int */
|
||||||
uptr = mt_dev.units + u;
|
uptr = mt_dev.units + u;
|
||||||
MT_CLR_PNU (uptr); /* clear pos flag */
|
sim_tape_reset (uptr); /* clear pos flag */
|
||||||
sim_cancel (uptr); /* cancel activity */
|
sim_cancel (uptr); /* cancel activity */
|
||||||
uptr->UST = (uptr->UST & STA_UFLGS) | STA_NMTN; /* init status */
|
uptr->UST = (uptr->UST & STA_UFLGS) | STA_NMTN; /* init status */
|
||||||
uptr->UCMD = 0; } /* init cmd */
|
uptr->UCMD = 0; } /* init cmd */
|
||||||
|
@ -473,10 +426,8 @@ t_stat mt_attach (UNIT *uptr, char *cptr)
|
||||||
int32 u = uptr - mt_dev.units;
|
int32 u = uptr - mt_dev.units;
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
r = attach_unit (uptr, cptr);
|
r = sim_tape_attach (uptr, cptr);
|
||||||
if (r != SCPE_OK) return r;
|
if (r != SCPE_OK) return r;
|
||||||
uptr->pos = 0;
|
|
||||||
MT_CLR_PNU (uptr);
|
|
||||||
uptr->UST = STA_EOT;
|
uptr->UST = STA_EOT;
|
||||||
if (mt_arm[u]) SET_INT (v_MT + u);
|
if (mt_arm[u]) SET_INT (v_MT + u);
|
||||||
return r;
|
return r;
|
||||||
|
@ -489,11 +440,9 @@ t_stat mt_detach (UNIT* uptr)
|
||||||
int32 u = uptr - mt_dev.units;
|
int32 u = uptr - mt_dev.units;
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK;
|
r = sim_tape_detach (uptr);
|
||||||
r = detach_unit (uptr);
|
|
||||||
if (r != SCPE_OK) return r;
|
if (r != SCPE_OK) return r;
|
||||||
if (mt_arm[u]) SET_INT (v_MT + u);
|
if (mt_arm[u]) SET_INT (v_MT + u);
|
||||||
MT_CLR_PNU (uptr);
|
|
||||||
uptr->UST = 0;
|
uptr->UST = 0;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -518,7 +467,7 @@ extern DIB sch_dib;
|
||||||
uint32 sch_dev;
|
uint32 sch_dev;
|
||||||
|
|
||||||
if (decrom[0xD5] & dec_flgs) return SCPE_NOFNC; /* AL defined? */
|
if (decrom[0xD5] & dec_flgs) return SCPE_NOFNC; /* AL defined? */
|
||||||
mt_unit[unitno].pos = 0; /* rewind */
|
sim_tape_rewind (&mt_unit[unitno]); /* rewind */
|
||||||
sch_dev = sch_dib.dno + mt_dib.sch; /* sch dev # */
|
sch_dev = sch_dib.dno + mt_dib.sch; /* sch dev # */
|
||||||
IOWriteBlk (BOOT_START, BOOT_LEN, boot_rom); /* copy boot */
|
IOWriteBlk (BOOT_START, BOOT_LEN, boot_rom); /* copy boot */
|
||||||
IOWriteB (AL_DEV, mt_dib.dno + (unitno * o_MT0)); /* set dev no for unit */
|
IOWriteB (AL_DEV, mt_dib.dno + (unitno * o_MT0)); /* set dev no for unit */
|
||||||
|
|
|
@ -76,8 +76,8 @@ extern int32 pas_par (int32 cmd, int32 c);
|
||||||
DIB ttp_dib = { d_TTP, -1, v_TTP, ttp_tplte, &ttp, NULL };
|
DIB ttp_dib = { d_TTP, -1, v_TTP, ttp_tplte, &ttp, NULL };
|
||||||
|
|
||||||
UNIT ttp_unit[] = {
|
UNIT ttp_unit[] = {
|
||||||
{ UDATA (&ttpi_svc, UNIT_UC, 0), KBD_POLL_WAIT },
|
{ UDATA (&ttpi_svc, 0, 0), KBD_POLL_WAIT },
|
||||||
{ UDATA (&ttpo_svc, UNIT_UC, 0), SERIAL_OUT_WAIT }
|
{ UDATA (&ttpo_svc, 0, 0), SERIAL_OUT_WAIT }
|
||||||
};
|
};
|
||||||
|
|
||||||
REG ttp_reg[] = {
|
REG ttp_reg[] = {
|
||||||
|
|
|
@ -25,6 +25,9 @@
|
||||||
|
|
||||||
pic precision incremental clock
|
pic precision incremental clock
|
||||||
lfc line frequency clock
|
lfc line frequency clock
|
||||||
|
|
||||||
|
01-Mar-03 RMS Added SET/SHOW LFC FREQ support
|
||||||
|
Changed precision clock algorithm for V7 UNIX
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "id_defs.h"
|
#include "id_defs.h"
|
||||||
|
@ -56,7 +59,9 @@ uint32 pic_rdp = 0;
|
||||||
uint32 pic_wdp = 0;
|
uint32 pic_wdp = 0;
|
||||||
uint32 pic_cnti = 0; /* instr/timer */
|
uint32 pic_cnti = 0; /* instr/timer */
|
||||||
uint32 pic_arm = 0; /* int arm */
|
uint32 pic_arm = 0; /* int arm */
|
||||||
|
uint32 pic_decr = 1; /* decrement */
|
||||||
uint16 pic_time[4] = { 1, 10, 100, 1000 }; /* delays */
|
uint16 pic_time[4] = { 1, 10, 100, 1000 }; /* delays */
|
||||||
|
uint16 pic_usec[4] = { 1, 10, 100, 1000 }; /* usec per tick */
|
||||||
static int32 pic_map[16] = { /* map rate to delay */
|
static int32 pic_map[16] = { /* map rate to delay */
|
||||||
0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 };
|
0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 };
|
||||||
|
|
||||||
|
@ -74,6 +79,8 @@ DEVICE lfc_dev;
|
||||||
uint32 lfc (uint32 dev, uint32 op, uint32 dat);
|
uint32 lfc (uint32 dev, uint32 op, uint32 dat);
|
||||||
t_stat lfc_svc (UNIT *uptr);
|
t_stat lfc_svc (UNIT *uptr);
|
||||||
t_stat lfc_reset (DEVICE *dptr);
|
t_stat lfc_reset (DEVICE *dptr);
|
||||||
|
t_stat lfc_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat lfc_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
|
|
||||||
/* PIC data structures
|
/* PIC data structures
|
||||||
|
|
||||||
|
@ -90,7 +97,6 @@ REG pic_reg[] = {
|
||||||
{ HRDATA (BUF, pic_db, 16) },
|
{ HRDATA (BUF, pic_db, 16) },
|
||||||
{ HRDATA (RIC, pic_ric, 16) },
|
{ HRDATA (RIC, pic_ric, 16) },
|
||||||
{ HRDATA (CIC, pic_cic, 12) },
|
{ HRDATA (CIC, pic_cic, 12) },
|
||||||
{ DRDATA (SAVE, pic_save, 32), REG_HRO + PV_LEFT },
|
|
||||||
{ FLDATA (RDP, pic_rdp, 0) },
|
{ FLDATA (RDP, pic_rdp, 0) },
|
||||||
{ FLDATA (WDP, pic_wdp, 0) },
|
{ FLDATA (WDP, pic_wdp, 0) },
|
||||||
{ FLDATA (OVF, pic_ovf, 0) },
|
{ FLDATA (OVF, pic_ovf, 0) },
|
||||||
|
@ -98,6 +104,9 @@ REG pic_reg[] = {
|
||||||
{ FLDATA (IENB, int_enb[l_PIC], i_PIC) },
|
{ FLDATA (IENB, int_enb[l_PIC], i_PIC) },
|
||||||
{ FLDATA (IARM, pic_arm, 0) },
|
{ FLDATA (IARM, pic_arm, 0) },
|
||||||
{ BRDATA (TIME, pic_time, 10, 16, 4), REG_NZ + PV_LEFT },
|
{ BRDATA (TIME, pic_time, 10, 16, 4), REG_NZ + PV_LEFT },
|
||||||
|
{ DRDATA (SAVE, pic_save, 32), REG_HRO + PV_LEFT },
|
||||||
|
{ DRDATA (DECR, pic_decr, 16), REG_HRO + PV_LEFT },
|
||||||
|
{ FLDATA (MODE, pic_cnti, 0), REG_HRO },
|
||||||
{ HRDATA (DEVNO, pic_dib.dno, 8), REG_HRO },
|
{ HRDATA (DEVNO, pic_dib.dno, 8), REG_HRO },
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
|
@ -131,11 +140,17 @@ REG lfc_reg[] = {
|
||||||
{ FLDATA (IENB, int_enb[l_LFC], i_LFC) },
|
{ FLDATA (IENB, int_enb[l_LFC], i_LFC) },
|
||||||
{ FLDATA (IARM, lfc_arm, 0) },
|
{ FLDATA (IARM, lfc_arm, 0) },
|
||||||
{ DRDATA (TIME, lfc_unit.wait, 24), REG_NZ + PV_LEFT },
|
{ DRDATA (TIME, lfc_unit.wait, 24), REG_NZ + PV_LEFT },
|
||||||
{ DRDATA (TPS, lfc_tps, 8), REG_NZ + PV_LEFT },
|
{ DRDATA (TPS, lfc_tps, 8), PV_LEFT + REG_HRO },
|
||||||
{ HRDATA (DEVNO, lfc_dib.dno, 8), REG_HRO },
|
{ HRDATA (DEVNO, lfc_dib.dno, 8), REG_HRO },
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
MTAB lfc_mod[] = {
|
MTAB lfc_mod[] = {
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 100, NULL, "50HZ",
|
||||||
|
&lfc_set_freq, NULL, NULL },
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 120, NULL, "60HZ",
|
||||||
|
&lfc_set_freq, NULL, NULL },
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 0, "FREQUENCY", NULL,
|
||||||
|
NULL, &lfc_show_freq, NULL },
|
||||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||||
&set_dev, &show_dev, NULL },
|
&set_dev, &show_dev, NULL },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
@ -200,9 +215,9 @@ t_stat pic_svc (UNIT *uptr)
|
||||||
{
|
{
|
||||||
t_bool rate_chg = FALSE;
|
t_bool rate_chg = FALSE;
|
||||||
|
|
||||||
if (pic_cnti) pic_cic = -1; /* one shot? */
|
if (pic_cnti) pic_cic = 0; /* one shot? */
|
||||||
pic_cic = pic_cic - 1; /* decrement */
|
pic_cic = pic_cic - pic_decr; /* decrement */
|
||||||
if (pic_cic < 0) { /* overflow? */
|
if (pic_cic <= 0) { /* overflow? */
|
||||||
if (pic_wdp) pic_ovf = 1; /* broken wr? set flag */
|
if (pic_wdp) pic_ovf = 1; /* broken wr? set flag */
|
||||||
if (pic_arm) SET_INT (v_PIC); /* if armed, intr */
|
if (pic_arm) SET_INT (v_PIC); /* if armed, intr */
|
||||||
if (GET_RATE (pic_ric) != GET_RATE (pic_db)) /* rate change? */
|
if (GET_RATE (pic_ric) != GET_RATE (pic_db)) /* rate change? */
|
||||||
|
@ -216,23 +231,27 @@ return SCPE_OK;
|
||||||
|
|
||||||
/* Schedule next interval
|
/* Schedule next interval
|
||||||
|
|
||||||
If rate < 1ms, or diagnostic mode, count instructions
|
If eff rate < 1ms, or diagnostic mode, count instructions
|
||||||
If rate = 1ms, and not diagnostic mode, use timer
|
If eff rate = 1ms, and not diagnostic mode, use timer
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void pic_sched (t_bool strt)
|
void pic_sched (t_bool strt)
|
||||||
{
|
{
|
||||||
int32 r, t;
|
int32 r, t, intv, intv_usec;
|
||||||
|
|
||||||
pic_save = sim_grtime (); /* save start */
|
pic_save = sim_grtime (); /* save start */
|
||||||
r = pic_map[GET_RATE (pic_ric)]; /* get mapped rate */
|
r = pic_map[GET_RATE (pic_ric)]; /* get mapped rate */
|
||||||
t = pic_time[r]; /* get delay */
|
intv = pic_cic? pic_cic: 1; /* get cntr */
|
||||||
if ((r == 3) && !(pic_unit.flags & UNIT_DIAG)) { /* timer? */
|
intv_usec = intv * pic_usec[r]; /* cvt to usec */
|
||||||
|
if (!(pic_unit.flags & UNIT_DIAG) && /* not diag? */
|
||||||
|
((intv_usec % 1000) == 0)) { /* 1ms multiple? */
|
||||||
pic_cnti = 0; /* clr mode */
|
pic_cnti = 0; /* clr mode */
|
||||||
if (strt) t = sim_rtcn_init (t, TMR_PIC); /* init or */
|
pic_decr = pic_usec[3 - r]; /* set decrement */
|
||||||
|
if (strt) t = sim_rtcn_init (pic_time[3], TMR_PIC); /* init or */
|
||||||
else t = sim_rtcn_calb (PIC_TPS, TMR_PIC); } /* calibrate */
|
else t = sim_rtcn_calb (PIC_TPS, TMR_PIC); } /* calibrate */
|
||||||
else { pic_cnti = 1; /* set mode */
|
else { pic_cnti = 1; /* set mode */
|
||||||
t = t * (pic_cic + 1); /* interval */
|
pic_decr = 1; /* decr = 1 */
|
||||||
|
t = pic_time[r] * intv; /* interval */
|
||||||
if (t == 1) t++; } /* for diagn */
|
if (t == 1) t++; } /* for diagn */
|
||||||
sim_activate (&pic_unit, t); /* activate */
|
sim_activate (&pic_unit, t); /* activate */
|
||||||
return;
|
return;
|
||||||
|
@ -260,6 +279,7 @@ pic_ric = pic_cic = 0;
|
||||||
pic_db = 0;
|
pic_db = 0;
|
||||||
pic_ovf = 0; /* clear state */
|
pic_ovf = 0; /* clear state */
|
||||||
pic_cnti = 0;
|
pic_cnti = 0;
|
||||||
|
pic_decr = 1;
|
||||||
pic_rdp = pic_wdp = 0;
|
pic_rdp = pic_wdp = 0;
|
||||||
CLR_INT (v_PIC); /* clear int */
|
CLR_INT (v_PIC); /* clear int */
|
||||||
CLR_ENB (v_PIC); /* disable int */
|
CLR_ENB (v_PIC); /* disable int */
|
||||||
|
@ -309,3 +329,22 @@ CLR_ENB (v_LFC); /* disable int */
|
||||||
lfc_arm = 0; /* disarm int */
|
lfc_arm = 0; /* disarm int */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set frequency */
|
||||||
|
|
||||||
|
t_stat lfc_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
if (cptr) return SCPE_ARG;
|
||||||
|
if ((val != 100) && (val != 120)) return SCPE_IERR;
|
||||||
|
lfc_tps = val;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Show frequency */
|
||||||
|
|
||||||
|
t_stat lfc_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
|
{
|
||||||
|
fprintf (st, (lfc_tps == 100)? "50Hz": "60Hz");
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* nova_clk.c: NOVA real-time clock simulator
|
/* nova_clk.c: NOVA real-time clock simulator
|
||||||
|
|
||||||
Copyright (c) 1993-2002, Robert M. Supnik
|
Copyright (c) 1993-2003, Robert M. Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
clk real-time clock
|
clk real-time clock
|
||||||
|
|
||||||
|
01-Mar-03 RMS Added SET/SHOW CLK FREQ support
|
||||||
03-Oct-02 RMS Added DIB
|
03-Oct-02 RMS Added DIB
|
||||||
17-Sep-01 RMS Added terminal multiplexor support
|
17-Sep-01 RMS Added terminal multiplexor support
|
||||||
17-Mar-01 RMS Moved function prototype
|
17-Mar-01 RMS Moved function prototype
|
||||||
|
@ -45,6 +46,8 @@ int32 tmxr_poll = 16000; /* tmxr poll */
|
||||||
int32 clk (int32 pulse, int32 code, int32 AC);
|
int32 clk (int32 pulse, int32 code, int32 AC);
|
||||||
t_stat clk_svc (UNIT *uptr);
|
t_stat clk_svc (UNIT *uptr);
|
||||||
t_stat clk_reset (DEVICE *dptr);
|
t_stat clk_reset (DEVICE *dptr);
|
||||||
|
t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
|
|
||||||
/* CLK data structures
|
/* CLK data structures
|
||||||
|
|
||||||
|
@ -67,10 +70,20 @@ REG clk_reg[] = {
|
||||||
{ DRDATA (TIME1, clk_time[1], 24), REG_NZ + PV_LEFT },
|
{ DRDATA (TIME1, clk_time[1], 24), REG_NZ + PV_LEFT },
|
||||||
{ DRDATA (TIME2, clk_time[2], 24), REG_NZ + PV_LEFT },
|
{ DRDATA (TIME2, clk_time[2], 24), REG_NZ + PV_LEFT },
|
||||||
{ DRDATA (TIME3, clk_time[3], 24), REG_NZ + PV_LEFT },
|
{ DRDATA (TIME3, clk_time[3], 24), REG_NZ + PV_LEFT },
|
||||||
|
{ DRDATA (TPS0, clk_tps[0], 6), PV_LEFT + REG_HRO },
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
|
MTAB clk_mod[] = {
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 50, NULL, "50HZ",
|
||||||
|
&clk_set_freq, NULL, NULL },
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 60, NULL, "60HZ",
|
||||||
|
&clk_set_freq, NULL, NULL },
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 0, "LINE", NULL,
|
||||||
|
NULL, &clk_show_freq, NULL },
|
||||||
|
{ 0 } };
|
||||||
|
|
||||||
DEVICE clk_dev = {
|
DEVICE clk_dev = {
|
||||||
"CLK", &clk_unit, clk_reg, NULL,
|
"CLK", &clk_unit, clk_reg, clk_mod,
|
||||||
1, 0, 0, 0, 0, 0,
|
1, 0, 0, 0, 0, 0,
|
||||||
NULL, NULL, &clk_reset,
|
NULL, NULL, &clk_reset,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
|
@ -130,3 +143,21 @@ sim_cancel (&clk_unit); /* deactivate unit */
|
||||||
tmxr_poll = clk_time[0]; /* poll is default */
|
tmxr_poll = clk_time[0]; /* poll is default */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set line frequency */
|
||||||
|
|
||||||
|
t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
if (cptr) return SCPE_ARG;
|
||||||
|
if ((val != 50) && (val != 60)) return SCPE_IERR;
|
||||||
|
clk_tps[0] = val;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Show line frequency */
|
||||||
|
|
||||||
|
t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
|
{
|
||||||
|
fprintf (st, (clk_tps[0] == 50)? "50Hz": "60Hz");
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
To: Users
|
To: Users
|
||||||
From: Bob Supnik
|
From: Bob Supnik
|
||||||
Subj: Nova Simulator Usage
|
Subj: Nova Simulator Usage
|
||||||
Date: 1-Feb-2003
|
Date: 15-Mar-2003
|
||||||
|
|
||||||
COPYRIGHT NOTICE
|
COPYRIGHT NOTICE
|
||||||
|
|
||||||
|
@ -39,10 +39,12 @@ This memorandum documents the Nova simulator.
|
||||||
sim/ sim_defs.h
|
sim/ sim_defs.h
|
||||||
sim_rev.h
|
sim_rev.h
|
||||||
sim_sock.h
|
sim_sock.h
|
||||||
|
sim_tape.h
|
||||||
sim_tmxr.h
|
sim_tmxr.h
|
||||||
scp.c
|
scp.c
|
||||||
scp_tty.c
|
scp_tty.c
|
||||||
sim_sock.c
|
sim_sock.c
|
||||||
|
sim_tape.c
|
||||||
sim_tmxr.c
|
sim_tmxr.c
|
||||||
|
|
||||||
sim/nova/ nova_defs.h
|
sim/nova/ nova_defs.h
|
||||||
|
@ -282,7 +284,14 @@ Error handling is as follows:
|
||||||
|
|
||||||
2.2.6 Real-Time Clock (CLK)
|
2.2.6 Real-Time Clock (CLK)
|
||||||
|
|
||||||
The real-time clock (CLK) implements these registers:
|
The real-time clock (CLK) line frequency can be adjusted as follows:
|
||||||
|
|
||||||
|
SET CLK 60HZ set line frequency to 60Hz
|
||||||
|
SET CLK 50HZ set line frequency to 50Hz
|
||||||
|
|
||||||
|
The default is 60Hz.
|
||||||
|
|
||||||
|
The clock implements these registers:
|
||||||
|
|
||||||
name size comments
|
name size comments
|
||||||
|
|
||||||
|
@ -397,7 +406,7 @@ from the attached file:
|
||||||
SET RF 8P eight platters (2048K)
|
SET RF 8P eight platters (2048K)
|
||||||
SET RF AUTOSIZE autosized on attach
|
SET RF AUTOSIZE autosized on attach
|
||||||
|
|
||||||
The default is 8P (maximum size).
|
The default is 1P (minimum size).
|
||||||
|
|
||||||
The fixed head disk controller implements these registers:
|
The fixed head disk controller implements these registers:
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
dsk fixed head disk
|
dsk fixed head disk
|
||||||
|
|
||||||
|
03-Mar-03 RMS Fixed variable capacity and autosizing
|
||||||
03-Oct-02 RMS Added DIB
|
03-Oct-02 RMS Added DIB
|
||||||
06-Jan-02 RMS Revised enable/disable support
|
06-Jan-02 RMS Revised enable/disable support
|
||||||
23-Aug-01 RMS Fixed bug in write watermarking
|
23-Aug-01 RMS Fixed bug in write watermarking
|
||||||
|
@ -41,9 +42,11 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */
|
#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */
|
||||||
#define UNIT_V_MSIZE (UNIT_V_UF + 1) /* dummy mask */
|
#define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */
|
||||||
|
#define UNIT_M_PLAT 07
|
||||||
|
#define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1)
|
||||||
#define UNIT_AUTO (1 << UNIT_V_AUTO)
|
#define UNIT_AUTO (1 << UNIT_V_AUTO)
|
||||||
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
|
#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT)
|
||||||
|
|
||||||
/* Constants */
|
/* Constants */
|
||||||
|
|
||||||
|
@ -112,7 +115,7 @@ DIB dsk_dib = { DEV_DSK, INT_DSK, PI_DSK, &dsk };
|
||||||
|
|
||||||
UNIT dsk_unit =
|
UNIT dsk_unit =
|
||||||
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF,
|
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF,
|
||||||
DSK_NUMDK * DSK_DKSIZE) };
|
DSK_DKSIZE) };
|
||||||
|
|
||||||
REG dsk_reg[] = {
|
REG dsk_reg[] = {
|
||||||
{ ORDATA (STAT, dsk_stat, 16) },
|
{ ORDATA (STAT, dsk_stat, 16) },
|
||||||
|
@ -128,14 +131,14 @@ REG dsk_reg[] = {
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
MTAB dsk_mod[] = {
|
MTAB dsk_mod[] = {
|
||||||
{ UNIT_MSIZE, 262144, NULL, "1P", &dsk_set_size },
|
{ UNIT_PLAT, 0, NULL, "1P", &dsk_set_size },
|
||||||
{ UNIT_MSIZE, 524288, NULL, "2P", &dsk_set_size },
|
{ UNIT_PLAT, 1, NULL, "2P", &dsk_set_size },
|
||||||
{ UNIT_MSIZE, 786432, NULL, "3P", &dsk_set_size },
|
{ UNIT_PLAT, 2, NULL, "3P", &dsk_set_size },
|
||||||
{ UNIT_MSIZE, 1048576, NULL, "4P", &dsk_set_size },
|
{ UNIT_PLAT, 3, NULL, "4P", &dsk_set_size },
|
||||||
{ UNIT_MSIZE, 1310720, NULL, "5P", &dsk_set_size },
|
{ UNIT_PLAT, 4, NULL, "5P", &dsk_set_size },
|
||||||
{ UNIT_MSIZE, 1572864, NULL, "6P", &dsk_set_size },
|
{ UNIT_PLAT, 5, NULL, "6P", &dsk_set_size },
|
||||||
{ UNIT_MSIZE, 1835008, NULL, "7P", &dsk_set_size },
|
{ UNIT_PLAT, 6, NULL, "7P", &dsk_set_size },
|
||||||
{ UNIT_MSIZE, 2097152, NULL, "8P", &dsk_set_size },
|
{ UNIT_PLAT, 7, NULL, "8P", &dsk_set_size },
|
||||||
{ UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL },
|
{ UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
|
||||||
|
@ -268,19 +271,15 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat dsk_attach (UNIT *uptr, char *cptr)
|
t_stat dsk_attach (UNIT *uptr, char *cptr)
|
||||||
{
|
{
|
||||||
int32 p, d;
|
t_addr sz, p;
|
||||||
int32 ds_bytes = DSK_DKSIZE * sizeof (int16);
|
t_addr ds_bytes = DSK_DKSIZE * sizeof (int16);
|
||||||
|
|
||||||
if (uptr->flags & UNIT_AUTO) {
|
if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (cptr))) {
|
||||||
FILE *fp = fopen (cptr, "rb");
|
p = (sz + ds_bytes - 1) / ds_bytes;
|
||||||
if (fp == NULL) return SCPE_OPENERR;
|
if (p == 0) p = 1;
|
||||||
fseek (fp, 0, SEEK_END);
|
if (p > DSK_NUMDK) p = DSK_NUMDK; }
|
||||||
p = ftell (fp);
|
else p = UNIT_GETP (uptr->flags); /* get # plat */
|
||||||
d = (p + ds_bytes - 1) / ds_bytes;
|
uptr->capac = p * DSK_DKSIZE; /* set capacity */
|
||||||
if (d == 0) d = 1;
|
|
||||||
if (d > DSK_NUMDK) d = DSK_NUMDK;
|
|
||||||
uptr->capac = d * DSK_DKSIZE;
|
|
||||||
fclose (fp); }
|
|
||||||
return attach_unit (uptr, cptr);
|
return attach_unit (uptr, cptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,10 +287,9 @@ return attach_unit (uptr, cptr);
|
||||||
|
|
||||||
t_stat dsk_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
t_stat dsk_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
{
|
{
|
||||||
if ((val == 0) || (val > (DSK_NUMDK * DSK_DKSIZE)))
|
if ((val < 0) || (val >= DSK_NUMDK)) return SCPE_IERR;
|
||||||
return SCPE_IERR;
|
|
||||||
if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
|
if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
|
||||||
uptr->capac = val;
|
uptr->capac = (val + 1) * DSK_DKSIZE;
|
||||||
uptr->flags = uptr->flags & ~UNIT_AUTO;
|
uptr->flags = uptr->flags & ~UNIT_AUTO;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
216
NOVA/nova_mta.c
216
NOVA/nova_mta.c
|
@ -1,6 +1,6 @@
|
||||||
/* nova_mta.c: NOVA magnetic tape simulator
|
/* nova_mta.c: NOVA magnetic tape simulator
|
||||||
|
|
||||||
Copyright (c) 1993-2002, Robert M. Supnik
|
Copyright (c) 1993-2003, Robert M. Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
mta magnetic tape
|
mta magnetic tape
|
||||||
|
|
||||||
|
28-Feb-03 RMS Revised for magtape library
|
||||||
30-Oct-02 RMS Fixed BOT handling, added error record handling
|
30-Oct-02 RMS Fixed BOT handling, added error record handling
|
||||||
08-Oct-02 RMS Added DIB
|
08-Oct-02 RMS Added DIB
|
||||||
30-Sep-02 RMS Revamped error handling
|
30-Sep-02 RMS Revamped error handling
|
||||||
|
@ -60,17 +61,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "nova_defs.h"
|
#include "nova_defs.h"
|
||||||
|
#include "sim_tape.h"
|
||||||
|
|
||||||
#define MTA_NUMDR 8 /* #drives */
|
#define MTA_NUMDR 8 /* #drives */
|
||||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
|
||||||
#define UNIT_V_PNU (UNIT_V_UF + 1) /* pos not updated */
|
|
||||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
|
||||||
#define UNIT_PNU (1 << UNIT_V_PNU)
|
|
||||||
#define USTAT u3 /* unit status */
|
#define USTAT u3 /* unit status */
|
||||||
#define MTA_MAXFR (1 << 16) /* max record lnt */
|
#define MTA_MAXFR (1 << 16) /* max record lnt */
|
||||||
#define DTSIZE (1 << 14) /* max data xfer */
|
#define WC_SIZE (1 << 14) /* max word count */
|
||||||
#define DTMASK (DTSIZE - 1)
|
#define WC_MASK (WC_SIZE - 1)
|
||||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
|
||||||
|
|
||||||
/* Command/unit */
|
/* Command/unit */
|
||||||
|
|
||||||
|
@ -154,6 +151,7 @@ int32 mta_sta = 0; /* status register */
|
||||||
int32 mta_ep = 0; /* enable polling */
|
int32 mta_ep = 0; /* enable polling */
|
||||||
int32 mta_cwait = 100; /* command latency */
|
int32 mta_cwait = 100; /* command latency */
|
||||||
int32 mta_rwait = 100; /* record latency */
|
int32 mta_rwait = 100; /* record latency */
|
||||||
|
uint8 *mtxb = NULL; /* transfer buffer */
|
||||||
|
|
||||||
DEVICE mta_dev;
|
DEVICE mta_dev;
|
||||||
int32 mta (int32 pulse, int32 code, int32 AC);
|
int32 mta (int32 pulse, int32 code, int32 AC);
|
||||||
|
@ -164,9 +162,8 @@ t_stat mta_attach (UNIT *uptr, char *cptr);
|
||||||
t_stat mta_detach (UNIT *uptr);
|
t_stat mta_detach (UNIT *uptr);
|
||||||
int32 mta_updcsta (UNIT *uptr);
|
int32 mta_updcsta (UNIT *uptr);
|
||||||
void mta_upddsta (UNIT *uptr, int32 newsta);
|
void mta_upddsta (UNIT *uptr, int32 newsta);
|
||||||
|
t_stat mta_map_err (UNIT *uptr, t_stat st);
|
||||||
t_stat mta_vlock (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat mta_vlock (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
t_bool mta_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
|
||||||
t_bool mta_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
|
||||||
|
|
||||||
static const int ctype[32] = { /* c vs r timing */
|
static const int ctype[32] = { /* c vs r timing */
|
||||||
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
|
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
|
||||||
|
@ -211,8 +208,8 @@ REG mta_reg[] = {
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
MTAB mta_mod[] = {
|
MTAB mta_mod[] = {
|
||||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", &mta_vlock },
|
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", &mta_vlock },
|
||||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", &mta_vlock },
|
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", &mta_vlock },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
|
||||||
DEVICE mta_dev = {
|
DEVICE mta_dev = {
|
||||||
|
@ -305,40 +302,31 @@ return rval;
|
||||||
|
|
||||||
t_stat mta_svc (UNIT *uptr)
|
t_stat mta_svc (UNIT *uptr)
|
||||||
{
|
{
|
||||||
int32 c, p, pa, err, pnu, u;
|
int32 c, p, pa, u;
|
||||||
t_mtrlnt i, cbc, tbc, wc;
|
t_mtrlnt i, cbc, tbc, wc;
|
||||||
uint16 c1, c2;
|
uint16 c1, c2;
|
||||||
static uint8 dbuf[2 * DTSIZE];
|
t_stat st, r = SCPE_OK;
|
||||||
static t_mtrlnt bceof = { MTR_TMK };
|
|
||||||
|
|
||||||
err = 0;
|
|
||||||
u = uptr - mta_dev.units; /* get unit number */
|
u = uptr - mta_dev.units; /* get unit number */
|
||||||
pnu = MT_TST_PNU (uptr); /* get pos not upd */
|
c = GET_CMD (mta_cu); /* command */
|
||||||
MT_CLR_PNU (uptr); /* and clear */
|
wc = WC_SIZE - (mta_wc & WC_MASK); /* io wc */
|
||||||
|
|
||||||
if (uptr->USTAT & STA_REW) { /* rewind? */
|
if (uptr->USTAT & STA_REW) { /* rewind? */
|
||||||
uptr->pos = 0; /* update position */
|
sim_tape_rewind (uptr); /* update tape */
|
||||||
mta_upddsta (uptr, (uptr->USTAT & ~STA_REW) | STA_BOT | STA_RDY);
|
mta_upddsta (uptr, (uptr->USTAT & ~STA_REW) | STA_BOT | STA_RDY);
|
||||||
if (u == GET_UNIT (mta_cu)) mta_updcsta (uptr);
|
if (u == GET_UNIT (mta_cu)) mta_updcsta (uptr);
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
|
|
||||||
c = GET_CMD (mta_cu); /* command */
|
|
||||||
wc = DTSIZE - (mta_wc & DTMASK); /* io wc */
|
|
||||||
|
|
||||||
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
|
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
|
||||||
mta_upddsta (uptr, 0); /* unit off line */
|
mta_upddsta (uptr, 0); /* unit off line */
|
||||||
mta_sta = mta_sta | STA_ILL; } /* illegal operation */
|
mta_sta = mta_sta | STA_ILL; } /* illegal operation */
|
||||||
|
|
||||||
else if ((uptr->flags & UNIT_WPRT) && /* write locked? */
|
|
||||||
((c == CU_WRITE) || (c == CU_WREOF) || (c == CU_ERASE))) {
|
|
||||||
mta_upddsta (uptr, uptr->USTAT | STA_WLK | STA_RDY);
|
|
||||||
mta_sta = mta_sta | STA_ILL; } /* illegal operation */
|
|
||||||
|
|
||||||
else switch (c) { /* case on command */
|
else switch (c) { /* case on command */
|
||||||
|
|
||||||
case CU_CMODE: /* controller mode */
|
case CU_CMODE: /* controller mode */
|
||||||
mta_ep = mta_cu & CU_EP;
|
mta_ep = mta_cu & CU_EP;
|
||||||
break;
|
break;
|
||||||
case CU_DMODE: /* drive mode */
|
case CU_DMODE: /* drive mode */
|
||||||
if (uptr->pos) mta_sta = mta_sta | STA_ILL; /* must be BOT */
|
if (!sim_tape_bot (uptr)) mta_sta = mta_sta | STA_ILL; /* must be BOT */
|
||||||
else mta_upddsta (uptr, (mta_cu & CU_PE)? /* update drv status */
|
else mta_upddsta (uptr, (mta_cu & CU_PE)? /* update drv status */
|
||||||
uptr->USTAT | STA_PEM: uptr->USTAT & ~ STA_PEM);
|
uptr->USTAT | STA_PEM: uptr->USTAT & ~ STA_PEM);
|
||||||
break;
|
break;
|
||||||
|
@ -347,69 +335,62 @@ case CU_DMODE: /* drive mode */
|
||||||
|
|
||||||
case CU_READ: /* read */
|
case CU_READ: /* read */
|
||||||
case CU_READNS: /* read non-stop */
|
case CU_READNS: /* read non-stop */
|
||||||
if (mta_rdlntf (uptr, &tbc, & err)) break; /* read rec lnt, err? */
|
st = sim_tape_rdrecf (uptr, mtxb, &tbc, MTA_MAXFR); /* read rec */
|
||||||
if (tbc > MTA_MAXFR) return SCPE_MTRLNT; /* record too long? */
|
if (st == MTSE_RECE) mta_sta = mta_sta | STA_DAE; /* rec in err? */
|
||||||
|
else if (st != MTSE_OK) { /* other error? */
|
||||||
|
r = mta_map_err (uptr, st); /* map error */
|
||||||
|
break; }
|
||||||
cbc = wc * 2; /* expected bc */
|
cbc = wc * 2; /* expected bc */
|
||||||
if (tbc & 1) mta_sta = mta_sta | STA_ODD; /* odd byte count? */
|
if (tbc & 1) mta_sta = mta_sta | STA_ODD; /* odd byte count? */
|
||||||
if (tbc > cbc) mta_sta = mta_sta | STA_WCO; /* too big? */
|
if (tbc > cbc) mta_sta = mta_sta | STA_WCO; /* too big? */
|
||||||
else {
|
else {
|
||||||
cbc = tbc; /* no, use it */
|
cbc = tbc; /* no, use it */
|
||||||
wc = (cbc + 1) / 2; } /* adjust wc */
|
wc = (cbc + 1) / 2; } /* adjust wc */
|
||||||
i = fxread (dbuf, sizeof (int8), cbc, uptr->fileref);
|
|
||||||
for ( ; i < cbc; i++) dbuf[i] = 0;
|
|
||||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY);
|
|
||||||
if (err = ferror (uptr->fileref)) { /* error? */
|
|
||||||
MT_SET_PNU (uptr); /* pos not upd */
|
|
||||||
break; }
|
|
||||||
for (i = p = 0; i < wc; i++) { /* copy buf to mem */
|
for (i = p = 0; i < wc; i++) { /* copy buf to mem */
|
||||||
c1 = dbuf[p++];
|
c1 = mtxb[p++];
|
||||||
c2 = dbuf[p++];
|
c2 = mtxb[p++];
|
||||||
pa = MapAddr (0, mta_ma); /* map address */
|
pa = MapAddr (0, mta_ma); /* map address */
|
||||||
if (MEM_ADDR_OK (pa)) M[pa] = (c1 << 8) | c2;
|
if (MEM_ADDR_OK (pa)) M[pa] = (c1 << 8) | c2;
|
||||||
mta_ma = (mta_ma + 1) & AMASK; }
|
mta_ma = (mta_ma + 1) & AMASK; }
|
||||||
mta_wc = (mta_wc + wc) & DMASK;
|
mta_wc = (mta_wc + wc) & DMASK;
|
||||||
uptr->pos = uptr->pos + ((tbc + 1) & ~1) +
|
mta_upddsta (uptr, uptr->USTAT | STA_RDY);
|
||||||
(2 * sizeof (t_mtrlnt));
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CU_WRITE: /* write */
|
case CU_WRITE: /* write */
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
|
||||||
tbc = wc * 2; /* io byte count */
|
tbc = wc * 2; /* io byte count */
|
||||||
fxwrite (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
|
||||||
for (i = p = 0; i < wc; i++) { /* copy to buffer */
|
for (i = p = 0; i < wc; i++) { /* copy to buffer */
|
||||||
pa = MapAddr (0, mta_ma); /* map address */
|
pa = MapAddr (0, mta_ma); /* map address */
|
||||||
dbuf[p++] = (M[pa] >> 8) & 0377;
|
mtxb[p++] = (M[pa] >> 8) & 0377;
|
||||||
dbuf[p++] = M[pa] & 0377;
|
mtxb[p++] = M[pa] & 0377;
|
||||||
mta_ma = (mta_ma + 1) & AMASK; }
|
mta_ma = (mta_ma + 1) & AMASK; }
|
||||||
fxwrite (dbuf, sizeof (int8), tbc, uptr->fileref);
|
if (st = sim_tape_wrrecf (uptr, mtxb, tbc)) { /* write rec, err? */
|
||||||
fxwrite (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
r = mta_map_err (uptr, st); /* map error */
|
||||||
|
mta_ma = (mta_ma - wc) & AMASK; } /* restore wc */
|
||||||
|
else mta_wc = 0; /* clear wc */
|
||||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY);
|
mta_upddsta (uptr, uptr->USTAT | STA_RDY);
|
||||||
if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr); /* error? */
|
|
||||||
else {
|
|
||||||
mta_wc = 0;
|
|
||||||
uptr->pos = uptr->pos + tbc + (2 * sizeof (t_mtrlnt)); }
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Unit service, continued */
|
/* Unit service, continued */
|
||||||
|
|
||||||
case CU_WREOF: /* write eof */
|
case CU_WREOF: /* write eof */
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
|
||||||
fxwrite (&bceof, sizeof (t_mtrlnt), 1, uptr->fileref);
|
r = mta_map_err (uptr, st); /* map error */
|
||||||
mta_upddsta (uptr, uptr->USTAT | STA_EOF | STA_RDY);
|
else mta_upddsta (uptr, uptr->USTAT | STA_EOF | STA_RDY);
|
||||||
if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr); /* error? */
|
|
||||||
else uptr->pos = uptr->pos + sizeof (t_mtrlnt);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CU_ERASE: /* erase */
|
case CU_ERASE: /* erase */
|
||||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY);
|
if (sim_tape_wrp (uptr)) /* write protected? */
|
||||||
|
r = mta_map_err (uptr, MTSE_WRP); /* map error */
|
||||||
|
else mta_upddsta (uptr, uptr->USTAT | STA_RDY);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CU_SPACEF: /* space forward */
|
case CU_SPACEF: /* space forward */
|
||||||
do {
|
do {
|
||||||
mta_wc = (mta_wc + 1) & DMASK; /* incr wc */
|
mta_wc = (mta_wc + 1) & DMASK; /* incr wc */
|
||||||
if (mta_rdlntf (uptr, &tbc, &err)) break; /* read rec lnt, err? */
|
if (st = sim_tape_sprecf (uptr, &tbc)) { /* space rec fwd, err? */
|
||||||
uptr->pos = uptr->pos + ((tbc + 1) & ~1) +
|
r = mta_map_err (uptr, st); /* map error */
|
||||||
(2 * sizeof (t_mtrlnt)); }
|
break; }
|
||||||
|
}
|
||||||
while (mta_wc != 0);
|
while (mta_wc != 0);
|
||||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY);
|
mta_upddsta (uptr, uptr->USTAT | STA_RDY);
|
||||||
break;
|
break;
|
||||||
|
@ -417,29 +398,24 @@ case CU_SPACEF: /* space forward */
|
||||||
case CU_SPACER: /* space reverse */
|
case CU_SPACER: /* space reverse */
|
||||||
do {
|
do {
|
||||||
mta_wc = (mta_wc + 1) & DMASK; /* incr wc */
|
mta_wc = (mta_wc + 1) & DMASK; /* incr wc */
|
||||||
if (pnu) pnu = 0; /* pos not upd? */
|
if (st = sim_tape_sprecr (uptr, &tbc)) { /* space rec rev, err? */
|
||||||
else {
|
r = mta_map_err (uptr, st); /* map error */
|
||||||
if (mta_rdlntr (uptr, &tbc, &err)) break;
|
break; }
|
||||||
uptr->pos = uptr->pos - ((tbc + 1) & ~1) -
|
}
|
||||||
(2 * sizeof (t_mtrlnt)); } }
|
|
||||||
while (mta_wc != 0);
|
while (mta_wc != 0);
|
||||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY);
|
mta_upddsta (uptr, uptr->USTAT | STA_RDY);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: /* reserved */
|
default: /* reserved */
|
||||||
mta_sta = mta_sta | STA_ILL;
|
mta_sta = mta_sta | STA_ILL;
|
||||||
|
mta_upddsta (uptr, uptr->USTAT | STA_RDY);
|
||||||
break; } /* end case */
|
break; } /* end case */
|
||||||
|
|
||||||
if (err != 0) mta_sta = mta_sta | STA_DAE; /* I/O error */
|
|
||||||
mta_updcsta (uptr); /* update status */
|
mta_updcsta (uptr); /* update status */
|
||||||
dev_busy = dev_busy & ~INT_MTA; /* clear busy */
|
dev_busy = dev_busy & ~INT_MTA; /* clear busy */
|
||||||
dev_done = dev_done | INT_MTA; /* set done */
|
dev_done = dev_done | INT_MTA; /* set done */
|
||||||
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
|
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
|
||||||
if (err != 0) {
|
return r;
|
||||||
perror ("MTA I/O error");
|
|
||||||
clearerr (uptr->fileref);
|
|
||||||
return SCPE_IOERR; }
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update controller status */
|
/* Update controller status */
|
||||||
|
@ -471,60 +447,44 @@ if (change) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read record length forward - return T if error, EOM, or EOF */
|
/* Map tape error status */
|
||||||
|
|
||||||
t_bool mta_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
t_stat mta_map_err (UNIT *uptr, t_stat st)
|
||||||
{
|
{
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set tape pos */
|
switch (st) {
|
||||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref); /* read rec lnt */
|
case MTSE_FMT: /* illegal fmt */
|
||||||
if (*err = ferror (uptr->fileref)) { /* error? */
|
mta_upddsta (uptr, uptr->USTAT | STA_WLK | STA_RDY);
|
||||||
|
case MTSE_UNATT: /* unattached */
|
||||||
|
mta_sta = mta_sta | STA_ILL;
|
||||||
|
case MTSE_OK: /* no error */
|
||||||
|
return SCPE_IERR; /* never get here! */
|
||||||
|
case MTSE_TMK: /* end of file */
|
||||||
|
mta_upddsta (uptr, uptr->USTAT | STA_RDY | STA_EOF);
|
||||||
|
break;
|
||||||
|
case MTSE_IOERR: /* IO error */
|
||||||
mta_sta = mta_sta | STA_DAE; /* data error */
|
mta_sta = mta_sta | STA_DAE; /* data error */
|
||||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY); /* ready */
|
mta_upddsta (uptr, uptr->USTAT | STA_RDY); /* ready */
|
||||||
MT_SET_PNU (uptr); /* pos not upd */
|
return SCPE_IOERR;
|
||||||
return TRUE; }
|
case MTSE_INVRL: /* invalid rec lnt */
|
||||||
if (feof (uptr->fileref) || (*tbc == MTR_EOM)) { /* eof or eom? */
|
mta_sta = mta_sta | STA_DAE; /* data error */
|
||||||
|
mta_upddsta (uptr, uptr->USTAT | STA_RDY); /* ready */
|
||||||
|
return SCPE_MTRLNT;
|
||||||
|
case MTSE_RECE: /* record in error */
|
||||||
|
mta_sta = mta_sta | STA_DAE; /* data error */
|
||||||
|
mta_upddsta (uptr, uptr->USTAT | STA_RDY); /* ready */
|
||||||
|
break;
|
||||||
|
case MTSE_EOM: /* end of medium */
|
||||||
mta_sta = mta_sta | STA_BAT; /* bad tape */
|
mta_sta = mta_sta | STA_BAT; /* bad tape */
|
||||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY); /* ready */
|
mta_upddsta (uptr, uptr->USTAT | STA_RDY); /* ready */
|
||||||
MT_SET_PNU (uptr); /* pos not upd */
|
break;
|
||||||
return TRUE; }
|
case MTSE_BOT: /* reverse into BOT */
|
||||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
|
||||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY | STA_EOF);
|
|
||||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* spc over tmk */
|
|
||||||
return TRUE; }
|
|
||||||
if (MTRF (*tbc)) mta_sta = mta_sta | STA_DAE; /* record in error? */
|
|
||||||
*tbc = MTRL (*tbc); /* clear error flag */
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read record length reverse - return T if error, EOM, or EOF */
|
|
||||||
|
|
||||||
t_bool mta_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
|
||||||
{
|
|
||||||
if (uptr->pos < sizeof (t_mtrlnt)) { /* at BOT? */
|
|
||||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY | STA_BOT);
|
mta_upddsta (uptr, uptr->USTAT | STA_RDY | STA_BOT);
|
||||||
return TRUE; }
|
break;
|
||||||
fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET);
|
case MTSE_WRP: /* write protect */
|
||||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
mta_upddsta (uptr, uptr->USTAT | STA_WLK | STA_RDY);
|
||||||
if (*err = ferror (uptr->fileref)) { /* error? */
|
mta_sta = mta_sta | STA_ILL; /* illegal operation */
|
||||||
mta_sta = mta_sta | STA_DAE; /* data error */
|
break; }
|
||||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY); /* ready */
|
return SCPE_OK;
|
||||||
return TRUE; }
|
|
||||||
if (feof (uptr->fileref)) { /* eof? */
|
|
||||||
mta_sta = mta_sta | STA_BAT; /* bad tape */
|
|
||||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY); /* ready */
|
|
||||||
return TRUE; }
|
|
||||||
if (*tbc == MTR_EOM) { /* eom? */
|
|
||||||
mta_sta = mta_sta | STA_BAT; /* bad tape */
|
|
||||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY); /* ready */
|
|
||||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over eom */
|
|
||||||
return TRUE; }
|
|
||||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
|
||||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY | STA_EOF);
|
|
||||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over tmk */
|
|
||||||
return TRUE; }
|
|
||||||
if (MTRF (*tbc)) mta_sta = mta_sta | STA_DAE; /* record in error? */
|
|
||||||
*tbc = MTRL (*tbc); /* clear error flag */
|
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset routine */
|
/* Reset routine */
|
||||||
|
@ -541,14 +501,16 @@ mta_cu = mta_wc = mta_ma = mta_sta = 0; /* clear registers */
|
||||||
mta_ep = 0;
|
mta_ep = 0;
|
||||||
for (u = 0; u < MTA_NUMDR; u++) { /* loop thru units */
|
for (u = 0; u < MTA_NUMDR; u++) { /* loop thru units */
|
||||||
uptr = mta_dev.units + u;
|
uptr = mta_dev.units + u;
|
||||||
MT_CLR_PNU (uptr); /* clear pos flag */
|
sim_tape_reset (uptr); /* clear pos flag */
|
||||||
sim_cancel (uptr); /* cancel activity */
|
sim_cancel (uptr); /* cancel activity */
|
||||||
if (uptr->flags & UNIT_ATT) uptr->USTAT = STA_RDY |
|
if (uptr->flags & UNIT_ATT) uptr->USTAT = STA_RDY |
|
||||||
(uptr->USTAT & STA_PEM) |
|
(uptr->USTAT & STA_PEM) |
|
||||||
((uptr->flags & UNIT_WPRT)? STA_WLK: 0) |
|
(sim_tape_wrp (uptr)? STA_WLK: 0) |
|
||||||
((uptr->pos)? 0: STA_BOT);
|
(sim_tape_bot (uptr)? STA_BOT: 0);
|
||||||
else uptr->USTAT = 0; }
|
else uptr->USTAT = 0; }
|
||||||
mta_updcsta (&mta_unit[0]); /* update status */
|
mta_updcsta (&mta_unit[0]); /* update status */
|
||||||
|
if (mtxb == NULL) mtxb = calloc (MTA_MAXFR, sizeof (uint8));
|
||||||
|
if (mtxb == NULL) return SCPE_MEM;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -558,11 +520,10 @@ t_stat mta_attach (UNIT *uptr, char *cptr)
|
||||||
{
|
{
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
r = attach_unit (uptr, cptr);
|
r = sim_tape_attach (uptr, cptr);
|
||||||
if (r != SCPE_OK) return r;
|
if (r != SCPE_OK) return r;
|
||||||
MT_CLR_PNU (uptr);
|
|
||||||
if (!sim_is_active (uptr)) mta_upddsta (uptr, STA_RDY | STA_BOT | STA_PEM |
|
if (!sim_is_active (uptr)) mta_upddsta (uptr, STA_RDY | STA_BOT | STA_PEM |
|
||||||
((uptr->flags & UNIT_WPRT)? STA_WLK: 0));
|
(sim_tape_wrp (uptr)? STA_WLK: 0));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -570,16 +531,15 @@ return r;
|
||||||
|
|
||||||
t_stat mta_detach (UNIT* uptr)
|
t_stat mta_detach (UNIT* uptr)
|
||||||
{
|
{
|
||||||
MT_CLR_PNU (uptr);
|
|
||||||
if (!sim_is_active (uptr)) mta_upddsta (uptr, 0);
|
if (!sim_is_active (uptr)) mta_upddsta (uptr, 0);
|
||||||
return detach_unit (uptr);
|
return sim_tape_detach (uptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write lock/unlock validate routine */
|
/* Write lock/unlock validate routine */
|
||||||
|
|
||||||
t_stat mta_vlock (UNIT *uptr, int32 val, char *cptr, void *desc)
|
t_stat mta_vlock (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
{
|
{
|
||||||
if ((uptr->flags & UNIT_ATT) && val)
|
if ((uptr->flags & UNIT_ATT) && (val || sim_tape_wrp (uptr)))
|
||||||
mta_upddsta (uptr, uptr->USTAT | STA_WLK);
|
mta_upddsta (uptr, uptr->USTAT | STA_WLK);
|
||||||
else mta_upddsta (uptr, uptr->USTAT & ~STA_WLK);
|
else mta_upddsta (uptr, uptr->USTAT & ~STA_WLK);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -617,7 +577,7 @@ t_stat mta_boot (int32 unitno, DEVICE *dptr)
|
||||||
int32 i;
|
int32 i;
|
||||||
extern int32 saved_PC;
|
extern int32 saved_PC;
|
||||||
|
|
||||||
mta_unit[unitno].pos = 0;
|
sim_tape_rewind (&mta_unit[unitno]);
|
||||||
for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i];
|
for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i];
|
||||||
M[BOOT_UNIT] = (unitno & CU_M_UNIT) << CU_V_UNIT;
|
M[BOOT_UNIT] = (unitno & CU_M_UNIT) << CU_V_UNIT;
|
||||||
saved_PC = BOOT_START;
|
saved_PC = BOOT_START;
|
||||||
|
|
25
PDP10/pdp10_diag.txt
Normal file
25
PDP10/pdp10_diag.txt
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
Bugs Found
|
||||||
|
----------
|
||||||
|
|
||||||
|
1. pushj cleared T2 after setting it
|
||||||
|
2. if timer autoadjust is enabled, timer diagnostic may fail,
|
||||||
|
depending on host CPU speed
|
||||||
|
3. DFAD/DFSB should use FP_ONES instead of ONES
|
||||||
|
4. TLB physical address max = 1MW, tested in diagnostic
|
||||||
|
5. DPB does read/write, not read-modify/write
|
||||||
|
6. Fetch error takes priority over traps, due to prefetching
|
||||||
|
of next instruction
|
||||||
|
7. HSB is 36b, was 32b
|
||||||
|
8. CPU and PAG devices had mismatched types
|
||||||
|
9. non-zero sections in Tops-20 paging section indirect may
|
||||||
|
cause non-existent memory error, due to microcode "error"
|
||||||
|
10. PXCT test for user mode was backward
|
||||||
|
11. Timer interrupts were not implemented in Tops-20 indirect
|
||||||
|
chains
|
||||||
|
12. epta/upta hit known bug in VC++ implementation of 64b
|
||||||
|
data types
|
||||||
|
13. final W calculation in Tops-20 paging was incorrect
|
||||||
|
14. Timer representation lost sub msec values
|
||||||
|
15. UBA initialization reset the UBA itself
|
||||||
|
16. RHCS1: writing IE cannot trigger an interrupt
|
||||||
|
17. Tape bootstrap was set to 800bpi instead of 1600bpi
|
|
@ -297,7 +297,6 @@ t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
|
||||||
d10 data;
|
d10 data;
|
||||||
int32 wc, fmt;
|
int32 wc, fmt;
|
||||||
extern int32 sim_switches;
|
extern int32 sim_switches;
|
||||||
extern t_bool match_ext (char *fnam, char *ext);
|
|
||||||
|
|
||||||
fmt = 0; /* no fmt */
|
fmt = 0; /* no fmt */
|
||||||
if (sim_switches & SWMASK ('R')) fmt = FMT_R; /* -r? */
|
if (sim_switches & SWMASK ('R')) fmt = FMT_R; /* -r? */
|
||||||
|
|
198
PDP10/pdp10_tu.c
198
PDP10/pdp10_tu.c
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
tu RH11/TM03/TU45 magtape
|
tu RH11/TM03/TU45 magtape
|
||||||
|
|
||||||
|
28-Feb-03 RMS Revised for magtape library
|
||||||
27-Jan-03 RMS Changed to dynamically allocate buffer
|
27-Jan-03 RMS Changed to dynamically allocate buffer
|
||||||
21-Nov-02 RMS Fixed bug in bootstrap (reported by Michael Thompson)
|
21-Nov-02 RMS Fixed bug in bootstrap (reported by Michael Thompson)
|
||||||
Fixed bug in read (reported by Harris Newman)
|
Fixed bug in read (reported by Harris Newman)
|
||||||
|
@ -75,18 +76,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pdp10_defs.h"
|
#include "pdp10_defs.h"
|
||||||
|
#include "sim_tape.h"
|
||||||
|
|
||||||
#define TU_NUMFM 1 /* #formatters */
|
#define TU_NUMFM 1 /* #formatters */
|
||||||
#define TU_NUMDR 8 /* #drives */
|
#define TU_NUMDR 8 /* #drives */
|
||||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
|
||||||
#define UNIT_V_PNU (UNIT_V_UF + 1) /* pos not updated */
|
|
||||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
|
||||||
#define UNIT_PNU (1 << UNIT_V_PNU)
|
|
||||||
#define USTAT u3 /* unit status */
|
#define USTAT u3 /* unit status */
|
||||||
#define UDENS u4 /* unit density */
|
#define UDENS u4 /* unit density */
|
||||||
#define UD_UNK 0 /* unknown */
|
#define UD_UNK 0 /* unknown */
|
||||||
#define XBUFLNT (1 << 16) /* max data buf */
|
#define MT_MAXFR (1 << 16) /* max data buf */
|
||||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
|
||||||
|
|
||||||
/* MTCS1 - 172440 - control/status 1 */
|
/* MTCS1 - 172440 - control/status 1 */
|
||||||
|
|
||||||
|
@ -319,9 +316,7 @@ t_stat tu_detach (UNIT *uptr);
|
||||||
t_stat tu_boot (int32 unitno, DEVICE *dptr);
|
t_stat tu_boot (int32 unitno, DEVICE *dptr);
|
||||||
void tu_go (int32 drv);
|
void tu_go (int32 drv);
|
||||||
void update_tucs (int32 flag, int32 drv);
|
void update_tucs (int32 flag, int32 drv);
|
||||||
t_stat tu_vlock (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat tu_map_err (UNIT *uptr, t_stat st);
|
||||||
t_bool tu_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
|
||||||
t_bool tu_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
|
||||||
|
|
||||||
/* TU data structures
|
/* TU data structures
|
||||||
|
|
||||||
|
@ -369,8 +364,8 @@ REG tu_reg[] = {
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
MTAB tu_mod[] = {
|
MTAB tu_mod[] = {
|
||||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", &tu_vlock },
|
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", &tu_vlock },
|
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
|
||||||
{ MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL,
|
{ MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL,
|
||||||
NULL, &show_addr, NULL },
|
NULL, &show_addr, NULL },
|
||||||
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL,
|
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL,
|
||||||
|
@ -583,7 +578,7 @@ case FNC_NOP:
|
||||||
return;
|
return;
|
||||||
case FNC_RIP: /* read-in preset */
|
case FNC_RIP: /* read-in preset */
|
||||||
tutc = TC_800; /* density = 800 */
|
tutc = TC_800; /* density = 800 */
|
||||||
tu_unit[0].pos = 0; /* rewind unit 0 */
|
sim_tape_rewind (&tu_unit[0]); /* rewind unit 0 */
|
||||||
tu_unit[0].USTAT = 0;
|
tu_unit[0].USTAT = 0;
|
||||||
tucs1 = tucs1 & ~CS1_GO;
|
tucs1 = tucs1 & ~CS1_GO;
|
||||||
return;
|
return;
|
||||||
|
@ -632,7 +627,7 @@ case FNC_WRITE: /* write */
|
||||||
break; }
|
break; }
|
||||||
case FNC_WREOF: /* write tape mark */
|
case FNC_WREOF: /* write tape mark */
|
||||||
case FNC_ERASE: /* erase */
|
case FNC_ERASE: /* erase */
|
||||||
if (uptr->flags & UNIT_WPRT) { /* write locked? */
|
if (sim_tape_wrp (uptr)) { /* write locked? */
|
||||||
tuer = tuer | ER_NXF;
|
tuer = tuer | ER_NXF;
|
||||||
break; }
|
break; }
|
||||||
case FNC_WCHKF: /* wchk = read */
|
case FNC_WCHKF: /* wchk = read */
|
||||||
|
@ -674,22 +669,19 @@ return;
|
||||||
Complete movement or data transfer command
|
Complete movement or data transfer command
|
||||||
Unit must exist - can't remove an active unit
|
Unit must exist - can't remove an active unit
|
||||||
Unit must be attached - detach cancels in progress operations
|
Unit must be attached - detach cancels in progress operations
|
||||||
Unit must be writeable - can't write protect an active unit
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
t_stat tu_svc (UNIT *uptr)
|
t_stat tu_svc (UNIT *uptr)
|
||||||
{
|
{
|
||||||
int32 f, fmt, i, j, k, err, wc10, ba10, pnu;
|
int32 f, fmt, i, j, k, wc10, ba10;
|
||||||
int32 ba, fc, wc, drv, mpa10, vpn;
|
int32 ba, fc, wc, drv, mpa10, vpn;
|
||||||
d10 val, v[4];
|
d10 val, v[4];
|
||||||
t_mtrlnt abc, tbc;
|
t_mtrlnt tbc;
|
||||||
static t_mtrlnt bceof = { MTR_TMK };
|
t_stat st, r = SCPE_OK;
|
||||||
|
|
||||||
drv = uptr - tu_dev.units; /* get drive # */
|
drv = uptr - tu_dev.units; /* get drive # */
|
||||||
pnu = MT_TST_PNU (uptr); /* get pos not upd */
|
|
||||||
MT_CLR_PNU (uptr); /* and clear */
|
|
||||||
if (uptr->USTAT & FS_REW) { /* rewind or unload? */
|
if (uptr->USTAT & FS_REW) { /* rewind or unload? */
|
||||||
uptr->pos = 0; /* update position */
|
sim_tape_rewind (uptr); /* rewind tape */
|
||||||
uptr->USTAT = 0; /* clear status */
|
uptr->USTAT = 0; /* clear status */
|
||||||
tufs = tufs | FS_ATA | FS_SSC;
|
tufs = tufs | FS_ATA | FS_SSC;
|
||||||
update_tucs (CS1_SC, drv); /* update status */
|
update_tucs (CS1_SC, drv); /* update status */
|
||||||
|
@ -702,8 +694,8 @@ wc = 0200000 - tuwc; /* get word count */
|
||||||
fc = 0200000 - tufc; /* get frame count */
|
fc = 0200000 - tufc; /* get frame count */
|
||||||
wc10 = wc >> 1; /* 10 word count */
|
wc10 = wc >> 1; /* 10 word count */
|
||||||
ba10 = ba >> 2; /* 10 word addr */
|
ba10 = ba >> 2; /* 10 word addr */
|
||||||
err = 0;
|
|
||||||
uptr->USTAT = 0; /* clear status */
|
uptr->USTAT = 0; /* clear status */
|
||||||
|
|
||||||
switch (f) { /* case on function */
|
switch (f) { /* case on function */
|
||||||
|
|
||||||
/* Unit service - non-data transfer commands - set ATA when done */
|
/* Unit service - non-data transfer commands - set ATA when done */
|
||||||
|
@ -711,9 +703,10 @@ switch (f) { /* case on function */
|
||||||
case FNC_SPACEF: /* space forward */
|
case FNC_SPACEF: /* space forward */
|
||||||
do {
|
do {
|
||||||
tufc = (tufc + 1) & 0177777; /* incr fc */
|
tufc = (tufc + 1) & 0177777; /* incr fc */
|
||||||
if (tu_rdlntf (uptr, &tbc, &err)) break; /* read rec lnt, err? */
|
if (st = sim_tape_sprecf (uptr, &tbc)) { /* space rec fwd, err? */
|
||||||
uptr->pos = uptr->pos + ((MTRL (tbc) + 1) & ~1) +
|
r = tu_map_err (uptr, st); /* map error */
|
||||||
(2 * sizeof (t_mtrlnt)); }
|
break; }
|
||||||
|
}
|
||||||
while (tufc != 0);
|
while (tufc != 0);
|
||||||
if (tufc) tuer = tuer | ER_FCE;
|
if (tufc) tuer = tuer | ER_FCE;
|
||||||
else tutc = tutc & ~TC_FCS;
|
else tutc = tutc & ~TC_FCS;
|
||||||
|
@ -723,26 +716,25 @@ case FNC_SPACEF: /* space forward */
|
||||||
case FNC_SPACER: /* space reverse */
|
case FNC_SPACER: /* space reverse */
|
||||||
do {
|
do {
|
||||||
tufc = (tufc + 1) & 0177777; /* incr wc */
|
tufc = (tufc + 1) & 0177777; /* incr wc */
|
||||||
if (pnu) pnu = 0; /* pos not upd? */
|
if (st = sim_tape_sprecr (uptr, &tbc)) { /* space rec rev, err? */
|
||||||
else {
|
r = tu_map_err (uptr, st); /* map error */
|
||||||
if (tu_rdlntr (uptr, &tbc, &err)) break;
|
break; }
|
||||||
uptr->pos = uptr->pos - ((MTRL (tbc) + 1) & ~1) -
|
}
|
||||||
(2 * sizeof (t_mtrlnt)); } }
|
|
||||||
while (tufc != 0);
|
while (tufc != 0);
|
||||||
if (tufc) tuer = tuer | ER_FCE;
|
if (tufc) tuer = tuer | ER_FCE;
|
||||||
else tutc = tutc & ~TC_FCS;
|
else tutc = tutc & ~TC_FCS;
|
||||||
tufs = tufs | FS_ATA;
|
tufs = tufs | FS_ATA;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FNC_WREOF:
|
case FNC_WREOF: /* write end of file */
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
|
||||||
fxwrite (&bceof, sizeof (t_mtrlnt), 1, uptr->fileref);
|
r = tu_map_err (uptr, st); /* map error */
|
||||||
tufs = tufs | FS_ATA;
|
tufs = tufs | FS_ATA;
|
||||||
if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr);
|
|
||||||
else uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* update position */
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FNC_ERASE:
|
case FNC_ERASE:
|
||||||
|
if (sim_tape_wrp (uptr)) /* write protected? */
|
||||||
|
r = tu_map_err (uptr, MTSE_WRP); /* map error */
|
||||||
tufs = tufs | FS_ATA;
|
tufs = tufs | FS_ATA;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -762,21 +754,12 @@ case FNC_ERASE:
|
||||||
case FNC_READF: /* read */
|
case FNC_READF: /* read */
|
||||||
case FNC_WCHKF: /* wcheck = read */
|
case FNC_WCHKF: /* wcheck = read */
|
||||||
tufc = 0; /* clear frame count */
|
tufc = 0; /* clear frame count */
|
||||||
if ((uptr->UDENS == TC_1600) && (uptr->pos == 0))
|
if ((uptr->UDENS == TC_1600) && sim_tape_bot (uptr))
|
||||||
tufs = tufs | FS_ID; /* PE BOT? ID burst */
|
tufs = tufs | FS_ID; /* PE BOT? ID burst */
|
||||||
TXFR (ba, wc, 0); /* validate transfer */
|
TXFR (ba, wc, 0); /* validate transfer */
|
||||||
if (tu_rdlntf (uptr, &tbc, &err)) break; /* read rec lnt, err? */
|
if (st = sim_tape_rdrecf (uptr, xbuf, &tbc, MT_MAXFR)) { /* read fwd */
|
||||||
if (MTRF (tbc)) { /* bad record? */
|
r = tu_map_err (uptr, st); /* map error */
|
||||||
tuer = tuer | ER_CRC; /* set error flag */
|
break; } /* done */
|
||||||
uptr->pos = uptr->pos + ((MTRL (tbc) + 1) & ~1) +
|
|
||||||
(2 * sizeof (t_mtrlnt));
|
|
||||||
break; }
|
|
||||||
if (tbc > XBUFLNT) return SCPE_MTRLNT; /* bad rec length? */
|
|
||||||
abc = fxread (xbuf, sizeof (int8), tbc, uptr->fileref);
|
|
||||||
if (err = ferror (uptr->fileref)) { /* error? */
|
|
||||||
MT_SET_PNU (uptr); /* pos not upd */
|
|
||||||
break; }
|
|
||||||
for ( ; abc < tbc + 4; abc++) xbuf[abc] = 0; /* fill/pad with 0's */
|
|
||||||
for (i = j = 0; (i < wc10) && (j < ((int32) tbc)); i++) {
|
for (i = j = 0; (i < wc10) && (j < ((int32) tbc)); i++) {
|
||||||
if ((i == 0) || NEWPAGE (ba10 + i, 0)) { /* map new page */
|
if ((i == 0) || NEWPAGE (ba10 + i, 0)) { /* map new page */
|
||||||
MAPM (ba10 + i, mpa10, 0); }
|
MAPM (ba10 + i, mpa10, 0); }
|
||||||
|
@ -785,7 +768,6 @@ case FNC_WCHKF: /* wcheck = read */
|
||||||
if (fmt == TC_10C) val = val | ((d10) xbuf[j++] & 017);
|
if (fmt == TC_10C) val = val | ((d10) xbuf[j++] & 017);
|
||||||
if (f == FNC_READF) M[mpa10] = val;
|
if (f == FNC_READF) M[mpa10] = val;
|
||||||
mpa10 = mpa10 + 1; } /* end for */
|
mpa10 = mpa10 + 1; } /* end for */
|
||||||
uptr->pos = uptr->pos + ((tbc + 1) & ~1) + (2 * sizeof (t_mtrlnt));
|
|
||||||
tufc = tbc & 0177777;
|
tufc = tbc & 0177777;
|
||||||
tuwc = (tuwc + (i << 1)) & 0177777;
|
tuwc = (tuwc + (i << 1)) & 0177777;
|
||||||
ba = ba + (i << 2);
|
ba = ba + (i << 2);
|
||||||
|
@ -793,7 +775,6 @@ case FNC_WCHKF: /* wcheck = read */
|
||||||
|
|
||||||
case FNC_WRITE: /* write */
|
case FNC_WRITE: /* write */
|
||||||
TXFR (ba, wc, 0); /* validate transfer */
|
TXFR (ba, wc, 0); /* validate transfer */
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
|
||||||
for (i = j = 0; (i < wc10) && (j < fc); i++) {
|
for (i = j = 0; (i < wc10) && (j < fc); i++) {
|
||||||
if ((i == 0) || NEWPAGE (ba10 + i, 0)) { /* map new page */
|
if ((i == 0) || NEWPAGE (ba10 + i, 0)) { /* map new page */
|
||||||
MAPM (ba10 + i, mpa10, 0); }
|
MAPM (ba10 + i, mpa10, 0); }
|
||||||
|
@ -805,13 +786,9 @@ case FNC_WRITE: /* write */
|
||||||
if (fmt == TC_10C) xbuf[j++] = (uint8) (val & 017);
|
if (fmt == TC_10C) xbuf[j++] = (uint8) (val & 017);
|
||||||
mpa10 = mpa10 + 1; } /* end for */
|
mpa10 = mpa10 + 1; } /* end for */
|
||||||
if (j < fc) fc = j; /* short record? */
|
if (j < fc) fc = j; /* short record? */
|
||||||
fxwrite (&fc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
if (st = sim_tape_wrrecf (uptr, xbuf, fc)) /* write rec, err? */
|
||||||
fxwrite (xbuf, sizeof (int8), (fc + 1) & ~1, uptr->fileref);
|
r = tu_map_err (uptr, st); /* map error */
|
||||||
fxwrite (&fc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
|
||||||
if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr);
|
|
||||||
else {
|
else {
|
||||||
uptr->pos = uptr->pos + ((fc + 1) & ~1) +
|
|
||||||
(2 * sizeof (t_mtrlnt));
|
|
||||||
tufc = (tufc + fc) & 0177777;
|
tufc = (tufc + fc) & 0177777;
|
||||||
if (tufc == 0) tutc = tutc & ~TC_FCS;
|
if (tufc == 0) tutc = tutc & ~TC_FCS;
|
||||||
tuwc = (tuwc + (i << 1)) & 0177777;
|
tuwc = (tuwc + (i << 1)) & 0177777;
|
||||||
|
@ -822,18 +799,10 @@ case FNC_READR: /* read reverse */
|
||||||
case FNC_WCHKR: /* wcheck = read */
|
case FNC_WCHKR: /* wcheck = read */
|
||||||
tufc = 0; /* clear frame count */
|
tufc = 0; /* clear frame count */
|
||||||
TXFR (ba, wc, 1); /* validate xfer rev */
|
TXFR (ba, wc, 1); /* validate xfer rev */
|
||||||
if (tu_rdlntr (uptr, &tbc, &err)) break; /* read rec lnt, err? */
|
if (st = sim_tape_rdrecr (uptr, xbuf + 4, &tbc, MT_MAXFR)) { /* read rev */
|
||||||
if (MTRF (tbc)) { /* bad record? */
|
r = tu_map_err (uptr, st); /* map error */
|
||||||
tuer = tuer | ER_CRC; /* set error flag */
|
break; } /* done */
|
||||||
uptr->pos = uptr->pos - ((MTRL (tbc) + 1) & ~1) -
|
|
||||||
(2 * sizeof (t_mtrlnt));
|
|
||||||
break; }
|
|
||||||
if (tbc > XBUFLNT) return SCPE_MTRLNT; /* bad rec length? */
|
|
||||||
fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt)
|
|
||||||
- ((tbc + 1) & ~1), SEEK_SET);
|
|
||||||
fxread (xbuf + 4, sizeof (int8), tbc, uptr->fileref);
|
|
||||||
for (i = 0; i < 4; i++) xbuf[i] = 0;
|
for (i = 0; i < 4; i++) xbuf[i] = 0;
|
||||||
err = ferror (uptr->fileref); /* set err but finish */
|
|
||||||
for (i = 0, j = tbc + 4; (i < wc10) && (j >= 4); i++) {
|
for (i = 0, j = tbc + 4; (i < wc10) && (j >= 4); i++) {
|
||||||
if ((i == 0) || NEWPAGE (ba10 - i, PAG_M_OFF)) { /* map page */
|
if ((i == 0) || NEWPAGE (ba10 - i, PAG_M_OFF)) { /* map page */
|
||||||
MAPM (ba10 - i, mpa10, UMAP_RRV); }
|
MAPM (ba10 - i, mpa10, UMAP_RRV); }
|
||||||
|
@ -842,7 +811,6 @@ case FNC_WCHKR: /* wcheck = read */
|
||||||
val = val | (v[0] << 4) | (v[1] << 12) | (v[2] << 20) | (v[3] << 28);
|
val = val | (v[0] << 4) | (v[1] << 12) | (v[2] << 20) | (v[3] << 28);
|
||||||
if (f == FNC_READR) M[mpa10] = val;
|
if (f == FNC_READR) M[mpa10] = val;
|
||||||
mpa10 = mpa10 - 1; } /* end for */
|
mpa10 = mpa10 - 1; } /* end for */
|
||||||
uptr->pos = uptr->pos - ((tbc + 1) & ~1) - (2 * sizeof (t_mtrlnt));
|
|
||||||
tufc = tbc & 0177777;
|
tufc = tbc & 0177777;
|
||||||
tuwc = (tuwc + (i << 1)) & 0177777;
|
tuwc = (tuwc + (i << 1)) & 0177777;
|
||||||
ba = ba - (i << 2);
|
ba = ba - (i << 2);
|
||||||
|
@ -851,12 +819,6 @@ case FNC_WCHKR: /* wcheck = read */
|
||||||
tucs1 = (tucs1 & ~CS1_UAE) | ((ba >> (16 - CS1_V_UAE)) & CS1_UAE);
|
tucs1 = (tucs1 & ~CS1_UAE) | ((ba >> (16 - CS1_V_UAE)) & CS1_UAE);
|
||||||
tuba = ba & 0177777; /* update mem addr */
|
tuba = ba & 0177777; /* update mem addr */
|
||||||
tucs1 = tucs1 & ~CS1_GO; /* clear go */
|
tucs1 = tucs1 & ~CS1_GO; /* clear go */
|
||||||
if (err != 0) { /* I/O error */
|
|
||||||
tuer = tuer | ER_VPE; /* flag error */
|
|
||||||
update_tucs (CS1_DONE | CS1_TRE, drv); /* set done, err */
|
|
||||||
perror ("TU I/O error");
|
|
||||||
clearerr (uptr->fileref);
|
|
||||||
return (tu_stopioe? SCPE_IOERR: SCPE_OK); }
|
|
||||||
update_tucs (CS1_DONE, drv);
|
update_tucs (CS1_DONE, drv);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -880,8 +842,8 @@ if (GET_FMTR (tucs2) == 0) { /* formatter present? */
|
||||||
if (tu_unit[drv].flags & UNIT_ATT) {
|
if (tu_unit[drv].flags & UNIT_ATT) {
|
||||||
tufs = tufs | FS_MOL | tu_unit[drv].USTAT;
|
tufs = tufs | FS_MOL | tu_unit[drv].USTAT;
|
||||||
if (tu_unit[drv].UDENS == TC_1600) tufs = tufs | FS_PE;
|
if (tu_unit[drv].UDENS == TC_1600) tufs = tufs | FS_PE;
|
||||||
if (tu_unit[drv].flags & UNIT_WPRT) tufs = tufs | FS_WRL;
|
if (sim_tape_wrp (&tu_unit[drv])) tufs = tufs | FS_WRL;
|
||||||
if ((tu_unit[drv].pos == 0) && !act) tufs = tufs | FS_BOT; }
|
if (sim_tape_bot (&tu_unit[drv]) && !act) tufs = tufs | FS_BOT; }
|
||||||
if (tuer) tufs = tufs | FS_ERR; }
|
if (tuer) tufs = tufs | FS_ERR; }
|
||||||
else tufs = 0;
|
else tufs = 0;
|
||||||
tucs1 = (tucs1 & ~(CS1_SC | CS1_MCPE | CS1_MBZ)) | CS1_DVA | flag;
|
tucs1 = (tucs1 & ~(CS1_SC | CS1_MCPE | CS1_MBZ)) | CS1_DVA | flag;
|
||||||
|
@ -904,50 +866,38 @@ tuiff = 0; /* clear CSTB INTR */
|
||||||
return VEC_TU; /* acknowledge */
|
return VEC_TU; /* acknowledge */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read record length forward - return T if error, EOM, or EOF */
|
/* Map tape error status */
|
||||||
|
|
||||||
t_bool tu_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
t_stat tu_map_err (UNIT *uptr, t_stat st)
|
||||||
{
|
{
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set tape pos */
|
switch (st) {
|
||||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref); /* read rec lnt */
|
case MTSE_FMT: /* illegal fmt */
|
||||||
if (*err = ferror (uptr->fileref)) { /* error? */
|
case MTSE_UNATT: /* not attached */
|
||||||
tuer = tuer | ER_VPE; /* parity error */
|
tuer = tuer | ER_NXF; /* can't execute */
|
||||||
MT_SET_PNU (uptr); /* pos not updated */
|
case MTSE_OK: /* no error */
|
||||||
return TRUE; }
|
return SCPE_IERR;
|
||||||
if (feof (uptr->fileref) || (*tbc == MTR_EOM)) { /* eof or eom? */
|
case MTSE_TMK: /* end of file */
|
||||||
tuer = tuer | ER_OPI; /* incomplete */
|
|
||||||
MT_SET_PNU (uptr); /* pos not updated */
|
|
||||||
return TRUE; }
|
|
||||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
|
||||||
tufs = tufs | FS_TMK;
|
tufs = tufs | FS_TMK;
|
||||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* spc over tmk */
|
break;
|
||||||
return TRUE; }
|
case MTSE_IOERR: /* IO error */
|
||||||
return FALSE;
|
tuer = tuer | ER_VPE; /* flag error */
|
||||||
}
|
if (tu_stopioe) return SCPE_IOERR;
|
||||||
|
break;
|
||||||
/* Read record length reverse - return T if error, EOM, or EOF */
|
case MTSE_INVRL: /* invalid rec lnt */
|
||||||
|
tuer = tuer | ER_VPE; /* flag error */
|
||||||
t_bool tu_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
return SCPE_MTRLNT;
|
||||||
{
|
case MTSE_RECE: /* record in error */
|
||||||
if (uptr->pos < sizeof (t_mtrlnt)) return TRUE;
|
tuer = tuer | ER_CRC; /* set crc err */
|
||||||
fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET);
|
break;
|
||||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
case MTSE_EOM: /* end of medium */
|
||||||
if (*err = ferror (uptr->fileref)) { /* error? */
|
|
||||||
tuer = tuer | ER_VPE; /* parity error */
|
|
||||||
return TRUE; }
|
|
||||||
if (feof (uptr->fileref)) { /* eof? */
|
|
||||||
tuer = tuer | ER_OPI; /* incomplete */
|
tuer = tuer | ER_OPI; /* incomplete */
|
||||||
return TRUE; }
|
break;
|
||||||
if (*tbc == MTR_EOM) { /* eom? */
|
case MTSE_BOT: /* reverse into BOT */
|
||||||
tuer = tuer | ER_OPI; /* incomplete */
|
break;
|
||||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over eom */
|
case MTSE_WRP: /* write protect */
|
||||||
return TRUE; }
|
tuer = tuer | ER_NXF; /* can't execute */
|
||||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
break; }
|
||||||
tufs = tufs | FS_TMK;
|
return SCPE_OK;
|
||||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over tmk */
|
|
||||||
return TRUE; }
|
|
||||||
*tbc = MTRL (*tbc); /* ignore error flag */
|
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset routine */
|
/* Reset routine */
|
||||||
|
@ -966,10 +916,10 @@ tuiff = 0; /* clear CSTB INTR */
|
||||||
int_req = int_req & ~INT_TU; /* clear interrupt */
|
int_req = int_req & ~INT_TU; /* clear interrupt */
|
||||||
for (u = 0; u < TU_NUMDR; u++) { /* loop thru units */
|
for (u = 0; u < TU_NUMDR; u++) { /* loop thru units */
|
||||||
uptr = tu_dev.units + u;
|
uptr = tu_dev.units + u;
|
||||||
MT_CLR_PNU (uptr); /* clear pos flag */
|
sim_tape_reset (uptr); /* clear pos flag */
|
||||||
sim_cancel (uptr); /* cancel activity */
|
sim_cancel (uptr); /* cancel activity */
|
||||||
uptr->USTAT = 0; }
|
uptr->USTAT = 0; }
|
||||||
if (xbuf == NULL) xbuf = calloc (XBUFLNT + 4, sizeof (uint8));
|
if (xbuf == NULL) xbuf = calloc (MT_MAXFR + 4, sizeof (uint8));
|
||||||
if (xbuf == NULL) return SCPE_MEM;
|
if (xbuf == NULL) return SCPE_MEM;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -981,9 +931,8 @@ t_stat tu_attach (UNIT *uptr, char *cptr)
|
||||||
int32 drv = uptr - tu_dev.units;
|
int32 drv = uptr - tu_dev.units;
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
r = attach_unit (uptr, cptr);
|
r = sim_tape_attach (uptr, cptr);
|
||||||
if (r != SCPE_OK) return r;
|
if (r != SCPE_OK) return r;
|
||||||
MT_CLR_PNU (uptr);
|
|
||||||
uptr->USTAT = 0; /* clear unit status */
|
uptr->USTAT = 0; /* clear unit status */
|
||||||
uptr->UDENS = UD_UNK; /* unknown density */
|
uptr->UDENS = UD_UNK; /* unknown density */
|
||||||
tufs = tufs | FS_ATA | FS_SSC; /* set attention */
|
tufs = tufs | FS_ATA | FS_SSC; /* set attention */
|
||||||
|
@ -1004,21 +953,12 @@ if (sim_is_active (uptr)) { /* unit active? */
|
||||||
tuer = tuer | ER_UNS; /* set formatter error */
|
tuer = tuer | ER_UNS; /* set formatter error */
|
||||||
if ((uptr->USTAT & FS_REW) == 0) /* data transfer? */
|
if ((uptr->USTAT & FS_REW) == 0) /* data transfer? */
|
||||||
tucs1 = tucs1 | CS1_DONE | CS1_TRE; } /* set done, err */
|
tucs1 = tucs1 | CS1_DONE | CS1_TRE; } /* set done, err */
|
||||||
MT_CLR_PNU (uptr);
|
|
||||||
uptr->USTAT = 0; /* clear status flags */
|
uptr->USTAT = 0; /* clear status flags */
|
||||||
tufs = tufs | FS_ATA | FS_SSC; /* set attention */
|
tufs = tufs | FS_ATA | FS_SSC; /* set attention */
|
||||||
update_tucs (CS1_SC, drv); /* update status */
|
update_tucs (CS1_SC, drv); /* update status */
|
||||||
return detach_unit (uptr);
|
return sim_tape_detach (uptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write lock/enable routine */
|
|
||||||
|
|
||||||
t_stat tu_vlock (UNIT *uptr, int32 val, char *cptr, void *desc)
|
|
||||||
{
|
|
||||||
if (sim_is_active (uptr)) return SCPE_ARG;
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Device bootstrap */
|
/* Device bootstrap */
|
||||||
|
|
||||||
#define BOOT_START 0377000 /* start */
|
#define BOOT_START 0377000 /* start */
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
The author gratefully acknowledges the help of Max Burnet, Megan Gentry,
|
The author gratefully acknowledges the help of Max Burnet, Megan Gentry,
|
||||||
and John Wilson in resolving questions about the PDP-11
|
and John Wilson in resolving questions about the PDP-11
|
||||||
|
|
||||||
|
28-Feb-03 RMS Added TM logging support
|
||||||
19-Jan-03 RMS Changed mode definitions for Apple Dev Kit conflict
|
19-Jan-03 RMS Changed mode definitions for Apple Dev Kit conflict
|
||||||
11-Nov-02 RMS Changed log definitions to be VAX compatible
|
11-Nov-02 RMS Changed log definitions to be VAX compatible
|
||||||
10-Oct-02 RMS Added vector information to DIB
|
10-Oct-02 RMS Added vector information to DIB
|
||||||
|
@ -551,6 +552,7 @@ typedef struct pdp_dib DIB;
|
||||||
/* Logging */
|
/* Logging */
|
||||||
|
|
||||||
#define LOG_CPU_I 0x0001
|
#define LOG_CPU_I 0x0001
|
||||||
|
#define LOG_TM 0x0008
|
||||||
#define LOG_RP 0x0010
|
#define LOG_RP 0x0010
|
||||||
#define LOG_TS 0x0020
|
#define LOG_TS 0x0020
|
||||||
#define LOG_RQ 0x0040
|
#define LOG_RQ 0x0040
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
To: Users
|
To: Users
|
||||||
From: Bob Supnik
|
From: Bob Supnik
|
||||||
Subj: PDP-11 Simulator Usage
|
Subj: PDP-11 Simulator Usage
|
||||||
Date: 1-Feb-2003
|
Date: 15-Mar-2003
|
||||||
|
|
||||||
COPYRIGHT NOTICE
|
COPYRIGHT NOTICE
|
||||||
|
|
||||||
|
@ -377,6 +377,12 @@ implements these registers:
|
||||||
POS 32 number of characters input
|
POS 32 number of characters input
|
||||||
TIME 24 keyboard polling interval
|
TIME 24 keyboard polling interval
|
||||||
|
|
||||||
|
If the simulator is compiled under Windows Visual C++, typing ^C to the
|
||||||
|
terminal input causes a fatal run-time error. Use the following command
|
||||||
|
to simulate typing ^C:
|
||||||
|
|
||||||
|
SET TTI CTRL-C
|
||||||
|
|
||||||
2.3.4 DL11 Terminal Output (TTO)
|
2.3.4 DL11 Terminal Output (TTO)
|
||||||
|
|
||||||
The terminal output (TTO) writes to the simulator console window. It
|
The terminal output (TTO) writes to the simulator console window. It
|
||||||
|
@ -424,7 +430,14 @@ Error handling is as follows:
|
||||||
|
|
||||||
2.3.6 Line-Time Clock (CLK)
|
2.3.6 Line-Time Clock (CLK)
|
||||||
|
|
||||||
The line-time clock (CLK) implements these registers:
|
The line-time clock (CLK) frequency can be adjusted as follows:
|
||||||
|
|
||||||
|
SET CLK 60HZ set frequency to 60Hz
|
||||||
|
SET CLK 50HZ set frequency to 50Hz
|
||||||
|
|
||||||
|
The default is 60Hz.
|
||||||
|
|
||||||
|
The line-time clock implements these registers:
|
||||||
|
|
||||||
name size comments
|
name size comments
|
||||||
|
|
||||||
|
@ -433,14 +446,20 @@ The line-time clock (CLK) implements these registers:
|
||||||
DONE 1 device done flag (CSR<7>)
|
DONE 1 device done flag (CSR<7>)
|
||||||
IE 1 interrupt enable flag (CSR<6>)
|
IE 1 interrupt enable flag (CSR<6>)
|
||||||
TIME 24 clock interval
|
TIME 24 clock interval
|
||||||
TPS 8 ticks per second (60 or 50)
|
|
||||||
|
|
||||||
The line-time clock autocalibrates; the clock interval is adjusted up
|
The line-time clock autocalibrates; the clock interval is adjusted up
|
||||||
or down so that the clock tracks actual elapsed time.
|
or down so that the clock tracks actual elapsed time.
|
||||||
|
|
||||||
2.3.7 Programmable Clock (PCLK)
|
2.3.7 Programmable Clock (PCLK)
|
||||||
|
|
||||||
The programmable clock (PCLK) implements these registers:
|
The programmable clock (PCLK) line frequency can be adjusted as follows:
|
||||||
|
|
||||||
|
SET PCLK 60HZ set frequency to 60Hz
|
||||||
|
SET PCLK 50HZ set frequency to 50Hz
|
||||||
|
|
||||||
|
The default is 60Hz.
|
||||||
|
|
||||||
|
The programmable clock implements these registers:
|
||||||
|
|
||||||
name size comments
|
name size comments
|
||||||
|
|
||||||
|
@ -838,7 +857,7 @@ The simulator implements four MSCP disk controllers, RQ, RQB, RQC, RQD.
|
||||||
Initially, RQB, RQC, and RQD are disabled. Each RQ controller simulates
|
Initially, RQB, RQC, and RQD are disabled. Each RQ controller simulates
|
||||||
an RQDX3 MSCP disk controller. RQ options include the ability to set
|
an RQDX3 MSCP disk controller. RQ options include the ability to set
|
||||||
units write enabled or write locked, and to set the drive type to one
|
units write enabled or write locked, and to set the drive type to one
|
||||||
of eleven disk types:
|
of many disk types:
|
||||||
|
|
||||||
SET RQn LOCKED set unit n write locked
|
SET RQn LOCKED set unit n write locked
|
||||||
SET RQn WRITEENABLED set unit n write enabled
|
SET RQn WRITEENABLED set unit n write enabled
|
||||||
|
@ -854,6 +873,7 @@ of eleven disk types:
|
||||||
SET RQn RA90 set type to RA90
|
SET RQn RA90 set type to RA90
|
||||||
SET RQn RA92 set type to RA92
|
SET RQn RA92 set type to RA92
|
||||||
SET RQn RRD40 set type to RRD40 (CD ROM)
|
SET RQn RRD40 set type to RRD40 (CD ROM)
|
||||||
|
SET RQn RAUSER{=n} set type to RA81 with n LBNs
|
||||||
|
|
||||||
The type options can be used only when a unit is not attached to a file.
|
The type options can be used only when a unit is not attached to a file.
|
||||||
Units can also be set ONLINE or OFFLINE. Each RQ controller supports the
|
Units can also be set ONLINE or OFFLINE. Each RQ controller supports the
|
||||||
|
@ -862,6 +882,7 @@ a Qbus (22B) system, an RQ supports 22b addressing.
|
||||||
|
|
||||||
Each RQ controller implements the following special SHOW commands:
|
Each RQ controller implements the following special SHOW commands:
|
||||||
|
|
||||||
|
SHOW RQn TYPE show drive type
|
||||||
SHOW RQ RINGS show command and response rings
|
SHOW RQ RINGS show command and response rings
|
||||||
SHOW RQ FREEQ show packet free queue
|
SHOW RQ FREEQ show packet free queue
|
||||||
SHOW RQ RESPQ show packet response queue
|
SHOW RQ RESPQ show packet response queue
|
||||||
|
@ -1079,10 +1100,18 @@ Error handling is as follows:
|
||||||
2.9.3 TQK50 TMSCP Disk Controller (TQ)
|
2.9.3 TQK50 TMSCP Disk Controller (TQ)
|
||||||
|
|
||||||
The TQ controller simulates the TQK50 TMSCP disk controller. TQ options
|
The TQ controller simulates the TQK50 TMSCP disk controller. TQ options
|
||||||
include the ability to set units write enabled or write locked:
|
include the ability to set units write enabled or write locked, and to
|
||||||
|
specify the controller type and tape length:
|
||||||
|
|
||||||
SET TQn LOCKED set unit n write locked
|
SET TQn LOCKED set unit n write locked
|
||||||
SET TQn WRITEENABLED set unit n write enabled
|
SET TQn WRITEENABLED set unit n write enabled
|
||||||
|
SET TQ TK50 set controller type to TK50
|
||||||
|
SET TQ TK70 set controller type to TK70
|
||||||
|
SET TQ TU81 set controller type to TU81
|
||||||
|
SET TQ TKUSER{=n} set controller type to TK50 with
|
||||||
|
tape capacity of n MB
|
||||||
|
|
||||||
|
User-specified capacity must be between 50 and 2000 MB.
|
||||||
|
|
||||||
The TQ controller supports the BOOT command. In a Unibus system, the
|
The TQ controller supports the BOOT command. In a Unibus system, the
|
||||||
TQ supports 18b addressing. In a Qbus (22B) system, the TQ supports
|
TQ supports 18b addressing. In a Qbus (22B) system, the TQ supports
|
||||||
|
@ -1090,6 +1119,7 @@ TQ supports 18b addressing. In a Qbus (22B) system, the TQ supports
|
||||||
|
|
||||||
The TQ controller implements the following special SHOW commands:
|
The TQ controller implements the following special SHOW commands:
|
||||||
|
|
||||||
|
SHOW TQ TYPE show controller type
|
||||||
SHOW TQ RINGS show command and response rings
|
SHOW TQ RINGS show command and response rings
|
||||||
SHOW TQ FREEQ show packet free queue
|
SHOW TQ FREEQ show packet free queue
|
||||||
SHOW TQ RESPQ show packet response queue
|
SHOW TQ RESPQ show packet response queue
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* pdp11_mscp.h: DEC MSCP and TMSCP definitions
|
/* pdp11_mscp.h: DEC MSCP and TMSCP definitionsn
|
||||||
|
|
||||||
Copyright (c) 2001-2003, Robert M Supnik
|
Copyright (c) 2001-2003, Robert M Supnik
|
||||||
Derived from work by Stephen F. Shirron
|
Derived from work by Stephen F. Shirron
|
||||||
|
|
133
PDP11/pdp11_rq.c
133
PDP11/pdp11_rq.c
|
@ -1,6 +1,6 @@
|
||||||
/* pdp11_rq.c: RQDX3 disk controller simulator
|
/* pdp11_rq.c: RQDX3 disk controller simulator
|
||||||
|
|
||||||
Copyright (c) 2002, Robert M Supnik
|
Copyright (c) 2003, Robert M Supnik
|
||||||
Derived from work by Stephen F. Shirron
|
Derived from work by Stephen F. Shirron
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
@ -26,6 +26,9 @@
|
||||||
|
|
||||||
rq RQDX3 disk controller
|
rq RQDX3 disk controller
|
||||||
|
|
||||||
|
27-Feb-03 RMS Added user-defined drive support
|
||||||
|
26-Feb-03 RMS Fixed bug in vector calculation for VAXen
|
||||||
|
22-Feb-03 RMS Fixed ordering bug in queue process
|
||||||
12-Oct-02 RMS Added multicontroller support
|
12-Oct-02 RMS Added multicontroller support
|
||||||
29-Sep-02 RMS Changed addressing to 18b in Unibus mode
|
29-Sep-02 RMS Changed addressing to 18b in Unibus mode
|
||||||
Added variable address support to bootstrap
|
Added variable address support to bootstrap
|
||||||
|
@ -201,7 +204,7 @@ struct rqpkt {
|
||||||
|
|
||||||
Each drive can be a different type. The drive field in the
|
Each drive can be a different type. The drive field in the
|
||||||
unit flags specified the drive type and thus, indirectly,
|
unit flags specified the drive type and thus, indirectly,
|
||||||
the drive size. DISKS MUST BE DECLARED IN ASCENDING SIZE.
|
the drive size.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define RQDF_RMV 01 /* removable */
|
#define RQDF_RMV 01 /* removable */
|
||||||
|
@ -400,6 +403,24 @@ struct rqpkt {
|
||||||
#define RA92_MED 0x2564105C
|
#define RA92_MED 0x2564105C
|
||||||
#define RA92_FLGS RQDF_SDI
|
#define RA92_FLGS RQDF_SDI
|
||||||
|
|
||||||
|
#define RA8U_DTYPE 12 /* user defined */
|
||||||
|
#define RA8U_SECT 57 /* +1 spare/track */
|
||||||
|
#define RA8U_SURF 15
|
||||||
|
#define RA8U_CYL 1435 /* 0-1422 user */
|
||||||
|
#define RA8U_TPG RA8U_SURF
|
||||||
|
#define RA8U_GPC 1
|
||||||
|
#define RA8U_XBN 3420 /* cyl 1427-1430 */
|
||||||
|
#define RA8U_DBN 3420 /* cyl 1431-1434 */
|
||||||
|
#define RA8U_LBN 1216665 /* 57*15*1423 */
|
||||||
|
#define RA8U_RCTS 400 /* cyl 1423-1426 */
|
||||||
|
#define RA8U_RCTC 8
|
||||||
|
#define RA8U_RBN 21345 /* 1 *15*1423 */
|
||||||
|
#define RA8U_MOD 11 /* RA82 */
|
||||||
|
#define RA8U_MED 0x25641052 /* RA82 */
|
||||||
|
#define RA8U_FLGS RQDF_SDI
|
||||||
|
#define RA8U_MINC ((5 << 20) / RQ_NUMBY)
|
||||||
|
#define RA8U_MAXC ((2047 << 20) / RQ_NUMBY)
|
||||||
|
|
||||||
struct drvtyp {
|
struct drvtyp {
|
||||||
int32 sect; /* sectors */
|
int32 sect; /* sectors */
|
||||||
int32 surf; /* surfaces */
|
int32 surf; /* surfaces */
|
||||||
|
@ -415,6 +436,7 @@ struct drvtyp {
|
||||||
int32 mod; /* MSCP model */
|
int32 mod; /* MSCP model */
|
||||||
int32 med; /* MSCP media */
|
int32 med; /* MSCP media */
|
||||||
int32 flgs; /* flags */
|
int32 flgs; /* flags */
|
||||||
|
char *name; /* name */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define RQ_DRV(d) \
|
#define RQ_DRV(d) \
|
||||||
|
@ -425,13 +447,13 @@ struct drvtyp {
|
||||||
#define RQ_SIZE(d) (d##_LBN * RQ_NUMBY)
|
#define RQ_SIZE(d) (d##_LBN * RQ_NUMBY)
|
||||||
|
|
||||||
static struct drvtyp drv_tab[] = {
|
static struct drvtyp drv_tab[] = {
|
||||||
{ RQ_DRV (RX50) }, { RQ_DRV (RX33) },
|
{ RQ_DRV (RX50), "RX50" }, { RQ_DRV (RX33), "RX33" },
|
||||||
{ RQ_DRV (RD51) }, { RQ_DRV (RD31) },
|
{ RQ_DRV (RD51), "RD51" }, { RQ_DRV (RD31), "RD31" },
|
||||||
{ RQ_DRV (RD52) }, { RQ_DRV (RD53) },
|
{ RQ_DRV (RD52), "RD52" }, { RQ_DRV (RD53), "RD53" },
|
||||||
{ RQ_DRV (RD54) }, { RQ_DRV (RA82) },
|
{ RQ_DRV (RD54), "RD54" }, { RQ_DRV (RA82), "RA82" },
|
||||||
{ RQ_DRV (RRD40) }, { RQ_DRV (RA72) },
|
{ RQ_DRV (RRD40), "RRD40" }, { RQ_DRV (RA72), "RA72" },
|
||||||
{ RQ_DRV (RA90) }, { RQ_DRV (RA92) },
|
{ RQ_DRV (RA90), "RA90" }, { RQ_DRV (RA92), "RA92" },
|
||||||
{ 0 } };
|
{ RQ_DRV (RA8U), "RAUSER" }, { 0 } };
|
||||||
|
|
||||||
extern int32 int_req[IPL_HLVL];
|
extern int32 int_req[IPL_HLVL];
|
||||||
extern int32 tmr_poll, clk_tps;
|
extern int32 tmr_poll, clk_tps;
|
||||||
|
@ -483,7 +505,8 @@ t_stat rq_attach (UNIT *uptr, char *cptr);
|
||||||
t_stat rq_detach (UNIT *uptr);
|
t_stat rq_detach (UNIT *uptr);
|
||||||
t_stat rq_boot (int32 unitno, DEVICE *dptr);
|
t_stat rq_boot (int32 unitno, DEVICE *dptr);
|
||||||
t_stat rq_set_wlk (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat rq_set_wlk (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
t_stat rq_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat rq_set_type (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat rq_show_type (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
t_stat rq_show_wlk (FILE *st, UNIT *uptr, int32 val, void *desc);
|
t_stat rq_show_wlk (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
t_stat rq_show_ctrl (FILE *st, UNIT *uptr, int32 val, void *desc);
|
t_stat rq_show_ctrl (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
t_stat rq_show_unitq (FILE *st, UNIT *uptr, int32 val, void *desc);
|
t_stat rq_show_unitq (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
|
@ -584,6 +607,7 @@ REG rq_reg[] = {
|
||||||
{ URDATA (UFLG, rq_unit[0].uf, RQ_RDX, 16, 0, RQ_NUMDR, 0) },
|
{ URDATA (UFLG, rq_unit[0].uf, RQ_RDX, 16, 0, RQ_NUMDR, 0) },
|
||||||
{ GRDATA (DEVADDR, rq_dib.ba, RQ_RDX, 32, 0), REG_HRO },
|
{ GRDATA (DEVADDR, rq_dib.ba, RQ_RDX, 32, 0), REG_HRO },
|
||||||
{ GRDATA (DEVVEC, rq_dib.vec, RQ_RDX, 16, 0), REG_HRO },
|
{ GRDATA (DEVVEC, rq_dib.vec, RQ_RDX, 16, 0), REG_HRO },
|
||||||
|
{ DRDATA (DEVLBN, drv_tab[RA8U_DTYPE].lbn, 22), REG_HRO },
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
MTAB rq_mod[] = {
|
MTAB rq_mod[] = {
|
||||||
|
@ -603,19 +627,36 @@ MTAB rq_mod[] = {
|
||||||
NULL, &rq_show_unitq, 0 },
|
NULL, &rq_show_unitq, 0 },
|
||||||
{ MTAB_XTD | MTAB_VUN, 0, "WRITE", NULL,
|
{ MTAB_XTD | MTAB_VUN, 0, "WRITE", NULL,
|
||||||
NULL, &rq_show_wlk, NULL },
|
NULL, &rq_show_wlk, NULL },
|
||||||
{ UNIT_DTYPE, (RX50_DTYPE << UNIT_V_DTYPE), "RX50", "RX50", &rq_set_size },
|
{ MTAB_XTD | MTAB_VUN, RX50_DTYPE, NULL, "RX50",
|
||||||
{ UNIT_DTYPE, (RX33_DTYPE << UNIT_V_DTYPE), "RX33", "RX33", &rq_set_size },
|
&rq_set_type, NULL, NULL },
|
||||||
{ UNIT_DTYPE, (RD31_DTYPE << UNIT_V_DTYPE), "RD31", "RD31", &rq_set_size },
|
{ MTAB_XTD | MTAB_VUN, RX33_DTYPE, NULL, "RX33",
|
||||||
{ UNIT_DTYPE, (RD51_DTYPE << UNIT_V_DTYPE), "RD51", "RD51", &rq_set_size },
|
&rq_set_type, NULL, NULL },
|
||||||
{ UNIT_DTYPE, (RD52_DTYPE << UNIT_V_DTYPE), "RD52", "RD52", &rq_set_size },
|
{ MTAB_XTD | MTAB_VUN, RD31_DTYPE, NULL, "RD31",
|
||||||
{ UNIT_DTYPE, (RD53_DTYPE << UNIT_V_DTYPE), "RD53", "RD53", &rq_set_size },
|
&rq_set_type, NULL, NULL },
|
||||||
{ UNIT_DTYPE, (RD54_DTYPE << UNIT_V_DTYPE), "RD54", "RD54", &rq_set_size },
|
{ MTAB_XTD | MTAB_VUN, RD51_DTYPE, NULL, "RD51",
|
||||||
{ UNIT_DTYPE, (RA82_DTYPE << UNIT_V_DTYPE), "RA82", "RA82", &rq_set_size },
|
&rq_set_type, NULL, NULL },
|
||||||
{ UNIT_DTYPE, (RA72_DTYPE << UNIT_V_DTYPE), "RA72", "RA72", &rq_set_size },
|
{ MTAB_XTD | MTAB_VUN, RD52_DTYPE, NULL, "RD52",
|
||||||
{ UNIT_DTYPE, (RA90_DTYPE << UNIT_V_DTYPE), "RA90", "RA90", &rq_set_size },
|
&rq_set_type, NULL, NULL },
|
||||||
{ UNIT_DTYPE, (RA92_DTYPE << UNIT_V_DTYPE), "RA92", "RA92", &rq_set_size },
|
{ MTAB_XTD | MTAB_VUN, RD53_DTYPE, NULL, "RD53",
|
||||||
{ UNIT_DTYPE, (RRD40_DTYPE << UNIT_V_DTYPE), "RRD40", "RRD40", &rq_set_size },
|
&rq_set_type, NULL, NULL },
|
||||||
{ UNIT_DTYPE, (RRD40_DTYPE << UNIT_V_DTYPE), NULL, "CDROM", &rq_set_size },
|
{ MTAB_XTD | MTAB_VUN, RD54_DTYPE, NULL, "RD54",
|
||||||
|
&rq_set_type, NULL, NULL },
|
||||||
|
{ MTAB_XTD | MTAB_VUN, RA82_DTYPE, NULL, "RA82",
|
||||||
|
&rq_set_type, NULL, NULL },
|
||||||
|
{ MTAB_XTD | MTAB_VUN, RRD40_DTYPE, NULL, "RRD40",
|
||||||
|
&rq_set_type, NULL, NULL },
|
||||||
|
{ MTAB_XTD | MTAB_VUN, RRD40_DTYPE, NULL, "CDROM",
|
||||||
|
&rq_set_type, NULL, NULL },
|
||||||
|
{ MTAB_XTD | MTAB_VUN, RA72_DTYPE, NULL, "RA72",
|
||||||
|
&rq_set_type, NULL, NULL },
|
||||||
|
{ MTAB_XTD | MTAB_VUN, RA90_DTYPE, NULL, "RA90",
|
||||||
|
&rq_set_type, NULL, NULL },
|
||||||
|
{ MTAB_XTD | MTAB_VUN, RA92_DTYPE, NULL, "RA92",
|
||||||
|
&rq_set_type, NULL, NULL },
|
||||||
|
{ MTAB_XTD | MTAB_VUN, RA8U_DTYPE, NULL, "RAUSER",
|
||||||
|
&rq_set_type, NULL, NULL },
|
||||||
|
{ MTAB_XTD | MTAB_VUN, 0, "TYPE", NULL,
|
||||||
|
NULL, &rq_show_type, NULL },
|
||||||
#if defined (VM_PDP11)
|
#if defined (VM_PDP11)
|
||||||
{ MTAB_XTD|MTAB_VDV, 004, "ADDRESS", "ADDRESS",
|
{ MTAB_XTD|MTAB_VDV, 004, "ADDRESS", "ADDRESS",
|
||||||
&set_addr, &show_addr, NULL },
|
&set_addr, &show_addr, NULL },
|
||||||
|
@ -931,9 +972,8 @@ return OK;
|
||||||
queues, response queue) require servicing. Also invoked during
|
queues, response queue) require servicing. Also invoked during
|
||||||
initialization to provide some delay to the next step.
|
initialization to provide some delay to the next step.
|
||||||
|
|
||||||
Process at most one item off the host queue
|
Process at most one item off each unit queue
|
||||||
If the host queue is empty, process at most one item off
|
If the unit queues were empty, process at most one item off the host queue
|
||||||
each unit queue
|
|
||||||
Process at most one item off the response queue
|
Process at most one item off the response queue
|
||||||
|
|
||||||
If all queues are idle, terminate thread
|
If all queues are idle, terminate thread
|
||||||
|
@ -957,7 +997,8 @@ if (cp->csta < CST_UP) { /* still init? */
|
||||||
cp->csta = CST_S1_WR; } /* endless loop */
|
cp->csta = CST_S1_WR; } /* endless loop */
|
||||||
else {
|
else {
|
||||||
cp->s1dat = cp->saw; /* save data */
|
cp->s1dat = cp->saw; /* save data */
|
||||||
dibp->vec = VEC_Q + ((cp->s1dat & SA_S1H_VEC) << 2);
|
dibp->vec = (cp->s1dat & SA_S1H_VEC) << 2; /* get vector */
|
||||||
|
if (dibp->vec) dibp->vec = dibp->vec + VEC_Q; /* if nz, bias */
|
||||||
cp->sa = SA_S2 | SA_S2C_PT | SA_S2C_EC (cp->s1dat);
|
cp->sa = SA_S2 | SA_S2C_PT | SA_S2C_EC (cp->s1dat);
|
||||||
cp->csta = CST_S2; /* now in step 2 */
|
cp->csta = CST_S2; /* now in step 2 */
|
||||||
rq_init_int (cp); } /* intr if req */
|
rq_init_int (cp); } /* intr if req */
|
||||||
|
@ -996,7 +1037,12 @@ if (cp->csta < CST_UP) { /* still init? */
|
||||||
break; } /* end switch */
|
break; } /* end switch */
|
||||||
return SCPE_OK; } /* end if */
|
return SCPE_OK; } /* end if */
|
||||||
|
|
||||||
if (cp->pip) { /* polling? */
|
for (i = 0; i < RQ_NUMDR; i++) { /* chk unit q's */
|
||||||
|
nuptr = dptr->units + i; /* ptr to unit */
|
||||||
|
if (nuptr->cpkt || (nuptr->pktq == 0)) continue;
|
||||||
|
pkt = rq_deqh (cp, &nuptr->pktq); /* get top of q */
|
||||||
|
if (!rq_mscp (cp, pkt, FALSE)) return SCPE_OK; } /* process */
|
||||||
|
if ((pkt == 0) && cp->pip) { /* polling? */
|
||||||
if (!rq_getpkt (cp, &pkt)) return SCPE_OK; /* get host pkt */
|
if (!rq_getpkt (cp, &pkt)) return SCPE_OK; /* get host pkt */
|
||||||
if (pkt) { /* got one? */
|
if (pkt) { /* got one? */
|
||||||
if (DBG_LOG (LOG_RQ)) {
|
if (DBG_LOG (LOG_RQ)) {
|
||||||
|
@ -1019,13 +1065,6 @@ if (cp->pip) { /* polling? */
|
||||||
} /* end if pkt */
|
} /* end if pkt */
|
||||||
else cp->pip = 0; /* discontinue poll */
|
else cp->pip = 0; /* discontinue poll */
|
||||||
} /* end if pip */
|
} /* end if pip */
|
||||||
if (!cp->pip) { /* not polling? */
|
|
||||||
for (i = 0; i < RQ_NUMDR; i++) { /* chk unit q's */
|
|
||||||
nuptr = dptr->units + i; /* ptr to unit */
|
|
||||||
if (nuptr->cpkt || (nuptr->pktq == 0)) continue;
|
|
||||||
pkt = rq_deqh (cp, &nuptr->pktq); /* get top of q */
|
|
||||||
if (!rq_mscp (cp, pkt, FALSE)) return SCPE_OK; } /* process */
|
|
||||||
} /* end if !pip */
|
|
||||||
if (cp->rspq) { /* resp q? */
|
if (cp->rspq) { /* resp q? */
|
||||||
pkt = rq_deqh (cp, &cp->rspq); /* get top of q */
|
pkt = rq_deqh (cp, &cp->rspq); /* get top of q */
|
||||||
if (!rq_putpkt (cp, pkt, FALSE)) return SCPE_OK; /* send to hst */
|
if (!rq_putpkt (cp, pkt, FALSE)) return SCPE_OK; /* send to hst */
|
||||||
|
@ -1948,14 +1987,30 @@ else fprintf (st, "write enabled");
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Change unit size */
|
/* Set unit type (and capacity if user defined) */
|
||||||
|
|
||||||
t_stat rq_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
t_stat rq_set_type (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
{
|
{
|
||||||
uint32 dtyp = GET_DTYPE (val);
|
int32 cap;
|
||||||
|
t_stat r;
|
||||||
|
|
||||||
|
if ((val < 0) || (val > RA8U_DTYPE) || ((val != RA8U_DTYPE) && cptr))
|
||||||
|
return SCPE_ARG;
|
||||||
if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
|
if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
|
||||||
uptr->capac = drv_tab[dtyp].lbn * RQ_NUMBY;
|
if (cptr) {
|
||||||
|
cap = (int32) get_uint (cptr, 10, RA8U_MAXC, &r);
|
||||||
|
if ((r != SCPE_OK) || (cap < RA8U_MINC)) return SCPE_ARG;
|
||||||
|
drv_tab[val].lbn = cap; }
|
||||||
|
uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (val << UNIT_V_DTYPE);
|
||||||
|
uptr->capac = drv_tab[val].lbn * RQ_NUMBY;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Show unit type (and capacity if user defined) */
|
||||||
|
|
||||||
|
t_stat rq_show_type (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
|
{
|
||||||
|
fprintf (st, "%s", drv_tab[GET_DTYPE (uptr->flags)].name);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* pdp11_ry.c: RY11/RX02 floppy disk simulator
|
/* pdp11_ry.c: RY11/RX02 floppy disk simulator
|
||||||
|
|
||||||
Copyright (c) 1993-2002, Robert M Supnik
|
Copyright (c) 1993-2003, Robert M Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
ry RY11/RX02 floppy disk
|
ry RY11/RX02 floppy disk
|
||||||
|
|
||||||
|
03-Mar-03 RMS Fixed autosizing
|
||||||
12-Oct-02 RMS Added autoconfigure support
|
12-Oct-02 RMS Added autoconfigure support
|
||||||
|
|
||||||
An RX02 diskette consists of 77 tracks, each with 26 sectors of 256B.
|
An RX02 diskette consists of 77 tracks, each with 26 sectors of 256B.
|
||||||
|
@ -511,20 +512,13 @@ return auto_config (0, 0); /* run autoconfig */
|
||||||
|
|
||||||
t_stat ry_attach (UNIT *uptr, char *cptr)
|
t_stat ry_attach (UNIT *uptr, char *cptr)
|
||||||
{
|
{
|
||||||
int32 p;
|
t_addr sz;
|
||||||
t_stat r;
|
|
||||||
|
|
||||||
|
if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (cptr))) {
|
||||||
|
if (sz > RX_SIZE) uptr->flags = uptr->flags | UNIT_DEN;
|
||||||
|
else uptr->flags = uptr->flags & ~UNIT_DEN; }
|
||||||
uptr->capac = (uptr->flags & UNIT_DEN)? RY_SIZE: RX_SIZE;
|
uptr->capac = (uptr->flags & UNIT_DEN)? RY_SIZE: RX_SIZE;
|
||||||
r = attach_unit (uptr, cptr);
|
return attach_unit (uptr, cptr);
|
||||||
if ((r != SCPE_OK) || ((uptr->flags & UNIT_AUTO) == 0)) return r;
|
|
||||||
if (fseek (uptr->fileref, 0, SEEK_END)) return SCPE_OK;
|
|
||||||
if ((p = ftell (uptr->fileref)) == 0) return SCPE_OK;
|
|
||||||
if (p > RX_SIZE) {
|
|
||||||
uptr->flags = uptr->flags | UNIT_DEN;
|
|
||||||
uptr->capac = RY_SIZE; }
|
|
||||||
else { uptr->flags = uptr->flags & ~UNIT_DEN;
|
|
||||||
uptr->capac = RX_SIZE; }
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set size routine */
|
/* Set size routine */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* pdp11_stddev.c: PDP-11 standard I/O devices simulator
|
/* pdp11_stddev.c: PDP-11 standard I/O devices simulator
|
||||||
|
|
||||||
Copyright (c) 1993-2002, Robert M Supnik
|
Copyright (c) 1993-2003, Robert M Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -26,6 +26,7 @@
|
||||||
tti,tto DL11 terminal input/output
|
tti,tto DL11 terminal input/output
|
||||||
clk KW11L line frequency clock
|
clk KW11L line frequency clock
|
||||||
|
|
||||||
|
01-Mar-03 RMS Added SET/SHOW CLOCK FREQ, SET TTI CTRL-C
|
||||||
22-Nov-02 RMS Changed terminal default to 7B for UNIX
|
22-Nov-02 RMS Changed terminal default to 7B for UNIX
|
||||||
01-Nov-02 RMS Added 7B/8B support to terminal
|
01-Nov-02 RMS Added 7B/8B support to terminal
|
||||||
29-Sep-02 RMS Added vector display support
|
29-Sep-02 RMS Added vector display support
|
||||||
|
@ -58,7 +59,6 @@
|
||||||
|
|
||||||
#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */
|
#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */
|
||||||
#define UNIT_8B (1 << UNIT_V_8B)
|
#define UNIT_8B (1 << UNIT_V_8B)
|
||||||
#define UNIT_KSR (1 << UNIT_V_KSR)
|
|
||||||
|
|
||||||
extern int32 int_req[IPL_HLVL];
|
extern int32 int_req[IPL_HLVL];
|
||||||
extern int32 int_vec[IPL_HLVL][32];
|
extern int32 int_vec[IPL_HLVL][32];
|
||||||
|
@ -78,11 +78,14 @@ t_stat tto_rd (int32 *data, int32 PA, int32 access);
|
||||||
t_stat tto_wr (int32 data, int32 PA, int32 access);
|
t_stat tto_wr (int32 data, int32 PA, int32 access);
|
||||||
t_stat tto_svc (UNIT *uptr);
|
t_stat tto_svc (UNIT *uptr);
|
||||||
t_stat tto_reset (DEVICE *dptr);
|
t_stat tto_reset (DEVICE *dptr);
|
||||||
|
t_stat tti_set_ctrlc (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
t_stat clk_rd (int32 *data, int32 PA, int32 access);
|
t_stat clk_rd (int32 *data, int32 PA, int32 access);
|
||||||
t_stat clk_wr (int32 data, int32 PA, int32 access);
|
t_stat clk_wr (int32 data, int32 PA, int32 access);
|
||||||
t_stat clk_svc (UNIT *uptr);
|
t_stat clk_svc (UNIT *uptr);
|
||||||
t_stat clk_reset (DEVICE *dptr);
|
t_stat clk_reset (DEVICE *dptr);
|
||||||
|
t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
|
|
||||||
/* TTI data structures
|
/* TTI data structures
|
||||||
|
|
||||||
|
@ -110,6 +113,8 @@ REG tti_reg[] = {
|
||||||
MTAB tti_mod[] = {
|
MTAB tti_mod[] = {
|
||||||
{ UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode },
|
{ UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode },
|
||||||
{ UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode },
|
{ UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode },
|
||||||
|
{ MTAB_XTD|MTAB_VDV|MTAB_VUN, 0, NULL, "CTRL-C",
|
||||||
|
&tti_set_ctrlc, NULL, NULL },
|
||||||
{ MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL,
|
{ MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL,
|
||||||
NULL, &show_addr, NULL },
|
NULL, &show_addr, NULL },
|
||||||
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL,
|
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL,
|
||||||
|
@ -180,10 +185,16 @@ REG clk_reg[] = {
|
||||||
{ FLDATA (DONE, clk_csr, CSR_V_DONE) },
|
{ FLDATA (DONE, clk_csr, CSR_V_DONE) },
|
||||||
{ FLDATA (IE, clk_csr, CSR_V_IE) },
|
{ FLDATA (IE, clk_csr, CSR_V_IE) },
|
||||||
{ DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT },
|
{ DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT },
|
||||||
{ DRDATA (TPS, clk_tps, 8), REG_NZ + PV_LEFT },
|
{ DRDATA (TPS, clk_tps, 8), PV_LEFT + REG_HRO },
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
MTAB clk_mod[] = {
|
MTAB clk_mod[] = {
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 50, NULL, "50HZ",
|
||||||
|
&clk_set_freq, NULL, NULL },
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 60, NULL, "60HZ",
|
||||||
|
&clk_set_freq, NULL, NULL },
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 0, "FREQUENCY", NULL,
|
||||||
|
NULL, &clk_show_freq, NULL },
|
||||||
{ MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL,
|
{ MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL,
|
||||||
NULL, &show_addr, NULL },
|
NULL, &show_addr, NULL },
|
||||||
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL,
|
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL,
|
||||||
|
@ -254,6 +265,18 @@ CLR_INT (TTI);
|
||||||
sim_activate (&tti_unit, tti_unit.wait); /* activate unit */
|
sim_activate (&tti_unit, tti_unit.wait); /* activate unit */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set control-C */
|
||||||
|
|
||||||
|
t_stat tti_set_ctrlc (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
if (cptr) return SCPE_ARG;
|
||||||
|
uptr->buf = 003;
|
||||||
|
uptr->pos = uptr->pos + 1;
|
||||||
|
tti_csr = tti_csr | CSR_DONE;
|
||||||
|
if (tti_csr & CSR_IE) SET_INT (TTI);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* Terminal output address routines */
|
/* Terminal output address routines */
|
||||||
|
|
||||||
|
@ -365,3 +388,21 @@ tmr_poll = clk_unit.wait; /* set timer poll */
|
||||||
tmxr_poll = clk_unit.wait; /* set mux poll */
|
tmxr_poll = clk_unit.wait; /* set mux poll */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set frequency */
|
||||||
|
|
||||||
|
t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
if (cptr) return SCPE_ARG;
|
||||||
|
if ((val != 50) && (val != 60)) return SCPE_IERR;
|
||||||
|
clk_tps = val;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Show frequency */
|
||||||
|
|
||||||
|
t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
|
{
|
||||||
|
fprintf (st, (clk_tps == 50)? "50Hz": "60Hz");
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
201
PDP11/pdp11_tm.c
201
PDP11/pdp11_tm.c
|
@ -1,6 +1,6 @@
|
||||||
/* pdp11_tm.c: PDP-11 magnetic tape simulator
|
/* pdp11_tm.c: PDP-11 magnetic tape simulator
|
||||||
|
|
||||||
Copyright (c) 1993-2002, Robert M Supnik
|
Copyright (c) 1993-2003, Robert M Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
tm TM11/TU10 magtape
|
tm TM11/TU10 magtape
|
||||||
|
|
||||||
|
28-Feb-03 RMS Revised for magtape library, added logging
|
||||||
30-Oct-02 RMS Revised BOT handling, added error record handling
|
30-Oct-02 RMS Revised BOT handling, added error record handling
|
||||||
30-Sep-02 RMS Added variable address support to bootstrap
|
30-Sep-02 RMS Added variable address support to bootstrap
|
||||||
Added vector change/display support
|
Added vector change/display support
|
||||||
|
@ -72,14 +73,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pdp11_defs.h"
|
#include "pdp11_defs.h"
|
||||||
|
#include "sim_tape.h"
|
||||||
|
|
||||||
#define TM_NUMDR 8 /* #drives */
|
#define TM_NUMDR 8 /* #drives */
|
||||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
|
||||||
#define UNIT_V_PNU (UNIT_V_UF + 1) /* pos not updated */
|
|
||||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
|
||||||
#define UNIT_PNU (1 << UNIT_V_PNU)
|
|
||||||
#define USTAT u3 /* unit status */
|
#define USTAT u3 /* unit status */
|
||||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
|
||||||
|
|
||||||
/* Command - tm_cmd */
|
/* Command - tm_cmd */
|
||||||
|
|
||||||
|
@ -148,6 +145,8 @@
|
||||||
extern uint16 *M; /* memory */
|
extern uint16 *M; /* memory */
|
||||||
extern int32 int_req[IPL_HLVL];
|
extern int32 int_req[IPL_HLVL];
|
||||||
extern int32 int_vec[IPL_HLVL][32];
|
extern int32 int_vec[IPL_HLVL][32];
|
||||||
|
extern int32 cpu_log;
|
||||||
|
extern FILE *sim_log;
|
||||||
|
|
||||||
uint8 *tmxb = NULL; /* xfer buffer */
|
uint8 *tmxb = NULL; /* xfer buffer */
|
||||||
int32 tm_sta = 0; /* status register */
|
int32 tm_sta = 0; /* status register */
|
||||||
|
@ -170,8 +169,7 @@ t_stat tm_boot (int32 unitno, DEVICE *dptr);
|
||||||
void tm_go (UNIT *uptr);
|
void tm_go (UNIT *uptr);
|
||||||
int32 tm_updcsta (UNIT *uptr);
|
int32 tm_updcsta (UNIT *uptr);
|
||||||
void tm_set_done (void);
|
void tm_set_done (void);
|
||||||
t_bool tm_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
t_stat tm_map_err (UNIT *uptr, t_stat st);
|
||||||
t_bool tm_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
|
||||||
t_stat tm_vlock (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat tm_vlock (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
|
||||||
/* MT data structures
|
/* MT data structures
|
||||||
|
@ -216,8 +214,8 @@ REG tm_reg[] = {
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
MTAB tm_mod[] = {
|
MTAB tm_mod[] = {
|
||||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", &tm_vlock },
|
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", &tm_vlock },
|
||||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", &tm_vlock },
|
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", &tm_vlock },
|
||||||
{ MTAB_XTD|MTAB_VDV, 020, "ADDRESS", "ADDRESS",
|
{ MTAB_XTD|MTAB_VDV, 020, "ADDRESS", "ADDRESS",
|
||||||
&set_addr, &show_addr, NULL },
|
&set_addr, &show_addr, NULL },
|
||||||
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR",
|
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR",
|
||||||
|
@ -327,7 +325,7 @@ f = GET_FNC (tm_cmd); /* get function */
|
||||||
if (((uptr->flags & UNIT_ATT) == 0) || /* not attached? */
|
if (((uptr->flags & UNIT_ATT) == 0) || /* not attached? */
|
||||||
sim_is_active (uptr) || /* busy? */
|
sim_is_active (uptr) || /* busy? */
|
||||||
(((f == MTC_WRITE) || (f == MTC_WREOF) || (f == MTC_WREXT)) &&
|
(((f == MTC_WRITE) || (f == MTC_WREOF) || (f == MTC_WREXT)) &&
|
||||||
(uptr->flags & UNIT_WPRT))) { /* write locked? */
|
sim_tape_wrp (uptr))) { /* write locked? */
|
||||||
tm_sta = tm_sta | STA_ILL; /* illegal */
|
tm_sta = tm_sta | STA_ILL; /* illegal */
|
||||||
tm_set_done (); /* set done */
|
tm_set_done (); /* set done */
|
||||||
return; }
|
return; }
|
||||||
|
@ -353,19 +351,21 @@ return;
|
||||||
|
|
||||||
t_stat tm_svc (UNIT *uptr)
|
t_stat tm_svc (UNIT *uptr)
|
||||||
{
|
{
|
||||||
int32 f, t, err, pnu, u;
|
int32 f, t, u;
|
||||||
t_addr xma;
|
t_addr xma;
|
||||||
t_mtrlnt abc, tbc, cbc, ebc;
|
t_mtrlnt tbc, cbc;
|
||||||
static t_mtrlnt bceof = { MTR_TMK };
|
t_stat st, r = SCPE_OK;
|
||||||
|
|
||||||
u = uptr - tm_dev.units; /* get unit number */
|
u = uptr - tm_dev.units; /* get unit number */
|
||||||
pnu = MT_TST_PNU (uptr); /* get pos not upd */
|
f = GET_FNC (tm_cmd); /* get command */
|
||||||
MT_CLR_PNU (uptr); /* and clear */
|
xma = GET_EMA (tm_cmd) | tm_ca; /* get mem addr */
|
||||||
|
cbc = 0200000 - tm_bc; /* get bc */
|
||||||
|
|
||||||
if (uptr->USTAT & STA_REW) { /* rewind? */
|
if (uptr->USTAT & STA_REW) { /* rewind? */
|
||||||
uptr->pos = 0; /* update position */
|
sim_tape_rewind (uptr); /* update position */
|
||||||
if (uptr->flags & UNIT_ATT) /* still on line? */
|
if (uptr->flags & UNIT_ATT) /* still on line? */
|
||||||
uptr->USTAT = STA_ONL | STA_BOT |
|
uptr->USTAT = STA_ONL | STA_BOT |
|
||||||
((uptr->flags & UNIT_WPRT)? STA_WLK: 0);
|
(sim_tape_wrp (uptr)? STA_WLK: 0);
|
||||||
else uptr->USTAT = 0;
|
else uptr->USTAT = 0;
|
||||||
if (u == GET_UNIT (tm_cmd)) { /* selected? */
|
if (u == GET_UNIT (tm_cmd)) { /* selected? */
|
||||||
tm_set_done (); /* set done */
|
tm_set_done (); /* set done */
|
||||||
|
@ -379,38 +379,25 @@ if ((uptr->flags & UNIT_ATT) == 0) { /* if not attached */
|
||||||
tm_updcsta (uptr); /* update status */
|
tm_updcsta (uptr); /* update status */
|
||||||
return IORETURN (tm_stopioe, SCPE_UNATT); }
|
return IORETURN (tm_stopioe, SCPE_UNATT); }
|
||||||
|
|
||||||
f = GET_FNC (tm_cmd); /* get command */
|
if (DBG_LOG (LOG_TM)) fprintf (sim_log,
|
||||||
if (((f == MTC_WRITE) || (f == MTC_WREOF) || (f == MTC_WREXT)) &&
|
">>TM: op=%o, ma=%o, bc=%o, pos=%d\n", f, xma, cbc, uptr->pos);
|
||||||
(uptr->flags & UNIT_WPRT)) { /* write and locked? */
|
|
||||||
tm_sta = tm_sta | STA_ILL; /* illegal operation */
|
|
||||||
tm_set_done (); /* set done */
|
|
||||||
tm_updcsta (uptr); /* update status */
|
|
||||||
return SCPE_OK; }
|
|
||||||
|
|
||||||
err = 0;
|
|
||||||
xma = GET_EMA (tm_cmd) | tm_ca; /* get mem addr */
|
|
||||||
cbc = 0200000 - tm_bc; /* get bc */
|
|
||||||
switch (f) { /* case on function */
|
switch (f) { /* case on function */
|
||||||
|
|
||||||
/* Unit service, continued */
|
/* Unit service, continued */
|
||||||
|
|
||||||
case MTC_READ: /* read */
|
case MTC_READ: /* read */
|
||||||
if (tm_rdlntf (uptr, &tbc, &err)) break; /* read rec lnt, err? */
|
st = sim_tape_rdrecf (uptr, tmxb, &tbc, MT_MAXFR); /* read rec */
|
||||||
if (tbc > MT_MAXFR) return SCPE_MTRLNT; /* record too long? */
|
if (st == MTSE_RECE) tm_sta = tm_sta | STA_PAR; /* rec in error? */
|
||||||
|
else if (st != MTSE_OK) { /* other error? */
|
||||||
|
r = tm_map_err (uptr, st); /* map error */
|
||||||
|
break; }
|
||||||
if (tbc > cbc) tm_sta = tm_sta | STA_RLE; /* wrong size? */
|
if (tbc > cbc) tm_sta = tm_sta | STA_RLE; /* wrong size? */
|
||||||
if (tbc < cbc) cbc = tbc; /* use smaller */
|
if (tbc < cbc) cbc = tbc; /* use smaller */
|
||||||
abc = fxread (tmxb, sizeof (int8), cbc, uptr->fileref);
|
|
||||||
if (err = ferror (uptr->fileref)) { /* error? */
|
|
||||||
MT_SET_PNU (uptr); /* pos not upd */
|
|
||||||
break; }
|
|
||||||
for ( ; abc < cbc; abc++) tmxb[abc] = 0; /* fill with 0's */
|
|
||||||
if (t = Map_WriteB (xma, cbc, tmxb, MAP)) { /* copy buf to mem */
|
if (t = Map_WriteB (xma, cbc, tmxb, MAP)) { /* copy buf to mem */
|
||||||
tm_sta = tm_sta | STA_NXM; /* NXM, set err */
|
tm_sta = tm_sta | STA_NXM; /* NXM, set err */
|
||||||
cbc = cbc - t; } /* adj byte cnt */
|
cbc = cbc - t; } /* adj byte cnt */
|
||||||
xma = (xma + cbc) & 0777777; /* inc bus addr */
|
xma = (xma + cbc) & 0777777; /* inc bus addr */
|
||||||
tm_bc = (tm_bc + cbc) & 0177777; /* inc byte cnt */
|
tm_bc = (tm_bc + cbc) & 0177777; /* inc byte cnt */
|
||||||
uptr->pos = uptr->pos + ((tbc + 1) & ~1) + /* upd position */
|
|
||||||
(2 * sizeof (t_mtrlnt));
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MTC_WRITE: /* write */
|
case MTC_WRITE: /* write */
|
||||||
|
@ -419,58 +406,48 @@ case MTC_WREXT: /* write ext gap */
|
||||||
tm_sta = tm_sta | STA_NXM; /* NXM, set err */
|
tm_sta = tm_sta | STA_NXM; /* NXM, set err */
|
||||||
cbc = cbc - t; /* adj byte cnt */
|
cbc = cbc - t; /* adj byte cnt */
|
||||||
if (cbc == 0) break; } /* no xfr? done */
|
if (cbc == 0) break; } /* no xfr? done */
|
||||||
ebc = (cbc + 1) & ~1; /* force even */
|
if (st = sim_tape_wrrecf (uptr, tmxb, cbc)) /* write rec, err? */
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
r = tm_map_err (uptr, st); /* map error */
|
||||||
fxwrite (&cbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
|
||||||
fxwrite (tmxb, sizeof (int8), ebc, uptr->fileref);
|
|
||||||
fxwrite (&cbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
|
||||||
if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr); /* error? */
|
|
||||||
else {
|
else {
|
||||||
xma = (xma + cbc) & 0777777; /* inc bus addr */
|
xma = (xma + cbc) & 0777777; /* inc bus addr */
|
||||||
tm_bc = (tm_bc + cbc) & 0177777; /* inc byte cnt */
|
tm_bc = (tm_bc + cbc) & 0177777; } /* inc byte cnt */
|
||||||
uptr->pos = uptr->pos + ebc + /* upd pos */
|
|
||||||
(2 * sizeof (t_mtrlnt)); }
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Unit service, continued */
|
/* Unit service, continued */
|
||||||
|
|
||||||
case MTC_WREOF:
|
case MTC_WREOF: /* write eof */
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
|
||||||
fxwrite (&bceof, sizeof (t_mtrlnt), 1, uptr->fileref);
|
r = tm_map_err (uptr, st); /* map error */
|
||||||
if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr); /* error? */
|
|
||||||
else uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* update position */
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MTC_SPACEF: /* space forward */
|
case MTC_SPACEF: /* space forward */
|
||||||
do {
|
do {
|
||||||
tm_bc = (tm_bc + 1) & 0177777; /* incr wc */
|
tm_bc = (tm_bc + 1) & 0177777; /* incr wc */
|
||||||
if (tm_rdlntf (uptr, &tbc, &err)) break; /* read rec lnt, err? */
|
if (st = sim_tape_sprecf (uptr, &tbc)) { /* spc rec fwd, err? */
|
||||||
uptr->pos = uptr->pos + ((tbc + 1) & ~1) +
|
r = tm_map_err (uptr, st); /* map error */
|
||||||
(2 * sizeof (t_mtrlnt)); }
|
break; }
|
||||||
|
}
|
||||||
while (tm_bc != 0);
|
while (tm_bc != 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MTC_SPACER: /* space reverse */
|
case MTC_SPACER: /* space reverse */
|
||||||
do {
|
do {
|
||||||
tm_bc = (tm_bc + 1) & 0177777; /* incr wc */
|
tm_bc = (tm_bc + 1) & 0177777; /* incr wc */
|
||||||
if (pnu) pnu = 0; /* pos not upd? */
|
if (st = sim_tape_sprecr (uptr, &tbc)) { /* spc rec rev, err? */
|
||||||
else {
|
r = tm_map_err (uptr, st); /* map error */
|
||||||
if (tm_rdlntr (uptr, &tbc, &err)) break;
|
break; }
|
||||||
uptr->pos = uptr->pos - ((tbc + 1) & ~1) -
|
}
|
||||||
(2 * sizeof (t_mtrlnt)); } }
|
|
||||||
while (tm_bc != 0);
|
while (tm_bc != 0);
|
||||||
break; } /* end case */
|
break; } /* end case */
|
||||||
|
|
||||||
if (err != 0) tm_sta = tm_sta | STA_PAR; /* flag error */
|
|
||||||
tm_cmd = (tm_cmd & ~MTC_EMA) | ((xma >> (16 - MTC_V_EMA)) & MTC_EMA);
|
tm_cmd = (tm_cmd & ~MTC_EMA) | ((xma >> (16 - MTC_V_EMA)) & MTC_EMA);
|
||||||
tm_ca = xma & 0177777; /* update mem addr */
|
tm_ca = xma & 0177777; /* update mem addr */
|
||||||
tm_set_done (); /* set done */
|
tm_set_done (); /* set done */
|
||||||
tm_updcsta (uptr); /* update status */
|
tm_updcsta (uptr); /* update status */
|
||||||
if (err != 0) { /* I/O error */
|
if (DBG_LOG (LOG_TM)) fprintf (sim_log,
|
||||||
perror ("MT I/O error");
|
">>TM: sta=%o, ma=%o, wc=%o, pos=%d\n",
|
||||||
clearerr (uptr->fileref);
|
tm_sta, tm_ca, tm_bc, uptr->pos);
|
||||||
if (tm_stopioe) return SCPE_IOERR; }
|
return r;
|
||||||
return SCPE_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update controller status */
|
/* Update controller status */
|
||||||
|
@ -495,55 +472,39 @@ if (tm_cmd & MTC_IE) SET_INT (TM);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read record length forward - return T if error, EOM, or EOF */
|
/* Map tape error status */
|
||||||
|
|
||||||
t_bool tm_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
t_stat tm_map_err (UNIT *uptr, t_stat st)
|
||||||
{
|
{
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set tape pos */
|
switch (st) {
|
||||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref); /* read rec lnt */
|
case MTSE_FMT: /* illegal fmt */
|
||||||
if (*err = ferror (uptr->fileref)) { /* error? */
|
case MTSE_UNATT: /* not attached */
|
||||||
tm_sta = tm_sta | STA_PAR; /* parity error */
|
tm_sta = tm_sta | STA_ILL;
|
||||||
MT_SET_PNU (uptr); /* pos not upd */
|
case MTSE_OK: /* no error */
|
||||||
return TRUE; }
|
return SCPE_IERR;
|
||||||
if (feof (uptr->fileref) || (*tbc == MTR_EOM)) { /* eof or eom? */
|
case MTSE_TMK: /* tape mark */
|
||||||
tm_sta = tm_sta | STA_BAD; /* bad tape */
|
|
||||||
MT_SET_PNU (uptr); /* pos not upd */
|
|
||||||
return TRUE; }
|
|
||||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
|
||||||
uptr->USTAT = uptr->USTAT | STA_EOF; /* end of file */
|
uptr->USTAT = uptr->USTAT | STA_EOF; /* end of file */
|
||||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* spc over tmk */
|
break;
|
||||||
return TRUE; }
|
case MTSE_IOERR: /* IO error */
|
||||||
if (MTRF (*tbc)) tm_sta = tm_sta | STA_PAR; /* record in error? */
|
tm_sta = tm_sta | STA_PAR; /* parity error */
|
||||||
*tbc = MTRL (*tbc); /* clear error flag */
|
if (tm_stopioe) return SCPE_IOERR;
|
||||||
return FALSE;
|
break;
|
||||||
}
|
case MTSE_INVRL: /* invalid rec lnt */
|
||||||
|
tm_sta = tm_sta | STA_PAR; /* parity error */
|
||||||
/* Read record length reverse - return T if error, EOM, or EOF */
|
return SCPE_MTRLNT;
|
||||||
|
case MTSE_RECE: /* record in error */
|
||||||
t_bool tm_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
tm_sta = tm_sta | STA_PAR; /* parity error */
|
||||||
{
|
break;
|
||||||
if (uptr->pos < sizeof (t_mtrlnt)) { /* at BOT? */
|
case MTSE_EOM: /* end of medium */
|
||||||
|
tm_sta = tm_sta | STA_BAD; /* bad tape */
|
||||||
|
break;
|
||||||
|
case MTSE_BOT: /* reverse into BOT */
|
||||||
uptr->USTAT = uptr->USTAT | STA_BOT; /* set status */
|
uptr->USTAT = uptr->USTAT | STA_BOT; /* set status */
|
||||||
return TRUE; } /* error */
|
break;
|
||||||
fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET);
|
case MTSE_WRP: /* write protect */
|
||||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
tm_sta = tm_sta | STA_ILL; /* illegal operation */
|
||||||
if (*err = ferror (uptr->fileref)) { /* error? */
|
break; }
|
||||||
tm_sta = tm_sta | STA_PAR; /* parity error */
|
return SCPE_OK;
|
||||||
return TRUE; }
|
|
||||||
if (feof (uptr->fileref)) { /* eof? */
|
|
||||||
tm_sta = tm_sta | STA_BAD; /* bad tape */
|
|
||||||
return TRUE; }
|
|
||||||
if (*tbc == MTR_EOM) { /* eom? */
|
|
||||||
tm_sta = tm_sta | STA_BAD; /* bad tape */
|
|
||||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over eom */
|
|
||||||
return TRUE; }
|
|
||||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
|
||||||
uptr->USTAT = uptr->USTAT | STA_EOF; /* end of file */
|
|
||||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over tmk */
|
|
||||||
return TRUE; }
|
|
||||||
if (MTRF (*tbc)) tm_sta = tm_sta | STA_PAR; /* record in error? */
|
|
||||||
*tbc = MTRL (*tbc); /* clear error flag */
|
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset routine */
|
/* Reset routine */
|
||||||
|
@ -558,11 +519,11 @@ tm_bc = tm_ca = tm_db = tm_sta = tm_rdl = 0;
|
||||||
CLR_INT (TM); /* clear interrupt */
|
CLR_INT (TM); /* clear interrupt */
|
||||||
for (u = 0; u < TM_NUMDR; u++) { /* loop thru units */
|
for (u = 0; u < TM_NUMDR; u++) { /* loop thru units */
|
||||||
uptr = tm_dev.units + u;
|
uptr = tm_dev.units + u;
|
||||||
MT_CLR_PNU (uptr); /* clear pos flag */
|
sim_tape_reset (uptr); /* reset tape */
|
||||||
sim_cancel (uptr); /* cancel activity */
|
sim_cancel (uptr); /* cancel activity */
|
||||||
if (uptr->flags & UNIT_ATT) uptr->USTAT = STA_ONL |
|
if (uptr->flags & UNIT_ATT) uptr->USTAT = STA_ONL |
|
||||||
((uptr->pos)? 0: STA_BOT) |
|
(sim_tape_bot (uptr)? STA_BOT: 0) |
|
||||||
((uptr->flags & UNIT_WPRT)? STA_WLK: 0);
|
(sim_tape_wrp (uptr)? STA_WLK: 0);
|
||||||
else uptr->USTAT = 0; }
|
else uptr->USTAT = 0; }
|
||||||
if (tmxb == NULL) tmxb = calloc (MT_MAXFR, sizeof (unsigned int8));
|
if (tmxb == NULL) tmxb = calloc (MT_MAXFR, sizeof (unsigned int8));
|
||||||
if (tmxb == NULL) return SCPE_MEM;
|
if (tmxb == NULL) return SCPE_MEM;
|
||||||
|
@ -576,10 +537,9 @@ t_stat tm_attach (UNIT *uptr, char *cptr)
|
||||||
t_stat r;
|
t_stat r;
|
||||||
int32 u = uptr - tm_dev.units;
|
int32 u = uptr - tm_dev.units;
|
||||||
|
|
||||||
r = attach_unit (uptr, cptr);
|
r = sim_tape_attach (uptr, cptr);
|
||||||
if (r != SCPE_OK) return r;
|
if (r != SCPE_OK) return r;
|
||||||
MT_CLR_PNU (uptr);
|
uptr->USTAT = STA_ONL | STA_BOT | (sim_tape_wrp (uptr)? STA_WLK: 0);
|
||||||
uptr->USTAT = STA_ONL | STA_BOT | ((uptr->flags & UNIT_WPRT)? STA_WLK: 0);
|
|
||||||
if (u == GET_UNIT (tm_cmd)) tm_updcsta (uptr);
|
if (u == GET_UNIT (tm_cmd)) tm_updcsta (uptr);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -590,10 +550,9 @@ t_stat tm_detach (UNIT* uptr)
|
||||||
{
|
{
|
||||||
int32 u = uptr - tm_dev.units;
|
int32 u = uptr - tm_dev.units;
|
||||||
|
|
||||||
MT_CLR_PNU (uptr);
|
|
||||||
if (!sim_is_active (uptr)) uptr->USTAT = 0;
|
if (!sim_is_active (uptr)) uptr->USTAT = 0;
|
||||||
if (u == GET_UNIT (tm_cmd)) tm_updcsta (uptr);
|
if (u == GET_UNIT (tm_cmd)) tm_updcsta (uptr);
|
||||||
return detach_unit (uptr);
|
return sim_tape_detach (uptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write lock/enable routine */
|
/* Write lock/enable routine */
|
||||||
|
@ -603,7 +562,7 @@ t_stat tm_vlock (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
int32 u = uptr - tm_dev.units;
|
int32 u = uptr - tm_dev.units;
|
||||||
|
|
||||||
if ((uptr->flags & UNIT_ATT) &&
|
if ((uptr->flags & UNIT_ATT) &&
|
||||||
(val || (uptr->flags & UNIT_RO)))
|
(val || sim_tape_wrp (uptr)))
|
||||||
uptr->USTAT = uptr->USTAT | STA_WLK;
|
uptr->USTAT = uptr->USTAT | STA_WLK;
|
||||||
else uptr->USTAT = uptr->USTAT & ~STA_WLK;
|
else uptr->USTAT = uptr->USTAT & ~STA_WLK;
|
||||||
if (u == GET_UNIT (tm_cmd)) tm_updcsta (uptr);
|
if (u == GET_UNIT (tm_cmd)) tm_updcsta (uptr);
|
||||||
|
@ -680,7 +639,7 @@ int32 i;
|
||||||
extern int32 saved_PC;
|
extern int32 saved_PC;
|
||||||
extern int32 sim_switches;
|
extern int32 sim_switches;
|
||||||
|
|
||||||
tm_unit[unitno].pos = 0;
|
sim_tape_rewind (&tm_unit[unitno]);
|
||||||
if (sim_switches & SWMASK ('O')) {
|
if (sim_switches & SWMASK ('O')) {
|
||||||
for (i = 0; i < BOOT1_LEN; i++)
|
for (i = 0; i < BOOT1_LEN; i++)
|
||||||
M[(BOOT_START >> 1) + i] = boot1_rom[i]; }
|
M[(BOOT_START >> 1) + i] = boot1_rom[i]; }
|
||||||
|
|
331
PDP11/pdp11_tq.c
331
PDP11/pdp11_tq.c
|
@ -25,6 +25,10 @@
|
||||||
|
|
||||||
tq TQK50 tape controller
|
tq TQK50 tape controller
|
||||||
|
|
||||||
|
28-Feb-03 RMS Added variable controller, user-defined drive support
|
||||||
|
26-Feb-03 RMS Fixed bug in vector calculation for VAXen
|
||||||
|
22-Feb-03 RMS Fixed ordering bug in queue process
|
||||||
|
Fixed flags table to allow MD_CSE everywhere
|
||||||
09-Jan-03 RMS Fixed bug in transfer end packet status
|
09-Jan-03 RMS Fixed bug in transfer end packet status
|
||||||
17-Oct-02 RMS Fixed bug in read reverse (found by Hans Pufal)
|
17-Oct-02 RMS Fixed bug in read reverse (found by Hans Pufal)
|
||||||
*/
|
*/
|
||||||
|
@ -43,6 +47,7 @@ extern int32 cpu_18b, cpu_ubm;
|
||||||
|
|
||||||
#include "pdp11_uqssp.h"
|
#include "pdp11_uqssp.h"
|
||||||
#include "pdp11_mscp.h"
|
#include "pdp11_mscp.h"
|
||||||
|
#include "sim_tape.h"
|
||||||
|
|
||||||
#define UF_MSK (UF_SCH|UF_VSS|UF_CMR|UF_CMW) /* settable flags */
|
#define UF_MSK (UF_SCH|UF_VSS|UF_CMR|UF_CMW) /* settable flags */
|
||||||
|
|
||||||
|
@ -60,14 +65,12 @@ extern int32 cpu_18b, cpu_ubm;
|
||||||
#define TQ_NUMDR 4 /* # drives */
|
#define TQ_NUMDR 4 /* # drives */
|
||||||
#define TQ_MAXFR (1 << 16) /* max xfer */
|
#define TQ_MAXFR (1 << 16) /* max xfer */
|
||||||
|
|
||||||
#define UNIT_V_ONL (UNIT_V_UF + 0) /* online */
|
#define UNIT_V_ONL (MTUF_V_UF + 0) /* online */
|
||||||
#define UNIT_V_WLK (UNIT_V_UF + 1) /* hwre write lock */
|
#define UNIT_V_ATP (MTUF_V_UF + 1) /* attn pending */
|
||||||
#define UNIT_V_ATP (UNIT_V_UF + 2) /* attn pending */
|
#define UNIT_V_SXC (MTUF_V_UF + 2) /* serious exc */
|
||||||
#define UNIT_V_SXC (UNIT_V_UF + 3) /* serious exc */
|
#define UNIT_V_POL (MTUF_V_UF + 3) /* position lost */
|
||||||
#define UNIT_V_POL (UNIT_V_UF + 4) /* position lost */
|
#define UNIT_V_TMK (MTUF_V_UF + 4) /* tape mark seen */
|
||||||
#define UNIT_V_TMK (UNIT_V_UF + 5) /* tape mark seen */
|
|
||||||
#define UNIT_ONL (1 << UNIT_V_ONL)
|
#define UNIT_ONL (1 << UNIT_V_ONL)
|
||||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
|
||||||
#define UNIT_ATP (1 << UNIT_V_ATP)
|
#define UNIT_ATP (1 << UNIT_V_ATP)
|
||||||
#define UNIT_SXC (1 << UNIT_V_SXC)
|
#define UNIT_SXC (1 << UNIT_V_SXC)
|
||||||
#define UNIT_POL (1 << UNIT_V_POL)
|
#define UNIT_POL (1 << UNIT_V_POL)
|
||||||
|
@ -76,8 +79,7 @@ extern int32 cpu_18b, cpu_ubm;
|
||||||
#define pktq u4 /* packet queue */
|
#define pktq u4 /* packet queue */
|
||||||
#define uf buf /* settable unit flags */
|
#define uf buf /* settable unit flags */
|
||||||
#define objp wait /* object position */
|
#define objp wait /* object position */
|
||||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write prot */
|
#define TQ_WPH(u) (sim_tape_wrp (u))
|
||||||
#define TQ_WPH(u) ((u->flags & UNIT_WPRT)? UF_WPH: 0)
|
|
||||||
|
|
||||||
#define CST_S1 0 /* init stage 1 */
|
#define CST_S1 0 /* init stage 1 */
|
||||||
#define CST_S1_WR 1 /* stage 1 wrap */
|
#define CST_S1_WR 1 /* stage 1 wrap */
|
||||||
|
@ -153,12 +155,25 @@ struct tqpkt {
|
||||||
#define TQ8_CAP (180 * (1 << 20)) /* capacity */
|
#define TQ8_CAP (180 * (1 << 20)) /* capacity */
|
||||||
#define TQ8_FMT (TF_9TK|TF_9TK_GRP) /* menu */
|
#define TQ8_FMT (TF_9TK|TF_9TK_GRP) /* menu */
|
||||||
|
|
||||||
|
#define TQU_TYPE 3 /* TKuser defined */
|
||||||
|
#define TQU_UQPM 3 /* UQ port ID */
|
||||||
|
#define TQU_CMOD 9 /* ctrl ID */
|
||||||
|
#define TQU_UMOD 3 /* unit ID */
|
||||||
|
#define TQU_MED 0x6D68B032 /* media ID */
|
||||||
|
#define TQU_CREV ((1 << 8) | 5) /* ctrl revs */
|
||||||
|
#define TQU_FREV 0 /* formatter revs */
|
||||||
|
#define TQU_UREV 0 /* unit revs */
|
||||||
|
#define TQU_CAP (94 * (1 << 20)) /* capacity */
|
||||||
|
#define TQU_FMT (TF_CTP|TF_CTP_LO) /* menu */
|
||||||
|
#define TQU_MINC 30 /* min cap MB */
|
||||||
|
#define TQU_MAXC 2000 /* max cap MB */
|
||||||
|
|
||||||
#define TQ_DRV(d) \
|
#define TQ_DRV(d) \
|
||||||
d##_UQPM, \
|
d##_UQPM, \
|
||||||
d##_CMOD, d##_MED, d##_FMT, d##_CAP, \
|
d##_CMOD, d##_MED, d##_FMT, d##_CAP, \
|
||||||
d##_UMOD, d##_CREV, d##_FREV, d##_UREV
|
d##_UMOD, d##_CREV, d##_FREV, d##_UREV
|
||||||
|
|
||||||
#define TEST_EOT(u) (uptr->pos > drv_tab[tq_typ].cap)
|
#define TEST_EOT(u) (sim_tape_eot (u, drv_tab[tq_typ].cap))
|
||||||
|
|
||||||
struct drvtyp {
|
struct drvtyp {
|
||||||
uint32 uqpm; /* UQ port model */
|
uint32 uqpm; /* UQ port model */
|
||||||
|
@ -170,12 +185,14 @@ struct drvtyp {
|
||||||
uint32 cver;
|
uint32 cver;
|
||||||
uint32 fver;
|
uint32 fver;
|
||||||
uint32 uver;
|
uint32 uver;
|
||||||
|
char *name;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct drvtyp drv_tab[] = {
|
static struct drvtyp drv_tab[] = {
|
||||||
{ TQ_DRV (TQ5) },
|
{ TQ_DRV (TQ5), "TK50" },
|
||||||
{ TQ_DRV (TQ7) },
|
{ TQ_DRV (TQ7), "TK70" },
|
||||||
{ TQ_DRV (TQ8) }
|
{ TQ_DRV (TQ8), "TU81" },
|
||||||
|
{ TQ_DRV (TQU), "TKUSER" },
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Data */
|
/* Data */
|
||||||
|
@ -208,16 +225,16 @@ int32 tq_itime = 200; /* init time, except */
|
||||||
int32 tq_itime4 = 10; /* stage 4 */
|
int32 tq_itime4 = 10; /* stage 4 */
|
||||||
int32 tq_qtime = 200; /* queue time */
|
int32 tq_qtime = 200; /* queue time */
|
||||||
int32 tq_xtime = 500; /* transfer time */
|
int32 tq_xtime = 500; /* transfer time */
|
||||||
int32 tq_typ = 0; /* device type */
|
int32 tq_typ = TQ5_TYPE; /* device type */
|
||||||
|
|
||||||
/* Command table - legal modifiers (low 16b) and flags (high 16b) */
|
/* Command table - legal modifiers (low 16b) and flags (high 16b) */
|
||||||
|
|
||||||
static uint32 tq_cmf[64] = {
|
static uint32 tq_cmf[64] = {
|
||||||
0, /* 0 */
|
0, /* 0 */
|
||||||
CMF_IMM, /* abort */
|
CMF_IMM, /* abort */
|
||||||
CMF_IMM, /* get cmd status */
|
CMF_IMM|MD_CSE, /* get cmd status */
|
||||||
CMF_IMM|MD_NXU, /* get unit status */
|
CMF_IMM|MD_CSE|MD_NXU, /* get unit status */
|
||||||
CMF_IMM, /* set ctrl char */
|
CMF_IMM|MD_CSE, /* set ctrl char */
|
||||||
0, 0, 0, /* 5-7 */
|
0, 0, 0, /* 5-7 */
|
||||||
CMF_SEQ|MD_ACL|MD_CDL|MD_CSE|MD_EXA|MD_UNL, /* available */
|
CMF_SEQ|MD_ACL|MD_CDL|MD_CSE|MD_EXA|MD_UNL, /* available */
|
||||||
CMF_SEQ|MD_CDL|MD_CSE|MD_SWP|MD_EXA, /* online */
|
CMF_SEQ|MD_CDL|MD_CSE|MD_SWP|MD_EXA, /* online */
|
||||||
|
@ -265,6 +282,8 @@ t_stat tq_set_wlk (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
t_stat tq_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat tq_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
t_stat tq_show_ctrl (FILE *st, UNIT *uptr, int32 val, void *desc);
|
t_stat tq_show_ctrl (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
t_stat tq_show_unitq (FILE *st, UNIT *uptr, int32 val, void *desc);
|
t_stat tq_show_unitq (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
|
t_stat tq_set_type (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat tq_show_type (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
|
|
||||||
t_bool tq_step4 (void);
|
t_bool tq_step4 (void);
|
||||||
t_bool tq_mscp (int32 pkt, t_bool q);
|
t_bool tq_mscp (int32 pkt, t_bool q);
|
||||||
|
@ -284,11 +303,10 @@ t_bool tq_plf (uint32 err);
|
||||||
t_bool tq_dte (UNIT *uptr, uint32 err);
|
t_bool tq_dte (UNIT *uptr, uint32 err);
|
||||||
t_bool tq_hbe (UNIT *uptr, uint32 ba);
|
t_bool tq_hbe (UNIT *uptr, uint32 ba);
|
||||||
t_bool tq_una (UNIT *uptr);
|
t_bool tq_una (UNIT *uptr);
|
||||||
uint32 tq_rdlntf (UNIT *uptr, t_mtrlnt *tbc);
|
uint32 tq_map_status (UNIT *uptr, t_stat st);
|
||||||
uint32 tq_spacef (UNIT *uptr, uint32 cnt, uint32 *skipped, t_bool qrec);
|
uint32 tq_spacef (UNIT *uptr, uint32 cnt, uint32 *skipped, t_bool qrec);
|
||||||
uint32 tq_skipff (UNIT *uptr, uint32 cnt, uint32 *skipped);
|
uint32 tq_skipff (UNIT *uptr, uint32 cnt, uint32 *skipped);
|
||||||
uint32 tq_rdbuff (UNIT *uptr, t_mtrlnt *tbc);
|
uint32 tq_rdbuff (UNIT *uptr, t_mtrlnt *tbc);
|
||||||
uint32 tq_rdlntr (UNIT *uptr, t_mtrlnt *tbc);
|
|
||||||
uint32 tq_spacer (UNIT *uptr, uint32 cnt, uint32 *skipped, t_bool qrec);
|
uint32 tq_spacer (UNIT *uptr, uint32 cnt, uint32 *skipped, t_bool qrec);
|
||||||
uint32 tq_skipfr (UNIT *uptr, uint32 cnt, uint32 *skipped);
|
uint32 tq_skipfr (UNIT *uptr, uint32 cnt, uint32 *skipped);
|
||||||
uint32 tq_rdbufr (UNIT *uptr, t_mtrlnt *tbc);
|
uint32 tq_rdbufr (UNIT *uptr, t_mtrlnt *tbc);
|
||||||
|
@ -366,14 +384,25 @@ REG tq_reg[] = {
|
||||||
{ DRDATA (QTIME, tq_qtime, 24), PV_LEFT + REG_NZ },
|
{ DRDATA (QTIME, tq_qtime, 24), PV_LEFT + REG_NZ },
|
||||||
{ DRDATA (XTIME, tq_xtime, 24), PV_LEFT + REG_NZ },
|
{ DRDATA (XTIME, tq_xtime, 24), PV_LEFT + REG_NZ },
|
||||||
{ BRDATA (PKTS, tq_pkt, TQ_RDX, 16, TQ_NPKTS * (TQ_PKT_SIZE_W + 1)) },
|
{ BRDATA (PKTS, tq_pkt, TQ_RDX, 16, TQ_NPKTS * (TQ_PKT_SIZE_W + 1)) },
|
||||||
{ FLDATA (DEVTYPE, tq_typ, 0), REG_HRO },
|
{ DRDATA (DEVTYPE, tq_typ, 2), REG_HRO },
|
||||||
|
{ DRDATA (DEVCAP, drv_tab[TQU_TYPE].cap, 31), REG_HRO },
|
||||||
{ GRDATA (DEVADDR, tq_dib.ba, TQ_RDX, 32, 0), REG_HRO },
|
{ GRDATA (DEVADDR, tq_dib.ba, TQ_RDX, 32, 0), REG_HRO },
|
||||||
{ GRDATA (DEVVEC, tq_dib.vec, TQ_RDX, 16, 0), REG_HRO },
|
{ GRDATA (DEVVEC, tq_dib.vec, TQ_RDX, 16, 0), REG_HRO },
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
MTAB tq_mod[] = {
|
MTAB tq_mod[] = {
|
||||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
|
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
|
||||||
|
{ MTAB_XTD | MTAB_VDV, TQ5_TYPE, NULL, "TK50",
|
||||||
|
&tq_set_type, NULL, NULL },
|
||||||
|
{ MTAB_XTD | MTAB_VDV, TQ7_TYPE, NULL, "TK70",
|
||||||
|
&tq_set_type, NULL, NULL },
|
||||||
|
{ MTAB_XTD | MTAB_VDV, TQ8_TYPE, NULL, "TU81",
|
||||||
|
&tq_set_type, NULL, NULL },
|
||||||
|
{ MTAB_XTD | MTAB_VDV, TQU_TYPE, NULL, "TKUSER",
|
||||||
|
&tq_set_type, NULL, NULL },
|
||||||
|
{ MTAB_XTD | MTAB_VDV, 0, "TYPE", NULL,
|
||||||
|
NULL, &tq_show_type, NULL },
|
||||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, TQ_SH_RI, "RINGS", NULL,
|
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, TQ_SH_RI, "RINGS", NULL,
|
||||||
NULL, &tq_show_ctrl, NULL },
|
NULL, &tq_show_ctrl, NULL },
|
||||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, TQ_SH_FR, "FREEQ", NULL,
|
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, TQ_SH_FR, "FREEQ", NULL,
|
||||||
|
@ -431,7 +460,8 @@ t_stat tq_wr (int32 data, int32 PA, int32 access)
|
||||||
switch ((PA >> 1) & 01) { /* decode PA<1> */
|
switch ((PA >> 1) & 01) { /* decode PA<1> */
|
||||||
case 0: /* IP */
|
case 0: /* IP */
|
||||||
tq_reset (&tq_dev); /* init device */
|
tq_reset (&tq_dev); /* init device */
|
||||||
if (DBG_LOG (LOG_TQ)) fprintf (sim_log, ">>TQ: initialization started\n");
|
if (DBG_LOG (LOG_TQ)) fprintf (sim_log,
|
||||||
|
">>TQ: initialization started, time=%.0f\n", sim_gtime ());
|
||||||
break;
|
break;
|
||||||
case 1: /* SA */
|
case 1: /* SA */
|
||||||
tq_saw = data;
|
tq_saw = data;
|
||||||
|
@ -476,9 +506,8 @@ return OK;
|
||||||
queues, response queue) require servicing. Also invoked during
|
queues, response queue) require servicing. Also invoked during
|
||||||
initialization to provide some delay to the next step.
|
initialization to provide some delay to the next step.
|
||||||
|
|
||||||
Process at most one item off the host queue
|
Process at most one item off each unit queue
|
||||||
If the host queue is empty, process at most one item off
|
If the unit queues were empty, process at most one item off the host queue
|
||||||
each unit queue
|
|
||||||
Process at most one item off the response queue
|
Process at most one item off the response queue
|
||||||
|
|
||||||
If all queues are idle, terminate thread
|
If all queues are idle, terminate thread
|
||||||
|
@ -499,7 +528,8 @@ if (tq_csta < CST_UP) { /* still init? */
|
||||||
tq_csta = CST_S1_WR; } /* endless loop */
|
tq_csta = CST_S1_WR; } /* endless loop */
|
||||||
else {
|
else {
|
||||||
tq_s1dat = tq_saw; /* save data */
|
tq_s1dat = tq_saw; /* save data */
|
||||||
tq_dib.vec = VEC_Q + ((tq_s1dat & SA_S1H_VEC) << 2);
|
tq_dib.vec = (tq_s1dat & SA_S1H_VEC) << 2; /* get vector */
|
||||||
|
if (tq_dib.vec) tq_dib.vec = tq_dib.vec + VEC_Q; /* if nz, bias */
|
||||||
tq_sa = SA_S2 | SA_S2C_PT | SA_S2C_EC (tq_s1dat);
|
tq_sa = SA_S2 | SA_S2C_PT | SA_S2C_EC (tq_s1dat);
|
||||||
tq_csta = CST_S2; /* now in step 2 */
|
tq_csta = CST_S2; /* now in step 2 */
|
||||||
tq_init_int (); } /* intr if req */
|
tq_init_int (); } /* intr if req */
|
||||||
|
@ -538,7 +568,12 @@ if (tq_csta < CST_UP) { /* still init? */
|
||||||
break; } /* end switch */
|
break; } /* end switch */
|
||||||
return SCPE_OK; } /* end if */
|
return SCPE_OK; } /* end if */
|
||||||
|
|
||||||
if (tq_pip) { /* polling? */
|
for (i = 0; i < TQ_NUMDR; i++) { /* chk unit q's */
|
||||||
|
nuptr = tq_dev.units + i; /* ptr to unit */
|
||||||
|
if (nuptr->cpkt || (nuptr->pktq == 0)) continue;
|
||||||
|
pkt = tq_deqh (&nuptr->pktq); /* get top of q */
|
||||||
|
if (!tq_mscp (pkt, FALSE)) return SCPE_OK; } /* process */
|
||||||
|
if ((pkt == 0) && tq_pip) { /* polling? */
|
||||||
if (!tq_getpkt (&pkt)) return SCPE_OK; /* get host pkt */
|
if (!tq_getpkt (&pkt)) return SCPE_OK; /* get host pkt */
|
||||||
if (pkt) { /* got one? */
|
if (pkt) { /* got one? */
|
||||||
if (DBG_LOG (LOG_TQ)) {
|
if (DBG_LOG (LOG_TQ)) {
|
||||||
|
@ -563,13 +598,6 @@ if (tq_pip) { /* polling? */
|
||||||
} /* end if pkt */
|
} /* end if pkt */
|
||||||
else tq_pip = 0; /* discontinue poll */
|
else tq_pip = 0; /* discontinue poll */
|
||||||
} /* end if pip */
|
} /* end if pip */
|
||||||
if (!tq_pip) { /* not polling? */
|
|
||||||
for (i = 0; i < TQ_NUMDR; i++) { /* chk unit q's */
|
|
||||||
nuptr = tq_dev.units + i; /* ptr to unit */
|
|
||||||
if (nuptr->cpkt || (nuptr->pktq == 0)) continue;
|
|
||||||
pkt = tq_deqh (&nuptr->pktq); /* get top of q */
|
|
||||||
if (!tq_mscp (pkt, FALSE)) return SCPE_OK; } /* process */
|
|
||||||
} /* end if !pip */
|
|
||||||
if (tq_rspq) { /* resp q? */
|
if (tq_rspq) { /* resp q? */
|
||||||
pkt = tq_deqh (&tq_rspq); /* get top of q */
|
pkt = tq_deqh (&tq_rspq); /* get top of q */
|
||||||
if (!tq_putpkt (pkt, FALSE)) return SCPE_OK; /* send to hst */
|
if (!tq_putpkt (pkt, FALSE)) return SCPE_OK; /* send to hst */
|
||||||
|
@ -620,7 +648,8 @@ else if (mdf & ~tq_cmf[cmd]) { /* invalid mod? */
|
||||||
sts = ST_CMD | I_MODF; } /* ill mods */
|
sts = ST_CMD | I_MODF; } /* ill mods */
|
||||||
else { /* valid cmd */
|
else { /* valid cmd */
|
||||||
if (uptr = tq_getucb (lu)) { /* valid unit? */
|
if (uptr = tq_getucb (lu)) { /* valid unit? */
|
||||||
if (q && uptr->cpkt && (tq_cmf[cmd] & CMF_SEQ)) {
|
if (q && (tq_cmf[cmd] & CMF_SEQ) && /* queueing, seq, */
|
||||||
|
(uptr->cpkt || uptr->pktq)) { /* and active? */
|
||||||
tq_enqt (&uptr->pktq, pkt); /* do later */
|
tq_enqt (&uptr->pktq, pkt); /* do later */
|
||||||
return OK; }
|
return OK; }
|
||||||
/* if (tq_cmf[cmd] & MD_CDL) /* clr cch lost? */
|
/* if (tq_cmf[cmd] & MD_CDL) /* clr cch lost? */
|
||||||
|
@ -719,7 +748,8 @@ if (uptr = tq_getucb (lu)) { /* unit exist? */
|
||||||
if (uptr->flags & UNIT_SXC) sts = ST_SXC; /* ser exc pending? */
|
if (uptr->flags & UNIT_SXC) sts = ST_SXC; /* ser exc pending? */
|
||||||
else {
|
else {
|
||||||
uptr->flags = uptr->flags & ~(UNIT_ONL | UNIT_TMK | UNIT_POL);
|
uptr->flags = uptr->flags & ~(UNIT_ONL | UNIT_TMK | UNIT_POL);
|
||||||
uptr->uf = uptr->pos = uptr->objp = 0; /* clr flags, rewind */
|
sim_tape_rewind (uptr); /* rewind */
|
||||||
|
uptr->uf = uptr->objp = 0; /* clr flags */
|
||||||
if (uptr->flags & UNIT_ATT) { /* attached? */
|
if (uptr->flags & UNIT_ATT) { /* attached? */
|
||||||
sts = ST_SUC; /* success */
|
sts = ST_SUC; /* success */
|
||||||
if (mdf & MD_UNL) tq_detach (uptr); } /* unload? */
|
if (mdf & MD_UNL) tq_detach (uptr); } /* unload? */
|
||||||
|
@ -791,7 +821,8 @@ if (uptr = tq_getucb (lu)) { /* unit exist? */
|
||||||
else if (uptr->flags & UNIT_ONL) /* already online? */
|
else if (uptr->flags & UNIT_ONL) /* already online? */
|
||||||
sts = ST_SUC | SB_SUC_ON;
|
sts = ST_SUC | SB_SUC_ON;
|
||||||
else { sts = ST_SUC; /* mark online */
|
else { sts = ST_SUC; /* mark online */
|
||||||
uptr->pos = uptr->objp = 0; /* rewind */
|
sim_tape_rewind (uptr); /* rewind */
|
||||||
|
uptr->objp = 0; /* clear flags */
|
||||||
uptr->flags = (uptr->flags | UNIT_ONL) &
|
uptr->flags = (uptr->flags | UNIT_ONL) &
|
||||||
~(UNIT_TMK | UNIT_POL); /* onl, pos ok */
|
~(UNIT_TMK | UNIT_POL); /* onl, pos ok */
|
||||||
tq_setf_unit (pkt, uptr); } /* hack flags */
|
tq_setf_unit (pkt, uptr); } /* hack flags */
|
||||||
|
@ -976,7 +1007,7 @@ return ST_SUC; /* success! */
|
||||||
t_stat tq_svc (UNIT *uptr)
|
t_stat tq_svc (UNIT *uptr)
|
||||||
{
|
{
|
||||||
uint32 t, sts, sktmk, skrec;
|
uint32 t, sts, sktmk, skrec;
|
||||||
t_mtrlnt i, ebc, tbc, wbc;
|
t_mtrlnt i, tbc, wbc;
|
||||||
int32 pkt = uptr->cpkt; /* get packet */
|
int32 pkt = uptr->cpkt; /* get packet */
|
||||||
uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* get cmd */
|
uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* get cmd */
|
||||||
uint32 mdf = tq_pkt[pkt].d[CMD_MOD]; /* modifier */
|
uint32 mdf = tq_pkt[pkt].d[CMD_MOD]; /* modifier */
|
||||||
|
@ -984,8 +1015,6 @@ uint32 ba = GETP32 (pkt, RW_BAL); /* buf addr */
|
||||||
t_mtrlnt bc = GETP32 (pkt, RW_BCL); /* byte count */
|
t_mtrlnt bc = GETP32 (pkt, RW_BCL); /* byte count */
|
||||||
uint32 nrec = GETP32 (pkt, POS_RCL); /* #rec to skip */
|
uint32 nrec = GETP32 (pkt, POS_RCL); /* #rec to skip */
|
||||||
uint32 ntmk = GETP32 (pkt, POS_TMCL); /* #tmk to skp */
|
uint32 ntmk = GETP32 (pkt, POS_TMCL); /* #tmk to skp */
|
||||||
static t_mtrlnt bceof = MTR_TMK;
|
|
||||||
static t_mtrlnt bceom = MTR_EOM;
|
|
||||||
|
|
||||||
if (pkt == 0) return SCPE_IERR; /* what??? */
|
if (pkt == 0) return SCPE_IERR; /* what??? */
|
||||||
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
|
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
|
||||||
|
@ -1057,14 +1086,8 @@ case OP_WR: /* write */
|
||||||
if (tq_hbe (uptr, ba + bc - t)) /* post err log */
|
if (tq_hbe (uptr, ba + bc - t)) /* post err log */
|
||||||
tq_mot_end (uptr, EF_LOG, ST_HST | SB_HST_NXM, bc);
|
tq_mot_end (uptr, EF_LOG, ST_HST | SB_HST_NXM, bc);
|
||||||
return SCPE_OK; } /* end else wr */
|
return SCPE_OK; } /* end else wr */
|
||||||
ebc = (bc + 1) & ~1; /* force even */
|
if (sim_tape_wrrecf (uptr, tqxb, bc)) /* write rec fwd, err? */
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set pos */
|
|
||||||
fxwrite (&bc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
|
||||||
fxwrite (tqxb, sizeof (uint8), ebc, uptr->fileref);
|
|
||||||
fxwrite (&bc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
|
||||||
if (ferror (uptr->fileref)) /* error? */
|
|
||||||
return tq_mot_err (uptr, bc); /* log, end */
|
return tq_mot_err (uptr, bc); /* log, end */
|
||||||
uptr->pos = uptr->pos + ebc + (2 * sizeof (t_mtrlnt));
|
|
||||||
uptr->objp = uptr->objp + 1; /* upd obj pos */
|
uptr->objp = uptr->objp + 1; /* upd obj pos */
|
||||||
if (TEST_EOT (uptr)) /* EOT on write? */
|
if (TEST_EOT (uptr)) /* EOT on write? */
|
||||||
uptr->flags = uptr->flags | UNIT_SXC;
|
uptr->flags = uptr->flags | UNIT_SXC;
|
||||||
|
@ -1073,11 +1096,8 @@ case OP_WR: /* write */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_WTM: /* write tape mark */
|
case OP_WTM: /* write tape mark */
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set pos */
|
if (sim_tape_wrtmk (uptr)) /* write tmk, err? */
|
||||||
fxwrite (&bceof, sizeof (t_mtrlnt), 1, uptr->fileref);
|
|
||||||
if (ferror (uptr->fileref)) /* error? */
|
|
||||||
return tq_mot_err (uptr, 0); /* log, end */
|
return tq_mot_err (uptr, 0); /* log, end */
|
||||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* update pos */
|
|
||||||
uptr->objp = uptr->objp + 1; /* incr obj cnt */
|
uptr->objp = uptr->objp + 1; /* incr obj cnt */
|
||||||
case OP_ERG: /* erase gap */
|
case OP_ERG: /* erase gap */
|
||||||
if (TEST_EOT (uptr)) /* EOT on write? */
|
if (TEST_EOT (uptr)) /* EOT on write? */
|
||||||
|
@ -1086,18 +1106,18 @@ case OP_ERG: /* erase gap */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_ERS: /* erase */
|
case OP_ERS: /* erase */
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set pos */
|
if (sim_tape_wreom (uptr)) /* write eom, err? */
|
||||||
fxwrite (&bceom, sizeof (t_mtrlnt), 1, uptr->fileref);
|
return tq_mot_err (uptr, 0); /* log, end */
|
||||||
if (ferror (uptr->fileref)) /* error? */
|
sim_tape_rewind (uptr); /* rewind */
|
||||||
return tq_mot_err (uptr, 0);
|
uptr->objp = 0;
|
||||||
uptr->pos = uptr->objp = 0; /* rewind */
|
|
||||||
uptr->flags = uptr->flags & ~(UNIT_TMK | UNIT_POL);
|
uptr->flags = uptr->flags & ~(UNIT_TMK | UNIT_POL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_POS: /* position */
|
case OP_POS: /* position */
|
||||||
sktmk = skrec = 0; /* clr skipped */
|
sktmk = skrec = 0; /* clr skipped */
|
||||||
if (mdf & MD_RWD) { /* rewind? */
|
if (mdf & MD_RWD) { /* rewind? */
|
||||||
uptr->pos = uptr->objp = 0; /* clr flags */
|
sim_tape_rewind (uptr);
|
||||||
|
uptr->objp = 0; /* clr flags */
|
||||||
uptr->flags = uptr->flags & ~(UNIT_TMK | UNIT_POL); }
|
uptr->flags = uptr->flags & ~(UNIT_TMK | UNIT_POL); }
|
||||||
if (mdf & MD_OBC) { /* skip obj? */
|
if (mdf & MD_OBC) { /* skip obj? */
|
||||||
if (mdf & MD_REV) /* reverse? */
|
if (mdf & MD_REV) /* reverse? */
|
||||||
|
@ -1161,43 +1181,63 @@ return OK;
|
||||||
|
|
||||||
/* Tape motion routines */
|
/* Tape motion routines */
|
||||||
|
|
||||||
uint32 tq_rdlntf (UNIT *uptr, t_mtrlnt *tbc)
|
uint32 tq_map_status (UNIT *uptr, t_stat st)
|
||||||
{
|
{
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set pos */
|
switch (st)
|
||||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref); /* read rec lnt */
|
{
|
||||||
if (ferror (uptr->fileref)) { /* error? */
|
case MTSE_OK:
|
||||||
uptr->flags = uptr->flags | UNIT_SXC | UNIT_POL; /* ser exc, pos lost */
|
break;
|
||||||
return ST_DRV; }
|
case MTSE_UNATT:
|
||||||
if (feof (uptr->fileref) || (*tbc == MTR_EOM)) { /* end of medium? */
|
uptr->flags = uptr->flags | UNIT_SXC;
|
||||||
uptr->flags = uptr->flags | UNIT_SXC | UNIT_POL; /* ser exc, pos lost */
|
return (ST_OFL | SB_OFL_NV);
|
||||||
return ST_DAT; }
|
case MTSE_FMT:
|
||||||
return 0;
|
uptr->flags = uptr->flags | UNIT_SXC;
|
||||||
|
return ST_MFE;
|
||||||
|
case MTSE_TMK:
|
||||||
|
uptr->flags = uptr->flags | UNIT_SXC;
|
||||||
|
return ST_TMK;
|
||||||
|
case MTSE_INVRL:
|
||||||
|
uptr->flags = uptr->flags | UNIT_SXC | UNIT_POL;
|
||||||
|
return ST_FMT;
|
||||||
|
case MTSE_RECE:
|
||||||
|
case MTSE_IOERR:
|
||||||
|
uptr->flags = uptr->flags | UNIT_SXC | UNIT_POL;
|
||||||
|
return ST_DRV;
|
||||||
|
case MTSE_EOM:
|
||||||
|
uptr->flags = uptr->flags | UNIT_SXC | UNIT_POL;
|
||||||
|
return ST_DAT;
|
||||||
|
case MTSE_BOT:
|
||||||
|
uptr->flags = (uptr->flags | UNIT_SXC) & ~UNIT_POL;
|
||||||
|
return ST_BOT;
|
||||||
|
case MTSE_WRP:
|
||||||
|
uptr->flags = uptr->flags | UNIT_SXC;
|
||||||
|
return ST_WPR; }
|
||||||
|
return ST_SUC;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 tq_spacef (UNIT *uptr, uint32 cnt, uint32 *skipped, t_bool qrec)
|
uint32 tq_spacef (UNIT *uptr, uint32 cnt, uint32 *skipped, t_bool qrec)
|
||||||
{
|
{
|
||||||
uint32 st;
|
t_stat st;
|
||||||
t_mtrlnt tbc;
|
t_mtrlnt tbc;
|
||||||
|
|
||||||
*skipped = 0;
|
*skipped = 0;
|
||||||
while (*skipped < cnt) { /* loop */
|
while (*skipped < cnt) { /* loop */
|
||||||
if (st = tq_rdlntf (uptr, &tbc)) return st; /* read rec lnt */
|
st = sim_tape_sprecf (uptr, &tbc); /* space rec fwd */
|
||||||
|
if ((st != MTSE_OK) && (st != MTSE_TMK)) /* real error? */
|
||||||
|
return tq_map_status (uptr, st); /* map status */
|
||||||
uptr->objp = uptr->objp + 1; /* upd obj cnt */
|
uptr->objp = uptr->objp + 1; /* upd obj cnt */
|
||||||
if (tbc == MTR_TMK) { /* tape mark? */
|
if (st == MTSE_TMK) { /* tape mark? */
|
||||||
int32 pkt = uptr->cpkt; /* get pkt */
|
int32 pkt = uptr->cpkt; /* get pkt */
|
||||||
if ((tq_pkt[pkt].d[CMD_MOD] & MD_DLE) && /* LEOT? */
|
if ((tq_pkt[pkt].d[CMD_MOD] & MD_DLE) && /* LEOT? */
|
||||||
(uptr->flags & UNIT_TMK)) {
|
(uptr->flags & UNIT_TMK)) {
|
||||||
|
sim_tape_sprecr (uptr, &tbc); /* rev over tmk */
|
||||||
uptr->flags = uptr->flags | UNIT_SXC; /* serious exc */
|
uptr->flags = uptr->flags | UNIT_SXC; /* serious exc */
|
||||||
return ST_LED; } /* dont upd pos */
|
return ST_LED; }
|
||||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* update pos */
|
|
||||||
uptr->flags = uptr->flags | UNIT_TMK; /* set TM seen */
|
uptr->flags = uptr->flags | UNIT_TMK; /* set TM seen */
|
||||||
if (qrec) return ST_TMK; } /* rec spc? stop */
|
if (qrec) return ST_TMK; } /* rec spc? stop */
|
||||||
else {
|
else uptr->flags = uptr->flags & ~UNIT_TMK; /* clr TM seen */
|
||||||
uptr->pos = uptr->pos + ((MTRL (tbc) + 1) & ~1) +
|
*skipped = *skipped + 1; } /* # obj skipped */
|
||||||
(2 * sizeof (t_mtrlnt)); /* update pos */
|
return ST_SUC;
|
||||||
uptr->flags = uptr->flags & ~UNIT_TMK; } /* clr TM seen */
|
|
||||||
*skipped = *skipped + 1; } /* # rec skipped */
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 tq_skipff (UNIT *uptr, uint32 cnt, uint32 *skipped)
|
uint32 tq_skipff (UNIT *uptr, uint32 cnt, uint32 *skipped)
|
||||||
|
@ -1206,49 +1246,26 @@ uint32 st, skrec;
|
||||||
|
|
||||||
*skipped = 0;
|
*skipped = 0;
|
||||||
while (*skipped < cnt) { /* loop */
|
while (*skipped < cnt) { /* loop */
|
||||||
st = tq_spacef (uptr, 0xFFFFFFFF, &skrec, TRUE); /* rec spc fwd */
|
st = tq_spacef (uptr, INT_MAX, &skrec, TRUE); /* rec spc fwd */
|
||||||
if (st == ST_TMK) *skipped = *skipped + 1; /* count files */
|
if (st == ST_TMK) *skipped = *skipped + 1; /* count files */
|
||||||
else if (st != 0) return st; }
|
else if (st != ST_SUC) return st; }
|
||||||
return 0;
|
return ST_SUC;
|
||||||
}
|
|
||||||
|
|
||||||
uint32 tq_rdlntr (UNIT *uptr, t_mtrlnt *tbc)
|
|
||||||
{
|
|
||||||
uptr->flags = uptr->flags & ~UNIT_TMK; /* rev clrs tmk */
|
|
||||||
if (uptr->pos < sizeof (t_mtrlnt)) { /* at BOT? */
|
|
||||||
uptr->flags = (uptr->flags | UNIT_SXC) & ~UNIT_POL;
|
|
||||||
return ST_BOT; }
|
|
||||||
fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET);
|
|
||||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref); /* read rec lnt */
|
|
||||||
if (ferror (uptr->fileref)) { /* error? */
|
|
||||||
uptr->flags = uptr->flags | UNIT_SXC | UNIT_POL; /* ser exc, pos lost */
|
|
||||||
return ST_DRV; }
|
|
||||||
if (feof (uptr->fileref)) { /* end of file? */
|
|
||||||
uptr->flags = uptr->flags | UNIT_SXC | UNIT_POL; /* ser exc, pos lost */
|
|
||||||
return ST_DAT; }
|
|
||||||
if (*tbc == MTR_EOM) { /* end of medium? */
|
|
||||||
uptr->flags = uptr->flags | UNIT_SXC | UNIT_POL; /* ser exc, pos lost */
|
|
||||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over eom */
|
|
||||||
return ST_DAT; }
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 tq_spacer (UNIT *uptr, uint32 cnt, uint32 *skipped, t_bool qrec)
|
uint32 tq_spacer (UNIT *uptr, uint32 cnt, uint32 *skipped, t_bool qrec)
|
||||||
{
|
{
|
||||||
uint32 st;
|
t_stat st;
|
||||||
t_mtrlnt tbc;
|
t_mtrlnt tbc;
|
||||||
|
|
||||||
*skipped = 0;
|
*skipped = 0;
|
||||||
while (*skipped < cnt) { /* loop */
|
while (*skipped < cnt) { /* loop */
|
||||||
if (st = tq_rdlntr (uptr, &tbc)) return st; /* read rec lnt */
|
st = sim_tape_sprecr (uptr, &tbc); /* spc rec rev */
|
||||||
|
if ((st != MTSE_OK) && (st != MTSE_TMK)) /* real error? */
|
||||||
|
return tq_map_status (uptr, st); /* map status */
|
||||||
uptr->objp = uptr->objp - 1; /* upd obj cnt */
|
uptr->objp = uptr->objp - 1; /* upd obj cnt */
|
||||||
if (tbc == MTR_TMK) { /* tape mark? */
|
if ((st == MTSE_TMK) && qrec) return ST_TMK; /* tape mark, stop? */
|
||||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* update pos */
|
*skipped = *skipped + 1; } /* # obj skipped */
|
||||||
if (qrec) return ST_TMK; } /* recd spc? stop */
|
return ST_SUC;
|
||||||
else uptr->pos = uptr->pos - ((MTRL (tbc) + 1) & ~1) -
|
|
||||||
(2 * sizeof (t_mtrlnt)); /* update pos */
|
|
||||||
*skipped = *skipped + 1; } /* # rec skipped */
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 tq_skipfr (UNIT *uptr, uint32 cnt, uint32 *skipped)
|
uint32 tq_skipfr (UNIT *uptr, uint32 cnt, uint32 *skipped)
|
||||||
|
@ -1257,64 +1274,41 @@ uint32 st, skrec;
|
||||||
|
|
||||||
*skipped = 0;
|
*skipped = 0;
|
||||||
while (*skipped < cnt) { /* loopo */
|
while (*skipped < cnt) { /* loopo */
|
||||||
st = tq_spacer (uptr, 0xFFFFFFFF, &skrec, TRUE); /* rec spc rev */
|
st = tq_spacer (uptr, INT_MAX, &skrec, TRUE); /* rec spc rev */
|
||||||
if (st == ST_TMK) *skipped = *skipped + 1; /* tape mark? */
|
if (st == ST_TMK) *skipped = *skipped + 1; /* tape mark? */
|
||||||
else if (st != 0) return st; } /* error? */
|
else if (st != 0) return st; } /* error? */
|
||||||
return 0;
|
return ST_SUC;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read buffer - can return ST_TMK, ST_FMT, or ST_DRV */
|
/* Read buffer - can return ST_TMK, ST_FMT, or ST_DRV */
|
||||||
|
|
||||||
uint32 tq_rdbuff (UNIT *uptr, t_mtrlnt *tbc)
|
uint32 tq_rdbuff (UNIT *uptr, t_mtrlnt *tbc)
|
||||||
{
|
{
|
||||||
t_mtrlnt i;
|
t_stat st;
|
||||||
uint32 st;
|
|
||||||
|
|
||||||
if (st = tq_rdlntf (uptr, tbc)) return st; /* read rec lnt */
|
st = sim_tape_rdrecf (uptr, tqxb, tbc, MT_MAXFR); /* read rec fwd */
|
||||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
if (st == MTSE_TMK) { /* tape mark? */
|
||||||
uptr->flags = uptr->flags | UNIT_SXC | UNIT_TMK; /* serious exc */
|
uptr->flags = uptr->flags | UNIT_SXC | UNIT_TMK;/* serious exc */
|
||||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* update pos */
|
|
||||||
uptr->objp = uptr->objp + 1; /* update obj cnt */
|
uptr->objp = uptr->objp + 1; /* update obj cnt */
|
||||||
return ST_TMK; }
|
return ST_TMK; }
|
||||||
|
if (st != MTSE_OK) return tq_map_status (uptr, st); /* other error? */
|
||||||
uptr->flags = uptr->flags & ~UNIT_TMK; /* clr tape mark */
|
uptr->flags = uptr->flags & ~UNIT_TMK; /* clr tape mark */
|
||||||
*tbc = MTRL (*tbc); /* ignore err flag */
|
|
||||||
if (*tbc > MT_MAXFR) { /* rec out of range? */
|
|
||||||
uptr->flags = uptr->flags | UNIT_SXC | UNIT_POL;
|
|
||||||
return ST_FMT; }
|
|
||||||
i = fxread (tqxb, sizeof (uint8), *tbc, uptr->fileref); /* read record */
|
|
||||||
if (ferror (uptr->fileref)) { /* error? */
|
|
||||||
uptr->flags = uptr->flags | UNIT_SXC | UNIT_POL;
|
|
||||||
return ST_DRV; }
|
|
||||||
for ( ; i < *tbc; i++) tqxb[i] = 0; /* fill with 0's */
|
|
||||||
uptr->pos = uptr->pos + ((*tbc + 1) & ~1) + (2 * sizeof (t_mtrlnt));
|
|
||||||
uptr->objp = uptr->objp + 1; /* upd obj cnt */
|
uptr->objp = uptr->objp + 1; /* upd obj cnt */
|
||||||
return 0;
|
return ST_SUC;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 tq_rdbufr (UNIT *uptr, t_mtrlnt *tbc)
|
uint32 tq_rdbufr (UNIT *uptr, t_mtrlnt *tbc)
|
||||||
{
|
{
|
||||||
t_mtrlnt i;
|
t_stat st;
|
||||||
uint32 st;
|
|
||||||
|
|
||||||
if (st = tq_rdlntr (uptr, tbc)) return st; /* read rec lnt */
|
st = sim_tape_rdrecr (uptr, tqxb, tbc, MT_MAXFR); /* read rec rev */
|
||||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
if (st == MTSE_TMK) { /* tape mark? */
|
||||||
uptr->flags = uptr->flags | UNIT_SXC; /* serious exc */
|
uptr->flags = uptr->flags | UNIT_SXC; /* serious exc */
|
||||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* update pos */
|
|
||||||
uptr->objp = uptr->objp - 1; /* update obj cnt */
|
uptr->objp = uptr->objp - 1; /* update obj cnt */
|
||||||
return ST_TMK; }
|
return ST_TMK; }
|
||||||
*tbc = MTRL (*tbc); /* ignore err flag */
|
if (st != MTSE_OK) return tq_map_status (uptr, st); /* other error? */
|
||||||
if (*tbc > MT_MAXFR) { /* rec out of range? */
|
|
||||||
uptr->flags = uptr->flags | UNIT_SXC | UNIT_POL;
|
|
||||||
return ST_FMT; }
|
|
||||||
fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt) - *tbc, SEEK_SET);
|
|
||||||
i = fxread (tqxb, sizeof (uint8), *tbc, uptr->fileref); /* read record */
|
|
||||||
if (ferror (uptr->fileref)) { /* error? */
|
|
||||||
uptr->flags = uptr->flags | UNIT_SXC | UNIT_POL;
|
|
||||||
return ST_DRV; }
|
|
||||||
for ( ; i < *tbc; i++) tqxb[i] = 0; /* fill with 0's */
|
|
||||||
uptr->pos = uptr->pos - ((*tbc + 1) & ~1) - (2 * sizeof (t_mtrlnt));
|
|
||||||
uptr->objp = uptr->objp - 1; /* upd obj cnt */
|
uptr->objp = uptr->objp - 1; /* upd obj cnt */
|
||||||
return 0;
|
return ST_SUC;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Data transfer error log packet */
|
/* Data transfer error log packet */
|
||||||
|
@ -1671,21 +1665,13 @@ tq_perr = err; /* save error */
|
||||||
return ERR;
|
return ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Change controller type */
|
|
||||||
|
|
||||||
t_stat tq_set_type (UNIT *uptr, int32 val, char *cptr, void *desc)
|
|
||||||
{
|
|
||||||
tq_typ = val;
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Device attach */
|
/* Device attach */
|
||||||
|
|
||||||
t_stat tq_attach (UNIT *uptr, char *cptr)
|
t_stat tq_attach (UNIT *uptr, char *cptr)
|
||||||
{
|
{
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
r = attach_unit (uptr, cptr);
|
r = sim_tape_attach (uptr, cptr);
|
||||||
if (r != SCPE_OK) return r;
|
if (r != SCPE_OK) return r;
|
||||||
if (tq_csta == CST_UP) uptr->flags = (uptr->flags | UNIT_ATP) &
|
if (tq_csta == CST_UP) uptr->flags = (uptr->flags | UNIT_ATP) &
|
||||||
~(UNIT_SXC | UNIT_POL | UNIT_TMK);
|
~(UNIT_SXC | UNIT_POL | UNIT_TMK);
|
||||||
|
@ -1698,7 +1684,7 @@ t_stat tq_detach (UNIT *uptr)
|
||||||
{
|
{
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
r = detach_unit (uptr); /* detach unit */
|
r = sim_tape_detach (uptr); /* detach unit */
|
||||||
if (r != SCPE_OK) return r;
|
if (r != SCPE_OK) return r;
|
||||||
uptr->flags = uptr->flags & ~(UNIT_ONL | UNIT_ATP | UNIT_SXC | UNIT_POL | UNIT_TMK);
|
uptr->flags = uptr->flags & ~(UNIT_ONL | UNIT_ATP | UNIT_SXC | UNIT_POL | UNIT_TMK);
|
||||||
uptr->uf = 0; /* clr unit flgs */
|
uptr->uf = 0; /* clr unit flgs */
|
||||||
|
@ -1734,6 +1720,7 @@ CLR_INT (TQ); /* clr intr req */
|
||||||
for (i = 0; i < TQ_NUMDR + 2; i++) { /* init units */
|
for (i = 0; i < TQ_NUMDR + 2; i++) { /* init units */
|
||||||
uptr = tq_dev.units + i;
|
uptr = tq_dev.units + i;
|
||||||
sim_cancel (uptr); /* clr activity */
|
sim_cancel (uptr); /* clr activity */
|
||||||
|
sim_tape_reset (uptr);
|
||||||
uptr->flags = uptr->flags & /* not online */
|
uptr->flags = uptr->flags & /* not online */
|
||||||
~(UNIT_ONL|UNIT_ATP|UNIT_SXC|UNIT_POL|UNIT_TMK);
|
~(UNIT_ONL|UNIT_ATP|UNIT_SXC|UNIT_POL|UNIT_TMK);
|
||||||
uptr->uf = 0; /* clr unit flags */
|
uptr->uf = 0; /* clr unit flags */
|
||||||
|
@ -1984,3 +1971,31 @@ if (val & TQ_SH_UN) {
|
||||||
}
|
}
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set controller type (and capacity for user-defined type) */
|
||||||
|
|
||||||
|
tq_set_type (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
int32 i, cap;
|
||||||
|
t_stat r;
|
||||||
|
|
||||||
|
if ((val < 0) || (val > TQU_TYPE) || ((val != TQU_TYPE) && cptr))
|
||||||
|
return SCPE_ARG;
|
||||||
|
for (i = 0; i < TQ_NUMDR; i++) {
|
||||||
|
if (tq_unit[i].flags & UNIT_ATT) return SCPE_ALATT; }
|
||||||
|
if (cptr) {
|
||||||
|
cap = (int32) get_uint (cptr, 10, TQU_MAXC, &r);
|
||||||
|
if ((r != SCPE_OK) || (cap < TQU_MINC)) return SCPE_ARG;
|
||||||
|
drv_tab[TQU_TYPE].cap = cap << 20; }
|
||||||
|
tq_typ = val;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Show controller type (and capacity for user-defined type) */
|
||||||
|
|
||||||
|
tq_show_type (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
|
{
|
||||||
|
fprintf (st, "%s", drv_tab[tq_typ].name);
|
||||||
|
if (tq_typ == TQU_TYPE) fprintf (st, " (%dMB)", drv_tab[tq_typ].cap >> 20);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
222
PDP11/pdp11_ts.c
222
PDP11/pdp11_ts.c
|
@ -1,6 +1,6 @@
|
||||||
/* pdp11_ts.c: TS11/TSV05 magnetic tape simulator
|
/* pdp11_ts.c: TS11/TSV05 magnetic tape simulator
|
||||||
|
|
||||||
Copyright (c) 1993-2002, Robert M Supnik
|
Copyright (c) 1993-2003, Robert M Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
ts TS11/TSV05 magtape
|
ts TS11/TSV05 magtape
|
||||||
|
|
||||||
|
28-Feb-03 RMS Revised to use magtape library
|
||||||
30-Sep-02 RMS Added variable address support to bootstrap
|
30-Sep-02 RMS Added variable address support to bootstrap
|
||||||
Added vector change/display support
|
Added vector change/display support
|
||||||
Fixed CTL unload/clean decode
|
Fixed CTL unload/clean decode
|
||||||
|
@ -99,9 +100,7 @@ extern int32 cpu_18b, cpu_ubm;
|
||||||
#define WriteW(p,v) M[(p) >> 1] = (v)
|
#define WriteW(p,v) M[(p) >> 1] = (v)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
#include "sim_tape.h"
|
||||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
|
||||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
|
||||||
|
|
||||||
/* TSBA/TSDB - 17772520: base address/data buffer register
|
/* TSBA/TSDB - 17772520: base address/data buffer register
|
||||||
|
|
||||||
|
@ -296,6 +295,7 @@ int32 ts_updtssr (int32 t);
|
||||||
int32 ts_updxs0 (int32 t);
|
int32 ts_updxs0 (int32 t);
|
||||||
void ts_cmpendcmd (int32 s0, int32 s1);
|
void ts_cmpendcmd (int32 s0, int32 s1);
|
||||||
void ts_endcmd (int32 ssf, int32 xs0f, int32 msg);
|
void ts_endcmd (int32 ssf, int32 xs0f, int32 msg);
|
||||||
|
int32 ts_map_status (t_stat st);
|
||||||
|
|
||||||
/* TS data structures
|
/* TS data structures
|
||||||
|
|
||||||
|
@ -342,8 +342,8 @@ REG ts_reg[] = {
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
MTAB ts_mod[] = {
|
MTAB ts_mod[] = {
|
||||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
|
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
|
||||||
{ MTAB_XTD|MTAB_VDV, 004, "ADDRESS", "ADDRESS",
|
{ MTAB_XTD|MTAB_VDV, 004, "ADDRESS", "ADDRESS",
|
||||||
&set_addr, &show_addr, NULL },
|
&set_addr, &show_addr, NULL },
|
||||||
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR",
|
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR",
|
||||||
|
@ -422,32 +422,44 @@ return SCPE_OK;
|
||||||
#define GET_X(x) (((x) >> 16) & 0177777)
|
#define GET_X(x) (((x) >> 16) & 0177777)
|
||||||
#define GET_T(x) ((x) & 0177777)
|
#define GET_T(x) ((x) & 0177777)
|
||||||
|
|
||||||
int32 ts_rdlntf (UNIT *uptr, t_mtrlnt *tbc)
|
int32 ts_map_status (t_stat st)
|
||||||
{
|
{
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set pos */
|
switch (st) {
|
||||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref); /* read rec lnt */
|
case MTSE_OK:
|
||||||
if (ferror (uptr->fileref)) { /* error? */
|
break;
|
||||||
|
case MTSE_TMK:
|
||||||
|
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
||||||
|
return (XTC (XS0_TMK | XS0_RLS, TC2));
|
||||||
|
case MTSE_RECE: /* record in error */
|
||||||
|
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
||||||
|
case MTSE_INVRL: /* invalid rec lnt */
|
||||||
|
case MTSE_IOERR: /* IO error */
|
||||||
msgxs1 = msgxs1 | XS1_UCOR; /* uncorrectable */
|
msgxs1 = msgxs1 | XS1_UCOR; /* uncorrectable */
|
||||||
return (XTC (XS0_RLS, TC6)); } /* pos lost */
|
return (XTC (XS0_RLS, TC6)); /* pos lost */
|
||||||
if (feof (uptr->fileref) || (*tbc == MTR_EOM)) { /* end of medium? */
|
case MTSE_FMT:
|
||||||
|
case MTSE_UNATT:
|
||||||
|
case MTSE_EOM: /* end of medium */
|
||||||
msgxs3 = msgxs3 | XS3_OPI; /* incomplete */
|
msgxs3 = msgxs3 | XS3_OPI; /* incomplete */
|
||||||
return (XTC (XS0_RLS, TC6)); } /* pos lost */
|
return (XTC (XS0_RLS, TC6)); /* pos lost */
|
||||||
|
case MTSE_BOT: /* reverse into BOT */
|
||||||
|
msgxs3 = msgxs3 | XS3_RIB; /* set status */
|
||||||
|
return (XTC (XS0_BOT | XS0_RLS, TC2)); /* tape alert */
|
||||||
|
case MTSE_WRP: /* write protect */
|
||||||
|
msgxs0 = msgxs0 | XS0_WLE | XS0_NEF; /* can't execute */
|
||||||
|
return (XTC (XS0_WLE | XS0_NEF, TC3)); }
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 ts_spacef (UNIT *uptr, int32 fc, t_bool upd)
|
int32 ts_spacef (UNIT *uptr, int32 fc, t_bool upd)
|
||||||
{
|
{
|
||||||
int32 st;
|
t_stat st;
|
||||||
t_mtrlnt tbc;
|
t_mtrlnt tbc;
|
||||||
|
|
||||||
do { fc = (fc - 1) & DMASK; /* decr wc */
|
do { fc = (fc - 1) & DMASK; /* decr wc */
|
||||||
if (upd) msgrfc = fc;
|
if (upd) msgrfc = fc;
|
||||||
if (st = ts_rdlntf (uptr, &tbc)) return st; /* read rec lnt */
|
if (st = sim_tape_sprecf (uptr, &tbc)) /* space rec fwd, err? */
|
||||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* update pos */
|
return ts_map_status (st); /* map status */
|
||||||
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
||||||
if (tbc == MTR_TMK) /* tape mark? */
|
|
||||||
return (XTC (XS0_TMK | XS0_RLS, TC2));
|
|
||||||
uptr->pos = uptr->pos + ((MTRL (tbc) + 1) & ~1) + sizeof (t_mtrlnt);
|
|
||||||
}
|
}
|
||||||
while (fc != 0);
|
while (fc != 0);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -455,63 +467,38 @@ return 0;
|
||||||
|
|
||||||
int32 ts_skipf (UNIT *uptr, int32 fc)
|
int32 ts_skipf (UNIT *uptr, int32 fc)
|
||||||
{
|
{
|
||||||
int32 tc;
|
t_stat st;
|
||||||
t_mtrlnt prvp;
|
t_mtrlnt tbc;
|
||||||
t_bool tmkprv = FALSE;
|
t_bool tmkprv = FALSE;
|
||||||
|
|
||||||
msgrfc = fc;
|
msgrfc = fc;
|
||||||
if ((uptr->pos == 0) && (wchopt & WCH_ENB)) tmkprv = TRUE;
|
if (sim_tape_bot (uptr) && (wchopt & WCH_ENB)) tmkprv = TRUE;
|
||||||
do { prvp = uptr->pos; /* save cur pos */
|
do { st = sim_tape_sprecf (uptr, &tbc); /* space rec fwd */
|
||||||
tc = ts_spacef (uptr, 0, FALSE); /* space fwd */
|
if (st == MTSE_TMK) { /* tape mark? */
|
||||||
if (GET_X (tc) & XS0_TMK) { /* tape mark? */
|
|
||||||
msgrfc = (msgrfc - 1) & DMASK; /* decr count */
|
msgrfc = (msgrfc - 1) & DMASK; /* decr count */
|
||||||
if (tmkprv && (wchopt & WCH_ESS) &&
|
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
||||||
(uptr->pos - prvp == sizeof (t_mtrlnt)))
|
if (tmkprv && (wchopt & WCH_ESS)) /* 2nd tmk & ESS? */
|
||||||
return (XTC ((msgrfc? XS0_RLS: 0) |
|
return (XTC ((msgrfc? XS0_RLS: 0) |
|
||||||
XS0_TMK | XS0_LET, TC2));
|
XS0_TMK | XS0_LET, TC2));
|
||||||
tmkprv = TRUE; }
|
tmkprv = TRUE; } /* flag tmk */
|
||||||
else {
|
else if (st != MTSE_OK) return ts_map_status (st);
|
||||||
if (tc) return tc; /* other err? */
|
else tmkprv = FALSE; /* not a tmk */
|
||||||
tmkprv = FALSE; } }
|
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
||||||
|
}
|
||||||
while (msgrfc != 0);
|
while (msgrfc != 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 ts_rdlntr (UNIT *uptr, t_mtrlnt *tbc)
|
|
||||||
{
|
|
||||||
msgxs3 = msgxs3 | XS3_REV; /* set rev op */
|
|
||||||
if (uptr->pos < sizeof (t_mtrlnt)) { /* BOT? */
|
|
||||||
msgxs3 = msgxs3 | XS3_RIB; /* set status */
|
|
||||||
return (XTC (XS0_BOT | XS0_RLS, TC2)); } /* tape alert */
|
|
||||||
fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET);
|
|
||||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
|
||||||
if (ferror (uptr->fileref)) { /* error? */
|
|
||||||
msgxs1 = msgxs1 | XS1_UCOR; /* uncorrectable */
|
|
||||||
return (XTC (XS0_RLS, TC6)); } /* pos lost */
|
|
||||||
if (feof (uptr->fileref)) { /* end of file? */
|
|
||||||
msgxs3 = msgxs3 | XS3_OPI; /* incomplete */
|
|
||||||
return (XTC (XS0_RLS, TC6)); } /* pos lost */
|
|
||||||
if (*tbc == MTR_EOM) { /* eom? */
|
|
||||||
msgxs3 = msgxs3 | XS3_OPI; /* incomplete */
|
|
||||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over eom */
|
|
||||||
return (XTC (XS0_RLS, TC6)); } /* pos lost */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 ts_spacer (UNIT *uptr, int32 fc, t_bool upd)
|
int32 ts_spacer (UNIT *uptr, int32 fc, t_bool upd)
|
||||||
{
|
{
|
||||||
int32 st;
|
int32 st;
|
||||||
t_mtrlnt tbc;
|
t_mtrlnt tbc;
|
||||||
|
|
||||||
if (upd) msgrfc = fc;
|
|
||||||
do { fc = (fc - 1) & DMASK; /* decr wc */
|
do { fc = (fc - 1) & DMASK; /* decr wc */
|
||||||
if (upd) msgrfc = fc;
|
if (upd) msgrfc = fc;
|
||||||
if (st = ts_rdlntr (uptr, &tbc)) return st; /* read rec lnt */
|
if (st = sim_tape_sprecr (uptr, &tbc)) /* space rec rev, err? */
|
||||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* update pos */
|
return ts_map_status (st); /* map status */
|
||||||
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
||||||
if (tbc == MTR_TMK) /* tape mark? */
|
|
||||||
return (XTC (XS0_TMK | XS0_RLS, TC2));
|
|
||||||
uptr->pos = uptr->pos - ((MTRL (tbc) + 1) & ~1) - sizeof (t_mtrlnt);
|
|
||||||
}
|
}
|
||||||
while (fc != 0);
|
while (fc != 0);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -519,52 +506,39 @@ return 0;
|
||||||
|
|
||||||
int32 ts_skipr (UNIT *uptr, int32 fc)
|
int32 ts_skipr (UNIT *uptr, int32 fc)
|
||||||
{
|
{
|
||||||
int32 tc;
|
t_stat st;
|
||||||
t_mtrlnt prvp;
|
t_mtrlnt tbc;
|
||||||
t_bool tmkprv = FALSE;
|
t_bool tmkprv = FALSE;
|
||||||
|
|
||||||
msgrfc = fc;
|
msgrfc = fc;
|
||||||
do { prvp = uptr->pos; /* save cur pos */
|
do { st = sim_tape_sprecr (uptr, &tbc); /* space rec rev */
|
||||||
tc = ts_spacer (uptr, 0, FALSE); /* space rev */
|
if (st == MTSE_TMK) { /* tape mark? */
|
||||||
if (GET_X (tc) & XS0_TMK) { /* tape mark? */
|
msgrfc = (msgrfc - 1) & DMASK; /* decr count */
|
||||||
msgrfc = (msgrfc - 1) & DMASK; /* decr wc */
|
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
||||||
if (tmkprv && (wchopt & WCH_ESS) &&
|
if (tmkprv && (wchopt & WCH_ESS)) /* 2nd tmk & ESS? */
|
||||||
(prvp - uptr->pos == sizeof (t_mtrlnt)))
|
|
||||||
return (XTC ((msgrfc? XS0_RLS: 0) |
|
return (XTC ((msgrfc? XS0_RLS: 0) |
|
||||||
XS0_TMK | XS0_LET, TC2));
|
XS0_TMK | XS0_LET, TC2));
|
||||||
tmkprv = TRUE; }
|
tmkprv = TRUE; } /* flag tmk */
|
||||||
else {
|
else if (st != MTSE_OK) return ts_map_status (st);
|
||||||
if (tc) return tc; /* other err? */
|
else tmkprv = FALSE; /* not a tmk */
|
||||||
tmkprv = FALSE; } }
|
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
||||||
|
}
|
||||||
while (msgrfc != 0);
|
while (msgrfc != 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 ts_readf (UNIT *uptr, uint32 fc)
|
int32 ts_readf (UNIT *uptr, uint32 fc)
|
||||||
{
|
{
|
||||||
int32 st;
|
t_stat st;
|
||||||
t_mtrlnt i, tbc, wbc;
|
t_mtrlnt i, tbc, wbc;
|
||||||
t_addr wa, pa;
|
t_addr wa, pa;
|
||||||
|
|
||||||
msgrfc = fc;
|
msgrfc = fc;
|
||||||
if (st = ts_rdlntf (uptr, &tbc)) return st; /* read rec lnt */
|
st = sim_tape_rdrecf (uptr, tsxb, &tbc, MT_MAXFR); /* read rec fwd */
|
||||||
if (tbc == MTR_TMK) { /* tape mark? */
|
if (st != MTSE_OK) return ts_map_status (st); /* error? */
|
||||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* update pos */
|
|
||||||
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
|
||||||
return (XTC (XS0_TMK | XS0_RLS, TC2)); }
|
|
||||||
if (fc == 0) fc = 0200000; /* byte count */
|
if (fc == 0) fc = 0200000; /* byte count */
|
||||||
tsba = (cmdadh << 16) | cmdadl; /* buf addr */
|
tsba = (cmdadh << 16) | cmdadl; /* buf addr */
|
||||||
tbc = MTRL (tbc); /* ignore err flag */
|
|
||||||
if (tbc > MT_MAXFR) { /* record too long? */
|
|
||||||
msgxs1 = msgxs1 | XS1_UCOR; /* uncorrectable */
|
|
||||||
return XTC (XS0_RLS, TC6); } /* pos lost */
|
|
||||||
wbc = (tbc > fc)? fc: tbc; /* cap buf size */
|
wbc = (tbc > fc)? fc: tbc; /* cap buf size */
|
||||||
i = fxread (tsxb, sizeof (uint8), wbc, uptr->fileref); /* read record */
|
|
||||||
if (ferror (uptr->fileref)) { /* error? */
|
|
||||||
msgxs1 = msgxs1 | XS1_UCOR; /* uncorrectable */
|
|
||||||
return XTC (XS0_RLS, TC6); } /* pos lost */
|
|
||||||
for ( ; i < wbc; i++) tsxb[i] = 0; /* fill with 0's */
|
|
||||||
uptr->pos = uptr->pos + ((tbc + 1) & ~1) + (2 * sizeof (t_mtrlnt));
|
|
||||||
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
||||||
for (i = 0; i < wbc; i++) { /* copy buffer */
|
for (i = 0; i < wbc; i++) { /* copy buffer */
|
||||||
wa = (cmdhdr & CMD_SWP)? tsba ^ 1: tsba; /* apply OPP */
|
wa = (cmdhdr & CMD_SWP)? tsba ^ 1: tsba; /* apply OPP */
|
||||||
|
@ -582,30 +556,16 @@ return 0;
|
||||||
|
|
||||||
int32 ts_readr (UNIT *uptr, uint32 fc)
|
int32 ts_readr (UNIT *uptr, uint32 fc)
|
||||||
{
|
{
|
||||||
int32 st;
|
t_stat st;
|
||||||
t_mtrlnt i, tbc, wbc;
|
t_mtrlnt i, tbc, wbc;
|
||||||
t_addr wa, pa;
|
t_addr wa, pa;
|
||||||
|
|
||||||
msgrfc = fc;
|
msgrfc = fc;
|
||||||
if (st = ts_rdlntr (uptr, &tbc)) return st; /* read rec lnt */
|
st = sim_tape_rdrecr (uptr, tsxb, &tbc, MT_MAXFR); /* read rec rev */
|
||||||
if (tbc == MTR_TMK) { /* tape mark? */
|
if (st != MTSE_OK) return ts_map_status (st); /* error? */
|
||||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* update pos */
|
|
||||||
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
|
||||||
return XTC (XS0_TMK | XS0_RLS, TC2); }
|
|
||||||
if (fc == 0) fc = 0200000; /* byte count */
|
if (fc == 0) fc = 0200000; /* byte count */
|
||||||
tsba = (cmdadh << 16) | cmdadl + fc; /* buf addr */
|
tsba = (cmdadh << 16) | cmdadl + fc; /* buf addr */
|
||||||
tbc = MTRL (tbc); /* ignore err flag */
|
|
||||||
if (tbc > MT_MAXFR) { /* record too long? */
|
|
||||||
msgxs1 = msgxs1 | XS1_UCOR; /* uncorrectable */
|
|
||||||
return XTC (XS0_RLS, TC6); } /* pos lost */
|
|
||||||
wbc = (tbc > fc)? fc: tbc; /* cap buf size */
|
wbc = (tbc > fc)? fc: tbc; /* cap buf size */
|
||||||
fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt) - wbc, SEEK_SET);
|
|
||||||
i = fxread (tsxb, sizeof (uint8), wbc, uptr->fileref);
|
|
||||||
for ( ; i < wbc; i++) tsxb[i] = 0; /* fill with 0's */
|
|
||||||
if (ferror (uptr->fileref)) { /* error? */
|
|
||||||
msgxs1 = msgxs1 | XS1_UCOR; /* uncorrectable */
|
|
||||||
return XTC (XS0_RLS, TC6); } /* pos lost */
|
|
||||||
uptr->pos = uptr->pos - ((tbc + 1) & ~1) - (2 * sizeof (t_mtrlnt));
|
|
||||||
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
||||||
for (i = wbc; i > 0; i--) { /* copy buffer */
|
for (i = wbc; i > 0; i--) { /* copy buffer */
|
||||||
tsba = tsba - 1;
|
tsba = tsba - 1;
|
||||||
|
@ -623,8 +583,9 @@ return 0;
|
||||||
|
|
||||||
int32 ts_write (UNIT *uptr, int32 fc)
|
int32 ts_write (UNIT *uptr, int32 fc)
|
||||||
{
|
{
|
||||||
int32 i, ebc;
|
int32 i;
|
||||||
t_addr wa, pa;
|
t_addr wa, pa;
|
||||||
|
t_stat st;
|
||||||
|
|
||||||
msgrfc = fc;
|
msgrfc = fc;
|
||||||
if (fc == 0) fc = 0200000; /* byte count */
|
if (fc == 0) fc = 0200000; /* byte count */
|
||||||
|
@ -637,15 +598,8 @@ for (i = 0; i < fc; i++) { /* copy mem to buf */
|
||||||
tssr = ts_updtssr (tssr | TSSR_NXM);
|
tssr = ts_updtssr (tssr | TSSR_NXM);
|
||||||
return TC5; }
|
return TC5; }
|
||||||
tsba = tsba + 1; }
|
tsba = tsba + 1; }
|
||||||
ebc = (fc + 1) & ~1; /* force even */
|
if (st = sim_tape_wrrecf (uptr, tsxb, fc)) /* write rec, err? */
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* position */
|
return ts_map_status (st); /* return status */
|
||||||
fxwrite (&fc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
|
||||||
fxwrite (tsxb, sizeof (uint8), ebc, uptr->fileref);
|
|
||||||
fxwrite (&fc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
|
||||||
if (ferror (uptr->fileref)) { /* error? */
|
|
||||||
msgxs3 = msgxs3 | XS3_OPI;
|
|
||||||
return TC6; }
|
|
||||||
uptr->pos = uptr->pos + ebc + (2 * sizeof (t_mtrlnt)); /* update pos */
|
|
||||||
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
||||||
msgrfc = 0;
|
msgrfc = 0;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -653,12 +607,10 @@ return 0;
|
||||||
|
|
||||||
int32 ts_wtmk (UNIT *uptr)
|
int32 ts_wtmk (UNIT *uptr)
|
||||||
{
|
{
|
||||||
t_mtrlnt bceof = MTR_TMK;
|
t_stat st;
|
||||||
|
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set pos */
|
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
|
||||||
fxwrite (&bceof, sizeof (t_mtrlnt), 1, uptr->fileref);
|
return ts_map_status (st); /* return status */
|
||||||
if (ferror (uptr->fileref)) return TC6;
|
|
||||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* update position */
|
|
||||||
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
||||||
return XTC (XS0_TMK, TC0);
|
return XTC (XS0_TMK, TC0);
|
||||||
}
|
}
|
||||||
|
@ -683,7 +635,7 @@ static const int32 fnc_flg[CMD_N_FNC] = {
|
||||||
|
|
||||||
if (ts_bcmd) { /* boot? */
|
if (ts_bcmd) { /* boot? */
|
||||||
ts_bcmd = 0; /* clear flag */
|
ts_bcmd = 0; /* clear flag */
|
||||||
uptr->pos = 0; /* rewind */
|
sim_tape_rewind (uptr); /* rewind */
|
||||||
if (uptr->flags & UNIT_ATT) { /* attached? */
|
if (uptr->flags & UNIT_ATT) { /* attached? */
|
||||||
cmdlnt = cmdadh = cmdadl = 0; /* defang rd */
|
cmdlnt = cmdadh = cmdadl = 0; /* defang rd */
|
||||||
ts_spacef (uptr, 1, FALSE); /* space fwd */
|
ts_spacef (uptr, 1, FALSE); /* space fwd */
|
||||||
|
@ -721,12 +673,12 @@ if ((fnc_flg[fnc] & FLG_MO) && /* mot+(vck|!att)? */
|
||||||
ts_endcmd (TC3, XS0_NEF, MSG_ACK | MSG_MNEF | MSG_CFAIL);
|
ts_endcmd (TC3, XS0_NEF, MSG_ACK | MSG_MNEF | MSG_CFAIL);
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
if ((fnc_flg[fnc] & FLG_WR) && /* write? */
|
if ((fnc_flg[fnc] & FLG_WR) && /* write? */
|
||||||
(uptr->flags & UNIT_WPRT)) { /* write lck? */
|
sim_tape_wrp (uptr)) { /* write lck? */
|
||||||
ts_endcmd (TC3, XS0_WLE | XS0_NEF, MSG_ACK | MSG_MNEF | MSG_CFAIL);
|
ts_endcmd (TC3, XS0_WLE | XS0_NEF, MSG_ACK | MSG_MNEF | MSG_CFAIL);
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
if ((((fnc == FNC_READ) && (mod == 1)) || /* read rev */
|
if ((((fnc == FNC_READ) && (mod == 1)) || /* read rev */
|
||||||
((fnc == FNC_POS) && (mod & 1))) && /* space rev */
|
((fnc == FNC_POS) && (mod & 1))) && /* space rev */
|
||||||
(uptr->pos == 0)) { /* BOT? */
|
sim_tape_bot (uptr)) { /* BOT? */
|
||||||
ts_endcmd (TC3, XS0_NEF, MSG_ACK | MSG_MNEF | MSG_CFAIL);
|
ts_endcmd (TC3, XS0_NEF, MSG_ACK | MSG_MNEF | MSG_CFAIL);
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
if ((fnc_flg[fnc] & FLG_AD) && (cmdadh & ADDRTEST)) { /* buf addr > 22b? */
|
if ((fnc_flg[fnc] & FLG_AD) && (cmdadh & ADDRTEST)) { /* buf addr > 22b? */
|
||||||
|
@ -736,8 +688,8 @@ if ((fnc_flg[fnc] & FLG_AD) && (cmdadh & ADDRTEST)) { /* buf addr > 22b? */
|
||||||
st0 = st1 = 0;
|
st0 = st1 = 0;
|
||||||
switch (fnc) { /* case on func */
|
switch (fnc) { /* case on func */
|
||||||
case FNC_INIT: /* init */
|
case FNC_INIT: /* init */
|
||||||
if (uptr->pos) msgxs0 = msgxs0 | XS0_MOT; /* set if tape moves */
|
if (!sim_tape_bot (uptr)) msgxs0 = msgxs0 | XS0_MOT; /* set if tape moves */
|
||||||
uptr->pos = 0; /* rewind */
|
sim_tape_rewind (uptr); /* rewind */
|
||||||
case FNC_WSSM: /* write mem */
|
case FNC_WSSM: /* write mem */
|
||||||
case FNC_GSTA: /* get status */
|
case FNC_GSTA: /* get status */
|
||||||
ts_endcmd (TC0, 0, MSG_ACK | MSG_CEND); /* send end packet */
|
ts_endcmd (TC0, 0, MSG_ACK | MSG_CEND); /* send end packet */
|
||||||
|
@ -769,8 +721,8 @@ case FNC_CTL: /* control */
|
||||||
ts_ownc = 0; ts_ownm = 1; /* keep msg */
|
ts_ownc = 0; ts_ownm = 1; /* keep msg */
|
||||||
break;
|
break;
|
||||||
case 01: /* rewind and unload */
|
case 01: /* rewind and unload */
|
||||||
if (uptr->pos) msgxs0 = msgxs0 | XS0_MOT; /* if tape moves */
|
if (!sim_tape_bot (uptr)) msgxs0 = msgxs0 | XS0_MOT; /* if tape moves */
|
||||||
detach_unit (uptr); /* unload */
|
sim_tape_detach (uptr); /* unload */
|
||||||
ts_endcmd (TC0, 0, MSG_ACK | MSG_CEND);
|
ts_endcmd (TC0, 0, MSG_ACK | MSG_CEND);
|
||||||
break;
|
break;
|
||||||
case 02: /* clean */
|
case 02: /* clean */
|
||||||
|
@ -780,8 +732,8 @@ case FNC_CTL: /* control */
|
||||||
ts_endcmd (TC3, XS0_ILC, MSG_ACK | MSG_MILL | MSG_CFAIL);
|
ts_endcmd (TC3, XS0_ILC, MSG_ACK | MSG_MILL | MSG_CFAIL);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
case 04: /* rewind */
|
case 04: /* rewind */
|
||||||
if (uptr->pos) msgxs0 = msgxs0 | XS0_MOT; /* if tape moves */
|
if (!sim_tape_bot (uptr)) msgxs0 = msgxs0 | XS0_MOT; /* if tape moves */
|
||||||
uptr->pos = 0;
|
sim_tape_rewind (uptr);
|
||||||
ts_endcmd (TC0, XS0_BOT, MSG_ACK | MSG_CEND);
|
ts_endcmd (TC0, XS0_BOT, MSG_ACK | MSG_CEND);
|
||||||
break; }
|
break; }
|
||||||
break;
|
break;
|
||||||
|
@ -851,8 +803,8 @@ case FNC_POS:
|
||||||
st0 = ts_skipr (uptr, cmdadl);
|
st0 = ts_skipr (uptr, cmdadl);
|
||||||
break;
|
break;
|
||||||
case 04: /* rewind */
|
case 04: /* rewind */
|
||||||
if (uptr->pos) msgxs0 = msgxs0 | XS0_MOT; /* if tape moves */
|
if (!sim_tape_bot (uptr)) msgxs0 = msgxs0 | XS0_MOT; /* if tape moves */
|
||||||
uptr->pos = 0;
|
sim_tape_rewind (uptr);
|
||||||
break; }
|
break; }
|
||||||
ts_cmpendcmd (st0, 0);
|
ts_cmpendcmd (st0, 0);
|
||||||
break; }
|
break; }
|
||||||
|
@ -874,8 +826,8 @@ int32 ts_updxs0 (int32 t)
|
||||||
t = (t & ~(XS0_ONL | XS0_WLK | XS0_BOT | XS0_IE)) | XS0_PET;
|
t = (t & ~(XS0_ONL | XS0_WLK | XS0_BOT | XS0_IE)) | XS0_PET;
|
||||||
if (ts_unit.flags & UNIT_ATT) {
|
if (ts_unit.flags & UNIT_ATT) {
|
||||||
t = t | XS0_ONL;
|
t = t | XS0_ONL;
|
||||||
if (ts_unit.flags & UNIT_WPRT) t = t | XS0_WLK;
|
if (sim_tape_wrp (&ts_unit)) t = t | XS0_WLK;
|
||||||
if (ts_unit.pos == 0) t = (t | XS0_BOT) & ~XS0_EOT; }
|
if (sim_tape_bot (&ts_unit)) t = (t | XS0_BOT) & ~XS0_EOT; }
|
||||||
else t = t & ~XS0_EOT;
|
else t = t & ~XS0_EOT;
|
||||||
if (cmdhdr & CMD_IE) t = t | XS0_IE;
|
if (cmdhdr & CMD_IE) t = t | XS0_IE;
|
||||||
return t;
|
return t;
|
||||||
|
@ -933,7 +885,7 @@ t_stat ts_reset (DEVICE *dptr)
|
||||||
{
|
{
|
||||||
int32 i;
|
int32 i;
|
||||||
|
|
||||||
ts_unit.pos = 0;
|
sim_tape_rewind (&ts_unit);
|
||||||
tsba = tsdbx = 0;
|
tsba = tsdbx = 0;
|
||||||
ts_ownc = ts_ownm = 0;
|
ts_ownc = ts_ownm = 0;
|
||||||
ts_bcmd = 0;
|
ts_bcmd = 0;
|
||||||
|
@ -955,7 +907,7 @@ t_stat ts_attach (UNIT *uptr, char *cptr)
|
||||||
{
|
{
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
r = attach_unit (uptr, cptr); /* attach unit */
|
r = sim_tape_attach (uptr, cptr); /* attach unit */
|
||||||
if (r != SCPE_OK) return r; /* error? */
|
if (r != SCPE_OK) return r; /* error? */
|
||||||
tssr = tssr & ~TSSR_OFL; /* clr offline */
|
tssr = tssr & ~TSSR_OFL; /* clr offline */
|
||||||
if ((tssr & TSSR_NBA) || !(wchopt & WCH_EAI)) return r; /* attn msg? */
|
if ((tssr & TSSR_NBA) || !(wchopt & WCH_EAI)) return r; /* attn msg? */
|
||||||
|
@ -973,7 +925,7 @@ t_stat ts_detach (UNIT* uptr)
|
||||||
{
|
{
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
r = detach_unit (uptr); /* detach unit */
|
r = sim_tape_detach (uptr); /* detach unit */
|
||||||
if (r != SCPE_OK) return r; /* error? */
|
if (r != SCPE_OK) return r; /* error? */
|
||||||
tssr = tssr | TSSR_OFL; /* set offline */
|
tssr = tssr | TSSR_OFL; /* set offline */
|
||||||
if ((tssr & TSSR_NBA) || !(wchopt & WCH_EAI)) return r; /* attn msg? */
|
if ((tssr & TSSR_NBA) || !(wchopt & WCH_EAI)) return r; /* attn msg? */
|
||||||
|
@ -1036,7 +988,7 @@ t_stat ts_boot (int32 unitno, DEVICE *dptr)
|
||||||
int32 i;
|
int32 i;
|
||||||
extern int32 saved_PC;
|
extern int32 saved_PC;
|
||||||
|
|
||||||
ts_unit.pos = 0;
|
sim_tape_rewind (&ts_unit);
|
||||||
for (i = 0; i < BOOT_LEN; i++)
|
for (i = 0; i < BOOT_LEN; i++)
|
||||||
M[(BOOT_START >> 1) + i] = boot_rom[i];
|
M[(BOOT_START >> 1) + i] = boot_rom[i];
|
||||||
M[BOOT_CSR0 >> 1] = ts_dib.ba & DMASK;
|
M[BOOT_CSR0 >> 1] = ts_dib.ba & DMASK;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* pdp18b_cpu.c: 18b PDP CPU simulator
|
/* pdp18b_cpu.c: 18b PDP CPU simulator
|
||||||
|
|
||||||
Copyright (c) 1993-2002, Robert M Supnik
|
Copyright (c) 1993-2003, Robert M Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
cpu PDP-4/7/9/15 central processor
|
cpu PDP-4/7/9/15 central processor
|
||||||
|
|
||||||
|
18-Feb-03 RMS Fixed three EAE bugs (found by Hans Pufal)
|
||||||
05-Oct-02 RMS Added DIBs, device number support
|
05-Oct-02 RMS Added DIBs, device number support
|
||||||
25-Jul-02 RMS Added DECtape support for PDP-4
|
25-Jul-02 RMS Added DECtape support for PDP-4
|
||||||
06-Jan-02 RMS Revised enable/disable support
|
06-Jan-02 RMS Revised enable/disable support
|
||||||
|
@ -1076,11 +1077,11 @@ case 033: case 032: /* EAE */
|
||||||
if (IR & 0001000) LAC = LAC & 01000000; /* IR<8>? clear AC */
|
if (IR & 0001000) LAC = LAC & 01000000; /* IR<8>? clear AC */
|
||||||
link_init = LAC & 01000000; /* link temporary */
|
link_init = LAC & 01000000; /* link temporary */
|
||||||
fill = link_init? 0777777: 0; /* fill = link */
|
fill = link_init? 0777777: 0; /* fill = link */
|
||||||
esc = (IR & 077)? IR & 077: 0100; /* get eff SC */
|
esc = IR & 077; /* get eff SC */
|
||||||
|
|
||||||
switch ((IR >> 6) & 07) { /* case on IR<9:11> */
|
switch ((IR >> 6) & 07) { /* case on IR<9:11> */
|
||||||
case 0: /* setup */
|
case 0: /* setup */
|
||||||
if (IR & 04) LAC = LAC ^ 0777777; /* IR<15>? ~AC */
|
if (IR & 04) MQ = MQ ^ 0777777; /* IR<15>? ~MQ */
|
||||||
if (IR & 02) LAC = LAC | MQ; /* IR<16>? or MQ */
|
if (IR & 02) LAC = LAC | MQ; /* IR<16>? or MQ */
|
||||||
if (IR & 01) LAC = LAC | ((-SC) & 077); /* IR<17>? or SC */
|
if (IR & 01) LAC = LAC | ((-SC) & 077); /* IR<17>? or SC */
|
||||||
break;
|
break;
|
||||||
|
@ -1091,10 +1092,13 @@ case 033: case 032: /* EAE */
|
||||||
PC = INCR_ADDR (PC); /* increment PC */
|
PC = INCR_ADDR (PC); /* increment PC */
|
||||||
if (eae_ac_sign) MQ = MQ ^ 0777777; /* EAE AC sign? ~MQ */
|
if (eae_ac_sign) MQ = MQ ^ 0777777; /* EAE AC sign? ~MQ */
|
||||||
LAC = LAC & 0777777; /* clear link */
|
LAC = LAC & 0777777; /* clear link */
|
||||||
for (SC = esc; SC != 0; SC--) { /* loop per step cnt */
|
SC = esc; /* init SC */
|
||||||
|
do { /* loop */
|
||||||
if (MQ & 1) LAC = LAC + MA; /* MQ<17>? add */
|
if (MQ & 1) LAC = LAC + MA; /* MQ<17>? add */
|
||||||
MQ = (MQ >> 1) | ((LAC & 1) << 17);
|
MQ = (MQ >> 1) | ((LAC & 1) << 17);
|
||||||
LAC = LAC >> 1; } /* shift AC'MQ right */
|
LAC = LAC >> 1; /* shift AC'MQ right */
|
||||||
|
SC = (SC - 1) & 077; } /* decrement SC */
|
||||||
|
while (SC != 0); /* until SC = 0 */
|
||||||
if (eae_ac_sign ^ link_init) { /* result negative? */
|
if (eae_ac_sign ^ link_init) { /* result negative? */
|
||||||
LAC = LAC ^ 0777777;
|
LAC = LAC ^ 0777777;
|
||||||
MQ = MQ ^ 0777777; }
|
MQ = MQ ^ 0777777; }
|
||||||
|
@ -1121,16 +1125,19 @@ case 033: case 032: /* EAE */
|
||||||
break; }
|
break; }
|
||||||
LAC = LAC & 0777777; /* clear link */
|
LAC = LAC & 0777777; /* clear link */
|
||||||
t = 0; /* init loop */
|
t = 0; /* init loop */
|
||||||
for (SC = esc; SC != 0; SC--) { /* loop per step cnt */
|
SC = esc; /* init SC */
|
||||||
|
do { /* loop */
|
||||||
if (t) LAC = (LAC + MA) & 01777777;
|
if (t) LAC = (LAC + MA) & 01777777;
|
||||||
else LAC = (LAC - MA) & 01777777;
|
else LAC = (LAC - MA) & 01777777;
|
||||||
t = (LAC >> 18) & 1; /* quotient bit */
|
t = (LAC >> 18) & 1; /* quotient bit */
|
||||||
if (SC > 1) LAC = /* skip if last */
|
if (SC > 1) LAC = /* skip if last */
|
||||||
((LAC << 1) | (MQ >> 17)) & 01777777;
|
((LAC << 1) | (MQ >> 17)) & 01777777;
|
||||||
MQ = ((MQ << 1) | t) & 0777777; }
|
MQ = ((MQ << 1) | t) & 0777777; /* shift in quo bit */
|
||||||
|
SC = (SC - 1) & 077; } /* decrement SC */
|
||||||
|
while (SC != 0); /* until SC = 0 */
|
||||||
if (t) LAC = (LAC + MA) & 01777777;
|
if (t) LAC = (LAC + MA) & 01777777;
|
||||||
if (eae_ac_sign) LAC = LAC ^ 0777777; /* sgn rem = sgn divd */
|
if (eae_ac_sign) LAC = LAC ^ 0777777; /* sgn rem = sgn divd */
|
||||||
if (eae_ac_sign ^ link_init ^ 1) MQ = MQ ^ 0777777;
|
if ((eae_ac_sign ^ link_init) == 0) MQ = MQ ^ 0777777;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* EAE, continued
|
/* EAE, continued
|
||||||
|
@ -1144,14 +1151,16 @@ case 033: case 032: /* EAE */
|
||||||
#if defined (PDP15)
|
#if defined (PDP15)
|
||||||
if (!usmd) ion_defer = 2; /* free cycles */
|
if (!usmd) ion_defer = 2; /* free cycles */
|
||||||
#endif
|
#endif
|
||||||
for (SC = esc; (SC != 0) && ((LAC & 0400000) ==
|
for (SC = esc; ((LAC & 0400000) == ((LAC << 1) & 0400000)); ) {
|
||||||
((LAC << 1) & 0400000)); SC--) {
|
|
||||||
LAC = (LAC << 1) | ((MQ >> 17) & 1);
|
LAC = (LAC << 1) | ((MQ >> 17) & 1);
|
||||||
MQ = (MQ << 1) | (link_init >> 18); }
|
MQ = (MQ << 1) | (link_init >> 18);
|
||||||
|
SC = (SC - 1) & 077;
|
||||||
|
if (SC == 0) break; }
|
||||||
LAC = link_init | (LAC & 0777777); /* trim AC, restore L */
|
LAC = link_init | (LAC & 0777777); /* trim AC, restore L */
|
||||||
MQ = MQ & 0777777; /* trim MQ */
|
MQ = MQ & 0777777; /* trim MQ */
|
||||||
SC = SC & 077; /* trim SC */
|
SC = SC & 077; /* trim SC */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5: /* long right shift */
|
case 5: /* long right shift */
|
||||||
if (esc < 18) {
|
if (esc < 18) {
|
||||||
MQ = ((LAC << (18 - esc)) | (MQ >> esc)) & 0777777;
|
MQ = ((LAC << (18 - esc)) | (MQ >> esc)) & 0777777;
|
||||||
|
@ -1163,6 +1172,7 @@ case 033: case 032: /* EAE */
|
||||||
LAC = link_init | fill; }
|
LAC = link_init | fill; }
|
||||||
SC = 0; /* clear step count */
|
SC = 0; /* clear step count */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6: /* long left shift */
|
case 6: /* long left shift */
|
||||||
if (esc < 18) {
|
if (esc < 18) {
|
||||||
LAC = link_init |
|
LAC = link_init |
|
||||||
|
@ -1175,6 +1185,7 @@ case 033: case 032: /* EAE */
|
||||||
MQ = fill; }
|
MQ = fill; }
|
||||||
SC = 0; /* clear step count */
|
SC = 0; /* clear step count */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 7: /* AC left shift */
|
case 7: /* AC left shift */
|
||||||
if (esc < 18) LAC = link_init |
|
if (esc < 18) LAC = link_init |
|
||||||
(((LAC << esc) | (fill >> (18 - esc))) & 0777777);
|
(((LAC << esc) | (fill >> (18 - esc))) & 0777777);
|
||||||
|
|
|
@ -327,6 +327,12 @@ implements these registers:
|
||||||
POS 32 number of characters input
|
POS 32 number of characters input
|
||||||
TIME 24 keyboard polling interval
|
TIME 24 keyboard polling interval
|
||||||
|
|
||||||
|
If the simulator is compiled under Windows Visual C++, typing ^C to the
|
||||||
|
terminal input causes a fatal run-time error. Use the following command
|
||||||
|
to simulate typing ^C:
|
||||||
|
|
||||||
|
SET TTI CTRL-C
|
||||||
|
|
||||||
2.2.4 Terminal Output (TTO)
|
2.2.4 Terminal Output (TTO)
|
||||||
|
|
||||||
The terminal output (TTO) writes to the simulator console window. It
|
The terminal output (TTO) writes to the simulator console window. It
|
||||||
|
@ -419,7 +425,14 @@ For all printers, error handling is as follows:
|
||||||
|
|
||||||
2.2.6 Real-Time Clock (CLK)
|
2.2.6 Real-Time Clock (CLK)
|
||||||
|
|
||||||
The real-time clock (CLK) implements these registers:
|
The real-time clock (CLK) frequency can be adjusted as follows:
|
||||||
|
|
||||||
|
SET CLK 60HZ set frequency to 60Hz
|
||||||
|
SET CLK 50HZ set frequency to 50Hz
|
||||||
|
|
||||||
|
The default is 60Hz.
|
||||||
|
|
||||||
|
The clock implements these registers:
|
||||||
|
|
||||||
name size comments
|
name size comments
|
||||||
|
|
||||||
|
@ -427,7 +440,6 @@ The real-time clock (CLK) implements these registers:
|
||||||
DONE 1 device done flag
|
DONE 1 device done flag
|
||||||
ENABLE 1 clock enable
|
ENABLE 1 clock enable
|
||||||
TIME 24 clock frequency
|
TIME 24 clock frequency
|
||||||
TPS 8 ticks per second (60 or 50)
|
|
||||||
|
|
||||||
The real-time clock autocalibrates; the clock interval is adjusted up or
|
The real-time clock autocalibrates; the clock interval is adjusted up or
|
||||||
down so that the clock tracks actual elapsed time.
|
down so that the clock tracks actual elapsed time.
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
mt (PDP-9) TC59 magtape
|
mt (PDP-9) TC59 magtape
|
||||||
(PDP-15) TC59D magtape
|
(PDP-15) TC59D magtape
|
||||||
|
|
||||||
|
01-Mar-03 RMS Fixed bug in interrupt handling
|
||||||
|
Revised for magtape library
|
||||||
02-Feb-03 RMS Revised IOT decoding
|
02-Feb-03 RMS Revised IOT decoding
|
||||||
30-Oct-02 RMS Revised BOT handling, added error record handling
|
30-Oct-02 RMS Revised BOT handling, added error record handling
|
||||||
05-Oct-02 RMS Added DIB, device number support
|
05-Oct-02 RMS Added DIB, device number support
|
||||||
|
@ -59,19 +61,15 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pdp18b_defs.h"
|
#include "pdp18b_defs.h"
|
||||||
|
#include "sim_tape.h"
|
||||||
|
|
||||||
#define MT_NUMDR 8 /* #drives */
|
#define MT_NUMDR 8 /* #drives */
|
||||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
|
||||||
#define UNIT_V_PNU (UNIT_V_UF + 1) /* pos not updated */
|
|
||||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
|
||||||
#define UNIT_PNU (1 << UNIT_V_PNU)
|
|
||||||
#define USTAT u3 /* unit status */
|
#define USTAT u3 /* unit status */
|
||||||
#define MT_MAXFR (1 << 16) /* max record length */
|
#define MT_MAXFR (1 << 16) /* max record length */
|
||||||
#define DBSIZE (1 << 12) /* max word count */
|
|
||||||
#define DBMASK (DBSIZE - 1)
|
|
||||||
#define MT_WC 032 /* word count */
|
#define MT_WC 032 /* word count */
|
||||||
#define MT_CA 033 /* current addr */
|
#define MT_CA 033 /* current addr */
|
||||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
#define WC_SIZE (1 << 12) /* max word count */
|
||||||
|
#define WC_MASK (WC_SIZE - 1)
|
||||||
|
|
||||||
/* Command/unit - mt_cu */
|
/* Command/unit - mt_cu */
|
||||||
|
|
||||||
|
@ -117,9 +115,6 @@
|
||||||
#define STA_CLR 0000077 /* always clear */
|
#define STA_CLR 0000077 /* always clear */
|
||||||
#define STA_DYN (STA_REW | STA_BOT | STA_EOF | STA_EOT)
|
#define STA_DYN (STA_REW | STA_BOT | STA_EOF | STA_EOT)
|
||||||
/* kept in USTAT */
|
/* kept in USTAT */
|
||||||
#define STA_EFLGS (STA_BOT | STA_ILL | STA_PAR | STA_EOF | \
|
|
||||||
STA_EOT | STA_CPE | STA_RLE | STA_DLT | STA_BAD)
|
|
||||||
/* error flags */
|
|
||||||
|
|
||||||
extern int32 M[];
|
extern int32 M[];
|
||||||
extern int32 int_hwre[API_HLVL+1];
|
extern int32 int_hwre[API_HLVL+1];
|
||||||
|
@ -129,6 +124,7 @@ int32 mt_cu = 0; /* command/unit */
|
||||||
int32 mt_sta = 0; /* status register */
|
int32 mt_sta = 0; /* status register */
|
||||||
int32 mt_time = 10; /* record latency */
|
int32 mt_time = 10; /* record latency */
|
||||||
int32 mt_stopioe = 1; /* stop on error */
|
int32 mt_stopioe = 1; /* stop on error */
|
||||||
|
uint8 *mtxb = NULL; /* transfer buffer */
|
||||||
|
|
||||||
DEVICE mt_dev;
|
DEVICE mt_dev;
|
||||||
int32 mt (int32 pulse, int32 AC);
|
int32 mt (int32 pulse, int32 AC);
|
||||||
|
@ -138,8 +134,7 @@ t_stat mt_reset (DEVICE *dptr);
|
||||||
t_stat mt_attach (UNIT *uptr, char *cptr);
|
t_stat mt_attach (UNIT *uptr, char *cptr);
|
||||||
t_stat mt_detach (UNIT *uptr);
|
t_stat mt_detach (UNIT *uptr);
|
||||||
int32 mt_updcsta (UNIT *uptr, int32 val);
|
int32 mt_updcsta (UNIT *uptr, int32 val);
|
||||||
t_bool mt_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
t_stat mt_map_err (UNIT *uptr, t_stat st);
|
||||||
t_bool mt_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
|
||||||
UNIT *mt_busy (void);
|
UNIT *mt_busy (void);
|
||||||
|
|
||||||
/* MT data structures
|
/* MT data structures
|
||||||
|
@ -177,8 +172,8 @@ REG mt_reg[] = {
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
MTAB mt_mod[] = {
|
MTAB mt_mod[] = {
|
||||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
|
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
|
||||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno },
|
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
|
||||||
|
@ -221,9 +216,9 @@ if (pulse & 04) {
|
||||||
sim_is_active (uptr) ||
|
sim_is_active (uptr) ||
|
||||||
(f == FN_NOP) ||
|
(f == FN_NOP) ||
|
||||||
(((f == FN_SPACER) || (f == FN_REWIND)) && (uptr->USTAT & STA_BOT)) ||
|
(((f == FN_SPACER) || (f == FN_REWIND)) && (uptr->USTAT & STA_BOT)) ||
|
||||||
(((f == FN_WRITE) || (f == FN_WREOF)) && (uptr->flags & UNIT_WPRT)) ||
|
(((f == FN_WRITE) || (f == FN_WREOF)) && sim_tape_wrp (uptr)) ||
|
||||||
((uptr->flags & UNIT_ATT) == 0))
|
((uptr->flags & UNIT_ATT) == 0))
|
||||||
mt_sta = mt_sta | STA_ILL; /* illegal op flag */
|
mt_sta = mt_sta | STA_ILL | STA_ERR; /* set illegal op */
|
||||||
else {
|
else {
|
||||||
if (f == FN_REWIND) uptr->USTAT = STA_REW; /* rewind? */
|
if (f == FN_REWIND) uptr->USTAT = STA_REW; /* rewind? */
|
||||||
else mt_sta = uptr->USTAT = 0; /* no, clear status */
|
else mt_sta = uptr->USTAT = 0; /* no, clear status */
|
||||||
|
@ -243,20 +238,17 @@ return AC;
|
||||||
|
|
||||||
t_stat mt_svc (UNIT *uptr)
|
t_stat mt_svc (UNIT *uptr)
|
||||||
{
|
{
|
||||||
int32 c, c1, c2, c3, f, i, p, u, err, pnu;
|
int32 c, c1, c2, c3, f, i, p, u;
|
||||||
int32 wc, xma;
|
int32 wc, xma;
|
||||||
t_mtrlnt abc, tbc, cbc;
|
t_mtrlnt tbc, cbc;
|
||||||
static uint8 dbuf[(3 * DBSIZE)];
|
t_stat st, r = SCPE_OK;
|
||||||
static t_mtrlnt bceof = MTR_TMK;
|
|
||||||
|
|
||||||
err = 0;
|
|
||||||
u = uptr - mt_dev.units; /* get unit number */
|
u = uptr - mt_dev.units; /* get unit number */
|
||||||
f = GET_CMD (mt_cu); /* get command */
|
f = GET_CMD (mt_cu); /* get command */
|
||||||
pnu = MT_TST_PNU (uptr); /* get pos not upd */
|
wc = WC_SIZE - (M[MT_WC] & WC_MASK); /* word count is 12b */
|
||||||
MT_CLR_PNU (uptr); /* and clear */
|
|
||||||
|
|
||||||
if (uptr->USTAT & STA_REW) { /* rewind? */
|
if (uptr->USTAT & STA_REW) { /* rewind? */
|
||||||
uptr->pos = 0; /* update position */
|
sim_tape_rewind (uptr); /* rewind tape */
|
||||||
if (uptr->flags & UNIT_ATT) uptr->USTAT = STA_BOT;
|
if (uptr->flags & UNIT_ATT) uptr->USTAT = STA_BOT;
|
||||||
else uptr->USTAT = 0;
|
else uptr->USTAT = 0;
|
||||||
if (u == GET_UNIT (mt_cu)) mt_updcsta (uptr, STA_DON);
|
if (u == GET_UNIT (mt_cu)) mt_updcsta (uptr, STA_DON);
|
||||||
|
@ -266,124 +258,103 @@ if ((uptr->flags & UNIT_ATT) == 0) { /* if not attached */
|
||||||
mt_updcsta (uptr, STA_ILL); /* illegal operation */
|
mt_updcsta (uptr, STA_ILL); /* illegal operation */
|
||||||
return IORETURN (mt_stopioe, SCPE_UNATT); }
|
return IORETURN (mt_stopioe, SCPE_UNATT); }
|
||||||
|
|
||||||
if ((f == FN_WRITE) || (f == FN_WREOF)) { /* write? */
|
|
||||||
if (uptr->flags & UNIT_WPRT) { /* write locked? */
|
|
||||||
mt_updcsta (uptr, STA_ILL); /* illegal operation */
|
|
||||||
return SCPE_OK; }
|
|
||||||
mt_cu = mt_cu & ~CU_ERASE; } /* clear erase flag */
|
|
||||||
|
|
||||||
switch (f) { /* case on function */
|
switch (f) { /* case on function */
|
||||||
|
|
||||||
/* Unit service, continued */
|
/* Unit service, continued */
|
||||||
|
|
||||||
case FN_READ: /* read */
|
case FN_READ: /* read */
|
||||||
case FN_CMPARE: /* read/compare */
|
case FN_CMPARE: /* read/compare */
|
||||||
if (mt_rdlntf (uptr, &tbc, &err)) { /* read rec lnt, err? */
|
st = sim_tape_rdrecf (uptr, mtxb, &tbc, MT_MAXFR); /* read rec */
|
||||||
mt_updcsta (uptr, STA_RLE); /* set RLE flag */
|
if (st == MTSE_RECE) mt_sta = mt_sta | STA_PAR | STA_ERR; /* rec in err? */
|
||||||
|
else if (st != MTSE_OK) { /* other error? */
|
||||||
|
mt_sta = mt_sta | STA_RLE | STA_ERR; /* set RLE flag */
|
||||||
|
r = mt_map_err (uptr, st); /* map error */
|
||||||
break; }
|
break; }
|
||||||
if (tbc > MT_MAXFR) return SCPE_MTRLNT; /* record too long? */
|
|
||||||
wc = DBSIZE - (M[MT_WC] & DBMASK); /* get word count */
|
|
||||||
cbc = PACKED (mt_cu)? wc * 3: wc * 2; /* expected bc */
|
cbc = PACKED (mt_cu)? wc * 3: wc * 2; /* expected bc */
|
||||||
if (tbc != cbc) mt_sta = mt_sta | STA_RLE; /* wrong size? */
|
if (tbc != cbc) mt_sta = mt_sta | STA_RLE | STA_ERR; /* wrong size? */
|
||||||
if (tbc < cbc) { /* record small? */
|
if (tbc < cbc) { /* record small? */
|
||||||
cbc = tbc; /* use smaller */
|
cbc = tbc; /* use smaller */
|
||||||
wc = PACKED (mt_cu)? ((tbc + 2) / 3): ((tbc + 1) / 2); }
|
wc = PACKED (mt_cu)? ((tbc + 2) / 3): ((tbc + 1) / 2); }
|
||||||
abc = fxread (dbuf, sizeof (int8), cbc, uptr->fileref);
|
|
||||||
if (err = ferror (uptr->fileref)) { /* error */
|
|
||||||
MT_SET_PNU (uptr); /* pos not upd */
|
|
||||||
break; }
|
|
||||||
for ( ; abc < cbc; abc++) dbuf[abc] = 0; /* fill with 0's */
|
|
||||||
for (i = p = 0; i < wc; i++) { /* copy buffer */
|
for (i = p = 0; i < wc; i++) { /* copy buffer */
|
||||||
M[MT_WC] = (M[MT_WC] + 1) & 0777777; /* inc WC, CA */
|
M[MT_WC] = (M[MT_WC] + 1) & 0777777; /* inc WC, CA */
|
||||||
M[MT_CA] = (M[MT_CA] + 1) & 0777777;
|
M[MT_CA] = (M[MT_CA] + 1) & 0777777;
|
||||||
xma = M[MT_CA] & ADDRMASK;
|
xma = M[MT_CA] & ADDRMASK;
|
||||||
if (PACKED (mt_cu)) { /* packed? */
|
if (PACKED (mt_cu)) { /* packed? */
|
||||||
c1 = dbuf[p++] & 077;
|
c1 = mtxb[p++] & 077;
|
||||||
c2 = dbuf[p++] & 077;
|
c2 = mtxb[p++] & 077;
|
||||||
c3 = dbuf[p++] & 077;
|
c3 = mtxb[p++] & 077;
|
||||||
c = (c1 << 12) | (c2 << 6) | c3; }
|
c = (c1 << 12) | (c2 << 6) | c3; }
|
||||||
else {
|
else {
|
||||||
c1 = dbuf[p++];
|
c1 = mtxb[p++];
|
||||||
c2 = dbuf[p++];
|
c2 = mtxb[p++];
|
||||||
c = (c1 << 8) | c2; }
|
c = (c1 << 8) | c2; }
|
||||||
if ((f == FN_READ) && MEM_ADDR_OK (xma)) M[xma] = c;
|
if ((f == FN_READ) && MEM_ADDR_OK (xma)) M[xma] = c;
|
||||||
else if ((f == FN_CMPARE) && (c != (M[xma] &
|
else if ((f == FN_CMPARE) && (c != (M[xma] &
|
||||||
(PACKED (mt_cu)? 0777777: 0177777)))) {
|
(PACKED (mt_cu)? 0777777: 0177777)))) {
|
||||||
mt_updcsta (uptr, STA_CPE);
|
mt_updcsta (uptr, STA_CPE);
|
||||||
break; } }
|
break; } }
|
||||||
uptr->pos = uptr->pos + ((tbc + 1) & ~1) +
|
|
||||||
(2 * sizeof (t_mtrlnt));
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FN_WRITE: /* write */
|
case FN_WRITE: /* write */
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
|
||||||
wc = DBSIZE - (M[MT_WC] & DBMASK); /* get word count */
|
|
||||||
tbc = PACKED (mt_cu)? wc * 3: wc * 2;
|
tbc = PACKED (mt_cu)? wc * 3: wc * 2;
|
||||||
fxwrite (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
xma = M[MT_CA] & ADDRMASK; /* get mem addr */
|
||||||
for (i = p = 0; i < wc; i++) { /* copy buf to tape */
|
for (i = p = 0; i < wc; i++) { /* copy buf to tape */
|
||||||
M[MT_WC] = (M[MT_WC] + 1) & 0777777; /* inc WC, CA */
|
xma = (xma + 1) & ADDRMASK; /* incr mem addr */
|
||||||
M[MT_CA] = (M[MT_CA] + 1) & 0777777;
|
|
||||||
xma = M[MT_CA] & ADDRMASK;
|
|
||||||
if (PACKED (mt_cu)) { /* packed? */
|
if (PACKED (mt_cu)) { /* packed? */
|
||||||
dbuf[p++] = (M[xma] >> 12) & 077;
|
mtxb[p++] = (M[xma] >> 12) & 077;
|
||||||
dbuf[p++] = (M[xma] >> 6) & 077;
|
mtxb[p++] = (M[xma] >> 6) & 077;
|
||||||
dbuf[p++] = M[xma] & 077; }
|
mtxb[p++] = M[xma] & 077; }
|
||||||
else {
|
else {
|
||||||
dbuf[p++] = (M[xma] >> 8) & 0377;
|
mtxb[p++] = (M[xma] >> 8) & 0377;
|
||||||
dbuf[p++] = M[xma] & 0377; } }
|
mtxb[p++] = M[xma] & 0377; } }
|
||||||
fxwrite (dbuf, sizeof (char), (tbc + 1) & ~1, uptr->fileref);
|
if (st = sim_tape_wrrecf (uptr, mtxb, tbc)) /* write rec, err? */
|
||||||
fxwrite (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
r = mt_map_err (uptr, st); /* map error */
|
||||||
if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr); /* error? */
|
else {
|
||||||
else uptr->pos = uptr->pos + ((tbc + 1) & ~1) + /* no, upd pos */
|
M[MT_CA] = (M[MT_CA] + wc) & 0777777; /* advance mem addr */
|
||||||
(2 * sizeof (t_mtrlnt));
|
M[MT_WC] = 0; } /* clear word cnt */
|
||||||
|
mt_cu = mt_cu & ~CU_ERASE; /* clear erase flag */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Unit service, continued */
|
/* Unit service, continued */
|
||||||
|
|
||||||
case FN_WREOF:
|
case FN_WREOF:
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
|
||||||
fxwrite (&bceof, sizeof (t_mtrlnt), 1, uptr->fileref);
|
r = mt_map_err (uptr, st); /* map error */
|
||||||
uptr->USTAT = STA_EOF;
|
else uptr->USTAT = STA_EOF;
|
||||||
if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr); /* error? */
|
mt_cu = mt_cu & ~CU_ERASE; /* clear erase flag */
|
||||||
else uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* no, upd pos */
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FN_SPACEF: /* space forward */
|
case FN_SPACEF: /* space forward */
|
||||||
do {
|
do {
|
||||||
M[MT_WC] = (M[MT_WC] + 1) & 0777777; /* inc WC */
|
M[MT_WC] = (M[MT_WC] + 1) & 0777777; /* inc WC */
|
||||||
if (mt_rdlntf (uptr, &tbc, &err)) break; /* read rec lnt, err? */
|
if (st = sim_tape_sprecf (uptr, &tbc)) { /* space rec fwd, err? */
|
||||||
uptr->pos = uptr->pos + ((tbc + 1) & ~1) +
|
r = mt_map_err (uptr, st); /* map error */
|
||||||
(2 * sizeof (t_mtrlnt)); }
|
break; }
|
||||||
|
}
|
||||||
while (M[MT_WC] != 0);
|
while (M[MT_WC] != 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FN_SPACER: /* space reverse */
|
case FN_SPACER: /* space reverse */
|
||||||
do {
|
do {
|
||||||
M[MT_WC] = (M[MT_WC] + 1) & 0777777; /* inc WC */
|
M[MT_WC] = (M[MT_WC] + 1) & 0777777; /* inc WC */
|
||||||
if (pnu) pnu = 0; /* pos not upd? */
|
if (st = sim_tape_sprecr (uptr, &tbc)) { /* space rec rev, err? */
|
||||||
else {
|
r = mt_map_err (uptr, st); /* map error */
|
||||||
if (mt_rdlntf (uptr, &tbc, &err)) break;
|
break; }
|
||||||
uptr->pos = uptr->pos - ((tbc + 1) & ~1) -
|
}
|
||||||
(2 * sizeof (t_mtrlnt)); } }
|
|
||||||
while (M[MT_WC] != 0);
|
while (M[MT_WC] != 0);
|
||||||
break; } /* end case */
|
break; } /* end case */
|
||||||
|
|
||||||
mt_updcsta (uptr, STA_DON | (err? STA_PAR: 0)); /* set done */
|
mt_updcsta (uptr, STA_DON); /* set done */
|
||||||
if (err != 0) { /* I/O error? */
|
return r;
|
||||||
perror ("MT I/O error");
|
|
||||||
clearerr (uptr->fileref);
|
|
||||||
if (mt_stopioe) return SCPE_IOERR; }
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update controller status */
|
/* Update controller status */
|
||||||
|
|
||||||
int32 mt_updcsta (UNIT *uptr, int32 news)
|
int32 mt_updcsta (UNIT *uptr, int32 news)
|
||||||
{
|
{
|
||||||
mt_sta = (mt_sta & ~(STA_DYN | STA_ERR | STA_CLR)) |
|
mt_sta = (mt_sta & ~(STA_DYN | STA_CLR)) |
|
||||||
(uptr->USTAT & STA_DYN) | news;
|
(uptr->USTAT & STA_DYN) | news;
|
||||||
if (mt_sta & STA_EFLGS) mt_sta = mt_sta | STA_ERR; /* error flag */
|
if ((mt_sta & (STA_ERR | STA_DON)) && (mt_cu & CU_IE))
|
||||||
if ((mt_sta & (STA_ERR | STA_DON)) && ((mt_cu & CU_IE) == 0))
|
|
||||||
SET_INT (MTA);
|
SET_INT (MTA);
|
||||||
else CLR_INT (MTA); /* int request */
|
else CLR_INT (MTA); /* int request */
|
||||||
return mt_sta;
|
return mt_sta;
|
||||||
|
@ -403,55 +374,41 @@ for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read record length forward - return status flag if err, EOM, or EOF */
|
/* Map tape error status */
|
||||||
|
|
||||||
t_bool mt_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
t_stat mt_map_err (UNIT *uptr, t_stat st)
|
||||||
{
|
{
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set tape pos */
|
switch (st) {
|
||||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref); /* read rec lnt */
|
case MTSE_FMT: /* illegal fmt */
|
||||||
if (*err = ferror (uptr->fileref)) { /* error? */
|
case MTSE_UNATT: /* not attached */
|
||||||
mt_sta = mt_sta | STA_PAR; /* set flag */
|
mt_sta = mt_sta | STA_ILL | STA_ERR;
|
||||||
MT_SET_PNU (uptr); /* pos not upd */
|
case MTSE_OK: /* no error */
|
||||||
return TRUE; }
|
return SCPE_IERR;
|
||||||
if (feof (uptr->fileref) || (*tbc == MTR_EOM)) { /* eof or eom? */
|
case MTSE_TMK: /* end of file */
|
||||||
mt_sta = mt_sta | STA_BAD; /* bad tape */
|
uptr->USTAT = uptr->USTAT | STA_EOF; /* set EOF */
|
||||||
MT_SET_PNU (uptr); /* pos not upd */
|
mt_sta = mt_sta | STA_ERR;
|
||||||
return TRUE; }
|
break;
|
||||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
case MTSE_IOERR: /* IO error */
|
||||||
uptr->USTAT = uptr->USTAT | STA_EOF; /* end of file */
|
mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */
|
||||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* spc over tmk */
|
if (mt_stopioe) return SCPE_IOERR;
|
||||||
return TRUE; }
|
break;
|
||||||
if (MTRF (*tbc)) mt_sta = mt_sta | STA_PAR; /* record in error? */
|
case MTSE_INVRL: /* invalid rec lnt */
|
||||||
*tbc = MTRL (*tbc); /* clear error flag */
|
mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */
|
||||||
return FALSE;
|
return SCPE_MTRLNT;
|
||||||
}
|
case MTSE_RECE: /* record in error */
|
||||||
|
mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */
|
||||||
/* Read record length reverse - return status flag if err, EOM, or EOF */
|
break;
|
||||||
|
case MTSE_EOM: /* end of medium */
|
||||||
int32 mt_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
mt_sta = mt_sta | STA_BAD | STA_ERR; /* set bad tape */
|
||||||
{
|
break;
|
||||||
if (uptr->pos < sizeof (t_mtrlnt)) { /* at BOT? */
|
case MTSE_BOT: /* reverse into BOT */
|
||||||
uptr->USTAT = STA_BOT; /* set status */
|
uptr->USTAT = uptr->USTAT | STA_BOT; /* set status */
|
||||||
return TRUE; } /* error */
|
mt_sta = mt_sta | STA_ERR;
|
||||||
fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET);
|
break;
|
||||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
case MTSE_WRP: /* write protect */
|
||||||
if (*err = ferror (uptr->fileref)) { /* error? */
|
mt_sta = mt_sta | STA_ILL | STA_ERR; /* illegal operation */
|
||||||
mt_sta = mt_sta | STA_PAR; /* set flag */
|
break; }
|
||||||
return TRUE; }
|
return SCPE_OK;
|
||||||
if (feof (uptr->fileref)) { /* eof? */
|
|
||||||
mt_sta = mt_sta | STA_BAD; /* bad tape */
|
|
||||||
return TRUE; }
|
|
||||||
if (*tbc == MTR_EOM) { /* eom? */
|
|
||||||
mt_sta = mt_sta | STA_BAD; /* bad tape */
|
|
||||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over eom */
|
|
||||||
return TRUE; }
|
|
||||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
|
||||||
uptr->USTAT = uptr->USTAT | STA_EOF; /* end of file */
|
|
||||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over tmk */
|
|
||||||
return TRUE; }
|
|
||||||
if (MTRF (*tbc)) mt_sta = mt_sta | STA_PAR; /* record in error? */
|
|
||||||
*tbc = MTRL (*tbc); /* clear error flag */
|
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset routine */
|
/* Reset routine */
|
||||||
|
@ -464,11 +421,13 @@ UNIT *uptr;
|
||||||
mt_cu = mt_sta = 0;
|
mt_cu = mt_sta = 0;
|
||||||
for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */
|
for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */
|
||||||
uptr = mt_dev.units + u;
|
uptr = mt_dev.units + u;
|
||||||
MT_CLR_PNU (uptr); /* clr pos not upd */
|
sim_tape_reset (uptr); /* reset tape */
|
||||||
sim_cancel (uptr); /* cancel activity */
|
sim_cancel (uptr); /* cancel activity */
|
||||||
if (uptr->flags & UNIT_ATT) uptr->USTAT = STA_BOT;
|
if (uptr->flags & UNIT_ATT) uptr->USTAT = STA_BOT;
|
||||||
else uptr->USTAT = 0; }
|
else uptr->USTAT = 0; }
|
||||||
mt_updcsta (&mt_unit[0], 0); /* update status */
|
mt_updcsta (&mt_unit[0], 0); /* update status */
|
||||||
|
if (mtxb == NULL) mtxb = calloc (MT_MAXFR, sizeof (uint8));
|
||||||
|
if (mtxb == NULL) return SCPE_MEM;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -485,9 +444,8 @@ t_stat mt_attach (UNIT *uptr, char *cptr)
|
||||||
{
|
{
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
r = attach_unit (uptr, cptr);
|
r = sim_tape_attach (uptr, cptr);
|
||||||
if (r != SCPE_OK) return r;
|
if (r != SCPE_OK) return r;
|
||||||
MT_CLR_PNU (uptr);
|
|
||||||
uptr->USTAT = STA_BOT;
|
uptr->USTAT = STA_BOT;
|
||||||
mt_updcsta (mt_dev.units + GET_UNIT (mt_cu), 0); /* update status */
|
mt_updcsta (mt_dev.units + GET_UNIT (mt_cu), 0); /* update status */
|
||||||
return r;
|
return r;
|
||||||
|
@ -497,8 +455,7 @@ return r;
|
||||||
|
|
||||||
t_stat mt_detach (UNIT* uptr)
|
t_stat mt_detach (UNIT* uptr)
|
||||||
{
|
{
|
||||||
MT_CLR_PNU (uptr);
|
|
||||||
if (!sim_is_active (uptr)) uptr->USTAT = 0;
|
if (!sim_is_active (uptr)) uptr->USTAT = 0;
|
||||||
mt_updcsta (mt_dev.units + GET_UNIT (mt_cu), 0); /* update status */
|
mt_updcsta (mt_dev.units + GET_UNIT (mt_cu), 0); /* update status */
|
||||||
return detach_unit (uptr);
|
return sim_tape_detach (uptr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,9 @@
|
||||||
rf (PDP-9) RF09/RF09
|
rf (PDP-9) RF09/RF09
|
||||||
(PDP-15) RF15/RS09
|
(PDP-15) RF15/RS09
|
||||||
|
|
||||||
05-Feb-03 RMS Fixed decode bugs, added variable and auto sizing
|
03-Mar-03 RMS Fixed autosizing
|
||||||
|
12-Feb-03 RMS Removed 8 platter sizing hack
|
||||||
|
05-Feb-03 RMS Fixed decode bugs, added variable and autosizing
|
||||||
05-Oct-02 RMS Added DIB, dev number support
|
05-Oct-02 RMS Added DIB, dev number support
|
||||||
06-Jan-02 RMS Revised enable/disable support
|
06-Jan-02 RMS Revised enable/disable support
|
||||||
25-Nov-01 RMS Revised interrupt structure
|
25-Nov-01 RMS Revised interrupt structure
|
||||||
|
@ -50,9 +52,11 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */
|
#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */
|
||||||
#define UNIT_V_MSIZE (UNIT_V_UF + 1) /* dummy mask */
|
#define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */
|
||||||
|
#define UNIT_M_PLAT 07
|
||||||
|
#define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1)
|
||||||
#define UNIT_AUTO (1 << UNIT_V_AUTO)
|
#define UNIT_AUTO (1 << UNIT_V_AUTO)
|
||||||
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
|
#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT)
|
||||||
|
|
||||||
/* Constants */
|
/* Constants */
|
||||||
|
|
||||||
|
@ -144,14 +148,14 @@ REG rf_reg[] = {
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
MTAB rf_mod[] = {
|
MTAB rf_mod[] = {
|
||||||
{ UNIT_MSIZE, 262144, NULL, "1P", &rf_set_size },
|
{ UNIT_PLAT, 0, NULL, "1P", &rf_set_size },
|
||||||
{ UNIT_MSIZE, 524288, NULL, "2P", &rf_set_size },
|
{ UNIT_PLAT, 1, NULL, "2P", &rf_set_size },
|
||||||
{ UNIT_MSIZE, 786432, NULL, "3P", &rf_set_size },
|
{ UNIT_PLAT, 2, NULL, "3P", &rf_set_size },
|
||||||
{ UNIT_MSIZE, 1048576, NULL, "4P", &rf_set_size },
|
{ UNIT_PLAT, 3, NULL, "4P", &rf_set_size },
|
||||||
{ UNIT_MSIZE, 1310720, NULL, "5P", &rf_set_size },
|
{ UNIT_PLAT, 4, NULL, "5P", &rf_set_size },
|
||||||
{ UNIT_MSIZE, 1572864, NULL, "6P", &rf_set_size },
|
{ UNIT_PLAT, 5, NULL, "6P", &rf_set_size },
|
||||||
{ UNIT_MSIZE, 1835008, NULL, "7P", &rf_set_size },
|
{ UNIT_PLAT, 6, NULL, "7P", &rf_set_size },
|
||||||
{ UNIT_MSIZE, 2097152, NULL, "8P", &rf_set_size },
|
{ UNIT_PLAT, 7, NULL, "8P", &rf_set_size },
|
||||||
{ UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL },
|
{ UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL },
|
||||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno },
|
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
@ -186,7 +190,7 @@ if (pulse & 02) {
|
||||||
else if (sb == 040) /* DSFX */
|
else if (sb == 040) /* DSFX */
|
||||||
rf_sta = rf_sta ^ (AC & (RFS_FNC | RFS_IE)); /* xor func */
|
rf_sta = rf_sta ^ (AC & (RFS_FNC | RFS_IE)); /* xor func */
|
||||||
else if (sb == 060) /* DRAH */
|
else if (sb == 060) /* DRAH */
|
||||||
AC = AC | (rf_da >> 18);
|
AC = AC | (rf_da >> 18) | ((rf_sta & RFS_NED)? 010: 0);
|
||||||
}
|
}
|
||||||
if (pulse & 04) {
|
if (pulse & 04) {
|
||||||
if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy sets PGE */
|
if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy sets PGE */
|
||||||
|
@ -200,7 +204,7 @@ if (pulse & 04) {
|
||||||
if (t < 0) t = t + RF_NUMWD; /* wrap around? */
|
if (t < 0) t = t + RF_NUMWD; /* wrap around? */
|
||||||
sim_activate (&rf_unit, t * rf_time); } } /* schedule op */
|
sim_activate (&rf_unit, t * rf_time); } } /* schedule op */
|
||||||
else if (sb == 060) { /* DLAH */
|
else if (sb == 060) { /* DLAH */
|
||||||
rf_da = (rf_da & 0777777) | ((AC & 017) << 18);
|
rf_da = (rf_da & 0777777) | ((AC & 07) << 18);
|
||||||
if ((t_addr) rf_da >= rf_unit.capac) /* for sizing */
|
if ((t_addr) rf_da >= rf_unit.capac) /* for sizing */
|
||||||
rf_updsta (RFS_NED); }
|
rf_updsta (RFS_NED); }
|
||||||
}
|
}
|
||||||
|
@ -300,19 +304,15 @@ return ((rf_sta & (RFS_ERR | RFS_DON))? IOS_RF: 0);
|
||||||
|
|
||||||
t_stat rf_attach (UNIT *uptr, char *cptr)
|
t_stat rf_attach (UNIT *uptr, char *cptr)
|
||||||
{
|
{
|
||||||
int32 p, d;
|
t_addr p, sz;
|
||||||
int32 ds_bytes = RF_DKSIZE * sizeof (int32);
|
t_addr ds_bytes = RF_DKSIZE * sizeof (int32);
|
||||||
|
|
||||||
if (uptr->flags & UNIT_AUTO) {
|
if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (cptr))) {
|
||||||
FILE *fp = fopen (cptr, "rb");
|
p = (sz + ds_bytes - 1) / ds_bytes;
|
||||||
if (fp == NULL) return SCPE_OPENERR;
|
if (p == 0) p = 1;
|
||||||
fseek (fp, 0, SEEK_END);
|
if (p > RF_NUMDK) p = RF_NUMDK; }
|
||||||
p = ftell (fp);
|
else p = UNIT_GETP (uptr->flags);
|
||||||
d = (p + ds_bytes - 1) / ds_bytes;
|
uptr->capac = p * RF_DKSIZE;
|
||||||
if (d == 0) d = 1;
|
|
||||||
if (d > RF_NUMDK) d = RF_NUMDK;
|
|
||||||
uptr->capac = d * RF_DKSIZE;
|
|
||||||
fclose (fp); }
|
|
||||||
return attach_unit (uptr, cptr);
|
return attach_unit (uptr, cptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,10 +320,9 @@ return attach_unit (uptr, cptr);
|
||||||
|
|
||||||
t_stat rf_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
t_stat rf_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
{
|
{
|
||||||
if ((val == 0) || (val > (RF_NUMDK * RF_DKSIZE)))
|
if ((val < 0) || (val > RF_NUMDK)) return SCPE_IERR;
|
||||||
return SCPE_IERR;
|
|
||||||
if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
|
if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
|
||||||
uptr->capac = val;
|
uptr->capac = (val + 1) * RF_DKSIZE;
|
||||||
uptr->flags = uptr->flags & ~UNIT_AUTO;
|
uptr->flags = uptr->flags & ~UNIT_AUTO;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* pdp18b_stddev.c: 18b PDP's standard devices
|
/* pdp18b_stddev.c: 18b PDP's standard devices
|
||||||
|
|
||||||
Copyright (c) 1993-2002, Robert M Supnik
|
Copyright (c) 1993-2003, Robert M Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -29,6 +29,7 @@
|
||||||
tto teleprinter
|
tto teleprinter
|
||||||
clk clock
|
clk clock
|
||||||
|
|
||||||
|
01-Mar-03 RMS Added SET/SHOW CLK FREQ support, SET TTI CTRL-C support
|
||||||
22-Dec-02 RMS Added break support
|
22-Dec-02 RMS Added break support
|
||||||
01-Nov-02 RMS Added 7B/8B support to terminal
|
01-Nov-02 RMS Added 7B/8B support to terminal
|
||||||
05-Oct-02 RMS Added DIBs, device number support, IORS call
|
05-Oct-02 RMS Added DIBs, device number support, IORS call
|
||||||
|
@ -96,6 +97,9 @@ t_stat ptr_detach (UNIT *uptr);
|
||||||
t_stat ptp_detach (UNIT *uptr);
|
t_stat ptp_detach (UNIT *uptr);
|
||||||
t_stat ptr_boot (int32 unitno, DEVICE *dptr);
|
t_stat ptr_boot (int32 unitno, DEVICE *dptr);
|
||||||
t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat tti_set_ctrlc (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
|
|
||||||
extern int32 upd_iors (void);
|
extern int32 upd_iors (void);
|
||||||
|
|
||||||
|
@ -115,10 +119,16 @@ REG clk_reg[] = {
|
||||||
{ FLDATA (DONE, int_hwre[API_CLK], INT_V_CLK) },
|
{ FLDATA (DONE, int_hwre[API_CLK], INT_V_CLK) },
|
||||||
{ FLDATA (ENABLE, clk_state, 0) },
|
{ FLDATA (ENABLE, clk_state, 0) },
|
||||||
{ DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT },
|
{ DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT },
|
||||||
{ DRDATA (TPS, clk_tps, 8), REG_NZ + PV_LEFT },
|
{ DRDATA (TPS, clk_tps, 8), PV_LEFT + REG_HRO },
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
MTAB clk_mod[] = {
|
MTAB clk_mod[] = {
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 50, NULL, "50HZ",
|
||||||
|
&clk_set_freq, NULL, NULL },
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 60, NULL, "60HZ",
|
||||||
|
&clk_set_freq, NULL, NULL },
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 0, "FREQUENCY", NULL,
|
||||||
|
NULL, &clk_show_freq, NULL },
|
||||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_devno },
|
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_devno },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
|
||||||
|
@ -273,8 +283,9 @@ MTAB tti_mod[] = {
|
||||||
{ UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode },
|
{ UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode },
|
||||||
{ UNIT_HDX, 0 , "full duplex", "FDX", NULL },
|
{ UNIT_HDX, 0 , "full duplex", "FDX", NULL },
|
||||||
{ UNIT_HDX, UNIT_HDX, "half duplex", "HDX", NULL },
|
{ UNIT_HDX, UNIT_HDX, "half duplex", "HDX", NULL },
|
||||||
|
{ MTAB_XTD|MTAB_VDV|MTAB_VUN, 0, NULL, "CTRL-C", &tti_set_ctrlc, NULL, NULL },
|
||||||
#endif
|
#endif
|
||||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_devno },
|
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_devno, NULL },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
|
||||||
DEVICE tti_dev = {
|
DEVICE tti_dev = {
|
||||||
|
@ -392,6 +403,24 @@ sim_cancel (&clk_unit); /* stop clock */
|
||||||
tmxr_poll = clk_unit.wait; /* set mux poll */
|
tmxr_poll = clk_unit.wait; /* set mux poll */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set frequency */
|
||||||
|
|
||||||
|
t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
if (cptr) return SCPE_ARG;
|
||||||
|
if ((val != 50) && (val != 60)) return SCPE_IERR;
|
||||||
|
clk_tps = val;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Show frequency */
|
||||||
|
|
||||||
|
t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
|
{
|
||||||
|
fprintf (st, (clk_tps == 50)? "50Hz": "60Hz");
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* Paper tape reader: IOT routine */
|
/* Paper tape reader: IOT routine */
|
||||||
|
|
||||||
|
@ -801,8 +830,8 @@ if ((tti_unit.flags & UNIT_HDX) && out && /* half duplex and */
|
||||||
tti_unit.buf = c; /* got char */
|
tti_unit.buf = c; /* got char */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
SET_INT (TTI); /* set flag */
|
|
||||||
tti_unit.pos = tti_unit.pos + 1;
|
tti_unit.pos = tti_unit.pos + 1;
|
||||||
|
SET_INT (TTI); /* set flag */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -823,6 +852,17 @@ CLR_INT (TTI); /* clear flag */
|
||||||
sim_activate (&tti_unit, tti_unit.wait); /* activate unit */
|
sim_activate (&tti_unit, tti_unit.wait); /* activate unit */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set control-C */
|
||||||
|
|
||||||
|
t_stat tti_set_ctrlc (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
if (cptr) return SCPE_ARG;
|
||||||
|
uptr->buf = (uptr->flags & UNIT_KSR)? 0203: 0003;
|
||||||
|
uptr->pos = uptr->pos + 1;
|
||||||
|
SET_INT (TTI);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* Terminal output: IOT routine */
|
/* Terminal output: IOT routine */
|
||||||
|
|
||||||
|
@ -883,6 +923,8 @@ sim_cancel (&tto_unit); /* deactivate unit */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set mode */
|
||||||
|
|
||||||
t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc)
|
t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
{
|
{
|
||||||
tti_unit.flags = (tti_unit.flags & ~(UNIT_KSR | UNIT_8B)) | val;
|
tti_unit.flags = (tti_unit.flags & ~(UNIT_KSR | UNIT_8B)) | val;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* pdp18b_sys.c: 18b PDP's simulator interface
|
/* pdp18b_sys.c: 18b PDP's simulator interface
|
||||||
|
|
||||||
Copyright (c) 1993-2002, Robert M Supnik
|
Copyright (c) 1993-2003, Robert M Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -23,6 +23,8 @@
|
||||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
02-Mar-03 RMS Split loaders apart for greater flexibility
|
||||||
|
09-Feb-03 RMS Fixed bug in FMTASC (found by Hans Pufal)
|
||||||
31-Jan-03 RMS Added support for RB09
|
31-Jan-03 RMS Added support for RB09
|
||||||
05-Oct-02 RMS Added variable device number support
|
05-Oct-02 RMS Added variable device number support
|
||||||
25-Jul-02 RMS Added PDP-4 DECtape support
|
25-Jul-02 RMS Added PDP-4 DECtape support
|
||||||
|
@ -159,7 +161,7 @@ const char *sim_stop_messages[] = {
|
||||||
"Invalid API interrupt",
|
"Invalid API interrupt",
|
||||||
"Non-standard device number" };
|
"Non-standard device number" };
|
||||||
|
|
||||||
/* Binary loader */
|
/* Binary loaders */
|
||||||
|
|
||||||
int32 getword (FILE *fileref, int32 *hi)
|
int32 getword (FILE *fileref, int32 *hi)
|
||||||
{
|
{
|
||||||
|
@ -176,9 +178,7 @@ if (hi != NULL) *hi = bits;
|
||||||
return word;
|
return word;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined (PDP4) || defined (PDP7)
|
/* PDP-4/PDP-7 RIM format loader
|
||||||
|
|
||||||
/* PDP-4/PDP-7: RIM format only
|
|
||||||
|
|
||||||
Tape format
|
Tape format
|
||||||
dac addr
|
dac addr
|
||||||
|
@ -189,11 +189,12 @@ return word;
|
||||||
jmp addr or hlt
|
jmp addr or hlt
|
||||||
*/
|
*/
|
||||||
|
|
||||||
t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
|
t_stat rim_load_47 (FILE *fileref, char *cptr)
|
||||||
{
|
{
|
||||||
int32 origin, val;
|
int32 origin, val;
|
||||||
|
|
||||||
if ((*cptr != 0) || (flag != 0)) return SCPE_ARG;
|
if (*cptr != 0) return SCPE_2MARG;
|
||||||
|
origin = 0200;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT;
|
if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT;
|
||||||
if ((val & 0760000) == 0040000) { /* DAC? */
|
if ((val & 0760000) == 0040000) { /* DAC? */
|
||||||
|
@ -208,15 +209,40 @@ for (;;) {
|
||||||
return SCPE_FMT; /* error */
|
return SCPE_FMT; /* error */
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
/* PDP-9/15 RIM format loader
|
||||||
|
|
||||||
/* PDP-9/PDP-15: RIM format and BIN format
|
Tape format (read in address specified externally)
|
||||||
|
|
||||||
RIM format (read in address specified externally)
|
|
||||||
data
|
data
|
||||||
:
|
:
|
||||||
data
|
data
|
||||||
word to execute (bit 1 of last character set)
|
word to execute (bit 1 of last character set)
|
||||||
|
*/
|
||||||
|
|
||||||
|
t_stat rim_load_915 (FILE *fileref, char *cptr)
|
||||||
|
{
|
||||||
|
int32 bits, origin, val;
|
||||||
|
char gbuf[CBUFSIZE];
|
||||||
|
t_stat r;
|
||||||
|
|
||||||
|
if (*cptr != 0) { /* more input? */
|
||||||
|
cptr = get_glyph (cptr, gbuf, 0); /* get origin */
|
||||||
|
origin = get_uint (gbuf, 8, ADDRMASK, &r);
|
||||||
|
if (r != SCPE_OK) return r;
|
||||||
|
if (*cptr != 0) return SCPE_ARG; } /* no more */
|
||||||
|
else origin = 0200; /* default 200 */
|
||||||
|
|
||||||
|
for (;;) { /* word loop */
|
||||||
|
if ((val = getword (fileref, &bits)) < 0) return SCPE_FMT;
|
||||||
|
if (bits & 1) { /* end of tape? */
|
||||||
|
if ((val & 0760000) == OP_JMP) saved_PC =
|
||||||
|
((origin - 1) & 060000) | (val & 017777);
|
||||||
|
else if (val != OP_HLT) return SCPE_FMT;
|
||||||
|
break; }
|
||||||
|
else if (MEM_ADDR_OK (origin)) M[origin++] = val; }
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PDP-9/15 BIN format loader
|
||||||
|
|
||||||
BIN format (starts after RIM bootstrap)
|
BIN format (starts after RIM bootstrap)
|
||||||
block/ origin (>= 0)
|
block/ origin (>= 0)
|
||||||
|
@ -230,38 +256,11 @@ return SCPE_FMT; /* error */
|
||||||
endblock/ origin (< 0)
|
endblock/ origin (< 0)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
|
t_stat bin_load_915 (FILE *fileref, char *cptr)
|
||||||
{
|
{
|
||||||
extern int32 sim_switches;
|
int32 i, val, origin, count, cksum;
|
||||||
int32 i, bits, origin, count, cksum, val;
|
|
||||||
t_stat r;
|
|
||||||
char gbuf[CBUFSIZE];
|
|
||||||
extern t_bool match_ext (char *fnm, char *ext);
|
|
||||||
|
|
||||||
/* RIM loader */
|
if (*cptr != 0) return SCPE_2MARG; /* no arguments */
|
||||||
|
|
||||||
if ((sim_switches & SWMASK ('R')) || /* RIM format? */
|
|
||||||
(match_ext (fnam, "RIM") && !(sim_switches & SWMASK ('B')))) {
|
|
||||||
if (*cptr != 0) { /* more input? */
|
|
||||||
cptr = get_glyph (cptr, gbuf, 0); /* get origin */
|
|
||||||
origin = get_uint (gbuf, 8, ADDRMASK, &r);
|
|
||||||
if (r != SCPE_OK) return r;
|
|
||||||
if (*cptr != 0) return SCPE_ARG; } /* no more */
|
|
||||||
else origin = 0200; /* default 200 */
|
|
||||||
|
|
||||||
for (;;) { /* word loop */
|
|
||||||
if ((val = getword (fileref, &bits)) < 0) return SCPE_FMT;
|
|
||||||
if (bits & 1) { /* end of tape? */
|
|
||||||
if ((val & 0760000) == OP_JMP) saved_PC =
|
|
||||||
((origin - 1) & 060000) | (val & 017777);
|
|
||||||
else if (val != OP_HLT) return SCPE_FMT;
|
|
||||||
break; }
|
|
||||||
else if (MEM_ADDR_OK (origin)) M[origin++] = val; }
|
|
||||||
return SCPE_OK; }
|
|
||||||
|
|
||||||
/* Binary loader */
|
|
||||||
|
|
||||||
if (*cptr != 0) return SCPE_ARG; /* no arguments */
|
|
||||||
do { val = getc (fileref); } /* find end RIM */
|
do { val = getc (fileref); } /* find end RIM */
|
||||||
while (((val & 0100) == 0) && (val != EOF));
|
while (((val & 0100) == 0) && (val != EOF));
|
||||||
if (val == EOF) rewind (fileref); /* no RIM? rewind */
|
if (val == EOF) rewind (fileref); /* no RIM? rewind */
|
||||||
|
@ -283,6 +282,34 @@ for (;;) { /* block loop */
|
||||||
if ((cksum & DMASK) != 0) return SCPE_CSUM; }
|
if ((cksum & DMASK) != 0) return SCPE_CSUM; }
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined (PDP4) || defined (PDP7)
|
||||||
|
|
||||||
|
/* PDP-4/PDP-7: RIM format only */
|
||||||
|
|
||||||
|
t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
|
||||||
|
{
|
||||||
|
if (flag != 0) return SCPE_NOFNC;
|
||||||
|
return rim_load_47 (fileref, cptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/* PDP-9/PDP-15: all formats */
|
||||||
|
|
||||||
|
t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
|
||||||
|
{
|
||||||
|
extern int32 sim_switches;
|
||||||
|
|
||||||
|
if (flag != 0) return SCPE_NOFNC;
|
||||||
|
if (sim_switches & SWMASK ('S')) /* PDP-4/7 format? */
|
||||||
|
return rim_load_47 (fileref, cptr);
|
||||||
|
if ((sim_switches & SWMASK ('R')) || /* RIM format? */
|
||||||
|
(match_ext (fnam, "RIM") && !(sim_switches & SWMASK ('B'))))
|
||||||
|
return rim_load_915 (fileref, cptr);
|
||||||
|
return bin_load_915 (fileref, cptr); /* must be BIN */
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Symbol tables */
|
/* Symbol tables */
|
||||||
|
@ -679,7 +706,7 @@ return sp;
|
||||||
return = status code
|
return = status code
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define FMTASC(x) (((x) < 040)? "<%03o>": "%c", (x))
|
#define FMTASC(x) (((x) < 040)? "<%03o>": "%c"), (x)
|
||||||
#define SIXTOASC(x) (((x) >= 040)? (x): ((x) + 0100))
|
#define SIXTOASC(x) (((x) >= 040)? (x): ((x) + 0100))
|
||||||
|
|
||||||
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
|
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
|
||||||
|
@ -691,7 +718,7 @@ inst = val[0];
|
||||||
cflag = (uptr == NULL) || (uptr == &cpu_unit);
|
cflag = (uptr == NULL) || (uptr == &cpu_unit);
|
||||||
if (sw & SWMASK ('A')) { /* ASCII? */
|
if (sw & SWMASK ('A')) { /* ASCII? */
|
||||||
if (inst > 0377) return SCPE_ARG;
|
if (inst > 0377) return SCPE_ARG;
|
||||||
fprintf (of, "%c", FMTASC (inst & 0177));
|
fprintf (of, FMTASC (inst & 0177));
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
if (sw & SWMASK ('C')) { /* character? */
|
if (sw & SWMASK ('C')) { /* character? */
|
||||||
fprintf (of, "%c", SIXTOASC ((inst >> 12) & 077));
|
fprintf (of, "%c", SIXTOASC ((inst >> 12) & 077));
|
||||||
|
@ -701,11 +728,11 @@ if (sw & SWMASK ('C')) { /* character? */
|
||||||
#if defined (PDP15)
|
#if defined (PDP15)
|
||||||
if (sw & SWMASK ('P')) { /* packed ASCII? */
|
if (sw & SWMASK ('P')) { /* packed ASCII? */
|
||||||
i = val[1];
|
i = val[1];
|
||||||
fprintf (of, "%c", FMTASC ((inst >> 11) & 0177));
|
fprintf (of, FMTASC ((inst >> 11) & 0177));
|
||||||
fprintf (of, "%c", FMTASC ((inst >> 4) & 0177));
|
fprintf (of, FMTASC ((inst >> 4) & 0177));
|
||||||
fprintf (of, "%c", FMTASC (((inst << 3) | (i >> 15)) & 0177));
|
fprintf (of, FMTASC (((inst << 3) | (i >> 15)) & 0177));
|
||||||
fprintf (of, "%c", FMTASC ((i >> 8) & 0177));
|
fprintf (of, FMTASC ((i >> 8) & 0177));
|
||||||
fprintf (of, "%c", FMTASC ((i >> 1) & 0177));
|
fprintf (of, FMTASC ((i >> 1) & 0177));
|
||||||
return -1; }
|
return -1; }
|
||||||
#endif
|
#endif
|
||||||
if (!(sw & SWMASK ('M'))) return SCPE_ARG;
|
if (!(sw & SWMASK ('M'))) return SCPE_ARG;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* pdp8_clk.c: PDP-8 real-time clock simulator
|
/* pdp8_clk.c: PDP-8 real-time clock simulator
|
||||||
|
|
||||||
Copyright (c) 1993-2002, Robert M Supnik
|
Copyright (c) 1993-2003, Robert M Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
clk real time clock
|
clk real time clock
|
||||||
|
|
||||||
|
01-Mar-03 RMS Aded SET/SHOW CLK FREQ support
|
||||||
04-Oct-02 RMS Added DIB, device number support
|
04-Oct-02 RMS Added DIB, device number support
|
||||||
30-Dec-01 RMS Removed for generalized timers
|
30-Dec-01 RMS Removed for generalized timers
|
||||||
05-Sep-01 RMS Added terminal multiplexor support
|
05-Sep-01 RMS Added terminal multiplexor support
|
||||||
|
@ -44,6 +45,8 @@ int32 tmxr_poll = 16000; /* term mux poll */
|
||||||
int32 clk (int32 IR, int32 AC);
|
int32 clk (int32 IR, int32 AC);
|
||||||
t_stat clk_svc (UNIT *uptr);
|
t_stat clk_svc (UNIT *uptr);
|
||||||
t_stat clk_reset (DEVICE *dptr);
|
t_stat clk_reset (DEVICE *dptr);
|
||||||
|
t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
|
|
||||||
/* CLK data structures
|
/* CLK data structures
|
||||||
|
|
||||||
|
@ -61,10 +64,16 @@ REG clk_reg[] = {
|
||||||
{ FLDATA (ENABLE, int_enable, INT_V_CLK) },
|
{ FLDATA (ENABLE, int_enable, INT_V_CLK) },
|
||||||
{ FLDATA (INT, int_req, INT_V_CLK) },
|
{ FLDATA (INT, int_req, INT_V_CLK) },
|
||||||
{ DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT },
|
{ DRDATA (TIME, clk_unit.wait, 24), REG_NZ + PV_LEFT },
|
||||||
{ DRDATA (TPS, clk_tps, 8), REG_NZ + PV_LEFT },
|
{ DRDATA (TPS, clk_tps, 8), PV_LEFT + REG_HRO },
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
MTAB clk_mod[] = {
|
MTAB clk_mod[] = {
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 50, NULL, "50HZ",
|
||||||
|
&clk_set_freq, NULL, NULL },
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 60, NULL, "60HZ",
|
||||||
|
&clk_set_freq, NULL, NULL },
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 0, "FREQUENCY", NULL,
|
||||||
|
NULL, &clk_show_freq, NULL },
|
||||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev },
|
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
|
||||||
|
@ -137,3 +146,21 @@ int_enable = int_enable & ~INT_CLK; /* clear enable */
|
||||||
sim_activate (&clk_unit, clk_unit.wait); /* activate unit */
|
sim_activate (&clk_unit, clk_unit.wait); /* activate unit */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set frequency */
|
||||||
|
|
||||||
|
t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
if (cptr) return SCPE_ARG;
|
||||||
|
if ((val != 50) && (val != 60)) return SCPE_IERR;
|
||||||
|
clk_tps = val;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Show frequency */
|
||||||
|
|
||||||
|
t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
|
{
|
||||||
|
fprintf (st, (clk_tps == 50)? "50Hz": "60Hz");
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
df DF32 fixed head disk
|
df DF32 fixed head disk
|
||||||
|
|
||||||
|
03-Mar-03 RMS Fixed autosizing
|
||||||
02-Feb-03 RMS Added variable platter and autosizing support
|
02-Feb-03 RMS Added variable platter and autosizing support
|
||||||
04-Oct-02 RMS Added DIBs, device number support
|
04-Oct-02 RMS Added DIBs, device number support
|
||||||
28-Nov-01 RMS Added RL8A support
|
28-Nov-01 RMS Added RL8A support
|
||||||
|
@ -44,9 +45,11 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */
|
#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */
|
||||||
#define UNIT_V_MSIZE (UNIT_V_UF + 1) /* dummy mask */
|
#define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */
|
||||||
|
#define UNIT_M_PLAT 03
|
||||||
|
#define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1)
|
||||||
#define UNIT_AUTO (1 << UNIT_V_AUTO)
|
#define UNIT_AUTO (1 << UNIT_V_AUTO)
|
||||||
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
|
#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT)
|
||||||
|
|
||||||
/* Constants */
|
/* Constants */
|
||||||
|
|
||||||
|
@ -119,7 +122,7 @@ DIB df_dib = { DEV_DF, 3, { &df60, &df61, &df62 } };
|
||||||
|
|
||||||
UNIT df_unit =
|
UNIT df_unit =
|
||||||
{ UDATA (&df_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF,
|
{ UDATA (&df_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF,
|
||||||
DF_NUMDK * DF_DKSIZE) };
|
DF_DKSIZE) };
|
||||||
|
|
||||||
REG df_reg[] = {
|
REG df_reg[] = {
|
||||||
{ ORDATA (STA, df_sta, 12) },
|
{ ORDATA (STA, df_sta, 12) },
|
||||||
|
@ -136,10 +139,10 @@ REG df_reg[] = {
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
MTAB df_mod[] = {
|
MTAB df_mod[] = {
|
||||||
{ UNIT_MSIZE, 32768, NULL, "1P", &df_set_size },
|
{ UNIT_PLAT, 0, NULL, "1P", &df_set_size },
|
||||||
{ UNIT_MSIZE, 65536, NULL, "2P", &df_set_size },
|
{ UNIT_PLAT, 1, NULL, "2P", &df_set_size },
|
||||||
{ UNIT_MSIZE, 98304, NULL, "3P", &df_set_size },
|
{ UNIT_PLAT, 2, NULL, "3P", &df_set_size },
|
||||||
{ UNIT_MSIZE, 131072, NULL, "4P", &df_set_size },
|
{ UNIT_PLAT, 3, NULL, "4P", &df_set_size },
|
||||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||||
&set_dev, &show_dev, NULL },
|
&set_dev, &show_dev, NULL },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
@ -315,19 +318,15 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat df_attach (UNIT *uptr, char *cptr)
|
t_stat df_attach (UNIT *uptr, char *cptr)
|
||||||
{
|
{
|
||||||
int32 p, d;
|
t_addr p, sz;
|
||||||
int32 ds_bytes = DF_DKSIZE * sizeof (int16);
|
t_addr ds_bytes = DF_DKSIZE * sizeof (int16);
|
||||||
|
|
||||||
if (uptr->flags & UNIT_AUTO) {
|
if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (cptr))) {
|
||||||
FILE *fp = fopen (cptr, "rb");
|
p = (sz + ds_bytes - 1) / ds_bytes;
|
||||||
if (fp == NULL) return SCPE_OPENERR;
|
if (p == 0) p = 1;
|
||||||
fseek (fp, 0, SEEK_END);
|
if (p > DF_NUMDK) p = DF_NUMDK; }
|
||||||
p = ftell (fp);
|
else p = UNIT_GETP (uptr->flags);
|
||||||
d = (p + ds_bytes - 1) / ds_bytes;
|
uptr->capac = p * DF_DKSIZE;
|
||||||
if (d == 0) d = 1;
|
|
||||||
if (d > DF_NUMDK) d = DF_NUMDK;
|
|
||||||
uptr->capac = d * DF_DKSIZE;
|
|
||||||
fclose (fp); }
|
|
||||||
return attach_unit (uptr, cptr);
|
return attach_unit (uptr, cptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,10 +334,9 @@ return attach_unit (uptr, cptr);
|
||||||
|
|
||||||
t_stat df_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
t_stat df_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
{
|
{
|
||||||
if ((val == 0) || (val > (DF_NUMDK * DF_DKSIZE)))
|
if ((val < 0) || (val >= DF_NUMDK)) return SCPE_IERR;
|
||||||
return SCPE_IERR;
|
|
||||||
if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
|
if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
|
||||||
uptr->capac = val;
|
uptr->capac = (val + 1) * DF_DKSIZE;
|
||||||
uptr->flags = uptr->flags & ~UNIT_AUTO;
|
uptr->flags = uptr->flags & ~UNIT_AUTO;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,10 +39,12 @@ This memorandum documents the PDP-8 simulator.
|
||||||
sim/ sim_defs.h
|
sim/ sim_defs.h
|
||||||
sim_rev.h
|
sim_rev.h
|
||||||
sim_sock.h
|
sim_sock.h
|
||||||
|
sim_tape.h
|
||||||
sim_tmxr.h
|
sim_tmxr.h
|
||||||
scp.c
|
scp.c
|
||||||
scp_tty.c
|
scp_tty.c
|
||||||
sim_sock.c
|
sim_sock.c
|
||||||
|
sim_tape.c
|
||||||
sim_tmxr.c
|
sim_tmxr.c
|
||||||
|
|
||||||
sim/pdp8/ pdp8_defs.h
|
sim/pdp8/ pdp8_defs.h
|
||||||
|
@ -253,6 +255,12 @@ implements these registers:
|
||||||
POS 32 number of characters input
|
POS 32 number of characters input
|
||||||
TIME 24 keyboard polling interval
|
TIME 24 keyboard polling interval
|
||||||
|
|
||||||
|
If the simulator is compiled under Windows Visual C++, typing ^C to the
|
||||||
|
terminal input causes a fatal run-time error. Use the following command
|
||||||
|
to simulate typing ^C:
|
||||||
|
|
||||||
|
SET TTI CTRL-C
|
||||||
|
|
||||||
2.2.4 KL8E Terminal Output (TTO)
|
2.2.4 KL8E Terminal Output (TTO)
|
||||||
|
|
||||||
The terminal output (TTO) writes to the simulator console window. It
|
The terminal output (TTO) writes to the simulator console window. It
|
||||||
|
@ -296,7 +304,14 @@ Error handling is as follows:
|
||||||
|
|
||||||
2.2.6 DK8E Line-Frequency Clock (CLK)
|
2.2.6 DK8E Line-Frequency Clock (CLK)
|
||||||
|
|
||||||
The real-time clock (CLK) implements these registers:
|
The real-time clock (CLK) frequency can be adjusted as follows:
|
||||||
|
|
||||||
|
SET CLK 60HZ set frequency to 60Hz
|
||||||
|
SET CLK 50HZ set frequency to 50Hz
|
||||||
|
|
||||||
|
The default is 60Hz.
|
||||||
|
|
||||||
|
The clock implements these registers:
|
||||||
|
|
||||||
name size comments
|
name size comments
|
||||||
|
|
||||||
|
@ -304,7 +319,6 @@ The real-time clock (CLK) implements these registers:
|
||||||
ENABLE 1 interrupt enable flag
|
ENABLE 1 interrupt enable flag
|
||||||
INT 1 interrupt pending flag
|
INT 1 interrupt pending flag
|
||||||
TIME 24 clock interval
|
TIME 24 clock interval
|
||||||
TPS 8 ticks per second (60 or 50)
|
|
||||||
|
|
||||||
The real-time clock autocalibrates; the clock interval is adjusted up or
|
The real-time clock autocalibrates; the clock interval is adjusted up or
|
||||||
down so that the clock tracks actual elapsed time.
|
down so that the clock tracks actual elapsed time.
|
||||||
|
@ -516,7 +530,7 @@ from the attached file:
|
||||||
SET RF 4P four platters (1024K)
|
SET RF 4P four platters (1024K)
|
||||||
SET RF AUTOSIZE autosized on attach
|
SET RF AUTOSIZE autosized on attach
|
||||||
|
|
||||||
The default is four platters.
|
The default is one platter.
|
||||||
|
|
||||||
The RF08 implements these registers:
|
The RF08 implements these registers:
|
||||||
|
|
||||||
|
@ -562,7 +576,7 @@ from the attached file:
|
||||||
SET DF 4P four platters (128K)
|
SET DF 4P four platters (128K)
|
||||||
SET DF AUTOSIZE autosized on attach
|
SET DF AUTOSIZE autosized on attach
|
||||||
|
|
||||||
The default is four platters.
|
The default is one platter.
|
||||||
|
|
||||||
The DF32 implements these registers:
|
The DF32 implements these registers:
|
||||||
|
|
||||||
|
|
232
PDP8/pdp8_mt.c
232
PDP8/pdp8_mt.c
|
@ -1,6 +1,6 @@
|
||||||
/* pdp8_mt.c: PDP-8 magnetic tape simulator
|
/* pdp8_mt.c: PDP-8 magnetic tape simulator
|
||||||
|
|
||||||
Copyright (c) 1993-2002, Robert M Supnik
|
Copyright (c) 1993-2003, Robert M Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
mt TM8E/TU10 magtape
|
mt TM8E/TU10 magtape
|
||||||
|
|
||||||
|
01-Mar-03 RMS Fixed interrupt handling
|
||||||
|
Revised for magtape library
|
||||||
30-Oct-02 RMS Revised BOT handling, added error record handling
|
30-Oct-02 RMS Revised BOT handling, added error record handling
|
||||||
04-Oct-02 RMS Added DIBs, device number support
|
04-Oct-02 RMS Added DIBs, device number support
|
||||||
30-Aug-02 RMS Revamped error handling
|
30-Aug-02 RMS Revamped error handling
|
||||||
|
@ -55,17 +57,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pdp8_defs.h"
|
#include "pdp8_defs.h"
|
||||||
|
#include "sim_tape.h"
|
||||||
|
|
||||||
#define MT_NUMDR 8 /* #drives */
|
#define MT_NUMDR 8 /* #drives */
|
||||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
|
||||||
#define UNIT_V_PNU (UNIT_V_UF + 1) /* pos not updated */
|
|
||||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
|
||||||
#define UNIT_PNU (1 << UNIT_V_PNU)
|
|
||||||
#define USTAT u3 /* unit status */
|
#define USTAT u3 /* unit status */
|
||||||
#define MT_MAXFR (1 << 16) /* max record lnt */
|
#define MT_MAXFR (1 << 16) /* max record lnt */
|
||||||
#define DBSIZE (1 << 12) /* max data cmd */
|
#define WC_SIZE (1 << 12) /* max word count */
|
||||||
#define DBMASK (SBSIZE - 1)
|
#define WC_MASK (WC_SIZE - 1)
|
||||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
|
||||||
|
|
||||||
/* Command/unit - mt_cu */
|
/* Command/unit - mt_cu */
|
||||||
|
|
||||||
|
@ -125,9 +123,6 @@
|
||||||
#define STA_CLR (FN_RMASK | 00020) /* always clear */
|
#define STA_CLR (FN_RMASK | 00020) /* always clear */
|
||||||
#define STA_DYN (STA_REW | STA_BOT | STA_REM | STA_EOF | \
|
#define STA_DYN (STA_REW | STA_BOT | STA_REM | STA_EOF | \
|
||||||
STA_EOT | STA_WLK) /* kept in USTAT */
|
STA_EOT | STA_WLK) /* kept in USTAT */
|
||||||
#define STA_EFLGS (STA_BOT | STA_PAR | STA_RLE | STA_DLT | \
|
|
||||||
STA_EOT | STA_CPE | STA_ILL | STA_EOF | \
|
|
||||||
STA_INC )
|
|
||||||
/* set error */
|
/* set error */
|
||||||
#define TUR(u) (!sim_is_active (u)) /* tape unit ready */
|
#define TUR(u) (!sim_is_active (u)) /* tape unit ready */
|
||||||
|
|
||||||
|
@ -144,6 +139,7 @@ int32 mt_db = 0; /* data buffer */
|
||||||
int32 mt_done = 0; /* mag tape flag */
|
int32 mt_done = 0; /* mag tape flag */
|
||||||
int32 mt_time = 10; /* record latency */
|
int32 mt_time = 10; /* record latency */
|
||||||
int32 mt_stopioe = 1; /* stop on error */
|
int32 mt_stopioe = 1; /* stop on error */
|
||||||
|
uint8 *mtxb = NULL; /* transfer buffer */
|
||||||
|
|
||||||
DEVICE mt_dev;
|
DEVICE mt_dev;
|
||||||
int32 mt70 (int32 IR, int32 AC);
|
int32 mt70 (int32 IR, int32 AC);
|
||||||
|
@ -155,11 +151,10 @@ t_stat mt_attach (UNIT *uptr, char *cptr);
|
||||||
t_stat mt_detach (UNIT *uptr);
|
t_stat mt_detach (UNIT *uptr);
|
||||||
int32 mt_updcsta (UNIT *uptr);
|
int32 mt_updcsta (UNIT *uptr);
|
||||||
int32 mt_ixma (int32 xma);
|
int32 mt_ixma (int32 xma);
|
||||||
|
t_stat mt_map_err (UNIT *uptr, t_stat st);
|
||||||
t_stat mt_vlock (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat mt_vlock (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
UNIT *mt_busy (void);
|
UNIT *mt_busy (void);
|
||||||
void mt_set_done (void);
|
void mt_set_done (void);
|
||||||
t_bool mt_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
|
||||||
t_bool mt_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
|
||||||
|
|
||||||
/* MT data structures
|
/* MT data structures
|
||||||
|
|
||||||
|
@ -200,8 +195,8 @@ REG mt_reg[] = {
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
MTAB mt_mod[] = {
|
MTAB mt_mod[] = {
|
||||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", &mt_vlock },
|
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", &mt_vlock },
|
||||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", &mt_vlock },
|
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", &mt_vlock },
|
||||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||||
&set_dev, &show_dev, NULL },
|
&set_dev, &show_dev, NULL },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
@ -235,21 +230,21 @@ case 4: /* CCAR */
|
||||||
mt_ca = 0; /* clear mem address */
|
mt_ca = 0; /* clear mem address */
|
||||||
return AC;
|
return AC;
|
||||||
case 5: /* LCMR */
|
case 5: /* LCMR */
|
||||||
if (mt_busy ()) mt_sta = mt_sta | STA_ILL; /* busy? illegal op */
|
if (mt_busy ()) mt_sta = mt_sta | STA_ILL | STA_ERR; /* busy? illegal op */
|
||||||
mt_cu = AC; /* load command reg */
|
mt_cu = AC; /* load command reg */
|
||||||
mt_updcsta (mt_dev.units + GET_UNIT (mt_cu));
|
mt_updcsta (mt_dev.units + GET_UNIT (mt_cu));
|
||||||
return 0;
|
return 0;
|
||||||
case 6: /* LFGR */
|
case 6: /* LFGR */
|
||||||
if (mt_busy ()) mt_sta = mt_sta | STA_ILL; /* busy? illegal op */
|
if (mt_busy ()) mt_sta = mt_sta | STA_ILL | STA_ERR; /* busy? illegal op */
|
||||||
mt_fn = AC; /* load function */
|
mt_fn = AC; /* load function */
|
||||||
if ((mt_fn & FN_GO) == 0) { /* go set? */
|
if ((mt_fn & FN_GO) == 0) { /* go set? */
|
||||||
mt_updcsta (uptr); /* update status */
|
mt_updcsta (uptr); /* update status */
|
||||||
return 0; }
|
return 0; }
|
||||||
f = GET_FNC (mt_fn); /* get function */
|
f = GET_FNC (mt_fn); /* get function */
|
||||||
if (((uptr->flags & UNIT_ATT) == 0) || !TUR (uptr) ||
|
if (((uptr->flags & UNIT_ATT) == 0) || !TUR (uptr) ||
|
||||||
(((f == FN_WRITE) || (f == FN_WREOF)) && (uptr->flags & UNIT_WPRT))
|
(((f == FN_WRITE) || (f == FN_WREOF)) && sim_tape_wrp (uptr))
|
||||||
|| (((f == FN_SPACER) || (f == FN_REWIND)) && (uptr->USTAT & STA_BOT))) {
|
|| (((f == FN_SPACER) || (f == FN_REWIND)) && sim_tape_bot (uptr))) {
|
||||||
mt_sta = mt_sta | STA_ILL; /* illegal op error */
|
mt_sta = mt_sta | STA_ILL | STA_ERR; /* illegal op error */
|
||||||
mt_set_done (); /* set done */
|
mt_set_done (); /* set done */
|
||||||
mt_updcsta (uptr); /* update status */
|
mt_updcsta (uptr); /* update status */
|
||||||
return 0; }
|
return 0; }
|
||||||
|
@ -266,7 +261,7 @@ case 6: /* LFGR */
|
||||||
sim_activate (uptr, mt_time); /* start io */
|
sim_activate (uptr, mt_time); /* start io */
|
||||||
return 0;
|
return 0;
|
||||||
case 7: /* LDBR */
|
case 7: /* LDBR */
|
||||||
if (mt_busy ()) mt_sta = mt_sta | STA_ILL; /* busy? illegal op */
|
if (mt_busy ()) mt_sta = mt_sta | STA_ILL | STA_ERR; /* busy? illegal op */
|
||||||
mt_db = AC; /* load buffer */
|
mt_db = AC; /* load buffer */
|
||||||
mt_set_done (); /* set done */
|
mt_set_done (); /* set done */
|
||||||
mt_updcsta (uptr); /* update status */
|
mt_updcsta (uptr); /* update status */
|
||||||
|
@ -333,20 +328,18 @@ return (stop_inst << IOT_V_REASON) + AC; /* ill inst */
|
||||||
|
|
||||||
t_stat mt_svc (UNIT *uptr)
|
t_stat mt_svc (UNIT *uptr)
|
||||||
{
|
{
|
||||||
int32 f, i, p, u, err, wc, xma, pnu;
|
int32 f, i, p, u, wc, xma;
|
||||||
t_mtrlnt abc, tbc, cbc;
|
t_mtrlnt tbc, cbc;
|
||||||
uint16 c, c1, c2;
|
uint16 c, c1, c2;
|
||||||
uint8 dbuf[(2 * DBSIZE)];
|
t_stat st, r = SCPE_OK;
|
||||||
static t_mtrlnt bceof = MTR_TMK;
|
|
||||||
|
|
||||||
err = 0;
|
|
||||||
u = uptr - mt_dev.units; /* get unit number */
|
u = uptr - mt_dev.units; /* get unit number */
|
||||||
f = GET_FNC (mt_fn); /* get command */
|
f = GET_FNC (mt_fn); /* get command */
|
||||||
pnu = MT_TST_PNU (uptr); /* get pos not upd */
|
xma = GET_EMA (mt_cu) + mt_ca; /* get mem addr */
|
||||||
MT_CLR_PNU (uptr); /* and clear */
|
wc = WC_SIZE - mt_wc; /* get wc */
|
||||||
|
|
||||||
if (uptr->USTAT & STA_REW) { /* rewind? */
|
if (uptr->USTAT & STA_REW) { /* rewind? */
|
||||||
uptr->pos = 0; /* update position */
|
sim_tape_rewind (uptr); /* update position */
|
||||||
if (uptr->flags & UNIT_ATT) /* still on line? */
|
if (uptr->flags & UNIT_ATT) /* still on line? */
|
||||||
uptr->USTAT = (uptr->USTAT & STA_WLK) | STA_BOT;
|
uptr->USTAT = (uptr->USTAT & STA_WLK) | STA_BOT;
|
||||||
else uptr->USTAT = STA_REM;
|
else uptr->USTAT = STA_REM;
|
||||||
|
@ -357,122 +350,95 @@ if (uptr->USTAT & STA_REW) { /* rewind? */
|
||||||
|
|
||||||
if ((uptr->flags & UNIT_ATT) == 0) { /* if not attached */
|
if ((uptr->flags & UNIT_ATT) == 0) { /* if not attached */
|
||||||
uptr->USTAT = STA_REM; /* unit off line */
|
uptr->USTAT = STA_REM; /* unit off line */
|
||||||
mt_sta = mt_sta | STA_ILL; /* illegal operation */
|
mt_sta = mt_sta | STA_ILL | STA_ERR; /* illegal operation */
|
||||||
mt_set_done (); /* set done */
|
mt_set_done (); /* set done */
|
||||||
mt_updcsta (uptr); /* update status */
|
mt_updcsta (uptr); /* update status */
|
||||||
return IORETURN (mt_stopioe, SCPE_UNATT); }
|
return IORETURN (mt_stopioe, SCPE_UNATT); }
|
||||||
|
|
||||||
if (((f == FN_WRITE) || (f == FN_WREOF)) && (uptr->flags & UNIT_WPRT)) {
|
|
||||||
mt_sta = mt_sta | STA_ILL; /* illegal operation */
|
|
||||||
mt_set_done (); /* set done */
|
|
||||||
mt_updcsta (uptr); /* update status */
|
|
||||||
return SCPE_OK; }
|
|
||||||
|
|
||||||
xma = GET_EMA (mt_cu) + mt_ca; /* get mem addr */
|
|
||||||
wc = 010000 - mt_wc; /* get wc */
|
|
||||||
switch (f) { /* case on function */
|
switch (f) { /* case on function */
|
||||||
|
|
||||||
/* Unit service, continued */
|
/* Unit service, continued */
|
||||||
|
|
||||||
case FN_READ: /* read */
|
case FN_READ: /* read */
|
||||||
case FN_CMPARE: /* read/compare */
|
case FN_CMPARE: /* read/compare */
|
||||||
if (mt_rdlntf (uptr, &tbc, &err)) { /* read rec lnt */
|
st = sim_tape_rdrecf (uptr, mtxb, &tbc, MT_MAXFR); /* read rec */
|
||||||
mt_sta = mt_sta | STA_RLE; /* err, eof/eom, tmk */
|
if (st == MTSE_RECE) mt_sta = mt_sta | STA_PAR | STA_ERR; /* rec in err? */
|
||||||
|
else if (st != MTSE_OK) { /* other error? */
|
||||||
|
r = mt_map_err (uptr, st); /* map error */
|
||||||
|
mt_sta = mt_sta | STA_RLE | STA_ERR; /* err, eof/eom, tmk */
|
||||||
break; }
|
break; }
|
||||||
if (tbc > MT_MAXFR) return SCPE_MTRLNT; /* record too long? */
|
|
||||||
cbc = (mt_cu & CU_UNPAK)? wc: wc * 2; /* expected bc */
|
cbc = (mt_cu & CU_UNPAK)? wc: wc * 2; /* expected bc */
|
||||||
if (tbc != cbc) mt_sta = mt_sta | STA_RLE; /* wrong size? */
|
if (tbc != cbc) mt_sta = mt_sta | STA_RLE | STA_ERR; /* wrong size? */
|
||||||
if (tbc < cbc) { /* record small? */
|
if (tbc < cbc) { /* record small? */
|
||||||
cbc = tbc; /* use smaller */
|
cbc = tbc; /* use smaller */
|
||||||
wc = (mt_cu & CU_UNPAK)? cbc: (cbc + 1) / 2; }
|
wc = (mt_cu & CU_UNPAK)? cbc: (cbc + 1) / 2; }
|
||||||
abc = fxread (dbuf, sizeof (uint8), cbc, uptr->fileref);
|
|
||||||
if (err = ferror (uptr->fileref)) { /* error? */
|
|
||||||
mt_sta = mt_sta | STA_RLE; /* set flag */
|
|
||||||
MT_SET_PNU (uptr); /* pos not upd */
|
|
||||||
break; }
|
|
||||||
for ( ; abc < cbc; abc++) dbuf[abc] = 0; /* fill with 0's */
|
|
||||||
for (i = p = 0; i < wc; i++) { /* copy buffer */
|
for (i = p = 0; i < wc; i++) { /* copy buffer */
|
||||||
xma = mt_ixma (xma); /* increment xma */
|
xma = mt_ixma (xma); /* increment xma */
|
||||||
if (mt_cu & CU_UNPAK) c = dbuf[p++];
|
mt_wc = (mt_wc + 1) & 07777; /* incr word cnt */
|
||||||
|
if (mt_cu & CU_UNPAK) c = mtxb[p++];
|
||||||
else {
|
else {
|
||||||
c1 = dbuf[p++] & 077;
|
c1 = mtxb[p++] & 077;
|
||||||
c2 = dbuf[p++] & 077;
|
c2 = mtxb[p++] & 077;
|
||||||
c = (c1 << 6) | c2; }
|
c = (c1 << 6) | c2; }
|
||||||
if ((f == FN_READ) && MEM_ADDR_OK (xma)) M[xma] = c;
|
if ((f == FN_READ) && MEM_ADDR_OK (xma)) M[xma] = c;
|
||||||
else if ((f == FN_CMPARE) && (M[xma] != c)) {
|
else if ((f == FN_CMPARE) && (M[xma] != c)) {
|
||||||
mt_sta = mt_sta | STA_CPE;
|
mt_sta = mt_sta | STA_CPE | STA_ERR;
|
||||||
break; } }
|
break; } }
|
||||||
mt_wc = (mt_wc + wc) & 07777; /* update wc */
|
|
||||||
uptr->pos = uptr->pos + ((tbc + 1) & ~1) + /* update tape pos */
|
|
||||||
(2 * sizeof (t_mtrlnt));
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FN_WRITE: /* write */
|
case FN_WRITE: /* write */
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
|
||||||
tbc = (mt_cu & CU_UNPAK)? wc: wc * 2;
|
tbc = (mt_cu & CU_UNPAK)? wc: wc * 2;
|
||||||
fxwrite (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
|
||||||
for (i = p = 0; i < wc; i++) { /* copy buf to tape */
|
for (i = p = 0; i < wc; i++) { /* copy buf to tape */
|
||||||
xma = mt_ixma (xma); /* incr mem addr */
|
xma = mt_ixma (xma); /* incr mem addr */
|
||||||
if (mt_cu & CU_UNPAK) dbuf[p++] = M[xma] & 0377;
|
if (mt_cu & CU_UNPAK) mtxb[p++] = M[xma] & 0377;
|
||||||
else {
|
else {
|
||||||
dbuf[p++] = (M[xma] >> 6) & 077;
|
mtxb[p++] = (M[xma] >> 6) & 077;
|
||||||
dbuf[p++] = M[xma] & 077; } }
|
mtxb[p++] = M[xma] & 077; } }
|
||||||
fxwrite (dbuf, sizeof (int8), (tbc + 1) & ~1, uptr->fileref);
|
if (st = sim_tape_wrrecf (uptr, mtxb, tbc)) { /* write rec, err? */
|
||||||
fxwrite (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
r = mt_map_err (uptr, st); /* map error */
|
||||||
if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr); /* error? */
|
xma = GET_EMA (mt_cu) + mt_ca; } /* restore xma */
|
||||||
else {
|
else mt_wc = 0; /* ok, clear wc */
|
||||||
mt_wc = 0;
|
|
||||||
uptr->pos = uptr->pos + ((tbc + 1) & ~1) + /* upd tape pos */
|
|
||||||
(2 * sizeof (t_mtrlnt)); }
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Unit service, continued */
|
/* Unit service, continued */
|
||||||
|
|
||||||
case FN_WREOF:
|
case FN_WREOF:
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
|
||||||
fxwrite (&bceof, sizeof (t_mtrlnt), 1, uptr->fileref); /* write eof */
|
r = mt_map_err (uptr, st); /* map error */
|
||||||
if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr); /* error? */
|
|
||||||
else uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* update tape pos */
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FN_SPACEF: /* space forward */
|
case FN_SPACEF: /* space forward */
|
||||||
do {
|
do {
|
||||||
mt_wc = (mt_wc + 1) & 07777; /* incr wc */
|
mt_wc = (mt_wc + 1) & 07777; /* incr wc */
|
||||||
if (mt_rdlntf (uptr, &tbc, &err)) break; /* read rec lnt, err? */
|
if (st = sim_tape_sprecf (uptr, &tbc)) { /* space rec fwd, err? */
|
||||||
uptr->pos = uptr->pos + ((tbc + 1) & ~1) +
|
r = mt_map_err (uptr, st); /* map error */
|
||||||
(2 * sizeof (t_mtrlnt)); }
|
break; } /* stop */
|
||||||
|
}
|
||||||
while (mt_wc != 0);
|
while (mt_wc != 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FN_SPACER: /* space reverse */
|
case FN_SPACER: /* space reverse */
|
||||||
do {
|
do {
|
||||||
mt_wc = (mt_wc + 1) & 07777; /* incr wc */
|
mt_wc = (mt_wc + 1) & 07777; /* incr wc */
|
||||||
if (pnu) pnu = 0; /* pos not upd? */
|
if (st = sim_tape_sprecr (uptr, &tbc)) { /* space rec rev, err? */
|
||||||
else {
|
r = mt_map_err (uptr, st); /* map error */
|
||||||
if (mt_rdlntr (uptr, &tbc, &err)) break;
|
break; } /* stop */
|
||||||
uptr->pos = uptr->pos - ((tbc + 1) & ~1) -
|
}
|
||||||
(2 * sizeof (t_mtrlnt)); } }
|
|
||||||
while (mt_wc != 0);
|
while (mt_wc != 0);
|
||||||
break; } /* end case */
|
break; } /* end case */
|
||||||
|
|
||||||
if (err != 0) mt_sta = mt_sta | STA_PAR; /* error? set flag */
|
|
||||||
mt_cu = (mt_cu & ~CU_EMA) | ((xma >> (12 - CU_V_EMA)) & CU_EMA);
|
mt_cu = (mt_cu & ~CU_EMA) | ((xma >> (12 - CU_V_EMA)) & CU_EMA);
|
||||||
mt_ca = xma & 07777; /* update mem addr */
|
mt_ca = xma & 07777; /* update mem addr */
|
||||||
mt_set_done (); /* set done */
|
mt_set_done (); /* set done */
|
||||||
mt_updcsta (uptr); /* update status */
|
mt_updcsta (uptr); /* update status */
|
||||||
if (err != 0) { /* error? */
|
return r;
|
||||||
perror ("MT I/O error");
|
|
||||||
clearerr (uptr->fileref);
|
|
||||||
if (mt_stopioe) return SCPE_IOERR; }
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update controller status */
|
/* Update controller status */
|
||||||
|
|
||||||
int32 mt_updcsta (UNIT *uptr)
|
int32 mt_updcsta (UNIT *uptr)
|
||||||
{
|
{
|
||||||
mt_sta = (mt_sta & ~(STA_DYN | STA_ERR | STA_CLR)) | (uptr->USTAT & STA_DYN);
|
mt_sta = (mt_sta & ~(STA_DYN | STA_CLR)) | (uptr->USTAT & STA_DYN);
|
||||||
if (mt_sta & STA_EFLGS) mt_sta = mt_sta | STA_ERR;
|
|
||||||
if (((mt_sta & STA_ERR) && (mt_cu & CU_IEE)) ||
|
if (((mt_sta & STA_ERR) && (mt_cu & CU_IEE)) ||
|
||||||
(mt_done && (mt_cu & CU_IED))) int_req = int_req | INT_MT;
|
(mt_done && (mt_cu & CU_IED))) int_req = int_req | INT_MT;
|
||||||
else int_req = int_req & ~INT_MT;
|
else int_req = int_req & ~INT_MT;
|
||||||
|
@ -501,7 +467,7 @@ int32 v;
|
||||||
|
|
||||||
v = ((xma + 1) & 07777) | (xma & 070000); /* wrapped incr */
|
v = ((xma + 1) & 07777) | (xma & 070000); /* wrapped incr */
|
||||||
if (mt_fn & FN_INC) { /* increment mode? */
|
if (mt_fn & FN_INC) { /* increment mode? */
|
||||||
if (xma == 077777) mt_sta = mt_sta | STA_INC; /* at limit? error */
|
if (xma == 077777) mt_sta = mt_sta | STA_INC | STA_ERR; /* at limit? error */
|
||||||
else v = xma + 1; } /* else 15b incr */
|
else v = xma + 1; } /* else 15b incr */
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
@ -515,50 +481,39 @@ mt_fn = mt_fn & ~(FN_CRC | FN_GO | FN_INC); /* clear func<4:6> */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read record length forward - return T if error, EOM, or EOF */
|
/* Map tape error status */
|
||||||
|
|
||||||
t_bool mt_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
t_stat mt_map_err (UNIT *uptr, t_stat st)
|
||||||
{
|
{
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set tape pos */
|
switch (st) {
|
||||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref); /* read rec lnt */
|
case MTSE_FMT: /* illegal fmt */
|
||||||
if ((*err = ferror (uptr->fileref)) || /* error, */
|
case MTSE_UNATT: /* unattached */
|
||||||
feof (uptr->fileref) || (*tbc == MTR_EOM)) { /* eof or eom? */
|
mt_sta = mt_sta | STA_ILL | STA_ERR;
|
||||||
mt_sta = mt_sta | STA_PAR; /* parity error */
|
case MTSE_OK: /* no error */
|
||||||
MT_SET_PNU (uptr); /* pos not upd */
|
return SCPE_IERR; /* never get here! */
|
||||||
return TRUE; }
|
case MTSE_TMK: /* end of file */
|
||||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
uptr->USTAT = uptr->USTAT | STA_EOF; /* set EOF */
|
||||||
uptr->USTAT = uptr->USTAT | STA_EOF; /* end of file */
|
mt_sta = mt_sta | STA_ERR;
|
||||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* spc over tmk */
|
break;
|
||||||
return TRUE; }
|
case MTSE_IOERR: /* IO error */
|
||||||
if (MTRF (*tbc)) mt_sta = mt_sta | STA_PAR; /* record in error? */
|
mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */
|
||||||
*tbc = MTRL (*tbc); /* clear error flag */
|
if (mt_stopioe) return SCPE_IOERR;
|
||||||
return FALSE;
|
break;
|
||||||
}
|
case MTSE_INVRL: /* invalid rec lnt */
|
||||||
|
mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */
|
||||||
/* Read record length reverse - return T if error, EOM, or EOF */
|
return SCPE_MTRLNT;
|
||||||
|
case MTSE_RECE: /* record in error */
|
||||||
t_bool mt_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
case MTSE_EOM: /* end of medium */
|
||||||
{
|
mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */
|
||||||
if (uptr->pos < sizeof (t_mtrlnt)) { /* at BOT? */
|
break;
|
||||||
|
case MTSE_BOT: /* reverse into BOT */
|
||||||
uptr->USTAT = uptr->USTAT | STA_BOT; /* set status */
|
uptr->USTAT = uptr->USTAT | STA_BOT; /* set status */
|
||||||
return TRUE; } /* error */
|
mt_sta = mt_sta | STA_ERR;
|
||||||
fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET);
|
break;
|
||||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
case MTSE_WRP: /* write protect */
|
||||||
if ((*err = ferror (uptr->fileref)) || /* error? */
|
mt_sta = mt_sta | STA_ILL | STA_ERR; /* illegal operation */
|
||||||
feof (uptr->fileref)) { /* end of file? */
|
break; }
|
||||||
mt_sta = mt_sta | STA_PAR; /* parity error */
|
return SCPE_OK;
|
||||||
return TRUE; }
|
|
||||||
if (*tbc == MTR_EOM) { /* eom? */
|
|
||||||
mt_sta = mt_sta | STA_PAR; /* bad tape */
|
|
||||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over eom */
|
|
||||||
return TRUE; }
|
|
||||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
|
||||||
uptr->USTAT = uptr->USTAT | STA_EOF; /* end of file */
|
|
||||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over tmk */
|
|
||||||
return TRUE; }
|
|
||||||
if (MTRF (*tbc)) mt_sta = mt_sta | STA_PAR; /* record in error? */
|
|
||||||
*tbc = MTRL (*tbc); /* clear error flag */
|
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset routine */
|
/* Reset routine */
|
||||||
|
@ -573,11 +528,13 @@ int_req = int_req & ~INT_MT; /* clear interrupt */
|
||||||
for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */
|
for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */
|
||||||
uptr = mt_dev.units + u;
|
uptr = mt_dev.units + u;
|
||||||
sim_cancel (uptr); /* cancel activity */
|
sim_cancel (uptr); /* cancel activity */
|
||||||
MT_CLR_PNU (uptr); /* clear pos flag */
|
sim_tape_reset (uptr); /* reset tape */
|
||||||
if (uptr->flags & UNIT_ATT) uptr->USTAT =
|
if (uptr->flags & UNIT_ATT) uptr->USTAT =
|
||||||
((uptr->pos)? 0: STA_BOT) |
|
(sim_tape_bot (uptr)? STA_BOT: 0) |
|
||||||
((uptr->flags & UNIT_WPRT)? STA_WLK: 0);
|
(sim_tape_wrp (uptr)? STA_WLK: 0);
|
||||||
else uptr->USTAT = STA_REM; }
|
else uptr->USTAT = STA_REM; }
|
||||||
|
if (mtxb == NULL) mtxb = calloc (MT_MAXFR, sizeof (uint8));
|
||||||
|
if (mtxb == NULL) return SCPE_MEM;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -588,10 +545,9 @@ t_stat mt_attach (UNIT *uptr, char *cptr)
|
||||||
t_stat r;
|
t_stat r;
|
||||||
int32 u = uptr - mt_dev.units; /* get unit number */
|
int32 u = uptr - mt_dev.units; /* get unit number */
|
||||||
|
|
||||||
r = attach_unit (uptr, cptr);
|
r = sim_tape_attach (uptr, cptr);
|
||||||
if (r != SCPE_OK) return r;
|
if (r != SCPE_OK) return r;
|
||||||
MT_CLR_PNU (uptr);
|
uptr->USTAT = STA_BOT | (sim_tape_wrp (uptr)? STA_WLK: 0);
|
||||||
uptr->USTAT = STA_BOT | ((uptr->flags & UNIT_WPRT)? STA_WLK: 0);
|
|
||||||
if (u == GET_UNIT (mt_cu)) mt_updcsta (uptr);
|
if (u == GET_UNIT (mt_cu)) mt_updcsta (uptr);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -602,10 +558,9 @@ t_stat mt_detach (UNIT* uptr)
|
||||||
{
|
{
|
||||||
int32 u = uptr - mt_dev.units; /* get unit number */
|
int32 u = uptr - mt_dev.units; /* get unit number */
|
||||||
|
|
||||||
MT_CLR_PNU (uptr);
|
|
||||||
if (!sim_is_active (uptr)) uptr->USTAT = STA_REM;
|
if (!sim_is_active (uptr)) uptr->USTAT = STA_REM;
|
||||||
if (u == GET_UNIT (mt_cu)) mt_updcsta (uptr);
|
if (u == GET_UNIT (mt_cu)) mt_updcsta (uptr);
|
||||||
return detach_unit (uptr);
|
return sim_tape_detach (uptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write lock/enable routine */
|
/* Write lock/enable routine */
|
||||||
|
@ -614,7 +569,8 @@ t_stat mt_vlock (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
{
|
{
|
||||||
int32 u = uptr - mt_dev.units; /* get unit number */
|
int32 u = uptr - mt_dev.units; /* get unit number */
|
||||||
|
|
||||||
if ((uptr->flags & UNIT_ATT) && val) uptr->USTAT = uptr->USTAT | STA_WLK;
|
if ((uptr->flags & UNIT_ATT) && (val || sim_tape_wrp (uptr)))
|
||||||
|
uptr->USTAT = uptr->USTAT | STA_WLK;
|
||||||
else uptr->USTAT = uptr->USTAT & ~STA_WLK;
|
else uptr->USTAT = uptr->USTAT & ~STA_WLK;
|
||||||
if (u == GET_UNIT (mt_cu)) mt_updcsta (uptr);
|
if (u == GET_UNIT (mt_cu)) mt_updcsta (uptr);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
rf RF08 fixed head disk
|
rf RF08 fixed head disk
|
||||||
|
|
||||||
|
03-Mar-03 RMS Fixed autosizing
|
||||||
02-Feb-03 RMS Added variable platter and autosizing support
|
02-Feb-03 RMS Added variable platter and autosizing support
|
||||||
04-Oct-02 RMS Added DIB, device number support
|
04-Oct-02 RMS Added DIB, device number support
|
||||||
28-Nov-01 RMS Added RL8A support
|
28-Nov-01 RMS Added RL8A support
|
||||||
|
@ -48,9 +49,11 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */
|
#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */
|
||||||
#define UNIT_V_MSIZE (UNIT_V_UF + 1) /* dummy mask */
|
#define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */
|
||||||
|
#define UNIT_M_PLAT 03
|
||||||
|
#define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1)
|
||||||
#define UNIT_AUTO (1 << UNIT_V_AUTO)
|
#define UNIT_AUTO (1 << UNIT_V_AUTO)
|
||||||
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
|
#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT)
|
||||||
|
|
||||||
/* Constants */
|
/* Constants */
|
||||||
|
|
||||||
|
@ -130,7 +133,7 @@ DIB rf_dib = { DEV_RF, 5, { &rf60, &rf61, &rf62, NULL, &rf64 } };
|
||||||
|
|
||||||
UNIT rf_unit =
|
UNIT rf_unit =
|
||||||
{ UDATA (&rf_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF,
|
{ UDATA (&rf_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF,
|
||||||
RF_NUMDK * RF_DKSIZE) };
|
RF_DKSIZE) };
|
||||||
|
|
||||||
UNIT pcell_unit = { UDATA (&pcell_svc, 0, 0) };
|
UNIT pcell_unit = { UDATA (&pcell_svc, 0, 0) };
|
||||||
|
|
||||||
|
@ -149,10 +152,10 @@ REG rf_reg[] = {
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
MTAB rf_mod[] = {
|
MTAB rf_mod[] = {
|
||||||
{ UNIT_MSIZE, 262144, NULL, "1P", &rf_set_size },
|
{ UNIT_PLAT, 0, NULL, "1P", &rf_set_size },
|
||||||
{ UNIT_MSIZE, 524288, NULL, "2P", &rf_set_size },
|
{ UNIT_PLAT, 1, NULL, "2P", &rf_set_size },
|
||||||
{ UNIT_MSIZE, 786432, NULL, "3P", &rf_set_size },
|
{ UNIT_PLAT, 2, NULL, "3P", &rf_set_size },
|
||||||
{ UNIT_MSIZE, 1048576, NULL, "4P", &rf_set_size },
|
{ UNIT_PLAT, 3, NULL, "4P", &rf_set_size },
|
||||||
{ UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL },
|
{ UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL },
|
||||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||||
&set_dev, &show_dev, NULL },
|
&set_dev, &show_dev, NULL },
|
||||||
|
@ -370,19 +373,15 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat rf_attach (UNIT *uptr, char *cptr)
|
t_stat rf_attach (UNIT *uptr, char *cptr)
|
||||||
{
|
{
|
||||||
int32 p, d;
|
t_addr sz, p;
|
||||||
int32 ds_bytes = RF_DKSIZE * sizeof (int16);
|
t_addr ds_bytes = RF_DKSIZE * sizeof (int16);
|
||||||
|
|
||||||
if (uptr->flags & UNIT_AUTO) {
|
if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (cptr))) {
|
||||||
FILE *fp = fopen (cptr, "rb");
|
p = (sz + ds_bytes - 1) / ds_bytes;
|
||||||
if (fp == NULL) return SCPE_OPENERR;
|
if (p == 0) p = 1;
|
||||||
fseek (fp, 0, SEEK_END);
|
if (p > RF_NUMDK) p = RF_NUMDK; }
|
||||||
p = ftell (fp);
|
else p = UNIT_GETP (uptr->flags);
|
||||||
d = (p + ds_bytes - 1) / ds_bytes;
|
uptr->capac = p * RF_DKSIZE;
|
||||||
if (d == 0) d = 1;
|
|
||||||
if (d > RF_NUMDK) d = RF_NUMDK;
|
|
||||||
uptr->capac = d * RF_DKSIZE;
|
|
||||||
fclose (fp); }
|
|
||||||
return attach_unit (uptr, cptr);
|
return attach_unit (uptr, cptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -390,10 +389,9 @@ return attach_unit (uptr, cptr);
|
||||||
|
|
||||||
t_stat rf_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
t_stat rf_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
{
|
{
|
||||||
if ((val == 0) || (val > (RF_NUMDK * RF_DKSIZE)))
|
if ((val < 0) || (val >= RF_NUMDK)) return SCPE_IERR;
|
||||||
return SCPE_IERR;
|
|
||||||
if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
|
if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
|
||||||
uptr->capac = val;
|
uptr->capac = (val + 1) * RF_DKSIZE;
|
||||||
uptr->flags = uptr->flags & ~UNIT_AUTO;
|
uptr->flags = uptr->flags & ~UNIT_AUTO;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* pdp8_rx.c: RX8E/RX01, RX28/RX02 floppy disk simulator
|
/* pdp8_rx.c: RX8E/RX01, RX28/RX02 floppy disk simulator
|
||||||
|
|
||||||
Copyright (c) 1993-2002, Robert M Supnik
|
Copyright (c) 1993-2003, Robert M Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
rx RX8E/RX01, RX28/RX02 floppy disk
|
rx RX8E/RX01, RX28/RX02 floppy disk
|
||||||
|
|
||||||
|
03-Mar-03 RMS Fixed autosizing
|
||||||
08-Oct-02 RMS Added DIB, device number support
|
08-Oct-02 RMS Added DIB, device number support
|
||||||
Fixed reset to work with disabled device
|
Fixed reset to work with disabled device
|
||||||
15-Sep-02 RMS Added RX28/RX02 support
|
15-Sep-02 RMS Added RX28/RX02 support
|
||||||
|
@ -508,21 +509,13 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat rx_attach (UNIT *uptr, char *cptr)
|
t_stat rx_attach (UNIT *uptr, char *cptr)
|
||||||
{
|
{
|
||||||
int32 p;
|
t_addr sz;
|
||||||
t_stat r;
|
|
||||||
|
|
||||||
|
if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (cptr))) {
|
||||||
|
if (sz > RX_SIZE) uptr->flags = uptr->flags | UNIT_DEN;
|
||||||
|
else uptr->flags = uptr->flags & ~UNIT_DEN; }
|
||||||
uptr->capac = (uptr->flags & UNIT_DEN)? RX2_SIZE: RX_SIZE;
|
uptr->capac = (uptr->flags & UNIT_DEN)? RX2_SIZE: RX_SIZE;
|
||||||
r = attach_unit (uptr, cptr);
|
return attach_unit (uptr, cptr);
|
||||||
if ((r != SCPE_OK) || ((uptr->flags & UNIT_AUTO) == 0) ||
|
|
||||||
(rx_28 == 0)) return r;
|
|
||||||
if (fseek (uptr->fileref, 0, SEEK_END)) return SCPE_OK;
|
|
||||||
if ((p = ftell (uptr->fileref)) == 0) return SCPE_OK;
|
|
||||||
if (p > RX_SIZE) {
|
|
||||||
uptr->flags = uptr->flags | UNIT_DEN;
|
|
||||||
uptr->capac = RX2_SIZE; }
|
|
||||||
else { uptr->flags = uptr->flags & ~UNIT_DEN;
|
|
||||||
uptr->capac = RX_SIZE; }
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set size routine */
|
/* Set size routine */
|
||||||
|
|
|
@ -107,7 +107,6 @@ t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
|
||||||
{
|
{
|
||||||
int32 rubout, word, low, high, csum, newf, state, i;
|
int32 rubout, word, low, high, csum, newf, state, i;
|
||||||
t_addr origin, field;
|
t_addr origin, field;
|
||||||
extern t_bool match_ext (char *fnam, char *ext);
|
|
||||||
|
|
||||||
if ((*cptr != 0) || (flag != 0)) return SCPE_ARG;
|
if ((*cptr != 0) || (flag != 0)) return SCPE_ARG;
|
||||||
rubout = state = field = newf = origin = csum = 0;
|
rubout = state = field = newf = origin = csum = 0;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* pdp8_tt.c: PDP-8 console terminal simulator
|
/* pdp8_tt.c: PDP-8 console terminal simulator
|
||||||
|
|
||||||
Copyright (c) 1993-2002, Robert M Supnik
|
Copyright (c) 1993-2003, Robert M Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
tti,tto KL8E terminal input/output
|
tti,tto KL8E terminal input/output
|
||||||
|
|
||||||
|
02-Mar-02 RMS Added SET TTI CTRL-C
|
||||||
22-Dec-02 RMS Added break support
|
22-Dec-02 RMS Added break support
|
||||||
01-Nov-02 RMS Added 7B/8B support
|
01-Nov-02 RMS Added 7B/8B support
|
||||||
04-Oct-02 RMS Added DIBs, device number support
|
04-Oct-02 RMS Added DIBs, device number support
|
||||||
|
@ -48,6 +49,7 @@ t_stat tti_svc (UNIT *uptr);
|
||||||
t_stat tto_svc (UNIT *uptr);
|
t_stat tto_svc (UNIT *uptr);
|
||||||
t_stat tti_reset (DEVICE *dptr);
|
t_stat tti_reset (DEVICE *dptr);
|
||||||
t_stat tto_reset (DEVICE *dptr);
|
t_stat tto_reset (DEVICE *dptr);
|
||||||
|
t_stat tti_set_ctrlc (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc);
|
t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
|
||||||
/* TTI data structures
|
/* TTI data structures
|
||||||
|
@ -76,7 +78,8 @@ MTAB tti_mod[] = {
|
||||||
{ UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tty_set_mode },
|
{ UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tty_set_mode },
|
||||||
{ UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode },
|
{ UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode },
|
||||||
{ UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode },
|
{ UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode },
|
||||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev },
|
{ MTAB_XTD|MTAB_VDV|MTAB_VUN, 0, NULL, "CTRL-C", &tti_set_ctrlc, NULL, NULL },
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev, NULL },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
|
||||||
DEVICE tti_dev = {
|
DEVICE tti_dev = {
|
||||||
|
@ -159,14 +162,14 @@ int32 c;
|
||||||
sim_activate (&tti_unit, tti_unit.wait); /* continue poll */
|
sim_activate (&tti_unit, tti_unit.wait); /* continue poll */
|
||||||
if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */
|
if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */
|
||||||
if (c & SCPE_BREAK) tti_unit.buf = 0; /* break? */
|
if (c & SCPE_BREAK) tti_unit.buf = 0; /* break? */
|
||||||
else if (tti_unit.flags & UNIT_KSR) { /* UC only? */
|
else if (tti_unit.flags & UNIT_KSR) { /* KSR? */
|
||||||
c = c & 0177;
|
c = c & 0177;
|
||||||
if (islower (c)) c = toupper (c);
|
if (islower (c)) c = toupper (c);
|
||||||
tti_unit.buf = c | 0200; } /* add TTY bit */
|
tti_unit.buf = c | 0200; } /* add TTY bit */
|
||||||
else tti_unit.buf = c & ((tti_unit.flags & UNIT_8B)? 0377: 0177);
|
else tti_unit.buf = c & ((tti_unit.flags & UNIT_8B)? 0377: 0177);
|
||||||
|
tti_unit.pos = tti_unit.pos + 1;
|
||||||
dev_done = dev_done | INT_TTI; /* set done */
|
dev_done = dev_done | INT_TTI; /* set done */
|
||||||
int_req = INT_UPDATE; /* update interrupts */
|
int_req = INT_UPDATE; /* update interrupts */
|
||||||
tti_unit.pos = tti_unit.pos + 1;
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,6 +184,18 @@ int_enable = int_enable | INT_TTI; /* set enable */
|
||||||
sim_activate (&tti_unit, tti_unit.wait); /* activate unit */
|
sim_activate (&tti_unit, tti_unit.wait); /* activate unit */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set control-C */
|
||||||
|
|
||||||
|
t_stat tti_set_ctrlc (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
if (cptr) return SCPE_ARG;
|
||||||
|
uptr->buf = (uptr->flags & UNIT_KSR)? 0203: 0003;
|
||||||
|
uptr->pos = uptr->pos + 1;
|
||||||
|
dev_done = dev_done | INT_TTI; /* set done */
|
||||||
|
int_req = INT_UPDATE; /* update interrupts */
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* Terminal output: IOT routine */
|
/* Terminal output: IOT routine */
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* sds_cpu.c: SDS 940 CPU simulator
|
/* sds_cpu.c: SDS 940 CPU simulator
|
||||||
|
|
||||||
Copyright (c) 2001-2002, Robert M. Supnik
|
Copyright (c) 2001-2003, Robert M. Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -41,6 +41,8 @@
|
||||||
|
|
||||||
cpu central processor
|
cpu central processor
|
||||||
rtc real time clock
|
rtc real time clock
|
||||||
|
|
||||||
|
01-Mar-03 RMS Added SET/SHOW RTC FREQ support
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* The SDS 940 has three instruction format -- memory reference, register change,
|
/* The SDS 940 has three instruction format -- memory reference, register change,
|
||||||
|
@ -196,6 +198,9 @@ t_stat one_inst (uint32 inst, uint32 pc, uint32 mode);
|
||||||
t_stat rtc_inst (uint32 inst);
|
t_stat rtc_inst (uint32 inst);
|
||||||
t_stat rtc_svc (UNIT *uptr);
|
t_stat rtc_svc (UNIT *uptr);
|
||||||
t_stat rtc_reset (DEVICE *dptr);
|
t_stat rtc_reset (DEVICE *dptr);
|
||||||
|
t_stat rtc_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
t_stat rtc_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||||
|
|
||||||
extern t_bool io_init (void);
|
extern t_bool io_init (void);
|
||||||
extern t_stat op_wyim (uint32 inst, uint32 *dat);
|
extern t_stat op_wyim (uint32 inst, uint32 *dat);
|
||||||
extern t_stat op_miwy (uint32 inst, uint32 dat);
|
extern t_stat op_miwy (uint32 inst, uint32 dat);
|
||||||
|
@ -278,11 +283,20 @@ UNIT rtc_unit = { UDATA (&rtc_svc, 0, 0), 16000 };
|
||||||
REG rtc_reg[] = {
|
REG rtc_reg[] = {
|
||||||
{ FLDATA (PIE, rtc_pie, 0) },
|
{ FLDATA (PIE, rtc_pie, 0) },
|
||||||
{ DRDATA (TIME, rtc_unit.wait, 24), REG_NZ + PV_LEFT },
|
{ DRDATA (TIME, rtc_unit.wait, 24), REG_NZ + PV_LEFT },
|
||||||
{ DRDATA (TPS, rtc_tps, 8), REG_NZ + PV_LEFT },
|
{ DRDATA (TPS, rtc_tps, 8), PV_LEFT + REG_HRO },
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
|
MTAB rtc_mod[] = {
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 50, NULL, "50HZ",
|
||||||
|
&rtc_set_freq, NULL, NULL },
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 60, NULL, "60HZ",
|
||||||
|
&rtc_set_freq, NULL, NULL },
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 0, "FREQUENCY", NULL,
|
||||||
|
NULL, &rtc_show_freq, NULL },
|
||||||
|
{ 0 } };
|
||||||
|
|
||||||
DEVICE rtc_dev = {
|
DEVICE rtc_dev = {
|
||||||
"RTC", &rtc_unit, rtc_reg, NULL,
|
"RTC", &rtc_unit, rtc_reg, rtc_mod,
|
||||||
1, 8, 8, 1, 8, 8,
|
1, 8, 8, 1, 8, 8,
|
||||||
NULL, NULL, &rtc_reset,
|
NULL, NULL, &rtc_reset,
|
||||||
NULL, NULL, NULL };
|
NULL, NULL, NULL };
|
||||||
|
@ -1222,6 +1236,8 @@ sim_activate (&rtc_unit, sim_rtcn_calb (rtc_tps, TMR_RTC)); /* reactivate unit *
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Clock interrupt instruction */
|
||||||
|
|
||||||
t_stat rtc_inst (uint32 inst)
|
t_stat rtc_inst (uint32 inst)
|
||||||
{
|
{
|
||||||
uint32 op, dat, val, va;
|
uint32 op, dat, val, va;
|
||||||
|
@ -1239,9 +1255,29 @@ if (dat == 0) int_req = int_req | INT_RTCS; /* set clk sync int */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Clock reset */
|
||||||
|
|
||||||
t_stat rtc_reset (DEVICE *dptr)
|
t_stat rtc_reset (DEVICE *dptr)
|
||||||
{
|
{
|
||||||
rtc_pie = 0; /* disable pulse */
|
rtc_pie = 0; /* disable pulse */
|
||||||
sim_activate (&rtc_unit, rtc_unit.wait); /* activate unit */
|
sim_activate (&rtc_unit, rtc_unit.wait); /* activate unit */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set frequency */
|
||||||
|
|
||||||
|
t_stat rtc_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
if (cptr) return SCPE_ARG;
|
||||||
|
if ((val != 50) && (val != 60)) return SCPE_IERR;
|
||||||
|
rtc_tps = val;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Show frequency */
|
||||||
|
|
||||||
|
t_stat rtc_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||||
|
{
|
||||||
|
fprintf (st, (rtc_tps == 50)? "50Hz": "60Hz");
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
|
@ -60,7 +60,6 @@ sim> c
|
||||||
Breakpoint, P: 00112 (BRU 3)
|
Breakpoint, P: 00112 (BRU 3)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
930 P&S Register Test
|
930 P&S Register Test
|
||||||
|
|
||||||
sim> att mt diag.tap
|
sim> att mt diag.tap
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
To: Users
|
To: Users
|
||||||
From: Bob Supnik
|
From: Bob Supnik
|
||||||
Subj: SDS 940 Simulator Usage
|
Subj: SDS 940 Simulator Usage
|
||||||
Date: 15-Nov-2002
|
Date: 15-Mar-2003
|
||||||
|
|
||||||
COPYRIGHT NOTICE
|
COPYRIGHT NOTICE
|
||||||
|
|
||||||
The following copyright notice applies to both the SIMH source and binary:
|
The following copyright notice applies to both the SIMH source and binary:
|
||||||
|
|
||||||
Original code published in 1993-2002, written by Robert M Supnik
|
Original code published in 1993-2003, written by Robert M Supnik
|
||||||
Copyright (c) 1993-2002, Robert M Supnik
|
Copyright (c) 1993-2003, Robert M Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -39,10 +39,12 @@ This memorandum documents the SDS 940 simulator.
|
||||||
sim/ sim_defs.h
|
sim/ sim_defs.h
|
||||||
sim_rev.h
|
sim_rev.h
|
||||||
sim_sock.h
|
sim_sock.h
|
||||||
|
sim_tape.h
|
||||||
sim_tmxr.h
|
sim_tmxr.h
|
||||||
scp.c
|
scp.c
|
||||||
scp_tty.c
|
scp_tty.c
|
||||||
sim_sock.c
|
sim_sock.c
|
||||||
|
sim_tape.c
|
||||||
sim_tmxr.c
|
sim_tmxr.c
|
||||||
|
|
||||||
sim/sds/ sds_defs.h
|
sim/sds/ sds_defs.h
|
||||||
|
@ -296,15 +298,21 @@ Error handling is as follows:
|
||||||
|
|
||||||
By default, the line printer is assigned to channel W.
|
By default, the line printer is assigned to channel W.
|
||||||
|
|
||||||
2.8 Real Time Clock (RTC)
|
2.8 Real-Time Clock (RTC)
|
||||||
|
|
||||||
The real time clock (RTC) implements these registers:
|
The real-time clock (RTC) frequency can be adjusted as follows:
|
||||||
|
|
||||||
|
SET RTC 60HZ set frequency to 60Hz
|
||||||
|
SET RTC 50HZ set frequency to 50Hz
|
||||||
|
|
||||||
|
The default is 60Hz.
|
||||||
|
|
||||||
|
The clock implements these registers:
|
||||||
|
|
||||||
name size comments
|
name size comments
|
||||||
|
|
||||||
PIE 1 interrupt enable
|
PIE 1 interrupt enable
|
||||||
TIME 24 tick interval
|
TIME 24 tick interval
|
||||||
TPS 8 ticks per second
|
|
||||||
|
|
||||||
The real-time clock autocalibrates; the clock interval is adjusted up or
|
The real-time clock autocalibrates; the clock interval is adjusted up or
|
||||||
down so that the clock tracks actual elapsed time.
|
down so that the clock tracks actual elapsed time.
|
||||||
|
|
120
SDS/sds_mt.c
120
SDS/sds_mt.c
|
@ -1,6 +1,6 @@
|
||||||
/* sds_mt.c: SDS 940 magnetic tape simulator
|
/* sds_mt.c: SDS 940 magnetic tape simulator
|
||||||
|
|
||||||
Copyright (c) 2001-2002, Robert M. Supnik
|
Copyright (c) 2001-2003, Robert M. Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
mt 7 track magnetic tape
|
mt 7 track magnetic tape
|
||||||
|
|
||||||
|
28-Feb-03 RMS Revised for magtape library
|
||||||
|
|
||||||
Magnetic tapes are represented as a series of variable 8b records
|
Magnetic tapes are represented as a series of variable 8b records
|
||||||
of the form:
|
of the form:
|
||||||
|
|
||||||
|
@ -42,16 +44,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "sds_defs.h"
|
#include "sds_defs.h"
|
||||||
|
#include "sim_tape.h"
|
||||||
|
|
||||||
#define MT_MAXFR (32768 * 4)
|
#define MT_MAXFR (32768 * 4)
|
||||||
#define MT_NUMDR 8 /* number drives */
|
#define MT_NUMDR 8 /* number drives */
|
||||||
#define MT_UNIT 07
|
#define MT_UNIT 07
|
||||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
|
||||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
|
||||||
#define botf u3 /* bot tape flag */
|
#define botf u3 /* bot tape flag */
|
||||||
#define eotf u4 /* eot tape flag */
|
#define eotf u4 /* eot tape flag */
|
||||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
|
||||||
|
|
||||||
#define MTR_BOT 0xFFFFFFFE /* BOT pseudo mark */
|
|
||||||
|
|
||||||
extern uint32 xfr_req;
|
extern uint32 xfr_req;
|
||||||
extern int32 stop_invins, stop_invdev, stop_inviop;
|
extern int32 stop_invins, stop_invdev, stop_inviop;
|
||||||
|
@ -141,8 +140,8 @@ REG mt_reg[] = {
|
||||||
{ NULL } };
|
{ NULL } };
|
||||||
|
|
||||||
MTAB mt_mod[] = {
|
MTAB mt_mod[] = {
|
||||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
|
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
|
||||||
{ MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL",
|
{ MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL",
|
||||||
&set_chan, &show_chan, NULL },
|
&set_chan, &show_chan, NULL },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
@ -199,7 +198,8 @@ case IO_EOM1: /* EOM mode 1 */
|
||||||
if (new_ch != mt_dib.chan) CRETIOP; /* wrong chan? */
|
if (new_ch != mt_dib.chan) CRETIOP; /* wrong chan? */
|
||||||
t = inst & 07670; /* get command */
|
t = inst & 07670; /* get command */
|
||||||
if ((t == 04010) && !sim_is_active (uptr)) { /* rewind? */
|
if ((t == 04010) && !sim_is_active (uptr)) { /* rewind? */
|
||||||
uptr->pos = uptr->eotf = 0; /* clr pos, eot */
|
sim_tape_rewind (uptr); /* rewind unit */
|
||||||
|
uptr->eotf = 0; /* clr eot */
|
||||||
uptr->botf = 1; } /* set bot */
|
uptr->botf = 1; } /* set bot */
|
||||||
else if ((t == 03610) && sim_is_active (uptr) && /* skip rec? */
|
else if ((t == 03610) && sim_is_active (uptr) && /* skip rec? */
|
||||||
((mt_inst & DEV_OUT) == 0)) mt_skip = 1; /* set flag */
|
((mt_inst & DEV_OUT) == 0)) mt_skip = 1; /* set flag */
|
||||||
|
@ -245,7 +245,7 @@ case IO_SKS: /* SKS */
|
||||||
if (!mt_eof) *dat = 1; /* not EOF */
|
if (!mt_eof) *dat = 1; /* not EOF */
|
||||||
break;
|
break;
|
||||||
case 020: /* sks 1401n */
|
case 020: /* sks 1401n */
|
||||||
if (!(uptr->flags & UNIT_WPRT)) *dat = 1; /* not wrp */
|
if (!sim_tape_wrp (uptr)) *dat = 1; /* not wrp */
|
||||||
break;
|
break;
|
||||||
case 031: /* sks 1621n */
|
case 031: /* sks 1621n */
|
||||||
case 033: /* sks 1661n */
|
case 033: /* sks 1661n */
|
||||||
|
@ -301,62 +301,30 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat mt_readrec (UNIT *uptr)
|
t_stat mt_readrec (UNIT *uptr)
|
||||||
{
|
{
|
||||||
t_mtrlnt abc, tbc;
|
t_mtrlnt tbc;
|
||||||
|
t_stat st, r = SCPE_OK;
|
||||||
|
|
||||||
if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */
|
if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */
|
||||||
mt_set_err (uptr); /* no, err, disc */
|
mt_set_err (uptr); /* no, err, disc */
|
||||||
return SCPE_UNATT; }
|
return SCPE_UNATT; }
|
||||||
tbc = mt_readbc (uptr); /* get bc */
|
if (mt_inst & CHC_REV) /* reverse? */
|
||||||
if (tbc == MTR_EOM) { /* end of med? */
|
st = sim_tape_rdrecr (uptr, mtxb, &tbc, MT_MAXFR); /* read rec rev */
|
||||||
uptr->eotf = 1; /* end of tape */
|
else st = sim_tape_rdrecf (uptr, mtxb, &tbc, MT_MAXFR); /* no, fwd */
|
||||||
mt_set_err (uptr); /* err, disc */
|
if (st == MTSE_TMK) { /* tape mark? */
|
||||||
return SCPE_OK; }
|
|
||||||
if (tbc == MTR_BOT) { /* BOT? */
|
|
||||||
mt_set_err (uptr); /* err, disc */
|
|
||||||
return SCPE_OK; }
|
|
||||||
if (tbc == MTR_TMK) { /* tape mark? */
|
|
||||||
mt_eof = 1; /* set eof flag */
|
mt_eof = 1; /* set eof flag */
|
||||||
mtxb[0] = mtxb[1] = 017; /* EOR char */
|
mtxb[0] = mtxb[1] = 017; /* EOR char */
|
||||||
mt_blnt = 2; /* store 2 */
|
mt_blnt = 2; /* store 2 */
|
||||||
uptr->pos += sizeof (t_mtrlnt); /* update position */
|
return SCPE_OK; }
|
||||||
|
if (st != MTSE_OK) { /* other error? */
|
||||||
|
mt_set_err (uptr); /* err, disc */
|
||||||
|
if (st == MTSE_IOERR) return SCPE_IOERR; /* IO error? */
|
||||||
|
if (st == MTSE_INVRL) return SCPE_MTRLNT; /* inv rec lnt? */
|
||||||
|
if (st == MTSE_EOM) uptr->eotf = 1; /* eom? set eot */
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
mt_blnt = tbc; /* set buf lnt */
|
mt_blnt = tbc; /* set buf lnt */
|
||||||
if (tbc > MT_MAXFR) return SCPE_MTRLNT; /* record too long? */
|
|
||||||
if (mt_inst & CHC_REV) { /* reverse? */
|
|
||||||
fseek (uptr->fileref, uptr->pos - ((tbc + 1) & ~1) - sizeof (t_mtrlnt), SEEK_SET);
|
|
||||||
mt_bptr = mt_blnt; }
|
|
||||||
abc = fxread (mtxb, sizeof (uint8), tbc, uptr->fileref);/* read record */
|
|
||||||
for (; abc < tbc; abc++) mtxb[abc] = 0; /* zero fill */
|
|
||||||
if (ferror (uptr->fileref)) { /* I/O error */
|
|
||||||
mt_set_err (uptr); /* no, err, disc */
|
|
||||||
perror ("MT I/O error");
|
|
||||||
clearerr (uptr->fileref);
|
|
||||||
return SCPE_IOERR; }
|
|
||||||
if (mt_inst & CHC_REV) /* update pos */
|
|
||||||
uptr->pos -= (((tbc + 1) & ~1) + (2 * sizeof (t_mtrlnt)));
|
|
||||||
else uptr->pos += (((tbc + 1) & ~1) + (2 * sizeof (t_mtrlnt)));
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read record byte count */
|
|
||||||
|
|
||||||
t_mtrlnt mt_readbc (UNIT *uptr)
|
|
||||||
{
|
|
||||||
t_mtrlnt tbc;
|
|
||||||
|
|
||||||
if (mt_inst & CHC_REV) {
|
|
||||||
if (uptr->pos < sizeof (t_mtrlnt)) {
|
|
||||||
uptr->botf = 1;
|
|
||||||
return MTR_BOT; }
|
|
||||||
fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET); }
|
|
||||||
else fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
|
||||||
fxread (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
|
||||||
if (ferror (uptr->fileref) || feof (uptr->fileref) || /* err, eof, eom? */
|
|
||||||
(tbc == MTR_EOM)) return MTR_EOM; /* return EOM */
|
|
||||||
if (MTRF (tbc)) chan_set_flag (mt_dib.chan, CHF_ERR); /* rec err? set flag */
|
|
||||||
return MTRL (tbc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read done (eof, end of record) */
|
/* Read done (eof, end of record) */
|
||||||
|
|
||||||
void mt_readend (UNIT *uptr)
|
void mt_readend (UNIT *uptr)
|
||||||
|
@ -375,51 +343,32 @@ return;
|
||||||
|
|
||||||
t_stat mt_wrend (uint32 dev)
|
t_stat mt_wrend (uint32 dev)
|
||||||
{
|
{
|
||||||
static t_mtrlnt bceom = MTR_EOM;
|
|
||||||
static t_mtrlnt bceof = MTR_TMK;
|
|
||||||
UNIT *uptr = mt_dev.units + (dev & MT_UNIT);
|
UNIT *uptr = mt_dev.units + (dev & MT_UNIT);
|
||||||
t_addr old_pos = uptr->pos;
|
|
||||||
t_mtrlnt tbc;
|
t_mtrlnt tbc;
|
||||||
|
t_stat st;
|
||||||
|
|
||||||
sim_cancel (uptr); /* no more xfr's */
|
sim_cancel (uptr); /* no more xfr's */
|
||||||
if (mt_bptr == 0) return SCPE_OK; /* buf empty? */
|
if (mt_bptr == 0) return SCPE_OK; /* buf empty? */
|
||||||
if (!(uptr->flags & UNIT_ATT)) { /* attached? */
|
if (!(uptr->flags & UNIT_ATT)) { /* attached? */
|
||||||
mt_set_err (uptr); /* no, err, disc */
|
mt_set_err (uptr); /* no, err, disc */
|
||||||
return SCPE_UNATT; }
|
return SCPE_UNATT; }
|
||||||
if (uptr->flags & UNIT_WPRT) { /* write lock? */
|
if (sim_tape_wrp (uptr)) { /* write lock? */
|
||||||
mt_set_err (uptr); /* yes, err, disc */
|
mt_set_err (uptr); /* yes, err, disc */
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
if (dev & DEV_MTS) { /* erase? */
|
if (dev & DEV_MTS) { /* erase? */
|
||||||
if (mt_inst & CHC_REV) { /* reverse? */
|
if (mt_inst & CHC_REV) /* reverse? */
|
||||||
tbc = mt_readbc (uptr); /* get bc */
|
sim_tape_sprecr (uptr, &tbc); /* backspace */
|
||||||
if ((tbc == MTR_TMK) || (tbc == MTR_EOM)) /* tmk, eom? */
|
st = sim_tape_wreom (uptr); /* write eom */
|
||||||
fseek (uptr->fileref, uptr->pos -= sizeof (t_mtrlnt), SEEK_SET);
|
|
||||||
else if (tbc != MTR_BOT) { /* not BOT? */
|
|
||||||
tbc = MTRL (tbc); /* clear error */
|
|
||||||
fseek (uptr->fileref, uptr->pos -=
|
|
||||||
(((tbc + 1) & ~1) - sizeof (t_mtrlnt)), SEEK_SET); } }
|
|
||||||
fxwrite (&bceom, sizeof (t_mtrlnt), 1, uptr->fileref);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set position */
|
|
||||||
if ((mt_bptr == 1) && (mtxb[0] == 017) && /* wr eof? */
|
if ((mt_bptr == 1) && (mtxb[0] == 017) && /* wr eof? */
|
||||||
((mt_inst & 01670) == 00050)) {
|
((mt_inst & 01670) == 00050))
|
||||||
fxwrite (&bceof, sizeof (t_mtrlnt), 1, uptr->fileref);
|
st = sim_tape_wrtmk (uptr); /* write tape mark */
|
||||||
uptr->pos += sizeof (t_mtrlnt); }
|
else st = sim_tape_wrrecf (uptr, mtxb, mt_bptr); /* write record */
|
||||||
else { /* normal wr */
|
|
||||||
fxwrite (&mt_bptr, sizeof (t_mtrlnt), 1, uptr->fileref);
|
|
||||||
fxwrite (mtxb, sizeof (uint8), (mt_bptr + 1) & ~1, uptr->fileref);
|
|
||||||
fxwrite (&mt_bptr, sizeof (t_mtrlnt), 1, uptr->fileref);
|
|
||||||
uptr->pos += ((mt_bptr + 1) & ~1) + (2 * sizeof (t_mtrlnt));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
mt_bptr = 0;
|
mt_bptr = 0;
|
||||||
if (ferror (uptr->fileref)) { /* I/O error */
|
if (st != MTSE_OK) mt_set_err (uptr); /* error? */
|
||||||
uptr->pos = old_pos; /* restore pos */
|
if (st == MTSE_IOERR) return SCPE_IOERR;
|
||||||
mt_set_err (uptr); /* no, err, disc */
|
|
||||||
perror ("MT I/O error");
|
|
||||||
clearerr (uptr->fileref);
|
|
||||||
return SCPE_IOERR; }
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -449,6 +398,7 @@ mt_bptr = mt_blnt = 0;
|
||||||
xfr_req = xfr_req & ~XFR_MT0; /* clr xfr flag */
|
xfr_req = xfr_req & ~XFR_MT0; /* clr xfr flag */
|
||||||
for (i = 0; i < MT_NUMDR; i++) { /* deactivate */
|
for (i = 0; i < MT_NUMDR; i++) { /* deactivate */
|
||||||
sim_cancel (&mt_unit[i]);
|
sim_cancel (&mt_unit[i]);
|
||||||
|
sim_tape_reset (&mt_unit[i]);
|
||||||
mt_unit[i].eotf = 0; }
|
mt_unit[i].eotf = 0; }
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -459,7 +409,7 @@ t_stat mt_attach (UNIT *uptr, char *cptr)
|
||||||
{
|
{
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
r = attach_unit (uptr, cptr);
|
r = sim_tape_attach (uptr, cptr);
|
||||||
if (r != SCPE_OK) return r;
|
if (r != SCPE_OK) return r;
|
||||||
uptr->botf = 1;
|
uptr->botf = 1;
|
||||||
uptr->eotf = 0;
|
uptr->eotf = 0;
|
||||||
|
@ -469,7 +419,7 @@ return SCPE_OK;
|
||||||
t_stat mt_detach (UNIT *uptr)
|
t_stat mt_detach (UNIT *uptr)
|
||||||
{
|
{
|
||||||
uptr->botf = uptr->eotf = 0;
|
uptr->botf = uptr->eotf = 0;
|
||||||
return detach_unit (uptr);
|
return sim_tape_detach (uptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Boot routine - simulate FILL console command */
|
/* Boot routine - simulate FILL console command */
|
||||||
|
|
|
@ -415,6 +415,12 @@ implements these registers:
|
||||||
POS 32 number of characters input
|
POS 32 number of characters input
|
||||||
TIME 24 keyboard polling interval
|
TIME 24 keyboard polling interval
|
||||||
|
|
||||||
|
If the simulator is compiled under Windows Visual C++, typing ^C to the
|
||||||
|
terminal input causes a fatal run-time error. Use the following command
|
||||||
|
to simulate typing ^C:
|
||||||
|
|
||||||
|
SET TTI CTRL-C
|
||||||
|
|
||||||
2.3.4 Terminal Output (TTO)
|
2.3.4 Terminal Output (TTO)
|
||||||
|
|
||||||
The terminal output (TTO) writes to the simulator console window. It
|
The terminal output (TTO) writes to the simulator console window. It
|
||||||
|
@ -584,7 +590,7 @@ The simulator implements four MSCP disk controllers, RQ, RQB, RQC, RQD.
|
||||||
Initially, RQB, RQC, and RQD are disabled. Each RQ controller simulates
|
Initially, RQB, RQC, and RQD are disabled. Each RQ controller simulates
|
||||||
an RQDX3 MSCP disk controller. RQ options include the ability to set
|
an RQDX3 MSCP disk controller. RQ options include the ability to set
|
||||||
units write enabled or write locked, and to set the drive type to one
|
units write enabled or write locked, and to set the drive type to one
|
||||||
of eleven disk types:
|
of many disk types:
|
||||||
|
|
||||||
SET RQn LOCKED set unit n write locked
|
SET RQn LOCKED set unit n write locked
|
||||||
SET RQn WRITEENABLED set unit n write enabled
|
SET RQn WRITEENABLED set unit n write enabled
|
||||||
|
@ -599,12 +605,14 @@ of eleven disk types:
|
||||||
SET RQn RA72 set type to RA72
|
SET RQn RA72 set type to RA72
|
||||||
SET RQn RA90 set type to RA90
|
SET RQn RA90 set type to RA90
|
||||||
SET RQn RA92 set type to RA92
|
SET RQn RA92 set type to RA92
|
||||||
|
SET RQn RA81 set type to RA81 with n LBN's.
|
||||||
|
|
||||||
The type options can be used only when a unit is not attached to a file.
|
The type options can be used only when a unit is not attached to a file.
|
||||||
Units can also be set ONLINE or OFFLINE.
|
Units can also be set ONLINE or OFFLINE.
|
||||||
|
|
||||||
Each RQ controller implements the following special SHOW commands:
|
Each RQ controller implements the following special SHOW commands:
|
||||||
|
|
||||||
|
SHOW RQn TYPE show drive type
|
||||||
SHOW RQ RINGS show command and response rings
|
SHOW RQ RINGS show command and response rings
|
||||||
SHOW RQ FREEQ show packet free queue
|
SHOW RQ FREEQ show packet free queue
|
||||||
SHOW RQ RESPQ show packet response queue
|
SHOW RQ RESPQ show packet response queue
|
||||||
|
@ -705,13 +713,22 @@ Error handling is as follows:
|
||||||
2.7 TQK50 TMSCP Disk Controller (TQ)
|
2.7 TQK50 TMSCP Disk Controller (TQ)
|
||||||
|
|
||||||
The TQ controller simulates the TQK50 TMSCP disk controller. TQ options
|
The TQ controller simulates the TQK50 TMSCP disk controller. TQ options
|
||||||
include the ability to set units write enabled or write locked:
|
include the ability to set units write enabled or write locked, and to
|
||||||
|
specify the controller type and tape length:
|
||||||
|
|
||||||
SET TQn LOCKED set unit n write locked
|
SET TQn LOCKED set unit n write locked
|
||||||
SET TQn WRITEENABLED set unit n write enabled
|
SET TQn WRITEENABLED set unit n write enabled
|
||||||
|
SET TQ TK50 set controller type to TK50
|
||||||
|
SET TQ TK70 set controller type to TK70
|
||||||
|
SET TQ TU81 set controller type to TU81
|
||||||
|
SET TQ TKUSER{=n} set controller type to TK50 with
|
||||||
|
tape capacity of n MB
|
||||||
|
|
||||||
|
User-specified capacity must be between 50 and 2000 MB.
|
||||||
|
|
||||||
The TQ controller implements the following special SHOW commands:
|
The TQ controller implements the following special SHOW commands:
|
||||||
|
|
||||||
|
SHOW TQ TYPE show controller type
|
||||||
SHOW TQ RINGS show command and response rings
|
SHOW TQ RINGS show command and response rings
|
||||||
SHOW TQ FREEQ show packet free queue
|
SHOW TQ FREEQ show packet free queue
|
||||||
SHOW TQ RESPQ show packet response queue
|
SHOW TQ RESPQ show packet response queue
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* vax_stddev.c: VAX standard I/O devices simulator
|
/* vax_stddev.c: VAX standard I/O devices simulator
|
||||||
|
|
||||||
Copyright (c) 1998-2002, Robert M Supnik
|
Copyright (c) 1998-2003, Robert M Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -27,6 +27,7 @@
|
||||||
tto terminal output
|
tto terminal output
|
||||||
clk 100Hz and TODR clock
|
clk 100Hz and TODR clock
|
||||||
|
|
||||||
|
02-Mar-02 RMS Added SET TTI CTRL-C
|
||||||
22-Dec-02 RMS Added console halt capability
|
22-Dec-02 RMS Added console halt capability
|
||||||
01-Nov-02 RMS Added 7B/8B capability to terminal
|
01-Nov-02 RMS Added 7B/8B capability to terminal
|
||||||
12-Sep-02 RMS Removed paper tape, added variable vector support
|
12-Sep-02 RMS Removed paper tape, added variable vector support
|
||||||
|
@ -71,6 +72,7 @@ t_stat clk_svc (UNIT *uptr);
|
||||||
t_stat tti_reset (DEVICE *dptr);
|
t_stat tti_reset (DEVICE *dptr);
|
||||||
t_stat tto_reset (DEVICE *dptr);
|
t_stat tto_reset (DEVICE *dptr);
|
||||||
t_stat clk_reset (DEVICE *dptr);
|
t_stat clk_reset (DEVICE *dptr);
|
||||||
|
t_stat tti_set_ctrlc (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||||
|
|
||||||
extern int32 sysd_hlt_enb (void);
|
extern int32 sysd_hlt_enb (void);
|
||||||
|
|
||||||
|
@ -98,7 +100,10 @@ REG tti_reg[] = {
|
||||||
MTAB tti_mod[] = {
|
MTAB tti_mod[] = {
|
||||||
{ UNIT_8B, UNIT_8B, "8b", "8B", NULL },
|
{ UNIT_8B, UNIT_8B, "8b", "8B", NULL },
|
||||||
{ UNIT_8B, 0 , "7b", "7B", NULL },
|
{ UNIT_8B, 0 , "7b", "7B", NULL },
|
||||||
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, NULL, &show_vec },
|
{ MTAB_XTD|MTAB_VDV|MTAB_VUN, 0, NULL, "CTRL-C",
|
||||||
|
&tti_set_ctrlc, NULL, NULL },
|
||||||
|
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL,
|
||||||
|
NULL, &show_vec, NULL },
|
||||||
{ 0 } };
|
{ 0 } };
|
||||||
|
|
||||||
DEVICE tti_dev = {
|
DEVICE tti_dev = {
|
||||||
|
@ -285,6 +290,18 @@ CLR_INT (TTI);
|
||||||
sim_activate (&tti_unit, tti_unit.wait); /* activate unit */
|
sim_activate (&tti_unit, tti_unit.wait); /* activate unit */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set control-C */
|
||||||
|
|
||||||
|
t_stat tti_set_ctrlc (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||||
|
{
|
||||||
|
if (cptr) return SCPE_ARG;
|
||||||
|
uptr->buf = 003;
|
||||||
|
uptr->pos = uptr->pos + 1;
|
||||||
|
tti_csr = tti_csr | CSR_DONE;
|
||||||
|
if (tti_csr & CSR_IE) SET_INT (TTI);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* Terminal output routines
|
/* Terminal output routines
|
||||||
|
|
||||||
|
|
|
@ -98,9 +98,9 @@ CC = CC $(CC_FLAGS)
|
||||||
SIMH_DIR = SYS$DISK:[]
|
SIMH_DIR = SYS$DISK:[]
|
||||||
SIMH_LIB = $(LIB_DIR)SIMH-$(ARCH).OLB
|
SIMH_LIB = $(LIB_DIR)SIMH-$(ARCH).OLB
|
||||||
SIMH_SOURCE = $(SIMH_DIR)SCP_TTY.C,$(SIMH_DIR)SIM_SOCK.C,\
|
SIMH_SOURCE = $(SIMH_DIR)SCP_TTY.C,$(SIMH_DIR)SIM_SOCK.C,\
|
||||||
$(SIMH_DIR)SIM_TMXR.C,$(SIMH_DIR)SIM_ETHER.C
|
$(SIMH_DIR)SIM_TMXR.C,$(SIMH_DIR)SIM_ETHER.C,$(SIMH_DIR)SIM_TAPE.C
|
||||||
SIMH_OBJS = $(SIMH_DIR)SCP_TTY.OBJ,$(SIMH_DIR)SIM_SOCK.OBJ,\
|
SIMH_OBJS = $(SIMH_DIR)SCP_TTY.OBJ,$(SIMH_DIR)SIM_SOCK.OBJ,\
|
||||||
$(SIMH_DIR)SIM_TMXR.OBJ,$(SIMH_DIR)SIM_ETHER.OBJ
|
$(SIMH_DIR)SIM_TMXR.OBJ,$(SIMH_DIR)SIM_ETHER.OBJ,$(SIMH_DIR)SIM_TAPE.OBJ
|
||||||
|
|
||||||
#
|
#
|
||||||
# MITS Altair Simulator Definitions.
|
# MITS Altair Simulator Definitions.
|
||||||
|
|
11
makefile
11
makefile
|
@ -27,7 +27,7 @@ endif
|
||||||
# Common Libraries
|
# Common Libraries
|
||||||
#
|
#
|
||||||
BIN = BIN/
|
BIN = BIN/
|
||||||
SIM = scp.c scp_tty.c sim_sock.c sim_tmxr.c sim_ether.c
|
SIM = scp.c scp_tty.c sim_sock.c sim_tmxr.c sim_ether.c sim_tape.c
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -212,7 +212,7 @@ SDS_OPT = -I ${SDSD}
|
||||||
#
|
#
|
||||||
# Build everything
|
# Build everything
|
||||||
#
|
#
|
||||||
all : ${BIN}pdp1${EXE} ${BIN}pdp4${EXE} ${BIN}pdp7${EXE} ${BIN}pdp8${EXE} \
|
ALL = ${BIN}pdp1${EXE} ${BIN}pdp4${EXE} ${BIN}pdp7${EXE} ${BIN}pdp8${EXE} \
|
||||||
${BIN}pdp9${EXE} ${BIN}pdp15${EXE} ${BIN}pdp11${EXE} ${BIN}pdp10${EXE} \
|
${BIN}pdp9${EXE} ${BIN}pdp15${EXE} ${BIN}pdp11${EXE} ${BIN}pdp10${EXE} \
|
||||||
${BIN}vax${EXE} ${BIN}nova${EXE} ${BIN}eclipse${EXE} ${BIN}h316${EXE} \
|
${BIN}vax${EXE} ${BIN}nova${EXE} ${BIN}eclipse${EXE} ${BIN}h316${EXE} \
|
||||||
${BIN}hp2100${EXE} ${BIN}i1401${EXE} ${BIN}i1620${EXE} ${BIN}s3${EXE} \
|
${BIN}hp2100${EXE} ${BIN}i1401${EXE} ${BIN}i1620${EXE} ${BIN}s3${EXE} \
|
||||||
|
@ -220,7 +220,14 @@ all : ${BIN}pdp1${EXE} ${BIN}pdp4${EXE} ${BIN}pdp7${EXE} ${BIN}pdp8${EXE} \
|
||||||
${BIN}i1620${EXE} ${BIN}ibm1130${EXE} ${BIN}id16${EXE} \
|
${BIN}i1620${EXE} ${BIN}ibm1130${EXE} ${BIN}id16${EXE} \
|
||||||
${BIN}id32${EXE} ${BIN}sds${EXE}
|
${BIN}id32${EXE} ${BIN}sds${EXE}
|
||||||
|
|
||||||
|
all : ${ALL}
|
||||||
|
|
||||||
|
clean :
|
||||||
|
ifeq ($(WIN32),)
|
||||||
|
${RM} ${ALL}
|
||||||
|
else
|
||||||
|
if exist BIN\*.exe del /q BIN\*.exe
|
||||||
|
endif
|
||||||
#
|
#
|
||||||
# Individual builds
|
# Individual builds
|
||||||
#
|
#
|
||||||
|
|
284
scp.c
284
scp.c
|
@ -23,6 +23,11 @@
|
||||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
03-Mar-03 RMS Added sim_fsize
|
||||||
|
27-Feb-03 RMS Fixed bug in multiword deposits to files
|
||||||
|
08-Feb-03 RMS Changed sim_os_sleep to void, match_ext to char*
|
||||||
|
Added multiple actions, .ini file support
|
||||||
|
Added multiple switch evaluations per line
|
||||||
07-Feb-03 RMS Added VMS support for ! (from Mark Pizzolato)
|
07-Feb-03 RMS Added VMS support for ! (from Mark Pizzolato)
|
||||||
01-Feb-03 RMS Added breakpoint table extension, actions
|
01-Feb-03 RMS Added breakpoint table extension, actions
|
||||||
14-Jan-03 RMS Added missing function prototypes
|
14-Jan-03 RMS Added missing function prototypes
|
||||||
|
@ -165,13 +170,8 @@
|
||||||
else if (sz == sizeof (uint16)) *(((uint16 *) mb) + j) = (uint16) v; \
|
else if (sz == sizeof (uint16)) *(((uint16 *) mb) + j) = (uint16) v; \
|
||||||
else *(((uint32 *) mb) + j) = v;
|
else *(((uint32 *) mb) + j) = v;
|
||||||
#endif
|
#endif
|
||||||
#define GET_SWITCHES(cp,gb) \
|
#define GET_SWITCHES(cp) \
|
||||||
sim_switches = 0; \
|
if ((cp = get_sim_sw (cp)) == NULL) return SCPE_INVSW
|
||||||
while (*cp == '-') { \
|
|
||||||
int32 lsw; \
|
|
||||||
cp = get_glyph (cp, gb, 0); \
|
|
||||||
if ((lsw = get_switches (gb)) <= 0) return SCPE_INVSW; \
|
|
||||||
sim_switches = sim_switches | lsw; }
|
|
||||||
#define GET_RADIX(val,dft) \
|
#define GET_RADIX(val,dft) \
|
||||||
if (sim_switches & SWMASK ('O')) val = 8; \
|
if (sim_switches & SWMASK ('O')) val = 8; \
|
||||||
else if (sim_switches & SWMASK ('D')) val = 10; \
|
else if (sim_switches & SWMASK ('D')) val = 10; \
|
||||||
|
@ -234,6 +234,8 @@ t_stat sim_brk_clr (t_addr loc, int32 sw);
|
||||||
t_stat sim_brk_clrall (int32 sw);
|
t_stat sim_brk_clrall (int32 sw);
|
||||||
t_stat sim_brk_show (FILE *st, t_addr loc, int32 sw);
|
t_stat sim_brk_show (FILE *st, t_addr loc, int32 sw);
|
||||||
t_stat sim_brk_showall (FILE *st, int32 sw);
|
t_stat sim_brk_showall (FILE *st, int32 sw);
|
||||||
|
char *sim_brk_getact (char *buf, int32 size);
|
||||||
|
void sim_brk_clract (void);
|
||||||
void sim_brk_npc (void);
|
void sim_brk_npc (void);
|
||||||
t_stat set_telnet (int32 flg, char *cptr);
|
t_stat set_telnet (int32 flg, char *cptr);
|
||||||
t_stat set_notelnet (int32 flg, char *cptr);
|
t_stat set_notelnet (int32 flg, char *cptr);
|
||||||
|
@ -257,8 +259,8 @@ t_stat show_all_mods (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flg);
|
||||||
t_stat show_one_mod (FILE *st, DEVICE *dptr, UNIT *uptr, MTAB *mptr, int32 flag);
|
t_stat show_one_mod (FILE *st, DEVICE *dptr, UNIT *uptr, MTAB *mptr, int32 flag);
|
||||||
t_stat sim_check_console (int32 sec);
|
t_stat sim_check_console (int32 sec);
|
||||||
char *get_glyph_gen (char *iptr, char *optr, char mchar, t_bool uc);
|
char *get_glyph_gen (char *iptr, char *optr, char mchar, t_bool uc);
|
||||||
t_bool match_ext (char *fnam, char *ext);
|
|
||||||
int32 get_switches (char *cptr);
|
int32 get_switches (char *cptr);
|
||||||
|
char *get_sim_sw (char *cptr);
|
||||||
t_value get_rval (REG *rptr, int32 idx);
|
t_value get_rval (REG *rptr, int32 idx);
|
||||||
void put_rval (REG *rptr, int32 idx, t_value val);
|
void put_rval (REG *rptr, int32 idx, t_value val);
|
||||||
t_stat get_aval (t_addr addr, DEVICE *dptr, UNIT *uptr);
|
t_stat get_aval (t_addr addr, DEVICE *dptr, UNIT *uptr);
|
||||||
|
@ -285,8 +287,6 @@ t_stat dep_reg (int32 flag, char *cptr, REG *rptr, t_addr idx);
|
||||||
t_stat ex_addr (FILE *ofile, int32 flag, t_addr addr, DEVICE *dptr, UNIT *uptr);
|
t_stat ex_addr (FILE *ofile, int32 flag, t_addr addr, DEVICE *dptr, UNIT *uptr);
|
||||||
t_stat dep_addr (int32 flag, char *cptr, t_addr addr, DEVICE *dptr,
|
t_stat dep_addr (int32 flag, char *cptr, t_addr addr, DEVICE *dptr,
|
||||||
UNIT *uptr, int32 dfltinc);
|
UNIT *uptr, int32 dfltinc);
|
||||||
char *get_range (char *cptr, t_addr *lo, t_addr *hi, int32 rdx,
|
|
||||||
t_addr max, char term);
|
|
||||||
SCHTAB *get_search (char *cptr, DEVICE *dptr, SCHTAB *schptr);
|
SCHTAB *get_search (char *cptr, DEVICE *dptr, SCHTAB *schptr);
|
||||||
int32 test_search (t_value val, SCHTAB *schptr);
|
int32 test_search (t_value val, SCHTAB *schptr);
|
||||||
t_stat step_svc (UNIT *ptr);
|
t_stat step_svc (UNIT *ptr);
|
||||||
|
@ -519,11 +519,11 @@ for (i = 1; i < argc; i++) { /* loop thru args */
|
||||||
if (argv[i] == NULL) continue; /* paranoia */
|
if (argv[i] == NULL) continue; /* paranoia */
|
||||||
if ((*argv[i] == '-') && lookswitch) { /* switch? */
|
if ((*argv[i] == '-') && lookswitch) { /* switch? */
|
||||||
if ((sw = get_switches (argv[i])) < 0) {
|
if ((sw = get_switches (argv[i])) < 0) {
|
||||||
printf ("Invalid switch %s\n", argv[i]);
|
fprintf (stderr, "Invalid switch %s\n", argv[i]);
|
||||||
return 0; }
|
return 0; }
|
||||||
sim_switches = sim_switches | sw; }
|
sim_switches = sim_switches | sw; }
|
||||||
else { if ((strlen (argv[i]) + strlen (cbuf) + 1) >= CBUFSIZE) {
|
else { if ((strlen (argv[i]) + strlen (cbuf) + 1) >= CBUFSIZE) {
|
||||||
printf ("Argument string too long\n");
|
fprintf (stderr, "Argument string too long\n");
|
||||||
return 0; }
|
return 0; }
|
||||||
if (*cbuf) strcat (cbuf, " "); /* concat args */
|
if (*cbuf) strcat (cbuf, " "); /* concat args */
|
||||||
strcat (cbuf, argv[i]);
|
strcat (cbuf, argv[i]);
|
||||||
|
@ -544,18 +544,18 @@ sim_log = NULL;
|
||||||
if (sim_emax <= 0) sim_emax = 1;
|
if (sim_emax <= 0) sim_emax = 1;
|
||||||
|
|
||||||
if ((stat = ttinit ()) != SCPE_OK) {
|
if ((stat = ttinit ()) != SCPE_OK) {
|
||||||
printf ("Fatal terminal initialization error\n%s\n",
|
fprintf (stderr, "Fatal terminal initialization error\n%s\n",
|
||||||
scp_error_messages[stat - SCPE_BASE]);
|
scp_error_messages[stat - SCPE_BASE]);
|
||||||
return 0; }
|
return 0; }
|
||||||
if ((sim_eval = calloc (sim_emax, sizeof (t_value))) == NULL) {
|
if ((sim_eval = calloc (sim_emax, sizeof (t_value))) == NULL) {
|
||||||
printf ("Unable to allocate examine buffer\n");
|
fprintf (stderr, "Unable to allocate examine buffer\n");
|
||||||
return 0; };
|
return 0; };
|
||||||
if ((stat = reset_all (0)) != SCPE_OK) {
|
if ((stat = reset_all (0)) != SCPE_OK) {
|
||||||
printf ("Fatal simulator initialization error\n%s\n",
|
fprintf (stderr, "Fatal simulator initialization error\n%s\n",
|
||||||
scp_error_messages[stat - SCPE_BASE]);
|
scp_error_messages[stat - SCPE_BASE]);
|
||||||
return 0; }
|
return 0; }
|
||||||
if ((stat = sim_brk_init ()) != SCPE_OK) {
|
if ((stat = sim_brk_init ()) != SCPE_OK) {
|
||||||
printf ("Fatal breakpoint table initialization error\n%s\n",
|
fprintf (stderr, "Fatal breakpoint table initialization error\n%s\n",
|
||||||
scp_error_messages[stat - SCPE_BASE]);
|
scp_error_messages[stat - SCPE_BASE]);
|
||||||
return 0; }
|
return 0; }
|
||||||
if (!sim_quiet) {
|
if (!sim_quiet) {
|
||||||
|
@ -566,13 +566,18 @@ if (*cbuf) { /* cmd file arg? */
|
||||||
stat = do_cmd (1, cbuf); /* proc cmd file */
|
stat = do_cmd (1, cbuf); /* proc cmd file */
|
||||||
if (stat == SCPE_OPENERR) /* error? */
|
if (stat == SCPE_OPENERR) /* error? */
|
||||||
fprintf (stderr, "Can't open file %s\n", cbuf); }
|
fprintf (stderr, "Can't open file %s\n", cbuf); }
|
||||||
else stat = SCPE_OK;
|
else if (*argv[0]) { /* sim name arg? */
|
||||||
|
char nbuf[PATH_MAX + 7], *np; /* "path.ini" */
|
||||||
|
nbuf[0] = '"'; /* starting " */
|
||||||
|
strncpy (nbuf + 1, argv[0], PATH_MAX + 1); /* copy sim name */
|
||||||
|
if (np = match_ext (nbuf, "EXE")) *np = 0; /* remove .exe */
|
||||||
|
strcat (nbuf, ".ini\""); /* add .ini" */
|
||||||
|
stat = do_cmd (1, nbuf); } /* proc cmd file */
|
||||||
|
|
||||||
while (stat != SCPE_EXIT) { /* in case exit */
|
while (stat != SCPE_EXIT) { /* in case exit */
|
||||||
printf ("sim> "); /* prompt */
|
printf ("sim> "); /* prompt */
|
||||||
if (cptr = sim_brk_act) { /* pending action? */
|
if (cptr = sim_brk_getact (cbuf, CBUFSIZE)) /* pending action? */
|
||||||
printf ("%s\n", sim_brk_act);
|
printf ("%s\n", cptr); /* echo */
|
||||||
sim_brk_act = NULL; }
|
|
||||||
else if (sim_vm_read != NULL) /* sim routine? */
|
else if (sim_vm_read != NULL) /* sim routine? */
|
||||||
cptr = (*sim_vm_read) (cbuf, CBUFSIZE, stdin);
|
cptr = (*sim_vm_read) (cbuf, CBUFSIZE, stdin);
|
||||||
else cptr = read_line (cbuf, CBUFSIZE, stdin); /* read command line */
|
else cptr = read_line (cbuf, CBUFSIZE, stdin); /* read command line */
|
||||||
|
@ -580,6 +585,7 @@ while (stat != SCPE_EXIT) { /* in case exit */
|
||||||
if (*cptr == 0) continue; /* ignore blank */
|
if (*cptr == 0) continue; /* ignore blank */
|
||||||
if (sim_log) fprintf (sim_log, "sim> %s\n", cptr); /* log cmd */
|
if (sim_log) fprintf (sim_log, "sim> %s\n", cptr); /* log cmd */
|
||||||
cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */
|
cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */
|
||||||
|
sim_switches = 0; /* init switches */
|
||||||
if (cmdp = find_cmd (gbuf)) /* lookup command */
|
if (cmdp = find_cmd (gbuf)) /* lookup command */
|
||||||
stat = cmdp->action (cmdp->arg, cptr); /* if found, exec */
|
stat = cmdp->action (cmdp->arg, cptr); /* if found, exec */
|
||||||
else stat = SCPE_UNK;
|
else stat = SCPE_UNK;
|
||||||
|
@ -633,6 +639,7 @@ t_stat help_cmd (int32 flag, char *cptr)
|
||||||
char gbuf[CBUFSIZE];
|
char gbuf[CBUFSIZE];
|
||||||
CTAB *cmdp;
|
CTAB *cmdp;
|
||||||
|
|
||||||
|
GET_SWITCHES (cptr);
|
||||||
if (*cptr) {
|
if (*cptr) {
|
||||||
cptr = get_glyph (cptr, gbuf, 0);
|
cptr = get_glyph (cptr, gbuf, 0);
|
||||||
if (*cptr) return SCPE_2MARG;
|
if (*cptr) return SCPE_2MARG;
|
||||||
|
@ -665,6 +672,54 @@ return SCPE_OK;
|
||||||
|
|
||||||
/* Do command */
|
/* Do command */
|
||||||
|
|
||||||
|
t_stat do_cmd (int flag, char *fcptr)
|
||||||
|
{
|
||||||
|
char *cptr, cbuf[CBUFSIZE], gbuf[CBUFSIZE], *c, quote, *do_arg[10];
|
||||||
|
FILE *fpin;
|
||||||
|
CTAB *cmdp;
|
||||||
|
int32 echo, nargs;
|
||||||
|
t_stat stat = SCPE_OK;
|
||||||
|
|
||||||
|
if (flag == 0) { GET_SWITCHES (fcptr); } /* get switches */
|
||||||
|
echo = sim_switches & SWMASK ('V'); /* -v means echo */
|
||||||
|
|
||||||
|
c = fcptr;
|
||||||
|
for (nargs = 0; nargs < 10; ) { /* extract arguments */
|
||||||
|
while (isspace (*c)) c++; /* skip blanks */
|
||||||
|
if (*c == 0) break; /* all done */
|
||||||
|
if (*c == '\'' || *c == '"') quote = *c++; /* quoted string? */
|
||||||
|
else quote = 0;
|
||||||
|
do_arg[nargs++] = c; /* save start */
|
||||||
|
while (*c && (quote? (*c != quote): !isspace (*c))) c++;
|
||||||
|
if (*c) *c++ = 0; /* term at quote/spc */
|
||||||
|
} /* end for */
|
||||||
|
if (nargs <= 0) return SCPE_2FARG; /* need at least 1 */
|
||||||
|
if ((fpin = FOPEN (do_arg[0], "r")) == NULL) /* cmd file failed to open? */
|
||||||
|
return SCPE_OPENERR;
|
||||||
|
|
||||||
|
do { cptr = read_line (cbuf, CBUFSIZE, fpin); /* get cmd line */
|
||||||
|
sub_args (cbuf, gbuf, CBUFSIZE, nargs, do_arg);
|
||||||
|
if (cptr == NULL) break; /* exit on eof */
|
||||||
|
if (*cptr == 0) continue; /* ignore blank */
|
||||||
|
if (echo) printf("do> %s\n", cptr); /* echo if -v */
|
||||||
|
if (sim_log) fprintf (sim_log, "do> %s\n", cptr);
|
||||||
|
cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */
|
||||||
|
sim_switches = 0; /* init switches */
|
||||||
|
if (strcmp (gbuf, "do") == 0) { /* don't recurse */
|
||||||
|
fclose (fpin);
|
||||||
|
return SCPE_NEST; }
|
||||||
|
if (cmdp = find_cmd (gbuf)) /* lookup command */
|
||||||
|
stat = cmdp->action (cmdp->arg, cptr); /* if found, exec */
|
||||||
|
else stat = SCPE_UNK;
|
||||||
|
if (stat >= SCPE_BASE) /* error? */
|
||||||
|
printf ("%s\n", scp_error_messages[stat - SCPE_BASE]);
|
||||||
|
if (sim_vm_post != NULL) (*sim_vm_post) (TRUE);
|
||||||
|
} while (stat != SCPE_EXIT);
|
||||||
|
|
||||||
|
fclose (fpin); /* close file */
|
||||||
|
return (stat == SCPE_EXIT)? SCPE_EXIT: SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* Substitute_args - replace %n tokens in 'instr' with the do command's arguments
|
/* Substitute_args - replace %n tokens in 'instr' with the do command's arguments
|
||||||
|
|
||||||
Calling sequence
|
Calling sequence
|
||||||
|
@ -693,55 +748,6 @@ for (ip = instr, op = tmpbuf; *ip && (op < oend); ) {
|
||||||
strcpy (instr, tmpbuf);
|
strcpy (instr, tmpbuf);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
t_stat do_cmd (int flag, char *fcptr)
|
|
||||||
{
|
|
||||||
char *cptr, cbuf[CBUFSIZE], gbuf[CBUFSIZE], *c, quote, *do_arg[10];
|
|
||||||
FILE *fpin;
|
|
||||||
CTAB *cmdp;
|
|
||||||
int32 echo, nargs;
|
|
||||||
t_stat stat = SCPE_OK;
|
|
||||||
|
|
||||||
if (flag == 0) { GET_SWITCHES (fcptr, gbuf); } /* get switches */
|
|
||||||
echo = sim_switches & SWMASK ('V'); /* -v means echo */
|
|
||||||
|
|
||||||
c = fcptr;
|
|
||||||
for (nargs = 0; nargs < 10; ) { /* extract arguments */
|
|
||||||
while (*c && (*c <= ' ')) c++; /* skip blanks */
|
|
||||||
if (! *c) break; /* all done */
|
|
||||||
do_arg[nargs++] = c; /* save start */
|
|
||||||
while (*c && (*c > ' ')) {
|
|
||||||
if (*c == '\'' || *c == '"') { /* quoted string */
|
|
||||||
for (quote = *c++; *c; )
|
|
||||||
if (*c++ == quote) break; }
|
|
||||||
else c++; }
|
|
||||||
if (*c) *c++ = 0; /* term arg at spc */
|
|
||||||
} /* end for */
|
|
||||||
if (nargs <= 0) return SCPE_2FARG; /* need at least 1 */
|
|
||||||
if ((fpin = FOPEN (do_arg[0], "r")) == NULL) /* cmd file failed to open? */
|
|
||||||
return SCPE_OPENERR;
|
|
||||||
|
|
||||||
do { cptr = read_line (cbuf, CBUFSIZE, fpin); /* get cmd line */
|
|
||||||
sub_args (cbuf, gbuf, CBUFSIZE, nargs, do_arg);
|
|
||||||
if (cptr == NULL) break; /* exit on eof */
|
|
||||||
if (*cptr == 0) continue; /* ignore blank */
|
|
||||||
if (echo) printf("do> %s\n", cptr); /* echo if -v */
|
|
||||||
if (sim_log) fprintf (sim_log, "do> %s\n", cptr);
|
|
||||||
cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */
|
|
||||||
if (strcmp (gbuf, "do") == 0) { /* don't recurse */
|
|
||||||
fclose (fpin);
|
|
||||||
return SCPE_NEST; }
|
|
||||||
if (cmdp = find_cmd (gbuf)) /* lookup command */
|
|
||||||
stat = cmdp->action (cmdp->arg, cptr); /* if found, exec */
|
|
||||||
else stat = SCPE_UNK;
|
|
||||||
if (stat >= SCPE_BASE) /* error? */
|
|
||||||
printf ("%s\n", scp_error_messages[stat - SCPE_BASE]);
|
|
||||||
if (sim_vm_post != NULL) (*sim_vm_post) (TRUE);
|
|
||||||
} while (stat != SCPE_EXIT);
|
|
||||||
|
|
||||||
fclose (fpin); /* close file */
|
|
||||||
return (stat == SCPE_EXIT)? SCPE_EXIT: SCPE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set command */
|
/* Set command */
|
||||||
|
|
||||||
|
@ -773,7 +779,7 @@ static CTAB set_unit_tab[] = {
|
||||||
{ "OFFLINE", &set_onoff, 0 },
|
{ "OFFLINE", &set_onoff, 0 },
|
||||||
{ NULL, NULL, 0 } };
|
{ NULL, NULL, 0 } };
|
||||||
|
|
||||||
GET_SWITCHES (cptr, gbuf); /* get switches */
|
GET_SWITCHES (cptr); /* get switches */
|
||||||
if (*cptr == 0) return SCPE_2FARG; /* must be more */
|
if (*cptr == 0) return SCPE_2FARG; /* must be more */
|
||||||
cptr = get_glyph (cptr, gbuf, 0); /* get glob/dev/unit */
|
cptr = get_glyph (cptr, gbuf, 0); /* get glob/dev/unit */
|
||||||
|
|
||||||
|
@ -941,7 +947,7 @@ static CTAB show_table[] = {
|
||||||
{ "BREAK", &show_break, 0 },
|
{ "BREAK", &show_break, 0 },
|
||||||
{ NULL, NULL, 0 } };
|
{ NULL, NULL, 0 } };
|
||||||
|
|
||||||
GET_SWITCHES (cptr, gbuf); /* test for switches */
|
GET_SWITCHES (cptr); /* get switches */
|
||||||
if (*cptr == 0) return SCPE_2FARG; /* must be more */
|
if (*cptr == 0) return SCPE_2FARG; /* must be more */
|
||||||
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
|
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
|
||||||
for (i = 0; show_table[i].name != NULL; i++) { /* find command */
|
for (i = 0; show_table[i].name != NULL; i++) { /* find command */
|
||||||
|
@ -1078,10 +1084,10 @@ int32 accum;
|
||||||
|
|
||||||
if (cptr && (*cptr != 0)) return SCPE_2MARG;
|
if (cptr && (*cptr != 0)) return SCPE_2MARG;
|
||||||
if (sim_clock_queue == NULL) {
|
if (sim_clock_queue == NULL) {
|
||||||
fprintf (st, "%s event queue empty, time = %-16.0f\n",
|
fprintf (st, "%s event queue empty, time = %.0f\n",
|
||||||
sim_name, sim_time);
|
sim_name, sim_time);
|
||||||
return SCPE_OK; }
|
return SCPE_OK; }
|
||||||
fprintf (st, "%s event queue status, time = %-16.0f\n",
|
fprintf (st, "%s event queue status, time = %.0f\n",
|
||||||
sim_name, sim_time);
|
sim_name, sim_time);
|
||||||
accum = 0;
|
accum = 0;
|
||||||
for (uptr = sim_clock_queue; uptr != NULL; uptr = uptr->next) {
|
for (uptr = sim_clock_queue; uptr != NULL; uptr = uptr->next) {
|
||||||
|
@ -1099,7 +1105,7 @@ return SCPE_OK;
|
||||||
t_stat show_time (FILE *st, int32 flag, char *cptr)
|
t_stat show_time (FILE *st, int32 flag, char *cptr)
|
||||||
{
|
{
|
||||||
if (cptr && (*cptr != 0)) return SCPE_2MARG;
|
if (cptr && (*cptr != 0)) return SCPE_2MARG;
|
||||||
fprintf (st, "Time: %-16.0f\n", sim_time);
|
fprintf (st, "Time: %.0f\n", sim_time);
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1182,9 +1188,7 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat brk_cmd (int32 flg, char *cptr)
|
t_stat brk_cmd (int32 flg, char *cptr)
|
||||||
{
|
{
|
||||||
char gbuf[CBUFSIZE];
|
GET_SWITCHES (cptr); /* get switches */
|
||||||
|
|
||||||
GET_SWITCHES (cptr, gbuf); /* test for switches */
|
|
||||||
return ssh_break (NULL, cptr, flg); /* call common code */
|
return ssh_break (NULL, cptr, flg); /* call common code */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1244,7 +1248,7 @@ t_stat reset_cmd (int32 flag, char *cptr)
|
||||||
char gbuf[CBUFSIZE];
|
char gbuf[CBUFSIZE];
|
||||||
DEVICE *dptr;
|
DEVICE *dptr;
|
||||||
|
|
||||||
GET_SWITCHES (cptr, gbuf); /* test for switches */
|
GET_SWITCHES (cptr); /* get switches */
|
||||||
if (*cptr == 0) return (reset_all (0)); /* reset(cr) */
|
if (*cptr == 0) return (reset_all (0)); /* reset(cr) */
|
||||||
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
|
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
|
||||||
if (*cptr != 0) return SCPE_2MARG; /* now eol? */
|
if (*cptr != 0) return SCPE_2MARG; /* now eol? */
|
||||||
|
@ -1291,11 +1295,12 @@ char gbuf[CBUFSIZE];
|
||||||
FILE *loadfile;
|
FILE *loadfile;
|
||||||
t_stat reason;
|
t_stat reason;
|
||||||
|
|
||||||
GET_SWITCHES (cptr, gbuf); /* test for switches */
|
GET_SWITCHES (cptr); /* get switches */
|
||||||
if (*cptr == 0) return SCPE_2FARG; /* must be more */
|
if (*cptr == 0) return SCPE_2FARG; /* must be more */
|
||||||
cptr = get_glyph_nc (cptr, gbuf, 0); /* get file name */
|
cptr = get_glyph_nc (cptr, gbuf, 0); /* get file name */
|
||||||
loadfile = FOPEN (gbuf, flag? "wb": "rb"); /* open for wr/rd */
|
loadfile = FOPEN (gbuf, flag? "wb": "rb"); /* open for wr/rd */
|
||||||
if (loadfile == NULL) return SCPE_OPENERR;
|
if (loadfile == NULL) return SCPE_OPENERR;
|
||||||
|
GET_SWITCHES (cptr); /* get switches */
|
||||||
reason = sim_load (loadfile, cptr, gbuf, flag); /* load or dump */
|
reason = sim_load (loadfile, cptr, gbuf, flag); /* load or dump */
|
||||||
fclose (loadfile);
|
fclose (loadfile);
|
||||||
return reason;
|
return reason;
|
||||||
|
@ -1312,9 +1317,10 @@ char gbuf[CBUFSIZE];
|
||||||
DEVICE *dptr;
|
DEVICE *dptr;
|
||||||
UNIT *uptr;
|
UNIT *uptr;
|
||||||
|
|
||||||
GET_SWITCHES (cptr, gbuf); /* test for switches */
|
GET_SWITCHES (cptr); /* get switches */
|
||||||
if (*cptr == 0) return SCPE_2FARG; /* must be more */
|
if (*cptr == 0) return SCPE_2FARG; /* must be more */
|
||||||
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
|
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
|
||||||
|
GET_SWITCHES (cptr); /* get switches */
|
||||||
if (*cptr == 0) return SCPE_2FARG; /* now eol? */
|
if (*cptr == 0) return SCPE_2FARG; /* now eol? */
|
||||||
dptr = find_unit (gbuf, &uptr); /* locate unit */
|
dptr = find_unit (gbuf, &uptr); /* locate unit */
|
||||||
if (dptr == NULL) return SCPE_NXDEV; /* found dev? */
|
if (dptr == NULL) return SCPE_NXDEV; /* found dev? */
|
||||||
|
@ -1399,7 +1405,7 @@ char gbuf[CBUFSIZE];
|
||||||
DEVICE *dptr;
|
DEVICE *dptr;
|
||||||
UNIT *uptr;
|
UNIT *uptr;
|
||||||
|
|
||||||
GET_SWITCHES (cptr, gbuf); /* test for switches */
|
GET_SWITCHES (cptr); /* get switches */
|
||||||
if (*cptr == 0) return SCPE_2FARG; /* must be more */
|
if (*cptr == 0) return SCPE_2FARG; /* must be more */
|
||||||
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
|
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
|
||||||
if (*cptr != 0) return SCPE_2MARG; /* now eol? */
|
if (*cptr != 0) return SCPE_2MARG; /* now eol? */
|
||||||
|
@ -1470,7 +1476,6 @@ return (fclose (uptr->fileref) == EOF)? SCPE_IOERR: SCPE_OK;
|
||||||
|
|
||||||
t_stat save_cmd (int32 flag, char *cptr)
|
t_stat save_cmd (int32 flag, char *cptr)
|
||||||
{
|
{
|
||||||
char gbuf[CBUFSIZE];
|
|
||||||
void *mbuf;
|
void *mbuf;
|
||||||
FILE *sfile;
|
FILE *sfile;
|
||||||
int32 i, j, l, t;
|
int32 i, j, l, t;
|
||||||
|
@ -1485,7 +1490,7 @@ REG *rptr;
|
||||||
|
|
||||||
#define WRITE_I(xx) fxwrite (&(xx), sizeof (xx), 1, sfile)
|
#define WRITE_I(xx) fxwrite (&(xx), sizeof (xx), 1, sfile)
|
||||||
|
|
||||||
GET_SWITCHES (cptr, gbuf); /* test for switches */
|
GET_SWITCHES (cptr); /* get switches */
|
||||||
if (*cptr == 0) return SCPE_2FARG; /* must be more */
|
if (*cptr == 0) return SCPE_2FARG; /* must be more */
|
||||||
if ((sfile = FOPEN (cptr, "wb")) == NULL) return SCPE_OPENERR;
|
if ((sfile = FOPEN (cptr, "wb")) == NULL) return SCPE_OPENERR;
|
||||||
fputs (save_vercur, sfile); /* [V2.5] save format */
|
fputs (save_vercur, sfile); /* [V2.5] save format */
|
||||||
|
@ -1582,7 +1587,7 @@ REG *rptr;
|
||||||
#define READ_I(xx) if (fxread (&xx, sizeof (xx), 1, rfile) == 0) \
|
#define READ_I(xx) if (fxread (&xx, sizeof (xx), 1, rfile) == 0) \
|
||||||
{ fclose (rfile); return SCPE_IOERR; }
|
{ fclose (rfile); return SCPE_IOERR; }
|
||||||
|
|
||||||
GET_SWITCHES (cptr, buf); /* test for switches */
|
GET_SWITCHES (cptr); /* get switches */
|
||||||
if (*cptr == 0) return SCPE_2FARG; /* must be more */
|
if (*cptr == 0) return SCPE_2FARG; /* must be more */
|
||||||
if ((rfile = FOPEN (cptr, "rb")) == NULL) return SCPE_OPENERR;
|
if ((rfile = FOPEN (cptr, "rb")) == NULL) return SCPE_OPENERR;
|
||||||
READ_S (buf); /* [V2.5+] read version */
|
READ_S (buf); /* [V2.5+] read version */
|
||||||
|
@ -1753,7 +1758,7 @@ DEVICE *dptr;
|
||||||
UNIT *uptr;
|
UNIT *uptr;
|
||||||
void int_handler (int signal);
|
void int_handler (int signal);
|
||||||
|
|
||||||
GET_SWITCHES (cptr, gbuf); /* test for switches */
|
GET_SWITCHES (cptr); /* get switches */
|
||||||
step = 0;
|
step = 0;
|
||||||
if (((flag == RU_RUN) || (flag == RU_GO)) && (*cptr != 0)) { /* run or go */
|
if (((flag == RU_RUN) || (flag == RU_GO)) && (*cptr != 0)) { /* run or go */
|
||||||
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
|
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
|
||||||
|
@ -1804,7 +1809,7 @@ if ((r = sim_check_console (30)) != SCPE_OK) { /* check console, error? */
|
||||||
return r; }
|
return r; }
|
||||||
if (step) sim_activate (&step_unit, step); /* set step timer */
|
if (step) sim_activate (&step_unit, step); /* set step timer */
|
||||||
sim_is_running = 1; /* flag running */
|
sim_is_running = 1; /* flag running */
|
||||||
sim_brk_act = NULL; /* defang actions */
|
sim_brk_clract (); /* defang actions */
|
||||||
r = sim_instr();
|
r = sim_instr();
|
||||||
|
|
||||||
sim_is_running = 0; /* flag idle */
|
sim_is_running = 0; /* flag idle */
|
||||||
|
@ -2331,7 +2336,7 @@ for (i = 0, j = addr; i < count; i++, j = j + dptr->aincr) {
|
||||||
if (loc >= uptr->hwmark) uptr->hwmark = loc + 1; }
|
if (loc >= uptr->hwmark) uptr->hwmark = loc + 1; }
|
||||||
else {
|
else {
|
||||||
fseek (uptr->fileref, sz * loc, SEEK_SET);
|
fseek (uptr->fileref, sz * loc, SEEK_SET);
|
||||||
fxwrite (sim_eval, sz, 1, uptr->fileref);
|
fxwrite (&sim_eval[i], sz, 1, uptr->fileref);
|
||||||
if (ferror (uptr->fileref)) {
|
if (ferror (uptr->fileref)) {
|
||||||
clearerr (uptr->fileref);
|
clearerr (uptr->fileref);
|
||||||
return SCPE_IOERR; } } } }
|
return SCPE_IOERR; } } } }
|
||||||
|
@ -2342,12 +2347,11 @@ return reason;
|
||||||
|
|
||||||
t_stat eval_cmd (int32 flg, char *cptr)
|
t_stat eval_cmd (int32 flg, char *cptr)
|
||||||
{
|
{
|
||||||
char gbuf[CBUFSIZE];
|
|
||||||
DEVICE *dptr = sim_devices[0];
|
DEVICE *dptr = sim_devices[0];
|
||||||
int32 i, count, rdx;
|
int32 i, count, rdx;
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
GET_SWITCHES (cptr, gbuf);
|
GET_SWITCHES (cptr);
|
||||||
GET_RADIX (rdx, dptr->dradix);
|
GET_RADIX (rdx, dptr->dradix);
|
||||||
for (i = 0; i < sim_emax; i++) sim_eval[i] = 0;
|
for (i = 0; i < sim_emax; i++) sim_eval[i] = 0;
|
||||||
if (*cptr == 0) return SCPE_2FARG;
|
if (*cptr == 0) return SCPE_2FARG;
|
||||||
|
@ -2598,11 +2602,10 @@ t_stat r;
|
||||||
DEVICE *dptr;
|
DEVICE *dptr;
|
||||||
|
|
||||||
if (uptr == NULL) return NULL; /* arg error? */
|
if (uptr == NULL) return NULL; /* arg error? */
|
||||||
for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* exact match? */
|
if (dptr = find_dev (cptr)) { /* exact match? */
|
||||||
if (strcmp (cptr, dptr->name) == 0) {
|
|
||||||
if (qdisable (dptr)) return NULL; /* disabled? */
|
if (qdisable (dptr)) return NULL; /* disabled? */
|
||||||
*uptr = dptr->units; /* unit 0 */
|
*uptr = dptr->units; /* unit 0 */
|
||||||
return dptr; } }
|
return dptr; }
|
||||||
|
|
||||||
for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* base + unit#? */
|
for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* base + unit#? */
|
||||||
if ((dptr->numunits == 0) || /* no units? */
|
if ((dptr->numunits == 0) || /* no units? */
|
||||||
|
@ -2718,21 +2721,52 @@ if (*cptr != '-') return 0;
|
||||||
sw = 0;
|
sw = 0;
|
||||||
for (cptr++; (isspace (*cptr) == 0) && (*cptr != 0); cptr++) {
|
for (cptr++; (isspace (*cptr) == 0) && (*cptr != 0); cptr++) {
|
||||||
if (isalpha (*cptr) == 0) return -1;
|
if (isalpha (*cptr) == 0) return -1;
|
||||||
sw = sw | SWMASK (*cptr); }
|
sw = sw | SWMASK (toupper (*cptr)); }
|
||||||
return sw;
|
return sw;
|
||||||
}
|
}
|
||||||
|
|
||||||
t_bool match_ext (char *fnam, char *ext)
|
/* get_sim_sw accumulate sim_switches
|
||||||
{
|
|
||||||
char *fptr, *eptr;
|
|
||||||
|
|
||||||
if ((fnam == NULL) || (ext == NULL)) return FALSE;
|
Inputs:
|
||||||
fptr = strrchr (fnam, '.');
|
cptr = pointer to input string
|
||||||
if (fptr == NULL) return FALSE;
|
Outputs:
|
||||||
for (fptr++, eptr = ext; *fptr; fptr++, eptr++) {
|
ptr = pointer to first non-string glyph
|
||||||
if (toupper (*fptr) != toupper (*eptr)) return FALSE; }
|
NULL if error
|
||||||
if (*eptr) return FALSE;
|
*/
|
||||||
return TRUE;
|
|
||||||
|
char *get_sim_sw (char *cptr)
|
||||||
|
{
|
||||||
|
int32 lsw;
|
||||||
|
char gbuf[CBUFSIZE];
|
||||||
|
|
||||||
|
while (*cptr == '-') { /* while switches */
|
||||||
|
cptr = get_glyph (cptr, gbuf, 0); /* get switch glyph */
|
||||||
|
lsw = get_switches (gbuf); /* parse */
|
||||||
|
if (lsw <= 0) return NULL; /* invalid? */
|
||||||
|
sim_switches = sim_switches | lsw; } /* accumulate */
|
||||||
|
return cptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Match file extension
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
fnam = file name
|
||||||
|
ext = extension, without period
|
||||||
|
Outputs:
|
||||||
|
cp = pointer to final '.' if match, NULL if not
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *match_ext (char *fnam, char *ext)
|
||||||
|
{
|
||||||
|
char *pptr, *fptr, *eptr;
|
||||||
|
|
||||||
|
if ((fnam == NULL) || (ext == NULL)) return NULL;
|
||||||
|
pptr = strrchr (fnam, '.');
|
||||||
|
if (pptr) {
|
||||||
|
for (fptr = pptr + 1, eptr = ext; *fptr; fptr++, eptr++) {
|
||||||
|
if (toupper (*fptr) != toupper (*eptr)) return NULL; }
|
||||||
|
if (*eptr) return NULL; }
|
||||||
|
return pptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get search specification
|
/* Get search specification
|
||||||
|
@ -3143,6 +3177,21 @@ for (i = nbuf; i > 0; i--) {
|
||||||
total = total + c; }
|
total = total + c; }
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get file size */
|
||||||
|
|
||||||
|
t_addr sim_fsize (char *cptr)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
t_addr sz;
|
||||||
|
|
||||||
|
fp = fopen (cptr, "rb");
|
||||||
|
if (fp == NULL) return 0;
|
||||||
|
fseek (fp, 0, SEEK_END);
|
||||||
|
sz = ftell (fp);
|
||||||
|
fclose (fp);
|
||||||
|
return sz;
|
||||||
|
}
|
||||||
|
|
||||||
/* OS independent clock calibration package
|
/* OS independent clock calibration package
|
||||||
|
|
||||||
|
@ -3240,6 +3289,8 @@ return sim_rtcn_calb (ticksper, 0);
|
||||||
sim_brk_showall show all breakpoints
|
sim_brk_showall show all breakpoints
|
||||||
sim_brk_test test for breakpoint
|
sim_brk_test test for breakpoint
|
||||||
sim_brk_npc PC has been changed
|
sim_brk_npc PC has been changed
|
||||||
|
sim_brk_getact get next action
|
||||||
|
sim_brk_clract clear pending actions
|
||||||
|
|
||||||
Initialize breakpoint system.
|
Initialize breakpoint system.
|
||||||
*/
|
*/
|
||||||
|
@ -3422,6 +3473,33 @@ sim_brk_pend = FALSE;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get next pending action, if any */
|
||||||
|
|
||||||
|
char *sim_brk_getact (char *buf, int32 size)
|
||||||
|
{
|
||||||
|
char *ep;
|
||||||
|
size_t lnt;
|
||||||
|
|
||||||
|
if (sim_brk_act == NULL) return NULL; /* any action? */
|
||||||
|
while (isspace (*sim_brk_act)) sim_brk_act++; /* skip spaces */
|
||||||
|
if (*sim_brk_act == 0) return (sim_brk_act = NULL); /* now empty? */
|
||||||
|
if (ep = strchr (sim_brk_act, ';')) { /* cmd delimiter? */
|
||||||
|
lnt = ep - sim_brk_act; /* cmd length */
|
||||||
|
memcpy (buf, sim_brk_act, lnt + 1); /* copy with ; */
|
||||||
|
buf[lnt] = 0; /* erase ; */
|
||||||
|
sim_brk_act = sim_brk_act + lnt + 1; } /* adv ptr */
|
||||||
|
else { strncpy (buf, sim_brk_act, size); /* copy action */
|
||||||
|
sim_brk_act = NULL; } /* no more */
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear pending actions */
|
||||||
|
|
||||||
|
void sim_brk_clract (void)
|
||||||
|
{
|
||||||
|
sim_brk_act = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* New PC */
|
/* New PC */
|
||||||
|
|
||||||
void sim_brk_npc (void)
|
void sim_brk_npc (void)
|
||||||
|
|
25
scp_tty.c
25
scp_tty.c
|
@ -200,9 +200,10 @@ for (i = 0; i < 64; i++) { /* 64b quo */
|
||||||
return quo;
|
return quo;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sim_os_sleep (unsigned int sec)
|
void sim_os_sleep (unsigned int sec)
|
||||||
{
|
{
|
||||||
return sleep (sec);
|
sleep (sec);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -275,10 +276,10 @@ uint32 sim_os_msec ()
|
||||||
return GetTickCount ();
|
return GetTickCount ();
|
||||||
}
|
}
|
||||||
|
|
||||||
int sim_os_sleep (unsigned int sec)
|
void sim_os_sleep (unsigned int sec)
|
||||||
{
|
{
|
||||||
Sleep (sec * 1000);
|
Sleep (sec * 1000);
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -369,7 +370,6 @@ t_stat ttclose (void);
|
||||||
uint32 sim_os_msec (void);
|
uint32 sim_os_msec (void);
|
||||||
t_stat sim_os_poll_kbd (void);
|
t_stat sim_os_poll_kbd (void);
|
||||||
t_stat sim_os_putchar (int32 c);
|
t_stat sim_os_putchar (int32 c);
|
||||||
int sim_os_sleep (unsigned int sec);
|
|
||||||
|
|
||||||
extern char sim_name[];
|
extern char sim_name[];
|
||||||
extern pSIOUXWin SIOUXTextWindow;
|
extern pSIOUXWin SIOUXTextWindow;
|
||||||
|
@ -532,9 +532,10 @@ millis = micros / 1000LL;
|
||||||
return (uint32) millis;
|
return (uint32) millis;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sim_os_sleep (unsigned int sec)
|
void sim_os_sleep (unsigned int sec)
|
||||||
{
|
{
|
||||||
return sleep (sec);
|
sleep (sec);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -634,9 +635,10 @@ msec = (((uint32) cur.tv_sec) * 1000) + (((uint32) cur.tv_usec) / 1000);
|
||||||
return msec;
|
return msec;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sim_os_sleep (unsigned int sec)
|
void sim_os_sleep (unsigned int sec)
|
||||||
{
|
{
|
||||||
return sleep (sec);
|
sleep (sec);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -742,9 +744,10 @@ msec = (((uint32) cur.tv_sec) * 1000) + (((uint32) cur.tv_usec) / 1000);
|
||||||
return msec;
|
return msec;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sim_os_sleep (unsigned int sec)
|
void sim_os_sleep (unsigned int sec)
|
||||||
{
|
{
|
||||||
return sleep (sec);
|
sleep (sec);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
03-Mar-03 RMS Added sim_fsize
|
||||||
|
08-Feb-03 RMS Changed sim_os_sleep to void, added match_ext
|
||||||
05-Jan-03 RMS Added hidden switch definitions, device dyn memory support,
|
05-Jan-03 RMS Added hidden switch definitions, device dyn memory support,
|
||||||
parameters for function pointers, case sensitive SET support
|
parameters for function pointers, case sensitive SET support
|
||||||
22-Dec-02 RMS Added break flag
|
22-Dec-02 RMS Added break flag
|
||||||
|
@ -411,6 +413,7 @@ t_stat detach_unit (UNIT *uptr);
|
||||||
t_stat reset_all (int start_device);
|
t_stat reset_all (int start_device);
|
||||||
size_t fxread (void *bptr, size_t size, size_t count, FILE *fptr);
|
size_t fxread (void *bptr, size_t size, size_t count, FILE *fptr);
|
||||||
size_t fxwrite (void *bptr, size_t size, size_t count, FILE *fptr);
|
size_t fxwrite (void *bptr, size_t size, size_t count, FILE *fptr);
|
||||||
|
t_addr sim_fsize (char *cptr);
|
||||||
t_stat get_yn (char *ques, t_stat deflt);
|
t_stat get_yn (char *ques, t_stat deflt);
|
||||||
char *get_glyph (char *iptr, char *optr, char mchar);
|
char *get_glyph (char *iptr, char *optr, char mchar);
|
||||||
char *get_glyph_nc (char *iptr, char *optr, char mchar);
|
char *get_glyph_nc (char *iptr, char *optr, char mchar);
|
||||||
|
@ -429,6 +432,7 @@ int32 sim_rtcn_calb (int32 time, int32 tmr);
|
||||||
t_stat sim_poll_kbd (void);
|
t_stat sim_poll_kbd (void);
|
||||||
t_stat sim_putchar (int32 out);
|
t_stat sim_putchar (int32 out);
|
||||||
t_bool sim_brk_test (t_addr bloc, int32 btyp);
|
t_bool sim_brk_test (t_addr bloc, int32 btyp);
|
||||||
int sim_os_sleep (unsigned int sec);
|
void sim_os_sleep (unsigned int sec);
|
||||||
|
char *match_ext (char *fnam, char *ext);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
88
sim_rev.h
88
sim_rev.h
|
@ -29,13 +29,97 @@
|
||||||
|
|
||||||
#define SIM_MAJOR 2
|
#define SIM_MAJOR 2
|
||||||
#define SIM_MINOR 10
|
#define SIM_MINOR 10
|
||||||
#define SIM_PATCH 3
|
#define SIM_PATCH 4
|
||||||
|
|
||||||
/* V2.10 revision history
|
/* V2.10 revision history
|
||||||
|
|
||||||
patch date module(s) and fix(es)
|
patch date module(s) and fix(es)
|
||||||
|
|
||||||
3 tbd scp.c:
|
4 22-Feb-03 scp.c
|
||||||
|
-- added .ini startup file capability
|
||||||
|
-- added multiple breakpoint actions
|
||||||
|
-- added multiple switch evaluation points
|
||||||
|
-- fixed bug in multiword deposits to file
|
||||||
|
|
||||||
|
sim_tape.c: magtape simulation library
|
||||||
|
|
||||||
|
h316_stddev.c: added set line frequency command
|
||||||
|
|
||||||
|
hp2100_mt.c, hp2100_ms.c: revised to use magtape library
|
||||||
|
|
||||||
|
i1401_mt.c: revised to use magtape library
|
||||||
|
|
||||||
|
id_dp.c, id_idc.c: fixed cylinder overflow on writes
|
||||||
|
|
||||||
|
id_mt.c:
|
||||||
|
-- fixed error handling to stop selector channel
|
||||||
|
-- revised to use magtape library
|
||||||
|
|
||||||
|
id16_sys.c, id32_sys.c: added relative addressing support
|
||||||
|
|
||||||
|
id_uvc.c:
|
||||||
|
-- added set frequency command to line frequency clock
|
||||||
|
-- improved calibration algorithm for precision clock
|
||||||
|
|
||||||
|
nova_clk.c: added set line frequency command
|
||||||
|
|
||||||
|
nova_dsk.c: fixed autosizing algorithm
|
||||||
|
|
||||||
|
nova_mt.c: revised to use magtape library
|
||||||
|
|
||||||
|
pdp10_tu.c: revised to use magtape library
|
||||||
|
|
||||||
|
pdp11_stddev.c
|
||||||
|
-- added set line frequency command
|
||||||
|
-- added set ctrl-c command
|
||||||
|
|
||||||
|
pdp11_rq.c:
|
||||||
|
-- fixed ordering problem in queue process
|
||||||
|
-- fixed bug in vector calculation for VAXen
|
||||||
|
-- added user defined drive support
|
||||||
|
|
||||||
|
pdp11_ry.c: fixed autosizing algorithm
|
||||||
|
|
||||||
|
pdp11_tm.c, pdp11_ts.c: revised to use magtape library
|
||||||
|
|
||||||
|
pdp11_tq.c:
|
||||||
|
-- fixed ordering problem in queue process
|
||||||
|
-- fixed overly restrictive test for bad modifiers
|
||||||
|
-- fixed bug in vector calculation for VAXen
|
||||||
|
-- added variable controller, user defined drive support
|
||||||
|
-- revised to use magtape library
|
||||||
|
|
||||||
|
pdp18b_cpu.c: fixed three EAE bugs (found by Hans Pufal)
|
||||||
|
|
||||||
|
pdp18b_mt.c:
|
||||||
|
-- fixed bugs in BOT error handling, interrupt handling
|
||||||
|
-- revised to use magtape library
|
||||||
|
|
||||||
|
pdp18b_rf.c: removed 22nd bit from disk address
|
||||||
|
|
||||||
|
pdp18b_stddev.c:
|
||||||
|
-- added set line frequency command
|
||||||
|
-- added set ctrl-c command
|
||||||
|
|
||||||
|
pdp18b_sys.c: fixed FMTASC printouts (found by Hans Pufal)
|
||||||
|
|
||||||
|
pdp8_clk.c: added set line frequency command
|
||||||
|
|
||||||
|
pdp8_df.c, pdp8_rf.c, pdp8_rx.c: fixed autosizing algorithm
|
||||||
|
|
||||||
|
pdp8_mt.c:
|
||||||
|
-- fixed bug in BOT error handling
|
||||||
|
-- revised to use magtape library
|
||||||
|
|
||||||
|
pdp8_tt.c: added set ctrl-c command
|
||||||
|
|
||||||
|
sds_cpu.c: added set line frequency command
|
||||||
|
|
||||||
|
sds_mt.c: revised to use magtape library
|
||||||
|
|
||||||
|
vax_stddev.c: added set ctrl-c command
|
||||||
|
|
||||||
|
3 06-Feb-03 scp.c:
|
||||||
-- added dynamic extension of the breakpoint table
|
-- added dynamic extension of the breakpoint table
|
||||||
-- added breakpoint actions
|
-- added breakpoint actions
|
||||||
|
|
||||||
|
|
|
@ -209,8 +209,9 @@ int32 sim_check_conn (SOCKET sock, t_bool rd)
|
||||||
fd_set rw_set, er_set;
|
fd_set rw_set, er_set;
|
||||||
fd_set *rw_p = &rw_set;
|
fd_set *rw_p = &rw_set;
|
||||||
fd_set *er_p = &er_set;
|
fd_set *er_p = &er_set;
|
||||||
struct timeval tz = { 0, 0};
|
struct timeval tz;
|
||||||
|
|
||||||
|
timerclear (&tz);
|
||||||
FD_ZERO (rw_p);
|
FD_ZERO (rw_p);
|
||||||
FD_ZERO (er_p);
|
FD_ZERO (er_p);
|
||||||
FD_SET (sock, rw_p);
|
FD_SET (sock, rw_p);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* sim_sock.h: OS-dependent socket routines header file
|
/* sim_sock.h: OS-dependent socket routines header file
|
||||||
|
|
||||||
Copyright (c) 2001, Robert M Supnik
|
Copyright (c) 2001-2003, Robert M Supnik
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the "Software"),
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
@ -23,6 +23,7 @@
|
||||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
15-Feb-03 RMS Added time.h for EMX (from Holger Veit)
|
||||||
17-Dec-02 RMS Added sim_connect_sock
|
17-Dec-02 RMS Added sim_connect_sock
|
||||||
08-Oct-02 RMS Revised for .NET compatibility
|
08-Oct-02 RMS Revised for .NET compatibility
|
||||||
20-Aug-02 RMS Changed calling sequence for sim_accept_conn
|
20-Aug-02 RMS Changed calling sequence for sim_accept_conn
|
||||||
|
@ -50,6 +51,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <netinet/in.h> /* for sockaddr_in */
|
#include <netinet/in.h> /* for sockaddr_in */
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
#include <sys/time.h> /* for EMX */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined (VMS) /* VMS unique */
|
#if defined (VMS) /* VMS unique */
|
||||||
|
|
367
sim_tape.c
Normal file
367
sim_tape.c
Normal file
|
@ -0,0 +1,367 @@
|
||||||
|
/* sim_tape.h: simulator tape support library
|
||||||
|
|
||||||
|
Copyright (c) 1993-2003, Robert M Supnik
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
Except as contained in this notice, the name of Robert M Supnik shall not
|
||||||
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
Ultimately, this will be a place to hide processing of various tape formats,
|
||||||
|
as well as OS-specific direct hardware access.
|
||||||
|
|
||||||
|
Public routines:
|
||||||
|
|
||||||
|
sim_tape_attach attach tape unit
|
||||||
|
sim_tape_detach detach tape unit
|
||||||
|
sim_tape_rdrecf read tape record forward
|
||||||
|
sim_tape_rdrecr read tape record reverse
|
||||||
|
sim_tape_wrrecf write tape record forward
|
||||||
|
sim_tape_sprecf space tape record forward
|
||||||
|
sim_tape_sprecr space tape record reverse
|
||||||
|
sim_tape_wrtmk write tape mark
|
||||||
|
sim_tape_wreom erase remainder of tape
|
||||||
|
sim_tape_rewind rewind
|
||||||
|
sim_tape_reset reset unit
|
||||||
|
sim_tape_bot TRUE if at beginning of tape
|
||||||
|
sim_tape_eot TRUE if at or beyond end of tape
|
||||||
|
sim_tape_wrp TRUE if write protected
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "sim_defs.h"
|
||||||
|
#include "sim_tape.h"
|
||||||
|
|
||||||
|
t_stat sim_tape_ioerr (UNIT *uptr);
|
||||||
|
t_stat sim_tape_wrdata (UNIT *uptr, uint32 dat);
|
||||||
|
|
||||||
|
/* Attach tape unit */
|
||||||
|
|
||||||
|
t_stat sim_tape_attach (UNIT *uptr, char *cptr)
|
||||||
|
{
|
||||||
|
t_stat r = attach_unit (uptr, cptr);
|
||||||
|
if (r != SCPE_OK) return r;
|
||||||
|
return sim_tape_rewind (uptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Detach tape unit */
|
||||||
|
|
||||||
|
t_stat sim_tape_detach (UNIT *uptr)
|
||||||
|
{
|
||||||
|
t_stat r = detach_unit (uptr);
|
||||||
|
|
||||||
|
if (r != SCPE_OK) return r;
|
||||||
|
return sim_tape_rewind (uptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read record length forward (internal routine)
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
uptr = pointer to tape unit
|
||||||
|
bc = pointer to returned record length
|
||||||
|
Outputs:
|
||||||
|
status = operation status
|
||||||
|
|
||||||
|
exit condition position
|
||||||
|
|
||||||
|
unit unattached unchanged
|
||||||
|
read error unchanged, PNU set
|
||||||
|
end of file/medium unchanged, PNU set
|
||||||
|
tape mark updated
|
||||||
|
data record unchanged
|
||||||
|
*/
|
||||||
|
|
||||||
|
t_stat sim_tape_rdlntf (UNIT *uptr, t_mtrlnt *bc)
|
||||||
|
{
|
||||||
|
MT_CLR_PNU (uptr);
|
||||||
|
if ((uptr->flags & UNIT_ATT) == 0) return MTSE_UNATT; /* not attached? */
|
||||||
|
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set tape pos */
|
||||||
|
fxread (bc, sizeof (t_mtrlnt), 1, uptr->fileref); /* read rec lnt */
|
||||||
|
if (ferror (uptr->fileref)) { /* error? */
|
||||||
|
MT_SET_PNU (uptr); /* pos not upd */
|
||||||
|
return sim_tape_ioerr (uptr); }
|
||||||
|
if (feof (uptr->fileref) || (*bc == MTR_EOM)) { /* eof or eom? */
|
||||||
|
MT_SET_PNU (uptr); /* pos not upd */
|
||||||
|
return MTSE_EOM; }
|
||||||
|
if (*bc == MTR_TMK) { /* tape mark? */
|
||||||
|
uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* spc over tmk */
|
||||||
|
return MTSE_TMK; }
|
||||||
|
return MTSE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read record length reverse (internal routine)
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
uptr = pointer to tape unit
|
||||||
|
bc = pointer to returned record length
|
||||||
|
Outputs:
|
||||||
|
status = operation status
|
||||||
|
|
||||||
|
exit condition position
|
||||||
|
|
||||||
|
unit unattached unchanged
|
||||||
|
beginning of tape unchanged
|
||||||
|
read error unchanged
|
||||||
|
end of file unchanged
|
||||||
|
end of medium updated
|
||||||
|
tape mark updated
|
||||||
|
data record unchanged
|
||||||
|
*/
|
||||||
|
|
||||||
|
t_stat sim_tape_rdlntr (UNIT *uptr, t_mtrlnt *bc)
|
||||||
|
{
|
||||||
|
MT_CLR_PNU (uptr);
|
||||||
|
if ((uptr->flags & UNIT_ATT) == 0) return MTSE_UNATT; /* not attached? */
|
||||||
|
if (uptr->pos < sizeof (t_mtrlnt)) return MTSE_BOT; /* at BOT? */
|
||||||
|
fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET);
|
||||||
|
fxread (bc, sizeof (t_mtrlnt), 1, uptr->fileref); /* read rec lnt */
|
||||||
|
if (ferror (uptr->fileref)) /* error? */
|
||||||
|
return sim_tape_ioerr (uptr);
|
||||||
|
if (feof (uptr->fileref)) return MTSE_EOM; /* eof? */
|
||||||
|
if (*bc == MTR_EOM) { /* eom? */
|
||||||
|
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over eom */
|
||||||
|
return MTSE_EOM; }
|
||||||
|
if (*bc == MTR_TMK) { /* tape mark? */
|
||||||
|
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over tmk */
|
||||||
|
return MTSE_TMK; }
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read record forward
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
uptr = pointer to tape unit
|
||||||
|
buf = pointer to buffer
|
||||||
|
bc = pointer to returned record length
|
||||||
|
max = maximum record size
|
||||||
|
Outputs:
|
||||||
|
status = operation status
|
||||||
|
|
||||||
|
exit condition position
|
||||||
|
|
||||||
|
unit unattached unchanged
|
||||||
|
read error unchanged, PNU set
|
||||||
|
end of file/medium unchanged, PNU set
|
||||||
|
invalid record unchanged, PNU set
|
||||||
|
tape mark updated
|
||||||
|
data record updated
|
||||||
|
data record error updated
|
||||||
|
*/
|
||||||
|
|
||||||
|
t_stat sim_tape_rdrecf (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max)
|
||||||
|
{
|
||||||
|
t_mtrlnt i, tbc, rbc, ebc;
|
||||||
|
t_stat st;
|
||||||
|
|
||||||
|
if (st = sim_tape_rdlntf (uptr, &tbc)) return st; /* read rec lnt */
|
||||||
|
*bc = rbc = MTR_L (tbc); /* strip error flag */
|
||||||
|
ebc = (rbc + 1) & ~1;
|
||||||
|
if (rbc > max) { /* rec out of range? */
|
||||||
|
MT_SET_PNU (uptr);
|
||||||
|
return MTSE_INVRL; }
|
||||||
|
i = fxread (buf, sizeof (uint8), rbc, uptr->fileref); /* read record */
|
||||||
|
if (ferror (uptr->fileref)) { /* error? */
|
||||||
|
MT_SET_PNU (uptr);
|
||||||
|
return sim_tape_ioerr (uptr); }
|
||||||
|
for ( ; i < rbc; i++) buf[i] = 0; /* fill with 0's */
|
||||||
|
uptr->pos = uptr->pos + ebc + (2 * sizeof (t_mtrlnt)); /* move tape */
|
||||||
|
return (MTR_F (tbc)? MTSE_RECE: MTSE_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read record reverse
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
uptr = pointer to tape unit
|
||||||
|
buf = pointer to buffer
|
||||||
|
bc = pointer to returned record length
|
||||||
|
max = maximum record size
|
||||||
|
Outputs:
|
||||||
|
status = operation status
|
||||||
|
|
||||||
|
exit condition position
|
||||||
|
|
||||||
|
unit unattached unchanged
|
||||||
|
read error unchanged
|
||||||
|
end of file unchanged
|
||||||
|
end of medium updated
|
||||||
|
invalid record unchanged
|
||||||
|
tape mark updated
|
||||||
|
data record updated
|
||||||
|
data record error updated
|
||||||
|
*/
|
||||||
|
|
||||||
|
t_stat sim_tape_rdrecr (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max)
|
||||||
|
{
|
||||||
|
t_mtrlnt i, rbc, tbc, ebc;
|
||||||
|
t_stat st;
|
||||||
|
|
||||||
|
if (st = sim_tape_rdlntr (uptr, &tbc)) return st; /* read rec lnt */
|
||||||
|
*bc = rbc = MTR_L (tbc); /* strip error flag */
|
||||||
|
ebc = (rbc + 1) & ~1;
|
||||||
|
if (rbc > max) return MTSE_INVRL; /* rec out of range? */
|
||||||
|
fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt) - ebc, SEEK_SET);
|
||||||
|
i = fxread (buf, sizeof (uint8), rbc, uptr->fileref); /* read record */
|
||||||
|
if (ferror (uptr->fileref)) /* error? */
|
||||||
|
return sim_tape_ioerr (uptr);
|
||||||
|
for ( ; i < rbc; i++) buf[i] = 0; /* fill with 0's */
|
||||||
|
uptr->pos = uptr->pos - ebc - (2 * sizeof (t_mtrlnt)); /* move tape */
|
||||||
|
return (MTR_F (tbc)? MTSE_RECE: MTSE_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write record forward
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
uptr = pointer to tape unit
|
||||||
|
buf = pointer to buffer
|
||||||
|
bc = record length
|
||||||
|
Outputs:
|
||||||
|
status = operation status
|
||||||
|
|
||||||
|
exit condition position
|
||||||
|
|
||||||
|
unit unattached unchanged
|
||||||
|
write protect unchanged
|
||||||
|
write error unchanged, PNU set
|
||||||
|
data record updated
|
||||||
|
*/
|
||||||
|
|
||||||
|
t_stat sim_tape_wrrecf (UNIT *uptr, uint8 *buf, t_mtrlnt bc)
|
||||||
|
{
|
||||||
|
t_mtrlnt ebc = (MTR_L (bc) + 1) & ~1;
|
||||||
|
|
||||||
|
MT_CLR_PNU (uptr);
|
||||||
|
if ((uptr->flags & UNIT_ATT) == 0) return MTSE_UNATT; /* not attached? */
|
||||||
|
if (uptr->flags & MTUF_WRP) return MTSE_WRP; /* write prot? */
|
||||||
|
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set pos */
|
||||||
|
fxwrite (&bc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||||
|
fxwrite (buf, sizeof (uint8), ebc, uptr->fileref);
|
||||||
|
fxwrite (&bc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||||
|
if (ferror (uptr->fileref)) { /* error? */
|
||||||
|
MT_SET_PNU (uptr);
|
||||||
|
return sim_tape_ioerr (uptr); }
|
||||||
|
uptr->pos = uptr->pos + ebc + (2 * sizeof (t_mtrlnt)); /* move tape */
|
||||||
|
return MTSE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write metadata forward (internal routine) */
|
||||||
|
|
||||||
|
t_stat sim_tape_wrdata (UNIT *uptr, uint32 dat)
|
||||||
|
{
|
||||||
|
MT_CLR_PNU (uptr);
|
||||||
|
if ((uptr->flags & UNIT_ATT) == 0) return MTSE_UNATT; /* not attached? */
|
||||||
|
if (uptr-> flags & MTUF_WRP) return MTSE_WRP; /* write prot? */
|
||||||
|
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set pos */
|
||||||
|
fxwrite (&dat, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||||
|
if (ferror (uptr->fileref)) { /* error? */
|
||||||
|
MT_SET_PNU (uptr);
|
||||||
|
return sim_tape_ioerr (uptr); }
|
||||||
|
uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* move tape */
|
||||||
|
return MTSE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write tape mark */
|
||||||
|
|
||||||
|
t_stat sim_tape_wrtmk (UNIT *uptr)
|
||||||
|
{
|
||||||
|
return sim_tape_wrdata (uptr, MTR_TMK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write end of medium */
|
||||||
|
|
||||||
|
t_stat sim_tape_wreom (UNIT *uptr)
|
||||||
|
{
|
||||||
|
return sim_tape_wrdata (uptr, MTR_EOM);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Space record forward */
|
||||||
|
|
||||||
|
t_stat sim_tape_sprecf (UNIT *uptr, t_mtrlnt *bc)
|
||||||
|
{
|
||||||
|
t_mtrlnt ebc;
|
||||||
|
t_stat st;
|
||||||
|
|
||||||
|
if (st = sim_tape_rdlntf (uptr, bc)) return st; /* get record length */
|
||||||
|
*bc = MTR_L (*bc);
|
||||||
|
ebc = (*bc + 1) & ~1;
|
||||||
|
uptr->pos = uptr->pos + ebc + (2 * sizeof (t_mtrlnt)); /* update position */
|
||||||
|
return MTSE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Space record reverse */
|
||||||
|
|
||||||
|
t_stat sim_tape_sprecr (UNIT *uptr, t_mtrlnt *bc)
|
||||||
|
{
|
||||||
|
t_mtrlnt ebc;
|
||||||
|
t_stat st;
|
||||||
|
|
||||||
|
if (MT_TST_PNU (uptr)) {
|
||||||
|
MT_CLR_PNU (uptr);
|
||||||
|
return SCPE_OK; }
|
||||||
|
if (st = sim_tape_rdlntr (uptr, bc)) return st; /* get record length */
|
||||||
|
*bc = MTR_L (*bc);
|
||||||
|
ebc = (*bc + 1) & ~1;
|
||||||
|
uptr->pos = uptr->pos - ebc - (2 * sizeof (t_mtrlnt)); /* update position */
|
||||||
|
return MTSE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Rewind tape */
|
||||||
|
|
||||||
|
t_stat sim_tape_rewind (UNIT *uptr)
|
||||||
|
{
|
||||||
|
uptr->pos = 0;
|
||||||
|
MT_CLR_PNU (uptr);
|
||||||
|
return MTSE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset tape */
|
||||||
|
|
||||||
|
t_stat sim_tape_reset (UNIT *uptr)
|
||||||
|
{
|
||||||
|
MT_CLR_PNU (uptr);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test for BOT */
|
||||||
|
|
||||||
|
t_bool sim_tape_bot (UNIT *uptr)
|
||||||
|
{
|
||||||
|
return (uptr->pos < sizeof (t_mtrlnt))? TRUE: FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test for end of tape */
|
||||||
|
|
||||||
|
t_bool sim_tape_eot (UNIT *uptr, t_addr cap)
|
||||||
|
{
|
||||||
|
return (uptr->pos > cap)? TRUE: FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test for write protect */
|
||||||
|
|
||||||
|
t_bool sim_tape_wrp (UNIT *uptr)
|
||||||
|
{
|
||||||
|
return (uptr->flags & MTUF_WRP)? TRUE: FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process I/O error */
|
||||||
|
|
||||||
|
t_stat sim_tape_ioerr (UNIT *uptr)
|
||||||
|
{
|
||||||
|
perror ("Magtape library I/O error");
|
||||||
|
clearerr (uptr->fileref);
|
||||||
|
return SCPE_IOERR;
|
||||||
|
}
|
101
sim_tape.h
Normal file
101
sim_tape.h
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
/* sim_tape.h: simulator tape support library definitions
|
||||||
|
|
||||||
|
Copyright (c) 1993-2003, Robert M Supnik
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the "Software"),
|
||||||
|
to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
Except as contained in this notice, the name of Robert M Supnik shall not
|
||||||
|
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SIM_TAPE_H_
|
||||||
|
#define _SIM_TAPE_H_ 0
|
||||||
|
|
||||||
|
/* Temporary for use with old sim_defs.h */
|
||||||
|
|
||||||
|
#undef MTR_TMK
|
||||||
|
#undef MTR_EOM
|
||||||
|
#undef MTR_ERF
|
||||||
|
#undef MT_SET_PNU
|
||||||
|
#undef MT_CLR_PNU
|
||||||
|
#undef MT_TST_PNU
|
||||||
|
|
||||||
|
/* Default tape format */
|
||||||
|
|
||||||
|
/* typedef uint32 t_mtrlnt; /* magtape rec lnt */
|
||||||
|
|
||||||
|
#define MTR_TMK 0x00000000 /* tape mark */
|
||||||
|
#define MTR_EOM 0xFFFFFFFF /* end of medium */
|
||||||
|
#define MTR_ERF 0x80000000 /* error flag */
|
||||||
|
#define MTR_F(x) ((x) & MTR_ERF) /* record error flg */
|
||||||
|
#define MTR_L(x) ((x) & ~MTR_ERF) /* record length */
|
||||||
|
|
||||||
|
/* Unit flags */
|
||||||
|
|
||||||
|
#define MTUF_V_PNU (UNIT_V_UF + 0) /* position not upd */
|
||||||
|
#define MTUF_V_WLK (UNIT_V_UF + 1) /* write locked */
|
||||||
|
#define MTUF_V_FMT (UNIT_V_UF + 2) /* tape file format */
|
||||||
|
#define MTUF_W_FMT 3 /* 3b of formats */
|
||||||
|
#define MTUF_N_FMT (1u << MTUF_W_FMT) /* number of formats */
|
||||||
|
#define MTUF_M_FMT ((1u << MTUF_W_FMT) - 1)
|
||||||
|
#define MTUF_F_STD 0 /* SIMH format */
|
||||||
|
#define MTUF_F_E11 1 /* E11 format */
|
||||||
|
#define MTUF_F_TPC 2 /* TPC format */
|
||||||
|
#define MUTF_F_TDF 3 /* TDF format */
|
||||||
|
#define MTUF_V_UF (MTUF_V_FMT + MTUF_W_FMT)
|
||||||
|
#define MTUF_PNU (1u << MTUF_V_PNU)
|
||||||
|
#define MTUF_WLK (1u << MTUF_V_WLK)
|
||||||
|
#define MTUF_WRP (MTUF_WLK | UNIT_RO)
|
||||||
|
|
||||||
|
#define MT_SET_PNU(u) (u)->flags = (u)->flags | MTUF_PNU
|
||||||
|
#define MT_CLR_PNU(u) (u)->flags = (u)->flags & ~MTUF_PNU
|
||||||
|
#define MT_TST_PNU(u) ((u)->flags & MTUF_PNU)
|
||||||
|
#define MT_GET_FMT(u) (((u)->flags >> MTUF_V_FMT) & MTUF_M_FMT)
|
||||||
|
|
||||||
|
/* Return status codes */
|
||||||
|
|
||||||
|
#define MTSE_OK 0 /* no error */
|
||||||
|
#define MTSE_TMK 1 /* tape mark */
|
||||||
|
#define MTSE_UNATT 2 /* unattached */
|
||||||
|
#define MTSE_IOERR 3 /* IO error */
|
||||||
|
#define MTSE_INVRL 4 /* invalid rec lnt */
|
||||||
|
#define MTSE_FMT 5 /* invalid format */
|
||||||
|
#define MTSE_BOT 6 /* beginning of tape */
|
||||||
|
#define MTSE_EOM 7 /* end of medium */
|
||||||
|
#define MTSE_RECE 8 /* error in record */
|
||||||
|
#define MTSE_WRP 9 /* write protected */
|
||||||
|
|
||||||
|
/* Prototypes */
|
||||||
|
|
||||||
|
t_stat sim_tape_attach (UNIT *uptr, char *cptr);
|
||||||
|
t_stat sim_tape_detach (UNIT *uptr);
|
||||||
|
t_stat sim_tape_rdrecf (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max);
|
||||||
|
t_stat sim_tape_rdrecr (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max);
|
||||||
|
t_stat sim_tape_wrrecf (UNIT *uptr, uint8 *buf, t_mtrlnt bc);
|
||||||
|
t_stat sim_tape_wrtmk (UNIT *uptr);
|
||||||
|
t_stat sim_tape_wreom (UNIT *uptr);
|
||||||
|
t_stat sim_tape_sprecf (UNIT *uptr, t_mtrlnt *bc);
|
||||||
|
t_stat sim_tape_sprecr (UNIT *uptr, t_mtrlnt *bc);
|
||||||
|
t_stat sim_tape_rewind (UNIT *uptr);
|
||||||
|
t_stat sim_tape_reset (UNIT *uptr);
|
||||||
|
t_bool sim_tape_bot (UNIT *uptr);
|
||||||
|
t_bool sim_tape_wrp (UNIT *uptr);
|
||||||
|
t_bool sim_tape_eot (UNIT *uptr, t_addr cap);
|
||||||
|
|
||||||
|
#endif
|
40
simh_doc.txt
40
simh_doc.txt
|
@ -82,16 +82,23 @@ To start the simulator, simply type its name. (On version of VMS
|
||||||
prior to 6.2, the simulators must then be defined as foreign commands
|
prior to 6.2, the simulators must then be defined as foreign commands
|
||||||
in order to be be started by name.) The simulator recognizes one
|
in order to be be started by name.) The simulator recognizes one
|
||||||
switch, -Q; if specified, certain informational messages are suppressed.
|
switch, -Q; if specified, certain informational messages are suppressed.
|
||||||
|
|
||||||
The simulator interprets the arguments on the command line, if any,
|
The simulator interprets the arguments on the command line, if any,
|
||||||
as the file name and arguments for a DO command. If a startup file
|
as the file name and arguments for a DO command:
|
||||||
is specified, it should contain a series of non-interactive simulator
|
|
||||||
commands, one per line. These command can be used to set up standard
|
|
||||||
parameters, for example, disk sizes:
|
|
||||||
|
|
||||||
% pdp10 {<startup file> {arg,arg,...}}(cr)
|
% pdp10 {<startup file> {arg,arg,...}}(cr)
|
||||||
|
|
||||||
The simulator types out its name and version, executes the commands
|
If no file is specified on the command line, the simulator looks for
|
||||||
in the startup file, if any, and then prompts for input with
|
an startup file consisting of the simulator name (including its path
|
||||||
|
components) plus the extension .ini. If a startup file is specified,
|
||||||
|
either on the command line or implicitly via the .ini capability, it
|
||||||
|
ishould contain a series of non-interactive simulator command, one
|
||||||
|
per line. These command can be used to set up standard parameters,
|
||||||
|
for example, disk sizes.
|
||||||
|
|
||||||
|
After initializing its internal structures and processing the startup
|
||||||
|
file (if any), the simulator types out its name and version and then
|
||||||
|
prompts for input with:
|
||||||
|
|
||||||
sim>
|
sim>
|
||||||
|
|
||||||
|
@ -106,11 +113,11 @@ The supplied makefile will compile the simulators for UNIX systems
|
||||||
which support the POSIX TERMIOS. The VAX and PDP-11 can be compiled
|
which support the POSIX TERMIOS. The VAX and PDP-11 can be compiled
|
||||||
with or without Ethernet support. To compile without Ethernet support:
|
with or without Ethernet support. To compile without Ethernet support:
|
||||||
|
|
||||||
gmake {target|ALL}
|
gmake {target|ALL|clean}
|
||||||
|
|
||||||
To compile with Ethernet support:
|
To compile with Ethernet support:
|
||||||
|
|
||||||
gmake USE_NETWORK=1 {target|ALL}
|
gmake USE_NETWORK=1 {target|ALL|clean}
|
||||||
|
|
||||||
Notes for hand compilation:
|
Notes for hand compilation:
|
||||||
|
|
||||||
|
@ -490,15 +497,16 @@ breakpoints of different types, identified by letter (for example, E
|
||||||
for execution, R for read, W for write, etc). At the moment, most
|
for execution, R for read, W for write, etc). At the moment, most
|
||||||
simulators support only E (execution) breakpoints.
|
simulators support only E (execution) breakpoints.
|
||||||
|
|
||||||
Associated with a breakpoint is a count and, optionally, an action.
|
Associated with a breakpoint is a count and, optionally, one or more
|
||||||
Each time the breakpoint is sprung, the associated count is decremented.
|
actions. Each time the breakpoint is sprung, the associated count is
|
||||||
If the count is less than or equal to 0, the breakpoint occurs; otherwise,
|
decremented. If the count is less than or equal to 0, the breakpoint
|
||||||
it is deferred. When the breakpoint occurs, the optional action is
|
occurs; otherwise, it is deferred. When the breakpoint occurs, the
|
||||||
automatically executed
|
optional actions are automatically executed.
|
||||||
|
|
||||||
A breakpoint is set by the BREAK command:
|
A breakpoint is set by the BREAK command:
|
||||||
|
|
||||||
sim> BREAK {-types} <addr range>{[count]},{addr range...}{;action}
|
sim> BREAK {-types} <addr range>{[count]},{addr range...}
|
||||||
|
{;action;action...}
|
||||||
|
|
||||||
If no type is specified, the simulator-specific default breakpoint
|
If no type is specified, the simulator-specific default breakpoint
|
||||||
type (usually E for execution) is used. As with EXAMINE and DEPOSIT,
|
type (usually E for execution) is used. As with EXAMINE and DEPOSIT,
|
||||||
|
@ -508,8 +516,8 @@ or a relative range of address/length. Examples of BREAK:
|
||||||
sim> break -e 200 -- set E break at 200
|
sim> break -e 200 -- set E break at 200
|
||||||
sim> break 2000/2[2] -- set E breaks at 2000,2001
|
sim> break 2000/2[2] -- set E breaks at 2000,2001
|
||||||
with count = 2
|
with count = 2
|
||||||
sim> break 100;ex ac -- set E break at 100 with
|
sim> break 100;ex ac;d mq 0 -- set E break at 100 with
|
||||||
action EX AC
|
actions EX AC and D MQ 0
|
||||||
sim> break 100; -- delete action on break at 100
|
sim> break 100; -- delete action on break at 100
|
||||||
|
|
||||||
Currently set breakpoints can be displayed with the SHOW BREAK command:
|
Currently set breakpoints can be displayed with the SHOW BREAK command:
|
||||||
|
|
|
@ -164,7 +164,7 @@ sockets library.
|
||||||
|
|
||||||
UNIX was first developed on the PDP-7; its first widespread usage was on
|
UNIX was first developed on the PDP-7; its first widespread usage was on
|
||||||
the PDP-11. UNIX provides a program development and execution environment
|
the PDP-11. UNIX provides a program development and execution environment
|
||||||
for assembler and C programs. UNIX V5, V7, V7 for the PDP-11 is provided
|
for assembler and C programs. UNIX V5, V6, V7 for the PDP-11 is provided
|
||||||
under license, as is, without fee, by Caldera Corportion, for non-commercial
|
under license, as is, without fee, by Caldera Corportion, for non-commercial
|
||||||
use only. Please read the enclosed license agreement for full terms and
|
use only. Please read the enclosed license agreement for full terms and
|
||||||
conditions. This license must be reproduced with any copy of the UNIX V5,
|
conditions. This license must be reproduced with any copy of the UNIX V5,
|
||||||
|
@ -646,4 +646,48 @@ TOPS-20 was a popular alternative derived from the BBN TENEX system.
|
||||||
Installation and distribution tapes for TOPS-10 7.03, TOPS-10 7.04,
|
Installation and distribution tapes for TOPS-10 7.03, TOPS-10 7.04,
|
||||||
and TOPS-20 4.1 are available at http://pdp-10.trailing-edge.com.
|
and TOPS-20 4.1 are available at http://pdp-10.trailing-edge.com.
|
||||||
|
|
||||||
|
10. Interdata 32b Systems
|
||||||
|
|
||||||
|
10.1 Interdata 7/32 UNIX
|
||||||
|
|
||||||
|
Interdata UNIX V6 was the first port of UNIX from its native environment
|
||||||
|
on the PDP-11. The port was done by Richard Miller and his colleagues
|
||||||
|
at the University of Wollongong, Australia, in 1976-77. UNIX V6 and V7
|
||||||
|
for the Interdata 7/32 is provided under license, as is, without fee, by
|
||||||
|
Caldera Corportion, for non-commercial use only. Please read the enclosed
|
||||||
|
license agreement for full terms and conditions. This license must be
|
||||||
|
reproduced with any copy of the UNIX V6 and V7 disk images. My thanks to
|
||||||
|
Richard Miller, without whose guidance, knowledge, and patience the
|
||||||
|
recreation of Interdata UNIX would not have been possible, and to Caldera,
|
||||||
|
which provided the license.
|
||||||
|
|
||||||
|
10.1.1 UNIX V6
|
||||||
|
|
||||||
|
UNIX V6 is contained on a single 10MB disk image. To boot UNIX V6:
|
||||||
|
|
||||||
|
sim> set ttp ena
|
||||||
|
sim> set pas dev=12
|
||||||
|
sim> set mt dev=85
|
||||||
|
sim> att -e dp0 iu6_dp0.dsk
|
||||||
|
sim> boot dp0
|
||||||
|
?unix
|
||||||
|
login: root
|
||||||
|
# ls -l
|
||||||
|
|
||||||
|
10.1.2 UNIX V7
|
||||||
|
|
||||||
|
UNIX V7 is contained on two 10MB disk images. To boot UNIX V7:
|
||||||
|
|
||||||
|
sim> set ttp ena
|
||||||
|
sim> set pas dev=12
|
||||||
|
sim> set mt dev=85
|
||||||
|
sim> att -e dp0 iu6_dp0.dsk
|
||||||
|
sim> att -e dp1 iu6_dp1.dsk
|
||||||
|
sim> boot dp0
|
||||||
|
Boot
|
||||||
|
: dsk(1,0)unix
|
||||||
|
#
|
||||||
|
|
||||||
|
Type ^D to enable multiuser mode. The root password is root.
|
||||||
|
|
||||||
[end simh_swre.txt]
|
[end simh_swre.txt]
|
||||||
|
|
Loading…
Add table
Reference in a new issue