1
0
mirror of https://github.com/simh/simh.git synced 2026-02-22 23:29:15 +00:00

Notes For V3.5-0

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

1. New Features in 3.4-1

1.1 All Ethernet devices

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

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

- Added support for SET <unit>n DISCONNECT

1.3 VAX

- Added latent QDSS support
- Revised autoconfigure to handle QDSS

1.4 PDP-11

- Revised autoconfigure to handle more casees

2. Bugs Fixed in 3.4-1

2.1 SCP and libraries

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

2.2 1401

- Fixed bug, CPU reset was clearing SSB through SSG

2.3 PDP-11

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

2.4 Interdata

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

2.5 SDS

- Fixed bug in SHOW MUX CONN/STATS

2.6 HP

- Fixed bug in SHOW MUX CONN/STATS

2.7 PDP-8

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

2.8 PDP-18b

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

2.9 Nova, Eclipse

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

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
/* h316_defs.h: Honeywell 316/516 simulator definitions
Copyright (c) 1999-2004, Robert M. Supnik
Copyright (c) 1999-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,181 +19,181 @@
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.
15-Feb-05 RMS Added start button interrupt
01-Dec-04 RMS Added double precision constants
24-Oct-03 RMS Added DMA/DMC support
25-Apr-03 RMS Revised for extended file support
15-Feb-05 RMS Added start button interrupt
01-Dec-04 RMS Added double precision constants
24-Oct-03 RMS Added DMA/DMC support
25-Apr-03 RMS Revised for extended file support
*/
#ifndef _H316_DEFS_H_
#define _H316_DEFS_H_ 0
#define _H316_DEFS_H_ 0
#include "sim_defs.h" /* simulator defns */
#include "sim_defs.h" /* simulator defns */
/* Simulator stop codes */
#define STOP_RSRV 1 /* must be 1 */
#define STOP_IODV 2 /* must be 2 */
#define STOP_HALT 3 /* HALT */
#define STOP_IBKPT 4 /* breakpoint */
#define STOP_IND 5 /* indirect loop */
#define STOP_DMAER 6 /* DMA error */
#define STOP_MTWRP 7 /* MT write protected */
#define STOP_DPOVR 8 /* DP write overrun */
#define STOP_DPFMT 9 /* DP invalid format */
#define STOP_RSRV 1 /* must be 1 */
#define STOP_IODV 2 /* must be 2 */
#define STOP_HALT 3 /* HALT */
#define STOP_IBKPT 4 /* breakpoint */
#define STOP_IND 5 /* indirect loop */
#define STOP_DMAER 6 /* DMA error */
#define STOP_MTWRP 7 /* MT write protected */
#define STOP_DPOVR 8 /* DP write overrun */
#define STOP_DPFMT 9 /* DP invalid format */
/* Memory */
#define MAXMEMSIZE 32768 /* max memory size */
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
#define X_AMASK (MAXMEMSIZE - 1) /* ext address mask */
#define NX_AMASK ((MAXMEMSIZE / 2) - 1) /* nx address mask */
#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE)
#define MAXMEMSIZE 32768 /* max memory size */
#define MEMSIZE (cpu_unit.capac) /* actual memory size */
#define X_AMASK (MAXMEMSIZE - 1) /* ext address mask */
#define NX_AMASK ((MAXMEMSIZE / 2) - 1) /* nx address mask */
#define MEM_ADDR_OK(x) (((uint32) (x)) < MEMSIZE)
/* Architectural constants */
#define SIGN 0100000 /* sign */
#define DP_SIGN 010000000000
#define DMASK 0177777 /* data mask */
#define MMASK (DMASK & ~SIGN) /* magnitude mask */
#define XR M[0]
#define M_CLK 061 /* clock location */
#define M_RSTINT 062 /* restrict int */
#define M_INT 063 /* int location */
#define SIGN 0100000 /* sign */
#define DP_SIGN 010000000000
#define DMASK 0177777 /* data mask */
#define MMASK (DMASK & ~SIGN) /* magnitude mask */
#define XR M[0]
#define M_CLK 061 /* clock location */
#define M_RSTINT 062 /* restrict int */
#define M_INT 063 /* int location */
/* CPU options */
#define UNIT_V_MSIZE (UNIT_V_UF + 0) /* dummy mask */
#define UNIT_V_EXT (UNIT_V_UF + 1) /* extended mem */
#define UNIT_V_HSA (UNIT_V_UF + 2) /* high speed arith */
#define UNIT_V_DMC (UNIT_V_UF + 3) /* DMC */
#define UNIT_MSIZE (1u << UNIT_V_MSIZE)
#define UNIT_EXT (1u << UNIT_V_EXT)
#define UNIT_HSA (1u << UNIT_V_HSA)
#define UNIT_DMC (1u << UNIT_V_DMC)
#define UNIT_V_MSIZE (UNIT_V_UF + 0) /* dummy mask */
#define UNIT_V_EXT (UNIT_V_UF + 1) /* extended mem */
#define UNIT_V_HSA (UNIT_V_UF + 2) /* high speed arith */
#define UNIT_V_DMC (UNIT_V_UF + 3) /* DMC */
#define UNIT_MSIZE (1u << UNIT_V_MSIZE)
#define UNIT_EXT (1u << UNIT_V_EXT)
#define UNIT_HSA (1u << UNIT_V_HSA)
#define UNIT_DMC (1u << UNIT_V_DMC)
/* Instruction format */
#define I_M_OP 077 /* opcode */
#define I_V_OP 10
#define I_GETOP(x) (((x) >> I_V_OP) & I_M_OP)
#define I_M_FNC 017 /* function */
#define I_V_FNC 6
#define I_GETFNC(x) (((x) >> I_V_FNC) & I_M_FNC)
#define IA 0100000 /* indirect address */
#define IDX 0040000 /* indexed */
#define SC 0001000 /* sector */
#define DISP 0000777 /* page displacement */
#define PAGENO 0077000 /* page number */
#define INCLRA (010 << I_V_FNC) /* INA clear A */
#define DEVMASK 0000077 /* device mask */
#define SHFMASK 0000077 /* shift mask */
#define I_M_OP 077 /* opcode */
#define I_V_OP 10
#define I_GETOP(x) (((x) >> I_V_OP) & I_M_OP)
#define I_M_FNC 017 /* function */
#define I_V_FNC 6
#define I_GETFNC(x) (((x) >> I_V_FNC) & I_M_FNC)
#define IA 0100000 /* indirect address */
#define IDX 0040000 /* indexed */
#define SC 0001000 /* sector */
#define DISP 0000777 /* page displacement */
#define PAGENO 0077000 /* page number */
#define INCLRA (010 << I_V_FNC) /* INA clear A */
#define DEVMASK 0000077 /* device mask */
#define SHFMASK 0000077 /* shift mask */
/* I/O opcodes */
#define ioOCP 0 /* output control */
#define ioSKS 1 /* skip if set */
#define ioINA 2 /* input to A */
#define ioOTA 3 /* output from A */
#define ioEND 4 /* channel end */
#define ioOCP 0 /* output control */
#define ioSKS 1 /* skip if set */
#define ioINA 2 /* input to A */
#define ioOTA 3 /* output from A */
#define ioEND 4 /* channel end */
/* Device information block */
struct h316_dib {
uint32 dev; /* device number */
uint32 chan; /* dma/dmc channel */
uint32 num; /* number of slots */
int32 (*io) (int32 inst, int32 fnc, int32 dat, int32 dev); };
uint32 dev; /* device number */
uint32 chan; /* dma/dmc channel */
uint32 num; /* number of slots */
int32 (*io) (int32 inst, int32 fnc, int32 dat, int32 dev); };
typedef struct h316_dib DIB;
/* DMA/DMC channel numbers */
#define IOBUS 0 /* IO bus */
#define DMA_MIN 1 /* 4 DMA channels */
#define DMA_MAX 4
#define DMC_MIN 1 /* 16 DMC channels */
#define DMC_MAX 16
#define IOBUS 0 /* IO bus */
#define DMA_MIN 1 /* 4 DMA channels */
#define DMA_MAX 4
#define DMC_MIN 1 /* 16 DMC channels */
#define DMC_MAX 16
#define DMA1 (DMA_MIN)
#define DMC1 (DMA_MAX+DMC_MIN)
#define DMA1 (DMA_MIN)
#define DMC1 (DMA_MAX+DMC_MIN)
/* DMA/DMC bit assignments in channel request word */
#define DMA_V_DMA1 0 /* DMA channels */
#define DMC_V_DMC1 4 /* DMC channels */
#define SET_CH_REQ(x) chan_req = chan_req | (1 << (x))
#define Q_DMA(x) (((x) >= 0) && ((x) < DMC_V_DMC1))
#define DMA_V_DMA1 0 /* DMA channels */
#define DMC_V_DMC1 4 /* DMC channels */
#define SET_CH_REQ(x) chan_req = chan_req | (1 << (x))
#define Q_DMA(x) (((x) >= 0) && ((x) < DMC_V_DMC1))
/* DMA/DMC definitions */
#define DMA_IN 0100000 /* input flag */
#define DMC_BASE 020 /* DMC memory base */
#define DMA_IN 0100000 /* input flag */
#define DMC_BASE 020 /* DMC memory base */
/* I/O device codes */
#define PTR 001 /* paper tape reader */
#define PTP 002 /* paper tape punch */
#define LPT 003 /* line printer */
#define TTY 004 /* console */
#define CDR 005 /* card reader */
#define MT 010 /* mag tape data */
#define CLK_KEYS 020 /* clock/keys (CPU) */
#define FHD 022 /* fixed head disk */
#define DMA 024 /* DMA control */
#define DP 025 /* moving head disk */
#define DEV_MAX 64
#define PTR 001 /* paper tape reader */
#define PTP 002 /* paper tape punch */
#define LPT 003 /* line printer */
#define TTY 004 /* console */
#define CDR 005 /* card reader */
#define MT 010 /* mag tape data */
#define CLK_KEYS 020 /* clock/keys (CPU) */
#define FHD 022 /* fixed head disk */
#define DMA 024 /* DMA control */
#define DP 025 /* moving head disk */
#define DEV_MAX 64
/* Interrupt flags, definitions correspond to SMK bits */
#define INT_V_CLK 0 /* clock */
#define INT_V_MPE 1 /* parity error */
#define INT_V_LPT 2 /* line printer */
#define INT_V_CDR 4 /* card reader */
#define INT_V_TTY 5 /* teletype */
#define INT_V_PTP 6 /* paper tape punch */
#define INT_V_PTR 7 /* paper tape reader */
#define INT_V_FHD 8 /* fixed head disk */
#define INT_V_DP 12 /* moving head disk */
#define INT_V_MT 15 /* mag tape */
#define INT_V_START 16 /* start button */
#define INT_V_NODEF 17 /* int not deferred */
#define INT_V_ON 18 /* int on */
#define INT_V_CLK 0 /* clock */
#define INT_V_MPE 1 /* parity error */
#define INT_V_LPT 2 /* line printer */
#define INT_V_CDR 4 /* card reader */
#define INT_V_TTY 5 /* teletype */
#define INT_V_PTP 6 /* paper tape punch */
#define INT_V_PTR 7 /* paper tape reader */
#define INT_V_FHD 8 /* fixed head disk */
#define INT_V_DP 12 /* moving head disk */
#define INT_V_MT 15 /* mag tape */
#define INT_V_START 16 /* start button */
#define INT_V_NODEF 17 /* int not deferred */
#define INT_V_ON 18 /* int on */
/* I/O macros */
#define IOT_V_REASON 17
#define IOT_V_SKIP 16
#define IOT_SKIP (1u << IOT_V_SKIP)
#define IORETURN(f,v) (((f)? (v): SCPE_OK) << IOT_V_REASON)
#define IOBADFNC(x) (((stop_inst) << IOT_V_REASON) | (x))
#define IOSKIP(x) (IOT_SKIP | (x))
#define IOT_V_REASON 17
#define IOT_V_SKIP 16
#define IOT_SKIP (1u << IOT_V_SKIP)
#define IORETURN(f,v) (((f)? (v): SCPE_OK) << IOT_V_REASON)
#define IOBADFNC(x) (((stop_inst) << IOT_V_REASON) | (x))
#define IOSKIP(x) (IOT_SKIP | (x))
#define INT_CLK (1u << INT_V_CLK)
#define INT_MPE (1u << INT_V_MPE)
#define INT_LPT (1u << INT_V_LPT)
#define INT_CDR (1u << INT_V_CDR)
#define INT_TTY (1u << INT_V_TTY)
#define INT_PTP (1u << INT_V_PTP)
#define INT_PTR (1u << INT_V_PTR)
#define INT_FHD (1u << INT_V_FHD)
#define INT_DP (1u << INT_V_DP)
#define INT_MT (1u << INT_V_MT)
#define INT_START (1u << INT_V_START)
#define INT_NODEF (1u << INT_V_NODEF)
#define INT_ON (1u << INT_V_ON)
#define INT_NMI (INT_START)
#define INT_PEND (INT_ON | INT_NODEF)
#define INT_CLK (1u << INT_V_CLK)
#define INT_MPE (1u << INT_V_MPE)
#define INT_LPT (1u << INT_V_LPT)
#define INT_CDR (1u << INT_V_CDR)
#define INT_TTY (1u << INT_V_TTY)
#define INT_PTP (1u << INT_V_PTP)
#define INT_PTR (1u << INT_V_PTR)
#define INT_FHD (1u << INT_V_FHD)
#define INT_DP (1u << INT_V_DP)
#define INT_MT (1u << INT_V_MT)
#define INT_START (1u << INT_V_START)
#define INT_NODEF (1u << INT_V_NODEF)
#define INT_ON (1u << INT_V_ON)
#define INT_NMI (INT_START)
#define INT_PEND (INT_ON | INT_NODEF)
#define SET_INT(x) dev_int = dev_int | (x)
#define CLR_INT(x) dev_int = dev_int & ~(x)
#define TST_INT(x) ((dev_int & (x)) != 0)
#define CLR_ENB(x) dev_enb = dev_enb & ~(x)
#define TST_INTREQ(x) ((dev_int & dev_enb & (x)) != 0)
#define SET_INT(x) dev_int = dev_int | (x)
#define CLR_INT(x) dev_int = dev_int & ~(x)
#define TST_INT(x) ((dev_int & (x)) != 0)
#define CLR_ENB(x) dev_enb = dev_enb & ~(x)
#define TST_INTREQ(x) ((dev_int & dev_enb & (x)) != 0)
/* Prototypes */

View File

