1
0
mirror of https://github.com/simh/simh.git synced 2026-01-26 04:01:38 +00:00

Notes For V3.5-0

The source set has been extensively overhauled.  For correct
viewing, set Visual C++ or Emacs to have tab stops every 4
characters.

1. New Features in 3.4-1

1.1 All Ethernet devices

- Added Windows user-defined adapter names (from Timothe Litt)

1.2 Interdata, SDS, HP, PDP-8, PDP-18b terminal multiplexors

- Added support for SET <unit>n DISCONNECT

1.3 VAX

- Added latent QDSS support
- Revised autoconfigure to handle QDSS

1.4 PDP-11

- Revised autoconfigure to handle more casees

2. Bugs Fixed in 3.4-1

2.1 SCP and libraries

- Trim trailing spaces on all input (for example, attach file names)
- Fixed sim_sock spurious SIGPIPE error in Unix/Linux
- Fixed sim_tape misallocation of TPC map array for 64b simulators

2.2 1401

- Fixed bug, CPU reset was clearing SSB through SSG

2.3 PDP-11

- Fixed bug in VH vector display routine
- Fixed XU runt packet processing (found by Tim Chapman)

2.4 Interdata

- Fixed bug in SHOW PAS CONN/STATS
- Fixed potential integer overflow exception in divide

2.5 SDS

- Fixed bug in SHOW MUX CONN/STATS

2.6 HP

- Fixed bug in SHOW MUX CONN/STATS

2.7 PDP-8

- Fixed bug in SHOW TTIX CONN/STATS
- Fixed bug in SET/SHOW TTOXn LOG

2.8 PDP-18b

- Fixed bug in SHOW TTIX CONN/STATS
- Fixed bug in SET/SHOW TTOXn LOG

2.9 Nova, Eclipse

