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:
committed by
Mark Pizzolato
parent
ec60bbf329
commit
b7c1eae41f
1725
H316/h316_cpu.c
1725
H316/h316_cpu.c
File diff suppressed because it is too large
Load Diff
252
H316/h316_defs.h
252
H316/h316_defs.h
@@ -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 */
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
1274
H316/h316_dp.c
1274
H316/h316_dp.c
File diff suppressed because it is too large
Load Diff
520
H316/h316_fhd.c
520
H316/h316_fhd.c
@@ -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;
|
||||
}
|
||||
|
||||
423
H316/h316_lp.c
423
H316/h316_lp.c
@@ -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;
|
||||
}
|
||||
|
||||
761
H316/h316_mt.c
761
H316/h316_mt.c
@@ -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 */
|
||||
}
|
||||
|
||||
1006
H316/h316_stddev.c
1006
H316/h316_stddev.c
File diff suppressed because it is too large
Load Diff
386
H316/h316_sys.c
386
H316/h316_sys.c
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user