@@ -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 Honeywell 316/516 simulator.

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
/* h316_fhd.c: H316/516 fixed head simulator
Copyright (c) 2003-2004, Robert M. Supnik
Copyright (c) 2003-2005, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@@ -19,13 +19,13 @@
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.
fhd 516-4400 fixed head disk
fhd 516-4400 fixed head disk
04-Jan-04 RMS Changed sim_fsize calling sequence
04-Jan-04 RMS Changed sim_fsize calling sequence
These head-per-track devices are buffered in memory, to minimize overhead.
*/
@@ -35,59 +35,59 @@
/* Constants */
#define FH_NUMWD 1536 /* words/track */
#define FH_NUMTK 64 /* tracks/surface */
#define FH_WDPSF (FH_NUMWD * FH_NUMTK) /* words/surface */
#define FH_NUMSF 16 /* surfaces/ctlr */
#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */
#define UNIT_V_SF (UNIT_V_UF + 1) /* #surfaces - 1 */
#define UNIT_M_SF 017
#define UNIT_AUTO (1 << UNIT_V_AUTO)
#define UNIT_SF (UNIT_M_SF << UNIT_V_SF)
#define UNIT_GETSF(x) ((((x) >> UNIT_V_SF) & UNIT_M_SF) + 1)
#define FH_NUMWD 1536 /* words/track */
#define FH_NUMTK 64 /* tracks/surface */
#define FH_WDPSF (FH_NUMWD * FH_NUMTK) /* words/surface */
#define FH_NUMSF 16 /* surfaces/ctlr */
#define UNIT_V_AUTO (UNIT_V_UF + 0) /* autosize */
#define UNIT_V_SF (UNIT_V_UF + 1) /* #surfaces - 1 */
#define UNIT_M_SF 017
#define UNIT_AUTO (1 << UNIT_V_AUTO)
#define UNIT_SF (UNIT_M_SF << UNIT_V_SF)
#define UNIT_GETSF(x) ((((x) >> UNIT_V_SF) & UNIT_M_SF) + 1)
/* Command word 1 */
#define CW1_RW 0100000 /* read vs write */
#define CW1_V_SF 10 /* surface */
#define CW1_M_SF 017
#define CW1_GETSF(x) (((x) >> CW1_V_SF) & CW1_M_SF)
#define CW1_V_TK 4 /* track */
#define CW1_M_TK 077
#define CW1_GETTK(x) (((x) >> CW1_V_TK) & CW1_M_TK)
#define CW1_RW 0100000 /* read vs write */
#define CW1_V_SF 10 /* surface */
#define CW1_M_SF 017
#define CW1_GETSF(x) (((x) >> CW1_V_SF) & CW1_M_SF)
#define CW1_V_TK 4 /* track */
#define CW1_M_TK 077
#define CW1_GETTK(x) (((x) >> CW1_V_TK) & CW1_M_TK)
/* Command word 2 */
#define CW2_V_CA 0 /* character addr */
#define CW2_M_CA 07777
#define CW2_GETCA(x) (((x) >> CW2_V_CA) & CW2_M_CA)
#define CW2_V_CA 0 /* character addr */
#define CW2_M_CA 07777
#define CW2_GETCA(x) (((x) >> CW2_V_CA) & CW2_M_CA)
#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \
((double) FH_NUMWD)))
#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \
((double) FH_NUMWD)))
/* OTA states */
#define OTA_NOP 0 /* normal */
#define OTA_CW1 1 /* expecting CW1 */
#define OTA_CW2 2 /* expecting CW2 */
#define OTA_NOP 0 /* normal */
#define OTA_CW1 1 /* expecting CW1 */
#define OTA_CW2 2 /* expecting CW2 */
extern int32 dev_int, dev_enb, chan_req;
extern int32 stop_inst;
extern uint32 dma_ad[DMA_MAX];
uint32 fhd_cw1 = 0; /* cmd word 1 */
uint32 fhd_cw2 = 0; /* cmd word 2 */
uint32 fhd_buf = 0; /* buffer */
uint32 fhd_otas = 0; /* state */
uint32 fhd_busy = 0; /* busy */
uint32 fhd_rdy = 0; /* word ready */
uint32 fhd_dte = 0; /* data err */
uint32 fhd_ace = 0; /* access error */
uint32 fhd_dma = 0; /* DMA/DMC */
uint32 fhd_eor = 0; /* end of range */
uint32 fhd_csum = 0; /* parity checksum */
uint32 fhd_stopioe = 1; /* stop on error */
int32 fhd_time = 10; /* time per word */
uint32 fhd_cw1 = 0; /* cmd word 1 */
uint32 fhd_cw2 = 0; /* cmd word 2 */
uint32 fhd_buf = 0; /* buffer */
uint32 fhd_otas = 0; /* state */
uint32 fhd_busy = 0; /* busy */
uint32 fhd_rdy = 0; /* word ready */
uint32 fhd_dte = 0; /* data err */
uint32 fhd_ace = 0; /* access error */
uint32 fhd_dma = 0; /* DMA/DMC */
uint32 fhd_eor = 0; /* end of range */
uint32 fhd_csum = 0; /* parity checksum */
uint32 fhd_stopioe = 1; /* stop on error */
int32 fhd_time = 10; /* time per word */
int32 fhdio (int32 inst, int32 fnc, int32 dat, int32 dev);
t_stat fhd_svc (UNIT *uptr);
@@ -105,133 +105,148 @@ uint32 fhd_csword (uint32 cs, uint32 ch);
/* FHD data structures
fhd_dev device descriptor
fhd_unit unit descriptor
fhd_mod unit modifiers
fhd_reg register list
fhd_dev device descriptor
fhd_unit unit descriptor
fhd_mod unit modifiers
fhd_reg register list
*/
DIB fhd_dib = { FHD, IOBUS, 1, &fhdio };
UNIT fhd_unit =
{ UDATA (&fhd_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+
UNIT_MUSTBUF, FH_WDPSF) };
UNIT fhd_unit = {
UDATA (&fhd_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_BUFABLE+UNIT_MUSTBUF,
FH_WDPSF)
};
REG fhd_reg[] = {
{ ORDATA (CW1, fhd_cw1, 16) },
{ ORDATA (CW2, fhd_cw2, 16) },
{ ORDATA (BUF, fhd_buf, 16) },
{ FLDATA (BUSY, fhd_busy, 0) },
{ FLDATA (RDY, fhd_rdy, 0) },
{ FLDATA (DTE, fhd_dte, 0) },
{ FLDATA (ACE, fhd_ace, 0) },
{ FLDATA (EOR, fhd_eor, 0) },
{ FLDATA (DMA, fhd_dma, 0) },
{ FLDATA (CSUM, fhd_csum, 7) },
{ FLDATA (INTREQ, dev_int, INT_V_MT) },
{ FLDATA (ENABLE, dev_enb, INT_V_MT) },
{ DRDATA (TIME, fhd_time, 31), REG_NZ + PV_LEFT },
{ ORDATA (OTAS, fhd_otas, 2), REG_HRO },
{ ORDATA (CHAN, fhd_dib.chan, 5), REG_HRO },
{ FLDATA (STOP_IOE, fhd_stopioe, 0) },
{ NULL } };
{ ORDATA (CW1, fhd_cw1, 16) },
{ ORDATA (CW2, fhd_cw2, 16) },
{ ORDATA (BUF, fhd_buf, 16) },
{ FLDATA (BUSY, fhd_busy, 0) },
{ FLDATA (RDY, fhd_rdy, 0) },
{ FLDATA (DTE, fhd_dte, 0) },
{ FLDATA (ACE, fhd_ace, 0) },
{ FLDATA (EOR, fhd_eor, 0) },
{ FLDATA (DMA, fhd_dma, 0) },
{ FLDATA (CSUM, fhd_csum, 7) },
{ FLDATA (INTREQ, dev_int, INT_V_MT) },
{ FLDATA (ENABLE, dev_enb, INT_V_MT) },
{ DRDATA (TIME, fhd_time, 31), REG_NZ + PV_LEFT },
{ ORDATA (OTAS, fhd_otas, 2), REG_HRO },
{ ORDATA (CHAN, fhd_dib.chan, 5), REG_HRO },
{ FLDATA (STOP_IOE, fhd_stopioe, 0) },
{ NULL }
};
MTAB fhd_mod[] = {
{ UNIT_SF, (0 << UNIT_V_SF), NULL, "1S", &fhd_set_size },
{ UNIT_SF, (1 << UNIT_V_SF), NULL, "2S", &fhd_set_size },
{ UNIT_SF, (2 << UNIT_V_SF), NULL, "3S", &fhd_set_size },
{ UNIT_SF, (3 << UNIT_V_SF), NULL, "4S", &fhd_set_size },
{ UNIT_SF, (4 << UNIT_V_SF), NULL, "5S", &fhd_set_size },
{ UNIT_SF, (5 << UNIT_V_SF), NULL, "6S", &fhd_set_size },
{ UNIT_SF, (6 << UNIT_V_SF), NULL, "7S", &fhd_set_size },
{ UNIT_SF, (7 << UNIT_V_SF), NULL, "8S", &fhd_set_size },
{ UNIT_SF, (8 << UNIT_V_SF), NULL, "9S", &fhd_set_size },
{ UNIT_SF, (9 << UNIT_V_SF), NULL, "10S", &fhd_set_size },
{ UNIT_SF, (10 << UNIT_V_SF), NULL, "11S", &fhd_set_size },
{ UNIT_SF, (11 << UNIT_V_SF), NULL, "12S", &fhd_set_size },
{ UNIT_SF, (12 << UNIT_V_SF), NULL, "13S", &fhd_set_size },
{ UNIT_SF, (13 << UNIT_V_SF), NULL, "14S", &fhd_set_size },
{ UNIT_SF, (14 << UNIT_V_SF), NULL, "15S", &fhd_set_size },
{ UNIT_SF, (15 << UNIT_V_SF), NULL, "16S", &fhd_set_size },
{ UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "IOBUS",
&io_set_iobus, NULL, NULL },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "DMC",
&io_set_dmc, NULL, NULL },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "DMA",
&io_set_dma, NULL, NULL },
{ MTAB_XTD|MTAB_VDV, 0, "CHANNEL", NULL,
NULL, &io_show_chan, NULL },
{ 0 } };
{ UNIT_SF, (0 << UNIT_V_SF), NULL, "1S", &fhd_set_size },
{ UNIT_SF, (1 << UNIT_V_SF), NULL, "2S", &fhd_set_size },
{ UNIT_SF, (2 << UNIT_V_SF), NULL, "3S", &fhd_set_size },
{ UNIT_SF, (3 << UNIT_V_SF), NULL, "4S", &fhd_set_size },
{ UNIT_SF, (4 << UNIT_V_SF), NULL, "5S", &fhd_set_size },
{ UNIT_SF, (5 << UNIT_V_SF), NULL, "6S", &fhd_set_size },
{ UNIT_SF, (6 << UNIT_V_SF), NULL, "7S", &fhd_set_size },
{ UNIT_SF, (7 << UNIT_V_SF), NULL, "8S", &fhd_set_size },
{ UNIT_SF, (8 << UNIT_V_SF), NULL, "9S", &fhd_set_size },
{ UNIT_SF, (9 << UNIT_V_SF), NULL, "10S", &fhd_set_size },
{ UNIT_SF, (10 << UNIT_V_SF), NULL, "11S", &fhd_set_size },
{ UNIT_SF, (11 << UNIT_V_SF), NULL, "12S", &fhd_set_size },
{ UNIT_SF, (12 << UNIT_V_SF), NULL, "13S", &fhd_set_size },
{ UNIT_SF, (13 << UNIT_V_SF), NULL, "14S", &fhd_set_size },
{ UNIT_SF, (14 << UNIT_V_SF), NULL, "15S", &fhd_set_size },
{ UNIT_SF, (15 << UNIT_V_SF), NULL, "16S", &fhd_set_size },
{ UNIT_AUTO, UNIT_AUTO, "autosize", "AUTOSIZE", NULL },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "IOBUS",
&io_set_iobus, NULL, NULL },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "DMC",
&io_set_dmc, NULL, NULL },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "DMA",
&io_set_dma, NULL, NULL },
{ MTAB_XTD|MTAB_VDV, 0, "CHANNEL", NULL,
NULL, &io_show_chan, NULL },
{ 0 }
};
DEVICE fhd_dev = {
"FHD", &fhd_unit, fhd_reg, fhd_mod,
1, 8, 22, 1, 8, 16,
NULL, NULL, &fhd_reset,
NULL, &fhd_attach, NULL,
&fhd_dib, DEV_DISABLE };
"FHD", &fhd_unit, fhd_reg, fhd_mod,
1, 8, 22, 1, 8, 16,
NULL, NULL, &fhd_reset,
NULL, &fhd_attach, NULL,
&fhd_dib, DEV_DISABLE
};
/* IO routines */
int32 fhdio (int32 inst, int32 fnc, int32 dat, int32 dev)
{
switch (inst) { /* case on opcode */
case ioOCP: /* control */
if (fnc == 04) { /* terminate output? */
fhd_eor = 1; /* stop */
CLR_INT (INT_FHD); } /* clear int req */
else if (fnc == 003) fhd_go (1); /* start, DMA */
else if (fnc == 007) fhd_go (0); /* start, IO bus */
else return IOBADFNC (dat);
break;
case ioOTA: /* output */
if (fnc) return IOBADFNC (dat); /* only fnc 0 */
if (fhd_rdy) { /* ready? */
fhd_buf = dat; /* store data */
if (fhd_otas == OTA_CW1) fhd_go1 (dat); /* expecting CW1? */
else if (fhd_otas == OTA_CW2) fhd_go2 (dat);/* expecting CW2? */
else fhd_rdy = 0; /* normal, clr ready */
return IOSKIP (dat); }
break;
case ioINA: /* input */
if (fnc) return IOBADFNC (dat); /* only fnc 0 */
if (fhd_rdy) { /* ready? */
fhd_rdy = 0; /* clear ready */
return IOSKIP (dat | fhd_buf); } /* return data */
break;
case ioSKS: /* sense */
if (((fnc == 000) && fhd_rdy) || /* 0 = skip if ready */
((fnc == 001) && !fhd_busy) || /* 1 = skip if !busy */
((fnc == 002) && !fhd_dte) || /* 2 = skip if !data err */
((fnc == 003) && !fhd_ace) || /* 3 = skip if !access err */
((fnc == 004) && !TST_INTREQ (INT_FHD))) /* 4 = skip if !interrupt */
return IOSKIP (dat);
break;
case ioEND:
fhd_eor = 1;
break; }
switch (inst) { /* case on opcode */
case ioOCP: /* control */
if (fnc == 04) { /* terminate output? */
fhd_eor = 1; /* stop */
CLR_INT (INT_FHD); /* clear int req */
}
else if (fnc == 003) fhd_go (1); /* start, DMA */
else if (fnc == 007) fhd_go (0); /* start, IO bus */
else return IOBADFNC (dat);
break;
case ioOTA: /* output */
if (fnc) return IOBADFNC (dat); /* only fnc 0 */
if (fhd_rdy) { /* ready? */
fhd_buf = dat; /* store data */
if (fhd_otas == OTA_CW1) fhd_go1 (dat); /* expecting CW1? */
else if (fhd_otas == OTA_CW2) fhd_go2 (dat);/* expecting CW2? */
else fhd_rdy = 0; /* normal, clr ready */
return IOSKIP (dat);
}
break;
case ioINA: /* input */
if (fnc) return IOBADFNC (dat); /* only fnc 0 */
if (fhd_rdy) { /* ready? */
fhd_rdy = 0; /* clear ready */
return IOSKIP (dat | fhd_buf); /* return data */
}
break;
case ioSKS: /* sense */
if (((fnc == 000) && fhd_rdy) || /* 0 = skip if ready */
((fnc == 001) && !fhd_busy) || /* 1 = skip if !busy */
((fnc == 002) && !fhd_dte) || /* 2 = skip if !data err */
((fnc == 003) && !fhd_ace) || /* 3 = skip if !access err */
((fnc == 004) && !TST_INTREQ (INT_FHD))) /* 4 = skip if !interrupt */
return IOSKIP (dat);
break;
case ioEND:
fhd_eor = 1;
break;
}
return dat;
}
/* Start new operation */
void fhd_go (uint32 dma)
{
int32 ch = fhd_dib.chan - 1; /* DMA/DMC chan */
int32 ch = fhd_dib.chan - 1; /* DMA/DMC chan */
if (fhd_busy) return; /* ignore if busy */
fhd_busy = 1; /* ctlr is busy */
fhd_eor = 0; /* transfer not done */
fhd_csum = 0; /* init checksum */
fhd_dte = 0; /* clear errors */
if (fhd_busy) return; /* ignore if busy */
fhd_busy = 1; /* ctlr is busy */
fhd_eor = 0; /* transfer not done */
fhd_csum = 0; /* init checksum */
fhd_dte = 0; /* clear errors */
fhd_ace = 0;
if (ch >= 0) fhd_dma = dma; /* DMA allowed? */
else fhd_dma = 0; /* no, force IO bus */
fhd_otas = OTA_CW1; /* expect CW1 */
fhd_rdy = 1; /* set ready */
if (fhd_dma && Q_DMA (ch)) { /* DMA and DMA channel? */
SET_CH_REQ (ch); /* set channel request */
dma_ad[ch] = dma_ad[ch] & ~DMA_IN; } /* force output */
if (ch >= 0) fhd_dma = dma; /* DMA allowed? */
else fhd_dma = 0; /* no, force IO bus */
fhd_otas = OTA_CW1; /* expect CW1 */
fhd_rdy = 1; /* set ready */
if (fhd_dma && Q_DMA (ch)) { /* DMA and DMA channel? */
SET_CH_REQ (ch); /* set channel request */
dma_ad[ch] = dma_ad[ch] & ~DMA_IN; /* force output */
}
return;
}
@@ -239,12 +254,12 @@ return;
void fhd_go1 (uint32 dat)
{
int32 ch = fhd_dib.chan - 1; /* DMA/DMC chan */
int32 ch = fhd_dib.chan - 1; /* DMA/DMC chan */
fhd_cw1 = dat; /* store CW1 */
fhd_otas = OTA_CW2; /* expect CW2 */
fhd_rdy = 1; /* set ready */
if (fhd_dma && Q_DMA (ch)) SET_CH_REQ (ch); /* DMA? set chan request */
fhd_cw1 = dat; /* store CW1 */
fhd_otas = OTA_CW2; /* expect CW2 */
fhd_rdy = 1; /* set ready */
if (fhd_dma && Q_DMA (ch)) SET_CH_REQ (ch); /* DMA? set chan request */
return;
}
@@ -252,89 +267,101 @@ return;
void fhd_go2 (uint32 dat)
{
int32 ch = fhd_dib.chan - 1; /* DMA/DMC chan */
uint32 sf = CW1_GETSF (fhd_cw1); /* surface */
int32 ch = fhd_dib.chan - 1; /* DMA/DMC chan */
uint32 sf = CW1_GETSF (fhd_cw1); /* surface */
int32 t, wa;
fhd_cw2 = dat; /* store CW2 */
fhd_otas = OTA_NOP; /* next state */
wa = CW2_GETCA (fhd_cw2) >> 1; /* word addr */
if ((wa >= FH_NUMWD) || /* if bad char addr */
((fhd_unit.flags & UNIT_ATT) == 0) || /* or unattached */
(sf >= UNIT_GETSF (fhd_unit.flags))) { /* or bad surface */
fhd_ace = 1; /* access error */
fhd_busy = 0; /* abort operation */
SET_INT (INT_FHD);
return; }
if (fhd_cw1 & CW1_RW) { /* write? */
fhd_rdy = 1; /* set ready */
if (fhd_dma) SET_CH_REQ (ch); } /* if DMA/DMC, req chan */
else { fhd_rdy = 0; /* read, clear ready */
if (fhd_dma && (ch < DMC_V_DMC1)) /* read and DMA chan? */
dma_ad[ch] = dma_ad[ch] | DMA_IN; } /* force input */
t = wa - GET_POS (fhd_time); /* delta to new loc */
if (t < 0) t = t + FH_NUMWD; /* wrap around? */
sim_activate (&fhd_unit, t * fhd_time); /* schedule op */
fhd_cw2 = dat; /* store CW2 */
fhd_otas = OTA_NOP; /* next state */
wa = CW2_GETCA (fhd_cw2) >> 1; /* word addr */
if ((wa >= FH_NUMWD) || /* if bad char addr */
((fhd_unit.flags & UNIT_ATT) == 0) || /* or unattached */
(sf >= UNIT_GETSF (fhd_unit.flags))) { /* or bad surface */
fhd_ace = 1; /* access error */
fhd_busy = 0; /* abort operation */
SET_INT (INT_FHD);
return;
}
if (fhd_cw1 & CW1_RW) { /* write? */
fhd_rdy = 1; /* set ready */
if (fhd_dma) SET_CH_REQ (ch); /* if DMA/DMC, req chan */
}
else {
fhd_rdy = 0; /* read, clear ready */
if (fhd_dma && (ch < DMC_V_DMC1)) /* read and DMA chan? */
dma_ad[ch] = dma_ad[ch] | DMA_IN; /* force input */
}
t = wa - GET_POS (fhd_time); /* delta to new loc */
if (t < 0) t = t + FH_NUMWD; /* wrap around? */
sim_activate (&fhd_unit, t * fhd_time); /* schedule op */
return;
}
/* Unit service */
t_stat fhd_svc (UNIT *uptr)
{
int32 ch = fhd_dib.chan - 1; /* DMA/DMC chan (-1 if IO bus) */
int32 ch = fhd_dib.chan - 1; /* DMA/DMC chan (-1 if IO bus) */
uint32 c1, c2;
if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */
fhd_ace = 1; /* access error */
fhd_busy = 0; /* abort operation */
SET_INT (INT_FHD);
return IORETURN (fhd_stopioe, SCPE_UNATT); }
if ((uptr->flags & UNIT_ATT) == 0) { /* unattached? */
fhd_ace = 1; /* access error */
fhd_busy = 0; /* abort operation */
SET_INT (INT_FHD);
return IORETURN (fhd_stopioe, SCPE_UNATT);
}
if (fhd_eor || fhd_rdy) { /* done or ready set? */
if (fhd_rdy) fhd_dte = 1; /* if ready set, data err */
if (fhd_cw1 & CW1_RW) { /* write? */
if (!fhd_rdy) { /* buffer full? */
fhd_putc (uptr, fhd_buf >> 8); /* store last word */
fhd_putc (uptr, fhd_buf); }
fhd_putc (uptr, fhd_csum); } /* store csum */
else { /* read */
fhd_getc (uptr, &c1); /* get csum */
if (fhd_csum) fhd_dte = 1; } /* if csum != 0, err */
fhd_busy = 0; /* operation complete */
SET_INT (INT_FHD);
return SCPE_OK; }
if (fhd_eor || fhd_rdy) { /* done or ready set? */
if (fhd_rdy) fhd_dte = 1; /* if ready set, data err */
if (fhd_cw1 & CW1_RW) { /* write? */
if (!fhd_rdy) { /* buffer full? */
fhd_putc (uptr, fhd_buf >> 8); /* store last word */
fhd_putc (uptr, fhd_buf);
}
fhd_putc (uptr, fhd_csum); /* store csum */
}
else { /* read */
fhd_getc (uptr, &c1); /* get csum */
if (fhd_csum) fhd_dte = 1; /* if csum != 0, err */
}
fhd_busy = 0; /* operation complete */
SET_INT (INT_FHD);
return SCPE_OK;
}
if (fhd_cw1 & CW1_RW) { /* write? */
if (fhd_putc (uptr, fhd_buf >> 8)) return SCPE_OK;
if (fhd_putc (uptr, fhd_buf)) return SCPE_OK; }
else { if (fhd_getc (uptr, &c1)) return SCPE_OK; /* read */
if (fhd_getc (uptr, &c2)) return SCPE_OK;
fhd_buf = (c1 << 8) | c2; }
sim_activate (uptr, fhd_time); /* next word */
fhd_rdy = 1; /* set ready */
if (fhd_dma) SET_CH_REQ (ch); /* if DMA/DMC, req chan */
if (fhd_cw1 & CW1_RW) { /* write? */
if (fhd_putc (uptr, fhd_buf >> 8)) return SCPE_OK;
if (fhd_putc (uptr, fhd_buf)) return SCPE_OK;
}
else {
if (fhd_getc (uptr, &c1)) return SCPE_OK; /* read */
if (fhd_getc (uptr, &c2)) return SCPE_OK;
fhd_buf = (c1 << 8) | c2;
}
sim_activate (uptr, fhd_time); /* next word */
fhd_rdy = 1; /* set ready */
if (fhd_dma) SET_CH_REQ (ch); /* if DMA/DMC, req chan */
return SCPE_OK;
}
/* Read character from disk */
t_bool fhd_getc (UNIT *uptr, uint32 *ch)
{
uint32 sf = CW1_GETSF (fhd_cw1); /* surface */
uint32 tk = CW1_GETTK (fhd_cw1); /* track */
uint32 ca = CW2_GETCA (fhd_cw2); /* char addr */
uint32 wa = ca >> 1; /* word addr */
uint32 ba = (((sf * FH_NUMTK) + tk) * FH_NUMWD) + wa; /* buffer offset */
uint16 *fbuf = uptr->filebuf; /* buffer base */
uint32 sf = CW1_GETSF (fhd_cw1); /* surface */
uint32 tk = CW1_GETTK (fhd_cw1); /* track */
uint32 ca = CW2_GETCA (fhd_cw2); /* char addr */
uint32 wa = ca >> 1; /* word addr */
uint32 ba = (((sf * FH_NUMTK) + tk) * FH_NUMWD) + wa; /* buffer offset */
uint16 *fbuf = uptr->filebuf; /* buffer base */
uint32 wd;
if (fhd_bad_wa (wa)) return TRUE; /* addr bad? */
fhd_cw2 = fhd_cw2 + 1; /* incr char addr */
if (ca & 1) wd = fbuf[ba] & 0377; /* select char */
if (fhd_bad_wa (wa)) return TRUE; /* addr bad? */
fhd_cw2 = fhd_cw2 + 1; /* incr char addr */
if (ca & 1) wd = fbuf[ba] & 0377; /* select char */
else wd = (fbuf[ba] >> 8) & 0377;
fhd_csum = fhd_csword (fhd_csum, wd); /* put in csum */
*ch = wd; /* return */
fhd_csum = fhd_csword (fhd_csum, wd); /* put in csum */
*ch = wd; /* return */
return FALSE;
}
@@ -342,20 +369,20 @@ return FALSE;
t_bool fhd_putc (UNIT *uptr, uint32 ch)
{
uint32 sf = CW1_GETSF (fhd_cw1); /* surface */
uint32 tk = CW1_GETTK (fhd_cw1); /* track */
uint32 ca = CW2_GETCA (fhd_cw2); /* char addr */
uint32 wa = ca >> 1; /* word addr */
uint32 ba = (((sf * FH_NUMTK) + tk) * FH_NUMWD) + wa; /* buffer offset */
uint16 *fbuf = uptr->filebuf; /* buffer base */
uint32 sf = CW1_GETSF (fhd_cw1); /* surface */
uint32 tk = CW1_GETTK (fhd_cw1); /* track */
uint32 ca = CW2_GETCA (fhd_cw2); /* char addr */
uint32 wa = ca >> 1; /* word addr */
uint32 ba = (((sf * FH_NUMTK) + tk) * FH_NUMWD) + wa; /* buffer offset */
uint16 *fbuf = uptr->filebuf; /* buffer base */
ch = ch & 0377; /* mask char */
if (fhd_bad_wa (wa)) return TRUE; /* addr bad? */
fhd_cw2 = fhd_cw2 + 1; /* incr char addr */
if (ca & 1) fbuf[ba] = (fbuf[ba] & ~0377) | ch; /* odd? low char */
else fbuf[ba] = (fbuf[ba] & 0377) | (ch << 8); /* even, hi char */
fhd_csum = fhd_csword (fhd_csum, ch); /* put in csum */
if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; /* update hwmark */
ch = ch & 0377; /* mask char */
if (fhd_bad_wa (wa)) return TRUE; /* addr bad? */
fhd_cw2 = fhd_cw2 + 1; /* incr char addr */
if (ca & 1) fbuf[ba] = (fbuf[ba] & ~0377) | ch; /* odd? low char */
else fbuf[ba] = (fbuf[ba] & 0377) | (ch << 8); /* even, hi char */
fhd_csum = fhd_csword (fhd_csum, ch); /* put in csum */
if (ba >= uptr->hwmark) uptr->hwmark = ba + 1; /* update hwmark */
return FALSE;
}
@@ -363,11 +390,12 @@ return FALSE;
t_bool fhd_bad_wa (uint32 wa)
{
if (wa >= FH_NUMWD) { /* bad address? */
fhd_ace = 1; /* access error */
fhd_busy = 0; /* abort operation */
SET_INT (INT_FHD);
return TRUE; }
if (wa >= FH_NUMWD) { /* bad address? */
fhd_ace = 1; /* access error */
fhd_busy = 0; /* abort operation */
SET_INT (INT_FHD);
return TRUE;
}
return FALSE;
}
@@ -375,26 +403,27 @@ return FALSE;
uint32 fhd_csword (uint32 cs, uint32 ch)
{
while (ch) { /* count bits */
ch = ch & ~(ch & (-(int32) ch));
cs = cs ^ 0200; } /* invert cs for each 1 */
while (ch) { /* count bits */
ch = ch & ~(ch & (-(int32) ch));
cs = cs ^ 0200; /* invert cs for each 1 */
}
return cs;
}
/* Reset routine */
t_stat fhd_reset (DEVICE *dptr)
{
fhd_busy = 0; /* reset state */
fhd_busy = 0; /* reset state */
fhd_rdy = 0;
fhd_ace = 0;
fhd_dte = 0;
fhd_eor = 0;
fhd_otas = OTA_NOP;
fhd_cw1 = fhd_cw2 = fhd_buf = 0;
CLR_INT (INT_FHD); /* clear int, enb */
CLR_INT (INT_FHD); /* clear int, enb */
CLR_ENB (INT_FHD);
sim_cancel (&fhd_unit); /* cancel operation */
sim_cancel (&fhd_unit); /* cancel operation */
return SCPE_OK;
}
@@ -409,10 +438,11 @@ t_stat r;
r = attach_unit (uptr, cptr);
if (r != SCPE_OK) return r;
if ((uptr->flags & UNIT_AUTO) && (sz = sim_fsize (uptr->fileref))) {
sf = (sz + ds_bytes - 1) / ds_bytes;
if (sf >= FH_NUMSF) sf = FH_NUMSF - 1;
uptr->flags = (uptr->flags & ~UNIT_SF) |
(sf << UNIT_V_SF); }
sf = (sz + ds_bytes - 1) / ds_bytes;
if (sf >= FH_NUMSF) sf = FH_NUMSF - 1;
uptr->flags = (uptr->flags & ~UNIT_SF) |
(sf << UNIT_V_SF);
}
uptr->capac = UNIT_GETSF (uptr->flags) * FH_WDPSF;
return SCPE_OK;
}

