1
0
mirror of https://github.com/simh/simh.git synced 2026-03-30 19:15:45 +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 @@
/* sds_defs.h: SDS 940 simulator definitions
Copyright (c) 2001-2004, Robert M. Supnik
Copyright (c) 2001-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,377 +19,381 @@
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.
25-Apr-03 RMS Revised for extended file support
25-Apr-03 RMS Revised for extended file support
*/
#include "sim_defs.h" /* simulator defns */
#ifndef _SDS_DEFS_H_
#define _SDS_DEFS_H_ 0
#include "sim_defs.h" /* simulator defns */
/* Simulator stop codes */
#define STOP_IONRDY 1 /* I/O dev not ready */
#define STOP_HALT 2 /* HALT */
#define STOP_IBKPT 3 /* breakpoint */
#define STOP_INVDEV 4 /* invalid dev */
#define STOP_INVINS 5 /* invalid instr */
#define STOP_INVIOP 6 /* invalid I/O op */
#define STOP_INDLIM 7 /* indirect limit */
#define STOP_EXULIM 8 /* EXU limit */
#define STOP_MMINT 9 /* mm in intr */
#define STOP_MMTRP 10 /* mm in trap */
#define STOP_TRPINS 11 /* trap inst not BRM */
#define STOP_RTCINS 12 /* rtc inst not MIN/SKR */
#define STOP_ILLVEC 13 /* zero vector */
#define STOP_CCT 14 /* runaway CCT */
#define STOP_IONRDY 1 /* I/O dev not ready */
#define STOP_HALT 2 /* HALT */
#define STOP_IBKPT 3 /* breakpoint */
#define STOP_INVDEV 4 /* invalid dev */
#define STOP_INVINS 5 /* invalid instr */
#define STOP_INVIOP 6 /* invalid I/O op */
#define STOP_INDLIM 7 /* indirect limit */
#define STOP_EXULIM 8 /* EXU limit */
#define STOP_MMINT 9 /* mm in intr */
#define STOP_MMTRP 10 /* mm in trap */
#define STOP_TRPINS 11 /* trap inst not BRM */
#define STOP_RTCINS 12 /* rtc inst not MIN/SKR */
#define STOP_ILLVEC 13 /* zero vector */
#define STOP_CCT 14 /* runaway CCT */
/* Trap codes */
#define MM_PRVINS -040 /* privileged */
#define MM_NOACC -041 /* no access */
#define MM_WRITE -043 /* write protect */
#define MM_MONUSR -044 /* mon to user */
#define MM_PRVINS -040 /* privileged */
#define MM_NOACC -041 /* no access */
#define MM_WRITE -043 /* write protect */
#define MM_MONUSR -044 /* mon to user */
/* Conditional error returns */
#define CRETINS return ((stop_invins)? STOP_INVINS: SCPE_OK)
#define CRETDEV return ((stop_invdev)? STOP_INVDEV: SCPE_OK)
#define CRETIOP return ((stop_inviop)? STOP_INVIOP: SCPE_OK)
#define CRETIOE(f,c) return ((f)? c: SCPE_OK)
#define CRETINS return ((stop_invins)? STOP_INVINS: SCPE_OK)
#define CRETDEV return ((stop_invdev)? STOP_INVDEV: SCPE_OK)
#define CRETIOP return ((stop_inviop)? STOP_INVIOP: SCPE_OK)
#define CRETIOE(f,c) return ((f)? c: SCPE_OK)
/* Architectural constants */
#define SIGN 040000000 /* sign */
#define DMASK 077777777 /* data mask */
#define EXPS 0400 /* exp sign */
#define EXPMASK 0777 /* exp mask */
#define SXT(x) ((int32) (((x) & SIGN)? ((x) | ~DMASK): \
((x) & DMASK)))
#define SXT_EXP(x) ((int32) (((x) & EXPS)? ((x) | ~EXPMASK): \
((x) & EXPMASK)))
#define SIGN 040000000 /* sign */
#define DMASK 077777777 /* data mask */
#define EXPS 0400 /* exp sign */
#define EXPMASK 0777 /* exp mask */
#define SXT(x) ((int32) (((x) & SIGN)? ((x) | ~DMASK): \
((x) & DMASK)))
#define SXT_EXP(x) ((int32) (((x) & EXPS)? ((x) | ~EXPMASK): \
((x) & EXPMASK)))
/* Memory */
#define MAXMEMSIZE (1 << 16) /* max memory size */
#define PAMASK (MAXMEMSIZE - 1) /* physical addr mask */
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE)
#define ReadP(x) M[x]
#define WriteP(x,y) if (MEM_ADDR_OK (x)) M[x] = y
#define MAXMEMSIZE (1 << 16) /* max memory size */
#define PAMASK (MAXMEMSIZE - 1) /* physical addr mask */
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE)
#define ReadP(x) M[x]
#define WriteP(x,y) if (MEM_ADDR_OK (x)) M[x] = y
/* Virtual addressing */
#define VA_SIZE (1 << 14) /* virtual addr size */
#define VA_MASK (VA_SIZE - 1) /* virtual addr mask */
#define VA_V_PN 11 /* page number */
#define VA_M_PN 07
#define VA_GETPN(x) (((x) >> VA_V_PN) & VA_M_PN)
#define VA_POFF ((1 << VA_V_PN) - 1) /* offset */
#define VA_USR (I_USR) /* user flag in addr */
#define XVA_MASK (VA_USR | VA_MASK)
#define VA_SIZE (1 << 14) /* virtual addr size */
#define VA_MASK (VA_SIZE - 1) /* virtual addr mask */
#define VA_V_PN 11 /* page number */
#define VA_M_PN 07
#define VA_GETPN(x) (((x) >> VA_V_PN) & VA_M_PN)
#define VA_POFF ((1 << VA_V_PN) - 1) /* offset */
#define VA_USR (I_USR) /* user flag in addr */
#define XVA_MASK (VA_USR | VA_MASK)
/* Arithmetic */
#define TSTS(x) ((x) & SIGN)
#define NEG(x) (-((int32) (x)) & DMASK)
#define ABS(x) (TSTS (x)? NEG(x): (x))
#define TSTS(x) ((x) & SIGN)
#define NEG(x) (-((int32) (x)) & DMASK)
#define ABS(x) (TSTS (x)? NEG(x): (x))
/* Memory map */
#define MAP_PROT (040 << VA_V_PN) /* protected */
#define MAP_PAGE (037 << VA_V_PN) /* phys page number */
#define MAP_PROT (040 << VA_V_PN) /* protected */
#define MAP_PAGE (037 << VA_V_PN) /* phys page number */
/* Instruction format */
#define I_USR (1 << 23) /* user */
#define I_IDX (1 << 22) /* indexed */
#define I_POP (1 << 21) /* programmed op */
#define I_V_TAG 21 /* tag */
#define I_V_OP 15 /* opcode */
#define I_M_OP 077
#define I_GETOP(x) (((x) >> I_V_OP) & I_M_OP)
#define I_IND (1 << 14) /* indirect */
#define I_V_SHFOP 11 /* shift op */
#define I_M_SHFOP 07
#define I_GETSHFOP(x) (((x) >> I_V_SHFOP) & I_M_SHFOP)
#define I_SHFMSK 0777 /* shift count */
#define I_V_IOMD 12 /* IO inst mode */
#define I_M_IOMD 03
#define I_GETIOMD(x) (((x) >> I_V_IOMD) & I_M_IOMD)
#define I_V_SKCND 7 /* SKS skip cond */
#define I_M_SKCND 037
#define I_GETSKCND(x) (((x) >> I_V_SKCND) & I_M_SKCND)
#define I_EOB2 000400000 /* chan# bit 2 */
#define I_SKB2 000040000 /* skschan# bit 2 */
#define I_EOB1 020000000 /* chan# bit 1 */
#define I_EOB0 000000100 /* chan# bit 0 */
#define I_GETEOCH(x) ((((x) & I_EOB2)? 4: 0) | \
(((x) & I_EOB1)? 2: 0) | \
(((x) & I_EOB0)? 1: 0))
#define I_SETEOCH(x) ((((x) & 4)? I_EOB2: 0) | \
(((x) & 2)? I_EOB1: 0) | \
(((x) & 1)? I_EOB0: 0))
#define I_GETSKCH(x) ((((x) & I_SKB2)? 4: 0) | \
(((x) & I_EOB1)? 2: 0) | \
(((x) & I_EOB0)? 1: 0))
#define I_SETSKCH(x) ((((x) & 4)? I_SKB2: 0) | \
(((x) & 2)? I_EOB1: 0) | \
(((x) & 1)? I_EOB0: 0))
#define I_USR (1 << 23) /* user */
#define I_IDX (1 << 22) /* indexed */
#define I_POP (1 << 21) /* programmed op */
#define I_V_TAG 21 /* tag */
#define I_V_OP 15 /* opcode */
#define I_M_OP 077
#define I_GETOP(x) (((x) >> I_V_OP) & I_M_OP)
#define I_IND (1 << 14) /* indirect */
#define I_V_SHFOP 11 /* shift op */
#define I_M_SHFOP 07
#define I_GETSHFOP(x) (((x) >> I_V_SHFOP) & I_M_SHFOP)
#define I_SHFMSK 0777 /* shift count */
#define I_V_IOMD 12 /* IO inst mode */
#define I_M_IOMD 03
#define I_GETIOMD(x) (((x) >> I_V_IOMD) & I_M_IOMD)
#define I_V_SKCND 7 /* SKS skip cond */
#define I_M_SKCND 037
#define I_GETSKCND(x) (((x) >> I_V_SKCND) & I_M_SKCND)
#define I_EOB2 000400000 /* chan# bit 2 */
#define I_SKB2 000040000 /* skschan# bit 2 */
#define I_EOB1 020000000 /* chan# bit 1 */
#define I_EOB0 000000100 /* chan# bit 0 */
#define I_GETEOCH(x) ((((x) & I_EOB2)? 4: 0) | \
(((x) & I_EOB1)? 2: 0) | \
(((x) & I_EOB0)? 1: 0))
#define I_SETEOCH(x) ((((x) & 4)? I_EOB2: 0) | \
(((x) & 2)? I_EOB1: 0) | \
(((x) & 1)? I_EOB0: 0))
#define I_GETSKCH(x) ((((x) & I_SKB2)? 4: 0) | \
(((x) & I_EOB1)? 2: 0) | \
(((x) & I_EOB0)? 1: 0))
#define I_SETSKCH(x) ((((x) & 4)? I_SKB2: 0) | \
(((x) & 2)? I_EOB1: 0) | \
(((x) & 1)? I_EOB0: 0))
/* Globally visible flags */
#define UNIT_V_GENIE (UNIT_V_UF + 0)
#define UNIT_GENIE (1 << UNIT_V_GENIE)
#define UNIT_V_GENIE (UNIT_V_UF + 0)
#define UNIT_GENIE (1 << UNIT_V_GENIE)
/* Timers */
#define TMR_RTC 0 /* clock */
#define TMR_MUX 1 /* mux */
#define TMR_RTC 0 /* clock */
#define TMR_MUX 1 /* mux */
/* I/O routine functions */
#define IO_CONN 0 /* connect */
#define IO_EOM1 1 /* EOM mode 1 */
#define IO_DISC 2 /* disconnect */
#define IO_READ 3 /* read */
#define IO_WRITE 4 /* write */
#define IO_WREOR 5 /* write eor */
#define IO_SKS 6 /* skip signal */
#define IO_CONN 0 /* connect */
#define IO_EOM1 1 /* EOM mode 1 */
#define IO_DISC 2 /* disconnect */
#define IO_READ 3 /* read */
#define IO_WRITE 4 /* write */
#define IO_WREOR 5 /* write eor */
#define IO_SKS 6 /* skip signal */
/* Dispatch template */
struct sdsdspt {
uint32 num; /* # entries */
uint32 off; /* offset from base */
};
uint32 num; /* # entries */
uint32 off; /* offset from base */
};
typedef struct sdsdspt DSPT;
/* Device information block */
struct sdsdib {
int32 chan; /* channel */
int32 dev; /* base dev no */
int32 xfr; /* xfer flag */
DSPT *tplt; /* dispatch templates */
t_stat (*iop) (uint32 fnc, uint32 dev, uint32 *dat);
};
int32 chan; /* channel */
int32 dev; /* base dev no */
int32 xfr; /* xfer flag */
DSPT *tplt; /* dispatch templates */
t_stat (*iop) (uint32 fnc, uint32 dev, uint32 *dat);
};
typedef struct sdsdib DIB;
/* Channels */
#define NUM_CHAN 8 /* max num chan */
#define CHAN_W 0 /* TMCC */
#define CHAN_Y 1
#define CHAN_C 2
#define CHAN_D 3
#define CHAN_E 4 /* DACC */
#define CHAN_F 5
#define CHAN_G 6
#define CHAN_H 7
#define NUM_CHAN 8 /* max num chan */
#define CHAN_W 0 /* TMCC */
#define CHAN_Y 1
#define CHAN_C 2
#define CHAN_D 3
#define CHAN_E 4 /* DACC */
#define CHAN_F 5
#define CHAN_G 6
#define CHAN_H 7
/* I/O control EOM */
#define CHC_REV 04000 /* reverse */
#define CHC_NLDR 02000 /* no leader */
#define CHC_BIN 01000 /* binary */
#define CHC_V_CPW 7 /* char/word */
#define CHC_M_CPW 03
#define CHC_GETCPW(x) (((x) >> CHC_V_CPW) & CHC_M_CPW)
#define CHC_REV 04000 /* reverse */
#define CHC_NLDR 02000 /* no leader */
#define CHC_BIN 01000 /* binary */
#define CHC_V_CPW 7 /* char/word */
#define CHC_M_CPW 03
#define CHC_GETCPW(x) (((x) >> CHC_V_CPW) & CHC_M_CPW)
/* Buffer control (extended) EOM */
#define CHM_CE 04000 /* compat/ext */
#define CHM_ER 02000 /* end rec int */
#define CHM_ZC 01000 /* zero wc int */
#define CHM_V_FNC 7 /* term func */
#define CHM_M_FNC 03
#define CHM_GETFNC(x) (((x) & CHM_CE)? (((x) >> CHM_V_FNC) & CHM_M_FNC): CHM_COMP)
#define CHM_IORD 0 /* record, disc */
#define CHM_IOSD 1 /* signal, disc */
#define CHM_IORP 2 /* record, proc */
#define CHM_IOSP 3 /* signal, proc */
#define CHM_COMP 5 /* compatible */
#define CHM_SGNL 1 /* signal bit */
#define CHM_PROC 2 /* proceed bit */
#define CHM_V_HMA 5 /* hi mem addr */
#define CHM_M_HMA 03
#define CHM_GETHMA(x) (((x) >> CHM_V_HMA) & CHM_M_HMA)
#define CHM_V_HWC 0 /* hi word count */
#define CHM_M_HWC 037
#define CHM_GETHWC(x) (((x) >> CHM_V_HWC) & CHM_M_HWC)
#define CHM_CE 04000 /* compat/ext */
#define CHM_ER 02000 /* end rec int */
#define CHM_ZC 01000 /* zero wc int */
#define CHM_V_FNC 7 /* term func */
#define CHM_M_FNC 03
#define CHM_GETFNC(x) (((x) & CHM_CE)? (((x) >> CHM_V_FNC) & CHM_M_FNC): CHM_COMP)
#define CHM_IORD 0 /* record, disc */
#define CHM_IOSD 1 /* signal, disc */
#define CHM_IORP 2 /* record, proc */
#define CHM_IOSP 3 /* signal, proc */
#define CHM_COMP 5 /* compatible */
#define CHM_SGNL 1 /* signal bit */
#define CHM_PROC 2 /* proceed bit */
#define CHM_V_HMA 5 /* hi mem addr */
#define CHM_M_HMA 03
#define CHM_GETHMA(x) (((x) >> CHM_V_HMA) & CHM_M_HMA)
#define CHM_V_HWC 0 /* hi word count */
#define CHM_M_HWC 037
#define CHM_GETHWC(x) (((x) >> CHM_V_HWC) & CHM_M_HWC)
/* Channel flags word */
#define CHF_ERR 00001 /* error */
#define CHF_IREC 00002 /* interrecord */
#define CHF_ILCE 00004 /* interlace */
#define CHF_DCHN 00010 /* data chain */
#define CHF_EOR 00020 /* end of record */
#define CHF_12B 00040 /* 12 bit mode */
#define CHF_24B 00100 /* 24 bit mode */
#define CHF_OWAK 00200 /* output wake */
#define CHF_SCAN 00400 /* scan */
#define CHF_TOP 01000 /* TOP pending */
#define CHF_N_FLG 9 /* <= 16 */
#define CHF_ERR 00001 /* error */
#define CHF_IREC 00002 /* interrecord */
#define CHF_ILCE 00004 /* interlace */
#define CHF_DCHN 00010 /* data chain */
#define CHF_EOR 00020 /* end of record */
#define CHF_12B 00040 /* 12 bit mode */
#define CHF_24B 00100 /* 24 bit mode */
#define CHF_OWAK 00200 /* output wake */
#define CHF_SCAN 00400 /* scan */
#define CHF_TOP 01000 /* TOP pending */
#define CHF_N_FLG 9 /* <= 16 */
/* Interrupts and vectors (0 is reserved), highest bit is highest priority */
#define INT_V_PWRO 31 /* power on */
#define INT_V_PWRF 30 /* power off */
#define INT_V_CPAR 29 /* CPU parity err */
#define INT_V_IPAR 28 /* IO parity err */
#define INT_V_RTCS 27 /* clock sync */
#define INT_V_RTCP 26 /* clock pulse */
#define INT_V_YZWC 25 /* chan Y zero wc */
#define INT_V_WZWC 24 /* chan W zero wc */
#define INT_V_YEOR 23 /* chan Y end rec */
#define INT_V_WEOR 22 /* chan W end rec */
#define INT_V_CZWC 21 /* chan C */
#define INT_V_CEOR 20
#define INT_V_DZWC 19 /* chan D */
#define INT_V_DEOR 18
#define INT_V_EZWC 17 /* chan E */
#define INT_V_EEOR 16
#define INT_V_FZWC 15 /* chan F */
#define INT_V_FEOR 14
#define INT_V_GZWC 13 /* chan G */
#define INT_V_GEOR 12
#define INT_V_HZWC 11 /* chan H */
#define INT_V_HEOR 10
#define INT_V_MUXR 9 /* mux receive */
#define INT_V_MUXT 8 /* mux transmit */
#define INT_V_MUXCO 7 /* SDS carrier on */
#define INT_V_MUXCF 6 /* SDS carrier off */
#define INT_V_DRM 5 /* Genie drum */
#define INT_V_FORK 4 /* fork */
#define INT_V_PWRO 31 /* power on */
#define INT_V_PWRF 30 /* power off */
#define INT_V_CPAR 29 /* CPU parity err */
#define INT_V_IPAR 28 /* IO parity err */
#define INT_V_RTCS 27 /* clock sync */
#define INT_V_RTCP 26 /* clock pulse */
#define INT_V_YZWC 25 /* chan Y zero wc */
#define INT_V_WZWC 24 /* chan W zero wc */
#define INT_V_YEOR 23 /* chan Y end rec */
#define INT_V_WEOR 22 /* chan W end rec */
#define INT_V_CZWC 21 /* chan C */
#define INT_V_CEOR 20
#define INT_V_DZWC 19 /* chan D */
#define INT_V_DEOR 18
#define INT_V_EZWC 17 /* chan E */
#define INT_V_EEOR 16
#define INT_V_FZWC 15 /* chan F */
#define INT_V_FEOR 14
#define INT_V_GZWC 13 /* chan G */
#define INT_V_GEOR 12
#define INT_V_HZWC 11 /* chan H */
#define INT_V_HEOR 10
#define INT_V_MUXR 9 /* mux receive */
#define INT_V_MUXT 8 /* mux transmit */
#define INT_V_MUXCO 7 /* SDS carrier on */
#define INT_V_MUXCF 6 /* SDS carrier off */
#define INT_V_DRM 5 /* Genie drum */
#define INT_V_FORK 4 /* fork */
#define INT_PWRO (1 << INT_V_PWRO)
#define INT_PWRF (1 << INT_V_PWRF)
#define INT_CPAR (1 << INT_V_CPAR)
#define INT_IPAR (1 << INT_V_IPAR)
#define INT_RTCS (1 << INT_V_RTCS)
#define INT_RTCP (1 << INT_V_RTCP)
#define INT_YZWC (1 << INT_V_YZWC)
#define INT_WZWC (1 << INT_V_WZWC)
#define INT_YEOR (1 << INT_V_YEOR)
#define INT_WEOR (1 << INT_V_WEOR)
#define INT_CZWC (1 << INT_V_CZWC)
#define INT_CEOR (1 << INT_V_CEOR)
#define INT_DZWC (1 << INT_V_DZWC)
#define INT_DEOR (1 << INT_V_DEOR)
#define INT_EZWC (1 << INT_V_EZWC)
#define INT_EEOR (1 << INT_V_EEOR)
#define INT_FZWC (1 << INT_V_FZWC)
#define INT_FEOR (1 << INT_V_FEOR)
#define INT_GZWC (1 << INT_V_GZWC)
#define INT_GEOR (1 << INT_V_GEOR)
#define INT_HZWC (1 << INT_V_HZWC)
#define INT_HEOR (1 << INT_V_HEOR)
#define INT_MUXR (1 << INT_V_MUXR)
#define INT_MUXT (1 << INT_V_MUXT)
#define INT_MUXCO (1 << INT_V_MUXCO)
#define INT_MUXCF (1 << INT_V_MUXCF)
#define INT_DRM (1 << INT_V_DRM)
#define INT_FORK (1 << INT_V_FORK)
#define INT_PWRO (1 << INT_V_PWRO)
#define INT_PWRF (1 << INT_V_PWRF)
#define INT_CPAR (1 << INT_V_CPAR)
#define INT_IPAR (1 << INT_V_IPAR)
#define INT_RTCS (1 << INT_V_RTCS)
#define INT_RTCP (1 << INT_V_RTCP)
#define INT_YZWC (1 << INT_V_YZWC)
#define INT_WZWC (1 << INT_V_WZWC)
#define INT_YEOR (1 << INT_V_YEOR)
#define INT_WEOR (1 << INT_V_WEOR)
#define INT_CZWC (1 << INT_V_CZWC)
#define INT_CEOR (1 << INT_V_CEOR)
#define INT_DZWC (1 << INT_V_DZWC)
#define INT_DEOR (1 << INT_V_DEOR)
#define INT_EZWC (1 << INT_V_EZWC)
#define INT_EEOR (1 << INT_V_EEOR)
#define INT_FZWC (1 << INT_V_FZWC)
#define INT_FEOR (1 << INT_V_FEOR)
#define INT_GZWC (1 << INT_V_GZWC)
#define INT_GEOR (1 << INT_V_GEOR)
#define INT_HZWC (1 << INT_V_HZWC)
#define INT_HEOR (1 << INT_V_HEOR)
#define INT_MUXR (1 << INT_V_MUXR)
#define INT_MUXT (1 << INT_V_MUXT)
#define INT_MUXCO (1 << INT_V_MUXCO)
#define INT_MUXCF (1 << INT_V_MUXCF)
#define INT_DRM (1 << INT_V_DRM)
#define INT_FORK (1 << INT_V_FORK)
#define VEC_PWRO 0036
#define VEC_PWRF 0037
#define VEC_CPAR 0056
#define VEC_IPAR 0057
#define VEC_RTCS 0074
#define VEC_RTCP 0075
#define VEC_YZWC 0030
#define VEC_WZWC 0031
#define VEC_YEOR 0032
#define VEC_WEOR 0033
#define VEC_CZWC 0060
#define VEC_CEOR 0061
#define VEC_DZWC 0062
#define VEC_DEOR 0063
#define VEC_EZWC 0064
#define VEC_EEOR 0065
#define VEC_FZWC 0066
#define VEC_FEOR 0067
#define VEC_GZWC 0070
#define VEC_GEOR 0071
#define VEC_HZWC 0072
#define VEC_HEOR 0073
#define VEC_MUXR 0200 /* term mux rcv */
#define VEC_MUXT 0201 /* term mux xmt */
#define VEC_MUXCO 0202 /* SDS: mux carrier on */
#define VEC_MUXCF 0203 /* SDS: mux carrier off */
#define VEC_DRM 0202 /* Genie: drum */
#define VEC_FORK 0216 /* "fork" */
#define VEC_PWRO 0036
#define VEC_PWRF 0037
#define VEC_CPAR 0056
#define VEC_IPAR 0057
#define VEC_RTCS 0074
#define VEC_RTCP 0075
#define VEC_YZWC 0030
#define VEC_WZWC 0031
#define VEC_YEOR 0032
#define VEC_WEOR 0033
#define VEC_CZWC 0060
#define VEC_CEOR 0061
#define VEC_DZWC 0062
#define VEC_DEOR 0063
#define VEC_EZWC 0064
#define VEC_EEOR 0065
#define VEC_FZWC 0066
#define VEC_FEOR 0067
#define VEC_GZWC 0070
#define VEC_GEOR 0071
#define VEC_HZWC 0072
#define VEC_HEOR 0073
#define VEC_MUXR 0200 /* term mux rcv */
#define VEC_MUXT 0201 /* term mux xmt */
#define VEC_MUXCO 0202 /* SDS: mux carrier on */
#define VEC_MUXCF 0203 /* SDS: mux carrier off */
#define VEC_DRM 0202 /* Genie: drum */
#define VEC_FORK 0216 /* "fork" */
/* Device constants */
#define DEV_MASK 077 /* device mask */
#define DEV_TTI 001 /* teletype */
#define DEV_PTR 004 /* paper tape rdr */
#define DEV_MT 010 /* magtape */
#define DEV_RAD 026 /* fixed head disk */
#define DEV_DSK 026 /* moving head disk */
#define DEV_TTO 041 /* teletype */
#define DEV_PTP 044 /* paper tape punch */
#define DEV_LPT 060 /* line printer */
#define DEV_MTS 020 /* MT scan/erase */
#define DEV_OUT 040 /* output flag */
#define DEV3_GDRM 004 /* Genie drum */
#define DEV3_GMUX 001 /* Genie mux */
#define DEV3_SMUX (DEV_MASK) /* standard mux */
#define DEV_MASK 077 /* device mask */
#define DEV_TTI 001 /* teletype */
#define DEV_PTR 004 /* paper tape rdr */
#define DEV_MT 010 /* magtape */
#define DEV_RAD 026 /* fixed head disk */
#define DEV_DSK 026 /* moving head disk */
#define DEV_TTO 041 /* teletype */
#define DEV_PTP 044 /* paper tape punch */
#define DEV_LPT 060 /* line printer */
#define DEV_MTS 020 /* MT scan/erase */
#define DEV_OUT 040 /* output flag */
#define DEV3_GDRM 004 /* Genie drum */
#define DEV3_GMUX 001 /* Genie mux */
#define DEV3_SMUX (DEV_MASK) /* standard mux */
#define LPT_WIDTH 132 /* line print width */
#define CCT_LNT 132 /* car ctrl length */
#define LPT_WIDTH 132 /* line print width */
#define CCT_LNT 132 /* car ctrl length */
/* Transfer request flags for devices (0 is reserved) */
#define XFR_V_TTI 1 /* console */
#define XFR_V_TTO 2
#define XFR_V_PTR 3 /* paper tape */
#define XFR_V_PTP 4
#define XFR_V_LPT 5 /* line printer */
#define XFR_V_RAD 6 /* fixed hd disk */
#define XFR_V_DSK 7 /* mving hd disk */
#define XFR_V_MT0 8 /* magtape */
#define XFR_V_TTI 1 /* console */
#define XFR_V_TTO 2
#define XFR_V_PTR 3 /* paper tape */
#define XFR_V_PTP 4
#define XFR_V_LPT 5 /* line printer */
#define XFR_V_RAD 6 /* fixed hd disk */
#define XFR_V_DSK 7 /* mving hd disk */
#define XFR_V_MT0 8 /* magtape */
#define XFR_TTI (1 << XFR_V_TTI)
#define XFR_TTO (1 << XFR_V_TTO)
#define XFR_PTR (1 << XFR_V_PTR)
#define XFR_PTP (1 << XFR_V_PTP)
#define XFR_LPT (1 << XFR_V_LPT)
#define XFR_RAD (1 << XFR_V_RAD)
#define XFR_DSK (1 << XFR_V_DSK)
#define XFR_MT0 (1 << XFR_V_MT0)
#define XFR_TTI (1 << XFR_V_TTI)
#define XFR_TTO (1 << XFR_V_TTO)
#define XFR_PTR (1 << XFR_V_PTR)
#define XFR_PTP (1 << XFR_V_PTP)
#define XFR_LPT (1 << XFR_V_LPT)
#define XFR_RAD (1 << XFR_V_RAD)
#define XFR_DSK (1 << XFR_V_DSK)
#define XFR_MT0 (1 << XFR_V_MT0)
/* PIN/POT ordinals (0 is reserved) */
#define POT_ILCY 1 /* interlace */
#define POT_DCRY (POT_ILCY + NUM_CHAN) /* data chain */
#define POT_ADRY (POT_DCRY + NUM_CHAN) /* address reg */
#define POT_RL1 (POT_ADRY + NUM_CHAN) /* RL1 */
#define POT_RL2 (POT_RL1 + 1) /* RL2 */
#define POT_RL4 (POT_RL2 + 1) /* RL4 */
#define POT_RADS (POT_RL4 + 1) /* fhd sector */
#define POT_RADA (POT_RADS + 1) /* fhd addr */
#define POT_DSK (POT_RADA + 1) /* mhd sec/addr */
#define POT_SYSI (POT_DSK + 1) /* sys intr */
#define POT_MUX (POT_SYSI + 1) /* multiplexor */
#define POT_ILCY 1 /* interlace */
#define POT_DCRY (POT_ILCY + NUM_CHAN) /* data chain */
#define POT_ADRY (POT_DCRY + NUM_CHAN) /* address reg */
#define POT_RL1 (POT_ADRY + NUM_CHAN) /* RL1 */
#define POT_RL2 (POT_RL1 + 1) /* RL2 */
#define POT_RL4 (POT_RL2 + 1) /* RL4 */
#define POT_RADS (POT_RL4 + 1) /* fhd sector */
#define POT_RADA (POT_RADS + 1) /* fhd addr */
#define POT_DSK (POT_RADA + 1) /* mhd sec/addr */
#define POT_SYSI (POT_DSK + 1) /* sys intr */
#define POT_MUX (POT_SYSI + 1) /* multiplexor */
/* Opcodes */
enum opcodes {
HLT, BRU, EOM, EOD = 006,
MIY = 010, BRI, MIW, POT, ETR, MRG = 016, EOR,
NOP, OVF = 022, EXU,
YIM = 030, WIM = 032, PIN, STA = 035, STB, STX,
SKS, BRX, BRM = 043, RCH = 046,
SKE = 050, BRR, SKB, SKN, SUB, ADD, SUC, ADC,
SKR, MIN, XMA, ADM, MUL, DIV, RSH, LSH,
SKM, LDX, SKA, SKG, SKD, LDB, LDA, EAX };
HLT, BRU, EOM, EOD = 006,
MIY = 010, BRI, MIW, POT, ETR, MRG = 016, EOR,
NOP, OVF = 022, EXU,
YIM = 030, WIM = 032, PIN, STA = 035, STB, STX,
SKS, BRX, BRM = 043, RCH = 046,
SKE = 050, BRR, SKB, SKN, SUB, ADD, SUC, ADC,
SKR, MIN, XMA, ADM, MUL, DIV, RSH, LSH,
SKM, LDX, SKA, SKG, SKD, LDB, LDA, EAX
};
/* Channel function prototypes */
@@ -401,3 +405,5 @@ t_stat set_chan (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat show_chan (FILE *st, UNIT *uptr, int32 val, void *desc);
t_stat chan_process (void);
t_bool chan_testact (void);
#endif

View File

@@ -1,14 +1,14 @@
To: Users
From: Bob Supnik
Subj: SDS 940 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 SDS 940 simulator.
@@ -367,8 +367,7 @@ or a DETACH MUX command.
The SHOW MUX CONNECTIONS command displays the current connections to the
extra terminals. The SHOW MUX STATISTICS command displays statistics for
active connections. The SET MUX DISCONNECT=linenumber disconnects the
specified line.
active connections. The SET MUXLn DISCONNECT command disconnects line n.
The controller (MUX) implements these registers:

View File

@@ -1,6 +1,6 @@
/* sds_drm.c: SDS 940 Project Genie drum simulator
Copyright (c) 2002-2004, Robert M. Supnik
Copyright (c) 2002-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,11 +19,11 @@
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 drum
drm drum
The drum is buffered in memory.
@@ -43,65 +43,65 @@
/* Constants */
#define DRM_N_WD 11 /* word addr width */
#define DRM_V_WD 0 /* position */
#define DRM_M_WD ((1 << DRM_N_WD) - 1) /* word mask */
#define DRM_NUMWD (1 << DRM_N_WD) /* words/sector */
#define DRM_NUMGP 236 /* gap/sector */
#define DRM_PHYWD (DRM_NUMWD + DRM_NUMGP) /* phys wds/sector */
#define DRM_N_SC 3 /* sect addr width */
#define DRM_V_SC (DRM_N_WD) /* position */
#define DRM_M_SC ((1 << DRM_N_SC) - 1) /* sector mask */
#define DRM_NUMSC (1 << DRM_N_SC) /* sectors/track */
#define DRM_N_TR 7 /* track addr width */
#define DRM_V_TR (DRM_N_WD+DRM_N_SC) /* position */
#define DRM_M_TR ((1 << DRM_N_TR) - 1) /* track mask */
#define DRM_NUMTR 84 /* tracks/drum */
#define DRM_N_ADDR (DRM_N_WD+DRM_N_SC+DRM_N_TR) /* drum addr width */
#define DRM_SWMASK ((1 << (DRM_N_WD+DRM_N_SC)) - 1)/* sector+word mask */
#define DRM_DAMASK ((1 << DRM_N_ADDR) - 1) /* drum addr mask */
#define DRM_SIZE (DRM_NUMTR*DRM_NUMSC*DRM_NUMWD) /* words/disk */
#define DRM_WCMASK 037777 /* wc mask */
#define DRM_GETSC(x) (((x) >> DRM_V_SC) & DRM_M_SC)
#define DRM_N_WD 11 /* word addr width */
#define DRM_V_WD 0 /* position */
#define DRM_M_WD ((1 << DRM_N_WD) - 1) /* word mask */
#define DRM_NUMWD (1 << DRM_N_WD) /* words/sector */
#define DRM_NUMGP 236 /* gap/sector */
#define DRM_PHYWD (DRM_NUMWD + DRM_NUMGP) /* phys wds/sector */
#define DRM_N_SC 3 /* sect addr width */
#define DRM_V_SC (DRM_N_WD) /* position */
#define DRM_M_SC ((1 << DRM_N_SC) - 1) /* sector mask */
#define DRM_NUMSC (1 << DRM_N_SC) /* sectors/track */
#define DRM_N_TR 7 /* track addr width */
#define DRM_V_TR (DRM_N_WD+DRM_N_SC) /* position */
#define DRM_M_TR ((1 << DRM_N_TR) - 1) /* track mask */
#define DRM_NUMTR 84 /* tracks/drum */
#define DRM_N_ADDR (DRM_N_WD+DRM_N_SC+DRM_N_TR) /* drum addr width */
#define DRM_SWMASK ((1 << (DRM_N_WD+DRM_N_SC)) - 1)/* sector+word mask */
#define DRM_DAMASK ((1 << DRM_N_ADDR) - 1) /* drum addr mask */
#define DRM_SIZE (DRM_NUMTR*DRM_NUMSC*DRM_NUMWD) /* words/disk */
#define DRM_WCMASK 037777 /* wc mask */
#define DRM_GETSC(x) (((x) >> DRM_V_SC) & DRM_M_SC)
#define DRM_PC 020
#define DRM_AD 021
#define DRM_ADAT (1 << (DRM_N_WD + DRM_N_SC)) /* data flag */
#define DRM_PC 020
#define DRM_AD 021
#define DRM_ADAT (1 << (DRM_N_WD + DRM_N_SC)) /* data flag */
#define DRM_SFET 0 /* fetch state */
#define DRM_SFCA 1 /* fetch CA */
#define DRM_SFDA 2 /* fetch DA */
#define DRM_SXFR 3 /* xfer */
#define DRM_SFET 0 /* fetch state */
#define DRM_SFCA 1 /* fetch CA */
#define DRM_SFDA 2 /* fetch DA */
#define DRM_SXFR 3 /* xfer */
#define DRM_V_OP 21 /* drum op */
#define DRM_M_OP 07
#define DRM_V_RW 20
#define DRM_GETOP(x) (((x) >> DRM_V_OP) & DRM_M_OP)
#define DRM_GETRW(x) (((x) >> DRM_V_RW) & 1)
#define DRM_OXF 0 /* xfer */
#define DRM_OCX 1 /* cond xfer */
#define DRM_OBR 2 /* branch */
#define DRM_ORS 3 /* reset error */
#define DRM_END 4 /* end prog */
#define DRM_EIE 5 /* end int if err */
#define DRM_EIU 7 /* end int uncond */
#define DRM_V_OP 21 /* drum op */
#define DRM_M_OP 07
#define DRM_V_RW 20
#define DRM_GETOP(x) (((x) >> DRM_V_OP) & DRM_M_OP)
#define DRM_GETRW(x) (((x) >> DRM_V_RW) & 1)
#define DRM_OXF 0 /* xfer */
#define DRM_OCX 1 /* cond xfer */
#define DRM_OBR 2 /* branch */
#define DRM_ORS 3 /* reset error */
#define DRM_END 4 /* end prog */
#define DRM_EIE 5 /* end int if err */
#define DRM_EIU 7 /* end int uncond */
#define GET_TWORD(x) ((int32) fmod (sim_gtime() / ((double) (x)), \
((double) (DRM_NUMSC * DRM_PHYWD))))
extern uint32 M[]; /* memory */
#define GET_TWORD(x) ((int32) fmod (sim_gtime() / ((double) (x)), \
((double) (DRM_NUMSC * DRM_PHYWD))))
extern uint32 M[]; /* memory */
extern uint32 alert, int_req;
extern int32 stop_invins, stop_invdev, stop_inviop;
uint32 drm_da = 0; /* disk address */
uint32 drm_ca = 0; /* core address */
uint32 drm_wc = 0; /* word count */
int32 drm_par = 0; /* cumulative par */
int32 drm_err = 0; /* error */
int32 drm_rw = 0; /* read/write */
int32 drm_sta = 0; /* drum state */
int32 drm_ftime = 3; /* time to fetch */
int32 drm_xtime = 1; /* time to xfr */
int32 drm_stopioe = 1; /* stop on error */
uint32 drm_da = 0; /* disk address */
uint32 drm_ca = 0; /* core address */
uint32 drm_wc = 0; /* word count */
int32 drm_par = 0; /* cumulative par */
int32 drm_err = 0; /* error */
int32 drm_rw = 0; /* read/write */
int32 drm_sta = 0; /* drum state */
int32 drm_ftime = 3; /* time to fetch */
int32 drm_xtime = 1; /* time to xfr */
int32 drm_stopioe = 1; /* stop on error */
DEVICE drm_dev;
t_stat drm (uint32 fnc, uint32 inst, uint32 *dat);
@@ -110,37 +110,40 @@ t_stat drm_reset (DEVICE *dptr);
/* DRM data structures
drm_dev device descriptor
drm_unit unit descriptor
drm_reg register list
drm_dev device descriptor
drm_unit unit descriptor
drm_reg register list
*/
DIB drm_dib = { -1, DEV3_GDRM, 0, NULL, &drm };
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, DRM_N_ADDR) },
{ ORDATA (CA, drm_ca, 16) },
{ ORDATA (WC, drm_wc, 14) },
{ ORDATA (PAR, drm_par, 12) },
{ FLDATA (RW, drm_rw, 0) },
{ FLDATA (ERR, drm_err, 0) },
{ ORDATA (STA, drm_sta, 2) },
{ DRDATA (FTIME, drm_ftime, 24), REG_NZ + PV_LEFT },
{ DRDATA (XTIME, drm_xtime, 24), REG_NZ + PV_LEFT },
{ FLDATA (STOP_IOE, drm_stopioe, 0) },
{ NULL } };
{ ORDATA (DA, drm_da, DRM_N_ADDR) },
{ ORDATA (CA, drm_ca, 16) },
{ ORDATA (WC, drm_wc, 14) },
{ ORDATA (PAR, drm_par, 12) },
{ FLDATA (RW, drm_rw, 0) },
{ FLDATA (ERR, drm_err, 0) },
{ ORDATA (STA, drm_sta, 2) },
{ DRDATA (FTIME, drm_ftime, 24), REG_NZ + PV_LEFT },
{ DRDATA (XTIME, drm_xtime, 24), REG_NZ + PV_LEFT },
{ FLDATA (STOP_IOE, drm_stopioe, 0) },
{ NULL }
};
DEVICE drm_dev = {
"DRM", &drm_unit, drm_reg, NULL,
1, 8, DRM_N_ADDR, 1, 8, 24,
NULL, NULL, &drm_reset,
NULL, NULL, NULL,
&drm_dib, DEV_DISABLE | DEV_DIS };
"DRM", &drm_unit, drm_reg, NULL,
1, 8, DRM_N_ADDR, 1, 8, 24,
NULL, NULL, &drm_reset,
NULL, NULL, NULL,
&drm_dib, DEV_DISABLE | DEV_DIS
};
/* Drum routine - EOM/SKS 3xx04 */
t_stat drm (uint32 fnc, uint32 inst, uint32 *dat)
@@ -148,31 +151,36 @@ t_stat drm (uint32 fnc, uint32 inst, uint32 *dat)
int32 t, op = inst & 07700;
switch (fnc) {
case IO_CONN: /* connect */
if (op == 00400) return drm_reset (&drm_dev); /* EOM 404 = reset */
if (op == 00500) { /* EOM 504 = read DA */
if (sim_is_active (&drm_unit)) return SCPE_OK; /* must be idle */
t = GET_TWORD (drm_xtime); /* get position */
if (t < DRM_NUMGP) M[DRM_AD] = DRM_NUMWD - t; /* in gap? */
else M[DRM_AD] = (t - DRM_NUMGP) | DRM_ADAT; } /* in data */
else if (op == 00200) { /* EOM 204 = start */
if (sim_is_active (&drm_unit)) return SCPE_OK; /* must be idle */
drm_sta = DRM_SFET; /* state = fetch */
sim_activate (&drm_unit, drm_ftime); } /* activate */
else CRETINS;
break;
case IO_SKS: /* SKS */
if (((op == 07400) && !drm_err) || /* 37404: no err */
((op == 00200) && !sim_is_active (&drm_unit))) /* 30204: idle */
*dat = 1;
break;
case IO_CONN: /* connect */
if (op == 00400) return drm_reset (&drm_dev); /* EOM 404 = reset */
if (op == 00500) { /* EOM 504 = read DA */
if (sim_is_active (&drm_unit)) return SCPE_OK; /* must be idle */
t = GET_TWORD (drm_xtime); /* get position */
if (t < DRM_NUMGP) M[DRM_AD] = DRM_NUMWD - t; /* in gap? */
else M[DRM_AD] = (t - DRM_NUMGP) | DRM_ADAT;/* in data */
}
else if (op == 00200) { /* EOM 204 = start */
if (sim_is_active (&drm_unit)) return SCPE_OK; /* must be idle */
drm_sta = DRM_SFET; /* state = fetch */
sim_activate (&drm_unit, drm_ftime); /* activate */
}
else CRETINS;
break;
case IO_SKS: /* SKS */
if (((op == 07400) && !drm_err) || /* 37404: no err */
((op == 00200) && !sim_is_active (&drm_unit))) /* 30204: idle */
*dat = 1;
break;
default:
return SCPE_IERR;
}
default:
return SCPE_IERR; } /* can't get here */
return SCPE_OK;
}
/* Unit service */
t_stat drm_svc (UNIT *uptr)
@@ -181,91 +189,105 @@ int32 t, rda;
uint32 dpc, dwd;
uint32 *fbuf = uptr->filebuf;
if (drm_sta != DRM_SXFR) { /* fetch drum prog? */
dpc = M[DRM_PC]; /* get drum PC */
dwd = M[dpc & PAMASK]; /* get drum inst */
M[DRM_PC] = (dpc + 1) & PAMASK; /* update drum PC */
if (drm_sta == DRM_SFCA) { /* fetch core addr? */
drm_rw = DRM_GETRW (dwd); /* set op */
drm_ca = dwd & PAMASK; /* set core addr */
drm_sta = DRM_SFDA; } /* next is disk addr */
else if (drm_sta == DRM_SFDA) { /* fetch disk addr? */
drm_da = dwd & DRM_DAMASK; /* set disk addr */
drm_sta = DRM_SXFR; /* next is xfer */
drm_par = 0; /* init parity */
rda = (drm_da & DRM_SWMASK) + (DRM_GETSC (drm_da) * DRM_NUMGP);
t = rda - GET_TWORD (drm_xtime); /* difference */
if (t <= 0) t = t + (DRM_NUMSC * DRM_PHYWD); /* add trk lnt */
sim_activate (&drm_unit, t * drm_xtime); } /* activate */
if (drm_sta != DRM_SXFR) { /* fetch drum prog? */
dpc = M[DRM_PC]; /* get drum PC */
dwd = M[dpc & PAMASK]; /* get drum inst */
M[DRM_PC] = (dpc + 1) & PAMASK; /* update drum PC */
if (drm_sta == DRM_SFCA) { /* fetch core addr? */
drm_rw = DRM_GETRW (dwd); /* set op */
drm_ca = dwd & PAMASK; /* set core addr */
drm_sta = DRM_SFDA; /* next is disk addr */
}
else if (drm_sta == DRM_SFDA) { /* fetch disk addr? */
drm_da = dwd & DRM_DAMASK; /* set disk addr */
drm_sta = DRM_SXFR; /* next is xfer */
drm_par = 0; /* init parity */
rda = (drm_da & DRM_SWMASK) + (DRM_GETSC (drm_da) * DRM_NUMGP);
t = rda - GET_TWORD (drm_xtime); /* difference */
if (t <= 0) t = t + (DRM_NUMSC * DRM_PHYWD); /* add trk lnt */
sim_activate (&drm_unit, t * drm_xtime); /* activate */
}
else {
switch (DRM_GETOP (dwd)) {
case DRM_OCX: /* cond xfr */
if (drm_err) { /* error? */
int_req = int_req | INT_DRM; /* req int */
return SCPE_OK; } /* done */
case DRM_OXF: /* transfer */
drm_wc = dwd & DRM_WCMASK; /* save wc */
drm_sta = DRM_SFCA; /* next state */
break;
case DRM_OBR: /* branch */
M[DRM_PC] = dwd & PAMASK; /* new drum PC */
break;
case DRM_END: /* end */
return SCPE_OK;
case DRM_EIE: /* end, int if err */
if (!drm_err) return SCPE_OK;
case DRM_EIU: /* end, int uncond */
int_req = int_req | INT_DRM;
return SCPE_OK; } /* end switch */
} /* end else sta */
sim_activate (uptr, drm_ftime); /* fetch next word */
} /* end if !xfr */
else { /* transfer word */
if ((uptr->flags & UNIT_BUF) == 0) { /* not buffered? */
drm_err = 1; /* error */
CRETIOE (drm_stopioe, SCPE_UNATT); }
if (drm_rw) { /* write? */
dwd = M[drm_ca]; /* get mem word */
fbuf[drm_da] = dwd; /* write to drum */
if (drm_da >= uptr->hwmark) uptr->hwmark = drm_da + 1; }
else { /* read */
dwd = fbuf[drm_da]; /* get drum word */
M[drm_ca] = dwd; } /* write to mem */
drm_da = drm_da + 1; /* inc drum addr */
if (drm_da >= DRM_SIZE) drm_da = 0; /* wrap */
drm_ca = (drm_ca + 1) & PAMASK; /* inc core addr */
drm_wc = (drm_wc - 1) & DRM_WCMASK; /* dec word cnt */
drm_par = drm_par ^ (dwd >> 12); /* parity */
switch (DRM_GETOP (dwd)) {
case DRM_OCX: /* cond xfr */
if (drm_err) { /* error? */
int_req = int_req | INT_DRM; /* req int */
return SCPE_OK; /* done */
}
case DRM_OXF: /* transfer */
drm_wc = dwd & DRM_WCMASK; /* save wc */
drm_sta = DRM_SFCA; /* next state */
break;
case DRM_OBR: /* branch */
M[DRM_PC] = dwd & PAMASK; /* new drum PC */
break;
case DRM_END: /* end */
return SCPE_OK;
case DRM_EIE: /* end, int if err */
if (!drm_err) return SCPE_OK;
case DRM_EIU: /* end, int uncond */
int_req = int_req | INT_DRM;
return SCPE_OK;
} /* end switch */
} /* end else sta */
sim_activate (uptr, drm_ftime); /* fetch next word */
} /* end if !xfr */
else { /* transfer word */
if ((uptr->flags & UNIT_BUF) == 0) { /* not buffered? */
drm_err = 1; /* error */
CRETIOE (drm_stopioe, SCPE_UNATT);
}
if (drm_rw) { /* write? */
dwd = M[drm_ca]; /* get mem word */
fbuf[drm_da] = dwd; /* write to drum */
if (drm_da >= uptr->hwmark) uptr->hwmark = drm_da + 1;
}
else { /* read */
dwd = fbuf[drm_da]; /* get drum word */
M[drm_ca] = dwd; /* write to mem */
}
drm_da = drm_da + 1; /* inc drum addr */
if (drm_da >= DRM_SIZE) drm_da = 0; /* wrap */
drm_ca = (drm_ca + 1) & PAMASK; /* inc core addr */
drm_wc = (drm_wc - 1) & DRM_WCMASK; /* dec word cnt */
drm_par = drm_par ^ (dwd >> 12); /* parity */
drm_par = ((drm_par << 1) | (drm_par >> 11)) & 07777;
drm_par = drm_par ^ (dwd & 07777);
if (drm_wc) { /* more to do */
if (drm_da & DRM_M_WD) sim_activate (uptr, drm_xtime);
else sim_activate (uptr, drm_xtime * DRM_NUMGP); }
else { /* end xfr */
if (drm_wc) { /* more to do */
if (drm_da & DRM_M_WD) sim_activate (uptr, drm_xtime);
else sim_activate (uptr, drm_xtime * DRM_NUMGP);
}
else { /* end xfr */
#if defined (DRM_PAR)
if ((drm_da & DRM_M_WD) && drm_rw) { /* wr end mid sector? */
M[drm_da] = drm_par << 12; /* clobber data */
if (drm_da >= uptr->hwmark) uptr->hwmark = drm_da + 1; }
if ((drm_da & DRM_M_WD) && drm_rw) { /* wr end mid sector? */
M[drm_da] = drm_par << 12; /* clobber data */
if (drm_da >= uptr->hwmark) uptr->hwmark = drm_da + 1;
}
#endif
drm_sta = DRM_SFET; /* back to fetch */
sim_activate (uptr, drm_ftime); /* schedule */
} /* end else end xfr */
} /* end else xfr */
drm_sta = DRM_SFET; /* back to fetch */
sim_activate (uptr, drm_ftime); /* schedule */
} /* end else end xfr */
} /* end else xfr */
return SCPE_OK;
}
/* Reset routine */
t_stat drm_reset (DEVICE *dptr)
{
drm_da = 0; /* clear state */
drm_da = 0; /* clear state */
drm_ca = 0;
drm_wc = 0;
drm_par = 0;
drm_sta = 0;
drm_err = 0;
drm_rw = 0;
int_req = int_req & ~INT_DRM; /* clear intr */
sim_cancel (&drm_unit); /* deactivate */
int_req = int_req & ~INT_DRM; /* clear intr */
sim_cancel (&drm_unit); /* deactivate */
return SCPE_OK;
}

