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:
committed by
Mark Pizzolato
parent
ec60bbf329
commit
b7c1eae41f
1806
SDS/sds_cpu.c
1806
SDS/sds_cpu.c
File diff suppressed because it is too large
Load Diff
582
SDS/sds_defs.h
582
SDS/sds_defs.h
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
362
SDS/sds_drm.c
362
SDS/sds_drm.c
@@ -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;
|
||||
}
|
||||
|
||||
417
SDS/sds_dsk.c
417
SDS/sds_dsk.c
@@ -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;
|
||||
}
|
||||
|
||||
950
SDS/sds_io.c
950
SDS/sds_io.c
File diff suppressed because it is too large
Load Diff
335
SDS/sds_lp.c
335
SDS/sds_lp.c
@@ -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);
|
||||
}
|
||||
|
||||
563
SDS/sds_mt.c
563
SDS/sds_mt.c
@@ -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;
|
||||
}
|
||||
|
||||
560
SDS/sds_mux.c
560
SDS/sds_mux.c
@@ -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;
|
||||
|
||||
331
SDS/sds_rad.c
331
SDS/sds_rad.c
@@ -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;
|
||||
}
|
||||
|
||||
618
SDS/sds_stddev.c
618
SDS/sds_stddev.c
@@ -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;
|
||||
}
|
||||
|
||||
584
SDS/sds_sys.c
584
SDS/sds_sys.c
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user