View File

@@ -1,6 +1,6 @@
/* h316_lp.c: Honeywell 316/516 line printer
Copyright (c) 1999-2004, Robert M. Supnik
Copyright (c) 1999-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,16 +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.
lpt line printer
lpt line printer
01-Dec-04 RMS Fixed bug in DMA/DMC support
24-Oct-03 RMS Added DMA/DMC support
25-Apr-03 RMS Revised for extended file support
30-May-02 RMS Widened POS to 32b
01-Dec-04 RMS Fixed bug in DMA/DMC support
24-Oct-03 RMS Added DMA/DMC support
25-Apr-03 RMS Revised for extended file support
30-May-02 RMS Widened POS to 32b
The Series 16 line printer is an unbuffered Analex shuttle printer.
Because it was unbuffered, the CPU had to scan out an entire line's
@@ -52,54 +52,54 @@
Printer state is maintained in a set of position and state variables:
lpt_wdpos word count within a line scan (0-59)
lpt_drpos drum position (0-63)
lpt_crpos carriage position (0-1)
lpt_svcst service state (shuttle, paper advance)
lpt_svcch channel for paper advance (0 = no adv)
lpt_rdy transfer ready flag
lpt_prdn printing done flag
lpt_dma use DMA/DMC
lpt_eor DMA/DMC end of range
lpt_wdpos word count within a line scan (0-59)
lpt_drpos drum position (0-63)
lpt_crpos carriage position (0-1)
lpt_svcst service state (shuttle, paper advance)
lpt_svcch channel for paper advance (0 = no adv)
lpt_rdy transfer ready flag
lpt_prdn printing done flag
lpt_dma use DMA/DMC
lpt_eor DMA/DMC end of range
*/
#include "h316_defs.h"
#define LPT_WIDTH 120 /* width */
#define LPT_SCAN (LPT_WIDTH / 2) /* words/scan */
#define LPT_DRUM 64 /* drum rows */
#define LPT_SVCSH 01 /* shuttle */
#define LPT_SVCPA 02 /* paper advance */
#define LPT_WIDTH 120 /* width */
#define LPT_SCAN (LPT_WIDTH / 2) /* words/scan */
#define LPT_DRUM 64 /* drum rows */
#define LPT_SVCSH 01 /* shuttle */
#define LPT_SVCPA 02 /* paper advance */
extern int32 dev_int, dev_enb;
extern int32 stop_inst;
extern uint32 chan_req;
int32 lpt_wdpos = 0; /* word position */
int32 lpt_drpos = 0; /* drum position */
int32 lpt_crpos = 0; /* carriage position */
int32 lpt_svcst = 0; /* service state */
int32 lpt_svcch = 0; /* service channel */
int32 lpt_rdy = 0; /* transfer flag */
int32 lpt_prdn = 1; /* printing done */
int32 lpt_dma = 0; /* use DMA/DMC */
int32 lpt_eor = 0; /* DMA/DMC end range */
char lpt_buf[LPT_WIDTH + 1] = { 0 }; /* line buffer */
int32 lpt_xtime = 5; /* transfer time */
int32 lpt_etime = 50; /* end of scan time */
int32 lpt_ptime = 5000; /* paper adv time */
int32 lpt_stopioe = 0; /* stop on error */
int32 lpt_wdpos = 0; /* word position */
int32 lpt_drpos = 0; /* drum position */
int32 lpt_crpos = 0; /* carriage position */
int32 lpt_svcst = 0; /* service state */
int32 lpt_svcch = 0; /* service channel */
int32 lpt_rdy = 0; /* transfer flag */
int32 lpt_prdn = 1; /* printing done */
int32 lpt_dma = 0; /* use DMA/DMC */
int32 lpt_eor = 0; /* DMA/DMC end range */
char lpt_buf[LPT_WIDTH + 1] = { 0 }; /* line buffer */
int32 lpt_xtime = 5; /* transfer time */
int32 lpt_etime = 50; /* end of scan time */
int32 lpt_ptime = 5000; /* paper adv time */
int32 lpt_stopioe = 0; /* stop on error */
int32 lptio (int32 inst, int32 fnc, int32 dat, int32 dev);
t_stat lpt_svc (UNIT *uptr);
t_stat lpt_reset (DEVICE *dptr);
/* LPT data structures
lpt_dev LPT device descriptor
lpt_unit LPT unit descriptor
lpt_mod LPT modifiers
lpt_reg LPT register list
lpt_dev LPT device descriptor
lpt_unit LPT unit descriptor
lpt_mod LPT modifiers
lpt_reg LPT register list
*/
DIB lpt_dib = { LPT, IOBUS, 1, &lptio };
@@ -107,138 +107,164 @@ DIB lpt_dib = { LPT, IOBUS, 1, &lptio };
UNIT lpt_unit = { UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE, 0) };
REG lpt_reg[] = {
{ DRDATA (WDPOS, lpt_wdpos, 6) },
{ DRDATA (DRPOS, lpt_drpos, 6) },
{ FLDATA (CRPOS, lpt_crpos, 0) },
{ FLDATA (RDY, lpt_rdy, 0) },
{ FLDATA (EOR, lpt_eor, 0) },
{ FLDATA (DMA, lpt_dma, 0) },
{ FLDATA (PRDN, lpt_prdn, 0) },
{ FLDATA (INTREQ, dev_int, INT_V_LPT) },
{ FLDATA (ENABLE, dev_enb, INT_V_LPT) },
{ ORDATA (SVCST, lpt_svcst, 2) },
{ ORDATA (SVCCH, lpt_svcch, 2) },
{ BRDATA (BUF, lpt_buf, 8, 8, 120) },
{ DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (XTIME, lpt_xtime, 24), PV_LEFT },
{ DRDATA (ETIME, lpt_etime, 24), PV_LEFT },
{ DRDATA (PTIME, lpt_ptime, 24), PV_LEFT },
{ FLDATA (STOP_IOE, lpt_stopioe, 0) },
{ NULL } };
{ DRDATA (WDPOS, lpt_wdpos, 6) },
{ DRDATA (DRPOS, lpt_drpos, 6) },
{ FLDATA (CRPOS, lpt_crpos, 0) },
{ FLDATA (RDY, lpt_rdy, 0) },
{ FLDATA (EOR, lpt_eor, 0) },
{ FLDATA (DMA, lpt_dma, 0) },
{ FLDATA (PRDN, lpt_prdn, 0) },
{ FLDATA (INTREQ, dev_int, INT_V_LPT) },
{ FLDATA (ENABLE, dev_enb, INT_V_LPT) },
{ ORDATA (SVCST, lpt_svcst, 2) },
{ ORDATA (SVCCH, lpt_svcch, 2) },
{ BRDATA (BUF, lpt_buf, 8, 8, 120) },
{ DRDATA (POS, lpt_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (XTIME, lpt_xtime, 24), PV_LEFT },
{ DRDATA (ETIME, lpt_etime, 24), PV_LEFT },
{ DRDATA (PTIME, lpt_ptime, 24), PV_LEFT },
{ FLDATA (STOP_IOE, lpt_stopioe, 0) },
{ NULL }
};
DEVICE lpt_dev = {
"LPT", &lpt_unit, lpt_reg, NULL,
1, 10, 31, 1, 8, 8,
NULL, NULL, &lpt_reset,
NULL, NULL, NULL,
&lpt_dib, DEV_DISABLE };
"LPT", &lpt_unit, lpt_reg, NULL,
1, 10, 31, 1, 8, 8,
NULL, NULL, &lpt_reset,
NULL, NULL, NULL,
&lpt_dib, DEV_DISABLE
};
/* IO routine */
int32 lptio (int32 inst, int32 fnc, int32 dat, int32 dev)
{
int32 ch = lpt_dib.chan - 1; /* DMA/DMC chan */
int32 ch = lpt_dib.chan - 1; /* DMA/DMC chan */
int32 chr;
switch (inst) { /* case on opcode */
case ioOCP: /* OCP */
switch (fnc) { /* case on fnc */
case 000: case 002: case 004: /* paper adv */
lpt_svcst = lpt_svcst | LPT_SVCPA; /* set state */
lpt_svcch = fnc >> 1; /* save channel */
sim_activate (&lpt_unit, lpt_ptime);
CLR_INT (INT_LPT); /* clear int */
break;
case 003: /* init scan DMA/DMC */
lpt_prdn = 0; /* clear pr done */
lpt_wdpos = 0; /* init scan pos */
lpt_eor = 0;
if (ch >= 0) lpt_dma = 1; /* try for DMA/DMC */
else lpt_dma = 0;
if (!sim_is_active (&lpt_unit)) {
lpt_rdy = 1;
if (lpt_dma) SET_CH_REQ (ch); }
CLR_INT (INT_LPT); /* clear int */
break;
case 007: /* init scan IO bus */
lpt_prdn = 0; /* clear pr done */
lpt_wdpos = 0; /* init scan pos */
lpt_eor = 0;
lpt_dma = 0; /* IO bus */
if (!sim_is_active (&lpt_unit)) lpt_rdy = 1;
CLR_INT (INT_LPT); /* clear int */
break;
default:
return IOBADFNC (dat); }
break;
switch (inst) { /* case on opcode */
case ioSKS: /* SKS */
switch (fnc) { /* case on fnc */
case 000: /* if xfer rdy */
if (lpt_rdy) return IOSKIP (dat);
break;
case 002: /* if !alarm */
if (lpt_unit.flags & UNIT_ATT) return IOSKIP (dat);
break;
case 003: /* if odd col */
if (lpt_crpos) return IOSKIP (dat);
break;
case 004: /* if !interrupt */
if (!TST_INTREQ (INT_LPT)) return IOSKIP (dat);
break;
case 011: /* if line printed */
if (lpt_prdn) return IOSKIP (dat);
break;
case 012: /* if !shuttling */
if (!(lpt_svcst & LPT_SVCSH)) return IOSKIP (dat);
break;
case 013:
if (lpt_prdn && !(lpt_svcst & LPT_SVCSH)) return IOSKIP (dat);
break;
case 014: /* if !advancing */
if (!(lpt_svcst & LPT_SVCPA)) return IOSKIP (dat);
break;
case 015:
if (lpt_prdn && !(lpt_svcst & LPT_SVCPA)) return IOSKIP (dat);
break;
case 016:
if (!(lpt_svcst & (LPT_SVCSH | LPT_SVCPA))) return IOSKIP (dat);
break;
case 017:
if (lpt_prdn && !(lpt_svcst & (LPT_SVCSH | LPT_SVCPA)))
return IOSKIP (dat);
break;
default:
return IOBADFNC (dat); }
break;
case ioOCP: /* OCP */
switch (fnc) { /* case on fnc */
case ioOTA: /* OTA */
if (fnc) return IOBADFNC (dat); /* only fnc 0 */
if (lpt_rdy) { /* xfer ready? */
lpt_rdy = 0; /* clear xfer */
chr = (dat >> (lpt_crpos? 0: 8)) & 077; /* get 6b char */
if (chr == lpt_drpos) { /* match drum pos? */
if (chr < 040) chr = chr | 0100;
lpt_buf[2 * lpt_wdpos + lpt_crpos] = chr; }
lpt_wdpos++; /* adv scan pos */
if (lpt_wdpos >= LPT_SCAN) { /* end of scan? */
lpt_wdpos = 0; /* reset scan pos */
lpt_drpos++; /* adv drum pos */
if (lpt_drpos >= LPT_DRUM) { /* end of drum? */
lpt_drpos = 0; /* reset drum pos */
lpt_crpos = lpt_crpos ^ 1; /* shuttle */
lpt_svcst = lpt_svcst | LPT_SVCSH;
sim_activate (&lpt_unit, lpt_ptime);
} /* end if shuttle */
else sim_activate (&lpt_unit, lpt_etime);
} /* end if endscan */
else sim_activate (&lpt_unit, lpt_xtime);
return IOSKIP (dat); } /* skip return */
break;
case 000: case 002: case 004: /* paper adv */
lpt_svcst = lpt_svcst | LPT_SVCPA; /* set state */
lpt_svcch = fnc >> 1; /* save channel */
sim_activate (&lpt_unit, lpt_ptime);
CLR_INT (INT_LPT); /* clear int */
break;
case 003: /* init scan DMA/DMC */
lpt_prdn = 0; /* clear pr done */
lpt_wdpos = 0; /* init scan pos */
lpt_eor = 0;
if (ch >= 0) lpt_dma = 1; /* try for DMA/DMC */
else lpt_dma = 0;
if (!sim_is_active (&lpt_unit)) {
lpt_rdy = 1;
if (lpt_dma) SET_CH_REQ (ch);
}
CLR_INT (INT_LPT); /* clear int */
break;
case 007: /* init scan IO bus */
lpt_prdn = 0; /* clear pr done */
lpt_wdpos = 0; /* init scan pos */
lpt_eor = 0;
lpt_dma = 0; /* IO bus */
if (!sim_is_active (&lpt_unit)) lpt_rdy = 1;
CLR_INT (INT_LPT); /* clear int */
break;
default:
return IOBADFNC (dat);
}
break;
case ioSKS: /* SKS */
switch (fnc) { /* case on fnc */
case 000: /* if xfer rdy */
if (lpt_rdy) return IOSKIP (dat);
break;
case 002: /* if !alarm */
if (lpt_unit.flags & UNIT_ATT) return IOSKIP (dat);
break;
case 003: /* if odd col */
if (lpt_crpos) return IOSKIP (dat);
break;
case 004: /* if !interrupt */
if (!TST_INTREQ (INT_LPT)) return IOSKIP (dat);
break;
case 011: /* if line printed */
if (lpt_prdn) return IOSKIP (dat);
break;
case 012: /* if !shuttling */
if (!(lpt_svcst & LPT_SVCSH)) return IOSKIP (dat);
break;
case 013:
if (lpt_prdn && !(lpt_svcst & LPT_SVCSH)) return IOSKIP (dat);
break;
case 014: /* if !advancing */
if (!(lpt_svcst & LPT_SVCPA)) return IOSKIP (dat);
break;
case 015:
if (lpt_prdn && !(lpt_svcst & LPT_SVCPA)) return IOSKIP (dat);
break;
case 016:
if (!(lpt_svcst & (LPT_SVCSH | LPT_SVCPA))) return IOSKIP (dat);
break;
case 017:
if (lpt_prdn && !(lpt_svcst & (LPT_SVCSH | LPT_SVCPA)))
return IOSKIP (dat);
break;
default:
return IOBADFNC (dat);
}
break;
case ioOTA: /* OTA */
if (fnc) return IOBADFNC (dat); /* only fnc 0 */
if (lpt_rdy) { /* xfer ready? */
lpt_rdy = 0; /* clear xfer */
chr = (dat >> (lpt_crpos? 0: 8)) & 077; /* get 6b char */
if (chr == lpt_drpos) { /* match drum pos? */
if (chr < 040) chr = chr | 0100;
lpt_buf[2 * lpt_wdpos + lpt_crpos] = chr;
}
lpt_wdpos++; /* adv scan pos */
if (lpt_wdpos >= LPT_SCAN) { /* end of scan? */
lpt_wdpos = 0; /* reset scan pos */
lpt_drpos++; /* adv drum pos */
if (lpt_drpos >= LPT_DRUM) { /* end of drum? */
lpt_drpos = 0; /* reset drum pos */
lpt_crpos = lpt_crpos ^ 1; /* shuttle */
lpt_svcst = lpt_svcst | LPT_SVCSH;
sim_activate (&lpt_unit, lpt_ptime);
} /* end if shuttle */
else sim_activate (&lpt_unit, lpt_etime);
} /* end if endscan */
else sim_activate (&lpt_unit, lpt_xtime);
return IOSKIP (dat); /* skip return */
}
break;
case ioEND: /* end DMA/DMC */
lpt_eor = 1; /* set end range */
break;
} /* end case op */
case ioEND: /* end DMA/DMC */
lpt_eor = 1; /* set end range */
break; } /* end case op */
return dat;
}
@@ -247,35 +273,40 @@ return dat;
t_stat lpt_svc (UNIT *uptr)
{
int32 i;
int32 ch = lpt_dib.chan - 1; /* DMA/DMC chan */
int32 ch = lpt_dib.chan - 1; /* DMA/DMC chan */
static const char *lpt_cc[] = {
"\r",
"\n",
"\n\f",
"\n" };
"\r",
"\n",
"\n\f",
"\n"
};
if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */
return IORETURN (lpt_stopioe, SCPE_UNATT);
if (lpt_dma) { /* DMA/DMC? */
if (lpt_eor) SET_INT (INT_LPT); /* end range? intr */
else {
lpt_rdy = 1; /* set ready */
SET_CH_REQ (ch); } } /* get more data */
else lpt_rdy = 1; /* IO, continue scan */
if (lpt_dma && lpt_eor) SET_INT (INT_LPT); /* end of range? */
if (lpt_svcst & LPT_SVCSH) { /* shuttling */
SET_INT (INT_LPT); /* interrupt */
if (lpt_crpos == 0) lpt_prdn = 1; }
if (lpt_svcst & LPT_SVCPA) { /* paper advance */
SET_INT (INT_LPT); /* interrupt */
for (i = LPT_WIDTH - 1; i >= 0; i++) {
if (lpt_buf[i] != ' ') break; }
lpt_buf[i + 1] = 0;
fputs (lpt_buf, uptr->fileref); /* output buf */
fputs (lpt_cc[lpt_svcch & 03], uptr->fileref); /* output eol */
uptr->pos = ftell (uptr->fileref); /* update pos */
for (i = 0; i < LPT_WIDTH; i++) lpt_buf[i] = ' '; /* clear buf */
}
if ((lpt_unit.flags & UNIT_ATT) == 0) /* attached? */
return IORETURN (lpt_stopioe, SCPE_UNATT);
if (lpt_dma) { /* DMA/DMC? */
if (lpt_eor) SET_INT (INT_LPT); /* end range? intr */
else {
lpt_rdy = 1; /* set ready */
SET_CH_REQ (ch); /* get more data */
}
}
else lpt_rdy = 1; /* IO, continue scan */
if (lpt_dma && lpt_eor) SET_INT (INT_LPT); /* end of range? */
if (lpt_svcst & LPT_SVCSH) { /* shuttling */
SET_INT (INT_LPT); /* interrupt */
if (lpt_crpos == 0) lpt_prdn = 1;
}
if (lpt_svcst & LPT_SVCPA) { /* paper advance */
SET_INT (INT_LPT); /* interrupt */
for (i = LPT_WIDTH - 1; i >= 0; i++) {
if (lpt_buf[i] != ' ') break;
}
lpt_buf[i + 1] = 0;
fputs (lpt_buf, uptr->fileref); /* output buf */
fputs (lpt_cc[lpt_svcch & 03], uptr->fileref); /* output eol */
uptr->pos = ftell (uptr->fileref); /* update pos */
for (i = 0; i < LPT_WIDTH; i++) lpt_buf[i] = ' '; /* clear buf */
}
lpt_svcst = 0;
return SCPE_OK;
}
@@ -286,16 +317,16 @@ t_stat lpt_reset (DEVICE *dptr)
{
int32 i;
lpt_wdpos = lpt_drpos = lpt_crpos = 0; /* clear positions */
lpt_svcst = lpt_svcch = 0; /* idle state */
lpt_rdy = 0; /* not rdy to xfer */
lpt_prdn = 1; /* printing done */
lpt_wdpos = lpt_drpos = lpt_crpos = 0; /* clear positions */
lpt_svcst = lpt_svcch = 0; /* idle state */
lpt_rdy = 0; /* not rdy to xfer */
lpt_prdn = 1; /* printing done */
lpt_eor = 0;
lpt_dma = 0;
for (i = 0; i < LPT_WIDTH; i++) lpt_buf[i] = ' '; /* clear buffer */
for (i = 0; i < LPT_WIDTH; i++) lpt_buf[i] = ' '; /* clear buffer */
lpt_buf[LPT_WIDTH] = 0;
CLR_INT (INT_LPT); /* clear int, enb */
CLR_INT (INT_LPT); /* clear int, enb */
CLR_ENB (INT_LPT);
sim_cancel (&lpt_unit); /* deactivate unit */
sim_cancel (&lpt_unit); /* deactivate unit */
return SCPE_OK;
}