View File

@@ -1,6 +1,6 @@
/* sds_dsk.c: SDS 940 moving head disk simulator
Copyright (c) 2001-2004, Robert M. Supnik
Copyright (c) 2001-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,70 +19,73 @@
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.
dsk moving head disk
dsk moving head disk
The SDS 9164 disk has a subsector feature, allowing each 64W sector to be
viewed as 16W packets. In addition, it has a chaining feature, allowing
records to be extended beyond a sector boundary. To accomodate this, the
first word of each sector has 3 extra bits:
<26> = end of chain flag
<25:24> = 4 - number of packets
<26> = end of chain flag
<25:24> = 4 - number of packets
These values were chosen so that 000 = continue chain, full sector.
*/
#include "sds_defs.h"
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
#define UNIT_WLK (1 << UNIT_V_WLK)
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
#define UNIT_V_WLK (UNIT_V_UF + 0) /* write locked */
#define UNIT_WLK (1 << UNIT_V_WLK)
#define UNIT_WPRT (UNIT_WLK | UNIT_RO) /* write protect */
#define DSK_PKTWD 16 /* words/packet */
#define DSK_NUMPKT 4 /* packets/sector */
#define DSK_NUMWD (DSK_PKTWD*DSK_NUMPKT) /* words/sector */
#define DSK_N_SC 5 /* sect addr width */
#define DSK_V_SC 0 /* position */
#define DSK_M_SC ((1 << DSK_N_SC) - 1) /* mask */
#define DSK_NUMSC (1 << DSK_N_SC) /* sectors/track */
#define DSK_N_TR 8 /* track addr width */
#define DSK_V_TR (DSK_N_SC) /* position */
#define DSK_M_TR ((1 << DSK_N_TR) - 1) /* mask */
#define DSK_NUMTR (1 << DSK_N_TR) /* tracks/surface */
#define DSK_N_SF 5 /* surf addr width */
#define DSK_V_SF (DSK_N_SC + DSK_N_TR) /* position */
#define DSK_M_SF ((1 << DSK_N_SF) - 1) /* mask */
#define DSK_NUMSF (1 << DSK_N_SF) /* surfaces/drive */
#define DSK_SCSIZE (DSK_NUMSF*DSK_NUMTR*DSK_NUMSC) /* sectors/drive */
#define DSK_AMASK (DSK_SCSIZE - 1) /* address mask */
#define DSK_SIZE (DSK_SCSIZE * DSK_NUMWD) /* words/drive */
#define DSK_GETTR(x) (((x) >> DSK_V_TR) & DSK_M_TR)
#define cyl u3 /* curr cylinder */
#define DSK_SIP (1 << (DSK_N_TR + 2))
#define DSK_V_PKT 24
#define DSK_M_PKT 03
#define DSK_V_CHN 26
#define DSK_GETPKT(x) (4 - (((x) >> DSK_V_PKT) & DSK_M_PKT))
#define DSK_ENDCHN(x) ((x) & (1 << DSK_V_CHN))
#define DSK_PKTWD 16 /* words/packet */
#define DSK_NUMPKT 4 /* packets/sector */
#define DSK_NUMWD (DSK_PKTWD*DSK_NUMPKT) /* words/sector */
#define DSK_N_SC 5 /* sect addr width */
#define DSK_V_SC 0 /* position */
#define DSK_M_SC ((1 << DSK_N_SC) - 1) /* mask */
#define DSK_NUMSC (1 << DSK_N_SC) /* sectors/track */
#define DSK_N_TR 8 /* track addr width */
#define DSK_V_TR (DSK_N_SC) /* position */
#define DSK_M_TR ((1 << DSK_N_TR) - 1) /* mask */
#define DSK_NUMTR (1 << DSK_N_TR) /* tracks/surface */
#define DSK_N_SF 5 /* surf addr width */
#define DSK_V_SF (DSK_N_SC + DSK_N_TR) /* position */
#define DSK_M_SF ((1 << DSK_N_SF) - 1) /* mask */
#define DSK_NUMSF (1 << DSK_N_SF) /* surfaces/drive */
#define DSK_SCSIZE (DSK_NUMSF*DSK_NUMTR*DSK_NUMSC) /* sectors/drive */
#define DSK_AMASK (DSK_SCSIZE - 1) /* address mask */
#define DSK_SIZE (DSK_SCSIZE * DSK_NUMWD) /* words/drive */
#define DSK_GETTR(x) (((x) >> DSK_V_TR) & DSK_M_TR)
#define cyl u3 /* curr cylinder */
#define DSK_SIP (1 << (DSK_N_TR + 2))
#define DSK_V_PKT 24
#define DSK_M_PKT 03
#define DSK_V_CHN 26
#define DSK_GETPKT(x) (4 - (((x) >> DSK_V_PKT) & DSK_M_PKT))
#define DSK_ENDCHN(x) ((x) & (1 << DSK_V_CHN))
extern uint32 xfr_req;
extern uint32 alert;
extern int32 stop_invins, stop_invdev, stop_inviop;
int32 dsk_da = 0; /* disk addr */
int32 dsk_op = 0; /* operation */
int32 dsk_err = 0; /* error flag */
uint32 dsk_buf[DSK_NUMWD]; /* sector buf */
int32 dsk_bptr = 0; /* byte ptr */
int32 dsk_blnt = 0; /* byte lnt */
int32 dsk_time = 5; /* time per char */
int32 dsk_stime = 200; /* seek time */
int32 dsk_da = 0; /* disk addr */
int32 dsk_op = 0; /* operation */
int32 dsk_err = 0; /* error flag */
uint32 dsk_buf[DSK_NUMWD]; /* sector buf */
int32 dsk_bptr = 0; /* byte ptr */
int32 dsk_blnt = 0; /* byte lnt */
int32 dsk_time = 5; /* time per char */
int32 dsk_stime = 200; /* seek time */
int32 dsk_stopioe = 1;
DSPT dsk_tplt[] = { /* template */
{ 1, 0 }, { 1, DEV_OUT }, { 0, 0 } };
DSPT dsk_tplt[] = { /* template */
{ 1, 0 },
{ 1, DEV_OUT },
{ 0, 0 }
};
DEVICE dsk_dev;
t_stat dsk_svc (UNIT *uptr);
@@ -95,52 +98,54 @@ t_stat dsk (uint32 fnc, uint32 inst, uint32 *dat);
/* DSK data structures
dsk_dev device descriptor
dsk_unit unit descriptor
dsk_reg register list
dsk_dev device descriptor
dsk_unit unit descriptor
dsk_reg register list
*/
DIB dsk_dib = { CHAN_F, DEV_DSK, XFR_DSK, dsk_tplt, &dsk };
UNIT dsk_unit =
{ UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE, DSK_SIZE) };
UNIT dsk_unit = { UDATA (&dsk_svc, UNIT_FIX+UNIT_ATTABLE, DSK_SIZE) };
REG dsk_reg[] = {
{ BRDATA (BUF, dsk_buf, 8, 24, DSK_NUMWD) },
{ DRDATA (BPTR, dsk_bptr, 9), PV_LEFT },
{ DRDATA (BLNT, dsk_bptr, 9), PV_LEFT },
{ ORDATA (DA, dsk_da, 21) },
{ ORDATA (INST, dsk_op, 24) },
{ FLDATA (XFR, xfr_req, XFR_V_DSK) },
{ FLDATA (ERR, dsk_err, 0) },
{ DRDATA (WTIME, dsk_time, 24), REG_NZ + PV_LEFT },
{ DRDATA (STIME, dsk_stime,24), REG_NZ + PV_LEFT },
{ FLDATA (STOP_IOE, dsk_stopioe, 0) },
{ NULL } };
{ BRDATA (BUF, dsk_buf, 8, 24, DSK_NUMWD) },
{ DRDATA (BPTR, dsk_bptr, 9), PV_LEFT },
{ DRDATA (BLNT, dsk_bptr, 9), PV_LEFT },
{ ORDATA (DA, dsk_da, 21) },
{ ORDATA (INST, dsk_op, 24) },
{ FLDATA (XFR, xfr_req, XFR_V_DSK) },
{ FLDATA (ERR, dsk_err, 0) },
{ DRDATA (WTIME, dsk_time, 24), REG_NZ + PV_LEFT },
{ DRDATA (STIME, dsk_stime,24), REG_NZ + PV_LEFT },
{ FLDATA (STOP_IOE, dsk_stopioe, 0) },
{ NULL }
};
MTAB dsk_mod[] = {
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
{ MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL",
&set_chan, &show_chan, NULL },
{ 0 } };
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
{ UNIT_WLK, UNIT_WLK, "write locked", "LOCKED", NULL },
{ MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL",
&set_chan, &show_chan, NULL },
{ 0 }
};
DEVICE dsk_dev = {
"DSK", &dsk_unit, dsk_reg, dsk_mod,
1, 8, 24, 1, 8, 27,
NULL, NULL, &dsk_reset,
NULL, NULL, NULL,
&dsk_dib, DEV_DISABLE };
"DSK", &dsk_unit, dsk_reg, dsk_mod,
1, 8, 24, 1, 8, 27,
NULL, NULL, &dsk_reset,
NULL, NULL, NULL,
&dsk_dib, DEV_DISABLE
};
/* Moving head disk routine
conn - inst = EOM0, dat = NULL
eom1 - inst = EOM1, dat = NULL
sks - inst = SKS, dat = ptr to result
disc - inst = device number, dat = NULL
wreor - inst = device number, dat = NULL
read - inst = device number, dat = ptr to data
write - inst = device number, dat = ptr to result
conn - inst = EOM0, dat = NULL
eom1 - inst = EOM1, dat = NULL
sks - inst = SKS, dat = ptr to result
disc - inst = device number, dat = NULL
wreor - inst = device number, dat = NULL
read - inst = device number, dat = ptr to data
write - inst = device number, dat = ptr to result
*/
t_stat dsk (uint32 fnc, uint32 inst, uint32 *dat)
@@ -148,79 +153,84 @@ t_stat dsk (uint32 fnc, uint32 inst, uint32 *dat)
int32 i, t, new_ch, dsk_wptr, dsk_byte;
t_stat r;
switch (fnc) { /* case on function */
case IO_CONN: /* connect */
new_ch = I_GETEOCH (inst); /* get new chan */
if (new_ch != dsk_dib.chan) return SCPE_IERR; /* wrong chan? */
dsk_op = inst; /* save instr */
dsk_bptr = dsk_blnt = 0; /* init ptrs */
for (i = 0; i < DSK_NUMWD; i++) dsk_buf[i] = 0; /* clear buffer */
xfr_req = xfr_req & ~XFR_DSK; /* clr xfr flg */
sim_activate (&dsk_unit, dsk_stime); /* activate */
break;
switch (fnc) { /* case on function */
case IO_EOM1: /* EOM mode 1 */
new_ch = I_GETEOCH (inst); /* get new chan */
if (new_ch != dsk_dib.chan) return SCPE_IERR; /* wrong chan? */
if (inst & 07600) CRETIOP; /* inv inst? */
alert = POT_DSK; /* alert */
break;
case IO_CONN: /* connect */
new_ch = I_GETEOCH (inst); /* get new chan */
if (new_ch != dsk_dib.chan) return SCPE_IERR; /* wrong chan? */
dsk_op = inst; /* save instr */
dsk_bptr = dsk_blnt = 0; /* init ptrs */
for (i = 0; i < DSK_NUMWD; i++) dsk_buf[i] = 0; /* clear buffer */
xfr_req = xfr_req & ~XFR_DSK; /* clr xfr flg */
sim_activate (&dsk_unit, dsk_stime); /* activate */
break;
case IO_DISC: /* disconnect */
dsk_end_op (0); /* normal term */
if (inst & DEV_OUT) return dsk_fill (inst); /* fill write */
break;
case IO_EOM1: /* EOM mode 1 */
new_ch = I_GETEOCH (inst); /* get new chan */
if (new_ch != dsk_dib.chan) return SCPE_IERR; /* wrong chan? */
if (inst & 07600) CRETIOP; /* inv inst? */
alert = POT_DSK; /* alert */
break;
case IO_WREOR: /* write eor */
dsk_end_op (CHF_EOR); /* eor term */
return dsk_fill (inst); /* fill write */
case IO_DISC: /* disconnect */
dsk_end_op (0); /* normal term */
if (inst & DEV_OUT) return dsk_fill (inst); /* fill write */
break;
case IO_SKS: /* SKS */
new_ch = I_GETSKCH (inst); /* sks chan */
if (new_ch != dsk_dib.chan) return SCPE_IERR; /* wrong chan? */
t = I_GETSKCND (inst); /* sks cond */
if (((t == 000) && !sim_is_active (&dsk_unit) && /* 10026: ready */
(dsk_unit.flags & UNIT_ATT)) ||
((t == 004) && !dsk_err && /* 11026: !err */
(dsk_unit.flags & UNIT_ATT)) ||
((t == 010) && ((dsk_unit.cyl & DSK_SIP) == 0)) || /* 12026: on trk */
((t == 014) && !(dsk_unit.flags & UNIT_WPRT)) ||/* 13026: !wrprot */
((t == 001) && (dsk_unit.flags & UNIT_ATT))) /* 10226: online */
*dat = 1;
break;
case IO_WREOR: /* write eor */
dsk_end_op (CHF_EOR); /* eor term */
return dsk_fill (inst); /* fill write */
case IO_READ:
xfr_req = xfr_req & ~XFR_DSK; /* clr xfr req */
if (dsk_bptr >= dsk_blnt) { /* no more data? */
if (r = dsk_read_buf (inst)) return r; } /* read sector */
dsk_wptr = dsk_bptr >> 2; /* word pointer */
dsk_byte = dsk_bptr & 03; /* byte in word */
*dat = (dsk_buf[dsk_wptr] >> ((3 - dsk_byte) * 6)) & 077;
dsk_bptr = dsk_bptr + 1; /* incr buf ptr */
if ((dsk_bptr >= dsk_blnt) && /* end sector, */
((dsk_op & CHC_BIN) || DSK_ENDCHN (dsk_buf[0])))/* sec mode | eoch? */
dsk_end_op (CHF_EOR); /* eor term */
break;
case IO_SKS: /* SKS */
new_ch = I_GETSKCH (inst); /* sks chan */
if (new_ch != dsk_dib.chan) return SCPE_IERR; /* wrong chan? */
t = I_GETSKCND (inst); /* sks cond */
if (((t == 000) && !sim_is_active (&dsk_unit) &&/* 10026: ready */
(dsk_unit.flags & UNIT_ATT)) ||
((t == 004) && !dsk_err && /* 11026: !err */
(dsk_unit.flags & UNIT_ATT)) ||
((t == 010) && ((dsk_unit.cyl & DSK_SIP) == 0)) || /* 12026: on trk */
((t == 014) && !(dsk_unit.flags & UNIT_WPRT)) || /* 13026: !wrprot */
((t == 001) && (dsk_unit.flags & UNIT_ATT))) /* 10226: online */
*dat = 1;
break;
case IO_WRITE:
xfr_req = xfr_req & ~XFR_DSK; /* clr xfr req */
if (dsk_bptr >= (DSK_NUMWD * 4)) { /* full? */
if (r = dsk_write_buf (inst)) return r; } /* write sector */
dsk_wptr = dsk_bptr >> 2; /* word pointer */
dsk_buf[dsk_wptr] = ((dsk_buf[dsk_wptr] << 6) | (*dat & 077)) & DMASK;
dsk_bptr = dsk_bptr + 1; /* incr buf ptr */
break;
case IO_READ:
xfr_req = xfr_req & ~XFR_DSK; /* clr xfr req */
if (dsk_bptr >= dsk_blnt) { /* no more data? */
if (r = dsk_read_buf (inst)) return r; /* read sector */
}
dsk_wptr = dsk_bptr >> 2; /* word pointer */
dsk_byte = dsk_bptr & 03; /* byte in word */
*dat = (dsk_buf[dsk_wptr] >> ((3 - dsk_byte) * 6)) & 077;
dsk_bptr = dsk_bptr + 1; /* incr buf ptr */
if ((dsk_bptr >= dsk_blnt) && /* end sector, */
((dsk_op & CHC_BIN) || DSK_ENDCHN (dsk_buf[0])))/* sec mode | eoch? */
dsk_end_op (CHF_EOR); /* eor term */
break;
default:
CRETINS; }
return SCPE_OK;
case IO_WRITE:
xfr_req = xfr_req & ~XFR_DSK; /* clr xfr req */
if (dsk_bptr >= (DSK_NUMWD * 4)) { /* full? */
if (r = dsk_write_buf (inst)) return r; /* write sector */
}
dsk_wptr = dsk_bptr >> 2; /* word pointer */
dsk_buf[dsk_wptr] = ((dsk_buf[dsk_wptr] << 6) | (*dat & 077)) & DMASK;
dsk_bptr = dsk_bptr + 1; /* incr buf ptr */
break;
default:
CRETINS;
}
return SCPE_OK;
}
/* PIN routine - return disk address */
t_stat pin_dsk (uint32 num, uint32 *dat)
{
*dat = dsk_da; /* ret disk addr */
*dat = dsk_da; /* ret disk addr */
return SCPE_OK;
}
@@ -230,13 +240,13 @@ t_stat pot_dsk (uint32 num, uint32 *dat)
{
int32 st;
if (sim_is_active (&dsk_unit)) return STOP_IONRDY; /* busy? wait */
dsk_da = (*dat) & DSK_AMASK; /* save dsk addr */
st = abs (DSK_GETTR (dsk_da) - /* calc seek time */
if (sim_is_active (&dsk_unit)) return STOP_IONRDY; /* busy? wait */
dsk_da = (*dat) & DSK_AMASK; /* save dsk addr */
st = abs (DSK_GETTR (dsk_da) - /* calc seek time */
(dsk_unit.cyl & DSK_M_TR)) * dsk_stime;
if (st == 0) st = dsk_stime; /* min time */
sim_activate (&dsk_unit, st); /* set timer */
dsk_unit.cyl = dsk_unit.cyl | DSK_SIP; /* seeking */
if (st == 0) st = dsk_stime; /* min time */
sim_activate (&dsk_unit, st); /* set timer */
dsk_unit.cyl = dsk_unit.cyl | DSK_SIP; /* seeking */
return SCPE_OK;
}
@@ -244,12 +254,14 @@ return SCPE_OK;
t_stat dsk_svc (UNIT *uptr)
{
if (uptr->cyl & DSK_SIP) { /* end seek? */
uptr->cyl = DSK_GETTR (dsk_da); /* on cylinder */
if (dsk_op) sim_activate (&dsk_unit, dsk_stime); } /* sched r/w */
if (uptr->cyl & DSK_SIP) { /* end seek? */
uptr->cyl = DSK_GETTR (dsk_da); /* on cylinder */
if (dsk_op) sim_activate (&dsk_unit, dsk_stime); /* sched r/w */
}
else {
xfr_req = xfr_req | XFR_DSK; /* set xfr req */
sim_activate (&dsk_unit, dsk_time); } /* activate */
xfr_req = xfr_req | XFR_DSK; /* set xfr req */
sim_activate (&dsk_unit, dsk_time); /* activate */
}
return SCPE_OK;
}
@@ -259,20 +271,22 @@ t_stat dsk_read_buf (uint32 dev)
{
int32 da, pkts, awc;
if ((dsk_unit.flags & UNIT_ATT) == 0) { /* !attached? */
dsk_end_op (CHF_ERR | CHF_EOR); /* disk error */
CRETIOE (dsk_stopioe, SCPE_UNATT); }
if ((dsk_unit.flags & UNIT_ATT) == 0) { /* !attached? */
dsk_end_op (CHF_ERR | CHF_EOR); /* disk error */
CRETIOE (dsk_stopioe, SCPE_UNATT);
}
da = dsk_da * DSK_NUMWD * sizeof (uint32);
fseek (dsk_unit.fileref, da, SEEK_SET); /* locate sector */
fseek (dsk_unit.fileref, da, SEEK_SET); /* locate sector */
awc = fxread (dsk_buf, sizeof (uint32), DSK_NUMWD, dsk_unit.fileref);
if (ferror (dsk_unit.fileref)) { /* error? */
dsk_end_op (CHF_ERR | CHF_EOR); /* disk error */
return SCPE_IOERR; }
if (ferror (dsk_unit.fileref)) { /* error? */
dsk_end_op (CHF_ERR | CHF_EOR); /* disk error */
return SCPE_IOERR;
}
for ( ; awc < DSK_NUMWD; awc++) dsk_buf[awc] = 0;
pkts = DSK_GETPKT (dsk_buf[0]); /* get packets */
dsk_blnt = pkts * DSK_PKTWD * 4; /* new buf size */
dsk_bptr = 0; /* init bptr */
dsk_da = (dsk_da + 1) & DSK_AMASK; /* incr disk addr */
pkts = DSK_GETPKT (dsk_buf[0]); /* get packets */
dsk_blnt = pkts * DSK_PKTWD * 4; /* new buf size */
dsk_bptr = 0; /* init bptr */
dsk_da = (dsk_da + 1) & DSK_AMASK; /* incr disk addr */
return SCPE_OK;
}
@@ -286,21 +300,24 @@ t_stat dsk_write_buf (uint32 dev)
{
int32 i, da;
if ((dsk_unit.flags & UNIT_ATT) == 0) { /* !attached? */
dsk_end_op (CHF_ERR | CHF_EOR); /* disk error */
CRETIOE (dsk_stopioe, SCPE_UNATT); }
if (dsk_unit.flags & UNIT_WPRT) { /* write prot? */
dsk_end_op (CHF_ERR | CHF_EOR); /* disk error */
return SCPE_OK; }
if ((dsk_unit.flags & UNIT_ATT) == 0) { /* !attached? */
dsk_end_op (CHF_ERR | CHF_EOR); /* disk error */
CRETIOE (dsk_stopioe, SCPE_UNATT);
}
if (dsk_unit.flags & UNIT_WPRT) { /* write prot? */
dsk_end_op (CHF_ERR | CHF_EOR); /* disk error */
return SCPE_OK;
}
da = dsk_da * DSK_NUMWD * sizeof (uint32);
fseek (dsk_unit.fileref, da, SEEK_SET); /* locate sector */
fseek (dsk_unit.fileref, da, SEEK_SET); /* locate sector */
fxwrite (dsk_buf, sizeof (uint32), DSK_NUMWD, dsk_unit.fileref);
if (ferror (dsk_unit.fileref)) { /* error? */
dsk_end_op (CHF_ERR | CHF_EOR); /* disk error */
return SCPE_IOERR; }
dsk_bptr = 0; /* init bptr */
dsk_da = (dsk_da + 1) & DSK_AMASK; /* incr disk addr */
for (i = 0; i < DSK_NUMWD; i++) dsk_buf[i] = 0; /* clear buffer */
if (ferror (dsk_unit.fileref)) { /* error? */
dsk_end_op (CHF_ERR | CHF_EOR); /* disk error */
return SCPE_IOERR;
}
dsk_bptr = 0; /* init bptr */
dsk_da = (dsk_da + 1) & DSK_AMASK; /* incr disk addr */
for (i = 0; i < DSK_NUMWD; i++) dsk_buf[i] = 0; /* clear buffer */
return SCPE_OK;
}
@@ -310,48 +327,50 @@ return SCPE_OK;
t_stat dsk_fill (uint32 dev)
{
int32 nochn = (dsk_op & CHC_BIN)? 0: 1; /* chain? */
int32 pktend = (dsk_bptr + ((DSK_PKTWD * 4) - 1)) & /* end pkt */
~((DSK_PKTWD * 4) - 1);
int32 pkts = pktend / (DSK_PKTWD * 4); /* # packets */
int32 nochn = (dsk_op & CHC_BIN)? 0: 1; /* chain? */
int32 pktend = (dsk_bptr + ((DSK_PKTWD * 4) - 1)) & /* end pkt */
~((DSK_PKTWD * 4) - 1);
int32 pkts = pktend / (DSK_PKTWD * 4); /* # packets */
if (dsk_bptr == 0) return SCPE_OK; /* no fill? */
for ( ; dsk_bptr < pktend; dsk_bptr++) { /* fill packet */
if (dsk_bptr == 0) return SCPE_OK; /* no fill? */
for ( ; dsk_bptr < pktend; dsk_bptr++) { /* fill packet */
int32 dsk_wptr = dsk_bptr >> 2;
dsk_buf[dsk_wptr] = (dsk_buf[dsk_wptr] << 6) & DMASK; }
dsk_buf[0] = dsk_buf[0] | (nochn << DSK_V_CHN) | /* insert chain, */
((4 - pkts) << DSK_V_PKT); /* num pkts */
return dsk_write_buf (dev); /* write sec */
dsk_buf[dsk_wptr] = (dsk_buf[dsk_wptr] << 6) & DMASK;
}
dsk_buf[0] = dsk_buf[0] | (nochn << DSK_V_CHN) | /* insert chain, */
((4 - pkts) << DSK_V_PKT); /* num pkts */
return dsk_write_buf (dev); /* write sec */
}
/* Terminate DSK operation */
void dsk_end_op (uint32 fl)
{
if (fl) chan_set_flag (dsk_dib.chan, fl); /* set flags */
dsk_op = 0; /* clear op */
xfr_req = xfr_req & ~XFR_DSK; /* clear xfr */
sim_cancel (&dsk_unit); /* stop */
if (fl & CHF_ERR) { /* error? */
chan_disc (dsk_dib.chan); /* disconnect */
dsk_err = 1; } /* set disk err */
if (fl) chan_set_flag (dsk_dib.chan, fl); /* set flags */
dsk_op = 0; /* clear op */
xfr_req = xfr_req & ~XFR_DSK; /* clear xfr */
sim_cancel (&dsk_unit); /* stop */
if (fl & CHF_ERR) { /* error? */
chan_disc (dsk_dib.chan); /* disconnect */
dsk_err = 1; /* set disk err */
}
return;
}
/* Reset routine */
t_stat dsk_reset (DEVICE *dptr)
{
int32 i;
chan_disc (dsk_dib.chan); /* disconnect */
dsk_da = 0; /* clear state */
chan_disc (dsk_dib.chan); /* disconnect */
dsk_da = 0; /* clear state */
dsk_op = 0;
dsk_err = 0;
dsk_bptr = dsk_blnt = 0;
xfr_req = xfr_req & ~XFR_DSK; /* clr xfr req */
sim_cancel (&dsk_unit); /* deactivate */
xfr_req = xfr_req & ~XFR_DSK; /* clr xfr req */
sim_cancel (&dsk_unit); /* deactivate */
dsk_unit.cyl = 0;
for (i = 0; i < DSK_NUMWD; i++) dsk_buf[i] = 0; /* clear buffer */
for (i = 0; i < DSK_NUMWD; i++) dsk_buf[i] = 0; /* clear buffer */
return SCPE_OK;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
/* sds_lp.c: SDS 940 line printer simulator
Copyright (c) 2001-2004, Robert M. Supnik
Copyright (c) 2001-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,40 +19,43 @@
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.
lpt line printer
lpt line printer
25-Apr-03 RMS Revised for extended file support
25-Apr-03 RMS Revised for extended file support
*/
#include "sds_defs.h"
#define LPT_V_LN 9
#define LPT_M_LN 07
#define LPT_GETLN(x) (((x) >> LPT_V_LN) & LPT_M_LN)
#define CHP(ch,val) ((val) & (1 << (ch))) /* CCL chan test */
#define SET_XFR 1 /* set xfr */
#define SET_EOR 2 /* print, set eor */
#define SET_SPC 4 /* space */
#define LPT_V_LN 9
#define LPT_M_LN 07
#define LPT_GETLN(x) (((x) >> LPT_V_LN) & LPT_M_LN)
#define CHP(ch,val) ((val) & (1 << (ch))) /* CCL chan test */
#define SET_XFR 1 /* set xfr */
#define SET_EOR 2 /* print, set eor */
#define SET_SPC 4 /* space */
extern char sds_to_ascii[64];
extern uint32 xfr_req;
extern int32 stop_invins, stop_invdev, stop_inviop;
int32 lpt_spc = 0; /* space instr */
int32 lpt_sta = 0; /* timeout state */
int32 lpt_bptr = 0; /* line buf ptr */
int32 lpt_err = 0; /* error */
int32 lpt_ccl = 1, lpt_ccp = 0; /* cctl lnt, ptr */
int32 lpt_ctime = 10; /* char time */
int32 lpt_ptime = 1000; /* print time */
int32 lpt_stime = 10000; /* space time */
int32 lpt_stopioe = 1; /* stop on err */
char lpt_buf[LPT_WIDTH + 1] = { 0 }; /* line buffer */
uint8 lpt_cct[CCT_LNT] = { 0377 }; /* car ctl tape */
DSPT lpt_tplt[] = { { 1, 0 }, { 0, 0 } }; /* template */
int32 lpt_spc = 0; /* space instr */
int32 lpt_sta = 0; /* timeout state */
int32 lpt_bptr = 0; /* line buf ptr */
int32 lpt_err = 0; /* error */
int32 lpt_ccl = 1, lpt_ccp = 0; /* cctl lnt, ptr */
int32 lpt_ctime = 10; /* char time */
int32 lpt_ptime = 1000; /* print time */
int32 lpt_stime = 10000; /* space time */
int32 lpt_stopioe = 1; /* stop on err */
char lpt_buf[LPT_WIDTH + 1] = { 0 }; /* line buffer */
uint8 lpt_cct[CCT_LNT] = { 0377 }; /* car ctl tape */
DSPT lpt_tplt[] = { /* template */
{ 1, 0 },
{ 0, 0 }
};
DEVICE lpt_dev;
t_stat lpt_svc (UNIT *uptr);
@@ -63,57 +66,61 @@ t_stat lpt_status (UNIT *uptr);
t_stat lpt_bufout (UNIT *uptr);
void lpt_end_op (int32 fl);
t_stat lpt (uint32 fnc, uint32 inst, uint32 *dat);
/* LPT data structures
lpt_dev LPT device descriptor
lpt_unit LPT unit descriptor
lpt_reg LPT register list
lpt_dev LPT device descriptor
lpt_unit LPT unit descriptor
lpt_reg LPT register list
*/
DIB lpt_dib = { CHAN_W, DEV_LPT, XFR_LPT, lpt_tplt, &lpt };
UNIT lpt_unit = {
UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0) };
UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0)
};
REG lpt_reg[] = {
{ BRDATA (BUF, lpt_buf, 8, 8, LPT_WIDTH) },
{ DRDATA (BPTR, lpt_bptr, 8), PV_LEFT },
{ FLDATA (XFR, xfr_req, XFR_V_LPT) },
{ FLDATA (ERR, lpt_err, 0) },
{ ORDATA (STA, lpt_sta, 3) },
{ BRDATA (CCT, lpt_cct, 8, 8, CCT_LNT) },
{ DRDATA (CCTP, lpt_ccp, 8), PV_LEFT },
{ DRDATA (CCTL, lpt_ccl, 8), REG_RO + PV_LEFT },
{ ORDATA (SPCINST, lpt_spc, 24) },
{ DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (CTIME, lpt_ctime, 24), REG_NZ + PV_LEFT },
{ DRDATA (PTIME, lpt_ptime, 24), REG_NZ + PV_LEFT },
{ DRDATA (STIME, lpt_stime, 24), REG_NZ + PV_LEFT },
{ FLDATA (STOP_IOE, lpt_stopioe, 0) },
{ NULL } };
{ BRDATA (BUF, lpt_buf, 8, 8, LPT_WIDTH) },
{ DRDATA (BPTR, lpt_bptr, 8), PV_LEFT },
{ FLDATA (XFR, xfr_req, XFR_V_LPT) },
{ FLDATA (ERR, lpt_err, 0) },
{ ORDATA (STA, lpt_sta, 3) },
{ BRDATA (CCT, lpt_cct, 8, 8, CCT_LNT) },
{ DRDATA (CCTP, lpt_ccp, 8), PV_LEFT },
{ DRDATA (CCTL, lpt_ccl, 8), REG_RO + PV_LEFT },
{ ORDATA (SPCINST, lpt_spc, 24) },
{ DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (CTIME, lpt_ctime, 24), REG_NZ + PV_LEFT },
{ DRDATA (PTIME, lpt_ptime, 24), REG_NZ + PV_LEFT },
{ DRDATA (STIME, lpt_stime, 24), REG_NZ + PV_LEFT },
{ FLDATA (STOP_IOE, lpt_stopioe, 0) },
{ NULL }
};
MTAB lpt_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL",
&set_chan, &show_chan, NULL },
{ 0 } };
{ MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL",
&set_chan, &show_chan, NULL },
{ 0 }
};
DEVICE lpt_dev = {
"LPT", &lpt_unit, lpt_reg, lpt_mod,
1, 10, 31, 1, 8, 7,
NULL, NULL, &lpt_reset,
NULL, &lpt_attach, NULL,
&lpt_dib, DEV_DISABLE };
"LPT", &lpt_unit, lpt_reg, lpt_mod,
1, 10, 31, 1, 8, 7,
NULL, NULL, &lpt_reset,
NULL, &lpt_attach, NULL,
&lpt_dib, DEV_DISABLE
};
/* Line printer routine
conn - inst = EOM0, dat = NULL
eom1 - inst = EOM1, dat = NULL
sks - inst = SKS, dat = ptr to result
disc - inst = device number, dat = NULL
wreor - inst = device number, dat = NULL
read - inst = device number, dat = ptr to data
write - inst = device number, dat = ptr to result
conn - inst = EOM0, dat = NULL
eom1 - inst = EOM1, dat = NULL
sks - inst = SKS, dat = ptr to result
disc - inst = device number, dat = NULL
wreor - inst = device number, dat = NULL
read - inst = device number, dat = ptr to data
write - inst = device number, dat = ptr to result
The line printer is an asynchronous output device, that is, it
can never set the channel rate error flag.
@@ -124,81 +131,89 @@ t_stat lpt (uint32 fnc, uint32 inst, uint32 *dat)
int32 i, t, new_ch;
char asc;
switch (fnc) { /* case function */
case IO_CONN: /* connect */
new_ch = I_GETEOCH (inst); /* get new chan */
if (new_ch != lpt_dib.chan) return SCPE_IERR; /* wrong chan? */
for (i = 0; i < LPT_WIDTH; i++) lpt_buf[i] = 0; /* clr buffer */
lpt_bptr = 0; /* clr buf ptr */
lpt_err = 0; /* err = 0 */
xfr_req = xfr_req & ~XFR_LPT; /* clr xfr flag */
lpt_sta = lpt_sta | SET_XFR; /* need xfr */
sim_activate (&lpt_unit, lpt_ctime); /* start timer */
break;
switch (fnc) { /* case function */
case IO_EOM1: /* EOM mode 1 */
new_ch = I_GETEOCH (inst); /* get new chan */
if (new_ch != lpt_dib.chan) CRETIOP; /* wrong chan? */
if (inst & 0400) { /* space? */
lpt_spc = inst; /* save instr */
lpt_sta = lpt_sta | SET_SPC; /* need space */
sim_cancel (&lpt_unit); /* cancel timer */
sim_activate (&lpt_unit, lpt_stime); } /* start timer */
break;
case IO_CONN: /* connect */
new_ch = I_GETEOCH (inst); /* get new chan */
if (new_ch != lpt_dib.chan) return SCPE_IERR; /* wrong chan? */
for (i = 0; i < LPT_WIDTH; i++) lpt_buf[i] = 0; /* clr buffer */
lpt_bptr = 0; /* clr buf ptr */
lpt_err = 0; /* err = 0 */
xfr_req = xfr_req & ~XFR_LPT; /* clr xfr flag */
lpt_sta = lpt_sta | SET_XFR; /* need xfr */
sim_activate (&lpt_unit, lpt_ctime); /* start timer */
break;
case IO_DISC: /* disconnect */
lpt_end_op (0); /* normal term */
return lpt_bufout (&lpt_unit); /* dump output */
case IO_EOM1: /* EOM mode 1 */
new_ch = I_GETEOCH (inst); /* get new chan */
if (new_ch != lpt_dib.chan) CRETIOP; /* wrong chan? */
if (inst & 0400) { /* space? */
lpt_spc = inst; /* save instr */
lpt_sta = lpt_sta | SET_SPC; /* need space */
sim_cancel (&lpt_unit); /* cancel timer */
sim_activate (&lpt_unit, lpt_stime); /* start timer */
}
break;
case IO_WREOR: /* write eor */
lpt_sta = (lpt_sta | SET_EOR) & ~SET_XFR; /* need eor */
sim_activate (&lpt_unit, lpt_ptime); /* start timer */
break;
case IO_DISC: /* disconnect */
lpt_end_op (0); /* normal term */
return lpt_bufout (&lpt_unit); /* dump output */
case IO_SKS: /* SKS */
new_ch = I_GETSKCH (inst); /* sks chan */
if (new_ch != lpt_dib.chan) return SCPE_IERR; /* wrong chan? */
t = I_GETSKCND (inst); /* sks cond */
if (((t == 020) && (!CHP (7, lpt_cct[lpt_ccp]))) || /* 14062: !ch 7 */
((t == 010) && (lpt_unit.flags & UNIT_ATT)) || /* 12062: !online */
(t == 004) && !lpt_err) *dat = 1; /* 11062: !err */
break;
case IO_WREOR: /* write eor */
lpt_sta = (lpt_sta | SET_EOR) & ~SET_XFR; /* need eor */
sim_activate (&lpt_unit, lpt_ptime); /* start timer */
break;
case IO_WRITE: /* write */
asc = sds_to_ascii[(*dat) & 077]; /* convert data */
xfr_req = xfr_req & ~XFR_LPT; /* clr xfr flag */
if (lpt_bptr < LPT_WIDTH) lpt_buf[lpt_bptr++] = asc;/* store data */
lpt_sta = lpt_sta | SET_XFR; /* need xfr */
sim_activate (&lpt_unit, lpt_ctime); /* start ch timer */
break;
case IO_SKS: /* SKS */
new_ch = I_GETSKCH (inst); /* sks chan */
if (new_ch != lpt_dib.chan) return SCPE_IERR; /* wrong chan? */
t = I_GETSKCND (inst); /* sks cond */
if (((t == 020) && (!CHP (7, lpt_cct[lpt_ccp]))) || /* 14062: !ch 7 */
((t == 010) && (lpt_unit.flags & UNIT_ATT)) || /* 12062: !online */
(t == 004) && !lpt_err) *dat = 1; /* 11062: !err */
break;
case IO_WRITE: /* write */
asc = sds_to_ascii[(*dat) & 077]; /* convert data */
xfr_req = xfr_req & ~XFR_LPT; /* clr xfr flag */
if (lpt_bptr < LPT_WIDTH) lpt_buf[lpt_bptr++] = asc;/* store data */
lpt_sta = lpt_sta | SET_XFR; /* need xfr */
sim_activate (&lpt_unit, lpt_ctime); /* start ch timer */
break;
default:
CRETINS;
}
default:
CRETINS; }
return SCPE_OK;
}
/* Unit service and write */
t_stat lpt_svc (UNIT *uptr)
{
t_stat r = SCPE_OK;
static const char *lpt_stabl[] = {
"\r", "\n", "\n\n", "\n\n\n",
"\n\n\n\n", "\n\n\n\n\n",
"\n\n\n\n\n\n", "\n\n\n\n\n\n\n" };
"\r", "\n", "\n\n", "\n\n\n",
"\n\n\n\n", "\n\n\n\n\n",
"\n\n\n\n\n\n", "\n\n\n\n\n\n\n"
};
if (lpt_sta & SET_XFR) chan_set_ordy (lpt_dib.chan); /* need lpt xfr? */
if (lpt_sta & SET_EOR) { /* printing? */
chan_set_flag (lpt_dib.chan, CHF_EOR); /* set eor flg */
r = lpt_bufout (uptr); } /* output buf */
if (lpt_sta & SET_SPC) { /* spacing? */
if (uptr->flags & UNIT_ATT) { /* attached? */
int32 ln = LPT_GETLN (lpt_spc); /* get lines, ch */
if (lpt_spc & 0200) /* n lines? */
fputs (lpt_stabl[ln], uptr->fileref); /* upspace */
else lpt_crctl (ln); } /* carriage ctl */
r = lpt_status (uptr); } /* update status */
lpt_sta = 0; /* clear state */
if (lpt_sta & SET_XFR) chan_set_ordy (lpt_dib.chan); /* need lpt xfr? */
if (lpt_sta & SET_EOR) { /* printing? */
chan_set_flag (lpt_dib.chan, CHF_EOR); /* set eor flg */
r = lpt_bufout (uptr); /* output buf */
}
if (lpt_sta & SET_SPC) { /* spacing? */
if (uptr->flags & UNIT_ATT) { /* attached? */
int32 ln = LPT_GETLN (lpt_spc); /* get lines, ch */
if (lpt_spc & 0200) /* n lines? */
fputs (lpt_stabl[ln], uptr->fileref); /* upspace */
else lpt_crctl (ln); /* carriage ctl */
}
r = lpt_status (uptr); /* update status */
}
lpt_sta = 0; /* clear state */
return r;
}
@@ -208,28 +223,32 @@ t_stat lpt_bufout (UNIT *uptr)
{
int32 i;
if ((uptr->flags & UNIT_ATT) && lpt_bptr) { /* attached? */
if ((uptr->flags & UNIT_ATT) && lpt_bptr) { /* attached? */
for (i = LPT_WIDTH - 1; (i >= 0) && (lpt_buf[i] == ' '); i--)
lpt_buf[i] = 0; /* trim line */
fputs (lpt_buf, uptr->fileref); /* write line */
lpt_bptr = 0; }
return lpt_status (uptr); /* return status */
lpt_buf[i] = 0; /* trim line */
fputs (lpt_buf, uptr->fileref); /* write line */
lpt_bptr = 0;
}
return lpt_status (uptr); /* return status */
}
/* Status update after I/O */
t_stat lpt_status (UNIT *uptr)
{
if (uptr->flags & UNIT_ATT) { /* attached? */
uptr->pos = ftell (uptr->fileref); /* update position */
if (ferror (uptr->fileref)) { /* I/O error? */
lpt_end_op (CHF_EOR | CHF_ERR); /* set err, disc */
perror ("LPT I/O error"); /* print msg */
clearerr (uptr->fileref);
return SCPE_IOERR; } } /* ret error */
if (uptr->flags & UNIT_ATT) { /* attached? */
uptr->pos = ftell (uptr->fileref); /* update position */
if (ferror (uptr->fileref)) { /* I/O error? */
lpt_end_op (CHF_EOR | CHF_ERR); /* set err, disc */
perror ("LPT I/O error"); /* print msg */
clearerr (uptr->fileref);
return SCPE_IOERR; /* ret error */
}
}
else {
lpt_end_op (CHF_EOR | CHF_ERR); /* set err, disc */
CRETIOE (lpt_stopioe, SCPE_UNATT); } /* ret error */
lpt_end_op (CHF_EOR | CHF_ERR); /* set err, disc */
CRETIOE (lpt_stopioe, SCPE_UNATT); /* ret error */
}
return SCPE_OK;
}
@@ -237,12 +256,13 @@ return SCPE_OK;
void lpt_end_op (int32 fl)
{
if (fl) chan_set_flag (lpt_dib.chan, fl); /* set flags */
xfr_req = xfr_req & ~XFR_LPT; /* clear xfr */
sim_cancel (&lpt_unit); /* stop */
if (fl & CHF_ERR) { /* error? */
chan_disc (lpt_dib.chan); /* disconnect */
lpt_err = 1; } /* set lpt err */
if (fl) chan_set_flag (lpt_dib.chan, fl); /* set flags */
xfr_req = xfr_req & ~XFR_LPT; /* clear xfr */
sim_cancel (&lpt_unit); /* stop */
if (fl & CHF_ERR) { /* error? */
chan_disc (lpt_dib.chan); /* disconnect */
lpt_err = 1; /* set lpt err */
}
return;
}
@@ -252,27 +272,30 @@ t_stat lpt_crctl (int32 ch)
{
int32 i, j;
if ((ch == 1) && CHP (ch, lpt_cct[0])) { /* top of form? */
fputs ("\f\n", lpt_unit.fileref); /* ff + nl */
lpt_ccp = 0; /* top of page */
return SCPE_OK; }
for (i = 1; i < lpt_ccl + 1; i++) { /* sweep thru cct */
lpt_ccp = (lpt_ccp + 1) %lpt_ccl; /* adv pointer */
if (CHP (ch, lpt_cct[lpt_ccp])) { /* chan punched? */
for (j = 0; j < i; j++) fputc ('\n', lpt_unit.fileref);
return SCPE_OK; } }
return STOP_CCT; /* runaway channel */
if ((ch == 1) && CHP (ch, lpt_cct[0])) { /* top of form? */
fputs ("\f\n", lpt_unit.fileref); /* ff + nl */
lpt_ccp = 0; /* top of page */
return SCPE_OK;
}
for (i = 1; i < lpt_ccl + 1; i++) { /* sweep thru cct */
lpt_ccp = (lpt_ccp + 1) %lpt_ccl; /* adv pointer */
if (CHP (ch, lpt_cct[lpt_ccp])) { /* chan punched? */
for (j = 0; j < i; j++) fputc ('\n', lpt_unit.fileref);
return SCPE_OK;
}
}
return STOP_CCT; /* runaway channel */
}
/* Reset routine */
t_stat lpt_reset (DEVICE *dptr)
{
chan_disc (lpt_dib.chan); /* disconnect */
lpt_spc = 0; /* clr state */
chan_disc (lpt_dib.chan); /* disconnect */
lpt_spc = 0; /* clr state */
lpt_sta = 0;
xfr_req = xfr_req & ~XFR_LPT; /* clr xfr flag */
sim_cancel (&lpt_unit); /* deactivate */
xfr_req = xfr_req & ~XFR_LPT; /* clr xfr flag */
sim_cancel (&lpt_unit); /* deactivate */
return SCPE_OK;
}
@@ -280,6 +303,6 @@ return SCPE_OK;
t_stat lpt_attach (UNIT *uptr, char *cptr)
{
lpt_ccp = 0; /* top of form */
lpt_ccp = 0; /* top of form */
return attach_unit (uptr, cptr);
}