- Fixed potential integer overflow exception in divide
This commit is contained in:
Bob Supnik
2005-09-09 18:09:00 -07:00
committed by Mark Pizzolato
parent ec60bbf329
commit b7c1eae41f
257 changed files with 107140 additions and 97195 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
/* pdp18b_defs.h: 18b PDP simulator definitions
Copyright (c) 1993-2004, Robert M Supnik
Copyright (c) 1993-2005, 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"),
@@ -19,28 +19,28 @@
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
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.
14-Jan-04 RMS Revised IO device call interface
18-Oct-03 RMS Added DECtape off reel message
18-Jul-03 RMS Added FP15 support
Added XVM support
Added EAE option for PDP-4
25-Apr-03 RMS Revised for extended file support
04-Feb-03 RMS Added RB09, LP09 support
22-Nov-02 RMS Added PDP-4 drum support
05-Oct-02 RMS Added DIB structure
25-Jul-02 RMS Added PDP-4 DECtape support
10-Feb-02 RMS Added PDP-7 DECtape support
25-Nov-01 RMS Revised interrupt structure
27-May-01 RMS Added second Teletype support
21-Jan-01 RMS Added DECtape support
14-Apr-99 RMS Changed t_addr to unsigned
02-Jan-96 RMS Added fixed head and moving head disks
31-Dec-95 RMS Added memory management
19-Mar-95 RMS Added dynamic memory size
14-Jan-04 RMS Revised IO device call interface
18-Oct-03 RMS Added DECtape off reel message
18-Jul-03 RMS Added FP15 support
Added XVM support
Added EAE option for PDP-4
25-Apr-03 RMS Revised for extended file support
04-Feb-03 RMS Added RB09, LP09 support
22-Nov-02 RMS Added PDP-4 drum support
05-Oct-02 RMS Added DIB structure
25-Jul-02 RMS Added PDP-4 DECtape support
10-Feb-02 RMS Added PDP-7 DECtape support
25-Nov-01 RMS Revised interrupt structure
27-May-01 RMS Added second Teletype support
21-Jan-01 RMS Added DECtape support
14-Apr-99 RMS Changed t_addr to unsigned
02-Jan-96 RMS Added fixed head and moving head disks
31-Dec-95 RMS Added memory management
19-Mar-95 RMS Added dynamic memory size
The author gratefully acknowledges the help of Craig St. Clair and
Deb Tevonian in locating archival material about the 18b PDP's, and of
@@ -48,230 +48,228 @@
*/
#ifndef _PDP18B_DEFS_H_
#define _PDP18B_DEFS_H_ 0
#define _PDP18B_DEFS_H_ 0
#include "sim_defs.h" /* simulator defns */
#include "sim_defs.h" /* simulator defns */
/* Models: only one should be defined
model memory CPU options I/O options
model memory CPU options I/O options
PDP4 8K Type 18 EAE Type 65 KSR-28 Teletype (Baudot)
??Type 16 mem extension integral paper tape reader
Type 75 paper tape punch
integral real time clock
Type 62 line printer (Hollerith)
Type 550/555 DECtape
Type 24 serial drum
PDP4 8K Type 18 EAE Type 65 KSR-28 Teletype (Baudot)
??Type 16 mem extension integral paper tape reader
Type 75 paper tape punch
integral real time clock
Type 62 line printer (Hollerith)
Type 550/555 DECtape
Type 24 serial drum
PDP7 32K Type 177 EAE Type 649 KSR-33 Teletype
Type 148 mem extension Type 444 paper tape reader
Type 75 paper tape punch
integral real time clock
Type 647B line printer (sixbit)
Type 550/555 DECtape
Type 24 serial drum
PDP7 32K Type 177 EAE Type 649 KSR-33 Teletype
Type 148 mem extension Type 444 paper tape reader
Type 75 paper tape punch
integral real time clock
Type 647B line printer (sixbit)
Type 550/555 DECtape
Type 24 serial drum
PDP9 32K KE09A EAE KSR-33 Teletype
KF09A auto pri intr PC09A paper tape reader and punch
KG09B mem extension integral real time clock
KP09A power detection Type 647D/E line printer (sixbit)
KX09A mem protection LP09 line printer (ASCII)
RF09/RS09 fixed head disk
RB09 fixed head disk
TC59 magnetic tape
TC02/TU55 DECtape
LT09A additional Teletypes
PDP9 32K KE09A EAE KSR-33 Teletype
KF09A auto pri intr PC09A paper tape reader and punch
KG09B mem extension integral real time clock
KP09A power detection Type 647D/E line printer (sixbit)
KX09A mem protection LP09 line printer (ASCII)
RF09/RS09 fixed head disk
RB09 fixed head disk
TC59 magnetic tape
TC02/TU55 DECtape
LT09A additional Teletypes
PDP15 128K KE15 EAE KSR-35 Teletype
KA15 auto pri intr PC15 paper tape reader and punch
KF15 power detection KW15 real time clock
KM15 mem protection LP09 line printer
KT15 mem relocation LP15 line printer
FP15 floating point RP15 disk pack
XVM option RF15/RF09 fixed head disk
TC59D magnetic tape
TC15/TU56 DECtape
LT15/LT19 additional Teletypes
PDP15 128K KE15 EAE KSR-35 Teletype
KA15 auto pri intr PC15 paper tape reader and punch
KF15 power detection KW15 real time clock
KM15 mem protection LP09 line printer
KT15 mem relocation LP15 line printer
FP15 floating point RP15 disk pack
XVM option RF15/RF09 fixed head disk
TC59D magnetic tape
TC15/TU56 DECtape
LT15/LT19 additional Teletypes
??Indicates not implemented. The PDP-4 manual refers to a memory
??extension control; there is no documentation on it.
*/
#if !defined (PDP4) && !defined (PDP7) && !defined (PDP9) && !defined (PDP15)
#define PDP15 0 /* default to PDP-15 */
#define PDP15 0 /* default to PDP-15 */
#endif
/* Simulator stop codes */
#define STOP_RSRV 1 /* must be 1 */
#define STOP_HALT 2 /* HALT */
#define STOP_IBKPT 3 /* breakpoint */
#define STOP_XCT 4 /* nested XCT's */
#define STOP_API 5 /* invalid API int */
#define STOP_NONSTD 6 /* non-std dev num */
#define STOP_MME 7 /* mem mgt error */
#define STOP_FPDIS 8 /* fp inst, fpp disabled */
#define STOP_DTOFF 9 /* DECtape off reel */
#define STOP_RSRV 1 /* must be 1 */
#define STOP_HALT 2 /* HALT */
#define STOP_IBKPT 3 /* breakpoint */
#define STOP_XCT 4 /* nested XCT's */
#define STOP_API 5 /* invalid API int */
#define STOP_NONSTD 6 /* non-std dev num */
#define STOP_MME 7 /* mem mgt error */
#define STOP_FPDIS 8 /* fp inst, fpp disabled */
#define STOP_DTOFF 9 /* DECtape off reel */
/* Peripheral configuration */
#if defined (PDP4)
#define ADDRSIZE 13
#define KSR28 0 /* Baudot terminal */
#define TYPE62 0 /* Hollerith printer */
#define TYPE550 0 /* DECtape */
#define DRM 0 /* drum */
#define ADDRSIZE 13
#define KSR28 0 /* Baudot terminal */
#define TYPE62 0 /* Hollerith printer */
#define TYPE550 0 /* DECtape */
#define DRM 0 /* drum */
#elif defined (PDP7)
#define ADDRSIZE 15
#define TYPE647 0 /* sixbit printer */
#define TYPE550 0 /* DECtape */
#define DRM 0 /* drum */
#define ADDRSIZE 15
#define TYPE647 0 /* sixbit printer */
#define TYPE550 0 /* DECtape */
#define DRM 0 /* drum */
#elif defined (PDP9)
#define ADDRSIZE 15
#define TYPE647 0 /* sixbit printer */
#define LP09 0 /* ASCII printer */
#define RB 0 /* fixed head disk */
#define RF 0 /* fixed head disk */
#define MTA 0 /* magtape */
#define TC02 0 /* DECtape */
#define TTY1 4 /* second Teletype(s) */
#define BRMASK 0076000 /* bounds mask */
#define ADDRSIZE 15
#define TYPE647 0 /* sixbit printer */
#define LP09 0 /* ASCII printer */
#define RB 0 /* fixed head disk */
#define RF 0 /* fixed head disk */
#define MTA 0 /* magtape */
#define TC02 0 /* DECtape */
#define TTY1 4 /* second Teletype(s) */
#define BRMASK 0076000 /* bounds mask */
#elif defined (PDP15)
#define ADDRSIZE 17
#define LP09 0 /* ASCII printer */
#define LP15 0 /* DMA printer */
#define RF 0 /* fixed head disk */
#define RP 0 /* disk pack */
#define MTA 0 /* magtape */
#define TC02 0 /* DECtape */
#define TTY1 16 /* second Teletype(s) */
#define BRMASK 0377400 /* bounds mask */
#define BRMASK_XVM 0777400 /* bounds mask, XVM */
#define ADDRSIZE 17
#define LP09 0 /* ASCII printer */
#define LP15 0 /* DMA printer */
#define RF 0 /* fixed head disk */
#define RP 0 /* disk pack */
#define MTA 0 /* magtape */
#define TC02 0 /* DECtape */
#define TTY1 16 /* second Teletype(s) */
#define BRMASK 0377400 /* bounds mask */
#define BRMASK_XVM 0777400 /* bounds mask, XVM */
#endif
/* Memory */
#define AMASK ((1 << ADDRSIZE) - 1) /* address mask */
#define IAMASK 077777 /* ind address mask */
#define BLKMASK (AMASK & (~IAMASK)) /* block mask */
#define MAXMEMSIZE (1 << ADDRSIZE) /* max memory size */
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE)
#define AMASK ((1 << ADDRSIZE) - 1) /* address mask */
#define IAMASK 077777 /* ind address mask */
#define BLKMASK (AMASK & (~IAMASK)) /* block mask */
#define MAXMEMSIZE (1 << ADDRSIZE) /* max memory size */
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE)
/* Instructions */
#define I_V_OP 14 /* opcode */
#define I_M_OP 017
#define I_V_IND 13 /* indirect */
#define I_V_IDX 12 /* index */
#define I_IND (1 << I_V_IND)
#define I_IDX (1 << I_V_IDX)
#define B_DAMASK 017777 /* bank mode address */
#define B_EPCMASK (AMASK & ~B_DAMASK)
#define P_DAMASK 007777 /* page mode address */
#define P_EPCMASK (AMASK & ~P_DAMASK)
#define I_V_OP 14 /* opcode */
#define I_M_OP 017
#define I_V_IND 13 /* indirect */
#define I_V_IDX 12 /* index */
#define I_IND (1 << I_V_IND)
#define I_IDX (1 << I_V_IDX)
#define B_DAMASK 017777 /* bank mode address */
#define B_EPCMASK (AMASK & ~B_DAMASK)
#define P_DAMASK 007777 /* page mode address */
#define P_EPCMASK (AMASK & ~P_DAMASK)
/* Memory cycles */
#define FE 0
#define DF 1
#define RD 2
#define WR 3
#define FE 0
#define DF 1
#define RD 2
#define WR 3
/* Memory status codes */
#define MM_OK 0
#define MM_ERR 1
#define MM_OK 0
#define MM_ERR 1
/* Memory management relocation checks (PDP-15 KT15 and XVM only) */
#define REL_C -1 /* console */
#define REL_R 0 /* read */
#define REL_W 1 /* write */
#define REL_C -1 /* console */
#define REL_R 0 /* read */
#define REL_W 1 /* write */
/* Architectural constants */
#define DMASK 0777777 /* data mask */
#define LINK (DMASK + 1) /* link */
#define LACMASK (LINK | DMASK) /* link + data */
#define SIGN 0400000 /* sign bit */
#define OP_JMS 0100000 /* JMS */
#define OP_JMP 0600000 /* JMP */
#define OP_HLT 0740040 /* HLT */
#define DMASK 0777777 /* data mask */
#define LINK (DMASK + 1) /* link */
#define LACMASK (LINK | DMASK) /* link + data */
#define SIGN 0400000 /* sign bit */
#define OP_JMS 0100000 /* JMS */
#define OP_JMP 0600000 /* JMP */
#define OP_HLT 0740040 /* HLT */
/* IOT subroutine return codes */
#define IOT_V_SKP 18 /* skip */
#define IOT_V_REASON 19 /* reason */
#define IOT_SKP (1 << IOT_V_SKP)
#define IOT_REASON (1 << IOT_V_REASON)
#define IOT_V_SKP 18 /* skip */
#define IOT_V_REASON 19 /* reason */
#define IOT_SKP (1 << IOT_V_SKP)
#define IOT_REASON (1 << IOT_V_REASON)
#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */
#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* stop on error */
/* PC change queue */
#define PCQ_SIZE 64 /* must be 2**n */
#define PCQ_MASK (PCQ_SIZE - 1)
#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = PC
#define PCQ_SIZE 64 /* must be 2**n */
#define PCQ_MASK (PCQ_SIZE - 1)
#define PCQ_ENTRY pcq[pcq_p = (pcq_p - 1) & PCQ_MASK] = PC
/* XVM memory management registers */
#define MM_RDIS 0400000 /* reloc disabled */
#define MM_V_GM 15 /* G mode */
#define MM_M_GM 03
#define MM_GM (MM_M_GM << MM_V_GM)
#define MM_G_W0 0077777 /* virt addr width */
#define MM_G_W1 0177777
#define MM_G_W2 0777777
#define MM_G_W3 0377777
#define MM_G_B0 0060000 /* SAS base */
#define MM_G_B1 0160000
#define MM_G_B2 0760000
#define MM_G_B3 0360000
#define MM_UIOT 0040000 /* user mode IOT's */
#define MM_WP 0020000 /* share write prot */
#define MM_SH 0010000 /* share enabled */
#define MM_V_SLR 10 /* segment length reg */
#define MM_M_SLR 03
#define MM_SLR_L0 001000 /* SAS length */
#define MM_SLR_L1 002000
#define MM_SLR_L2 010000
#define MM_SLR_L3 020000
#define MM_SBR_MASK 01777 /* share base reg */
#define MM_GETGM(x) (((x) >> MM_V_GM) & MM_M_GM)
#define MM_GETSLR(x) (((x) >> MM_V_SLR) & MM_M_SLR)
#define MM_RDIS 0400000 /* reloc disabled */
#define MM_V_GM 15 /* G mode */
#define MM_M_GM 03
#define MM_GM (MM_M_GM << MM_V_GM)
#define MM_G_W0 0077777 /* virt addr width */
#define MM_G_W1 0177777
#define MM_G_W2 0777777
#define MM_G_W3 0377777
#define MM_G_B0 0060000 /* SAS base */
#define MM_G_B1 0160000
#define MM_G_B2 0760000
#define MM_G_B3 0360000
#define MM_UIOT 0040000 /* user mode IOT's */
#define MM_WP 0020000 /* share write prot */
#define MM_SH 0010000 /* share enabled */
#define MM_V_SLR 10 /* segment length reg */
#define MM_M_SLR 03
#define MM_SLR_L0 001000 /* SAS length */
#define MM_SLR_L1 002000
#define MM_SLR_L2 010000
#define MM_SLR_L3 020000
#define MM_SBR_MASK 01777 /* share base reg */
#define MM_GETGM(x) (((x) >> MM_V_GM) & MM_M_GM)
#define MM_GETSLR(x) (((x) >> MM_V_SLR) & MM_M_SLR)
/* Device information block */
#define DEV_MAXBLK 8 /* max dev block */
#define DEV_MAX 64 /* total devices */
#define DEV_MAXBLK 8 /* max dev block */
#define DEV_MAX 64 /* total devices */
struct pdp18b_dib {
uint32 dev; /* base dev number */
uint32 num; /* number of slots */
int32 (*iors)(void); /* IORS responder */
int32 (*dsp[DEV_MAXBLK])(int32 dev, int32 pulse, int32 dat);
};
typedef struct pdp18b_dib DIB;
typedef struct {
uint32 dev; /* base dev number */
uint32 num; /* number of slots */
int32 (*iors)(void); /* IORS responder */
int32 (*dsp[DEV_MAXBLK])(int32 dev, int32 pulse, int32 dat);
} DIB;
/* Standard device numbers */
#define DEV_PTR 001 /* paper tape reader */
#define DEV_PTP 002 /* paper tape punch */
#define DEV_TTI 003 /* console input */
#define DEV_TTO 004 /* console output */
#define DEV_TTI1 041 /* extra terminals */
#define DEV_TTO1 040
#define DEV_DRM 060 /* drum */
#define DEV_RP 063 /* RP15 */
#define DEV_LPT 065 /* line printer */
#define DEV_RF 070 /* RF09 */
#define DEV_RB 071 /* RB09 */
#define DEV_MT 073 /* magtape */
#define DEV_DTA 075 /* dectape */
#define DEV_PTR 001 /* paper tape reader */
#define DEV_PTP 002 /* paper tape punch */
#define DEV_TTI 003 /* console input */
#define DEV_TTO 004 /* console output */
#define DEV_TTI1 041 /* extra terminals */
#define DEV_TTO1 040
#define DEV_DRM 060 /* drum */
#define DEV_RP 063 /* RP15 */
#define DEV_LPT 065 /* line printer */
#define DEV_RF 070 /* RF09 */
#define DEV_RB 071 /* RB09 */
#define DEV_MT 073 /* magtape */
#define DEV_DTA 075 /* dectape */
/* Interrupt system
The interrupt system can be modelled on either the flag driven system
@@ -279,210 +277,210 @@ typedef struct pdp18b_dib DIB;
If flag based, API is hard to implement; if API based, IORS requires
extra code for implementation. I've chosen an API based model.
API channel Device API priority Notes
API channel Device API priority Notes
00 software 4 4
01 software 5 5
02 software 6 6
03 software 7 7
04 TC02/TC15 1
05 TC59D 1
06 drum 1 PDP-9 only
07 RB09 1 PDP-9 only
10 paper tape reader 2
11 real time clock 3
12 power fail 0
13 memory parity 0
14 display 2
15 card reader 2
16 line printer 2
17 A/D converter 0
20 interprocessor buffer 3
21 360 link 3 PDP-9 only
22 data phone 2 PDP-15 only
23 RF09/RF15 1
24 RP15 1 PDP-15 only
25 plotter 1 PDP-15 only
26 -
27 -
30 -
31 -
32 -
33 -
34 LT15 TTO 3 PDP-15 only
35 LT15 TTI 3 PDP-15 only
36 -
37 -
00 software 4 4
01 software 5 5
02 software 6 6
03 software 7 7
04 TC02/TC15 1
05 TC59D 1
06 drum 1 PDP-9 only
07 RB09 1 PDP-9 only
10 paper tape reader 2
11 real time clock 3
12 power fail 0
13 memory parity 0
14 display 2
15 card reader 2
16 line printer 2
17 A/D converter 0
20 interprocessor buffer 3
21 360 link 3 PDP-9 only
22 data phone 2 PDP-15 only
23 RF09/RF15 1
24 RP15 1 PDP-15 only
25 plotter 1 PDP-15 only
26 -
27 -
30 -
31 -
32 -
33 -
34 LT15 TTO 3 PDP-15 only
35 LT15 TTI 3 PDP-15 only
36 -
37 -
On the PDP-9, any API level active masks PI, and PI does not mask API.
On the PDP-15, only the hardware API levels active mask PI, and PI masks
the API software levels. */
#define API_ML0 0200 /* API masks: level 0 */
#define API_ML1 0100
#define API_ML2 0040
#define API_ML3 0020
#define API_ML4 0010
#define API_ML5 0004
#define API_ML6 0002
#define API_ML7 0001 /* level 7 */
#define API_ML0 0200 /* API masks: level 0 */
#define API_ML1 0100
#define API_ML2 0040
#define API_ML3 0020
#define API_ML4 0010
#define API_ML5 0004
#define API_ML6 0002
#define API_ML7 0001 /* level 7 */
#if defined (PDP9) /* levels which mask PI */
#define API_MASKPI (API_ML0|API_ML1|API_ML2|API_ML3|API_ML4|API_ML5|API_ML6|API_ML7)
#if defined (PDP9) /* levels which mask PI */
#define API_MASKPI (API_ML0|API_ML1|API_ML2|API_ML3|API_ML4|API_ML5|API_ML6|API_ML7)
#else
#define API_MASKPI (API_ML0|API_ML1|API_ML2|API_ML3)
#define API_MASKPI (API_ML0|API_ML1|API_ML2|API_ML3)
#endif
#define API_HLVL 4 /* hwre levels */
#define ACH_SWRE 040 /* swre int vec */
#define API_HLVL 4 /* hwre levels */
#define ACH_SWRE 040 /* swre int vec */
/* API level 0 */
#define INT_V_PWRFL 0 /* powerfail */
#define INT_V_PWRFL 0 /* powerfail */
#define INT_PWRFL (1 << INT_V_PWRFL)
#define INT_PWRFL (1 << INT_V_PWRFL)
#define API_PWRFL 0
#define API_PWRFL 0
#define ACH_PWRFL 052
#define ACH_PWRFL 052
/* API level 1 */
#define INT_V_DTA 0 /* DECtape */
#define INT_V_MTA 1 /* magtape */
#define INT_V_DRM 2 /* drum */
#define INT_V_RF 3 /* fixed head disk */
#define INT_V_RP 4 /* disk pack */
#define INT_V_RB 5 /* RB disk */
#define INT_V_DTA 0 /* DECtape */
#define INT_V_MTA 1 /* magtape */
#define INT_V_DRM 2 /* drum */
#define INT_V_RF 3 /* fixed head disk */
#define INT_V_RP 4 /* disk pack */
#define INT_V_RB 5 /* RB disk */
#define INT_DTA (1 << INT_V_DTA)
#define INT_MTA (1 << INT_V_MTA)
#define INT_DRM (1 << INT_V_DRM)
#define INT_RF (1 << INT_V_RF)
#define INT_RP (1 << INT_V_RP)
#define INT_RB (1 << INT_V_RB)
#define INT_DTA (1 << INT_V_DTA)
#define INT_MTA (1 << INT_V_MTA)
#define INT_DRM (1 << INT_V_DRM)
#define INT_RF (1 << INT_V_RF)
#define INT_RP (1 << INT_V_RP)
#define INT_RB (1 << INT_V_RB)
#define API_DTA 1
#define API_MTA 1
#define API_DRM 1
#define API_RF 1
#define API_RP 1
#define API_RB 1
#define API_DTA 1
#define API_MTA 1
#define API_DRM 1
#define API_RF 1
#define API_RP 1
#define API_RB 1
#define ACH_DTA 044
#define ACH_MTA 045
#define ACH_DRM 046
#define ACH_RB 047
#define ACH_RF 063
#define ACH_RP 064
#define ACH_DTA 044
#define ACH_MTA 045
#define ACH_DRM 046
#define ACH_RB 047
#define ACH_RF 063
#define ACH_RP 064
/* API level 2 */
#define INT_V_PTR 0 /* paper tape reader */
#define INT_V_LPT 1 /* line printer */
#define INT_V_LPTSPC 2 /* line printer spc */
#define INT_V_PTR 0 /* paper tape reader */
#define INT_V_LPT 1 /* line printer */
#define INT_V_LPTSPC 2 /* line printer spc */
#define INT_PTR (1 << INT_V_PTR)
#define INT_LPT (1 << INT_V_LPT)
#define INT_LPTSPC (1 << INT_V_LPTSPC)
#define INT_PTR (1 << INT_V_PTR)
#define INT_LPT (1 << INT_V_LPT)
#define INT_LPTSPC (1 << INT_V_LPTSPC)
#define API_PTR 2
#define API_LPT 2
#define API_LPTSPC 2
#define API_PTR 2
#define API_LPT 2
#define API_LPTSPC 2
#define ACH_PTR 050
#define ACH_LPT 056
#define ACH_PTR 050
#define ACH_LPT 056
/* API level 3 */
#define INT_V_CLK 0 /* clock */
#define INT_V_TTI1 1 /* LT15 keyboard */
#define INT_V_TTO1 2 /* LT15 output */
#define INT_V_CLK 0 /* clock */
#define INT_V_TTI1 1 /* LT15 keyboard */
#define INT_V_TTO1 2 /* LT15 output */
#define INT_CLK (1 << INT_V_CLK)
#define INT_TTI1 (1 << INT_V_TTI1)
#define INT_TTO1 (1 << INT_V_TTO1)
#define INT_CLK (1 << INT_V_CLK)
#define INT_TTI1 (1 << INT_V_TTI1)
#define INT_TTO1 (1 << INT_V_TTO1)
#define API_CLK 3
#define API_TTI1 3
#define API_TTO1 3
#define API_CLK 3
#define API_TTI1 3
#define API_TTO1 3
#define ACH_CLK 051
#define ACH_TTI1 075
#define ACH_TTO1 074
#define ACH_CLK 051
#define ACH_TTI1 075
#define ACH_TTO1 074
/* PI level */
#define INT_V_TTI 0 /* console keyboard */
#define INT_V_TTO 1 /* console output */
#define INT_V_PTP 2 /* paper tape punch */
#define INT_V_TTI 0 /* console keyboard */
#define INT_V_TTO 1 /* console output */
#define INT_V_PTP 2 /* paper tape punch */
#define INT_TTI (1 << INT_V_TTI)
#define INT_TTO (1 << INT_V_TTO)
#define INT_PTP (1 << INT_V_PTP)
#define INT_TTI (1 << INT_V_TTI)
#define INT_TTO (1 << INT_V_TTO)
#define INT_PTP (1 << INT_V_PTP)
#define API_TTI 4 /* PI level */
#define API_TTO 4
#define API_PTP 4
#define API_TTI 4 /* PI level */
#define API_TTO 4
#define API_PTP 4
/* Interrupt macros */
#define SET_INT(dv) int_hwre[API_##dv] = int_hwre[API_##dv] | INT_##dv
#define CLR_INT(dv) int_hwre[API_##dv] = int_hwre[API_##dv] & ~INT_##dv
#define TST_INT(dv) (int_hwre[API_##dv] & INT_##dv)
#define SET_INT(dv) int_hwre[API_##dv] = int_hwre[API_##dv] | INT_##dv
#define CLR_INT(dv) int_hwre[API_##dv] = int_hwre[API_##dv] & ~INT_##dv
#define TST_INT(dv) (int_hwre[API_##dv] & INT_##dv)
/* I/O status flags for the IORS instruction
bit PDP-4 PDP-7 PDP-9 PDP-15
bit PDP-4 PDP-7 PDP-9 PDP-15
0 intr on intr on intr on intr on
1 tape rdr flag* tape rdr flag* tape rdr flag* tape rdr flag*
2 tape pun flag* tape pun flag* tape pun flag* tape pun flag*
3 keyboard flag* keyboard flag* keyboard flag* keyboard flag*
4 type out flag* type out flag* type out flag* type out flag*
5 display flag* display flag* light pen flag* light pen flag*
6 clk ovflo flag* clk ovflo flag* clk ovflo flag* clk ovflo flag*
7 clk enable flag clk enable flag clk enable flag clk enable flag
8 mag tape flag* mag tape flag* tape rdr empty* tape rdr empty*
9 card rdr col* * tape pun empty tape pun empty
10 card rdr ~busy DECtape flag* DECtape flag*
11 card rdr error magtape flag* magtape flag*
12 card rdr EOF disk pack flag*
13 card pun row* DECdisk flag* DECdisk flag*
14 card pun error lpt flag*
15 lpt flag* lpt flag* lpt flag*
16 lpt space flag* lpt error flag lpt error flag
17 drum flag* drum flag*
0 intr on intr on intr on intr on
1 tape rdr flag* tape rdr flag* tape rdr flag* tape rdr flag*
2 tape pun flag* tape pun flag* tape pun flag* tape pun flag*
3 keyboard flag* keyboard flag* keyboard flag* keyboard flag*
4 type out flag* type out flag* type out flag* type out flag*
5 display flag* display flag* light pen flag* light pen flag*
6 clk ovflo flag* clk ovflo flag* clk ovflo flag* clk ovflo flag*
7 clk enable flag clk enable flag clk enable flag clk enable flag
8 mag tape flag* mag tape flag* tape rdr empty* tape rdr empty*
9 card rdr col* * tape pun empty tape pun empty
10 card rdr ~busy DECtape flag* DECtape flag*
11 card rdr error magtape flag* magtape flag*
12 card rdr EOF disk pack flag*
13 card pun row* DECdisk flag* DECdisk flag*
14 card pun error lpt flag*
15 lpt flag* lpt flag* lpt flag*
16 lpt space flag* lpt error flag lpt error flag
17 drum flag* drum flag*
*/
#define IOS_ION 0400000 /* interrupts on */
#define IOS_PTR 0200000 /* tape reader */
#define IOS_PTP 0100000 /* tape punch */
#define IOS_TTI 0040000 /* keyboard */
#define IOS_TTO 0020000 /* terminal */
#define IOS_LPEN 0010000 /* light pen */
#define IOS_CLK 0004000 /* clock */
#define IOS_CLKON 0002000 /* clock enable */
#define IOS_DTA 0000200 /* DECtape */
#define IOS_RP 0000040 /* disk pack */
#define IOS_RF 0000020 /* fixed head disk */
#define IOS_DRM 0000001 /* drum */
#define IOS_ION 0400000 /* interrupts on */
#define IOS_PTR 0200000 /* tape reader */
#define IOS_PTP 0100000 /* tape punch */
#define IOS_TTI 0040000 /* keyboard */
#define IOS_TTO 0020000 /* terminal */
#define IOS_LPEN 0010000 /* light pen */
#define IOS_CLK 0004000 /* clock */
#define IOS_CLKON 0002000 /* clock enable */
#define IOS_DTA 0000200 /* DECtape */
#define IOS_RP 0000040 /* disk pack */
#define IOS_RF 0000020 /* fixed head disk */
#define IOS_DRM 0000001 /* drum */
#if defined (PDP4) || defined (PDP7)
#define IOS_MTA 0001000 /* magtape */
#define IOS_LPT 0000004 /* line printer */
#define IOS_LPT1 0000002 /* line printer stat */
#define IOS_MTA 0001000 /* magtape */
#define IOS_LPT 0000004 /* line printer */
#define IOS_LPT1 0000002 /* line printer stat */
#elif defined (PDP9)
#define IOS_PTRERR 0001000 /* reader empty */
#define IOS_PTPERR 0000400 /* punch empty */
#define IOS_MTA 0000100 /* magtape */
#define IOS_LPT 0000004 /* line printer */
#define IOS_LPT1 0000002 /* line printer stat */
#define IOS_PTRERR 0001000 /* reader empty */
#define IOS_PTPERR 0000400 /* punch empty */
#define IOS_MTA 0000100 /* magtape */
#define IOS_LPT 0000004 /* line printer */
#define IOS_LPT1 0000002 /* line printer stat */
#elif defined (PDP15)
#define IOS_PTRERR 0001000 /* reader empty */
#define IOS_PTPERR 0000400 /* punch empty */
#define IOS_MTA 0000100 /* magtape */
#define IOS_LPT 0000010 /* line printer */
#define IOS_LPT1 0000000 /* not used */
#define IOS_PTRERR 0001000 /* reader empty */
#define IOS_PTPERR 0000400 /* punch empty */
#define IOS_MTA 0000100 /* magtape */
#define IOS_LPT 0000010 /* line printer */
#define IOS_LPT1 0000000 /* not used */
#endif
/* Function prototypes */
@@ -491,4 +489,3 @@ t_stat set_devno (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat show_devno (FILE *st, UNIT *uptr, int32 val, void *desc);
#endif

View File

@@ -55,4 +55,4 @@ MAINDEC-15-D1CD-PB Extended memory test
Read in: 200 (ignored, binary tape)
Start: 200
Halts after printout, set SR = 30000
Breakpoint: 563 for one pass
Breakpoint: 563 for one pass

View File

@@ -1,14 +1,14 @@
To: Users
From: Bob Supnik
Subj: 18b PDP Simulator Usage
Date: 15-Nov-2004
Date: 01-Jul-2005
COPYRIGHT NOTICE
The following copyright notice applies to both the SIMH source and binary:
Original code published in 1993-2004, written by Robert M Supnik
Copyright (c) 1993-2004, Robert M Supnik
Original code published in 1993-2005, written by Robert M Supnik
Copyright (c) 1993-2005, 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,8 +27,8 @@ The following copyright notice applies to both the SIMH source and binary:
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
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.
This memorandum documents the PDP-4, PDP-7, PDP-9, and PDP-15 simulators.
@@ -569,8 +569,7 @@ or a DETACH TTIX command.
The SHOW TTIX CONNECTIONS command displays the current connections to the
extra terminals. The SHOW TTIX STATISTICS command displays statistics for
active connections. The SET TTIX DISCONNECT=linenumber disconnects the
specified line.
active connections. The SET TTIXn DISCONNECT command disconnects line n.
The input device (TTIX) implements these registers:

View File

@@ -1,6 +1,6 @@
/* pdp18b_drm.c: drum/fixed head disk simulator
Copyright (c) 1993-2004, Robert M Supnik
Copyright (c) 1993-2005, 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"),
@@ -19,23 +19,23 @@
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
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.
drm (PDP-4,PDP-7) Type 24 serial drum
drm (PDP-4,PDP-7) Type 24 serial drum
14-Jan-04 RMS Revised IO device call interface
26-Oct-03 RMS Cleaned up buffer copy code
05-Dec-02 RMS Updated from Type 24 documentation
22-Nov-02 RMS Added PDP-4 support
05-Feb-02 RMS Added DIB, device number support
03-Feb-02 RMS Fixed bug in reset routine (found by Robert Alan Byer)
06-Jan-02 RMS Revised enable/disable support
25-Nov-01 RMS Revised interrupt structure
10-Jun-01 RMS Cleaned up IOT decoding to reflect hardware
26-Apr-01 RMS Added device enable/disable support
14-Apr-99 RMS Changed t_addr to unsigned
14-Jan-04 RMS Revised IO device call interface
26-Oct-03 RMS Cleaned up buffer copy code
05-Dec-02 RMS Updated from Type 24 documentation
22-Nov-02 RMS Added PDP-4 support
05-Feb-02 RMS Added DIB, device number support
03-Feb-02 RMS Fixed bug in reset routine (found by Robert Alan Byer)
06-Jan-02 RMS Revised enable/disable support
25-Nov-01 RMS Revised interrupt structure
10-Jun-01 RMS Cleaned up IOT decoding to reflect hardware
26-Apr-01 RMS Added device enable/disable support
14-Apr-99 RMS Changed t_addr to unsigned
*/
#include "pdp18b_defs.h"
@@ -43,33 +43,33 @@
/* Constants */
#define DRM_NUMWDS 256 /* words/sector */
#define DRM_NUMSC 2 /* sectors/track */
#define DRM_NUMTR 256 /* tracks/drum */
#define DRM_NUMDK 1 /* drum/controller */
#define DRM_NUMWDT (DRM_NUMWDS * DRM_NUMSC) /* words/track */
#define DRM_SIZE (DRM_NUMDK * DRM_NUMTR * DRM_NUMWDT) /* words/drum */
#define DRM_SMASK ((DRM_NUMTR * DRM_NUMSC) - 1) /* sector mask */
#define DRM_NUMWDS 256 /* words/sector */
#define DRM_NUMSC 2 /* sectors/track */
#define DRM_NUMTR 256 /* tracks/drum */
#define DRM_NUMDK 1 /* drum/controller */
#define DRM_NUMWDT (DRM_NUMWDS * DRM_NUMSC) /* words/track */
#define DRM_SIZE (DRM_NUMDK * DRM_NUMTR * DRM_NUMWDT) /* words/drum */
#define DRM_SMASK ((DRM_NUMTR * DRM_NUMSC) - 1) /* sector mask */
/* Parameters in the unit descriptor */
#define FUNC u4 /* function */
#define DRM_READ 000 /* read */
#define DRM_WRITE 040 /* write */
#define FUNC u4 /* function */
#define DRM_READ 000 /* read */
#define DRM_WRITE 040 /* write */
#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \
((double) DRM_NUMWDT)))
#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \
((double) DRM_NUMWDT)))
extern int32 M[];
extern int32 int_hwre[API_HLVL+1];
extern UNIT cpu_unit;
int32 drm_da = 0; /* track address */
int32 drm_ma = 0; /* memory address */
int32 drm_err = 0; /* error flag */
int32 drm_wlk = 0; /* write lock */
int32 drm_time = 10; /* inter-word time */
int32 drm_stopioe = 1; /* stop on error */
int32 drm_da = 0; /* track address */
int32 drm_ma = 0; /* memory address */
int32 drm_err = 0; /* error flag */
int32 drm_wlk = 0; /* write lock */
int32 drm_time = 10; /* inter-word time */
int32 drm_stopioe = 1; /* stop on error */
DEVICE drm_dev;
int32 drm60 (int32 dev, int32 pulse, int32 AC);
@@ -82,47 +82,52 @@ t_stat drm_boot (int32 unitno, DEVICE *dptr);
/* DRM data structures
drm_dev DRM device descriptor
drm_unit DRM unit descriptor
drm_reg DRM register list
drm_dev DRM device descriptor
drm_unit DRM unit descriptor
drm_reg DRM register list
*/
DIB drm_dib = { DEV_DRM, 3 ,&drm_iors, { &drm60, &drm61, &drm62 } };
UNIT drm_unit =
{ UDATA (&drm_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF,
DRM_SIZE) };
UNIT drm_unit = {
UDATA (&drm_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF,
DRM_SIZE)
};
REG drm_reg[] = {
{ ORDATA (DA, drm_da, 9) },
{ ORDATA (MA, drm_ma, 16) },
{ FLDATA (INT, int_hwre[API_DRM], INT_V_DRM) },
{ FLDATA (DONE, int_hwre[API_DRM], INT_V_DRM) },
{ FLDATA (ERR, drm_err, 0) },
{ ORDATA (WLK, drm_wlk, 32) },
{ DRDATA (TIME, drm_time, 24), REG_NZ + PV_LEFT },
{ FLDATA (STOP_IOE, drm_stopioe, 0) },
{ ORDATA (DEVNO, drm_dib.dev, 6), REG_HRO },
{ NULL } };
{ ORDATA (DA, drm_da, 9) },
{ ORDATA (MA, drm_ma, 16) },
{ FLDATA (INT, int_hwre[API_DRM], INT_V_DRM) },
{ FLDATA (DONE, int_hwre[API_DRM], INT_V_DRM) },
{ FLDATA (ERR, drm_err, 0) },
{ ORDATA (WLK, drm_wlk, 32) },
{ DRDATA (TIME, drm_time, 24), REG_NZ + PV_LEFT },
{ FLDATA (STOP_IOE, drm_stopioe, 0) },
{ ORDATA (DEVNO, drm_dib.dev, 6), REG_HRO },
{ NULL }
};
MTAB drm_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno },
{ 0 } };
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno },
{ 0 }
};
DEVICE drm_dev = {
"DRM", &drm_unit, drm_reg, drm_mod,
1, 8, 20, 1, 8, 18,
NULL, NULL, &drm_reset,
&drm_boot, NULL, NULL,
&drm_dib, DEV_DISABLE };
"DRM", &drm_unit, drm_reg, drm_mod,
1, 8, 20, 1, 8, 18,
NULL, NULL, &drm_reset,
&drm_boot, NULL, NULL,
&drm_dib, DEV_DISABLE
};
/* IOT routines */
int32 drm60 (int32 dev, int32 pulse, int32 AC)
{
if ((pulse & 027) == 06) { /* DRLR, DRLW */
drm_ma = AC & 0177777; /* load mem addr */
drm_unit.FUNC = pulse & DRM_WRITE; } /* save function */
if ((pulse & 027) == 06) { /* DRLR, DRLW */
drm_ma = AC & 0177777; /* load mem addr */
drm_unit.FUNC = pulse & DRM_WRITE; /* save function */
}
return AC;
}
@@ -130,16 +135,19 @@ int32 drm61 (int32 dev, int32 pulse, int32 AC)
{
int32 t;
if (pulse & 001) { /* DRSF */
if (TST_INT (DRM)) AC = AC | IOT_SKP; }
if (pulse & 002) { /* DRCF */
CLR_INT (DRM); /* clear done */
drm_err = 0; } /* clear error */
if (pulse & 004) { /* DRSS */
drm_da = AC & DRM_SMASK; /* load sector # */
t = ((drm_da % DRM_NUMSC) * DRM_NUMWDS) - GET_POS (drm_time);
if (t <= 0) t = t + DRM_NUMWDT; /* wrap around? */
sim_activate (&drm_unit, t * drm_time); } /* schedule op */
if (pulse & 001) { /* DRSF */
if (TST_INT (DRM)) AC = AC | IOT_SKP;
}
if (pulse & 002) { /* DRCF */
CLR_INT (DRM); /* clear done */
drm_err = 0; /* clear error */
}
if (pulse & 004) { /* DRSS */
drm_da = AC & DRM_SMASK; /* load sector # */
t = ((drm_da % DRM_NUMSC) * DRM_NUMWDS) - GET_POS (drm_time);
if (t <= 0) t = t + DRM_NUMWDT; /* wrap around? */
sim_activate (&drm_unit, t * drm_time); /* schedule op */
}
return AC;
}
@@ -147,17 +155,19 @@ int32 drm62 (int32 dev, int32 pulse, int32 AC)
{
int32 t;
if (pulse & 001) { /* DRSN */
if (drm_err == 0) AC = AC | IOT_SKP; }
if (pulse & 004) { /* DRCS */
CLR_INT (DRM); /* clear done */
drm_err = 0; /* clear error */
t = ((drm_da % DRM_NUMSC) * DRM_NUMWDS) - GET_POS (drm_time);
if (t <= 0) t = t + DRM_NUMWDT; /* wrap around? */
sim_activate (&drm_unit, t * drm_time); } /* schedule op */
if (pulse & 001) { /* DRSN */
if (drm_err == 0) AC = AC | IOT_SKP;
}
if (pulse & 004) { /* DRCS */
CLR_INT (DRM); /* clear done */
drm_err = 0; /* clear error */
t = ((drm_da % DRM_NUMSC) * DRM_NUMWDS) - GET_POS (drm_time);
if (t <= 0) t = t + DRM_NUMWDT; /* wrap around? */
sim_activate (&drm_unit, t * drm_time); /* schedule op */
}
return AC;
}
/* Unit service
This code assumes the entire drum is buffered.
@@ -169,33 +179,38 @@ int32 i;
uint32 da;
int32 *fbuf = uptr->filebuf;
if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
drm_err = 1; /* set error */
SET_INT (DRM); /* set done */
return IORETURN (drm_stopioe, SCPE_UNATT); }
if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
drm_err = 1; /* set error */
SET_INT (DRM); /* set done */
return IORETURN (drm_stopioe, SCPE_UNATT);
}
da = drm_da * DRM_NUMWDS; /* compute dev addr */
for (i = 0; i < DRM_NUMWDS; i++, da++) { /* do transfer */
if (uptr->FUNC == DRM_READ) { /* read? */
if (MEM_ADDR_OK (drm_ma)) /* if !nxm */
M[drm_ma] = fbuf[da]; } /* read word */
else { /* write */
if ((drm_wlk >> (drm_da >> 4)) & 1) drm_err = 1;
else { /* not locked */
fbuf[da] = M[drm_ma]; /* write word */
if (da >= uptr->hwmark) uptr->hwmark = da + 1; } }
drm_ma = (drm_ma + 1) & 0177777; } /* incr mem addr */
drm_da = (drm_da + 1) & DRM_SMASK; /* incr dev addr */
SET_INT (DRM); /* set done */
da = drm_da * DRM_NUMWDS; /* compute dev addr */
for (i = 0; i < DRM_NUMWDS; i++, da++) { /* do transfer */
if (uptr->FUNC == DRM_READ) { /* read? */
if (MEM_ADDR_OK (drm_ma)) /* if !nxm */
M[drm_ma] = fbuf[da]; /* read word */
}
else { /* write */
if ((drm_wlk >> (drm_da >> 4)) & 1) drm_err = 1;
else { /* not locked */
fbuf[da] = M[drm_ma]; /* write word */
if (da >= uptr->hwmark) uptr->hwmark = da + 1;
}
}
drm_ma = (drm_ma + 1) & 0177777; /* incr mem addr */
}
drm_da = (drm_da + 1) & DRM_SMASK; /* incr dev addr */
SET_INT (DRM); /* set done */
return SCPE_OK;
}
/* Reset routine */
t_stat drm_reset (DEVICE *dptr)
{
drm_da = drm_ma = drm_err = 0;
CLR_INT (DRM); /* clear done */
CLR_INT (DRM); /* clear done */
sim_cancel (&drm_unit);
return SCPE_OK;
}
@@ -213,20 +228,20 @@ return (TST_INT (DRM)? IOS_DRM: 0);
#define BOOT_LEN (sizeof (boot_rom) / sizeof (int))
static const int32 boot_rom[] = {
0750000, /* CLA ; dev, mem addr */
0706006, /* DRLR ; load ma */
0706106, /* DRSS ; load da, start */
0706101, /* DRSF ; wait for done */
0602003, /* JMP .-1 */
0600000 /* JMP 0 ; enter boot */
};
0750000, /* CLA ; dev, mem addr */
0706006, /* DRLR ; load ma */
0706106, /* DRSS ; load da, start */
0706101, /* DRSF ; wait for done */
0602003, /* JMP .-1 */
0600000 /* JMP 0 ; enter boot */
};
t_stat drm_boot (int32 unitno, DEVICE *dptr)
{
int32 i;
extern int32 PC;
if (drm_dib.dev != DEV_DRM) return STOP_NONSTD; /* non-std addr? */
if (drm_dib.dev != DEV_DRM) return STOP_NONSTD; /* non-std addr? */
for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i];
PC = BOOT_START;
return SCPE_OK;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -19,47 +19,48 @@
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
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.
mt (PDP-9) TC59 magtape
(PDP-15) TC59D magtape
mt (PDP-9) TC59 magtape
(PDP-15) TC59D magtape
18-Mar-05 RMS Added attached test to detach routine
14-Jan-04 RMS Revised IO device call interface
25-Apr-03 RMS Revised for extended file support
28-Mar-03 RMS Added multiformat support
04-Mar-03 RMS Fixed bug in MTTR
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
Revamped error recovery
28-Aug-02 RMS Added end of medium support
30-May-02 RMS Widened POS to 32b
22-Apr-02 RMS Added maximum record length test
06-Jan-02 RMS Revised enabled/disable support
29-Nov-01 RMS Added read only unit support
25-Nov-01 RMS Revised interrupt structure
Changed UST, POS, FLG to arrays
26-Apr-01 RMS Added device enable/disable support
15-Feb-01 RMS Fixed 3-cycle data break sequence
04-Oct-98 RMS V2.4 magtape format
22-Jan-97 RMS V2.3 magtape format
29-Jun-96 RMS Added unit enable/disable support
16-Aug-05 RMS Fixed C++ declaration and cast problems
18-Mar-05 RMS Added attached test to detach routine
14-Jan-04 RMS Revised IO device call interface
25-Apr-03 RMS Revised for extended file support
28-Mar-03 RMS Added multiformat support
04-Mar-03 RMS Fixed bug in MTTR
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
Revamped error recovery
28-Aug-02 RMS Added end of medium support
30-May-02 RMS Widened POS to 32b
22-Apr-02 RMS Added maximum record length test
06-Jan-02 RMS Revised enabled/disable support
29-Nov-01 RMS Added read only unit support
25-Nov-01 RMS Revised interrupt structure
Changed UST, POS, FLG to arrays
26-Apr-01 RMS Added device enable/disable support
15-Feb-01 RMS Fixed 3-cycle data break sequence
04-Oct-98 RMS V2.4 magtape format
22-Jan-97 RMS V2.3 magtape format
29-Jun-96 RMS Added unit enable/disable support
Magnetic tapes are represented as a series of variable records
of the form:
32b byte count
byte 0
byte 1
:
byte n-2
byte n-1
32 byte count
32b byte count
byte 0
byte 1
:
byte n-2
byte n-1
32 byte count
If the byte count is odd, the record is padded with an extra byte
of junk. File marks are represented by a byte count of 0.
@@ -68,69 +69,69 @@
#include "pdp18b_defs.h"
#include "sim_tape.h"
#define MT_NUMDR 8 /* #drives */
#define USTAT u3 /* unit status */
#define MT_MAXFR (1 << 16) /* max record length */
#define MT_WC 032 /* word count */
#define MT_CA 033 /* current addr */
#define WC_SIZE (1 << 12) /* max word count */
#define WC_MASK (WC_SIZE - 1)
#define MT_NUMDR 8 /* #drives */
#define USTAT u3 /* unit status */
#define MT_MAXFR (1 << 16) /* max record length */
#define MT_WC 032 /* word count */
#define MT_CA 033 /* current addr */
#define WC_SIZE (1 << 12) /* max word count */
#define WC_MASK (WC_SIZE - 1)
/* Command/unit - mt_cu */
#define CU_V_UNIT 15 /* unit */
#define CU_M_UNIT 07
#define CU_PARITY 0040000 /* parity select */
#define CU_DUMP 0020000 /* dump mode */
#define CU_ERASE 0010000 /* ext rec gap */
#define CU_V_CMD 9 /* command */
#define CU_M_CMD 07
#define FN_NOP 00
#define FN_REWIND 01
#define FN_READ 02
#define FN_CMPARE 03
#define FN_WRITE 04
#define FN_WREOF 05
#define FN_SPACEF 06
#define FN_SPACER 07
#define CU_IE 0000400 /* interrupt enable */
#define CU_V_TYPE 6 /* drive type */
#define CU_M_TYPE 03
#define TY_9TK 3
#define GET_UNIT(x) (((x) >> CU_V_UNIT) & CU_M_UNIT)
#define GET_CMD(x) (((x) >> CU_V_CMD) & CU_M_CMD)
#define GET_TYPE(x) (((x) >> CU_V_TYPE) & CU_M_TYPE)
#define PACKED(x) (((x) & CU_DUMP) || (GET_TYPE (x) != TY_9TK))
#define CU_V_UNIT 15 /* unit */
#define CU_M_UNIT 07
#define CU_PARITY 0040000 /* parity select */
#define CU_DUMP 0020000 /* dump mode */
#define CU_ERASE 0010000 /* ext rec gap */
#define CU_V_CMD 9 /* command */
#define CU_M_CMD 07
#define FN_NOP 00
#define FN_REWIND 01
#define FN_READ 02
#define FN_CMPARE 03
#define FN_WRITE 04
#define FN_WREOF 05
#define FN_SPACEF 06
#define FN_SPACER 07
#define CU_IE 0000400 /* interrupt enable */
#define CU_V_TYPE 6 /* drive type */
#define CU_M_TYPE 03
#define TY_9TK 3
#define GET_UNIT(x) (((x) >> CU_V_UNIT) & CU_M_UNIT)
#define GET_CMD(x) (((x) >> CU_V_CMD) & CU_M_CMD)
#define GET_TYPE(x) (((x) >> CU_V_TYPE) & CU_M_TYPE)
#define PACKED(x) (((x) & CU_DUMP) || (GET_TYPE (x) != TY_9TK))
/* Status - stored in mt_sta or (*) uptr->USTAT */
#define STA_ERR 0400000 /* error */
#define STA_REW 0200000 /* *rewinding */
#define STA_BOT 0100000 /* *start of tape */
#define STA_ILL 0040000 /* illegal cmd */
#define STA_PAR 0020000 /* parity error */
#define STA_EOF 0010000 /* *end of file */
#define STA_EOT 0004000 /* *end of tape */
#define STA_CPE 0002000 /* compare error */
#define STA_RLE 0001000 /* rec lnt error */
#define STA_DLT 0000400 /* data late */
#define STA_BAD 0000200 /* bad tape */
#define STA_DON 0000100 /* done */
#define STA_ERR 0400000 /* error */
#define STA_REW 0200000 /* *rewinding */
#define STA_BOT 0100000 /* *start of tape */
#define STA_ILL 0040000 /* illegal cmd */
#define STA_PAR 0020000 /* parity error */
#define STA_EOF 0010000 /* *end of file */
#define STA_EOT 0004000 /* *end of tape */
#define STA_CPE 0002000 /* compare error */
#define STA_RLE 0001000 /* rec lnt error */
#define STA_DLT 0000400 /* data late */
#define STA_BAD 0000200 /* bad tape */
#define STA_DON 0000100 /* done */
#define STA_CLR 0000077 /* always clear */
#define STA_DYN (STA_REW | STA_BOT | STA_EOF | STA_EOT)
/* kept in USTAT */
#define STA_CLR 0000077 /* always clear */
#define STA_DYN (STA_REW | STA_BOT | STA_EOF | STA_EOT)
/* kept in USTAT */
extern int32 M[];
extern int32 int_hwre[API_HLVL+1];
extern UNIT cpu_unit;
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 */
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 */
int32 mt_log = 0;
uint8 *mtxb = NULL; /* transfer buffer */
uint8 *mtxb = NULL; /* transfer buffer */
DEVICE mt_dev;
int32 mt (int32 dev, int32 pulse, int32 dat);
@@ -145,55 +146,59 @@ UNIT *mt_busy (void);
/* MT data structures
mt_dev MT device descriptor
mt_unit MT unit list
mt_reg MT register list
mt_mod MT modifier list
mt_dev MT device descriptor
mt_unit MT unit list
mt_reg MT register list
mt_mod MT modifier list
*/
DIB mt_dib = { DEV_MT, 1, &mt_iors, { &mt } };
UNIT mt_unit[] = {
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) } };
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE, 0) }
};
REG mt_reg[] = {
{ ORDATA (STA, mt_sta, 18) },
{ ORDATA (CMD, mt_cu, 18) },
{ ORDATA (WC, M[MT_WC], 18) },
{ ORDATA (CA, M[MT_CA], 18) },
{ FLDATA (INT, int_hwre[API_MTA], INT_V_MTA) },
{ FLDATA (STOP_IOE, mt_stopioe, 0) },
{ DRDATA (TIME, mt_time, 24), PV_LEFT },
{ URDATA (UST, mt_unit[0].USTAT, 8, 16, 0, MT_NUMDR, 0) },
{ URDATA (POS, mt_unit[0].pos, 10, T_ADDR_W, 0,
MT_NUMDR, PV_LEFT | REG_RO) },
{ FLDATA (LOG, mt_log, 0), REG_HIDDEN },
{ ORDATA (DEVNO, mt_dib.dev, 6), REG_HRO },
{ NULL } };
{ ORDATA (STA, mt_sta, 18) },
{ ORDATA (CMD, mt_cu, 18) },
{ ORDATA (WC, M[MT_WC], 18) },
{ ORDATA (CA, M[MT_CA], 18) },
{ FLDATA (INT, int_hwre[API_MTA], INT_V_MTA) },
{ FLDATA (STOP_IOE, mt_stopioe, 0) },
{ DRDATA (TIME, mt_time, 24), PV_LEFT },
{ URDATA (UST, mt_unit[0].USTAT, 8, 16, 0, MT_NUMDR, 0) },
{ URDATA (POS, mt_unit[0].pos, 10, T_ADDR_W, 0,
MT_NUMDR, PV_LEFT | REG_RO) },
{ FLDATA (LOG, mt_log, 0), REG_HIDDEN },
{ ORDATA (DEVNO, mt_dib.dev, 6), REG_HRO },
{ NULL }
};
MTAB mt_mod[] = {
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
{ MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
&set_devno, &show_devno, NULL },
{ 0 } };
{ MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL },
{ MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL },
{ MTAB_XTD|MTAB_VUN, 0, "FORMAT", "FORMAT",
&sim_tape_set_fmt, &sim_tape_show_fmt, NULL },
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
&set_devno, &show_devno, NULL },
{ 0 }
};
DEVICE mt_dev = {
"MT", mt_unit, mt_reg, mt_mod,
MT_NUMDR, 10, 31, 1, 8, 8,
NULL, NULL, &mt_reset,
NULL, &mt_attach, &mt_detach,
&mt_dib, DEV_DISABLE };
"MT", mt_unit, mt_reg, mt_mod,
MT_NUMDR, 10, 31, 1, 8, 8,
NULL, NULL, &mt_reset,
NULL, &mt_attach, &mt_detach,
&mt_dib, DEV_DISABLE
};
/* IOT routine */
int32 mt (int32 dev, int32 pulse, int32 dat)
@@ -201,49 +206,52 @@ int32 mt (int32 dev, int32 pulse, int32 dat)
int32 f, sb;
UNIT *uptr;
uptr = mt_dev.units + GET_UNIT (mt_cu); /* get unit */
mt_updcsta (uptr, 0); /* update status */
sb = pulse & 060; /* subop */
uptr = mt_dev.units + GET_UNIT (mt_cu); /* get unit */
mt_updcsta (uptr, 0); /* update status */
sb = pulse & 060; /* subop */
if (pulse & 01) {
if ((sb == 000) && (uptr->flags & UNIT_ATT) && /* MTTR */
!sim_is_active (uptr))
dat = IOT_SKP | dat;
else if ((sb == 020) && !mt_busy ()) /* MTCR */
dat = IOT_SKP | dat;
else if ((sb == 040) && (mt_sta & (STA_ERR | STA_DON))) /* MTSF */
dat = IOT_SKP | dat;
}
if ((sb == 000) && (uptr->flags & UNIT_ATT) && /* MTTR */
!sim_is_active (uptr))
dat = IOT_SKP | dat;
else if ((sb == 020) && !mt_busy ()) /* MTCR */
dat = IOT_SKP | dat;
else if ((sb == 040) && (mt_sta & (STA_ERR | STA_DON))) /* MTSF */
dat = IOT_SKP | dat;
}
if ((pulse & 06) && mt_log)
printf ("[MT%d: IOT=%o, AC=%o, sta=%o]\n",
GET_UNIT (mt_cu), 0707300 + pulse, dat, mt_sta);
printf ("[MT%d: IOT=%o, AC=%o, sta=%o]\n",
GET_UNIT (mt_cu), 0707300 + pulse, dat, mt_sta);
if (pulse & 02) {
if (sb == 000) dat = dat | (mt_cu & 0777700); /* MTRC */
else if (sb == 020) { /* MTAF, MTLC */
if (!mt_busy ()) mt_cu = mt_sta = 0; /* if not busy, clr */
mt_sta = mt_sta & ~(STA_ERR | STA_DON); } /* clear flags */
else if (sb == 040) dat = dat | mt_sta; /* MTRS */
}
if (sb == 000) dat = dat | (mt_cu & 0777700); /* MTRC */
else if (sb == 020) { /* MTAF, MTLC */
if (!mt_busy ()) mt_cu = mt_sta = 0; /* if not busy, clr */
mt_sta = mt_sta & ~(STA_ERR | STA_DON); /* clear flags */
}
else if (sb == 040) dat = dat | mt_sta; /* MTRS */
}
if (pulse & 04) {
if (sb == 000) { /* MTGO */
f = GET_CMD (mt_cu); /* get function */
if (mt_busy () ||
sim_is_active (uptr) ||
(f == FN_NOP) ||
(((f == FN_SPACER) || (f == FN_REWIND)) && (uptr->USTAT & STA_BOT)) ||
(((f == FN_WRITE) || (f == FN_WREOF)) && sim_tape_wrp (uptr)) ||
((uptr->flags & UNIT_ATT) == 0))
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 */
sim_activate (uptr, mt_time); } } /* start io */
if (sb == 020) /* MTCM, MTLC */
mt_cu = (mt_cu & 0770700) | (dat & 0777700); /* load status */
}
mt_updcsta (mt_dev.units + GET_UNIT (mt_cu), 0); /* update status */
if (sb == 000) { /* MTGO */
f = GET_CMD (mt_cu); /* get function */
if (mt_busy () ||
sim_is_active (uptr) ||
(f == FN_NOP) ||
(((f == FN_SPACER) || (f == FN_REWIND)) && (uptr->USTAT & STA_BOT)) ||
(((f == FN_WRITE) || (f == FN_WREOF)) && sim_tape_wrp (uptr)) ||
((uptr->flags & UNIT_ATT) == 0))
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 */
sim_activate (uptr, mt_time); /* start io */
}
}
if (sb == 020) /* MTCM, MTLC */
mt_cu = (mt_cu & 0770700) | (dat & 0777700); /* load status */
}
mt_updcsta (mt_dev.units + GET_UNIT (mt_cu), 0); /* update status */
return dat;
}
/* Unit service
If rewind done, reposition to start of tape, set status
@@ -257,123 +265,132 @@ int32 wc, xma;
t_mtrlnt tbc, cbc;
t_stat st, r = SCPE_OK;
u = uptr - mt_dev.units; /* get unit number */
f = GET_CMD (mt_cu); /* get command */
wc = WC_SIZE - (M[MT_WC] & WC_MASK); /* word count is 12b */
u = (int32) (uptr - mt_dev.units); /* get unit number */
f = GET_CMD (mt_cu); /* get command */
wc = WC_SIZE - (M[MT_WC] & WC_MASK); /* word count is 12b */
if (uptr->USTAT & STA_REW) { /* rewind? */
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);
if (mt_log) printf ("[MT%d: rewind complete, sta=%o]\n", u, mt_sta);
return SCPE_OK; }
if (uptr->USTAT & STA_REW) { /* rewind? */
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);
if (mt_log) printf ("[MT%d: rewind complete, sta=%o]\n", u, mt_sta);
return SCPE_OK;
}
if ((uptr->flags & UNIT_ATT) == 0) { /* if not attached */
mt_updcsta (uptr, STA_ILL); /* illegal operation */
return IORETURN (mt_stopioe, SCPE_UNATT); }
if ((uptr->flags & UNIT_ATT) == 0) { /* if not attached */
mt_updcsta (uptr, STA_ILL); /* illegal operation */
return IORETURN (mt_stopioe, SCPE_UNATT);
}
switch (f) { /* case on function */
/* Unit service, continued */
switch (f) { /* case on function */
case FN_READ: /* read */
case FN_CMPARE: /* read/compare */
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; }
cbc = PACKED (mt_cu)? wc * 3: wc * 2; /* expected bc */
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); }
for (i = p = 0; i < wc; i++) { /* copy buffer */
M[MT_WC] = (M[MT_WC] + 1) & DMASK; /* inc WC, CA */
M[MT_CA] = (M[MT_CA] + 1) & DMASK;
xma = M[MT_CA] & AMASK;
if (PACKED (mt_cu)) { /* packed? */
c1 = mtxb[p++] & 077;
c2 = mtxb[p++] & 077;
c3 = mtxb[p++] & 077;
c = (c1 << 12) | (c2 << 6) | c3; }
else {
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)? DMASK: 0177777)))) {
mt_updcsta (uptr, STA_CPE);
break; } }
break;
case FN_READ: /* read */
case FN_CMPARE: /* read/compare */
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;
}
cbc = PACKED (mt_cu)? wc * 3: wc * 2; /* expected bc */
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);
}
for (i = p = 0; i < wc; i++) { /* copy buffer */
M[MT_WC] = (M[MT_WC] + 1) & DMASK; /* inc WC, CA */
M[MT_CA] = (M[MT_CA] + 1) & DMASK;
xma = M[MT_CA] & AMASK;
if (PACKED (mt_cu)) { /* packed? */
c1 = mtxb[p++] & 077;
c2 = mtxb[p++] & 077;
c3 = mtxb[p++] & 077;
c = (c1 << 12) | (c2 << 6) | c3;
}
else {
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)? DMASK: 0177777)))) {
mt_updcsta (uptr, STA_CPE);
break;
}
} /* end for */
break;
case FN_WRITE: /* write */
tbc = PACKED (mt_cu)? wc * 3: wc * 2;
xma = M[MT_CA] & AMASK; /* get mem addr */
for (i = p = 0; i < wc; i++) { /* copy buf to tape */
xma = (xma + 1) & AMASK; /* incr mem addr */
if (PACKED (mt_cu)) { /* packed? */
mtxb[p++] = (M[xma] >> 12) & 077;
mtxb[p++] = (M[xma] >> 6) & 077;
mtxb[p++] = M[xma] & 077; }
else {
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) & DMASK; /* 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_WRITE: /* write */
tbc = PACKED (mt_cu)? wc * 3: wc * 2;
xma = M[MT_CA] & AMASK; /* get mem addr */
for (i = p = 0; i < wc; i++) { /* copy buf to tape */
xma = (xma + 1) & AMASK; /* incr mem addr */
if (PACKED (mt_cu)) { /* packed? */
mtxb[p++] = (M[xma] >> 12) & 077;
mtxb[p++] = (M[xma] >> 6) & 077;
mtxb[p++] = M[xma] & 077;
}
else {
mtxb[p++] = (M[xma] >> 8) & 0377;
mtxb[p++] = M[xma] & 0377;
}
} /* end for */
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) & DMASK; /* advance mem addr */
M[MT_WC] = 0; /* clear word cnt */
}
mt_cu = mt_cu & ~CU_ERASE; /* clear erase flag */
break;
case FN_WREOF:
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_WREOF:
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) & DMASK; /* inc WC */
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_SPACEF: /* space forward */
do {
M[MT_WC] = (M[MT_WC] + 1) & DMASK; /* inc WC */
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) & DMASK; /* inc WC */
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 */
case FN_SPACER: /* space reverse */
do {
M[MT_WC] = (M[MT_WC] + 1) & DMASK; /* inc WC */
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); /* set done */
mt_updcsta (uptr, STA_DON); /* set done */
if (mt_log) printf ("MT%d: fnc=%d done, ma=%o, wc=%o, sta=%o]\n",
u, f, M[MT_CA], M[MT_WC], mt_sta);
u, f, M[MT_CA], M[MT_WC], mt_sta);
return r;
}
/* Update controller status */
int32 mt_updcsta (UNIT *uptr, int32 news)
{
mt_sta = (mt_sta & ~(STA_DYN | STA_CLR)) |
(uptr->USTAT & STA_DYN) | news;
(uptr->USTAT & STA_DYN) | news;
if ((mt_sta & (STA_ERR | STA_DON)) && (mt_cu & CU_IE))
SET_INT (MTA);
else CLR_INT (MTA); /* int request */
SET_INT (MTA);
else CLR_INT (MTA); /* int request */
return mt_sta;
}
@@ -384,10 +401,11 @@ UNIT *mt_busy (void)
int32 u;
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; }
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 NULL;
}
@@ -396,38 +414,48 @@ return NULL;
t_stat mt_map_err (UNIT *uptr, t_stat st)
{
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 end 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; }
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 end 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 */
t_stat mt_reset (DEVICE *dptr)
@@ -436,14 +464,15 @@ int32 u;
UNIT *uptr;
mt_cu = mt_sta = 0;
for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */
uptr = mt_dev.units + u;
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));
for (u = 0; u < MT_NUMDR; u++) { /* loop thru units */
uptr = mt_dev.units + u;
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 = (uint8 *) calloc (MT_MAXFR, sizeof (uint8));
if (mtxb == NULL) return SCPE_MEM;
return SCPE_OK;
}
@@ -464,7 +493,7 @@ t_stat r;
r = sim_tape_attach (uptr, cptr);
if (r != SCPE_OK) return r;
uptr->USTAT = STA_BOT;
mt_updcsta (mt_dev.units + GET_UNIT (mt_cu), 0); /* update status */
mt_updcsta (mt_dev.units + GET_UNIT (mt_cu), 0); /* update status */
return r;
}
@@ -472,8 +501,8 @@ return r;
t_stat mt_detach (UNIT* uptr)
{
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */
if (!(uptr->flags & UNIT_ATT)) return SCPE_OK; /* attached? */
if (!sim_is_active (uptr)) uptr->USTAT = 0;
mt_updcsta (mt_dev.units + GET_UNIT (mt_cu), 0); /* update status */
mt_updcsta (mt_dev.units + GET_UNIT (mt_cu), 0); /* update status */
return sim_tape_detach (uptr);
}