View File

@@ -19,25 +19,26 @@
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 516-4100 seven track magnetic tape
mt 516-4100 seven track magnetic tape
08-Feb-05 RMS Fixed error reporting from OCP (found by Philipp Hachtmann)
01-Dec-04 RMS Fixed bug in DMA/DMC support
26-Aug-05 RMS Revised to use API for write lock check
08-Feb-05 RMS Fixed error reporting from OCP (found by Philipp Hachtmann)
01-Dec-04 RMS Fixed bug in DMA/DMC support
Magnetic tapes are represented as a series of variable records
of the form:
32b byte count
byte 0
byte 1
:
byte n-2
byte n-1
32b byte count
32b byte count
byte 0
byte 1
:
byte n-2
byte n-1
32b byte count
If the byte count is odd, the record is padded with an extra byte
of junk. File marks are represented by a byte count of 0.
@@ -46,57 +47,56 @@
#include "h316_defs.h"
#include "sim_tape.h"
#define MT_NUMDR 4 /* number of drives */
#define DB_N_SIZE 16 /* max data buf */
#define DBSIZE (1 << DB_N_SIZE) /* max data cmd */
#define FNC u3 /* function */
#define UST u4 /* unit status */
#define UNIT_WPRT (MTUF_WLK | UNIT_RO) /* write prot */
#define MT_NUMDR 4 /* number of drives */
#define DB_N_SIZE 16 /* max data buf */
#define DBSIZE (1 << DB_N_SIZE) /* max data cmd */
#define FNC u3 /* function */
#define UST u4 /* unit status */
/* Function codes */
#define FNC_RBCD2 000
#define FNC_RBIN2 001
#define FNC_RBIN3 002
#define FNC_DMANM 003
#define FNC_WBCD2 004
#define FNC_WBIN2 005
#define FNC_WEOF 006
#define FNC_IOBUS 007
#define FNC_WBIN3 010
#define FNC_FSR 011
#define FNC_FSF 012
#define FNC_DMAAU 013
#define FNC_REW 014
#define FNC_BSR 015
#define FNC_BSF 016
#define FNC_STOPW 017
#define FNC_2ND 020 /* second state */
#define FNC_NOP (FNC_STOPW|FNC_2ND)
#define FNC_EOM 040 /* end of motion */
#define FNC_RBCD2 000
#define FNC_RBIN2 001
#define FNC_RBIN3 002
#define FNC_DMANM 003
#define FNC_WBCD2 004
#define FNC_WBIN2 005
#define FNC_WEOF 006
#define FNC_IOBUS 007
#define FNC_WBIN3 010
#define FNC_FSR 011
#define FNC_FSF 012
#define FNC_DMAAU 013
#define FNC_REW 014
#define FNC_BSR 015
#define FNC_BSF 016
#define FNC_STOPW 017
#define FNC_2ND 020 /* second state */
#define FNC_NOP (FNC_STOPW|FNC_2ND)
#define FNC_EOM 040 /* end of motion */
/* Status - unit.UST */
#define STA_BOT 0000002 /* beg of tape */
#define STA_EOT 0000001 /* end of tape */
#define STA_BOT 0000002 /* beg of tape */
#define STA_EOT 0000001 /* end of tape */
extern int32 dev_int, dev_enb, chan_req;
extern int32 stop_inst;
uint32 mt_buf = 0; /* data buffer */
uint32 mt_usel = 0; /* unit select */
uint32 mt_busy = 0; /* ctlr busy */
uint32 mt_mdirq = 0; /* motion done int req */
uint32 mt_rdy = 0; /* transfer ready (int) */
uint32 mt_err = 0; /* error */
uint32 mt_eof = 0; /* end of file */
uint32 mt_eor = 0; /* transfer done */
uint32 mt_dma = 0; /* DMA/DMC */
uint32 mt_xtime = 16; /* transfer time */
uint32 mt_ctime = 3000; /* start/stop time */
uint32 mt_stopioe = 1; /* stop on I/O error */
uint8 mtxb[DBSIZE] = { 0 }; /* data buffer */
t_mtrlnt mt_ptr = 0, mt_max = 0; /* buffer ptrs */
uint32 mt_buf = 0; /* data buffer */
uint32 mt_usel = 0; /* unit select */
uint32 mt_busy = 0; /* ctlr busy */
uint32 mt_mdirq = 0; /* motion done int req */
uint32 mt_rdy = 0; /* transfer ready (int) */
uint32 mt_err = 0; /* error */
uint32 mt_eof = 0; /* end of file */
uint32 mt_eor = 0; /* transfer done */
uint32 mt_dma = 0; /* DMA/DMC */
uint32 mt_xtime = 16; /* transfer time */
uint32 mt_ctime = 3000; /* start/stop time */
uint32 mt_stopioe = 1; /* stop on I/O error */
uint8 mtxb[DBSIZE] = { 0 }; /* data buffer */
t_mtrlnt mt_ptr = 0, mt_max = 0; /* buffer ptrs */
int32 mtio (int32 inst, int32 fnc, int32 dat, int32 dev);
void mt_updint (uint32 rdy, uint32 mdone);
@@ -106,174 +106,206 @@ t_stat mt_attach (UNIT *uptr, char *cptr);
t_stat mt_detach (UNIT *uptr);
t_stat mt_map_err (UNIT *uptr, t_stat st);
void mt_wrwd (UNIT *uptr, uint32 dat);
/* MT data structures
mt_dev MT device descriptor
mt_unit MT unit list
mt_reg MT register list
mt_mod MT modifier list
mt_dev MT device descriptor
mt_unit MT unit list
mt_reg MT register list
mt_mod MT modifier list
*/
DIB mt_dib = { MT, IOBUS, MT_NUMDR, &mtio };
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) }
};
REG mt_reg[] = {
{ ORDATA (BUF, mt_buf, 16) },
{ ORDATA (USEL, mt_usel, 2) },
{ FLDATA (BUSY, mt_busy, 0) },
{ FLDATA (RDY, mt_rdy, 0) },
{ FLDATA (ERR, mt_err, 0) },
{ FLDATA (EOF, mt_eof, 0) },
{ FLDATA (EOR, mt_eor, 0) },
{ FLDATA (MDIRQ, mt_mdirq, 0) },
{ FLDATA (DMA, mt_dma, 0) },
{ FLDATA (INTREQ, dev_int, INT_V_MT) },
{ FLDATA (ENABLE, dev_enb, INT_V_MT) },
{ BRDATA (DBUF, mtxb, 8, 8, DBSIZE) },
{ DRDATA (BPTR, mt_ptr, DB_N_SIZE + 1) },
{ DRDATA (BMAX, mt_max, DB_N_SIZE + 1) },
{ DRDATA (CTIME, mt_ctime, 24), REG_NZ + PV_LEFT },
{ DRDATA (XTIME, mt_xtime, 24), REG_NZ + PV_LEFT },
{ URDATA (POS, mt_unit[0].pos, 10, T_ADDR_W, 0, MT_NUMDR, PV_LEFT) },
{ URDATA (FNC, mt_unit[0].FNC, 8, 8, 0, MT_NUMDR, REG_HRO) },
{ URDATA (UST, mt_unit[0].UST, 8, 2, 0, MT_NUMDR, REG_HRO) },
{ ORDATA (CHAN, mt_dib.chan, 5), REG_HRO },
{ FLDATA (STOP_IOE, mt_stopioe, 0) },
{ NULL } };
{ ORDATA (BUF, mt_buf, 16) },
{ ORDATA (USEL, mt_usel, 2) },
{ FLDATA (BUSY, mt_busy, 0) },
{ FLDATA (RDY, mt_rdy, 0) },
{ FLDATA (ERR, mt_err, 0) },
{ FLDATA (EOF, mt_eof, 0) },
{ FLDATA (EOR, mt_eor, 0) },
{ FLDATA (MDIRQ, mt_mdirq, 0) },
{ FLDATA (DMA, mt_dma, 0) },
{ FLDATA (INTREQ, dev_int, INT_V_MT) },
{ FLDATA (ENABLE, dev_enb, INT_V_MT) },
{ BRDATA (DBUF, mtxb, 8, 8, DBSIZE) },
{ DRDATA (BPTR, mt_ptr, DB_N_SIZE + 1) },
{ DRDATA (BMAX, mt_max, DB_N_SIZE + 1) },
{ DRDATA (CTIME, mt_ctime, 24), REG_NZ + PV_LEFT },
{ DRDATA (XTIME, mt_xtime, 24), REG_NZ + PV_LEFT },
{ URDATA (POS, mt_unit[0].pos, 10, T_ADDR_W, 0, MT_NUMDR, PV_LEFT) },
{ URDATA (FNC, mt_unit[0].FNC, 8, 8, 0, MT_NUMDR, REG_HRO) },
{ URDATA (UST, mt_unit[0].UST, 8, 2, 0, MT_NUMDR, REG_HRO) },
{ ORDATA (CHAN, mt_dib.chan, 5), REG_HRO },
{ 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, NULL, "IOBUS",
&io_set_iobus, NULL, NULL },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "DMC",
&io_set_dmc, NULL, NULL },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "DMA",
&io_set_dma, NULL, NULL },
{ MTAB_XTD|MTAB_VDV, 0, "CHANNEL", NULL,
NULL, &io_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, NULL, "IOBUS",
&io_set_iobus, NULL, NULL },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "DMC",
&io_set_dmc, NULL, NULL },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "DMA",
&io_set_dma, NULL, NULL },
{ MTAB_XTD|MTAB_VDV, 0, "CHANNEL", NULL,
NULL, &io_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,
NULL, &mt_attach, &mt_detach,
&mt_dib, DEV_DISABLE };
"MT", mt_unit, mt_reg, mt_mod,
MT_NUMDR, 10, 31, 1, 8, 8,
NULL, NULL, &mt_reset,
NULL, &mt_attach, &mt_detach,
&mt_dib, DEV_DISABLE
};
/* IO routine */
int32 mtio (int32 inst, int32 fnc, int32 dat, int32 dev)
{
uint32 u = dev & 03;
UNIT *uptr = mt_dev.units + u;
static uint8 wrt_fnc[16] = { /* >0 = wr, 1 = chan op */
0, 0, 0, 0, 1, 1, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0 };
static uint8 wrt_fnc[16] = { /* >0 = wr, 1 = chan op */
0, 0, 0, 0, 1, 1, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0
};
switch (inst) { /* case on opcode */
case ioOCP:
mt_updint (mt_rdy, 0); /* clear motion intr */
mt_eof = 0; /* clear eof */
switch (fnc) { /* case on function */
case FNC_DMANM: /* set DMA/DMC */
case FNC_DMAAU:
mt_usel = u; /* save unit select */
if (mt_dib.chan) mt_dma = 1; /* set DMA if configured */
else mt_dma = 0;
break;
case FNC_IOBUS: /* set IOBUS */
mt_usel = u; /* save unit select */
mt_dma = 0;
break;
case FNC_STOPW: /* stop write */
mt_usel = u; /* save unit select */
mt_updint (0, mt_mdirq); /* clear ready */
if (wrt_fnc[uptr->FNC & 017] == 1) /* writing? */
mt_eor = 1; /* set transfer done */
break;
default: /* motion command */
if (mt_busy) return dat; /* nop if ctlr busy */
mt_eor = 0; /* clr transfer done */
mt_err = 0; /* clr error */
mt_usel = u; /* save unit select */
if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */
return (((mt_stopioe? SCPE_UNATT: SCPE_OK) << IOT_V_REASON) | dat);
if (sim_is_active (uptr)) return dat; /* nop if busy */
if (wrt_fnc[fnc] && sim_tape_wrp (uptr))
return ((STOP_MTWRP << IOT_V_REASON) | dat);
uptr->FNC = fnc;
uptr->UST = 0;
mt_busy = 1;
sim_activate (uptr, mt_ctime); /* schedule */
break;
}
break;
case ioINA: /* INA */
if (fnc) return IOBADFNC (dat); /* fnc 0 only */
if (mt_rdy) { /* ready? */
mt_rdy = 0; /* clear ready */
return IOSKIP (dat | mt_buf); /* ret buf, skip */
}
break;
case ioOTA: /* OTA */
if (fnc) return IOBADFNC (dat); /* fnc 0 only */
if (mt_rdy) { /* ready? */
mt_rdy = 0; /* clear ready */
mt_buf = dat; /* store buf */
return IOSKIP (dat); /* skip */
}
break;
case ioSKS:
uptr = mt_dev.units + mt_usel; /* use saved unit sel */
switch (fnc) {
case 000: /* ready */
if (mt_rdy) return IOSKIP (dat);
break;
case 001: /* !busy */
if (!mt_busy) return IOSKIP (dat);
break;
case 002: /* !error */
if (!mt_err) return IOSKIP (dat);
break;
case 003: /* !BOT */
if (!(uptr->UST & STA_BOT)) return IOSKIP (dat);
break;
case 004: /* !interrupting */
if (!TST_INTREQ (INT_MT)) return IOSKIP (dat);
break;
case 005: /* !EOT */
if (!(uptr->UST & STA_EOT)) return IOSKIP (dat);
break;
case 006: /* !EOF */
if (!mt_eof) return IOSKIP (dat);
break;
case 007: /* !write prot */
if (!sim_tape_wrp (uptr)) return IOSKIP (dat);
break;
case 011: /* operational */
if ((uptr->flags & UNIT_ATT) &&
((uptr->FNC & 017) != FNC_REW)) return IOSKIP (dat);
break;
case 012: /* skip if !chan 2 */
return IOSKIP (dat);
case 013: /* skip if !auto */
return IOSKIP (dat);
case 014: /* !rewinding */
uptr = mt_dev.units + (dev & 03); /* use specified unit */
if ((uptr->FNC & 017) != FNC_REW) return IOSKIP (dat);
break;
}
break;
case ioEND: /* end of range */
mt_eor = 1; /* transfer done */
break;
}
switch (inst) { /* case on opcode */
case ioOCP:
mt_updint (mt_rdy, 0); /* clear motion intr */
mt_eof = 0; /* clear eof */
switch (fnc) { /* case on function */
case FNC_DMANM: /* set DMA/DMC */
case FNC_DMAAU:
mt_usel = u; /* save unit select */
if (mt_dib.chan) mt_dma = 1; /* set DMA if configured */
else mt_dma = 0;
break;
case FNC_IOBUS: /* set IOBUS */
mt_usel = u; /* save unit select */
mt_dma = 0;
break;
case FNC_STOPW: /* stop write */
mt_usel = u; /* save unit select */
mt_updint (0, mt_mdirq); /* clear ready */
if (wrt_fnc[uptr->FNC & 017] == 1) /* writing? */
mt_eor = 1; /* set transfer done */
break;
default: /* motion command */
if (mt_busy) return dat; /* nop if ctlr busy */
mt_eor = 0; /* clr transfer done */
mt_err = 0; /* clr error */
mt_usel = u; /* save unit select */
if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */
return (((mt_stopioe? SCPE_UNATT: SCPE_OK) << IOT_V_REASON) | dat);
if (sim_is_active (uptr)) return dat; /* nop if busy */
if (wrt_fnc[fnc] && (uptr->flags & UNIT_WPRT))
return ((STOP_MTWRP << IOT_V_REASON) | dat);
uptr->FNC = fnc;
uptr->UST = 0;
mt_busy = 1;
sim_activate (uptr, mt_ctime); /* schedule */
break; }
break;
case ioINA: /* INA */
if (fnc) return IOBADFNC (dat); /* fnc 0 only */
if (mt_rdy) { /* ready? */
mt_rdy = 0; /* clear ready */
return IOSKIP (dat | mt_buf); } /* ret buf, skip */
break;
case ioOTA: /* OTA */
if (fnc) return IOBADFNC (dat); /* fnc 0 only */
if (mt_rdy) { /* ready? */
mt_rdy = 0; /* clear ready */
mt_buf = dat; /* store buf */
return IOSKIP (dat); } /* skip */
break;
case ioSKS:
uptr = mt_dev.units + mt_usel; /* use saved unit sel */
switch (fnc) {
case 000: /* ready */
if (mt_rdy) return IOSKIP (dat);
break;
case 001: /* !busy */
if (!mt_busy) return IOSKIP (dat);
break;
case 002: /* !error */
if (!mt_err) return IOSKIP (dat);
break;
case 003: /* !BOT */
if (!(uptr->UST & STA_BOT)) return IOSKIP (dat);
break;
case 004: /* !interrupting */
if (!TST_INTREQ (INT_MT)) return IOSKIP (dat);
break;
case 005: /* !EOT */
if (!(uptr->UST & STA_EOT)) return IOSKIP (dat);
break;
case 006: /* !EOF */
if (!mt_eof) return IOSKIP (dat);
break;
case 007: /* !write prot */
if (!(uptr->flags & UNIT_WPRT)) return IOSKIP (dat);
break;
case 011: /* operational */
if ((uptr->flags & UNIT_ATT) &&
((uptr->FNC & 017) != FNC_REW)) return IOSKIP (dat);
break;
case 012: /* skip if !chan 2 */
return IOSKIP (dat);
case 013: /* skip if !auto */
return IOSKIP (dat);
case 014: /* !rewinding */
uptr = mt_dev.units + (dev & 03); /* use specified unit */
if ((uptr->FNC & 017) != FNC_REW) return IOSKIP (dat);
break; }
break;
case ioEND: /* end of range */
mt_eor = 1; /* transfer done */
break; }
return dat;
}
/* Unit service
If rewind done, reposition to start of tape, set status
@@ -284,150 +316,159 @@ return dat;
t_stat mt_svc (UNIT *uptr)
{
int32 ch = mt_dib.chan - 1; /* DMA/DMC ch */
int32 ch = mt_dib.chan - 1; /* DMA/DMC ch */
uint32 i, c1, c2, c3;
t_mtrlnt tbc;
t_stat st, r = SCPE_OK;
if ((uptr->flags & UNIT_ATT) == 0) { /* offline? */
mt_err = 1;
mt_busy = 0;
mt_updint (0, 1); /* cmd done */
return IORETURN (mt_stopioe, SCPE_UNATT); }
if ((uptr->flags & UNIT_ATT) == 0) { /* offline? */
mt_err = 1;
mt_busy = 0;
mt_updint (0, 1); /* cmd done */
return IORETURN (mt_stopioe, SCPE_UNATT);
}
switch (uptr->FNC) { /* case on function */
case FNC_REW: /* rewind (initial) */
mt_busy = 0; /* ctlr not busy */
uptr->FNC = uptr->FNC | FNC_2ND;
sim_activate (uptr, mt_ctime);
return SCPE_OK; /* continue */
switch (uptr->FNC) { /* case on function */
case FNC_REW | FNC_2ND: /* rewind done */
uptr->pos = 0; /* reposition file */
uptr->UST = STA_BOT; /* set BOT */
uptr->FNC = FNC_NOP; /* nop function */
for (i = 0; i < MT_NUMDR; i++) { /* last rewind? */
if ((mt_unit[i].FNC & 017) == FNC_REW) return SCPE_OK; }
mt_updint (mt_rdy, 1); /* yes, motion done */
return SCPE_OK;
case FNC_REW: /* rewind (initial) */
mt_busy = 0; /* ctlr not busy */
uptr->FNC = uptr->FNC | FNC_2ND;
sim_activate (uptr, mt_ctime);
return SCPE_OK; /* continue */
case FNC_WEOF: /* write file mark */
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
r = mt_map_err (uptr, st); /* map error */
break; /* sched end motion */
case FNC_REW | FNC_2ND: /* rewind done */
uptr->pos = 0; /* reposition file */
uptr->UST = STA_BOT; /* set BOT */
uptr->FNC = FNC_NOP; /* nop function */
for (i = 0; i < MT_NUMDR; i++) { /* last rewind? */
if ((mt_unit[i].FNC & 017) == FNC_REW) return SCPE_OK;
}
mt_updint (mt_rdy, 1); /* yes, motion done */
return SCPE_OK;
case FNC_FSR: /* space fwd rec */
if (st = sim_tape_sprecf (uptr, &tbc)) /* space fwd, err? */
r = mt_map_err (uptr, st); /* map error */
break; /* sched end motion */
case FNC_WEOF: /* write file mark */
if (st = sim_tape_wrtmk (uptr)) /* write tmk, err? */
r = mt_map_err (uptr, st); /* map error */
break; /* sched end motion */
case FNC_BSR: /* space rev rec */
if (st = sim_tape_sprecr (uptr, &tbc)) /* space rev, err? */
r = mt_map_err (uptr, st); /* map error */
break; /* sched end motion */
case FNC_FSR: /* space fwd rec */
if (st = sim_tape_sprecf (uptr, &tbc)) /* space fwd, err? */
r = mt_map_err (uptr, st); /* map error */
break; /* sched end motion */
case FNC_FSF: /* space fwd file */
while ((st = sim_tape_sprecf (uptr, &tbc)) == MTSE_OK) ;
r = mt_map_err (uptr, st); /* map error */
break; /* sched end motion */
case FNC_BSR: /* space rev rec */
if (st = sim_tape_sprecr (uptr, &tbc)) /* space rev, err? */
r = mt_map_err (uptr, st); /* map error */
break; /* sched end motion */
case FNC_BSF: /* space rev file */
while ((st = sim_tape_sprecr (uptr, &tbc)) == MTSE_OK) ;
r = mt_map_err (uptr, st); /* map error */
break; /* sched end motion */
case FNC_FSF: /* space fwd file */
while ((st = sim_tape_sprecf (uptr, &tbc)) == MTSE_OK) ;
r = mt_map_err (uptr, st); /* map error */
break; /* sched end motion */
case FNC_EOM: /* end of motion */
uptr->FNC = FNC_NOP; /* nop function */
mt_busy = 0; /* not busy */
mt_updint (mt_rdy, 1); /* end of motion */
return SCPE_OK; /* done! */
/* Unit service, continued */
case FNC_BSF: /* space rev file */
while ((st = sim_tape_sprecr (uptr, &tbc)) == MTSE_OK) ;
r = mt_map_err (uptr, st); /* map error */
break; /* sched end motion */
case FNC_RBCD2: case FNC_RBIN2: case FNC_RBIN3: /* read first */
mt_ptr = 0; /* clr buf ptr */
st = sim_tape_rdrecf (uptr, mtxb, &mt_max, DBSIZE); /* read rec */
if (st != MTSE_OK) { /* error? */
r = mt_map_err (uptr, st); /* map error */
break; } /* sched end motion */
uptr->FNC = uptr->FNC | FNC_2ND; /* next state */
sim_activate (uptr, mt_xtime); /* sched xfer */
return SCPE_OK;
case FNC_EOM: /* end of motion */
uptr->FNC = FNC_NOP; /* nop function */
mt_busy = 0; /* not busy */
mt_updint (mt_rdy, 1); /* end of motion */
return SCPE_OK; /* done! */
case FNC_RBCD2 | FNC_2ND: /* read, word */
case FNC_RBIN2 | FNC_2ND:
case FNC_RBIN3 | FNC_2ND:
if (mt_ptr >= mt_max) break; /* record done? */
c1 = mtxb[mt_ptr++] & 077; /* get 2 chars */
c2 = mtxb[mt_ptr++] & 077;
if (uptr->FNC == (FNC_RBCD2 | FNC_2ND)) { /* BCD? */
if (c1 == 012) c1 = 0; /* change 12 to 0 */
if (c2 == 012) c2 = 0; }
if (uptr->FNC == (FNC_RBIN3 | FNC_2ND)) { /* read 3? */
if (mt_ptr >= mt_max) break; /* lose wd if not enuf */
c3 = mtxb[mt_ptr++] & 017; } /* get 3rd char */
else c3 = 0;
sim_activate (uptr, mt_xtime); /* no, sched word */
if (mt_eor) return SCPE_OK; /* xfer done? */
mt_buf = (c1 << 10) | (c2 << 4) | c3; /* pack chars */
if (mt_rdy) mt_err = 1; /* buf full? err */
mt_updint (1, mt_mdirq); /* set ready */
if (mt_dma) SET_CH_REQ (ch); /* DMC/DMA? req chan */
return SCPE_OK; /* continue */
case FNC_WBCD2: case FNC_WBIN2: case FNC_WBIN3: /* write first */
mt_ptr = 0; /* clear buf ptr */
mt_updint (1, mt_mdirq); /* set ready */
if (mt_dma) SET_CH_REQ (ch); /* DMC/DMA? req chan */
uptr->FNC = uptr->FNC | FNC_2ND; /* next state */
sim_activate (uptr, mt_xtime); /* sched xfer */
return SCPE_OK; /* continue */
case FNC_RBCD2: case FNC_RBIN2: case FNC_RBIN3: /* read first */
mt_ptr = 0; /* clr buf ptr */
st = sim_tape_rdrecf (uptr, mtxb, &mt_max, DBSIZE); /* read rec */
if (st != MTSE_OK) { /* error? */
r = mt_map_err (uptr, st); /* map error */
break; /* sched end motion */
}
uptr->FNC = uptr->FNC | FNC_2ND; /* next state */
sim_activate (uptr, mt_xtime); /* sched xfer */
return SCPE_OK;
case FNC_WBCD2 | FNC_2ND: /* write, word */
case FNC_WBIN2 | FNC_2ND:
case FNC_WBIN3 | FNC_2ND:
if (mt_eor || mt_rdy) { /* done or no data? */
if (!mt_rdy) mt_wrwd (uptr, mt_buf); /* write last word */
if (mt_ptr) { /* any data? */
if (st = sim_tape_wrrecf (uptr, mtxb, mt_ptr)) /* write, err? */
r = mt_map_err (uptr, st); } /* map error */
break; } /* sched end motion */
mt_wrwd (uptr, mt_buf); /* write word */
sim_activate (uptr, mt_xtime); /* no, sched word */
mt_updint (1, mt_mdirq); /* set ready */
if (mt_dma) SET_CH_REQ (ch); /* DMC/DMA? req chan */
return SCPE_OK; /* continue */
case FNC_RBCD2 | FNC_2ND: /* read, word */
case FNC_RBIN2 | FNC_2ND:
case FNC_RBIN3 | FNC_2ND:
if (mt_ptr >= mt_max) break; /* record done? */
c1 = mtxb[mt_ptr++] & 077; /* get 2 chars */
c2 = mtxb[mt_ptr++] & 077;
if (uptr->FNC == (FNC_RBCD2 | FNC_2ND)) { /* BCD? */
if (c1 == 012) c1 = 0; /* change 12 to 0 */
if (c2 == 012) c2 = 0;
}
if (uptr->FNC == (FNC_RBIN3 | FNC_2ND)) { /* read 3? */
if (mt_ptr >= mt_max) break; /* lose wd if not enuf */
c3 = mtxb[mt_ptr++] & 017; /* get 3rd char */
}
else c3 = 0;
sim_activate (uptr, mt_xtime); /* no, sched word */
if (mt_eor) return SCPE_OK; /* xfer done? */
mt_buf = (c1 << 10) | (c2 << 4) | c3; /* pack chars */
if (mt_rdy) mt_err = 1; /* buf full? err */
mt_updint (1, mt_mdirq); /* set ready */
if (mt_dma) SET_CH_REQ (ch); /* DMC/DMA? req chan */
return SCPE_OK; /* continue */
case FNC_WBCD2: case FNC_WBIN2: case FNC_WBIN3: /* write first */
mt_ptr = 0; /* clear buf ptr */
mt_updint (1, mt_mdirq); /* set ready */
if (mt_dma) SET_CH_REQ (ch); /* DMC/DMA? req chan */
uptr->FNC = uptr->FNC | FNC_2ND; /* next state */
sim_activate (uptr, mt_xtime); /* sched xfer */
return SCPE_OK; /* continue */
default: /* unknown */
break; }
case FNC_WBCD2 | FNC_2ND: /* write, word */
case FNC_WBIN2 | FNC_2ND:
case FNC_WBIN3 | FNC_2ND:
if (mt_eor || mt_rdy) { /* done or no data? */
if (!mt_rdy) mt_wrwd (uptr, mt_buf); /* write last word */
if (mt_ptr) { /* any data? */
if (st = sim_tape_wrrecf (uptr, mtxb, mt_ptr)) /* write, err? */
r = mt_map_err (uptr, st); /* map error */
}
break; /* sched end motion */
}
mt_wrwd (uptr, mt_buf); /* write word */
sim_activate (uptr, mt_xtime); /* no, sched word */
mt_updint (1, mt_mdirq); /* set ready */
if (mt_dma) SET_CH_REQ (ch); /* DMC/DMA? req chan */
return SCPE_OK; /* continue */
default: /* unknown */
break;
}
/* End of command, process error or schedule end of motion */
if (r != SCPE_OK) {
uptr->FNC = FNC_NOP; /* nop function */
mt_busy = 0; /* not busy */
mt_updint (mt_rdy, 1); /* end of motion */
return r; }
uptr->FNC = FNC_EOM; /* sched end motion */
uptr->FNC = FNC_NOP; /* nop function */
mt_busy = 0; /* not busy */
mt_updint (mt_rdy, 1); /* end of motion */
return r;
}
uptr->FNC = FNC_EOM; /* sched end motion */
sim_activate (uptr, mt_ctime);
return SCPE_OK;
}
/* Write word to buffer */
void mt_wrwd (UNIT *uptr, uint32 dat)
{
uint32 c1, c2;
c1 = (dat >> 10) & 077; /* get 2 chars */
c1 = (dat >> 10) & 077; /* get 2 chars */
c2 = (dat >> 4) & 077;
if (uptr->FNC == (FNC_WBCD2 | FNC_2ND)) { /* BCD? */
if (c1 == 0) c1 = 012; /* change 0 to 12 */
if (c2 == 0) c2 = 012; }
if (mt_ptr < DBSIZE) mtxb[mt_ptr++] = c1; /* store 2 char */
if (uptr->FNC == (FNC_WBCD2 | FNC_2ND)) { /* BCD? */
if (c1 == 0) c1 = 012; /* change 0 to 12 */
if (c2 == 0) c2 = 012;
}
if (mt_ptr < DBSIZE) mtxb[mt_ptr++] = c1; /* store 2 char */
if (mt_ptr < DBSIZE) mtxb[mt_ptr++] = c2;
if ((uptr->FNC == (FNC_WBIN3 | FNC_2ND)) && /* write 3? */
(mt_ptr < DBSIZE)) mtxb[mt_ptr++] = mt_buf & 017;
if ((uptr->FNC == (FNC_WBIN3 | FNC_2ND)) && /* write 3? */
(mt_ptr < DBSIZE)) mtxb[mt_ptr++] = mt_buf & 017;
return;
}
@@ -436,31 +477,40 @@ return;
t_stat mt_map_err (UNIT *uptr, t_stat st)
{
switch (st) {
case MTSE_FMT: /* illegal fmt */
case MTSE_UNATT: /* unattached */
mt_err = 1; /* reject */
case MTSE_OK: /* no error */
return SCPE_IERR; /* never get here! */
case MTSE_TMK: /* end of file */
mt_eof = 1; /* eof */
break;
case MTSE_INVRL: /* invalid rec lnt */
mt_err = 1;
return SCPE_MTRLNT;
case MTSE_IOERR: /* IO error */
mt_err = 1; /* error */
if (mt_stopioe) return SCPE_IOERR;
break;
case MTSE_RECE: /* record in error */
case MTSE_EOM: /* end of medium */
mt_err = 1; /* error */
break;
case MTSE_BOT: /* reverse into BOT */
uptr->UST = STA_BOT; /* set status */
break;
case MTSE_WRP: /* write protect */
mt_err = 1; /* error */
return STOP_MTWRP; }
case MTSE_FMT: /* illegal fmt */
case MTSE_UNATT: /* unattached */
mt_err = 1; /* reject */
case MTSE_OK: /* no error */
return SCPE_IERR; /* never get here! */
case MTSE_TMK: /* end of file */
mt_eof = 1; /* eof */
break;
case MTSE_INVRL: /* invalid rec lnt */
mt_err = 1;
return SCPE_MTRLNT;
case MTSE_IOERR: /* IO error */
mt_err = 1; /* error */
if (mt_stopioe) return SCPE_IOERR;
break;
case MTSE_RECE: /* record in error */
case MTSE_EOM: /* end of medium */
mt_err = 1; /* error */
break;
case MTSE_BOT: /* reverse into BOT */
uptr->UST = STA_BOT; /* set status */
break;
case MTSE_WRP: /* write protect */
mt_err = 1; /* error */
return STOP_MTWRP;
}
return SCPE_OK;
}
@@ -468,13 +518,13 @@ return SCPE_OK;
void mt_updint (uint32 rdy, uint32 mdirq)
{
mt_rdy = rdy; /* store new ready */
mt_mdirq = mdirq; /* store new motion irq */
if ((mt_rdy && !mt_dma) || mt_mdirq) SET_INT (INT_MT); /* update int request */
mt_rdy = rdy; /* store new ready */
mt_mdirq = mdirq; /* store new motion irq */
if ((mt_rdy && !mt_dma) || mt_mdirq) SET_INT (INT_MT); /* update int request */
else CLR_INT (INT_MT);
return;
}
/* Reset routine */
t_stat mt_reset (DEVICE *dptr)
@@ -482,7 +532,7 @@ t_stat mt_reset (DEVICE *dptr)
int32 i;
UNIT *uptr;
mt_buf = 0; /* clear state */
mt_buf = 0; /* clear state */
mt_usel = 0;
mt_mdirq = 0;
mt_eor = 0;
@@ -491,14 +541,15 @@ mt_rdy = 0;
mt_eof = 0;
mt_err = 0;
mt_dma = 0;
CLR_INT (INT_MT); /* clear int, enb */
CLR_INT (INT_MT); /* clear int, enb */
CLR_ENB (INT_MT);
for (i = 0; i < MT_NUMDR; i++) { /* loop thru units */
uptr = mt_dev.units + i;
sim_tape_reset (uptr); /* reset tape */
sim_cancel (uptr); /* cancel op */
uptr->UST = uptr->pos? 0: STA_BOT; /* update status */
uptr->FNC = FNC_NOP; }
for (i = 0; i < MT_NUMDR; i++) { /* loop thru units */
uptr = mt_dev.units + i;
sim_tape_reset (uptr); /* reset tape */
sim_cancel (uptr); /* cancel op */
uptr->UST = uptr->pos? 0: STA_BOT; /* update status */
uptr->FNC = FNC_NOP;
}
return SCPE_OK;
}
@@ -508,8 +559,8 @@ t_stat mt_attach (UNIT *uptr, char *cptr)
{
t_stat r;
r = sim_tape_attach (uptr, cptr); /* attach unit */
if (r != SCPE_OK) return r; /* update status */
r = sim_tape_attach (uptr, cptr); /* attach unit */
if (r != SCPE_OK) return r; /* update status */
uptr->UST = STA_BOT;
return r;
}
@@ -518,7 +569,7 @@ return r;
t_stat mt_detach (UNIT* uptr)
{
uptr->UST = 0; /* update status */
uptr->FNC = FNC_NOP; /* nop function */
return sim_tape_detach (uptr); /* detach unit */
uptr->UST = 0; /* update status */
uptr->FNC = FNC_NOP; /* nop function */
return sim_tape_detach (uptr); /* detach unit */
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
/* h316_sys.c: Honeywell 316/516 simulator interface
Copyright (c) 1999-2004, Robert M Supnik
Copyright (c) 1999-2005, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@@ -19,13 +19,13 @@
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.
01-Dec-04 RMS Fixed fprint_opr calling sequence
24-Oct-03 RMS Added DMA/DMC support
17-Sep-01 RMS Removed multiconsole support
01-Dec-04 RMS Fixed fprint_opr calling sequence
24-Oct-03 RMS Added DMA/DMC support
17-Sep-01 RMS Removed multiconsole support
*/
#include "h316_defs.h"
@@ -47,12 +47,12 @@ extern int32 sim_switches;
/* SCP data structures and interface routines
sim_name simulator name string
sim_PC pointer to saved PC register descriptor
sim_emax maximum number of words for examine/deposit
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 maximum number of words for examine/deposit
sim_devices array of pointers to simulated devices
sim_stop_messages array of pointers to stop messages
sim_load binary loader
*/
char sim_name[] = "H316";
@@ -62,29 +62,31 @@ REG *sim_PC = &cpu_reg[0];
int32 sim_emax = 1;
DEVICE *sim_devices[] = {
&cpu_dev,
&ptr_dev,
&ptp_dev,
&tty_dev,
&lpt_dev,
&clk_dev,
&dp_dev,
&fhd_dev,
&mt_dev,
NULL };
&cpu_dev,
&ptr_dev,
&ptp_dev,
&tty_dev,
&lpt_dev,
&clk_dev,
&dp_dev,
&fhd_dev,
&mt_dev,
NULL
};
const char *sim_stop_messages[] = {
"Unknown error",
"Unimplemented instruction",
"Unimplemented I/O device",
"HALT instruction",
"Breakpoint",
"Indirect address loop",
"DMA error",
"MT write protected",
"DP write overrun, track destroyed",
"DP track format invalid" };
"Unknown error",
"Unimplemented instruction",
"Unimplemented I/O device",
"HALT instruction",
"Breakpoint",
"Indirect address loop",
"DMA error",
"MT write protected",
"DP write overrun, track destroyed",
"DP track format invalid"
};
/* Binary loader
Tbs.
@@ -94,29 +96,30 @@ t_stat sim_load (FILE *fileref, char *cptr, char *fnam, int flag)
{
return SCPE_FMT;
}
/* Symbol tables */
#define I_V_FL 16 /* flag start */
#define I_M_FL 07 /* flag mask */
#define I_V_NPN 0 /* no operand */
#define I_V_MRF 1 /* mem ref */
#define I_V_MRX 2 /* mem ref, no idx */
#define I_V_IOT 3 /* I/O */
#define I_V_SHF 4 /* shift */
#define I_V_SK0 5 /* skip 0 */
#define I_V_SK1 6 /* skip 1 */
#define I_NPN (I_V_NPN << I_V_FL)
#define I_MRF (I_V_MRF << I_V_FL)
#define I_MRX (I_V_MRX << I_V_FL)
#define I_IOT (I_V_IOT << I_V_FL)
#define I_SHF (I_V_SHF << I_V_FL)
#define I_SK0 (I_V_SK0 << I_V_FL)
#define I_SK1 (I_V_SK1 << I_V_FL)
#define I_V_FL 16 /* flag start */
#define I_M_FL 07 /* flag mask */
#define I_V_NPN 0 /* no operand */
#define I_V_MRF 1 /* mem ref */
#define I_V_MRX 2 /* mem ref, no idx */
#define I_V_IOT 3 /* I/O */
#define I_V_SHF 4 /* shift */
#define I_V_SK0 5 /* skip 0 */
#define I_V_SK1 6 /* skip 1 */
#define I_NPN (I_V_NPN << I_V_FL)
#define I_MRF (I_V_MRF << I_V_FL)
#define I_MRX (I_V_MRX << I_V_FL)
#define I_IOT (I_V_IOT << I_V_FL)
#define I_SHF (I_V_SHF << I_V_FL)
#define I_SK0 (I_V_SK0 << I_V_FL)
#define I_SK1 (I_V_SK1 << I_V_FL)
static const int32 masks[] = {
0177777, 0136000, 0176000, 0176000,
0177700, 0177000, 0177000 };
0177700, 0177000, 0177000
};
static const char *opcode[] = {
"HLT", "SGL", "DBL",
@@ -143,14 +146,15 @@ static const char *opcode[] = {
"LGL", "ALS", "ALR",
"OCP", "SKS", "INA", "OTA",
"SMK",
"SPL", "SPN", "SLZ", /* encode only */
"SPL", "SPN", "SLZ", /* encode only */
"SZE", "SR1", "SR2",
"SR3", "SR4", "SRC",
"SMI", "SPS", "SLN",
"SNZ", "SS1", "SS2",
"SS3", "SS4", "SSC",
NULL, NULL, /* decode only */
NULL };
NULL, NULL, /* decode only */
NULL
};
static const int32 opc_val[] = {
0000000+I_NPN, 0000005+I_NPN, 0000007+I_NPN,
@@ -177,115 +181,129 @@ static const int32 opc_val[] = {
0041400+I_SHF, 0041500+I_SHF, 0041600+I_SHF,
0030000+I_IOT, 0070000+I_IOT, 0130000+I_IOT, 0170000+I_IOT,
0170000+I_IOT,
0100400+I_SK0, 0100200+I_SK0, 0100100+I_SK0, /* encode only */
0100400+I_SK0, 0100200+I_SK0, 0100100+I_SK0, /* encode only */
0100040+I_SK0, 0100020+I_SK0, 0100010+I_SK0,
0100004+I_SK0, 0100002+I_SK0, 0100001+I_SK0,
0101400+I_SK1, 0101200+I_SK1, 0101100+I_SK1,
0101040+I_SK1, 0101020+I_SK1, 0101010+I_SK1,
0101004+I_SK1, 0101002+I_SK1, 0101001+I_SK1,
0100000+I_SK0, 0101000+I_SK1, /* decode only */
-1 };
0100000+I_SK0, 0101000+I_SK1, /* decode only */
-1
};
/* Operate decode
Inputs:
*of = output stream
inst = mask bits
class = instruction class code
sp = space needed?
*of = output stream
inst = mask bits
class = instruction class code
sp = space needed?
Outputs:
status = space needed
status = space needed
*/
void fprint_opr (FILE *of, int32 inst, int32 class)
{
int32 i, j, sp;
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 == class) && (opc_val[i] & inst)) { /* same class? */
inst = inst & ~opc_val[i]; /* mask bit set? */
fprintf (of, (sp? " %s": "%s"), opcode[i]);
sp = 1; } }
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 == class) && (opc_val[i] & inst)) { /* same 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 data
*uptr = pointer to unit
sw = switches
*of = output stream
addr = current PC
*val = pointer to data
*uptr = pointer to unit
sw = switches
Outputs:
return = status code
return = status code
*/
#define FMTASC(x) ((x) < 040)? "<%03o>": "%c", (x)
t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
UNIT *uptr, int32 sw)
UNIT *uptr, int32 sw)
{
int32 cflag, i, j, inst, disp;
cflag = (uptr == NULL) || (uptr == &cpu_unit);
inst = val[0];
if (sw & SWMASK ('A')) { /* ASCII? */
if (inst > 0377) return SCPE_ARG;
fprintf (of, FMTASC (inst & 0177));
return SCPE_OK; }
if (sw & SWMASK ('C')) { /* characters? */
fprintf (of, FMTASC ((inst >> 8) & 0177));
fprintf (of, FMTASC (inst & 0177));
return SCPE_OK; }
if (sw & SWMASK ('A')) { /* ASCII? */
if (inst > 0377) return SCPE_ARG;
fprintf (of, FMTASC (inst & 0177));
return SCPE_OK;
}
if (sw & SWMASK ('C')) { /* characters? */
fprintf (of, FMTASC ((inst >> 8) & 0177));
fprintf (of, FMTASC (inst & 0177));
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 */
fprintf (of, "%s", opcode[i]); /* opcode */
break;
case I_V_MRF: case I_V_MRX: /* mem ref */
disp = inst & DISP; /* displacement */
fprintf (of, "%s ", opcode[i]); /* opcode */
if (inst & SC) { /* current sector? */
if (cflag) fprintf (of, "%-o", (addr & PAGENO) | disp);
else fprintf (of, "C %-o", disp); }
else fprintf (of, "%-o", disp); /* sector zero */
if ((j == I_V_MRF) && (inst & IDX)) fprintf (of, ",1");
break;
case I_V_IOT: /* I/O */
disp = inst & 01777; /* pulse+dev */
fprintf (of, "%s %o", opcode[i], disp);
break;
case I_V_SHF: /* shift */
disp = -inst & SHFMASK; /* shift count */
fprintf (of, "%s %o", opcode[i], disp);
break;
case I_V_SK0: case I_V_SK1: /* skips */
fprint_opr (of, inst & 0777, j); /* print skips */
break; } /* end case */
return SCPE_OK; } /* end if */
} /* end for */
switch (j) { /* case on class */
case I_V_NPN: /* no operands */
fprintf (of, "%s", opcode[i]); /* opcode */
break;
case I_V_MRF: case I_V_MRX: /* mem ref */
disp = inst & DISP; /* displacement */
fprintf (of, "%s ", opcode[i]); /* opcode */
if (inst & SC) { /* current sector? */
if (cflag) fprintf (of, "%-o", (addr & PAGENO) | disp);
else fprintf (of, "C %-o", disp);
}
else fprintf (of, "%-o", disp); /* sector zero */
if ((j == I_V_MRF) && (inst & IDX)) fprintf (of, ",1");
break;
case I_V_IOT: /* I/O */
disp = inst & 01777; /* pulse+dev */
fprintf (of, "%s %o", opcode[i], disp);
break;
case I_V_SHF: /* shift */
disp = -inst & SHFMASK; /* shift count */
fprintf (of, "%s %o", opcode[i], disp);
break;
case I_V_SK0: case I_V_SK1: /* skips */
fprint_opr (of, inst & 0777, j); /* print skips */
break;
} /* end case */
return SCPE_OK;
} /* end if */
} /* end for */
return SCPE_ARG;
}
/* 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)
@@ -295,69 +313,81 @@ t_stat r;
char gbuf[CBUFSIZE];
cflag = (uptr == NULL) || (uptr == &cpu_unit);
while (isspace (*cptr)) cptr++; /* absorb spaces */
while (isspace (*cptr)) cptr++; /* absorb spaces */
if ((sw & SWMASK ('A')) || ((*cptr == '\'') && cptr++)) { /* ASCII char? */
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
val[0] = (t_value) cptr[0] & 0177;
return SCPE_OK; }
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
val[0] = (t_value) cptr[0] & 0177;
return SCPE_OK;
}
if ((sw & SWMASK ('C')) || ((*cptr == '"') && cptr++)) { /* char string? */
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
val[0] = (((t_value) cptr[0] & 0177) << 8) |
((t_value) cptr[1] & 0177);
return SCPE_OK; }
if (cptr[0] == 0) return SCPE_ARG; /* must have 1 char */
val[0] = (((t_value) cptr[0] & 0177) << 8) |
((t_value) cptr[1] & 0177);
return SCPE_OK;
}
/* Instruction parse */
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: /* no operand */
break;
case I_V_IOT: /* IOT */
cptr = get_glyph (cptr, gbuf, 0); /* get pulse+dev */
d = get_uint (gbuf, 8, 01777, &r);
if (r != SCPE_OK) return SCPE_ARG;
val[0] = val[0] | d;
break;
case I_V_SHF: /* shift */
cptr = get_glyph (cptr, gbuf, 0); /* get shift count */
d = get_uint (gbuf, 8, SHFMASK, &r);
if (r != SCPE_OK) return SCPE_ARG;
val[0] = val[0] | (-d & SHFMASK); /* store 2's comp */
break;
case I_V_MRF: case I_V_MRX: /* mem ref */
cptr = get_glyph (cptr, gbuf, ','); /* get next field */
if (k = (strcmp (gbuf, "C") == 0)) { /* C specified? */
val[0] = val[0] | SC;
cptr = get_glyph (cptr, gbuf, 0); }
else if (k = (strcmp (gbuf, "Z") == 0)) { /* Z specified? */
cptr = get_glyph (cptr, gbuf, ','); }
d = get_uint (gbuf, 8, X_AMASK, &r); /* construe as addr */
if (r != SCPE_OK) return SCPE_ARG;
if (d <= DISP) val[0] = val[0] | d; /* fits? */
else if (cflag && !k && (((addr ^ d) & PAGENO) == 0))
val[0] = val[0] | (d & DISP) | SC;
else return SCPE_ARG;
if ((j == I_V_MRX) || (*cptr == 0)) break; /* indexed? */
cptr = get_glyph (cptr, gbuf, 0);
d = get_uint (gbuf, 8, 1, &r); /* get tag */
if (r != SCPE_OK) return SCPE_ARG;
if (d) val[0] = val[0] | IDX; /* or in index */
break;
case I_V_SK0: case I_V_SK1: /* skips */
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++) ;
k = opc_val[i] & DMASK;
if ((opcode[i] == NULL) || (((k ^ val[0]) & 0177000) != 0))
return SCPE_ARG;
val[0] = val[0] | k; }
break; } /* end case */
if (*cptr != 0) return SCPE_ARG; /* junk at end? */
switch (j) { /* case on class */
case I_V_NPN: /* no operand */
break;
case I_V_IOT: /* IOT */
cptr = get_glyph (cptr, gbuf, 0); /* get pulse+dev */
d = get_uint (gbuf, 8, 01777, &r);
if (r != SCPE_OK) return SCPE_ARG;
val[0] = val[0] | d;
break;
case I_V_SHF: /* shift */
cptr = get_glyph (cptr, gbuf, 0); /* get shift count */
d = get_uint (gbuf, 8, SHFMASK, &r);
if (r != SCPE_OK) return SCPE_ARG;
val[0] = val[0] | (-d & SHFMASK); /* store 2's comp */
break;
case I_V_MRF: case I_V_MRX: /* mem ref */
cptr = get_glyph (cptr, gbuf, ','); /* get next field */
if (k = (strcmp (gbuf, "C") == 0)) { /* C specified? */
val[0] = val[0] | SC;
cptr = get_glyph (cptr, gbuf, 0);
}
else if (k = (strcmp (gbuf, "Z") == 0)) { /* Z specified? */
cptr = get_glyph (cptr, gbuf, ',');
}
d = get_uint (gbuf, 8, X_AMASK, &r); /* construe as addr */
if (r != SCPE_OK) return SCPE_ARG;
if (d <= DISP) val[0] = val[0] | d; /* fits? */
else if (cflag && !k && (((addr ^ d) & PAGENO) == 0))
val[0] = val[0] | (d & DISP) | SC;
else return SCPE_ARG;
if ((j == I_V_MRX) || (*cptr == 0)) break; /* indexed? */
cptr = get_glyph (cptr, gbuf, 0);
d = get_uint (gbuf, 8, 1, &r); /* get tag */
if (r != SCPE_OK) return SCPE_ARG;
if (d) val[0] = val[0] | IDX; /* or in index */
break;
case I_V_SK0: case I_V_SK1: /* skips */
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++) ;
k = opc_val[i] & DMASK;
if ((opcode[i] == NULL) || (((k ^ val[0]) & 0177000) != 0))
return SCPE_ARG;
val[0] = val[0] | k;
}
break;
} /* end case */
if (*cptr != 0) return SCPE_ARG; /* junk at end? */
return SCPE_OK;
}