View File

@@ -1,6 +1,6 @@
/* sds_mt.c: SDS 940 magnetic tape simulator
Copyright (c) 2001-2004, Robert M. Supnik
Copyright (c) 2001-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,27 +19,27 @@
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 7 track magnetic tape
mt 7 track magnetic tape
07-Dec-04 RMS Added read-only file support
25-Apr-03 RMS Revised for extended file support
28-Mar-03 RMS Added multiformat support
28-Feb-03 RMS Revised for magtape library
07-Dec-04 RMS Added read-only file support
25-Apr-03 RMS Revised for extended file support
28-Mar-03 RMS Added multiformat support
28-Feb-03 RMS Revised for magtape library
Magnetic tapes are represented as a series of variable 8b records
of the form:
32b record length in bytes - exact number
byte 0
byte 1
:
byte n-2
byte n-1
32b record length in bytes - exact number
32b record length in bytes - exact number
byte 0
byte 1
:
byte n-2
byte n-1
32b record length in bytes - exact number
If the byte count is odd, the record is padded with an extra byte
of junk. File marks are represented by a single record length of 0.
@@ -49,28 +49,31 @@
#include "sds_defs.h"
#include "sim_tape.h"
#define MT_MAXFR (32768 * 4)
#define MT_NUMDR 8 /* number drives */
#define MT_UNIT 07
#define botf u3 /* bot tape flag */
#define eotf u4 /* eot tape flag */
#define MT_MAXFR (32768 * 4)
#define MT_NUMDR 8 /* number drives */
#define MT_UNIT 07
#define botf u3 /* bot tape flag */
#define eotf u4 /* eot tape flag */
extern uint32 xfr_req;
extern int32 stop_invins, stop_invdev, stop_inviop;
int32 mt_inst = 0; /* saved instr */
int32 mt_eof = 0; /* end of file */
int32 mt_gap = 0; /* in gap */
int32 mt_skip = 0; /* skip rec */
int32 mt_bptr = 0; /* buf ptr */
int32 mt_blnt = 0; /* buf length */
int32 mt_ctime = 10; /* char time */
int32 mt_gtime = 1000; /* gap time */
int32 mt_stopioe = 1; /* stop on err */
uint8 mtxb[MT_MAXFR]; /* record buffer */
DSPT mt_tplt[] = { /* template */
{ MT_NUMDR, 0 }, { MT_NUMDR, DEV_MTS },
{ MT_NUMDR, DEV_OUT }, { MT_NUMDR, DEV_MTS+DEV_OUT },
{ 0, 0 } };
int32 mt_inst = 0; /* saved instr */
int32 mt_eof = 0; /* end of file */
int32 mt_gap = 0; /* in gap */
int32 mt_skip = 0; /* skip rec */
int32 mt_bptr = 0; /* buf ptr */
int32 mt_blnt = 0; /* buf length */
int32 mt_ctime = 10; /* char time */
int32 mt_gtime = 1000; /* gap time */
int32 mt_stopioe = 1; /* stop on err */
uint8 mtxb[MT_MAXFR]; /* record buffer */
DSPT mt_tplt[] = { /* template */
{ MT_NUMDR, 0 },
{ MT_NUMDR, DEV_MTS },
{ MT_NUMDR, DEV_OUT },
{ MT_NUMDR, DEV_MTS+DEV_OUT },
{ 0, 0 }
};
DEVICE mt_dev;
t_stat mt_svc (UNIT *uptr);
@@ -86,219 +89,234 @@ void mt_set_err (UNIT *uptr);
t_stat mt (uint32 fnc, uint32 inst, uint32 *dat);
static const char sds_to_bcd[64] = {
012, 001, 002, 003, 004, 005, 006, 007,
010, 011, 012, 013, 014, 015, 016, 017,
060, 061, 062, 063, 064, 065, 066, 067,
070, 071, 072, 073, 074, 075, 076, 077,
040, 041, 042, 043, 044, 045, 046, 047,
050, 051, 052, 053, 054, 055, 056, 057,
020, 021, 022, 023, 024, 025, 026, 027,
030, 031, 032, 033, 034, 035, 036, 037 };
012, 001, 002, 003, 004, 005, 006, 007,
010, 011, 012, 013, 014, 015, 016, 017,
060, 061, 062, 063, 064, 065, 066, 067,
070, 071, 072, 073, 074, 075, 076, 077,
040, 041, 042, 043, 044, 045, 046, 047,
050, 051, 052, 053, 054, 055, 056, 057,
020, 021, 022, 023, 024, 025, 026, 027,
030, 031, 032, 033, 034, 035, 036, 037
};
static const char bcd_to_sds[64] = {
000, 001, 002, 003, 004, 005, 006, 007,
010, 011, 000, 013, 014, 015, 016, 017,
060, 061, 062, 063, 064, 065, 066, 067,
070, 071, 072, 073, 074, 075, 076, 077,
040, 041, 042, 043, 044, 045, 046, 047,
050, 051, 052, 053, 054, 055, 056, 057,
020, 021, 022, 023, 024, 025, 026, 027,
030, 031, 032, 033, 034, 035, 036, 037 };
000, 001, 002, 003, 004, 005, 006, 007,
010, 011, 000, 013, 014, 015, 016, 017,
060, 061, 062, 063, 064, 065, 066, 067,
070, 071, 072, 073, 074, 075, 076, 077,
040, 041, 042, 043, 044, 045, 046, 047,
050, 051, 052, 053, 054, 055, 056, 057,
020, 021, 022, 023, 024, 025, 026, 027,
030, 031, 032, 033, 034, 035, 036, 037
};
/* MT data structures
mt_dev MT device descriptor
mt_unit MT unit descriptor
mt_reg MT register list
mt_dev MT device descriptor
mt_unit MT unit descriptor
mt_reg MT register list
*/
DIB mt_dib = { CHAN_W, DEV_MT, XFR_MT0, mt_tplt, &mt };
UNIT mt_unit[] = {
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE +UNIT_DISABLE, 0) } };
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) },
{ UDATA (&mt_svc, UNIT_ATTABLE + UNIT_ROABLE + UNIT_DISABLE, 0) }
};
REG mt_reg[] = {
{ BRDATA (BUF, mtxb, 8, 8, MT_MAXFR) },
{ DRDATA (BPTR, mt_bptr, 18), PV_LEFT },
{ DRDATA (BLNT, mt_blnt, 18), PV_LEFT },
{ FLDATA (XFR, xfr_req, XFR_V_MT0) },
{ ORDATA (INST, mt_inst, 24) },
{ FLDATA (EOF, mt_eof, 0) },
{ FLDATA (GAP, mt_gap, 0) },
{ FLDATA (SKIP, mt_skip, 0) },
{ DRDATA (CTIME, mt_ctime, 24), REG_NZ + PV_LEFT },
{ DRDATA (GTIME, mt_gtime, 24), REG_NZ + PV_LEFT },
{ URDATA (POS, mt_unit[0].pos, 10, T_ADDR_W, 0,
MT_NUMDR, PV_LEFT | REG_RO) },
{ URDATA (BOT, mt_unit[0].botf, 10, 1, 0, MT_NUMDR, REG_RO) },
{ URDATA (EOT, mt_unit[0].eotf, 10, 1, 0, MT_NUMDR, REG_RO) },
{ FLDATA (STOP_IOE, mt_stopioe, 0) },
{ NULL } };
{ BRDATA (BUF, mtxb, 8, 8, MT_MAXFR) },
{ DRDATA (BPTR, mt_bptr, 18), PV_LEFT },
{ DRDATA (BLNT, mt_blnt, 18), PV_LEFT },
{ FLDATA (XFR, xfr_req, XFR_V_MT0) },
{ ORDATA (INST, mt_inst, 24) },
{ FLDATA (EOF, mt_eof, 0) },
{ FLDATA (GAP, mt_gap, 0) },
{ FLDATA (SKIP, mt_skip, 0) },
{ DRDATA (CTIME, mt_ctime, 24), REG_NZ + PV_LEFT },
{ DRDATA (GTIME, mt_gtime, 24), REG_NZ + PV_LEFT },
{ URDATA (POS, mt_unit[0].pos, 10, T_ADDR_W, 0,
MT_NUMDR, PV_LEFT | REG_RO) },
{ URDATA (BOT, mt_unit[0].botf, 10, 1, 0, MT_NUMDR, REG_RO) },
{ URDATA (EOT, mt_unit[0].eotf, 10, 1, 0, MT_NUMDR, REG_RO) },
{ FLDATA (STOP_IOE, mt_stopioe, 0) },
{ 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, "CHANNEL", "CHANNEL",
&set_chan, &show_chan, 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, "CHANNEL", "CHANNEL",
&set_chan, &show_chan, NULL },
{ 0 }
};
DEVICE mt_dev = {
"MT", mt_unit, mt_reg, mt_mod,
MT_NUMDR, 10, 31, 1, 8, 8,
NULL, NULL, &mt_reset,
&mt_boot, &mt_attach, NULL,
&mt_dib, DEV_DISABLE };
"MT", mt_unit, mt_reg, mt_mod,
MT_NUMDR, 10, 31, 1, 8, 8,
NULL, NULL, &mt_reset,
&mt_boot, &mt_attach, NULL,
&mt_dib, DEV_DISABLE
};
/* Mag tape routine
conn - inst = EOM0, dat = NULL
eom1 - inst = EOM1, dat = NULL
sks - inst = SKS, dat = ptr to result
disc - inst = device number, dat = NULL
wreor - inst = device number, dat = NULL
read - inst = device number, dat = ptr to data
write - inst = device number, dat = ptr to result
conn - inst = EOM0, dat = NULL
eom1 - inst = EOM1, dat = NULL
sks - inst = SKS, dat = ptr to result
disc - inst = device number, dat = NULL
wreor - inst = device number, dat = NULL
read - inst = device number, dat = ptr to data
write - inst = device number, dat = ptr to result
*/
t_stat mt (uint32 fnc, uint32 inst, uint32 *dat)
{
int32 u = inst & MT_UNIT; /* get unit */
UNIT *uptr = mt_dev.units + u; /* get unit ptr */
int32 u = inst & MT_UNIT; /* get unit */
UNIT *uptr = mt_dev.units + u; /* get unit ptr */
int32 t, new_ch;
uint8 chr;
t_stat r;
switch (fnc) { /* case function */
case IO_CONN: /* connect */
new_ch = I_GETEOCH (inst); /* get new chan */
if (new_ch != mt_dib.chan) return SCPE_IERR; /* wrong chan? */
if (mt_gap) { /* in gap? */
mt_gap = 0; /* clr gap flg */
sim_cancel (uptr); } /* cancel timer */
else if (sim_is_active (uptr)) CRETIOP; /* busy? */
uptr->eotf = 0; /* clr eot flag */
mt_eof = 0; /* clr eof flag */
mt_skip = 0; /* clr skp flag */
mt_bptr = mt_blnt = 0; /* init buffer */
if ((inst & DEV_MTS)? (CHC_GETCPW (inst) < 2): /* scn & cpw<3? */
(inst & CHC_REV)) return STOP_INVIOP; /* rw & rev? */
mt_inst = inst; /* save inst */
if ((inst & DEV_MTS) && !(inst && DEV_OUT)) /* scanning? */
chan_set_flag (mt_dib.chan, CHF_SCAN); /* set chan flg */
xfr_req = xfr_req & ~XFR_MT0; /* clr xfr flag */
sim_activate (uptr, mt_gtime); /* start timer */
break;
switch (fnc) { /* case function */
case IO_EOM1: /* EOM mode 1 */
new_ch = I_GETEOCH (inst); /* get new chan */
if (new_ch != mt_dib.chan) CRETIOP; /* wrong chan? */
t = inst & 07670; /* get command */
if ((t == 04010) && !sim_is_active (uptr)) { /* rewind? */
sim_tape_rewind (uptr); /* rewind unit */
uptr->eotf = 0; /* clr eot */
uptr->botf = 1; } /* set bot */
else if ((t == 03610) && sim_is_active (uptr) && /* skip rec? */
((mt_inst & DEV_OUT) == 0)) mt_skip = 1; /* set flag */
else CRETINS;
break;
case IO_CONN: /* connect */
new_ch = I_GETEOCH (inst); /* get new chan */
if (new_ch != mt_dib.chan) return SCPE_IERR; /* wrong chan? */
if (mt_gap) { /* in gap? */
mt_gap = 0; /* clr gap flg */
sim_cancel (uptr); /* cancel timer */
}
else if (sim_is_active (uptr)) CRETIOP; /* busy? */
uptr->eotf = 0; /* clr eot flag */
mt_eof = 0; /* clr eof flag */
mt_skip = 0; /* clr skp flag */
mt_bptr = mt_blnt = 0; /* init buffer */
if ((inst & DEV_MTS)? (CHC_GETCPW (inst) < 2): /* scn & cpw<3? */
(inst & CHC_REV)) return STOP_INVIOP; /* rw & rev? */
mt_inst = inst; /* save inst */
if ((inst & DEV_MTS) && !(inst && DEV_OUT)) /* scanning? */
chan_set_flag (mt_dib.chan, CHF_SCAN); /* set chan flg */
xfr_req = xfr_req & ~XFR_MT0; /* clr xfr flag */
sim_activate (uptr, mt_gtime); /* start timer */
break;
case IO_DISC: /* disconnect */
sim_cancel (uptr); /* no more xfr's */
if (inst & DEV_OUT) { /* write? */
if (r = mt_wrend (inst)) return r; } /* end record */
break;
case IO_EOM1: /* EOM mode 1 */
new_ch = I_GETEOCH (inst); /* get new chan */
if (new_ch != mt_dib.chan) CRETIOP; /* wrong chan? */
t = inst & 07670; /* get command */
if ((t == 04010) && !sim_is_active (uptr)) { /* rewind? */
sim_tape_rewind (uptr); /* rewind unit */
uptr->eotf = 0; /* clr eot */
uptr->botf = 1; /* set bot */
}
else if ((t == 03610) && sim_is_active (uptr) &&/* skip rec? */
((mt_inst & DEV_OUT) == 0)) mt_skip = 1; /* set flag */
else CRETINS;
break;
case IO_WREOR: /* write eor */
chan_set_flag (mt_dib.chan, CHF_EOR); /* set eor flg */
if (r = mt_wrend (inst)) return r; /* end record */
mt_gap = 1; /* in gap */
sim_activate (uptr, mt_gtime); /* start timer */
break;
case IO_DISC: /* disconnect */
sim_cancel (uptr); /* no more xfr's */
if (inst & DEV_OUT) { /* write? */
if (r = mt_wrend (inst)) return r; /* end record */
}
break;
case IO_SKS: /* SKS */
new_ch = I_GETSKCH (inst); /* get chan # */
if (new_ch != mt_dib.chan) return SCPE_IERR; /* wrong chan? */
if ((inst & (DEV_OUT | DEV_MTS)) == 0) { /* not sks 1n? */
t = I_GETSKCND (inst); /* get skip cond */
switch (t) { /* case sks cond */
case 001: /* sks 1021n */
*dat = 1; /* not magpak */
break;
case 002: /* sks 1041n */
if (!(uptr->flags & UNIT_ATT) || /* not ready */
sim_is_active (uptr)) *dat = 1;
break;
case 004: /* sks 1101n */
if (!uptr->eotf) *dat = 1; /* not EOT */
break;
case 010: /* sks 1201n */
if (!uptr->botf) *dat = 1; /* not BOT */
break;
case 013: /* sks 12610 */
if (!mt_gap) *dat = 1; /* not in gap */
break;
case 017: /* sks 13610 */
if (!mt_eof) *dat = 1; /* not EOF */
break;
case 020: /* sks 1401n */
if (!sim_tape_wrp (uptr)) *dat = 1; /* not wrp */
break;
case 031: /* sks 1621n */
case 033: /* sks 1661n */
*dat = 1; /* not 556bpi */
case 035: /* sks 1721n */
break; } /* not 800bpi */
} /* end if */
break;
case IO_WREOR: /* write eor */
chan_set_flag (mt_dib.chan, CHF_EOR); /* set eor flg */
if (r = mt_wrend (inst)) return r; /* end record */
mt_gap = 1; /* in gap */
sim_activate (uptr, mt_gtime); /* start timer */
break;
case IO_READ: /* read */
xfr_req = xfr_req & ~XFR_MT0; /* clr xfr flag */
if (mt_blnt == 0) { /* first read? */
r = mt_readrec (uptr); /* get data */
if ((r != SCPE_OK) || (mt_blnt == 0)) return r; } /* err, inv reclnt? */
uptr->botf = 0; /* off BOT */
if (mt_inst & CHC_REV) chr = mtxb[--mt_bptr] & 077; /* get next rev */
else chr = mtxb[mt_bptr++] & 077; /* get next fwd */
if (!(mt_inst & CHC_BIN)) chr = bcd_to_sds[chr]; /* bcd? */
*dat = chr & 077; /* give to chan */
if ((mt_inst & CHC_REV)? (mt_bptr <= 0): /* rev or fwd, */
(mt_bptr >= mt_blnt)) mt_readend (uptr); /* recd done? */
break;
case IO_SKS: /* SKS */
new_ch = I_GETSKCH (inst); /* get chan # */
if (new_ch != mt_dib.chan) return SCPE_IERR; /* wrong chan? */
if ((inst & (DEV_OUT | DEV_MTS)) == 0) { /* not sks 1n? */
t = I_GETSKCND (inst); /* get skip cond */
switch (t) { /* case sks cond */
case 001: /* sks 1021n */
*dat = 1; /* not magpak */
break;
case 002: /* sks 1041n */
if (!(uptr->flags & UNIT_ATT) || /* not ready */
sim_is_active (uptr)) *dat = 1;
break;
case 004: /* sks 1101n */
if (!uptr->eotf) *dat = 1; /* not EOT */
break;
case 010: /* sks 1201n */
if (!uptr->botf) *dat = 1; /* not BOT */
break;
case 013: /* sks 12610 */
if (!mt_gap) *dat = 1; /* not in gap */
break;
case 017: /* sks 13610 */
if (!mt_eof) *dat = 1; /* not EOF */
break;
case 020: /* sks 1401n */
if (!sim_tape_wrp (uptr)) *dat = 1; /* not wrp */
break;
case 031: /* sks 1621n */
case 033: /* sks 1661n */
*dat = 1; /* not 556bpi */
case 035: /* sks 1721n */
break; /* not 800bpi */
}
} /* end if */
break;
case IO_WRITE: /* write */
uptr->botf = 0; /* off BOT */
chr = (*dat) & 077;
xfr_req = xfr_req & ~XFR_MT0; /* clr xfr flag */
if (!(mt_inst & CHC_BIN)) chr = sds_to_bcd[chr]; /* bcd? */
if (mt_bptr < MT_MAXFR) mtxb[mt_bptr++] = chr; /* insert in buf */
break;
case IO_READ: /* read */
xfr_req = xfr_req & ~XFR_MT0; /* clr xfr flag */
if (mt_blnt == 0) { /* first read? */
r = mt_readrec (uptr); /* get data */
if ((r != SCPE_OK) || (mt_blnt == 0)) return r; /* err, inv reclnt? */
}
uptr->botf = 0; /* off BOT */
if (mt_inst & CHC_REV) chr = mtxb[--mt_bptr] & 077; /* get next rev */
else chr = mtxb[mt_bptr++] & 077; /* get next fwd */
if (!(mt_inst & CHC_BIN)) chr = bcd_to_sds[chr];/* bcd? */
*dat = chr & 077; /* give to chan */
if ((mt_inst & CHC_REV)? (mt_bptr <= 0): /* rev or fwd, */
(mt_bptr >= mt_blnt)) mt_readend (uptr); /* recd done? */
break;
default:
CRETINS; }
case IO_WRITE: /* write */
uptr->botf = 0; /* off BOT */
chr = (*dat) & 077;
xfr_req = xfr_req & ~XFR_MT0; /* clr xfr flag */
if (!(mt_inst & CHC_BIN)) chr = sds_to_bcd[chr];/* bcd? */
if (mt_bptr < MT_MAXFR) mtxb[mt_bptr++] = chr; /* insert in buf */
break;
default:
CRETINS;
}
return SCPE_OK;
}
/* Unit service */
t_stat mt_svc (UNIT *uptr)
{
if (mt_gap) { /* gap timeout */
mt_gap = 0; /* clr gap flg */
chan_disc (mt_dib.chan); } /* disc chan */
else if (mt_skip) mt_readend (uptr); /* skip record */
else { /* normal xfr */
xfr_req = xfr_req | XFR_MT0; /* set xfr req */
sim_activate (uptr, mt_ctime); } /* reactivate */
if (mt_gap) { /* gap timeout */
mt_gap = 0; /* clr gap flg */
chan_disc (mt_dib.chan); /* disc chan */
}
else if (mt_skip) mt_readend (uptr); /* skip record */
else { /* normal xfr */
xfr_req = xfr_req | XFR_MT0; /* set xfr req */
sim_activate (uptr, mt_ctime); /* reactivate */
}
return SCPE_OK;
}
@@ -307,26 +325,29 @@ return SCPE_OK;
t_stat mt_readrec (UNIT *uptr)
{
t_mtrlnt tbc;
t_stat st, r = SCPE_OK;
t_stat st;
if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */
mt_set_err (uptr); /* no, err, disc */
return SCPE_UNATT; }
if (mt_inst & CHC_REV) /* reverse? */
st = sim_tape_rdrecr (uptr, mtxb, &tbc, MT_MAXFR); /* read rec rev */
else st = sim_tape_rdrecf (uptr, mtxb, &tbc, MT_MAXFR); /* no, fwd */
if (st == MTSE_TMK) { /* tape mark? */
mt_eof = 1; /* set eof flag */
mtxb[0] = mtxb[1] = 017; /* EOR char */
mt_blnt = 2; /* store 2 */
return SCPE_OK; }
if (st != MTSE_OK) { /* other error? */
mt_set_err (uptr); /* err, disc */
if (st == MTSE_IOERR) return SCPE_IOERR; /* IO error? */
if (st == MTSE_INVRL) return SCPE_MTRLNT; /* inv rec lnt? */
if (st == MTSE_EOM) uptr->eotf = 1; /* eom? set eot */
return SCPE_OK; }
mt_blnt = tbc; /* set buf lnt */
if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */
mt_set_err (uptr); /* no, err, disc */
return SCPE_UNATT;
}
if (mt_inst & CHC_REV) /* reverse? */
st = sim_tape_rdrecr (uptr, mtxb, &tbc, MT_MAXFR); /* read rec rev */
else st = sim_tape_rdrecf (uptr, mtxb, &tbc, MT_MAXFR); /* no, fwd */
if (st == MTSE_TMK) { /* tape mark? */
mt_eof = 1; /* set eof flag */
mtxb[0] = mtxb[1] = 017; /* EOR char */
mt_blnt = 2; /* store 2 */
return SCPE_OK;
}
if (st != MTSE_OK) { /* other error? */
mt_set_err (uptr); /* err, disc */
if (st == MTSE_IOERR) return SCPE_IOERR; /* IO error? */
if (st == MTSE_INVRL) return SCPE_MTRLNT; /* inv rec lnt? */
if (st == MTSE_EOM) uptr->eotf = 1; /* eom? set eot */
return SCPE_OK;
}
mt_blnt = tbc; /* set buf lnt */
return SCPE_OK;
}
@@ -334,16 +355,17 @@ return SCPE_OK;
void mt_readend (UNIT *uptr)
{
sim_cancel (uptr); /* stop timer */
mt_skip = 0; /* clr skp flg */
chan_set_flag (mt_dib.chan, CHF_EOR); /* end record */
if (mt_eof) chan_disc (mt_dib.chan); /* EOF? */
sim_cancel (uptr); /* stop timer */
mt_skip = 0; /* clr skp flg */
chan_set_flag (mt_dib.chan, CHF_EOR); /* end record */
if (mt_eof) chan_disc (mt_dib.chan); /* EOF? */
else {
mt_gap = 1; /* no, in gap */
sim_activate (uptr, mt_gtime); } /* start timer */
mt_gap = 1; /* no, in gap */
sim_activate (uptr, mt_gtime); /* start timer */
}
return;
}
/* Write complete (end of record or disconnect) */
t_stat mt_wrend (uint32 dev)
@@ -352,40 +374,42 @@ UNIT *uptr = mt_dev.units + (dev & MT_UNIT);
t_mtrlnt tbc;
t_stat st;
sim_cancel (uptr); /* no more xfr's */
if (mt_bptr == 0) return SCPE_OK; /* buf empty? */
if (!(uptr->flags & UNIT_ATT)) { /* attached? */
mt_set_err (uptr); /* no, err, disc */
return SCPE_UNATT; }
if (sim_tape_wrp (uptr)) { /* write lock? */
mt_set_err (uptr); /* yes, err, disc */
return SCPE_OK; }
if (dev & DEV_MTS) { /* erase? */
if (mt_inst & CHC_REV) /* reverse? */
sim_tape_sprecr (uptr, &tbc); /* backspace */
st = sim_tape_wreom (uptr); /* write eom */
sim_cancel (uptr); /* no more xfr's */
if (mt_bptr == 0) return SCPE_OK; /* buf empty? */
if (!(uptr->flags & UNIT_ATT)) { /* attached? */
mt_set_err (uptr); /* no, err, disc */
return SCPE_UNATT;
}
if (sim_tape_wrp (uptr)) { /* write lock? */
mt_set_err (uptr); /* yes, err, disc */
return SCPE_OK;
}
if (dev & DEV_MTS) { /* erase? */
if (mt_inst & CHC_REV) /* reverse? */
sim_tape_sprecr (uptr, &tbc); /* backspace */
st = sim_tape_wreom (uptr); /* write eom */
}
else {
if ((mt_bptr == 1) && (mtxb[0] == 017) && /* wr eof? */
((mt_inst & 01670) == 00050))
st = sim_tape_wrtmk (uptr); /* write tape mark */
else st = sim_tape_wrrecf (uptr, mtxb, mt_bptr); /* write record */
if ((mt_bptr == 1) && (mtxb[0] == 017) && /* wr eof? */
((mt_inst & 01670) == 00050))
st = sim_tape_wrtmk (uptr); /* write tape mark */
else st = sim_tape_wrrecf (uptr, mtxb, mt_bptr); /* write record */
}
mt_bptr = 0;
if (st != MTSE_OK) mt_set_err (uptr); /* error? */
if (st != MTSE_OK) mt_set_err (uptr); /* error? */
if (st == MTSE_IOERR) return SCPE_IOERR;
return SCPE_OK;
}
/* Fatal error */
void mt_set_err (UNIT *uptr)
{
chan_set_flag (mt_dib.chan, CHF_EOR | CHF_ERR); /* eor, error */
chan_disc (mt_dib.chan); /* disconnect */
xfr_req = xfr_req & ~XFR_MT0; /* clear xfr */
sim_cancel (uptr); /* stop */
mt_bptr = 0; /* buf empty */
chan_set_flag (mt_dib.chan, CHF_EOR | CHF_ERR); /* eor, error */
chan_disc (mt_dib.chan); /* disconnect */
xfr_req = xfr_req & ~XFR_MT0; /* clear xfr */
sim_cancel (uptr); /* stop */
mt_bptr = 0; /* buf empty */
return;
}
/* Reset routine */
@@ -394,17 +418,18 @@ t_stat mt_reset (DEVICE *dptr)
{
int32 i;
chan_disc (mt_dib.chan); /* disconnect */
mt_eof = 0; /* clear state */
chan_disc (mt_dib.chan); /* disconnect */
mt_eof = 0; /* clear state */
mt_gap = 0;
mt_skip = 0;
mt_inst = 0;
mt_bptr = mt_blnt = 0;
xfr_req = xfr_req & ~XFR_MT0; /* clr xfr flag */
for (i = 0; i < MT_NUMDR; i++) { /* deactivate */
xfr_req = xfr_req & ~XFR_MT0; /* clr xfr flag */
for (i = 0; i < MT_NUMDR; i++) { /* deactivate */
sim_cancel (&mt_unit[i]);
sim_tape_reset (&mt_unit[i]);
mt_unit[i].eotf = 0; }
mt_unit[i].eotf = 0;
}
return SCPE_OK;
}
@@ -433,12 +458,12 @@ t_stat mt_boot (int32 unitno, DEVICE *dptr)
{
extern uint32 P, M[];
if (unitno) return SCPE_ARG; /* only unit 0 */
M[0] = 077777771; /* -7B */
M[1] = 007100000; /* LDX 0 */
M[2] = 000203610; /* EOM 3610B */
M[3] = 003200002; /* WIM 2 */
M[4] = 000100002; /* BRU 2 */
P = 1; /* start at 1 */
if (unitno) return SCPE_ARG; /* only unit 0 */
M[0] = 077777771; /* -7B */
M[1] = 007100000; /* LDX 0 */
M[2] = 000203610; /* EOM 3610B */
M[3] = 003200002; /* WIM 2 */
M[4] = 000100002; /* BRU 2 */
P = 1; /* start at 1 */
return SCPE_OK;
}