View File

@@ -1,6 +1,6 @@
/* pdp18b_rb.c: RB09 fixed head disk simulator
Copyright (c) 2003-2004, Robert M Supnik
Copyright (c) 2003-2005, 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"),
@@ -19,23 +19,23 @@
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
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.
rb RB09 fixed head disk
rb RB09 fixed head disk
14-Jan-04 RMS Revised IO device call interface
26-Oct-03 RMS Cleaned up buffer copy code
14-Jan-04 RMS Revised IO device call interface
26-Oct-03 RMS Cleaned up buffer copy code
The RB09 is a head-per-track disk. It uses the single cycle data break
facility. To minimize overhead, the entire RB09 is buffered in memory.
Two timing parameters are provided:
rb_time Interword timing. Must be non-zero.
rb_burst Burst mode. If 0, DMA occurs cycle by cycle; otherwise,
DMA occurs in a burst.
rb_time Interword timing. Must be non-zero.
rb_burst Burst mode. If 0, DMA occurs cycle by cycle; otherwise,
DMA occurs in a burst.
*/
#include "pdp18b_defs.h"
@@ -43,51 +43,51 @@
/* Constants */
#define RB_NUMWD 64 /* words/sector */
#define RB_NUMSC 80 /* sectors/track */
#define RB_NUMTR 200 /* tracks/disk */
#define RB_WLKTR 10 /* tracks/wlock switch */
#define RB_SIZE (RB_NUMTR * RB_NUMSC * RB_NUMWD) /* words/drive */
#define RB_NUMWD 64 /* words/sector */
#define RB_NUMSC 80 /* sectors/track */
#define RB_NUMTR 200 /* tracks/disk */
#define RB_WLKTR 10 /* tracks/wlock switch */
#define RB_SIZE (RB_NUMTR * RB_NUMSC * RB_NUMWD) /* words/drive */
/* Function/status register */
#define RBS_ERR 0400000 /* error */
#define RBS_PAR 0200000 /* parity error */
#define RBS_ILA 0100000 /* ill addr error */
#define RBS_TIM 0040000 /* timing transfer */
#define RBS_NRY 0020000 /* not ready error */
#define RBS_DON 0010000 /* done */
#define RBS_IE 0004000 /* int enable */
#define RBS_BSY 0002000 /* busy */
#define RBS_WR 0001000 /* read/write */
#define RBS_XOR (RBS_IE|RBS_BSY|RBS_WR) /* set by XOR */
#define RBS_MBZ 0000777 /* always clear */
#define RBS_EFLGS (RBS_PAR|RBS_ILA|RBS_TIM|RBS_NRY) /* error flags */
#define RBS_ERR 0400000 /* error */
#define RBS_PAR 0200000 /* parity error */
#define RBS_ILA 0100000 /* ill addr error */
#define RBS_TIM 0040000 /* timing transfer */
#define RBS_NRY 0020000 /* not ready error */
#define RBS_DON 0010000 /* done */
#define RBS_IE 0004000 /* int enable */
#define RBS_BSY 0002000 /* busy */
#define RBS_WR 0001000 /* read/write */
#define RBS_XOR (RBS_IE|RBS_BSY|RBS_WR) /* set by XOR */
#define RBS_MBZ 0000777 /* always clear */
#define RBS_EFLGS (RBS_PAR|RBS_ILA|RBS_TIM|RBS_NRY) /* error flags */
/* BCD disk address */
#define RBA_V_TR 8
#define RBA_M_TR 0x1FF
#define RBA_V_SC 0
#define RBA_M_SC 0xFF
#define RBA_GETTR(x) (((x) >> RBA_V_TR) & RBA_M_TR)
#define RBA_GETSC(x) (((x) >> RBA_V_SC) & RBA_M_SC)
#define RBA_V_TR 8
#define RBA_M_TR 0x1FF
#define RBA_V_SC 0
#define RBA_M_SC 0xFF
#define RBA_GETTR(x) (((x) >> RBA_V_TR) & RBA_M_TR)
#define RBA_GETSC(x) (((x) >> RBA_V_SC) & RBA_M_SC)
#define GET_POS(x) ((int) fmod (sim_gtime () / ((double) (x)), \
((double) (RB_NUMSC * RB_NUMWD))))
#define GET_POS(x) ((int) fmod (sim_gtime () / ((double) (x)), \
((double) (RB_NUMSC * RB_NUMWD))))
extern int32 M[];
extern int32 int_hwre[API_HLVL+1];
extern UNIT cpu_unit;
int32 rb_sta = 0; /* status register */
int32 rb_da = 0; /* disk address */
int32 rb_ma = 0; /* current addr */
int32 rb_wc = 0; /* word count */
int32 rb_wlk = 0; /* write lock */
int32 rb_time = 10; /* inter-word time */
int32 rb_burst = 1; /* burst mode flag */
int32 rb_stopioe = 1; /* stop on error */
int32 rb_sta = 0; /* status register */
int32 rb_da = 0; /* disk address */
int32 rb_ma = 0; /* current addr */
int32 rb_wc = 0; /* word count */
int32 rb_wlk = 0; /* write lock */
int32 rb_time = 10; /* inter-word time */
int32 rb_burst = 1; /* burst mode flag */
int32 rb_stopioe = 1; /* stop on error */
DEVICE rb_dev;
int32 rb71 (int32 dev, int32 pulse, int32 AC);
@@ -98,44 +98,48 @@ int32 rb_make_da (int32 dat);
int32 rb_make_bcd (int32 dat);
int32 rb_set_da (int32 dat, int32 old);
int32 rb_set_bcd (int32 dat);
/* RB data structures
rb_dev RF device descriptor
rb_unit RF unit descriptor
rb_reg RF register list
rb_dev RF device descriptor
rb_unit RF unit descriptor
rb_reg RF register list
*/
DIB rb_dib = { DEV_RB, 1, NULL, { &rb71 } };
UNIT rb_unit =
{ UDATA (&rb_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF,
RB_SIZE) };
UNIT rb_unit = {
UDATA (&rb_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF,
RB_SIZE)
};
REG rb_reg[] = {
{ ORDATA (STA, rb_sta, 18) },
{ ORDATA (DA, rb_da, 20) },
{ ORDATA (WC, rb_wc, 16) },
{ ORDATA (MA, rb_ma, ADDRSIZE) },
{ FLDATA (INT, int_hwre[API_RB], INT_V_RB) },
{ ORDATA (WLK, rb_wlk, RB_NUMTR / RB_WLKTR) },
{ DRDATA (TIME, rb_time, 24), PV_LEFT + REG_NZ },
{ FLDATA (BURST, rb_burst, 0) },
{ FLDATA (STOP_IOE, rb_stopioe, 0) },
{ ORDATA (DEVNO, rb_dib.dev, 6), REG_HRO },
{ NULL } };
{ ORDATA (STA, rb_sta, 18) },
{ ORDATA (DA, rb_da, 20) },
{ ORDATA (WC, rb_wc, 16) },
{ ORDATA (MA, rb_ma, ADDRSIZE) },
{ FLDATA (INT, int_hwre[API_RB], INT_V_RB) },
{ ORDATA (WLK, rb_wlk, RB_NUMTR / RB_WLKTR) },
{ DRDATA (TIME, rb_time, 24), PV_LEFT + REG_NZ },
{ FLDATA (BURST, rb_burst, 0) },
{ FLDATA (STOP_IOE, rb_stopioe, 0) },
{ ORDATA (DEVNO, rb_dib.dev, 6), REG_HRO },
{ NULL }
};
MTAB rb_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno },
{ 0 } };
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno },
{ 0 }
};
DEVICE rb_dev = {
"RB", &rb_unit, rb_reg, rb_mod,
1, 8, 21, 1, 8, 18,
NULL, NULL, &rb_reset,
NULL, NULL, NULL,
&rb_dib, DEV_DIS | DEV_DISABLE };
"RB", &rb_unit, rb_reg, rb_mod,
1, 8, 21, 1, 8, 18,
NULL, NULL, &rb_reset,
NULL, NULL, NULL,
&rb_dib, DEV_DIS | DEV_DISABLE
};
/* IOT routines */
int32 rb71 (int32 dev, int32 pulse, int32 AC)
@@ -143,65 +147,70 @@ int32 rb71 (int32 dev, int32 pulse, int32 AC)
int32 tow, t, sb = pulse & 060;
if (pulse & 001) {
if (sb == 000) rb_sta = rb_sta & /* DBCF */
~(RBS_ERR | RBS_EFLGS | RBS_DON);
if ((sb == 020) && (rb_sta & (RBS_ERR | RBS_DON)))
AC = AC | IOT_SKP; /* DBSF */
if (sb == 040) rb_sta = 0; /* DBCS */
}
if (sb == 000) rb_sta = rb_sta & /* DBCF */
~(RBS_ERR | RBS_EFLGS | RBS_DON);
if ((sb == 020) && (rb_sta & (RBS_ERR | RBS_DON)))
AC = AC | IOT_SKP; /* DBSF */
if (sb == 040) rb_sta = 0; /* DBCS */
}
if (pulse & 002) {
if (sb == 000) AC = AC | rb_make_da (rb_da); /* DBRD */
if (sb == 020) AC = AC | rb_sta; /* DBRS */
if (sb == 040) rb_ma = AC & AMASK; /* DBLM */
}
if (sb == 000) AC = AC | rb_make_da (rb_da); /* DBRD */
if (sb == 020) AC = AC | rb_sta; /* DBRS */
if (sb == 040) rb_ma = AC & AMASK; /* DBLM */
}
if (pulse & 004) {
if (sb == 000) rb_da = rb_set_da (AC, rb_da); /* DBLD */
if (sb == 020) rb_wc = AC & 0177777; /* DBLW */
if (sb == 040) { /* DBLS */
rb_sta = (rb_sta & RBS_XOR) ^ (AC & ~RBS_MBZ);
if (rb_sta & RBS_BSY) { /* busy set? */
if (!sim_is_active (&rb_unit)) { /* schedule */
tow = rb_da % (RB_NUMSC * RB_NUMWD);
t = tow - GET_POS (rb_time);
if (t < 0) t = t + (RB_NUMSC * RB_NUMWD);
sim_activate (&rb_unit, t * rb_time); } }
else sim_cancel (&rb_unit); } /* no, stop */
}
rb_updsta (0); /* update status */
if (sb == 000) rb_da = rb_set_da (AC, rb_da); /* DBLD */
if (sb == 020) rb_wc = AC & 0177777; /* DBLW */
if (sb == 040) { /* DBLS */
rb_sta = (rb_sta & RBS_XOR) ^ (AC & ~RBS_MBZ);
if (rb_sta & RBS_BSY) { /* busy set? */
if (!sim_is_active (&rb_unit)) { /* schedule */
tow = rb_da % (RB_NUMSC * RB_NUMWD);
t = tow - GET_POS (rb_time);
if (t < 0) t = t + (RB_NUMSC * RB_NUMWD);
sim_activate (&rb_unit, t * rb_time);
}
}
else sim_cancel (&rb_unit); /* no, stop */
}
}
rb_updsta (0); /* update status */
return AC;
}
int32 rb_make_da (int32 da)
{
int32 t = da / (RB_NUMSC * RB_NUMWD); /* bin track */
int32 s = (da % (RB_NUMSC * RB_NUMWD)) / RB_NUMWD; /* bin sector */
int32 bcd_t = rb_make_bcd (t); /* bcd track */
int32 bcd_s = rb_make_bcd (s); /* bcd sector */
int32 t = da / (RB_NUMSC * RB_NUMWD); /* bin track */
int32 s = (da % (RB_NUMSC * RB_NUMWD)) / RB_NUMWD; /* bin sector */
int32 bcd_t = rb_make_bcd (t); /* bcd track */
int32 bcd_s = rb_make_bcd (s); /* bcd sector */
return (bcd_t << RBA_V_TR) | (bcd_s << RBA_V_SC);
}
int32 rb_set_da (int32 bcda, int32 old_da)
{
int32 bcd_t = RBA_GETTR (bcda); /* bcd track */
int32 bcd_s = RBA_GETSC (bcda); /* bcd sector */
int32 t = rb_set_bcd (bcd_t); /* bin track */
int32 s = rb_set_bcd (bcd_s); /* bin sector */
int32 bcd_t = RBA_GETTR (bcda); /* bcd track */
int32 bcd_s = RBA_GETSC (bcda); /* bcd sector */
int32 t = rb_set_bcd (bcd_t); /* bin track */
int32 s = rb_set_bcd (bcd_s); /* bin sector */
if ((t >= RB_NUMTR) || (t < 0) || /* invalid? */
if ((t >= RB_NUMTR) || (t < 0) || /* invalid? */
(s >= RB_NUMSC) || (s < 0)) {
rb_updsta (RBS_ILA); /* error */
return old_da; } /* don't change */
else return (((t * RB_NUMSC) + s) * RB_NUMWD); /* new da */
rb_updsta (RBS_ILA); /* error */
return old_da; /* don't change */
}
else return (((t * RB_NUMSC) + s) * RB_NUMWD); /* new da */
}
int32 rb_make_bcd (int32 bin)
{
int32 d, i, r;
for (r = i = 0; bin != 0; bin = bin / 10) { /* while nz */
d = bin % 10; /* dec digit */
r = r | (d << i); /* insert bcd */
i = i + 4; }
for (r = i = 0; bin != 0; bin = bin / 10) { /* while nz */
d = bin % 10; /* dec digit */
r = r | (d << i); /* insert bcd */
i = i + 4;
}
return r;
}
@@ -209,14 +218,15 @@ int32 rb_set_bcd (int32 bcd)
{
int32 d, i, r;
for (r = 0, i = 1; bcd != 0; bcd = bcd >> 4) { /* while nz */
d = bcd & 0xF; /* bcd digit */
if (d >= 10) return -1; /* invalid? */
r = r + (d * i); /* insert bin */
i = i * 10; }
for (r = 0, i = 1; bcd != 0; bcd = bcd >> 4) { /* while nz */
d = bcd & 0xF; /* bcd digit */
if (d >= 10) return -1; /* invalid? */
r = r + (d * i); /* insert bin */
i = i * 10;
}
return r;
}
}
/* Unit service - disk is buffered in memory */
t_stat rb_svc (UNIT *uptr)
@@ -224,31 +234,35 @@ t_stat rb_svc (UNIT *uptr)
int32 t, sw;
int32 *fbuf = uptr->filebuf;
if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
rb_updsta (RBS_NRY | RBS_DON); /* set nxd, done */
return IORETURN (rb_stopioe, SCPE_UNATT); }
if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
rb_updsta (RBS_NRY | RBS_DON); /* set nxd, done */
return IORETURN (rb_stopioe, SCPE_UNATT);
}
do { if (rb_sta & RBS_WR) { /* write? */
t = rb_da / (RB_NUMSC * RB_NUMWD); /* track */
sw = t / RB_WLKTR; /* switch */
if ((rb_wlk >> sw) & 1) { /* write locked? */
rb_updsta (RBS_ILA | RBS_DON);
break; }
else { /* not locked */
fbuf[rb_da] = M[rb_ma]; /* write word */
if (((t_addr) rb_da) >= uptr->hwmark) uptr->hwmark = rb_da + 1; } }
else if (MEM_ADDR_OK (rb_ma)) /* read, valid addr? */
M[rb_ma] = fbuf[rb_da]; /* read word */
rb_wc = (rb_wc + 1) & 0177777; /* incr word count */
rb_ma = (rb_ma + 1) & AMASK; /* incr mem addr */
rb_da = rb_da + 1; /* incr disk addr */
if (rb_da > RB_SIZE) rb_da = 0; /* disk wraparound? */
}
while ((rb_wc != 0) && (rb_burst != 0)); /* brk if wc, no brst */
do {
if (rb_sta & RBS_WR) { /* write? */
t = rb_da / (RB_NUMSC * RB_NUMWD); /* track */
sw = t / RB_WLKTR; /* switch */
if ((rb_wlk >> sw) & 1) { /* write locked? */
rb_updsta (RBS_ILA | RBS_DON);
break;
}
else { /* not locked */
fbuf[rb_da] = M[rb_ma]; /* write word */
if (((t_addr) rb_da) >= uptr->hwmark) uptr->hwmark = rb_da + 1;
}
}
else if (MEM_ADDR_OK (rb_ma)) /* read, valid addr? */
M[rb_ma] = fbuf[rb_da]; /* read word */
rb_wc = (rb_wc + 1) & 0177777; /* incr word count */
rb_ma = (rb_ma + 1) & AMASK; /* incr mem addr */
rb_da = rb_da + 1; /* incr disk addr */
if (rb_da > RB_SIZE) rb_da = 0; /* disk wraparound? */
} while ((rb_wc != 0) && (rb_burst != 0)); /* brk if wc, no brst */
if ((rb_wc != 0) && ((rb_sta & RBS_ERR) == 0)) /* more to do? */
sim_activate (&rb_unit, rb_time); /* sched next */
else rb_updsta (RBS_DON); /* set done */
if ((rb_wc != 0) && ((rb_sta & RBS_ERR) == 0)) /* more to do? */
sim_activate (&rb_unit, rb_time); /* sched next */
else rb_updsta (RBS_DON); /* set done */
return SCPE_OK;
}
@@ -256,11 +270,11 @@ return SCPE_OK;
int32 rb_updsta (int32 new)
{
rb_sta = (rb_sta | new) & ~(RBS_ERR | RBS_MBZ); /* clear err, mbz */
if (rb_sta & RBS_EFLGS) rb_sta = rb_sta | RBS_ERR; /* error? */
if (rb_sta & RBS_DON) rb_sta = rb_sta & ~RBS_BSY; /* done? clear busy */
rb_sta = (rb_sta | new) & ~(RBS_ERR | RBS_MBZ); /* clear err, mbz */
if (rb_sta & RBS_EFLGS) rb_sta = rb_sta | RBS_ERR; /* error? */
if (rb_sta & RBS_DON) rb_sta = rb_sta & ~RBS_BSY; /* done? clear busy */
if ((rb_sta & (RBS_ERR | RBS_DON)) && (rb_sta & RBS_IE))
SET_INT (RB); /* set or clr intr */
SET_INT (RB); /* set or clr intr */
else CLR_INT (RB);
return rb_sta;
}

