mirror of
https://github.com/simh/simh.git
synced 2026-04-29 05:05:14 +00:00
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:
committed by
Mark Pizzolato
parent
f20f5c629d
commit
43385c9616
@@ -26,6 +26,7 @@
|
||||
The author gratefully acknowledges the help of Max Burnet, Megan Gentry,
|
||||
and John Wilson in resolving questions about the PDP-11
|
||||
|
||||
28-Feb-03 RMS Added TM logging support
|
||||
19-Jan-03 RMS Changed mode definitions for Apple Dev Kit conflict
|
||||
11-Nov-02 RMS Changed log definitions to be VAX compatible
|
||||
10-Oct-02 RMS Added vector information to DIB
|
||||
@@ -551,6 +552,7 @@ typedef struct pdp_dib DIB;
|
||||
/* Logging */
|
||||
|
||||
#define LOG_CPU_I 0x0001
|
||||
#define LOG_TM 0x0008
|
||||
#define LOG_RP 0x0010
|
||||
#define LOG_TS 0x0020
|
||||
#define LOG_RQ 0x0040
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
To: Users
|
||||
From: Bob Supnik
|
||||
Subj: PDP-11 Simulator Usage
|
||||
Date: 1-Feb-2003
|
||||
Date: 15-Mar-2003
|
||||
|
||||
COPYRIGHT NOTICE
|
||||
|
||||
@@ -377,6 +377,12 @@ implements these registers:
|
||||
POS 32 number of characters input
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
|
||||
@@ -433,14 +446,20 @@ The line-time clock (CLK) implements these registers:
|
||||
DONE 1 device done flag (CSR<7>)
|
||||
IE 1 interrupt enable flag (CSR<6>)
|
||||
TIME 24 clock interval
|
||||
TPS 8 ticks per second (60 or 50)
|
||||
|
||||
The line-time clock autocalibrates; the clock interval is adjusted up
|
||||
or down so that the clock tracks actual elapsed time.
|
||||
|
||||
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
|
||||
|
||||
@@ -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
|
||||
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
|
||||
of eleven disk types:
|
||||
of many disk types:
|
||||
|
||||
SET RQn LOCKED set unit n write locked
|
||||
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 RA92 set type to RA92
|
||||
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.
|
||||
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:
|
||||
|
||||
SHOW RQn TYPE show drive type
|
||||
SHOW RQ RINGS show command and response rings
|
||||
SHOW RQ FREEQ show packet free 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)
|
||||
|
||||
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 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
|
||||
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:
|
||||
|
||||
SHOW TQ TYPE show controller type
|
||||
SHOW TQ RINGS show command and response rings
|
||||
SHOW TQ FREEQ show packet free 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
|
||||
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
|
||||
|
||||
Copyright (c) 2002, Robert M Supnik
|
||||
Copyright (c) 2003, Robert M Supnik
|
||||
Derived from work by Stephen F. Shirron
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
@@ -26,6 +26,9 @@
|
||||
|
||||
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
|
||||
29-Sep-02 RMS Changed addressing to 18b in Unibus mode
|
||||
Added variable address support to bootstrap
|
||||
@@ -201,7 +204,7 @@ struct rqpkt {
|
||||
|
||||
Each drive can be a different type. The drive field in the
|
||||
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 */
|
||||
@@ -400,6 +403,24 @@ struct rqpkt {
|
||||
#define RA92_MED 0x2564105C
|
||||
#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 {
|
||||
int32 sect; /* sectors */
|
||||
int32 surf; /* surfaces */
|
||||
@@ -415,6 +436,7 @@ struct drvtyp {
|
||||
int32 mod; /* MSCP model */
|
||||
int32 med; /* MSCP media */
|
||||
int32 flgs; /* flags */
|
||||
char *name; /* name */
|
||||
};
|
||||
|
||||
#define RQ_DRV(d) \
|
||||
@@ -425,13 +447,13 @@ struct drvtyp {
|
||||
#define RQ_SIZE(d) (d##_LBN * RQ_NUMBY)
|
||||
|
||||
static struct drvtyp drv_tab[] = {
|
||||
{ RQ_DRV (RX50) }, { RQ_DRV (RX33) },
|
||||
{ RQ_DRV (RD51) }, { RQ_DRV (RD31) },
|
||||
{ RQ_DRV (RD52) }, { RQ_DRV (RD53) },
|
||||
{ RQ_DRV (RD54) }, { RQ_DRV (RA82) },
|
||||
{ RQ_DRV (RRD40) }, { RQ_DRV (RA72) },
|
||||
{ RQ_DRV (RA90) }, { RQ_DRV (RA92) },
|
||||
{ 0 } };
|
||||
{ RQ_DRV (RX50), "RX50" }, { RQ_DRV (RX33), "RX33" },
|
||||
{ RQ_DRV (RD51), "RD51" }, { RQ_DRV (RD31), "RD31" },
|
||||
{ RQ_DRV (RD52), "RD52" }, { RQ_DRV (RD53), "RD53" },
|
||||
{ RQ_DRV (RD54), "RD54" }, { RQ_DRV (RA82), "RA82" },
|
||||
{ RQ_DRV (RRD40), "RRD40" }, { RQ_DRV (RA72), "RA72" },
|
||||
{ RQ_DRV (RA90), "RA90" }, { RQ_DRV (RA92), "RA92" },
|
||||
{ RQ_DRV (RA8U), "RAUSER" }, { 0 } };
|
||||
|
||||
extern int32 int_req[IPL_HLVL];
|
||||
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_boot (int32 unitno, DEVICE *dptr);
|
||||
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_ctrl (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) },
|
||||
{ GRDATA (DEVADDR, rq_dib.ba, RQ_RDX, 32, 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 } };
|
||||
|
||||
MTAB rq_mod[] = {
|
||||
@@ -603,19 +627,36 @@ MTAB rq_mod[] = {
|
||||
NULL, &rq_show_unitq, 0 },
|
||||
{ MTAB_XTD | MTAB_VUN, 0, "WRITE", NULL,
|
||||
NULL, &rq_show_wlk, NULL },
|
||||
{ UNIT_DTYPE, (RX50_DTYPE << UNIT_V_DTYPE), "RX50", "RX50", &rq_set_size },
|
||||
{ UNIT_DTYPE, (RX33_DTYPE << UNIT_V_DTYPE), "RX33", "RX33", &rq_set_size },
|
||||
{ UNIT_DTYPE, (RD31_DTYPE << UNIT_V_DTYPE), "RD31", "RD31", &rq_set_size },
|
||||
{ UNIT_DTYPE, (RD51_DTYPE << UNIT_V_DTYPE), "RD51", "RD51", &rq_set_size },
|
||||
{ UNIT_DTYPE, (RD52_DTYPE << UNIT_V_DTYPE), "RD52", "RD52", &rq_set_size },
|
||||
{ UNIT_DTYPE, (RD53_DTYPE << UNIT_V_DTYPE), "RD53", "RD53", &rq_set_size },
|
||||
{ UNIT_DTYPE, (RD54_DTYPE << UNIT_V_DTYPE), "RD54", "RD54", &rq_set_size },
|
||||
{ UNIT_DTYPE, (RA82_DTYPE << UNIT_V_DTYPE), "RA82", "RA82", &rq_set_size },
|
||||
{ UNIT_DTYPE, (RA72_DTYPE << UNIT_V_DTYPE), "RA72", "RA72", &rq_set_size },
|
||||
{ UNIT_DTYPE, (RA90_DTYPE << UNIT_V_DTYPE), "RA90", "RA90", &rq_set_size },
|
||||
{ UNIT_DTYPE, (RA92_DTYPE << UNIT_V_DTYPE), "RA92", "RA92", &rq_set_size },
|
||||
{ UNIT_DTYPE, (RRD40_DTYPE << UNIT_V_DTYPE), "RRD40", "RRD40", &rq_set_size },
|
||||
{ UNIT_DTYPE, (RRD40_DTYPE << UNIT_V_DTYPE), NULL, "CDROM", &rq_set_size },
|
||||
{ MTAB_XTD | MTAB_VUN, RX50_DTYPE, NULL, "RX50",
|
||||
&rq_set_type, NULL, NULL },
|
||||
{ MTAB_XTD | MTAB_VUN, RX33_DTYPE, NULL, "RX33",
|
||||
&rq_set_type, NULL, NULL },
|
||||
{ MTAB_XTD | MTAB_VUN, RD31_DTYPE, NULL, "RD31",
|
||||
&rq_set_type, NULL, NULL },
|
||||
{ MTAB_XTD | MTAB_VUN, RD51_DTYPE, NULL, "RD51",
|
||||
&rq_set_type, NULL, NULL },
|
||||
{ MTAB_XTD | MTAB_VUN, RD52_DTYPE, NULL, "RD52",
|
||||
&rq_set_type, NULL, NULL },
|
||||
{ MTAB_XTD | MTAB_VUN, RD53_DTYPE, NULL, "RD53",
|
||||
&rq_set_type, NULL, NULL },
|
||||
{ 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)
|
||||
{ MTAB_XTD|MTAB_VDV, 004, "ADDRESS", "ADDRESS",
|
||||
&set_addr, &show_addr, NULL },
|
||||
@@ -931,9 +972,8 @@ return OK;
|
||||
queues, response queue) require servicing. Also invoked during
|
||||
initialization to provide some delay to the next step.
|
||||
|
||||
Process at most one item off the host queue
|
||||
If the host queue is empty, process at most one item off
|
||||
each unit queue
|
||||
Process at most one item off each unit queue
|
||||
If the unit queues were empty, process at most one item off the host queue
|
||||
Process at most one item off the response queue
|
||||
|
||||
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 */
|
||||
else {
|
||||
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->csta = CST_S2; /* now in step 2 */
|
||||
rq_init_int (cp); } /* intr if req */
|
||||
@@ -996,7 +1037,12 @@ if (cp->csta < CST_UP) { /* still init? */
|
||||
break; } /* end switch */
|
||||
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 (pkt) { /* got one? */
|
||||
if (DBG_LOG (LOG_RQ)) {
|
||||
@@ -1019,13 +1065,6 @@ if (cp->pip) { /* polling? */
|
||||
} /* end if pkt */
|
||||
else cp->pip = 0; /* discontinue poll */
|
||||
} /* 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? */
|
||||
pkt = rq_deqh (cp, &cp->rspq); /* get top of q */
|
||||
if (!rq_putpkt (cp, pkt, FALSE)) return SCPE_OK; /* send to hst */
|
||||
@@ -1948,14 +1987,30 @@ else fprintf (st, "write enabled");
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
ry RY11/RX02 floppy disk
|
||||
|
||||
03-Mar-03 RMS Fixed autosizing
|
||||
12-Oct-02 RMS Added autoconfigure support
|
||||
|
||||
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)
|
||||
{
|
||||
int32 p;
|
||||
t_stat r;
|
||||
t_addr sz;
|
||||
|
||||
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;
|
||||
r = 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;
|
||||
return attach_unit (uptr, cptr);
|
||||
}
|
||||
|
||||
/* Set size routine */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* 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
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -26,6 +26,7 @@
|
||||
tti,tto DL11 terminal input/output
|
||||
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
|
||||
01-Nov-02 RMS Added 7B/8B support to terminal
|
||||
29-Sep-02 RMS Added vector display support
|
||||
@@ -58,7 +59,6 @@
|
||||
|
||||
#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */
|
||||
#define UNIT_8B (1 << UNIT_V_8B)
|
||||
#define UNIT_KSR (1 << UNIT_V_KSR)
|
||||
|
||||
extern int32 int_req[IPL_HLVL];
|
||||
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_svc (UNIT *uptr);
|
||||
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 clk_rd (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_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
|
||||
|
||||
@@ -110,6 +113,8 @@ REG tti_reg[] = {
|
||||
MTAB tti_mod[] = {
|
||||
{ UNIT_8B, 0 , "7b" , "7B" , &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,
|
||||
NULL, &show_addr, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL,
|
||||
@@ -180,10 +185,16 @@ REG clk_reg[] = {
|
||||
{ FLDATA (DONE, clk_csr, CSR_V_DONE) },
|
||||
{ FLDATA (IE, clk_csr, CSR_V_IE) },
|
||||
{ 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 } };
|
||||
|
||||
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,
|
||||
NULL, &show_addr, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL,
|
||||
@@ -254,6 +265,18 @@ CLR_INT (TTI);
|
||||
sim_activate (&tti_unit, tti_unit.wait); /* activate unit */
|
||||
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 */
|
||||
|
||||
@@ -365,3 +388,21 @@ tmr_poll = clk_unit.wait; /* set timer poll */
|
||||
tmxr_poll = clk_unit.wait; /* set mux poll */
|
||||
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
|
||||
|
||||
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
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
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-Sep-02 RMS Added variable address support to bootstrap
|
||||
Added vector change/display support
|
||||
@@ -72,14 +73,10 @@
|
||||
*/
|
||||
|
||||
#include "pdp11_defs.h"
|
||||
#include "sim_tape.h"
|
||||
|
||||
#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 UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
|
||||
/* Command - tm_cmd */
|
||||
|
||||
@@ -148,6 +145,8 @@
|
||||
extern uint16 *M; /* memory */
|
||||
extern int32 int_req[IPL_HLVL];
|
||||
extern int32 int_vec[IPL_HLVL][32];
|
||||
extern int32 cpu_log;
|
||||
extern FILE *sim_log;
|
||||
|
||||
uint8 *tmxb = NULL; /* xfer buffer */
|
||||
int32 tm_sta = 0; /* status register */
|
||||
@@ -170,8 +169,7 @@ t_stat tm_boot (int32 unitno, DEVICE *dptr);
|
||||
void tm_go (UNIT *uptr);
|
||||
int32 tm_updcsta (UNIT *uptr);
|
||||
void tm_set_done (void);
|
||||
t_bool tm_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
||||
t_bool tm_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
||||
t_stat tm_map_err (UNIT *uptr, t_stat st);
|
||||
t_stat tm_vlock (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
|
||||
/* MT data structures
|
||||
@@ -216,8 +214,8 @@ REG tm_reg[] = {
|
||||
{ NULL } };
|
||||
|
||||
MTAB tm_mod[] = {
|
||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", &tm_vlock },
|
||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", &tm_vlock },
|
||||
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", &tm_vlock },
|
||||
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", &tm_vlock },
|
||||
{ MTAB_XTD|MTAB_VDV, 020, "ADDRESS", "ADDRESS",
|
||||
&set_addr, &show_addr, NULL },
|
||||
{ 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? */
|
||||
sim_is_active (uptr) || /* busy? */
|
||||
(((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_set_done (); /* set done */
|
||||
return; }
|
||||
@@ -353,19 +351,21 @@ return;
|
||||
|
||||
t_stat tm_svc (UNIT *uptr)
|
||||
{
|
||||
int32 f, t, err, pnu, u;
|
||||
int32 f, t, u;
|
||||
t_addr xma;
|
||||
t_mtrlnt abc, tbc, cbc, ebc;
|
||||
static t_mtrlnt bceof = { MTR_TMK };
|
||||
t_mtrlnt tbc, cbc;
|
||||
t_stat st, r = SCPE_OK;
|
||||
|
||||
u = uptr - tm_dev.units; /* get unit number */
|
||||
pnu = MT_TST_PNU (uptr); /* get pos not upd */
|
||||
MT_CLR_PNU (uptr); /* and clear */
|
||||
f = GET_FNC (tm_cmd); /* get command */
|
||||
xma = GET_EMA (tm_cmd) | tm_ca; /* get mem addr */
|
||||
cbc = 0200000 - tm_bc; /* get bc */
|
||||
|
||||
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? */
|
||||
uptr->USTAT = STA_ONL | STA_BOT |
|
||||
((uptr->flags & UNIT_WPRT)? STA_WLK: 0);
|
||||
(sim_tape_wrp (uptr)? STA_WLK: 0);
|
||||
else uptr->USTAT = 0;
|
||||
if (u == GET_UNIT (tm_cmd)) { /* selected? */
|
||||
tm_set_done (); /* set done */
|
||||
@@ -379,38 +379,25 @@ if ((uptr->flags & UNIT_ATT) == 0) { /* if not attached */
|
||||
tm_updcsta (uptr); /* update status */
|
||||
return IORETURN (tm_stopioe, SCPE_UNATT); }
|
||||
|
||||
f = GET_FNC (tm_cmd); /* get command */
|
||||
if (((f == MTC_WRITE) || (f == MTC_WREOF) || (f == MTC_WREXT)) &&
|
||||
(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 */
|
||||
if (DBG_LOG (LOG_TM)) fprintf (sim_log,
|
||||
">>TM: op=%o, ma=%o, bc=%o, pos=%d\n", f, xma, cbc, uptr->pos);
|
||||
switch (f) { /* case on function */
|
||||
|
||||
/* Unit service, continued */
|
||||
|
||||
case MTC_READ: /* read */
|
||||
if (tm_rdlntf (uptr, &tbc, &err)) break; /* read rec lnt, err? */
|
||||
if (tbc > MT_MAXFR) return SCPE_MTRLNT; /* record too long? */
|
||||
st = sim_tape_rdrecf (uptr, tmxb, &tbc, MT_MAXFR); /* read rec */
|
||||
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) 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 */
|
||||
tm_sta = tm_sta | STA_NXM; /* NXM, set err */
|
||||
cbc = cbc - t; } /* adj byte cnt */
|
||||
xma = (xma + cbc) & 0777777; /* inc bus addr */
|
||||
tm_bc = (tm_bc + cbc) & 0177777; /* inc byte cnt */
|
||||
uptr->pos = uptr->pos + ((tbc + 1) & ~1) + /* upd position */
|
||||
(2 * sizeof (t_mtrlnt));
|
||||
break;
|
||||
|
||||
case MTC_WRITE: /* write */
|
||||
@@ -419,58 +406,48 @@ case MTC_WREXT: /* write ext gap */
|
||||
tm_sta = tm_sta | STA_NXM; /* NXM, set err */
|
||||
cbc = cbc - t; /* adj byte cnt */
|
||||
if (cbc == 0) break; } /* no xfr? done */
|
||||
ebc = (cbc + 1) & ~1; /* force even */
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
||||
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? */
|
||||
if (st = sim_tape_wrrecf (uptr, tmxb, cbc)) /* write rec, err? */
|
||||
r = tm_map_err (uptr, st); /* map error */
|
||||
else {
|
||||
xma = (xma + cbc) & 0777777; /* inc bus addr */
|
||||
tm_bc = (tm_bc + cbc) & 0177777; /* inc byte cnt */
|
||||
uptr->pos = uptr->pos + ebc + /* upd pos */
|
||||
(2 * sizeof (t_mtrlnt)); }
|
||||
tm_bc = (tm_bc + cbc) & 0177777; } /* inc byte cnt */
|
||||
break;
|
||||
|
||||
/* Unit service, continued */
|
||||
|
||||
case MTC_WREOF:
|
||||
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); /* update position */
|
||||
case MTC_WREOF: /* write eof */
|
||||
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
|
||||
r = tm_map_err (uptr, st); /* map error */
|
||||
break;
|
||||
|
||||
case MTC_SPACEF: /* space forward */
|
||||
do {
|
||||
tm_bc = (tm_bc + 1) & 0177777; /* incr wc */
|
||||
if (tm_rdlntf (uptr, &tbc, &err)) break; /* read rec lnt, err? */
|
||||
uptr->pos = uptr->pos + ((tbc + 1) & ~1) +
|
||||
(2 * sizeof (t_mtrlnt)); }
|
||||
if (st = sim_tape_sprecf (uptr, &tbc)) { /* spc rec fwd, err? */
|
||||
r = tm_map_err (uptr, st); /* map error */
|
||||
break; }
|
||||
}
|
||||
while (tm_bc != 0);
|
||||
break;
|
||||
|
||||
case MTC_SPACER: /* space reverse */
|
||||
do {
|
||||
tm_bc = (tm_bc + 1) & 0177777; /* incr wc */
|
||||
if (pnu) pnu = 0; /* pos not upd? */
|
||||
else {
|
||||
if (tm_rdlntr (uptr, &tbc, &err)) break;
|
||||
uptr->pos = uptr->pos - ((tbc + 1) & ~1) -
|
||||
(2 * sizeof (t_mtrlnt)); } }
|
||||
if (st = sim_tape_sprecr (uptr, &tbc)) { /* spc rec rev, err? */
|
||||
r = tm_map_err (uptr, st); /* map error */
|
||||
break; }
|
||||
}
|
||||
while (tm_bc != 0);
|
||||
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_ca = xma & 0177777; /* update mem addr */
|
||||
tm_set_done (); /* set done */
|
||||
tm_updcsta (uptr); /* update status */
|
||||
if (err != 0) { /* I/O error */
|
||||
perror ("MT I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
if (tm_stopioe) return SCPE_IOERR; }
|
||||
return SCPE_OK;
|
||||
if (DBG_LOG (LOG_TM)) fprintf (sim_log,
|
||||
">>TM: sta=%o, ma=%o, wc=%o, pos=%d\n",
|
||||
tm_sta, tm_ca, tm_bc, uptr->pos);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Update controller status */
|
||||
@@ -495,55 +472,39 @@ if (tm_cmd & MTC_IE) SET_INT (TM);
|
||||
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 */
|
||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref); /* read rec lnt */
|
||||
if (*err = ferror (uptr->fileref)) { /* error? */
|
||||
tm_sta = tm_sta | STA_PAR; /* parity error */
|
||||
MT_SET_PNU (uptr); /* pos not upd */
|
||||
return TRUE; }
|
||||
if (feof (uptr->fileref) || (*tbc == MTR_EOM)) { /* eof or eom? */
|
||||
tm_sta = tm_sta | STA_BAD; /* bad tape */
|
||||
MT_SET_PNU (uptr); /* pos not upd */
|
||||
return TRUE; }
|
||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
||||
switch (st) {
|
||||
case MTSE_FMT: /* illegal fmt */
|
||||
case MTSE_UNATT: /* not attached */
|
||||
tm_sta = tm_sta | STA_ILL;
|
||||
case MTSE_OK: /* no error */
|
||||
return SCPE_IERR;
|
||||
case MTSE_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;
|
||||
}
|
||||
|
||||
/* Read record length reverse - return T if error, EOM, or EOF */
|
||||
|
||||
t_bool tm_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
||||
{
|
||||
if (uptr->pos < sizeof (t_mtrlnt)) { /* at BOT? */
|
||||
break;
|
||||
case MTSE_IOERR: /* IO error */
|
||||
tm_sta = tm_sta | STA_PAR; /* parity error */
|
||||
if (tm_stopioe) return SCPE_IOERR;
|
||||
break;
|
||||
case MTSE_INVRL: /* invalid rec lnt */
|
||||
tm_sta = tm_sta | STA_PAR; /* parity error */
|
||||
return SCPE_MTRLNT;
|
||||
case MTSE_RECE: /* record in error */
|
||||
tm_sta = tm_sta | STA_PAR; /* parity error */
|
||||
break;
|
||||
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 */
|
||||
return TRUE; } /* error */
|
||||
fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET);
|
||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
if (*err = ferror (uptr->fileref)) { /* error? */
|
||||
tm_sta = tm_sta | STA_PAR; /* parity error */
|
||||
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;
|
||||
break;
|
||||
case MTSE_WRP: /* write protect */
|
||||
tm_sta = tm_sta | STA_ILL; /* illegal operation */
|
||||
break; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
@@ -558,11 +519,11 @@ tm_bc = tm_ca = tm_db = tm_sta = tm_rdl = 0;
|
||||
CLR_INT (TM); /* clear interrupt */
|
||||
for (u = 0; u < TM_NUMDR; u++) { /* loop thru units */
|
||||
uptr = tm_dev.units + u;
|
||||
MT_CLR_PNU (uptr); /* clear pos flag */
|
||||
sim_tape_reset (uptr); /* reset tape */
|
||||
sim_cancel (uptr); /* cancel activity */
|
||||
if (uptr->flags & UNIT_ATT) uptr->USTAT = STA_ONL |
|
||||
((uptr->pos)? 0: STA_BOT) |
|
||||
((uptr->flags & UNIT_WPRT)? STA_WLK: 0);
|
||||
(sim_tape_bot (uptr)? STA_BOT: 0) |
|
||||
(sim_tape_wrp (uptr)? STA_WLK: 0);
|
||||
else uptr->USTAT = 0; }
|
||||
if (tmxb == NULL) tmxb = calloc (MT_MAXFR, sizeof (unsigned int8));
|
||||
if (tmxb == NULL) return SCPE_MEM;
|
||||
@@ -576,10 +537,9 @@ t_stat tm_attach (UNIT *uptr, char *cptr)
|
||||
t_stat r;
|
||||
int32 u = uptr - tm_dev.units;
|
||||
|
||||
r = attach_unit (uptr, cptr);
|
||||
r = sim_tape_attach (uptr, cptr);
|
||||
if (r != SCPE_OK) return r;
|
||||
MT_CLR_PNU (uptr);
|
||||
uptr->USTAT = STA_ONL | STA_BOT | ((uptr->flags & UNIT_WPRT)? STA_WLK: 0);
|
||||
uptr->USTAT = STA_ONL | STA_BOT | (sim_tape_wrp (uptr)? STA_WLK: 0);
|
||||
if (u == GET_UNIT (tm_cmd)) tm_updcsta (uptr);
|
||||
return r;
|
||||
}
|
||||
@@ -590,10 +550,9 @@ t_stat tm_detach (UNIT* uptr)
|
||||
{
|
||||
int32 u = uptr - tm_dev.units;
|
||||
|
||||
MT_CLR_PNU (uptr);
|
||||
if (!sim_is_active (uptr)) uptr->USTAT = 0;
|
||||
if (u == GET_UNIT (tm_cmd)) tm_updcsta (uptr);
|
||||
return detach_unit (uptr);
|
||||
return sim_tape_detach (uptr);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) &&
|
||||
(val || (uptr->flags & UNIT_RO)))
|
||||
(val || sim_tape_wrp (uptr)))
|
||||
uptr->USTAT = uptr->USTAT | STA_WLK;
|
||||
else uptr->USTAT = uptr->USTAT & ~STA_WLK;
|
||||
if (u == GET_UNIT (tm_cmd)) tm_updcsta (uptr);
|
||||
@@ -680,7 +639,7 @@ int32 i;
|
||||
extern int32 saved_PC;
|
||||
extern int32 sim_switches;
|
||||
|
||||
tm_unit[unitno].pos = 0;
|
||||
sim_tape_rewind (&tm_unit[unitno]);
|
||||
if (sim_switches & SWMASK ('O')) {
|
||||
for (i = 0; i < BOOT1_LEN; i++)
|
||||
M[(BOOT_START >> 1) + i] = boot1_rom[i]; }
|
||||
|
||||
369
PDP11/pdp11_tq.c
369
PDP11/pdp11_tq.c
@@ -25,6 +25,10 @@
|
||||
|
||||
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
|
||||
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_mscp.h"
|
||||
#include "sim_tape.h"
|
||||
|
||||
#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_MAXFR (1 << 16) /* max xfer */
|
||||
|
||||
#define UNIT_V_ONL (UNIT_V_UF + 0) /* online */
|
||||
#define UNIT_V_WLK (UNIT_V_UF + 1) /* hwre write lock */
|
||||
#define UNIT_V_ATP (UNIT_V_UF + 2) /* attn pending */
|
||||
#define UNIT_V_SXC (UNIT_V_UF + 3) /* serious exc */
|
||||
#define UNIT_V_POL (UNIT_V_UF + 4) /* position lost */
|
||||
#define UNIT_V_TMK (UNIT_V_UF + 5) /* tape mark seen */
|
||||
#define UNIT_V_ONL (MTUF_V_UF + 0) /* online */
|
||||
#define UNIT_V_ATP (MTUF_V_UF + 1) /* attn pending */
|
||||
#define UNIT_V_SXC (MTUF_V_UF + 2) /* serious exc */
|
||||
#define UNIT_V_POL (MTUF_V_UF + 3) /* position lost */
|
||||
#define UNIT_V_TMK (MTUF_V_UF + 4) /* tape mark seen */
|
||||
#define UNIT_ONL (1 << UNIT_V_ONL)
|
||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
||||
#define UNIT_ATP (1 << UNIT_V_ATP)
|
||||
#define UNIT_SXC (1 << UNIT_V_SXC)
|
||||
#define UNIT_POL (1 << UNIT_V_POL)
|
||||
@@ -76,8 +79,7 @@ extern int32 cpu_18b, cpu_ubm;
|
||||
#define pktq u4 /* packet queue */
|
||||
#define uf buf /* settable unit flags */
|
||||
#define objp wait /* object position */
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write prot */
|
||||
#define TQ_WPH(u) ((u->flags & UNIT_WPRT)? UF_WPH: 0)
|
||||
#define TQ_WPH(u) (sim_tape_wrp (u))
|
||||
|
||||
#define CST_S1 0 /* init stage 1 */
|
||||
#define CST_S1_WR 1 /* stage 1 wrap */
|
||||
@@ -153,12 +155,25 @@ struct tqpkt {
|
||||
#define TQ8_CAP (180 * (1 << 20)) /* capacity */
|
||||
#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) \
|
||||
d##_UQPM, \
|
||||
d##_CMOD, d##_MED, d##_FMT, d##_CAP, \
|
||||
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 {
|
||||
uint32 uqpm; /* UQ port model */
|
||||
@@ -170,12 +185,14 @@ struct drvtyp {
|
||||
uint32 cver;
|
||||
uint32 fver;
|
||||
uint32 uver;
|
||||
char *name;
|
||||
};
|
||||
|
||||
static struct drvtyp drv_tab[] = {
|
||||
{ TQ_DRV (TQ5) },
|
||||
{ TQ_DRV (TQ7) },
|
||||
{ TQ_DRV (TQ8) }
|
||||
{ TQ_DRV (TQ5), "TK50" },
|
||||
{ TQ_DRV (TQ7), "TK70" },
|
||||
{ TQ_DRV (TQ8), "TU81" },
|
||||
{ TQ_DRV (TQU), "TKUSER" },
|
||||
};
|
||||
|
||||
/* Data */
|
||||
@@ -208,16 +225,16 @@ int32 tq_itime = 200; /* init time, except */
|
||||
int32 tq_itime4 = 10; /* stage 4 */
|
||||
int32 tq_qtime = 200; /* queue time */
|
||||
int32 tq_xtime = 500; /* transfer time */
|
||||
int32 tq_typ = 0; /* device type */
|
||||
int32 tq_typ = TQ5_TYPE; /* device type */
|
||||
|
||||
/* Command table - legal modifiers (low 16b) and flags (high 16b) */
|
||||
|
||||
static uint32 tq_cmf[64] = {
|
||||
0, /* 0 */
|
||||
CMF_IMM, /* abort */
|
||||
CMF_IMM, /* get cmd status */
|
||||
CMF_IMM|MD_NXU, /* get unit status */
|
||||
CMF_IMM, /* set ctrl char */
|
||||
CMF_IMM|MD_CSE, /* get cmd status */
|
||||
CMF_IMM|MD_CSE|MD_NXU, /* get unit status */
|
||||
CMF_IMM|MD_CSE, /* set ctrl char */
|
||||
0, 0, 0, /* 5-7 */
|
||||
CMF_SEQ|MD_ACL|MD_CDL|MD_CSE|MD_EXA|MD_UNL, /* available */
|
||||
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_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_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_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_hbe (UNIT *uptr, uint32 ba);
|
||||
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_skipff (UNIT *uptr, uint32 cnt, uint32 *skipped);
|
||||
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_skipfr (UNIT *uptr, uint32 cnt, uint32 *skipped);
|
||||
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 (XTIME, tq_xtime, 24), PV_LEFT + REG_NZ },
|
||||
{ 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 (DEVVEC, tq_dib.vec, TQ_RDX, 16, 0), REG_HRO },
|
||||
{ NULL } };
|
||||
|
||||
MTAB tq_mod[] = {
|
||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
|
||||
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", 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,
|
||||
NULL, &tq_show_ctrl, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, TQ_SH_FR, "FREEQ", NULL,
|
||||
@@ -417,8 +446,8 @@ case 0: /* IP */
|
||||
*data = 0; /* reads zero */
|
||||
if (tq_csta == CST_S3_PPB) tq_step4 (); /* waiting for poll? */
|
||||
else if (tq_csta == CST_UP) { /* if up */
|
||||
tq_pip = 1; /* poll host */
|
||||
sim_activate (&tq_unit[TQ_QUEUE], tq_qtime); }
|
||||
tq_pip = 1; /* poll host */
|
||||
sim_activate (&tq_unit[TQ_QUEUE], tq_qtime); }
|
||||
break;
|
||||
case 1: /* SA */
|
||||
*data = tq_sa;
|
||||
@@ -431,7 +460,8 @@ t_stat tq_wr (int32 data, int32 PA, int32 access)
|
||||
switch ((PA >> 1) & 01) { /* decode PA<1> */
|
||||
case 0: /* IP */
|
||||
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;
|
||||
case 1: /* SA */
|
||||
tq_saw = data;
|
||||
@@ -476,9 +506,8 @@ return OK;
|
||||
queues, response queue) require servicing. Also invoked during
|
||||
initialization to provide some delay to the next step.
|
||||
|
||||
Process at most one item off the host queue
|
||||
If the host queue is empty, process at most one item off
|
||||
each unit queue
|
||||
Process at most one item off each unit queue
|
||||
If the unit queues were empty, process at most one item off the host queue
|
||||
Process at most one item off the response queue
|
||||
|
||||
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 */
|
||||
else {
|
||||
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_csta = CST_S2; /* now in step 2 */
|
||||
tq_init_int (); } /* intr if req */
|
||||
@@ -538,7 +568,12 @@ if (tq_csta < CST_UP) { /* still init? */
|
||||
break; } /* end switch */
|
||||
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 (pkt) { /* got one? */
|
||||
if (DBG_LOG (LOG_TQ)) {
|
||||
@@ -563,13 +598,6 @@ if (tq_pip) { /* polling? */
|
||||
} /* end if pkt */
|
||||
else tq_pip = 0; /* discontinue poll */
|
||||
} /* 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? */
|
||||
pkt = tq_deqh (&tq_rspq); /* get top of q */
|
||||
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 */
|
||||
else { /* valid cmd */
|
||||
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 */
|
||||
return OK; }
|
||||
/* 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? */
|
||||
else {
|
||||
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? */
|
||||
sts = ST_SUC; /* success */
|
||||
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? */
|
||||
sts = ST_SUC | SB_SUC_ON;
|
||||
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) &
|
||||
~(UNIT_TMK | UNIT_POL); /* onl, pos ok */
|
||||
tq_setf_unit (pkt, uptr); } /* hack flags */
|
||||
@@ -976,7 +1007,7 @@ return ST_SUC; /* success! */
|
||||
t_stat tq_svc (UNIT *uptr)
|
||||
{
|
||||
uint32 t, sts, sktmk, skrec;
|
||||
t_mtrlnt i, ebc, tbc, wbc;
|
||||
t_mtrlnt i, tbc, wbc;
|
||||
int32 pkt = uptr->cpkt; /* get packet */
|
||||
uint32 cmd = GETP (pkt, CMD_OPC, OPC); /* get cmd */
|
||||
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 */
|
||||
uint32 nrec = GETP32 (pkt, POS_RCL); /* #rec to skip */
|
||||
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 ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
|
||||
@@ -1052,19 +1081,13 @@ case OP_RD:case OP_ACC:case OP_CMP: /* read-like op */
|
||||
break;
|
||||
|
||||
case OP_WR: /* write */
|
||||
if (t = Map_ReadB (ba, bc, tqxb, MAP)) { /* fetch buf, nxm? */
|
||||
if (t = Map_ReadB (ba, bc, tqxb, MAP)) { /* fetch buf, nxm? */
|
||||
PUTP32 (pkt, RW_BCL, 0); /* no bytes xfer'd */
|
||||
if (tq_hbe (uptr, ba + bc - t)) /* post err log */
|
||||
tq_mot_end (uptr, EF_LOG, ST_HST | SB_HST_NXM, bc);
|
||||
return SCPE_OK; } /* end else wr */
|
||||
ebc = (bc + 1) & ~1; /* force even */
|
||||
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? */
|
||||
if (sim_tape_wrrecf (uptr, tqxb, bc)) /* write rec fwd, err? */
|
||||
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 */
|
||||
if (TEST_EOT (uptr)) /* EOT on write? */
|
||||
uptr->flags = uptr->flags | UNIT_SXC;
|
||||
@@ -1073,11 +1096,8 @@ case OP_WR: /* write */
|
||||
break;
|
||||
|
||||
case OP_WTM: /* write tape mark */
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set pos */
|
||||
fxwrite (&bceof, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
if (ferror (uptr->fileref)) /* error? */
|
||||
if (sim_tape_wrtmk (uptr)) /* write tmk, err? */
|
||||
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 */
|
||||
case OP_ERG: /* erase gap */
|
||||
if (TEST_EOT (uptr)) /* EOT on write? */
|
||||
@@ -1086,18 +1106,18 @@ case OP_ERG: /* erase gap */
|
||||
break;
|
||||
|
||||
case OP_ERS: /* erase */
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set pos */
|
||||
fxwrite (&bceom, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
if (ferror (uptr->fileref)) /* error? */
|
||||
return tq_mot_err (uptr, 0);
|
||||
uptr->pos = uptr->objp = 0; /* rewind */
|
||||
if (sim_tape_wreom (uptr)) /* write eom, err? */
|
||||
return tq_mot_err (uptr, 0); /* log, end */
|
||||
sim_tape_rewind (uptr); /* rewind */
|
||||
uptr->objp = 0;
|
||||
uptr->flags = uptr->flags & ~(UNIT_TMK | UNIT_POL);
|
||||
break;
|
||||
|
||||
case OP_POS: /* position */
|
||||
sktmk = skrec = 0; /* clr skipped */
|
||||
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); }
|
||||
if (mdf & MD_OBC) { /* skip obj? */
|
||||
if (mdf & MD_REV) /* reverse? */
|
||||
@@ -1161,43 +1181,63 @@ return OK;
|
||||
|
||||
/* 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 */
|
||||
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) || (*tbc == MTR_EOM)) { /* end of medium? */
|
||||
uptr->flags = uptr->flags | UNIT_SXC | UNIT_POL; /* ser exc, pos lost */
|
||||
return ST_DAT; }
|
||||
return 0;
|
||||
switch (st)
|
||||
{
|
||||
case MTSE_OK:
|
||||
break;
|
||||
case MTSE_UNATT:
|
||||
uptr->flags = uptr->flags | UNIT_SXC;
|
||||
return (ST_OFL | SB_OFL_NV);
|
||||
case MTSE_FMT:
|
||||
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 st;
|
||||
t_stat st;
|
||||
t_mtrlnt tbc;
|
||||
|
||||
*skipped = 0;
|
||||
while (*skipped < cnt) { /* loop */
|
||||
if (st = tq_rdlntf (uptr, &tbc)) return st; /* read rec lnt */
|
||||
uptr->objp = uptr->objp + 1; /* upd obj cnt */
|
||||
if (tbc == MTR_TMK) { /* tape mark? */
|
||||
int32 pkt = uptr->cpkt; /* get pkt */
|
||||
if ((tq_pkt[pkt].d[CMD_MOD] & MD_DLE) && /* LEOT? */
|
||||
(uptr->flags & UNIT_TMK)) {
|
||||
uptr->flags = uptr->flags | UNIT_SXC; /* serious exc */
|
||||
return ST_LED; } /* dont upd pos */
|
||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* update pos */
|
||||
uptr->flags = uptr->flags | UNIT_TMK; /* set TM seen */
|
||||
if (qrec) return ST_TMK; } /* rec spc? stop */
|
||||
else {
|
||||
uptr->pos = uptr->pos + ((MTRL (tbc) + 1) & ~1) +
|
||||
(2 * sizeof (t_mtrlnt)); /* update pos */
|
||||
uptr->flags = uptr->flags & ~UNIT_TMK; } /* clr TM seen */
|
||||
*skipped = *skipped + 1; } /* # rec skipped */
|
||||
return 0;
|
||||
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 */
|
||||
if (st == MTSE_TMK) { /* tape mark? */
|
||||
int32 pkt = uptr->cpkt; /* get pkt */
|
||||
if ((tq_pkt[pkt].d[CMD_MOD] & MD_DLE) && /* LEOT? */
|
||||
(uptr->flags & UNIT_TMK)) {
|
||||
sim_tape_sprecr (uptr, &tbc); /* rev over tmk */
|
||||
uptr->flags = uptr->flags | UNIT_SXC; /* serious exc */
|
||||
return ST_LED; }
|
||||
uptr->flags = uptr->flags | UNIT_TMK; /* set TM seen */
|
||||
if (qrec) return ST_TMK; } /* rec spc? stop */
|
||||
else uptr->flags = uptr->flags & ~UNIT_TMK; /* clr TM seen */
|
||||
*skipped = *skipped + 1; } /* # obj skipped */
|
||||
return ST_SUC;
|
||||
}
|
||||
|
||||
uint32 tq_skipff (UNIT *uptr, uint32 cnt, uint32 *skipped)
|
||||
@@ -1206,49 +1246,26 @@ uint32 st, skrec;
|
||||
|
||||
*skipped = 0;
|
||||
while (*skipped < cnt) { /* loop */
|
||||
st = tq_spacef (uptr, 0xFFFFFFFF, &skrec, TRUE); /* rec spc fwd */
|
||||
if (st == ST_TMK) *skipped = *skipped + 1; /* count files */
|
||||
else if (st != 0) return st; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
st = tq_spacef (uptr, INT_MAX, &skrec, TRUE); /* rec spc fwd */
|
||||
if (st == ST_TMK) *skipped = *skipped + 1; /* count files */
|
||||
else if (st != ST_SUC) return st; }
|
||||
return ST_SUC;
|
||||
}
|
||||
|
||||
uint32 tq_spacer (UNIT *uptr, uint32 cnt, uint32 *skipped, t_bool qrec)
|
||||
{
|
||||
uint32 st;
|
||||
t_stat st;
|
||||
t_mtrlnt tbc;
|
||||
|
||||
*skipped = 0;
|
||||
while (*skipped < cnt) { /* loop */
|
||||
if (st = tq_rdlntr (uptr, &tbc)) return st; /* read rec lnt */
|
||||
uptr->objp = uptr->objp - 1; /* upd obj cnt */
|
||||
if (tbc == MTR_TMK) { /* tape mark? */
|
||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* update pos */
|
||||
if (qrec) return ST_TMK; } /* recd spc? stop */
|
||||
else uptr->pos = uptr->pos - ((MTRL (tbc) + 1) & ~1) -
|
||||
(2 * sizeof (t_mtrlnt)); /* update pos */
|
||||
*skipped = *skipped + 1; } /* # rec skipped */
|
||||
return 0;
|
||||
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 */
|
||||
if ((st == MTSE_TMK) && qrec) return ST_TMK; /* tape mark, stop? */
|
||||
*skipped = *skipped + 1; } /* # obj skipped */
|
||||
return ST_SUC;
|
||||
}
|
||||
|
||||
uint32 tq_skipfr (UNIT *uptr, uint32 cnt, uint32 *skipped)
|
||||
@@ -1257,64 +1274,41 @@ uint32 st, skrec;
|
||||
|
||||
*skipped = 0;
|
||||
while (*skipped < cnt) { /* loopo */
|
||||
st = tq_spacer (uptr, 0xFFFFFFFF, &skrec, TRUE); /* rec spc rev */
|
||||
if (st == ST_TMK) *skipped = *skipped + 1; /* tape mark? */
|
||||
else if (st != 0) return st; } /* error? */
|
||||
return 0;
|
||||
st = tq_spacer (uptr, INT_MAX, &skrec, TRUE); /* rec spc rev */
|
||||
if (st == ST_TMK) *skipped = *skipped + 1; /* tape mark? */
|
||||
else if (st != 0) return st; } /* error? */
|
||||
return ST_SUC;
|
||||
}
|
||||
|
||||
/* Read buffer - can return ST_TMK, ST_FMT, or ST_DRV */
|
||||
|
||||
uint32 tq_rdbuff (UNIT *uptr, t_mtrlnt *tbc)
|
||||
{
|
||||
t_mtrlnt i;
|
||||
uint32 st;
|
||||
t_stat st;
|
||||
|
||||
if (st = tq_rdlntf (uptr, tbc)) return st; /* read rec lnt */
|
||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
||||
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 */
|
||||
return ST_TMK; }
|
||||
st = sim_tape_rdrecf (uptr, tqxb, tbc, MT_MAXFR); /* read rec fwd */
|
||||
if (st == MTSE_TMK) { /* tape mark? */
|
||||
uptr->flags = uptr->flags | UNIT_SXC | UNIT_TMK;/* serious exc */
|
||||
uptr->objp = uptr->objp + 1; /* update obj cnt */
|
||||
return ST_TMK; }
|
||||
if (st != MTSE_OK) return tq_map_status (uptr, st); /* other error? */
|
||||
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 */
|
||||
return 0;
|
||||
return ST_SUC;
|
||||
}
|
||||
|
||||
uint32 tq_rdbufr (UNIT *uptr, t_mtrlnt *tbc)
|
||||
{
|
||||
t_mtrlnt i;
|
||||
uint32 st;
|
||||
t_stat st;
|
||||
|
||||
if (st = tq_rdlntr (uptr, tbc)) return st; /* read rec lnt */
|
||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
||||
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 */
|
||||
return ST_TMK; }
|
||||
*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; }
|
||||
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));
|
||||
st = sim_tape_rdrecr (uptr, tqxb, tbc, MT_MAXFR); /* read rec rev */
|
||||
if (st == MTSE_TMK) { /* tape mark? */
|
||||
uptr->flags = uptr->flags | UNIT_SXC; /* serious exc */
|
||||
uptr->objp = uptr->objp - 1; /* update obj cnt */
|
||||
return ST_TMK; }
|
||||
if (st != MTSE_OK) return tq_map_status (uptr, st); /* other error? */
|
||||
uptr->objp = uptr->objp - 1; /* upd obj cnt */
|
||||
return 0;
|
||||
return ST_SUC;
|
||||
}
|
||||
|
||||
/* Data transfer error log packet */
|
||||
@@ -1671,21 +1665,13 @@ tq_perr = err; /* save error */
|
||||
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 */
|
||||
|
||||
t_stat tq_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
t_stat r;
|
||||
|
||||
r = attach_unit (uptr, cptr);
|
||||
r = sim_tape_attach (uptr, cptr);
|
||||
if (r != SCPE_OK) return r;
|
||||
if (tq_csta == CST_UP) uptr->flags = (uptr->flags | UNIT_ATP) &
|
||||
~(UNIT_SXC | UNIT_POL | UNIT_TMK);
|
||||
@@ -1698,7 +1684,7 @@ t_stat tq_detach (UNIT *uptr)
|
||||
{
|
||||
t_stat r;
|
||||
|
||||
r = detach_unit (uptr); /* detach unit */
|
||||
r = sim_tape_detach (uptr); /* detach unit */
|
||||
if (r != SCPE_OK) return r;
|
||||
uptr->flags = uptr->flags & ~(UNIT_ONL | UNIT_ATP | UNIT_SXC | UNIT_POL | UNIT_TMK);
|
||||
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 */
|
||||
uptr = tq_dev.units + i;
|
||||
sim_cancel (uptr); /* clr activity */
|
||||
sim_tape_reset (uptr);
|
||||
uptr->flags = uptr->flags & /* not online */
|
||||
~(UNIT_ONL|UNIT_ATP|UNIT_SXC|UNIT_POL|UNIT_TMK);
|
||||
uptr->uf = 0; /* clr unit flags */
|
||||
@@ -1984,3 +1971,31 @@ if (val & TQ_SH_UN) {
|
||||
}
|
||||
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
|
||||
|
||||
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
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
ts TS11/TSV05 magtape
|
||||
|
||||
28-Feb-03 RMS Revised to use magtape library
|
||||
30-Sep-02 RMS Added variable address support to bootstrap
|
||||
Added vector change/display support
|
||||
Fixed CTL unload/clean decode
|
||||
@@ -99,9 +100,7 @@ extern int32 cpu_18b, cpu_ubm;
|
||||
#define WriteW(p,v) M[(p) >> 1] = (v)
|
||||
#endif
|
||||
|
||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
#include "sim_tape.h"
|
||||
|
||||
/* TSBA/TSDB - 17772520: base address/data buffer register
|
||||
|
||||
@@ -296,6 +295,7 @@ int32 ts_updtssr (int32 t);
|
||||
int32 ts_updxs0 (int32 t);
|
||||
void ts_cmpendcmd (int32 s0, int32 s1);
|
||||
void ts_endcmd (int32 ssf, int32 xs0f, int32 msg);
|
||||
int32 ts_map_status (t_stat st);
|
||||
|
||||
/* TS data structures
|
||||
|
||||
@@ -342,8 +342,8 @@ REG ts_reg[] = {
|
||||
{ NULL } };
|
||||
|
||||
MTAB ts_mod[] = {
|
||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
|
||||
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 004, "ADDRESS", "ADDRESS",
|
||||
&set_addr, &show_addr, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR",
|
||||
@@ -422,32 +422,44 @@ return SCPE_OK;
|
||||
#define GET_X(x) (((x) >> 16) & 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 */
|
||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref); /* read rec lnt */
|
||||
if (ferror (uptr->fileref)) { /* error? */
|
||||
switch (st) {
|
||||
case MTSE_OK:
|
||||
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 */
|
||||
return (XTC (XS0_RLS, TC6)); } /* pos lost */
|
||||
if (feof (uptr->fileref) || (*tbc == MTR_EOM)) { /* end of medium? */
|
||||
return (XTC (XS0_RLS, TC6)); /* pos lost */
|
||||
case MTSE_FMT:
|
||||
case MTSE_UNATT:
|
||||
case MTSE_EOM: /* end of medium */
|
||||
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;
|
||||
}
|
||||
|
||||
int32 ts_spacef (UNIT *uptr, int32 fc, t_bool upd)
|
||||
{
|
||||
int32 st;
|
||||
t_stat st;
|
||||
t_mtrlnt tbc;
|
||||
|
||||
do { fc = (fc - 1) & DMASK; /* decr wc */
|
||||
if (upd) msgrfc = fc;
|
||||
if (st = ts_rdlntf (uptr, &tbc)) return st; /* read rec lnt */
|
||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* update pos */
|
||||
if (st = sim_tape_sprecf (uptr, &tbc)) /* space rec fwd, err? */
|
||||
return ts_map_status (st); /* map status */
|
||||
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);
|
||||
return 0;
|
||||
@@ -455,63 +467,38 @@ return 0;
|
||||
|
||||
int32 ts_skipf (UNIT *uptr, int32 fc)
|
||||
{
|
||||
int32 tc;
|
||||
t_mtrlnt prvp;
|
||||
t_stat st;
|
||||
t_mtrlnt tbc;
|
||||
t_bool tmkprv = FALSE;
|
||||
|
||||
msgrfc = fc;
|
||||
if ((uptr->pos == 0) && (wchopt & WCH_ENB)) tmkprv = TRUE;
|
||||
do { prvp = uptr->pos; /* save cur pos */
|
||||
tc = ts_spacef (uptr, 0, FALSE); /* space fwd */
|
||||
if (GET_X (tc) & XS0_TMK) { /* tape mark? */
|
||||
if (sim_tape_bot (uptr) && (wchopt & WCH_ENB)) tmkprv = TRUE;
|
||||
do { st = sim_tape_sprecf (uptr, &tbc); /* space rec fwd */
|
||||
if (st == MTSE_TMK) { /* tape mark? */
|
||||
msgrfc = (msgrfc - 1) & DMASK; /* decr count */
|
||||
if (tmkprv && (wchopt & WCH_ESS) &&
|
||||
(uptr->pos - prvp == sizeof (t_mtrlnt)))
|
||||
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
||||
if (tmkprv && (wchopt & WCH_ESS)) /* 2nd tmk & ESS? */
|
||||
return (XTC ((msgrfc? XS0_RLS: 0) |
|
||||
XS0_TMK | XS0_LET, TC2));
|
||||
tmkprv = TRUE; }
|
||||
else {
|
||||
if (tc) return tc; /* other err? */
|
||||
tmkprv = FALSE; } }
|
||||
tmkprv = TRUE; } /* flag tmk */
|
||||
else if (st != MTSE_OK) return ts_map_status (st);
|
||||
else tmkprv = FALSE; /* not a tmk */
|
||||
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
||||
}
|
||||
while (msgrfc != 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 st;
|
||||
t_mtrlnt tbc;
|
||||
|
||||
if (upd) msgrfc = fc;
|
||||
do { fc = (fc - 1) & DMASK; /* decr wc */
|
||||
if (upd) msgrfc = fc;
|
||||
if (st = ts_rdlntr (uptr, &tbc)) return st; /* read rec lnt */
|
||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* update pos */
|
||||
if (st = sim_tape_sprecr (uptr, &tbc)) /* space rec rev, err? */
|
||||
return ts_map_status (st); /* map status */
|
||||
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);
|
||||
return 0;
|
||||
@@ -519,52 +506,39 @@ return 0;
|
||||
|
||||
int32 ts_skipr (UNIT *uptr, int32 fc)
|
||||
{
|
||||
int32 tc;
|
||||
t_mtrlnt prvp;
|
||||
t_stat st;
|
||||
t_mtrlnt tbc;
|
||||
t_bool tmkprv = FALSE;
|
||||
|
||||
msgrfc = fc;
|
||||
do { prvp = uptr->pos; /* save cur pos */
|
||||
tc = ts_spacer (uptr, 0, FALSE); /* space rev */
|
||||
if (GET_X (tc) & XS0_TMK) { /* tape mark? */
|
||||
msgrfc = (msgrfc - 1) & DMASK; /* decr wc */
|
||||
if (tmkprv && (wchopt & WCH_ESS) &&
|
||||
(prvp - uptr->pos == sizeof (t_mtrlnt)))
|
||||
do { st = sim_tape_sprecr (uptr, &tbc); /* space rec rev */
|
||||
if (st == MTSE_TMK) { /* tape mark? */
|
||||
msgrfc = (msgrfc - 1) & DMASK; /* decr count */
|
||||
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
||||
if (tmkprv && (wchopt & WCH_ESS)) /* 2nd tmk & ESS? */
|
||||
return (XTC ((msgrfc? XS0_RLS: 0) |
|
||||
XS0_TMK | XS0_LET, TC2));
|
||||
tmkprv = TRUE; }
|
||||
else {
|
||||
if (tc) return tc; /* other err? */
|
||||
tmkprv = FALSE; } }
|
||||
tmkprv = TRUE; } /* flag tmk */
|
||||
else if (st != MTSE_OK) return ts_map_status (st);
|
||||
else tmkprv = FALSE; /* not a tmk */
|
||||
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
||||
}
|
||||
while (msgrfc != 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32 ts_readf (UNIT *uptr, uint32 fc)
|
||||
{
|
||||
int32 st;
|
||||
t_stat st;
|
||||
t_mtrlnt i, tbc, wbc;
|
||||
t_addr wa, pa;
|
||||
|
||||
msgrfc = fc;
|
||||
if (st = ts_rdlntf (uptr, &tbc)) return st; /* read rec lnt */
|
||||
if (tbc == MTR_TMK) { /* tape mark? */
|
||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* update pos */
|
||||
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
||||
return (XTC (XS0_TMK | XS0_RLS, TC2)); }
|
||||
st = sim_tape_rdrecf (uptr, tsxb, &tbc, MT_MAXFR); /* read rec fwd */
|
||||
if (st != MTSE_OK) return ts_map_status (st); /* error? */
|
||||
if (fc == 0) fc = 0200000; /* byte count */
|
||||
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 */
|
||||
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 */
|
||||
for (i = 0; i < wbc; i++) { /* copy buffer */
|
||||
wa = (cmdhdr & CMD_SWP)? tsba ^ 1: tsba; /* apply OPP */
|
||||
@@ -582,30 +556,16 @@ return 0;
|
||||
|
||||
int32 ts_readr (UNIT *uptr, uint32 fc)
|
||||
{
|
||||
int32 st;
|
||||
t_stat st;
|
||||
t_mtrlnt i, tbc, wbc;
|
||||
t_addr wa, pa;
|
||||
|
||||
msgrfc = fc;
|
||||
if (st = ts_rdlntr (uptr, &tbc)) return st; /* read rec lnt */
|
||||
if (tbc == MTR_TMK) { /* tape mark? */
|
||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* update pos */
|
||||
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
||||
return XTC (XS0_TMK | XS0_RLS, TC2); }
|
||||
st = sim_tape_rdrecr (uptr, tsxb, &tbc, MT_MAXFR); /* read rec rev */
|
||||
if (st != MTSE_OK) return ts_map_status (st); /* error? */
|
||||
if (fc == 0) fc = 0200000; /* byte count */
|
||||
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 */
|
||||
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 */
|
||||
for (i = wbc; i > 0; i--) { /* copy buffer */
|
||||
tsba = tsba - 1;
|
||||
@@ -623,8 +583,9 @@ return 0;
|
||||
|
||||
int32 ts_write (UNIT *uptr, int32 fc)
|
||||
{
|
||||
int32 i, ebc;
|
||||
int32 i;
|
||||
t_addr wa, pa;
|
||||
t_stat st;
|
||||
|
||||
msgrfc = fc;
|
||||
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);
|
||||
return TC5; }
|
||||
tsba = tsba + 1; }
|
||||
ebc = (fc + 1) & ~1; /* force even */
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* position */
|
||||
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 */
|
||||
if (st = sim_tape_wrrecf (uptr, tsxb, fc)) /* write rec, err? */
|
||||
return ts_map_status (st); /* return status */
|
||||
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
||||
msgrfc = 0;
|
||||
return 0;
|
||||
@@ -653,12 +607,10 @@ return 0;
|
||||
|
||||
int32 ts_wtmk (UNIT *uptr)
|
||||
{
|
||||
t_mtrlnt bceof = MTR_TMK;
|
||||
t_stat st;
|
||||
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set pos */
|
||||
fxwrite (&bceof, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
if (ferror (uptr->fileref)) return TC6;
|
||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* update position */
|
||||
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
|
||||
return ts_map_status (st); /* return status */
|
||||
msgxs0 = msgxs0 | XS0_MOT; /* tape has moved */
|
||||
return XTC (XS0_TMK, TC0);
|
||||
}
|
||||
@@ -683,7 +635,7 @@ static const int32 fnc_flg[CMD_N_FNC] = {
|
||||
|
||||
if (ts_bcmd) { /* boot? */
|
||||
ts_bcmd = 0; /* clear flag */
|
||||
uptr->pos = 0; /* rewind */
|
||||
sim_tape_rewind (uptr); /* rewind */
|
||||
if (uptr->flags & UNIT_ATT) { /* attached? */
|
||||
cmdlnt = cmdadh = cmdadl = 0; /* defang rd */
|
||||
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);
|
||||
return SCPE_OK; }
|
||||
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);
|
||||
return SCPE_OK; }
|
||||
if ((((fnc == FNC_READ) && (mod == 1)) || /* read 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);
|
||||
return SCPE_OK; }
|
||||
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;
|
||||
switch (fnc) { /* case on func */
|
||||
case FNC_INIT: /* init */
|
||||
if (uptr->pos) msgxs0 = msgxs0 | XS0_MOT; /* set if tape moves */
|
||||
uptr->pos = 0; /* rewind */
|
||||
if (!sim_tape_bot (uptr)) msgxs0 = msgxs0 | XS0_MOT; /* set if tape moves */
|
||||
sim_tape_rewind (uptr); /* rewind */
|
||||
case FNC_WSSM: /* write mem */
|
||||
case FNC_GSTA: /* get status */
|
||||
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 */
|
||||
break;
|
||||
case 01: /* rewind and unload */
|
||||
if (uptr->pos) msgxs0 = msgxs0 | XS0_MOT; /* if tape moves */
|
||||
detach_unit (uptr); /* unload */
|
||||
if (!sim_tape_bot (uptr)) msgxs0 = msgxs0 | XS0_MOT; /* if tape moves */
|
||||
sim_tape_detach (uptr); /* unload */
|
||||
ts_endcmd (TC0, 0, MSG_ACK | MSG_CEND);
|
||||
break;
|
||||
case 02: /* clean */
|
||||
@@ -780,8 +732,8 @@ case FNC_CTL: /* control */
|
||||
ts_endcmd (TC3, XS0_ILC, MSG_ACK | MSG_MILL | MSG_CFAIL);
|
||||
return SCPE_OK;
|
||||
case 04: /* rewind */
|
||||
if (uptr->pos) msgxs0 = msgxs0 | XS0_MOT; /* if tape moves */
|
||||
uptr->pos = 0;
|
||||
if (!sim_tape_bot (uptr)) msgxs0 = msgxs0 | XS0_MOT; /* if tape moves */
|
||||
sim_tape_rewind (uptr);
|
||||
ts_endcmd (TC0, XS0_BOT, MSG_ACK | MSG_CEND);
|
||||
break; }
|
||||
break;
|
||||
@@ -851,8 +803,8 @@ case FNC_POS:
|
||||
st0 = ts_skipr (uptr, cmdadl);
|
||||
break;
|
||||
case 04: /* rewind */
|
||||
if (uptr->pos) msgxs0 = msgxs0 | XS0_MOT; /* if tape moves */
|
||||
uptr->pos = 0;
|
||||
if (!sim_tape_bot (uptr)) msgxs0 = msgxs0 | XS0_MOT; /* if tape moves */
|
||||
sim_tape_rewind (uptr);
|
||||
break; }
|
||||
ts_cmpendcmd (st0, 0);
|
||||
break; }
|
||||
@@ -874,8 +826,8 @@ int32 ts_updxs0 (int32 t)
|
||||
t = (t & ~(XS0_ONL | XS0_WLK | XS0_BOT | XS0_IE)) | XS0_PET;
|
||||
if (ts_unit.flags & UNIT_ATT) {
|
||||
t = t | XS0_ONL;
|
||||
if (ts_unit.flags & UNIT_WPRT) t = t | XS0_WLK;
|
||||
if (ts_unit.pos == 0) t = (t | XS0_BOT) & ~XS0_EOT; }
|
||||
if (sim_tape_wrp (&ts_unit)) t = t | XS0_WLK;
|
||||
if (sim_tape_bot (&ts_unit)) t = (t | XS0_BOT) & ~XS0_EOT; }
|
||||
else t = t & ~XS0_EOT;
|
||||
if (cmdhdr & CMD_IE) t = t | XS0_IE;
|
||||
return t;
|
||||
@@ -933,7 +885,7 @@ t_stat ts_reset (DEVICE *dptr)
|
||||
{
|
||||
int32 i;
|
||||
|
||||
ts_unit.pos = 0;
|
||||
sim_tape_rewind (&ts_unit);
|
||||
tsba = tsdbx = 0;
|
||||
ts_ownc = ts_ownm = 0;
|
||||
ts_bcmd = 0;
|
||||
@@ -955,7 +907,7 @@ t_stat ts_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
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? */
|
||||
tssr = tssr & ~TSSR_OFL; /* clr offline */
|
||||
if ((tssr & TSSR_NBA) || !(wchopt & WCH_EAI)) return r; /* attn msg? */
|
||||
@@ -973,7 +925,7 @@ t_stat ts_detach (UNIT* uptr)
|
||||
{
|
||||
t_stat r;
|
||||
|
||||
r = detach_unit (uptr); /* detach unit */
|
||||
r = sim_tape_detach (uptr); /* detach unit */
|
||||
if (r != SCPE_OK) return r; /* error? */
|
||||
tssr = tssr | TSSR_OFL; /* set offline */
|
||||
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;
|
||||
extern int32 saved_PC;
|
||||
|
||||
ts_unit.pos = 0;
|
||||
sim_tape_rewind (&ts_unit);
|
||||
for (i = 0; i < BOOT_LEN; i++)
|
||||
M[(BOOT_START >> 1) + i] = boot_rom[i];
|
||||
M[BOOT_CSR0 >> 1] = ts_dib.ba & DMASK;
|
||||
|
||||
Reference in New Issue
Block a user