View File

@@ -1,6 +1,6 @@
/* sds_mux.c: SDS 940 terminal multiplexor simulator
Copyright (c) 2001-2004, Robert M Supnik
Copyright (c) 2001-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,14 +19,16 @@
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.
mux terminal multiplexor
mux terminal multiplexor
05-Jan-04 RMS Revised for tmxr library changes
09-May-03 RMS Added network device flag
29-Jun-05 RMS Added SET MUXLn DISCONNECT
21-Jun-05 RMS Fixed bug in SHOW CONN/STATS
05-Jan-04 RMS Revised for tmxr library changes
09-May-03 RMS Added network device flag
This module implements up to 32 individual serial interfaces, representing
either the project Genie terminal multiplexor or the SDS 940 CTE option.
@@ -37,80 +39,81 @@
#include "sim_tmxr.h"
#include <ctype.h>
#define PROJ_GENIE (cpu_unit.flags & UNIT_GENIE)
#define MUX_NUMLIN mux_desc.lines
#define PROJ_GENIE (cpu_unit.flags & UNIT_GENIE)
#define MUX_NUMLIN mux_desc.lines
#define MUX_LINES 32 /* lines */
#define MUX_FLAGS 4 /* intr per line */
#define MUX_FLAGMASK (MUX_FLAGS - 1)
#define MUX_SCANMAX (MUX_LINES * MUX_FLAGS) /* flags to scan */
#define MUX_SCANMASK (MUX_SCANMAX - 1)
#define UNIT_V_UC (UNIT_V_UF + 0) /* UC only */
#define UNIT_UC (1 << UNIT_V_UC)
#define MUX_INIT_POLL 8000
#define MUXL_WAIT 500
#define MUX_SETFLG(l,x) mux_flags[((l) * MUX_FLAGS) + (x)] = 1
#define MUX_SETINT(x) int_req = int_req | (INT_MUXR >> (x))
#define MUX_CLRINT(x) int_req = int_req & ~(INT_MUXR >> (x))
#define MUX_LINES 32 /* lines */
#define MUX_FLAGS 4 /* intr per line */
#define MUX_FLAGMASK (MUX_FLAGS - 1)
#define MUX_SCANMAX (MUX_LINES * MUX_FLAGS) /* flags to scan */
#define MUX_SCANMASK (MUX_SCANMAX - 1)
#define UNIT_V_UC (UNIT_V_UF + 0) /* UC only */
#define UNIT_UC (1 << UNIT_V_UC)
#define MUX_INIT_POLL 8000
#define MUXL_WAIT 500
#define MUX_SETFLG(l,x) mux_flags[((l) * MUX_FLAGS) + (x)] = 1
#define MUX_SETINT(x) int_req = int_req | (INT_MUXR >> (x))
#define MUX_CLRINT(x) int_req = int_req & ~(INT_MUXR >> (x))
/* PIN/POT */
#define P_V_CHAR 16 /* char */
#define P_M_CHAR 0377
#define P_CHAR(x) (((x) >> P_V_CHAR) & P_M_CHAR)
#define PIN_OVR 000100000 /* overrun */
#define POT_NOX 000100000 /* no xmit */
#define POT_XMI 000040000 /* xmit int */
#define POT_GLNE 000020000 /* Genie: enable */
#define POT_SCDT 000020000 /* 940: clr DTR */
#define P_V_CHAN 0 /* channel */
#define P_M_CHAN (MUX_LINES - 1)
#define P_CHAN(x) (((x) >> P_V_CHAN) & P_M_CHAN)
#define P_V_CHAR 16 /* char */
#define P_M_CHAR 0377
#define P_CHAR(x) (((x) >> P_V_CHAR) & P_M_CHAR)
#define PIN_OVR 000100000 /* overrun */
#define POT_NOX 000100000 /* no xmit */
#define POT_XMI 000040000 /* xmit int */
#define POT_GLNE 000020000 /* Genie: enable */
#define POT_SCDT 000020000 /* 940: clr DTR */
#define P_V_CHAN 0 /* channel */
#define P_M_CHAN (MUX_LINES - 1)
#define P_CHAN(x) (((x) >> P_V_CHAN) & P_M_CHAN)
/* SKS 940 */
#define SKS_XBE 000001000 /* xmt buf empty */
#define SKS_CRO 000000400 /* carrier on */
#define SKS_DSR 000000200 /* data set ready */
#define SKS_CHAN(x) P_CHAN(x)
#define SKS_XBE 000001000 /* xmt buf empty */
#define SKS_CRO 000000400 /* carrier on */
#define SKS_DSR 000000200 /* data set ready */
#define SKS_CHAN(x) P_CHAN(x)
/* SKS Genie */
#define SKG_V_CHAN 7
#define SKG_M_CHAN (MUX_LINES - 1)
#define SKG_CHAN(x) (((x) >> SKG_V_CHAN) & SKG_M_CHAN)
#define SKG_V_CHAN 7
#define SKG_M_CHAN (MUX_LINES - 1)
#define SKG_CHAN(x) (((x) >> SKG_V_CHAN) & SKG_M_CHAN)
/* Flags */
#define MUX_FRCV 0 /* receive */
#define MUX_FXMT 1 /* transmit */
#define MUX_FCRN 2 /* carrier on */
#define MUX_FCRF 3 /* carrier off */
#define MUX_FRCV 0 /* receive */
#define MUX_FXMT 1 /* transmit */
#define MUX_FCRN 2 /* carrier on */
#define MUX_FCRF 3 /* carrier off */
/* Line status */
#define MUX_SCHP 001 /* char pending */
#define MUX_SOVR 002 /* overrun */
#define MUX_SLNE 004 /* line enabled */
#define MUX_SXIE 010 /* xmt int enab */
#define MUX_SCRO 020 /* carrier on */
#define MUX_SDSR 040 /* data set ready */
#define MUX_SCHP 001 /* char pending */
#define MUX_SOVR 002 /* overrun */
#define MUX_SLNE 004 /* line enabled */
#define MUX_SXIE 010 /* xmt int enab */
#define MUX_SCRO 020 /* carrier on */
#define MUX_SDSR 040 /* data set ready */
/* Data */
extern uint32 alert, int_req;
extern int32 stop_invins, stop_invdev, stop_inviop;
extern UNIT cpu_unit;
uint8 mux_rbuf[MUX_LINES]; /* rcv buf */
uint8 mux_xbuf[MUX_LINES]; /* xmt buf */
uint8 mux_sta[MUX_LINES]; /* status */
uint8 mux_flags[MUX_SCANMAX]; /* flags */
uint32 mux_tps = 100; /* polls/second */
uint32 mux_scan = 0; /* scanner */
uint32 mux_slck = 0; /* scanner locked */
uint8 mux_rbuf[MUX_LINES]; /* rcv buf */
uint8 mux_xbuf[MUX_LINES]; /* xmt buf */
uint8 mux_sta[MUX_LINES]; /* status */
uint8 mux_flags[MUX_SCANMAX]; /* flags */
uint32 mux_tps = 100; /* polls/second */
uint32 mux_scan = 0; /* scanner */
uint32 mux_slck = 0; /* scanner locked */
TMLN mux_ldsc[MUX_LINES] = { 0 }; /* line descriptors */
TMXR mux_desc = { MUX_LINES, 0, 0, mux_ldsc }; /* mux descriptor */
TMLN mux_ldsc[MUX_LINES] = { 0 }; /* line descriptors */
TMXR mux_desc = { MUX_LINES, 0, 0, mux_ldsc }; /* mux descriptor */
t_stat mux (uint32 fnc, uint32 inst, uint32 *dat);
t_stat muxi_svc (UNIT *uptr);
@@ -123,13 +126,13 @@ t_stat mux_show (FILE *st, UNIT *uptr, int32 val, void *desc);
t_stat mux_vlines (UNIT *uptr, int32 val, char *cptr, void *desc);
void mux_reset_ln (int32 ln);
void mux_scan_next (void);
/* MUX data structures
mux_dev MUX device descriptor
mux_unit MUX unit descriptor
mux_reg MUX register list
mux_mod MUX modifiers list
mux_dev MUX device descriptor
mux_unit MUX unit descriptor
mux_reg MUX register list
mux_mod MUX modifiers list
*/
DIB mux_dib = { -1, DEV3_GMUX, 0, NULL, &mux };
@@ -139,97 +142,106 @@ REG mux_nlreg = { DRDATA (NLINES, MUX_NUMLIN, 6), PV_LEFT };
UNIT mux_unit = { UDATA (&muxi_svc, UNIT_ATTABLE, 0), MUX_INIT_POLL };
REG mux_reg[] = {
{ BRDATA (STA, mux_sta, 8, 6, MUX_LINES) },
{ BRDATA (RBUF, mux_rbuf, 8, 8, MUX_LINES) },
{ BRDATA (XBUF, mux_xbuf, 8, 8, MUX_LINES) },
{ BRDATA (INT, mux_flags, 8, 1, MUX_SCANMAX) },
{ ORDATA (SCAN, mux_scan, 7) },
{ FLDATA (SLCK, mux_slck, 0) },
{ DRDATA (TPS, mux_tps, 8), REG_NZ + PV_LEFT },
{ NULL } };
{ BRDATA (STA, mux_sta, 8, 6, MUX_LINES) },
{ BRDATA (RBUF, mux_rbuf, 8, 8, MUX_LINES) },
{ BRDATA (XBUF, mux_xbuf, 8, 8, MUX_LINES) },
{ BRDATA (INT, mux_flags, 8, 1, MUX_SCANMAX) },
{ ORDATA (SCAN, mux_scan, 7) },
{ FLDATA (SLCK, mux_slck, 0) },
{ DRDATA (TPS, mux_tps, 8), REG_NZ + PV_LEFT },
{ NULL }
};
MTAB mux_mod[] = {
{ MTAB_XTD | MTAB_VDV | MTAB_VAL, 0, "lines", "LINES",
&mux_vlines, NULL, &mux_nlreg },
{ MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT",
&tmxr_dscln, NULL, &mux_desc },
{ UNIT_ATT, UNIT_ATT, "connections", NULL, NULL, &mux_summ },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL,
NULL, &mux_show, NULL },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL,
NULL, &mux_show, NULL },
{ 0 } };
{ MTAB_XTD | MTAB_VDV | MTAB_VAL, 0, "lines", "LINES",
&mux_vlines, NULL, &mux_nlreg },
{ MTAB_XTD | MTAB_VDV, 1, NULL, "DISCONNECT",
&tmxr_dscln, NULL, &mux_desc },
{ UNIT_ATT, UNIT_ATT, "connections", NULL, NULL, &mux_summ },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "CONNECTIONS", NULL,
NULL, &mux_show, NULL },
{ MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATISTICS", NULL,
NULL, &mux_show, NULL },
{ 0 }
};
DEVICE mux_dev = {
"MUX", &mux_unit, mux_reg, mux_mod,
1, 10, 31, 1, 8, 8,
&tmxr_ex, &tmxr_dep, &mux_reset,
NULL, &mux_attach, &mux_detach,
&mux_dib, DEV_NET | DEV_DISABLE };
"MUX", &mux_unit, mux_reg, mux_mod,
1, 10, 31, 1, 8, 8,
&tmxr_ex, &tmxr_dep, &mux_reset,
NULL, &mux_attach, &mux_detach,
&mux_dib, DEV_NET | DEV_DISABLE
};
/* MUXL data structures
muxl_dev MUXL device descriptor
muxl_unit MUXL unit descriptor
muxl_reg MUXL register list
muxl_mod MUXL modifiers list
muxl_dev MUXL device descriptor
muxl_unit MUXL unit descriptor
muxl_reg MUXL register list
muxl_mod MUXL modifiers list
*/
UNIT muxl_unit[] = {
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT } };
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT },
{ UDATA (&muxo_svc, UNIT_UC, 0), MUXL_WAIT }
};
MTAB muxl_mod[] = {
{ UNIT_UC, 0, "lower case", "LC", NULL },
{ UNIT_UC, UNIT_UC, "upper case", "UC", NULL },
{ MTAB_XTD|MTAB_VUN|MTAB_NC, 0, "LOG", "LOG",
&tmxr_set_log, &tmxr_show_log, &mux_desc },
{ MTAB_XTD|MTAB_VUN|MTAB_NC, 0, NULL, "NOLOG",
&tmxr_set_nolog, NULL, &mux_desc },
{ 0 } };
{ UNIT_UC, 0, "lower case", "LC", NULL },
{ UNIT_UC, UNIT_UC, "upper case", "UC", NULL },
{ MTAB_XTD|MTAB_VUN, 0, NULL, "DISCONNECT",
&tmxr_dscln, NULL, &mux_desc },
{ MTAB_XTD|MTAB_VUN|MTAB_NC, 0, "LOG", "LOG",
&tmxr_set_log, &tmxr_show_log, &mux_desc },
{ MTAB_XTD|MTAB_VUN|MTAB_NC, 0, NULL, "NOLOG",
&tmxr_set_nolog, NULL, &mux_desc },
{ 0 }
};
REG muxl_reg[] = {
{ URDATA (TIME, muxl_unit[0].wait, 10, 24, 0,
MUX_LINES, REG_NZ + PV_LEFT) },
{ NULL } };
{ URDATA (TIME, muxl_unit[0].wait, 10, 24, 0,
MUX_LINES, REG_NZ + PV_LEFT) },
{ NULL }
};
DEVICE muxl_dev = {
"MUXL", muxl_unit, muxl_reg, muxl_mod,
MUX_LINES, 10, 31, 1, 8, 8,
NULL, NULL, &mux_reset,
NULL, NULL, NULL,
NULL, 0 };
"MUXL", muxl_unit, muxl_reg, muxl_mod,
MUX_LINES, 10, 31, 1, 8, 8,
NULL, NULL, &mux_reset,
NULL, NULL, NULL,
NULL, 0
};
/* MUX: IO routine */
/* Mux routine - EOM 30001 or EOM 77777,2 */
@@ -239,25 +251,32 @@ t_stat mux (uint32 fnc, uint32 inst, uint32 *dat)
uint32 ln;
switch (fnc) {
case IO_CONN: /* connect */
if ((PROJ_GENIE && (inst == 000230001)) || /* set alert */
(!PROJ_GENIE && (inst == 020277777))) alert = POT_MUX;
else CRETINS;
break;
case IO_SKS: /* skip */
if (PROJ_GENIE && ((inst & 077770077) == 004030001)) {
ln = SKG_CHAN (inst); /* get line */
if (!sim_is_active (&muxl_unit[ln])) *dat = 1; }
else if (!PROJ_GENIE && ((inst & 077776000) == 024076000)) {
ln = SKS_CHAN (inst); /* get line */
if (inst & (SKS_XBE|SKS_CRO|SKS_DSR)) *dat = 1;
if (((inst & SKS_XBE) && sim_is_active (&muxl_unit[ln])) ||
((inst & SKS_CRO) && !(mux_sta[ln] & MUX_SCRO)) ||
((inst & SKS_DSR) && !(mux_sta[ln] & MUX_SDSR)))
*dat = 0; } /* no skip if fail */
else CRETINS;
default:
return SCPE_IERR; } /* end case */
case IO_CONN: /* connect */
if ((PROJ_GENIE && (inst == 000230001)) || /* set alert */
(!PROJ_GENIE && (inst == 020277777))) alert = POT_MUX;
else CRETINS;
break;
case IO_SKS: /* skip */
if (PROJ_GENIE && ((inst & 077770077) == 004030001)) {
ln = SKG_CHAN (inst); /* get line */
if (!sim_is_active (&muxl_unit[ln])) *dat = 1;
}
else if (!PROJ_GENIE && ((inst & 077776000) == 024076000)) {
ln = SKS_CHAN (inst); /* get line */
if (inst & (SKS_XBE|SKS_CRO|SKS_DSR)) *dat = 1;
if (((inst & SKS_XBE) && sim_is_active (&muxl_unit[ln])) ||
((inst & SKS_CRO) && !(mux_sta[ln] & MUX_SCRO)) ||
((inst & SKS_DSR) && !(mux_sta[ln] & MUX_SDSR)))
*dat = 0; /* no skip if fail */
}
else CRETINS;
default:
return SCPE_IERR;
} /* end case */
return SCPE_OK;
}
@@ -268,15 +287,16 @@ t_stat pin_mux (uint32 num, uint32 *dat)
uint32 ln = mux_scan >> 2;
uint32 flag = mux_scan & MUX_FLAGMASK;
mux_scan = mux_scan & MUX_SCANMASK; /* mask scan */
mux_flags[mux_scan] = 0; /* clear flag */
if (flag == MUX_FRCV) { /* rcv event? */
*dat = ln | ((uint32) mux_rbuf[ln] << P_V_CHAR) | /* line + char + */
((mux_sta[ln] & MUX_SOVR)? PIN_OVR: 0); /* overrun */
mux_sta[ln] = mux_sta[ln] & ~(MUX_SCHP | MUX_SOVR); }
else *dat = ln; /* just line */
mux_slck = 0; /* unlock scanner */
mux_scan_next (); /* kick scanner */
mux_scan = mux_scan & MUX_SCANMASK; /* mask scan */
mux_flags[mux_scan] = 0; /* clear flag */
if (flag == MUX_FRCV) { /* rcv event? */
*dat = ln | ((uint32) mux_rbuf[ln] << P_V_CHAR) | /* line + char + */
((mux_sta[ln] & MUX_SOVR)? PIN_OVR: 0); /* overrun */
mux_sta[ln] = mux_sta[ln] & ~(MUX_SCHP | MUX_SOVR);
}
else *dat = ln; /* just line */
mux_slck = 0; /* unlock scanner */
mux_scan_next (); /* kick scanner */
return SCPE_OK;
}
@@ -285,29 +305,34 @@ t_stat pot_mux (uint32 num, uint32 *dat)
uint32 ln = P_CHAN (*dat);
uint32 chr = P_CHAR (*dat);
if (PROJ_GENIE && ((*dat & POT_GLNE) == 0)) { /* Genie disable? */
mux_sta[ln] = mux_sta[ln] & ~MUX_SLNE; /* clear status */
mux_ldsc[ln].rcve = 0; }
else if (!PROJ_GENIE && (*dat & POT_SCDT)) { /* SDS disable? */
if (mux_ldsc[ln].conn) { /* connected? */
tmxr_linemsg (&mux_ldsc[ln], "\r\nLine hangup\r\n");
tmxr_reset_ln (&mux_ldsc[ln]); /* reset line */
mux_reset_ln (ln); /* reset state */
MUX_SETFLG (ln, MUX_FCRF); /* set carrier off */
mux_scan_next (); } /* kick scanner */
mux_sta[ln] = mux_sta[ln] & ~MUX_SLNE; /* clear status */
mux_ldsc[ln].rcve = 0; }
else { /* enabled */
if ((*dat & POT_NOX) == 0) { /* output char? */
mux_xbuf[ln] = chr; /* store char */
sim_activate (&muxl_unit[ln], muxl_unit[ln].wait); }
if (PROJ_GENIE && ((*dat & POT_GLNE) == 0)) { /* Genie disable? */
mux_sta[ln] = mux_sta[ln] & ~MUX_SLNE; /* clear status */
mux_ldsc[ln].rcve = 0;
}
else if (!PROJ_GENIE && (*dat & POT_SCDT)) { /* SDS disable? */
if (mux_ldsc[ln].conn) { /* connected? */
tmxr_linemsg (&mux_ldsc[ln], "\r\nLine hangup\r\n");
tmxr_reset_ln (&mux_ldsc[ln]); /* reset line */
mux_reset_ln (ln); /* reset state */
MUX_SETFLG (ln, MUX_FCRF); /* set carrier off */
mux_scan_next (); /* kick scanner */
}
mux_sta[ln] = mux_sta[ln] & ~MUX_SLNE; /* clear status */
mux_ldsc[ln].rcve = 0;
}
else { /* enabled */
if ((*dat & POT_NOX) == 0) { /* output char? */
mux_xbuf[ln] = chr; /* store char */
sim_activate (&muxl_unit[ln], muxl_unit[ln].wait);
}
if (*dat & POT_XMI) mux_sta[ln] = mux_sta[ln] | MUX_SXIE;
else mux_sta[ln] = mux_sta[ln] & ~MUX_SXIE;
mux_sta[ln] = mux_sta[ln] | MUX_SLNE; /* line is enabled */
mux_ldsc[ln].rcve = 1; }
mux_sta[ln] = mux_sta[ln] | MUX_SLNE; /* line is enabled */
mux_ldsc[ln].rcve = 1;
}
return SCPE_OK;
}
/* Unit service - receive side
Poll all active lines for input
@@ -318,31 +343,35 @@ t_stat muxi_svc (UNIT *uptr)
{
int32 ln, c, t;
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */
t = sim_rtcn_calb (mux_tps, TMR_MUX); /* calibrate */
sim_activate (uptr, t); /* continue poll */
ln = tmxr_poll_conn (&mux_desc); /* look for connect */
if (ln >= 0) { /* got one? */
if (!PROJ_GENIE && (mux_sta[ln] & MUX_SLNE)) { /* modem & DTR? */
mux_sta[ln] = mux_sta[ln] | (MUX_SCRO|MUX_SDSR);/* carrier on */
MUX_SETFLG (ln, MUX_FCRN); /* set carr on flag */
mux_scan_next (); } /* kick scanner */
mux_ldsc[ln].rcve = 1; } /* set rcv enable */
tmxr_poll_rx (&mux_desc); /* poll for input */
for (ln = 0; ln < MUX_NUMLIN; ln++) { /* loop thru lines */
if (mux_ldsc[ln].conn) { /* connected? */
if (c = tmxr_getc_ln (&mux_ldsc[ln])) { /* get char */
if (mux_sta[ln] & MUX_SCHP) /* already got one? */
mux_sta[ln] = mux_sta[ln] | MUX_SOVR; /* overrun */
else mux_sta[ln] = mux_sta[ln] | MUX_SCHP; /* char pending */
c = c & 0177; /* mask to 7b */
if ((muxl_unit[ln].flags & UNIT_UC) && /* cvt to UC? */
islower (c & 0x7F)) c = toupper (c);
mux_rbuf[ln] = c; /* save char */
MUX_SETFLG (ln, MUX_FRCV); /* set rcv flag */
mux_scan_next (); } } /* kick scanner */
else mux_sta[ln] = 0; /* disconnected */
} /* end for */
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_OK; /* attached? */
t = sim_rtcn_calb (mux_tps, TMR_MUX); /* calibrate */
sim_activate (uptr, t); /* continue poll */
ln = tmxr_poll_conn (&mux_desc); /* look for connect */
if (ln >= 0) { /* got one? */
if (!PROJ_GENIE && (mux_sta[ln] & MUX_SLNE)) { /* modem & DTR? */
mux_sta[ln] = mux_sta[ln] | (MUX_SCRO|MUX_SDSR);/* carrier on */
MUX_SETFLG (ln, MUX_FCRN); /* set carr on flag */
mux_scan_next (); /* kick scanner */
}
mux_ldsc[ln].rcve = 1; /* set rcv enable */
}
tmxr_poll_rx (&mux_desc); /* poll for input */
for (ln = 0; ln < MUX_NUMLIN; ln++) { /* loop thru lines */
if (mux_ldsc[ln].conn) { /* connected? */
if (c = tmxr_getc_ln (&mux_ldsc[ln])) { /* get char */
if (mux_sta[ln] & MUX_SCHP) /* already got one? */
mux_sta[ln] = mux_sta[ln] | MUX_SOVR; /* overrun */
else mux_sta[ln] = mux_sta[ln] | MUX_SCHP; /* char pending */
c = c & 0177; /* mask to 7b */
if ((muxl_unit[ln].flags & UNIT_UC) && /* cvt to UC? */
islower (c & 0x7F)) c = toupper (c);
mux_rbuf[ln] = c; /* save char */
MUX_SETFLG (ln, MUX_FRCV); /* set rcv flag */
mux_scan_next (); /* kick scanner */
}
}
else mux_sta[ln] = 0; /* disconnected */
} /* end for */
return SCPE_OK;
}
@@ -351,22 +380,26 @@ return SCPE_OK;
t_stat muxo_svc (UNIT *uptr)
{
int32 c;
uint32 ln = uptr - muxl_unit; /* line # */
uint32 ln = uptr - muxl_unit; /* line # */
if (mux_ldsc[ln].conn) { /* connected? */
if (mux_ldsc[ln].xmte) { /* xmt enabled? */
c = mux_xbuf[ln] & 0177; /* get char */
if ((muxl_unit[ln].flags & UNIT_UC) && islower (c))
c = toupper (c); /* cvt to UC? */
tmxr_putc_ln (&mux_ldsc[ln], c); /* output char */
tmxr_poll_tx (&mux_desc); } /* poll xmt */
else { /* buf full */
tmxr_poll_tx (&mux_desc); /* poll xmt */
sim_activate (uptr, muxl_unit[ln].wait); /* wait */
return SCPE_OK; } }
if (mux_ldsc[ln].conn) { /* connected? */
if (mux_ldsc[ln].xmte) { /* xmt enabled? */
c = mux_xbuf[ln] & 0177; /* get char */
if ((muxl_unit[ln].flags & UNIT_UC) && islower (c))
c = toupper (c); /* cvt to UC? */
tmxr_putc_ln (&mux_ldsc[ln], c); /* output char */
tmxr_poll_tx (&mux_desc); /* poll xmt */
}
else { /* buf full */
tmxr_poll_tx (&mux_desc); /* poll xmt */
sim_activate (uptr, muxl_unit[ln].wait); /* wait */
return SCPE_OK;
}
}
if (mux_sta[ln] & MUX_SXIE) {
MUX_SETFLG (ln, MUX_FXMT); /* set flag */
mux_scan_next (); } /* kick scanner */
MUX_SETFLG (ln, MUX_FXMT); /* set flag */
mux_scan_next (); /* kick scanner */
}
return SCPE_OK;
}
@@ -376,33 +409,36 @@ void mux_scan_next (void)
{
int32 i;
if (mux_slck) return; /* locked? */
for (i = 0; i < MUX_SCANMAX; i++) { /* scan flags */
mux_scan = (mux_scan + 1) & MUX_SCANMASK; /* next flag */
if (mux_flags[mux_scan]) { /* flag set? */
mux_slck = 1; /* lock scanner */
MUX_SETINT (mux_scan & MUX_FLAGMASK); /* request int */
return; }
if (mux_slck) return; /* locked? */
for (i = 0; i < MUX_SCANMAX; i++) { /* scan flags */
mux_scan = (mux_scan + 1) & MUX_SCANMASK; /* next flag */
if (mux_flags[mux_scan]) { /* flag set? */
mux_slck = 1; /* lock scanner */
MUX_SETINT (mux_scan & MUX_FLAGMASK); /* request int */
return;
}
}
return;
}
/* Reset routine */
t_stat mux_reset (DEVICE *dptr)
{
int32 i, t;
if (mux_dev.flags & DEV_DIS) /* master disabled? */
muxl_dev.flags = muxl_dev.flags | DEV_DIS; /* disable lines */
if (mux_dev.flags & DEV_DIS) /* master disabled? */
muxl_dev.flags = muxl_dev.flags | DEV_DIS; /* disable lines */
else muxl_dev.flags = muxl_dev.flags & ~DEV_DIS;
if (mux_unit.flags & UNIT_ATT) { /* master att? */
if (mux_unit.flags & UNIT_ATT) { /* master att? */
if (!sim_is_active (&mux_unit)) {
t = sim_rtcn_init (mux_unit.wait, TMR_MUX);
sim_activate (&mux_unit, t); } } /* activate */
else sim_cancel (&mux_unit); /* else stop */
t = sim_rtcn_init (mux_unit.wait, TMR_MUX);
sim_activate (&mux_unit, t); /* activate */
}
}
else sim_cancel (&mux_unit); /* else stop */
for (i = 0; i < MUX_LINES; i++) mux_reset_ln (i);
for (i = 0; i < MUX_FLAGS; i++) MUX_CLRINT (i); /* clear all ints */
for (i = 0; i < MUX_FLAGS; i++) MUX_CLRINT (i); /* clear all ints */
return SCPE_OK;
}
@@ -413,10 +449,10 @@ t_stat mux_attach (UNIT *uptr, char *cptr)
t_stat r;
int32 t;
r = tmxr_attach (&mux_desc, uptr, cptr); /* attach */
if (r != SCPE_OK) return r; /* error */
r = tmxr_attach (&mux_desc, uptr, cptr); /* attach */
if (r != SCPE_OK) return r; /* error */
t = sim_rtcn_init (mux_unit.wait, TMR_MUX);
sim_activate (uptr, t); /* start poll */
sim_activate (uptr, t); /* start poll */
return SCPE_OK;
}
@@ -427,9 +463,9 @@ t_stat mux_detach (UNIT *uptr)
int32 i;
t_stat r;
r = tmxr_detach (&mux_desc, uptr); /* detach */
for (i = 0; i < MUX_LINES; i++) mux_ldsc[i].rcve = 0; /* disable rcv */
sim_cancel (uptr); /* stop poll */
r = tmxr_detach (&mux_desc, uptr); /* detach */
for (i = 0; i < MUX_LINES; i++) mux_ldsc[i].rcve = 0; /* disable rcv */
sim_cancel (uptr); /* stop poll */
return r;
}
@@ -449,14 +485,17 @@ return SCPE_OK;
t_stat mux_show (FILE *st, UNIT *uptr, int32 val, void *desc)
{
int32 i;
int32 i, t;
for (i = 0; (i < MUX_LINES) && (mux_ldsc[i].conn == 0); i++) ;
if (i < MUX_LINES) {
for (i = t = 0; i < MUX_LINES; i++) t = t + (mux_ldsc[i].conn != 0);
if (t) {
for (i = 0; i < MUX_LINES; i++) {
if (mux_ldsc[i].conn)
if (val) tmxr_fconns (st, &mux_ldsc[i], i);
else tmxr_fstats (st, &mux_ldsc[i], i); } }
if (mux_ldsc[i].conn) {
if (val) tmxr_fconns (st, &mux_ldsc[i], i);
else tmxr_fstats (st, &mux_ldsc[i], i);
}
}
}
else fprintf (st, "all disconnected\n");
return SCPE_OK;
}
@@ -475,18 +514,21 @@ if (newln == 0) return SCPE_ARG;
if (newln < MUX_NUMLIN) {
for (i = newln, t = 0; i < MUX_NUMLIN; i++) t = t | mux_ldsc[i].conn;
if (t && !get_yn ("This will disconnect users; proceed [N]?", FALSE))
return SCPE_OK;
return SCPE_OK;
for (i = newln; i < MUX_NUMLIN; i++) {
if (mux_ldsc[i].conn) {
tmxr_linemsg (&mux_ldsc[i], "\r\nOperator disconnected line\r\n");
tmxr_reset_ln (&mux_ldsc[i]); } /* reset line */
muxl_unit[i].flags = muxl_unit[i].flags | UNIT_DIS;
mux_reset_ln (i); }
if (mux_ldsc[i].conn) {
tmxr_linemsg (&mux_ldsc[i], "\r\nOperator disconnected line\r\n");
tmxr_reset_ln (&mux_ldsc[i]); /* reset line */
}
muxl_unit[i].flags = muxl_unit[i].flags | UNIT_DIS;
mux_reset_ln (i);
}
}
else {
for (i = MUX_NUMLIN; i < newln; i++) {
muxl_unit[i].flags = muxl_unit[i].flags & ~UNIT_DIS;
mux_reset_ln (i); }
muxl_unit[i].flags = muxl_unit[i].flags & ~UNIT_DIS;
mux_reset_ln (i);
}
}
MUX_NUMLIN = newln;
return SCPE_OK;