View File

@@ -1,6 +1,6 @@
/* pdp18b_rf.c: fixed head disk simulator
Copyright (c) 1993-2004, Robert M Supnik
Copyright (c) 1993-2005, 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"),
@@ -19,102 +19,102 @@
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
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.
rf (PDP-9) RF09/RF09
(PDP-15) RF15/RS09
rf (PDP-9) RF09/RF09
(PDP-15) RF15/RS09
14-Jan-04 RMS Revised IO device call interface
Changed sim_fsize calling sequence
26-Oct-03 RMS Cleaned up buffer copy code
26-Jul-03 RMS Fixed bug in set size routine
14-Mar-03 RMS Fixed variable platter interaction with save/restore
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
24-Nov-01 RMS Changed WLK to array
26-Apr-01 RMS Added device enable/disable support
15-Feb-01 RMS Fixed 3 cycle data break sequencing
30-Nov-99 RMS Added non-zero requirement to rf_time
14-Apr-99 RMS Changed t_addr to unsigned
14-Jan-04 RMS Revised IO device call interface
Changed sim_fsize calling sequence
26-Oct-03 RMS Cleaned up buffer copy code
26-Jul-03 RMS Fixed bug in set size routine
14-Mar-03 RMS Fixed variable platter interaction with save/restore
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
24-Nov-01 RMS Changed WLK to array
26-Apr-01 RMS Added device enable/disable support
15-Feb-01 RMS Fixed 3 cycle data break sequencing
30-Nov-99 RMS Added non-zero requirement to rf_time
14-Apr-99 RMS Changed t_addr to unsigned
The RFxx is a head-per-track disk. It uses the multicycle data break
facility. To minimize overhead, the entire RFxx is buffered in memory.
Two timing parameters are provided:
rf_time Interword timing. Must be non-zero.
rf_burst Burst mode. If 0, DMA occurs cycle by cycle; otherwise,
DMA occurs in a burst.
rf_time Interword timing. Must be non-zero.
rf_burst Burst mode. If 0, DMA occurs cycle by cycle; otherwise,
DMA occurs in a burst.
*/
#include "pdp18b_defs.h"
#include <math.h>
#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */
#define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */
#define UNIT_M_PLAT 07
#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT)
#define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1)
#define UNIT_AUTO (1 << UNIT_V_AUTO)
#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT)
#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */
#define UNIT_V_PLAT (UNIT_V_UF + 1) /* #platters - 1 */
#define UNIT_M_PLAT 07
#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT)
#define UNIT_GETP(x) ((((x) >> UNIT_V_PLAT) & UNIT_M_PLAT) + 1)
#define UNIT_AUTO (1 << UNIT_V_AUTO)
#define UNIT_PLAT (UNIT_M_PLAT << UNIT_V_PLAT)
/* Constants */
#define RF_NUMWD 2048 /* words/track */
#define RF_NUMTR 128 /* tracks/disk */
#define RF_DKSIZE (RF_NUMTR * RF_NUMWD) /* words/disk */
#define RF_NUMDK 8 /* disks/controller */
#define RF_WMASK (RF_NUMWD - 1) /* word mask */
#define RF_WC 036 /* word count */
#define RF_CA 037 /* current addr */
#define RF_NUMWD 2048 /* words/track */
#define RF_NUMTR 128 /* tracks/disk */
#define RF_DKSIZE (RF_NUMTR * RF_NUMWD) /* words/disk */
#define RF_NUMDK 8 /* disks/controller */
#define RF_WMASK (RF_NUMWD - 1) /* word mask */
#define RF_WC 036 /* word count */
#define RF_CA 037 /* current addr */
/* Function/status register */
#define RFS_ERR 0400000 /* error */
#define RFS_HDW 0200000 /* hardware error */
#define RFS_APE 0100000 /* addr parity error */
#define RFS_MXF 0040000 /* missed transfer */
#define RFS_WCE 0020000 /* write check error */
#define RFS_DPE 0010000 /* data parity error */
#define RFS_WLO 0004000 /* write lock error */
#define RFS_NED 0002000 /* non-existent disk */
#define RFS_DCH 0001000 /* data chan timing */
#define RFS_PGE 0000400 /* programming error */
#define RFS_DON 0000200 /* transfer complete */
#define RFS_V_FNC 1 /* function */
#define RFS_M_FNC 03
#define RFS_FNC (RFS_M_FNC << RFS_V_FNC)
#define FN_NOP 0
#define FN_READ 1
#define FN_WRITE 2
#define FN_WCHK 3
#define RFS_IE 0000001 /* interrupt enable */
#define RFS_ERR 0400000 /* error */
#define RFS_HDW 0200000 /* hardware error */
#define RFS_APE 0100000 /* addr parity error */
#define RFS_MXF 0040000 /* missed transfer */
#define RFS_WCE 0020000 /* write check error */
#define RFS_DPE 0010000 /* data parity error */
#define RFS_WLO 0004000 /* write lock error */
#define RFS_NED 0002000 /* non-existent disk */
#define RFS_DCH 0001000 /* data chan timing */
#define RFS_PGE 0000400 /* programming error */
#define RFS_DON 0000200 /* transfer complete */
#define RFS_V_FNC 1 /* function */
#define RFS_M_FNC 03
#define RFS_FNC (RFS_M_FNC << RFS_V_FNC)
#define FN_NOP 0
#define FN_READ 1
#define FN_WRITE 2
#define FN_WCHK 3
#define RFS_IE 0000001 /* interrupt enable */
#define RFS_CLR 0000170 /* always clear */
#define RFS_EFLGS (RFS_HDW | RFS_APE | RFS_MXF | RFS_WCE | \
RFS_DPE | RFS_WLO | RFS_NED ) /* error flags */
#define GET_FNC(x) (((x) >> RFS_V_FNC) & RFS_M_FNC)
#define GET_POS(x) ((int) fmod (sim_gtime () / ((double) (x)), \
((double) RF_NUMWD)))
#define RF_BUSY (sim_is_active (&rf_unit))
#define RFS_CLR 0000170 /* always clear */
#define RFS_EFLGS (RFS_HDW | RFS_APE | RFS_MXF | RFS_WCE | \
RFS_DPE | RFS_WLO | RFS_NED ) /* error flags */
#define GET_FNC(x) (((x) >> RFS_V_FNC) & RFS_M_FNC)
#define GET_POS(x) ((int) fmod (sim_gtime () / ((double) (x)), \
((double) RF_NUMWD)))
#define RF_BUSY (sim_is_active (&rf_unit))
extern int32 M[];
extern int32 int_hwre[API_HLVL+1];
extern UNIT cpu_unit;
int32 rf_sta = 0; /* status register */
int32 rf_da = 0; /* disk address */
int32 rf_dbuf = 0; /* data buffer */
int32 rf_wlk[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; /* write lock */
int32 rf_time = 10; /* inter-word time */
int32 rf_burst = 1; /* burst mode flag */
int32 rf_stopioe = 1; /* stop on error */
int32 rf_sta = 0; /* status register */
int32 rf_da = 0; /* disk address */
int32 rf_dbuf = 0; /* data buffer */
int32 rf_wlk[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; /* write lock */
int32 rf_time = 10; /* inter-word time */
int32 rf_burst = 1; /* burst mode flag */
int32 rf_stopioe = 1; /* stop on error */
DEVICE rf_dev;
int32 rf70 (int32 dev, int32 pulse, int32 dat);
@@ -128,94 +128,102 @@ t_stat rf_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
/* RF data structures
rf_dev RF device descriptor
rf_unit RF unit descriptor
rf_reg RF register list
rf_dev RF device descriptor
rf_unit RF unit descriptor
rf_reg RF register list
*/
DIB rf_dib = { DEV_RF, 3, &rf_iors, { &rf70, NULL, &rf72 } };
UNIT rf_unit =
{ UDATA (&rf_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_AUTO,
RF_DKSIZE) };
UNIT rf_unit = {
UDATA (&rf_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF+UNIT_AUTO,
RF_DKSIZE)
};
REG rf_reg[] = {
{ ORDATA (STA, rf_sta, 18) },
{ ORDATA (DA, rf_da, 22) },
{ ORDATA (WC, M[RF_WC], 18) },
{ ORDATA (CA, M[RF_CA], 18) },
{ ORDATA (BUF, rf_dbuf, 18) },
{ FLDATA (INT, int_hwre[API_RF], INT_V_RF) },
{ BRDATA (WLK, rf_wlk, 8, 16, RF_NUMDK) },
{ DRDATA (TIME, rf_time, 24), PV_LEFT + REG_NZ },
{ FLDATA (BURST, rf_burst, 0) },
{ FLDATA (STOP_IOE, rf_stopioe, 0) },
{ DRDATA (CAPAC, rf_unit.capac, 31), PV_LEFT + REG_HRO },
{ ORDATA (DEVNO, rf_dib.dev, 6), REG_HRO },
{ NULL } };
{ ORDATA (STA, rf_sta, 18) },
{ ORDATA (DA, rf_da, 22) },
{ ORDATA (WC, M[RF_WC], 18) },
{ ORDATA (CA, M[RF_CA], 18) },
{ ORDATA (BUF, rf_dbuf, 18) },
{ FLDATA (INT, int_hwre[API_RF], INT_V_RF) },
{ BRDATA (WLK, rf_wlk, 8, 16, RF_NUMDK) },
{ DRDATA (TIME, rf_time, 24), PV_LEFT + REG_NZ },
{ FLDATA (BURST, rf_burst, 0) },
{ FLDATA (STOP_IOE, rf_stopioe, 0) },
{ DRDATA (CAPAC, rf_unit.capac, 31), PV_LEFT + REG_HRO },
{ ORDATA (DEVNO, rf_dib.dev, 6), REG_HRO },
{ NULL }
};
MTAB rf_mod[] = {
{ UNIT_PLAT, (0 << UNIT_V_PLAT), NULL, "1P", &rf_set_size },
{ UNIT_PLAT, (1 << UNIT_V_PLAT), NULL, "2P", &rf_set_size },
{ UNIT_PLAT, (2 << UNIT_V_PLAT), NULL, "3P", &rf_set_size },
{ UNIT_PLAT, (3 << UNIT_V_PLAT), NULL, "4P", &rf_set_size },
{ UNIT_PLAT, (4 << UNIT_V_PLAT), NULL, "5P", &rf_set_size },
{ UNIT_PLAT, (5 << UNIT_V_PLAT), NULL, "6P", &rf_set_size },
{ UNIT_PLAT, (6 << UNIT_V_PLAT), NULL, "7P", &rf_set_size },
{ UNIT_PLAT, (7 << UNIT_V_PLAT), NULL, "8P", &rf_set_size },
{ UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL },
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno },
{ 0 } };
{ UNIT_PLAT, (0 << UNIT_V_PLAT), NULL, "1P", &rf_set_size },
{ UNIT_PLAT, (1 << UNIT_V_PLAT), NULL, "2P", &rf_set_size },
{ UNIT_PLAT, (2 << UNIT_V_PLAT), NULL, "3P", &rf_set_size },
{ UNIT_PLAT, (3 << UNIT_V_PLAT), NULL, "4P", &rf_set_size },
{ UNIT_PLAT, (4 << UNIT_V_PLAT), NULL, "5P", &rf_set_size },
{ UNIT_PLAT, (5 << UNIT_V_PLAT), NULL, "6P", &rf_set_size },
{ UNIT_PLAT, (6 << UNIT_V_PLAT), NULL, "7P", &rf_set_size },
{ UNIT_PLAT, (7 << UNIT_V_PLAT), NULL, "8P", &rf_set_size },
{ UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL },
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno },
{ 0 }
};
DEVICE rf_dev = {
"RF", &rf_unit, rf_reg, rf_mod,
1, 8, 21, 1, 8, 18,
NULL, NULL, &rf_reset,
NULL, &rf_attach, NULL,
&rf_dib, DEV_DISABLE };
"RF", &rf_unit, rf_reg, rf_mod,
1, 8, 21, 1, 8, 18,
NULL, NULL, &rf_reset,
NULL, &rf_attach, NULL,
&rf_dib, DEV_DISABLE
};
/* IOT routines */
int32 rf70 (int32 dev, int32 pulse, int32 dat)
{
int32 t, sb;
sb = pulse & 060; /* subopcode */
sb = pulse & 060; /* subopcode */
if (pulse & 01) {
if ((sb == 000) && (rf_sta & (RFS_ERR | RFS_DON)))
dat = IOT_SKP | dat; /* DSSF */
else if (sb == 020) rf_reset (&rf_dev); /* DSCC */
else if (sb == 040) { /* DSCF */
if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy inhibits */
else rf_sta = rf_sta & ~(RFS_FNC | RFS_IE); } /* clear func */
}
if ((sb == 000) && (rf_sta & (RFS_ERR | RFS_DON)))
dat = IOT_SKP | dat; /* DSSF */
else if (sb == 020) rf_reset (&rf_dev); /* DSCC */
else if (sb == 040) { /* DSCF */
if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy inhibits */
else rf_sta = rf_sta & ~(RFS_FNC | RFS_IE); /* clear func */
}
}
if (pulse & 02) {
if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy sets PGE */
else if (sb == 000) dat = dat | rf_dbuf; /* DRBR */
else if (sb == 020) /* DRAL */
dat = dat | (rf_da & DMASK);
else if (sb == 040) /* DSFX */
rf_sta = rf_sta ^ (dat & (RFS_FNC | RFS_IE)); /* xor func */
else if (sb == 060) /* DRAH */
dat = dat | (rf_da >> 18) | ((rf_sta & RFS_NED)? 010: 0);
}
if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy sets PGE */
else if (sb == 000) dat = dat | rf_dbuf; /* DRBR */
else if (sb == 020) /* DRAL */
dat = dat | (rf_da & DMASK);
else if (sb == 040) /* DSFX */
rf_sta = rf_sta ^ (dat & (RFS_FNC | RFS_IE)); /* xor func */
else if (sb == 060) /* DRAH */
dat = dat | (rf_da >> 18) | ((rf_sta & RFS_NED)? 010: 0);
}
if (pulse & 04) {
if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy sets PGE */
else if (sb == 000) rf_dbuf = dat & DMASK; /* DLBR */
else if (sb == 020) /* DLAL */
rf_da = (rf_da & ~DMASK) | (dat & DMASK);
else if (sb == 040) { /* DSCN */
rf_sta = rf_sta & ~RFS_DON; /* clear done */
if (GET_FNC (rf_sta) != FN_NOP) {
t = (rf_da & RF_WMASK) - GET_POS (rf_time); /* delta to new */
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 & DMASK) | ((dat & 07) << 18);
if ((uint32) rf_da >= rf_unit.capac) /* for sizing */
rf_updsta (RFS_NED); }
}
rf_updsta (0); /* update status */
if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy sets PGE */
else if (sb == 000) rf_dbuf = dat & DMASK; /* DLBR */
else if (sb == 020) /* DLAL */
rf_da = (rf_da & ~DMASK) | (dat & DMASK);
else if (sb == 040) { /* DSCN */
rf_sta = rf_sta & ~RFS_DON; /* clear done */
if (GET_FNC (rf_sta) != FN_NOP) {
t = (rf_da & RF_WMASK) - GET_POS (rf_time); /* delta to new */
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 & DMASK) | ((dat & 07) << 18);
if ((uint32) rf_da >= rf_unit.capac) /* for sizing */
rf_updsta (RFS_NED);
}
}
rf_updsta (0); /* update status */
return dat;
}
@@ -224,19 +232,21 @@ int32 rf72 (int32 dev, int32 pulse, int32 dat)
int32 sb = pulse & 060;
if (pulse & 02) {
if (sb == 000) dat = dat | GET_POS (rf_time) | /* DLOK */
(sim_is_active (&rf_unit)? 0400000: 0);
else if (sb == 040) { /* DSCD */
if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy inhibits */
else rf_sta = 0;
rf_updsta (0); }
else if (sb == 060) { /* DSRS */
if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy sets PGE */
dat = dat | rf_updsta (0); }
}
if (sb == 000) dat = dat | GET_POS (rf_time) | /* DLOK */
(sim_is_active (&rf_unit)? 0400000: 0);
else if (sb == 040) { /* DSCD */
if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy inhibits */
else rf_sta = 0;
rf_updsta (0);
}
else if (sb == 060) { /* DSRS */
if (RF_BUSY) rf_sta = rf_sta | RFS_PGE; /* busy sets PGE */
dat = dat | rf_updsta (0);
}
}
return dat;
}
/* Unit service - assumes the entire disk is buffered */
t_stat rf_svc (UNIT *uptr)
@@ -244,40 +254,46 @@ t_stat rf_svc (UNIT *uptr)
int32 f, pa, d, t;
int32 *fbuf = uptr->filebuf;
if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
rf_updsta (RFS_NED | RFS_DON); /* set nxd, done */
return IORETURN (rf_stopioe, SCPE_UNATT); }
if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
rf_updsta (RFS_NED | RFS_DON); /* set nxd, done */
return IORETURN (rf_stopioe, SCPE_UNATT);
}
f = GET_FNC (rf_sta); /* get function */
do { if ((uint32) rf_da >= uptr->capac) { /* disk overflow? */
rf_updsta (RFS_NED); /* nx disk error */
break; }
M[RF_WC] = (M[RF_WC] + 1) & DMASK; /* incr word count */
pa = M[RF_CA] = (M[RF_CA] + 1) & AMASK; /* incr mem addr */
if ((f == FN_READ) && MEM_ADDR_OK (pa)) /* read? */
M[pa] = fbuf[rf_da];
if ((f == FN_WCHK) && (M[pa] != fbuf[rf_da])) { /* write check? */
rf_updsta (RFS_WCE); /* flag error */
break; }
if (f == FN_WRITE) { /* write? */
d = (rf_da >> 18) & 07; /* disk */
t = (rf_da >> 14) & 017; /* track groups */
if ((rf_wlk[d] >> t) & 1) { /* write locked? */
rf_updsta (RFS_WLO);
break; }
else { /* not locked */
fbuf[rf_da] = M[pa]; /* write word */
if (((uint32) rf_da) >= uptr->hwmark) uptr->hwmark = rf_da + 1; } }
rf_da = rf_da + 1; /* incr disk addr */
}
while ((M[RF_WC] != 0) && (rf_burst != 0)); /* brk if wc, no brst */
f = GET_FNC (rf_sta); /* get function */
do {
if ((uint32) rf_da >= uptr->capac) { /* disk overflow? */
rf_updsta (RFS_NED); /* nx disk error */
break;
}
M[RF_WC] = (M[RF_WC] + 1) & DMASK; /* incr word count */
pa = M[RF_CA] = (M[RF_CA] + 1) & AMASK; /* incr mem addr */
if ((f == FN_READ) && MEM_ADDR_OK (pa)) /* read? */
M[pa] = fbuf[rf_da];
if ((f == FN_WCHK) && (M[pa] != fbuf[rf_da])) { /* write check? */
rf_updsta (RFS_WCE); /* flag error */
break;
}
if (f == FN_WRITE) { /* write? */
d = (rf_da >> 18) & 07; /* disk */
t = (rf_da >> 14) & 017; /* track groups */
if ((rf_wlk[d] >> t) & 1) { /* write locked? */
rf_updsta (RFS_WLO);
break;
}
else { /* not locked */
fbuf[rf_da] = M[pa]; /* write word */
if (((uint32) rf_da) >= uptr->hwmark) uptr->hwmark = rf_da + 1;
}
}
rf_da = rf_da + 1; /* incr disk addr */
} while ((M[RF_WC] != 0) && (rf_burst != 0)); /* brk if wc, no brst */
if ((M[RF_WC] != 0) && ((rf_sta & RFS_ERR) == 0)) /* more to do? */
sim_activate (&rf_unit, rf_time); /* sched next */
if ((M[RF_WC] != 0) && ((rf_sta & RFS_ERR) == 0)) /* more to do? */
sim_activate (&rf_unit, rf_time); /* sched next */
else rf_updsta (RFS_DON);
return SCPE_OK;
}
/* Update status */
int32 rf_updsta (int32 new)
@@ -285,7 +301,7 @@ int32 rf_updsta (int32 new)
rf_sta = (rf_sta | new) & ~(RFS_ERR | RFS_CLR);
if (rf_sta & RFS_EFLGS) rf_sta = rf_sta | RFS_ERR;
if ((rf_sta & (RFS_ERR | RFS_DON)) && (rf_sta & RFS_IE))
SET_INT (RF);
SET_INT (RF);
else CLR_INT (RF);
return rf_sta;
}
@@ -318,10 +334,11 @@ t_stat r;
r = attach_unit (uptr, cptr);
if (r != SCPE_OK) return r;
if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (uptr->fileref))) {
p = (sz + ds_bytes - 1) / ds_bytes;
if (p >= RF_NUMDK) p = RF_NUMDK - 1;
uptr->flags = (uptr->flags & ~UNIT_PLAT) |
(p << UNIT_V_PLAT); }
p = (sz + ds_bytes - 1) / ds_bytes;
if (p >= RF_NUMDK) p = RF_NUMDK - 1;
uptr->flags = (uptr->flags & ~UNIT_PLAT) |
(p << UNIT_V_PLAT);
}
uptr->capac = UNIT_GETP (uptr->flags) * RF_DKSIZE;
return SCPE_OK;
}

