Notes For V2.10-4
1. New Features in 2.10-4 1.1 SCP and Libraries - Added .ini startup file capability (suggested by Hans Pufal). - Added multiple switch evaluation points (suggested by Hans Pufal). - Added multiple command per action. - Added new library, sim_tape.c, for magtape emulation. 1.2 PDP-11 - Added user-defined disk capacity to RQ. - Addec choice of controllers to TQ. - Added user-defined tape capacity to TQ. 1.3 Interdata - Added SHOW SELCH n command to display selector channel state. 1.4 Line Frequency Clocks (H316, Interdata, Nova, PDP-8, PDP-11, PDP-18B, SDS) - Added SET <device> {50HZ/60HZ}, to set the line frequency. 1.5 DEC Console Input (PDP-8, PDP-11, PDP-18B, VAX) - Added SET TTI CTRL-C, to generate ^C from SIMH prompt (^C crashes simulators compiled with Windows Visual C++). 1.6 Magtapes - Revised to use magtape library for consistency. 2. Bugs Fixed in 2.10-4 - SCP: fixed bug in multiword deposits to files - Interdata disks: fixed bug in cylinder overflow on writes - Interdata tape: fixed bug, read error did not stop selector channel - Interdata precision clock: improved autocalibrate algorithm for UNIX V7. - Nova fixed head disk: fixed autosize algorithm. - PDP-11 RQ and TQ: fixed bugs in queue process and in vector calculation for VAXen. - PDP-11 TQ: fixed overly strict implementation of illegal modifiers check. - PDP-11 RY: fixed autosize algorithm. - PDP-18B CPU: fixed three EAE bugs (found by Hans Pufal). - PDP-18B MT: fixed bugs in interrupt handling, BOT error handling. - PDP-18B RF: removed extra bit from disk address, fixed autosize algorithm. - PDP-18B SYS: fixed bug in FMTASC usage (found by Hans Pufal). - PDP-8 MT: fixed bug in BOT error handling. - PDP-8 DF, RF, RX: fixed autosize algorithm. 3. New Features in 2.10 vs prior releases 3.1 SCP and Libraries - The VT emulation package has been replaced by the capability to remote the console to a Telnet session. Telnet clients typically have more complete and robust VT100 emulation. - Simulated devices may now have statically allocated buffers, in addition to dynamically allocated buffers or disk-based data stores. - The DO command now takes substitutable arguments (max 9). In command files, %n represents substitutable argument n. - The initial command line is now interpreted as the command name and substitutable arguments for a DO command. This is backward compatible to prior versions. - The initial command line parses switches. -Q is interpreted as quiet mode; informational messages are suppressed. - The HELP command now takes an optional argument. HELP <cmd> types help on the specified command. - Hooks have been added for implementing GUI-based consoles, as well as simulator-specific command extensions. A few internal data structures and definitions have changed. - Two new routines (tmxr_open_master, tmxr_close_master) have been added to sim_tmxr.c. The calling sequence for sim_accept_conn has been changed in sim_sock.c. - The calling sequence for the VM boot routine has been modified to add an additional parameter. - SAVE now saves, and GET now restores, controller and unit flags. - Library sim_ether.c has been added for Ethernet support. - The EVAL command will evaluate a symbolic type-in and display it in numeric form. - The ! command (with no arguments) will launch the host operating system command shell. The ! command (with an argument) executes the argument as a host operating system command. (Code from Mark Pizzolato) - Telnet sessions now recognize BREAK. How a BREAK is transmitted dependent on the particular Telnet client. (Code from Mark Pizzolato) - The sockets library includes code for active connections as well as listening connections. - The RESTORE command will restore saved memory size, if the simulator supports dynamic memory resizing. - Added dynamic extension of the breakpoint table. - Added breakpoint actions. - Added VMS support for ! (from Mark Pizzolato). 3.2 VAX - Non-volatile RAM (NVR) can behave either like a memory or like a disk-based peripheral. If unattached, it behaves like memory and is saved and restored by SAVE and RESTORE, respectively. If attached, its contents are loaded from disk by ATTACH and written back to disk at DETACH and EXIT. - SHOW <device> VECTOR displays the device's interrupt vector. A few devices allow the vector to be changed with SET <device> VECTOR=nnn. - SHOW CPU IOSPACE displays the I/O space address map. - The TK50 (TMSCP tape) has been added. - The DEQNA/DELQA (Qbus Ethernet controllers) have been added. - Autoconfiguration support has been added. - The paper tape reader has been removed from vax_stddev.c and now references a common implementation file, dec_pt.h. - Examine and deposit switches now work on all devices, not just the CPU. - Device address conflicts are not detected until simulation starts. - If the VAX console is attached to a Telnet session, BREAK is interpreted as console halt. - The SET/SHOW HISTORY commands enable and display a history of the most recently executed instructions. (Code from Mark Pizzolato) 3.3 PDP-11 - SHOW <device> VECTOR displays the device's interrupt vector. Most devices allow the vector to be changed with SET <device> VECTOR=nnn. - SHOW CPU IOSPACE displays the I/O space address map. - The TK50 (TMSCP tape), RK611/RK06/RK07 (cartridge disk), RX211 (double density floppy), and KW11P programmable clock have been added. - The DEQNA/DELQA (Qbus Ethernet controllers) have been added. - Autoconfiguration support has been added. - The paper tape reader has been removed from pdp11_stddev.c and now references a common implementation file, dec_pt.h. - Device bootstraps now use the actual CSR specified by the SET ADDRESS command, rather than just the default CSR. Note that PDP-11 operating systems may NOT support booting with non-standard addresses. - Specifying more than 256KB of memory, or changing the bus configuration, causes all peripherals that are not compatible with the current bus configuration to be disabled. - Device address conflicts are not detected until simulation starts. - The PDP-11 implements a stub DEUNA/DELUA (XU). The real XU module will be included in a later release. 3.4 PDP-10 - SHOW <device> VECTOR displays the device's interrupt vector. A few devices allow the vector to be changed with SET <device> VECTOR=nnn. - SHOW CPU IOSPACE displays the I/O space address map. - The RX211 (double density floppy) has been added; it is off by default. - The paper tape now references a common implementation file, dec_pt.h. - Device address conflicts are not detected until simulation starts. - The PDP-10 implements a stub DEUNA/DELUA (XU). The real XU module will be included in a later release. 3.5 PDP-1 - DECtape (then known as MicroTape) support has been added. - The line printer and DECtape can be disabled and enabled. - The PDP-1 supports the Type 24 serial drum (based on recently discovered documents). 3.6 18b PDP's - The PDP-4 supports the Type 24 serial drum (based on recently discovered documents). - Added RB09 fixed head disk for the PDP-9. - Added LP09 line printer for the PDP-9 and PDP-15. - Added variable size support and autosizing to the RF15/RF09. 3.7 PDP-8 - The RX28 (double density floppy) has been added as an option to the existing RX8E controller. - SHOW <device> DEVNO displays the device's device number. Most devices allow the device number to be changed with SET <device> DEVNO=nnn. - Device number conflicts are not detected until simulation starts. - Added variable size support and autosizing to the DF32 and RF08. 3.8 Nova - Added variable size support and autosizing to the Novadisk. 3.9 AltairZ80 - A hard drive has been added for increased storage. - Several bugs have been fixed. 3.10 HP 2100 - The 12845A has been added and made the default line printer (LPT). The 12653A has been renamed LPS and is off by default. It also supports the diagnostic functions needed to run the DCPC and DMS diagnostics. - The 12557A/13210A disk defaults to the 13210A (7900/7901). - The 12559A magtape is off by default. - New CPU options (EAU/NOEAU) enable/disable the extended arithmetic instructions for the 2116. These instructions are standard on the 2100 and 21MX. - New CPU options (MPR/NOMPR) enable/disable memory protect for the 2100 and 21MX. - New CPU options (DMS/NODMS) enable/disable the dynamic mapping instructions for the 21MX. - The 12539 timebase generator autocalibrates. - The IOP microinstruction set is supported for the 21MX as well as the 2100. - The HP2100 supports the Access Interprocessor Link (IPL). 3.11 Simulated Magtapes - Simulated magtapes recognize end of file and the marker 0xFFFFFFFF as end of medium. Only the TMSCP tape simulator can generate an end of medium marker. - The error handling in simulated magtapes was overhauled to be consistent through all simulators. 3.12 Simulated DECtapes - Added support for RT11 image file format (256 x 16b) to DECtapes. 3.13 Terminals Multiplexors - BREAK detection was added to the HP, DEC, and Interdata terminal multiplexors. 4. Bugs Fixed in 2.10 vs prior releases - TS11/TSV05 was not simulating the XS0_MOT bit, causing failures under VMS. In addition, two of the CTL options were coded interchanged. - IBM 1401 tape was not setting a word mark under group mark for load mode reads. This caused the diagnostics to crash. - SCP bugs in ssh_break and set_logon were fixed (found by Dave Hittner). - Numerous bugs in the HP 2100 extended arithmetic, floating point, 21MX, DMS, and IOP instructions were fixed. Bugs were also fixed in the memory protect and DMS functions. The moving head disks (DP, DQ) were revised to simulate the hardware more accurately. Missing functions in DQ (address skip, read address) were added. - PDP-10 tape wouldn't boot, and then wouldn't read (reported by Michael Thompson and Harris Newman, respectively) - PDP-1 typewriter is half duplex, with only one shift state for both input and output (found by Derek Peschel) - PDP-11 console must default to 7b for early UNIX compatibility. - PDP-11/VAX TMSCP emulator was using the wrong packet length for read/write end packets. - Telnet IAC+IAC processing was fixed, both for input and output (found by Mark Pizzolato). - PDP-11/VAX Ethernet setting flag bits wrong for chained descriptors (found by Mark Pizzolato). - 18b PDP RF15/RF09: fixed IOT decoding and address wraparound logic (found by Hans Pufal). - 18b PDP RP15: fixed IOT decoding and command initiation. - HP2100 IPL: changed to full duplex (found by Mike Gemeny). - HP2100 CPU: fixed last cycle bug in DMA outpout (found by Mike Gemeny). - Interdata 16b CPU: fixed bug in SETM, SETMR (found by Mark Pizzolato). 5. General Notes WARNING: The build procedures have changed. There is only one UNIX makefile. To compile without Ethernet support, simply type gmake {target|all} To compile with Ethernet support, type gmake USE_NETWORK=1 {target|all} The Mingw batch files require Mingw release 2 and invoke the Unix makefile. There are still separate batch files for compilation with or without Ethernet support. WARNING: V2.10 has reorganized and renamed some of the definition files for the PDP-10, PDP-11, and VAX. Be sure to delete all previous source files before you unpack the Zip archive, or unpack it into a new directory structure. WARNING: V2.10 has a new, more comprehensive save file format. Restoring save files from previous releases will cause 'invalid register' errors and loss of CPU option flags, device enable/ disable flags, unit online/offline flags, and unit writelock flags. WARNING: If you are using Visual Studio .NET through the IDE, be sure to turn off the /Wp64 flag in the project settings, or dozens of spurious errors will be generated. WARNING: Compiling Ethernet support under Windows requires extra steps; see the Ethernet readme file. Ethernet support is currently available only for Windows, Linux, NetBSD, and OpenBSD.
This commit is contained in:
parent
f20f5c629d
commit
43385c9616
72 changed files with 3065 additions and 2189 deletions
|
@ -1,37 +1,59 @@
|
|||
Notes For V2.10-3
|
||||
Notes For V2.10-4
|
||||
|
||||
1. New Features in 2.10-3
|
||||
1. New Features in 2.10-4
|
||||
|
||||
1.1 SCP and Libraries
|
||||
|
||||
- Added dynamic extension of the breakpoint table.
|
||||
- Added breakpoint actions.
|
||||
- Added VMS support for ! (from Mark Pizzolato).
|
||||
- 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 18b PDP's
|
||||
1.2 PDP-11
|
||||
|
||||
- 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.
|
||||
- Added user-defined disk capacity to RQ.
|
||||
- Addec choice of controllers to TQ.
|
||||
- Added user-defined tape capacity to TQ.
|
||||
|
||||
1.3 PDP-8
|
||||
1.3 Interdata
|
||||
|
||||
- Added variable size support and autosizing to the DF32 and RF08.
|
||||
- Added SHOW SELCH n command to display selector channel state.
|
||||
|
||||
1.4 Nova
|
||||
1.4 Line Frequency Clocks (H316, Interdata, Nova, PDP-8, PDP-11,
|
||||
PDP-18B, SDS)
|
||||
|
||||
- Added variable size support and autosizing to the Novadisk.
|
||||
- Added SET <device> {50HZ/60HZ}, to set the line frequency.
|
||||
|
||||
2. Bugs Fixed in 2.10-3
|
||||
1.5 DEC Console Input (PDP-8, PDP-11, PDP-18B, VAX)
|
||||
|
||||
- 18b PDP RF15/RF09: fixed IOT decoding and address wraparound
|
||||
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).
|
||||
- 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
|
||||
|
||||
|
@ -75,6 +97,9 @@ Notes For V2.10-3
|
|||
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
|
||||
|
||||
|
@ -150,6 +175,9 @@ Notes For V2.10-3
|
|||
|
||||
- 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
|
||||
|
||||
|
@ -159,13 +187,18 @@ Notes For V2.10-3
|
|||
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 AltairZ80
|
||||
3.8 Nova
|
||||
|
||||
- Added variable size support and autosizing to the Novadisk.
|
||||
|
||||
3.9 AltairZ80
|
||||
|
||||
- A hard drive has been added for increased storage.
|
||||
- Several bugs have been fixed.
|
||||
|
||||
3.9 HP 2100
|
||||
3.10 HP 2100
|
||||
|
||||
- The 12845A has been added and made the default line printer (LPT).
|
||||
The 12653A has been renamed LPS and is off by default. It also
|
||||
|
@ -185,7 +218,7 @@ Notes For V2.10-3
|
|||
as the 2100.
|
||||
- The HP2100 supports the Access Interprocessor Link (IPL).
|
||||
|
||||
3.10 Simulated Magtapes
|
||||
3.11 Simulated Magtapes
|
||||
|
||||
- Simulated magtapes recognize end of file and the marker
|
||||
0xFFFFFFFF as end of medium. Only the TMSCP tape simulator
|
||||
|
@ -193,11 +226,11 @@ Notes For V2.10-3
|
|||
- The error handling in simulated magtapes was overhauled to be
|
||||
consistent through all simulators.
|
||||
|
||||
3.11 Simulated DECtapes
|
||||
3.12 Simulated DECtapes
|
||||
|
||||
- Added support for RT11 image file format (256 x 16b) to DECtapes.
|
||||
|
||||
3.12 Terminals Multiplexors
|
||||
3.13 Terminals Multiplexors
|
||||
|
||||
- BREAK detection was added to the HP, DEC, and Interdata terminal
|
||||
multiplexors.
|
||||
|
@ -227,6 +260,15 @@ Notes For V2.10-3
|
|||
(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
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
To: Users
|
||||
From: Bob Supnik
|
||||
Subj: H316 Simulator Usage
|
||||
Date: 15-Nov-2002
|
||||
Date: 15-Mar-2003
|
||||
|
||||
COPYRIGHT NOTICE
|
||||
|
||||
The following copyright notice applies to both the SIMH source and binary:
|
||||
|
||||
Original code published in 1993-2002, written by Robert M Supnik
|
||||
Copyright (c) 1993-2002, Robert M Supnik
|
||||
Original code published in 1993-2003, written by 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"),
|
||||
|
@ -211,7 +211,14 @@ simulator console window. It implements these registers:
|
|||
|
||||
2.2.4 316/516-12 Real Time Clock (CLK)
|
||||
|
||||
The real time clock (CLK) implements these registers:
|
||||
The real time clock (CLK) frequency can be adjusted as follows:
|
||||
|
||||
SET CLK 60HZ set frequency to 60Hz
|
||||
SET CLK 50HZ set frequency to 50Hz
|
||||
|
||||
The default is 60Hz.
|
||||
|
||||
The clock implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* h316_stddev.c: Honeywell 316/516 standard devices
|
||||
|
||||
Copyright (c) 1999-2002, Robert M. Supnik
|
||||
Copyright (c) 1999-2003, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -28,6 +28,7 @@
|
|||
tty 316/516-33 teleprinter
|
||||
clk/options 316/516-12 real time clocks/internal options
|
||||
|
||||
01-Mar-03 RMS Added SET/SHOW CLK FREQ support
|
||||
22-Dec-02 RMS Added break support
|
||||
01-Nov-02 RMS Added 7b/8b support to terminal
|
||||
30-May-02 RMS Widened POS to 32b
|
||||
|
@ -54,7 +55,7 @@ extern UNIT cpu_unit;
|
|||
int32 ptr_stopioe = 0, ptp_stopioe = 0; /* stop on error */
|
||||
int32 ptp_power = 0, ptp_ptime; /* punch power, time */
|
||||
int32 tty_mode = 0, tty_buf = 0; /* tty mode, buf */
|
||||
int32 clk_tps = 60; /* ticks per second */
|
||||
int32 clk_tps = 60; /* ticks per second */
|
||||
|
||||
t_stat ptr_svc (UNIT *uptr);
|
||||
t_stat ptr_reset (DEVICE *dptr);
|
||||
|
@ -67,6 +68,8 @@ t_stat tty_reset (DEVICE *dptr);
|
|||
t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat 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);
|
||||
|
||||
/* PTR data structures
|
||||
|
||||
|
@ -177,11 +180,20 @@ REG clk_reg[] = {
|
|||
{ FLDATA (READY, dev_ready, INT_V_CLK) },
|
||||
{ FLDATA (ENABLE, dev_enable, INT_V_CLK) },
|
||||
{ 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 },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE clk_dev = {
|
||||
"CLK", &clk_unit, clk_reg, NULL,
|
||||
"CLK", &clk_unit, clk_reg, clk_mod,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
NULL, NULL, &clk_reset,
|
||||
NULL, NULL, NULL };
|
||||
|
@ -506,3 +518,21 @@ CLR_ENABLE (INT_CLK);
|
|||
sim_cancel (&clk_unit); /* deactivate unit */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Set frequency */
|
||||
|
||||
t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if (cptr) return SCPE_ARG;
|
||||
if ((val != 50) && (val != 60)) return SCPE_IERR;
|
||||
clk_tps = val;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Show frequency */
|
||||
|
||||
t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
fprintf (st, (clk_tps == 50)? "50Hz": "60Hz");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
|
|
@ -159,11 +159,12 @@ Peripherals
|
|||
12965 2883/2884 disk passed 12965 manual no
|
||||
12559 3030 magtape not run no documentation
|
||||
13181 7970B magtape partial in 21MX CE no
|
||||
- initial s = 102030
|
||||
- set MSC CTIME to 180000
|
||||
- do not change MSC XTIME
|
||||
- attach scratch tapes to units 0,1
|
||||
- set s = 2000 (suppress CRC/LRC)
|
||||
- run with test select a = 37737, b = 7767
|
||||
- set s = 1201 (suppress CRC/LRC)
|
||||
- run with test select a = 37757, b = 7767
|
||||
- tests 4, 14, 15 are timing dependent
|
||||
- test 19 uses non-supported read rev
|
||||
13183 7970E magtape not run in 21MX CE no
|
||||
|
|
|
@ -51,16 +51,11 @@
|
|||
*/
|
||||
|
||||
#include "hp2100_defs.h"
|
||||
#include "sim_tape.h"
|
||||
|
||||
#define MS_NUMDR 4 /* number of drives */
|
||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
||||
#define UNIT_V_PNU (UNIT_V_UF + 1) /* pos not updated */
|
||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
||||
#define UNIT_PNU (1 << UNIT_V_PNU)
|
||||
#define DB_N_SIZE 16 /* max data buf */
|
||||
#define DBSIZE (1 << DB_N_SIZE) /* max data cmd */
|
||||
#define DBMASK (DBSIZE - 1)
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
#define FNC u3 /* function */
|
||||
#define UST u4 /* unit status */
|
||||
|
||||
|
@ -138,12 +133,7 @@ t_stat msc_reset (DEVICE *dptr);
|
|||
t_stat msc_attach (UNIT *uptr, char *cptr);
|
||||
t_stat msc_detach (UNIT *uptr);
|
||||
t_stat msc_boot (int32 unitno, DEVICE *dptr);
|
||||
t_stat msc_vlock (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_bool ms_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
||||
t_bool ms_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
||||
t_bool ms_forwsp (UNIT *uptr, int32 *err);
|
||||
t_bool ms_backsp (UNIT *uptr, int32 *err);
|
||||
int32 ms_wrtrec (UNIT *uptr, t_mtrlnt lnt);
|
||||
t_stat ms_map_err (UNIT *uptr, t_stat st);
|
||||
t_stat ms_settype (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat ms_showtype (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
|
||||
|
@ -223,8 +213,8 @@ REG msc_reg[] = {
|
|||
{ NULL } };
|
||||
|
||||
MTAB msc_mod[] = {
|
||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", &msc_vlock },
|
||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", &msc_vlock },
|
||||
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 0, NULL, "13181A",
|
||||
&ms_settype, NULL, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 1, NULL, "13183A",
|
||||
|
@ -285,6 +275,7 @@ return dat;
|
|||
int32 mscio (int32 inst, int32 IR, int32 dat)
|
||||
{
|
||||
int32 i, devc, devd;
|
||||
t_stat st;
|
||||
UNIT *uptr = msc_dev.units + msc_usl;
|
||||
static const uint8 map_sel[16] = {
|
||||
0, 0, 1, 1, 2, 2, 2, 2,
|
||||
|
@ -314,7 +305,7 @@ case ioOTX: /* output */
|
|||
uptr = msc_dev.units + msc_usl; }
|
||||
if (((dat & FNF_MOT) && sim_is_active (uptr)) ||
|
||||
((dat & FNF_REV) && (uptr->UST & STA_BOT)) ||
|
||||
((dat & FNF_WRT) && (uptr->flags & UNIT_WPRT)))
|
||||
((dat & FNF_WRT) && sim_tape_wrp (uptr)))
|
||||
msc_sta = msc_sta | STA_REJ; /* reject? */
|
||||
break;
|
||||
case ioLIX: /* load */
|
||||
|
@ -324,7 +315,7 @@ case ioMIX: /* merge */
|
|||
if (uptr->flags & UNIT_ATT) { /* online? */
|
||||
if (sim_is_active (uptr)) /* busy */
|
||||
dat = dat | STA_TBSY;
|
||||
if (uptr->flags & UNIT_WPRT) /* write prot? */
|
||||
if (sim_tape_wrp (uptr)) /* write prot? */
|
||||
dat = dat | STA_WLK; }
|
||||
else dat = dat | STA_TBSY | STA_LOCAL;
|
||||
if (ms_ctype) dat = dat | STA_PE | /* 13183A? */
|
||||
|
@ -336,8 +327,9 @@ case ioCTL: /* control clear/set */
|
|||
if ((msc_buf & 0377) == FNC_CLR) { /* clear? */
|
||||
for (i = 0; i < MS_NUMDR; i++) { /* loop thru units */
|
||||
if (sim_is_active (&msc_unit[i]) && /* write in prog? */
|
||||
(msc_unit[i].FNC == FNC_WC) && (ms_ptr > 0))
|
||||
ms_wrtrec (uptr, ms_ptr | MTR_ERF);
|
||||
(msc_unit[i].FNC == FNC_WC) && (ms_ptr > 0)) {
|
||||
if (st = sim_tape_wrrecf (uptr, msxb, ms_ptr | MTR_ERF))
|
||||
ms_map_err (uptr, st); }
|
||||
if ((msc_unit[i].UST & STA_REW) == 0)
|
||||
sim_cancel (&msc_unit[i]); } /* stop if now rew */
|
||||
clrCTL (devc); /* init device */
|
||||
|
@ -371,10 +363,10 @@ return dat;
|
|||
|
||||
t_stat msc_svc (UNIT *uptr)
|
||||
{
|
||||
int32 devc, devd, err, pnu;
|
||||
static t_mtrlnt i, bceof = { MTR_TMK };
|
||||
int32 devc, devd;
|
||||
t_mtrlnt tbc;
|
||||
t_stat st, r = SCPE_OK;
|
||||
|
||||
err = 0; /* assume no errors */
|
||||
devc = msc_dib.devno; /* get device nos */
|
||||
devd = msd_dib.devno;
|
||||
|
||||
|
@ -383,14 +375,11 @@ if ((uptr->flags & UNIT_ATT) == 0) { /* offline? */
|
|||
setFLG (devc); /* set cch flg */
|
||||
return IORETURN (msc_stopioe, SCPE_UNATT); }
|
||||
|
||||
pnu = MT_TST_PNU (uptr); /* get pos not upd */
|
||||
MT_CLR_PNU (uptr); /* and clear */
|
||||
|
||||
switch (uptr->FNC) { /* case on function */
|
||||
case FNC_REW: /* rewind */
|
||||
case FNC_RWS: /* rewind offline */
|
||||
if (uptr->UST & STA_REW) { /* rewind in prog? */
|
||||
uptr->pos = 0; /* done */
|
||||
sim_tape_rewind (uptr); /* done */
|
||||
uptr->UST = STA_BOT; /* set BOT status */
|
||||
if (uptr->FNC & FNF_OFL) detach_unit (uptr);
|
||||
return SCPE_OK; }
|
||||
|
@ -400,32 +389,40 @@ case FNC_RWS: /* rewind offline */
|
|||
|
||||
case FNC_GFM: /* gap file mark */
|
||||
case FNC_WFM: /* write file mark */
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
||||
fxwrite (&bceof, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
|
||||
r = ms_map_err (uptr, st); /* map error */
|
||||
msc_sta = STA_EOF; /* set EOF status */
|
||||
if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr);
|
||||
else uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* update tape pos */
|
||||
break;
|
||||
|
||||
case FNC_GAP: /* erase gap */
|
||||
break;
|
||||
|
||||
case FNC_FSF:
|
||||
while (ms_forwsp (uptr, &err)) ; /* spc until EOF/EOT */
|
||||
case FNC_FSR: /* space forward */
|
||||
if (st = sim_tape_sprecf (uptr, &tbc)) /* space rec fwd, err? */
|
||||
r = ms_map_err (uptr, st); /* map error */
|
||||
if (tbc & 1) msc_sta = msc_sta | STA_ODD;
|
||||
else msc_sta = msc_sta & ~STA_ODD;
|
||||
break;
|
||||
|
||||
case FNC_FSR: /* space forward */
|
||||
ms_forwsp (uptr, &err);
|
||||
case FNC_BSR:
|
||||
if (st = sim_tape_sprecr (uptr, &tbc)) /* space rec rev, err? */
|
||||
r = ms_map_err (uptr, st); /* map error */
|
||||
if (tbc & 1) msc_sta = msc_sta | STA_ODD;
|
||||
else msc_sta = msc_sta & ~STA_ODD;
|
||||
break;
|
||||
|
||||
case FNC_FSF:
|
||||
while ((st = sim_tape_sprecf (uptr, &tbc)) == MTSE_OK) ;
|
||||
if (st == MTSE_TMK) /* stopped by tmk? */
|
||||
msc_sta = msc_sta | STA_EOF | STA_ODD; /* normal status */
|
||||
else r = ms_map_err (uptr, st); /* map error */
|
||||
break;
|
||||
|
||||
case FNC_BSF:
|
||||
while (ms_backsp (uptr, &err)) ; /* spc until EOF/BOT */
|
||||
break;
|
||||
|
||||
case FNC_BSR: /* space reverse */
|
||||
if (!pnu) { /* position ok? */
|
||||
ms_backsp (uptr, &err); /* backspace */
|
||||
if (msc_sta & STA_ODD) msc_sta = msc_sta | STA_PAR; }
|
||||
while ((st = sim_tape_sprecr (uptr, &tbc)) == MTSE_OK) ;
|
||||
if (st == MTSE_TMK) /* stopped by tmk? */
|
||||
msc_sta = msc_sta | STA_EOF | STA_ODD; /* normal status */
|
||||
else r = ms_map_err (uptr, st); /* map error */
|
||||
break;
|
||||
|
||||
/* Unit service, continued */
|
||||
|
@ -434,21 +431,16 @@ case FNC_RFF: /* diagnostic read */
|
|||
case FNC_RC: /* read */
|
||||
if (msc_1st) { /* first svc? */
|
||||
msc_1st = ms_ptr = 0; /* clr 1st flop */
|
||||
if (ms_rdlntf (uptr, &ms_max, &err)) { /* read rec lnt */
|
||||
if (!err) { /* tmk or eom? */
|
||||
st = sim_tape_rdrecf (uptr, msxb, &ms_max, DBSIZE); /* read rec */
|
||||
if (st == MTSE_RECE) msc_sta = msc_sta | STA_PAR; /* rec in err? */
|
||||
else if (st != MTSE_OK) { /* other error? */
|
||||
r = ms_map_err (uptr, st); /* map error */
|
||||
if (r == SCPE_OK) { /* recoverable? */
|
||||
sim_activate (uptr, msc_gtime); /* sched IRG */
|
||||
uptr->FNC = 0; /* NOP func */
|
||||
return SCPE_OK; }
|
||||
break; } /* err, done */
|
||||
if (ms_max > DBSIZE) return SCPE_MTRLNT; /* record too long? */
|
||||
i = fxread (msxb, sizeof (int8), ms_max, uptr->fileref);
|
||||
if (err = ferror (uptr->fileref)) { /* error? */
|
||||
msc_sta = msc_sta | STA_PAR; /* set flag */
|
||||
MT_SET_PNU (uptr); /* pos not upd */
|
||||
break; }
|
||||
for ( ; i < ms_max; i++) msxb[i] = 0; /* fill with 0's */
|
||||
uptr->pos = uptr->pos + ((ms_max + 1) & ~1) +
|
||||
(2 * sizeof (t_mtrlnt)); } /* update position */
|
||||
}
|
||||
if (ms_ptr < ms_max) { /* more chars? */
|
||||
if (FLG (devd)) msc_sta = msc_sta | STA_TIM | STA_PAR;
|
||||
msd_buf = ((uint16) msxb[ms_ptr] << 8) | msxb[ms_ptr + 1];
|
||||
|
@ -475,7 +467,9 @@ case FNC_WC: /* write */
|
|||
sim_activate (uptr, msc_xtime); /* re-activate */
|
||||
return SCPE_OK; }
|
||||
if (ms_ptr) { /* any data? write */
|
||||
if (err = ms_wrtrec (uptr, ms_ptr)) break; }
|
||||
if (st = sim_tape_wrrecf (uptr, msxb, ms_ptr)) { /* write, err? */
|
||||
r = ms_map_err (uptr, st); /* map error */
|
||||
break; } }
|
||||
sim_activate (uptr, msc_gtime); /* sched IRG */
|
||||
uptr->FNC = 0; /* NOP func */
|
||||
return SCPE_OK;
|
||||
|
@ -485,94 +479,40 @@ default: /* unknown */
|
|||
|
||||
setFLG (devc); /* set cch flg */
|
||||
msc_sta = msc_sta & ~STA_BUSY; /* update status */
|
||||
if (err != 0) { /* I/O error */
|
||||
perror ("MT I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
if (msc_stopioe) return SCPE_IOERR; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Tape motion routines */
|
||||
/* Map tape error status */
|
||||
|
||||
t_bool ms_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
||||
t_stat ms_map_err (UNIT *uptr, t_stat st)
|
||||
{
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* position */
|
||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref); /* get bc */
|
||||
if ((*err = ferror (uptr->fileref)) || /* error or eom? */
|
||||
feof (uptr->fileref) || (*tbc == MTR_EOM)) {
|
||||
msc_sta = msc_sta | STA_PAR; /* error */
|
||||
MT_SET_PNU (uptr); /* pos not upd */
|
||||
return TRUE; }
|
||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt);
|
||||
switch (st) {
|
||||
case MTSE_FMT: /* illegal fmt */
|
||||
case MTSE_UNATT: /* unattached */
|
||||
msc_sta = msc_sta | STA_REJ; /* reject */
|
||||
case MTSE_OK: /* no error */
|
||||
return SCPE_IERR; /* never get here! */
|
||||
case MTSE_TMK: /* end of file */
|
||||
msc_sta = msc_sta | STA_EOF | STA_ODD; /* eof (also sets odd) */
|
||||
return TRUE; }
|
||||
if (MTRF (*tbc)) msc_sta = msc_sta | STA_PAR; /* error in rec? */
|
||||
*tbc = MTRL (*tbc); /* clear err flag */
|
||||
if (*tbc & 1) msc_sta = msc_sta | STA_ODD;
|
||||
else msc_sta = msc_sta & ~STA_ODD;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
t_bool ms_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
||||
{
|
||||
if (uptr->pos < sizeof (t_mtrlnt)) { /* at bot? */
|
||||
break;
|
||||
case MTSE_INVRL: /* invalid rec lnt */
|
||||
msc_sta = msc_sta | STA_PAR;
|
||||
return SCPE_MTRLNT;
|
||||
case MTSE_IOERR: /* IO error */
|
||||
msc_sta = msc_sta | STA_PAR; /* error */
|
||||
if (msc_stopioe) return SCPE_IOERR;
|
||||
break;
|
||||
case MTSE_RECE: /* record in error */
|
||||
case MTSE_EOM: /* end of medium */
|
||||
msc_sta = msc_sta | STA_PAR; /* error */
|
||||
break;
|
||||
case MTSE_BOT: /* reverse into BOT */
|
||||
uptr->UST = 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); /* get bc */
|
||||
if ((*err = ferror (uptr->fileref)) || /* error or eof? */
|
||||
feof (uptr->fileref)) {
|
||||
msc_sta = msc_sta | STA_PAR; /* error */
|
||||
return TRUE; }
|
||||
if (*tbc == MTR_EOM) { /* eom? */
|
||||
msc_sta = msc_sta | STA_PAR; /* error */
|
||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over eom */
|
||||
return TRUE; }
|
||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
||||
msc_sta = msc_sta | STA_EOF; /* eof */
|
||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over tmk */
|
||||
return TRUE; }
|
||||
if (MTRF (*tbc)) msc_sta = msc_sta | STA_PAR; /* error in rec? */
|
||||
*tbc = MTRL (*tbc); /* clear err flag */
|
||||
if (*tbc & 1) msc_sta = msc_sta | STA_ODD;
|
||||
else msc_sta = msc_sta & ~STA_ODD;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
t_bool ms_forwsp (UNIT *uptr, int32 *err)
|
||||
{
|
||||
t_mtrlnt tbc;
|
||||
|
||||
if (ms_rdlntf (uptr, &tbc, err)) return FALSE; /* read rec lnt, err? */
|
||||
uptr->pos = uptr->pos + ((tbc + 1) & ~1) + /* incr tape position */
|
||||
(2 * sizeof (t_mtrlnt));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
t_bool ms_backsp (UNIT *uptr, int32 *err)
|
||||
{
|
||||
t_mtrlnt tbc;
|
||||
|
||||
if (ms_rdlntr (uptr, &tbc, err)) return FALSE; /* read rec lnt, err? */
|
||||
uptr->pos = uptr->pos - ((MTRL (tbc) + 1) & ~1) - /* decr tape position */
|
||||
(2 * sizeof (t_mtrlnt));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int32 ms_wrtrec (UNIT *uptr, t_mtrlnt lnt)
|
||||
{
|
||||
int32 elnt = MTRL ((lnt + 1) & ~1); /* even lnt, no err */
|
||||
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* seek to record */
|
||||
fxwrite (&lnt, sizeof (t_mtrlnt), 1, uptr->fileref); /* write rec lnt */
|
||||
fxwrite (msxb, sizeof (int8), elnt, uptr->fileref); /* write data */
|
||||
fxwrite (&lnt, sizeof (t_mtrlnt), 1, uptr->fileref); /* write rec lnt */
|
||||
if (ferror (uptr->fileref)) { /* error? */
|
||||
MT_SET_PNU (uptr); /* pos not updated */
|
||||
return 1; }
|
||||
else uptr->pos = uptr->pos + elnt + (2 * sizeof (t_mtrlnt)); /* no, upd pos */
|
||||
return 0;
|
||||
break;
|
||||
case MTSE_WRP: /* write protect */
|
||||
msc_sta = msc_sta | STA_REJ; /* reject */
|
||||
break; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
@ -592,7 +532,7 @@ msc_dib.flg = msd_dib.flg = 1; /* set flg */
|
|||
msc_dib.fbf = msd_dib.fbf = 1; /* set fbf */
|
||||
for (i = 0; i < MS_NUMDR; i++) {
|
||||
uptr = msc_dev.units + i;
|
||||
MT_CLR_PNU (uptr);
|
||||
sim_tape_reset (uptr);
|
||||
sim_cancel (uptr);
|
||||
uptr->UST = 0; }
|
||||
return SCPE_OK;
|
||||
|
@ -604,9 +544,8 @@ t_stat msc_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; /* update status */
|
||||
MT_CLR_PNU (uptr);
|
||||
uptr->UST = STA_BOT;
|
||||
return r;
|
||||
}
|
||||
|
@ -616,16 +555,7 @@ return r;
|
|||
t_stat msc_detach (UNIT* uptr)
|
||||
{
|
||||
uptr->UST = 0; /* update status */
|
||||
MT_CLR_PNU (uptr);
|
||||
return detach_unit (uptr); /* detach unit */
|
||||
}
|
||||
|
||||
/* Write lock/enable routine */
|
||||
|
||||
t_stat msc_vlock (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if (val && (uptr->flags & UNIT_ATT)) return SCPE_ARG;
|
||||
return SCPE_OK;
|
||||
return sim_tape_detach (uptr); /* detach unit */
|
||||
}
|
||||
|
||||
/* Set controller type */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* hp2100_mt.c: HP 2100 12559A magnetic tape simulator
|
||||
|
||||
Copyright (c) 1993-2002, Robert M. Supnik
|
||||
Copyright (c) 1993-2003, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -25,6 +25,7 @@
|
|||
|
||||
mt 12559A 3030 nine track magnetic tape
|
||||
|
||||
28-Feb-03 RMS Revised for magtape library
|
||||
30-Sep-02 RMS Revamped error handling
|
||||
28-Aug-02 RMS Added end of medium support
|
||||
30-May-02 RMS Widened POS to 32b
|
||||
|
@ -54,15 +55,10 @@
|
|||
*/
|
||||
|
||||
#include "hp2100_defs.h"
|
||||
#include "sim_tape.h"
|
||||
|
||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
||||
#define UNIT_V_PNU (UNIT_V_UF + 1) /* pos not updated */
|
||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
||||
#define UNIT_PNU (1 << UNIT_V_PNU)
|
||||
#define DB_V_SIZE 16 /* max data buf */
|
||||
#define DBSIZE (1 << DB_V_SIZE) /* max data cmd */
|
||||
#define DBMASK (DBSIZE - 1)
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
|
||||
/* Command - mtc_fnc */
|
||||
|
||||
|
@ -108,12 +104,9 @@ int32 mtdio (int32 inst, int32 IR, int32 dat);
|
|||
int32 mtcio (int32 inst, int32 IR, int32 dat);
|
||||
t_stat mtc_svc (UNIT *uptr);
|
||||
t_stat mtc_reset (DEVICE *dptr);
|
||||
t_stat mtc_vlock (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat mtc_attach (UNIT *uptr, char *cptr);
|
||||
t_stat mtc_detach (UNIT *uptr);
|
||||
t_bool mt_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
||||
t_bool mt_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
||||
int32 mt_wrtrec (UNIT *uptr, t_mtrlnt lnt);
|
||||
t_stat mt_map_err (UNIT *uptr, t_stat st);
|
||||
|
||||
/* MTD data structures
|
||||
|
||||
|
@ -143,6 +136,8 @@ REG mtd_reg[] = {
|
|||
{ NULL } };
|
||||
|
||||
MTAB mtd_mod[] = {
|
||||
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
|
||||
{ MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO",
|
||||
&hp_setdev, &hp_showdev, &mtd_dev },
|
||||
{ 0 } };
|
||||
|
@ -183,8 +178,6 @@ REG mtc_reg[] = {
|
|||
{ NULL } };
|
||||
|
||||
MTAB mtc_mod[] = {
|
||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", &mtc_vlock },
|
||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", &mtc_vlock },
|
||||
{ MTAB_XTD | MTAB_VDV, 1, "DEVNO", "DEVNO",
|
||||
&hp_setdev, &hp_showdev, &mtd_dev },
|
||||
{ 0 } };
|
||||
|
@ -234,6 +227,7 @@ return dat;
|
|||
int32 mtcio (int32 inst, int32 IR, int32 dat)
|
||||
{
|
||||
int32 i, devc, devd, valid;
|
||||
t_stat st;
|
||||
|
||||
devc = IR & I_DEVMASK; /* get device no */
|
||||
devd = devc - 1;
|
||||
|
@ -252,8 +246,9 @@ case ioOTX: /* output */
|
|||
mtc_sta = mtc_sta & ~STA_REJ; /* clear reject */
|
||||
if (dat == FNC_CLR) { /* clear? */
|
||||
if (sim_is_active (&mtc_unit) && /* write in prog? */
|
||||
(mtc_fnc == FNC_WC) && (mt_ptr > 0)) /* yes, bad rec */
|
||||
mt_wrtrec (&mtc_unit, mt_ptr | MTR_ERF);
|
||||
(mtc_fnc == FNC_WC) && (mt_ptr > 0)) { /* yes, bad rec */
|
||||
if (st = sim_tape_wrrecf (&mtc_unit, mtxb, mt_ptr | MTR_ERF))
|
||||
mt_map_err (&mtc_unit, st); }
|
||||
if (((mtc_fnc == FNC_REW) || (mtc_fnc == FNC_RWS)) &&
|
||||
sim_is_active (&mtc_unit)) sim_cancel (&mtc_unit);
|
||||
mtc_1st = mtc_dtf = 0;
|
||||
|
@ -267,7 +262,7 @@ case ioOTX: /* output */
|
|||
if (dat == mtc_cmd[i]) valid = 1;
|
||||
if (!valid || sim_is_active (&mtc_unit) || /* is cmd valid? */
|
||||
((mtc_sta & STA_BOT) && (dat == FNC_BSR)) ||
|
||||
((mtc_unit.flags & UNIT_WPRT) &&
|
||||
(sim_tape_wrp (&mtc_unit) &&
|
||||
((dat == FNC_WC) || (dat == FNC_GAP) || (dat == FNC_WFM))))
|
||||
mtc_sta = mtc_sta | STA_REJ;
|
||||
else {
|
||||
|
@ -286,7 +281,7 @@ case ioMIX: /* merge */
|
|||
dat = dat | (mtc_sta & ~(STA_LOCAL | STA_WLK | STA_BUSY));
|
||||
if (mtc_unit.flags & UNIT_ATT) { /* construct status */
|
||||
if (sim_is_active (&mtc_unit)) dat = dat | STA_BUSY;
|
||||
if (mtc_unit.flags & UNIT_WPRT) dat = dat | STA_WLK; }
|
||||
if (sim_tape_wrp (&mtc_unit)) dat = dat | STA_WLK; }
|
||||
else dat = dat | STA_BUSY | STA_LOCAL;
|
||||
break;
|
||||
case ioCTL: /* control clear/set */
|
||||
|
@ -309,10 +304,10 @@ return dat;
|
|||
|
||||
t_stat mtc_svc (UNIT *uptr)
|
||||
{
|
||||
int32 devc, devd, err, pnu;
|
||||
static t_mtrlnt i, bceof = { MTR_TMK };
|
||||
int32 devc, devd;
|
||||
t_mtrlnt tbc;
|
||||
t_stat st, r = SCPE_OK;
|
||||
|
||||
err = 0; /* assume no errors */
|
||||
devc = mtc_dib.devno; /* get device nos */
|
||||
devd = mtd_dib.devno;
|
||||
if ((mtc_unit.flags & UNIT_ATT) == 0) { /* offline? */
|
||||
|
@ -320,66 +315,54 @@ if ((mtc_unit.flags & UNIT_ATT) == 0) { /* offline? */
|
|||
setFLG (devc); /* set cch flg */
|
||||
return IORETURN (mtc_stopioe, SCPE_UNATT); }
|
||||
|
||||
pnu = MT_TST_PNU (uptr); /* get pos not upd */
|
||||
MT_CLR_PNU (uptr); /* and clear */
|
||||
switch (mtc_fnc) { /* case on function */
|
||||
|
||||
case FNC_REW: /* rewind */
|
||||
mtc_unit.pos = 0; /* BOT */
|
||||
sim_tape_rewind (uptr); /* BOT */
|
||||
mtc_sta = STA_BOT; /* update status */
|
||||
break;
|
||||
|
||||
case FNC_RWS: /* rewind and offline */
|
||||
mtc_unit.pos = 0; /* clear position */
|
||||
return detach_unit (uptr); /* don't set cch flg */
|
||||
sim_tape_rewind (uptr); /* clear position */
|
||||
return sim_tape_detach (uptr); /* don't set cch flg */
|
||||
|
||||
case FNC_WFM: /* write file mark */
|
||||
fseek (mtc_unit.fileref, mtc_unit.pos, SEEK_SET);
|
||||
fxwrite (&bceof, sizeof (t_mtrlnt), 1, mtc_unit.fileref);
|
||||
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
mtc_sta = STA_EOF; /* set EOF status */
|
||||
if (err = ferror (mtc_unit.fileref)) MT_SET_PNU (uptr);
|
||||
else mtc_unit.pos = mtc_unit.pos + sizeof (t_mtrlnt); /* update tape pos */
|
||||
break;
|
||||
|
||||
case FNC_GAP: /* erase gap */
|
||||
break;
|
||||
|
||||
case FNC_FSR: /* space forward */
|
||||
if (mt_rdlntf (uptr, &mt_max, &err)) break; /* read rec lnt, err? */
|
||||
mtc_unit.pos = mtc_unit.pos + ((mt_max + 1) & ~1) +
|
||||
(2 * sizeof (t_mtrlnt)); /* update position */
|
||||
if (st = sim_tape_sprecf (uptr, &tbc)) /* space rec fwd, err? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
break;
|
||||
|
||||
case FNC_BSR: /* space reverse */
|
||||
if (pnu) break; /* pnu? do nothing */
|
||||
if (mt_rdlntr (uptr, &mt_max, &err)) break; /* read rec lnt, err? */
|
||||
mtc_unit.pos = mtc_unit.pos - ((mt_max + 1) & ~1) -
|
||||
(2 * sizeof (t_mtrlnt)); /* update position */
|
||||
if (st = sim_tape_sprecr (uptr, &tbc)) /* space rec rev, err? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
break;
|
||||
|
||||
/* Unit service, continued */
|
||||
|
||||
case FNC_RC: /* read */
|
||||
if (mtc_1st) { /* first svc? */
|
||||
mtc_1st = 0; /* clr 1st flop */
|
||||
if (mt_rdlntf (uptr, &mt_max, &err)) { /* read rec lnt */
|
||||
if (!err) { /* tmk or eom? */
|
||||
mtc_1st = mt_ptr = 0; /* clr 1st flop */
|
||||
st = sim_tape_rdrecf (uptr, mtxb, &mt_max, DBSIZE); /* read rec */
|
||||
if (st == MTSE_RECE) mtc_sta = mtc_sta | STA_PAR; /* rec in err? */
|
||||
else if (st != MTSE_OK) { /* other error? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
if (r == SCPE_OK) { /* recoverable? */
|
||||
sim_activate (uptr, mtc_gtime); /* sched IRG */
|
||||
mtc_fnc = 0; /* NOP func */
|
||||
return SCPE_OK; }
|
||||
break; } /* error, done */
|
||||
if (mt_max > DBSIZE) return SCPE_MTRLNT; /* record too long? */
|
||||
break; } /* non-recov, done */
|
||||
if (mt_max < 12) { /* record too short? */
|
||||
mtc_sta = mtc_sta | STA_PAR; /* set flag */
|
||||
break; }
|
||||
i = fxread (mtxb, sizeof (int8), mt_max, mtc_unit.fileref);
|
||||
for ( ; i < mt_max; i++) mtxb[i] = 0; /* fill with 0's */
|
||||
if (err = ferror (mtc_unit.fileref)) { /* error? */
|
||||
mtc_sta = mtc_sta | STA_PAR; /* set flag */
|
||||
MT_SET_PNU (uptr); /* pos not upd */
|
||||
break; }
|
||||
mtc_unit.pos = mtc_unit.pos + ((mt_max + 1) & ~1) +
|
||||
(2 * sizeof (t_mtrlnt)); } /* update position */
|
||||
}
|
||||
if (mt_ptr < mt_max) { /* more chars? */
|
||||
if (FLG (devd)) mtc_sta = mtc_sta | STA_TIM;
|
||||
mtc_unit.buf = mtxb[mt_ptr++]; /* fetch next */
|
||||
|
@ -402,7 +385,9 @@ case FNC_WC: /* write */
|
|||
sim_activate (uptr, mtc_xtime); /* re-activate */
|
||||
return SCPE_OK; }
|
||||
if (mt_ptr) { /* write buffer */
|
||||
if (err = mt_wrtrec (uptr, mt_ptr)) break; }
|
||||
if (st = sim_tape_wrrecf (uptr, mtxb, mt_ptr)) { /* write, err? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
break; } } /* done */
|
||||
sim_activate (uptr, mtc_gtime); /* schedule gap */
|
||||
mtc_fnc = 0; /* nop */
|
||||
return SCPE_OK;
|
||||
|
@ -412,70 +397,40 @@ default: /* unknown */
|
|||
|
||||
setFLG (devc); /* set cch flg */
|
||||
mtc_sta = mtc_sta & ~STA_BUSY; /* not busy */
|
||||
if (err != 0) { /* I/O error */
|
||||
perror ("MT I/O error");
|
||||
clearerr (mtc_unit.fileref);
|
||||
if (mtc_stopioe) return SCPE_IOERR; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Tape motion routines */
|
||||
/* Map tape error status */
|
||||
|
||||
t_bool mt_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
||||
t_stat mt_map_err (UNIT *uptr, t_stat st)
|
||||
{
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* position */
|
||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref); /* get bc */
|
||||
if ((*err = ferror (uptr->fileref)) || /* error or eom? */
|
||||
feof (uptr->fileref) || (*tbc == MTR_EOM)) {
|
||||
mtc_sta = mtc_sta | STA_PAR; /* error */
|
||||
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: /* unattached */
|
||||
mtc_sta = mtc_sta | STA_REJ; /* reject */
|
||||
case MTSE_OK: /* no error */
|
||||
return SCPE_IERR; /* never get here! */
|
||||
case MTSE_TMK: /* end of file */
|
||||
mtc_sta = mtc_sta | STA_EOF; /* eof */
|
||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* spc over tmk */
|
||||
return TRUE; }
|
||||
if (MTRF (*tbc)) mtc_sta = mtc_sta | STA_PAR; /* error in rec? */
|
||||
*tbc = MTRL (*tbc); /* clear err flag */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
t_bool mt_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
||||
{
|
||||
if (uptr->pos < sizeof (t_mtrlnt)) { /* no data to read? */
|
||||
mtc_sta = mtc_sta | STA_BOT; /* update status */
|
||||
return TRUE; }
|
||||
fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET);
|
||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref); /* get bc */
|
||||
if ((*err = ferror (uptr->fileref)) || /* error or eof? */
|
||||
feof (uptr->fileref)) {
|
||||
break;
|
||||
case MTSE_IOERR: /* IO error */
|
||||
mtc_sta = mtc_sta | STA_PAR; /* error */
|
||||
return TRUE; }
|
||||
if (*tbc == MTR_EOM) { /* eom? */
|
||||
if (mtc_stopioe) return SCPE_IOERR;
|
||||
break;
|
||||
case MTSE_INVRL: /* invalid rec lnt */
|
||||
mtc_sta = mtc_sta | STA_PAR;
|
||||
return SCPE_MTRLNT;
|
||||
case MTSE_RECE: /* record in error */
|
||||
case MTSE_EOM: /* end of medium */
|
||||
mtc_sta = mtc_sta | STA_PAR; /* error */
|
||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over eom */
|
||||
return TRUE; }
|
||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
||||
mtc_sta = mtc_sta | STA_EOF; /* eof */
|
||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over tmk */
|
||||
return TRUE; }
|
||||
if (MTRF (*tbc)) mtc_sta = mtc_sta | STA_PAR; /* error in rec? */
|
||||
*tbc = MTRL (*tbc); /* clear err flag */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int32 mt_wrtrec (UNIT *uptr, t_mtrlnt lnt)
|
||||
{
|
||||
int32 elnt = MTRL ((lnt + 1) & ~1); /* even lnt, no err */
|
||||
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* seek to record */
|
||||
fxwrite (&lnt, sizeof (t_mtrlnt), 1, uptr->fileref); /* write rec lnt */
|
||||
fxwrite (mtxb, sizeof (int8), elnt, uptr->fileref); /* write data */
|
||||
fxwrite (&lnt, sizeof (t_mtrlnt), 1, uptr->fileref); /* write rec lnt */
|
||||
if (ferror (uptr->fileref)) { /* error? */
|
||||
MT_SET_PNU (uptr); /* pos not updated */
|
||||
return 1; }
|
||||
else uptr->pos = uptr->pos + elnt + (2 * sizeof (t_mtrlnt)); /* no, upd pos */
|
||||
return 0;
|
||||
break;
|
||||
case MTSE_BOT: /* reverse into BOT */
|
||||
mtc_sta = mtc_sta | STA_BOT; /* set status */
|
||||
break;
|
||||
case MTSE_WRP: /* write protect */
|
||||
mtc_sta = mtc_sta | STA_REJ; /* reject */
|
||||
break; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
@ -490,9 +445,10 @@ mtc_dib.ctl = mtd_dib.ctl = 0; /* clear ctl */
|
|||
mtc_dib.flg = mtd_dib.flg = 0; /* clear flg */
|
||||
mtc_dib.fbf = mtd_dib.fbf = 0; /* clear fbf */
|
||||
sim_cancel (&mtc_unit); /* cancel activity */
|
||||
mtc_unit.flags = mtc_unit.flags & ~UNIT_PNU; /* clear pos flag */
|
||||
if (mtc_unit.flags & UNIT_ATT) mtc_sta = ((mtc_unit.pos)? 0: STA_BOT) |
|
||||
((mtc_unit.flags & UNIT_WPRT)? STA_WLK: 0);
|
||||
sim_tape_reset (&mtc_unit);
|
||||
if (mtc_unit.flags & UNIT_ATT) mtc_sta =
|
||||
(sim_tape_bot (&mtc_unit)? STA_BOT: 0) |
|
||||
(sim_tape_wrp (&mtc_unit)? STA_WLK: 0);
|
||||
else mtc_sta = STA_LOCAL | STA_BUSY;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -503,9 +459,8 @@ t_stat mtc_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; /* update status */
|
||||
MT_CLR_PNU (uptr);
|
||||
mtc_sta = STA_BOT;
|
||||
return r;
|
||||
}
|
||||
|
@ -515,14 +470,5 @@ return r;
|
|||
t_stat mtc_detach (UNIT* uptr)
|
||||
{
|
||||
mtc_sta = 0; /* update status */
|
||||
MT_CLR_PNU (uptr);
|
||||
return detach_unit (uptr); /* detach unit */
|
||||
}
|
||||
|
||||
/* Write lock/enable routine */
|
||||
|
||||
t_stat mtc_vlock (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if (val && (uptr->flags & UNIT_ATT)) return SCPE_ARG;
|
||||
return SCPE_OK;
|
||||
return sim_tape_detach (uptr); /* detach unit */
|
||||
}
|
||||
|
|
142
I1401/i1401_mt.c
142
I1401/i1401_mt.c
|
@ -1,6 +1,6 @@
|
|||
/* i1401_mt.c: IBM 1401 magnetic tape simulator
|
||||
|
||||
Copyright (c) 1993-2002, Robert M. Supnik
|
||||
Copyright (c) 1993-2003, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -25,6 +25,7 @@
|
|||
|
||||
mt 7-track magtape
|
||||
|
||||
28-Feb-03 RMS Modified for magtape library
|
||||
31-Oct-02 RMS Added error record handling
|
||||
10-Oct-02 RMS Fixed end-of-record on load read writes WM plus GM
|
||||
30-Sep-02 RMS Revamped error handling
|
||||
|
@ -59,13 +60,9 @@
|
|||
*/
|
||||
|
||||
#include "i1401_defs.h"
|
||||
#include "sim_tape.h"
|
||||
|
||||
#define MT_NUMDR 7 /* #drives */
|
||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
||||
#define UNIT_V_PNU (UNIT_V_UF + 1) /* pos not upd */
|
||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
||||
#define UNIT_PNU (1 << UNIT_V_PNU)
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
#define MT_MAXFR (MAXMEMSIZE * 2) /* max transfer */
|
||||
|
||||
extern uint8 M[]; /* memory */
|
||||
|
@ -75,7 +72,7 @@ extern UNIT cpu_unit;
|
|||
uint8 dbuf[MT_MAXFR]; /* tape buffer */
|
||||
t_stat mt_reset (DEVICE *dptr);
|
||||
t_stat mt_boot (int32 unitno, DEVICE *dptr);
|
||||
t_stat mt_attach (UNIT *uptr, char *cptr);
|
||||
t_stat mt_map_status (t_stat st);
|
||||
UNIT *get_unit (int32 unit);
|
||||
|
||||
/* MT data structures
|
||||
|
@ -113,15 +110,15 @@ REG mt_reg[] = {
|
|||
{ NULL } };
|
||||
|
||||
MTAB mt_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 },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE mt_dev = {
|
||||
"MT", mt_unit, mt_reg, mt_mod,
|
||||
MT_NUMDR, 10, 31, 1, 8, 8,
|
||||
NULL, NULL, &mt_reset,
|
||||
&mt_boot, &mt_attach, NULL };
|
||||
&mt_boot, &sim_tape_attach, &sim_tape_detach };
|
||||
|
||||
/* Function routine
|
||||
|
||||
|
@ -134,59 +131,38 @@ DEVICE mt_dev = {
|
|||
|
||||
t_stat mt_func (int32 unit, int32 mod)
|
||||
{
|
||||
int32 err, pnu;
|
||||
t_mtrlnt tbc;
|
||||
UNIT *uptr;
|
||||
static t_mtrlnt bceof = { MTR_TMK };
|
||||
t_stat st;
|
||||
|
||||
if ((uptr = get_unit (unit)) == NULL) return STOP_INVMTU; /* valid unit? */
|
||||
pnu = MT_TST_PNU (uptr); /* get pos not upd */
|
||||
MT_CLR_PNU (uptr); /* and clear */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */
|
||||
switch (mod) { /* case on modifier */
|
||||
case BCD_B: /* backspace */
|
||||
ind[IN_END] = 0; /* clear end of reel */
|
||||
if (pnu || (uptr->pos < sizeof (t_mtrlnt))) /* bot or pnu? */
|
||||
return SCPE_OK;
|
||||
fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET);
|
||||
fxread (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
if ((err = ferror (uptr->fileref)) || /* err or eof? */
|
||||
feof (uptr->fileref)) break;
|
||||
if ((tbc == MTR_TMK) || (tbc == MTR_EOM)) /* tmk or eom? */
|
||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt);
|
||||
else uptr->pos = uptr->pos - ((MTRL (tbc) + 1) & ~1) -
|
||||
(2 * sizeof (t_mtrlnt));
|
||||
ind[IN_END] = 0; /* clear end of file */
|
||||
st = sim_tape_sprecr (uptr, &tbc); /* space rev */
|
||||
break; /* end case */
|
||||
|
||||
case BCD_E: /* erase = nop */
|
||||
if (uptr->flags & UNIT_WPRT) return STOP_MTL;
|
||||
if (sim_tape_wrp (uptr)) return STOP_MTL;
|
||||
return SCPE_OK;
|
||||
|
||||
case BCD_M: /* write tapemark */
|
||||
if (uptr->flags & UNIT_WPRT) return STOP_MTL;
|
||||
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);
|
||||
st = sim_tape_wrtmk (uptr); /* write tmk */
|
||||
break;
|
||||
|
||||
case BCD_R: /* rewind */
|
||||
uptr->pos = 0; /* update position */
|
||||
sim_tape_rewind (uptr); /* update position */
|
||||
return SCPE_OK;
|
||||
|
||||
case BCD_U: /* unload */
|
||||
uptr->pos = 0; /* update position */
|
||||
sim_tape_rewind (uptr); /* update position */
|
||||
return detach_unit (uptr); /* detach */
|
||||
|
||||
default:
|
||||
return STOP_INVM; }
|
||||
|
||||
if (err != 0) { /* I/O error */
|
||||
perror ("MT I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
ind[IN_TAP] = 1; /* set indicator */
|
||||
if (iochk) return SCPE_IOERR; }
|
||||
return SCPE_OK;
|
||||
return mt_map_status (st);
|
||||
}
|
||||
|
||||
/* Read and write routines
|
||||
|
@ -201,37 +177,21 @@ return SCPE_OK;
|
|||
|
||||
t_stat mt_io (int32 unit, int32 flag, int32 mod)
|
||||
{
|
||||
int32 err, t, wm_seen;
|
||||
t_mtrlnt i, tbc, ebc;
|
||||
int32 t, wm_seen;
|
||||
t_mtrlnt i, tbc;
|
||||
t_stat st;
|
||||
UNIT *uptr;
|
||||
|
||||
if ((uptr = get_unit (unit)) == NULL) return STOP_INVMTU; /* valid unit? */
|
||||
uptr->flags = uptr->flags & ~UNIT_PNU; /* clr pos not upd */
|
||||
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* attached? */
|
||||
|
||||
switch (mod) {
|
||||
case BCD_R: /* read */
|
||||
ind[IN_TAP] = ind[IN_END] = 0; /* clear error */
|
||||
wm_seen = 0; /* no word mk seen */
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
||||
fxread (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
if (err = ferror (uptr->fileref)) break; /* error? */
|
||||
if (feof (uptr->fileref) || (tbc == MTR_EOM)) { /* eom or eof? */
|
||||
ind[IN_TAP] = 1; /* pretend error */
|
||||
MT_SET_PNU (uptr); /* pos not upd */
|
||||
break; }
|
||||
if (tbc == MTR_TMK) { /* tape mark? */
|
||||
ind[IN_END] = 1; /* set end mark */
|
||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt);
|
||||
break; }
|
||||
if (MTRF (tbc)) ind[IN_TAP] = 1; /* error? set flag */
|
||||
tbc = MTRL (tbc); /* clear error flag */
|
||||
if (tbc > MT_MAXFR) return SCPE_MTRLNT; /* record too long? */
|
||||
i = fxread (dbuf, sizeof (int8), tbc, uptr->fileref);
|
||||
if (err = ferror (uptr->fileref)) break; /* I/O error? */
|
||||
for ( ; i < tbc; i++) dbuf[i] = 0; /* fill with 0's */
|
||||
uptr->pos = uptr->pos + ((tbc + 1) & ~1) +
|
||||
(2 * sizeof (t_mtrlnt));
|
||||
st = sim_tape_rdrecf (uptr, dbuf, &tbc, MT_MAXFR); /* read rec */
|
||||
if (st == MTSE_RECE) ind[IN_TAP] = 1; /* rec in error? */
|
||||
else if (st != MTSE_OK) break; /* stop on error */
|
||||
for (i = 0; i < tbc; i++) { /* loop thru buf */
|
||||
if (M[BS] == (BCD_GRPMRK + WM)) { /* GWM in memory? */
|
||||
BS++; /* incr BS */
|
||||
|
@ -260,7 +220,7 @@ case BCD_R: /* read */
|
|||
break;
|
||||
|
||||
case BCD_W:
|
||||
if (uptr->flags & UNIT_WPRT) return STOP_MTL; /* locked? */
|
||||
if (uptr->flags & MTUF_WRP) return STOP_MTL; /* locked? */
|
||||
if (M[BS] == (BCD_GRPMRK + WM)) return STOP_MTZ; /* eor? */
|
||||
ind[IN_TAP] = ind[IN_END] = 0; /* clear error */
|
||||
for (tbc = 0; (t = M[BS++]) != (BCD_GRPMRK + WM); ) {
|
||||
|
@ -271,13 +231,7 @@ case BCD_W:
|
|||
if (ADDR_ERR (BS)) { /* check next BS */
|
||||
BS = BA | (BS % MAXMEMSIZE);
|
||||
return STOP_WRAP; } }
|
||||
ebc = (tbc + 1) & ~1; /* force even */
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
||||
fxwrite (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
fxwrite (dbuf, sizeof (int8), ebc, uptr->fileref);
|
||||
fxwrite (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
if (err = ferror (uptr->fileref)) break; /* I/O error? */
|
||||
uptr->pos = uptr->pos + ebc + (2 * sizeof (t_mtrlnt));
|
||||
st = sim_tape_wrrecf (uptr, dbuf, tbc); /* write record */
|
||||
if (ADDR_ERR (BS)) { /* check final BS */
|
||||
BS = BA | (BS % MAXMEMSIZE);
|
||||
return STOP_WRAP; }
|
||||
|
@ -285,13 +239,7 @@ case BCD_W:
|
|||
default:
|
||||
return STOP_INVM; }
|
||||
|
||||
if (err != 0) { /* I/O error? */
|
||||
perror ("MT I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
MT_SET_PNU (uptr); /* pos not upd */
|
||||
ind[IN_TAP] = 1; /* flag error */
|
||||
if (iochk) return SCPE_IOERR; }
|
||||
return SCPE_OK;
|
||||
return mt_map_status (st);
|
||||
}
|
||||
|
||||
/* Get unit pointer from unit number */
|
||||
|
@ -299,7 +247,37 @@ return SCPE_OK;
|
|||
UNIT *get_unit (int32 unit)
|
||||
{
|
||||
if ((unit <= 0) || (unit >= MT_NUMDR)) return NULL;
|
||||
else return mt_dev.units + unit;
|
||||
return mt_dev.units + unit;
|
||||
}
|
||||
|
||||
/* Map tape status */
|
||||
|
||||
t_stat mt_map_status (t_stat st)
|
||||
{
|
||||
switch (st) {
|
||||
case MTSE_OK: /* no error */
|
||||
case MTSE_BOT: /* reverse into BOT */
|
||||
break;
|
||||
case MTSE_FMT: /* illegal fmt */
|
||||
return SCPE_IERR;
|
||||
case MTSE_UNATT: /* not attached */
|
||||
return SCPE_UNATT;
|
||||
case MTSE_INVRL: /* invalid rec lnt */
|
||||
return SCPE_MTRLNT;
|
||||
case MTSE_TMK: /* end of file */
|
||||
ind[IN_END] = 1; /* set end mark */
|
||||
break;
|
||||
case MTSE_IOERR: /* IO error */
|
||||
ind[IN_TAP] = 1; /* set error */
|
||||
if (iochk) return SCPE_IOERR;
|
||||
break;
|
||||
case MTSE_RECE: /* record in error */
|
||||
case MTSE_EOM: /* end of medium */
|
||||
ind[IN_TAP] = 1; /* set error */
|
||||
break;
|
||||
case MTSE_WRP: /* write protect */
|
||||
return STOP_MTL; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
@ -315,21 +293,13 @@ ind[IN_END] = ind[IN_TAP] = 0; /* clear indicators */
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Attach routine */
|
||||
|
||||
t_stat mt_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
MT_CLR_PNU (uptr);
|
||||
return attach_unit (uptr, cptr);
|
||||
}
|
||||
|
||||
/* Bootstrap routine */
|
||||
|
||||
t_stat mt_boot (int32 unitno, DEVICE *dptr)
|
||||
{
|
||||
extern int32 saved_IS;
|
||||
|
||||
mt_unit[unitno].pos = 0; /* force rewind */
|
||||
sim_tape_rewind (&mt_unit[unitno]); /* force rewind */
|
||||
BS = 1; /* set BS = 001 */
|
||||
mt_io (unitno, MD_WM, BCD_R); /* LDA %U1 001 R */
|
||||
saved_IS = 1;
|
||||
|
|
|
@ -303,23 +303,27 @@ static uint8 dboot_rom[] = {
|
|||
|
||||
struct dboot_id {
|
||||
char *name;
|
||||
uint32 sw;
|
||||
uint32 cap;
|
||||
uint32 dtype;
|
||||
uint32 offset;
|
||||
uint32 adder;
|
||||
};
|
||||
|
||||
static struct dboot_id dboot_tab[] = {
|
||||
{ "DP", 2, 0x31, o_DP0 },
|
||||
{ "DP", 9, 0x33, o_DP0 },
|
||||
{ "DM", 64, 0x35, o_ID0 },
|
||||
{ "DM", 244, 0x36, o_ID0 },
|
||||
{ "DP", 0, 2, 0x31, o_DP0, 0 },
|
||||
{ "DP", SWMASK ('F'), 9, 0x32, o_DP0, o_DPF },
|
||||
{ "DP", 0, 9, 0x33, o_DP0, 0 },
|
||||
{ "DM", 0, 64, 0x35, o_ID0, 0 },
|
||||
{ "DM", 0, 244, 0x36, o_ID0, 0 },
|
||||
{ NULL } };
|
||||
|
||||
t_stat id_dboot (int32 u, DEVICE *dptr)
|
||||
{
|
||||
extern DIB pt_dib, sch_dib;
|
||||
extern uint32 PC;
|
||||
uint32 i, typ, ctlno, off, cap, sch_dev;
|
||||
extern int32 sim_switches;
|
||||
uint32 i, typ, ctlno, off, add, cap, sch_dev;
|
||||
UNIT *uptr;
|
||||
|
||||
DIB *ddib = (DIB *) dptr->ctxt; /* get disk DIB */
|
||||
|
@ -331,13 +335,15 @@ for (i = typ = 0; dboot_tab[i].name != NULL; i++) {
|
|||
if ((strcmp (dboot_tab[i].name, dptr->name) == 0) &&
|
||||
(dboot_tab[i].cap == cap)) {
|
||||
typ = dboot_tab[i].dtype;
|
||||
off = dboot_tab[i].offset; } }
|
||||
off = dboot_tab[i].offset;
|
||||
add = dboot_tab[i].adder;
|
||||
break; } }
|
||||
if (typ == 0) return SCPE_NOFNC;
|
||||
|
||||
IOWriteBlk (DBOOT_BEG, DBOOT_LEN, dboot_rom); /* copy boot */
|
||||
IOWriteB (AL_DEV, pt_dib.dno); /* bin input dev */
|
||||
IOWriteB (AL_IOC, 0x99);
|
||||
IOWriteB (AL_DSKU, ctlno + ((u + 1) * off)); /* disk param */
|
||||
IOWriteB (AL_DSKU, ctlno + ((u + 1) * off) + add); /* disk param */
|
||||
IOWriteB (AL_DSKT, typ);
|
||||
IOWriteB (AL_DSKC, ctlno);
|
||||
IOWriteB (AL_SCH, sch_dev);
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
Except as contained in this notice, the name of Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
27-Feb-03 RMS Added relative addressing support
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
|
@ -42,8 +44,8 @@ extern UNIT cpu_unit;
|
|||
extern REG cpu_reg[];
|
||||
extern uint16 *M;
|
||||
|
||||
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val);
|
||||
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val);
|
||||
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val, t_bool cf);
|
||||
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val, t_bool cf);
|
||||
extern t_stat lp_load (FILE *fileref, char *cptr, char *fnam);
|
||||
extern pt_dump (FILE *of, char *cptr, char *fnam);
|
||||
|
||||
|
@ -297,7 +299,7 @@ if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */
|
|||
return -(vp - 1); } /* return # chars */
|
||||
|
||||
if (sw & SWMASK ('M')) { /* inst format? */
|
||||
r = fprint_sym_m (of, addr, val); /* decode inst */
|
||||
r = fprint_sym_m (of, addr, val, uptr == &cpu_unit); /* decode inst */
|
||||
if (r <= 0) return r; }
|
||||
|
||||
GETNUM (num, lnt); /* get number */
|
||||
|
@ -311,14 +313,15 @@ return -(vp - 1);
|
|||
of = output stream
|
||||
addr = current PC
|
||||
*val = values to decode
|
||||
cf = true if decoding for CPU
|
||||
Outputs:
|
||||
return = if >= 0, error code
|
||||
if < 0, number of extra bytes retired
|
||||
*/
|
||||
|
||||
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val)
|
||||
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val, t_bool cf)
|
||||
{
|
||||
uint32 i, j, k, inst, r1, r2, ea, tgt, vp;
|
||||
uint32 i, j, k, inst, r1, r2, ea, vp;
|
||||
|
||||
vp = 0;
|
||||
GETNUM (inst, 2); /* first 16b */
|
||||
|
@ -328,40 +331,39 @@ for (i = 0; opcode[i] != NULL; i++) { /* loop thru ops */
|
|||
if ((opc_val[i] & 0xFFFF) == (inst & masks[j])) { /* match? */
|
||||
r1 = (inst >> 4) & 0xF;
|
||||
r2 = inst & 0xF;
|
||||
fprintf (of, "%s ", opcode[i]); /* print opcode */
|
||||
switch (j) { /* case on class */
|
||||
case I_V_MR: /* mask-register */
|
||||
fprintf (of, "%s %-X,R%d", opcode[i], r1, r2);
|
||||
return -1;
|
||||
fprintf (of, "%-X,R%d", r1, r2);
|
||||
return -1;
|
||||
case I_V_RR: /* register-register */
|
||||
case I_V_FF: /* floating-floating */
|
||||
fprintf (of, "%s R%d,R%d", opcode[i], r1, r2);
|
||||
return -1;
|
||||
fprintf (of, "R%d,R%d", r1, r2);
|
||||
return -1;
|
||||
case I_V_SI: /* short immediate */
|
||||
fprintf (of, "%s R%d,%-X", opcode[i], r1, r2);
|
||||
return -1;
|
||||
fprintf (of, "R%d,%-X", r1, r2);
|
||||
return -1;
|
||||
case I_V_SB: /* short branch */
|
||||
if (inst & MSK_SBF) tgt = addr + r2 + r2;
|
||||
else tgt = addr - r2 - r2;
|
||||
fprintf (of, "%s %-X,%-X", opcode[i], r1, tgt);
|
||||
return -1;
|
||||
fprintf (of, "%-X,", r1);
|
||||
case I_V_SX: /* ext short branch */
|
||||
if (inst & MSK_SBF) tgt = addr + r2 + r2;
|
||||
else tgt = addr - r2 - r2;
|
||||
fprintf (of, "%s %-X", opcode[i], tgt);
|
||||
return -1;
|
||||
if (cf) fprintf (of, "%-X", ((inst & MSK_SBF)?
|
||||
(addr + r2 + r2): (addr - r2 - r2)));
|
||||
else fprintf (of, ((inst & MSK_SBF)?
|
||||
".+%-X": ".-%X"), r2 + r2);
|
||||
return -1;
|
||||
case I_V_R: /* register */
|
||||
fprintf (of, "%s R%d", opcode[i], r2);
|
||||
return -1;
|
||||
fprintf (of, "R%d", r2);
|
||||
return -1;
|
||||
case I_V_MX: /* mask-memory */
|
||||
fprintf (of, "%s %-X,%-X", opcode[i], r1, ea);
|
||||
break;
|
||||
fprintf (of, "%-X,%-X", r1, ea);
|
||||
break;
|
||||
case I_V_RX: /* register-memory */
|
||||
case I_V_FX: /* floating-memory */
|
||||
fprintf (of, "%s R%d,%-X", opcode[i], r1, ea);
|
||||
break;
|
||||
fprintf (of, "R%d,%-X", r1, ea);
|
||||
break;
|
||||
case I_V_X: /* memory */
|
||||
fprintf (of, "%s %-X", opcode[i], ea);
|
||||
break; } /* end case */
|
||||
fprintf (of, "%-X", ea);
|
||||
break; } /* end case */
|
||||
if (r2) fprintf (of, "(R%d)", r2);
|
||||
return -3; } /* end if */
|
||||
} /* end for */
|
||||
|
@ -398,6 +400,41 @@ if ((rtype == R_F) && (reg & 1)) return -1;
|
|||
*optr = cptr + 1;
|
||||
return reg;
|
||||
}
|
||||
|
||||
/* Address
|
||||
|
||||
Inputs:
|
||||
*cptr = pointer to input string
|
||||
**tptr = pointer to moved pointer
|
||||
*ea = effective address
|
||||
*rel = relative flag
|
||||
addr = base address
|
||||
cf = true if parsing for CPU
|
||||
Outputs:
|
||||
status = SCPE_OK if ok, else error code
|
||||
*/
|
||||
|
||||
t_stat get_addr (char *cptr, char **tptr, t_addr *ea, t_bool *rel,
|
||||
t_addr addr, t_bool cf)
|
||||
{
|
||||
int32 sign = 1;
|
||||
|
||||
*ea = 0;
|
||||
if (*cptr == '.') { /* relative? */
|
||||
*rel = TRUE;
|
||||
cptr++;
|
||||
if (cf) *ea = addr;
|
||||
if (*cptr == '+') cptr++; /* .+? */
|
||||
else if (*cptr == '-') { /* .-? */
|
||||
sign = -1;
|
||||
cptr++; }
|
||||
else return SCPE_OK; }
|
||||
else *rel = FALSE;
|
||||
errno = 0;
|
||||
*ea = *ea + (sign * ((int32) strtoul (cptr, tptr, 16)));
|
||||
if (errno || (cptr == *tptr)) return SCPE_ARG;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
#define PUTNUM(d,n) for (k = n; k > 0; k--) \
|
||||
val[vp++] = (d >> ((k - 1) * 8)) & 0xFF
|
||||
|
@ -431,9 +468,8 @@ if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */
|
|||
val[vp++] = *cptr++; }
|
||||
return -(vp - 1); } /* return # chars */
|
||||
|
||||
if (uptr == &cpu_unit) { /* cpu only */
|
||||
r = parse_sym_m (cptr, addr, val); /* try to parse inst */
|
||||
if (r <= 0) return r; }
|
||||
r = parse_sym_m (cptr, addr, val, uptr == &cpu_unit); /* try to parse inst */
|
||||
if (r <= 0) return r;
|
||||
|
||||
num = (int32) get_uint (cptr, rdx, maxv[lnt], &r); /* get number */
|
||||
if (r != SCPE_OK) return r;
|
||||
|
@ -447,15 +483,17 @@ return -(lnt - 1);
|
|||
*cptr = pointer to input string
|
||||
addr = current PC
|
||||
*val = pointer to output values
|
||||
cf = true if parsing for CPU
|
||||
Outputs:
|
||||
status = > 0 error code
|
||||
<= 0 -number of extra words
|
||||
*/
|
||||
|
||||
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val)
|
||||
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val, t_bool cf)
|
||||
{
|
||||
uint32 i, j, k, t, df, db, inst, ea, vp;
|
||||
int32 r1, r2;
|
||||
uint32 i, j, k, t, df, db, inst, vp;
|
||||
int32 st, r1, r2;
|
||||
t_bool rel;
|
||||
t_stat r;
|
||||
char *tptr, gbuf[CBUFSIZE];
|
||||
|
||||
|
@ -488,9 +526,9 @@ case I_V_R: /* register */
|
|||
case I_V_FX: /* float-memory */
|
||||
case I_V_MX: case I_V_RX: /* mask/reg-mem */
|
||||
case I_V_X: /* memory */
|
||||
errno = 0;
|
||||
ea = strtoul (gbuf, &tptr, 16); /* get address */
|
||||
if (errno || (gbuf == tptr)) return SCPE_ARG; /* error? */
|
||||
r = get_addr (gbuf, &tptr, &t, &rel, addr, cf); /* get addr */
|
||||
if ((r != SCPE_OK) || (t > PAMASK16) ||
|
||||
(!cf && rel)) return SCPE_ARG;
|
||||
if (*tptr == '(') { /* index? */
|
||||
if ((r2 = get_reg (tptr + 1, &tptr, R_R)) < 0)
|
||||
return SCPE_ARG;
|
||||
|
@ -498,23 +536,34 @@ case I_V_X: /* memory */
|
|||
inst = inst | r2; } /* or in R2 */
|
||||
if (*tptr != 0) return SCPE_ARG;
|
||||
PUTNUM (inst, 2);
|
||||
PUTNUM (ea, 2);
|
||||
PUTNUM (t, 2);
|
||||
return -3;
|
||||
|
||||
case I_V_SB: case I_V_SX: /* short branches */
|
||||
t = get_uint (gbuf, 16, DMASK16, &r); /* get addr */
|
||||
if ((r != SCPE_OK) || (t & 1)) return r; /* error if odd */
|
||||
db = (addr - t) & 0x1F; /* back displ */
|
||||
df = (t - addr) & 0x1F; /* fwd displ */
|
||||
if ((t == ((addr - db) & VAMASK16)) && /* back work and */
|
||||
((j == I_V_SX) || !(inst & MSK_SBF))) { /* ext or back br? */
|
||||
inst = inst | (db >> 1); /* or in back displ */
|
||||
break; }
|
||||
if ((t == ((addr + df) & VAMASK16)) && /* fwd work and */
|
||||
((j == I_V_SX) || (inst & MSK_SBF))) { /* ext or fwd br? */
|
||||
inst = inst | (df >> 1) | MSK_SBF; /* or in fwd displ */
|
||||
break; }
|
||||
return SCPE_ARG; } /* end case */
|
||||
r = get_addr (gbuf, &tptr, &t, &rel, addr, cf); /* get addr */
|
||||
if ((r != SCPE_OK) || (t & 1) || *tptr) /* error if odd */
|
||||
return SCPE_ARG;
|
||||
st = t; /* signed version */
|
||||
if (cf) { /* for CPU? */
|
||||
db = (addr - t) & 0x1F; /* back displ */
|
||||
df = (t - addr) & 0x1F; /* fwd displ */
|
||||
if ((t == ((addr - db) & VAMASK16)) && /* back work and */
|
||||
((j == I_V_SX) || !(inst & MSK_SBF))) /* ext or back br? */
|
||||
inst = inst | (db >> 1); /* or in back displ */
|
||||
else if ((t == ((addr + df) & VAMASK16)) && /* fwd work and */
|
||||
((j == I_V_SX) || (inst & MSK_SBF))) /* ext or fwd br? */
|
||||
inst = inst | (df >> 1) | MSK_SBF; /* or in fwd displ */
|
||||
else return SCPE_ARG; }
|
||||
else if (rel) { /* periph, must be rel */
|
||||
if ((st <= 0) && (st >= -0x1F) && /* relative back? */
|
||||
((j == I_V_SX) || !(inst & MSK_SBF)))
|
||||
inst = inst | ((-st & 0x1F) >> 1);
|
||||
else if ((st >= 0) && (st < 0x1F) && /* relative fwd? */
|
||||
((j == I_V_SX) || (inst & MSK_SBF)))
|
||||
inst = inst | ((t & 0x1F) >> 1);
|
||||
else return SCPE_ARG; }
|
||||
else return SCPE_ARG; /* periph & ~rel, err */
|
||||
} /* end case */
|
||||
|
||||
PUTNUM (inst, 2);
|
||||
return -1;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* id32_cpu.c: Interdata 32b CPU simulator
|
||||
|
||||
Copyright (c) 2000-2002, Robert M. Supnik
|
||||
Copyright (c) 2000-2003, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -740,7 +740,7 @@ case 0x63: /* LRA - RX */
|
|||
break;
|
||||
|
||||
case 0x40: /* STH - RX */
|
||||
WriteH (ea, R[r1] & DMASK16, VW); /* store register */
|
||||
WriteH (ea, R[r1], VW); /* store register */
|
||||
break;
|
||||
|
||||
case 0x50: /* ST - RX */
|
||||
|
@ -775,7 +775,7 @@ case 0x92: /* STBR - NO */
|
|||
R[r2] = (R[r2] & ~DMASK8) | (R[r1] & DMASK8); /* store byte */
|
||||
break;
|
||||
case 0xD2: /* STB - RX */
|
||||
WriteB (ea, R[r1] & DMASK8, VW); /* store byte */
|
||||
WriteB (ea, R[r1], VW); /* store byte */
|
||||
break;
|
||||
|
||||
case 0x34: /* EXHR - NO */
|
||||
|
@ -1291,7 +1291,7 @@ case 0xE3: /* SCP - RX */
|
|||
else WriteB ((bufa + sr) & VAMASK, R[r1], VW); /* read, R1 to mem */
|
||||
sr = sr + 1; /* inc count */
|
||||
CC_GL_32 (sr & DMASK32); /* set cc's */
|
||||
WriteH (t & VAMASK, sr & DMASK16, VW); /* rewrite */
|
||||
WriteH (t & VAMASK, sr, VW); /* rewrite */
|
||||
if ((sr > 0) && !(opnd & CCW32_FST)) /* buf switch? */
|
||||
WriteH (ea, opnd ^ CCW32_B1, VW); /* flip CCW bit */
|
||||
} /* end if */
|
||||
|
@ -1603,7 +1603,7 @@ slt = (t >> 16) & DMASK16; /* # slots */
|
|||
usd = t & DMASK16; /* # used */
|
||||
if (usd == 0) return CC_V; /* empty? */
|
||||
usd = usd - 1; /* dec used */
|
||||
WriteH (ea + Q32_USD, usd & DMASK16, VW); /* rewrite */
|
||||
WriteH (ea + Q32_USD, usd, VW); /* rewrite */
|
||||
if (flg) { /* RBL? */
|
||||
rda = ReadH ((ea + Q32_BOT) & VAMASK, VR); /* get bottom */
|
||||
if (rda == 0) rda = (slt - 1) & DMASK16; /* wrap if necc */
|
||||
|
@ -1673,7 +1673,7 @@ if (ccw & CCW32_FST) { /* fast mode? */
|
|||
t = dev_tab[dev] (dev, IO_RD, 0); /* get byte */
|
||||
WriteB (addr, t, VW); } /* write to mem */
|
||||
bufc = bufc + 1; } /* adv buf cnt */
|
||||
WriteH (ccwa + CCB32_B0C, bufc & DMASK16, VW);/* rewrite cnt */
|
||||
WriteH (ccwa + CCB32_B0C, bufc, VW); /* rewrite cnt */
|
||||
if (bufc > 0) {
|
||||
PC = ReadH (ccwa + CCB32_SUB, VR); /* get subr */
|
||||
return CC_G; } /* CC = G */
|
||||
|
@ -1709,7 +1709,7 @@ else { /* slow mode */
|
|||
PC = t << 1; /* change PC */
|
||||
R[3] = by; /* untrans char */
|
||||
return 0; } /* CC = 0 */
|
||||
WriteB (addr, t & DMASK8, VW); } /* wr trans */
|
||||
WriteB (addr, t, VW); } /* wr trans */
|
||||
else WriteB (addr, by, VW); } /* wr orig */
|
||||
t = ReadH (ccwa + CCB32_CHK, VR); /* get check wd */
|
||||
t = t ^ by; /* start LRC */
|
||||
|
@ -1719,7 +1719,7 @@ else { /* slow mode */
|
|||
else t = t >> 1; } }
|
||||
WriteH (ccwa + CCB32_CHK, t, VW); /* rewrite chk wd */
|
||||
bufc = bufc + 1; /* adv buf cnt */
|
||||
WriteH (ccwb, bufc & DMASK16, VW); /* rewrite cnt */
|
||||
WriteH (ccwb, bufc, VW); /* rewrite cnt */
|
||||
if (bufc > 0) { /* cnt pos? */
|
||||
ccw = ccw ^ CCW32_B1; /* flip buf */
|
||||
WriteH (ccwa, ccw, VW); /* rewrite */
|
||||
|
@ -1826,10 +1826,10 @@ uint32 val;
|
|||
uint32 sc = (3 - (loc & 3)) << 3;
|
||||
|
||||
if ((PSW & PSW_REL) == 0) { /* reloc off? */
|
||||
val = M[loc >> 2]; /* get mem word */
|
||||
if ((loc & ~03) == MAC_STA) { /* MAC status? */
|
||||
val = mac_sta; /* read it */
|
||||
qevent = qevent & ~EV_MAC; } } /* clr MAC intr */
|
||||
qevent = qevent & ~EV_MAC; } /* clr MAC intr */
|
||||
else val = M[loc >> 2]; } /* get mem word */
|
||||
else if (rel == 0) val = M[loc >> 2]; /* phys ref? */
|
||||
else { uint32 pa = Reloc (loc, rel); /* relocate */
|
||||
val = M[pa >> 2]; }
|
||||
|
@ -1841,10 +1841,10 @@ uint32 ReadH (uint32 loc, uint32 rel)
|
|||
uint32 val;
|
||||
|
||||
if ((PSW & PSW_REL) == 0) { /* reloc off? */
|
||||
val = M[loc >> 2]; /* get mem word */
|
||||
if ((loc & ~03) == MAC_STA) { /* MAC status? */
|
||||
val = mac_sta; /* read it */
|
||||
qevent = qevent & ~EV_MAC; } } /* clr MAC intr */
|
||||
qevent = qevent & ~EV_MAC; } /* clr MAC intr */
|
||||
else val = M[loc >> 2]; } /* get mem word */
|
||||
else if (rel == 0) val = M[loc >> 2]; /* phys ref? */
|
||||
else { uint32 pa = Reloc (loc, rel); /* relocate */
|
||||
val = M[pa >> 2]; }
|
||||
|
@ -1856,10 +1856,10 @@ uint32 ReadF (uint32 loc, uint32 rel)
|
|||
uint32 val;
|
||||
|
||||
if ((PSW & PSW_REL) == 0) { /* reloc off? */
|
||||
val = M[loc >> 2]; /* get mem word */
|
||||
if ((loc & ~03) == MAC_STA) { /* MAC status? */
|
||||
val = mac_sta; /* read it */
|
||||
qevent = qevent & ~EV_MAC; } } /* clr MAC intr */
|
||||
qevent = qevent & ~EV_MAC; } /* clr MAC intr */
|
||||
else val = M[loc >> 2]; } /* get mem word */
|
||||
else if (rel == 0) val = M[loc >> 2]; /* phys ref? */
|
||||
else { uint32 pa = Reloc (loc, rel); /* relocate */
|
||||
val = M[pa >> 2]; }
|
||||
|
@ -1894,9 +1894,9 @@ val = val & DMASK16;
|
|||
if ((PSW & PSW_REL) == 0) { /* reloc off? */
|
||||
uint32 idx = (pa - MAC_BASE) >> 2; /* check for MAC */
|
||||
if (idx <= MAC_LNT) {
|
||||
if (idx < MAC_LNT) mac_reg[idx] = ((loc & 2)?
|
||||
((mac_reg[idx] & ~DMASK16) | val):
|
||||
((mac_reg[idx] & DMASK16) | (val << 16))) & SR_MASK;
|
||||
if (idx < MAC_LNT) mac_reg[idx] = ((loc & 2)?
|
||||
((mac_reg[idx] & ~DMASK16) | val):
|
||||
((mac_reg[idx] & DMASK16) | (val << 16))) & SR_MASK;
|
||||
else {
|
||||
mac_sta = 0;
|
||||
qevent = qevent & ~EV_MAC; } } }
|
||||
|
@ -1911,6 +1911,7 @@ void WriteF (uint32 loc, uint32 val, uint32 rel)
|
|||
{
|
||||
uint32 pa = loc;
|
||||
|
||||
val = val & DMASK32;
|
||||
if (loc & 2) {
|
||||
WriteH (loc & VAMASK, (val >> 16) & DMASK16, rel);
|
||||
WriteH ((loc + 2) & VAMASK, val & DMASK16, rel);
|
||||
|
@ -1918,7 +1919,7 @@ if (loc & 2) {
|
|||
if ((PSW & PSW_REL) == 0) { /* reloc off? */
|
||||
uint32 idx = (pa - MAC_BASE) >> 2; /* check for MAC */
|
||||
if (idx <= MAC_LNT) {
|
||||
if (idx < MAC_LNT) mac_reg[idx] = val & SR_MASK;
|
||||
if (idx < MAC_LNT) mac_reg[idx] = val & SR_MASK;
|
||||
else {
|
||||
mac_sta = 0;
|
||||
qevent = qevent & ~EV_MAC; } } }
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* id32_dboot.c: Interdata 32b simulator disk bootstrap
|
||||
|
||||
Copyright (c) 2000-2002, Robert M. Supnik
|
||||
Copyright (c) 2000-2003, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -22,6 +22,8 @@
|
|||
Except as contained in this notice, the name of Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
17-Feb-03 RMS Fixed for UNIX bootstrap, upper platter bootstrap
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
|
@ -140,7 +142,7 @@ static uint8 dboot_rom[] = {
|
|||
0x11, 0xa5,
|
||||
0x06, 0xba,
|
||||
0x98, 0x49,
|
||||
0xde, 0x4d, 0x03, 0x28,
|
||||
0xde, 0x4d, 0x03, 0x2b,
|
||||
0x9d, 0x3f,
|
||||
0x22, 0x21,
|
||||
0x9d, 0x4f,
|
||||
|
@ -265,23 +267,27 @@ static uint8 dboot_rom[] = {
|
|||
|
||||
struct dboot_id {
|
||||
char *name;
|
||||
uint32 sw;
|
||||
uint32 cap;
|
||||
uint32 dtype;
|
||||
uint32 offset;
|
||||
uint32 adder;
|
||||
};
|
||||
|
||||
static struct dboot_id dboot_tab[] = {
|
||||
{ "DP", 2, 0x31, o_DP0 },
|
||||
{ "DP", 9, 0x33, o_DP0 },
|
||||
{ "DM", 64, 0x35, o_ID0 },
|
||||
{ "DM", 244, 0x36, o_ID0 },
|
||||
{ "DP", 0, 2, 0x31, o_DP0, 0 },
|
||||
{ "DP", SWMASK ('F'), 9, 0x32, o_DP0, o_DPF },
|
||||
{ "DP", 0, 9, 0x33, o_DP0, 0 },
|
||||
{ "DM", 0, 64, 0x35, o_ID0, 0 },
|
||||
{ "DM", 0, 244, 0x36, o_ID0, 0 },
|
||||
{ NULL } };
|
||||
|
||||
t_stat id_dboot (int32 u, DEVICE *dptr)
|
||||
{
|
||||
extern DIB pt_dib, sch_dib;
|
||||
extern DIB ttp_dib, sch_dib;
|
||||
extern uint32 PC;
|
||||
uint32 i, typ, ctlno, off, cap, sch_dev;
|
||||
extern int32 sim_switches;
|
||||
uint32 i, typ, ctlno, off, add, cap, sch_dev;
|
||||
UNIT *uptr;
|
||||
|
||||
DIB *ddib = (DIB *) dptr->ctxt; /* get disk DIB */
|
||||
|
@ -291,17 +297,20 @@ uptr = dptr->units + u; /* get capacity */
|
|||
cap = uptr->capac >> 20;
|
||||
for (i = typ = 0; dboot_tab[i].name != NULL; i++) {
|
||||
if ((strcmp (dboot_tab[i].name, dptr->name) == 0) &&
|
||||
((dboot_tab[i].sw == 0) || (dboot_tab[i].sw & sim_switches)) &&
|
||||
(dboot_tab[i].cap == cap)) {
|
||||
typ = dboot_tab[i].dtype;
|
||||
off = dboot_tab[i].offset; } }
|
||||
off = dboot_tab[i].offset;
|
||||
add = dboot_tab[i].adder;
|
||||
break; } }
|
||||
if (typ == 0) return SCPE_NOFNC;
|
||||
|
||||
IOWriteBlk (DBOOT_BEG, DBOOT_LEN, dboot_rom); /* copy boot */
|
||||
IOWriteB (AL_DEV, pt_dib.dno); /* bin input dev */
|
||||
IOWriteB (AL_IOC, 0x99);
|
||||
IOWriteB (AL_DSKU, ctlno + ((u + 1) * off)); /* disk param */
|
||||
IOWriteB (AL_DSKT, typ);
|
||||
IOWriteB (AL_DSKC, ctlno);
|
||||
IOWriteB (AL_DEV, ttp_dib.dno); /* bin input dev */
|
||||
IOWriteB (AL_IOC, 0xa3);
|
||||
IOWriteB (AL_DSKU, ctlno + ((u + 1) * off) + add); /* disk dev addr */
|
||||
IOWriteB (AL_DSKT, typ); /* disk type */
|
||||
IOWriteB (AL_DSKC, ctlno); /* disk ctl addr */
|
||||
IOWriteB (AL_SCH, sch_dev);
|
||||
PC = DBOOT_START;
|
||||
return SCPE_OK;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
27-Feb-03 RMS Added relative addressing support
|
||||
23-Dec-01 RMS Cloned from ID4 sources
|
||||
*/
|
||||
|
||||
|
@ -30,7 +31,7 @@
|
|||
#include <ctype.h>
|
||||
|
||||
#define MSK_SBF 0x0100
|
||||
#define SEXT15(x) (((x) & 0x4000)? ((x) | 0xFFFF8000): ((x) & 0x7FFF))
|
||||
#define SEXT15(x) (((x) & 0x4000)? ((x) | ~0x3FFF): ((x) & 0x3FFF))
|
||||
|
||||
extern DEVICE cpu_dev;
|
||||
extern DEVICE sch_dev;
|
||||
|
@ -45,8 +46,8 @@ extern UNIT cpu_unit;
|
|||
extern REG cpu_reg[];
|
||||
extern uint32 *M;
|
||||
|
||||
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val);
|
||||
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val);
|
||||
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val, t_bool cf);
|
||||
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val, t_bool cf);
|
||||
extern t_stat lp_load (FILE *fileref, char *cptr, char *fnam);
|
||||
extern pt_dump (FILE *of, char *cptr, char *fnam);
|
||||
|
||||
|
@ -286,7 +287,8 @@ static const uint32 opc_val[] = {
|
|||
|
||||
/* Print an RX specifier */
|
||||
|
||||
t_stat fprint_addr (FILE *of, t_addr addr, uint32 rx, uint32 ea1, uint32 ea2)
|
||||
t_stat fprint_addr (FILE *of, t_addr addr, uint32 rx, uint32 ea1,
|
||||
uint32 ea2, t_bool cf)
|
||||
{
|
||||
uint32 rx2;
|
||||
|
||||
|
@ -295,8 +297,13 @@ if ((ea1 & 0xC000) == 0) { /* RX1 */
|
|||
if (rx) fprintf (of, "(R%d)", rx);
|
||||
return -3; }
|
||||
if (ea1 & 0x8000) { /* RX2 */
|
||||
ea1 = addr + 4 + SEXT15 (ea1);
|
||||
fprintf (of, "%-X", ea1 & VAMASK32);
|
||||
if (cf) { /* for CPU? */
|
||||
ea1 = addr + 4 + SEXT15 (ea1);
|
||||
fprintf (of, "%-X", ea1 & VAMASK32); }
|
||||
else { /* for dev */
|
||||
int32 disp = SEXT15 (ea1); /* get disp */
|
||||
if (disp >= -4) fprintf (of, ".+%-X", disp + 4);
|
||||
else fprintf (of, ".-%-X", -4 - disp); }
|
||||
if (rx) fprintf (of, "(R%d)", rx);
|
||||
return -3; }
|
||||
rx2 = (ea1 >> 8) & 0xF;
|
||||
|
@ -351,7 +358,7 @@ if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */
|
|||
return -(vp - 1); } /* return # chars */
|
||||
|
||||
if (sw & SWMASK ('M')) { /* inst format? */
|
||||
r = fprint_sym_m (of, addr, val); /* decode inst */
|
||||
r = fprint_sym_m (of, addr, val, uptr == &cpu_unit); /* decode inst */
|
||||
if (r <= 0) return r; /* success? */
|
||||
lnt = 2; } /* no, skip 16b */
|
||||
|
||||
|
@ -366,14 +373,15 @@ return -(vp - 1);
|
|||
of = output stream
|
||||
addr = current PC
|
||||
*val = values to decode
|
||||
cf = true if parsing for CPU
|
||||
Outputs:
|
||||
return = if >= 0, error code
|
||||
if < 0, number of extra bytes retired
|
||||
*/
|
||||
|
||||
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val)
|
||||
t_stat fprint_sym_m (FILE *of, t_addr addr, t_value *val, t_bool cf)
|
||||
{
|
||||
uint32 i, j, k, inst, r1, r2, ea1, ea2, tgt, vp;
|
||||
uint32 i, j, k, inst, r1, r2, ea1, ea2, vp;
|
||||
|
||||
vp = 0;
|
||||
GETNUM (inst,2); /* high 16b */
|
||||
|
@ -384,49 +392,45 @@ for (i = 0; opc_val[i] != 0xFFFF; i++) { /* loop thru ops */
|
|||
if ((opc_val[i] & 0xFFFF) == (inst & masks[j])) { /* match? */
|
||||
r1 = (inst >> 4) & 0xF;
|
||||
r2 = inst & 0xF;
|
||||
fprintf (of, "%s ", opcode[i]); /* print opcode */
|
||||
switch (j) { /* case on class */
|
||||
case I_V_MR: /* mask-register */
|
||||
fprintf (of, "%s %-X,R%d", opcode[i], r1, r2);
|
||||
return -1;
|
||||
fprintf (of, "%-X,R%d", r1, r2);
|
||||
return -1;
|
||||
case I_V_RR: /* register-register */
|
||||
case I_V_FF: /* floating-floating */
|
||||
fprintf (of, "%s R%d,R%d", opcode[i], r1, r2);
|
||||
return -1;
|
||||
fprintf (of, "R%d,R%d", r1, r2);
|
||||
return -1;
|
||||
case I_V_SI: /* short immediate */
|
||||
fprintf (of, "%s R%d,%-X", opcode[i], r1, r2);
|
||||
return -1;
|
||||
fprintf (of, "R%d,%-X", r1, r2);
|
||||
return -1;
|
||||
case I_V_SB: /* short branch */
|
||||
if (inst & MSK_SBF) tgt = addr + r2 + r2;
|
||||
else tgt = addr - r2 - r2;
|
||||
fprintf (of, "%s %-X,%-X", opcode[i], r1, tgt);
|
||||
return -1;
|
||||
fprintf (of, "%-X,", r1);
|
||||
case I_V_SX: /* ext short branch */
|
||||
if (inst & MSK_SBF) tgt = addr + r2 + r2;
|
||||
else tgt = addr - r2 - r2;
|
||||
fprintf (of, "%s %-X", opcode[i], tgt);
|
||||
return -1;
|
||||
if (cf) fprintf (of, "%-X", ((inst & MSK_SBF)?
|
||||
(addr + r2 + r2): (addr - r2 - r2)));
|
||||
else fprintf (of, ((inst & MSK_SBF)?
|
||||
".+%-X": ".-%X"), r2 + r2);
|
||||
return -1;
|
||||
case I_V_R: /* register */
|
||||
fprintf (of, "%s R%d", opcode[i], r2);
|
||||
return -1;
|
||||
fprintf (of, "R%d", r2);
|
||||
return -1;
|
||||
case I_V_RI: /* reg-immed */
|
||||
fprintf (of, "%s R%d,%-X", opcode[i], r1, ea1);
|
||||
if (r2) fprintf (of, "(R%d)", r2);
|
||||
return -3;
|
||||
fprintf (of, "R%d,%-X", r1, ea1);
|
||||
if (r2) fprintf (of, "(R%d)", r2);
|
||||
return -3;
|
||||
case I_V_RF: /* reg-full imm */
|
||||
fprintf (of, "%s R%d,%-X", opcode[i], r1,
|
||||
(ea1 << 16) | ea2);
|
||||
if (r2) fprintf (of, "(R%d)", r2);
|
||||
return -5;
|
||||
fprintf (of, "R%d,%-X", r1, (ea1 << 16) | ea2);
|
||||
if (r2) fprintf (of, "(R%d)", r2);
|
||||
return -5;
|
||||
case I_V_MX: /* mask-memory */
|
||||
fprintf (of, "%s %-X,", opcode[i], r1);
|
||||
return fprint_addr (of, addr, r2, ea1, ea2);
|
||||
fprintf (of, "%-X,", r1);
|
||||
return fprint_addr (of, addr, r2, ea1, ea2, cf);
|
||||
case I_V_RX: /* register-memory */
|
||||
case I_V_FX: /* floating-memory */
|
||||
fprintf (of, "%s R%d,", opcode[i], r1);
|
||||
return fprint_addr (of, addr, r2, ea1, ea2);
|
||||
fprintf (of, "R%d,", r1);
|
||||
case I_V_X: /* memory */
|
||||
fprintf (of, "%s ", opcode[i]);
|
||||
return fprint_addr (of, addr, r2, ea1, ea2); }
|
||||
return fprint_addr (of, addr, r2, ea1, ea2, cf); }
|
||||
return SCPE_IERR; } /* end if */
|
||||
} /* end for */
|
||||
return SCPE_ARG; /* no match */
|
||||
|
@ -490,6 +494,41 @@ if (*tptr == '(') { /* index? */
|
|||
if (*tptr != 0) return SCPE_ARG;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Address
|
||||
|
||||
Inputs:
|
||||
*cptr = pointer to input string
|
||||
**tptr = pointer to moved pointer
|
||||
*ea = effective address
|
||||
*rel = relative flag
|
||||
addr = base address
|
||||
cf = true if parsing for CPU
|
||||
Outputs:
|
||||
status = SCPE_OK if ok, else error code
|
||||
*/
|
||||
|
||||
t_stat get_addr (char *cptr, char **tptr, t_addr *ea, t_bool *rel,
|
||||
t_addr addr, t_bool cf)
|
||||
{
|
||||
int32 sign = 1;
|
||||
|
||||
*ea = 0;
|
||||
if (*cptr == '.') { /* relative? */
|
||||
*rel = TRUE;
|
||||
cptr++;
|
||||
if (cf) *ea = addr;
|
||||
if (*cptr == '+') cptr++; /* .+? */
|
||||
else if (*cptr == '-') { /* .-? */
|
||||
sign = -1;
|
||||
cptr++; }
|
||||
else return SCPE_OK; }
|
||||
else *rel = FALSE;
|
||||
errno = 0;
|
||||
*ea = *ea + (sign * ((int32) strtoul (cptr, tptr, 16)));
|
||||
if (errno || (cptr == *tptr)) return SCPE_ARG;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
#define PUTNUM(d,n) for (k = n; k > 0; k--) \
|
||||
val[vp++] = (d >> ((k - 1) * 8)) & 0xFF
|
||||
|
@ -523,9 +562,8 @@ if ((sw & SWMASK ('A')) || (sw & SWMASK ('C'))) { /* char format? */
|
|||
val[vp++] = *cptr++; }
|
||||
return -(vp - 1); } /* return # chars */
|
||||
|
||||
if (uptr == &cpu_unit) { /* cpu only */
|
||||
r = parse_sym_m (cptr, addr, val); /* try to parse inst */
|
||||
if (r <= 0) return r; }
|
||||
r = parse_sym_m (cptr, addr, val, uptr == &cpu_unit); /* try to parse */
|
||||
if (r <= 0) return r;
|
||||
|
||||
num = (int32) get_uint (cptr, rdx, maxv[lnt], &r); /* get number */
|
||||
if (r != SCPE_OK) return r;
|
||||
|
@ -539,16 +577,18 @@ return -(lnt - 1);
|
|||
*cptr = pointer to input string
|
||||
addr = current PC
|
||||
*val = pointer to output values
|
||||
cf = true if parsing for CPU
|
||||
Outputs:
|
||||
status = > 0 error code
|
||||
<= 0 -number of extra words
|
||||
*/
|
||||
|
||||
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val)
|
||||
t_stat parse_sym_m (char *cptr, t_addr addr, t_value *val, t_bool cf)
|
||||
{
|
||||
uint32 i, j, k, t, df, db, inst, ea, vp;
|
||||
uint32 i, j, k, df, db, t, inst, vp;
|
||||
int32 st, r1, r2, rx2;
|
||||
t_stat r;
|
||||
t_bool rel;
|
||||
char *tptr, gbuf[CBUFSIZE];
|
||||
|
||||
vp = 0;
|
||||
|
@ -580,9 +620,8 @@ case I_V_R: /* register */
|
|||
case I_V_FX: /* float-memory */
|
||||
case I_V_MX: case I_V_RX: /* mask/reg-memory */
|
||||
case I_V_X: /* memory */
|
||||
errno = 0;
|
||||
ea = strtoul (gbuf, &tptr, 16); /* get address */
|
||||
if (errno || (gbuf == tptr)) return SCPE_ARG; /* error? */
|
||||
r = get_addr (gbuf, &tptr, &t, &rel, addr, cf); /* get addr */
|
||||
if (r != SCPE_OK) return SCPE_ARG; /* error? */
|
||||
rx2 = 0; /* assume no 2nd */
|
||||
if (*tptr == '(') { /* index? */
|
||||
if ((r2 = get_reg (tptr + 1, &tptr, R_R)) < 0)
|
||||
|
@ -594,47 +633,65 @@ case I_V_X: /* memory */
|
|||
if (*tptr++ != ')') return SCPE_ARG; } /* all done? */
|
||||
if (*tptr != 0) return SCPE_ARG;
|
||||
PUTNUM (inst, 2); /* store inst */
|
||||
if (!cf && rel) { /* periph, rel */
|
||||
st = t - 4; /* displ */
|
||||
if (rx2 || (st > 0x3FFF) || (st < -0x4000)) /* rx2 or too big? */
|
||||
return SCPE_ARG;
|
||||
t = (st & 0x7FFF) | 0x8000;
|
||||
PUTNUM (t, 2); /* store displ */
|
||||
return -3; }
|
||||
if (rx2 == 0) { /* no 2nd? */
|
||||
if (ea < 0x4000) { /* RX1? */
|
||||
PUTNUM (ea, 2); /* store ea */
|
||||
if (t < 0x4000) { /* RX1? */
|
||||
PUTNUM (t, 2); /* store ea */
|
||||
return -3; }
|
||||
st = (ea - (addr + 4)); /* displ */
|
||||
if ((st <= 0x3FFF) && (st >= -0x4000)) { /* RX2? */
|
||||
st = (t - (addr + 4)); /* displ */
|
||||
if (cf && (st <= 0x3FFF) && (st >= -0x4000)) { /* RX2? CPU only */
|
||||
t = (st & 0x7FFF) | 0x8000;
|
||||
PUTNUM (t, 2); /* store displ */
|
||||
return -3; } }
|
||||
ea = (ea & VAMASK32) | 0x40000000 | (rx2 << 24);
|
||||
PUTNUM (ea, 4); /* RX3 */
|
||||
t = (t & VAMASK32) | 0x40000000 | (rx2 << 24);
|
||||
PUTNUM (t, 4); /* RX3 */
|
||||
return -5;
|
||||
|
||||
case I_V_RI: /* 16b immediate */
|
||||
r = get_imm (gbuf, &ea, &inst, DMASK16); /* process imm */
|
||||
r = get_imm (gbuf, &t, &inst, DMASK16); /* process imm */
|
||||
if (r != SCPE_OK) return r;
|
||||
PUTNUM (inst, 2); /* store inst */
|
||||
PUTNUM (ea, 2); /* store 16b imm */
|
||||
PUTNUM (t, 2); /* store 16b imm */
|
||||
return -3;
|
||||
|
||||
case I_V_RF:
|
||||
r = get_imm (gbuf, &ea, &inst, DMASK32); /* process imm */
|
||||
r = get_imm (gbuf, &t, &inst, DMASK32); /* process imm */
|
||||
if (r != SCPE_OK) return r;
|
||||
PUTNUM (inst, 2); /* store inst */
|
||||
PUTNUM (ea, 4); /* store 32b imm */
|
||||
PUTNUM (t, 4); /* store 32b imm */
|
||||
return -5;
|
||||
|
||||
case I_V_SB: case I_V_SX: /* short branches */
|
||||
t = get_uint (gbuf, 16, DMASK16, &r); /* get addr */
|
||||
if ((r != SCPE_OK) || (t & 1)) return r; /* error if odd */
|
||||
db = (addr - t) & 0x1F; /* back displ */
|
||||
df = (t - addr) & 0x1F; /* fwd displ */
|
||||
if ((t == ((addr - db) & VAMASK16)) && /* back work and */
|
||||
((j == I_V_SX) || !(inst & MSK_SBF))) { /* ext or back br? */
|
||||
inst = inst | (db >> 1); /* or in back displ */
|
||||
break; }
|
||||
if ((t == ((addr + df) & VAMASK16)) && /* fwd work and */
|
||||
((j == I_V_SX) || (inst & MSK_SBF))) { /* ext or fwd br? */
|
||||
inst = inst | (df >> 1) | MSK_SBF; /* or in fwd displ */
|
||||
break; }
|
||||
return SCPE_ARG; } /* end case */
|
||||
r = get_addr (gbuf, &tptr, &t, &rel, addr, cf); /* get addr */
|
||||
if ((r != SCPE_OK) || (t & 1) || *tptr) /* error if odd */
|
||||
return SCPE_ARG;
|
||||
st = t; /* signed version */
|
||||
if (cf) { /* for CPU? */
|
||||
db = (addr - t) & 0x1F; /* back displ */
|
||||
df = (t - addr) & 0x1F; /* fwd displ */
|
||||
if ((t == ((addr - db) & VAMASK16)) && /* back work and */
|
||||
((j == I_V_SX) || !(inst & MSK_SBF))) /* ext or back br? */
|
||||
inst = inst | (db >> 1); /* or in back displ */
|
||||
else if ((t == ((addr + df) & VAMASK16)) && /* fwd work and */
|
||||
((j == I_V_SX) || (inst & MSK_SBF))) /* ext or fwd br? */
|
||||
inst = inst | (df >> 1) | MSK_SBF; /* or in fwd displ */
|
||||
else return SCPE_ARG; }
|
||||
else if (rel) { /* periph, must be rel */
|
||||
if ((st <= 0) && (st >= -0x1F) && /* relative back? */
|
||||
((j == I_V_SX) || !(inst & MSK_SBF)))
|
||||
inst = inst | ((-st & 0x1F) >> 1);
|
||||
else if ((st >= 0) && (st < 0x1F) && /* relative fwd? */
|
||||
((j == I_V_SX) || (inst & MSK_SBF)))
|
||||
inst = inst | ((t & 0x1F) >> 1);
|
||||
else return SCPE_ARG; }
|
||||
else return SCPE_ARG; /* periph & ~rel, err */
|
||||
} /* end case */
|
||||
|
||||
PUTNUM (inst, 2);
|
||||
return -1;
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
The author gratefully acknowledges the help of Carl Friend and Al Kossow,
|
||||
who provided key documents about the Interdata product line.
|
||||
|
||||
28-Feb-03 RMS Changed magtape device default to 0x85
|
||||
*/
|
||||
|
||||
#include "sim_defs.h" /* simulator defns */
|
||||
|
@ -260,12 +262,12 @@ typedef struct interdib DIB;
|
|||
#define d_LPT 0x62 /* line printer */
|
||||
#define d_PIC 0x6C /* interval timer */
|
||||
#define d_LFC 0x6D /* line freq clk */
|
||||
#define d_MT 0x85 /* magtape */
|
||||
#define o_MT0 0x10
|
||||
#define d_DPC 0xB6 /* disk controller */
|
||||
#define o_DP0 0x10
|
||||
#define o_DPF 0x01 /* offset to fixed */
|
||||
#define d_FD 0xC1 /* floppy disk */
|
||||
#define d_MT 0xC5 /* magtape */
|
||||
#define o_MT0 0x10
|
||||
#define d_SCH 0xF0 /* selector chan */
|
||||
#define d_IDC 0xFB /* MSM disk ctrl */
|
||||
#define o_ID0 0x01
|
||||
|
|
|
@ -561,8 +561,8 @@ END OF TEST
|
|||
---
|
||||
Common magtape diagnostic
|
||||
|
||||
sim> set mt dev=85 ; 800 bpi default
|
||||
sim> att -e pt0 diag.bin
|
||||
sim> att mt foo.tap
|
||||
sim> br c4
|
||||
sim> boot pt0
|
||||
|
||||
|
@ -577,9 +577,6 @@ COMMON MAGNETIC TAPE TEST PROGRAM 06-172R02
|
|||
*MODE 0 ; prog i/o and selch
|
||||
*RUN
|
||||
|
||||
*MODE 0
|
||||
*RUN
|
||||
|
||||
TEST 00
|
||||
NO ERROR
|
||||
TEST 01
|
||||
|
@ -880,7 +877,7 @@ Bugs found
|
|||
65. PIC, LFC: ric reloaded from output buffer on count overflow
|
||||
66. PIC, LFC: added diagnostic mode, revised use of count vs timer
|
||||
67. DP: track increment algorithm incorrect
|
||||
68. DP,IDC: incorrectly setting overrun for less than full sector reads
|
||||
68. DP, IDC: incorrectly setting overrun for less than full sector reads
|
||||
69. DP: should interrupt on detach (offline)
|
||||
70. FD: high water mark not updated on write
|
||||
71. FD: deleted data not implemented, required for diagnostic
|
||||
|
@ -905,4 +902,6 @@ Bugs found
|
|||
90. IDC: drive command 0x30 is an instant NOP
|
||||
91. IDC: set cylinder with invalid cylinder sets SKI
|
||||
92. IDC: read with invalid head sets ACF, not DTE
|
||||
93. DP, IDC: write with cylinder overflow advanced selch pointer
|
||||
94. MT: read error must stop selector channel (if active)
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
To: Users
|
||||
From: Bob Supnik
|
||||
Subj: Interdata 16b/32b Simulator Usage
|
||||
Date: 15-Jan-2003
|
||||
Date: 15-Mar-2003
|
||||
|
||||
COPYRIGHT NOTICE
|
||||
|
||||
The following copyright notice applies to both the SIMH source and binary:
|
||||
|
||||
Original code published in 1993-2002, written by Robert M Supnik
|
||||
Original code published in 1993-2003, written by Robert M Supnik
|
||||
Copyright (c) 1993-2003, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
|
@ -91,7 +91,7 @@ DP 2.5MB/10MB cartridge disk
|
|||
DM mass storage module (MSM)/intelligent (IDC) disk controller
|
||||
MT magnetic tape
|
||||
PAS programmable asynchronous line controller
|
||||
PASL programmable asyhchronous lines, up to 32
|
||||
PASL programmable asynchronous lines, up to 32
|
||||
|
||||
The Interdata simulator implements two unique stop conditions:
|
||||
|
||||
|
@ -268,6 +268,10 @@ channels can be changed with the command:
|
|||
|
||||
SET SELCH CHANNELS=num
|
||||
|
||||
All the state for a selector channel can be displayed with the command:
|
||||
|
||||
SHOW SELCH num
|
||||
|
||||
The selector channels implement these registers:
|
||||
|
||||
name size comments
|
||||
|
@ -398,7 +402,7 @@ UC, 7B, or 8B. In UC mode, lower case input and output characters
|
|||
are automatically converted to upper case. In 7B mode, input and
|
||||
output characters are masked to 7 bits. In 8B mode, characters
|
||||
are not modified. Changing the mode of either unit changes both.
|
||||
The default mode is UC.
|
||||
The default mode is 7B.
|
||||
|
||||
To simulate pressing the break key, stop the simulator and use
|
||||
the command:
|
||||
|
@ -412,6 +416,8 @@ The PASLA console interface implements these registers:
|
|||
|
||||
name size comments
|
||||
|
||||
CMD 16 command register
|
||||
STA 8 status register
|
||||
KBUF 8 input buffer
|
||||
KPOS 32 number of characters input
|
||||
KTIME 24 input polling interval
|
||||
|
@ -480,7 +486,14 @@ Error handling is as follows:
|
|||
|
||||
2.4.5 Line Frequency Clock (LFC)
|
||||
|
||||
The line frequency clock (LFC) implements these registers:
|
||||
The line frequency clock (LFC) frequency can be adjusted as follows:
|
||||
|
||||
SET LFC 60HZ set frequency to 60Hz
|
||||
SET LFC 50HZ set frequency to 50Hz
|
||||
|
||||
The default is 60Hz.
|
||||
|
||||
The line frequency clock implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
|
@ -488,10 +501,9 @@ The line frequency clock (LFC) implements these registers:
|
|||
IENB 1 clock interrupt enable
|
||||
IARM 1 clock interrupt armed
|
||||
TIME 24 clock frequency
|
||||
TPS 8 ticks per second (120 or 100)
|
||||
|
||||
The real-time clock autocalibrates; the clock interval is adjusted up or
|
||||
down so that the clock tracks actual elapsed time.
|
||||
The line frequency clock autocalibrates; the clock interval is adjusted
|
||||
up or down so that the clock tracks actual elapsed time.
|
||||
|
||||
2.4.6 Programmable Interval Clock (PIC)
|
||||
|
||||
|
@ -509,8 +521,9 @@ The programmable interval clock (PIC) implements these registers:
|
|||
IENB 1 clock interrupt enable
|
||||
IARM 1 clock interrupt armed
|
||||
|
||||
If the interval requested is longer than 1 msec, the programmable clock
|
||||
auto-calibrates; if not, it simply counts instructions.
|
||||
If the interval requested is longer than 1 msec, and a multiple of
|
||||
1 msec, the programmable clock auto-calibrates; if not, it simply
|
||||
counts instructions.
|
||||
|
||||
2.4.7 Floppy Disk Controller (FD)
|
||||
|
||||
|
@ -634,7 +647,8 @@ block 0, and uses that to locate the volume directory. It then searches
|
|||
the directory for a filename of the form OS16xxxx.hhh or OS32xxxx.hhh,
|
||||
where the xxxx is ignored and hhh is the ASCII form of the extension from
|
||||
locations 7E:7F. The 32b bootstrap can also boot Wollongong UNIX; locations
|
||||
7E:7F must be 0.
|
||||
7E:7F must be 0. The bootstrap normally boots from the first (removable)
|
||||
platter in a 5440; to boot from the second (fixed) platter, use BOOT -F.
|
||||
|
||||
All drives have 256 8b bytes per sector. The other disk parameters are:
|
||||
|
||||
|
@ -877,7 +891,9 @@ number, optionally preceded by R, between 1 and F (15).
|
|||
Instruction input uses standard Interdata assembler syntax. There are
|
||||
nine instruction classes: short branch, extended short branch, short
|
||||
immediate, 16b immediate, 32b immediate, register, register-register,
|
||||
memory, and register-memory.
|
||||
memory, and register-memory. Addresses, where required, can be
|
||||
specified as either absolute numbers or relative to the current
|
||||
location (.+n or .-n).
|
||||
|
||||
Short branch instructions have the format
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* id_dp.c: Interdata 2.5MB/10MB cartridge disk simulator
|
||||
|
||||
Copyright (c) 2001-2002, Robert M. Supnik
|
||||
Copyright (c) 2001-2003, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -24,6 +24,8 @@
|
|||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
dp M46-421 2.5MB/10MB cartridge disk
|
||||
|
||||
16-Feb-03 RMS Fixed read to test transfer ok before selch operation
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
|
@ -133,6 +135,7 @@ static struct drvtyp drv_tab[] = {
|
|||
{ 0 } };
|
||||
|
||||
extern uint32 int_req[INTSZ], int_enb[INTSZ];
|
||||
extern FILE *sim_log;
|
||||
|
||||
uint8 dpxb[DP_NUMBY]; /* xfer buffer */
|
||||
uint32 dp_bptr = 0; /* buffer ptr */
|
||||
|
@ -148,6 +151,7 @@ uint32 dpd_arm[DP_NUMDR] = { 0 }; /* drives armed */
|
|||
int32 dp_stime = 100; /* seek latency */
|
||||
int32 dp_rtime = 100; /* rotate latency */
|
||||
int32 dp_wtime = 1; /* word time */
|
||||
int32 dp_log = 0; /* debug log */
|
||||
uint8 dp_tplte[(2 * DP_NUMDR) + 2]; /* fix/rmv + ctrl + end */
|
||||
|
||||
DEVICE dp_dev;
|
||||
|
@ -208,6 +212,7 @@ REG dp_reg[] = {
|
|||
DP_NUMDR, REG_RO) },
|
||||
{ URDATA (CAPAC, dp_unit[0].capac, 10, 31, 0,
|
||||
DP_NUMDR, PV_LEFT | REG_HRO) },
|
||||
{ FLDATA (LOG, dp_log, 0), REG_HIDDEN },
|
||||
{ HRDATA (DEVNO, dp_dib.dno, 8), REG_HRO },
|
||||
{ HRDATA (SELCH, dp_dib.sch, 2), REG_HRO },
|
||||
{ NULL } };
|
||||
|
@ -260,6 +265,8 @@ case IO_RD: /* read data */
|
|||
else dp_sta = dp_sta | STA_BSY; /* xfr? set busy */
|
||||
return dp_db; /* return data */
|
||||
case IO_WD: /* write data */
|
||||
if (sim_log && dp_log) fprintf (sim_log,
|
||||
">>DPC WD = %02X, STA = %02X\n", dat, dp_sta);
|
||||
if (dp_sta & STC_IDL) dp_hdsc = dat & HS_MASK; /* idle? hdsc */
|
||||
else { /* data xfer */
|
||||
dp_sta = dp_sta | STA_BSY; /* set busy */
|
||||
|
@ -270,6 +277,8 @@ case IO_SS: /* status */
|
|||
if (t & SETC_EX) t = t | STA_EX; /* test for EX */
|
||||
return t;
|
||||
case IO_OC: /* command */
|
||||
if (sim_log && dp_log) fprintf (sim_log,
|
||||
">>DPC OC = %02X, STA = %02X\n", dat, dp_sta);
|
||||
f = dat & CMC_MASK; /* get cmd */
|
||||
if (f & CMC_CLR) { /* clear? */
|
||||
dp_reset (&dp_dev); /* reset world */
|
||||
|
@ -305,6 +314,8 @@ case IO_ADR: /* select */
|
|||
if (dp_sta & STC_IDL) dp_svun = dev; /* idle? save unit */
|
||||
return BY; /* byte only */
|
||||
case IO_WD: /* write data */
|
||||
if (sim_log && dp_log) fprintf (sim_log,
|
||||
">>DP%d WD = %02X, STA = %02X\n", u, dat, dp_sta);
|
||||
if (GET_DTYPE (uptr->flags) == TYPE_2315) /* 2.5MB drive? */
|
||||
dp_cyl = dat & 0xFF; /* cyl is 8b */
|
||||
else dp_cyl = ((dp_cyl << 8) | dat) & DMASK16; /* insert byte */
|
||||
|
@ -318,6 +329,8 @@ case IO_SS: /* status */
|
|||
if (t & SETD_EX) t = t | STA_EX; /* test for ex */
|
||||
return t;
|
||||
case IO_OC: /* command */
|
||||
if (sim_log && dp_log) fprintf (sim_log,
|
||||
">>DP%d OC = %02X, STA = %02X\n", u, dat, dp_sta);
|
||||
dpd_arm[u] = int_chg (v_DPC + u + 1, dat, dpd_arm[u]);
|
||||
if (dat & CMD_SK) t = dp_cyl; /* seek? get cyl */
|
||||
else if (dat & CMD_RST) t = 0; /* rest? cyl 0 */
|
||||
|
@ -378,9 +391,9 @@ case CMC_RD: /* read */
|
|||
|
||||
case CMC_WR: /* write */
|
||||
if (sch_actv (dp_dib.sch, dp_dib.dno)) { /* sch transfer? */
|
||||
if (dp_dter (uptr, dp_1st)) return SCPE_OK; /* check xfr err */
|
||||
dp_bptr = sch_rdmem (dp_dib.sch, dpxb, DP_NUMBY); /* read from mem */
|
||||
dp_db = dpxb[dp_bptr - 1]; /* last byte */
|
||||
if (dp_dter (uptr, dp_1st)) return SCPE_OK; /* check xfr err */
|
||||
if (r = dp_wds (uptr)) return r; /* write sec, err? */
|
||||
dp_1st = 0;
|
||||
if (sch_actv (dp_dib.sch, dp_dib.dno)) { /* more to do? */
|
||||
|
@ -440,8 +453,10 @@ if (((uptr->flags & UNIT_ATT) == 0) || /* not attached? */
|
|||
hd = GET_SRF (dp_hdsc); /* get head */
|
||||
sc = GET_SEC (dp_hdsc); /* get sector */
|
||||
if (dp_cyl != (uint32) uptr->CYL) { /* wrong cylinder? */
|
||||
dp_done (STC_ACF); /* error, done */
|
||||
return TRUE; }
|
||||
if (dp_cyl == 0) uptr->CYL = 0;
|
||||
else {
|
||||
dp_done (STC_ACF); /* error, done */
|
||||
return TRUE; } }
|
||||
if (sc >= DP_NUMSC) { /* bad sector? */
|
||||
dp_done (STC_OVR); /* error, done */
|
||||
return TRUE; }
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* id_idc.c: Interdata MSM/IDC disk controller simulator
|
||||
|
||||
Copyright (c) 2001-2002, Robert M. Supnik
|
||||
Copyright (c) 2001-2003, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -25,6 +25,8 @@
|
|||
|
||||
idc MSM/IDC disk controller
|
||||
|
||||
16-Feb-03 RMS Fixed read to test transfer ok before selch operation
|
||||
|
||||
Note: define flag ID_IDC to enable the extra functions of the intelligent
|
||||
disk controller
|
||||
*/
|
||||
|
@ -490,8 +492,7 @@ case CMC_RUNC: /* read uncorr */
|
|||
#endif
|
||||
case CMC_RD: /* read */
|
||||
if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* sch transfer? */
|
||||
if (idc_dter (uptr, idc_1st)) return SCPE_OK; /* dte? done */
|
||||
/* fseek done */
|
||||
if (idc_dter (uptr, idc_1st)) return SCPE_OK; /* dte? done */
|
||||
if (r = idc_rds (uptr)) return r; /* read sec, err? */
|
||||
idc_1st = 0;
|
||||
t = sch_wrmem (idc_dib.sch, idcxb, IDC_NUMBY); /* write mem */
|
||||
|
@ -504,9 +505,9 @@ case CMC_RD: /* read */
|
|||
|
||||
case CMC_WR: /* write */
|
||||
if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* sch transfer? */
|
||||
if (idc_dter (uptr, idc_1st)) return SCPE_OK; /* dte? done */
|
||||
idc_bptr = sch_rdmem (idc_dib.sch, idcxb, IDC_NUMBY); /* read mem */
|
||||
idc_db = idcxb[idc_bptr - 1]; /* last byte */
|
||||
if (idc_dter (uptr, idc_1st)) return SCPE_OK; /* dte? done */
|
||||
if (r = idc_wds (uptr)) return r; /* write sec, err? */
|
||||
idc_1st = 0;
|
||||
if (sch_actv (idc_dib.sch, idc_dib.dno)) { /* more to do? */
|
||||
|
|
|
@ -35,8 +35,7 @@
|
|||
Interdata I/O uses the following interconnected tables:
|
||||
|
||||
dev_tab[dev] Indexed by device number, points to the I/O instruction
|
||||
processing routine for the device. Initialized in the
|
||||
device reset routine.
|
||||
processing routine for the device.
|
||||
|
||||
sch_tab[dev] Indexed by device number, if non-zero, the number + 1
|
||||
of the selector channel used by the device.
|
||||
|
@ -81,7 +80,8 @@ uint8 sch_tplte[SCH_NUMCH + 1]; /* dnum template */
|
|||
uint32 sch (uint32 dev, uint32 op, uint32 dat);
|
||||
void sch_ini (t_bool dtpl);
|
||||
t_stat sch_reset (DEVICE *dptr);
|
||||
t_stat sch_vchan (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat sch_set_nchan (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat sch_show_reg (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
|
||||
/* Selector channel data structures
|
||||
|
||||
|
@ -110,7 +110,15 @@ REG sch_reg[] = {
|
|||
|
||||
MTAB sch_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_VAL, 0, "channels", "CHANNELS",
|
||||
&sch_vchan, NULL, &sch_reg[0] },
|
||||
&sch_set_nchan, NULL, &sch_reg[0] },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "0", NULL,
|
||||
NULL, &sch_show_reg, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "1", NULL,
|
||||
NULL, &sch_show_reg, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 2, "2", NULL,
|
||||
NULL, &sch_show_reg, NULL },
|
||||
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 3, "3", NULL,
|
||||
NULL, &sch_show_reg, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, &sch_dib },
|
||||
{ 0 } };
|
||||
|
@ -298,7 +306,7 @@ return SCPE_OK;
|
|||
|
||||
/* Set number of channels */
|
||||
|
||||
t_stat sch_vchan (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
t_stat sch_set_nchan (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
DEVICE *dptr;
|
||||
DIB *dibp;
|
||||
|
@ -323,6 +331,21 @@ sch_reset_ch (sch_max); /* reset chan */
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Show channel registers */
|
||||
|
||||
t_stat sch_show_reg (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
if (val < 0) return SCPE_IERR;
|
||||
if (val >= (int32) sch_max) fprintf (st, "Channel %d disabled\n", val);
|
||||
else { fprintf (st, "SA: %05X\n", sch_sa[val]);
|
||||
fprintf (st, "EA: %05X\n", sch_ea[val]);
|
||||
fprintf (st, "CMD: %02X\n", sch_cmd[val]);
|
||||
fprintf (st, "DEV: %02X\n", sch_sdv[val]);
|
||||
fprintf (st, "RDP: %X\n", sch_rdp[val]);
|
||||
fprintf (st, "WDC: %X\n", sch_wdc[val]); }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Initialize template */
|
||||
|
||||
void sch_ini (t_bool dtpl)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* id_mt.c: Interdata magnetic tape simulator
|
||||
|
||||
Copyright (c) 2001-2002, Robert M Supnik
|
||||
Copyright (c) 2001-2003, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -25,6 +25,9 @@
|
|||
|
||||
mt M46-494 dual density 9-track magtape controller
|
||||
|
||||
28-Feb-03 RMS Revised for magtape library
|
||||
20-Feb-03 RMS Fixed read to stop selch on error
|
||||
|
||||
Magnetic tapes are represented as a series of variable 8b records
|
||||
of the form:
|
||||
|
||||
|
@ -42,15 +45,11 @@
|
|||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
#include "sim_tape.h"
|
||||
|
||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
||||
#define UNIT_V_PNU (UNIT_V_UF + 1) /* pos not updated */
|
||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
||||
#define UNIT_PNU (1 << UNIT_V_PNU)
|
||||
#define UST u3 /* unit status */
|
||||
#define UCMD u4 /* unit command */
|
||||
#define MT_MAXFR (1 << 16) /* max transfer */
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
|
||||
/* Command - in UCMD */
|
||||
|
||||
|
@ -98,15 +97,12 @@ static const uint8 bad_cmd[64] = {
|
|||
|
||||
DEVICE mt_dev;
|
||||
uint32 mt (uint32 dev, uint32 op, uint32 dat);
|
||||
t_bool mt_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
||||
t_bool mt_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
||||
t_bool mt_forwsp (UNIT *uptr, int32 *err);
|
||||
t_bool mt_backsp (UNIT *uptr, int32 *err);
|
||||
t_stat mt_svc (UNIT *uptr);
|
||||
t_stat mt_reset (DEVICE *dptr);
|
||||
t_stat mt_attach (UNIT *uptr, char *cptr);
|
||||
t_stat mt_detach (UNIT *uptr);
|
||||
t_stat mt_boot (int32 unitno, DEVICE *dptr);
|
||||
t_stat mt_map_err (UNIT *uptr, t_stat st);
|
||||
|
||||
/* MT data structures
|
||||
|
||||
|
@ -146,8 +142,8 @@ REG mt_reg[] = {
|
|||
{ NULL } };
|
||||
|
||||
MTAB mt_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, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "SELCH", "SELCH",
|
||||
|
@ -200,7 +196,7 @@ case IO_OC: /* command */
|
|||
if (((uptr->flags & UNIT_ATT) == 0) || /* ignore if unatt */
|
||||
bad_cmd[f] || /* or bad cmd */
|
||||
(((f == MTC_WR) || (f == MTC_WEOF)) && /* or write */
|
||||
(uptr->flags & UNIT_WPRT))) break; /* and protected */
|
||||
sim_tape_wrp (uptr))) break; /* and protected */
|
||||
for (i = 0; i < MT_NUMDR; i++) { /* check other drvs */
|
||||
if (sim_is_active (&mt_unit[i]) && /* active? */
|
||||
(mt_unit[i].UCMD != MTC_REW)) { /* not rewind? */
|
||||
|
@ -238,16 +234,11 @@ return 0;
|
|||
|
||||
t_stat mt_svc (UNIT *uptr)
|
||||
{
|
||||
uint32 i, pnu;
|
||||
int32 err;
|
||||
uint32 i;
|
||||
int32 u = uptr - mt_dev.units;
|
||||
uint32 dev = mt_dib.dno + (u * o_MT0);
|
||||
t_mtrlnt tbc;
|
||||
static t_mtrlnt bceof = { 0 };
|
||||
|
||||
err = 0;
|
||||
pnu = MT_TST_PNU (uptr); /* get pos not upd */
|
||||
MT_CLR_PNU (uptr); /* and clear */
|
||||
t_stat st, r = SCPE_OK;
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
|
||||
uptr->UCMD = 0; /* clr cmd */
|
||||
|
@ -274,8 +265,8 @@ if (uptr->UCMD & MTC_STOP1) { /* stop, gen EOM? */
|
|||
switch (uptr->UCMD) { /* case on function */
|
||||
|
||||
case MTC_REW: /* rewind */
|
||||
sim_tape_rewind (uptr); /* reposition */
|
||||
uptr->UCMD = 0; /* clr cmd */
|
||||
uptr->pos = 0; /* update position */
|
||||
uptr->UST = STA_NMTN | STA_EOT; /* update status */
|
||||
mt_sta = mt_sta & ~STA_BSY; /* don't set EOM */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* interrupt */
|
||||
|
@ -293,16 +284,15 @@ case MTC_REW: /* rewind */
|
|||
|
||||
case MTC_RD: /* read */
|
||||
if (mt_blnt == 0) { /* first time? */
|
||||
if (mt_rdlntf (uptr, &tbc, &err)) break; /* read rec lnt, err? */
|
||||
mt_blnt = tbc; /* set buf lnt */
|
||||
if (tbc > MT_MAXFR) return SCPE_MTRLNT; /* record too long? */
|
||||
i = fxread (mtxb, sizeof (uint8), mt_blnt, uptr->fileref);
|
||||
if (err = ferror (uptr->fileref)) { /* error? */
|
||||
MT_SET_PNU (uptr); /* pos not upd */
|
||||
st = sim_tape_rdrecf (uptr, mtxb, &tbc, MT_MAXFR); /* read rec */
|
||||
if (st == MTSE_RECE) mt_sta = mt_sta | STA_ERR; /* rec in err? */
|
||||
else if (st != SCPE_OK) { /* other error? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
if (sch_actv (mt_dib.sch, dev)) /* if sch, stop */
|
||||
sch_stop (mt_dib.sch);
|
||||
break; }
|
||||
for ( ; i < mt_blnt; i++) mtxb[i] = 0; /* fill with 0's */
|
||||
uptr->pos = uptr->pos + ((tbc + 1) & ~1) /* upd pos */
|
||||
+ (2 * sizeof (t_mtrlnt)); }
|
||||
mt_blnt = tbc; /* set buf lnt */
|
||||
}
|
||||
|
||||
if (sch_actv (mt_dib.sch, dev)) { /* sch active? */
|
||||
i = sch_wrmem (mt_dib.sch, mtxb, mt_blnt); /* store rec in mem */
|
||||
|
@ -334,114 +324,77 @@ case MTC_WR: /* write */
|
|||
return SCPE_OK; }
|
||||
|
||||
if (mt_bptr) { /* any chars? */
|
||||
int32 ebc = (mt_bptr + 1) & ~1; /* force even */
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
||||
fxwrite (&mt_bptr, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
fxwrite (mtxb, sizeof (uint8), ebc, uptr->fileref);
|
||||
fxwrite (&mt_bptr, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr);
|
||||
else uptr->pos = uptr->pos + ebc + (2 * sizeof (t_mtrlnt)); }
|
||||
if (st = sim_tape_wrrecf (uptr, mtxb, mt_bptr)) /* write, err? */
|
||||
r = mt_map_err (uptr, st); } /* map error */
|
||||
break; /* record done */
|
||||
|
||||
/* Unit service, continued */
|
||||
|
||||
case MTC_WEOF: /* write eof */
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set pos */
|
||||
fxwrite (&bceof, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr);
|
||||
else uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* update pos */
|
||||
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
mt_sta = mt_sta | STA_EOF; /* set eof */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* interrupt */
|
||||
break;
|
||||
|
||||
case MTC_SKFF: /* skip file fwd */
|
||||
while (mt_forwsp (uptr, &err)) ; /* spc until EOF/EOT */
|
||||
while ((st = sim_tape_sprecf (uptr, &tbc)) == MTSE_OK) ;
|
||||
if (st == MTSE_TMK) { /* stopped by tmk? */
|
||||
mt_sta = mt_sta | STA_EOF; /* set eof */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); } /* set intr */
|
||||
else r = mt_map_err (uptr, st); /* map error */
|
||||
break;
|
||||
|
||||
case MTC_SKFR: /* skip file rev */
|
||||
while (mt_backsp (uptr, &err)) ; /* spc until EOF/BOT */
|
||||
while ((st = sim_tape_sprecr (uptr, &tbc)) == MTSE_OK) ;
|
||||
if (st == MTSE_TMK) { /* stopped by tmk? */
|
||||
mt_sta = mt_sta | STA_EOF; /* set eof */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); } /* set intr */
|
||||
else r = mt_map_err (uptr, st); /* map error */
|
||||
break;
|
||||
|
||||
case MTC_SPCR: /* backspace */
|
||||
if (!pnu) mt_backsp (uptr, &err); /* if pos not upd */
|
||||
if (st = sim_tape_sprecr (uptr, &tbc)) /* skip rec rev, err? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
break; } /* end case */
|
||||
|
||||
if (err != 0) { /* I/O error */
|
||||
mt_sta = mt_sta | STA_ERR;
|
||||
perror ("MT I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
if (mt_stopioe) return SCPE_IOERR; }
|
||||
uptr->UCMD = uptr->UCMD | MTC_STOP1; /* set stop stage 1 */
|
||||
sim_activate (uptr, mt_rtime); /* schedule */
|
||||
return SCPE_OK;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Tape motion routines */
|
||||
/* Map tape error status */
|
||||
|
||||
t_bool mt_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
||||
t_stat mt_map_err (UNIT *uptr, t_stat st)
|
||||
{
|
||||
int32 u = uptr - mt_dev.units;
|
||||
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* position */
|
||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref); /* get bc */
|
||||
if ((*err = ferror (uptr->fileref)) || /* err or eom? */
|
||||
feof (uptr->fileref) || (*tbc == MTR_EOM)) {
|
||||
mt_sta = mt_sta | STA_ERR; /* set err */
|
||||
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 */
|
||||
mt_sta = mt_sta | STA_ERR;
|
||||
case MTSE_OK: /* no error */
|
||||
return SCPE_IERR;
|
||||
case MTSE_TMK: /* end of file */
|
||||
mt_sta = mt_sta | STA_EOF; /* set eof */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */
|
||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* update pos */
|
||||
return TRUE; }
|
||||
*tbc = MTRL (*tbc);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
t_bool mt_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
||||
{
|
||||
int32 u = uptr - mt_dev.units;
|
||||
|
||||
if (uptr->pos < sizeof (t_mtrlnt)) { /* at bot? */
|
||||
break;
|
||||
case MTSE_IOERR: /* IO error */
|
||||
mt_sta = mt_sta | STA_ERR; /* set err */
|
||||
if (mt_stopioe) return SCPE_IOERR;
|
||||
break;
|
||||
case MTSE_INVRL: /* invalid rec lnt */
|
||||
mt_sta = mt_sta | STA_ERR;
|
||||
return SCPE_MTRLNT;
|
||||
case MTSE_WRP: /* write protect */
|
||||
case MTSE_RECE: /* record in error */
|
||||
case MTSE_EOM: /* end of medium */
|
||||
mt_sta = mt_sta | STA_ERR; /* set err */
|
||||
break;
|
||||
case MTSE_BOT: /* reverse into BOT */
|
||||
uptr->UST = uptr->UST | STA_EOT; /* set err */
|
||||
return TRUE; }
|
||||
fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET);
|
||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref); /* get bc */
|
||||
if ((*err = ferror (uptr->fileref)) || /* err or eof? */
|
||||
feof (uptr->fileref)) {
|
||||
mt_sta = mt_sta | STA_ERR; /* set err */
|
||||
return TRUE; }
|
||||
if (*tbc == MTR_EOM) { /* eom? */
|
||||
mt_sta = mt_sta | STA_ERR; /* set err */
|
||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* update pos */
|
||||
return TRUE; }
|
||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
||||
mt_sta = mt_sta | STA_EOF; /* set eof */
|
||||
if (mt_arm[u]) SET_INT (v_MT + u); /* set intr */
|
||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* update pos */
|
||||
return TRUE; }
|
||||
*tbc = MTRL (*tbc);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
t_bool mt_forwsp (UNIT *uptr, int32 *err)
|
||||
{
|
||||
t_mtrlnt tbc;
|
||||
|
||||
if (mt_rdlntf (uptr, &tbc, err)) return FALSE; /* read rec lnt, err? */
|
||||
uptr->pos = uptr->pos + ((tbc + 1) & ~1) + /* space to next rec */
|
||||
(2 * sizeof (t_mtrlnt));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
t_bool mt_backsp (UNIT *uptr, int32 *err)
|
||||
{
|
||||
t_mtrlnt tbc;
|
||||
|
||||
if (mt_rdlntr (uptr, &tbc, err)) return FALSE; /* read rec lnt, err? */
|
||||
uptr->pos = uptr->pos - ((tbc + 1) & ~1) - /* space to prv rec */
|
||||
(2 * sizeof (t_mtrlnt));
|
||||
return TRUE;
|
||||
break; } /* end switch */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
@ -459,7 +412,7 @@ for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */
|
|||
CLR_ENB (v_MT + u); /* disable int */
|
||||
mt_arm[u] = 0; /* disarm int */
|
||||
uptr = mt_dev.units + u;
|
||||
MT_CLR_PNU (uptr); /* clear pos flag */
|
||||
sim_tape_reset (uptr); /* clear pos flag */
|
||||
sim_cancel (uptr); /* cancel activity */
|
||||
uptr->UST = (uptr->UST & STA_UFLGS) | STA_NMTN; /* init status */
|
||||
uptr->UCMD = 0; } /* init cmd */
|
||||
|
@ -473,10 +426,8 @@ t_stat mt_attach (UNIT *uptr, char *cptr)
|
|||
int32 u = uptr - mt_dev.units;
|
||||
t_stat r;
|
||||
|
||||
r = attach_unit (uptr, cptr);
|
||||
r = sim_tape_attach (uptr, cptr);
|
||||
if (r != SCPE_OK) return r;
|
||||
uptr->pos = 0;
|
||||
MT_CLR_PNU (uptr);
|
||||
uptr->UST = STA_EOT;
|
||||
if (mt_arm[u]) SET_INT (v_MT + u);
|
||||
return r;
|
||||
|
@ -489,11 +440,9 @@ t_stat mt_detach (UNIT* uptr)
|
|||
int32 u = uptr - mt_dev.units;
|
||||
t_stat r;
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK;
|
||||
r = detach_unit (uptr);
|
||||
r = sim_tape_detach (uptr);
|
||||
if (r != SCPE_OK) return r;
|
||||
if (mt_arm[u]) SET_INT (v_MT + u);
|
||||
MT_CLR_PNU (uptr);
|
||||
uptr->UST = 0;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -518,7 +467,7 @@ extern DIB sch_dib;
|
|||
uint32 sch_dev;
|
||||
|
||||
if (decrom[0xD5] & dec_flgs) return SCPE_NOFNC; /* AL defined? */
|
||||
mt_unit[unitno].pos = 0; /* rewind */
|
||||
sim_tape_rewind (&mt_unit[unitno]); /* rewind */
|
||||
sch_dev = sch_dib.dno + mt_dib.sch; /* sch dev # */
|
||||
IOWriteBlk (BOOT_START, BOOT_LEN, boot_rom); /* copy boot */
|
||||
IOWriteB (AL_DEV, mt_dib.dno + (unitno * o_MT0)); /* set dev no for unit */
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
pt paper tape reader and punch
|
||||
pt paper tape reader and punch
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
tt console
|
||||
tt console
|
||||
|
||||
11-Jan-03 RMS Added TTP support
|
||||
22-Dec-02 RMS Added break support
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
ttp console (on PAS)
|
||||
ttp console (on PAS)
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
|
@ -76,8 +76,8 @@ extern int32 pas_par (int32 cmd, int32 c);
|
|||
DIB ttp_dib = { d_TTP, -1, v_TTP, ttp_tplte, &ttp, NULL };
|
||||
|
||||
UNIT ttp_unit[] = {
|
||||
{ UDATA (&ttpi_svc, UNIT_UC, 0), KBD_POLL_WAIT },
|
||||
{ UDATA (&ttpo_svc, UNIT_UC, 0), SERIAL_OUT_WAIT }
|
||||
{ UDATA (&ttpi_svc, 0, 0), KBD_POLL_WAIT },
|
||||
{ UDATA (&ttpo_svc, 0, 0), SERIAL_OUT_WAIT }
|
||||
};
|
||||
|
||||
REG ttp_reg[] = {
|
||||
|
|
|
@ -23,8 +23,11 @@
|
|||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
pic precision incremental clock
|
||||
lfc line frequency clock
|
||||
pic precision incremental clock
|
||||
lfc line frequency clock
|
||||
|
||||
01-Mar-03 RMS Added SET/SHOW LFC FREQ support
|
||||
Changed precision clock algorithm for V7 UNIX
|
||||
*/
|
||||
|
||||
#include "id_defs.h"
|
||||
|
@ -56,7 +59,9 @@ uint32 pic_rdp = 0;
|
|||
uint32 pic_wdp = 0;
|
||||
uint32 pic_cnti = 0; /* instr/timer */
|
||||
uint32 pic_arm = 0; /* int arm */
|
||||
uint32 pic_decr = 1; /* decrement */
|
||||
uint16 pic_time[4] = { 1, 10, 100, 1000 }; /* delays */
|
||||
uint16 pic_usec[4] = { 1, 10, 100, 1000 }; /* usec per tick */
|
||||
static int32 pic_map[16] = { /* map rate to delay */
|
||||
0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 };
|
||||
|
||||
|
@ -74,6 +79,8 @@ DEVICE lfc_dev;
|
|||
uint32 lfc (uint32 dev, uint32 op, uint32 dat);
|
||||
t_stat lfc_svc (UNIT *uptr);
|
||||
t_stat lfc_reset (DEVICE *dptr);
|
||||
t_stat lfc_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat lfc_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
|
||||
/* PIC data structures
|
||||
|
||||
|
@ -90,7 +97,6 @@ REG pic_reg[] = {
|
|||
{ HRDATA (BUF, pic_db, 16) },
|
||||
{ HRDATA (RIC, pic_ric, 16) },
|
||||
{ HRDATA (CIC, pic_cic, 12) },
|
||||
{ DRDATA (SAVE, pic_save, 32), REG_HRO + PV_LEFT },
|
||||
{ FLDATA (RDP, pic_rdp, 0) },
|
||||
{ FLDATA (WDP, pic_wdp, 0) },
|
||||
{ FLDATA (OVF, pic_ovf, 0) },
|
||||
|
@ -98,6 +104,9 @@ REG pic_reg[] = {
|
|||
{ FLDATA (IENB, int_enb[l_PIC], i_PIC) },
|
||||
{ FLDATA (IARM, pic_arm, 0) },
|
||||
{ BRDATA (TIME, pic_time, 10, 16, 4), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (SAVE, pic_save, 32), REG_HRO + PV_LEFT },
|
||||
{ DRDATA (DECR, pic_decr, 16), REG_HRO + PV_LEFT },
|
||||
{ FLDATA (MODE, pic_cnti, 0), REG_HRO },
|
||||
{ HRDATA (DEVNO, pic_dib.dno, 8), REG_HRO },
|
||||
{ NULL } };
|
||||
|
||||
|
@ -131,11 +140,17 @@ REG lfc_reg[] = {
|
|||
{ FLDATA (IENB, int_enb[l_LFC], i_LFC) },
|
||||
{ FLDATA (IARM, lfc_arm, 0) },
|
||||
{ DRDATA (TIME, lfc_unit.wait, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TPS, lfc_tps, 8), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TPS, lfc_tps, 8), PV_LEFT + REG_HRO },
|
||||
{ HRDATA (DEVNO, lfc_dib.dno, 8), REG_HRO },
|
||||
{ NULL } };
|
||||
|
||||
MTAB lfc_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 100, NULL, "50HZ",
|
||||
&lfc_set_freq, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 120, NULL, "60HZ",
|
||||
&lfc_set_freq, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "FREQUENCY", NULL,
|
||||
NULL, &lfc_show_freq, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 } };
|
||||
|
@ -200,9 +215,9 @@ t_stat pic_svc (UNIT *uptr)
|
|||
{
|
||||
t_bool rate_chg = FALSE;
|
||||
|
||||
if (pic_cnti) pic_cic = -1; /* one shot? */
|
||||
pic_cic = pic_cic - 1; /* decrement */
|
||||
if (pic_cic < 0) { /* overflow? */
|
||||
if (pic_cnti) pic_cic = 0; /* one shot? */
|
||||
pic_cic = pic_cic - pic_decr; /* decrement */
|
||||
if (pic_cic <= 0) { /* overflow? */
|
||||
if (pic_wdp) pic_ovf = 1; /* broken wr? set flag */
|
||||
if (pic_arm) SET_INT (v_PIC); /* if armed, intr */
|
||||
if (GET_RATE (pic_ric) != GET_RATE (pic_db)) /* rate change? */
|
||||
|
@ -216,23 +231,27 @@ return SCPE_OK;
|
|||
|
||||
/* Schedule next interval
|
||||
|
||||
If rate < 1ms, or diagnostic mode, count instructions
|
||||
If rate = 1ms, and not diagnostic mode, use timer
|
||||
If eff rate < 1ms, or diagnostic mode, count instructions
|
||||
If eff rate = 1ms, and not diagnostic mode, use timer
|
||||
*/
|
||||
|
||||
void pic_sched (t_bool strt)
|
||||
{
|
||||
int32 r, t;
|
||||
int32 r, t, intv, intv_usec;
|
||||
|
||||
pic_save = sim_grtime (); /* save start */
|
||||
r = pic_map[GET_RATE (pic_ric)]; /* get mapped rate */
|
||||
t = pic_time[r]; /* get delay */
|
||||
if ((r == 3) && !(pic_unit.flags & UNIT_DIAG)) { /* timer? */
|
||||
intv = pic_cic? pic_cic: 1; /* get cntr */
|
||||
intv_usec = intv * pic_usec[r]; /* cvt to usec */
|
||||
if (!(pic_unit.flags & UNIT_DIAG) && /* not diag? */
|
||||
((intv_usec % 1000) == 0)) { /* 1ms multiple? */
|
||||
pic_cnti = 0; /* clr mode */
|
||||
if (strt) t = sim_rtcn_init (t, TMR_PIC); /* init or */
|
||||
pic_decr = pic_usec[3 - r]; /* set decrement */
|
||||
if (strt) t = sim_rtcn_init (pic_time[3], TMR_PIC); /* init or */
|
||||
else t = sim_rtcn_calb (PIC_TPS, TMR_PIC); } /* calibrate */
|
||||
else { pic_cnti = 1; /* set mode */
|
||||
t = t * (pic_cic + 1); /* interval */
|
||||
pic_decr = 1; /* decr = 1 */
|
||||
t = pic_time[r] * intv; /* interval */
|
||||
if (t == 1) t++; } /* for diagn */
|
||||
sim_activate (&pic_unit, t); /* activate */
|
||||
return;
|
||||
|
@ -260,6 +279,7 @@ pic_ric = pic_cic = 0;
|
|||
pic_db = 0;
|
||||
pic_ovf = 0; /* clear state */
|
||||
pic_cnti = 0;
|
||||
pic_decr = 1;
|
||||
pic_rdp = pic_wdp = 0;
|
||||
CLR_INT (v_PIC); /* clear int */
|
||||
CLR_ENB (v_PIC); /* disable int */
|
||||
|
@ -309,3 +329,22 @@ CLR_ENB (v_LFC); /* disable int */
|
|||
lfc_arm = 0; /* disarm int */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Set frequency */
|
||||
|
||||
t_stat lfc_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if (cptr) return SCPE_ARG;
|
||||
if ((val != 100) && (val != 120)) return SCPE_IERR;
|
||||
lfc_tps = val;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Show frequency */
|
||||
|
||||
t_stat lfc_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
fprintf (st, (lfc_tps == 100)? "50Hz": "60Hz");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* nova_clk.c: NOVA real-time clock simulator
|
||||
|
||||
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 @@
|
|||
|
||||
clk real-time clock
|
||||
|
||||
01-Mar-03 RMS Added SET/SHOW CLK FREQ support
|
||||
03-Oct-02 RMS Added DIB
|
||||
17-Sep-01 RMS Added terminal multiplexor support
|
||||
17-Mar-01 RMS Moved function prototype
|
||||
|
@ -45,6 +46,8 @@ int32 tmxr_poll = 16000; /* tmxr poll */
|
|||
int32 clk (int32 pulse, int32 code, int32 AC);
|
||||
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);
|
||||
|
||||
/* CLK data structures
|
||||
|
||||
|
@ -67,10 +70,20 @@ REG clk_reg[] = {
|
|||
{ DRDATA (TIME1, clk_time[1], 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TIME2, clk_time[2], 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TIME3, clk_time[3], 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TPS0, clk_tps[0], 6), 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, "LINE", NULL,
|
||||
NULL, &clk_show_freq, NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE clk_dev = {
|
||||
"CLK", &clk_unit, clk_reg, NULL,
|
||||
"CLK", &clk_unit, clk_reg, clk_mod,
|
||||
1, 0, 0, 0, 0, 0,
|
||||
NULL, NULL, &clk_reset,
|
||||
NULL, NULL, NULL,
|
||||
|
@ -130,3 +143,21 @@ sim_cancel (&clk_unit); /* deactivate unit */
|
|||
tmxr_poll = clk_time[0]; /* poll is default */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Set line frequency */
|
||||
|
||||
t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if (cptr) return SCPE_ARG;
|
||||
if ((val != 50) && (val != 60)) return SCPE_IERR;
|
||||
clk_tps[0] = val;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Show line frequency */
|
||||
|
||||
t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
fprintf (st, (clk_tps[0] == 50)? "50Hz": "60Hz");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
To: Users
|
||||
From: Bob Supnik
|
||||
Subj: Nova Simulator Usage
|
||||
Date: 1-Feb-2003
|
||||
Date: 15-Mar-2003
|
||||
|
||||
COPYRIGHT NOTICE
|
||||
|
||||
|
@ -39,10 +39,12 @@ This memorandum documents the Nova simulator.
|
|||
sim/ sim_defs.h
|
||||
sim_rev.h
|
||||
sim_sock.h
|
||||
sim_tape.h
|
||||
sim_tmxr.h
|
||||
scp.c
|
||||
scp_tty.c
|
||||
sim_sock.c
|
||||
sim_tape.c
|
||||
sim_tmxr.c
|
||||
|
||||
sim/nova/ nova_defs.h
|
||||
|
@ -282,7 +284,14 @@ Error handling is as follows:
|
|||
|
||||
2.2.6 Real-Time Clock (CLK)
|
||||
|
||||
The real-time clock (CLK) implements these registers:
|
||||
The real-time clock (CLK) line frequency can be adjusted as follows:
|
||||
|
||||
SET CLK 60HZ set line frequency to 60Hz
|
||||
SET CLK 50HZ set line frequency to 50Hz
|
||||
|
||||
The default is 60Hz.
|
||||
|
||||
The clock implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
|
@ -397,7 +406,7 @@ from the attached file:
|
|||
SET RF 8P eight platters (2048K)
|
||||
SET RF AUTOSIZE autosized on attach
|
||||
|
||||
The default is 8P (maximum size).
|
||||
The default is 1P (minimum size).
|
||||
|
||||
The fixed head disk controller implements these registers:
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
dsk fixed head disk
|
||||
|
||||
03-Mar-03 RMS Fixed variable capacity and autosizing
|
||||
03-Oct-02 RMS Added DIB
|
||||
06-Jan-02 RMS Revised enable/disable support
|
||||
23-Aug-01 RMS Fixed bug in write watermarking
|
||||
|
@ -41,9 +42,11 @@
|
|||
#include <math.h>
|
||||
|
||||
#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */
|
||||
#define UNIT_V_MSIZE (UNIT_V_UF + 1) /* dummy mask */
|
||||
#define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */
|
||||
#define UNIT_M_PLAT 07
|
||||
#define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1)
|
||||
#define UNIT_AUTO (1 << UNIT_V_AUTO)
|
||||
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
|
||||
#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT)
|
||||
|
||||
/* Constants */
|
||||
|
||||
|
@ -112,7 +115,7 @@ DIB dsk_dib = { DEV_DSK, INT_DSK, PI_DSK, &dsk };
|
|||
|
||||
UNIT dsk_unit =
|
||||
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF,
|
||||
DSK_NUMDK * DSK_DKSIZE) };
|
||||
DSK_DKSIZE) };
|
||||
|
||||
REG dsk_reg[] = {
|
||||
{ ORDATA (STAT, dsk_stat, 16) },
|
||||
|
@ -128,14 +131,14 @@ REG dsk_reg[] = {
|
|||
{ NULL } };
|
||||
|
||||
MTAB dsk_mod[] = {
|
||||
{ UNIT_MSIZE, 262144, NULL, "1P", &dsk_set_size },
|
||||
{ UNIT_MSIZE, 524288, NULL, "2P", &dsk_set_size },
|
||||
{ UNIT_MSIZE, 786432, NULL, "3P", &dsk_set_size },
|
||||
{ UNIT_MSIZE, 1048576, NULL, "4P", &dsk_set_size },
|
||||
{ UNIT_MSIZE, 1310720, NULL, "5P", &dsk_set_size },
|
||||
{ UNIT_MSIZE, 1572864, NULL, "6P", &dsk_set_size },
|
||||
{ UNIT_MSIZE, 1835008, NULL, "7P", &dsk_set_size },
|
||||
{ UNIT_MSIZE, 2097152, NULL, "8P", &dsk_set_size },
|
||||
{ UNIT_PLAT, 0, NULL, "1P", &dsk_set_size },
|
||||
{ UNIT_PLAT, 1, NULL, "2P", &dsk_set_size },
|
||||
{ UNIT_PLAT, 2, NULL, "3P", &dsk_set_size },
|
||||
{ UNIT_PLAT, 3, NULL, "4P", &dsk_set_size },
|
||||
{ UNIT_PLAT, 4, NULL, "5P", &dsk_set_size },
|
||||
{ UNIT_PLAT, 5, NULL, "6P", &dsk_set_size },
|
||||
{ UNIT_PLAT, 6, NULL, "7P", &dsk_set_size },
|
||||
{ UNIT_PLAT, 7, NULL, "8P", &dsk_set_size },
|
||||
{ UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL },
|
||||
{ 0 } };
|
||||
|
||||
|
@ -268,19 +271,15 @@ return SCPE_OK;
|
|||
|
||||
t_stat dsk_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
int32 p, d;
|
||||
int32 ds_bytes = DSK_DKSIZE * sizeof (int16);
|
||||
t_addr sz, p;
|
||||
t_addr ds_bytes = DSK_DKSIZE * sizeof (int16);
|
||||
|
||||
if (uptr->flags & UNIT_AUTO) {
|
||||
FILE *fp = fopen (cptr, "rb");
|
||||
if (fp == NULL) return SCPE_OPENERR;
|
||||
fseek (fp, 0, SEEK_END);
|
||||
p = ftell (fp);
|
||||
d = (p + ds_bytes - 1) / ds_bytes;
|
||||
if (d == 0) d = 1;
|
||||
if (d > DSK_NUMDK) d = DSK_NUMDK;
|
||||
uptr->capac = d * DSK_DKSIZE;
|
||||
fclose (fp); }
|
||||
if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (cptr))) {
|
||||
p = (sz + ds_bytes - 1) / ds_bytes;
|
||||
if (p == 0) p = 1;
|
||||
if (p > DSK_NUMDK) p = DSK_NUMDK; }
|
||||
else p = UNIT_GETP (uptr->flags); /* get # plat */
|
||||
uptr->capac = p * DSK_DKSIZE; /* set capacity */
|
||||
return attach_unit (uptr, cptr);
|
||||
}
|
||||
|
||||
|
@ -288,10 +287,9 @@ return attach_unit (uptr, cptr);
|
|||
|
||||
t_stat dsk_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if ((val == 0) || (val > (DSK_NUMDK * DSK_DKSIZE)))
|
||||
return SCPE_IERR;
|
||||
if ((val < 0) || (val >= DSK_NUMDK)) return SCPE_IERR;
|
||||
if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
|
||||
uptr->capac = val;
|
||||
uptr->capac = (val + 1) * DSK_DKSIZE;
|
||||
uptr->flags = uptr->flags & ~UNIT_AUTO;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
|
218
NOVA/nova_mta.c
218
NOVA/nova_mta.c
|
@ -1,6 +1,6 @@
|
|||
/* nova_mta.c: NOVA magnetic tape simulator
|
||||
|
||||
Copyright (c) 1993-2002, Robert M. Supnik
|
||||
Copyright (c) 1993-2003, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -25,6 +25,7 @@
|
|||
|
||||
mta magnetic tape
|
||||
|
||||
28-Feb-03 RMS Revised for magtape library
|
||||
30-Oct-02 RMS Fixed BOT handling, added error record handling
|
||||
08-Oct-02 RMS Added DIB
|
||||
30-Sep-02 RMS Revamped error handling
|
||||
|
@ -60,17 +61,13 @@
|
|||
*/
|
||||
|
||||
#include "nova_defs.h"
|
||||
#include "sim_tape.h"
|
||||
|
||||
#define MTA_NUMDR 8 /* #drives */
|
||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
||||
#define UNIT_V_PNU (UNIT_V_UF + 1) /* pos not updated */
|
||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
||||
#define UNIT_PNU (1 << UNIT_V_PNU)
|
||||
#define USTAT u3 /* unit status */
|
||||
#define MTA_MAXFR (1 << 16) /* max record lnt */
|
||||
#define DTSIZE (1 << 14) /* max data xfer */
|
||||
#define DTMASK (DTSIZE - 1)
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
#define WC_SIZE (1 << 14) /* max word count */
|
||||
#define WC_MASK (WC_SIZE - 1)
|
||||
|
||||
/* Command/unit */
|
||||
|
||||
|
@ -154,6 +151,7 @@ int32 mta_sta = 0; /* status register */
|
|||
int32 mta_ep = 0; /* enable polling */
|
||||
int32 mta_cwait = 100; /* command latency */
|
||||
int32 mta_rwait = 100; /* record latency */
|
||||
uint8 *mtxb = NULL; /* transfer buffer */
|
||||
|
||||
DEVICE mta_dev;
|
||||
int32 mta (int32 pulse, int32 code, int32 AC);
|
||||
|
@ -164,9 +162,8 @@ t_stat mta_attach (UNIT *uptr, char *cptr);
|
|||
t_stat mta_detach (UNIT *uptr);
|
||||
int32 mta_updcsta (UNIT *uptr);
|
||||
void mta_upddsta (UNIT *uptr, int32 newsta);
|
||||
t_stat mta_map_err (UNIT *uptr, t_stat st);
|
||||
t_stat mta_vlock (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_bool mta_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
||||
t_bool mta_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
||||
|
||||
static const int ctype[32] = { /* c vs r timing */
|
||||
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
|
||||
|
@ -211,8 +208,8 @@ REG mta_reg[] = {
|
|||
{ NULL } };
|
||||
|
||||
MTAB mta_mod[] = {
|
||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", &mta_vlock },
|
||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", &mta_vlock },
|
||||
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", &mta_vlock },
|
||||
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", &mta_vlock },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE mta_dev = {
|
||||
|
@ -305,40 +302,31 @@ return rval;
|
|||
|
||||
t_stat mta_svc (UNIT *uptr)
|
||||
{
|
||||
int32 c, p, pa, err, pnu, u;
|
||||
int32 c, p, pa, u;
|
||||
t_mtrlnt i, cbc, tbc, wc;
|
||||
uint16 c1, c2;
|
||||
static uint8 dbuf[2 * DTSIZE];
|
||||
static t_mtrlnt bceof = { MTR_TMK };
|
||||
t_stat st, r = SCPE_OK;
|
||||
|
||||
err = 0;
|
||||
u = uptr - mta_dev.units; /* get unit number */
|
||||
pnu = MT_TST_PNU (uptr); /* get pos not upd */
|
||||
MT_CLR_PNU (uptr); /* and clear */
|
||||
c = GET_CMD (mta_cu); /* command */
|
||||
wc = WC_SIZE - (mta_wc & WC_MASK); /* io wc */
|
||||
|
||||
if (uptr->USTAT & STA_REW) { /* rewind? */
|
||||
uptr->pos = 0; /* update position */
|
||||
sim_tape_rewind (uptr); /* update tape */
|
||||
mta_upddsta (uptr, (uptr->USTAT & ~STA_REW) | STA_BOT | STA_RDY);
|
||||
if (u == GET_UNIT (mta_cu)) mta_updcsta (uptr);
|
||||
return SCPE_OK; }
|
||||
|
||||
c = GET_CMD (mta_cu); /* command */
|
||||
wc = DTSIZE - (mta_wc & DTMASK); /* io wc */
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
|
||||
mta_upddsta (uptr, 0); /* unit off line */
|
||||
mta_sta = mta_sta | STA_ILL; } /* illegal operation */
|
||||
|
||||
else if ((uptr->flags & UNIT_WPRT) && /* write locked? */
|
||||
((c == CU_WRITE) || (c == CU_WREOF) || (c == CU_ERASE))) {
|
||||
mta_upddsta (uptr, uptr->USTAT | STA_WLK | STA_RDY);
|
||||
mta_sta = mta_sta | STA_ILL; } /* illegal operation */
|
||||
|
||||
else switch (c) { /* case on command */
|
||||
|
||||
case CU_CMODE: /* controller mode */
|
||||
mta_ep = mta_cu & CU_EP;
|
||||
break;
|
||||
case CU_DMODE: /* drive mode */
|
||||
if (uptr->pos) mta_sta = mta_sta | STA_ILL; /* must be BOT */
|
||||
if (!sim_tape_bot (uptr)) mta_sta = mta_sta | STA_ILL; /* must be BOT */
|
||||
else mta_upddsta (uptr, (mta_cu & CU_PE)? /* update drv status */
|
||||
uptr->USTAT | STA_PEM: uptr->USTAT & ~ STA_PEM);
|
||||
break;
|
||||
|
@ -347,69 +335,62 @@ case CU_DMODE: /* drive mode */
|
|||
|
||||
case CU_READ: /* read */
|
||||
case CU_READNS: /* read non-stop */
|
||||
if (mta_rdlntf (uptr, &tbc, & err)) break; /* read rec lnt, err? */
|
||||
if (tbc > MTA_MAXFR) return SCPE_MTRLNT; /* record too long? */
|
||||
st = sim_tape_rdrecf (uptr, mtxb, &tbc, MTA_MAXFR); /* read rec */
|
||||
if (st == MTSE_RECE) mta_sta = mta_sta | STA_DAE; /* rec in err? */
|
||||
else if (st != MTSE_OK) { /* other error? */
|
||||
r = mta_map_err (uptr, st); /* map error */
|
||||
break; }
|
||||
cbc = wc * 2; /* expected bc */
|
||||
if (tbc & 1) mta_sta = mta_sta | STA_ODD; /* odd byte count? */
|
||||
if (tbc > cbc) mta_sta = mta_sta | STA_WCO; /* too big? */
|
||||
else {
|
||||
cbc = tbc; /* no, use it */
|
||||
wc = (cbc + 1) / 2; } /* adjust wc */
|
||||
i = fxread (dbuf, sizeof (int8), cbc, uptr->fileref);
|
||||
for ( ; i < cbc; i++) dbuf[i] = 0;
|
||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY);
|
||||
if (err = ferror (uptr->fileref)) { /* error? */
|
||||
MT_SET_PNU (uptr); /* pos not upd */
|
||||
break; }
|
||||
for (i = p = 0; i < wc; i++) { /* copy buf to mem */
|
||||
c1 = dbuf[p++];
|
||||
c2 = dbuf[p++];
|
||||
c1 = mtxb[p++];
|
||||
c2 = mtxb[p++];
|
||||
pa = MapAddr (0, mta_ma); /* map address */
|
||||
if (MEM_ADDR_OK (pa)) M[pa] = (c1 << 8) | c2;
|
||||
mta_ma = (mta_ma + 1) & AMASK; }
|
||||
mta_wc = (mta_wc + wc) & DMASK;
|
||||
uptr->pos = uptr->pos + ((tbc + 1) & ~1) +
|
||||
(2 * sizeof (t_mtrlnt));
|
||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY);
|
||||
break;
|
||||
|
||||
case CU_WRITE: /* write */
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
||||
tbc = wc * 2; /* io byte count */
|
||||
fxwrite (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
for (i = p = 0; i < wc; i++) { /* copy to buffer */
|
||||
pa = MapAddr (0, mta_ma); /* map address */
|
||||
dbuf[p++] = (M[pa] >> 8) & 0377;
|
||||
dbuf[p++] = M[pa] & 0377;
|
||||
pa = MapAddr (0, mta_ma); /* map address */
|
||||
mtxb[p++] = (M[pa] >> 8) & 0377;
|
||||
mtxb[p++] = M[pa] & 0377;
|
||||
mta_ma = (mta_ma + 1) & AMASK; }
|
||||
fxwrite (dbuf, sizeof (int8), tbc, uptr->fileref);
|
||||
fxwrite (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
if (st = sim_tape_wrrecf (uptr, mtxb, tbc)) { /* write rec, err? */
|
||||
r = mta_map_err (uptr, st); /* map error */
|
||||
mta_ma = (mta_ma - wc) & AMASK; } /* restore wc */
|
||||
else mta_wc = 0; /* clear wc */
|
||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY);
|
||||
if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr); /* error? */
|
||||
else {
|
||||
mta_wc = 0;
|
||||
uptr->pos = uptr->pos + tbc + (2 * sizeof (t_mtrlnt)); }
|
||||
break;
|
||||
|
||||
/* Unit service, continued */
|
||||
|
||||
case CU_WREOF: /* write eof */
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
||||
fxwrite (&bceof, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
mta_upddsta (uptr, uptr->USTAT | STA_EOF | STA_RDY);
|
||||
if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr); /* error? */
|
||||
else uptr->pos = uptr->pos + sizeof (t_mtrlnt);
|
||||
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
|
||||
r = mta_map_err (uptr, st); /* map error */
|
||||
else mta_upddsta (uptr, uptr->USTAT | STA_EOF | STA_RDY);
|
||||
break;
|
||||
|
||||
case CU_ERASE: /* erase */
|
||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY);
|
||||
if (sim_tape_wrp (uptr)) /* write protected? */
|
||||
r = mta_map_err (uptr, MTSE_WRP); /* map error */
|
||||
else mta_upddsta (uptr, uptr->USTAT | STA_RDY);
|
||||
break;
|
||||
|
||||
case CU_SPACEF: /* space forward */
|
||||
do {
|
||||
mta_wc = (mta_wc + 1) & DMASK; /* incr wc */
|
||||
if (mta_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)) { /* space rec fwd, err? */
|
||||
r = mta_map_err (uptr, st); /* map error */
|
||||
break; }
|
||||
}
|
||||
while (mta_wc != 0);
|
||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY);
|
||||
break;
|
||||
|
@ -417,29 +398,24 @@ case CU_SPACEF: /* space forward */
|
|||
case CU_SPACER: /* space reverse */
|
||||
do {
|
||||
mta_wc = (mta_wc + 1) & DMASK; /* incr wc */
|
||||
if (pnu) pnu = 0; /* pos not upd? */
|
||||
else {
|
||||
if (mta_rdlntr (uptr, &tbc, &err)) break;
|
||||
uptr->pos = uptr->pos - ((tbc + 1) & ~1) -
|
||||
(2 * sizeof (t_mtrlnt)); } }
|
||||
if (st = sim_tape_sprecr (uptr, &tbc)) { /* space rec rev, err? */
|
||||
r = mta_map_err (uptr, st); /* map error */
|
||||
break; }
|
||||
}
|
||||
while (mta_wc != 0);
|
||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY);
|
||||
break;
|
||||
|
||||
default: /* reserved */
|
||||
mta_sta = mta_sta | STA_ILL;
|
||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY);
|
||||
break; } /* end case */
|
||||
|
||||
if (err != 0) mta_sta = mta_sta | STA_DAE; /* I/O error */
|
||||
mta_updcsta (uptr); /* update status */
|
||||
dev_busy = dev_busy & ~INT_MTA; /* clear busy */
|
||||
dev_done = dev_done | INT_MTA; /* set done */
|
||||
int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);
|
||||
if (err != 0) {
|
||||
perror ("MTA I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
return SCPE_IOERR; }
|
||||
return SCPE_OK;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Update controller status */
|
||||
|
@ -471,60 +447,44 @@ if (change) {
|
|||
return;
|
||||
}
|
||||
|
||||
/* Read record length forward - return T if error, EOM, or EOF */
|
||||
/* Map tape error status */
|
||||
|
||||
t_bool mta_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
||||
t_stat mta_map_err (UNIT *uptr, t_stat st)
|
||||
{
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set tape pos */
|
||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref); /* read rec lnt */
|
||||
if (*err = ferror (uptr->fileref)) { /* error? */
|
||||
switch (st) {
|
||||
case MTSE_FMT: /* illegal fmt */
|
||||
mta_upddsta (uptr, uptr->USTAT | STA_WLK | STA_RDY);
|
||||
case MTSE_UNATT: /* unattached */
|
||||
mta_sta = mta_sta | STA_ILL;
|
||||
case MTSE_OK: /* no error */
|
||||
return SCPE_IERR; /* never get here! */
|
||||
case MTSE_TMK: /* end of file */
|
||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY | STA_EOF);
|
||||
break;
|
||||
case MTSE_IOERR: /* IO error */
|
||||
mta_sta = mta_sta | STA_DAE; /* data error */
|
||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY); /* ready */
|
||||
MT_SET_PNU (uptr); /* pos not upd */
|
||||
return TRUE; }
|
||||
if (feof (uptr->fileref) || (*tbc == MTR_EOM)) { /* eof or eom? */
|
||||
return SCPE_IOERR;
|
||||
case MTSE_INVRL: /* invalid rec lnt */
|
||||
mta_sta = mta_sta | STA_DAE; /* data error */
|
||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY); /* ready */
|
||||
return SCPE_MTRLNT;
|
||||
case MTSE_RECE: /* record in error */
|
||||
mta_sta = mta_sta | STA_DAE; /* data error */
|
||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY); /* ready */
|
||||
break;
|
||||
case MTSE_EOM: /* end of medium */
|
||||
mta_sta = mta_sta | STA_BAT; /* bad tape */
|
||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY); /* ready */
|
||||
MT_SET_PNU (uptr); /* pos not upd */
|
||||
return TRUE; }
|
||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY | STA_EOF);
|
||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* spc over tmk */
|
||||
return TRUE; }
|
||||
if (MTRF (*tbc)) mta_sta = mta_sta | STA_DAE; /* record in error? */
|
||||
*tbc = MTRL (*tbc); /* clear error flag */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Read record length reverse - return T if error, EOM, or EOF */
|
||||
|
||||
t_bool mta_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
||||
{
|
||||
if (uptr->pos < sizeof (t_mtrlnt)) { /* at BOT? */
|
||||
break;
|
||||
case MTSE_BOT: /* reverse into BOT */
|
||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY | STA_BOT);
|
||||
return TRUE; }
|
||||
fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET);
|
||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
if (*err = ferror (uptr->fileref)) { /* error? */
|
||||
mta_sta = mta_sta | STA_DAE; /* data error */
|
||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY); /* ready */
|
||||
return TRUE; }
|
||||
if (feof (uptr->fileref)) { /* eof? */
|
||||
mta_sta = mta_sta | STA_BAT; /* bad tape */
|
||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY); /* ready */
|
||||
return TRUE; }
|
||||
if (*tbc == MTR_EOM) { /* eom? */
|
||||
mta_sta = mta_sta | STA_BAT; /* bad tape */
|
||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY); /* ready */
|
||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over eom */
|
||||
return TRUE; }
|
||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
||||
mta_upddsta (uptr, uptr->USTAT | STA_RDY | STA_EOF);
|
||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over tmk */
|
||||
return TRUE; }
|
||||
if (MTRF (*tbc)) mta_sta = mta_sta | STA_DAE; /* record in error? */
|
||||
*tbc = MTRL (*tbc); /* clear error flag */
|
||||
return FALSE;
|
||||
break;
|
||||
case MTSE_WRP: /* write protect */
|
||||
mta_upddsta (uptr, uptr->USTAT | STA_WLK | STA_RDY);
|
||||
mta_sta = mta_sta | STA_ILL; /* illegal operation */
|
||||
break; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
@ -541,14 +501,16 @@ mta_cu = mta_wc = mta_ma = mta_sta = 0; /* clear registers */
|
|||
mta_ep = 0;
|
||||
for (u = 0; u < MTA_NUMDR; u++) { /* loop thru units */
|
||||
uptr = mta_dev.units + u;
|
||||
MT_CLR_PNU (uptr); /* clear pos flag */
|
||||
sim_tape_reset (uptr); /* clear pos flag */
|
||||
sim_cancel (uptr); /* cancel activity */
|
||||
if (uptr->flags & UNIT_ATT) uptr->USTAT = STA_RDY |
|
||||
(uptr->USTAT & STA_PEM) |
|
||||
((uptr->flags & UNIT_WPRT)? STA_WLK: 0) |
|
||||
((uptr->pos)? 0: STA_BOT);
|
||||
(sim_tape_wrp (uptr)? STA_WLK: 0) |
|
||||
(sim_tape_bot (uptr)? STA_BOT: 0);
|
||||
else uptr->USTAT = 0; }
|
||||
mta_updcsta (&mta_unit[0]); /* update status */
|
||||
if (mtxb == NULL) mtxb = calloc (MTA_MAXFR, sizeof (uint8));
|
||||
if (mtxb == NULL) return SCPE_MEM;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -558,11 +520,10 @@ t_stat mta_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;
|
||||
MT_CLR_PNU (uptr);
|
||||
if (!sim_is_active (uptr)) mta_upddsta (uptr, STA_RDY | STA_BOT | STA_PEM |
|
||||
((uptr->flags & UNIT_WPRT)? STA_WLK: 0));
|
||||
(sim_tape_wrp (uptr)? STA_WLK: 0));
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -570,16 +531,15 @@ return r;
|
|||
|
||||
t_stat mta_detach (UNIT* uptr)
|
||||
{
|
||||
MT_CLR_PNU (uptr);
|
||||
if (!sim_is_active (uptr)) mta_upddsta (uptr, 0);
|
||||
return detach_unit (uptr);
|
||||
return sim_tape_detach (uptr);
|
||||
}
|
||||
|
||||
/* Write lock/unlock validate routine */
|
||||
|
||||
t_stat mta_vlock (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if ((uptr->flags & UNIT_ATT) && val)
|
||||
if ((uptr->flags & UNIT_ATT) && (val || sim_tape_wrp (uptr)))
|
||||
mta_upddsta (uptr, uptr->USTAT | STA_WLK);
|
||||
else mta_upddsta (uptr, uptr->USTAT & ~STA_WLK);
|
||||
return SCPE_OK;
|
||||
|
@ -617,7 +577,7 @@ t_stat mta_boot (int32 unitno, DEVICE *dptr)
|
|||
int32 i;
|
||||
extern int32 saved_PC;
|
||||
|
||||
mta_unit[unitno].pos = 0;
|
||||
sim_tape_rewind (&mta_unit[unitno]);
|
||||
for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i];
|
||||
M[BOOT_UNIT] = (unitno & CU_M_UNIT) << CU_V_UNIT;
|
||||
saved_PC = BOOT_START;
|
||||
|
|
25
PDP10/pdp10_diag.txt
Normal file
25
PDP10/pdp10_diag.txt
Normal file
|
@ -0,0 +1,25 @@
|
|||
Bugs Found
|
||||
----------
|
||||
|
||||
1. pushj cleared T2 after setting it
|
||||
2. if timer autoadjust is enabled, timer diagnostic may fail,
|
||||
depending on host CPU speed
|
||||
3. DFAD/DFSB should use FP_ONES instead of ONES
|
||||
4. TLB physical address max = 1MW, tested in diagnostic
|
||||
5. DPB does read/write, not read-modify/write
|
||||
6. Fetch error takes priority over traps, due to prefetching
|
||||
of next instruction
|
||||
7. HSB is 36b, was 32b
|
||||
8. CPU and PAG devices had mismatched types
|
||||
9. non-zero sections in Tops-20 paging section indirect may
|
||||
cause non-existent memory error, due to microcode "error"
|
||||
10. PXCT test for user mode was backward
|
||||
11. Timer interrupts were not implemented in Tops-20 indirect
|
||||
chains
|
||||
12. epta/upta hit known bug in VC++ implementation of 64b
|
||||
data types
|
||||
13. final W calculation in Tops-20 paging was incorrect
|
||||
14. Timer representation lost sub msec values
|
||||
15. UBA initialization reset the UBA itself
|
||||
16. RHCS1: writing IE cannot trigger an interrupt
|
||||
17. Tape bootstrap was set to 800bpi instead of 1600bpi
|
|
@ -297,7 +297,6 @@ t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
|
|||
d10 data;
|
||||
int32 wc, fmt;
|
||||
extern int32 sim_switches;
|
||||
extern t_bool match_ext (char *fnam, char *ext);
|
||||
|
||||
fmt = 0; /* no fmt */
|
||||
if (sim_switches & SWMASK ('R')) fmt = FMT_R; /* -r? */
|
||||
|
|
198
PDP10/pdp10_tu.c
198
PDP10/pdp10_tu.c
|
@ -25,6 +25,7 @@
|
|||
|
||||
tu RH11/TM03/TU45 magtape
|
||||
|
||||
28-Feb-03 RMS Revised for magtape library
|
||||
27-Jan-03 RMS Changed to dynamically allocate buffer
|
||||
21-Nov-02 RMS Fixed bug in bootstrap (reported by Michael Thompson)
|
||||
Fixed bug in read (reported by Harris Newman)
|
||||
|
@ -75,18 +76,14 @@
|
|||
*/
|
||||
|
||||
#include "pdp10_defs.h"
|
||||
#include "sim_tape.h"
|
||||
|
||||
#define TU_NUMFM 1 /* #formatters */
|
||||
#define TU_NUMDR 8 /* #drives */
|
||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
||||
#define UNIT_V_PNU (UNIT_V_UF + 1) /* pos not updated */
|
||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
||||
#define UNIT_PNU (1 << UNIT_V_PNU)
|
||||
#define USTAT u3 /* unit status */
|
||||
#define UDENS u4 /* unit density */
|
||||
#define UD_UNK 0 /* unknown */
|
||||
#define XBUFLNT (1 << 16) /* max data buf */
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
#define MT_MAXFR (1 << 16) /* max data buf */
|
||||
|
||||
/* MTCS1 - 172440 - control/status 1 */
|
||||
|
||||
|
@ -319,9 +316,7 @@ t_stat tu_detach (UNIT *uptr);
|
|||
t_stat tu_boot (int32 unitno, DEVICE *dptr);
|
||||
void tu_go (int32 drv);
|
||||
void update_tucs (int32 flag, int32 drv);
|
||||
t_stat tu_vlock (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_bool tu_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
||||
t_bool tu_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
||||
t_stat tu_map_err (UNIT *uptr, t_stat st);
|
||||
|
||||
/* TU data structures
|
||||
|
||||
|
@ -369,8 +364,8 @@ REG tu_reg[] = {
|
|||
{ NULL } };
|
||||
|
||||
MTAB tu_mod[] = {
|
||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", &tu_vlock },
|
||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", &tu_vlock },
|
||||
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
|
||||
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "ADDRESS", NULL,
|
||||
NULL, &show_addr, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL,
|
||||
|
@ -583,7 +578,7 @@ case FNC_NOP:
|
|||
return;
|
||||
case FNC_RIP: /* read-in preset */
|
||||
tutc = TC_800; /* density = 800 */
|
||||
tu_unit[0].pos = 0; /* rewind unit 0 */
|
||||
sim_tape_rewind (&tu_unit[0]); /* rewind unit 0 */
|
||||
tu_unit[0].USTAT = 0;
|
||||
tucs1 = tucs1 & ~CS1_GO;
|
||||
return;
|
||||
|
@ -632,7 +627,7 @@ case FNC_WRITE: /* write */
|
|||
break; }
|
||||
case FNC_WREOF: /* write tape mark */
|
||||
case FNC_ERASE: /* erase */
|
||||
if (uptr->flags & UNIT_WPRT) { /* write locked? */
|
||||
if (sim_tape_wrp (uptr)) { /* write locked? */
|
||||
tuer = tuer | ER_NXF;
|
||||
break; }
|
||||
case FNC_WCHKF: /* wchk = read */
|
||||
|
@ -674,22 +669,19 @@ return;
|
|||
Complete movement or data transfer command
|
||||
Unit must exist - can't remove an active unit
|
||||
Unit must be attached - detach cancels in progress operations
|
||||
Unit must be writeable - can't write protect an active unit
|
||||
*/
|
||||
|
||||
t_stat tu_svc (UNIT *uptr)
|
||||
{
|
||||
int32 f, fmt, i, j, k, err, wc10, ba10, pnu;
|
||||
int32 f, fmt, i, j, k, wc10, ba10;
|
||||
int32 ba, fc, wc, drv, mpa10, vpn;
|
||||
d10 val, v[4];
|
||||
t_mtrlnt abc, tbc;
|
||||
static t_mtrlnt bceof = { MTR_TMK };
|
||||
t_mtrlnt tbc;
|
||||
t_stat st, r = SCPE_OK;
|
||||
|
||||
drv = uptr - tu_dev.units; /* get drive # */
|
||||
pnu = MT_TST_PNU (uptr); /* get pos not upd */
|
||||
MT_CLR_PNU (uptr); /* and clear */
|
||||
if (uptr->USTAT & FS_REW) { /* rewind or unload? */
|
||||
uptr->pos = 0; /* update position */
|
||||
sim_tape_rewind (uptr); /* rewind tape */
|
||||
uptr->USTAT = 0; /* clear status */
|
||||
tufs = tufs | FS_ATA | FS_SSC;
|
||||
update_tucs (CS1_SC, drv); /* update status */
|
||||
|
@ -702,8 +694,8 @@ wc = 0200000 - tuwc; /* get word count */
|
|||
fc = 0200000 - tufc; /* get frame count */
|
||||
wc10 = wc >> 1; /* 10 word count */
|
||||
ba10 = ba >> 2; /* 10 word addr */
|
||||
err = 0;
|
||||
uptr->USTAT = 0; /* clear status */
|
||||
|
||||
switch (f) { /* case on function */
|
||||
|
||||
/* Unit service - non-data transfer commands - set ATA when done */
|
||||
|
@ -711,9 +703,10 @@ switch (f) { /* case on function */
|
|||
case FNC_SPACEF: /* space forward */
|
||||
do {
|
||||
tufc = (tufc + 1) & 0177777; /* incr fc */
|
||||
if (tu_rdlntf (uptr, &tbc, &err)) break; /* read rec lnt, err? */
|
||||
uptr->pos = uptr->pos + ((MTRL (tbc) + 1) & ~1) +
|
||||
(2 * sizeof (t_mtrlnt)); }
|
||||
if (st = sim_tape_sprecf (uptr, &tbc)) { /* space rec fwd, err? */
|
||||
r = tu_map_err (uptr, st); /* map error */
|
||||
break; }
|
||||
}
|
||||
while (tufc != 0);
|
||||
if (tufc) tuer = tuer | ER_FCE;
|
||||
else tutc = tutc & ~TC_FCS;
|
||||
|
@ -723,26 +716,25 @@ case FNC_SPACEF: /* space forward */
|
|||
case FNC_SPACER: /* space reverse */
|
||||
do {
|
||||
tufc = (tufc + 1) & 0177777; /* incr wc */
|
||||
if (pnu) pnu = 0; /* pos not upd? */
|
||||
else {
|
||||
if (tu_rdlntr (uptr, &tbc, &err)) break;
|
||||
uptr->pos = uptr->pos - ((MTRL (tbc) + 1) & ~1) -
|
||||
(2 * sizeof (t_mtrlnt)); } }
|
||||
if (st = sim_tape_sprecr (uptr, &tbc)) { /* space rec rev, err? */
|
||||
r = tu_map_err (uptr, st); /* map error */
|
||||
break; }
|
||||
}
|
||||
while (tufc != 0);
|
||||
if (tufc) tuer = tuer | ER_FCE;
|
||||
else tutc = tutc & ~TC_FCS;
|
||||
tufs = tufs | FS_ATA;
|
||||
break;
|
||||
|
||||
case FNC_WREOF:
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
||||
fxwrite (&bceof, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
case FNC_WREOF: /* write end of file */
|
||||
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
|
||||
r = tu_map_err (uptr, st); /* map error */
|
||||
tufs = tufs | FS_ATA;
|
||||
if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr);
|
||||
else uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* update position */
|
||||
break;
|
||||
|
||||
case FNC_ERASE:
|
||||
if (sim_tape_wrp (uptr)) /* write protected? */
|
||||
r = tu_map_err (uptr, MTSE_WRP); /* map error */
|
||||
tufs = tufs | FS_ATA;
|
||||
break;
|
||||
|
||||
|
@ -762,21 +754,12 @@ case FNC_ERASE:
|
|||
case FNC_READF: /* read */
|
||||
case FNC_WCHKF: /* wcheck = read */
|
||||
tufc = 0; /* clear frame count */
|
||||
if ((uptr->UDENS == TC_1600) && (uptr->pos == 0))
|
||||
if ((uptr->UDENS == TC_1600) && sim_tape_bot (uptr))
|
||||
tufs = tufs | FS_ID; /* PE BOT? ID burst */
|
||||
TXFR (ba, wc, 0); /* validate transfer */
|
||||
if (tu_rdlntf (uptr, &tbc, &err)) break; /* read rec lnt, err? */
|
||||
if (MTRF (tbc)) { /* bad record? */
|
||||
tuer = tuer | ER_CRC; /* set error flag */
|
||||
uptr->pos = uptr->pos + ((MTRL (tbc) + 1) & ~1) +
|
||||
(2 * sizeof (t_mtrlnt));
|
||||
break; }
|
||||
if (tbc > XBUFLNT) return SCPE_MTRLNT; /* bad rec length? */
|
||||
abc = fxread (xbuf, sizeof (int8), tbc, uptr->fileref);
|
||||
if (err = ferror (uptr->fileref)) { /* error? */
|
||||
MT_SET_PNU (uptr); /* pos not upd */
|
||||
break; }
|
||||
for ( ; abc < tbc + 4; abc++) xbuf[abc] = 0; /* fill/pad with 0's */
|
||||
if (st = sim_tape_rdrecf (uptr, xbuf, &tbc, MT_MAXFR)) { /* read fwd */
|
||||
r = tu_map_err (uptr, st); /* map error */
|
||||
break; } /* done */
|
||||
for (i = j = 0; (i < wc10) && (j < ((int32) tbc)); i++) {
|
||||
if ((i == 0) || NEWPAGE (ba10 + i, 0)) { /* map new page */
|
||||
MAPM (ba10 + i, mpa10, 0); }
|
||||
|
@ -785,7 +768,6 @@ case FNC_WCHKF: /* wcheck = read */
|
|||
if (fmt == TC_10C) val = val | ((d10) xbuf[j++] & 017);
|
||||
if (f == FNC_READF) M[mpa10] = val;
|
||||
mpa10 = mpa10 + 1; } /* end for */
|
||||
uptr->pos = uptr->pos + ((tbc + 1) & ~1) + (2 * sizeof (t_mtrlnt));
|
||||
tufc = tbc & 0177777;
|
||||
tuwc = (tuwc + (i << 1)) & 0177777;
|
||||
ba = ba + (i << 2);
|
||||
|
@ -793,7 +775,6 @@ case FNC_WCHKF: /* wcheck = read */
|
|||
|
||||
case FNC_WRITE: /* write */
|
||||
TXFR (ba, wc, 0); /* validate transfer */
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
||||
for (i = j = 0; (i < wc10) && (j < fc); i++) {
|
||||
if ((i == 0) || NEWPAGE (ba10 + i, 0)) { /* map new page */
|
||||
MAPM (ba10 + i, mpa10, 0); }
|
||||
|
@ -805,13 +786,9 @@ case FNC_WRITE: /* write */
|
|||
if (fmt == TC_10C) xbuf[j++] = (uint8) (val & 017);
|
||||
mpa10 = mpa10 + 1; } /* end for */
|
||||
if (j < fc) fc = j; /* short record? */
|
||||
fxwrite (&fc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
fxwrite (xbuf, sizeof (int8), (fc + 1) & ~1, uptr->fileref);
|
||||
fxwrite (&fc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr);
|
||||
if (st = sim_tape_wrrecf (uptr, xbuf, fc)) /* write rec, err? */
|
||||
r = tu_map_err (uptr, st); /* map error */
|
||||
else {
|
||||
uptr->pos = uptr->pos + ((fc + 1) & ~1) +
|
||||
(2 * sizeof (t_mtrlnt));
|
||||
tufc = (tufc + fc) & 0177777;
|
||||
if (tufc == 0) tutc = tutc & ~TC_FCS;
|
||||
tuwc = (tuwc + (i << 1)) & 0177777;
|
||||
|
@ -822,18 +799,10 @@ case FNC_READR: /* read reverse */
|
|||
case FNC_WCHKR: /* wcheck = read */
|
||||
tufc = 0; /* clear frame count */
|
||||
TXFR (ba, wc, 1); /* validate xfer rev */
|
||||
if (tu_rdlntr (uptr, &tbc, &err)) break; /* read rec lnt, err? */
|
||||
if (MTRF (tbc)) { /* bad record? */
|
||||
tuer = tuer | ER_CRC; /* set error flag */
|
||||
uptr->pos = uptr->pos - ((MTRL (tbc) + 1) & ~1) -
|
||||
(2 * sizeof (t_mtrlnt));
|
||||
break; }
|
||||
if (tbc > XBUFLNT) return SCPE_MTRLNT; /* bad rec length? */
|
||||
fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt)
|
||||
- ((tbc + 1) & ~1), SEEK_SET);
|
||||
fxread (xbuf + 4, sizeof (int8), tbc, uptr->fileref);
|
||||
if (st = sim_tape_rdrecr (uptr, xbuf + 4, &tbc, MT_MAXFR)) { /* read rev */
|
||||
r = tu_map_err (uptr, st); /* map error */
|
||||
break; } /* done */
|
||||
for (i = 0; i < 4; i++) xbuf[i] = 0;
|
||||
err = ferror (uptr->fileref); /* set err but finish */
|
||||
for (i = 0, j = tbc + 4; (i < wc10) && (j >= 4); i++) {
|
||||
if ((i == 0) || NEWPAGE (ba10 - i, PAG_M_OFF)) { /* map page */
|
||||
MAPM (ba10 - i, mpa10, UMAP_RRV); }
|
||||
|
@ -842,7 +811,6 @@ case FNC_WCHKR: /* wcheck = read */
|
|||
val = val | (v[0] << 4) | (v[1] << 12) | (v[2] << 20) | (v[3] << 28);
|
||||
if (f == FNC_READR) M[mpa10] = val;
|
||||
mpa10 = mpa10 - 1; } /* end for */
|
||||
uptr->pos = uptr->pos - ((tbc + 1) & ~1) - (2 * sizeof (t_mtrlnt));
|
||||
tufc = tbc & 0177777;
|
||||
tuwc = (tuwc + (i << 1)) & 0177777;
|
||||
ba = ba - (i << 2);
|
||||
|
@ -851,12 +819,6 @@ case FNC_WCHKR: /* wcheck = read */
|
|||
tucs1 = (tucs1 & ~CS1_UAE) | ((ba >> (16 - CS1_V_UAE)) & CS1_UAE);
|
||||
tuba = ba & 0177777; /* update mem addr */
|
||||
tucs1 = tucs1 & ~CS1_GO; /* clear go */
|
||||
if (err != 0) { /* I/O error */
|
||||
tuer = tuer | ER_VPE; /* flag error */
|
||||
update_tucs (CS1_DONE | CS1_TRE, drv); /* set done, err */
|
||||
perror ("TU I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
return (tu_stopioe? SCPE_IOERR: SCPE_OK); }
|
||||
update_tucs (CS1_DONE, drv);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -880,8 +842,8 @@ if (GET_FMTR (tucs2) == 0) { /* formatter present? */
|
|||
if (tu_unit[drv].flags & UNIT_ATT) {
|
||||
tufs = tufs | FS_MOL | tu_unit[drv].USTAT;
|
||||
if (tu_unit[drv].UDENS == TC_1600) tufs = tufs | FS_PE;
|
||||
if (tu_unit[drv].flags & UNIT_WPRT) tufs = tufs | FS_WRL;
|
||||
if ((tu_unit[drv].pos == 0) && !act) tufs = tufs | FS_BOT; }
|
||||
if (sim_tape_wrp (&tu_unit[drv])) tufs = tufs | FS_WRL;
|
||||
if (sim_tape_bot (&tu_unit[drv]) && !act) tufs = tufs | FS_BOT; }
|
||||
if (tuer) tufs = tufs | FS_ERR; }
|
||||
else tufs = 0;
|
||||
tucs1 = (tucs1 & ~(CS1_SC | CS1_MCPE | CS1_MBZ)) | CS1_DVA | flag;
|
||||
|
@ -904,50 +866,38 @@ tuiff = 0; /* clear CSTB INTR */
|
|||
return VEC_TU; /* acknowledge */
|
||||
}
|
||||
|
||||
/* Read record length forward - return T if error, EOM, or EOF */
|
||||
/* Map tape error status */
|
||||
|
||||
t_bool tu_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
||||
t_stat tu_map_err (UNIT *uptr, t_stat st)
|
||||
{
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set tape pos */
|
||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref); /* read rec lnt */
|
||||
if (*err = ferror (uptr->fileref)) { /* error? */
|
||||
tuer = tuer | ER_VPE; /* parity error */
|
||||
MT_SET_PNU (uptr); /* pos not updated */
|
||||
return TRUE; }
|
||||
if (feof (uptr->fileref) || (*tbc == MTR_EOM)) { /* eof or eom? */
|
||||
tuer = tuer | ER_OPI; /* incomplete */
|
||||
MT_SET_PNU (uptr); /* pos not updated */
|
||||
return TRUE; }
|
||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
||||
switch (st) {
|
||||
case MTSE_FMT: /* illegal fmt */
|
||||
case MTSE_UNATT: /* not attached */
|
||||
tuer = tuer | ER_NXF; /* can't execute */
|
||||
case MTSE_OK: /* no error */
|
||||
return SCPE_IERR;
|
||||
case MTSE_TMK: /* end of file */
|
||||
tufs = tufs | FS_TMK;
|
||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* spc over tmk */
|
||||
return TRUE; }
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Read record length reverse - return T if error, EOM, or EOF */
|
||||
|
||||
t_bool tu_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
||||
{
|
||||
if (uptr->pos < sizeof (t_mtrlnt)) return TRUE;
|
||||
fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET);
|
||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
if (*err = ferror (uptr->fileref)) { /* error? */
|
||||
tuer = tuer | ER_VPE; /* parity error */
|
||||
return TRUE; }
|
||||
if (feof (uptr->fileref)) { /* eof? */
|
||||
break;
|
||||
case MTSE_IOERR: /* IO error */
|
||||
tuer = tuer | ER_VPE; /* flag error */
|
||||
if (tu_stopioe) return SCPE_IOERR;
|
||||
break;
|
||||
case MTSE_INVRL: /* invalid rec lnt */
|
||||
tuer = tuer | ER_VPE; /* flag error */
|
||||
return SCPE_MTRLNT;
|
||||
case MTSE_RECE: /* record in error */
|
||||
tuer = tuer | ER_CRC; /* set crc err */
|
||||
break;
|
||||
case MTSE_EOM: /* end of medium */
|
||||
tuer = tuer | ER_OPI; /* incomplete */
|
||||
return TRUE; }
|
||||
if (*tbc == MTR_EOM) { /* eom? */
|
||||
tuer = tuer | ER_OPI; /* incomplete */
|
||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over eom */
|
||||
return TRUE; }
|
||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
||||
tufs = tufs | FS_TMK;
|
||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over tmk */
|
||||
return TRUE; }
|
||||
*tbc = MTRL (*tbc); /* ignore error flag */
|
||||
return FALSE;
|
||||
break;
|
||||
case MTSE_BOT: /* reverse into BOT */
|
||||
break;
|
||||
case MTSE_WRP: /* write protect */
|
||||
tuer = tuer | ER_NXF; /* can't execute */
|
||||
break; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
@ -966,10 +916,10 @@ tuiff = 0; /* clear CSTB INTR */
|
|||
int_req = int_req & ~INT_TU; /* clear interrupt */
|
||||
for (u = 0; u < TU_NUMDR; u++) { /* loop thru units */
|
||||
uptr = tu_dev.units + u;
|
||||
MT_CLR_PNU (uptr); /* clear pos flag */
|
||||
sim_tape_reset (uptr); /* clear pos flag */
|
||||
sim_cancel (uptr); /* cancel activity */
|
||||
uptr->USTAT = 0; }
|
||||
if (xbuf == NULL) xbuf = calloc (XBUFLNT + 4, sizeof (uint8));
|
||||
if (xbuf == NULL) xbuf = calloc (MT_MAXFR + 4, sizeof (uint8));
|
||||
if (xbuf == NULL) return SCPE_MEM;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -981,9 +931,8 @@ t_stat tu_attach (UNIT *uptr, char *cptr)
|
|||
int32 drv = uptr - tu_dev.units;
|
||||
t_stat r;
|
||||
|
||||
r = attach_unit (uptr, cptr);
|
||||
r = sim_tape_attach (uptr, cptr);
|
||||
if (r != SCPE_OK) return r;
|
||||
MT_CLR_PNU (uptr);
|
||||
uptr->USTAT = 0; /* clear unit status */
|
||||
uptr->UDENS = UD_UNK; /* unknown density */
|
||||
tufs = tufs | FS_ATA | FS_SSC; /* set attention */
|
||||
|
@ -1004,21 +953,12 @@ if (sim_is_active (uptr)) { /* unit active? */
|
|||
tuer = tuer | ER_UNS; /* set formatter error */
|
||||
if ((uptr->USTAT & FS_REW) == 0) /* data transfer? */
|
||||
tucs1 = tucs1 | CS1_DONE | CS1_TRE; } /* set done, err */
|
||||
MT_CLR_PNU (uptr);
|
||||
uptr->USTAT = 0; /* clear status flags */
|
||||
tufs = tufs | FS_ATA | FS_SSC; /* set attention */
|
||||
update_tucs (CS1_SC, drv); /* update status */
|
||||
return detach_unit (uptr);
|
||||
return sim_tape_detach (uptr);
|
||||
}
|
||||
|
||||
/* Write lock/enable routine */
|
||||
|
||||
t_stat tu_vlock (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if (sim_is_active (uptr)) return SCPE_ARG;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Device bootstrap */
|
||||
|
||||
#define BOOT_START 0377000 /* start */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp18b_cpu.c: 18b PDP CPU simulator
|
||||
|
||||
Copyright (c) 1993-2002, Robert M Supnik
|
||||
Copyright (c) 1993-2003, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -25,6 +25,7 @@
|
|||
|
||||
cpu PDP-4/7/9/15 central processor
|
||||
|
||||
18-Feb-03 RMS Fixed three EAE bugs (found by Hans Pufal)
|
||||
05-Oct-02 RMS Added DIBs, device number support
|
||||
25-Jul-02 RMS Added DECtape support for PDP-4
|
||||
06-Jan-02 RMS Revised enable/disable support
|
||||
|
@ -1076,11 +1077,11 @@ case 033: case 032: /* EAE */
|
|||
if (IR & 0001000) LAC = LAC & 01000000; /* IR<8>? clear AC */
|
||||
link_init = LAC & 01000000; /* link temporary */
|
||||
fill = link_init? 0777777: 0; /* fill = link */
|
||||
esc = (IR & 077)? IR & 077: 0100; /* get eff SC */
|
||||
esc = IR & 077; /* get eff SC */
|
||||
|
||||
switch ((IR >> 6) & 07) { /* case on IR<9:11> */
|
||||
case 0: /* setup */
|
||||
if (IR & 04) LAC = LAC ^ 0777777; /* IR<15>? ~AC */
|
||||
if (IR & 04) MQ = MQ ^ 0777777; /* IR<15>? ~MQ */
|
||||
if (IR & 02) LAC = LAC | MQ; /* IR<16>? or MQ */
|
||||
if (IR & 01) LAC = LAC | ((-SC) & 077); /* IR<17>? or SC */
|
||||
break;
|
||||
|
@ -1091,10 +1092,13 @@ case 033: case 032: /* EAE */
|
|||
PC = INCR_ADDR (PC); /* increment PC */
|
||||
if (eae_ac_sign) MQ = MQ ^ 0777777; /* EAE AC sign? ~MQ */
|
||||
LAC = LAC & 0777777; /* clear link */
|
||||
for (SC = esc; SC != 0; SC--) { /* loop per step cnt */
|
||||
SC = esc; /* init SC */
|
||||
do { /* loop */
|
||||
if (MQ & 1) LAC = LAC + MA; /* MQ<17>? add */
|
||||
MQ = (MQ >> 1) | ((LAC & 1) << 17);
|
||||
LAC = LAC >> 1; } /* shift AC'MQ right */
|
||||
LAC = LAC >> 1; /* shift AC'MQ right */
|
||||
SC = (SC - 1) & 077; } /* decrement SC */
|
||||
while (SC != 0); /* until SC = 0 */
|
||||
if (eae_ac_sign ^ link_init) { /* result negative? */
|
||||
LAC = LAC ^ 0777777;
|
||||
MQ = MQ ^ 0777777; }
|
||||
|
@ -1121,16 +1125,19 @@ case 033: case 032: /* EAE */
|
|||
break; }
|
||||
LAC = LAC & 0777777; /* clear link */
|
||||
t = 0; /* init loop */
|
||||
for (SC = esc; SC != 0; SC--) { /* loop per step cnt */
|
||||
SC = esc; /* init SC */
|
||||
do { /* loop */
|
||||
if (t) LAC = (LAC + MA) & 01777777;
|
||||
else LAC = (LAC - MA) & 01777777;
|
||||
t = (LAC >> 18) & 1; /* quotient bit */
|
||||
if (SC > 1) LAC = /* skip if last */
|
||||
((LAC << 1) | (MQ >> 17)) & 01777777;
|
||||
MQ = ((MQ << 1) | t) & 0777777; }
|
||||
MQ = ((MQ << 1) | t) & 0777777; /* shift in quo bit */
|
||||
SC = (SC - 1) & 077; } /* decrement SC */
|
||||
while (SC != 0); /* until SC = 0 */
|
||||
if (t) LAC = (LAC + MA) & 01777777;
|
||||
if (eae_ac_sign) LAC = LAC ^ 0777777; /* sgn rem = sgn divd */
|
||||
if (eae_ac_sign ^ link_init ^ 1) MQ = MQ ^ 0777777;
|
||||
if ((eae_ac_sign ^ link_init) == 0) MQ = MQ ^ 0777777;
|
||||
break;
|
||||
|
||||
/* EAE, continued
|
||||
|
@ -1144,14 +1151,16 @@ case 033: case 032: /* EAE */
|
|||
#if defined (PDP15)
|
||||
if (!usmd) ion_defer = 2; /* free cycles */
|
||||
#endif
|
||||
for (SC = esc; (SC != 0) && ((LAC & 0400000) ==
|
||||
((LAC << 1) & 0400000)); SC--) {
|
||||
for (SC = esc; ((LAC & 0400000) == ((LAC << 1) & 0400000)); ) {
|
||||
LAC = (LAC << 1) | ((MQ >> 17) & 1);
|
||||
MQ = (MQ << 1) | (link_init >> 18); }
|
||||
MQ = (MQ << 1) | (link_init >> 18);
|
||||
SC = (SC - 1) & 077;
|
||||
if (SC == 0) break; }
|
||||
LAC = link_init | (LAC & 0777777); /* trim AC, restore L */
|
||||
MQ = MQ & 0777777; /* trim MQ */
|
||||
SC = SC & 077; /* trim SC */
|
||||
break;
|
||||
|
||||
case 5: /* long right shift */
|
||||
if (esc < 18) {
|
||||
MQ = ((LAC << (18 - esc)) | (MQ >> esc)) & 0777777;
|
||||
|
@ -1163,6 +1172,7 @@ case 033: case 032: /* EAE */
|
|||
LAC = link_init | fill; }
|
||||
SC = 0; /* clear step count */
|
||||
break;
|
||||
|
||||
case 6: /* long left shift */
|
||||
if (esc < 18) {
|
||||
LAC = link_init |
|
||||
|
@ -1175,6 +1185,7 @@ case 033: case 032: /* EAE */
|
|||
MQ = fill; }
|
||||
SC = 0; /* clear step count */
|
||||
break;
|
||||
|
||||
case 7: /* AC left shift */
|
||||
if (esc < 18) LAC = link_init |
|
||||
(((LAC << esc) | (fill >> (18 - esc))) & 0777777);
|
||||
|
|
|
@ -327,6 +327,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.2.4 Terminal Output (TTO)
|
||||
|
||||
The terminal output (TTO) writes to the simulator console window. It
|
||||
|
@ -419,7 +425,14 @@ For all printers, error handling is as follows:
|
|||
|
||||
2.2.6 Real-Time Clock (CLK)
|
||||
|
||||
The real-time clock (CLK) implements these registers:
|
||||
The real-time clock (CLK) frequency can be adjusted as follows:
|
||||
|
||||
SET CLK 60HZ set frequency to 60Hz
|
||||
SET CLK 50HZ set frequency to 50Hz
|
||||
|
||||
The default is 60Hz.
|
||||
|
||||
The clock implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
|
@ -427,7 +440,6 @@ The real-time clock (CLK) implements these registers:
|
|||
DONE 1 device done flag
|
||||
ENABLE 1 clock enable
|
||||
TIME 24 clock frequency
|
||||
TPS 8 ticks per second (60 or 50)
|
||||
|
||||
The real-time clock autocalibrates; the clock interval is adjusted up or
|
||||
down so that the clock tracks actual elapsed time.
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
mt (PDP-9) TC59 magtape
|
||||
(PDP-15) TC59D magtape
|
||||
|
||||
01-Mar-03 RMS Fixed bug in interrupt handling
|
||||
Revised for magtape library
|
||||
02-Feb-03 RMS Revised IOT decoding
|
||||
30-Oct-02 RMS Revised BOT handling, added error record handling
|
||||
05-Oct-02 RMS Added DIB, device number support
|
||||
|
@ -59,19 +61,15 @@
|
|||
*/
|
||||
|
||||
#include "pdp18b_defs.h"
|
||||
#include "sim_tape.h"
|
||||
|
||||
#define MT_NUMDR 8 /* #drives */
|
||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
||||
#define UNIT_V_PNU (UNIT_V_UF + 1) /* pos not updated */
|
||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
||||
#define UNIT_PNU (1 << UNIT_V_PNU)
|
||||
#define USTAT u3 /* unit status */
|
||||
#define MT_MAXFR (1 << 16) /* max record length */
|
||||
#define DBSIZE (1 << 12) /* max word count */
|
||||
#define DBMASK (DBSIZE - 1)
|
||||
#define MT_WC 032 /* word count */
|
||||
#define MT_CA 033 /* current addr */
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
#define WC_SIZE (1 << 12) /* max word count */
|
||||
#define WC_MASK (WC_SIZE - 1)
|
||||
|
||||
/* Command/unit - mt_cu */
|
||||
|
||||
|
@ -117,9 +115,6 @@
|
|||
#define STA_CLR 0000077 /* always clear */
|
||||
#define STA_DYN (STA_REW | STA_BOT | STA_EOF | STA_EOT)
|
||||
/* kept in USTAT */
|
||||
#define STA_EFLGS (STA_BOT | STA_ILL | STA_PAR | STA_EOF | \
|
||||
STA_EOT | STA_CPE | STA_RLE | STA_DLT | STA_BAD)
|
||||
/* error flags */
|
||||
|
||||
extern int32 M[];
|
||||
extern int32 int_hwre[API_HLVL+1];
|
||||
|
@ -129,6 +124,7 @@ int32 mt_cu = 0; /* command/unit */
|
|||
int32 mt_sta = 0; /* status register */
|
||||
int32 mt_time = 10; /* record latency */
|
||||
int32 mt_stopioe = 1; /* stop on error */
|
||||
uint8 *mtxb = NULL; /* transfer buffer */
|
||||
|
||||
DEVICE mt_dev;
|
||||
int32 mt (int32 pulse, int32 AC);
|
||||
|
@ -138,8 +134,7 @@ t_stat mt_reset (DEVICE *dptr);
|
|||
t_stat mt_attach (UNIT *uptr, char *cptr);
|
||||
t_stat mt_detach (UNIT *uptr);
|
||||
int32 mt_updcsta (UNIT *uptr, int32 val);
|
||||
t_bool mt_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
||||
t_bool mt_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
||||
t_stat mt_map_err (UNIT *uptr, t_stat st);
|
||||
UNIT *mt_busy (void);
|
||||
|
||||
/* MT data structures
|
||||
|
@ -177,8 +172,8 @@ REG mt_reg[] = {
|
|||
{ NULL } };
|
||||
|
||||
MTAB mt_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, 0, "DEVNO", "DEVNO", &set_devno, &show_devno },
|
||||
{ 0 } };
|
||||
|
||||
|
@ -221,9 +216,9 @@ if (pulse & 04) {
|
|||
sim_is_active (uptr) ||
|
||||
(f == FN_NOP) ||
|
||||
(((f == FN_SPACER) || (f == FN_REWIND)) && (uptr->USTAT & STA_BOT)) ||
|
||||
(((f == FN_WRITE) || (f == FN_WREOF)) && (uptr->flags & UNIT_WPRT)) ||
|
||||
(((f == FN_WRITE) || (f == FN_WREOF)) && sim_tape_wrp (uptr)) ||
|
||||
((uptr->flags & UNIT_ATT) == 0))
|
||||
mt_sta = mt_sta | STA_ILL; /* illegal op flag */
|
||||
mt_sta = mt_sta | STA_ILL | STA_ERR; /* set illegal op */
|
||||
else {
|
||||
if (f == FN_REWIND) uptr->USTAT = STA_REW; /* rewind? */
|
||||
else mt_sta = uptr->USTAT = 0; /* no, clear status */
|
||||
|
@ -243,20 +238,17 @@ return AC;
|
|||
|
||||
t_stat mt_svc (UNIT *uptr)
|
||||
{
|
||||
int32 c, c1, c2, c3, f, i, p, u, err, pnu;
|
||||
int32 c, c1, c2, c3, f, i, p, u;
|
||||
int32 wc, xma;
|
||||
t_mtrlnt abc, tbc, cbc;
|
||||
static uint8 dbuf[(3 * DBSIZE)];
|
||||
static t_mtrlnt bceof = MTR_TMK;
|
||||
t_mtrlnt tbc, cbc;
|
||||
t_stat st, r = SCPE_OK;
|
||||
|
||||
err = 0;
|
||||
u = uptr - mt_dev.units; /* get unit number */
|
||||
f = GET_CMD (mt_cu); /* get command */
|
||||
pnu = MT_TST_PNU (uptr); /* get pos not upd */
|
||||
MT_CLR_PNU (uptr); /* and clear */
|
||||
wc = WC_SIZE - (M[MT_WC] & WC_MASK); /* word count is 12b */
|
||||
|
||||
if (uptr->USTAT & STA_REW) { /* rewind? */
|
||||
uptr->pos = 0; /* update position */
|
||||
sim_tape_rewind (uptr); /* rewind tape */
|
||||
if (uptr->flags & UNIT_ATT) uptr->USTAT = STA_BOT;
|
||||
else uptr->USTAT = 0;
|
||||
if (u == GET_UNIT (mt_cu)) mt_updcsta (uptr, STA_DON);
|
||||
|
@ -266,124 +258,103 @@ if ((uptr->flags & UNIT_ATT) == 0) { /* if not attached */
|
|||
mt_updcsta (uptr, STA_ILL); /* illegal operation */
|
||||
return IORETURN (mt_stopioe, SCPE_UNATT); }
|
||||
|
||||
if ((f == FN_WRITE) || (f == FN_WREOF)) { /* write? */
|
||||
if (uptr->flags & UNIT_WPRT) { /* write locked? */
|
||||
mt_updcsta (uptr, STA_ILL); /* illegal operation */
|
||||
return SCPE_OK; }
|
||||
mt_cu = mt_cu & ~CU_ERASE; } /* clear erase flag */
|
||||
|
||||
switch (f) { /* case on function */
|
||||
|
||||
/* Unit service, continued */
|
||||
|
||||
case FN_READ: /* read */
|
||||
case FN_CMPARE: /* read/compare */
|
||||
if (mt_rdlntf (uptr, &tbc, &err)) { /* read rec lnt, err? */
|
||||
mt_updcsta (uptr, STA_RLE); /* set RLE flag */
|
||||
st = sim_tape_rdrecf (uptr, mtxb, &tbc, MT_MAXFR); /* read rec */
|
||||
if (st == MTSE_RECE) mt_sta = mt_sta | STA_PAR | STA_ERR; /* rec in err? */
|
||||
else if (st != MTSE_OK) { /* other error? */
|
||||
mt_sta = mt_sta | STA_RLE | STA_ERR; /* set RLE flag */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
break; }
|
||||
if (tbc > MT_MAXFR) return SCPE_MTRLNT; /* record too long? */
|
||||
wc = DBSIZE - (M[MT_WC] & DBMASK); /* get word count */
|
||||
cbc = PACKED (mt_cu)? wc * 3: wc * 2; /* expected bc */
|
||||
if (tbc != cbc) mt_sta = mt_sta | STA_RLE; /* wrong size? */
|
||||
if (tbc != cbc) mt_sta = mt_sta | STA_RLE | STA_ERR; /* wrong size? */
|
||||
if (tbc < cbc) { /* record small? */
|
||||
cbc = tbc; /* use smaller */
|
||||
wc = PACKED (mt_cu)? ((tbc + 2) / 3): ((tbc + 1) / 2); }
|
||||
abc = fxread (dbuf, sizeof (int8), cbc, uptr->fileref);
|
||||
if (err = ferror (uptr->fileref)) { /* error */
|
||||
MT_SET_PNU (uptr); /* pos not upd */
|
||||
break; }
|
||||
for ( ; abc < cbc; abc++) dbuf[abc] = 0; /* fill with 0's */
|
||||
for (i = p = 0; i < wc; i++) { /* copy buffer */
|
||||
M[MT_WC] = (M[MT_WC] + 1) & 0777777; /* inc WC, CA */
|
||||
M[MT_CA] = (M[MT_CA] + 1) & 0777777;
|
||||
xma = M[MT_CA] & ADDRMASK;
|
||||
if (PACKED (mt_cu)) { /* packed? */
|
||||
c1 = dbuf[p++] & 077;
|
||||
c2 = dbuf[p++] & 077;
|
||||
c3 = dbuf[p++] & 077;
|
||||
c1 = mtxb[p++] & 077;
|
||||
c2 = mtxb[p++] & 077;
|
||||
c3 = mtxb[p++] & 077;
|
||||
c = (c1 << 12) | (c2 << 6) | c3; }
|
||||
else {
|
||||
c1 = dbuf[p++];
|
||||
c2 = dbuf[p++];
|
||||
c1 = mtxb[p++];
|
||||
c2 = mtxb[p++];
|
||||
c = (c1 << 8) | c2; }
|
||||
if ((f == FN_READ) && MEM_ADDR_OK (xma)) M[xma] = c;
|
||||
else if ((f == FN_CMPARE) && (c != (M[xma] &
|
||||
(PACKED (mt_cu)? 0777777: 0177777)))) {
|
||||
mt_updcsta (uptr, STA_CPE);
|
||||
break; } }
|
||||
uptr->pos = uptr->pos + ((tbc + 1) & ~1) +
|
||||
(2 * sizeof (t_mtrlnt));
|
||||
break;
|
||||
|
||||
case FN_WRITE: /* write */
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
||||
wc = DBSIZE - (M[MT_WC] & DBMASK); /* get word count */
|
||||
tbc = PACKED (mt_cu)? wc * 3: wc * 2;
|
||||
fxwrite (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
xma = M[MT_CA] & ADDRMASK; /* get mem addr */
|
||||
for (i = p = 0; i < wc; i++) { /* copy buf to tape */
|
||||
M[MT_WC] = (M[MT_WC] + 1) & 0777777; /* inc WC, CA */
|
||||
M[MT_CA] = (M[MT_CA] + 1) & 0777777;
|
||||
xma = M[MT_CA] & ADDRMASK;
|
||||
xma = (xma + 1) & ADDRMASK; /* incr mem addr */
|
||||
if (PACKED (mt_cu)) { /* packed? */
|
||||
dbuf[p++] = (M[xma] >> 12) & 077;
|
||||
dbuf[p++] = (M[xma] >> 6) & 077;
|
||||
dbuf[p++] = M[xma] & 077; }
|
||||
mtxb[p++] = (M[xma] >> 12) & 077;
|
||||
mtxb[p++] = (M[xma] >> 6) & 077;
|
||||
mtxb[p++] = M[xma] & 077; }
|
||||
else {
|
||||
dbuf[p++] = (M[xma] >> 8) & 0377;
|
||||
dbuf[p++] = M[xma] & 0377; } }
|
||||
fxwrite (dbuf, sizeof (char), (tbc + 1) & ~1, uptr->fileref);
|
||||
fxwrite (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr); /* error? */
|
||||
else uptr->pos = uptr->pos + ((tbc + 1) & ~1) + /* no, upd pos */
|
||||
(2 * sizeof (t_mtrlnt));
|
||||
mtxb[p++] = (M[xma] >> 8) & 0377;
|
||||
mtxb[p++] = M[xma] & 0377; } }
|
||||
if (st = sim_tape_wrrecf (uptr, mtxb, tbc)) /* write rec, err? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
else {
|
||||
M[MT_CA] = (M[MT_CA] + wc) & 0777777; /* advance mem addr */
|
||||
M[MT_WC] = 0; } /* clear word cnt */
|
||||
mt_cu = mt_cu & ~CU_ERASE; /* clear erase flag */
|
||||
break;
|
||||
|
||||
/* Unit service, continued */
|
||||
|
||||
case FN_WREOF:
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
||||
fxwrite (&bceof, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
uptr->USTAT = STA_EOF;
|
||||
if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr); /* error? */
|
||||
else uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* no, upd pos */
|
||||
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
else uptr->USTAT = STA_EOF;
|
||||
mt_cu = mt_cu & ~CU_ERASE; /* clear erase flag */
|
||||
break;
|
||||
|
||||
case FN_SPACEF: /* space forward */
|
||||
do {
|
||||
M[MT_WC] = (M[MT_WC] + 1) & 0777777; /* inc WC */
|
||||
if (mt_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)) { /* space rec fwd, err? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
break; }
|
||||
}
|
||||
while (M[MT_WC] != 0);
|
||||
break;
|
||||
|
||||
case FN_SPACER: /* space reverse */
|
||||
do {
|
||||
M[MT_WC] = (M[MT_WC] + 1) & 0777777; /* inc WC */
|
||||
if (pnu) pnu = 0; /* pos not upd? */
|
||||
else {
|
||||
if (mt_rdlntf (uptr, &tbc, &err)) break;
|
||||
uptr->pos = uptr->pos - ((tbc + 1) & ~1) -
|
||||
(2 * sizeof (t_mtrlnt)); } }
|
||||
if (st = sim_tape_sprecr (uptr, &tbc)) { /* space rec rev, err? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
break; }
|
||||
}
|
||||
while (M[MT_WC] != 0);
|
||||
break; } /* end case */
|
||||
|
||||
mt_updcsta (uptr, STA_DON | (err? STA_PAR: 0)); /* set done */
|
||||
if (err != 0) { /* I/O error? */
|
||||
perror ("MT I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
if (mt_stopioe) return SCPE_IOERR; }
|
||||
return SCPE_OK;
|
||||
mt_updcsta (uptr, STA_DON); /* set done */
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Update controller status */
|
||||
|
||||
int32 mt_updcsta (UNIT *uptr, int32 news)
|
||||
{
|
||||
mt_sta = (mt_sta & ~(STA_DYN | STA_ERR | STA_CLR)) |
|
||||
mt_sta = (mt_sta & ~(STA_DYN | STA_CLR)) |
|
||||
(uptr->USTAT & STA_DYN) | news;
|
||||
if (mt_sta & STA_EFLGS) mt_sta = mt_sta | STA_ERR; /* error flag */
|
||||
if ((mt_sta & (STA_ERR | STA_DON)) && ((mt_cu & CU_IE) == 0))
|
||||
if ((mt_sta & (STA_ERR | STA_DON)) && (mt_cu & CU_IE))
|
||||
SET_INT (MTA);
|
||||
else CLR_INT (MTA); /* int request */
|
||||
return mt_sta;
|
||||
|
@ -399,59 +370,45 @@ UNIT *uptr;
|
|||
for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */
|
||||
uptr = mt_dev.units + u;
|
||||
if (sim_is_active (uptr) && ((uptr->USTAT & STA_REW) == 0))
|
||||
return uptr; }
|
||||
return uptr; }
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Read record length forward - return status flag if err, EOM, or EOF */
|
||||
/* Map tape error status */
|
||||
|
||||
t_bool mt_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
||||
t_stat mt_map_err (UNIT *uptr, t_stat st)
|
||||
{
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set tape pos */
|
||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref); /* read rec lnt */
|
||||
if (*err = ferror (uptr->fileref)) { /* error? */
|
||||
mt_sta = mt_sta | STA_PAR; /* set flag */
|
||||
MT_SET_PNU (uptr); /* pos not upd */
|
||||
return TRUE; }
|
||||
if (feof (uptr->fileref) || (*tbc == MTR_EOM)) { /* eof or eom? */
|
||||
mt_sta = mt_sta | STA_BAD; /* bad tape */
|
||||
MT_SET_PNU (uptr); /* pos not upd */
|
||||
return TRUE; }
|
||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
||||
uptr->USTAT = uptr->USTAT | STA_EOF; /* end of file */
|
||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* spc over tmk */
|
||||
return TRUE; }
|
||||
if (MTRF (*tbc)) mt_sta = mt_sta | STA_PAR; /* record in error? */
|
||||
*tbc = MTRL (*tbc); /* clear error flag */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Read record length reverse - return status flag if err, EOM, or EOF */
|
||||
|
||||
int32 mt_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
||||
{
|
||||
if (uptr->pos < sizeof (t_mtrlnt)) { /* at BOT? */
|
||||
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? */
|
||||
mt_sta = mt_sta | STA_PAR; /* set flag */
|
||||
return TRUE; }
|
||||
if (feof (uptr->fileref)) { /* eof? */
|
||||
mt_sta = mt_sta | STA_BAD; /* bad tape */
|
||||
return TRUE; }
|
||||
if (*tbc == MTR_EOM) { /* eom? */
|
||||
mt_sta = mt_sta | STA_BAD; /* bad tape */
|
||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over eom */
|
||||
return TRUE; }
|
||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
||||
uptr->USTAT = uptr->USTAT | STA_EOF; /* end of file */
|
||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over tmk */
|
||||
return TRUE; }
|
||||
if (MTRF (*tbc)) mt_sta = mt_sta | STA_PAR; /* record in error? */
|
||||
*tbc = MTRL (*tbc); /* clear error flag */
|
||||
return FALSE;
|
||||
switch (st) {
|
||||
case MTSE_FMT: /* illegal fmt */
|
||||
case MTSE_UNATT: /* not attached */
|
||||
mt_sta = mt_sta | STA_ILL | STA_ERR;
|
||||
case MTSE_OK: /* no error */
|
||||
return SCPE_IERR;
|
||||
case MTSE_TMK: /* end of file */
|
||||
uptr->USTAT = uptr->USTAT | STA_EOF; /* set EOF */
|
||||
mt_sta = mt_sta | STA_ERR;
|
||||
break;
|
||||
case MTSE_IOERR: /* IO error */
|
||||
mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */
|
||||
if (mt_stopioe) return SCPE_IOERR;
|
||||
break;
|
||||
case MTSE_INVRL: /* invalid rec lnt */
|
||||
mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */
|
||||
return SCPE_MTRLNT;
|
||||
case MTSE_RECE: /* record in error */
|
||||
mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */
|
||||
break;
|
||||
case MTSE_EOM: /* end of medium */
|
||||
mt_sta = mt_sta | STA_BAD | STA_ERR; /* set bad tape */
|
||||
break;
|
||||
case MTSE_BOT: /* reverse into BOT */
|
||||
uptr->USTAT = uptr->USTAT | STA_BOT; /* set status */
|
||||
mt_sta = mt_sta | STA_ERR;
|
||||
break;
|
||||
case MTSE_WRP: /* write protect */
|
||||
mt_sta = mt_sta | STA_ILL | STA_ERR; /* illegal operation */
|
||||
break; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
@ -464,11 +421,13 @@ UNIT *uptr;
|
|||
mt_cu = mt_sta = 0;
|
||||
for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */
|
||||
uptr = mt_dev.units + u;
|
||||
MT_CLR_PNU (uptr); /* clr pos not upd */
|
||||
sim_tape_reset (uptr); /* reset tape */
|
||||
sim_cancel (uptr); /* cancel activity */
|
||||
if (uptr->flags & UNIT_ATT) uptr->USTAT = STA_BOT;
|
||||
else uptr->USTAT = 0; }
|
||||
mt_updcsta (&mt_unit[0], 0); /* update status */
|
||||
if (mtxb == NULL) mtxb = calloc (MT_MAXFR, sizeof (uint8));
|
||||
if (mtxb == NULL) return SCPE_MEM;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -485,9 +444,8 @@ t_stat mt_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;
|
||||
MT_CLR_PNU (uptr);
|
||||
uptr->USTAT = STA_BOT;
|
||||
mt_updcsta (mt_dev.units + GET_UNIT (mt_cu), 0); /* update status */
|
||||
return r;
|
||||
|
@ -497,8 +455,7 @@ return r;
|
|||
|
||||
t_stat mt_detach (UNIT* uptr)
|
||||
{
|
||||
MT_CLR_PNU (uptr);
|
||||
if (!sim_is_active (uptr)) uptr->USTAT = 0;
|
||||
mt_updcsta (mt_dev.units + GET_UNIT (mt_cu), 0); /* update status */
|
||||
return detach_unit (uptr);
|
||||
return sim_tape_detach (uptr);
|
||||
}
|
||||
|
|
|
@ -26,7 +26,9 @@
|
|||
rf (PDP-9) RF09/RF09
|
||||
(PDP-15) RF15/RS09
|
||||
|
||||
05-Feb-03 RMS Fixed decode bugs, added variable and auto sizing
|
||||
03-Mar-03 RMS Fixed autosizing
|
||||
12-Feb-03 RMS Removed 8 platter sizing hack
|
||||
05-Feb-03 RMS Fixed decode bugs, added variable and autosizing
|
||||
05-Oct-02 RMS Added DIB, dev number support
|
||||
06-Jan-02 RMS Revised enable/disable support
|
||||
25-Nov-01 RMS Revised interrupt structure
|
||||
|
@ -50,9 +52,11 @@
|
|||
#include <math.h>
|
||||
|
||||
#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */
|
||||
#define UNIT_V_MSIZE (UNIT_V_UF + 1) /* dummy mask */
|
||||
#define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */
|
||||
#define UNIT_M_PLAT 07
|
||||
#define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1)
|
||||
#define UNIT_AUTO (1 << UNIT_V_AUTO)
|
||||
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
|
||||
#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT)
|
||||
|
||||
/* Constants */
|
||||
|
||||
|
@ -144,14 +148,14 @@ REG rf_reg[] = {
|
|||
{ NULL } };
|
||||
|
||||
MTAB rf_mod[] = {
|
||||
{ UNIT_MSIZE, 262144, NULL, "1P", &rf_set_size },
|
||||
{ UNIT_MSIZE, 524288, NULL, "2P", &rf_set_size },
|
||||
{ UNIT_MSIZE, 786432, NULL, "3P", &rf_set_size },
|
||||
{ UNIT_MSIZE, 1048576, NULL, "4P", &rf_set_size },
|
||||
{ UNIT_MSIZE, 1310720, NULL, "5P", &rf_set_size },
|
||||
{ UNIT_MSIZE, 1572864, NULL, "6P", &rf_set_size },
|
||||
{ UNIT_MSIZE, 1835008, NULL, "7P", &rf_set_size },
|
||||
{ UNIT_MSIZE, 2097152, NULL, "8P", &rf_set_size },
|
||||
{ UNIT_PLAT, 0, NULL, "1P", &rf_set_size },
|
||||
{ UNIT_PLAT, 1, NULL, "2P", &rf_set_size },
|
||||
{ UNIT_PLAT, 2, NULL, "3P", &rf_set_size },
|
||||
{ UNIT_PLAT, 3, NULL, "4P", &rf_set_size },
|
||||
{ UNIT_PLAT, 4, NULL, "5P", &rf_set_size },
|
||||
{ UNIT_PLAT, 5, NULL, "6P", &rf_set_size },
|
||||
{ UNIT_PLAT, 6, NULL, "7P", &rf_set_size },
|
||||
{ UNIT_PLAT, 7, NULL, "8P", &rf_set_size },
|
||||
{ UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno },
|
||||
{ 0 } };
|
||||
|
@ -186,7 +190,7 @@ if (pulse & 02) {
|
|||
else if (sb == 040) /* DSFX */
|
||||
rf_sta = rf_sta ^ (AC & (RFS_FNC | RFS_IE)); /* xor func */
|
||||
else if (sb == 060) /* DRAH */
|
||||
AC = AC | (rf_da >> 18);
|
||||
AC = AC | (rf_da >> 18) | ((rf_sta & RFS_NED)? 010: 0);
|
||||
}
|
||||
if (pulse & 04) {
|
||||
if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy sets PGE */
|
||||
|
@ -200,7 +204,7 @@ if (pulse & 04) {
|
|||
if (t < 0) t = t + RF_NUMWD; /* wrap around? */
|
||||
sim_activate (&rf_unit, t * rf_time); } } /* schedule op */
|
||||
else if (sb == 060) { /* DLAH */
|
||||
rf_da = (rf_da & 0777777) | ((AC & 017) << 18);
|
||||
rf_da = (rf_da & 0777777) | ((AC & 07) << 18);
|
||||
if ((t_addr) rf_da >= rf_unit.capac) /* for sizing */
|
||||
rf_updsta (RFS_NED); }
|
||||
}
|
||||
|
@ -300,19 +304,15 @@ return ((rf_sta & (RFS_ERR | RFS_DON))? IOS_RF: 0);
|
|||
|
||||
t_stat rf_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
int32 p, d;
|
||||
int32 ds_bytes = RF_DKSIZE * sizeof (int32);
|
||||
t_addr p, sz;
|
||||
t_addr ds_bytes = RF_DKSIZE * sizeof (int32);
|
||||
|
||||
if (uptr->flags & UNIT_AUTO) {
|
||||
FILE *fp = fopen (cptr, "rb");
|
||||
if (fp == NULL) return SCPE_OPENERR;
|
||||
fseek (fp, 0, SEEK_END);
|
||||
p = ftell (fp);
|
||||
d = (p + ds_bytes - 1) / ds_bytes;
|
||||
if (d == 0) d = 1;
|
||||
if (d > RF_NUMDK) d = RF_NUMDK;
|
||||
uptr->capac = d * RF_DKSIZE;
|
||||
fclose (fp); }
|
||||
if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (cptr))) {
|
||||
p = (sz + ds_bytes - 1) / ds_bytes;
|
||||
if (p == 0) p = 1;
|
||||
if (p > RF_NUMDK) p = RF_NUMDK; }
|
||||
else p = UNIT_GETP (uptr->flags);
|
||||
uptr->capac = p * RF_DKSIZE;
|
||||
return attach_unit (uptr, cptr);
|
||||
}
|
||||
|
||||
|
@ -320,10 +320,9 @@ return attach_unit (uptr, cptr);
|
|||
|
||||
t_stat rf_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if ((val == 0) || (val > (RF_NUMDK * RF_DKSIZE)))
|
||||
return SCPE_IERR;
|
||||
if ((val < 0) || (val > RF_NUMDK)) return SCPE_IERR;
|
||||
if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
|
||||
uptr->capac = val;
|
||||
uptr->capac = (val + 1) * RF_DKSIZE;
|
||||
uptr->flags = uptr->flags & ~UNIT_AUTO;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp18b_stddev.c: 18b PDP's standard devices
|
||||
|
||||
Copyright (c) 1993-2002, Robert M Supnik
|
||||
Copyright (c) 1993-2003, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -29,6 +29,7 @@
|
|||
tto teleprinter
|
||||
clk clock
|
||||
|
||||
01-Mar-03 RMS Added SET/SHOW CLK FREQ support, SET TTI CTRL-C support
|
||||
22-Dec-02 RMS Added break support
|
||||
01-Nov-02 RMS Added 7B/8B support to terminal
|
||||
05-Oct-02 RMS Added DIBs, device number support, IORS call
|
||||
|
@ -96,6 +97,9 @@ t_stat ptr_detach (UNIT *uptr);
|
|||
t_stat ptp_detach (UNIT *uptr);
|
||||
t_stat ptr_boot (int32 unitno, DEVICE *dptr);
|
||||
t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat tti_set_ctrlc (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
|
||||
extern int32 upd_iors (void);
|
||||
|
||||
|
@ -115,10 +119,16 @@ REG clk_reg[] = {
|
|||
{ FLDATA (DONE, int_hwre[API_CLK], INT_V_CLK) },
|
||||
{ FLDATA (ENABLE, clk_state, 0) },
|
||||
{ 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, "DEVNO", NULL, NULL, &show_devno },
|
||||
{ 0 } };
|
||||
|
||||
|
@ -273,8 +283,9 @@ MTAB tti_mod[] = {
|
|||
{ UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode },
|
||||
{ UNIT_HDX, 0 , "full duplex", "FDX", NULL },
|
||||
{ UNIT_HDX, UNIT_HDX, "half duplex", "HDX", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_VUN, 0, NULL, "CTRL-C", &tti_set_ctrlc, NULL, NULL },
|
||||
#endif
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_devno },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_devno, NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE tti_dev = {
|
||||
|
@ -392,6 +403,24 @@ sim_cancel (&clk_unit); /* stop clock */
|
|||
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;
|
||||
}
|
||||
|
||||
/* Paper tape reader: IOT routine */
|
||||
|
||||
|
@ -801,8 +830,8 @@ if ((tti_unit.flags & UNIT_HDX) && out && /* half duplex and */
|
|||
tti_unit.buf = c; /* got char */
|
||||
|
||||
#endif
|
||||
SET_INT (TTI); /* set flag */
|
||||
tti_unit.pos = tti_unit.pos + 1;
|
||||
SET_INT (TTI); /* set flag */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -823,6 +852,17 @@ CLR_INT (TTI); /* clear flag */
|
|||
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 = (uptr->flags & UNIT_KSR)? 0203: 0003;
|
||||
uptr->pos = uptr->pos + 1;
|
||||
SET_INT (TTI);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Terminal output: IOT routine */
|
||||
|
||||
|
@ -883,6 +923,8 @@ sim_cancel (&tto_unit); /* deactivate unit */
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Set mode */
|
||||
|
||||
t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
tti_unit.flags = (tti_unit.flags & ~(UNIT_KSR | UNIT_8B)) | val;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp18b_sys.c: 18b PDP's simulator interface
|
||||
|
||||
Copyright (c) 1993-2002, Robert M Supnik
|
||||
Copyright (c) 1993-2003, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,8 @@
|
|||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
02-Mar-03 RMS Split loaders apart for greater flexibility
|
||||
09-Feb-03 RMS Fixed bug in FMTASC (found by Hans Pufal)
|
||||
31-Jan-03 RMS Added support for RB09
|
||||
05-Oct-02 RMS Added variable device number support
|
||||
25-Jul-02 RMS Added PDP-4 DECtape support
|
||||
|
@ -159,7 +161,7 @@ const char *sim_stop_messages[] = {
|
|||
"Invalid API interrupt",
|
||||
"Non-standard device number" };
|
||||
|
||||
/* Binary loader */
|
||||
/* Binary loaders */
|
||||
|
||||
int32 getword (FILE *fileref, int32 *hi)
|
||||
{
|
||||
|
@ -176,9 +178,7 @@ if (hi != NULL) *hi = bits;
|
|||
return word;
|
||||
}
|
||||
|
||||
#if defined (PDP4) || defined (PDP7)
|
||||
|
||||
/* PDP-4/PDP-7: RIM format only
|
||||
/* PDP-4/PDP-7 RIM format loader
|
||||
|
||||
Tape format
|
||||
dac addr
|
||||
|
@ -189,11 +189,12 @@ return word;
|
|||
jmp addr or hlt
|
||||
*/
|
||||
|
||||
t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
|
||||
t_stat rim_load_47 (FILE *fileref, char *cptr)
|
||||
{
|
||||
int32 origin, val;
|
||||
|
||||
if ((*cptr != 0) || (flag != 0)) return SCPE_ARG;
|
||||
if (*cptr != 0) return SCPE_2MARG;
|
||||
origin = 0200;
|
||||
for (;;) {
|
||||
if ((val = getword (fileref, NULL)) < 0) return SCPE_FMT;
|
||||
if ((val & 0760000) == 0040000) { /* DAC? */
|
||||
|
@ -208,60 +209,58 @@ for (;;) {
|
|||
return SCPE_FMT; /* error */
|
||||
}
|
||||
|
||||
#else
|
||||
/* PDP-9/15 RIM format loader
|
||||
|
||||
/* PDP-9/PDP-15: RIM format and BIN format
|
||||
|
||||
RIM format (read in address specified externally)
|
||||
Tape format (read in address specified externally)
|
||||
data
|
||||
:
|
||||
data
|
||||
word to execute (bit 1 of last character set)
|
||||
|
||||
BIN format (starts after RIM bootstrap)
|
||||
block/ origin (>= 0)
|
||||
count
|
||||
checksum
|
||||
data
|
||||
:
|
||||
data
|
||||
block/
|
||||
:
|
||||
endblock/ origin (< 0)
|
||||
*/
|
||||
|
||||
t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
|
||||
t_stat rim_load_915 (FILE *fileref, char *cptr)
|
||||
{
|
||||
extern int32 sim_switches;
|
||||
int32 i, bits, origin, count, cksum, val;
|
||||
t_stat r;
|
||||
int32 bits, origin, val;
|
||||
char gbuf[CBUFSIZE];
|
||||
extern t_bool match_ext (char *fnm, char *ext);
|
||||
t_stat r;
|
||||
|
||||
/* RIM loader */
|
||||
if (*cptr != 0) { /* more input? */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get origin */
|
||||
origin = get_uint (gbuf, 8, ADDRMASK, &r);
|
||||
if (r != SCPE_OK) return r;
|
||||
if (*cptr != 0) return SCPE_ARG; } /* no more */
|
||||
else origin = 0200; /* default 200 */
|
||||
|
||||
if ((sim_switches & SWMASK ('R')) || /* RIM format? */
|
||||
(match_ext (fnam, "RIM") && !(sim_switches & SWMASK ('B')))) {
|
||||
if (*cptr != 0) { /* more input? */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get origin */
|
||||
origin = get_uint (gbuf, 8, ADDRMASK, &r);
|
||||
if (r != SCPE_OK) return r;
|
||||
if (*cptr != 0) return SCPE_ARG; } /* no more */
|
||||
else origin = 0200; /* default 200 */
|
||||
for (;;) { /* word loop */
|
||||
if ((val = getword (fileref, &bits)) < 0) return SCPE_FMT;
|
||||
if (bits & 1) { /* end of tape? */
|
||||
if ((val & 0760000) == OP_JMP) saved_PC =
|
||||
((origin - 1) & 060000) | (val & 017777);
|
||||
else if (val != OP_HLT) return SCPE_FMT;
|
||||
break; }
|
||||
else if (MEM_ADDR_OK (origin)) M[origin++] = val; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
for (;;) { /* word loop */
|
||||
if ((val = getword (fileref, &bits)) < 0) return SCPE_FMT;
|
||||
if (bits & 1) { /* end of tape? */
|
||||
if ((val & 0760000) == OP_JMP) saved_PC =
|
||||
((origin - 1) & 060000) | (val & 017777);
|
||||
else if (val != OP_HLT) return SCPE_FMT;
|
||||
break; }
|
||||
else if (MEM_ADDR_OK (origin)) M[origin++] = val; }
|
||||
return SCPE_OK; }
|
||||
/* PDP-9/15 BIN format loader
|
||||
|
||||
/* Binary loader */
|
||||
BIN format (starts after RIM bootstrap)
|
||||
block/ origin (>= 0)
|
||||
count
|
||||
checksum
|
||||
data
|
||||
:
|
||||
data
|
||||
block/
|
||||
:
|
||||
endblock/ origin (< 0)
|
||||
*/
|
||||
|
||||
if (*cptr != 0) return SCPE_ARG; /* no arguments */
|
||||
t_stat bin_load_915 (FILE *fileref, char *cptr)
|
||||
{
|
||||
int32 i, val, origin, count, cksum;
|
||||
|
||||
if (*cptr != 0) return SCPE_2MARG; /* no arguments */
|
||||
do { val = getc (fileref); } /* find end RIM */
|
||||
while (((val & 0100) == 0) && (val != EOF));
|
||||
if (val == EOF) rewind (fileref); /* no RIM? rewind */
|
||||
|
@ -283,6 +282,34 @@ for (;;) { /* block loop */
|
|||
if ((cksum & DMASK) != 0) return SCPE_CSUM; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
#if defined (PDP4) || defined (PDP7)
|
||||
|
||||
/* PDP-4/PDP-7: RIM format only */
|
||||
|
||||
t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
|
||||
{
|
||||
if (flag != 0) return SCPE_NOFNC;
|
||||
return rim_load_47 (fileref, cptr);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* PDP-9/PDP-15: all formats */
|
||||
|
||||
t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
|
||||
{
|
||||
extern int32 sim_switches;
|
||||
|
||||
if (flag != 0) return SCPE_NOFNC;
|
||||
if (sim_switches & SWMASK ('S')) /* PDP-4/7 format? */
|
||||
return rim_load_47 (fileref, cptr);
|
||||
if ((sim_switches & SWMASK ('R')) || /* RIM format? */
|
||||
(match_ext (fnam, "RIM") && !(sim_switches & SWMASK ('B'))))
|
||||
return rim_load_915 (fileref, cptr);
|
||||
return bin_load_915 (fileref, cptr); /* must be BIN */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Symbol tables */
|
||||
|
@ -679,7 +706,7 @@ return sp;
|
|||
return = status code
|
||||
*/
|
||||
|
||||
#define FMTASC(x) (((x) < 040)? "<%03o>": "%c", (x))
|
||||
#define FMTASC(x) (((x) < 040)? "<%03o>": "%c"), (x)
|
||||
#define SIXTOASC(x) (((x) >= 040)? (x): ((x) + 0100))
|
||||
|
||||
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
|
||||
|
@ -691,7 +718,7 @@ inst = val[0];
|
|||
cflag = (uptr == NULL) || (uptr == &cpu_unit);
|
||||
if (sw & SWMASK ('A')) { /* ASCII? */
|
||||
if (inst > 0377) return SCPE_ARG;
|
||||
fprintf (of, "%c", FMTASC (inst & 0177));
|
||||
fprintf (of, FMTASC (inst & 0177));
|
||||
return SCPE_OK; }
|
||||
if (sw & SWMASK ('C')) { /* character? */
|
||||
fprintf (of, "%c", SIXTOASC ((inst >> 12) & 077));
|
||||
|
@ -701,11 +728,11 @@ if (sw & SWMASK ('C')) { /* character? */
|
|||
#if defined (PDP15)
|
||||
if (sw & SWMASK ('P')) { /* packed ASCII? */
|
||||
i = val[1];
|
||||
fprintf (of, "%c", FMTASC ((inst >> 11) & 0177));
|
||||
fprintf (of, "%c", FMTASC ((inst >> 4) & 0177));
|
||||
fprintf (of, "%c", FMTASC (((inst << 3) | (i >> 15)) & 0177));
|
||||
fprintf (of, "%c", FMTASC ((i >> 8) & 0177));
|
||||
fprintf (of, "%c", FMTASC ((i >> 1) & 0177));
|
||||
fprintf (of, FMTASC ((inst >> 11) & 0177));
|
||||
fprintf (of, FMTASC ((inst >> 4) & 0177));
|
||||
fprintf (of, FMTASC (((inst << 3) | (i >> 15)) & 0177));
|
||||
fprintf (of, FMTASC ((i >> 8) & 0177));
|
||||
fprintf (of, FMTASC ((i >> 1) & 0177));
|
||||
return -1; }
|
||||
#endif
|
||||
if (!(sw & SWMASK ('M'))) return SCPE_ARG;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp8_clk.c: PDP-8 real-time clock simulator
|
||||
|
||||
Copyright (c) 1993-2002, Robert M Supnik
|
||||
Copyright (c) 1993-2003, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -25,6 +25,7 @@
|
|||
|
||||
clk real time clock
|
||||
|
||||
01-Mar-03 RMS Aded SET/SHOW CLK FREQ support
|
||||
04-Oct-02 RMS Added DIB, device number support
|
||||
30-Dec-01 RMS Removed for generalized timers
|
||||
05-Sep-01 RMS Added terminal multiplexor support
|
||||
|
@ -44,6 +45,8 @@ int32 tmxr_poll = 16000; /* term mux poll */
|
|||
int32 clk (int32 IR, int32 AC);
|
||||
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);
|
||||
|
||||
/* CLK data structures
|
||||
|
||||
|
@ -61,10 +64,16 @@ REG clk_reg[] = {
|
|||
{ FLDATA (ENABLE, int_enable, INT_V_CLK) },
|
||||
{ FLDATA (INT, int_req, INT_V_CLK) },
|
||||
{ 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, "DEVNO", NULL, NULL, &show_dev },
|
||||
{ 0 } };
|
||||
|
||||
|
@ -137,3 +146,21 @@ int_enable = int_enable & ~INT_CLK; /* clear enable */
|
|||
sim_activate (&clk_unit, clk_unit.wait); /* activate unit */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Set frequency */
|
||||
|
||||
t_stat clk_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if (cptr) return SCPE_ARG;
|
||||
if ((val != 50) && (val != 60)) return SCPE_IERR;
|
||||
clk_tps = val;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Show frequency */
|
||||
|
||||
t_stat clk_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
fprintf (st, (clk_tps == 50)? "50Hz": "60Hz");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
df DF32 fixed head disk
|
||||
|
||||
03-Mar-03 RMS Fixed autosizing
|
||||
02-Feb-03 RMS Added variable platter and autosizing support
|
||||
04-Oct-02 RMS Added DIBs, device number support
|
||||
28-Nov-01 RMS Added RL8A support
|
||||
|
@ -44,9 +45,11 @@
|
|||
#include <math.h>
|
||||
|
||||
#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */
|
||||
#define UNIT_V_MSIZE (UNIT_V_UF + 1) /* dummy mask */
|
||||
#define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */
|
||||
#define UNIT_M_PLAT 03
|
||||
#define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1)
|
||||
#define UNIT_AUTO (1 << UNIT_V_AUTO)
|
||||
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
|
||||
#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT)
|
||||
|
||||
/* Constants */
|
||||
|
||||
|
@ -119,7 +122,7 @@ DIB df_dib = { DEV_DF, 3, { &df60, &df61, &df62 } };
|
|||
|
||||
UNIT df_unit =
|
||||
{ UDATA (&df_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF,
|
||||
DF_NUMDK * DF_DKSIZE) };
|
||||
DF_DKSIZE) };
|
||||
|
||||
REG df_reg[] = {
|
||||
{ ORDATA (STA, df_sta, 12) },
|
||||
|
@ -136,10 +139,10 @@ REG df_reg[] = {
|
|||
{ NULL } };
|
||||
|
||||
MTAB df_mod[] = {
|
||||
{ UNIT_MSIZE, 32768, NULL, "1P", &df_set_size },
|
||||
{ UNIT_MSIZE, 65536, NULL, "2P", &df_set_size },
|
||||
{ UNIT_MSIZE, 98304, NULL, "3P", &df_set_size },
|
||||
{ UNIT_MSIZE, 131072, NULL, "4P", &df_set_size },
|
||||
{ UNIT_PLAT, 0, NULL, "1P", &df_set_size },
|
||||
{ UNIT_PLAT, 1, NULL, "2P", &df_set_size },
|
||||
{ UNIT_PLAT, 2, NULL, "3P", &df_set_size },
|
||||
{ UNIT_PLAT, 3, NULL, "4P", &df_set_size },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 } };
|
||||
|
@ -315,19 +318,15 @@ return SCPE_OK;
|
|||
|
||||
t_stat df_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
int32 p, d;
|
||||
int32 ds_bytes = DF_DKSIZE * sizeof (int16);
|
||||
t_addr p, sz;
|
||||
t_addr ds_bytes = DF_DKSIZE * sizeof (int16);
|
||||
|
||||
if (uptr->flags & UNIT_AUTO) {
|
||||
FILE *fp = fopen (cptr, "rb");
|
||||
if (fp == NULL) return SCPE_OPENERR;
|
||||
fseek (fp, 0, SEEK_END);
|
||||
p = ftell (fp);
|
||||
d = (p + ds_bytes - 1) / ds_bytes;
|
||||
if (d == 0) d = 1;
|
||||
if (d > DF_NUMDK) d = DF_NUMDK;
|
||||
uptr->capac = d * DF_DKSIZE;
|
||||
fclose (fp); }
|
||||
if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (cptr))) {
|
||||
p = (sz + ds_bytes - 1) / ds_bytes;
|
||||
if (p == 0) p = 1;
|
||||
if (p > DF_NUMDK) p = DF_NUMDK; }
|
||||
else p = UNIT_GETP (uptr->flags);
|
||||
uptr->capac = p * DF_DKSIZE;
|
||||
return attach_unit (uptr, cptr);
|
||||
}
|
||||
|
||||
|
@ -335,10 +334,9 @@ return attach_unit (uptr, cptr);
|
|||
|
||||
t_stat df_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if ((val == 0) || (val > (DF_NUMDK * DF_DKSIZE)))
|
||||
return SCPE_IERR;
|
||||
if ((val < 0) || (val >= DF_NUMDK)) return SCPE_IERR;
|
||||
if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
|
||||
uptr->capac = val;
|
||||
uptr->capac = (val + 1) * DF_DKSIZE;
|
||||
uptr->flags = uptr->flags & ~UNIT_AUTO;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
|
|
@ -39,10 +39,12 @@ This memorandum documents the PDP-8 simulator.
|
|||
sim/ sim_defs.h
|
||||
sim_rev.h
|
||||
sim_sock.h
|
||||
sim_tape.h
|
||||
sim_tmxr.h
|
||||
scp.c
|
||||
scp_tty.c
|
||||
sim_sock.c
|
||||
sim_tape.c
|
||||
sim_tmxr.c
|
||||
|
||||
sim/pdp8/ pdp8_defs.h
|
||||
|
@ -253,6 +255,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.2.4 KL8E Terminal Output (TTO)
|
||||
|
||||
The terminal output (TTO) writes to the simulator console window. It
|
||||
|
@ -296,7 +304,14 @@ Error handling is as follows:
|
|||
|
||||
2.2.6 DK8E Line-Frequency Clock (CLK)
|
||||
|
||||
The real-time clock (CLK) implements these registers:
|
||||
The real-time clock (CLK) frequency can be adjusted as follows:
|
||||
|
||||
SET CLK 60HZ set frequency to 60Hz
|
||||
SET CLK 50HZ set frequency to 50Hz
|
||||
|
||||
The default is 60Hz.
|
||||
|
||||
The clock implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
|
@ -304,7 +319,6 @@ The real-time clock (CLK) implements these registers:
|
|||
ENABLE 1 interrupt enable flag
|
||||
INT 1 interrupt pending flag
|
||||
TIME 24 clock interval
|
||||
TPS 8 ticks per second (60 or 50)
|
||||
|
||||
The real-time clock autocalibrates; the clock interval is adjusted up or
|
||||
down so that the clock tracks actual elapsed time.
|
||||
|
@ -516,7 +530,7 @@ from the attached file:
|
|||
SET RF 4P four platters (1024K)
|
||||
SET RF AUTOSIZE autosized on attach
|
||||
|
||||
The default is four platters.
|
||||
The default is one platter.
|
||||
|
||||
The RF08 implements these registers:
|
||||
|
||||
|
@ -562,7 +576,7 @@ from the attached file:
|
|||
SET DF 4P four platters (128K)
|
||||
SET DF AUTOSIZE autosized on attach
|
||||
|
||||
The default is four platters.
|
||||
The default is one platter.
|
||||
|
||||
The DF32 implements these registers:
|
||||
|
||||
|
|
232
PDP8/pdp8_mt.c
232
PDP8/pdp8_mt.c
|
@ -1,6 +1,6 @@
|
|||
/* pdp8_mt.c: PDP-8 magnetic tape simulator
|
||||
|
||||
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,8 @@
|
|||
|
||||
mt TM8E/TU10 magtape
|
||||
|
||||
01-Mar-03 RMS Fixed interrupt handling
|
||||
Revised for magtape library
|
||||
30-Oct-02 RMS Revised BOT handling, added error record handling
|
||||
04-Oct-02 RMS Added DIBs, device number support
|
||||
30-Aug-02 RMS Revamped error handling
|
||||
|
@ -55,17 +57,13 @@
|
|||
*/
|
||||
|
||||
#include "pdp8_defs.h"
|
||||
#include "sim_tape.h"
|
||||
|
||||
#define MT_NUMDR 8 /* #drives */
|
||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
||||
#define UNIT_V_PNU (UNIT_V_UF + 1) /* pos not updated */
|
||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
||||
#define UNIT_PNU (1 << UNIT_V_PNU)
|
||||
#define USTAT u3 /* unit status */
|
||||
#define MT_MAXFR (1 << 16) /* max record lnt */
|
||||
#define DBSIZE (1 << 12) /* max data cmd */
|
||||
#define DBMASK (SBSIZE - 1)
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
#define WC_SIZE (1 << 12) /* max word count */
|
||||
#define WC_MASK (WC_SIZE - 1)
|
||||
|
||||
/* Command/unit - mt_cu */
|
||||
|
||||
|
@ -125,9 +123,6 @@
|
|||
#define STA_CLR (FN_RMASK | 00020) /* always clear */
|
||||
#define STA_DYN (STA_REW | STA_BOT | STA_REM | STA_EOF | \
|
||||
STA_EOT | STA_WLK) /* kept in USTAT */
|
||||
#define STA_EFLGS (STA_BOT | STA_PAR | STA_RLE | STA_DLT | \
|
||||
STA_EOT | STA_CPE | STA_ILL | STA_EOF | \
|
||||
STA_INC )
|
||||
/* set error */
|
||||
#define TUR(u) (!sim_is_active (u)) /* tape unit ready */
|
||||
|
||||
|
@ -144,6 +139,7 @@ int32 mt_db = 0; /* data buffer */
|
|||
int32 mt_done = 0; /* mag tape flag */
|
||||
int32 mt_time = 10; /* record latency */
|
||||
int32 mt_stopioe = 1; /* stop on error */
|
||||
uint8 *mtxb = NULL; /* transfer buffer */
|
||||
|
||||
DEVICE mt_dev;
|
||||
int32 mt70 (int32 IR, int32 AC);
|
||||
|
@ -155,11 +151,10 @@ t_stat mt_attach (UNIT *uptr, char *cptr);
|
|||
t_stat mt_detach (UNIT *uptr);
|
||||
int32 mt_updcsta (UNIT *uptr);
|
||||
int32 mt_ixma (int32 xma);
|
||||
t_stat mt_map_err (UNIT *uptr, t_stat st);
|
||||
t_stat mt_vlock (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
UNIT *mt_busy (void);
|
||||
void mt_set_done (void);
|
||||
t_bool mt_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
||||
t_bool mt_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err);
|
||||
|
||||
/* MT data structures
|
||||
|
||||
|
@ -200,8 +195,8 @@ REG mt_reg[] = {
|
|||
{ NULL } };
|
||||
|
||||
MTAB mt_mod[] = {
|
||||
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", &mt_vlock },
|
||||
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", &mt_vlock },
|
||||
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", &mt_vlock },
|
||||
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", &mt_vlock },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
{ 0 } };
|
||||
|
@ -235,21 +230,21 @@ case 4: /* CCAR */
|
|||
mt_ca = 0; /* clear mem address */
|
||||
return AC;
|
||||
case 5: /* LCMR */
|
||||
if (mt_busy ()) mt_sta = mt_sta | STA_ILL; /* busy? illegal op */
|
||||
if (mt_busy ()) mt_sta = mt_sta | STA_ILL | STA_ERR; /* busy? illegal op */
|
||||
mt_cu = AC; /* load command reg */
|
||||
mt_updcsta (mt_dev.units + GET_UNIT (mt_cu));
|
||||
return 0;
|
||||
case 6: /* LFGR */
|
||||
if (mt_busy ()) mt_sta = mt_sta | STA_ILL; /* busy? illegal op */
|
||||
if (mt_busy ()) mt_sta = mt_sta | STA_ILL | STA_ERR; /* busy? illegal op */
|
||||
mt_fn = AC; /* load function */
|
||||
if ((mt_fn & FN_GO) == 0) { /* go set? */
|
||||
mt_updcsta (uptr); /* update status */
|
||||
return 0; }
|
||||
f = GET_FNC (mt_fn); /* get function */
|
||||
if (((uptr->flags & UNIT_ATT) == 0) || !TUR (uptr) ||
|
||||
(((f == FN_WRITE) || (f == FN_WREOF)) && (uptr->flags & UNIT_WPRT))
|
||||
|| (((f == FN_SPACER) || (f == FN_REWIND)) && (uptr->USTAT & STA_BOT))) {
|
||||
mt_sta = mt_sta | STA_ILL; /* illegal op error */
|
||||
(((f == FN_WRITE) || (f == FN_WREOF)) && sim_tape_wrp (uptr))
|
||||
|| (((f == FN_SPACER) || (f == FN_REWIND)) && sim_tape_bot (uptr))) {
|
||||
mt_sta = mt_sta | STA_ILL | STA_ERR; /* illegal op error */
|
||||
mt_set_done (); /* set done */
|
||||
mt_updcsta (uptr); /* update status */
|
||||
return 0; }
|
||||
|
@ -266,7 +261,7 @@ case 6: /* LFGR */
|
|||
sim_activate (uptr, mt_time); /* start io */
|
||||
return 0;
|
||||
case 7: /* LDBR */
|
||||
if (mt_busy ()) mt_sta = mt_sta | STA_ILL; /* busy? illegal op */
|
||||
if (mt_busy ()) mt_sta = mt_sta | STA_ILL | STA_ERR; /* busy? illegal op */
|
||||
mt_db = AC; /* load buffer */
|
||||
mt_set_done (); /* set done */
|
||||
mt_updcsta (uptr); /* update status */
|
||||
|
@ -333,20 +328,18 @@ return (stop_inst << IOT_V_REASON) + AC; /* ill inst */
|
|||
|
||||
t_stat mt_svc (UNIT *uptr)
|
||||
{
|
||||
int32 f, i, p, u, err, wc, xma, pnu;
|
||||
t_mtrlnt abc, tbc, cbc;
|
||||
int32 f, i, p, u, wc, xma;
|
||||
t_mtrlnt tbc, cbc;
|
||||
uint16 c, c1, c2;
|
||||
uint8 dbuf[(2 * DBSIZE)];
|
||||
static t_mtrlnt bceof = MTR_TMK;
|
||||
t_stat st, r = SCPE_OK;
|
||||
|
||||
err = 0;
|
||||
u = uptr - mt_dev.units; /* get unit number */
|
||||
f = GET_FNC (mt_fn); /* get command */
|
||||
pnu = MT_TST_PNU (uptr); /* get pos not upd */
|
||||
MT_CLR_PNU (uptr); /* and clear */
|
||||
xma = GET_EMA (mt_cu) + mt_ca; /* get mem addr */
|
||||
wc = WC_SIZE - mt_wc; /* get wc */
|
||||
|
||||
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 = (uptr->USTAT & STA_WLK) | STA_BOT;
|
||||
else uptr->USTAT = STA_REM;
|
||||
|
@ -357,122 +350,95 @@ if (uptr->USTAT & STA_REW) { /* rewind? */
|
|||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* if not attached */
|
||||
uptr->USTAT = STA_REM; /* unit off line */
|
||||
mt_sta = mt_sta | STA_ILL; /* illegal operation */
|
||||
mt_sta = mt_sta | STA_ILL | STA_ERR; /* illegal operation */
|
||||
mt_set_done (); /* set done */
|
||||
mt_updcsta (uptr); /* update status */
|
||||
return IORETURN (mt_stopioe, SCPE_UNATT); }
|
||||
|
||||
if (((f == FN_WRITE) || (f == FN_WREOF)) && (uptr->flags & UNIT_WPRT)) {
|
||||
mt_sta = mt_sta | STA_ILL; /* illegal operation */
|
||||
mt_set_done (); /* set done */
|
||||
mt_updcsta (uptr); /* update status */
|
||||
return SCPE_OK; }
|
||||
|
||||
xma = GET_EMA (mt_cu) + mt_ca; /* get mem addr */
|
||||
wc = 010000 - mt_wc; /* get wc */
|
||||
switch (f) { /* case on function */
|
||||
|
||||
/* Unit service, continued */
|
||||
|
||||
case FN_READ: /* read */
|
||||
case FN_CMPARE: /* read/compare */
|
||||
if (mt_rdlntf (uptr, &tbc, &err)) { /* read rec lnt */
|
||||
mt_sta = mt_sta | STA_RLE; /* err, eof/eom, tmk */
|
||||
st = sim_tape_rdrecf (uptr, mtxb, &tbc, MT_MAXFR); /* read rec */
|
||||
if (st == MTSE_RECE) mt_sta = mt_sta | STA_PAR | STA_ERR; /* rec in err? */
|
||||
else if (st != MTSE_OK) { /* other error? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
mt_sta = mt_sta | STA_RLE | STA_ERR; /* err, eof/eom, tmk */
|
||||
break; }
|
||||
if (tbc > MT_MAXFR) return SCPE_MTRLNT; /* record too long? */
|
||||
cbc = (mt_cu & CU_UNPAK)? wc: wc * 2; /* expected bc */
|
||||
if (tbc != cbc) mt_sta = mt_sta | STA_RLE; /* wrong size? */
|
||||
if (tbc != cbc) mt_sta = mt_sta | STA_RLE | STA_ERR; /* wrong size? */
|
||||
if (tbc < cbc) { /* record small? */
|
||||
cbc = tbc; /* use smaller */
|
||||
wc = (mt_cu & CU_UNPAK)? cbc: (cbc + 1) / 2; }
|
||||
abc = fxread (dbuf, sizeof (uint8), cbc, uptr->fileref);
|
||||
if (err = ferror (uptr->fileref)) { /* error? */
|
||||
mt_sta = mt_sta | STA_RLE; /* set flag */
|
||||
MT_SET_PNU (uptr); /* pos not upd */
|
||||
break; }
|
||||
for ( ; abc < cbc; abc++) dbuf[abc] = 0; /* fill with 0's */
|
||||
for (i = p = 0; i < wc; i++) { /* copy buffer */
|
||||
xma = mt_ixma (xma); /* increment xma */
|
||||
if (mt_cu & CU_UNPAK) c = dbuf[p++];
|
||||
mt_wc = (mt_wc + 1) & 07777; /* incr word cnt */
|
||||
if (mt_cu & CU_UNPAK) c = mtxb[p++];
|
||||
else {
|
||||
c1 = dbuf[p++] & 077;
|
||||
c2 = dbuf[p++] & 077;
|
||||
c1 = mtxb[p++] & 077;
|
||||
c2 = mtxb[p++] & 077;
|
||||
c = (c1 << 6) | c2; }
|
||||
if ((f == FN_READ) && MEM_ADDR_OK (xma)) M[xma] = c;
|
||||
else if ((f == FN_CMPARE) && (M[xma] != c)) {
|
||||
mt_sta = mt_sta | STA_CPE;
|
||||
mt_sta = mt_sta | STA_CPE | STA_ERR;
|
||||
break; } }
|
||||
mt_wc = (mt_wc + wc) & 07777; /* update wc */
|
||||
uptr->pos = uptr->pos + ((tbc + 1) & ~1) + /* update tape pos */
|
||||
(2 * sizeof (t_mtrlnt));
|
||||
break;
|
||||
|
||||
case FN_WRITE: /* write */
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
||||
tbc = (mt_cu & CU_UNPAK)? wc: wc * 2;
|
||||
fxwrite (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
for (i = p = 0; i < wc; i++) { /* copy buf to tape */
|
||||
xma = mt_ixma (xma); /* incr mem addr */
|
||||
if (mt_cu & CU_UNPAK) dbuf[p++] = M[xma] & 0377;
|
||||
if (mt_cu & CU_UNPAK) mtxb[p++] = M[xma] & 0377;
|
||||
else {
|
||||
dbuf[p++] = (M[xma] >> 6) & 077;
|
||||
dbuf[p++] = M[xma] & 077; } }
|
||||
fxwrite (dbuf, sizeof (int8), (tbc + 1) & ~1, uptr->fileref);
|
||||
fxwrite (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr); /* error? */
|
||||
else {
|
||||
mt_wc = 0;
|
||||
uptr->pos = uptr->pos + ((tbc + 1) & ~1) + /* upd tape pos */
|
||||
(2 * sizeof (t_mtrlnt)); }
|
||||
mtxb[p++] = (M[xma] >> 6) & 077;
|
||||
mtxb[p++] = M[xma] & 077; } }
|
||||
if (st = sim_tape_wrrecf (uptr, mtxb, tbc)) { /* write rec, err? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
xma = GET_EMA (mt_cu) + mt_ca; } /* restore xma */
|
||||
else mt_wc = 0; /* ok, clear wc */
|
||||
break;
|
||||
|
||||
/* Unit service, continued */
|
||||
|
||||
case FN_WREOF:
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
||||
fxwrite (&bceof, sizeof (t_mtrlnt), 1, uptr->fileref); /* write eof */
|
||||
if (err = ferror (uptr->fileref)) MT_SET_PNU (uptr); /* error? */
|
||||
else uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* update tape pos */
|
||||
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
break;
|
||||
|
||||
case FN_SPACEF: /* space forward */
|
||||
do {
|
||||
mt_wc = (mt_wc + 1) & 07777; /* incr wc */
|
||||
if (mt_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)) { /* space rec fwd, err? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
break; } /* stop */
|
||||
}
|
||||
while (mt_wc != 0);
|
||||
break;
|
||||
|
||||
case FN_SPACER: /* space reverse */
|
||||
do {
|
||||
mt_wc = (mt_wc + 1) & 07777; /* incr wc */
|
||||
if (pnu) pnu = 0; /* pos not upd? */
|
||||
else {
|
||||
if (mt_rdlntr (uptr, &tbc, &err)) break;
|
||||
uptr->pos = uptr->pos - ((tbc + 1) & ~1) -
|
||||
(2 * sizeof (t_mtrlnt)); } }
|
||||
if (st = sim_tape_sprecr (uptr, &tbc)) { /* space rec rev, err? */
|
||||
r = mt_map_err (uptr, st); /* map error */
|
||||
break; } /* stop */
|
||||
}
|
||||
while (mt_wc != 0);
|
||||
break; } /* end case */
|
||||
|
||||
if (err != 0) mt_sta = mt_sta | STA_PAR; /* error? set flag */
|
||||
mt_cu = (mt_cu & ~CU_EMA) | ((xma >> (12 - CU_V_EMA)) & CU_EMA);
|
||||
mt_ca = xma & 07777; /* update mem addr */
|
||||
mt_set_done (); /* set done */
|
||||
mt_updcsta (uptr); /* update status */
|
||||
if (err != 0) { /* error? */
|
||||
perror ("MT I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
if (mt_stopioe) return SCPE_IOERR; }
|
||||
return SCPE_OK;
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Update controller status */
|
||||
|
||||
int32 mt_updcsta (UNIT *uptr)
|
||||
{
|
||||
mt_sta = (mt_sta & ~(STA_DYN | STA_ERR | STA_CLR)) | (uptr->USTAT & STA_DYN);
|
||||
if (mt_sta & STA_EFLGS) mt_sta = mt_sta | STA_ERR;
|
||||
mt_sta = (mt_sta & ~(STA_DYN | STA_CLR)) | (uptr->USTAT & STA_DYN);
|
||||
if (((mt_sta & STA_ERR) && (mt_cu & CU_IEE)) ||
|
||||
(mt_done && (mt_cu & CU_IED))) int_req = int_req | INT_MT;
|
||||
else int_req = int_req & ~INT_MT;
|
||||
|
@ -501,7 +467,7 @@ int32 v;
|
|||
|
||||
v = ((xma + 1) & 07777) | (xma & 070000); /* wrapped incr */
|
||||
if (mt_fn & FN_INC) { /* increment mode? */
|
||||
if (xma == 077777) mt_sta = mt_sta | STA_INC; /* at limit? error */
|
||||
if (xma == 077777) mt_sta = mt_sta | STA_INC | STA_ERR; /* at limit? error */
|
||||
else v = xma + 1; } /* else 15b incr */
|
||||
return v;
|
||||
}
|
||||
|
@ -515,50 +481,39 @@ mt_fn = mt_fn & ~(FN_CRC | FN_GO | FN_INC); /* clear func<4:6> */
|
|||
return;
|
||||
}
|
||||
|
||||
/* Read record length forward - return T if error, EOM, or EOF */
|
||||
/* Map tape error status */
|
||||
|
||||
t_bool mt_rdlntf (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
||||
t_stat mt_map_err (UNIT *uptr, t_stat st)
|
||||
{
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set tape pos */
|
||||
fxread (tbc, sizeof (t_mtrlnt), 1, uptr->fileref); /* read rec lnt */
|
||||
if ((*err = ferror (uptr->fileref)) || /* error, */
|
||||
feof (uptr->fileref) || (*tbc == MTR_EOM)) { /* eof or eom? */
|
||||
mt_sta = mt_sta | STA_PAR; /* parity error */
|
||||
MT_SET_PNU (uptr); /* pos not upd */
|
||||
return TRUE; }
|
||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
||||
uptr->USTAT = uptr->USTAT | STA_EOF; /* end of file */
|
||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* spc over tmk */
|
||||
return TRUE; }
|
||||
if (MTRF (*tbc)) mt_sta = mt_sta | STA_PAR; /* record in error? */
|
||||
*tbc = MTRL (*tbc); /* clear error flag */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Read record length reverse - return T if error, EOM, or EOF */
|
||||
|
||||
t_bool mt_rdlntr (UNIT *uptr, t_mtrlnt *tbc, int32 *err)
|
||||
{
|
||||
if (uptr->pos < sizeof (t_mtrlnt)) { /* at BOT? */
|
||||
switch (st) {
|
||||
case MTSE_FMT: /* illegal fmt */
|
||||
case MTSE_UNATT: /* unattached */
|
||||
mt_sta = mt_sta | STA_ILL | STA_ERR;
|
||||
case MTSE_OK: /* no error */
|
||||
return SCPE_IERR; /* never get here! */
|
||||
case MTSE_TMK: /* end of file */
|
||||
uptr->USTAT = uptr->USTAT | STA_EOF; /* set EOF */
|
||||
mt_sta = mt_sta | STA_ERR;
|
||||
break;
|
||||
case MTSE_IOERR: /* IO error */
|
||||
mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */
|
||||
if (mt_stopioe) return SCPE_IOERR;
|
||||
break;
|
||||
case MTSE_INVRL: /* invalid rec lnt */
|
||||
mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */
|
||||
return SCPE_MTRLNT;
|
||||
case MTSE_RECE: /* record in error */
|
||||
case MTSE_EOM: /* end of medium */
|
||||
mt_sta = mt_sta | STA_PAR | STA_ERR; /* set par err */
|
||||
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? */
|
||||
feof (uptr->fileref)) { /* end of file? */
|
||||
mt_sta = mt_sta | STA_PAR; /* parity error */
|
||||
return TRUE; }
|
||||
if (*tbc == MTR_EOM) { /* eom? */
|
||||
mt_sta = mt_sta | STA_PAR; /* bad tape */
|
||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over eom */
|
||||
return TRUE; }
|
||||
if (*tbc == MTR_TMK) { /* tape mark? */
|
||||
uptr->USTAT = uptr->USTAT | STA_EOF; /* end of file */
|
||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over tmk */
|
||||
return TRUE; }
|
||||
if (MTRF (*tbc)) mt_sta = mt_sta | STA_PAR; /* record in error? */
|
||||
*tbc = MTRL (*tbc); /* clear error flag */
|
||||
return FALSE;
|
||||
mt_sta = mt_sta | STA_ERR;
|
||||
break;
|
||||
case MTSE_WRP: /* write protect */
|
||||
mt_sta = mt_sta | STA_ILL | STA_ERR; /* illegal operation */
|
||||
break; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Reset routine */
|
||||
|
@ -573,11 +528,13 @@ int_req = int_req & ~INT_MT; /* clear interrupt */
|
|||
for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */
|
||||
uptr = mt_dev.units + u;
|
||||
sim_cancel (uptr); /* cancel activity */
|
||||
MT_CLR_PNU (uptr); /* clear pos flag */
|
||||
sim_tape_reset (uptr); /* reset tape */
|
||||
if (uptr->flags & UNIT_ATT) uptr->USTAT =
|
||||
((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 = STA_REM; }
|
||||
if (mtxb == NULL) mtxb = calloc (MT_MAXFR, sizeof (uint8));
|
||||
if (mtxb == NULL) return SCPE_MEM;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -588,10 +545,9 @@ t_stat mt_attach (UNIT *uptr, char *cptr)
|
|||
t_stat r;
|
||||
int32 u = uptr - mt_dev.units; /* get unit number */
|
||||
|
||||
r = attach_unit (uptr, cptr);
|
||||
r = sim_tape_attach (uptr, cptr);
|
||||
if (r != SCPE_OK) return r;
|
||||
MT_CLR_PNU (uptr);
|
||||
uptr->USTAT = STA_BOT | ((uptr->flags & UNIT_WPRT)? STA_WLK: 0);
|
||||
uptr->USTAT = STA_BOT | (sim_tape_wrp (uptr)? STA_WLK: 0);
|
||||
if (u == GET_UNIT (mt_cu)) mt_updcsta (uptr);
|
||||
return r;
|
||||
}
|
||||
|
@ -602,10 +558,9 @@ t_stat mt_detach (UNIT* uptr)
|
|||
{
|
||||
int32 u = uptr - mt_dev.units; /* get unit number */
|
||||
|
||||
MT_CLR_PNU (uptr);
|
||||
if (!sim_is_active (uptr)) uptr->USTAT = STA_REM;
|
||||
if (u == GET_UNIT (mt_cu)) mt_updcsta (uptr);
|
||||
return detach_unit (uptr);
|
||||
return sim_tape_detach (uptr);
|
||||
}
|
||||
|
||||
/* Write lock/enable routine */
|
||||
|
@ -614,7 +569,8 @@ t_stat mt_vlock (UNIT *uptr, int32 val, char *cptr, void *desc)
|
|||
{
|
||||
int32 u = uptr - mt_dev.units; /* get unit number */
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) && val) uptr->USTAT = uptr->USTAT | STA_WLK;
|
||||
if ((uptr->flags & UNIT_ATT) && (val || sim_tape_wrp (uptr)))
|
||||
uptr->USTAT = uptr->USTAT | STA_WLK;
|
||||
else uptr->USTAT = uptr->USTAT & ~STA_WLK;
|
||||
if (u == GET_UNIT (mt_cu)) mt_updcsta (uptr);
|
||||
return SCPE_OK;
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
rf RF08 fixed head disk
|
||||
|
||||
03-Mar-03 RMS Fixed autosizing
|
||||
02-Feb-03 RMS Added variable platter and autosizing support
|
||||
04-Oct-02 RMS Added DIB, device number support
|
||||
28-Nov-01 RMS Added RL8A support
|
||||
|
@ -48,9 +49,11 @@
|
|||
#include <math.h>
|
||||
|
||||
#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */
|
||||
#define UNIT_V_MSIZE (UNIT_V_UF + 1) /* dummy mask */
|
||||
#define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */
|
||||
#define UNIT_M_PLAT 03
|
||||
#define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1)
|
||||
#define UNIT_AUTO (1 << UNIT_V_AUTO)
|
||||
#define UNIT_MSIZE (1 << UNIT_V_MSIZE)
|
||||
#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT)
|
||||
|
||||
/* Constants */
|
||||
|
||||
|
@ -130,7 +133,7 @@ DIB rf_dib = { DEV_RF, 5, { &rf60, &rf61, &rf62, NULL, &rf64 } };
|
|||
|
||||
UNIT rf_unit =
|
||||
{ UDATA (&rf_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF,
|
||||
RF_NUMDK * RF_DKSIZE) };
|
||||
RF_DKSIZE) };
|
||||
|
||||
UNIT pcell_unit = { UDATA (&pcell_svc, 0, 0) };
|
||||
|
||||
|
@ -149,10 +152,10 @@ REG rf_reg[] = {
|
|||
{ NULL } };
|
||||
|
||||
MTAB rf_mod[] = {
|
||||
{ UNIT_MSIZE, 262144, NULL, "1P", &rf_set_size },
|
||||
{ UNIT_MSIZE, 524288, NULL, "2P", &rf_set_size },
|
||||
{ UNIT_MSIZE, 786432, NULL, "3P", &rf_set_size },
|
||||
{ UNIT_MSIZE, 1048576, NULL, "4P", &rf_set_size },
|
||||
{ UNIT_PLAT, 0, NULL, "1P", &rf_set_size },
|
||||
{ UNIT_PLAT, 1, NULL, "2P", &rf_set_size },
|
||||
{ UNIT_PLAT, 2, NULL, "3P", &rf_set_size },
|
||||
{ UNIT_PLAT, 3, NULL, "4P", &rf_set_size },
|
||||
{ UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
|
||||
&set_dev, &show_dev, NULL },
|
||||
|
@ -370,19 +373,15 @@ return SCPE_OK;
|
|||
|
||||
t_stat rf_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
int32 p, d;
|
||||
int32 ds_bytes = RF_DKSIZE * sizeof (int16);
|
||||
t_addr sz, p;
|
||||
t_addr ds_bytes = RF_DKSIZE * sizeof (int16);
|
||||
|
||||
if (uptr->flags & UNIT_AUTO) {
|
||||
FILE *fp = fopen (cptr, "rb");
|
||||
if (fp == NULL) return SCPE_OPENERR;
|
||||
fseek (fp, 0, SEEK_END);
|
||||
p = ftell (fp);
|
||||
d = (p + ds_bytes - 1) / ds_bytes;
|
||||
if (d == 0) d = 1;
|
||||
if (d > RF_NUMDK) d = RF_NUMDK;
|
||||
uptr->capac = d * RF_DKSIZE;
|
||||
fclose (fp); }
|
||||
if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (cptr))) {
|
||||
p = (sz + ds_bytes - 1) / ds_bytes;
|
||||
if (p == 0) p = 1;
|
||||
if (p > RF_NUMDK) p = RF_NUMDK; }
|
||||
else p = UNIT_GETP (uptr->flags);
|
||||
uptr->capac = p * RF_DKSIZE;
|
||||
return attach_unit (uptr, cptr);
|
||||
}
|
||||
|
||||
|
@ -390,10 +389,9 @@ return attach_unit (uptr, cptr);
|
|||
|
||||
t_stat rf_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if ((val == 0) || (val > (RF_NUMDK * RF_DKSIZE)))
|
||||
return SCPE_IERR;
|
||||
if ((val < 0) || (val >= RF_NUMDK)) return SCPE_IERR;
|
||||
if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
|
||||
uptr->capac = val;
|
||||
uptr->capac = (val + 1) * RF_DKSIZE;
|
||||
uptr->flags = uptr->flags & ~UNIT_AUTO;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
#define RL01_SIZE (RL_NUMCY*RL_NUMSF*RL_NUMSC*RL_NUMBY) /* words/drive */
|
||||
#define RL02_SIZE (RL01_SIZE * 2) /* words/drive */
|
||||
#define RL_BBMAP 014 /* sector for bblk map */
|
||||
#define RL_BBID 0123 /* ID for bblk map */
|
||||
#define RL_BBID 0123 /* ID for bblk map */
|
||||
|
||||
/* Flags in the unit flags word */
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp8_rx.c: RX8E/RX01, RX28/RX02 floppy disk simulator
|
||||
|
||||
Copyright (c) 1993-2002, Robert M Supnik
|
||||
Copyright (c) 1993-2003, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -25,6 +25,7 @@
|
|||
|
||||
rx RX8E/RX01, RX28/RX02 floppy disk
|
||||
|
||||
03-Mar-03 RMS Fixed autosizing
|
||||
08-Oct-02 RMS Added DIB, device number support
|
||||
Fixed reset to work with disabled device
|
||||
15-Sep-02 RMS Added RX28/RX02 support
|
||||
|
@ -508,21 +509,13 @@ return SCPE_OK;
|
|||
|
||||
t_stat rx_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)? RX2_SIZE: RX_SIZE;
|
||||
r = attach_unit (uptr, cptr);
|
||||
if ((r != SCPE_OK) || ((uptr->flags & UNIT_AUTO) == 0) ||
|
||||
(rx_28 == 0)) return r;
|
||||
if (fseek (uptr->fileref, 0, SEEK_END)) return SCPE_OK;
|
||||
if ((p = ftell (uptr->fileref)) == 0) return SCPE_OK;
|
||||
if (p > RX_SIZE) {
|
||||
uptr->flags = uptr->flags | UNIT_DEN;
|
||||
uptr->capac = RX2_SIZE; }
|
||||
else { uptr->flags = uptr->flags & ~UNIT_DEN;
|
||||
uptr->capac = RX_SIZE; }
|
||||
return SCPE_OK;
|
||||
return attach_unit (uptr, cptr);
|
||||
}
|
||||
|
||||
/* Set size routine */
|
||||
|
|
|
@ -107,7 +107,6 @@ t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
|
|||
{
|
||||
int32 rubout, word, low, high, csum, newf, state, i;
|
||||
t_addr origin, field;
|
||||
extern t_bool match_ext (char *fnam, char *ext);
|
||||
|
||||
if ((*cptr != 0) || (flag != 0)) return SCPE_ARG;
|
||||
rubout = state = field = newf = origin = csum = 0;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* pdp8_tt.c: PDP-8 console terminal simulator
|
||||
|
||||
Copyright (c) 1993-2002, Robert M Supnik
|
||||
Copyright (c) 1993-2003, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -25,6 +25,7 @@
|
|||
|
||||
tti,tto KL8E terminal input/output
|
||||
|
||||
02-Mar-02 RMS Added SET TTI CTRL-C
|
||||
22-Dec-02 RMS Added break support
|
||||
01-Nov-02 RMS Added 7B/8B support
|
||||
04-Oct-02 RMS Added DIBs, device number support
|
||||
|
@ -48,6 +49,7 @@ t_stat tti_svc (UNIT *uptr);
|
|||
t_stat tto_svc (UNIT *uptr);
|
||||
t_stat tti_reset (DEVICE *dptr);
|
||||
t_stat tto_reset (DEVICE *dptr);
|
||||
t_stat tti_set_ctrlc (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
|
||||
/* TTI data structures
|
||||
|
@ -76,7 +78,8 @@ MTAB tti_mod[] = {
|
|||
{ UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", &tty_set_mode },
|
||||
{ UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , &tty_set_mode },
|
||||
{ UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , &tty_set_mode },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_VUN, 0, NULL, "CTRL-C", &tti_set_ctrlc, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev, NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE tti_dev = {
|
||||
|
@ -159,14 +162,14 @@ int32 c;
|
|||
sim_activate (&tti_unit, tti_unit.wait); /* continue poll */
|
||||
if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */
|
||||
if (c & SCPE_BREAK) tti_unit.buf = 0; /* break? */
|
||||
else if (tti_unit.flags & UNIT_KSR) { /* UC only? */
|
||||
else if (tti_unit.flags & UNIT_KSR) { /* KSR? */
|
||||
c = c & 0177;
|
||||
if (islower (c)) c = toupper (c);
|
||||
tti_unit.buf = c | 0200; } /* add TTY bit */
|
||||
else tti_unit.buf = c & ((tti_unit.flags & UNIT_8B)? 0377: 0177);
|
||||
tti_unit.pos = tti_unit.pos + 1;
|
||||
dev_done = dev_done | INT_TTI; /* set done */
|
||||
int_req = INT_UPDATE; /* update interrupts */
|
||||
tti_unit.pos = tti_unit.pos + 1;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -181,6 +184,18 @@ int_enable = int_enable | INT_TTI; /* set enable */
|
|||
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 = (uptr->flags & UNIT_KSR)? 0203: 0003;
|
||||
uptr->pos = uptr->pos + 1;
|
||||
dev_done = dev_done | INT_TTI; /* set done */
|
||||
int_req = INT_UPDATE; /* update interrupts */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Terminal output: IOT routine */
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* sds_cpu.c: SDS 940 CPU simulator
|
||||
|
||||
Copyright (c) 2001-2002, Robert M. Supnik
|
||||
Copyright (c) 2001-2003, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -41,6 +41,8 @@
|
|||
|
||||
cpu central processor
|
||||
rtc real time clock
|
||||
|
||||
01-Mar-03 RMS Added SET/SHOW RTC FREQ support
|
||||
*/
|
||||
|
||||
/* The SDS 940 has three instruction format -- memory reference, register change,
|
||||
|
@ -196,6 +198,9 @@ t_stat one_inst (uint32 inst, uint32 pc, uint32 mode);
|
|||
t_stat rtc_inst (uint32 inst);
|
||||
t_stat rtc_svc (UNIT *uptr);
|
||||
t_stat rtc_reset (DEVICE *dptr);
|
||||
t_stat rtc_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
t_stat rtc_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc);
|
||||
|
||||
extern t_bool io_init (void);
|
||||
extern t_stat op_wyim (uint32 inst, uint32 *dat);
|
||||
extern t_stat op_miwy (uint32 inst, uint32 dat);
|
||||
|
@ -278,11 +283,20 @@ UNIT rtc_unit = { UDATA (&rtc_svc, 0, 0), 16000 };
|
|||
REG rtc_reg[] = {
|
||||
{ FLDATA (PIE, rtc_pie, 0) },
|
||||
{ DRDATA (TIME, rtc_unit.wait, 24), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TPS, rtc_tps, 8), REG_NZ + PV_LEFT },
|
||||
{ DRDATA (TPS, rtc_tps, 8), PV_LEFT + REG_HRO },
|
||||
{ NULL } };
|
||||
|
||||
MTAB rtc_mod[] = {
|
||||
{ MTAB_XTD|MTAB_VDV, 50, NULL, "50HZ",
|
||||
&rtc_set_freq, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 60, NULL, "60HZ",
|
||||
&rtc_set_freq, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "FREQUENCY", NULL,
|
||||
NULL, &rtc_show_freq, NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE rtc_dev = {
|
||||
"RTC", &rtc_unit, rtc_reg, NULL,
|
||||
"RTC", &rtc_unit, rtc_reg, rtc_mod,
|
||||
1, 8, 8, 1, 8, 8,
|
||||
NULL, NULL, &rtc_reset,
|
||||
NULL, NULL, NULL };
|
||||
|
@ -1222,6 +1236,8 @@ sim_activate (&rtc_unit, sim_rtcn_calb (rtc_tps, TMR_RTC)); /* reactivate unit *
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Clock interrupt instruction */
|
||||
|
||||
t_stat rtc_inst (uint32 inst)
|
||||
{
|
||||
uint32 op, dat, val, va;
|
||||
|
@ -1239,9 +1255,29 @@ if (dat == 0) int_req = int_req | INT_RTCS; /* set clk sync int */
|
|||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Clock reset */
|
||||
|
||||
t_stat rtc_reset (DEVICE *dptr)
|
||||
{
|
||||
rtc_pie = 0; /* disable pulse */
|
||||
sim_activate (&rtc_unit, rtc_unit.wait); /* activate unit */
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Set frequency */
|
||||
|
||||
t_stat rtc_set_freq (UNIT *uptr, int32 val, char *cptr, void *desc)
|
||||
{
|
||||
if (cptr) return SCPE_ARG;
|
||||
if ((val != 50) && (val != 60)) return SCPE_IERR;
|
||||
rtc_tps = val;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Show frequency */
|
||||
|
||||
t_stat rtc_show_freq (FILE *st, UNIT *uptr, int32 val, void *desc)
|
||||
{
|
||||
fprintf (st, (rtc_tps == 50)? "50Hz": "60Hz");
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
|
|
@ -60,7 +60,6 @@ sim> c
|
|||
Breakpoint, P: 00112 (BRU 3)
|
||||
|
||||
---
|
||||
|
||||
930 P&S Register Test
|
||||
|
||||
sim> att mt diag.tap
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
To: Users
|
||||
From: Bob Supnik
|
||||
Subj: SDS 940 Simulator Usage
|
||||
Date: 15-Nov-2002
|
||||
Date: 15-Mar-2003
|
||||
|
||||
COPYRIGHT NOTICE
|
||||
|
||||
The following copyright notice applies to both the SIMH source and binary:
|
||||
|
||||
Original code published in 1993-2002, written by Robert M Supnik
|
||||
Copyright (c) 1993-2002, Robert M Supnik
|
||||
Original code published in 1993-2003, written by 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"),
|
||||
|
@ -39,10 +39,12 @@ This memorandum documents the SDS 940 simulator.
|
|||
sim/ sim_defs.h
|
||||
sim_rev.h
|
||||
sim_sock.h
|
||||
sim_tape.h
|
||||
sim_tmxr.h
|
||||
scp.c
|
||||
scp_tty.c
|
||||
sim_sock.c
|
||||
sim_tape.c
|
||||
sim_tmxr.c
|
||||
|
||||
sim/sds/ sds_defs.h
|
||||
|
@ -296,15 +298,21 @@ Error handling is as follows:
|
|||
|
||||
By default, the line printer is assigned to channel W.
|
||||
|
||||
2.8 Real Time Clock (RTC)
|
||||
2.8 Real-Time Clock (RTC)
|
||||
|
||||
The real time clock (RTC) implements these registers:
|
||||
The real-time clock (RTC) frequency can be adjusted as follows:
|
||||
|
||||
SET RTC 60HZ set frequency to 60Hz
|
||||
SET RTC 50HZ set frequency to 50Hz
|
||||
|
||||
The default is 60Hz.
|
||||
|
||||
The clock implements these registers:
|
||||
|
||||
name size comments
|
||||
|
||||
PIE 1 interrupt enable
|
||||
TIME 24 tick interval
|
||||
TPS 8 ticks per second
|
||||
|
||||
The real-time clock autocalibrates; the clock interval is adjusted up or
|
||||
down so that the clock tracks actual elapsed time.
|
||||
|
|
124
SDS/sds_mt.c
124
SDS/sds_mt.c
|
@ -1,6 +1,6 @@
|
|||
/* sds_mt.c: SDS 940 magnetic tape simulator
|
||||
|
||||
Copyright (c) 2001-2002, Robert M. Supnik
|
||||
Copyright (c) 2001-2003, Robert M. Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,7 +23,9 @@
|
|||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
mt 7 track magnetic tape
|
||||
mt 7 track magnetic tape
|
||||
|
||||
28-Feb-03 RMS Revised for magtape library
|
||||
|
||||
Magnetic tapes are represented as a series of variable 8b records
|
||||
of the form:
|
||||
|
@ -42,16 +44,13 @@
|
|||
*/
|
||||
|
||||
#include "sds_defs.h"
|
||||
#include "sim_tape.h"
|
||||
|
||||
#define MT_MAXFR (32768 * 4)
|
||||
#define MT_NUMDR 8 /* number drives */
|
||||
#define MT_UNIT 07
|
||||
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
|
||||
#define UNIT_WLK (1 << UNIT_V_WLK)
|
||||
#define botf u3 /* bot tape flag */
|
||||
#define eotf u4 /* eot tape flag */
|
||||
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
|
||||
|
||||
#define MTR_BOT 0xFFFFFFFE /* BOT pseudo mark */
|
||||
|
||||
extern uint32 xfr_req;
|
||||
extern int32 stop_invins, stop_invdev, stop_inviop;
|
||||
|
@ -141,8 +140,8 @@ REG mt_reg[] = {
|
|||
{ NULL } };
|
||||
|
||||
MTAB mt_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, 0, "CHANNEL", "CHANNEL",
|
||||
&set_chan, &show_chan, NULL },
|
||||
{ 0 } };
|
||||
|
@ -199,7 +198,8 @@ case IO_EOM1: /* EOM mode 1 */
|
|||
if (new_ch != mt_dib.chan) CRETIOP; /* wrong chan? */
|
||||
t = inst & 07670; /* get command */
|
||||
if ((t == 04010) && !sim_is_active (uptr)) { /* rewind? */
|
||||
uptr->pos = uptr->eotf = 0; /* clr pos, eot */
|
||||
sim_tape_rewind (uptr); /* rewind unit */
|
||||
uptr->eotf = 0; /* clr eot */
|
||||
uptr->botf = 1; } /* set bot */
|
||||
else if ((t == 03610) && sim_is_active (uptr) && /* skip rec? */
|
||||
((mt_inst & DEV_OUT) == 0)) mt_skip = 1; /* set flag */
|
||||
|
@ -245,7 +245,7 @@ case IO_SKS: /* SKS */
|
|||
if (!mt_eof) *dat = 1; /* not EOF */
|
||||
break;
|
||||
case 020: /* sks 1401n */
|
||||
if (!(uptr->flags & UNIT_WPRT)) *dat = 1; /* not wrp */
|
||||
if (!sim_tape_wrp (uptr)) *dat = 1; /* not wrp */
|
||||
break;
|
||||
case 031: /* sks 1621n */
|
||||
case 033: /* sks 1661n */
|
||||
|
@ -301,62 +301,30 @@ return SCPE_OK;
|
|||
|
||||
t_stat mt_readrec (UNIT *uptr)
|
||||
{
|
||||
t_mtrlnt abc, tbc;
|
||||
t_mtrlnt tbc;
|
||||
t_stat st, r = SCPE_OK;
|
||||
|
||||
if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */
|
||||
mt_set_err (uptr); /* no, err, disc */
|
||||
return SCPE_UNATT; }
|
||||
tbc = mt_readbc (uptr); /* get bc */
|
||||
if (tbc == MTR_EOM) { /* end of med? */
|
||||
uptr->eotf = 1; /* end of tape */
|
||||
mt_set_err (uptr); /* err, disc */
|
||||
return SCPE_OK; }
|
||||
if (tbc == MTR_BOT) { /* BOT? */
|
||||
mt_set_err (uptr); /* err, disc */
|
||||
return SCPE_OK; }
|
||||
if (tbc == MTR_TMK) { /* tape mark? */
|
||||
if (mt_inst & CHC_REV) /* reverse? */
|
||||
st = sim_tape_rdrecr (uptr, mtxb, &tbc, MT_MAXFR); /* read rec rev */
|
||||
else st = sim_tape_rdrecf (uptr, mtxb, &tbc, MT_MAXFR); /* no, fwd */
|
||||
if (st == MTSE_TMK) { /* tape mark? */
|
||||
mt_eof = 1; /* set eof flag */
|
||||
mtxb[0] = mtxb[1] = 017; /* EOR char */
|
||||
mt_blnt = 2; /* store 2 */
|
||||
uptr->pos += sizeof (t_mtrlnt); /* update position */
|
||||
return SCPE_OK; }
|
||||
if (st != MTSE_OK) { /* other error? */
|
||||
mt_set_err (uptr); /* err, disc */
|
||||
if (st == MTSE_IOERR) return SCPE_IOERR; /* IO error? */
|
||||
if (st == MTSE_INVRL) return SCPE_MTRLNT; /* inv rec lnt? */
|
||||
if (st == MTSE_EOM) uptr->eotf = 1; /* eom? set eot */
|
||||
return SCPE_OK; }
|
||||
mt_blnt = tbc; /* set buf lnt */
|
||||
if (tbc > MT_MAXFR) return SCPE_MTRLNT; /* record too long? */
|
||||
if (mt_inst & CHC_REV) { /* reverse? */
|
||||
fseek (uptr->fileref, uptr->pos - ((tbc + 1) & ~1) - sizeof (t_mtrlnt), SEEK_SET);
|
||||
mt_bptr = mt_blnt; }
|
||||
abc = fxread (mtxb, sizeof (uint8), tbc, uptr->fileref);/* read record */
|
||||
for (; abc < tbc; abc++) mtxb[abc] = 0; /* zero fill */
|
||||
if (ferror (uptr->fileref)) { /* I/O error */
|
||||
mt_set_err (uptr); /* no, err, disc */
|
||||
perror ("MT I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
return SCPE_IOERR; }
|
||||
if (mt_inst & CHC_REV) /* update pos */
|
||||
uptr->pos -= (((tbc + 1) & ~1) + (2 * sizeof (t_mtrlnt)));
|
||||
else uptr->pos += (((tbc + 1) & ~1) + (2 * sizeof (t_mtrlnt)));
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Read record byte count */
|
||||
|
||||
t_mtrlnt mt_readbc (UNIT *uptr)
|
||||
{
|
||||
t_mtrlnt tbc;
|
||||
|
||||
if (mt_inst & CHC_REV) {
|
||||
if (uptr->pos < sizeof (t_mtrlnt)) {
|
||||
uptr->botf = 1;
|
||||
return MTR_BOT; }
|
||||
fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET); }
|
||||
else fseek (uptr->fileref, uptr->pos, SEEK_SET);
|
||||
fxread (&tbc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
if (ferror (uptr->fileref) || feof (uptr->fileref) || /* err, eof, eom? */
|
||||
(tbc == MTR_EOM)) return MTR_EOM; /* return EOM */
|
||||
if (MTRF (tbc)) chan_set_flag (mt_dib.chan, CHF_ERR); /* rec err? set flag */
|
||||
return MTRL (tbc);
|
||||
}
|
||||
|
||||
/* Read done (eof, end of record) */
|
||||
|
||||
void mt_readend (UNIT *uptr)
|
||||
|
@ -375,51 +343,32 @@ return;
|
|||
|
||||
t_stat mt_wrend (uint32 dev)
|
||||
{
|
||||
static t_mtrlnt bceom = MTR_EOM;
|
||||
static t_mtrlnt bceof = MTR_TMK;
|
||||
UNIT *uptr = mt_dev.units + (dev & MT_UNIT);
|
||||
t_addr old_pos = uptr->pos;
|
||||
t_mtrlnt tbc;
|
||||
t_stat st;
|
||||
|
||||
sim_cancel (uptr); /* no more xfr's */
|
||||
if (mt_bptr == 0) return SCPE_OK; /* buf empty? */
|
||||
if (!(uptr->flags & UNIT_ATT)) { /* attached? */
|
||||
mt_set_err (uptr); /* no, err, disc */
|
||||
return SCPE_UNATT; }
|
||||
if (uptr->flags & UNIT_WPRT) { /* write lock? */
|
||||
if (sim_tape_wrp (uptr)) { /* write lock? */
|
||||
mt_set_err (uptr); /* yes, err, disc */
|
||||
return SCPE_OK; }
|
||||
if (dev & DEV_MTS) { /* erase? */
|
||||
if (mt_inst & CHC_REV) { /* reverse? */
|
||||
tbc = mt_readbc (uptr); /* get bc */
|
||||
if ((tbc == MTR_TMK) || (tbc == MTR_EOM)) /* tmk, eom? */
|
||||
fseek (uptr->fileref, uptr->pos -= sizeof (t_mtrlnt), SEEK_SET);
|
||||
else if (tbc != MTR_BOT) { /* not BOT? */
|
||||
tbc = MTRL (tbc); /* clear error */
|
||||
fseek (uptr->fileref, uptr->pos -=
|
||||
(((tbc + 1) & ~1) - sizeof (t_mtrlnt)), SEEK_SET); } }
|
||||
fxwrite (&bceom, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
}
|
||||
if (mt_inst & CHC_REV) /* reverse? */
|
||||
sim_tape_sprecr (uptr, &tbc); /* backspace */
|
||||
st = sim_tape_wreom (uptr); /* write eom */
|
||||
}
|
||||
else {
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set position */
|
||||
if ((mt_bptr == 1) && (mtxb[0] == 017) && /* wr eof? */
|
||||
((mt_inst & 01670) == 00050)) {
|
||||
fxwrite (&bceof, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
uptr->pos += sizeof (t_mtrlnt); }
|
||||
else { /* normal wr */
|
||||
fxwrite (&mt_bptr, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
fxwrite (mtxb, sizeof (uint8), (mt_bptr + 1) & ~1, uptr->fileref);
|
||||
fxwrite (&mt_bptr, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
uptr->pos += ((mt_bptr + 1) & ~1) + (2 * sizeof (t_mtrlnt));
|
||||
}
|
||||
((mt_inst & 01670) == 00050))
|
||||
st = sim_tape_wrtmk (uptr); /* write tape mark */
|
||||
else st = sim_tape_wrrecf (uptr, mtxb, mt_bptr); /* write record */
|
||||
}
|
||||
mt_bptr = 0;
|
||||
if (ferror (uptr->fileref)) { /* I/O error */
|
||||
uptr->pos = old_pos; /* restore pos */
|
||||
mt_set_err (uptr); /* no, err, disc */
|
||||
perror ("MT I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
return SCPE_IOERR; }
|
||||
if (st != MTSE_OK) mt_set_err (uptr); /* error? */
|
||||
if (st == MTSE_IOERR) return SCPE_IOERR;
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -449,6 +398,7 @@ mt_bptr = mt_blnt = 0;
|
|||
xfr_req = xfr_req & ~XFR_MT0; /* clr xfr flag */
|
||||
for (i = 0; i < MT_NUMDR; i++) { /* deactivate */
|
||||
sim_cancel (&mt_unit[i]);
|
||||
sim_tape_reset (&mt_unit[i]);
|
||||
mt_unit[i].eotf = 0; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
@ -459,7 +409,7 @@ t_stat mt_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;
|
||||
uptr->botf = 1;
|
||||
uptr->eotf = 0;
|
||||
|
@ -469,7 +419,7 @@ return SCPE_OK;
|
|||
t_stat mt_detach (UNIT *uptr)
|
||||
{
|
||||
uptr->botf = uptr->eotf = 0;
|
||||
return detach_unit (uptr);
|
||||
return sim_tape_detach (uptr);
|
||||
}
|
||||
|
||||
/* Boot routine - simulate FILL console command */
|
||||
|
|
|
@ -415,6 +415,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 Terminal Output (TTO)
|
||||
|
||||
The terminal output (TTO) writes to the simulator console window. It
|
||||
|
@ -584,7 +590,7 @@ The simulator implements four MSCP disk controllers, RQ, RQB, RQC, RQD.
|
|||
Initially, RQB, RQC, and RQD are disabled. Each RQ controller simulates
|
||||
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
|
||||
|
@ -599,12 +605,14 @@ of eleven disk types:
|
|||
SET RQn RA72 set type to RA72
|
||||
SET RQn RA90 set type to RA90
|
||||
SET RQn RA92 set type to RA92
|
||||
SET RQn RA81 set type to RA81 with n LBN's.
|
||||
|
||||
The type options can be used only when a unit is not attached to a file.
|
||||
Units can also be set ONLINE or OFFLINE.
|
||||
|
||||
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
|
||||
|
@ -705,13 +713,22 @@ Error handling is as follows:
|
|||
2.7 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 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,6 +1,6 @@
|
|||
/* vax_stddev.c: VAX standard I/O devices simulator
|
||||
|
||||
Copyright (c) 1998-2002, Robert M Supnik
|
||||
Copyright (c) 1998-2003, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -27,6 +27,7 @@
|
|||
tto terminal output
|
||||
clk 100Hz and TODR clock
|
||||
|
||||
02-Mar-02 RMS Added SET TTI CTRL-C
|
||||
22-Dec-02 RMS Added console halt capability
|
||||
01-Nov-02 RMS Added 7B/8B capability to terminal
|
||||
12-Sep-02 RMS Removed paper tape, added variable vector support
|
||||
|
@ -71,6 +72,7 @@ t_stat clk_svc (UNIT *uptr);
|
|||
t_stat tti_reset (DEVICE *dptr);
|
||||
t_stat tto_reset (DEVICE *dptr);
|
||||
t_stat clk_reset (DEVICE *dptr);
|
||||
t_stat tti_set_ctrlc (UNIT *uptr, int32 val, char *cptr, void *desc);
|
||||
|
||||
extern int32 sysd_hlt_enb (void);
|
||||
|
||||
|
@ -98,7 +100,10 @@ REG tti_reg[] = {
|
|||
MTAB tti_mod[] = {
|
||||
{ UNIT_8B, UNIT_8B, "8b", "8B", NULL },
|
||||
{ UNIT_8B, 0 , "7b", "7B", NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL, NULL, &show_vec },
|
||||
{ MTAB_XTD|MTAB_VDV|MTAB_VUN, 0, NULL, "CTRL-C",
|
||||
&tti_set_ctrlc, NULL, NULL },
|
||||
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL,
|
||||
NULL, &show_vec, NULL },
|
||||
{ 0 } };
|
||||
|
||||
DEVICE tti_dev = {
|
||||
|
@ -285,6 +290,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 routines
|
||||
|
||||
|
|
|
@ -98,9 +98,9 @@ CC = CC $(CC_FLAGS)
|
|||
SIMH_DIR = SYS$DISK:[]
|
||||
SIMH_LIB = $(LIB_DIR)SIMH-$(ARCH).OLB
|
||||
SIMH_SOURCE = $(SIMH_DIR)SCP_TTY.C,$(SIMH_DIR)SIM_SOCK.C,\
|
||||
$(SIMH_DIR)SIM_TMXR.C,$(SIMH_DIR)SIM_ETHER.C
|
||||
$(SIMH_DIR)SIM_TMXR.C,$(SIMH_DIR)SIM_ETHER.C,$(SIMH_DIR)SIM_TAPE.C
|
||||
SIMH_OBJS = $(SIMH_DIR)SCP_TTY.OBJ,$(SIMH_DIR)SIM_SOCK.OBJ,\
|
||||
$(SIMH_DIR)SIM_TMXR.OBJ,$(SIMH_DIR)SIM_ETHER.OBJ
|
||||
$(SIMH_DIR)SIM_TMXR.OBJ,$(SIMH_DIR)SIM_ETHER.OBJ,$(SIMH_DIR)SIM_TAPE.OBJ
|
||||
|
||||
#
|
||||
# MITS Altair Simulator Definitions.
|
||||
|
|
11
makefile
11
makefile
|
@ -27,7 +27,7 @@ endif
|
|||
# Common Libraries
|
||||
#
|
||||
BIN = BIN/
|
||||
SIM = scp.c scp_tty.c sim_sock.c sim_tmxr.c sim_ether.c
|
||||
SIM = scp.c scp_tty.c sim_sock.c sim_tmxr.c sim_ether.c sim_tape.c
|
||||
|
||||
|
||||
|
||||
|
@ -212,7 +212,7 @@ SDS_OPT = -I ${SDSD}
|
|||
#
|
||||
# Build everything
|
||||
#
|
||||
all : ${BIN}pdp1${EXE} ${BIN}pdp4${EXE} ${BIN}pdp7${EXE} ${BIN}pdp8${EXE} \
|
||||
ALL = ${BIN}pdp1${EXE} ${BIN}pdp4${EXE} ${BIN}pdp7${EXE} ${BIN}pdp8${EXE} \
|
||||
${BIN}pdp9${EXE} ${BIN}pdp15${EXE} ${BIN}pdp11${EXE} ${BIN}pdp10${EXE} \
|
||||
${BIN}vax${EXE} ${BIN}nova${EXE} ${BIN}eclipse${EXE} ${BIN}h316${EXE} \
|
||||
${BIN}hp2100${EXE} ${BIN}i1401${EXE} ${BIN}i1620${EXE} ${BIN}s3${EXE} \
|
||||
|
@ -220,7 +220,14 @@ all : ${BIN}pdp1${EXE} ${BIN}pdp4${EXE} ${BIN}pdp7${EXE} ${BIN}pdp8${EXE} \
|
|||
${BIN}i1620${EXE} ${BIN}ibm1130${EXE} ${BIN}id16${EXE} \
|
||||
${BIN}id32${EXE} ${BIN}sds${EXE}
|
||||
|
||||
all : ${ALL}
|
||||
|
||||
clean :
|
||||
ifeq ($(WIN32),)
|
||||
${RM} ${ALL}
|
||||
else
|
||||
if exist BIN\*.exe del /q BIN\*.exe
|
||||
endif
|
||||
#
|
||||
# Individual builds
|
||||
#
|
||||
|
|
288
scp.c
288
scp.c
|
@ -23,6 +23,11 @@
|
|||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
03-Mar-03 RMS Added sim_fsize
|
||||
27-Feb-03 RMS Fixed bug in multiword deposits to files
|
||||
08-Feb-03 RMS Changed sim_os_sleep to void, match_ext to char*
|
||||
Added multiple actions, .ini file support
|
||||
Added multiple switch evaluations per line
|
||||
07-Feb-03 RMS Added VMS support for ! (from Mark Pizzolato)
|
||||
01-Feb-03 RMS Added breakpoint table extension, actions
|
||||
14-Jan-03 RMS Added missing function prototypes
|
||||
|
@ -165,13 +170,8 @@
|
|||
else if (sz == sizeof (uint16)) *(((uint16 *) mb) + j) = (uint16) v; \
|
||||
else *(((uint32 *) mb) + j) = v;
|
||||
#endif
|
||||
#define GET_SWITCHES(cp,gb) \
|
||||
sim_switches = 0; \
|
||||
while (*cp == '-') { \
|
||||
int32 lsw; \
|
||||
cp = get_glyph (cp, gb, 0); \
|
||||
if ((lsw = get_switches (gb)) <= 0) return SCPE_INVSW; \
|
||||
sim_switches = sim_switches | lsw; }
|
||||
#define GET_SWITCHES(cp) \
|
||||
if ((cp = get_sim_sw (cp)) == NULL) return SCPE_INVSW
|
||||
#define GET_RADIX(val,dft) \
|
||||
if (sim_switches & SWMASK ('O')) val = 8; \
|
||||
else if (sim_switches & SWMASK ('D')) val = 10; \
|
||||
|
@ -234,6 +234,8 @@ t_stat sim_brk_clr (t_addr loc, int32 sw);
|
|||
t_stat sim_brk_clrall (int32 sw);
|
||||
t_stat sim_brk_show (FILE *st, t_addr loc, int32 sw);
|
||||
t_stat sim_brk_showall (FILE *st, int32 sw);
|
||||
char *sim_brk_getact (char *buf, int32 size);
|
||||
void sim_brk_clract (void);
|
||||
void sim_brk_npc (void);
|
||||
t_stat set_telnet (int32 flg, char *cptr);
|
||||
t_stat set_notelnet (int32 flg, char *cptr);
|
||||
|
@ -257,8 +259,8 @@ t_stat show_all_mods (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flg);
|
|||
t_stat show_one_mod (FILE *st, DEVICE *dptr, UNIT *uptr, MTAB *mptr, int32 flag);
|
||||
t_stat sim_check_console (int32 sec);
|
||||
char *get_glyph_gen (char *iptr, char *optr, char mchar, t_bool uc);
|
||||
t_bool match_ext (char *fnam, char *ext);
|
||||
int32 get_switches (char *cptr);
|
||||
char *get_sim_sw (char *cptr);
|
||||
t_value get_rval (REG *rptr, int32 idx);
|
||||
void put_rval (REG *rptr, int32 idx, t_value val);
|
||||
t_stat get_aval (t_addr addr, DEVICE *dptr, UNIT *uptr);
|
||||
|
@ -285,8 +287,6 @@ t_stat dep_reg (int32 flag, char *cptr, REG *rptr, t_addr idx);
|
|||
t_stat ex_addr (FILE *ofile, int32 flag, t_addr addr, DEVICE *dptr, UNIT *uptr);
|
||||
t_stat dep_addr (int32 flag, char *cptr, t_addr addr, DEVICE *dptr,
|
||||
UNIT *uptr, int32 dfltinc);
|
||||
char *get_range (char *cptr, t_addr *lo, t_addr *hi, int32 rdx,
|
||||
t_addr max, char term);
|
||||
SCHTAB *get_search (char *cptr, DEVICE *dptr, SCHTAB *schptr);
|
||||
int32 test_search (t_value val, SCHTAB *schptr);
|
||||
t_stat step_svc (UNIT *ptr);
|
||||
|
@ -519,11 +519,11 @@ for (i = 1; i < argc; i++) { /* loop thru args */
|
|||
if (argv[i] == NULL) continue; /* paranoia */
|
||||
if ((*argv[i] == '-') && lookswitch) { /* switch? */
|
||||
if ((sw = get_switches (argv[i])) < 0) {
|
||||
printf ("Invalid switch %s\n", argv[i]);
|
||||
fprintf (stderr, "Invalid switch %s\n", argv[i]);
|
||||
return 0; }
|
||||
sim_switches = sim_switches | sw; }
|
||||
else { if ((strlen (argv[i]) + strlen (cbuf) + 1) >= CBUFSIZE) {
|
||||
printf ("Argument string too long\n");
|
||||
fprintf (stderr, "Argument string too long\n");
|
||||
return 0; }
|
||||
if (*cbuf) strcat (cbuf, " "); /* concat args */
|
||||
strcat (cbuf, argv[i]);
|
||||
|
@ -544,18 +544,18 @@ sim_log = NULL;
|
|||
if (sim_emax <= 0) sim_emax = 1;
|
||||
|
||||
if ((stat = ttinit ()) != SCPE_OK) {
|
||||
printf ("Fatal terminal initialization error\n%s\n",
|
||||
fprintf (stderr, "Fatal terminal initialization error\n%s\n",
|
||||
scp_error_messages[stat - SCPE_BASE]);
|
||||
return 0; }
|
||||
if ((sim_eval = calloc (sim_emax, sizeof (t_value))) == NULL) {
|
||||
printf ("Unable to allocate examine buffer\n");
|
||||
fprintf (stderr, "Unable to allocate examine buffer\n");
|
||||
return 0; };
|
||||
if ((stat = reset_all (0)) != SCPE_OK) {
|
||||
printf ("Fatal simulator initialization error\n%s\n",
|
||||
fprintf (stderr, "Fatal simulator initialization error\n%s\n",
|
||||
scp_error_messages[stat - SCPE_BASE]);
|
||||
return 0; }
|
||||
if ((stat = sim_brk_init ()) != SCPE_OK) {
|
||||
printf ("Fatal breakpoint table initialization error\n%s\n",
|
||||
fprintf (stderr, "Fatal breakpoint table initialization error\n%s\n",
|
||||
scp_error_messages[stat - SCPE_BASE]);
|
||||
return 0; }
|
||||
if (!sim_quiet) {
|
||||
|
@ -566,13 +566,18 @@ if (*cbuf) { /* cmd file arg? */
|
|||
stat = do_cmd (1, cbuf); /* proc cmd file */
|
||||
if (stat == SCPE_OPENERR) /* error? */
|
||||
fprintf (stderr, "Can't open file %s\n", cbuf); }
|
||||
else stat = SCPE_OK;
|
||||
else if (*argv[0]) { /* sim name arg? */
|
||||
char nbuf[PATH_MAX + 7], *np; /* "path.ini" */
|
||||
nbuf[0] = '"'; /* starting " */
|
||||
strncpy (nbuf + 1, argv[0], PATH_MAX + 1); /* copy sim name */
|
||||
if (np = match_ext (nbuf, "EXE")) *np = 0; /* remove .exe */
|
||||
strcat (nbuf, ".ini\""); /* add .ini" */
|
||||
stat = do_cmd (1, nbuf); } /* proc cmd file */
|
||||
|
||||
while (stat != SCPE_EXIT) { /* in case exit */
|
||||
printf ("sim> "); /* prompt */
|
||||
if (cptr = sim_brk_act) { /* pending action? */
|
||||
printf ("%s\n", sim_brk_act);
|
||||
sim_brk_act = NULL; }
|
||||
if (cptr = sim_brk_getact (cbuf, CBUFSIZE)) /* pending action? */
|
||||
printf ("%s\n", cptr); /* echo */
|
||||
else if (sim_vm_read != NULL) /* sim routine? */
|
||||
cptr = (*sim_vm_read) (cbuf, CBUFSIZE, stdin);
|
||||
else cptr = read_line (cbuf, CBUFSIZE, stdin); /* read command line */
|
||||
|
@ -580,6 +585,7 @@ while (stat != SCPE_EXIT) { /* in case exit */
|
|||
if (*cptr == 0) continue; /* ignore blank */
|
||||
if (sim_log) fprintf (sim_log, "sim> %s\n", cptr); /* log cmd */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */
|
||||
sim_switches = 0; /* init switches */
|
||||
if (cmdp = find_cmd (gbuf)) /* lookup command */
|
||||
stat = cmdp->action (cmdp->arg, cptr); /* if found, exec */
|
||||
else stat = SCPE_UNK;
|
||||
|
@ -633,6 +639,7 @@ t_stat help_cmd (int32 flag, char *cptr)
|
|||
char gbuf[CBUFSIZE];
|
||||
CTAB *cmdp;
|
||||
|
||||
GET_SWITCHES (cptr);
|
||||
if (*cptr) {
|
||||
cptr = get_glyph (cptr, gbuf, 0);
|
||||
if (*cptr) return SCPE_2MARG;
|
||||
|
@ -665,6 +672,54 @@ return SCPE_OK;
|
|||
|
||||
/* Do command */
|
||||
|
||||
t_stat do_cmd (int flag, char *fcptr)
|
||||
{
|
||||
char *cptr, cbuf[CBUFSIZE], gbuf[CBUFSIZE], *c, quote, *do_arg[10];
|
||||
FILE *fpin;
|
||||
CTAB *cmdp;
|
||||
int32 echo, nargs;
|
||||
t_stat stat = SCPE_OK;
|
||||
|
||||
if (flag == 0) { GET_SWITCHES (fcptr); } /* get switches */
|
||||
echo = sim_switches & SWMASK ('V'); /* -v means echo */
|
||||
|
||||
c = fcptr;
|
||||
for (nargs = 0; nargs < 10; ) { /* extract arguments */
|
||||
while (isspace (*c)) c++; /* skip blanks */
|
||||
if (*c == 0) break; /* all done */
|
||||
if (*c == '\'' || *c == '"') quote = *c++; /* quoted string? */
|
||||
else quote = 0;
|
||||
do_arg[nargs++] = c; /* save start */
|
||||
while (*c && (quote? (*c != quote): !isspace (*c))) c++;
|
||||
if (*c) *c++ = 0; /* term at quote/spc */
|
||||
} /* end for */
|
||||
if (nargs <= 0) return SCPE_2FARG; /* need at least 1 */
|
||||
if ((fpin = FOPEN (do_arg[0], "r")) == NULL) /* cmd file failed to open? */
|
||||
return SCPE_OPENERR;
|
||||
|
||||
do { cptr = read_line (cbuf, CBUFSIZE, fpin); /* get cmd line */
|
||||
sub_args (cbuf, gbuf, CBUFSIZE, nargs, do_arg);
|
||||
if (cptr == NULL) break; /* exit on eof */
|
||||
if (*cptr == 0) continue; /* ignore blank */
|
||||
if (echo) printf("do> %s\n", cptr); /* echo if -v */
|
||||
if (sim_log) fprintf (sim_log, "do> %s\n", cptr);
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */
|
||||
sim_switches = 0; /* init switches */
|
||||
if (strcmp (gbuf, "do") == 0) { /* don't recurse */
|
||||
fclose (fpin);
|
||||
return SCPE_NEST; }
|
||||
if (cmdp = find_cmd (gbuf)) /* lookup command */
|
||||
stat = cmdp->action (cmdp->arg, cptr); /* if found, exec */
|
||||
else stat = SCPE_UNK;
|
||||
if (stat >= SCPE_BASE) /* error? */
|
||||
printf ("%s\n", scp_error_messages[stat - SCPE_BASE]);
|
||||
if (sim_vm_post != NULL) (*sim_vm_post) (TRUE);
|
||||
} while (stat != SCPE_EXIT);
|
||||
|
||||
fclose (fpin); /* close file */
|
||||
return (stat == SCPE_EXIT)? SCPE_EXIT: SCPE_OK;
|
||||
}
|
||||
|
||||
/* Substitute_args - replace %n tokens in 'instr' with the do command's arguments
|
||||
|
||||
Calling sequence
|
||||
|
@ -693,55 +748,6 @@ for (ip = instr, op = tmpbuf; *ip && (op < oend); ) {
|
|||
strcpy (instr, tmpbuf);
|
||||
return;
|
||||
}
|
||||
|
||||
t_stat do_cmd (int flag, char *fcptr)
|
||||
{
|
||||
char *cptr, cbuf[CBUFSIZE], gbuf[CBUFSIZE], *c, quote, *do_arg[10];
|
||||
FILE *fpin;
|
||||
CTAB *cmdp;
|
||||
int32 echo, nargs;
|
||||
t_stat stat = SCPE_OK;
|
||||
|
||||
if (flag == 0) { GET_SWITCHES (fcptr, gbuf); } /* get switches */
|
||||
echo = sim_switches & SWMASK ('V'); /* -v means echo */
|
||||
|
||||
c = fcptr;
|
||||
for (nargs = 0; nargs < 10; ) { /* extract arguments */
|
||||
while (*c && (*c <= ' ')) c++; /* skip blanks */
|
||||
if (! *c) break; /* all done */
|
||||
do_arg[nargs++] = c; /* save start */
|
||||
while (*c && (*c > ' ')) {
|
||||
if (*c == '\'' || *c == '"') { /* quoted string */
|
||||
for (quote = *c++; *c; )
|
||||
if (*c++ == quote) break; }
|
||||
else c++; }
|
||||
if (*c) *c++ = 0; /* term arg at spc */
|
||||
} /* end for */
|
||||
if (nargs <= 0) return SCPE_2FARG; /* need at least 1 */
|
||||
if ((fpin = FOPEN (do_arg[0], "r")) == NULL) /* cmd file failed to open? */
|
||||
return SCPE_OPENERR;
|
||||
|
||||
do { cptr = read_line (cbuf, CBUFSIZE, fpin); /* get cmd line */
|
||||
sub_args (cbuf, gbuf, CBUFSIZE, nargs, do_arg);
|
||||
if (cptr == NULL) break; /* exit on eof */
|
||||
if (*cptr == 0) continue; /* ignore blank */
|
||||
if (echo) printf("do> %s\n", cptr); /* echo if -v */
|
||||
if (sim_log) fprintf (sim_log, "do> %s\n", cptr);
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get command glyph */
|
||||
if (strcmp (gbuf, "do") == 0) { /* don't recurse */
|
||||
fclose (fpin);
|
||||
return SCPE_NEST; }
|
||||
if (cmdp = find_cmd (gbuf)) /* lookup command */
|
||||
stat = cmdp->action (cmdp->arg, cptr); /* if found, exec */
|
||||
else stat = SCPE_UNK;
|
||||
if (stat >= SCPE_BASE) /* error? */
|
||||
printf ("%s\n", scp_error_messages[stat - SCPE_BASE]);
|
||||
if (sim_vm_post != NULL) (*sim_vm_post) (TRUE);
|
||||
} while (stat != SCPE_EXIT);
|
||||
|
||||
fclose (fpin); /* close file */
|
||||
return (stat == SCPE_EXIT)? SCPE_EXIT: SCPE_OK;
|
||||
}
|
||||
|
||||
/* Set command */
|
||||
|
||||
|
@ -773,7 +779,7 @@ static CTAB set_unit_tab[] = {
|
|||
{ "OFFLINE", &set_onoff, 0 },
|
||||
{ NULL, NULL, 0 } };
|
||||
|
||||
GET_SWITCHES (cptr, gbuf); /* get switches */
|
||||
GET_SWITCHES (cptr); /* get switches */
|
||||
if (*cptr == 0) return SCPE_2FARG; /* must be more */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get glob/dev/unit */
|
||||
|
||||
|
@ -941,7 +947,7 @@ static CTAB show_table[] = {
|
|||
{ "BREAK", &show_break, 0 },
|
||||
{ NULL, NULL, 0 } };
|
||||
|
||||
GET_SWITCHES (cptr, gbuf); /* test for switches */
|
||||
GET_SWITCHES (cptr); /* get switches */
|
||||
if (*cptr == 0) return SCPE_2FARG; /* must be more */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
|
||||
for (i = 0; show_table[i].name != NULL; i++) { /* find command */
|
||||
|
@ -1078,10 +1084,10 @@ int32 accum;
|
|||
|
||||
if (cptr && (*cptr != 0)) return SCPE_2MARG;
|
||||
if (sim_clock_queue == NULL) {
|
||||
fprintf (st, "%s event queue empty, time = %-16.0f\n",
|
||||
fprintf (st, "%s event queue empty, time = %.0f\n",
|
||||
sim_name, sim_time);
|
||||
return SCPE_OK; }
|
||||
fprintf (st, "%s event queue status, time = %-16.0f\n",
|
||||
fprintf (st, "%s event queue status, time = %.0f\n",
|
||||
sim_name, sim_time);
|
||||
accum = 0;
|
||||
for (uptr = sim_clock_queue; uptr != NULL; uptr = uptr->next) {
|
||||
|
@ -1099,7 +1105,7 @@ return SCPE_OK;
|
|||
t_stat show_time (FILE *st, int32 flag, char *cptr)
|
||||
{
|
||||
if (cptr && (*cptr != 0)) return SCPE_2MARG;
|
||||
fprintf (st, "Time: %-16.0f\n", sim_time);
|
||||
fprintf (st, "Time: %.0f\n", sim_time);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
@ -1182,9 +1188,7 @@ return SCPE_OK;
|
|||
|
||||
t_stat brk_cmd (int32 flg, char *cptr)
|
||||
{
|
||||
char gbuf[CBUFSIZE];
|
||||
|
||||
GET_SWITCHES (cptr, gbuf); /* test for switches */
|
||||
GET_SWITCHES (cptr); /* get switches */
|
||||
return ssh_break (NULL, cptr, flg); /* call common code */
|
||||
}
|
||||
|
||||
|
@ -1244,7 +1248,7 @@ t_stat reset_cmd (int32 flag, char *cptr)
|
|||
char gbuf[CBUFSIZE];
|
||||
DEVICE *dptr;
|
||||
|
||||
GET_SWITCHES (cptr, gbuf); /* test for switches */
|
||||
GET_SWITCHES (cptr); /* get switches */
|
||||
if (*cptr == 0) return (reset_all (0)); /* reset(cr) */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
|
||||
if (*cptr != 0) return SCPE_2MARG; /* now eol? */
|
||||
|
@ -1291,11 +1295,12 @@ char gbuf[CBUFSIZE];
|
|||
FILE *loadfile;
|
||||
t_stat reason;
|
||||
|
||||
GET_SWITCHES (cptr, gbuf); /* test for switches */
|
||||
GET_SWITCHES (cptr); /* get switches */
|
||||
if (*cptr == 0) return SCPE_2FARG; /* must be more */
|
||||
cptr = get_glyph_nc (cptr, gbuf, 0); /* get file name */
|
||||
loadfile = FOPEN (gbuf, flag? "wb": "rb"); /* open for wr/rd */
|
||||
if (loadfile == NULL) return SCPE_OPENERR;
|
||||
GET_SWITCHES (cptr); /* get switches */
|
||||
reason = sim_load (loadfile, cptr, gbuf, flag); /* load or dump */
|
||||
fclose (loadfile);
|
||||
return reason;
|
||||
|
@ -1312,9 +1317,10 @@ char gbuf[CBUFSIZE];
|
|||
DEVICE *dptr;
|
||||
UNIT *uptr;
|
||||
|
||||
GET_SWITCHES (cptr, gbuf); /* test for switches */
|
||||
GET_SWITCHES (cptr); /* get switches */
|
||||
if (*cptr == 0) return SCPE_2FARG; /* must be more */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
|
||||
GET_SWITCHES (cptr); /* get switches */
|
||||
if (*cptr == 0) return SCPE_2FARG; /* now eol? */
|
||||
dptr = find_unit (gbuf, &uptr); /* locate unit */
|
||||
if (dptr == NULL) return SCPE_NXDEV; /* found dev? */
|
||||
|
@ -1399,7 +1405,7 @@ char gbuf[CBUFSIZE];
|
|||
DEVICE *dptr;
|
||||
UNIT *uptr;
|
||||
|
||||
GET_SWITCHES (cptr, gbuf); /* test for switches */
|
||||
GET_SWITCHES (cptr); /* get switches */
|
||||
if (*cptr == 0) return SCPE_2FARG; /* must be more */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
|
||||
if (*cptr != 0) return SCPE_2MARG; /* now eol? */
|
||||
|
@ -1470,7 +1476,6 @@ return (fclose (uptr->fileref) == EOF)? SCPE_IOERR: SCPE_OK;
|
|||
|
||||
t_stat save_cmd (int32 flag, char *cptr)
|
||||
{
|
||||
char gbuf[CBUFSIZE];
|
||||
void *mbuf;
|
||||
FILE *sfile;
|
||||
int32 i, j, l, t;
|
||||
|
@ -1485,7 +1490,7 @@ REG *rptr;
|
|||
|
||||
#define WRITE_I(xx) fxwrite (&(xx), sizeof (xx), 1, sfile)
|
||||
|
||||
GET_SWITCHES (cptr, gbuf); /* test for switches */
|
||||
GET_SWITCHES (cptr); /* get switches */
|
||||
if (*cptr == 0) return SCPE_2FARG; /* must be more */
|
||||
if ((sfile = FOPEN (cptr, "wb")) == NULL) return SCPE_OPENERR;
|
||||
fputs (save_vercur, sfile); /* [V2.5] save format */
|
||||
|
@ -1582,7 +1587,7 @@ REG *rptr;
|
|||
#define READ_I(xx) if (fxread (&xx, sizeof (xx), 1, rfile) == 0) \
|
||||
{ fclose (rfile); return SCPE_IOERR; }
|
||||
|
||||
GET_SWITCHES (cptr, buf); /* test for switches */
|
||||
GET_SWITCHES (cptr); /* get switches */
|
||||
if (*cptr == 0) return SCPE_2FARG; /* must be more */
|
||||
if ((rfile = FOPEN (cptr, "rb")) == NULL) return SCPE_OPENERR;
|
||||
READ_S (buf); /* [V2.5+] read version */
|
||||
|
@ -1753,7 +1758,7 @@ DEVICE *dptr;
|
|||
UNIT *uptr;
|
||||
void int_handler (int signal);
|
||||
|
||||
GET_SWITCHES (cptr, gbuf); /* test for switches */
|
||||
GET_SWITCHES (cptr); /* get switches */
|
||||
step = 0;
|
||||
if (((flag == RU_RUN) || (flag == RU_GO)) && (*cptr != 0)) { /* run or go */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get next glyph */
|
||||
|
@ -1804,7 +1809,7 @@ if ((r = sim_check_console (30)) != SCPE_OK) { /* check console, error? */
|
|||
return r; }
|
||||
if (step) sim_activate (&step_unit, step); /* set step timer */
|
||||
sim_is_running = 1; /* flag running */
|
||||
sim_brk_act = NULL; /* defang actions */
|
||||
sim_brk_clract (); /* defang actions */
|
||||
r = sim_instr();
|
||||
|
||||
sim_is_running = 0; /* flag idle */
|
||||
|
@ -2331,7 +2336,7 @@ for (i = 0, j = addr; i < count; i++, j = j + dptr->aincr) {
|
|||
if (loc >= uptr->hwmark) uptr->hwmark = loc + 1; }
|
||||
else {
|
||||
fseek (uptr->fileref, sz * loc, SEEK_SET);
|
||||
fxwrite (sim_eval, sz, 1, uptr->fileref);
|
||||
fxwrite (&sim_eval[i], sz, 1, uptr->fileref);
|
||||
if (ferror (uptr->fileref)) {
|
||||
clearerr (uptr->fileref);
|
||||
return SCPE_IOERR; } } } }
|
||||
|
@ -2342,12 +2347,11 @@ return reason;
|
|||
|
||||
t_stat eval_cmd (int32 flg, char *cptr)
|
||||
{
|
||||
char gbuf[CBUFSIZE];
|
||||
DEVICE *dptr = sim_devices[0];
|
||||
int32 i, count, rdx;
|
||||
t_stat r;
|
||||
|
||||
GET_SWITCHES (cptr, gbuf);
|
||||
GET_SWITCHES (cptr);
|
||||
GET_RADIX (rdx, dptr->dradix);
|
||||
for (i = 0; i < sim_emax; i++) sim_eval[i] = 0;
|
||||
if (*cptr == 0) return SCPE_2FARG;
|
||||
|
@ -2598,11 +2602,10 @@ t_stat r;
|
|||
DEVICE *dptr;
|
||||
|
||||
if (uptr == NULL) return NULL; /* arg error? */
|
||||
for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* exact match? */
|
||||
if (strcmp (cptr, dptr->name) == 0) {
|
||||
if (qdisable (dptr)) return NULL; /* disabled? */
|
||||
*uptr = dptr->units; /* unit 0 */
|
||||
return dptr; } }
|
||||
if (dptr = find_dev (cptr)) { /* exact match? */
|
||||
if (qdisable (dptr)) return NULL; /* disabled? */
|
||||
*uptr = dptr->units; /* unit 0 */
|
||||
return dptr; }
|
||||
|
||||
for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* base + unit#? */
|
||||
if ((dptr->numunits == 0) || /* no units? */
|
||||
|
@ -2718,21 +2721,52 @@ if (*cptr != '-') return 0;
|
|||
sw = 0;
|
||||
for (cptr++; (isspace (*cptr) == 0) && (*cptr != 0); cptr++) {
|
||||
if (isalpha (*cptr) == 0) return -1;
|
||||
sw = sw | SWMASK (*cptr); }
|
||||
sw = sw | SWMASK (toupper (*cptr)); }
|
||||
return sw;
|
||||
}
|
||||
|
||||
t_bool match_ext (char *fnam, char *ext)
|
||||
{
|
||||
char *fptr, *eptr;
|
||||
/* get_sim_sw accumulate sim_switches
|
||||
|
||||
if ((fnam == NULL) || (ext == NULL)) return FALSE;
|
||||
fptr = strrchr (fnam, '.');
|
||||
if (fptr == NULL) return FALSE;
|
||||
for (fptr++, eptr = ext; *fptr; fptr++, eptr++) {
|
||||
if (toupper (*fptr) != toupper (*eptr)) return FALSE; }
|
||||
if (*eptr) return FALSE;
|
||||
return TRUE;
|
||||
Inputs:
|
||||
cptr = pointer to input string
|
||||
Outputs:
|
||||
ptr = pointer to first non-string glyph
|
||||
NULL if error
|
||||
*/
|
||||
|
||||
char *get_sim_sw (char *cptr)
|
||||
{
|
||||
int32 lsw;
|
||||
char gbuf[CBUFSIZE];
|
||||
|
||||
while (*cptr == '-') { /* while switches */
|
||||
cptr = get_glyph (cptr, gbuf, 0); /* get switch glyph */
|
||||
lsw = get_switches (gbuf); /* parse */
|
||||
if (lsw <= 0) return NULL; /* invalid? */
|
||||
sim_switches = sim_switches | lsw; } /* accumulate */
|
||||
return cptr;
|
||||
}
|
||||
|
||||
/* Match file extension
|
||||
|
||||
Inputs:
|
||||
fnam = file name
|
||||
ext = extension, without period
|
||||
Outputs:
|
||||
cp = pointer to final '.' if match, NULL if not
|
||||
*/
|
||||
|
||||
char *match_ext (char *fnam, char *ext)
|
||||
{
|
||||
char *pptr, *fptr, *eptr;
|
||||
|
||||
if ((fnam == NULL) || (ext == NULL)) return NULL;
|
||||
pptr = strrchr (fnam, '.');
|
||||
if (pptr) {
|
||||
for (fptr = pptr + 1, eptr = ext; *fptr; fptr++, eptr++) {
|
||||
if (toupper (*fptr) != toupper (*eptr)) return NULL; }
|
||||
if (*eptr) return NULL; }
|
||||
return pptr;
|
||||
}
|
||||
|
||||
/* Get search specification
|
||||
|
@ -3143,6 +3177,21 @@ for (i = nbuf; i > 0; i--) {
|
|||
total = total + c; }
|
||||
return total;
|
||||
}
|
||||
|
||||
/* Get file size */
|
||||
|
||||
t_addr sim_fsize (char *cptr)
|
||||
{
|
||||
FILE *fp;
|
||||
t_addr sz;
|
||||
|
||||
fp = fopen (cptr, "rb");
|
||||
if (fp == NULL) return 0;
|
||||
fseek (fp, 0, SEEK_END);
|
||||
sz = ftell (fp);
|
||||
fclose (fp);
|
||||
return sz;
|
||||
}
|
||||
|
||||
/* OS independent clock calibration package
|
||||
|
||||
|
@ -3240,6 +3289,8 @@ return sim_rtcn_calb (ticksper, 0);
|
|||
sim_brk_showall show all breakpoints
|
||||
sim_brk_test test for breakpoint
|
||||
sim_brk_npc PC has been changed
|
||||
sim_brk_getact get next action
|
||||
sim_brk_clract clear pending actions
|
||||
|
||||
Initialize breakpoint system.
|
||||
*/
|
||||
|
@ -3422,6 +3473,33 @@ sim_brk_pend = FALSE;
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/* Get next pending action, if any */
|
||||
|
||||
char *sim_brk_getact (char *buf, int32 size)
|
||||
{
|
||||
char *ep;
|
||||
size_t lnt;
|
||||
|
||||
if (sim_brk_act == NULL) return NULL; /* any action? */
|
||||
while (isspace (*sim_brk_act)) sim_brk_act++; /* skip spaces */
|
||||
if (*sim_brk_act == 0) return (sim_brk_act = NULL); /* now empty? */
|
||||
if (ep = strchr (sim_brk_act, ';')) { /* cmd delimiter? */
|
||||
lnt = ep - sim_brk_act; /* cmd length */
|
||||
memcpy (buf, sim_brk_act, lnt + 1); /* copy with ; */
|
||||
buf[lnt] = 0; /* erase ; */
|
||||
sim_brk_act = sim_brk_act + lnt + 1; } /* adv ptr */
|
||||
else { strncpy (buf, sim_brk_act, size); /* copy action */
|
||||
sim_brk_act = NULL; } /* no more */
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* Clear pending actions */
|
||||
|
||||
void sim_brk_clract (void)
|
||||
{
|
||||
sim_brk_act = NULL;
|
||||
}
|
||||
|
||||
/* New PC */
|
||||
|
||||
void sim_brk_npc (void)
|
||||
|
|
25
scp_tty.c
25
scp_tty.c
|
@ -200,9 +200,10 @@ for (i = 0; i < 64; i++) { /* 64b quo */
|
|||
return quo;
|
||||
}
|
||||
|
||||
int sim_os_sleep (unsigned int sec)
|
||||
void sim_os_sleep (unsigned int sec)
|
||||
{
|
||||
return sleep (sec);
|
||||
sleep (sec);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -275,10 +276,10 @@ uint32 sim_os_msec ()
|
|||
return GetTickCount ();
|
||||
}
|
||||
|
||||
int sim_os_sleep (unsigned int sec)
|
||||
void sim_os_sleep (unsigned int sec)
|
||||
{
|
||||
Sleep (sec * 1000);
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -369,7 +370,6 @@ t_stat ttclose (void);
|
|||
uint32 sim_os_msec (void);
|
||||
t_stat sim_os_poll_kbd (void);
|
||||
t_stat sim_os_putchar (int32 c);
|
||||
int sim_os_sleep (unsigned int sec);
|
||||
|
||||
extern char sim_name[];
|
||||
extern pSIOUXWin SIOUXTextWindow;
|
||||
|
@ -532,9 +532,10 @@ millis = micros / 1000LL;
|
|||
return (uint32) millis;
|
||||
}
|
||||
|
||||
int sim_os_sleep (unsigned int sec)
|
||||
void sim_os_sleep (unsigned int sec)
|
||||
{
|
||||
return sleep (sec);
|
||||
sleep (sec);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -634,9 +635,10 @@ msec = (((uint32) cur.tv_sec) * 1000) + (((uint32) cur.tv_usec) / 1000);
|
|||
return msec;
|
||||
}
|
||||
|
||||
int sim_os_sleep (unsigned int sec)
|
||||
void sim_os_sleep (unsigned int sec)
|
||||
{
|
||||
return sleep (sec);
|
||||
sleep (sec);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -742,9 +744,10 @@ msec = (((uint32) cur.tv_sec) * 1000) + (((uint32) cur.tv_usec) / 1000);
|
|||
return msec;
|
||||
}
|
||||
|
||||
int sim_os_sleep (unsigned int sec)
|
||||
void sim_os_sleep (unsigned int sec)
|
||||
{
|
||||
return sleep (sec);
|
||||
sleep (sec);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
03-Mar-03 RMS Added sim_fsize
|
||||
08-Feb-03 RMS Changed sim_os_sleep to void, added match_ext
|
||||
05-Jan-03 RMS Added hidden switch definitions, device dyn memory support,
|
||||
parameters for function pointers, case sensitive SET support
|
||||
22-Dec-02 RMS Added break flag
|
||||
|
@ -411,6 +413,7 @@ t_stat detach_unit (UNIT *uptr);
|
|||
t_stat reset_all (int start_device);
|
||||
size_t fxread (void *bptr, size_t size, size_t count, FILE *fptr);
|
||||
size_t fxwrite (void *bptr, size_t size, size_t count, FILE *fptr);
|
||||
t_addr sim_fsize (char *cptr);
|
||||
t_stat get_yn (char *ques, t_stat deflt);
|
||||
char *get_glyph (char *iptr, char *optr, char mchar);
|
||||
char *get_glyph_nc (char *iptr, char *optr, char mchar);
|
||||
|
@ -429,6 +432,7 @@ int32 sim_rtcn_calb (int32 time, int32 tmr);
|
|||
t_stat sim_poll_kbd (void);
|
||||
t_stat sim_putchar (int32 out);
|
||||
t_bool sim_brk_test (t_addr bloc, int32 btyp);
|
||||
int sim_os_sleep (unsigned int sec);
|
||||
void sim_os_sleep (unsigned int sec);
|
||||
char *match_ext (char *fnam, char *ext);
|
||||
|
||||
#endif
|
||||
|
|
88
sim_rev.h
88
sim_rev.h
|
@ -29,13 +29,97 @@
|
|||
|
||||
#define SIM_MAJOR 2
|
||||
#define SIM_MINOR 10
|
||||
#define SIM_PATCH 3
|
||||
#define SIM_PATCH 4
|
||||
|
||||
/* V2.10 revision history
|
||||
|
||||
patch date module(s) and fix(es)
|
||||
|
||||
3 tbd scp.c:
|
||||
4 22-Feb-03 scp.c
|
||||
-- added .ini startup file capability
|
||||
-- added multiple breakpoint actions
|
||||
-- added multiple switch evaluation points
|
||||
-- fixed bug in multiword deposits to file
|
||||
|
||||
sim_tape.c: magtape simulation library
|
||||
|
||||
h316_stddev.c: added set line frequency command
|
||||
|
||||
hp2100_mt.c, hp2100_ms.c: revised to use magtape library
|
||||
|
||||
i1401_mt.c: revised to use magtape library
|
||||
|
||||
id_dp.c, id_idc.c: fixed cylinder overflow on writes
|
||||
|
||||
id_mt.c:
|
||||
-- fixed error handling to stop selector channel
|
||||
-- revised to use magtape library
|
||||
|
||||
id16_sys.c, id32_sys.c: added relative addressing support
|
||||
|
||||
id_uvc.c:
|
||||
-- added set frequency command to line frequency clock
|
||||
-- improved calibration algorithm for precision clock
|
||||
|
||||
nova_clk.c: added set line frequency command
|
||||
|
||||
nova_dsk.c: fixed autosizing algorithm
|
||||
|
||||
nova_mt.c: revised to use magtape library
|
||||
|
||||
pdp10_tu.c: revised to use magtape library
|
||||
|
||||
pdp11_stddev.c
|
||||
-- added set line frequency command
|
||||
-- added set ctrl-c command
|
||||
|
||||
pdp11_rq.c:
|
||||
-- fixed ordering problem in queue process
|
||||
-- fixed bug in vector calculation for VAXen
|
||||
-- added user defined drive support
|
||||
|
||||
pdp11_ry.c: fixed autosizing algorithm
|
||||
|
||||
pdp11_tm.c, pdp11_ts.c: revised to use magtape library
|
||||
|
||||
pdp11_tq.c:
|
||||
-- fixed ordering problem in queue process
|
||||
-- fixed overly restrictive test for bad modifiers
|
||||
-- fixed bug in vector calculation for VAXen
|
||||
-- added variable controller, user defined drive support
|
||||
-- revised to use magtape library
|
||||
|
||||
pdp18b_cpu.c: fixed three EAE bugs (found by Hans Pufal)
|
||||
|
||||
pdp18b_mt.c:
|
||||
-- fixed bugs in BOT error handling, interrupt handling
|
||||
-- revised to use magtape library
|
||||
|
||||
pdp18b_rf.c: removed 22nd bit from disk address
|
||||
|
||||
pdp18b_stddev.c:
|
||||
-- added set line frequency command
|
||||
-- added set ctrl-c command
|
||||
|
||||
pdp18b_sys.c: fixed FMTASC printouts (found by Hans Pufal)
|
||||
|
||||
pdp8_clk.c: added set line frequency command
|
||||
|
||||
pdp8_df.c, pdp8_rf.c, pdp8_rx.c: fixed autosizing algorithm
|
||||
|
||||
pdp8_mt.c:
|
||||
-- fixed bug in BOT error handling
|
||||
-- revised to use magtape library
|
||||
|
||||
pdp8_tt.c: added set ctrl-c command
|
||||
|
||||
sds_cpu.c: added set line frequency command
|
||||
|
||||
sds_mt.c: revised to use magtape library
|
||||
|
||||
vax_stddev.c: added set ctrl-c command
|
||||
|
||||
3 06-Feb-03 scp.c:
|
||||
-- added dynamic extension of the breakpoint table
|
||||
-- added breakpoint actions
|
||||
|
||||
|
|
|
@ -209,8 +209,9 @@ int32 sim_check_conn (SOCKET sock, t_bool rd)
|
|||
fd_set rw_set, er_set;
|
||||
fd_set *rw_p = &rw_set;
|
||||
fd_set *er_p = &er_set;
|
||||
struct timeval tz = { 0, 0};
|
||||
struct timeval tz;
|
||||
|
||||
timerclear (&tz);
|
||||
FD_ZERO (rw_p);
|
||||
FD_ZERO (er_p);
|
||||
FD_SET (sock, rw_p);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* sim_sock.h: OS-dependent socket routines header file
|
||||
|
||||
Copyright (c) 2001, Robert M Supnik
|
||||
Copyright (c) 2001-2003, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -23,6 +23,7 @@
|
|||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
15-Feb-03 RMS Added time.h for EMX (from Holger Veit)
|
||||
17-Dec-02 RMS Added sim_connect_sock
|
||||
08-Oct-02 RMS Revised for .NET compatibility
|
||||
20-Aug-02 RMS Changed calling sequence for sim_accept_conn
|
||||
|
@ -50,6 +51,7 @@
|
|||
#include <unistd.h>
|
||||
#include <netinet/in.h> /* for sockaddr_in */
|
||||
#include <netdb.h>
|
||||
#include <sys/time.h> /* for EMX */
|
||||
#endif
|
||||
|
||||
#if defined (VMS) /* VMS unique */
|
||||
|
|
367
sim_tape.c
Normal file
367
sim_tape.c
Normal file
|
@ -0,0 +1,367 @@
|
|||
/* sim_tape.h: simulator tape support library
|
||||
|
||||
Copyright (c) 1993-2003, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
|
||||
Ultimately, this will be a place to hide processing of various tape formats,
|
||||
as well as OS-specific direct hardware access.
|
||||
|
||||
Public routines:
|
||||
|
||||
sim_tape_attach attach tape unit
|
||||
sim_tape_detach detach tape unit
|
||||
sim_tape_rdrecf read tape record forward
|
||||
sim_tape_rdrecr read tape record reverse
|
||||
sim_tape_wrrecf write tape record forward
|
||||
sim_tape_sprecf space tape record forward
|
||||
sim_tape_sprecr space tape record reverse
|
||||
sim_tape_wrtmk write tape mark
|
||||
sim_tape_wreom erase remainder of tape
|
||||
sim_tape_rewind rewind
|
||||
sim_tape_reset reset unit
|
||||
sim_tape_bot TRUE if at beginning of tape
|
||||
sim_tape_eot TRUE if at or beyond end of tape
|
||||
sim_tape_wrp TRUE if write protected
|
||||
*/
|
||||
|
||||
#include "sim_defs.h"
|
||||
#include "sim_tape.h"
|
||||
|
||||
t_stat sim_tape_ioerr (UNIT *uptr);
|
||||
t_stat sim_tape_wrdata (UNIT *uptr, uint32 dat);
|
||||
|
||||
/* Attach tape unit */
|
||||
|
||||
t_stat sim_tape_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
t_stat r = attach_unit (uptr, cptr);
|
||||
if (r != SCPE_OK) return r;
|
||||
return sim_tape_rewind (uptr);
|
||||
}
|
||||
|
||||
/* Detach tape unit */
|
||||
|
||||
t_stat sim_tape_detach (UNIT *uptr)
|
||||
{
|
||||
t_stat r = detach_unit (uptr);
|
||||
|
||||
if (r != SCPE_OK) return r;
|
||||
return sim_tape_rewind (uptr);
|
||||
}
|
||||
|
||||
/* Read record length forward (internal routine)
|
||||
|
||||
Inputs:
|
||||
uptr = pointer to tape unit
|
||||
bc = pointer to returned record length
|
||||
Outputs:
|
||||
status = operation status
|
||||
|
||||
exit condition position
|
||||
|
||||
unit unattached unchanged
|
||||
read error unchanged, PNU set
|
||||
end of file/medium unchanged, PNU set
|
||||
tape mark updated
|
||||
data record unchanged
|
||||
*/
|
||||
|
||||
t_stat sim_tape_rdlntf (UNIT *uptr, t_mtrlnt *bc)
|
||||
{
|
||||
MT_CLR_PNU (uptr);
|
||||
if ((uptr->flags & UNIT_ATT) == 0) return MTSE_UNATT; /* not attached? */
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set tape pos */
|
||||
fxread (bc, sizeof (t_mtrlnt), 1, uptr->fileref); /* read rec lnt */
|
||||
if (ferror (uptr->fileref)) { /* error? */
|
||||
MT_SET_PNU (uptr); /* pos not upd */
|
||||
return sim_tape_ioerr (uptr); }
|
||||
if (feof (uptr->fileref) || (*bc == MTR_EOM)) { /* eof or eom? */
|
||||
MT_SET_PNU (uptr); /* pos not upd */
|
||||
return MTSE_EOM; }
|
||||
if (*bc == MTR_TMK) { /* tape mark? */
|
||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* spc over tmk */
|
||||
return MTSE_TMK; }
|
||||
return MTSE_OK;
|
||||
}
|
||||
|
||||
/* Read record length reverse (internal routine)
|
||||
|
||||
Inputs:
|
||||
uptr = pointer to tape unit
|
||||
bc = pointer to returned record length
|
||||
Outputs:
|
||||
status = operation status
|
||||
|
||||
exit condition position
|
||||
|
||||
unit unattached unchanged
|
||||
beginning of tape unchanged
|
||||
read error unchanged
|
||||
end of file unchanged
|
||||
end of medium updated
|
||||
tape mark updated
|
||||
data record unchanged
|
||||
*/
|
||||
|
||||
t_stat sim_tape_rdlntr (UNIT *uptr, t_mtrlnt *bc)
|
||||
{
|
||||
MT_CLR_PNU (uptr);
|
||||
if ((uptr->flags & UNIT_ATT) == 0) return MTSE_UNATT; /* not attached? */
|
||||
if (uptr->pos < sizeof (t_mtrlnt)) return MTSE_BOT; /* at BOT? */
|
||||
fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt), SEEK_SET);
|
||||
fxread (bc, sizeof (t_mtrlnt), 1, uptr->fileref); /* read rec lnt */
|
||||
if (ferror (uptr->fileref)) /* error? */
|
||||
return sim_tape_ioerr (uptr);
|
||||
if (feof (uptr->fileref)) return MTSE_EOM; /* eof? */
|
||||
if (*bc == MTR_EOM) { /* eom? */
|
||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over eom */
|
||||
return MTSE_EOM; }
|
||||
if (*bc == MTR_TMK) { /* tape mark? */
|
||||
uptr->pos = uptr->pos - sizeof (t_mtrlnt); /* spc over tmk */
|
||||
return MTSE_TMK; }
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Read record forward
|
||||
|
||||
Inputs:
|
||||
uptr = pointer to tape unit
|
||||
buf = pointer to buffer
|
||||
bc = pointer to returned record length
|
||||
max = maximum record size
|
||||
Outputs:
|
||||
status = operation status
|
||||
|
||||
exit condition position
|
||||
|
||||
unit unattached unchanged
|
||||
read error unchanged, PNU set
|
||||
end of file/medium unchanged, PNU set
|
||||
invalid record unchanged, PNU set
|
||||
tape mark updated
|
||||
data record updated
|
||||
data record error updated
|
||||
*/
|
||||
|
||||
t_stat sim_tape_rdrecf (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max)
|
||||
{
|
||||
t_mtrlnt i, tbc, rbc, ebc;
|
||||
t_stat st;
|
||||
|
||||
if (st = sim_tape_rdlntf (uptr, &tbc)) return st; /* read rec lnt */
|
||||
*bc = rbc = MTR_L (tbc); /* strip error flag */
|
||||
ebc = (rbc + 1) & ~1;
|
||||
if (rbc > max) { /* rec out of range? */
|
||||
MT_SET_PNU (uptr);
|
||||
return MTSE_INVRL; }
|
||||
i = fxread (buf, sizeof (uint8), rbc, uptr->fileref); /* read record */
|
||||
if (ferror (uptr->fileref)) { /* error? */
|
||||
MT_SET_PNU (uptr);
|
||||
return sim_tape_ioerr (uptr); }
|
||||
for ( ; i < rbc; i++) buf[i] = 0; /* fill with 0's */
|
||||
uptr->pos = uptr->pos + ebc + (2 * sizeof (t_mtrlnt)); /* move tape */
|
||||
return (MTR_F (tbc)? MTSE_RECE: MTSE_OK);
|
||||
}
|
||||
|
||||
/* Read record reverse
|
||||
|
||||
Inputs:
|
||||
uptr = pointer to tape unit
|
||||
buf = pointer to buffer
|
||||
bc = pointer to returned record length
|
||||
max = maximum record size
|
||||
Outputs:
|
||||
status = operation status
|
||||
|
||||
exit condition position
|
||||
|
||||
unit unattached unchanged
|
||||
read error unchanged
|
||||
end of file unchanged
|
||||
end of medium updated
|
||||
invalid record unchanged
|
||||
tape mark updated
|
||||
data record updated
|
||||
data record error updated
|
||||
*/
|
||||
|
||||
t_stat sim_tape_rdrecr (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max)
|
||||
{
|
||||
t_mtrlnt i, rbc, tbc, ebc;
|
||||
t_stat st;
|
||||
|
||||
if (st = sim_tape_rdlntr (uptr, &tbc)) return st; /* read rec lnt */
|
||||
*bc = rbc = MTR_L (tbc); /* strip error flag */
|
||||
ebc = (rbc + 1) & ~1;
|
||||
if (rbc > max) return MTSE_INVRL; /* rec out of range? */
|
||||
fseek (uptr->fileref, uptr->pos - sizeof (t_mtrlnt) - ebc, SEEK_SET);
|
||||
i = fxread (buf, sizeof (uint8), rbc, uptr->fileref); /* read record */
|
||||
if (ferror (uptr->fileref)) /* error? */
|
||||
return sim_tape_ioerr (uptr);
|
||||
for ( ; i < rbc; i++) buf[i] = 0; /* fill with 0's */
|
||||
uptr->pos = uptr->pos - ebc - (2 * sizeof (t_mtrlnt)); /* move tape */
|
||||
return (MTR_F (tbc)? MTSE_RECE: MTSE_OK);
|
||||
}
|
||||
|
||||
/* Write record forward
|
||||
|
||||
Inputs:
|
||||
uptr = pointer to tape unit
|
||||
buf = pointer to buffer
|
||||
bc = record length
|
||||
Outputs:
|
||||
status = operation status
|
||||
|
||||
exit condition position
|
||||
|
||||
unit unattached unchanged
|
||||
write protect unchanged
|
||||
write error unchanged, PNU set
|
||||
data record updated
|
||||
*/
|
||||
|
||||
t_stat sim_tape_wrrecf (UNIT *uptr, uint8 *buf, t_mtrlnt bc)
|
||||
{
|
||||
t_mtrlnt ebc = (MTR_L (bc) + 1) & ~1;
|
||||
|
||||
MT_CLR_PNU (uptr);
|
||||
if ((uptr->flags & UNIT_ATT) == 0) return MTSE_UNATT; /* not attached? */
|
||||
if (uptr->flags & MTUF_WRP) return MTSE_WRP; /* write prot? */
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set pos */
|
||||
fxwrite (&bc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
fxwrite (buf, sizeof (uint8), ebc, uptr->fileref);
|
||||
fxwrite (&bc, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
if (ferror (uptr->fileref)) { /* error? */
|
||||
MT_SET_PNU (uptr);
|
||||
return sim_tape_ioerr (uptr); }
|
||||
uptr->pos = uptr->pos + ebc + (2 * sizeof (t_mtrlnt)); /* move tape */
|
||||
return MTSE_OK;
|
||||
}
|
||||
|
||||
/* Write metadata forward (internal routine) */
|
||||
|
||||
t_stat sim_tape_wrdata (UNIT *uptr, uint32 dat)
|
||||
{
|
||||
MT_CLR_PNU (uptr);
|
||||
if ((uptr->flags & UNIT_ATT) == 0) return MTSE_UNATT; /* not attached? */
|
||||
if (uptr-> flags & MTUF_WRP) return MTSE_WRP; /* write prot? */
|
||||
fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set pos */
|
||||
fxwrite (&dat, sizeof (t_mtrlnt), 1, uptr->fileref);
|
||||
if (ferror (uptr->fileref)) { /* error? */
|
||||
MT_SET_PNU (uptr);
|
||||
return sim_tape_ioerr (uptr); }
|
||||
uptr->pos = uptr->pos + sizeof (t_mtrlnt); /* move tape */
|
||||
return MTSE_OK;
|
||||
}
|
||||
|
||||
/* Write tape mark */
|
||||
|
||||
t_stat sim_tape_wrtmk (UNIT *uptr)
|
||||
{
|
||||
return sim_tape_wrdata (uptr, MTR_TMK);
|
||||
}
|
||||
|
||||
/* Write end of medium */
|
||||
|
||||
t_stat sim_tape_wreom (UNIT *uptr)
|
||||
{
|
||||
return sim_tape_wrdata (uptr, MTR_EOM);
|
||||
}
|
||||
|
||||
/* Space record forward */
|
||||
|
||||
t_stat sim_tape_sprecf (UNIT *uptr, t_mtrlnt *bc)
|
||||
{
|
||||
t_mtrlnt ebc;
|
||||
t_stat st;
|
||||
|
||||
if (st = sim_tape_rdlntf (uptr, bc)) return st; /* get record length */
|
||||
*bc = MTR_L (*bc);
|
||||
ebc = (*bc + 1) & ~1;
|
||||
uptr->pos = uptr->pos + ebc + (2 * sizeof (t_mtrlnt)); /* update position */
|
||||
return MTSE_OK;
|
||||
}
|
||||
|
||||
/* Space record reverse */
|
||||
|
||||
t_stat sim_tape_sprecr (UNIT *uptr, t_mtrlnt *bc)
|
||||
{
|
||||
t_mtrlnt ebc;
|
||||
t_stat st;
|
||||
|
||||
if (MT_TST_PNU (uptr)) {
|
||||
MT_CLR_PNU (uptr);
|
||||
return SCPE_OK; }
|
||||
if (st = sim_tape_rdlntr (uptr, bc)) return st; /* get record length */
|
||||
*bc = MTR_L (*bc);
|
||||
ebc = (*bc + 1) & ~1;
|
||||
uptr->pos = uptr->pos - ebc - (2 * sizeof (t_mtrlnt)); /* update position */
|
||||
return MTSE_OK;
|
||||
}
|
||||
|
||||
/* Rewind tape */
|
||||
|
||||
t_stat sim_tape_rewind (UNIT *uptr)
|
||||
{
|
||||
uptr->pos = 0;
|
||||
MT_CLR_PNU (uptr);
|
||||
return MTSE_OK;
|
||||
}
|
||||
|
||||
/* Reset tape */
|
||||
|
||||
t_stat sim_tape_reset (UNIT *uptr)
|
||||
{
|
||||
MT_CLR_PNU (uptr);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
/* Test for BOT */
|
||||
|
||||
t_bool sim_tape_bot (UNIT *uptr)
|
||||
{
|
||||
return (uptr->pos < sizeof (t_mtrlnt))? TRUE: FALSE;
|
||||
}
|
||||
|
||||
/* Test for end of tape */
|
||||
|
||||
t_bool sim_tape_eot (UNIT *uptr, t_addr cap)
|
||||
{
|
||||
return (uptr->pos > cap)? TRUE: FALSE;
|
||||
}
|
||||
|
||||
/* Test for write protect */
|
||||
|
||||
t_bool sim_tape_wrp (UNIT *uptr)
|
||||
{
|
||||
return (uptr->flags & MTUF_WRP)? TRUE: FALSE;
|
||||
}
|
||||
|
||||
/* Process I/O error */
|
||||
|
||||
t_stat sim_tape_ioerr (UNIT *uptr)
|
||||
{
|
||||
perror ("Magtape library I/O error");
|
||||
clearerr (uptr->fileref);
|
||||
return SCPE_IOERR;
|
||||
}
|
101
sim_tape.h
Normal file
101
sim_tape.h
Normal file
|
@ -0,0 +1,101 @@
|
|||
/* sim_tape.h: simulator tape support library definitions
|
||||
|
||||
Copyright (c) 1993-2003, Robert M Supnik
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of Robert M Supnik shall not
|
||||
be used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Robert M Supnik.
|
||||
*/
|
||||
|
||||
#ifndef _SIM_TAPE_H_
|
||||
#define _SIM_TAPE_H_ 0
|
||||
|
||||
/* Temporary for use with old sim_defs.h */
|
||||
|
||||
#undef MTR_TMK
|
||||
#undef MTR_EOM
|
||||
#undef MTR_ERF
|
||||
#undef MT_SET_PNU
|
||||
#undef MT_CLR_PNU
|
||||
#undef MT_TST_PNU
|
||||
|
||||
/* Default tape format */
|
||||
|
||||
/* typedef uint32 t_mtrlnt; /* magtape rec lnt */
|
||||
|
||||
#define MTR_TMK 0x00000000 /* tape mark */
|
||||
#define MTR_EOM 0xFFFFFFFF /* end of medium */
|
||||
#define MTR_ERF 0x80000000 /* error flag */
|
||||
#define MTR_F(x) ((x) & MTR_ERF) /* record error flg */
|
||||
#define MTR_L(x) ((x) & ~MTR_ERF) /* record length */
|
||||
|
||||
/* Unit flags */
|
||||
|
||||
#define MTUF_V_PNU (UNIT_V_UF + 0) /* position not upd */
|
||||
#define MTUF_V_WLK (UNIT_V_UF + 1) /* write locked */
|
||||
#define MTUF_V_FMT (UNIT_V_UF + 2) /* tape file format */
|
||||
#define MTUF_W_FMT 3 /* 3b of formats */
|
||||
#define MTUF_N_FMT (1u << MTUF_W_FMT) /* number of formats */
|
||||
#define MTUF_M_FMT ((1u << MTUF_W_FMT) - 1)
|
||||
#define MTUF_F_STD 0 /* SIMH format */
|
||||
#define MTUF_F_E11 1 /* E11 format */
|
||||
#define MTUF_F_TPC 2 /* TPC format */
|
||||
#define MUTF_F_TDF 3 /* TDF format */
|
||||
#define MTUF_V_UF (MTUF_V_FMT + MTUF_W_FMT)
|
||||
#define MTUF_PNU (1u << MTUF_V_PNU)
|
||||
#define MTUF_WLK (1u << MTUF_V_WLK)
|
||||
#define MTUF_WRP (MTUF_WLK | UNIT_RO)
|
||||
|
||||
#define MT_SET_PNU(u) (u)->flags = (u)->flags | MTUF_PNU
|
||||
#define MT_CLR_PNU(u) (u)->flags = (u)->flags & ~MTUF_PNU
|
||||
#define MT_TST_PNU(u) ((u)->flags & MTUF_PNU)
|
||||
#define MT_GET_FMT(u) (((u)->flags >> MTUF_V_FMT) & MTUF_M_FMT)
|
||||
|
||||
/* Return status codes */
|
||||
|
||||
#define MTSE_OK 0 /* no error */
|
||||
#define MTSE_TMK 1 /* tape mark */
|
||||
#define MTSE_UNATT 2 /* unattached */
|
||||
#define MTSE_IOERR 3 /* IO error */
|
||||
#define MTSE_INVRL 4 /* invalid rec lnt */
|
||||
#define MTSE_FMT 5 /* invalid format */
|
||||
#define MTSE_BOT 6 /* beginning of tape */
|
||||
#define MTSE_EOM 7 /* end of medium */
|
||||
#define MTSE_RECE 8 /* error in record */
|
||||
#define MTSE_WRP 9 /* write protected */
|
||||
|
||||
/* Prototypes */
|
||||
|
||||
t_stat sim_tape_attach (UNIT *uptr, char *cptr);
|
||||
t_stat sim_tape_detach (UNIT *uptr);
|
||||
t_stat sim_tape_rdrecf (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max);
|
||||
t_stat sim_tape_rdrecr (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max);
|
||||
t_stat sim_tape_wrrecf (UNIT *uptr, uint8 *buf, t_mtrlnt bc);
|
||||
t_stat sim_tape_wrtmk (UNIT *uptr);
|
||||
t_stat sim_tape_wreom (UNIT *uptr);
|
||||
t_stat sim_tape_sprecf (UNIT *uptr, t_mtrlnt *bc);
|
||||
t_stat sim_tape_sprecr (UNIT *uptr, t_mtrlnt *bc);
|
||||
t_stat sim_tape_rewind (UNIT *uptr);
|
||||
t_stat sim_tape_reset (UNIT *uptr);
|
||||
t_bool sim_tape_bot (UNIT *uptr);
|
||||
t_bool sim_tape_wrp (UNIT *uptr);
|
||||
t_bool sim_tape_eot (UNIT *uptr, t_addr cap);
|
||||
|
||||
#endif
|
40
simh_doc.txt
40
simh_doc.txt
|
@ -82,16 +82,23 @@ To start the simulator, simply type its name. (On version of VMS
|
|||
prior to 6.2, the simulators must then be defined as foreign commands
|
||||
in order to be be started by name.) The simulator recognizes one
|
||||
switch, -Q; if specified, certain informational messages are suppressed.
|
||||
|
||||
The simulator interprets the arguments on the command line, if any,
|
||||
as the file name and arguments for a DO command. If a startup file
|
||||
is specified, it should contain a series of non-interactive simulator
|
||||
commands, one per line. These command can be used to set up standard
|
||||
parameters, for example, disk sizes:
|
||||
as the file name and arguments for a DO command:
|
||||
|
||||
% pdp10 {<startup file> {arg,arg,...}}(cr)
|
||||
|
||||
The simulator types out its name and version, executes the commands
|
||||
in the startup file, if any, and then prompts for input with
|
||||
If no file is specified on the command line, the simulator looks for
|
||||
an startup file consisting of the simulator name (including its path
|
||||
components) plus the extension .ini. If a startup file is specified,
|
||||
either on the command line or implicitly via the .ini capability, it
|
||||
ishould contain a series of non-interactive simulator command, one
|
||||
per line. These command can be used to set up standard parameters,
|
||||
for example, disk sizes.
|
||||
|
||||
After initializing its internal structures and processing the startup
|
||||
file (if any), the simulator types out its name and version and then
|
||||
prompts for input with:
|
||||
|
||||
sim>
|
||||
|
||||
|
@ -106,11 +113,11 @@ The supplied makefile will compile the simulators for UNIX systems
|
|||
which support the POSIX TERMIOS. The VAX and PDP-11 can be compiled
|
||||
with or without Ethernet support. To compile without Ethernet support:
|
||||
|
||||
gmake {target|ALL}
|
||||
gmake {target|ALL|clean}
|
||||
|
||||
To compile with Ethernet support:
|
||||
|
||||
gmake USE_NETWORK=1 {target|ALL}
|
||||
gmake USE_NETWORK=1 {target|ALL|clean}
|
||||
|
||||
Notes for hand compilation:
|
||||
|
||||
|
@ -490,15 +497,16 @@ breakpoints of different types, identified by letter (for example, E
|
|||
for execution, R for read, W for write, etc). At the moment, most
|
||||
simulators support only E (execution) breakpoints.
|
||||
|
||||
Associated with a breakpoint is a count and, optionally, an action.
|
||||
Each time the breakpoint is sprung, the associated count is decremented.
|
||||
If the count is less than or equal to 0, the breakpoint occurs; otherwise,
|
||||
it is deferred. When the breakpoint occurs, the optional action is
|
||||
automatically executed
|
||||
Associated with a breakpoint is a count and, optionally, one or more
|
||||
actions. Each time the breakpoint is sprung, the associated count is
|
||||
decremented. If the count is less than or equal to 0, the breakpoint
|
||||
occurs; otherwise, it is deferred. When the breakpoint occurs, the
|
||||
optional actions are automatically executed.
|
||||
|
||||
A breakpoint is set by the BREAK command:
|
||||
|
||||
sim> BREAK {-types} <addr range>{[count]},{addr range...}{;action}
|
||||
sim> BREAK {-types} <addr range>{[count]},{addr range...}
|
||||
{;action;action...}
|
||||
|
||||
If no type is specified, the simulator-specific default breakpoint
|
||||
type (usually E for execution) is used. As with EXAMINE and DEPOSIT,
|
||||
|
@ -508,8 +516,8 @@ or a relative range of address/length. Examples of BREAK:
|
|||
sim> break -e 200 -- set E break at 200
|
||||
sim> break 2000/2[2] -- set E breaks at 2000,2001
|
||||
with count = 2
|
||||
sim> break 100;ex ac -- set E break at 100 with
|
||||
action EX AC
|
||||
sim> break 100;ex ac;d mq 0 -- set E break at 100 with
|
||||
actions EX AC and D MQ 0
|
||||
sim> break 100; -- delete action on break at 100
|
||||
|
||||
Currently set breakpoints can be displayed with the SHOW BREAK command:
|
||||
|
|
|
@ -164,7 +164,7 @@ sockets library.
|
|||
|
||||
UNIX was first developed on the PDP-7; its first widespread usage was on
|
||||
the PDP-11. UNIX provides a program development and execution environment
|
||||
for assembler and C programs. UNIX V5, V7, V7 for the PDP-11 is provided
|
||||
for assembler and C programs. UNIX V5, V6, V7 for the PDP-11 is provided
|
||||
under license, as is, without fee, by Caldera Corportion, for non-commercial
|
||||
use only. Please read the enclosed license agreement for full terms and
|
||||
conditions. This license must be reproduced with any copy of the UNIX V5,
|
||||
|
@ -646,4 +646,48 @@ TOPS-20 was a popular alternative derived from the BBN TENEX system.
|
|||
Installation and distribution tapes for TOPS-10 7.03, TOPS-10 7.04,
|
||||
and TOPS-20 4.1 are available at http://pdp-10.trailing-edge.com.
|
||||
|
||||
10. Interdata 32b Systems
|
||||
|
||||
10.1 Interdata 7/32 UNIX
|
||||
|
||||
Interdata UNIX V6 was the first port of UNIX from its native environment
|
||||
on the PDP-11. The port was done by Richard Miller and his colleagues
|
||||
at the University of Wollongong, Australia, in 1976-77. UNIX V6 and V7
|
||||
for the Interdata 7/32 is provided under license, as is, without fee, by
|
||||
Caldera Corportion, for non-commercial use only. Please read the enclosed
|
||||
license agreement for full terms and conditions. This license must be
|
||||
reproduced with any copy of the UNIX V6 and V7 disk images. My thanks to
|
||||
Richard Miller, without whose guidance, knowledge, and patience the
|
||||
recreation of Interdata UNIX would not have been possible, and to Caldera,
|
||||
which provided the license.
|
||||
|
||||
10.1.1 UNIX V6
|
||||
|
||||
UNIX V6 is contained on a single 10MB disk image. To boot UNIX V6:
|
||||
|
||||
sim> set ttp ena
|
||||
sim> set pas dev=12
|
||||
sim> set mt dev=85
|
||||
sim> att -e dp0 iu6_dp0.dsk
|
||||
sim> boot dp0
|
||||
?unix
|
||||
login: root
|
||||
# ls -l
|
||||
|
||||
10.1.2 UNIX V7
|
||||
|
||||
UNIX V7 is contained on two 10MB disk images. To boot UNIX V7:
|
||||
|
||||
sim> set ttp ena
|
||||
sim> set pas dev=12
|
||||
sim> set mt dev=85
|
||||
sim> att -e dp0 iu6_dp0.dsk
|
||||
sim> att -e dp1 iu6_dp1.dsk
|
||||
sim> boot dp0
|
||||
Boot
|
||||
: dsk(1,0)unix
|
||||
#
|
||||
|
||||
Type ^D to enable multiuser mode. The root password is root.
|
||||
|
||||
[end simh_swre.txt]
|
||||
|
|
Loading…
Add table
Reference in a new issue