View File

@@ -1,6 +1,6 @@
/* sds_rad.c: SDS 940 fixed head disk simulator
Copyright (c) 2001-2004, Robert M. Supnik
Copyright (c) 2001-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,11 +19,11 @@
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.
rad fixed head disk
rad fixed head disk
The fixed head disk is a head-per-track disk, with up to four disks. Each
disk is divided into two logical units. Reads and writes cannot cross logical
@@ -36,32 +36,35 @@
/* Constants */
#define RAD_NUMWD 64 /* words/sector */
#define RAD_NUMSC 64 /* sectors/track */
#define RAD_NUMTR 64 /* tracks/log unit */
#define RAD_NUMLU 8 /* log units/ctrl */
#define RAD_SCSIZE (RAD_NUMLU*RAD_NUMTR*RAD_NUMSC) /* sectors/disk */
#define RAD_AMASK (RAD_SCSIZE - 1) /* sec addr mask */
#define RAD_SIZE (RAD_SCSIZE * RAD_NUMWD) /* words/disk */
#define RAD_GETLUN(x) ((x) / (RAD_NUMTR * RAD_NUMSC))
#define RAD_SCMASK (RAD_NUMSC - 1) /* sector mask */
#define RAD_TRSCMASK ((RAD_NUMSC * RAD_NUMTR) - 1) /* track/sec mask */
#define RAD_NUMWD 64 /* words/sector */
#define RAD_NUMSC 64 /* sectors/track */
#define RAD_NUMTR 64 /* tracks/log unit */
#define RAD_NUMLU 8 /* log units/ctrl */
#define RAD_SCSIZE (RAD_NUMLU*RAD_NUMTR*RAD_NUMSC) /* sectors/disk */
#define RAD_AMASK (RAD_SCSIZE - 1) /* sec addr mask */
#define RAD_SIZE (RAD_SCSIZE * RAD_NUMWD) /* words/disk */
#define RAD_GETLUN(x) ((x) / (RAD_NUMTR * RAD_NUMSC))
#define RAD_SCMASK (RAD_NUMSC - 1) /* sector mask */
#define RAD_TRSCMASK ((RAD_NUMSC * RAD_NUMTR) - 1) /* track/sec mask */
#define GET_SECTOR(x) ((int) fmod (sim_gtime() / ((double) (x)), \
((double) RAD_NUMSC)))
#define GET_SECTOR(x) ((int) fmod (sim_gtime() / ((double) (x)), \
((double) RAD_NUMSC)))
extern uint32 xfr_req;
extern uint32 alert;
extern int32 stop_invins, stop_invdev, stop_inviop;
int32 rad_err = 0; /* error */
int32 rad_nobi = 0; /* !incr x track */
int32 rad_da = 0; /* disk address */
int32 rad_sba = 0; /* sec byte addr */
int32 rad_wrp = 0; /* write prot */
int32 rad_time = 2; /* time per 12b */
int32 rad_stopioe = 1; /* stop on error */
DSPT rad_tplt[] = { /* template */
{ 1, 0 }, { 1, DEV_OUT }, { 0, 0 } };
int32 rad_err = 0; /* error */
int32 rad_nobi = 0; /* !incr x track */
int32 rad_da = 0; /* disk address */
int32 rad_sba = 0; /* sec byte addr */
int32 rad_wrp = 0; /* write prot */
int32 rad_time = 2; /* time per 12b */
int32 rad_stopioe = 1; /* stop on error */
DSPT rad_tplt[] = { /* template */
{ 1, 0 },
{ 1, DEV_OUT },
{ 0, 0 }
};
DEVICE rad_dev;
t_stat rad_svc (UNIT *uptr);
@@ -73,50 +76,54 @@ t_stat rad (uint32 fnc, uint32 inst, uint32 *dat);
/* RAD data structures
rad_dev device descriptor
rad_unit unit descriptor
rad_reg register list
rad_dev device descriptor
rad_unit unit descriptor
rad_reg register list
*/
DIB rad_dib = { CHAN_E, DEV_RAD, XFR_RAD, rad_tplt, &rad };
UNIT rad_unit =
{ UDATA (&rad_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF,
RAD_SIZE) };
UNIT rad_unit = {
UDATA (&rad_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF,
RAD_SIZE)
};
REG rad_reg[] = {
{ ORDATA (DA, rad_da, 15) },
{ GRDATA (SA, rad_sba, 8, 6, 1) },
{ FLDATA (BP, rad_sba, 0) },
{ FLDATA (XFR, xfr_req, XFR_V_RAD) },
{ FLDATA (NOBD, rad_nobi, 0) },
{ FLDATA (ERR, rad_err, 0) },
{ ORDATA (PROT, rad_wrp, 8) },
{ DRDATA (TIME, rad_time, 24), REG_NZ + PV_LEFT },
{ FLDATA (STOP_IOE, rad_stopioe, 0) },
{ NULL } };
{ ORDATA (DA, rad_da, 15) },
{ GRDATA (SA, rad_sba, 8, 6, 1) },
{ FLDATA (BP, rad_sba, 0) },
{ FLDATA (XFR, xfr_req, XFR_V_RAD) },
{ FLDATA (NOBD, rad_nobi, 0) },
{ FLDATA (ERR, rad_err, 0) },
{ ORDATA (PROT, rad_wrp, 8) },
{ DRDATA (TIME, rad_time, 24), REG_NZ + PV_LEFT },
{ FLDATA (STOP_IOE, rad_stopioe, 0) },
{ NULL }
};
MTAB rad_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL",
&set_chan, &show_chan, NULL },
{ 0 } };
{ MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL",
&set_chan, &show_chan, NULL },
{ 0 }
};
DEVICE rad_dev = {
"RAD", &rad_unit, rad_reg, rad_mod,
1, 8, 21, 1, 8, 24,
NULL, NULL, &rad_reset,
NULL, NULL, NULL,
&rad_dib, DEV_DISABLE };
"RAD", &rad_unit, rad_reg, rad_mod,
1, 8, 21, 1, 8, 24,
NULL, NULL, &rad_reset,
NULL, NULL, NULL,
&rad_dib, DEV_DISABLE
};
/* Fixed head disk routine
conn - inst = EOM0, dat = NULL
eom1 - inst = EOM1, dat = NULL
sks - inst = SKS, dat = ptr to result
disc - inst = device number, dat = NULL
wreor - inst = device number, dat = NULL
read - inst = device number, dat = ptr to data
write - inst = device number, dat = ptr to result
conn - inst = EOM0, dat = NULL
eom1 - inst = EOM1, dat = NULL
sks - inst = SKS, dat = ptr to result
disc - inst = device number, dat = NULL
wreor - inst = device number, dat = NULL
read - inst = device number, dat = ptr to data
write - inst = device number, dat = ptr to result
*/
t_stat rad (uint32 fnc, uint32 inst, uint32 *dat)
@@ -125,93 +132,102 @@ int32 t, lun, new_ch;
uint32 p;
uint32 *fbuf = rad_unit.filebuf;
switch (fnc) { /* case function */
case IO_CONN: /* connect */
new_ch = I_GETEOCH (inst); /* get new chan */
if (new_ch != rad_dib.chan) return SCPE_IERR; /* wrong chan? */
if (CHC_GETCPW (inst) > 1) return STOP_INVIOP; /* 1-2 char/word? */
if (sim_is_active (&rad_unit) || (alert == POT_RADA)) /* protocol viol? */
return STOP_INVIOP;
rad_err = 0; /* clr error */
rad_sba = 0; /* clr sec bptr */
chan_set_flag (rad_dib.chan, CHF_12B); /* 12B mode */
t = (rad_da & RAD_SCMASK) - GET_SECTOR (rad_time * RAD_NUMWD);
if (t <= 0) t = t + RAD_NUMSC; /* seek */
sim_activate (&rad_unit, t * rad_time * (RAD_NUMWD / 2));
xfr_req = xfr_req & ~XFR_RAD; /* clr xfr flg */
break;
switch (fnc) { /* case function */
case IO_EOM1: /* EOM mode 1 */
new_ch = I_GETEOCH (inst); /* get new chan */
if (new_ch != rad_dib.chan) return SCPE_IERR; /* wrong chan? */
if ((inst & 00600) == 00200) alert = POT_RADS; /* alert for sec */
else if ((inst & 06600) == 0) { /* alert for addr */
if (sim_is_active (&rad_unit)) rad_err = 1; /* busy? */
else {
rad_nobi = (inst & 01000)? 1: 0; /* save inc type */
alert = POT_RADA; } } /* set alert */
break;
case IO_CONN: /* connect */
new_ch = I_GETEOCH (inst); /* get new chan */
if (new_ch != rad_dib.chan) return SCPE_IERR; /* wrong chan? */
if (CHC_GETCPW (inst) > 1) return STOP_INVIOP; /* 1-2 char/word? */
if (sim_is_active (&rad_unit) || (alert == POT_RADA)) /* protocol viol? */
return STOP_INVIOP;
rad_err = 0; /* clr error */
rad_sba = 0; /* clr sec bptr */
chan_set_flag (rad_dib.chan, CHF_12B); /* 12B mode */
t = (rad_da & RAD_SCMASK) - GET_SECTOR (rad_time * RAD_NUMWD);
if (t <= 0) t = t + RAD_NUMSC; /* seek */
sim_activate (&rad_unit, t * rad_time * (RAD_NUMWD / 2));
xfr_req = xfr_req & ~XFR_RAD; /* clr xfr flg */
break;
case IO_DISC: /* disconnect */
rad_end_op (0); /* normal term */
if (inst & DEV_OUT) return rad_fill (rad_sba); /* fill write */
break;
case IO_EOM1: /* EOM mode 1 */
new_ch = I_GETEOCH (inst); /* get new chan */
if (new_ch != rad_dib.chan) return SCPE_IERR; /* wrong chan? */
if ((inst & 00600) == 00200) alert = POT_RADS; /* alert for sec */
else if ((inst & 06600) == 0) { /* alert for addr */
if (sim_is_active (&rad_unit)) rad_err = 1; /* busy? */
else {
rad_nobi = (inst & 01000)? 1: 0; /* save inc type */
alert = POT_RADA; /* set alert */
}
}
break;
case IO_WREOR: /* write eor */
rad_end_op (CHF_EOR); /* eor term */
return rad_fill (rad_sba); /* fill write */
case IO_DISC: /* disconnect */
rad_end_op (0); /* normal term */
if (inst & DEV_OUT) return rad_fill (rad_sba); /* fill write */
break;
case IO_SKS: /* SKS */
new_ch = I_GETSKCH (inst); /* sks chan */
if (new_ch != rad_dib.chan) return SCPE_IERR; /* wrong chan? */
t = I_GETSKCND (inst); /* sks cond */
lun = RAD_GETLUN (rad_da);
if (((t == 000) && !sim_is_active (&rad_unit)) || /* 10026: ready */
((t == 004) && !rad_err) || /* 11026: !err */
((t == 014) && !(rad_wrp & (1 << lun)))) /* 13026: !wrprot */
*dat = 1;
break;
case IO_WREOR: /* write eor */
rad_end_op (CHF_EOR); /* eor term */
return rad_fill (rad_sba); /* fill write */
case IO_READ: /* read */
p = (rad_da * RAD_NUMWD) + (rad_sba >> 1); /* buf wd addr */
xfr_req = xfr_req & ~XFR_RAD; /* clr xfr req */
if ((rad_unit.flags & UNIT_BUF) == 0) { /* not buffered? */
rad_end_op (CHF_ERR | CHF_EOR); /* set rad err */
CRETIOE (rad_stopioe, SCPE_UNATT); }
if (p >= rad_unit.capac) { /* end of disk? */
rad_end_op (CHF_ERR | CHF_EOR); /* set rad err */
return SCPE_OK; }
if (rad_sba & 1) *dat = fbuf[p] & 07777; /* odd byte? */
else *dat = (fbuf[p] >> 12) & 07777; /* even */
rad_sba = rad_adjda (rad_sba, 1); /* next byte */
break;
case IO_SKS: /* SKS */
new_ch = I_GETSKCH (inst); /* sks chan */
if (new_ch != rad_dib.chan) return SCPE_IERR; /* wrong chan? */
t = I_GETSKCND (inst); /* sks cond */
lun = RAD_GETLUN (rad_da);
if (((t == 000) && !sim_is_active (&rad_unit)) || /* 10026: ready */
((t == 004) && !rad_err) || /* 11026: !err */
((t == 014) && !(rad_wrp & (1 << lun)))) /* 13026: !wrprot */
*dat = 1;
break;
case IO_WRITE:
p = (rad_da * RAD_NUMWD) + (rad_sba >> 1);
xfr_req = xfr_req & ~XFR_RAD; /* clr xfr req */
if ((rad_unit.flags & UNIT_BUF) == 0) { /* not buffered? */
rad_end_op (CHF_ERR | CHF_EOR); /* set rad err */
CRETIOE (rad_stopioe, SCPE_UNATT); }
if ((p >= rad_unit.capac) || /* end of disk? */
(rad_wrp & (1 << RAD_GETLUN (rad_da)))) { /* write prot? */
rad_end_op (CHF_ERR | CHF_EOR); /* set rad err */
return SCPE_OK; }
if (rad_sba & 1) fbuf[p] = fbuf[p] | (*dat & 07777); /* odd byte? */
else fbuf[p] = (*dat & 07777) << 12; /* even */
if (p >= rad_unit.hwmark) rad_unit.hwmark = p + 1; /* mark hiwater */
rad_sba = rad_adjda (rad_sba, 1); /* next byte */
break;
case IO_READ: /* read */
p = (rad_da * RAD_NUMWD) + (rad_sba >> 1); /* buf wd addr */
xfr_req = xfr_req & ~XFR_RAD; /* clr xfr req */
if ((rad_unit.flags & UNIT_BUF) == 0) { /* not buffered? */
rad_end_op (CHF_ERR | CHF_EOR); /* set rad err */
CRETIOE (rad_stopioe, SCPE_UNATT);
}
if (p >= rad_unit.capac) { /* end of disk? */
rad_end_op (CHF_ERR | CHF_EOR); /* set rad err */
return SCPE_OK;
}
if (rad_sba & 1) *dat = fbuf[p] & 07777; /* odd byte? */
else *dat = (fbuf[p] >> 12) & 07777; /* even */
rad_sba = rad_adjda (rad_sba, 1); /* next byte */
break;
case IO_WRITE:
p = (rad_da * RAD_NUMWD) + (rad_sba >> 1);
xfr_req = xfr_req & ~XFR_RAD; /* clr xfr req */
if ((rad_unit.flags & UNIT_BUF) == 0) { /* not buffered? */
rad_end_op (CHF_ERR | CHF_EOR); /* set rad err */
CRETIOE (rad_stopioe, SCPE_UNATT);
}
if ((p >= rad_unit.capac) || /* end of disk? */
(rad_wrp & (1 << RAD_GETLUN (rad_da)))) { /* write prot? */
rad_end_op (CHF_ERR | CHF_EOR); /* set rad err */
return SCPE_OK;
}
if (rad_sba & 1) fbuf[p] = fbuf[p] | (*dat & 07777); /* odd byte? */
else fbuf[p] = (*dat & 07777) << 12; /* even */
if (p >= rad_unit.hwmark) rad_unit.hwmark = p + 1; /* mark hiwater */
rad_sba = rad_adjda (rad_sba, 1); /* next byte */
break;
default:
CRETINS;
}
default:
CRETINS; }
return SCPE_OK;
}
/* PIN routine */
t_stat pin_rads (uint32 num, uint32 *dat)
{
*dat = GET_SECTOR (rad_time * RAD_NUMWD); /* ret curr sec */
*dat = GET_SECTOR (rad_time * RAD_NUMWD); /* ret curr sec */
return SCPE_OK;
}
@@ -219,7 +235,7 @@ return SCPE_OK;
t_stat pot_rada (uint32 num, uint32 *dat)
{
rad_da = (*dat) & RAD_AMASK; /* save dsk addr */
rad_da = (*dat) & RAD_AMASK; /* save dsk addr */
return SCPE_OK;
}
@@ -227,8 +243,8 @@ return SCPE_OK;
t_stat rad_svc (UNIT *uptr)
{
xfr_req = xfr_req | XFR_RAD; /* set xfr req */
sim_activate (&rad_unit, rad_time); /* activate */
xfr_req = xfr_req | XFR_RAD; /* set xfr req */
sim_activate (&rad_unit, rad_time); /* activate */
return SCPE_OK;
}
@@ -238,12 +254,13 @@ t_stat rad_fill (int32 sba)
{
uint32 p = rad_da * RAD_NUMWD;
uint32 *fbuf = rad_unit.filebuf;
int32 wa = (sba + 1) >> 1; /* whole words */
int32 wa = (sba + 1) >> 1; /* whole words */
if (sba && (p < rad_unit.capac)) { /* fill needed? */
if (sba && (p < rad_unit.capac)) { /* fill needed? */
for ( ; wa < RAD_NUMWD; wa++) fbuf[p + wa] = 0;
if ((p + wa) >= rad_unit.hwmark) rad_unit.hwmark = p + wa + 1;
rad_adjda (sba, RAD_NUMWD - 1); } /* inc da */
rad_adjda (sba, RAD_NUMWD - 1); /* inc da */
}
return SCPE_OK;
}
@@ -252,12 +269,13 @@ return SCPE_OK;
int32 rad_adjda (int32 sba, int32 inc)
{
sba = sba + inc;
if (rad_sba >= (RAD_NUMWD * 2)) { /* next sector? */
if (rad_nobi) rad_da = (rad_da & ~RAD_SCMASK) + /* within band? */
((rad_da + 1) & RAD_SCMASK);
else rad_da = (rad_da & ~RAD_TRSCMASK) + /* cross band */
((rad_da + 1) & RAD_TRSCMASK);
sba = 0; } /* start new sec */
if (rad_sba >= (RAD_NUMWD * 2)) { /* next sector? */
if (rad_nobi) rad_da = (rad_da & ~RAD_SCMASK) + /* within band? */
((rad_da + 1) & RAD_SCMASK);
else rad_da = (rad_da & ~RAD_TRSCMASK) + /* cross band */
((rad_da + 1) & RAD_TRSCMASK);
sba = 0; /* start new sec */
}
return sba;
}
@@ -265,24 +283,25 @@ return sba;
void rad_end_op (int32 fl)
{
if (fl) chan_set_flag (rad_dib.chan, fl); /* set flags */
xfr_req = xfr_req & ~XFR_RAD; /* clear xfr */
sim_cancel (&rad_unit); /* stop */
if (fl & CHF_ERR) { /* error? */
chan_disc (rad_dib.chan); /* disconnect */
rad_err = 1; } /* set rad err */
if (fl) chan_set_flag (rad_dib.chan, fl); /* set flags */
xfr_req = xfr_req & ~XFR_RAD; /* clear xfr */
sim_cancel (&rad_unit); /* stop */
if (fl & CHF_ERR) { /* error? */
chan_disc (rad_dib.chan); /* disconnect */
rad_err = 1; /* set rad err */
}
return;
}
/* Reset routine */
t_stat rad_reset (DEVICE *dptr)
{
chan_disc (rad_dib.chan); /* disconnect */
rad_nobi = 0; /* clear state */
chan_disc (rad_dib.chan); /* disconnect */
rad_nobi = 0; /* clear state */
rad_da = 0;
rad_sba = 0;
xfr_req = xfr_req & ~XFR_RAD; /* clr xfr req */
sim_cancel (&rad_unit); /* deactivate */
xfr_req = xfr_req & ~XFR_RAD; /* clr xfr req */
sim_cancel (&rad_unit); /* deactivate */
return SCPE_OK;
}