View File

@@ -1,6 +1,6 @@
/* pdp18b_rp.c: RP15/RP02 disk pack simulator
Copyright (c) 1993-2004, Robert M Supnik
Copyright (c) 1993-2005, 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"),
@@ -19,130 +19,130 @@
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
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.
rp RP15/RP02 disk pack
rp RP15/RP02 disk pack
14-Jan-04 RMS Revised IO device call interface
06-Feb-03 RMS Revised IOT decoding, fixed bug in initiation
05-Oct-02 RMS Added DIB, device number support
06-Jan-02 RMS Revised enable/disable support
29-Nov-01 RMS Added read only unit support
25-Nov-01 RMS Revised interrupt structure
Changed FLG to array
26-Apr-01 RMS Added device enable/disable support
14-Apr-99 RMS Changed t_addr to unsigned
29-Jun-96 RMS Added unit enable/disable support
14-Jan-04 RMS Revised IO device call interface
06-Feb-03 RMS Revised IOT decoding, fixed bug in initiation
05-Oct-02 RMS Added DIB, device number support
06-Jan-02 RMS Revised enable/disable support
29-Nov-01 RMS Added read only unit support
25-Nov-01 RMS Revised interrupt structure
Changed FLG to array
26-Apr-01 RMS Added device enable/disable support
14-Apr-99 RMS Changed t_addr to unsigned
29-Jun-96 RMS Added unit enable/disable support
*/
#include "pdp18b_defs.h"
/* Constants */
#define RP_NUMWD 256 /* words/sector */
#define RP_NUMSC 10 /* sectors/surface */
#define RP_NUMSF 20 /* surfaces/cylinder */
#define RP_NUMCY 203 /* cylinders/drive */
#define RP_NUMDR 8 /* drives/controller */
#define RP_NUMWD 256 /* words/sector */
#define RP_NUMSC 10 /* sectors/surface */
#define RP_NUMSF 20 /* surfaces/cylinder */
#define RP_NUMCY 203 /* cylinders/drive */
#define RP_NUMDR 8 /* drives/controller */
#define RP_SIZE (RP_NUMCY * RP_NUMSF * RP_NUMSC * RP_NUMWD) /* words/drive */
/* Unit specific flags */
#define UNIT_V_WLK (UNIT_V_UF + 0) /* hwre write lock */
#define UNIT_WLK (1u << UNIT_V_WLK)
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
#define UNIT_V_WLK (UNIT_V_UF + 0) /* hwre write lock */
#define UNIT_WLK (1u << UNIT_V_WLK)
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
/* Parameters in the unit descriptor */
#define CYL u3 /* current cylinder */
#define FUNC u4 /* function */
#define CYL u3 /* current cylinder */
#define FUNC u4 /* function */
/* Status register A */
#define STA_V_UNIT 15 /* unit select */
#define STA_M_UNIT 07
#define STA_V_FUNC 12 /* function */
#define STA_M_FUNC 07
#define FN_IDLE 0
#define FN_READ 1
#define FN_WRITE 2
#define FN_RECAL 3
#define FN_SEEK 4
#define FN_RDALL 5
#define FN_WRALL 6
#define FN_WRCHK 7
#define FN_2ND 010 /* second state flag */
#define STA_IED 0004000 /* int enable done */
#define STA_IEA 0002000 /* int enable attn */
#define STA_GO 0001000 /* go */
#define STA_WPE 0000400 /* write lock error */
#define STA_NXC 0000200 /* nx cyl error */
#define STA_NXF 0000100 /* nx surface error */
#define STA_NXS 0000040 /* nx sector error */
#define STA_HNF 0000020 /* hdr not found */
#define STA_SUWP 0000010 /* sel unit wrt lock */
#define STA_SUSI 0000004 /* sel unit seek inc */
#define STA_DON 0000002 /* done */
#define STA_ERR 0000001 /* error */
#define STA_V_UNIT 15 /* unit select */
#define STA_M_UNIT 07
#define STA_V_FUNC 12 /* function */
#define STA_M_FUNC 07
#define FN_IDLE 0
#define FN_READ 1
#define FN_WRITE 2
#define FN_RECAL 3
#define FN_SEEK 4
#define FN_RDALL 5
#define FN_WRALL 6
#define FN_WRCHK 7
#define FN_2ND 010 /* second state flag */
#define STA_IED 0004000 /* int enable done */
#define STA_IEA 0002000 /* int enable attn */
#define STA_GO 0001000 /* go */
#define STA_WPE 0000400 /* write lock error */
#define STA_NXC 0000200 /* nx cyl error */
#define STA_NXF 0000100 /* nx surface error */
#define STA_NXS 0000040 /* nx sector error */
#define STA_HNF 0000020 /* hdr not found */
#define STA_SUWP 0000010 /* sel unit wrt lock */
#define STA_SUSI 0000004 /* sel unit seek inc */
#define STA_DON 0000002 /* done */
#define STA_ERR 0000001 /* error */
#define STA_RW 0777000 /* read/write */
#define STA_EFLGS (STA_WPE | STA_NXC | STA_NXF | STA_NXS | \
STA_HNF | STA_SUSI) /* error flags */
#define STA_DYN (STA_SUWP | STA_SUSI) /* per unit status */
#define GET_UNIT(x) (((x) >> STA_V_UNIT) & STA_M_UNIT)
#define GET_FUNC(x) (((x) >> STA_V_FUNC) & STA_M_FUNC)
#define STA_RW 0777000 /* read/write */
#define STA_EFLGS (STA_WPE | STA_NXC | STA_NXF | STA_NXS | \
STA_HNF | STA_SUSI) /* error flags */
#define STA_DYN (STA_SUWP | STA_SUSI) /* per unit status */
#define GET_UNIT(x) (((x) >> STA_V_UNIT) & STA_M_UNIT)
#define GET_FUNC(x) (((x) >> STA_V_FUNC) & STA_M_FUNC)
/* Status register B */
#define STB_V_ATT0 17 /* unit 0 attention */
#define STB_ATTN 0776000 /* attention flags */
#define STB_SUFU 0001000 /* sel unit unsafe */
#define STB_PGE 0000400 /* programming error */
#define STB_EOP 0000200 /* end of pack */
#define STB_TME 0000100 /* timing error */
#define STB_FME 0000040 /* format error */
#define STB_WCE 0000020 /* write check error */
#define STB_WPE 0000010 /* word parity error */
#define STB_LON 0000004 /* long parity error */
#define STB_SUSU 0000002 /* sel unit seeking */
#define STB_SUNR 0000001 /* sel unit not rdy */
#define STB_V_ATT0 17 /* unit 0 attention */
#define STB_ATTN 0776000 /* attention flags */
#define STB_SUFU 0001000 /* sel unit unsafe */
#define STB_PGE 0000400 /* programming error */
#define STB_EOP 0000200 /* end of pack */
#define STB_TME 0000100 /* timing error */
#define STB_FME 0000040 /* format error */
#define STB_WCE 0000020 /* write check error */
#define STB_WPE 0000010 /* word parity error */
#define STB_LON 0000004 /* long parity error */
#define STB_SUSU 0000002 /* sel unit seeking */
#define STB_SUNR 0000001 /* sel unit not rdy */
#define STB_EFLGS (STB_SUFU | STB_PGE | STB_EOP | STB_TME | STB_FME | \
STB_WCE | STB_WPE | STB_LON ) /* error flags */
#define STB_DYN (STB_SUFU | STB_SUSU | STB_SUNR) /* per unit */
#define STB_EFLGS (STB_SUFU | STB_PGE | STB_EOP | STB_TME | STB_FME | \
STB_WCE | STB_WPE | STB_LON ) /* error flags */
#define STB_DYN (STB_SUFU | STB_SUSU | STB_SUNR) /* per unit */
/* Disk address */
#define DA_V_SECT 0 /* sector */
#define DA_M_SECT 017
#define DA_V_SURF 5
#define DA_M_SURF 037
#define DA_V_CYL 10 /* cylinder */
#define DA_M_CYL 0377
#define GET_SECT(x) (((x) >> DA_V_SECT) & DA_M_SECT)
#define GET_SURF(x) (((x) >> DA_V_SURF) & DA_M_SURF)
#define GET_CYL(x) (((x) >> DA_V_CYL) & DA_M_CYL)
#define GET_DA(x) ((((GET_CYL (x) * RP_NUMSF) + GET_SURF (x)) * \
RP_NUMSC) + GET_SECT (x))
#define DA_V_SECT 0 /* sector */
#define DA_M_SECT 017
#define DA_V_SURF 5
#define DA_M_SURF 037
#define DA_V_CYL 10 /* cylinder */
#define DA_M_CYL 0377
#define GET_SECT(x) (((x) >> DA_V_SECT) & DA_M_SECT)
#define GET_SURF(x) (((x) >> DA_V_SURF) & DA_M_SURF)
#define GET_CYL(x) (((x) >> DA_V_CYL) & DA_M_CYL)
#define GET_DA(x) ((((GET_CYL (x) * RP_NUMSF) + GET_SURF (x)) * \
RP_NUMSC) + GET_SECT (x))
#define RP_MIN 2
#define MAX(x,y) (((x) > (y))? (x): (y))
extern int32 M[];
extern int32 int_hwre[API_HLVL+1], nexm;
extern UNIT cpu_unit;
int32 rp_sta = 0; /* status A */
int32 rp_stb = 0; /* status B */
int32 rp_ma = 0; /* memory address */
int32 rp_da = 0; /* disk address */
int32 rp_wc = 0; /* word count */
int32 rp_busy = 0; /* busy */
int32 rp_stopioe = 1; /* stop on error */
int32 rp_swait = 10; /* seek time */
int32 rp_rwait = 10; /* rotate time */
int32 rp_sta = 0; /* status A */
int32 rp_stb = 0; /* status B */
int32 rp_ma = 0; /* memory address */
int32 rp_da = 0; /* disk address */
int32 rp_wc = 0; /* word count */
int32 rp_busy = 0; /* busy */
int32 rp_stopioe = 1; /* stop on error */
int32 rp_swait = 10; /* seek time */
int32 rp_rwait = 10; /* rotate time */
DEVICE rp_dev;
int32 rp63 (int32 dev, int32 pulse, int32 dat);
@@ -156,93 +156,100 @@ t_stat rp_detach (UNIT *uptr);
/* RP15 data structures
rp_dev RP device descriptor
rp_unit RP unit list
rp_reg RP register list
rp_mod RP modifier list
rp_dev RP device descriptor
rp_unit RP unit list
rp_reg RP register list
rp_mod RP modifier list
*/
DIB rp_dib = { DEV_RP, 2, &rp_iors, { &rp63, &rp64 } };
UNIT rp_unit[] = {
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) } };
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) },
{ UDATA (&rp_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE, RP_SIZE) }
};
REG rp_reg[] = {
{ ORDATA (STA, rp_sta, 18) },
{ ORDATA (STB, rp_stb, 18) },
{ ORDATA (DA, rp_da, 18) },
{ ORDATA (MA, rp_ma, 18) },
{ ORDATA (WC, rp_wc, 18) },
{ FLDATA (INT, int_hwre[API_RP], INT_V_RP) },
{ FLDATA (BUSY, rp_busy, 0) },
{ FLDATA (STOP_IOE, rp_stopioe, 0) },
{ DRDATA (STIME, rp_swait, 24), PV_LEFT },
{ DRDATA (RTIME, rp_rwait, 24), PV_LEFT },
{ ORDATA (DEVNO, rp_dib.dev, 6), REG_HRO },
{ NULL } };
{ ORDATA (STA, rp_sta, 18) },
{ ORDATA (STB, rp_stb, 18) },
{ ORDATA (DA, rp_da, 18) },
{ ORDATA (MA, rp_ma, 18) },
{ ORDATA (WC, rp_wc, 18) },
{ FLDATA (INT, int_hwre[API_RP], INT_V_RP) },
{ FLDATA (BUSY, rp_busy, 0) },
{ FLDATA (STOP_IOE, rp_stopioe, 0) },
{ DRDATA (STIME, rp_swait, 24), PV_LEFT },
{ DRDATA (RTIME, rp_rwait, 24), PV_LEFT },
{ ORDATA (DEVNO, rp_dib.dev, 6), REG_HRO },
{ NULL }
};
MTAB rp_mod[] = {
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno },
{ 0 } };
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO", &set_devno, &show_devno },
{ 0 }
};
DEVICE rp_dev = {
"RP", rp_unit, rp_reg, rp_mod,
RP_NUMDR, 8, 24, 1, 8, 18,
NULL, NULL, &rp_reset,
NULL, &rp_attach, &rp_detach,
&rp_dib, DEV_DISABLE };
"RP", rp_unit, rp_reg, rp_mod,
RP_NUMDR, 8, 24, 1, 8, 18,
NULL, NULL, &rp_reset,
NULL, &rp_attach, &rp_detach,
&rp_dib, DEV_DISABLE
};
/* IOT routines */
int32 rp63 (int32 dev, int32 pulse, int32 dat)
{
int32 sb = pulse & 060; /* subopcode */
int32 sb = pulse & 060; /* subopcode */
rp_updsta (0, 0);
if (pulse & 01) {
if ((sb == 000) && /* DPSF */
((rp_sta & (STA_DON | STA_ERR)) || (rp_stb & STB_ATTN)))
dat = IOT_SKP | dat;
else if ((sb == 020) && (rp_stb & STB_ATTN)) /* DPSA */
dat = IOT_SKP | dat;
else if ((sb == 040) && (rp_sta & STA_DON)) /* DPSJ */
dat = IOT_SKP | dat;
else if ((sb == 060) && (rp_sta & STA_ERR)) /* DPSE */
dat = IOT_SKP | dat;
}
if ((sb == 000) && /* DPSF */
((rp_sta & (STA_DON | STA_ERR)) || (rp_stb & STB_ATTN)))
dat = IOT_SKP | dat;
else if ((sb == 020) && (rp_stb & STB_ATTN)) /* DPSA */
dat = IOT_SKP | dat;
else if ((sb == 040) && (rp_sta & STA_DON)) /* DPSJ */
dat = IOT_SKP | dat;
else if ((sb == 060) && (rp_sta & STA_ERR)) /* DPSE */
dat = IOT_SKP | dat;
}
if (pulse & 02) {
if (sb == 000) dat = dat | rp_sta; /* DPOSA */
else if (sb == 020) dat = dat | rp_stb; /* DPOSB */
}
if (sb == 000) dat = dat | rp_sta; /* DPOSA */
else if (sb == 020) dat = dat | rp_stb; /* DPOSB */
}
if (pulse & 04) {
if (rp_busy) { /* busy? */
rp_updsta (0, STB_PGE);
return dat; }
else if (sb == 000) { /* DPLA */
rp_da = dat & DMASK;
if (GET_SECT (rp_da) >= RP_NUMSC) rp_updsta (STA_NXS, 0);
if (GET_SURF (rp_da) >= RP_NUMSF) rp_updsta (STA_NXF, 0);
if (GET_CYL (rp_da) >= RP_NUMCY) rp_updsta (STA_NXC, 0); }
else if (sb == 020) { /* DPCS */
rp_sta = rp_sta & ~(STA_HNF | STA_DON);
rp_stb = rp_stb & ~(STB_FME | STB_WPE | STB_LON | STB_WCE |
STB_TME | STB_PGE | STB_EOP);
rp_updsta (0, 0); }
else if (sb == 040) rp_ma = dat & DMASK; /* DPCA */
else if (sb == 060) rp_wc = dat & DMASK; /* DPWC */
}
if (rp_busy) { /* busy? */
rp_updsta (0, STB_PGE);
return dat;
}
else if (sb == 000) { /* DPLA */
rp_da = dat & DMASK;
if (GET_SECT (rp_da) >= RP_NUMSC) rp_updsta (STA_NXS, 0);
if (GET_SURF (rp_da) >= RP_NUMSF) rp_updsta (STA_NXF, 0);
if (GET_CYL (rp_da) >= RP_NUMCY) rp_updsta (STA_NXC, 0);
}
else if (sb == 020) { /* DPCS */
rp_sta = rp_sta & ~(STA_HNF | STA_DON);
rp_stb = rp_stb & ~(STB_FME | STB_WPE | STB_LON | STB_WCE |
STB_TME | STB_PGE | STB_EOP);
rp_updsta (0, 0);
}
else if (sb == 040) rp_ma = dat & DMASK; /* DPCA */
else if (sb == 060) rp_wc = dat & DMASK; /* DPWC */
}
return dat;
}
/* IOT 64 */
int32 rp64 (int32 dev, int32 pulse, int32 dat)
@@ -252,49 +259,52 @@ UNIT *uptr;
sb = pulse & 060;
if (pulse & 01) {
if (sb == 020) dat = IOT_SKP | dat; /* DPSN */
}
if (sb == 020) dat = IOT_SKP | dat; /* DPSN */
}
if (pulse & 02) {
if (sb == 000) dat = dat | rp_unit[GET_UNIT (rp_sta)].CYL; /* DPOU */
else if (sb == 020) dat = dat | rp_da; /* DPOA */
else if (sb == 040) dat = dat | rp_ma; /* DPOC */
else if (sb == 060) dat = dat | rp_wc; /* DPOW */
}
if (sb == 000) dat = dat | rp_unit[GET_UNIT (rp_sta)].CYL; /* DPOU */
else if (sb == 020) dat = dat | rp_da; /* DPOA */
else if (sb == 040) dat = dat | rp_ma; /* DPOC */
else if (sb == 060) dat = dat | rp_wc; /* DPOW */
}
if (pulse & 04) {
if (rp_busy) { /* busy? */
rp_updsta (0, STB_PGE);
return dat; }
if (sb == 000) rp_sta = rp_sta & ~STA_RW; /* DPCF */
else if (sb == 020) rp_sta = rp_sta & (dat | ~STA_RW); /* DPLZ */
else if (sb == 040) rp_sta = rp_sta | (dat & STA_RW); /* DPLO */
else if (sb == 060) /* DPLF */
rp_sta = (rp_sta & ~STA_RW) | (dat & STA_RW);
rp_sta = rp_sta & ~STA_DON; /* clear done */
u = GET_UNIT (rp_sta); /* get unit num */
uptr = rp_dev.units + u; /* select unit */
if ((rp_sta & STA_GO) && !sim_is_active (uptr)) {
f = uptr->FUNC = GET_FUNC (rp_sta); /* get function */
rp_busy = 1; /* set ctrl busy */
rp_sta = rp_sta & ~(STA_HNF | STA_DON); /* clear flags */
rp_stb = rp_stb & ~(STB_FME | STB_WPE | STB_LON | STB_WCE |
STB_TME | STB_PGE | STB_EOP | (1 << (STB_V_ATT0 - u)));
if (((uptr->flags & UNIT_ATT) == 0) || (f == FN_IDLE) ||
(f == FN_SEEK) || (f == FN_RECAL))
sim_activate (uptr, RP_MIN); /* short delay */
else {
c = GET_CYL (rp_da);
c = abs (c - uptr->CYL) * rp_swait; /* seek time */
sim_activate (uptr, MAX (RP_MIN, c + rp_rwait)); } }
}
if (rp_busy) { /* busy? */
rp_updsta (0, STB_PGE);
return dat;
}
if (sb == 000) rp_sta = rp_sta & ~STA_RW; /* DPCF */
else if (sb == 020) rp_sta = rp_sta & (dat | ~STA_RW); /* DPLZ */
else if (sb == 040) rp_sta = rp_sta | (dat & STA_RW); /* DPLO */
else if (sb == 060) /* DPLF */
rp_sta = (rp_sta & ~STA_RW) | (dat & STA_RW);
rp_sta = rp_sta & ~STA_DON; /* clear done */
u = GET_UNIT (rp_sta); /* get unit num */
uptr = rp_dev.units + u; /* select unit */
if ((rp_sta & STA_GO) && !sim_is_active (uptr)) {
f = uptr->FUNC = GET_FUNC (rp_sta); /* get function */
rp_busy = 1; /* set ctrl busy */
rp_sta = rp_sta & ~(STA_HNF | STA_DON); /* clear flags */
rp_stb = rp_stb & ~(STB_FME | STB_WPE | STB_LON | STB_WCE |
STB_TME | STB_PGE | STB_EOP | (1 << (STB_V_ATT0 - u)));
if (((uptr->flags & UNIT_ATT) == 0) || (f == FN_IDLE) ||
(f == FN_SEEK) || (f == FN_RECAL))
sim_activate (uptr, RP_MIN); /* short delay */
else {
c = GET_CYL (rp_da);
c = abs (c - uptr->CYL) * rp_swait; /* seek time */
sim_activate (uptr, MAX (RP_MIN, c + rp_rwait));
}
}
}
rp_updsta (0, 0);
return dat;
}
/* Unit service
If function = idle, clear busy
If seek or recal initial state, clear attention line, compute seek time,
put on cylinder, set second state
put on cylinder, set second state
If unit not attached, give error
If seek or recal second state, set attention line, compute errors
Else complete data transfer command
@@ -309,86 +319,100 @@ t_stat rp_svc (UNIT *uptr)
int32 f, u, comp, cyl, sect, surf;
int32 err, pa, da, wc, awc, i;
u = uptr - rp_dev.units; /* get drv number */
f = uptr->FUNC; /* get function */
if (f == FN_IDLE) { /* idle? */
rp_busy = 0; /* clear busy */
return SCPE_OK; }
u = (int32) (uptr - rp_dev.units); /* get drv number */
f = uptr->FUNC; /* get function */
if (f == FN_IDLE) { /* idle? */
rp_busy = 0; /* clear busy */
return SCPE_OK;
}
if ((f == FN_SEEK) || (f == FN_RECAL)) { /* seek or recal? */
rp_busy = 0; /* not busy */
cyl = (f == FN_SEEK)? GET_CYL (rp_da): 0; /* get cylinder */
sim_activate (uptr, MAX (RP_MIN, abs (cyl - uptr->CYL) * rp_swait));
uptr->CYL = cyl; /* on cylinder */
uptr->FUNC = FN_SEEK | FN_2ND; /* set second state */
rp_updsta (0, 0); /* update status */
return SCPE_OK; }
if ((f == FN_SEEK) || (f == FN_RECAL)) { /* seek or recal? */
rp_busy = 0; /* not busy */
cyl = (f == FN_SEEK)? GET_CYL (rp_da): 0; /* get cylinder */
sim_activate (uptr, MAX (RP_MIN, abs (cyl - uptr->CYL) * rp_swait));
uptr->CYL = cyl; /* on cylinder */
uptr->FUNC = FN_SEEK | FN_2ND; /* set second state */
rp_updsta (0, 0); /* update status */
return SCPE_OK;
}
if (f == (FN_SEEK | FN_2ND)) { /* seek done? */
rp_updsta (0, rp_stb | (1 << (STB_V_ATT0 - u))); /* set attention */
return SCPE_OK; }
if (f == (FN_SEEK | FN_2ND)) { /* seek done? */
rp_updsta (0, rp_stb | (1 << (STB_V_ATT0 - u))); /* set attention */
return SCPE_OK;
}
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
rp_updsta (STA_DON, STB_SUFU); /* done, unsafe */
return IORETURN (rp_stopioe, SCPE_UNATT); }
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
rp_updsta (STA_DON, STB_SUFU); /* done, unsafe */
return IORETURN (rp_stopioe, SCPE_UNATT);
}
if ((f == FN_WRITE) && (uptr->flags & UNIT_WPRT)) { /* write locked? */
rp_updsta (STA_DON | STA_WPE, 0); /* error */
return SCPE_OK; }
if ((f == FN_WRITE) && (uptr->flags & UNIT_WPRT)) { /* write locked? */
rp_updsta (STA_DON | STA_WPE, 0); /* error */
return SCPE_OK;
}
if (GET_SECT (rp_da) >= RP_NUMSC) rp_updsta (STA_NXS, 0);
if (GET_SURF (rp_da) >= RP_NUMSF) rp_updsta (STA_NXF, 0);
if (GET_CYL (rp_da) >= RP_NUMCY) rp_updsta (STA_NXC, 0);
if (rp_sta & (STA_NXS | STA_NXF | STA_NXC)) { /* or bad disk addr? */
rp_updsta (STA_DON, STB_SUFU); /* done, unsafe */
return SCPE_OK; }
if (rp_sta & (STA_NXS | STA_NXF | STA_NXC)) { /* or bad disk addr? */
rp_updsta (STA_DON, STB_SUFU); /* done, unsafe */
return SCPE_OK;
}
pa = rp_ma & AMASK; /* get mem addr */
da = GET_DA (rp_da) * RP_NUMWD; /* get disk addr */
wc = 01000000 - rp_wc; /* get true wc */
if (((uint32) (pa + wc)) > MEMSIZE) { /* memory overrun? */
nexm = 1; /* set nexm flag */
wc = MEMSIZE - pa; } /* limit xfer */
if ((da + wc) > RP_SIZE) { /* disk overrun? */
rp_updsta (0, STB_EOP); /* error */
wc = RP_SIZE - da; } /* limit xfer */
pa = rp_ma & AMASK; /* get mem addr */
da = GET_DA (rp_da) * RP_NUMWD; /* get disk addr */
wc = 01000000 - rp_wc; /* get true wc */
if (((uint32) (pa + wc)) > MEMSIZE) { /* memory overrun? */
nexm = 1; /* set nexm flag */
wc = MEMSIZE - pa; /* limit xfer */
}
if ((da + wc) > RP_SIZE) { /* disk overrun? */
rp_updsta (0, STB_EOP); /* error */
wc = RP_SIZE - da; /* limit xfer */
}
err = fseek (uptr->fileref, da * sizeof (int), SEEK_SET);
if ((f == FN_READ) && (err == 0)) { /* read? */
awc = fxread (&M[pa], sizeof (int32), wc, uptr->fileref);
for ( ; awc < wc; awc++) M[pa + awc] = 0;
err = ferror (uptr->fileref); }
if ((f == FN_READ) && (err == 0)) { /* read? */
awc = fxread (&M[pa], sizeof (int32), wc, uptr->fileref);
for ( ; awc < wc; awc++) M[pa + awc] = 0;
err = ferror (uptr->fileref);
}
if ((f == FN_WRITE) && (err == 0)) { /* write? */
fxwrite (&M[pa], sizeof (int32), wc, uptr->fileref);
err = ferror (uptr->fileref);
if ((err == 0) && (i = (wc & (RP_NUMWD - 1)))) {
fxwrite (fill, sizeof (int), i, uptr->fileref);
err = ferror (uptr->fileref); } }
if ((f == FN_WRITE) && (err == 0)) { /* write? */
fxwrite (&M[pa], sizeof (int32), wc, uptr->fileref);
err = ferror (uptr->fileref);
if ((err == 0) && (i = (wc & (RP_NUMWD - 1)))) {
fxwrite (fill, sizeof (int), i, uptr->fileref);
err = ferror (uptr->fileref);
}
}
if ((f == FN_WRCHK) && (err == 0)) { /* write check? */
for (i = 0; (err == 0) && (i < wc); i++) {
awc = fxread (&comp, sizeof (int32), 1, uptr->fileref);
if (awc == 0) comp = 0;
if (comp != M[pa + i]) rp_updsta (0, STB_WCE); }
err = ferror (uptr->fileref); }
if ((f == FN_WRCHK) && (err == 0)) { /* write check? */
for (i = 0; (err == 0) && (i < wc); i++) {
awc = fxread (&comp, sizeof (int32), 1, uptr->fileref);
if (awc == 0) comp = 0;
if (comp != M[pa + i]) rp_updsta (0, STB_WCE);
}
err = ferror (uptr->fileref);
}
rp_wc = (rp_wc + wc) & DMASK; /* final word count */
rp_ma = (rp_ma + wc) & DMASK; /* final mem addr */
da = (da + wc + (RP_NUMWD - 1)) / RP_NUMWD; /* final sector num */
cyl = da / (RP_NUMSC * RP_NUMSF); /* get cyl */
rp_wc = (rp_wc + wc) & DMASK; /* final word count */
rp_ma = (rp_ma + wc) & DMASK; /* final mem addr */
da = (da + wc + (RP_NUMWD - 1)) / RP_NUMWD; /* final sector num */
cyl = da / (RP_NUMSC * RP_NUMSF); /* get cyl */
if (cyl >= RP_NUMCY) cyl = RP_NUMCY - 1;
surf = (da % (RP_NUMSC * RP_NUMSF)) / RP_NUMSC; /* get surface */
sect = (da % (RP_NUMSC * RP_NUMSF)) % RP_NUMSC; /* get sector */
surf = (da % (RP_NUMSC * RP_NUMSF)) / RP_NUMSC; /* get surface */
sect = (da % (RP_NUMSC * RP_NUMSF)) % RP_NUMSC; /* get sector */
rp_da = (cyl << DA_V_CYL) | (surf << DA_V_SURF) | (sect << DA_V_SECT);
rp_busy = 0; /* clear busy */
rp_updsta (STA_DON, 0); /* set done */
rp_busy = 0; /* clear busy */
rp_updsta (STA_DON, 0); /* set done */
if (err != 0) { /* error? */
perror ("RP I/O error");
clearerr (uptr->fileref);
return IORETURN (rp_stopioe, SCPE_IOERR); }
if (err != 0) { /* error? */
perror ("RP I/O error");
clearerr (uptr->fileref);
return IORETURN (rp_stopioe, SCPE_IOERR);
}
return SCPE_OK;
}
@@ -405,9 +429,10 @@ rp_stb = (rp_stb & ~STB_DYN) | newb;
if (uptr->flags & UNIT_WPRT) rp_sta = rp_sta | STA_SUWP;
if ((uptr->flags & UNIT_ATT) == 0) rp_stb = rp_stb | STB_SUFU | STB_SUNR;
else if (sim_is_active (uptr)) {
f = (uptr->FUNC) & STA_M_FUNC;
if ((f == FN_SEEK) || (f == FN_RECAL))
rp_stb = rp_stb | STB_SUSU | STB_SUNR; }
f = (uptr->FUNC) & STA_M_FUNC;
if ((f == FN_SEEK) || (f == FN_RECAL))
rp_stb = rp_stb | STB_SUSU | STB_SUNR;
}
else if (uptr->CYL >= RP_NUMCY) rp_sta = rp_sta | STA_SUSI;
if ((rp_sta & STA_EFLGS) || (rp_stb & STB_EFLGS)) rp_sta = rp_sta | STA_ERR;
if (((rp_sta & (STA_ERR | STA_DON)) && (rp_sta & STA_IED)) ||
@@ -415,7 +440,7 @@ if (((rp_sta & (STA_ERR | STA_DON)) && (rp_sta & STA_IED)) ||
else CLR_INT (RP);
return;
}
/* Reset routine */
t_stat rp_reset (DEVICE *dptr)
@@ -426,9 +451,10 @@ UNIT *uptr;
rp_sta = rp_stb = rp_da = rp_wc = rp_ma = rp_busy = 0;
CLR_INT (RP);
for (i = 0; i < RP_NUMDR; i++) {
uptr = rp_dev.units + i;
sim_cancel (uptr);
uptr->CYL = uptr->FUNC = 0; }
uptr = rp_dev.units + i;
sim_cancel (uptr);
uptr->CYL = uptr->FUNC = 0;
}
return SCPE_OK;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
/* pdp15_ttx.c: PDP-15 additional terminals simulator
Copyright (c) 1993-2004, Robert M Supnik
Copyright (c) 1993-2005, 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"),
@@ -19,13 +19,15 @@
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
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.
ttix,ttox LT15/LT19 terminal input/output
ttix,ttox LT15/LT19 terminal input/output
14-Jan-04 RMS Cloned from pdp8_ttx.c
29-Jun-05 RMS Added SET TTOXn DISCONNECT
21-Jun-05 RMS Fixed bug in SHOW CONN/STATS
14-Jan-04 RMS Cloned from pdp8_ttx.c
This module implements 16 individual serial interfaces similar in function
to the console. These interfaces are mapped to Telnet based connections as
@@ -39,25 +41,25 @@
#include <ctype.h>
#if defined (PDP15)
#define TTX_MAXL 16 /* max number of lines */
#define TTX_MAXL 16 /* max number of lines */
#elif defined (PDP9)
#define TTX_MAXL 4
#define TTX_MAXL 4
#else
#define TTX_MAXL 1
#define TTX_MAXL 1
#endif
#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */
#define UNIT_V_KSR (UNIT_V_UF + 1) /* KSR33 */
#define UNIT_8B (1 << UNIT_V_8B)
#define UNIT_KSR (1 << UNIT_V_KSR)
#define UNIT_V_8B (UNIT_V_UF + 0) /* 8B */
#define UNIT_V_KSR (UNIT_V_UF + 1) /* KSR33 */
#define UNIT_8B (1 << UNIT_V_8B)
#define UNIT_KSR (1 << UNIT_V_KSR)
uint32 ttix_done = 0; /* input flags */
uint32 ttox_done = 0; /* output flags */
uint8 ttix_buf[TTX_MAXL] = { 0 }; /* input buffers */
uint8 ttox_buf[TTX_MAXL] = { 0 }; /* output buffers */
TMLN ttx_ldsc[TTX_MAXL] = { 0 }; /* line descriptors */
TMXR ttx_desc = { 1, 0, 0, ttx_ldsc }; /* mux descriptor */
#define ttx_lines ttx_desc.lines /* current number of lines */
uint32 ttix_done = 0; /* input flags */
uint32 ttox_done = 0; /* output flags */
uint8 ttix_buf[TTX_MAXL] = { 0 }; /* input buffers */
uint8 ttox_buf[TTX_MAXL] = { 0 }; /* output buffers */
TMLN ttx_ldsc[TTX_MAXL] = { 0 }; /* line descriptors */
TMXR ttx_desc = { 1, 0, 0, ttx_ldsc }; /* mux descriptor */
#define ttx_lines ttx_desc.lines /* current number of lines */
extern int32 int_hwre[API_HLVL+1];
extern int32 tmxr_poll;
@@ -82,113 +84,126 @@ void ttx_reset_ln (int32 i);
t_stat ttx_summ (FILE *st, UNIT *uptr, int32 val, void *desc);
t_stat ttx_show (FILE *st, UNIT *uptr, int32 val, void *desc);
t_stat ttx_vlines (UNIT *uptr, int32 val, char *cptr, void *desc);
/* TTIx data structures
ttix_dev TTIx device descriptor
ttix_unit TTIx unit descriptor
ttix_reg TTIx register list
ttix_mod TTIx modifiers list
ttix_dev TTIx device descriptor
ttix_unit TTIx unit descriptor
ttix_reg TTIx register list
ttix_mod TTIx modifiers list
*/
DIB ttix_dib = { DEV_TTO1, 8, NULL,
{ &ttox, &ttix, &ttox, &ttix, &ttox, &ttix, &ttox, &ttix } };
DIB ttix_dib = {
DEV_TTO1, 8, NULL,
{ &ttox, &ttix, &ttox, &ttix, &ttox, &ttix, &ttox, &ttix }
};
UNIT ttix_unit = { UDATA (&ttix_svc, UNIT_ATTABLE, 0), KBD_POLL_WAIT };
REG ttx_nlreg = { DRDATA (NLINES, ttx_lines, 4), PV_LEFT };
REG ttix_reg[] = {
{ BRDATA (BUF, ttix_buf, 8, 8, TTX_MAXL) },
{ ORDATA (DONE, ttix_done, TTX_MAXL) },
{ FLDATA (INT, int_hwre[API_TTI1], INT_V_TTI1) },
{ DRDATA (TIME, ttix_unit.wait, 24), REG_NZ + PV_LEFT },
{ ORDATA (DEVNUM, ttix_dib.dev, 6), REG_HRO },
{ NULL } };
{ BRDATA (BUF, ttix_buf, 8, 8, TTX_MAXL) },
{ ORDATA (DONE, ttix_done, TTX_MAXL) },
{ FLDATA (INT, int_hwre[API_TTI1], INT_V_TTI1) },
{ DRDATA (TIME, ttix_unit.wait, 24), REG_NZ + PV_LEFT },
{ ORDATA (DEVNUM, ttix_dib.dev, 6), REG_HRO },
{ NULL }
};
MTAB ttix_mod[] = {
{ MTAB_XTD | MTAB_VDV | MTAB_VAL, 0, "lines", "LINES",
&ttx_vlines, NULL, &ttx_nlreg },
{ UNIT_ATT, UNIT_ATT, "summary", NULL, NULL, &ttx_summ },
{ MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT",
&tmxr_dscln, NULL, &ttx_desc },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL,
NULL, &ttx_show, NULL },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL,
NULL, &ttx_show, NULL },
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
&set_devno, &show_devno, NULL },
{ MTAB_XTD|MTAB_VUN|MTAB_NC, 0, "LOG", "LOG",
&tmxr_set_log, &tmxr_show_log, &ttx_desc },
{ MTAB_XTD|MTAB_VUN|MTAB_NC, 0, NULL, "NOLOG",
&tmxr_set_nolog, NULL, &ttx_desc },
{ 0 } };
{ MTAB_XTD | MTAB_VDV | MTAB_VAL, 0, "lines", "LINES",
&ttx_vlines, NULL, &ttx_nlreg },
{ UNIT_ATT, UNIT_ATT, "summary", NULL, NULL, &ttx_summ },
{ MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT",
&tmxr_dscln, NULL, &ttx_desc },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL,
NULL, &ttx_show, NULL },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL,
NULL, &ttx_show, NULL },
{ MTAB_XTD|MTAB_VDV, 0, "DEVNO", "DEVNO",
&set_devno, &show_devno, NULL },
{ 0 }
};
DEVICE tti1_dev = {
"TTIX", &ttix_unit, ttix_reg, ttix_mod,
1, 10, 31, 1, 8, 8,
&tmxr_ex, &tmxr_dep, &ttx_reset,
NULL, &ttx_attach, &ttx_detach,
&ttix_dib, DEV_NET | DEV_DISABLE };
"TTIX", &ttix_unit, ttix_reg, ttix_mod,
1, 10, 31, 1, 8, 8,
&tmxr_ex, &tmxr_dep, &ttx_reset,
NULL, &ttx_attach, &ttx_detach,
&ttix_dib, DEV_NET | DEV_DISABLE
};
/* TTOx data structures
ttox_dev TTOx device descriptor
ttox_unit TTOx unit descriptor
ttox_reg TTOx register list
ttox_dev TTOx device descriptor
ttox_unit TTOx unit descriptor
ttox_reg TTOx register list
*/
UNIT ttox_unit[] = {
{ UDATA (&ttox_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT } };
{ UDATA (&ttox_svc, UNIT_KSR, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT },
{ UDATA (&ttox_svc, UNIT_KSR+UNIT_DIS, 0), SERIAL_OUT_WAIT }
};
REG ttox_reg[] = {
{ BRDATA (BUF, ttox_buf, 8, 8, TTX_MAXL) },
{ ORDATA (DONE, ttox_done, TTX_MAXL) },
{ FLDATA (INT, int_hwre[API_TTO1], INT_V_TTO1) },
{ URDATA (TIME, ttox_unit[0].wait, 10, 24, 0,
TTX_MAXL, PV_LEFT) },
{ NULL } };
{ BRDATA (BUF, ttox_buf, 8, 8, TTX_MAXL) },
{ ORDATA (DONE, ttox_done, TTX_MAXL) },
{ FLDATA (INT, int_hwre[API_TTO1], INT_V_TTO1) },
{ URDATA (TIME, ttox_unit[0].wait, 10, 24, 0,
TTX_MAXL, PV_LEFT) },
{ NULL }
};
MTAB ttox_mod[] = {
{ UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", NULL },
{ UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , NULL },
{ UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , NULL },
{ 0 } };
{ UNIT_KSR+UNIT_8B, UNIT_KSR, "KSR", "KSR", NULL },
{ UNIT_KSR+UNIT_8B, 0 , "7b" , "7B" , NULL },
{ UNIT_KSR+UNIT_8B, UNIT_8B , "8b" , "8B" , NULL },
{ MTAB_XTD|MTAB_VUN, 0, NULL, "DISCONNECT",
&tmxr_dscln, NULL, &ttx_desc },
{ MTAB_XTD|MTAB_VUN|MTAB_NC, 0, "LOG", "LOG",
&tmxr_set_log, &tmxr_show_log, &ttx_desc },
{ MTAB_XTD|MTAB_VUN|MTAB_NC, 0, NULL, "NOLOG",
&tmxr_set_nolog, NULL, &ttx_desc },
{ 0 }
};
DEVICE tto1_dev = {
"TTOX", ttox_unit, ttox_reg, ttox_mod,
TTX_MAXL, 10, 31, 1, 8, 8,
NULL, NULL, &ttx_reset,
NULL, NULL, NULL,
NULL, DEV_DISABLE };
"TTOX", ttox_unit, ttox_reg, ttox_mod,
TTX_MAXL, 10, 31, 1, 8, 8,
NULL, NULL, &ttx_reset,
NULL, NULL, NULL,
NULL, DEV_DISABLE
};
/* Terminal input: IOT routine */
int32 ttix (int32 dev, int32 pulse, int32 dat)
{
int32 ln = ttx_getln (dev, pulse); /* line # */
int32 ln = ttx_getln (dev, pulse); /* line # */
if (ln > ttx_lines) return dat;
if (pulse & 001) { /* KSF1 */
if (ttix_test_done (ln)) dat = dat | IOT_SKP; }
if (pulse & 002) { /* KRB1 */
ttix_clr_done (ln); /* clear flag */
dat = dat | ttix_buf[ln]; } /* return buffer */
if (pulse & 001) { /* KSF1 */
if (ttix_test_done (ln)) dat = dat | IOT_SKP;
}
if (pulse & 002) { /* KRB1 */
ttix_clr_done (ln); /* clear flag */
dat = dat | ttix_buf[ln]; /* return buffer */
}
return dat;
}
@@ -198,22 +213,26 @@ t_stat ttix_svc (UNIT *uptr)
{
int32 ln, c, temp;
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */
sim_activate (uptr, tmxr_poll); /* continue poll */
ln = tmxr_poll_conn (&ttx_desc); /* look for connect */
if (ln >= 0) ttx_ldsc[ln].rcve = 1; /* got one? rcv enab */
tmxr_poll_rx (&ttx_desc); /* poll for input */
for (ln = 0; ln < TTX_MAXL; ln++) { /* loop thru lines */
if (ttx_ldsc[ln].conn) { /* connected? */
if (temp = tmxr_getc_ln (&ttx_ldsc[ln])) { /* get char */
if (temp & SCPE_BREAK) c = 0; /* break? */
else if (ttox_unit[ln].flags & UNIT_KSR) { /* KSR? */
c = temp & 0177;
if (islower (c)) c = toupper (c);
c = c | 0200; }
else c = temp & ((ttox_unit[ln].flags & UNIT_8B)? 0377: 0177);
ttix_buf[ln] = c;
ttix_set_done (ln); } } }
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */
sim_activate (uptr, tmxr_poll); /* continue poll */
ln = tmxr_poll_conn (&ttx_desc); /* look for connect */
if (ln >= 0) ttx_ldsc[ln].rcve = 1; /* got one? rcv enab */
tmxr_poll_rx (&ttx_desc); /* poll for input */
for (ln = 0; ln < TTX_MAXL; ln++) { /* loop thru lines */
if (ttx_ldsc[ln].conn) { /* connected? */
if (temp = tmxr_getc_ln (&ttx_ldsc[ln])) { /* get char */
if (temp & SCPE_BREAK) c = 0; /* break? */
else if (ttox_unit[ln].flags & UNIT_KSR) { /* KSR? */
c = temp & 0177;
if (islower (c)) c = toupper (c);
c = c | 0200;
}
else c = temp & ((ttox_unit[ln].flags & UNIT_8B)? 0377: 0177);
ttix_buf[ln] = c;
ttix_set_done (ln);
}
}
}
return SCPE_OK;
}
@@ -236,23 +255,27 @@ void ttix_clr_done (int32 ln)
{
ttix_done = ttix_done & ~(1 << ln);
if (ttix_done) { SET_INT (TTI1); }
else { CLR_INT (TTI1); }
else {
CLR_INT (TTI1);
}
return;
}
/* Terminal output: IOT routine */
int32 ttox (int32 dev, int32 pulse, int32 dat)
{
int32 ln = ttx_getln (dev, pulse); /* line # */
int32 ln = ttx_getln (dev, pulse); /* line # */
if (ln > ttx_lines) return dat;
if (pulse & 001) { /* TSF */
if (ttox_test_done (ln)) dat = dat | IOT_SKP; }
if (pulse & 002) ttox_clr_done (ln); /* clear flag */
if (pulse & 004) { /* load buffer */
sim_activate (&ttox_unit[ln], ttox_unit[ln].wait); /* activate unit */
ttox_buf[ln] = dat & 0377; } /* load buffer */
if (pulse & 001) { /* TSF */
if (ttox_test_done (ln)) dat = dat | IOT_SKP;
}
if (pulse & 002) ttox_clr_done (ln); /* clear flag */
if (pulse & 004) { /* load buffer */
sim_activate (&ttox_unit[ln], ttox_unit[ln].wait); /* activate unit */
ttox_buf[ln] = dat & 0377; /* load buffer */
}
return dat;
}
@@ -260,23 +283,27 @@ return dat;
t_stat ttox_svc (UNIT *uptr)
{
int32 c, ln = uptr - ttox_unit; /* line # */
int32 c, ln = uptr - ttox_unit; /* line # */
if (ttx_ldsc[ln].conn) { /* connected? */
if (ttx_ldsc[ln].xmte) { /* tx enabled? */
TMLN *lp = &ttx_ldsc[ln]; /* get line */
if (ttox_unit[ln].flags & UNIT_KSR) { /* KSR mode? */
c = ttox_buf[ln] & 0177; /* get char */
if (islower (c)) c = toupper (c);
if ((c < 007) || (c > 0137)) c = -1; }
else c = ttox_buf[ln] & ((ttox_unit[ln].flags & UNIT_8B)? 0377: 0177);
if (c >= 0) tmxr_putc_ln (lp, c); /* output char */
tmxr_poll_tx (&ttx_desc); } /* poll xmt */
else {
tmxr_poll_tx (&ttx_desc); /* poll xmt */
sim_activate (uptr, ttox_unit[ln].wait); /* wait */
return SCPE_OK; } }
ttox_set_done (ln); /* set done */
if (ttx_ldsc[ln].conn) { /* connected? */
if (ttx_ldsc[ln].xmte) { /* tx enabled? */
TMLN *lp = &ttx_ldsc[ln]; /* get line */
if (ttox_unit[ln].flags & UNIT_KSR) { /* KSR mode? */
c = ttox_buf[ln] & 0177; /* get char */
if (islower (c)) c = toupper (c);
if ((c < 007) || (c > 0137)) c = -1;
}
else c = ttox_buf[ln] & ((ttox_unit[ln].flags & UNIT_8B)? 0377: 0177);
if (c >= 0) tmxr_putc_ln (lp, c); /* output char */
tmxr_poll_tx (&ttx_desc); /* poll xmt */
}
else {
tmxr_poll_tx (&ttx_desc); /* poll xmt */
sim_activate (uptr, ttox_unit[ln].wait); /* wait */
return SCPE_OK;
}
}
ttox_set_done (ln); /* set done */
return SCPE_OK;
}
@@ -299,10 +326,10 @@ void ttox_clr_done (int32 ln)
{
ttox_done = ttox_done & ~(1 << ln);
if (ttox_done) { SET_INT (TTO1); }
else { CLR_INT (TTO1); }
else { CLR_INT (TTO1); }
return;
}
/* Compute relative line number
This algorithm does not assign contiguous line numbers of ascending
@@ -313,11 +340,11 @@ int32 ttx_getln (int32 dev, int32 pulse)
{
int32 rdno = ((dev - ttix_dib.dev) >> 1) & 3;
#if defined (PDP15) /* PDP-15? */
#if defined (PDP15) /* PDP-15? */
int32 sub = (pulse >> 4) & 3;
return (rdno * 4) + sub; /* use dev, subdev */
#else /* others */
return rdno; /* use dev only */
return (rdno * 4) + sub; /* use dev, subdev */
#else /* others */
return rdno; /* use dev only */
#endif
}
@@ -327,15 +354,18 @@ t_stat ttx_reset (DEVICE *dptr)
{
int32 ln;
if (dptr->flags & DEV_DIS) { /* sync enables */
ttix_dev.flags = ttox_dev.flags | DEV_DIS;
ttox_dev.flags = ttox_dev.flags | DEV_DIS; }
else { ttix_dev.flags = ttix_dev.flags & ~DEV_DIS;
ttox_dev.flags = ttox_dev.flags & ~DEV_DIS; }
if (ttix_unit.flags & UNIT_ATT) /* if attached, */
sim_activate (&ttix_unit, tmxr_poll); /* activate */
else sim_cancel (&ttix_unit); /* else stop */
for (ln = 0; ln < TTX_MAXL; ln++) ttx_reset_ln (ln); /* for all lines */
if (dptr->flags & DEV_DIS) { /* sync enables */
ttix_dev.flags = ttox_dev.flags | DEV_DIS;
ttox_dev.flags = ttox_dev.flags | DEV_DIS;
}
else {
ttix_dev.flags = ttix_dev.flags & ~DEV_DIS;
ttox_dev.flags = ttox_dev.flags & ~DEV_DIS;
}
if (ttix_unit.flags & UNIT_ATT) /* if attached, */
sim_activate (&ttix_unit, tmxr_poll); /* activate */
else sim_cancel (&ttix_unit); /* else stop */
for (ln = 0; ln < TTX_MAXL; ln++) ttx_reset_ln (ln); /* for all lines */
return SCPE_OK;
}
@@ -343,11 +373,11 @@ return SCPE_OK;
void ttx_reset_ln (int32 ln)
{
ttix_buf[ln] = 0; /* clear buf, */
ttix_buf[ln] = 0; /* clear buf, */
ttox_buf[ln] = 0;
ttix_clr_done (ln); /* clear done */
ttix_clr_done (ln); /* clear done */
ttox_clr_done (ln);
sim_cancel (&ttox_unit[ln]); /* stop poll */
sim_cancel (&ttox_unit[ln]); /* stop poll */
return;
}
@@ -357,9 +387,9 @@ t_stat ttx_attach (UNIT *uptr, char *cptr)
{
t_stat r;
r = tmxr_attach (&ttx_desc, uptr, cptr); /* attach */
if (r != SCPE_OK) return r; /* error */
sim_activate (uptr, tmxr_poll); /* start poll */
r = tmxr_attach (&ttx_desc, uptr, cptr); /* attach */
if (r != SCPE_OK) return r; /* error */
sim_activate (uptr, tmxr_poll); /* start poll */
return SCPE_OK;
}
@@ -370,9 +400,9 @@ t_stat ttx_detach (UNIT *uptr)
int32 i;
t_stat r;
r = tmxr_detach (&ttx_desc, uptr); /* detach */
sim_cancel (uptr); /* stop poll */
for (i = 0; i < TTX_MAXL; i++) ttx_ldsc[i].rcve = 0; /* disable rcv */
r = tmxr_detach (&ttx_desc, uptr); /* detach */
sim_cancel (uptr); /* stop poll */
for (i = 0; i < TTX_MAXL; i++) ttx_ldsc[i].rcve = 0; /* disable rcv */
return r;
}
@@ -392,14 +422,17 @@ return SCPE_OK;
t_stat ttx_show (FILE *st, UNIT *uptr, int32 val, void *desc)
{
int32 i;
int32 i, t;
for (i = 0; (i < ttx_lines) && (ttx_ldsc[i].conn == 0); i++) ;
if (i < ttx_lines) {
for (i = 0; i < ttx_lines; i++) {
if (ttx_ldsc[i].conn)
if (val) tmxr_fconns (st, &ttx_ldsc[i], i);
else tmxr_fstats (st, &ttx_ldsc[i], i); } }
for (i = t = 0; i < TTX_MAXL; i++) t = t + (ttx_ldsc[i].conn != 0);
if (t) {
for (i = 0; i < ttx_lines; i++) {
if (ttx_ldsc[i].conn) {
if (val) tmxr_fconns (st, &ttx_ldsc[i], i);
else tmxr_fstats (st, &ttx_ldsc[i], i);
}
}
}
else fprintf (st, "all disconnected\n");
return SCPE_OK;
}
@@ -416,20 +449,24 @@ newln = get_uint (cptr, 10, TTX_MAXL, &r);
if ((r != SCPE_OK) || (newln == ttx_lines)) return r;
if (newln == 0) return SCPE_ARG;
if (newln < ttx_lines) {
for (i = newln, t = 0; i < ttx_lines; i++) t = t | ttx_ldsc[i].conn;
if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE))
return SCPE_OK;
for (i = newln; i < ttx_lines; i++) {
if (ttx_ldsc[i].conn) {
tmxr_linemsg (&ttx_ldsc[i], "\r\nOperator disconnected line\r\n");
tmxr_reset_ln (&ttx_ldsc[i]); } /* reset line */
ttox_unit[i].flags = ttox_unit[i].flags | UNIT_DIS;
ttx_reset_ln (i); }
}
else { for (i = ttx_lines; i < newln; i++) {
ttox_unit[i].flags = ttox_unit[i].flags & ~UNIT_DIS;
ttx_reset_ln (i); }
}
for (i = newln, t = 0; i < ttx_lines; i++) t = t | ttx_ldsc[i].conn;
if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE))
return SCPE_OK;
for (i = newln; i < ttx_lines; i++) {
if (ttx_ldsc[i].conn) {
tmxr_linemsg (&ttx_ldsc[i], "\r\nOperator disconnected line\r\n");
tmxr_reset_ln (&ttx_ldsc[i]); /* reset line */
}
ttox_unit[i].flags = ttox_unit[i].flags | UNIT_DIS;
ttx_reset_ln (i);
}
}
else {
for (i = ttx_lines; i < newln; i++) {
ttox_unit[i].flags = ttox_unit[i].flags & ~UNIT_DIS;
ttx_reset_ln (i);
}
}
ttx_lines = newln;
return SCPE_OK;
}