View File

@@ -1,6 +1,6 @@
/* sds_stddev.c: SDS 940 standard devices
Copyright (c) 2001-2004, Robert M. Supnik
Copyright (c) 2001-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,31 +19,32 @@
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.
ptr paper tape reader
ptp paper tape punch
tti keyboard
tto teleprinter
ptr paper tape reader
ptp paper tape punch
tti keyboard
tto teleprinter
29-Dec-03 RMS Added console backpressure support
25-Apr-03 RMS Revised for extended file support
29-Dec-03 RMS Added console backpressure support
25-Apr-03 RMS Revised for extended file support
*/
#include "sds_defs.h"
#define TT_CR 052 /* typewriter */
#define TT_TB 072
#define TT_BS 032
#define TT_CR 052 /* typewriter */
#define TT_TB 072
#define TT_BS 032
extern uint32 xfr_req;
extern int32 stop_invins, stop_invdev, stop_inviop;
int32 ptr_sor = 0; /* start of rec */
int32 ptr_stopioe = 1; /* stop on err */
int32 ptp_ldr = 0; /* no leader */
int32 ptr_sor = 0; /* start of rec */
int32 ptr_stopioe = 1; /* stop on err */
int32 ptp_ldr = 0; /* no leader */
int32 ptp_stopioe = 1;
DSPT std_tplt[] = { { 1, 0 }, { 0, 0 } }; /* template */
DSPT std_tplt[] = { { 1, 0 }, { 0, 0 } }; /* template */
DEVICE ptr_dev, ptp_dev;
t_stat ptr (uint32 fnc, uint32 inst, uint32 *dat);
@@ -66,79 +67,87 @@ t_stat tto_reset (DEVICE *dptr);
extern const char ascii_to_sds[128];
extern const char sds_to_ascii[64];
extern const char odd_par[64];
/* PTR data structures
ptr_dev PTR device descriptor
ptr_unit PTR unit
ptr_reg PTR register list
ptr_dev PTR device descriptor
ptr_unit PTR unit
ptr_reg PTR register list
*/
DIB ptr_dib = { CHAN_W, DEV_PTR, XFR_PTR, std_tplt, &ptr };
UNIT ptr_unit = {
UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0),
SERIAL_IN_WAIT };
UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0),
SERIAL_IN_WAIT
};
REG ptr_reg[] = {
{ ORDATA (BUF, ptr_unit.buf, 7) },
{ FLDATA (XFR, xfr_req, XFR_V_PTR) },
{ FLDATA (SOR, ptr_sor, 0) },
{ DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, ptr_unit.wait, 24), REG_NZ + PV_LEFT },
{ FLDATA (STOP_IOE, ptr_stopioe, 0) },
{ NULL } };
{ ORDATA (BUF, ptr_unit.buf, 7) },
{ FLDATA (XFR, xfr_req, XFR_V_PTR) },
{ FLDATA (SOR, ptr_sor, 0) },
{ DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, ptr_unit.wait, 24), REG_NZ + PV_LEFT },
{ FLDATA (STOP_IOE, ptr_stopioe, 0) },
{ NULL }
};
MTAB ptr_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "CHANNEL",
"CHANNEL", &set_chan, &show_chan, NULL },
{ 0 } };
{ MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL",
&set_chan, &show_chan, NULL },
{ 0 }
};
DEVICE ptr_dev = {
"PTR", &ptr_unit, ptr_reg, ptr_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &ptr_reset,
&ptr_boot, NULL, NULL,
&ptr_dib, DEV_DISABLE };
"PTR", &ptr_unit, ptr_reg, ptr_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &ptr_reset,
&ptr_boot, NULL, NULL,
&ptr_dib, DEV_DISABLE
};
/* PTP data structures
ptp_dev PTP device descriptor
ptp_unit PTP unit
ptp_reg PTP register list
ptp_dev PTP device descriptor
ptp_unit PTP unit
ptp_reg PTP register list
*/
DIB ptp_dib = { CHAN_W, DEV_PTP, XFR_PTP, std_tplt, &ptp };
UNIT ptp_unit = {
UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT };
UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT
};
REG ptp_reg[] = {
{ ORDATA (BUF, ptp_unit.buf, 7) },
{ FLDATA (XFR, xfr_req, XFR_V_PTP) },
{ FLDATA (LDR, ptp_ldr, 0) },
{ DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, ptp_unit.wait, 24), REG_NZ + PV_LEFT },
{ FLDATA (STOP_IOE, ptp_stopioe, 0) },
{ NULL } };
{ ORDATA (BUF, ptp_unit.buf, 7) },
{ FLDATA (XFR, xfr_req, XFR_V_PTP) },
{ FLDATA (LDR, ptp_ldr, 0) },
{ DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, ptp_unit.wait, 24), REG_NZ + PV_LEFT },
{ FLDATA (STOP_IOE, ptp_stopioe, 0) },
{ NULL }
};
MTAB ptp_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL",
&set_chan, &show_chan, NULL },
{ 0 } };
{ MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL",
&set_chan, &show_chan, NULL },
{ 0 }
};
DEVICE ptp_dev = {
"PTP", &ptp_unit, ptp_reg, ptp_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &ptp_reset,
NULL, NULL, NULL,
&ptp_dib, DEV_DISABLE };
"PTP", &ptp_unit, ptp_reg, ptp_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &ptp_reset,
NULL, NULL, NULL,
&ptp_dib, DEV_DISABLE
};
/* TTI data structures
tti_dev TTI device descriptor
tti_unit TTI unit
tti_reg TTI register list
tti_dev TTI device descriptor
tti_unit TTI unit
tti_reg TTI register list
*/
DIB tti_dib = { CHAN_W, DEV_TTI, XFR_TTI, std_tplt, &tti };
@@ -146,29 +155,32 @@ DIB tti_dib = { CHAN_W, DEV_TTI, XFR_TTI, std_tplt, &tti };
UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT };
REG tti_reg[] = {
{ ORDATA (BUF, tti_unit.buf, 6) },
{ FLDATA (XFR, xfr_req, XFR_V_TTI) },
{ DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT },
{ NULL } };
{ ORDATA (BUF, tti_unit.buf, 6) },
{ FLDATA (XFR, xfr_req, XFR_V_TTI) },
{ DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT },
{ NULL }
};
MTAB tti_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL",
&set_chan, &show_chan, &tti_dib },
{ 0 } };
{ MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL",
&set_chan, &show_chan, &tti_dib },
{ 0 }
};
DEVICE tti_dev = {
"TTI", &tti_unit, tti_reg, tti_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &tti_reset,
NULL, NULL, NULL,
&tti_dib, 0 };
"TTI", &tti_unit, tti_reg, tti_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &tti_reset,
NULL, NULL, NULL,
&tti_dib, 0
};
/* TTO data structures
tto_dev TTO device descriptor
tto_unit TTO unit
tto_reg TTO register list
tto_dev TTO device descriptor
tto_unit TTO unit
tto_reg TTO register list
*/
DIB tto_dib = { CHAN_W, DEV_TTO, XFR_TTO, std_tplt, &tto };
@@ -176,33 +188,36 @@ DIB tto_dib = { CHAN_W, DEV_TTO, XFR_TTO, std_tplt, &tto };
UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT };
REG tto_reg[] = {
{ ORDATA (BUF, tto_unit.buf, 6) },
{ FLDATA (XFR, xfr_req, XFR_V_TTO) },
{ DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, tto_unit.wait, 24), REG_NZ + PV_LEFT },
{ NULL } };
{ ORDATA (BUF, tto_unit.buf, 6) },
{ FLDATA (XFR, xfr_req, XFR_V_TTO) },
{ DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, tto_unit.wait, 24), REG_NZ + PV_LEFT },
{ NULL }
};
MTAB tto_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL",
&set_chan, &show_chan, &tto_dib },
{ 0 } };
{ MTAB_XTD|MTAB_VDV, 0, "CHANNEL", "CHANNEL",
&set_chan, &show_chan, &tto_dib },
{ 0 }
};
DEVICE tto_dev = {
"TTO", &tto_unit, tto_reg, tto_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &tto_reset,
NULL, NULL, NULL,
&tto_dib, 0 };
"TTO", &tto_unit, tto_reg, tto_mod,
1, 10, 31, 1, 8, 8,
NULL, NULL, &tto_reset,
NULL, NULL, NULL,
&tto_dib, 0
};
/* Paper tape reader
conn - inst = EOM0, dat = NULL
eom1 - inst = EOM1, dat = NULL
sks - inst = SKS, dat = ptr to result
disc - inst = device number, dat = NULL
wreor - inst = device number, dat = NULL
read - inst = device number, dat = ptr to data
write - inst = device number, dat = ptr to result
conn - inst = EOM0, dat = NULL
eom1 - inst = EOM1, dat = NULL
sks - inst = SKS, dat = ptr to result
disc - inst = device number, dat = NULL
wreor - inst = device number, dat = NULL
read - inst = device number, dat = ptr to data
write - inst = device number, dat = ptr to result
The paper tape reader is a streaming input device. Once started, it
continues to read until disconnected. Leader before the current record
@@ -213,62 +228,69 @@ t_stat ptr (uint32 fnc, uint32 inst, uint32 *dat)
{
int32 new_ch;
switch (fnc) { /* case function */
case IO_CONN: /* connect */
new_ch = I_GETEOCH (inst); /* get new chan */
if (new_ch != ptr_dib.chan) return SCPE_IERR; /* inv conn? err */
ptr_sor = 1; /* start of rec */
xfr_req = xfr_req & ~XFR_PTR; /* clr xfr flag */
sim_activate (&ptr_unit, ptr_unit.wait); /* activate */
break;
switch (fnc) { /* case function */
case IO_DISC: /* disconnect */
ptr_sor = 0; /* clear state */
xfr_req = xfr_req & ~XFR_PTR; /* clr xfr flag */
sim_cancel (&ptr_unit); /* deactivate unit */
break;
case IO_CONN: /* connect */
new_ch = I_GETEOCH (inst); /* get new chan */
if (new_ch != ptr_dib.chan) return SCPE_IERR; /* inv conn? err */
ptr_sor = 1; /* start of rec */
xfr_req = xfr_req & ~XFR_PTR; /* clr xfr flag */
sim_activate (&ptr_unit, ptr_unit.wait); /* activate */
break;
case IO_READ: /* read */
xfr_req = xfr_req & ~XFR_PTR; /* clr xfr flag */
*dat = ptr_unit.buf & 077; /* get buf data */
if (ptr_unit.buf != odd_par[*dat]) /* good parity? */
chan_set_flag (ptr_dib.chan, CHF_ERR); /* no, error */
break;
case IO_DISC: /* disconnect */
ptr_sor = 0; /* clear state */
xfr_req = xfr_req & ~XFR_PTR; /* clr xfr flag */
sim_cancel (&ptr_unit); /* deactivate unit */
break;
case IO_WREOR: /* write eor */
break;
case IO_READ: /* read */
xfr_req = xfr_req & ~XFR_PTR; /* clr xfr flag */
*dat = ptr_unit.buf & 077; /* get buf data */
if (ptr_unit.buf != odd_par[*dat]) /* good parity? */
chan_set_flag (ptr_dib.chan, CHF_ERR); /* no, error */
break;
case IO_WREOR: /* write eor */
break;
case IO_EOM1: /* EOM mode 1*/
case IO_WRITE: /* write */
CRETINS; /* error */
}
case IO_EOM1: /* EOM mode 1*/
case IO_WRITE: /* write */
CRETINS; } /* error */
return SCPE_OK;
}
/* Unit service */
t_stat ptr_svc (UNIT *uptr)
{
int32 temp;
if ((ptr_unit.flags & UNIT_ATT) == 0) { /* attached? */
ptr_set_err (); /* no, err, disc */
CRETIOE (ptr_stopioe, SCPE_UNATT); }
if ((temp = getc (ptr_unit.fileref)) == EOF) { /* end of file? */
ptr_set_err (); /* yes, err, disc */
if (feof (ptr_unit.fileref)) { /* end of file? */
if (ptr_stopioe) printf ("PTR end of file\n");
else return SCPE_OK; }
else perror ("PTR I/O error"); /* I/O error */
if ((ptr_unit.flags & UNIT_ATT) == 0) { /* attached? */
ptr_set_err (); /* no, err, disc */
CRETIOE (ptr_stopioe, SCPE_UNATT);
}
if ((temp = getc (ptr_unit.fileref)) == EOF) { /* end of file? */
ptr_set_err (); /* yes, err, disc */
if (feof (ptr_unit.fileref)) { /* end of file? */
if (ptr_stopioe) printf ("PTR end of file\n");
else return SCPE_OK;
}
else perror ("PTR I/O error"); /* I/O error */
clearerr (ptr_unit.fileref);
return SCPE_IOERR; }
ptr_unit.pos = ptr_unit.pos + 1; /* inc position */
if (temp) { /* leader/gap? */
ptr_unit.buf = temp & 0177; /* no, save char */
xfr_req = xfr_req | XFR_PTR; /* set xfr flag */
ptr_sor = 0; } /* in record */
else if (!ptr_sor) /* end record? */
chan_set_flag (ptr_dib.chan, CHF_EOR); /* ignore leader */
sim_activate (&ptr_unit, ptr_unit.wait); /* get next char */
return SCPE_IOERR;
}
ptr_unit.pos = ptr_unit.pos + 1; /* inc position */
if (temp) { /* leader/gap? */
ptr_unit.buf = temp & 0177; /* no, save char */
xfr_req = xfr_req | XFR_PTR; /* set xfr flag */
ptr_sor = 0; /* in record */
}
else if (!ptr_sor) /* end record? */
chan_set_flag (ptr_dib.chan, CHF_EOR); /* ignore leader */
sim_activate (&ptr_unit, ptr_unit.wait); /* get next char */
return SCPE_OK;
}
@@ -276,10 +298,10 @@ return SCPE_OK;
void ptr_set_err (void)
{
chan_set_flag (ptr_dib.chan, CHF_EOR | CHF_ERR); /* eor, error */
chan_disc (ptr_dib.chan); /* disconnect */
xfr_req = xfr_req & ~XFR_PTR; /* clear xfr */
sim_cancel (&ptr_unit); /* stop */
chan_set_flag (ptr_dib.chan, CHF_EOR | CHF_ERR); /* eor, error */
chan_disc (ptr_dib.chan); /* disconnect */
xfr_req = xfr_req & ~XFR_PTR; /* clear xfr */
sim_cancel (&ptr_unit); /* stop */
return;
}
@@ -287,11 +309,11 @@ return;
t_stat ptr_reset (DEVICE *dptr)
{
chan_disc (ptr_dib.chan); /* disconnect */
ptr_sor = 0; /* clear state */
chan_disc (ptr_dib.chan); /* disconnect */
ptr_sor = 0; /* clear state */
ptr_unit.buf = 0;
xfr_req = xfr_req & ~XFR_PTR; /* clr xfr flag */
sim_cancel (&ptr_unit); /* deactivate unit */
xfr_req = xfr_req & ~XFR_PTR; /* clr xfr flag */
sim_cancel (&ptr_unit); /* deactivate unit */
return SCPE_OK;
}
@@ -301,24 +323,24 @@ t_stat ptr_boot (int32 unitno, DEVICE *dptr)
{
extern uint32 P, M[];
M[0] = 077777771; /* -7B */
M[1] = 007100000; /* LDX 0 */
M[2] = 000203604; /* EOM 3604B */
M[3] = 003200002; /* WIM 2 */
M[4] = 000100002; /* BRU 2 */
P = 1; /* start at 1 */
M[0] = 077777771; /* -7B */
M[1] = 007100000; /* LDX 0 */
M[2] = 000203604; /* EOM 3604B */
M[3] = 003200002; /* WIM 2 */
M[4] = 000100002; /* BRU 2 */
P = 1; /* start at 1 */
return SCPE_OK;
}
/* Paper tape punch
conn - inst = EOM0, dat = NULL
eom1 - inst = EOM1, dat = NULL
sks - inst = SKS, dat = ptr to result
disc - inst = device number, dat = NULL
wreor - inst = device number, dat = NULL
read - inst = device number, dat = ptr to data
write - inst = device number, dat = ptr to result
conn - inst = EOM0, dat = NULL
eom1 - inst = EOM1, dat = NULL
sks - inst = SKS, dat = ptr to result
disc - inst = device number, dat = NULL
wreor - inst = device number, dat = NULL
read - inst = device number, dat = ptr to data
write - inst = device number, dat = ptr to result
The paper tape punch is an asynchronous streaming output device. That is,
it can never cause a channel rate error; if no data is available, it waits.
@@ -328,36 +350,39 @@ t_stat ptp (uint32 fnc, uint32 inst, uint32 *dat)
{
int32 new_ch;
switch (fnc) { /* case function */
case IO_CONN:
new_ch = I_GETEOCH (inst); /* get new chan */
if (new_ch != ptp_dib.chan) return SCPE_IERR; /* inv conn? err */
ptp_ldr = (inst & CHC_NLDR)? 0: 1; /* leader? */
xfr_req = xfr_req & ~XFR_PTP; /* clr xfr flag */
sim_activate (&ptp_unit, ptp_unit.wait); /* activate */
break;
switch (fnc) { /* case function */
case IO_DISC: /* disconnect */
ptp_ldr = 0; /* clear state */
xfr_req = xfr_req & ~XFR_PTP; /* clr xfr flag */
sim_cancel (&ptp_unit); /* deactivate unit */
break;
case IO_CONN:
new_ch = I_GETEOCH (inst); /* get new chan */
if (new_ch != ptp_dib.chan) return SCPE_IERR; /* inv conn? err */
ptp_ldr = (inst & CHC_NLDR)? 0: 1; /* leader? */
xfr_req = xfr_req & ~XFR_PTP; /* clr xfr flag */
sim_activate (&ptp_unit, ptp_unit.wait); /* activate */
break;
case IO_WRITE: /* write */
xfr_req = xfr_req & ~XFR_PTP; /* clr xfr flag */
sim_activate (&ptp_unit, ptp_unit.wait); /* activate */
ptp_unit.buf = odd_par[(*dat) & 077]; /* save data */
return ptp_out (ptp_unit.buf); /* punch w/ par */
case IO_DISC: /* disconnect */
ptp_ldr = 0; /* clear state */
xfr_req = xfr_req & ~XFR_PTP; /* clr xfr flag */
sim_cancel (&ptp_unit); /* deactivate unit */
break;
case IO_WREOR: /* write eor */
break;
case IO_WRITE: /* write */
xfr_req = xfr_req & ~XFR_PTP; /* clr xfr flag */
sim_activate (&ptp_unit, ptp_unit.wait); /* activate */
ptp_unit.buf = odd_par[(*dat) & 077]; /* save data */
return ptp_out (ptp_unit.buf); /* punch w/ par */
case IO_WREOR: /* write eor */
break;
case IO_EOM1: /* EOM mode 1*/
case IO_READ: /* read */
CRETINS; /* error */
}
case IO_EOM1: /* EOM mode 1*/
case IO_READ: /* read */
CRETINS; } /* error */
return SCPE_OK;
}
/* Unit service */
t_stat ptp_svc (UNIT *uptr)
@@ -365,11 +390,13 @@ t_stat ptp_svc (UNIT *uptr)
int32 i;
t_stat r = SCPE_OK;
if (ptp_ldr) { /* need leader? */
for (i = 0; i < 12; i++) { /* punch leader */
if (r = ptp_out (0)) break; } }
ptp_ldr = 0; /* clear flag */
chan_set_ordy (ptp_dib.chan); /* ptp ready */
if (ptp_ldr) { /* need leader? */
for (i = 0; i < 12; i++) { /* punch leader */
if (r = ptp_out (0)) break;
}
}
ptp_ldr = 0; /* clear flag */
chan_set_ordy (ptp_dib.chan); /* ptp ready */
return r;
}
@@ -377,15 +404,17 @@ return r;
t_stat ptp_out (int32 dat)
{
if ((ptp_unit.flags & UNIT_ATT) == 0) { /* attached? */
ptp_set_err (); /* no, disc, err */
CRETIOE (ptp_stopioe, SCPE_UNATT); }
if (putc (dat, ptp_unit.fileref) == EOF) { /* I/O error? */
ptp_set_err (); /* yes, disc, err */
perror ("PTP I/O error"); /* print msg */
if ((ptp_unit.flags & UNIT_ATT) == 0) { /* attached? */
ptp_set_err (); /* no, disc, err */
CRETIOE (ptp_stopioe, SCPE_UNATT);
}
if (putc (dat, ptp_unit.fileref) == EOF) { /* I/O error? */
ptp_set_err (); /* yes, disc, err */
perror ("PTP I/O error"); /* print msg */
clearerr (ptp_unit.fileref);
return SCPE_IOERR; }
ptp_unit.pos = ptp_unit.pos + 1; /* inc position */
return SCPE_IOERR;
}
ptp_unit.pos = ptp_unit.pos + 1; /* inc position */
return SCPE_OK;
}
@@ -393,10 +422,10 @@ return SCPE_OK;
void ptp_set_err (void)
{
chan_set_flag (ptp_dib.chan, CHF_ERR); /* error */
chan_disc (ptp_dib.chan); /* disconnect */
xfr_req = xfr_req & ~XFR_PTP; /* clear xfr */
sim_cancel (&ptp_unit); /* stop */
chan_set_flag (ptp_dib.chan, CHF_ERR); /* error */
chan_disc (ptp_dib.chan); /* disconnect */
xfr_req = xfr_req & ~XFR_PTP; /* clear xfr */
sim_cancel (&ptp_unit); /* stop */
return;
}
@@ -404,23 +433,23 @@ return;
t_stat ptp_reset (DEVICE *dptr)
{
chan_disc (ptp_dib.chan); /* disconnect */
ptp_ldr = 0; /* clear state */
chan_disc (ptp_dib.chan); /* disconnect */
ptp_ldr = 0; /* clear state */
ptp_unit.buf = 0;
xfr_req = xfr_req & ~XFR_PTP; /* clr xfr flag */
sim_cancel (&ptp_unit); /* deactivate unit */
xfr_req = xfr_req & ~XFR_PTP; /* clr xfr flag */
sim_cancel (&ptp_unit); /* deactivate unit */
return SCPE_OK;
}
/* Typewriter input
conn - inst = EOM0, dat = NULL
eom1 - inst = EOM1, dat = NULL
sks - inst = SKS, dat = ptr to result
disc - inst = device number, dat = NULL
wreor - inst = device number, dat = NULL
read - inst = device number, dat = ptr to data
write - inst = device number, dat = ptr to result
conn - inst = EOM0, dat = NULL
eom1 - inst = EOM1, dat = NULL
sks - inst = SKS, dat = ptr to result
disc - inst = device number, dat = NULL
wreor - inst = device number, dat = NULL
read - inst = device number, dat = ptr to data
write - inst = device number, dat = ptr to result
The typewriter input is an asynchronous input device. That is, it can
never cause a channel rate error; if no data is available, it waits.
@@ -430,69 +459,73 @@ t_stat tti (uint32 fnc, uint32 inst, uint32 *dat)
{
int32 new_ch;
switch (fnc) { /* case function */
case IO_CONN: /* connect */
new_ch = I_GETEOCH (inst); /* get new chan */
if (new_ch != tti_dib.chan) return SCPE_IERR; /* inv conn? err */
xfr_req = xfr_req & ~XFR_TTI; /* clr xfr flag */
break;
switch (fnc) { /* case function */
case IO_DISC: /* disconnect */
xfr_req = xfr_req & ~XFR_TTI; /* clr xfr flag */
break;
case IO_CONN: /* connect */
new_ch = I_GETEOCH (inst); /* get new chan */
if (new_ch != tti_dib.chan) return SCPE_IERR; /* inv conn? err */
xfr_req = xfr_req & ~XFR_TTI; /* clr xfr flag */
break;
case IO_READ: /* read */
xfr_req = xfr_req & ~XFR_TTI; /* clr xfr flag */
*dat = tti_unit.buf; /* get buf data */
break;
case IO_DISC: /* disconnect */
xfr_req = xfr_req & ~XFR_TTI; /* clr xfr flag */
break;
case IO_WREOR: /* write eor */
break;
case IO_READ: /* read */
xfr_req = xfr_req & ~XFR_TTI; /* clr xfr flag */
*dat = tti_unit.buf; /* get buf data */
break;
case IO_WREOR: /* write eor */
break;
case IO_EOM1: /* EOM mode 1*/
case IO_WRITE: /* write */
CRETINS; /* error */
}
case IO_EOM1: /* EOM mode 1*/
case IO_WRITE: /* write */
CRETINS; } /* error */
return SCPE_OK;
}
/* Unit service */
t_stat tti_svc (UNIT *uptr)
{
int32 temp;
sim_activate (&tti_unit, tti_unit.wait); /* continue poll */
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */
if (temp & SCPE_BREAK) return SCPE_OK; /* ignore break */
sim_activate (&tti_unit, tti_unit.wait); /* continue poll */
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */
if (temp & SCPE_BREAK) return SCPE_OK; /* ignore break */
temp = temp & 0177;
tti_unit.pos = tti_unit.pos + 1;
if (ascii_to_sds[temp] >= 0) {
tti_unit.buf = ascii_to_sds[temp]; /* internal rep */
sim_putchar (temp); /* echo */
if (temp == '\r') sim_putchar ('\n'); /* lf after cr */
xfr_req = xfr_req | XFR_TTI; } /* set xfr flag */
else sim_putchar (007); /* ding! */
tti_unit.buf = ascii_to_sds[temp]; /* internal rep */
sim_putchar (temp); /* echo */
if (temp == '\r') sim_putchar ('\n'); /* lf after cr */
xfr_req = xfr_req | XFR_TTI; /* set xfr flag */
}
else sim_putchar (007); /* ding! */
return SCPE_OK;
}
t_stat tti_reset (DEVICE *dptr)
{
chan_disc (tti_dib.chan); /* disconnect */
tti_unit.buf = 0; /* clear state */
xfr_req = xfr_req & ~XFR_TTI; /* clr xfr flag */
sim_activate (&tti_unit, tti_unit.wait); /* start poll */
chan_disc (tti_dib.chan); /* disconnect */
tti_unit.buf = 0; /* clear state */
xfr_req = xfr_req & ~XFR_TTI; /* clr xfr flag */
sim_activate (&tti_unit, tti_unit.wait); /* start poll */
return SCPE_OK;
}
/* Typewriter output
conn - inst = EOM0, dat = NULL
eom1 - inst = EOM1, dat = NULL
sks - inst = SKS, dat = ptr to result
disc - inst = device number, dat = NULL
wreor - inst = device number, dat = NULL
read - inst = device number, dat = ptr to data
write - inst = device number, dat = ptr to result
conn - inst = EOM0, dat = NULL
eom1 - inst = EOM1, dat = NULL
sks - inst = SKS, dat = ptr to result
disc - inst = device number, dat = NULL
wreor - inst = device number, dat = NULL
read - inst = device number, dat = ptr to data
write - inst = device number, dat = ptr to result
The typewriter output is an asynchronous streaming output device. That is,
it can never cause a channel rate error; if no data is available, it waits.
@@ -502,34 +535,37 @@ t_stat tto (uint32 fnc, uint32 inst, uint32 *dat)
{
int32 new_ch;
switch (fnc) { /* case function */
case IO_CONN:
new_ch = I_GETEOCH (inst); /* get new chan */
if (new_ch != tto_dib.chan) return SCPE_IERR; /* inv conn? err */
xfr_req = xfr_req & ~XFR_TTO; /* clr xfr flag */
sim_activate (&tto_unit, tto_unit.wait); /* activate */
break;
switch (fnc) { /* case function */
case IO_DISC: /* disconnect */
xfr_req = xfr_req & ~XFR_TTO; /* clr xfr flag */
sim_cancel (&tto_unit); /* deactivate unit */
break;
case IO_CONN:
new_ch = I_GETEOCH (inst); /* get new chan */
if (new_ch != tto_dib.chan) return SCPE_IERR; /* inv conn? err */
xfr_req = xfr_req & ~XFR_TTO; /* clr xfr flag */
sim_activate (&tto_unit, tto_unit.wait); /* activate */
break;
case IO_WRITE: /* write */
xfr_req = xfr_req & ~XFR_TTO; /* clr xfr flag */
tto_unit.buf = (*dat) & 077; /* save data */
sim_activate (&tto_unit, tto_unit.wait); /* activate */
break;
case IO_DISC: /* disconnect */
xfr_req = xfr_req & ~XFR_TTO; /* clr xfr flag */
sim_cancel (&tto_unit); /* deactivate unit */
break;
case IO_WREOR: /* write eor */
break;
case IO_WRITE: /* write */
xfr_req = xfr_req & ~XFR_TTO; /* clr xfr flag */
tto_unit.buf = (*dat) & 077; /* save data */
sim_activate (&tto_unit, tto_unit.wait); /* activate */
break;
case IO_WREOR: /* write eor */
break;
case IO_EOM1: /* EOM mode 1*/
case IO_READ: /* read */
CRETINS; } /* error */
case IO_EOM1: /* EOM mode 1*/
case IO_READ: /* read */
CRETINS; /* error */
}
return SCPE_OK;
}
/* Unit service */
t_stat tto_svc (UNIT *uptr)
@@ -537,18 +573,20 @@ t_stat tto_svc (UNIT *uptr)
int32 asc;
t_stat r;
if (uptr->buf == TT_CR) asc = '\r'; /* control chars? */
if (uptr->buf == TT_CR) asc = '\r'; /* control chars? */
else if (uptr->buf == TT_BS) asc = '\b';
else if (uptr->buf == TT_TB) asc = '\t';
else asc = sds_to_ascii[uptr->buf]; /* translate */
if ((r = sim_putchar_s (asc)) != SCPE_OK) { /* output; error? */
sim_activate (uptr, uptr->wait); /* retry */
return ((r == SCPE_STALL)? SCPE_OK: r); } /* !stall? report */
uptr->pos = uptr->pos + 1; /* inc position */
chan_set_ordy (tto_dib.chan); /* tto rdy */
if (asc == '\r') { /* CR? */
sim_putchar ('\n'); /* add lf */
uptr->pos = uptr->pos + 1; } /* inc position */
else asc = sds_to_ascii[uptr->buf]; /* translate */
if ((r = sim_putchar_s (asc)) != SCPE_OK) { /* output; error? */
sim_activate (uptr, uptr->wait); /* retry */
return ((r == SCPE_STALL)? SCPE_OK: r); /* !stall? report */
}
uptr->pos = uptr->pos + 1; /* inc position */
chan_set_ordy (tto_dib.chan); /* tto rdy */
if (asc == '\r') { /* CR? */
sim_putchar ('\n'); /* add lf */
uptr->pos = uptr->pos + 1; /* inc position */
}
return SCPE_OK;
}
@@ -556,9 +594,9 @@ return SCPE_OK;
t_stat tto_reset (DEVICE *dptr)
{
chan_disc (tto_dib.chan); /* disconnect */
tto_unit.buf = 0; /* clear state */
xfr_req = xfr_req & ~XFR_TTO; /* clr xfr flag */
sim_cancel (&tto_unit); /* deactivate unit */
chan_disc (tto_dib.chan); /* disconnect */
tto_unit.buf = 0; /* clear state */
xfr_req = xfr_req & ~XFR_TTO; /* clr xfr flag */
sim_cancel (&tto_unit); /* deactivate unit */
return SCPE_OK;
}

View File

@@ -1,6 +1,6 @@
/* sds_sys.c: SDS 940 simulator interface
Copyright (c) 2001-2004, Robert M Supnik
Copyright (c) 2001-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,8 +19,8 @@
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.
*/
@@ -47,12 +47,12 @@ extern uint32 M[MAXMEMSIZE];
/* SCP data structures and interface routines
sim_name simulator name string
sim_PC pointer to saved PC register descriptor
sim_emax number of words for examine
sim_devices array of pointers to simulated devices
sim_stop_messages array of pointers to stop messages
sim_load binary loader
sim_name simulator name string
sim_PC pointer to saved PC register descriptor
sim_emax number of words for examine
sim_devices array of pointers to simulated devices
sim_stop_messages array of pointers to stop messages
sim_load binary loader
*/
char sim_name[] = "SDS 940";
@@ -62,85 +62,89 @@ REG *sim_PC = &cpu_reg[0];
int32 sim_emax = 1;
DEVICE *sim_devices[] = {
&cpu_dev,
&chan_dev,
&ptr_dev,
&ptp_dev,
&tti_dev,
&tto_dev,
&lpt_dev,
&rtc_dev,
&drm_dev,
&rad_dev,
&dsk_dev,
&mt_dev,
&mux_dev,
&muxl_dev,
NULL };
&cpu_dev,
&chan_dev,
&ptr_dev,
&ptp_dev,
&tti_dev,
&tto_dev,
&lpt_dev,
&rtc_dev,
&drm_dev,
&rad_dev,
&dsk_dev,
&mt_dev,
&mux_dev,
&muxl_dev,
NULL
};
const char *sim_stop_messages[] = {
"Unknown error",
"IO device not ready",
"HALT instruction",
"Breakpoint",
"Invalid IO device",
"Invalid instruction",
"Invalid I/O operation",
"Nested indirects exceed limit",
"Nested EXU's exceed limit",
"Memory management trap during interrupt",
"Memory management trap during trap",
"Trap instruction not BRM",
"RTC instruction not MIN or SKR",
"Interrupt vector zero",
"Runaway carriage control tape" };
"Unknown error",
"IO device not ready",
"HALT instruction",
"Breakpoint",
"Invalid IO device",
"Invalid instruction",
"Invalid I/O operation",
"Nested indirects exceed limit",
"Nested EXU's exceed limit",
"Memory management trap during interrupt",
"Memory management trap during trap",
"Trap instruction not BRM",
"RTC instruction not MIN or SKR",
"Interrupt vector zero",
"Runaway carriage control tape"
};
/* Character conversion tables */
const char sds_to_ascii[64] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', ' ', '=', '\'', ':', '>', '%', /* 17 = check mark */
'+', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', '?', '.', ')', '[', '<', '@', /* 37 = stop code */
'-', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', '!', '$', '*', ']', ';', '^', /* 57 = triangle */
'_', '/', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', '?', ',', '(', '~', '\\', '#' }; /* 72 = rec mark */
/* 75 = squiggle, 77 = del */
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', ' ', '=', '\'', ':', '>', '%', /* 17 = check mark */
'+', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', '?', '.', ')', '[', '<', '@', /* 37 = stop code */
'-', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', '!', '$', '*', ']', ';', '^', /* 57 = triangle */
'_', '/', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', '?', ',', '(', '~', '\\', '#' /* 72 = rec mark */
}; /* 75 = squiggle, 77 = del */
const char ascii_to_sds[128] = {
-1, -1, -1, -1, -1, -1, -1, -1, /* 0 - 37 */
032, 072, -1, -1, -1, 052, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
012, 052, -1, 077, 053, 017, -1, 014, /* 40 - 77 */
074, 034, 054, 020, 073, 040, 033, 061,
000, 001, 002, 003, 004, 005, 006, 007,
010, 011, 015, 056, 036, 013, 016, 072,
037, 021, 022, 023, 024, 025, 026, 027, /* 100 - 137 */
030, 031, 041, 042, 043, 044, 045, 046,
047, 050, 051, 062, 063, 064, 065, 066,
067, 070, 071, 035, 076, 055, 057, 060,
000, 021, 022, 023, 024, 025, 026, 027, /* 140 - 177 */
030, 031, 041, 042, 043, 044, 045, 046,
047, 050, 051, 062, 063, 064, 065, 066,
067, 070, 071, -1, -1, -1, -1, -1 };
-1, -1, -1, -1, -1, -1, -1, -1, /* 0 - 37 */
032, 072, -1, -1, -1, 052, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
012, 052, -1, 077, 053, 017, -1, 014, /* 40 - 77 */
074, 034, 054, 020, 073, 040, 033, 061,
000, 001, 002, 003, 004, 005, 006, 007,
010, 011, 015, 056, 036, 013, 016, 072,
037, 021, 022, 023, 024, 025, 026, 027, /* 100 - 137 */
030, 031, 041, 042, 043, 044, 045, 046,
047, 050, 051, 062, 063, 064, 065, 066,
067, 070, 071, 035, 076, 055, 057, 060,
000, 021, 022, 023, 024, 025, 026, 027, /* 140 - 177 */
030, 031, 041, 042, 043, 044, 045, 046,
047, 050, 051, 062, 063, 064, 065, 066,
067, 070, 071, -1, -1, -1, -1, -1
};
const char odd_par[64] = {
0100, 0001, 0002, 0103, 0004, 0105, 0106, 0007,
0010, 0111, 0112, 0013, 0114, 0015, 0016, 0117,
0020, 0121, 0122, 0023, 0124, 0025, 0026, 0127,
0130, 0031, 0032, 0133, 0034, 0135, 0136, 0037,
0040, 0141, 0142, 0043, 0144, 0045, 0046, 0147,
0150, 0051, 0052, 0153, 0054, 0155, 0156, 0057,
0160, 0061, 0062, 0163, 0064, 0165, 0166, 0067,
0070, 0171, 0172, 0073, 0174, 0075, 0076, 0177 };
0100, 0001, 0002, 0103, 0004, 0105, 0106, 0007,
0010, 0111, 0112, 0013, 0114, 0015, 0016, 0117,
0020, 0121, 0122, 0023, 0124, 0025, 0026, 0127,
0130, 0031, 0032, 0133, 0034, 0135, 0136, 0037,
0040, 0141, 0142, 0043, 0144, 0045, 0046, 0147,
0150, 0051, 0052, 0153, 0054, 0155, 0156, 0057,
0160, 0061, 0062, 0163, 0064, 0165, 0166, 0067,
0070, 0171, 0172, 0073, 0174, 0075, 0076, 0177
};
/* Load carriage control tape
A carriage control tape consists of entries of the form
(repeat count) column number,column number,column number,...
(repeat count) column number,column number,column number,...
The CCT entries are stored in lpt_cct[0:lnt-1], lpt_ccl contains the
number of entries
@@ -154,21 +158,25 @@ extern int32 lpt_ccl, lpt_ccp, lpt_cct[CCT_LNT];
char *cptr, cbuf[CBUFSIZE], gbuf[CBUFSIZE];
ptr = 0;
for ( ; (cptr = fgets (cbuf, CBUFSIZE, fileref)) != NULL; ) { /* until eof */
for ( ; (cptr = fgets (cbuf, CBUFSIZE, fileref)) != NULL; ) { /* until eof */
mask = 0;
if (*cptr == '(') { /* repeat count? */
cptr = get_glyph (cptr + 1, gbuf, ')'); /* get 1st field */
rpt = get_uint (gbuf, 10, CCT_LNT, &r); /* repeat count */
if (r != SCPE_OK) return SCPE_FMT; }
if (*cptr == '(') { /* repeat count? */
cptr = get_glyph (cptr + 1, gbuf, ')'); /* get 1st field */
rpt = get_uint (gbuf, 10, CCT_LNT, &r); /* repeat count */
if (r != SCPE_OK) return SCPE_FMT;
}
else rpt = 1;
while (*cptr != 0) { /* get col no's */
cptr = get_glyph (cptr, gbuf, ','); /* get next field */
col = get_uint (gbuf, 10, 7, &r); /* column number */
if (r != SCPE_OK) return SCPE_FMT;
mask = mask | (1 << col); } /* set bit */
for ( ; rpt > 0; rpt--) { /* store vals */
if (ptr >= CCT_LNT) return SCPE_FMT;
cctbuf[ptr++] = mask; } }
while (*cptr != 0) { /* get col no's */
cptr = get_glyph (cptr, gbuf, ','); /* get next field */
col = get_uint (gbuf, 10, 7, &r); /* column number */
if (r != SCPE_OK) return SCPE_FMT;
mask = mask | (1 << col); /* set bit */
}
for ( ; rpt > 0; rpt--) { /* store vals */
if (ptr >= CCT_LNT) return SCPE_FMT;
cctbuf[ptr++] = mask;
}
}
if (ptr == 0) return SCPE_FMT;
lpt_ccl = ptr;
lpt_ccp = 0;
@@ -190,10 +198,11 @@ for (i = wd = 0; i < 4; ) {
if (c == 0) continue;
*ldr = 0;
wd = (wd << 6) | (c & 077);
i++; }
i++;
}
return wd;
}
t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
{
int32 i, wd, buf[8];
@@ -203,50 +212,53 @@ extern uint32 P;
if ((*cptr != 0) || (flag != 0)) return SCPE_ARG;
if (sim_switches & SWMASK ('L')) return sim_load_cct (fileref);
for (i = 0; i < 8; i++) { /* read boot */
for (i = 0; i < 8; i++) { /* read boot */
if ((wd = get_word (fileref, &ldr)) < 0) return SCPE_FMT;
buf[i] = wd; }
if ((buf[0] != 023200012) || /* 2 = WIM 12,2 */
(buf[1] != 004100002) || /* 3 = BRX 2 */
(buf[2] != 007100011) || /* 4 = LDX 11 */
(buf[3] != 023200000) || /* 5 = WIM 0,2 */
(buf[4] != 004021000) || /* 6 = SKS 21000 */
(buf[5] != 004100005)) return SCPE_FMT; /* 7 = BRX 5 */
for (i = 0; i < 8; i++) M[i + 2] = buf[i]; /* copy boot */
buf[i] = wd;
}
if ((buf[0] != 023200012) || /* 2 = WIM 12,2 */
(buf[1] != 004100002) || /* 3 = BRX 2 */
(buf[2] != 007100011) || /* 4 = LDX 11 */
(buf[3] != 023200000) || /* 5 = WIM 0,2 */
(buf[4] != 004021000) || /* 6 = SKS 21000 */
(buf[5] != 004100005)) return SCPE_FMT; /* 7 = BRX 5 */
for (i = 0; i < 8; i++) M[i + 2] = buf[i]; /* copy boot */
if (I_GETOP (buf[6]) == BRU) P = buf[6] & VA_MASK;
for (i = buf[7] & VA_MASK; i <= VA_MASK; i++) { /* load data */
for (i = buf[7] & VA_MASK; i <= VA_MASK; i++) { /* load data */
if ((wd = get_word (fileref, &ldr)) < 0) return SCPE_OK;
M[i] = wd; }
M[i] = wd;
}
return SCPE_NXM;
}
/* Symbol tables */
#define I_V_FL 24 /* inst class */
#define I_M_FL 017 /* class mask */
#define I_V_NPN 000 /* no operand */
#define I_V_PPO 001 /* POP */
#define I_V_IOI 002 /* IO */
#define I_V_MRF 003 /* memory reference */
#define I_V_REG 004 /* register change */
#define I_V_SHF 005 /* shift */
#define I_V_OPO 006 /* opcode only */
#define I_V_CHC 007 /* chan cmd */
#define I_V_CHT 010 /* chan test */
#define I_NPN (I_V_NPN << I_V_FL)
#define I_PPO (I_V_PPO << I_V_FL)
#define I_IOI (I_V_IOI << I_V_FL)
#define I_MRF (I_V_MRF << I_V_FL)
#define I_REG (I_V_REG << I_V_FL)
#define I_SHF (I_V_SHF << I_V_FL)
#define I_OPO (I_V_OPO << I_V_FL)
#define I_CHC (I_V_CHC << I_V_FL)
#define I_CHT (I_V_CHT << I_V_FL)
#define I_V_FL 24 /* inst class */
#define I_M_FL 017 /* class mask */
#define I_V_NPN 000 /* no operand */
#define I_V_PPO 001 /* POP */
#define I_V_IOI 002 /* IO */
#define I_V_MRF 003 /* memory reference */
#define I_V_REG 004 /* register change */
#define I_V_SHF 005 /* shift */
#define I_V_OPO 006 /* opcode only */
#define I_V_CHC 007 /* chan cmd */
#define I_V_CHT 010 /* chan test */
#define I_NPN (I_V_NPN << I_V_FL)
#define I_PPO (I_V_PPO << I_V_FL)
#define I_IOI (I_V_IOI << I_V_FL)
#define I_MRF (I_V_MRF << I_V_FL)
#define I_REG (I_V_REG << I_V_FL)
#define I_SHF (I_V_SHF << I_V_FL)
#define I_OPO (I_V_OPO << I_V_FL)
#define I_CHC (I_V_CHC << I_V_FL)
#define I_CHT (I_V_CHT << I_V_FL)
static const int32 masks[] = {
037777777, 010000000, 017700000,
017740000, 017700000, 017774000,
017700000, 017377677, 027737677 };
017700000, 017377677, 027737677
};
static const char *opcode[] = {
"POP", "EIR", "DIR",
@@ -292,11 +304,12 @@ static const char *opcode[] = {
"ALC", "DSC", "ASC", "TOP",
"CAT", "CET", "CZT", "CIT",
"CLA", "CLB", "CAB", /* encode only */
"CLA", "CLB", "CAB", /* encode only */
"CBA", "CBX", "CXB",
"XPO", "CXA", "CAX",
"CNA", "CLX", NULL,
NULL };
NULL
};
static const int32 opc_val[] = {
010000000+I_PPO, 000220002+I_NPN, 000220004+I_NPN,
@@ -346,121 +359,136 @@ static const int32 opc_val[] = {
004600010+I_REG, 004600020+I_REG, 004600040+I_REG,
004600100+I_REG, 004600200+I_REG, 004600400+I_REG,
004601000+I_REG, 024600000+I_REG, 004600000+I_REG,
-1 };
-1
};
static const char *chname[] = {
"W", "Y", "C", "D", "E", "F", "G", "H", NULL };
"W", "Y", "C", "D", "E", "F", "G", "H", NULL
};
/* Register change decode
Inputs:
*of = output stream
inst = mask bits
*of = output stream
inst = mask bits
*/
void fprint_reg (FILE *of, int32 inst)
{
int32 i, j, sp;
inst = inst & ~(I_M_OP << I_V_OP); /* clear opcode */
for (i = sp = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
if ((j == I_V_REG) && (opc_val[i] & inst)) { /* reg class? */
inst = inst & ~opc_val[i]; /* mask bit set? */
fprintf (of, (sp? " %s": "%s"), opcode[i]);
sp = 1; } }
inst = inst & ~(I_M_OP << I_V_OP); /* clear opcode */
for (i = sp = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
if ((j == I_V_REG) && (opc_val[i] & inst)) { /* reg class? */
inst = inst & ~opc_val[i]; /* mask bit set? */
fprintf (of, (sp? " %s": "%s"), opcode[i]);
sp = 1;
}
}
return;
}
/* Symbolic decode
Inputs:
*of = output stream
addr = current PC
*val = pointer to values
*uptr = pointer to unit
sw = switches
*of = output stream
addr = current PC
*val = pointer to values
*uptr = pointer to unit
sw = switches
Outputs:
return = status code
return = status code
*/
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
UNIT *uptr, int32 sw)
UNIT *uptr, int32 sw)
{
int32 i, j, ch;
int32 inst, op, tag, va, shf, nonop;
inst = val[0]; /* get inst */
op = I_GETOP (inst); /* get fields */
inst = val[0]; /* get inst */
op = I_GETOP (inst); /* get fields */
tag = (inst >> 21) & 06;
va = inst & VA_MASK;
shf = inst & I_SHFMSK;
nonop = inst & 077777;
if (sw & SWMASK ('A')) { /* ASCII? */
if (sw & SWMASK ('A')) { /* ASCII? */
if (inst > 0377) return SCPE_ARG;
fprintf (of, FMTASC (inst & 0177));
return SCPE_OK; }
if (sw & SWMASK ('C')) { /* character? */
return SCPE_OK;
}
if (sw & SWMASK ('C')) { /* character? */
fprintf (of, "%c", sds_to_ascii[(inst >> 18) & 077]);
fprintf (of, "%c", sds_to_ascii[(inst >> 12) & 077]);
fprintf (of, "%c", sds_to_ascii[(inst >> 6) & 077]);
fprintf (of, "%c", sds_to_ascii[inst & 077]);
return SCPE_OK; }
return SCPE_OK;
}
if (!(sw & SWMASK ('M'))) return SCPE_ARG;
/* Instruction decode */
for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
if ((opc_val[i] & DMASK) == (inst & masks[j])) { /* match? */
for (i = 0; opc_val[i] >= 0; i++) { /* loop thru ops */
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
if ((opc_val[i] & DMASK) == (inst & masks[j])) { /* match? */
switch (j) { /* case on class */
case I_V_NPN: /* no operands */
case I_V_OPO: /* opcode only */
fprintf (of, "%s", opcode[i]); /* opcode */
break;
case I_V_SHF: /* shift */
fprintf (of, "%s %-o", opcode[i], shf);
if (tag) fprintf (of, ",%-o", tag);
break;
case I_V_PPO: /* pop */
fprintf (of, "POP %-o,%-o", op, nonop);
if (tag) fprintf (of, ",%-o", tag);
break;
case I_V_IOI: /* I/O */
fprintf (of, "%s %-o", opcode[i], nonop);
if (tag) fprintf (of, ",%-o", tag);
break;
case I_V_MRF: /* mem ref */
fprintf (of, "%s %-o", opcode[i], va);
if (tag) fprintf (of, ",%-o", tag);
break;
case I_V_REG: /* reg change */
fprint_reg (of, inst); /* decode */
break;
case I_V_CHC: /* chan cmd */
ch = I_GETEOCH (inst); /* get chan */
fprintf (of, "%s %s", opcode[i], chname[ch]);
break;
case I_V_CHT: /* chan test */
ch = I_GETSKCH (inst); /* get chan */
fprintf (of, "%s %s", opcode[i], chname[ch]);
break;
} /* end case */
return SCPE_OK;
} /* end if */
} /* end for */
switch (j) { /* case on class */
case I_V_NPN: /* no operands */
case I_V_OPO: /* opcode only */
fprintf (of, "%s", opcode[i]); /* opcode */
break;
case I_V_SHF: /* shift */
fprintf (of, "%s %-o", opcode[i], shf);
if (tag) fprintf (of, ",%-o", tag);
break;
case I_V_PPO: /* pop */
fprintf (of, "POP %-o,%-o", op, nonop);
if (tag) fprintf (of, ",%-o", tag);
break;
case I_V_IOI: /* I/O */
fprintf (of, "%s %-o", opcode[i], nonop);
if (tag) fprintf (of, ",%-o", tag);
break;
case I_V_MRF: /* mem ref */
fprintf (of, "%s %-o", opcode[i], va);
if (tag) fprintf (of, ",%-o", tag);
break;
case I_V_REG: /* reg change */
fprint_reg (of, inst); /* decode */
break;
case I_V_CHC: /* chan cmd */
ch = I_GETEOCH (inst); /* get chan */
fprintf (of, "%s %s", opcode[i], chname[ch]);
break;
case I_V_CHT: /* chan test */
ch = I_GETSKCH (inst); /* get chan */
fprintf (of, "%s %s", opcode[i], chname[ch]);
break;
} /* end case */
return SCPE_OK;
} /* end if */
} /* end for */
return SCPE_ARG;
}
/* Get (optional) tag
Inputs:
*cptr = pointer to input string
*tag = pointer to tag
*cptr = pointer to input string
*tag = pointer to tag
Outputs:
cptr = updated pointer to input string
cptr = updated pointer to input string
*/
char *get_tag (char *cptr, t_value *tag)
@@ -468,23 +496,23 @@ char *get_tag (char *cptr, t_value *tag)
char *tptr, gbuf[CBUFSIZE];
t_stat r;
tptr = get_glyph (cptr, gbuf, 0); /* get next field */
*tag = get_uint (gbuf, 8, 07, &r) << I_V_TAG; /* parse */
if (r == SCPE_OK) return tptr; /* ok? advance */
tptr = get_glyph (cptr, gbuf, 0); /* get next field */
*tag = get_uint (gbuf, 8, 07, &r) << I_V_TAG; /* parse */
if (r == SCPE_OK) return tptr; /* ok? advance */
*tag = 0;
return cptr; /* no change */
return cptr; /* no change */
}
/* Symbolic input
Inputs:
*cptr = pointer to input string
addr = current PC
uptr = pointer to unit
*val = pointer to output values
sw = switches
*cptr = pointer to input string
addr = current PC
uptr = pointer to unit
*val = pointer to output values
sw = switches
Outputs:
status = error status
status = error status
*/
t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val, int32 sw)
@@ -498,79 +526,93 @@ while (isspace (*cptr)) cptr++;
for (i = 1; (i < 4) && (cptr[i] != 0); i++)
if (cptr[i] == 0) for (j = i + 1; j <= 4; j++) cptr[j] = 0;
if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
val[0] = (t_value) cptr[0] | 0200;
return SCPE_OK; }
return SCPE_OK;
}
if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* string? */
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
for (i = j = 0, val[0] = 0; i < 4; i++) {
if (cptr[i] == 0) j = 1; /* latch str end */
k = ascii_to_sds[cptr[i] & 0177]; /* cvt char */
if (j || (k < 0)) k = 0; /* bad, end? spc */
val[0] = (val[0] << 6) | k; }
return SCPE_OK; }
/* Symbolic input, continued */
if (cptr[i] == 0) j = 1; /* latch str end */
k = ascii_to_sds[cptr[i] & 0177]; /* cvt char */
if (j || (k < 0)) k = 0; /* bad, end? spc */
val[0] = (val[0] << 6) | k;
}
return SCPE_OK;
}
cptr = get_glyph (cptr, gbuf, 0); /* get opcode */
cptr = get_glyph (cptr, gbuf, 0); /* get opcode */
for (i = 0; (opcode[i] != NULL) && (strcmp (opcode[i], gbuf) != 0) ; i++) ;
if (opcode[i] == NULL) return SCPE_ARG;
val[0] = opc_val[i] & DMASK; /* get value */
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
val[0] = opc_val[i] & DMASK; /* get value */
j = (opc_val[i] >> I_V_FL) & I_M_FL; /* get class */
switch (j) { /* case on class */
case I_V_NPN: case I_V_OPO: /* opcode only */
break;
case I_V_SHF: /* shift */
cptr = get_glyph (cptr, gbuf, ','); /* get next field */
d = get_uint (gbuf, 8, I_SHFMSK, &r); /* shift count */
if (r != SCPE_OK) return SCPE_ARG;
cptr = get_tag (cptr, &tag); /* get opt tag */
val[0] = val[0] | d | tag;
break;
case I_V_PPO: /* pop */
cptr = get_glyph (cptr, gbuf, ','); /* get next field */
d = get_uint (gbuf, 8, 077, &r); /* opcode */
if (r != SCPE_OK) return SCPE_ARG;
val[0] = val[0] | d; /* fall thru */
case I_V_IOI: /* I/O */
cptr = get_glyph (cptr, gbuf, ','); /* get next field */
d = get_uint (gbuf, 8, 077777, &r); /* 15b address */
if (r != SCPE_OK) return SCPE_ARG;
cptr = get_tag (cptr, &tag); /* get opt tag */
val[0] = val[0] | d | tag;
break;
case I_V_MRF: /* mem ref */
cptr = get_glyph (cptr, gbuf, ','); /* get next field */
d = get_uint (gbuf, 8, VA_MASK, &r); /* virt address */
if (r != SCPE_OK) return SCPE_ARG;
cptr = get_tag (cptr, &tag); /* get opt tag */
val[0] = val[0] | d | tag;
break;
case I_V_REG: /* register */
for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0;
cptr = get_glyph (cptr, gbuf, 0)) {
for (i = 0; (opcode[i] != NULL) &&
(strcmp (opcode[i], gbuf) != 0); i++) ;
if (opcode[i] != NULL) {
k = opc_val[i] & DMASK;;
if (I_GETOP (k) != RCH) return SCPE_ARG;
val[0] = val[0] | k; }
else {
d = get_uint (gbuf, 8, 077777, &r);
if (r != SCPE_OK) return SCPE_ARG;
else val[0] = val[0] | d; } }
break;
case I_V_CHC: case I_V_CHT: /* channel */
cptr = get_glyph (cptr, gbuf, ','); /* get next field */
for (i = 0; (chname[i] != NULL) && (strcmp (chname[i], gbuf) != 0);
i++);
if (chname[i] != NULL) d = i; /* named chan */
else {
d = get_uint (gbuf, 8, NUM_CHAN - 1, &r);
if (r != SCPE_OK) return SCPE_ARG; } /* numbered chan */
val[0] = val[0] | ((j == I_V_CHC)? I_SETEOCH (d): I_SETSKCH (d));
break; } /* end case */
if (*cptr != 0) return SCPE_ARG; /* junk at end? */
switch (j) { /* case on class */
case I_V_NPN: case I_V_OPO: /* opcode only */
break;
case I_V_SHF: /* shift */
cptr = get_glyph (cptr, gbuf, ','); /* get next field */
d = get_uint (gbuf, 8, I_SHFMSK, &r); /* shift count */
if (r != SCPE_OK) return SCPE_ARG;
cptr = get_tag (cptr, &tag); /* get opt tag */
val[0] = val[0] | d | tag;
break;
case I_V_PPO: /* pop */
cptr = get_glyph (cptr, gbuf, ','); /* get next field */
d = get_uint (gbuf, 8, 077, &r); /* opcode */
if (r != SCPE_OK) return SCPE_ARG;
val[0] = val[0] | d; /* fall thru */
case I_V_IOI: /* I/O */
cptr = get_glyph (cptr, gbuf, ','); /* get next field */
d = get_uint (gbuf, 8, 077777, &r); /* 15b address */
if (r != SCPE_OK) return SCPE_ARG;
cptr = get_tag (cptr, &tag); /* get opt tag */
val[0] = val[0] | d | tag;
break;
case I_V_MRF: /* mem ref */
cptr = get_glyph (cptr, gbuf, ','); /* get next field */
d = get_uint (gbuf, 8, VA_MASK, &r); /* virt address */
if (r != SCPE_OK) return SCPE_ARG;
cptr = get_tag (cptr, &tag); /* get opt tag */
val[0] = val[0] | d | tag;
break;
case I_V_REG: /* register */
for (cptr = get_glyph (cptr, gbuf, 0); gbuf[0] != 0;
cptr = get_glyph (cptr, gbuf, 0)) {
for (i = 0; (opcode[i] != NULL) &&
(strcmp (opcode[i], gbuf) != 0); i++) ;
if (opcode[i] != NULL) {
k = opc_val[i] & DMASK;;
if (I_GETOP (k) != RCH) return SCPE_ARG;
val[0] = val[0] | k;
}
else {
d = get_uint (gbuf, 8, 077777, &r);
if (r != SCPE_OK) return SCPE_ARG;
else val[0] = val[0] | d;
}
}
break;
case I_V_CHC: case I_V_CHT: /* channel */
cptr = get_glyph (cptr, gbuf, ','); /* get next field */
for (i = 0; (chname[i] != NULL) && (strcmp (chname[i], gbuf) != 0);
i++);
if (chname[i] != NULL) d = i; /* named chan */
else {
d = get_uint (gbuf, 8, NUM_CHAN - 1, &r);
if (r != SCPE_OK) return SCPE_ARG; /* numbered chan */
}
val[0] = val[0] | ((j == I_V_CHC)? I_SETEOCH (d): I_SETSKCH (d));
break;
} /* end case */
if (*cptr != 0) return SCPE_ARG; /* junk at end? */
return SCPE_OK;
}