1
0
mirror of https://github.com/simh/simh.git synced 2026-04-08 22:21:24 +00:00

Bob Supnik's state as of 10/12/2013

This commit is contained in:
Mark Pizzolato
2013-10-12 13:23:44 -07:00
parent 6031deddf8
commit 34ce1a038c
71 changed files with 5708 additions and 377 deletions

862
PDP11/old/pdp11_defs.h Normal file
View File

@@ -0,0 +1,862 @@
/* pdp11_defs.h: PDP-11 simulator definitions
Copyright (c) 1993-2012, 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"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
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
in this Software without prior written authorization from Robert M Supnik.
The author gratefully acknowledges the help of Max Burnet, Megan Gentry,
and John Wilson in resolving questions about the PDP-11
12-Dec-12 RMS Fixed base address for RQB, RQC, RQD
11-Dec-11 RMS Fixed priority of PIRQ vs IO; added INT_INTERNALn
22-May-10 RMS Added check for 64b definitions
19-Nov-08 RMS Moved I/O support routines to I/O library
16-May-08 RMS Added KE11A, DC11 support
02-Feb-08 RMS Fixed DMA memory address limit test (found by John Dundas)
25-Jan-08 RMS Added RC11, KG11A support (from John Dundas)
16-Dec-06 RMS Added TA11 support
29-Oct-06 RMS Added clock coscheduling
06-Jul-06 RMS Added multiple KL11/DL11 support
26-Jun-06 RMS Added RF11 support
24-May-06 RMS Added 11/44 DR support (from CIS diagnostic)
17-May-06 RMS Added CR11/CD11 support (from John Dundas)
30-Sep-04 RMS Added Massbus support
Removed Map_Addr prototype
Removed map argument from Unibus routines
Added framework for model selection
28-May-04 RMS Added DHQ support
25-Jan-04 RMS Removed local debug logging support
22-Dec-03 RMS Added second DEUNA/DELUA support
18-Oct-03 RMS Added DECtape off reel message
19-May-03 RMS Revised for new conditional compilation
05-Apr-03 RMS Fixed bug in MMR1 update (found by Tim Stark)
28-Feb-03 RMS Added TM logging support
19-Jan-03 RMS Changed mode definitions for Apple Dev Kit conflict
11-Nov-02 RMS Changed log definitions to be VAX compatible
10-Oct-02 RMS Added vector information to DIB
Changed DZ11 vector to Unibus standard
Added DEQNA/DELQA, DEUNA/DELUA support
Added multiple RQDX3, autoconfigure support
12-Sep-02 RMS Added TMSCP, KW11P,and RX211 support
28-Apr-02 RMS Clarified PDF ACF mnemonics
22-Apr-02 RMS Added HTRAP, BPOK maint register flags, MT_MAXFR
06-Mar-02 RMS Changed system type to KDJ11A
20-Jan-02 RMS Added multiboard DZ11 support
09-Nov-01 RMS Added bus map support
07-Nov-01 RMS Added RQDX3 support
26-Oct-01 RMS Added symbolic definitions for IO page
19-Oct-01 RMS Added DZ definitions
15-Oct-01 RMS Added logging capabilities
07-Sep-01 RMS Revised for multilevel interrupts
01-Jun-01 RMS Added DZ11 support
23-Apr-01 RMS Added RK611 support
05-Apr-01 RMS Added TS11/TSV05 support
10-Feb-01 RMS Added DECtape support
*/
#ifndef _PDP11_DEFS_H
#define _PDP11_DEFS_H 0
#ifndef VM_PDP11
#define VM_PDP11 0
#endif
#include "sim_defs.h" /* simulator defns */
#include <setjmp.h>
#if defined(USE_INT64) || defined(USE_ADDR64)
#error "PDP-11 does not support 64b values!"
#endif
/* Architectural constants */
#define STKL_R 0340 /* stack limit */
#define STKL_Y 0400
#define VASIZE 0200000 /* 2**16 */
#define VAMASK (VASIZE - 1) /* 2**16 - 1 */
#define MEMSIZE64K 0200000 /* 2**16 */
#define INIMEMSIZE 001000000 /* 2**18 */
#define UNIMEMSIZE 001000000 /* 2**18 */
#define UNIMASK (UNIMEMSIZE - 1) /* 2**18 - 1 */
#define IOPAGEBASE 017760000 /* 2**22 - 2**13 */
#define IOPAGESIZE 000020000 /* 2**13 */
#define IOPAGEMASK (IOPAGESIZE - 1) /* 2**13 - 1 */
#define MAXMEMSIZE 020000000 /* 2**22 */
#define PAMASK (MAXMEMSIZE - 1) /* 2**22 - 1 */
#define MEMSIZE (cpu_unit.capac)
#define ADDR_IS_MEM(x) (((t_addr) (x)) < cpu_memsize) /* use only in sim! */
#define DMASK 0177777
/* CPU models */
#define MOD_1103 0
#define MOD_1104 1
#define MOD_1105 2
#define MOD_1120 3
#define MOD_1123 4
#define MOD_1123P 5
#define MOD_1124 6
#define MOD_1134 7
#define MOD_1140 8
#define MOD_1144 9
#define MOD_1145 10
#define MOD_1160 11
#define MOD_1170 12
#define MOD_1173 13
#define MOD_1153 14
#define MOD_1173B 15
#define MOD_1183 16
#define MOD_1184 17
#define MOD_1193 18
#define MOD_1194 19
#define MOD_T 20
#define CPUT_03 (1u << MOD_1103) /* LSI-11 */
#define CPUT_04 (1u << MOD_1104) /* 11/04 */
#define CPUT_05 (1u << MOD_1105) /* 11/05 */
#define CPUT_20 (1u << MOD_1120) /* 11/20 */
#define CPUT_23 (1u << MOD_1123) /* 11/23 */
#define CPUT_23P (1u << MOD_1123P) /* 11/23+ */
#define CPUT_24 (1u << MOD_1124) /* 11/24 */
#define CPUT_34 (1u << MOD_1134) /* 11/34 */
#define CPUT_40 (1u << MOD_1140) /* 11/40 */
#define CPUT_44 (1u << MOD_1144) /* 11/44 */
#define CPUT_45 (1u << MOD_1145) /* 11/45 */
#define CPUT_60 (1u << MOD_1160) /* 11/60 */
#define CPUT_70 (1u << MOD_1170) /* 11/70 */
#define CPUT_73 (1u << MOD_1173) /* 11/73 */
#define CPUT_53 (1u << MOD_1153) /* 11/53 */
#define CPUT_73B (1u << MOD_1173B) /* 11/73B */
#define CPUT_83 (1u << MOD_1183) /* 11/83 */
#define CPUT_84 (1u << MOD_1184) /* 11/84 */
#define CPUT_93 (1u << MOD_1193) /* 11/93 */
#define CPUT_94 (1u << MOD_1194) /* 11/94 */
#define CPUT_T (1u << MOD_T) /* T-11 */
#define CPUT_F (CPUT_23|CPUT_23P|CPUT_24) /* all F11's */
#define CPUT_J (CPUT_53|CPUT_73|CPUT_73B| \
CPUT_83|CPUT_84|CPUT_93|CPUT_94)
#define CPUT_JB (CPUT_73B|CPUT_83|CPUT_84) /* KDJ11B */
#define CPUT_JE (CPUT_93|CPUT_94) /* KDJ11E */
#define CPUT_JU (CPUT_84|CPUT_94) /* KTJ11B UBA */
#define CPUT_ALL 0xFFFFFFFF
/* CPU options */
#define BUS_U (1u << 0) /* Unibus */
#define BUS_Q (0) /* Qbus */
#define OPT_EIS (1u << 1) /* EIS */
#define OPT_FIS (1u << 2) /* FIS */
#define OPT_FPP (1u << 3) /* FPP */
#define OPT_CIS (1u << 4) /* CIS */
#define OPT_MMU (1u << 5) /* MMU */
#define OPT_RH11 (1u << 6) /* RH11 */
#define OPT_PAR (1u << 7) /* parity */
#define OPT_UBM (1u << 8) /* UBM */
#define CPUT(x) ((cpu_type & (x)) != 0)
#define CPUO(x) ((cpu_opt & (x)) != 0)
#define UNIBUS (cpu_opt & BUS_U)
/* Feature sets
SDSD source addr, dest addr, source fetch, dest fetch
SR switch register
DR display register
RTT RTT instruction
SXS SXT, XOR, SOB instructions
MARK MARK instruction
SPL SPL instruction
MXPY MTPI, MTPD, MFPI, MFPD instructions
MXPS MTPS, MFPS instructions
MFPT MFPT instruction
CSM CSM instruction
TSWLK TSTSET, WRLCK instructions
PSW PSW register
EXPT explicit PSW writes can alter T-bit
IOSR general registers readable from programs in IO space
2REG dual register set
MMR3 MMR3 register
MMTR mem mgt traps
STKLR STKLIM register
STKLF fixed stack limit
SID supervisor mode, I/D spaces
ODD odd address trap
HALT4 halt in kernel mode traps to 4
JREG4 JMP/JSR R traps to 4
STKA stop on stack abort
LTCR LTC CSR
LTCM LTC CSR<7>
*/
#define IS_SDSD (CPUT_20|CPUT_F|CPUT_40|CPUT_60|CPUT_J|CPUT_T)
#define HAS_SR (CPUT_04|CPUT_05|CPUT_20|CPUT_34|CPUT_40| \
CPUT_44|CPUT_45|CPUT_60|CPUT_70)
#define HAS_DR (CPUT_04|CPUT_05|CPUT_20|CPUT_24|CPUT_34| \
CPUT_40|CPUT_44|CPUT_45|CPUT_60|CPUT_70)
#define HAS_RTT (CPUT_03|CPUT_04|CPUT_F|CPUT_34|CPUT_40| \
CPUT_44|CPUT_45|CPUT_60|CPUT_70|CPUT_J|CPUT_T)
#define HAS_SXS (CPUT_03|CPUT_F|CPUT_34|CPUT_40|CPUT_44| \
CPUT_45|CPUT_60|CPUT_70|CPUT_J|CPUT_T)
#define HAS_MARK (CPUT_03|CPUT_F|CPUT_34|CPUT_40|CPUT_44| \
CPUT_45|CPUT_60|CPUT_70|CPUT_J)
#define HAS_SPL (CPUT_44|CPUT_45|CPUT_70|CPUT_J)
#define HAS_MXPY (CPUT_F|CPUT_34|CPUT_40|CPUT_44|CPUT_45| \
CPUT_60|CPUT_70|CPUT_J)
#define HAS_MXPS (CPUT_03|CPUT_F|CPUT_34|CPUT_J|CPUT_T)
#define HAS_MFPT (CPUT_F|CPUT_44|CPUT_J|CPUT_T)
#define HAS_CSM (CPUT_44|CPUT_J)
#define HAS_TSWLK (CPUT_J)
#define HAS_PSW (CPUT_04|CPUT_05|CPUT_20|CPUT_F|CPUT_34|CPUT_40| \
CPUT_44|CPUT_45|CPUT_60|CPUT_70|CPUT_J)
#define HAS_EXPT (CPUT_04|CPUT_05|CPUT_20)
#define HAS_IOSR (CPUT_04|CPUT_05)
#define HAS_2REG (CPUT_45|CPUT_70|CPUT_J)
#define HAS_MMR3 (CPUT_F|CPUT_44|CPUT_45|CPUT_70|CPUT_J)
#define HAS_MMTR (CPUT_45|CPUT_70)
#define HAS_STKLR (CPUT_45|CPUT_60|CPUT_70)
#define HAS_STKLF (CPUT_04|CPUT_05|CPUT_20|CPUT_F|CPUT_34| \
CPUT_40|CPUT_44|CPUT_J)
#define HAS_SID (CPUT_44|CPUT_45|CPUT_70|CPUT_J)
#define HAS_ODD (CPUT_04|CPUT_05|CPUT_20|CPUT_34|CPUT_40| \
CPUT_44|CPUT_45|CPUT_60|CPUT_70|CPUT_J)
#define HAS_HALT4 (CPUT_44|CPUT_45|CPUT_70|CPUT_J)
#define HAS_JREG4 (CPUT_03|CPUT_04|CPUT_05|CPUT_20|CPUT_F| \
CPUT_34|CPUT_40|CPUT_60|CPUT_T)
#define STOP_STKA (CPUT_03|CPUT_04|CPUT_05|CPUT_20|CPUT_34|CPUT_44)
#define HAS_LTCR (CPUT_04|CPUT_05|CPUT_20|CPUT_23P|CPUT_24| \
CPUT_34|CPUT_40|CPUT_44|CPUT_45|CPUT_60| \
CPUT_70|CPUT_J)
#define HAS_LTCM (CPUT_04|CPUT_05|CPUT_20|CPUT_24|CPUT_34| \
CPUT_40|CPUT_44|CPUT_45|CPUT_60|CPUT_70|CPUT_J)
/* Protection modes */
#define MD_KER 0
#define MD_SUP 1
#define MD_UND 2
#define MD_USR 3
/* I/O access modes */
#define READ 0
#define READC 1 /* read console */
#define WRITE 2
#define WRITEC 3 /* write console */
#define WRITEB 4
/* PSW */
#define PSW_V_C 0 /* condition codes */
#define PSW_V_V 1
#define PSW_V_Z 2
#define PSW_V_N 3
#define PSW_V_TBIT 4 /* trace trap */
#define PSW_V_IPL 5 /* int priority */
#define PSW_V_FPD 8 /* first part done */
#define PSW_V_RS 11 /* register set */
#define PSW_V_PM 12 /* previous mode */
#define PSW_V_CM 14 /* current mode */
#define PSW_CC 017
#define PSW_TBIT (1 << PSW_V_TBIT)
#define PSW_PM (3 << PSW_V_PM)
/* FPS */
#define FPS_V_C 0 /* condition codes */
#define FPS_V_V 1
#define FPS_V_Z 2
#define FPS_V_N 3
#define FPS_V_T 5 /* truncate */
#define FPS_V_L 6 /* long */
#define FPS_V_D 7 /* double */
#define FPS_V_IC 8 /* ic err int */
#define FPS_V_IV 9 /* overflo err int */
#define FPS_V_IU 10 /* underflo err int */
#define FPS_V_IUV 11 /* undef var err int */
#define FPS_V_ID 14 /* int disable */
#define FPS_V_ER 15 /* error */
/* PIRQ */
#define PIRQ_PIR1 0001000
#define PIRQ_PIR2 0002000
#define PIRQ_PIR3 0004000
#define PIRQ_PIR4 0010000
#define PIRQ_PIR5 0020000
#define PIRQ_PIR6 0040000
#define PIRQ_PIR7 0100000
#define PIRQ_IMP 0177356 /* implemented bits */
#define PIRQ_RW 0177000 /* read/write bits */
/* STKLIM */
#define STKLIM_RW 0177400
/* MMR0 */
#define MMR0_MME 0000001 /* mem mgt enable */
#define MMR0_V_PAGE 1 /* offset to pageno */
#define MMR0_M_PAGE 077 /* mask for pageno */
#define MMR0_PAGE (MMR0_M_PAGE << MMR0_V_PAGE)
#define MMR0_IC 0000200 /* instr complete */
#define MMR0_MAINT 0000400 /* maintenance */
#define MMR0_TENB 0001000 /* trap enable */
#define MMR0_TRAP 0010000 /* mem mgt trap */
#define MMR0_RO 0020000 /* read only error */
#define MMR0_PL 0040000 /* page lnt error */
#define MMR0_NR 0100000 /* no access error */
#define MMR0_FREEZE 0160000 /* if set, no update */
#define MMR0_WR 0171401 /* writeable bits */
/* MMR3 */
#define MMR3_UDS 001 /* user dspace enbl */
#define MMR3_SDS 002 /* super dspace enbl */
#define MMR3_KDS 004 /* krnl dspace enbl */
#define MMR3_CSM 010 /* CSM enable */
#define MMR3_M22E 020 /* 22b mem mgt enbl */
#define MMR3_BME 040 /* DMA bus map enbl */
/* PAR */
#define PAR_18B 0007777 /* 18b addressing */
#define PAR_22B 0177777 /* 22b addressing */
/* PDR */
#define PDR_ACF 0000007 /* access control */
#define PDR_ACS 0000006 /* 2b access control */
#define PDR_ED 0000010 /* expansion dir */
#define PDR_W 0000100 /* written flag */
#define PDR_A 0000200 /* access flag */
#define PDR_PLF 0077400 /* page lnt field */
#define PDR_NOC 0100000 /* don't cache */
#define PDR_PRD 0000003 /* page readable if 2 */
/* Virtual address */
#define VA_DF 0017777 /* displacement */
#define VA_BN 0017700 /* block number */
#define VA_V_APF 13 /* offset to APF */
#define VA_V_DS 16 /* offset to space */
#define VA_V_MODE 17 /* offset to mode */
#define VA_DS (1u << VA_V_DS) /* data space flag */
/* Unibus map (if present) */
#define UBM_LNT_LW 32 /* size in LW */
#define UBM_V_PN 13 /* page number */
#define UBM_M_PN 037
#define UBM_V_OFF 0 /* offset */
#define UBM_M_OFF 017777
#define UBM_PAGSIZE (UBM_M_OFF + 1) /* page size */
#define UBM_GETPN(x) (((x) >> UBM_V_PN) & UBM_M_PN)
#define UBM_GETOFF(x) ((x) & UBM_M_OFF)
/* CPUERR */
#define CPUE_RED 0004 /* red stack */
#define CPUE_YEL 0010 /* yellow stack */
#define CPUE_TMO 0020 /* IO page nxm */
#define CPUE_NXM 0040 /* memory nxm */
#define CPUE_ODD 0100 /* odd address */
#define CPUE_HALT 0200 /* HALT not kernel */
#define CPUE_IMP 0374 /* implemented bits */
/* Floating point accumulators */
typedef struct {
uint32 l; /* low 32b */
uint32 h; /* high 32b */
} fpac_t;
/* Device CSRs */
#define CSR_V_GO 0 /* go */
#define CSR_V_IE 6 /* interrupt enable */
#define CSR_V_DONE 7 /* done */
#define CSR_V_BUSY 11 /* busy */
#define CSR_V_ERR 15 /* error */
#define CSR_GO (1u << CSR_V_GO)
#define CSR_IE (1u << CSR_V_IE)
#define CSR_DONE (1u << CSR_V_DONE)
#define CSR_BUSY (1u << CSR_V_BUSY)
#define CSR_ERR (1u << CSR_V_ERR)
/* Trap masks, descending priority order, following J-11
An interrupt summary bit is kept with traps, to minimize overhead
*/
#define TRAP_V_RED 0 /* red stk abort 4 */
#define TRAP_V_ODD 1 /* odd address 4 */
#define TRAP_V_MME 2 /* mem mgt 250 */
#define TRAP_V_NXM 3 /* nx memory 4 */
#define TRAP_V_PAR 4 /* parity err 114 */
#define TRAP_V_PRV 5 /* priv inst 4 */
#define TRAP_V_ILL 6 /* illegal inst 10 */
#define TRAP_V_BPT 7 /* BPT 14 */
#define TRAP_V_IOT 8 /* IOT 20 */
#define TRAP_V_EMT 9 /* EMT 30 */
#define TRAP_V_TRAP 10 /* TRAP 34 */
#define TRAP_V_TRC 11 /* T bit 14 */
#define TRAP_V_YEL 12 /* stack 4 */
#define TRAP_V_PWRFL 13 /* power fail 24 */
#define TRAP_V_FPE 14 /* fpe 244 */
#define TRAP_V_MAX 15 /* intr = max trp # */
#define TRAP_RED (1u << TRAP_V_RED)
#define TRAP_ODD (1u << TRAP_V_ODD)
#define TRAP_MME (1u << TRAP_V_MME)
#define TRAP_NXM (1u << TRAP_V_NXM)
#define TRAP_PAR (1u << TRAP_V_PAR)
#define TRAP_PRV (1u << TRAP_V_PRV)
#define TRAP_ILL (1u << TRAP_V_ILL)
#define TRAP_BPT (1u << TRAP_V_BPT)
#define TRAP_IOT (1u << TRAP_V_IOT)
#define TRAP_EMT (1u << TRAP_V_EMT)
#define TRAP_TRAP (1u << TRAP_V_TRAP)
#define TRAP_TRC (1u << TRAP_V_TRC)
#define TRAP_YEL (1u << TRAP_V_YEL)
#define TRAP_PWRFL (1u << TRAP_V_PWRFL)
#define TRAP_FPE (1u << TRAP_V_FPE)
#define TRAP_INT (1u << TRAP_V_MAX)
#define TRAP_ALL ((1u << TRAP_V_MAX) - 1) /* all traps */
#define VEC_RED 0004 /* trap vectors */
#define VEC_ODD 0004
#define VEC_MME 0250
#define VEC_NXM 0004
#define VEC_PAR 0114
#define VEC_PRV 0004
#define VEC_ILL 0010
#define VEC_BPT 0014
#define VEC_IOT 0020
#define VEC_EMT 0030
#define VEC_TRAP 0034
#define VEC_TRC 0014
#define VEC_YEL 0004
#define VEC_PWRFL 0024
#define VEC_FPE 0244
/* Simulator stop codes; codes 1:TRAP_V_MAX correspond to traps 0:TRAPMAX-1 */
#define STOP_HALT (TRAP_V_MAX + 1) /* HALT instruction */
#define STOP_IBKPT (TRAP_V_MAX + 2) /* instruction bkpt */
#define STOP_WAIT (TRAP_V_MAX + 3) /* wait, no events */
#define STOP_VECABORT (TRAP_V_MAX + 4) /* abort vector read */
#define STOP_SPABORT (TRAP_V_MAX + 5) /* abort trap push */
#define STOP_RQ (TRAP_V_MAX + 6) /* RQDX3 panic */
#define STOP_SANITY (TRAP_V_MAX + 7) /* sanity timer exp */
#define STOP_DTOFF (TRAP_V_MAX + 8) /* DECtape off reel */
#define IORETURN(f,v) ((f)? (v): SCPE_OK) /* cond error return */
/* Timers */
#define TMR_CLK 0 /* line clock */
#define TMR_PCLK 1 /* KW11P */
/* IO parameters */
#define DZ_MUXES 4 /* max # of DZ muxes */
#define DZ_LINES 8 /* lines per DZ mux */
#define VH_MUXES 4 /* max # of VH muxes */
#define DLX_LINES 16 /* max # of KL11/DL11's */
#define DCX_LINES 16 /* max # of DC11's */
#define MT_MAXFR (1 << 16) /* magtape max rec */
#define AUTO_LNT 34 /* autoconfig ranks */
#define DIB_MAX 100 /* max DIBs */
#define DEV_V_UBUS (DEV_V_UF + 0) /* Unibus */
#define DEV_V_QBUS (DEV_V_UF + 1) /* Qbus */
#define DEV_V_Q18 (DEV_V_UF + 2) /* Qbus with <= 256KB */
#define DEV_V_FLTA (DEV_V_UF + 3) /* flt addr */
#define DEV_V_MBUS (DEV_V_UF + 4) /* Massbus */
#define DEV_V_FFUF (DEV_V_UF + 5) /* first free flag */
#define DEV_UBUS (1u << DEV_V_UBUS)
#define DEV_QBUS (1u << DEV_V_QBUS)
#define DEV_Q18 (1u << DEV_V_Q18)
#define DEV_FLTA (1u << DEV_V_FLTA)
#define DEV_MBUS (1u << DEV_V_MBUS)
#define DEV_RDX 8 /* default device radix */
/* Device information block */
#define VEC_DEVMAX 4 /* max device vec */
struct pdp_dib {
uint32 ba; /* base addr */
uint32 lnt; /* length */
t_stat (*rd)(int32 *dat, int32 ad, int32 md);
t_stat (*wr)(int32 dat, int32 ad, int32 md);
int32 vnum; /* vectors: number */
int32 vloc; /* locator */
int32 vec; /* value */
int32 (*ack[VEC_DEVMAX])(void); /* ack routines */
};
typedef struct pdp_dib DIB;
/* I/O page layout - XUB, RQB,RQC,RQD float based on number of DZ's */
#define IOBA_DZ (IOPAGEBASE + 000100) /* DZ11 */
#define IOLN_DZ 010
#define IOBA_XUB (IOPAGEBASE + 000330 + (020 * (DZ_MUXES / 2)))
#define IOLN_XUB 010
#define IOBA_RQB (IOPAGEBASE + 000334 + (020 * (DZ_MUXES / 2)))
#define IOLN_RQB 004
#define IOBA_RQC (IOBA_RQB + IOLN_RQB)
#define IOLN_RQC 004
#define IOBA_RQD (IOBA_RQC + IOLN_RQC)
#define IOLN_RQD 004
#define IOBA_VH (IOPAGEBASE + 000440) /* DHQ11 */
#define IOLN_VH 020
#define IOBA_UBM (IOPAGEBASE + 010200) /* Unibus map */
#define IOLN_UBM (UBM_LNT_LW * sizeof (int32))
#define IOBA_KG (IOPAGEBASE + 010700) /* KG11-A */
#define IOLN_KG 006
#define IOBA_RQ (IOPAGEBASE + 012150) /* RQDX3 */
#define IOLN_RQ 004
#define IOBA_SUP (IOPAGEBASE + 012200) /* supervisor APR's */
#define IOLN_SUP 0100
#define IOBA_KIPDR (IOPAGEBASE + 012300) /* kernel APR's */
#define IOLN_KIPDR 020
#define IOBA_KDPDR (IOPAGEBASE + 012320)
#define IOLN_KDPDR 020
#define IOBA_KIPAR (IOPAGEBASE + 012340)
#define IOLN_KIPAR 020
#define IOBA_KDPAR (IOPAGEBASE + 012360)
#define IOLN_KDPAR 020
#define IOBA_TU (IOPAGEBASE + 012440) /* TU */
#define IOLN_TU 040
#define IOBA_MMR3 (IOPAGEBASE + 012516) /* MMR3 */
#define IOLN_MMR3 002
#define IOBA_TM (IOPAGEBASE + 012520) /* TM11 */
#define IOLN_TM 014
#define IOBA_TS (IOPAGEBASE + 012520) /* TS11 */
#define IOLN_TS 004
#define IOBA_PCLK (IOPAGEBASE + 012540) /* KW11P */
#define IOLN_PCLK 006
#define IOBA_DC (IOPAGEBASE + 014000) /* DC11 */
#define IOLN_DC (DCX_LINES * 010)
#define IOBA_RL (IOPAGEBASE + 014400) /* RL11 */
#define IOLN_RL 012
#define IOBA_XQ (IOPAGEBASE + 014440) /* DEQNA/DELQA */
#define IOLN_XQ 020
#define IOBA_XQB (IOPAGEBASE + 014460) /* 2nd DEQNA/DELQA */
#define IOLN_XQB 020
#define IOBA_TQ (IOPAGEBASE + 014500) /* TMSCP */
#define IOLN_TQ 004
#define IOBA_XU (IOPAGEBASE + 014510) /* DEUNA/DELUA */
#define IOLN_XU 010
#define IOBA_DL (IOPAGEBASE + 016500) /* extra KL11/DL11 */
#define IOLN_DL (DLX_LINES * 010)
#define IOBA_RP (IOPAGEBASE + 016700) /* RP/RM */
#define IOLN_RP 054
#define IOBA_CR (IOPAGEBASE + 017160) /* CD/CR/CM */
#define IOLN_CR 010
#define IOBA_RX (IOPAGEBASE + 017170) /* RX11 */
#define IOLN_RX 004
#define IOBA_RY (IOPAGEBASE + 017170) /* RY11 */
#define IOLN_RY 004
#define IOBA_KE (IOPAGEBASE + 017300) /* KE11-A */
#define IOLN_KE 020
#define IOBA_TC (IOPAGEBASE + 017340) /* TC11 */
#define IOLN_TC 012
#define IOBA_QDSS (IOPAGEBASE + 017400) /* QDSS */
#define IOLN_QDSS 002
#define IOBA_RK (IOPAGEBASE + 017400) /* RK11 */
#define IOLN_RK 020
#define IOBA_RC (IOPAGEBASE + 017440) /* RC11/RS64 */
#define IOLN_RC 020
#define IOBA_HK (IOPAGEBASE + 017440) /* RK611 */
#define IOLN_HK 040
#define IOBA_RF (IOPAGEBASE + 017460) /* RF11 */
#define IOLN_RF 020
#define IOBA_TA (IOPAGEBASE + 017500) /* TA11 */
#define IOLN_TA 004
#define IOBA_LPT (IOPAGEBASE + 017514) /* LP11 */
#define IOLN_LPT 004
#define IOBA_CTL (IOPAGEBASE + 017520) /* board ctrl */
#define IOLN_CTL 010
#define IOBA_CLK (IOPAGEBASE + 017546) /* KW11L */
#define IOLN_CLK 002
#define IOBA_PTR (IOPAGEBASE + 017550) /* PC11 reader */
#define IOLN_PTR 004
#define IOBA_PTP (IOPAGEBASE + 017554) /* PC11 punch */
#define IOLN_PTP 004
#define IOBA_TTI (IOPAGEBASE + 017560) /* DL11 rcv */
#define IOLN_TTI 004
#define IOBA_TTO (IOPAGEBASE + 017564) /* DL11 xmt */
#define IOLN_TTO 004
#define IOBA_SR (IOPAGEBASE + 017570) /* SR */
#define IOLN_SR 002
#define IOBA_MMR012 (IOPAGEBASE + 017572) /* MMR0-2 */
#define IOLN_MMR012 006
#define IOBA_UIPDR (IOPAGEBASE + 017600) /* user APR's */
#define IOLN_UIPDR 020
#define IOBA_UDPDR (IOPAGEBASE + 017620)
#define IOLN_UDPDR 020
#define IOBA_UIPAR (IOPAGEBASE + 017640)
#define IOLN_UIPAR 020
#define IOBA_UDPAR (IOPAGEBASE + 017660)
#define IOLN_UDPAR 020
#define IOBA_GPR (IOPAGEBASE + 017700) /* GPR's */
#define IOLN_GPR 010
#define IOBA_UCTL (IOPAGEBASE + 017730) /* UBA ctrl */
#define IOLN_UCTL 010
#define IOBA_CPU (IOPAGEBASE + 017740) /* CPU reg */
#define IOLN_CPU 036
#define IOBA_PSW (IOPAGEBASE + 017776) /* PSW */
#define IOLN_PSW 002
/* Interrupt assignments; within each level, priority is right to left
PIRQn has the highest priority with a level and is always bit <0>
On level 6, the clock is second highest priority */
#define IPL_HLVL 8 /* # int levels */
#define IPL_HMIN 4 /* lowest IO int level */
#define INT_V_PIR7 0 /* BR7 */
#define INT_V_PIR6 0 /* BR6 */
#define INT_V_CLK 1
#define INT_V_PCLK 2
#define INT_V_DTA 3
#define INT_V_TA 4
#define INT_V_PIR5 0 /* BR5 */
#define INT_V_RK 1
#define INT_V_RL 2
#define INT_V_RX 3
#define INT_V_TM 4
#define INT_V_RP 5
#define INT_V_TS 6
#define INT_V_HK 7
#define INT_V_RQ 8
#define INT_V_DZRX 9
#define INT_V_DZTX 10
#define INT_V_TQ 11
#define INT_V_RY 12
#define INT_V_XQ 13
#define INT_V_XU 14
#define INT_V_TU 15
#define INT_V_RF 16
#define INT_V_RC 17
#define INT_V_PIR4 0 /* BR4 */
#define INT_V_TTI 1
#define INT_V_TTO 2
#define INT_V_PTR 3
#define INT_V_PTP 4
#define INT_V_LPT 5
#define INT_V_VHRX 6
#define INT_V_VHTX 7
#define INT_V_CR 8
#define INT_V_DLI 9
#define INT_V_DLO 10
#define INT_V_DCI 11
#define INT_V_DCO 12
#define INT_V_PIR3 0 /* BR3 */
#define INT_V_PIR2 0 /* BR2 */
#define INT_V_PIR1 0 /* BR1 */
#define INT_PIR7 (1u << INT_V_PIR7)
#define INT_PIR6 (1u << INT_V_PIR6)
#define INT_CLK (1u << INT_V_CLK)
#define INT_PCLK (1u << INT_V_PCLK)
#define INT_DTA (1u << INT_V_DTA)
#define INT_TA (1u << INT_V_TA)
#define INT_PIR5 (1u << INT_V_PIR5)
#define INT_RK (1u << INT_V_RK)
#define INT_RL (1u << INT_V_RL)
#define INT_RX (1u << INT_V_RX)
#define INT_TM (1u << INT_V_TM)
#define INT_RP (1u << INT_V_RP)
#define INT_TS (1u << INT_V_TS)
#define INT_HK (1u << INT_V_HK)
#define INT_RQ (1u << INT_V_RQ)
#define INT_DZRX (1u << INT_V_DZRX)
#define INT_DZTX (1u << INT_V_DZTX)
#define INT_TQ (1u << INT_V_TQ)
#define INT_RY (1u << INT_V_RY)
#define INT_XQ (1u << INT_V_XQ)
#define INT_XU (1u << INT_V_XU)
#define INT_TU (1u << INT_V_TU)
#define INT_RF (1u << INT_V_RF)
#define INT_RC (1u << INT_V_RC)
#define INT_PIR4 (1u << INT_V_PIR4)
#define INT_TTI (1u << INT_V_TTI)
#define INT_TTO (1u << INT_V_TTO)
#define INT_PTR (1u << INT_V_PTR)
#define INT_PTP (1u << INT_V_PTP)
#define INT_LPT (1u << INT_V_LPT)
#define INT_VHRX (1u << INT_V_VHRX)
#define INT_VHTX (1u << INT_V_VHTX)
#define INT_CR (1u << INT_V_CR)
#define INT_DLI (1u << INT_V_DLI)
#define INT_DLO (1u << INT_V_DLO)
#define INT_DCI (1u << INT_V_DCI)
#define INT_DCO (1u << INT_V_DCO)
#define INT_PIR3 (1u << INT_V_PIR3)
#define INT_PIR2 (1u << INT_V_PIR2)
#define INT_PIR1 (1u << INT_V_PIR1)
#define INT_INTERNAL7 (INT_PIR7)
#define INT_INTERNAL6 (INT_PIR6 | INT_CLK)
#define INT_INTERNAL5 (INT_PIR5)
#define INT_INTERNAL4 (INT_PIR4)
#define INT_INTERNAL3 (INT_PIR3)
#define INT_INTERNAL2 (INT_PIR2)
#define INT_INTERNAL1 (INT_PIR1)
#define IPL_CLK 6 /* int pri levels */
#define IPL_PCLK 6
#define IPL_DTA 6
#define IPL_TA 6
#define IPL_RK 5
#define IPL_RL 5
#define IPL_RX 5
#define IPL_TM 5
#define IPL_RP 5
#define IPL_TS 5
#define IPL_HK 5
#define IPL_RQ 5
#define IPL_DZRX 5
#define IPL_DZTX 5
#define IPL_TQ 5
#define IPL_RY 5
#define IPL_XQ 5
#define IPL_XU 5
#define IPL_TU 5
#define IPL_RF 5
#define IPL_RC 5
#define IPL_PTR 4
#define IPL_PTP 4
#define IPL_TTI 4
#define IPL_TTO 4
#define IPL_LPT 4
#define IPL_VHRX 4
#define IPL_VHTX 4
#define IPL_CR 4
#define IPL_DLI 4
#define IPL_DLO 4
#define IPL_DCI 4
#define IPL_DCO 4
#define IPL_PIR7 7
#define IPL_PIR6 6
#define IPL_PIR5 5
#define IPL_PIR4 4
#define IPL_PIR3 3
#define IPL_PIR2 2
#define IPL_PIR1 1
/* Device vectors */
#define VEC_Q 0000 /* vector base */
#define VEC_PIRQ 0240
#define VEC_TTI 0060
#define VEC_TTO 0064
#define VEC_PTR 0070
#define VEC_PTP 0074
#define VEC_CLK 0100
#define VEC_PCLK 0104
#define VEC_XQ 0120
#define VEC_XU 0120
#define VEC_RQ 0154
#define VEC_RL 0160
#define VEC_LPT 0200
#define VEC_RF 0204
#define VEC_HK 0210
#define VEC_RC 0210
#define VEC_RK 0220
#define VEC_DTA 0214
#define VEC_TM 0224
#define VEC_TS 0224
#define VEC_TU 0224
#define VEC_CR 0230
#define VEC_RP 0254
#define VEC_TQ 0260
#define VEC_TA 0260
#define VEC_RX 0264
#define VEC_RY 0264
#define VEC_DLI 0300
#define VEC_DLO 0304
#define VEC_DCI 0300
#define VEC_DCO 0304
#define VEC_DZRX 0300
#define VEC_DZTX 0304
#define VEC_VHRX 0310
#define VEC_VHTX 0314
/* Interrupt macros */
#define IVCL(dv) ((IPL_##dv * 32) + INT_V_##dv)
#define IREQ(dv) int_req[IPL_##dv]
#define SET_INT(dv) int_req[IPL_##dv] = int_req[IPL_##dv] | (INT_##dv)
#define CLR_INT(dv) int_req[IPL_##dv] = int_req[IPL_##dv] & ~(INT_##dv)
/* Massbus definitions */
#define MBA_NUM 2 /* number of MBA's */
#define MBA_RP 0 /* MBA for RP */
#define MBA_TU 1 /* MBA for TU */
#define MBA_RMASK 037 /* max 32 reg */
#define MBE_NXD 1 /* nx drive */
#define MBE_NXR 2 /* nx reg */
#define MBE_GOE 3 /* err on GO */
/* CPU and FPU macros */
#define update_MM ((MMR0 & MMR0_FREEZE) == 0)
#define setTRAP(name) trap_req = trap_req | (name)
#define setCPUERR(name) CPUERR = CPUERR | (name)
#define ABORT(val) longjmp (save_env, (val))
#define SP R[6]
#define PC R[7]
/* Function prototypes */
int32 Map_ReadB (uint32 ba, int32 bc, uint8 *buf);
int32 Map_ReadW (uint32 ba, int32 bc, uint16 *buf);
int32 Map_WriteB (uint32 ba, int32 bc, uint8 *buf);
int32 Map_WriteW (uint32 ba, int32 bc, uint16 *buf);
int32 mba_rdbufW (uint32 mbus, int32 bc, uint16 *buf);
int32 mba_wrbufW (uint32 mbus, int32 bc, uint16 *buf);
int32 mba_chbufW (uint32 mbus, int32 bc, uint16 *buf);
int32 mba_get_bc (uint32 mbus);
int32 mba_get_csr (uint32 mbus);
void mba_upd_ata (uint32 mbus, uint32 val);
void mba_set_exc (uint32 mbus);
void mba_set_don (uint32 mbus);
void mba_set_enbdis (uint32 mb, t_bool dis);
t_stat mba_show_num (FILE *st, UNIT *uptr, int32 val, void *desc);
int32 clk_cosched (int32 wait);
#include "pdp11_io_lib.h"
#endif

856
PDP11/old/pdp11_rh.c Normal file
View File

@@ -0,0 +1,856 @@
/* pdp11_rh.c: PDP-11 Massbus adapter simulator
Copyright (c) 2005-2012, 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"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
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
in this Software without prior written authorization from Robert M Supnik.
rha, rhb RH11/RH70 Massbus adapter
19-Mar-12 RMS Fixed declaration of cpu_opt (Mark Pizzolato)
02-Feb-08 RMS Fixed DMA memory address limit test (John Dundas)
17-May-07 RMS Moved CS1 drive enable to devices
21-Nov-05 RMS Added enable/disable routine
07-Jul-05 RMS Removed extraneous externs
WARNING: The interupt logic of the RH11/RH70 is unusual and must be
simulated with great precision. The RH11 has an internal interrupt
request flop, CSTB INTR, which is controlled as follows:
- Writing IE and DONE simultaneously sets CSTB INTR
- Controller clear, INIT, and interrupt acknowledge clear CSTB INTR
(and also clear IE)
- A transition of DONE from 0 to 1 sets CSTB INTR from IE
The output of CSTB INTR is OR'd with the AND of RPCS1<SC,DONE,IE> to
create the interrupt request signal. Thus,
- The DONE interrupt is edge sensitive, but the SC interrupt is
level sensitive.
- The DONE interrupt, once set, is not disabled if IE is cleared,
but the SC interrupt is.
*/
#if defined (VM_PDP10) /* PDP10 version */
#error "PDP-10 uses pdp10_rp.c and pdp10_tu.c!"
#elif defined (VM_VAX) /* VAX version */
#error "VAX uses vax780_mba.c!"
#else /* PDP-11 version */
#include "pdp11_defs.h"
#endif
/* CS1 - base + 000 - control/status 1 */
#define CS1_OF 0
#define CS1_GO CSR_GO /* go */
#define CS1_V_FNC 1 /* function pos */
#define CS1_M_FNC 037 /* function mask */
#define CS1_FNC (CS1_M_FNC << CS1_V_FNC)
#define FNC_XFER 024 /* >=? data xfr */
#define CS1_IE CSR_IE /* int enable */
#define CS1_DONE CSR_DONE /* ready */
#define CS1_V_UAE 8 /* Unibus addr ext */
#define CS1_M_UAE 03
#define CS1_UAE (CS1_M_UAE << CS1_V_UAE)
#define CS1_MCPE 0020000 /* Mbus par err NI */
#define CS1_TRE 0040000 /* transfer err */
#define CS1_SC 0100000 /* special cond */
#define CS1_MBZ 0012000
#define CS1_DRV (CS1_FNC | CS1_GO)
#define GET_FNC(x) (((x) >> CS1_V_FNC) & CS1_M_FNC)
/* WC - base + 002 - word count */
#define WC_OF 1
/* BA - base + 004 - base address */
#define BA_OF 2
#define BA_MBZ 0000001 /* must be zero */
/* CS2 - base + 010 - control/status 2 */
#define CS2_OF 3
#define CS2_V_UNIT 0 /* unit pos */
#define CS2_M_UNIT 07 /* unit mask */
#define CS2_UNIT (CS2_M_UNIT << CS2_V_UNIT)
#define CS2_UAI 0000010 /* addr inhibit */
#define CS2_PAT 0000020 /* parity test NI */
#define CS2_CLR 0000040 /* controller clear */
#define CS2_IR 0000100 /* input ready */
#define CS2_OR 0000200 /* output ready */
#define CS2_MDPE 0000400 /* Mbus par err NI */
#define CS2_MXF 0001000 /* missed xfer NI */
#define CS2_PGE 0002000 /* program err */
#define CS2_NEM 0004000 /* nx mem err */
#define CS2_NED 0010000 /* nx drive err */
#define CS2_PE 0020000 /* parity err NI */
#define CS2_WCE 0040000 /* write check err */
#define CS2_DLT 0100000 /* data late NI */
#define CS2_MBZ (CS2_CLR)
#define CS2_RW (CS2_UNIT | CS2_UAI | CS2_PAT | CS2_MXF | CS2_PE)
#define CS2_ERR (CS2_MDPE | CS2_MXF | CS2_PGE | CS2_NEM | \
CS2_NED | CS2_PE | CS2_WCE | CS2_DLT)
#define GET_UNIT(x) (((x) >> CS2_V_UNIT) & CS2_M_UNIT)
/* DB - base + 022 - data buffer */
#define DB_OF 4
/* BAE - base + 050/34 - bus address extension */
#define BAE_OF 5
#define AE_M_MAE 0 /* addr ext pos */
#define AE_V_MAE 077 /* addr ext mask */
#define AE_MBZ 0177700
/* CS3 - base + 052/36 - control/status 3 */
#define CS3_OF 6
#define CS3_APE 0100000 /* addr perr - NI */
#define CS3_DPO 0040000 /* data perr odd - NI */
#define CS3_DPE 0020000 /* data perr even - NI */
#define CS3_WCO 0010000 /* wchk err odd */
#define CS3_WCE 0004000 /* wchk err even */
#define CS3_DBL 0002000 /* dbl word xfer - NI */
#define CS3_IPCK 0000017 /* wrong par - NI */
#define CS3_ERR (CS3_APE|CS3_DPO|CS3_DPE|CS3_WCO|CS3_WCE)
#define CS3_MBZ 0001660
#define CS3_RW (CS1_IE | CS3_IPCK)
#define MBA_OFSMASK 077 /* max 32 reg */
#define INT 0000 /* int reg flag */
#define EXT 0100 /* ext reg flag */
/* Declarations */
#define RH11 (cpu_opt & OPT_RH11)
typedef struct {
uint32 cs1; /* ctrl/status 1 */
uint32 wc; /* word count */
uint32 ba; /* bus addr */
uint32 cs2; /* ctrl/status 2 */
uint32 db; /* data buffer */
uint32 bae; /* addr ext */
uint32 cs3; /* ctrl/status 3 */
uint32 iff; /* int flip flop */
} MBACTX;
MBACTX massbus[MBA_NUM];
extern uint32 cpu_opt;
extern int32 cpu_bme;
extern uint16 *M;
extern int32 int_req[IPL_HLVL];
extern t_addr cpu_memsize;
extern FILE *sim_deb;
extern FILE *sim_log;
extern int32 sim_switches;
t_stat mba_reset (DEVICE *dptr);
t_stat mba_rd (int32 *val, int32 pa, int32 access);
t_stat mba_wr (int32 val, int32 pa, int32 access);
t_stat mba_set_type (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat mba_show_type (FILE *st, UNIT *uptr, int32 val, void *desc);
int32 mba0_inta (void);
int32 mba1_inta (void);
void mba_set_int (uint32 mb);
void mba_clr_int (uint32 mb);
void mba_upd_cs1 (uint32 set, uint32 clr, uint32 mb);
void mba_set_cs2 (uint32 flg, uint32 mb);
uint32 mba_map_pa (int32 pa, int32 *ofs);
DEVICE mba0_dev, mba1_dev;
extern uint32 Map_Addr (uint32 ba);
/* Massbus register dispatches */
static t_stat (*mbregR[MBA_NUM])(int32 *dat, int32 ad, int32 md);
static t_stat (*mbregW[MBA_NUM])(int32 dat, int32 ad, int32 md);
static int32 (*mbabort[MBA_NUM])(void);
/* Unibus to register offset map */
static int32 mba_mapofs[(MBA_OFSMASK + 1) >> 1] = {
INT|0, INT|1, INT|2, EXT|5, INT|3, EXT|1, EXT|2, EXT|4,
EXT|7, INT|4, EXT|3, EXT|6, EXT|8, EXT|9, EXT|10, EXT|11,
EXT|12, EXT|13, EXT|14, EXT|15, EXT|16, EXT|17, EXT|18, EXT|19,
EXT|20, EXT|21, EXT|22, EXT|23, EXT|24, EXT|25, EXT|26, EXT|27
};
/* Massbus adapter data structures
mbax_dev RHx device descriptor
mbax_unit RHx units
mbax_reg RHx register list
*/
DIB mba0_dib = {
IOBA_RP, IOLN_RP, &mba_rd, &mba_wr,
1, IVCL (RP), VEC_RP, { &mba0_inta }
};
UNIT mba0_unit = { UDATA (NULL, 0, 0) };
REG mba0_reg[] = {
{ ORDATA (CS1, massbus[0].cs1, 16) },
{ ORDATA (WC, massbus[0].wc, 16) },
{ ORDATA (BA, massbus[0].ba, 16) },
{ ORDATA (CS2, massbus[0].cs2, 16) },
{ ORDATA (DB, massbus[0].db, 16) },
{ ORDATA (BAE, massbus[0].bae, 6) },
{ ORDATA (CS3, massbus[0].cs3, 16) },
{ FLDATA (IFF, massbus[0].iff, 0) },
{ FLDATA (INT, IREQ (RP), INT_V_RP) },
{ FLDATA (SC, massbus[0].cs1, CSR_V_ERR) },
{ FLDATA (DONE, massbus[0].cs1, CSR_V_DONE) },
{ FLDATA (IE, massbus[0].cs1, CSR_V_IE) },
{ ORDATA (DEVADDR, mba0_dib.ba, 32), REG_HRO },
{ ORDATA (DEVVEC, mba0_dib.vec, 16), REG_HRO },
{ NULL }
};
MTAB mba0_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0100, "ADDRESS", "ADDRESS",
&set_addr, &show_addr, NULL },
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR",
&set_vec, &show_vec, NULL },
{ 0 }
};
DIB mba1_dib = {
IOBA_TU, IOLN_TU, &mba_rd, &mba_wr,
1, IVCL (TU), VEC_TU, { &mba1_inta }
};
UNIT mba1_unit = { UDATA (NULL, 0, 0) };
REG mba1_reg[] = {
{ ORDATA (CS1, massbus[1].cs1, 16) },
{ ORDATA (WC, massbus[1].wc, 16) },
{ ORDATA (BA, massbus[1].ba, 16) },
{ ORDATA (CS2, massbus[1].cs2, 16) },
{ ORDATA (DB, massbus[1].db, 16) },
{ ORDATA (BAE, massbus[1].bae, 6) },
{ ORDATA (CS3, massbus[1].cs3, 16) },
{ FLDATA (IFF, massbus[1].iff, 0) },
{ FLDATA (INT, IREQ (TU), INT_V_TU) },
{ FLDATA (SC, massbus[1].cs1, CSR_V_ERR) },
{ FLDATA (DONE, massbus[1].cs1, CSR_V_DONE) },
{ FLDATA (IE, massbus[1].cs1, CSR_V_IE) },
{ ORDATA (DEVADDR, mba1_dib.ba, 32), REG_HRO },
{ ORDATA (DEVVEC, mba1_dib.vec, 16), REG_HRO },
{ NULL }
};
MTAB mba1_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0040, "ADDRESS", "ADDRESS",
&set_addr, &show_addr, NULL },
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR",
&set_vec, &show_vec, NULL },
{ 0 }
};
DEVICE mba_dev[] = {
{
"RHA", &mba0_unit, mba0_reg, mba0_mod,
1, 0, 0, 0, 0, 0,
NULL, NULL, &mba_reset,
NULL, NULL, NULL,
&mba0_dib, DEV_DEBUG | DEV_DISABLE | DEV_UBUS | DEV_QBUS
},
{
"RHB", &mba1_unit, mba1_reg, mba1_mod,
1, 0, 0, 0, 0, 0,
NULL, NULL, &mba_reset,
NULL, NULL, NULL,
&mba1_dib, DEV_DEBUG | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS
}
};
/* Read Massbus adapter register */
t_stat mba_rd (int32 *val, int32 pa, int32 mode)
{
int32 ofs, dat, mb, drv;
t_stat r;
mb = mba_map_pa (pa, &ofs); /* get mb number */
if ((mb < 0) || (ofs < 0)) /* valid? */
return SCPE_NXM;
drv = GET_UNIT (massbus[mb].cs2); /* get drive */
mba_upd_cs1 (0, 0, mb); /* update CS1 */
if (ofs & EXT) { /* external? */
if (!mbregR[mb]) /* device there? */
return SCPE_NXM;
r = mbregR[mb] (val, ofs & ~EXT, drv); /* call device */
if (r == MBE_NXD) /* nx drive? */
mba_set_cs2 (CS2_NED, mb);
else if (r == MBE_NXR) /* nx reg? */
return SCPE_NXM;
return SCPE_OK;
}
switch (ofs) { /* case on reg */
case CS1_OF: /* CS1 */
if (!mbregR[mb]) /* nx device? */
return SCPE_NXM;
r = mbregR[mb] (&dat, ofs, drv); /* get dev cs1 */
if (r == MBE_NXD) /* nx drive? */
mba_set_cs2 (CS2_NED, mb);
*val = massbus[mb].cs1 | dat;
break;
case WC_OF: /* WC */
*val = massbus[mb].wc;
break;
case BA_OF: /* BA */
*val = massbus[mb].ba & ~BA_MBZ;
break;
case CS2_OF: /* CS2 */
*val = massbus[mb].cs2 = (massbus[mb].cs2 & ~CS2_MBZ) | CS2_IR | CS2_OR;
break;
case DB_OF: /* DB */
*val = massbus[mb].db;
break;
case BAE_OF: /* BAE */
*val = massbus[mb].bae = massbus[mb].bae & ~AE_MBZ;
break;
case CS3_OF: /* CS3 */
*val = massbus[mb].cs3 = (massbus[mb].cs3 & ~(CS1_IE | CS3_MBZ)) |
(massbus[mb].cs1 & CS1_IE);
break;
default: /* huh? */
return SCPE_NXM;
}
return SCPE_OK;
}
t_stat mba_wr (int32 val, int32 pa, int32 access)
{
int32 ofs, cs1f, drv, mb;
t_stat r;
t_bool cs1dt;
mb = mba_map_pa (pa, &ofs); /* get mb number */
if ((mb < 0) || (ofs < 0)) /* valid? */
return SCPE_NXM;
drv = GET_UNIT (massbus[mb].cs2); /* get drive */
if (ofs & EXT) { /* external? */
if (!mbregW[mb]) /* device there? */
return SCPE_NXM;
if ((access == WRITEB) && (pa & 1)) /* byte writes */
val = val << 8; /* don't work */
r = mbregW[mb] (val, ofs & ~EXT, drv); /* write dev reg */
if (r == MBE_NXD) /* nx drive? */
mba_set_cs2 (CS2_NED, mb);
else if (r == MBE_NXR) /* nx reg? */
return SCPE_NXM;
mba_upd_cs1 (0, 0, mb); /* update status */
return SCPE_OK;
}
cs1f = 0; /* no int on cs1 upd */
switch (ofs) { /* case on reg */
case CS1_OF: /* CS1 */
if (!mbregW[mb]) /* device exist? */
return SCPE_NXM;
if ((access == WRITEB) && (pa & 1))
val = val << 8;
if (val & CS1_TRE) { /* error clear? */
massbus[mb].cs1 &= ~CS1_TRE; /* clr CS1<TRE> */
massbus[mb].cs2 &= ~CS2_ERR; /* clr CS2<15:8> */
massbus[mb].cs3 &= ~CS3_ERR; /* clr CS3<15:11> */
}
if ((access == WRITE) || (pa & 1)) { /* hi byte write? */
if (massbus[mb].cs1 & CS1_DONE) /* done set? */
massbus[mb].cs1 = (massbus[mb].cs1 & ~CS1_UAE) | (val & CS1_UAE);
}
if ((access == WRITE) || !(pa & 1)) { /* lo byte write? */
if ((val & CS1_DONE) && (val & CS1_IE)) /* to DONE+IE? */
massbus[mb].iff = 1; /* set CSTB INTR */
massbus[mb].cs1 = (massbus[mb].cs1 & ~CS1_IE) | (val & CS1_IE);
cs1dt = (val & CS1_GO) && (GET_FNC (val) >= FNC_XFER);
if (cs1dt && ((massbus[mb].cs1 & CS1_DONE) == 0)) /* dt, done clr? */
mba_set_cs2 (CS2_PGE, mb); /* prgm error */
else {
r = mbregW[mb] (val & 077, ofs, drv); /* write dev CS1 */
if (r == MBE_NXD) /* nx drive? */
mba_set_cs2 (CS2_NED, mb);
else if (r == MBE_NXR) /* nx reg? */
return SCPE_NXM;
else if (cs1dt && (r == SCPE_OK)) { /* xfer, no err? */
massbus[mb].cs1 &= ~(CS1_TRE | CS1_MCPE | CS1_DONE);
massbus[mb].cs2 &= ~CS2_ERR; /* clear errors */
massbus[mb].cs3 &= ~(CS3_ERR | CS3_DBL);
}
}
}
massbus[mb].cs3 = (massbus[mb].cs3 & ~CS1_IE) | /* update CS3 */
(massbus[mb].cs1 & CS1_IE);
massbus[mb].bae = (massbus[mb].bae & ~CS1_M_UAE) | /* update BAE */
((massbus[mb].cs1 >> CS1_V_UAE) & CS1_M_UAE);
break;
case WC_OF: /* WC */
if (access == WRITEB)
val = (pa & 1)?
(massbus[mb].wc & 0377) | (val << 8):
(massbus[mb].wc & ~0377) | val;
massbus[mb].wc = val;
break;
case BA_OF: /* BA */
if (access == WRITEB)
val = (pa & 1)?
(massbus[mb].ba & 0377) | (val << 8):
(massbus[mb].ba & ~0377) | val;
massbus[mb].ba = val & ~BA_MBZ;
break;
case CS2_OF: /* CS2 */
if ((access == WRITEB) && (pa & 1))
val = val << 8;
if (val & CS2_CLR) /* init? */
mba_reset (&mba_dev[mb]);
else {
if ((val & ~massbus[mb].cs2) & (CS2_PE | CS2_MXF))
cs1f = CS1_SC; /* diagn intr */
if (access == WRITEB) /* merge val */
val = (massbus[mb].cs2 & ((pa & 1)? 0377: 0177400)) | val;
massbus[mb].cs2 = (massbus[mb].cs2 & ~CS2_RW) |
(val & CS2_RW) | CS2_IR | CS2_OR;
}
break;
case DB_OF: /* DB */
if (access == WRITEB)
val = (pa & 1)?
(massbus[mb].db & 0377) | (val << 8):
(massbus[mb].db & ~0377) | val;
massbus[mb].db = val;
break;
case BAE_OF: /* BAE */
if ((access == WRITEB) && (pa & 1))
break;
massbus[mb].bae = val & ~AE_MBZ;
massbus[mb].cs1 = (massbus[mb].cs1 & ~CS1_UAE) | /* update CS1 */
((massbus[mb].bae << CS1_V_UAE) & CS1_UAE);
break;
case CS3_OF: /* CS3 */
if ((access == WRITEB) && (pa & 1))
break;
massbus[mb].cs3 = (massbus[mb].cs3 & ~CS3_RW) | (val & CS3_RW);
massbus[mb].cs1 = (massbus[mb].cs1 & ~CS1_IE) | /* update CS1 */
(massbus[mb].cs3 & CS1_IE);
break;
default:
return SCPE_NXM;
}
mba_upd_cs1 (cs1f, 0, mb); /* update status */
return SCPE_OK;
}
/* Massbus I/O routines
mb_rdbufW - fetch word buffer from memory
mb_wrbufW - store word buffer into memory
mb_chbufW - compare word buffer with memory
Returns number of bytes successfully transferred/checked
*/
int32 mba_rdbufW (uint32 mb, int32 bc, uint16 *buf)
{
int32 i, j, ba, mbc, pbc;
uint32 pa;
bc = bc & ~1; /* bc even */
if (mb >= MBA_NUM) /* valid MBA? */
return 0;
ba = (massbus[mb].bae << 16) | massbus[mb].ba; /* get busaddr */
mbc = (0200000 - massbus[mb].wc) << 1; /* MB byte count */
if (bc > mbc) /* use smaller */
bc = mbc;
for (i = 0; i < bc; i = i + pbc) { /* loop by pages */
if (RH11 && cpu_bme) /* map addr */
pa = Map_Addr (ba);
else pa = ba;
if (!ADDR_IS_MEM (pa)) { /* NXM? */
mba_set_cs2 (CS2_NEM, mb); /* set error */
break;
}
pbc = UBM_PAGSIZE - UBM_GETOFF (pa); /* left in page */
if (pbc > (bc - i)) /* limit to rem xfr */
pbc = bc - i;
for (j = 0; j < pbc; j = j + 2) { /* loop by words */
*buf++ = M[pa >> 1]; /* fetch word */
if (!(massbus[mb].cs2 & CS2_UAI)) { /* if not inhb */
ba = ba + 2; /* incr ba, pa */
pa = pa + 2;
}
}
}
massbus[mb].wc = (massbus[mb].wc + (bc >> 1)) & DMASK; /* update wc */
massbus[mb].ba = ba & DMASK; /* update ba */
massbus[mb].bae = (ba >> 16) & ~AE_MBZ; /* upper 6b */
massbus[mb].cs1 = (massbus[mb].cs1 & ~ CS1_UAE) | /* update CS1 */
((massbus[mb].bae << CS1_V_UAE) & CS1_UAE);
return i;
}
int32 mba_wrbufW (uint32 mb, int32 bc, uint16 *buf)
{
int32 i, j, ba, mbc, pbc;
uint32 pa;
bc = bc & ~1; /* bc even */
if (mb >= MBA_NUM) /* valid MBA? */
return 0;
ba = (massbus[mb].bae << 16) | massbus[mb].ba; /* get busaddr */
mbc = (0200000 - massbus[mb].wc) << 1; /* MB byte count */
if (bc > mbc) /* use smaller */
bc = mbc;
for (i = 0; i < bc; i = i + pbc) { /* loop by pages */
if (RH11 && cpu_bme) /* map addr */
pa = Map_Addr (ba);
else pa = ba;
if (!ADDR_IS_MEM (pa)) { /* NXM? */
mba_set_cs2 (CS2_NEM, mb); /* set error */
break;
}
pbc = UBM_PAGSIZE - UBM_GETOFF (pa); /* left in page */
if (pbc > (bc - i)) /* limit to rem xfr */
pbc = bc - i;
for (j = 0; j < pbc; j = j + 2) { /* loop by words */
M[pa >> 1] = *buf++; /* put word */
if (!(massbus[mb].cs2 & CS2_UAI)) { /* if not inhb */
ba = ba + 2; /* incr ba, pa */
pa = pa + 2;
}
}
}
massbus[mb].wc = (massbus[mb].wc + (bc >> 1)) & DMASK; /* update wc */
massbus[mb].ba = ba & DMASK; /* update ba */
massbus[mb].bae = (ba >> 16) & ~AE_MBZ; /* upper 6b */
massbus[mb].cs1 = (massbus[mb].cs1 & ~ CS1_UAE) | /* update CS1 */
((massbus[mb].bae << CS1_V_UAE) & CS1_UAE);
return i;
}
int32 mba_chbufW (uint32 mb, int32 bc, uint16 *buf)
{
int32 i, j, ba, mbc, pbc;
uint32 pa;
bc = bc & ~1; /* bc even */
if (mb >= MBA_NUM) /* valid MBA? */
return 0;
ba = (massbus[mb].bae << 16) | massbus[mb].ba; /* get busaddr */
mbc = (0200000 - massbus[mb].wc) << 1; /* MB byte count */
if (bc > mbc) /* use smaller */
bc = mbc;
for (i = 0; i < bc; i = i + pbc) { /* loop by pages */
if (RH11 && cpu_bme) pa = Map_Addr (ba); /* map addr */
else pa = ba;
if (!ADDR_IS_MEM (pa)) { /* NXM? */
mba_set_cs2 (CS2_NEM, mb); /* set error */
break;
}
pbc = UBM_PAGSIZE - UBM_GETOFF (pa); /* left in page */
if (pbc > (bc - i)) /* limit to rem xfr */
pbc = bc - i;
for (j = 0; j < pbc; j = j + 2) { /* loop by words */
massbus[mb].db = *buf++; /* get dev word */
if (M[pa >> 1] != massbus[mb].db) { /* miscompare? */
mba_set_cs2 (CS2_WCE, mb); /* set error */
massbus[mb].cs3 = massbus[mb].cs3 | /* set even/odd */
((pa & 1)? CS3_WCO: CS3_WCE);
break;
}
if (!(massbus[mb].cs2 & CS2_UAI)) { /* if not inhb */
ba = ba + 2; /* incr ba, pa */
pa = pa + 2;
}
}
}
massbus[mb].wc = (massbus[mb].wc + (bc >> 1)) & DMASK; /* update wc */
massbus[mb].ba = ba & DMASK; /* update ba */
massbus[mb].bae = (ba >> 16) & ~AE_MBZ; /* upper 6b */
massbus[mb].cs1 = (massbus[mb].cs1 & ~ CS1_UAE) | /* update CS1 */
((massbus[mb].bae << CS1_V_UAE) & CS1_UAE);
return i;
}
/* Device access, status, and interrupt routines */
void mba_set_don (uint32 mb)
{
mba_upd_cs1 (CS1_DONE, 0, mb);
return;
}
void mba_upd_ata (uint32 mb, uint32 val)
{
if (val)
mba_upd_cs1 (CS1_SC, 0, mb);
else mba_upd_cs1 (0, CS1_SC, mb);
return;
}
void mba_set_exc (uint32 mb)
{
mba_upd_cs1 (CS1_TRE | CS1_DONE, 0, mb);
return;
}
int32 mba_get_bc (uint32 mb)
{
if (mb >= MBA_NUM)
return 0;
return ((0200000 - massbus[mb].wc) << 1);
}
int32 mba_get_csr (uint32 mb)
{
DIB *dibp;
if (mb >= MBA_NUM)
return 0;
dibp = (DIB *) mba_dev[mb].ctxt;
return dibp->ba;
}
void mba_set_int (uint32 mb)
{
DIB *dibp;
if (mb >= MBA_NUM)
return;
dibp = (DIB *) mba_dev[mb].ctxt;
int_req[dibp->vloc >> 5] |= (1 << (dibp->vloc & 037));
return;
}
void mba_clr_int (uint32 mb)
{
DIB *dibp;
if (mb >= MBA_NUM)
return;
dibp = (DIB *) mba_dev[mb].ctxt;
int_req[dibp->vloc >> 5] &= ~(1 << (dibp->vloc & 037));
return;
}
void mba_upd_cs1 (uint32 set, uint32 clr, uint32 mb)
{
if (mb >= MBA_NUM)
return;
if ((set & ~massbus[mb].cs1) & CS1_DONE) /* DONE 0 to 1? */
massbus[mb].iff = (massbus[mb].cs1 & CS1_IE)? 1: 0; /* CSTB INTR <- IE */
massbus[mb].cs1 = (massbus[mb].cs1 & ~(clr | CS1_MCPE | CS1_MBZ | CS1_DRV)) | set;
if (massbus[mb].cs2 & CS2_ERR)
massbus[mb].cs1 = massbus[mb].cs1 | CS1_TRE | CS1_SC;
else if (massbus[mb].cs1 & CS1_TRE)
massbus[mb].cs1 = massbus[mb].cs1 | CS1_SC;
if (massbus[mb].iff ||
((massbus[mb].cs1 & CS1_SC) &&
(massbus[mb].cs1 & CS1_DONE) &&
(massbus[mb].cs1 & CS1_IE)))
mba_set_int (mb);
else mba_clr_int (mb);
return;
}
void mba_set_cs2 (uint32 flag, uint32 mb)
{
if (mb >= MBA_NUM)
return;
massbus[mb].cs2 = massbus[mb].cs2 | flag;
mba_upd_cs1 (0, 0, mb);
return;
}
/* Interrupt acknowledge */
int32 mba0_inta (void)
{
massbus[0].cs1 &= ~CS1_IE; /* clear int enable */
massbus[0].cs3 &= ~CS1_IE; /* in both registers */
massbus[0].iff = 0; /* clear CSTB INTR */
return mba0_dib.vec; /* acknowledge */
}
int32 mba1_inta (void)
{
massbus[1].cs1 &= ~CS1_IE; /* clear int enable */
massbus[1].cs3 &= ~CS1_IE; /* in both registers */
massbus[1].iff = 0; /* clear CSTB INTR */
return mba1_dib.vec; /* acknowledge */
}
/* Map physical address to Massbus number, offset */
uint32 mba_map_pa (int32 pa, int32 *ofs)
{
int32 i, uo, ba, lnt;
DIB *dibp;
for (i = 0; i < MBA_NUM; i++) { /* loop thru ctrls */
dibp = (DIB *) mba_dev[i].ctxt; /* get DIB */
ba = dibp->ba;
lnt = dibp->lnt;
if ((pa >= ba) && /* in range? */
(pa < (ba + lnt))) {
if (pa < (ba + (lnt - 4))) { /* not last two? */
uo = ((pa - ba) & MBA_OFSMASK) >> 1; /* get Unibus offset */
*ofs = mba_mapofs[uo]; /* map thru PROM */
return i; /* return ctrl idx */
}
else if (RH11) /* RH11? done */
return -1;
else { /* RH70 */
uo = (pa - (ba + (lnt - 4))) >> 1; /* offset relative */
*ofs = BAE_OF + uo; /* to BAE */
return i;
}
}
}
return -1;
}
/* Reset Massbus adapter */
t_stat mba_reset (DEVICE *dptr)
{
uint32 mb;
mb = dptr - mba_dev;
if (mb >= MBA_NUM)
return SCPE_NOFNC;
massbus[mb].cs1 = CS1_DONE;
massbus[mb].wc = 0;
massbus[mb].ba = 0;
massbus[mb].cs2 = 0;
massbus[mb].db = 0;
massbus[mb].bae= 0;
massbus[mb].cs3 = 0;
massbus[mb].iff = 0;
mba_clr_int (mb);
if (mbabort[mb])
mbabort[mb] ();
return SCPE_OK;
}
/* Enable/disable Massbus adapter */
void mba_set_enbdis (uint32 mb, t_bool dis)
{
if (mb >= MBA_NUM) /* valid MBA? */
return;
if (dis)
mba_dev[mb].flags |= DEV_DIS;
else mba_dev[mb].flags &= ~DEV_DIS;
return;
}
/* Show Massbus adapter number */
t_stat mba_show_num (FILE *st, UNIT *uptr, int32 val, void *desc)
{
DEVICE *dptr = find_dev_from_unit (uptr);
DIB *dibp;
if (dptr == NULL)
return SCPE_IERR;
dibp = (DIB *) dptr->ctxt;
if (dibp == NULL)
return SCPE_IERR;
fprintf (st, "Massbus adapter %d", dibp->ba);
return SCPE_OK;
}
/* Init Mbus tables */
void init_mbus_tab (void)
{
uint32 i;
for (i = 0; i < MBA_NUM; i++) {
mbregR[i] = NULL;
mbregW[i] = NULL;
mbabort[i] = NULL;
}
return;
}
/* Build dispatch tables */
t_stat build_mbus_tab (DEVICE *dptr, DIB *dibp)
{
uint32 idx;
if ((dptr == NULL) || (dibp == NULL)) /* validate args */
return SCPE_IERR;
idx = dibp->ba; /* Mbus # */
if (idx >= MBA_NUM)
return SCPE_STOP;
if ((mbregR[idx] && dibp->rd && /* conflict? */
(mbregR[idx] != dibp->rd)) ||
(mbregW[idx] && dibp->wr &&
(mbregW[idx] != dibp->wr)) ||
(mbabort[idx] && dibp->ack[0] &&
(mbabort[idx] != dibp->ack[0]))) {
printf ("Massbus %s assignment conflict at %d\n",
sim_dname (dptr), dibp->ba);
if (sim_log)
fprintf (sim_log, "Massbus %s assignment conflict at %d\n",
sim_dname (dptr), dibp->ba);
return SCPE_STOP;
}
if (dibp->rd) /* set rd dispatch */
mbregR[idx] = dibp->rd;
if (dibp->wr) /* set wr dispatch */
mbregW[idx] = dibp->wr;
if (dibp->ack[0]) /* set abort dispatch */
mbabort[idx] = dibp->ack[0];
return SCPE_OK;
}

1089
PDP11/old/pdp11_sys.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1324,7 +1324,7 @@ return;
(a^x)(b^y) TMP
Note that the low bit of each digit is the same as the low bit of
the sum of the digits, ignoring the cary, since the low bit of the
the sum of the digits, ignoring the carry, since the low bit of the
sum is the xor of the bits.
Now compute I+J+66 to get decimal addition with carry forced left

View File

@@ -1,6 +1,6 @@
/* pdp11_cpu.c: PDP-11 CPU simulator
Copyright (c) 1993-2012, Robert M Supnik
Copyright (c) 1993-2013, 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"),
@@ -25,6 +25,7 @@
cpu PDP-11 CPU
10-Apr-13 RMS MMR1 does not track PC changes (Johnny Billquist)
29-Apr-12 RMS Fixed compiler warning (Mark Pizzolato)
19-Mar-12 RMS Fixed declaration of sim_switches (Mark Pizzolato)
29-Dec-08 RMS Fixed failure to clear cpu_bme on RESET (Walter Mueller)
@@ -696,7 +697,8 @@ if (abortval != 0) {
if ((trapea > 0) && stop_vecabort)
reason = STOP_VECABORT;
if ((trapea < 0) && /* stack push abort? */
(CPUT (STOP_STKA) || stop_spabort)) reason = STOP_SPABORT;
(CPUT (STOP_STKA) || stop_spabort))
reason = STOP_SPABORT;
if (trapea == ~MD_KER) { /* kernel stk abort? */
setTRAP (TRAP_RED);
setCPUERR (CPUE_RED);
@@ -722,7 +724,7 @@ while (reason == 0) {
cpu_astop = 0;
reason = SCPE_STOP;
break;
}
}
if (sim_interval <= 0) { /* intv cnt expired? */
reason = sim_process_event (); /* process events */
@@ -815,7 +817,7 @@ while (reason == 0) {
if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
reason = STOP_IBKPT; /* stop simulation */
continue;
}
}
if (update_MM) { /* if mm not frozen */
MMR1 = 0;
@@ -913,7 +915,8 @@ while (reason == 0) {
trap_req = calc_ints (ipl, trap_req);
JMP_PC (src);
if (CPUT (HAS_RTT) && tbit && /* RTT impl? */
(IR == 000002)) setTRAP (TRAP_TRC); /* RTI immed trap */
(IR == 000002))
setTRAP (TRAP_TRC); /* RTI immed trap */
break;
case 7: /* MFPT */
if (CPUT (HAS_MFPT)) /* implemented? */
@@ -1358,7 +1361,8 @@ while (reason == 0) {
}
else {
dst = srcreg? R[srcspec]: ReadW (GeteaW (srcspec));
if (!dstreg) ea = GeteaW (dstspec);
if (!dstreg)
ea = GeteaW (dstspec);
}
N = GET_SIGN_W (dst);
Z = GET_Z (dst);
@@ -1894,6 +1898,7 @@ while (reason == 0) {
R[dstspec] = (R[dstspec] & 0177400) | dst;
else PWriteB (dst, last_pa);
break;
/* Notes:
- MTPS cannot alter the T bit
- MxPD must mask GeteaW returned address, dspace is from cm not pm
@@ -1987,7 +1992,8 @@ while (reason == 0) {
}
else {
dst = srcreg? R[srcspec] & 0377: ReadB (GeteaB (srcspec));
if (!dstreg) ea = GeteaB (dstspec);
if (!dstreg)
ea = GeteaB (dstspec);
}
N = GET_SIGN_B (dst);
Z = GET_Z (dst);
@@ -2167,20 +2173,20 @@ switch (spec >> 3) { /* decode spec<5:3> */
case 2: /* (R)+ */
R[reg] = ((adr = R[reg]) + 2) & 0177777;
if (update_MM)
if (update_MM && (reg != 7))
MMR1 = calc_MMR1 (020 | reg);
return (adr | ds);
case 3: /* @(R)+ */
R[reg] = ((adr = R[reg]) + 2) & 0177777;
if (update_MM)
if (update_MM && (reg != 7))
MMR1 = calc_MMR1 (020 | reg);
adr = ReadW (adr | ds);
return (adr | dsenable);
case 4: /* -(R) */
adr = R[reg] = (R[reg] - 2) & 0177777;
if (update_MM)
if (update_MM && (reg != 7))
MMR1 = calc_MMR1 (0360 | reg);
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
set_stack_trap (adr);
@@ -2188,7 +2194,7 @@ switch (spec >> 3) { /* decode spec<5:3> */
case 5: /* @-(R) */
adr = R[reg] = (R[reg] - 2) & 0177777;
if (update_MM)
if (update_MM && (reg != 7))
MMR1 = calc_MMR1 (0360 | reg);
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
set_stack_trap (adr);
@@ -2225,13 +2231,13 @@ switch (spec >> 3) { /* decode spec<5:3> */
case 2: /* (R)+ */
delta = 1 + (reg >= 6); /* 2 if R6, PC */
R[reg] = ((adr = R[reg]) + delta) & 0177777;
if (update_MM)
if (update_MM && (reg != 7))
MMR1 = calc_MMR1 ((delta << 3) | reg);
return (adr | ds);
case 3: /* @(R)+ */
R[reg] = ((adr = R[reg]) + 2) & 0177777;
if (update_MM)
if (update_MM && (reg != 7))
MMR1 = calc_MMR1 (020 | reg);
adr = ReadW (adr | ds);
return (adr | dsenable);
@@ -2239,7 +2245,7 @@ switch (spec >> 3) { /* decode spec<5:3> */
case 4: /* -(R) */
delta = 1 + (reg >= 6); /* 2 if R6, PC */
adr = R[reg] = (R[reg] - delta) & 0177777;
if (update_MM)
if (update_MM && (reg != 7))
MMR1 = calc_MMR1 ((((-delta) & 037) << 3) | reg);
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
set_stack_trap (adr);
@@ -2247,7 +2253,7 @@ switch (spec >> 3) { /* decode spec<5:3> */
case 5: /* @-(R) */
adr = R[reg] = (R[reg] - 2) & 0177777;
if (update_MM)
if (update_MM && (reg != 7))
MMR1 = calc_MMR1 (0360 | reg);
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
set_stack_trap (adr);

View File

@@ -1,6 +1,6 @@
/* pdp11_cpumod.c: PDP-11 CPU model-specific features
Copyright (c) 2004-2008, Robert M Supnik
Copyright (c) 2004-2013, 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"),
@@ -25,6 +25,7 @@
system PDP-11 model-specific registers
06-Jun-13 RMS Fixed change model to set memory size last
20-May-08 RMS Added JCSR default for KDJ11B, KDJ11E
22-Apr-08 RMS Fixed write behavior of 11/70 MBRK, LOSIZE, HISIZE
(Walter Mueller)
@@ -1092,14 +1093,14 @@ if (val >= MOD_MAX)
return SCPE_IERR;
if (val == (int32) cpu_model)
return SCPE_OK;
if (MEMSIZE > cpu_tab[val].maxm)
cpu_set_size (uptr, cpu_tab[val].maxm, NULL, NULL);
if (MEMSIZE > cpu_tab[val].maxm)
return SCPE_INCOMP;
cpu_model = val;
cpu_type = 1u << cpu_model;
cpu_opt = cpu_tab[cpu_model].std;
cpu_set_bus (cpu_opt);
if (MEMSIZE > cpu_tab[val].maxm)
cpu_set_size (uptr, cpu_tab[val].maxm, NULL, NULL);
if (MEMSIZE > cpu_tab[val].maxm)
return SCPE_INCOMP;
reset_all (0); /* reset world */
return SCPE_OK;
}

View File

@@ -87,6 +87,7 @@
Revision History:
06-Jun-13 RMS Default start state is disabled
03-Jan-10 JAD Eliminate gcc warnings
01-Feb-07 RMS Added PDP-10 support
12-May-06 JAD Modify the DEBUG code to use the SIMH DEBUG_x
@@ -181,7 +182,7 @@ extern int32 int_req[IPL_HLVL];
#else /* PDP-11 version */
#include "pdp11_defs.h"
extern int32 int_req[IPL_HLVL];
#define DFLT_DIS (0)
#define DFLT_DIS (DEV_DIS)
#define DFLT_CR11 (UNIT_CR11)
#define DFLT_CPM 285
#endif

View File

@@ -1,6 +1,6 @@
/* pdp11_dc.c: PDP-11 DC11 multiple terminal interface simulator
Copyright (c) 1993-2012, Robert M Supnik
Copyright (c) 1993-2013, 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"),
@@ -25,6 +25,7 @@
dci,dco DC11 terminal input/output
11-Oct-2013 RMS Poll DCI immediately after attach to pick up connect
18-Apr-2012 RMS Modified to use clock coscheduling
17-Aug-2011 RMS Added AUTOCONFIGURE modifier
19-Nov-2008 RMS Revised for common TMXR show routines
@@ -541,7 +542,7 @@ t_stat r;
r = tmxr_attach (&dcx_desc, uptr, cptr); /* attach */
if (r != SCPE_OK) /* error? */
return r;
sim_activate (uptr, tmxr_poll); /* start poll */
sim_activate (uptr, 0); /* start poll at once */
return SCPE_OK;
}

View File

@@ -1,6 +1,6 @@
/* pdp11_defs.h: PDP-11 simulator definitions
Copyright (c) 1993-2011, Robert M Supnik
Copyright (c) 1993-2013, 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"),
@@ -26,6 +26,8 @@
The author gratefully acknowledges the help of Max Burnet, Megan Gentry,
and John Wilson in resolving questions about the PDP-11
02-Sep-13 RMS Added third Massbus adapter and RS drive
12-Dec-12 RMS Fixed base address for RQB, RQC, RQD
11-Dec-11 RMS Fixed priority of PIRQ vs IO; added INT_INTERNALn
22-May-10 RMS Added check for 64b definitions
19-Nov-08 RMS Moved I/O support routines to I/O library
@@ -524,14 +526,16 @@ typedef struct pdp_dib DIB;
#define IOLN_XUB 010
#define IOBA_RQB (IOPAGEBASE + 000334 + (020 * (DZ_MUXES / 2)))
#define IOLN_RQB 004
#define IOBA_RQC (IOPAGEBASE + IOBA_RQB + IOLN_RQB)
#define IOBA_RQC (IOBA_RQB + IOLN_RQB)
#define IOLN_RQC 004
#define IOBA_RQD (IOPAGEBASE + IOBA_RQC + IOLN_RQC)
#define IOBA_RQD (IOBA_RQC + IOLN_RQC)
#define IOLN_RQD 004
#define IOBA_VH (IOPAGEBASE + 000440) /* DHQ11 */
#define IOLN_VH 020
#define IOBA_UBM (IOPAGEBASE + 010200) /* Unibus map */
#define IOLN_UBM (UBM_LNT_LW * sizeof (int32))
#define IOBA_RS (IOPAGEBASE + 012040) /* RHC: RS03/RS04 */
#define IOLN_RS 040
#define IOBA_KG (IOPAGEBASE + 010700) /* KG11-A */
#define IOLN_KG 006
#define IOBA_RQ (IOPAGEBASE + 012150) /* RQDX3 */
@@ -546,7 +550,7 @@ typedef struct pdp_dib DIB;
#define IOLN_KIPAR 020
#define IOBA_KDPAR (IOPAGEBASE + 012360)
#define IOLN_KDPAR 020
#define IOBA_TU (IOPAGEBASE + 012440) /* TU */
#define IOBA_TU (IOPAGEBASE + 012440) /* RHB: TU */
#define IOLN_TU 040
#define IOBA_MMR3 (IOPAGEBASE + 012516) /* MMR3 */
#define IOLN_MMR3 002
@@ -570,7 +574,7 @@ typedef struct pdp_dib DIB;
#define IOLN_XU 010
#define IOBA_DL (IOPAGEBASE + 016500) /* extra KL11/DL11 */
#define IOLN_DL (DLX_LINES * 010)
#define IOBA_RP (IOPAGEBASE + 016700) /* RP/RM */
#define IOBA_RP (IOPAGEBASE + 016700) /* RHA: RP/RM */
#define IOLN_RP 054
#define IOBA_CR (IOPAGEBASE + 017160) /* CD/CR/CM */
#define IOLN_CR 010
@@ -662,6 +666,7 @@ typedef struct pdp_dib DIB;
#define INT_V_TU 15
#define INT_V_RF 16
#define INT_V_RC 17
#define INT_V_RS 18
#define INT_V_PIR4 0 /* BR4 */
#define INT_V_TTI 1
@@ -705,6 +710,7 @@ typedef struct pdp_dib DIB;
#define INT_TU (1u << INT_V_TU)
#define INT_RF (1u << INT_V_RF)
#define INT_RC (1u << INT_V_RC)
#define INT_RS (1u << INT_V_RS)
#define INT_PIR4 (1u << INT_V_PIR4)
#define INT_TTI (1u << INT_V_TTI)
#define INT_TTO (1u << INT_V_TTO)
@@ -751,6 +757,7 @@ typedef struct pdp_dib DIB;
#define IPL_TU 5
#define IPL_RF 5
#define IPL_RC 5
#define IPL_RS 5
#define IPL_PTR 4
#define IPL_PTP 4
#define IPL_TTI 4
@@ -788,6 +795,7 @@ typedef struct pdp_dib DIB;
#define VEC_RL 0160
#define VEC_LPT 0200
#define VEC_RF 0204
#define VEC_RS 0204
#define VEC_HK 0210
#define VEC_RC 0210
#define VEC_RK 0220
@@ -819,9 +827,10 @@ typedef struct pdp_dib DIB;
/* Massbus definitions */
#define MBA_NUM 2 /* number of MBA's */
#define MBA_NUM 3 /* number of MBA's */
#define MBA_RP 0 /* MBA for RP */
#define MBA_TU 1 /* MBA for TU */
#define MBA_RS 2 /* MBA for RS */
#define MBA_RMASK 037 /* max 32 reg */
#define MBE_NXD 1 /* nx drive */
#define MBE_NXR 2 /* nx reg */

View File

@@ -1,6 +1,6 @@
/* pdp11_dl.c: PDP-11 multiple terminal interface simulator
Copyright (c) 1993-2012, Robert M Supnik
Copyright (c) 1993-2013, 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"),
@@ -25,6 +25,7 @@
dli,dlo DL11 terminal input/output
11-Oct-2013 RMS Poll DLI immediately after attach to pick up connect
18-Apr-2012 RMS Modified to use clock coscheduling
17-Aug-2011 RMS Added AUTOCONFIGURE modifier
19-Nov-2008 RMS Revised for common TMXR show routines
@@ -500,7 +501,7 @@ t_stat r;
r = tmxr_attach (&dlx_desc, uptr, cptr); /* attach */
if (r != SCPE_OK) /* error */
return r;
sim_activate (uptr, tmxr_poll); /* start poll */
sim_activate (uptr, 0); /* start poll at once */
return SCPE_OK;
}

View File

@@ -1,6 +1,6 @@
/* pdp11_fp.c: PDP-11 floating point simulator (32b version)
Copyright (c) 1993-2008, Robert M Supnik
Copyright (c) 1993-2013, 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"),
@@ -23,6 +23,7 @@
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
20-Apr-13 RMS MMR1 does not track PC changes (Johnny Billquist)
22-Sep-05 RMS Fixed declarations (Sterling Garwood)
04-Oct-04 RMS Added FIS instructions
19-Jan-03 RMS Changed mode definitions for Apple Dev Kit conflict
@@ -106,7 +107,7 @@
#define FPS_C (1u << FPS_V_C)
#define FPS_CC (FPS_N + FPS_Z + FPS_V + FPS_C)
#define FPS_RW (FPS_ER + FPS_ID + FPS_IUV + FPS_IU + FPS_IV + \
FPS_IC + FPS_D + FPS_L + FPS_T + FPS_CC)
FPS_IC + FPS_D + FPS_L + FPS_T + FPS_CC)
/* Floating point exception codes */
@@ -584,20 +585,20 @@ switch (spec >> 3) { /* case on spec */
if (reg == 7)
len = 2;
R[reg] = ((adr = R[reg]) + len) & 0177777;
if (update_MM)
if (update_MM && (reg != 7))
MMR1 = (len << 3) | reg;
return (adr | ds);
case 3: /* @(R)+ */
R[reg] = ((adr = R[reg]) + 2) & 0177777;
if (update_MM)
if (update_MM && (reg != 7))
MMR1 = 020 | reg;
adr = ReadW (adr | ds);
return (adr | dsenable);
case 4: /* -(R) */
adr = R[reg] = (R[reg] - len) & 0177777;
if (update_MM)
if (update_MM && (reg != 7))
MMR1 = (((-len) & 037) << 3) | reg;
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
set_stack_trap (adr);
@@ -605,7 +606,7 @@ switch (spec >> 3) { /* case on spec */
case 5: /* @-(R) */
adr = R[reg] = (R[reg] - 2) & 0177777;
if (update_MM)
if (update_MM && (reg != 7))
MMR1 = 0360 | reg;
if ((reg == 6) && (cm == MD_KER) && (adr < (STKLIM + STKL_Y)))
set_stack_trap (adr);
@@ -675,8 +676,10 @@ else {
(ReadW (exta | ((VA + 6) & 0177777)) << FP_V_F3);
else fptr->l = 0;
}
if ((GET_SIGN (fptr->h) != 0) && (GET_EXP (fptr->h) == 0) &&
(fpnotrap (FEC_UNDFV) == 0)) ABORT (TRAP_INT);
if ((GET_SIGN (fptr->h) != 0) &&
(GET_EXP (fptr->h) == 0) &&
(fpnotrap (FEC_UNDFV) == 0))
ABORT (TRAP_INT);
return;
}
@@ -744,7 +747,7 @@ if (IR & 000740) { /* defined? */
if (CPUT (CPUT_03)) /* 11/03 reads word */
ReadW (exta | R[reg]);
ABORT (TRAP_ILL);
}
}
FEC = 0; /* no errors */
FPS = FPS_IU|FPS_IV; /* trap ovf,unf */
@@ -1227,7 +1230,8 @@ int32 fpnotrap (int32 code)
{
static const int32 test_code[] = { 0, 0, 0, FPS_IC, FPS_IV, FPS_IU, FPS_IUV };
if ((code >= FEC_ICVT) && (code <= FEC_UNDFV) &&
if ((code >= FEC_ICVT) &&
(code <= FEC_UNDFV) &&
((FPS & test_code[code >> 1]) == 0))
return TRUE;
FPS = FPS | FPS_ER;

View File

@@ -1,6 +1,6 @@
/* pdp11_hk.c - RK611/RK06/RK07 disk controller
Copyright (c) 1993-2012, Robert M Supnik
Copyright (c) 1993-2013, 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"),
@@ -25,8 +25,14 @@
hk RK611/RK06/RK07 disk
01-Sep-13 RMS Revised error handling to command-response model
Revised interrupt logic to follow the hardware
10-Jun-13 RMS Fixed bug to write through end of sector (Oleg Safiullin)
18-Apr-13 RMS Fixed ATN setting on errors
Changed wrong drive type to status, not fatal error
10-Dec-12 RMS Fixed interrupt logic and CCLR unit cancellation
19-Mar-12 RMS Fixed declaration of cpu_opt (Mark Pizzolato)
29-Apr-07 RMS NOP and DCLR (at least) do not check drive type
29-Apr-07 RMS NOP and DCLR (at least) do not check drive type [wrong]
MR2 and MR3 only updated on NOP
17-Nov-05 RMS Removed unused variable
13-Nov-05 RMS Fixed overlapped seek interaction with NOP, DCLR, PACK
@@ -41,16 +47,13 @@
29-Dec-03 RMS Added 18b Qbus support
25-Apr-03 RMS Revised for extended file support
This is a somewhat abstracted implementation of the RK611, more closely
modelled on third party clones than DEC's own implementation. In particular,
the drive-to-controller serial communications system is simulated only at
a level equal to the Emulex SC21.
The RK611 functions only in 18b Unibus systems with I/O maps. The Emulex
SC02/C was a Qbus work-alike with a unique extension to 22b addressing. It
The RK611 functions only in 18b Unibus systems with I/O maps. The Emulex
SC02/C was a Qbus work-alike with a unique extension to 22b addressing. It
was only supported in Ultrix-11 and other third party software.
This module includes ideas from a previous implementation by Fred Van Kempen.
However, the interrupt logic has been rewritten to follow the bug-for-bug
peculiarities of the RK611 controller.
*/
#if defined (VM_PDP10) /* PDP10 version */
@@ -97,7 +100,7 @@ extern uint16 *M;
#define CYL u3 /* current cylinder */
#define FNC u4 /* function */
/* HKCS1 - 177440 - control/status 1 */
/* HKCS1 - 177440 - control/status 1 ^ = calculated dynamically */
#define CS1_GO CSR_GO /* go */
#define CS1_V_FNC 1 /* function pos */
@@ -128,7 +131,7 @@ extern uint16 *M;
#define CS1_CTO 0004000 /* ctrl timeout NI */
#define CS1_FMT 0010000 /* 16b/18b NI */
#define CS1_PAR 0020000 /* par err NI */
#define CS1_DI 0040000 /* drive intr */
#define CS1_DI 0040000 /* ^drive intr */
#define CS1_ERR 0100000 /* error */
#define CS1_CCLR 0100000 /* ctrl clear */
#define CS1_RW (CS1_DT|CS1_UAE|CS1_IE|CS1_SPA|CS1_FNC)
@@ -198,7 +201,7 @@ extern uint16 *M;
#define ER_SKI 0000002 /* seek incomp */
#define ER_NXF 0000004 /* non-exec func */
#define ER_PAR 0000010 /* parity err */
#define ER_FER 0000020 /* format err NI */
#define ER_FER 0000020 /* format err */
#define ER_DTY 0000040 /* drive type err */
#define ER_ECH 0000100 /* ECC hard err NI */
#define ER_BSE 0000200 /* bad sector err NI */
@@ -340,6 +343,9 @@ int32 hkmr2 = 0;
int32 hkmr3 = 0;
int32 hkdc = 0; /* cylinder */
int32 hkspr = 0; /* spare */
int32 hkci = 0; /* ctlr interrupt */
int32 hkdi = 0; /* drive interrupt */
int32 hkei = 0; /* error interrupt */
int32 hk_cwait = 5; /* command time */
int32 hk_swait = 10; /* seek time */
int32 hk_rwait = 10; /* rotate time */
@@ -347,8 +353,13 @@ int32 hk_min2wait = 300; /* min time to 2nd int *
int16 hkdb[3] = { 0 }; /* data buffer silo */
int16 hk_off[HK_NUMDR] = { 0 }; /* saved offset */
int16 hk_dif[HK_NUMDR] = { 0 }; /* cylinder diff */
static uint8 reg_in_drive[16] = {
static const uint8 reg_in_drive[16] = {
0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
static const char* reg_name[] = {
"HKCS1", "HKWC", "HKBA", "HKDA",
"HKCS2", "HKDS", "HKER", "HKAS",
"HKDC", "spare", "HKDB", "HKMR",
"HKEC1", "HKEC2", "HKMR2", "HKMR3" };
DEVICE hk_dev;
t_stat hk_rd (int32 *data, int32 PA, int32 access);
@@ -358,11 +369,12 @@ t_stat hk_reset (DEVICE *dptr);
t_stat hk_boot (int32 unitno, DEVICE *dptr);
t_stat hk_attach (UNIT *uptr, char *cptr);
t_stat hk_detach (UNIT *uptr);
int32 hk_inta (void);
int32 hk_rdmr2 (int32 msg);
int32 hk_rdmr3 (int32 msg);
void update_hkcs (int32 flags, int32 drv);
void update_hkds (int32 drv);
void hk_cmderr (int32 err, int32 drv);
void hk_err (int32 cs1e, int32 cs2e, int32 drve, int32 drv);
void hk_go (int32 drv);
t_stat hk_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat hk_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc);
@@ -377,7 +389,7 @@ t_stat hk_set_bad (UNIT *uptr, int32 val, char *cptr, void *desc);
DIB hk_dib = {
IOBA_HK, IOLN_HK, &hk_rd, &hk_wr,
1, IVCL (HK), VEC_HK, { NULL }
1, IVCL (HK), VEC_HK, { &hk_inta }
};
UNIT hk_unit[] = {
@@ -414,6 +426,9 @@ REG hk_reg[] = {
{ GRDATA (HKMR2, hkmr2, DEV_RDX, 16, 0), REG_RO },
{ GRDATA (HKMR3, hkmr3, DEV_RDX, 16, 0), REG_RO },
{ GRDATA (HKSPR, hkspr, DEV_RDX, 16, 0) },
{ FLDATA (HKCI, hkci, 0) },
{ FLDATA (HKDI, hkdi, 0) },
{ FLDATA (HKEI, hkei, 0) },
{ FLDATA (INT, IREQ (HK), INT_V_HK) },
{ FLDATA (ERR, hkcs1, CSR_V_ERR) },
{ FLDATA (DONE, hkcs1, CSR_V_DONE) },
@@ -421,6 +436,7 @@ REG hk_reg[] = {
{ DRDATA (CTIME, hk_cwait, 24), REG_NZ + PV_LEFT },
{ DRDATA (STIME, hk_swait, 24), REG_NZ + PV_LEFT },
{ DRDATA (RTIME, hk_rwait, 24), REG_NZ + PV_LEFT },
{ DRDATA (M2TIME, hk_min2wait, 24), REG_NZ + PV_LEFT },
{ DRDATA (MIN2TIME, hk_min2wait, 24), REG_NZ + PV_LEFT + REG_HRO },
{ URDATA (FNC, hk_unit[0].FNC, DEV_RDX, 5, 0,
HK_NUMDR, REG_HRO) },
@@ -485,8 +501,7 @@ int32 drv, i, j;
drv = GET_UNIT (hkcs2); /* get current unit */
j = (PA >> 1) & 017; /* get reg offset */
if (reg_in_drive[j] && (hk_unit[drv].flags & UNIT_DIS)) { /* nx disk */
hkcs2 = hkcs2 | CS2_NED; /* set error flag */
update_hkcs (0, drv);
hk_err (CS1_ERR|CS1_DONE, CS2_NED, 0, drv); /* set err, stop op */
*data = 0;
return SCPE_OK;
}
@@ -495,7 +510,7 @@ update_hkcs (0, drv); /* update status */
switch (j) { /* decode PA<4:1> */
case 000: /* HKCS1 */
*data = hkcs1;
*data = (hkcs1 & ~CS1_DI) | (hkdi? CS1_DI: 0); /* DI dynamic */
break;
case 001: /* HKWC */
@@ -564,7 +579,7 @@ switch (j) { /* decode PA<4:1> */
}
if (DEBUG_PRI (hk_dev, HKDEB_RRD))
fprintf (sim_deb, ">>HK%d read: reg%d=%o\n", drv, j, *data);
fprintf (sim_deb, ">>HK%d read: %s=%o\n", drv, reg_name[j], *data);
return SCPE_OK;
}
@@ -576,16 +591,19 @@ UNIT *uptr;
drv = GET_UNIT (hkcs2); /* get current unit */
uptr = hk_dev.units + drv; /* get unit */
j = (PA >> 1) & 017; /* get reg offset */
if (reg_in_drive[j] && (hk_unit[drv].flags & UNIT_DIS)) { /* nx disk */
hk_err (CS1_ERR|CS1_DONE, CS2_NED, 0, drv); /* set err, stop op */
return SCPE_OK;
}
if ((hkcs1 & CS1_GO) && /* busy? */
!(((j == 0) && (data & CS1_CCLR)) || /* not cclr or sclr? */
((j == 4) && (data & CS2_CLR)))) {
hkcs2 = hkcs2 | CS2_PGE; /* prog error */
update_hkcs (0, drv);
hk_err (CS1_ERR|CS1_DONE, CS2_PGE, 0, drv); /* set err, stop op */
return SCPE_OK;
}
if (DEBUG_PRI (hk_dev, HKDEB_RWR))
fprintf (sim_deb, ">>HK%d write: reg%d=%o\n", drv, j, data);
fprintf (sim_deb, ">>HK%d write: %s=%o\n", drv, reg_name[j], data);
switch (j) { /* decode PA<4:1> */
case 000: /* HKCS1 */
@@ -596,25 +614,22 @@ switch (j) { /* decode PA<4:1> */
hkda = hkdc = 0;
hkba = hkwc = 0;
hkspr = hkof = 0;
CLR_INT (HK); /* clr int */
hkci = hkdi = hkei = 0; /* clr int flops */
for (i = 0; i < HK_NUMDR; i++) { /* stop data xfr */
if (sim_is_active (&hk_unit[i]) &&
((uptr->FNC & CS1_M_FNC) >= FNC_XFER))
((hk_unit[i].FNC & CS1_M_FNC) >= FNC_XFER))
sim_cancel (&hk_unit[i]);
}
drv = 0;
break;
}
if (data & CS1_IE) { /* setting IE? */
if (data & CS1_DONE) /* write to DONE+IE? */
SET_INT (HK);
}
else CLR_INT (HK); /* no, clr intr */
if (((data & CS1_IE) != 0) && ((data & CS1_DONE) != 0))
hkci = 1; /* set ctlr intr */
hkcs1 = (hkcs1 & ~CS1_RW) | (data & CS1_RW); /* merge data */
if (SC02C)
hkspr = (hkspr & ~CS1_M_UAE) | GET_UAE (hkcs1);
if ((data & CS1_GO) && !(hkcs1 & CS1_ERR)) /* go? */
hk_go (drv);
if (((data & CS1_GO) != 0) && ((hkcs1 & CS1_ERR) == 0))
hk_go (drv); /* go & ~err? */
break;
case 001: /* HKWC */
@@ -671,12 +686,12 @@ return SCPE_OK;
void hk_go (int32 drv)
{
int32 fnc, t;
t_bool dte;
UNIT *uptr;
static uint8 fnc_cdt[16] = {
0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
static uint8 fnc_dte[16] = {
0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0
};
static uint8 fnc_nxf[16] = {
0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0
};
@@ -695,51 +710,64 @@ if (DEBUG_PRI (hk_dev, HKDEB_OPS))
fprintf (sim_deb, ">>HK%d strt: fnc=%o, cs1=%o, cs2=%o, ds=%o, er=%o, cyl=%o, da=%o, ba=%o, wc=%o\n",
drv, fnc, hkcs1, hkcs2, hkds[drv], hker[drv], hkdc, hkda, hkba, hkwc);
uptr = hk_dev.units + drv; /* get unit */
dte = ((hkcs1 & CS1_DT) !=0) != ((uptr->flags & UNIT_DTYPE) != 0);
if (fnc != FNC_NOP) /* !nop, clr msg sel */
hkmr = hkmr & ~MR_MS;
if (uptr->flags & UNIT_DIS) { /* nx unit? */
hkcs2 = hkcs2 | CS2_NED; /* set error flag */
update_hkcs (CS1_DONE, drv); /* done */
hk_err (CS1_ERR|CS1_DONE, CS2_NED, 0, drv); /* set err, no op */
return;
}
if (fnc_cdt[fnc] && /* need dtype match? */
(((hkcs1 & CS1_DT) != 0) != ((uptr->flags & UNIT_DTYPE) != 0))) {
hk_cmderr (ER_DTY, drv); /* type error */
return;
if ((hkcs1 & CS1_FMT) != 0) { /* 18b format? */
hk_err (CS1_ERR|CS1_DONE, 0, ER_FER, drv); /* set err, no op */
return;
}
if (fnc_dte[fnc] && dte) { /* need drv match ? */
hker[drv] = hker[drv] | ER_DTY; /* drive type mismatch? */
hk_err (CS1_ERR|CS1_DONE, 0, ER_DTY, drv); /* set err, no op */
}
if (fnc_nxf[fnc] && ((hkds[drv] & DS_VV) == 0)) { /* need vol valid? */
hk_cmderr (ER_NXF, drv); /* non exec func */
hkds[drv] = hkds[drv] | DS_ATA; /* set ATTN */
hk_err (CS1_ERR|CS1_DI|CS1_DONE, 0, ER_NXF, drv); /* set err, no op */
return;
}
if (fnc_att[fnc] && !(uptr->flags & UNIT_ATT)) { /* need attached? */
hk_cmderr (ER_UNS, drv); /* unsafe */
hkds[drv] = hkds[drv] | DS_ATA; /* set ATTN */
hk_err (CS1_ERR|CS1_DI|CS1_DONE, 0, ER_UNS, drv); /* set err, no op */
return;
}
if (fnc_rdy[fnc] && sim_is_active (uptr)) /* need inactive? */
return;
if (fnc_cyl[fnc] && /* need valid cyl */
((GET_CY (hkdc) >= HK_CYL (uptr)) || /* bad cylinder */
(GET_SF (hkda) >= HK_NUMSF) || /* bad surface */
(GET_SC (hkda) >= HK_NUMSC))) { /* or bad sector? */
hk_cmderr (ER_IAE, drv); /* illegal addr */
(GET_SF (hkda) >= HK_NUMSF))) { /* bad surface */
hk_err (CS1_ERR|CS1_DONE, 0, ER_SKI|ER_IAE, drv); /* set err, no op */
return;
}
hkcs1 = (hkcs1 | CS1_GO) & ~CS1_DONE; /* set go, clear done */
hkci = hkdi = hkei = 0; /* clear all intr */
CLR_INT (HK);
switch (fnc) { /* case on function */
/* Instantaneous functions (unit may be busy, can't schedule thread) */
/* Instantaneous functions (unit may be busy, can't schedule thread,
can't overwrite unit function field) */
case FNC_NOP: /* no operation */
hkmr2 = hk_rdmr2 (GET_MS (hkmr)); /* get serial msgs */
hkmr3 = hk_rdmr3 (GET_MS (hkmr));
update_hkcs (CS1_DONE, drv); /* done */
if (dte) /* drive type err? */
hk_err (CS1_ERR|CS1_DONE, 0, ER_DTY, drv);
else update_hkcs (CS1_DONE, drv); /* done */
break;
case FNC_DCLR: /* drive clear */
hkds[drv] &= ~DS_ATA; /* clr ATA */
hker[drv] = 0; /* clear errors */
update_hkcs (CS1_DONE, drv); /* done */
hker[drv] = 0; /* clr err */
if (dte) /* drive type err? */
hk_err (CS1_ERR|CS1_DONE, 0, ER_DTY, drv);
else update_hkcs (CS1_DONE, drv); /* done */
break;
case FNC_PACK: /* pack acknowledge */
@@ -774,15 +802,19 @@ switch (fnc) { /* case on function */
case FNC_WCHK: /* write check */
case FNC_READ: /* read */
case FNC_READH: /* read headers */
if (GET_SC (hkda) >= HK_NUMSC) { /* invalid sector? */
hk_err (CS1_ERR|CS1_DONE, 0, ER_OPI, drv); /* set err, no op */
return;
}
hk_dif[drv] = hkdc - uptr->CYL; /* cyl diff */
t = abs (hk_dif[drv]); /* |cyl diff| */
sim_activate (uptr, hk_rwait + (hk_swait * t)); /* schedule */
uptr->FNC = fnc; /* save function */
sim_activate (uptr, hk_rwait + (hk_swait * t)); /* schedule */
uptr->CYL = hkdc; /* update cyl */
return;
default:
hk_cmderr (ER_ILF, drv); /* not supported */
hk_err (CS1_ERR|CS1_DONE, 0, ER_ILF, drv); /* not supported */
break;
}
return;
@@ -821,7 +853,7 @@ switch (fnc) { /* case on function */
case FNC_OFFSET: /* offset */
if (uptr->FNC & FNC_2ND) { /* 2nd int? */
hkds[drv] = (hkds[drv] & ~DS_PIP) | DS_ATA; /* upd sta */
update_hkcs (CS1_DI, drv); /* drive intr */
update_hkcs (CS1_DI, drv); /* ATN set */
}
else {
uptr->FNC = uptr->FNC | FNC_2ND; /* second state */
@@ -835,7 +867,7 @@ switch (fnc) { /* case on function */
case FNC_SEEK: /* seek */
if (uptr->FNC & FNC_2ND) { /* 2nd int? */
hkds[drv] = (hkds[drv] & ~DS_PIP) | DS_ATA; /* upd sta */
update_hkcs (CS1_DI, drv); /* drive intr */
update_hkcs (CS1_DI, drv); /* ATN set */
}
else {
uptr->FNC = uptr->FNC | FNC_2ND; /* second state */
@@ -863,7 +895,7 @@ switch (fnc) { /* case on function */
case FNC_WRITE: /* write */
if (uptr->flags & UNIT_WPRT) { /* write locked? */
hk_cmderr (ER_WLE, drv); /* command error */
hk_err (CS1_ERR|CS1_DONE, 0, ER_WLE, drv); /* set err, stop op */
return SCPE_OK;
}
case FNC_WCHK: /* write check */
@@ -889,7 +921,7 @@ switch (fnc) { /* case on function */
if (hkcs2 & CS2_UAI) { /* no addr inc? */
if (t = Map_ReadW (ba, 2, &comp)) { /* get 1st wd */
wc = 0; /* NXM, no xfr */
hkcs2 = hkcs2 | CS2_NEM; /* set nxm err */
hk_err (CS1_ERR, CS2_NEM, 0, drv);
}
for (i = 0; i < wc; i++)
hkxb[i] = comp;
@@ -897,7 +929,7 @@ switch (fnc) { /* case on function */
else { /* normal */
if (t = Map_ReadW (ba, wc << 1, hkxb)) { /* get buf */
wc = wc - (t >> 1); /* NXM, adj wc */
hkcs2 = hkcs2 | CS2_NEM; /* set nxm err */
hk_err (CS1_ERR, CS2_NEM, 0, drv);
}
ba = ba + (wc << 1); /* adv ba */
}
@@ -905,7 +937,7 @@ switch (fnc) { /* case on function */
for (i = wc; i < awc; i++) /* fill buf */
hkxb[i] = 0;
if (wc && !err) { /* write buf */
fxwrite (hkxb, sizeof (uint16), wc, uptr->fileref);
fxwrite (hkxb, sizeof (uint16), awc, uptr->fileref);
err = ferror (uptr->fileref);
}
} /* end if wr */
@@ -917,13 +949,13 @@ switch (fnc) { /* case on function */
if (hkcs2 & CS2_UAI) { /* no addr inc? */
if (t = Map_WriteW (ba, 2, &hkxb[wc - 1])) {
wc = 0; /* NXM, no xfr */
hkcs2 = hkcs2 | CS2_NEM; /* set nxm err */
hk_err (CS1_ERR, CS2_NEM, 0, drv);
}
}
else { /* normal */
if (t = Map_WriteW (ba, wc << 1, hkxb)) { /* put buf */
wc = wc - (t >> 1); /* NXM, adj wc */
hkcs2 = hkcs2 | CS2_NEM; /* set nxm err */
hk_err (CS1_ERR, CS2_NEM, 0, drv);
}
ba = ba + (wc << 1); /* adv ba */
}
@@ -936,15 +968,15 @@ switch (fnc) { /* case on function */
awc = wc;
for (wc = 0; wc < awc; wc++) { /* loop thru buf */
if (Map_ReadW (ba, 2, &comp)) { /* read word */
hkcs2 = hkcs2 | CS2_NEM; /* set error */
hk_err (CS1_ERR, CS2_NEM, 0, drv);
break;
}
if (comp != hkxb[wc]) { /* compare wd */
hkcs2 = hkcs2 | CS2_WCE; /* set error */
hk_err (CS1_ERR, CS2_WCE, 0, drv);
break;
}
if ((hkcs2 & CS2_UAI)
== 0) ba = ba + 2;
if ((hkcs2 & CS2_UAI) == 0)
ba = ba + 2;
}
} /* end else wchk */
@@ -961,7 +993,7 @@ switch (fnc) { /* case on function */
hkdc = da / HK_NUMSF;
if (err != 0) { /* error? */
hk_cmderr (ER_PAR, drv); /* set drive error */
hk_err (CS1_ERR|CS1_DONE, 0, ER_PAR, drv); /* set drive error */
perror ("HK I/O error");
clearerr (uptr->fileref);
return SCPE_IOERR;
@@ -977,35 +1009,49 @@ return SCPE_OK;
/* Controller status update
Check for done transition
Update drive status
Update HKCS1
Check for done transition
clock CI from IE
set DI if any ATN bits set
Check for DI set if no transition but DONE is set
Update interrupt request
*/
void update_hkcs (int32 flag, int32 drv)
{
int32 i;
int32 old_hkcs1 = hkcs1;
update_hkds (drv); /* upd drv status */
if (flag & CS1_DONE) /* clear go */
hkcs1 = hkcs1 & ~CS1_GO;
if (hkcs1 & CS1_IE) { /* intr enable? */
if (((flag & CS1_DONE) && ((hkcs1 & CS1_DONE) == 0)) ||
((flag & CS1_DI) && (hkcs1 & CS1_DONE))) /* done 0->1 or DI? */
SET_INT (HK);
hkcs1 = (hkcs1 & (CS1_ERR|CS1_DT|CS1_UAE|CS1_DONE|CS1_IE|CS1_SPA|CS1_FNC|CS1_GO)) |
(flag & ~CS1_DI);
if ((hkcs1 & CS1_DONE) != 0) { /* done? */
hkcs1 = hkcs1 & ~CS1_GO; /* clear go */
if ((old_hkcs1 & CS1_DONE) == 0) { /* done 0->1? */
hkci = (hkcs1 & CS1_IE)? 1: 0; /* clk CI from IE */
for (i = 0; i < HK_NUMDR; i++) { /* if ATA, set DI */
if (hkds[i] & DS_ATA)
hkdi = 1;
}
}
else if ((flag & CS1_DI) != 0) /* done set; new ATN? */
hkdi = 1; /* set drv int */
}
else hkdi = 0; /* not done, clr DI */
if (((hkcs1 & CS1_IE) != 0) && (hkci || hkdi || hkei)) /* int enab & set? */
SET_INT (HK);
else CLR_INT (HK);
hkcs1 = (hkcs1 & (CS1_DT|CS1_UAE|CS1_DONE|CS1_IE|CS1_SPA|CS1_FNC|CS1_GO)) | flag;
for (i = 0; i < HK_NUMDR; i++) { /* if ATA, set DI */
if (hkds[i] & DS_ATA) hkcs1 = hkcs1 | CS1_DI;
if (DEBUG_PRI (hk_dev, HKDEB_OPS)) { /* debug info? */
if (flag & CS1_DONE) /* set done? */
fprintf (sim_deb,
">>HK%d done: fnc=%o, cs1=%o, cs2=%o, ds=%o, er=%o, cyl=%o, da=%o, ba=%o, wc=%o, ci=%d, di=%d\n",
drv, GET_FNC (hkcs1), hkcs1, hkcs2, hkds[drv], hker[drv], hkdc, hkda, hkba, hkwc, hkci, hkdi);
if (flag & CS1_DI) /* set ATA? */
fprintf (sim_deb,
">>HK%d ATA: fnc=%o, cs1=%o, cs2=%o, ds=%o, er=%o, cyl=%o, da=%o, ba=%o, wc=%o, ci=%d, di=%d\n",
drv, GET_FNC (hkcs1), hkcs1, hkcs2, hkds[drv], hker[drv], hkdc, hkda, hkba, hkwc, hkci, hkdi);
}
if (hker[drv] | (hkcs1 & (CS1_PAR | CS1_CTO)) | /* if err, set ERR */
(hkcs2 & CS2_ERR)) hkcs1 = hkcs1 | CS1_ERR;
if ((flag & CS1_DONE) && /* set done && debug? */
(DEBUG_PRI (hk_dev, HKDEB_OPS)))
fprintf (sim_deb, ">>HK%d done: fnc=%o, cs1=%o, cs2=%o, ds=%o, er=%o, cyl=%o, da=%o, ba=%o, wc=%o\n",
drv, GET_FNC (hkcs1), hkcs1, hkcs2, hkds[drv], hker[drv], hkdc, hkda, hkba, hkwc);
return;
}
@@ -1018,35 +1064,42 @@ if (hk_unit[drv].flags & UNIT_DIS) { /* disabled? */
return;
}
hkds[drv] = (hkds[drv] & (DS_VV | DS_PIP | DS_ATA)) | DS_VLD | DS_DRA;
if (hk_unit[drv].flags & UNIT_RK07)
hkds[drv] = hkds[drv] | DS_DT;
if (hk_unit[drv].flags & UNIT_ATT) { /* attached? */
if (!sim_is_active (&hk_unit[drv])) /* not busy? */
hkds[drv] = hkds[drv] | DS_RDY; /* set RDY */
if (hker[drv]) /* err? set ATA */
hkds[drv] = hkds[drv] | DS_ATA;
if (hk_off[drv]) /* offset? set OF */
hkds[drv] = hkds[drv] | DS_OF;
if (hk_unit[drv].flags & UNIT_WPRT) /* write locked? */
hkds[drv] = hkds[drv] | DS_WRL; /* set WRL */
}
else {
hkds[drv] = hkds[drv] & ~(DS_PIP | DS_VV); /* no, clr PIP,VV */
hker[drv] = 0; /* no errors */
}
if (hk_unit[drv].flags & UNIT_RK07)
hkds[drv] = hkds[drv] | DS_DT;
else hkds[drv] = hkds[drv] & ~(DS_PIP | DS_VV); /* no, clr PIP,VV */
return;
}
/* Set error and abort command */
/* Set errors */
void hk_cmderr (int32 err, int32 drv)
void hk_err (int32 cs1e, int32 cs2e, int32 drve, int32 drv)
{
hker[drv] = hker[drv] | err; /* set error */
hkds[drv] = hkds[drv] | DS_ATA; /* set attn */
update_hkcs (CS1_DONE, drv); /* set done */
hker[drv] = hker[drv] | drve; /* set drv error */
hkcs2 = hkcs2 | cs2e; /* set cs2 err */
if ((cs1e & CS1_ERR) != 0) /* set combined err? */
hkei = 1; /* then set EI */
if ((cs1e & CS1_DONE) != 0) /* set done? */
update_hkcs (CS1_ERR|CS1_DONE, drv); /* stop now */
else hkcs1 = hkcs1 | cs1e; /* no, just upd */
return;
}
/* Interrupt routine */
int32 hk_inta (void)
{
hkci = hkdi = hkei = 0; /* clear all flops */
return hk_dib.vec; /* return vector */
}
/* Diagnostic registers
It's unclear whether the drivers actually use these values, but the
@@ -1164,12 +1217,13 @@ hkmr = hkmr2 = hkmr3 = 0;
hkda = hkdc = 0;
hkba = hkwc = 0;
hkof = hkspr = 0;
hkci = hkdi = hkei = 0; /* clear intr flops */
CLR_INT (HK); /* clear intr req */
for (i = 0; i < HK_NUMDR; i++) { /* stop operations */
uptr = hk_dev.units + i;
sim_cancel (uptr);
if (uptr->flags & UNIT_ATT)
hkds[i] = hkds[i] & DS_VV;
hkds[i] = hkds[i] & (DS_VV | DS_DT);
else hkds[i] = 0;
uptr->CYL = uptr->FNC = 0; /* clear state */
hk_dif[i] = 0;
@@ -1189,18 +1243,23 @@ t_stat hk_attach (UNIT *uptr, char *cptr)
{
uint32 drv, p;
t_stat r;
int32 old_hkds;
uptr->capac = HK_SIZE (uptr);
r = attach_unit (uptr, cptr); /* attach unit */
if (r != SCPE_OK) /* error? */
return r;
drv = (uint32) (uptr - hk_dev.units); /* get drv number */
hkds[drv] = DS_ATA | DS_RDY | ((uptr->flags & UNIT_WPRT)? DS_WRL: 0);
old_hkds = hkds[drv]; /* save hkds */
hkds[drv] = DS_ATA | DS_RDY |
((uptr->flags & UNIT_WPRT)? DS_WRL: 0) |
((uptr->flags & UNIT_DTYPE)? DS_DT: 0);
hker[drv] = 0; /* upd drv status */
hk_off[drv] = 0;
hk_dif[drv] = 0;
uptr->CYL = 0;
update_hkcs (CS1_DI, drv); /* upd ctlr status */
if ((old_hkds & DS_ATA) == 0) /* ATN transition? */
update_hkcs (CS1_DI, drv); /* upd ctlr status */
p = sim_fsize (uptr->fileref); /* get file size */
if (p == 0) { /* new disk image? */
@@ -1226,18 +1285,21 @@ return SCPE_OK;
t_stat hk_detach (UNIT *uptr)
{
uint32 drv;
int32 old_hkds;
if (!(uptr->flags & UNIT_ATT)) /* attached? */
return SCPE_OK;
drv = (uint32) (uptr - hk_dev.units); /* get drv number */
hkds[drv] = (hkds[drv] & ~(DS_RDY | DS_WRL | DS_VV | DS_OF)) | DS_ATA;
old_hkds = hkds[drv];
hkds[drv] = (hkds[drv] & ~(DS_RDY | DS_WRL | DS_VV | DS_OF | DS_PIP)) | DS_ATA;
if (sim_is_active (uptr)) { /* unit active? */
sim_cancel (uptr); /* cancel operation */
hker[drv] = hker[drv] | ER_OPI; /* set drive error */
if ((uptr->FNC & FNC_2ND) == 0) /* expecting done? */
update_hkcs (CS1_DONE, drv); /* set done */
update_hkcs (CS1_ERR|CS1_DONE, drv); /* set done */
}
update_hkcs (CS1_DI, drv); /* request intr */
if ((old_hkds & DS_ATA) == 0) /* ATN transition? */
update_hkcs (CS1_DI, drv); /* upd ctlr status */
return detach_unit (uptr);
}

View File

@@ -1,6 +1,6 @@
/* pdp11_rc.c: RC11/RS64 fixed head disk simulator
Copyright (c) 2007-2008, John A. Dundas III
Copyright (c) 2007-2013, John A. Dundas III
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@@ -25,6 +25,7 @@
rc RC11/RS64 fixed head disk
03-Dec-13 RMS Added explicit void * cast
28-Dec-07 JAD Correct extraction of unit number from da in rc_svc.
Clear _all_ error bits when a new operation starts.
Passes all diagnostics in all configurations.
@@ -439,7 +440,7 @@ static t_stat rc_svc (UNIT *uptr)
{
uint32 ma, da, t, u_old, u_new, last_da;
uint16 dat;
uint16 *fbuf = uptr->filebuf;
uint16 *fbuf = (uint16 *) uptr->filebuf;
if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
update_rccs (RCCS_NED | RCCS_DONE, 0); /* nx disk */

View File

@@ -1,6 +1,6 @@
/* pdp11_rf.c: RF11 fixed head disk simulator
Copyright (c) 2006-2012, Robert M Supnik
Copyright (c) 2006-2013, 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"),
@@ -25,6 +25,7 @@
rf RF11 fixed head disk
03-Sep-13 RMS Added WC to debug printout
19-Mar-12 RMS Fixed bug in updating mem addr extension (Peter Schorn)
25-Dec-06 RMS Fixed bug in unit mask (John Dundas)
26-Jun-06 RMS Cloned from RF08 simulator
@@ -266,8 +267,8 @@ switch ((PA >> 1) & 07) { /* decode PA<3:1> */
rf_cs &= ~(RFCS_WCHK|RFCS_DPAR|RFCS_NED|RFCS_WLK|RFCS_MXFR|RFCS_DONE);
CLR_INT (RF);
if (DEBUG_PRS (rf_dev))
fprintf (sim_deb, ">>RF start: cs = %o, da = %o, ma = %o\n",
update_rfcs (0, 0), GET_DEX (rf_dae) | rf_da, GET_MEX (rf_cs) | rf_cma);
fprintf (sim_deb, ">>RF start: cs = %o, da = %o, ma = %o, wc = %o\n",
update_rfcs (0, 0), GET_DEX (rf_dae) | rf_da, GET_MEX (rf_cs) | rf_cma, rf_wc);
}
break;
@@ -321,7 +322,7 @@ t_stat rf_svc (UNIT *uptr)
{
uint32 ma, da, t;
uint16 dat;
uint16 *fbuf = uptr->filebuf;
uint16 *fbuf = (uint16 *) uptr->filebuf;
if ((uptr->flags & UNIT_BUF) == 0) { /* not buf? abort */
update_rfcs (RFCS_NED|RFCS_DONE, 0); /* nx disk */

View File

@@ -1,6 +1,6 @@
/* pdp11_rh.c: PDP-11 Massbus adapter simulator
Copyright (c) 2005-2012, Robert M Supnik
Copyright (c) 2005-2013, 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"),
@@ -25,6 +25,7 @@
rha, rhb RH11/RH70 Massbus adapter
02-Sep-13 RMS Added third Massbus adapter, debug printouts
19-Mar-12 RMS Fixed declaration of cpu_opt (Mark Pizzolato)
02-Feb-08 RMS Fixed DMA memory address limit test (John Dundas)
17-May-07 RMS Moved CS1 drive enable to devices
@@ -175,11 +176,12 @@ t_stat mba_set_type (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat mba_show_type (FILE *st, UNIT *uptr, int32 val, void *desc);
int32 mba0_inta (void);
int32 mba1_inta (void);
int32 mba2_inta (void);
void mba_set_int (uint32 mb);
void mba_clr_int (uint32 mb);
void mba_upd_cs1 (uint32 set, uint32 clr, uint32 mb);
void mba_set_cs2 (uint32 flg, uint32 mb);
uint32 mba_map_pa (int32 pa, int32 *ofs);
int32 mba_map_pa (int32 pa, int32 *ofs);
DEVICE mba0_dev, mba1_dev;
extern uint32 Map_Addr (uint32 ba);
@@ -272,6 +274,39 @@ MTAB mba1_mod[] = {
{ 0 }
};
DIB mba2_dib = {
IOBA_RS, IOLN_RS, &mba_rd, &mba_wr,
1, IVCL (RS), VEC_RS, { &mba2_inta }
};
UNIT mba2_unit = { UDATA (NULL, 0, 0) };
REG mba2_reg[] = {
{ ORDATA (CS1, massbus[2].cs1, 16) },
{ ORDATA (WC, massbus[2].wc, 16) },
{ ORDATA (BA, massbus[2].ba, 16) },
{ ORDATA (CS2, massbus[2].cs2, 16) },
{ ORDATA (DB, massbus[2].db, 16) },
{ ORDATA (BAE, massbus[2].bae, 6) },
{ ORDATA (CS3, massbus[2].cs3, 16) },
{ FLDATA (IFF, massbus[2].iff, 0) },
{ FLDATA (INT, IREQ (RS), INT_V_RS) },
{ FLDATA (SC, massbus[2].cs1, CSR_V_ERR) },
{ FLDATA (DONE, massbus[2].cs1, CSR_V_DONE) },
{ FLDATA (IE, massbus[2].cs1, CSR_V_IE) },
{ ORDATA (DEVADDR, mba2_dib.ba, 32), REG_HRO },
{ ORDATA (DEVVEC, mba2_dib.vec, 16), REG_HRO },
{ NULL }
};
MTAB mba2_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0040, "ADDRESS", "ADDRESS",
&set_addr, &show_addr, NULL },
{ MTAB_XTD|MTAB_VDV, 0, "VECTOR", "VECTOR",
&set_vec, &show_vec, NULL },
{ 0 }
};
DEVICE mba_dev[] = {
{
"RHA", &mba0_unit, mba0_reg, mba0_mod,
@@ -286,6 +321,13 @@ DEVICE mba_dev[] = {
NULL, NULL, &mba_reset,
NULL, NULL, NULL,
&mba1_dib, DEV_DEBUG | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS
},
{
"RHC", &mba2_unit, mba2_reg, mba2_mod,
1, 0, 0, 0, 0, 0,
NULL, NULL, &mba_reset,
NULL, NULL, NULL,
&mba2_dib, DEV_DEBUG | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS
}
};
@@ -415,6 +457,9 @@ switch (ofs) { /* case on reg */
massbus[mb].cs1 &= ~(CS1_TRE | CS1_MCPE | CS1_DONE);
massbus[mb].cs2 &= ~CS2_ERR; /* clear errors */
massbus[mb].cs3 &= ~(CS3_ERR | CS3_DBL);
if (DEBUG_PRS (mba_dev[mb]))
fprintf (sim_deb, ">>RH%d STRT: cs1=%o, cs2=%o,ba=%o, wc=%o\n",
mb, massbus[mb].cs1, massbus[mb].cs2, massbus[mb].ba, massbus[mb].wc);
}
}
}
@@ -623,6 +668,9 @@ return i;
void mba_set_don (uint32 mb)
{
mba_upd_cs1 (CS1_DONE, 0, mb);
if (DEBUG_PRS (mba_dev[mb]))
fprintf (sim_deb, ">>RH%d DONE: cs1=%o, cs2=%o,ba=%o, wc=%o\n",
mb, massbus[mb].cs1, massbus[mb].cs2, massbus[mb].ba, massbus[mb].wc);
return;
}
@@ -726,9 +774,17 @@ massbus[1].iff = 0; /* clear CSTB INTR */
return mba1_dib.vec; /* acknowledge */
}
int32 mba2_inta (void)
{
massbus[2].cs1 &= ~CS1_IE; /* clear int enable */
massbus[2].cs3 &= ~CS1_IE; /* in both registers */
massbus[2].iff = 0; /* clear CSTB INTR */
return mba2_dib.vec; /* acknowledge */
}
/* Map physical address to Massbus number, offset */
uint32 mba_map_pa (int32 pa, int32 *ofs)
int32 mba_map_pa (int32 pa, int32 *ofs)
{
int32 i, uo, ba, lnt;
DIB *dibp;

View File

@@ -1,6 +1,6 @@
/* pdp11_rk.c: RK11/RKV11 cartridge disk simulator
Copyright (c) 1993-2009, Robert M Supnik
Copyright (c) 1993-2013, 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"),
@@ -25,6 +25,7 @@
rk RK11/RKV11/RK05 cartridge disk
06-Sep-13 RMS Fixed RKDS content for non-existent disk (Mark Pizzolato)
20-Mar-09 RMS Fixed bug in read header (Walter F Mueller)
16-Aug-05 RMS Fixed C++ declaration and cast problems
07-Jul-05 RMS Removed extraneous externs
@@ -296,17 +297,20 @@ UNIT *uptr;
switch ((PA >> 1) & 07) { /* decode PA<3:1> */
case 0: /* RKDS: read only */
rkds = (rkds & RKDS_ID) | RKDS_RK05 | RKDS_SC_OK |
(rand () % RK_NUMSC); /* random sector */
rkds = rkds & RKDS_ID; /* identified unit */
uptr = rk_dev.units + GET_DRIVE (rkda); /* selected unit */
if (uptr->flags & UNIT_ATT) /* attached? */
rkds = rkds | RKDS_RDY;
if (!sim_is_active (uptr)) /* idle? */
rkds = rkds | RKDS_RWS;
if (uptr->flags & UNIT_WPRT)
rkds = rkds | RKDS_WLK;
if (GET_SECT (rkda) == (rkds & RKDS_SC))
rkds = rkds | RKDS_ON_SC;
if (!(uptr->flags & UNIT_DIS)) { /* not disabled? */
rkds = rkds | RKDS_RK05 | RKDS_SC_OK | /* random sector */
(rand () % RK_NUMSC);
if (uptr->flags & UNIT_ATT) /* attached? */
rkds = rkds | RKDS_RDY;
if (!sim_is_active (uptr)) /* idle? */
rkds = rkds | RKDS_RWS;
if (uptr->flags & UNIT_WPRT) /* write locked? */
rkds = rkds | RKDS_WLK;
if (GET_SECT (rkda) == (rkds & RKDS_SC))
rkds = rkds | RKDS_ON_SC;
}
*data = rkds;
return SCPE_OK;
@@ -413,7 +417,7 @@ if (func == RKCS_CTLRESET) { /* control reset? */
rker = rker & ~RKER_SOFT; /* clear soft errors */
if (rker == 0) /* redo summary */
rkcs = rkcs & ~RKCS_ERR;
rkcs = rkcs & ~RKCS_SCP; /* clear sch compl*/
rkcs = rkcs & ~RKCS_SCP; /* clear sch compl */
rk_clr_done (); /* clear done */
last_drv = GET_DRIVE (rkda); /* get drive no */
uptr = rk_dev.units + last_drv; /* select unit */

View File

@@ -1,6 +1,6 @@
/* pdp11_rp.c - RP04/05/06/07 RM02/03/05/80 Massbus disk controller
Copyright (c) 1993-2008, Robert M Supnik
Copyright (c) 1993-2012, 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"),
@@ -25,6 +25,7 @@
rp RH/RP/RM moving head disks
08-Dec-12 RMS UNLOAD shouldn't set ATTN (Mark Pizzolato)
17-May-07 RMS CS1 DVA resides in device, not MBA
21-Nov-05 RMS Enable/disable device also enables/disables Massbus adapter
12-Nov-05 RMS Fixed DriveClear, does not clear disk address
@@ -709,6 +710,13 @@ switch (fnc) { /* case on function */
return SCPE_OK;
case FNC_UNLOAD: /* unload */
if (drv_tab[dtype].ctrl == RM_CTRL) { /* RM? */
rp_set_er (ER1_ILF, drv); /* not supported */
break;
}
rp_detach (uptr); /* detach unit */
return SCPE_OK;
case FNC_RECAL: /* recalibrate */
dc = 0; /* seek to 0 */
case FNC_SEEK: /* seek */
@@ -1011,12 +1019,14 @@ return SCPE_OK;
t_stat rp_detach (UNIT *uptr)
{
int32 drv;
extern int32 sim_is_running;
if (!(uptr->flags & UNIT_ATT)) /* attached? */
return SCPE_OK;
drv = (int32) (uptr - rp_dev.units); /* get drv number */
rpds[drv] = rpds[drv] & ~(DS_MOL | DS_RDY | DS_WRL | DS_VV | DS_OFM);
rp_update_ds (DS_ATA, drv); /* request intr */
if (!sim_is_running) /* from console? */
rp_update_ds (DS_ATA, drv); /* request intr */
return detach_unit (uptr);
}

View File

@@ -1,6 +1,6 @@
/* pdp11_rq.c: MSCP disk controller simulator
Copyright (c) 2002-2010, Robert M Supnik
Copyright (c) 2002-2016, Robert M Supnik
Derived from work by Stephen F. Shirron
Permission is hereby granted, free of charge, to any person obtaining a
@@ -26,6 +26,7 @@
rq RQDX3 disk controller
17-Mar-13 RMS Fixed bug in ABORT link walk loop (Dave Bryan)
14-Jan-09 JH Added support for RD32 disc drive
18-Jun-07 RMS Added UNIT_IDLE flag to timer thread
31-Oct-05 RMS Fixed address width for large files
@@ -1371,6 +1372,7 @@ if (uptr = rq_getucb (cp, lu)) { /* get unit */
cp->pak[prv].link = cp->pak[tpkt].link;
break;
}
prv = tpkt; /* no match, next */
}
}
if (tpkt) { /* found target? */

699
PDP11/pdp11_rs.c Normal file
View File

@@ -0,0 +1,699 @@
/* pdp11_rs.c - RS03/RS04 Massbus disk controller
Copyright (c) 2013, 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"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
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
in this Software without prior written authorization from Robert M Supnik.
rs RS03/RS04 fixed head disks
*/
#if defined (VM_PDP10)
#error "RS03/RS04 not supported on the PDP-10!"
#elif defined (VM_PDP11)
#include "pdp11_defs.h"
#define DEV_RADIX 8
#elif defined (VM_VAX)
#error "RS03/RS04 not supported on the VAX!"
#endif
#include <math.h>
#define RS_NUMDR 8 /* #drives */
#define RS03_NUMWD 64 /* words/sector */
#define RS04_NUMWD 128 /* words/sector */
#define RS_NUMSC 64 /* sectors/track */
#define RS_NUMTK 64 /* tracks/disk */
#define RS_MAXFR (1 << 16) /* max transfer */
#define GET_POS(x) ((int) fmod (sim_gtime() / ((double) (x)), \
((double) (RS03_NUMWD * RS_NUMSC))))
#define RS03_ID 0
#define RS04_ID 2
#define RS03_SIZE (RS_NUMTK * RS_NUMSC * RS03_NUMWD)
#define RS04_SIZE (RS_NUMTK * RS_NUMSC * RS04_NUMWD)
#define RS_NUMWD(d) ((d)? RS04_NUMWD: RS03_NUMWD)
#define RS_SIZE(d) ((d)? RS04_SIZE: RS03_SIZE)
/* Flags in the unit flags word */
#define UNIT_V_DTYPE (UNIT_V_UF + 0) /* disk type */
#define RS03_DTYPE (0)
#define RS04_DTYPE (1)
#define UNIT_V_AUTO (UNIT_V_UF + 1) /* autosize */
#define UNIT_V_WLK (UNIT_V_UF + 2) /* write lock */
#define UNIT_DTYPE (1 << UNIT_V_DTYPE)
#define UNIT_AUTO (1 << UNIT_V_AUTO)
#define UNIT_WLK (1 << UNIT_V_WLK)
#define GET_DTYPE(x) (((x) >> UNIT_V_DTYPE) & 1)
/* RSCS1 - control/status 1 - offset 0 */
#define RS_CS1_OF 0
#define CS1_GO CSR_GO /* go */
#define CS1_V_FNC 1 /* function pos */
#define CS1_M_FNC 037 /* function mask */
#define CS1_N_FNC (CS1_M_FNC + 1)
#define FNC_NOP 000 /* no operation */
#define FNC_DCLR 004 /* drive clear */
#define FNC_SEARCH 014 /* search */
#define FNC_XFR 020 /* divide line for xfr */
#define FNC_WCHK 024 /* write check */
#define FNC_WRITE 030 /* write */
#define FNC_READ 034 /* read */
#define CS1_RW 076
#define CS1_DVA 04000 /* drive avail */
#define GET_FNC(x) (((x) >> CS1_V_FNC) & CS1_M_FNC)
/* RSDS - drive status - offset 1 */
#define RS_DS_OF 1
#define DS_RDY 0000200 /* drive ready */
#define DS_DPR 0000400 /* drive present */
#define DS_LST 0002000 /* last sector */
#define DS_WLK 0004000 /* write locked */
#define DS_MOL 0010000 /* medium online */
#define DS_PIP 0020000 /* pos in progress */
#define DS_ERR 0040000 /* error */
#define DS_ATA 0100000 /* attention active */
#define DS_MBZ 0001177
/* RSER - error status - offset 2 */
#define RS_ER_OF 2
#define ER_ILF 0000001 /* illegal func */
#define ER_ILR 0000002 /* illegal register */
#define ER_RMR 0000004 /* reg mod refused */
#define ER_PAR 0000010 /* parity err */
#define ER_AOE 0001000 /* addr ovflo err */
#define ER_IAE 0002000 /* invalid addr err */
#define ER_WLE 0004000 /* write lock err NI */
#define ER_DTE 0010000 /* drive time err NI */
#define ER_OPI 0020000 /* op incomplete */
#define ER_UNS 0040000 /* drive unsafe */
#define ER_DCK 0100000 /* data check NI */
#define ER_MBZ 0000760
/* RSMR - maintenace register - offset 3 */
#define RS_MR_OF 3
/* RSAS - attention summary - offset 4 */
#define RS_AS_OF 4
#define AS_U0 0000001 /* unit 0 flag */
/* RSDA - sector/track - offset 5
All 16b are RW, but only <14:12> are tested for "invalid" address */
#define RS_DA_OF 5
#define DA_V_SC 0 /* sector pos */
#define DA_M_SC 077 /* sector mask */
#define DA_V_TK 6 /* track pos */
#define DA_M_TK 077 /* track mask */
#define GET_SC(x) (((x) >> DA_V_SC) & DA_M_SC)
#define GET_TK(x) (((x) >> DA_V_TK) & DA_M_TK)
#define DA_INV 0070000 /* inv addr */
#define DA_IGN 0100000 /* ignored */
/* RSDT - drive type - offset 6 */
#define RS_DT_OF 6
/* RSLA - look ahead register - offset 7 */
#define RS_LA_OF 7
/* This controller supports many two disk drive types:
type #words/ #sectors/ #tracks/
sector track drive
RS03 64 64 64 =256KW
RS04 128 64 640 =512KW
In theory, each drive can be a different type. The size field in
each unit selects the drive capacity for each drive and thus the
drive type.
*/
uint16 rscs1[RS_NUMDR] = { 0 }; /* control/status 1 */
uint16 rsda[RS_NUMDR] = { 0 }; /* track/sector */
uint16 rsds[RS_NUMDR] = { 0 }; /* drive status */
uint16 rser[RS_NUMDR] = { 0 }; /* error status */
uint16 rsmr[RS_NUMDR] = { 0 }; /* maint register */
uint8 rswlk[RS_NUMDR] = { 0 }; /* wlk switches */
int32 rs_stopioe = 1; /* stop on error */
int32 rs_wait = 10; /* rotate time */
static const char *rs_fname[CS1_N_FNC] = {
"NOP", "01", "02", "03", "DCLR", "05", "06", "07",
"10", "11", "12", "13", "SCH", "15", "16", "17",
"20", "21", "22", "23", "WRCHK", "25", "26", "27",
"WRITE", "31", "32", "33", "READ", "35", "36", "37"
};
extern FILE *sim_deb;
t_stat rs_mbrd (int32 *data, int32 ofs, int32 drv);
t_stat rs_mbwr (int32 data, int32 ofs, int32 drv);
t_stat rs_svc (UNIT *uptr);
t_stat rs_reset (DEVICE *dptr);
t_stat rs_attach (UNIT *uptr, char *cptr);
t_stat rs_detach (UNIT *uptr);
t_stat rs_boot (int32 unitno, DEVICE *dptr);
void rs_set_er (int32 flg, int32 drv);
void rs_clr_as (int32 mask);
void rs_update_ds (int32 flg, int32 drv);
t_stat rs_go (int32 drv);
t_stat rs_set_size (UNIT *uptr, int32 val, char *cptr, void *desc);
int32 rs_abort (void);
/* RS data structures
rs_dev RS device descriptor
rs_unit RS unit list
rs_reg RS register list
rs_mod RS modifier list
*/
DIB rs_dib = { MBA_RS, 0, &rs_mbrd, &rs_mbwr, 0, 0, 0, { &rs_abort } };
UNIT rs_unit[] = {
{ UDATA (&rs_svc, UNIT_FIX|UNIT_ATTABLE|UNIT_DISABLE|UNIT_AUTO+
UNIT_BUFABLE|UNIT_MUSTBUF|(RS04_DTYPE << UNIT_V_DTYPE), RS04_SIZE) },
{ UDATA (&rs_svc, UNIT_FIX|UNIT_ATTABLE|UNIT_DISABLE|UNIT_AUTO+
UNIT_BUFABLE|UNIT_MUSTBUF|(RS04_DTYPE << UNIT_V_DTYPE), RS04_SIZE) },
{ UDATA (&rs_svc, UNIT_FIX|UNIT_ATTABLE|UNIT_DISABLE|UNIT_AUTO+
UNIT_BUFABLE|UNIT_MUSTBUF|(RS04_DTYPE << UNIT_V_DTYPE), RS04_SIZE) },
{ UDATA (&rs_svc, UNIT_FIX|UNIT_ATTABLE|UNIT_DISABLE|UNIT_AUTO+
UNIT_BUFABLE|UNIT_MUSTBUF|(RS04_DTYPE << UNIT_V_DTYPE), RS04_SIZE) },
{ UDATA (&rs_svc, UNIT_FIX|UNIT_ATTABLE|UNIT_DISABLE|UNIT_AUTO+
UNIT_BUFABLE|UNIT_MUSTBUF|(RS04_DTYPE << UNIT_V_DTYPE), RS04_SIZE) },
{ UDATA (&rs_svc, UNIT_FIX|UNIT_ATTABLE|UNIT_DISABLE|UNIT_AUTO+
UNIT_BUFABLE|UNIT_MUSTBUF|(RS04_DTYPE << UNIT_V_DTYPE), RS04_SIZE) },
{ UDATA (&rs_svc, UNIT_FIX|UNIT_ATTABLE|UNIT_DISABLE|UNIT_AUTO+
UNIT_BUFABLE|UNIT_MUSTBUF|(RS04_DTYPE << UNIT_V_DTYPE), RS04_SIZE) },
{ UDATA (&rs_svc, UNIT_FIX|UNIT_ATTABLE|UNIT_DISABLE|UNIT_AUTO+
UNIT_BUFABLE|UNIT_MUSTBUF|(RS04_DTYPE << UNIT_V_DTYPE), RS04_SIZE) }
};
REG rs_reg[] = {
{ BRDATA (CS1, rscs1, DEV_RDX, 16, RS_NUMDR) },
{ BRDATA (DA, rsda, DEV_RDX, 16, RS_NUMDR) },
{ BRDATA (DS, rsds, DEV_RDX, 16, RS_NUMDR) },
{ BRDATA (ER, rser, DEV_RDX, 16, RS_NUMDR) },
{ BRDATA (MR, rsmr, DEV_RDX, 16, RS_NUMDR) },
{ BRDATA (WLKS, rswlk, DEV_RDX, 6, RS_NUMDR) },
{ DRDATA (TIME, rs_wait, 24), REG_NZ + PV_LEFT },
{ URDATA (CAPAC, rs_unit[0].capac, 10, T_ADDR_W, 0,
RS_NUMDR, PV_LEFT | REG_HRO) },
{ FLDATA (STOP_IOE, rs_stopioe, 0) },
{ NULL }
};
MTAB rs_mod[] = {
{ MTAB_XTD|MTAB_VDV, 0, "MASSBUS", "MASSBUS", NULL, &mba_show_num },
{ UNIT_WLK, 0, "write enabled", "WRITEENABLED", NULL },
{ UNIT_WLK, UNIT_WLK, "write lockable", "LOCKABLE", NULL },
{ (UNIT_DTYPE|UNIT_ATT), (RS03_DTYPE << UNIT_V_DTYPE) + UNIT_ATT,
"RS03", NULL, NULL },
{ (UNIT_DTYPE|UNIT_ATT), (RS04_DTYPE << UNIT_V_DTYPE) + UNIT_ATT,
"RS04", NULL, NULL },
{ (UNIT_AUTO|UNIT_DTYPE|UNIT_ATT), (RS03_DTYPE << UNIT_V_DTYPE),
"RS03", NULL, NULL },
{ (UNIT_AUTO|UNIT_DTYPE|UNIT_ATT), (RS04_DTYPE << UNIT_V_DTYPE),
"RS04", NULL, NULL },
{ (UNIT_AUTO+UNIT_ATT), UNIT_AUTO, "autosize", NULL, NULL },
{ UNIT_AUTO, UNIT_AUTO, NULL, "AUTOSIZE", NULL },
{ (UNIT_AUTO|UNIT_DTYPE), (RS03_DTYPE << UNIT_V_DTYPE),
NULL, "RS03", &rs_set_size },
{ (UNIT_AUTO|UNIT_DTYPE), (RS04_DTYPE << UNIT_V_DTYPE),
NULL, "RS04", &rs_set_size },
{ 0 }
};
DEVICE rs_dev = {
"RS", rs_unit, rs_reg, rs_mod,
RS_NUMDR, DEV_RADIX, 19, 1, DEV_RADIX, 16,
NULL, NULL, &rs_reset,
&rs_boot, &rs_attach, &rs_detach,
&rs_dib, DEV_DISABLE|DEV_DIS|DEV_UBUS|DEV_QBUS|DEV_MBUS|DEV_DEBUG
};
/* Massbus register read */
t_stat rs_mbrd (int32 *data, int32 ofs, int32 drv)
{
uint32 val, dtype, i;
UNIT *uptr;
rs_update_ds (0, drv); /* update ds */
uptr = rs_dev.units + drv; /* get unit */
if (uptr->flags & UNIT_DIS) { /* nx disk */
*data = 0;
return MBE_NXD;
}
dtype = GET_DTYPE (uptr->flags); /* get drive type */
ofs = ofs & MBA_RMASK; /* mask offset */
switch (ofs) { /* decode offset */
case RS_CS1_OF: /* RSCS1 */
val = (rscs1[drv] & CS1_RW) | CS1_DVA; /* DVA always set */
break;
case RS_DA_OF: /* RSDA */
val = rsda[drv];
break;
case RS_DS_OF: /* RSDS */
val = rsds[drv] & ~DS_MBZ;
break;
case RS_ER_OF: /* RSER */
val = rser[drv] & ~ER_MBZ;
break;
case RS_AS_OF: /* RSAS */
val = 0;
for (i = 0; i < RS_NUMDR; i++) {
if (rsds[i] & DS_ATA)
val |= (AS_U0 << i);
}
break;
case RS_LA_OF: /* RSLA */
val = GET_POS (rs_wait);
break;
case RS_MR_OF: /* RSMR */
val = rsmr[drv];
break;
case RS_DT_OF: /* RSDT */
val = dtype? RS04_ID: RS03_ID;
break;
default: /* all others */
*data = 0;
return MBE_NXR;
}
*data = val;
return SCPE_OK;
}
/* Massbus register write */
t_stat rs_mbwr (int32 data, int32 ofs, int32 drv)
{
int32 dtype;
UNIT *uptr;
uptr = rs_dev.units + drv; /* get unit */
if (uptr->flags & UNIT_DIS) /* nx disk */
return MBE_NXD;
if ((ofs != RS_AS_OF) && sim_is_active (uptr)) { /* unit busy? */
rs_set_er (ER_RMR, drv); /* won't write */
rs_update_ds (0, drv);
return SCPE_OK;
}
dtype = GET_DTYPE (uptr->flags); /* get drive type */
ofs = ofs & MBA_RMASK; /* mask offset */
switch (ofs) { /* decode PA<5:1> */
case RS_CS1_OF: /* RSCS1 */
rscs1[drv] = data & CS1_RW;
if (data & CS1_GO) /* start op */
return rs_go (drv);
break;
case RS_DA_OF: /* RSDA */
rsda[drv] = data;
break;
case RS_AS_OF: /* RSAS */
rs_clr_as (data);
break;
case RS_MR_OF: /* RSMR */
rsmr[drv] = data;
break;
case RS_ER_OF: /* RSER */
case RS_DS_OF: /* RSDS */
case RS_LA_OF: /* RSLA */
case RS_DT_OF: /* RSDT */
break; /* read only */
default: /* all others */
return MBE_NXR;
} /* end switch */
rs_update_ds (0, drv); /* update status */
return SCPE_OK;
}
/* Initiate operation - unit not busy, function set */
t_stat rs_go (int32 drv)
{
int32 fnc, dtype, t;
UNIT *uptr;
fnc = GET_FNC (rscs1[drv]); /* get function */
if (DEBUG_PRS (rs_dev))
fprintf (sim_deb, ">>RS%d STRT: fnc=%s, ds=%o, da=%o, er=%o\n",
drv, rs_fname[fnc], rsds[drv], rsda[drv], rser[drv]);
uptr = rs_dev.units + drv; /* get unit */
rs_clr_as (AS_U0 << drv); /* clear attention */
dtype = GET_DTYPE (uptr->flags); /* get drive type */
if ((fnc != FNC_DCLR) && (rsds[drv] & DS_ERR)) { /* err & ~clear? */
rs_set_er (ER_ILF, drv); /* not allowed */
rs_update_ds (DS_ATA, drv); /* set attention */
return MBE_GOE;
}
switch (fnc) { /* case on function */
case FNC_DCLR: /* drive clear */
rser[drv] = 0; /* clear errors */
case FNC_NOP: /* no operation */
return SCPE_OK;
case FNC_SEARCH: /* search */
case FNC_WRITE: /* write */
case FNC_WCHK: /* write check */
case FNC_READ: /* read */
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
rs_set_er (ER_UNS, drv); /* unsafe */
break;
}
if (rsda[drv] & DA_INV) { /* bad address? */
rs_set_er (ER_IAE, drv);
break;
}
rsds[drv] = rsds[drv] & ~DS_RDY; /* clr drive rdy */
if (fnc == FNC_SEARCH) /* search? */
rsds[drv] = rsds[drv] | DS_PIP; /* set PIP */
t = abs (rsda[drv] - GET_POS (rs_wait)); /* pos diff */
if (t < 1) /* min time */
t = 1;
sim_activate (uptr, rs_wait * t); /* schedule */
return SCPE_OK;
default: /* all others */
rs_set_er (ER_ILF, drv); /* not supported */
break;
}
rs_update_ds (DS_ATA, drv); /* set attn, req int */
return MBE_GOE;
}
/* Abort opertion - there is a data transfer in progress */
int32 rs_abort (void)
{
return rs_reset (&rs_dev);
}
/* Service unit timeout
Complete search or data transfer command
Unit must exist - can't remove an active unit
Drives are buffered in memory - no IO errors
*/
t_stat rs_svc (UNIT *uptr)
{
int32 i, fnc, dtype, drv;
int32 wc, abc, awc, mbc, da;
uint16 *fbuf = (uint16 *)uptr->filebuf;
dtype = GET_DTYPE (uptr->flags); /* get drive type */
drv = (int32) (uptr - rs_dev.units); /* get drv number */
da = rsda[drv] * RS_NUMWD (dtype); /* get disk addr */
fnc = GET_FNC (rscs1[drv]); /* get function */
if ((uptr->flags & UNIT_ATT) == 0) { /* not attached? */
rs_set_er (ER_UNS, drv); /* set drive error */
if (fnc >= FNC_XFR) /* xfr? set done */
mba_set_don (rs_dib.ba);
rs_update_ds (DS_ATA, drv); /* set attn */
return (rs_stopioe? SCPE_UNATT: SCPE_OK);
}
rsds[drv] = (rsds[drv] & ~DS_PIP) | DS_RDY; /* change drive status */
switch (fnc) { /* case on function */
case FNC_SEARCH: /* search */
rs_update_ds (DS_ATA, drv);
break;
case FNC_WRITE: /* write */
if ((uptr->flags & UNIT_WLK) && /* write locked? */
(GET_TK (rsda[drv]) <= (int32) rswlk[drv])) {
rs_set_er (ER_WLE, drv); /* set drive error */
mba_set_exc (rs_dib.ba); /* set exception */
rs_update_ds (DS_ATA, drv); /* set attn */
return SCPE_OK;
}
case FNC_WCHK: /* write check */
case FNC_READ: /* read */
if (rsda[drv] & DA_INV) { /* bad addr? */
rs_set_er (ER_IAE, drv); /* set error */
mba_set_exc (rs_dib.ba); /* set exception */
rs_update_ds (DS_ATA, drv); /* set attn */
break;
}
fbuf = fbuf + da; /* ptr into buffer */
mbc = mba_get_bc (rs_dib.ba); /* get byte count */
wc = (mbc + 1) >> 1; /* convert to words */
if ((da + wc) > RS_SIZE (dtype)) { /* disk overrun? */
rs_set_er (ER_AOE, drv); /* set err */
wc = RS_SIZE (dtype) - da; /* trim xfer */
mbc = wc << 1; /* trim mb count */
}
if (fnc == FNC_WRITE) { /* write? */
abc = mba_rdbufW (rs_dib.ba, mbc, fbuf); /* rd mem to buf */
wc = (abc + 1) >> 1; /* actual # wds */
awc = (wc + (RS_NUMWD (dtype) - 1)) & ~(RS_NUMWD (dtype) - 1);
for (i = wc; i < awc; i++) /* fill buf */
fbuf[i] = 0;
if ((da + awc) > (int32) uptr->hwmark) /* update hw mark*/
uptr->hwmark = da + awc;
} /* end if wr */
else if (fnc == FNC_READ) /* read */
mba_wrbufW (rs_dib.ba, mbc, fbuf); /* wri buf to mem */
else mba_chbufW (rs_dib.ba, mbc, fbuf); /* check vs mem */
da = da + wc + (RS_NUMWD (dtype) - 1);
if (da >= RS_SIZE (dtype))
rsds[drv] = rsds[drv] | DS_LST;
rsda[drv] = da / RS_NUMWD (dtype);
mba_set_don (rs_dib.ba); /* set done */
rs_update_ds (0, drv); /* update ds */
break;
} /* end case func */
if (DEBUG_PRS (rs_dev))
fprintf (sim_deb, ">>RS%d DONE: fnc=%s, ds=%o, da=%o, er=%d\n",
drv, rs_fname[fnc], rsds[drv], rsda[drv], rser[drv]);
return SCPE_OK;
}
/* Set drive error */
void rs_set_er (int32 flag, int32 drv)
{
rser[drv] = rser[drv] | flag;
rsds[drv] = rsds[drv] | DS_ATA;
mba_upd_ata (rs_dib.ba, 1);
return;
}
/* Clear attention flags */
void rs_clr_as (int32 mask)
{
uint32 i, as;
for (i = as = 0; i < RS_NUMDR; i++) {
if (mask & (AS_U0 << i))
rsds[i] &= ~DS_ATA;
if (rsds[i] & DS_ATA)
as = 1;
}
mba_upd_ata (rs_dib.ba, as);
return;
}
/* Drive status update */
void rs_update_ds (int32 flag, int32 drv)
{
if (flag & DS_ATA)
mba_upd_ata (rs_dib.ba, 1);
if (rs_unit[drv].flags & UNIT_DIS) {
rsds[drv] = rser[drv] = 0;
return;
}
else rsds[drv] = (rsds[drv] | DS_DPR) & ~(DS_ERR | DS_WLK);
if (rs_unit[drv].flags & UNIT_ATT) {
rsds[drv] = rsds[drv] | DS_MOL;
if ((rs_unit[drv].flags & UNIT_WLK) &&
(GET_TK (rsda[drv]) <= (int32) rswlk[drv]))
rsds[drv] = rsds[drv] | DS_WLK;
}
if (rser[drv])
rsds[drv] = rsds[drv] | DS_ERR;
rsds[drv] = rsds[drv] | flag;
return;
}
/* Device reset */
t_stat rs_reset (DEVICE *dptr)
{
int32 i;
UNIT *uptr;
mba_set_enbdis (MBA_RS, rs_dev.flags & DEV_DIS);
for (i = 0; i < RS_NUMDR; i++) {
uptr = rs_dev.units + i;
sim_cancel (uptr);
rscs1[i] = 0;
rser[i] = 0;
rsda[i] = 0;
rsmr[i] = 0;
rsds[i] = DS_RDY;
rs_update_ds (0, i); /* upd drive status */
}
return SCPE_OK;
}
/* Device attach */
t_stat rs_attach (UNIT *uptr, char *cptr)
{
int32 drv, p;
t_stat r;
uptr->capac = RS_SIZE (GET_DTYPE (uptr->flags));
r = attach_unit (uptr, cptr); /* attach unit */
if (r != SCPE_OK) /* error? */
return r;
drv = (int32) (uptr - rs_dev.units); /* get drv number */
rsds[drv] = DS_MOL | DS_RDY | DS_DPR; /* upd drv status */
rser[drv] = 0;
rs_update_ds (DS_ATA, drv); /* upd drive status */
if ((uptr->flags & UNIT_AUTO) == 0) /* autosize? */
return SCPE_OK;
p = sim_fsize (uptr->fileref); /* get file size */
if (((p + 1) >> 1) <= RS03_SIZE) {
uptr->flags &= ~UNIT_DTYPE;
uptr->capac = RS03_SIZE;
}
else {
uptr->flags |= UNIT_DTYPE;
uptr->capac = RS04_SIZE;
}
return SCPE_OK;
}
/* Device detach */
t_stat rs_detach (UNIT *uptr)
{
int32 drv;
extern int32 sim_is_running;
if (!(uptr->flags & UNIT_ATT)) /* attached? */
return SCPE_OK;
drv = (int32) (uptr - rs_dev.units); /* get drv number */
rsds[drv] = 0;
if (!sim_is_running) /* from console? */
rs_update_ds (DS_ATA, drv); /* request intr */
return detach_unit (uptr);
}
/* Set size command validation routine */
t_stat rs_set_size (UNIT *uptr, int32 val, char *cptr, void *desc)
{
int32 dtype = GET_DTYPE (val);
if (uptr->flags & UNIT_ATT)
return SCPE_ALATT;
uptr->capac = RS_SIZE (dtype);
return SCPE_OK;
}
/* Set bad block routine */
/* Boot routine */
#define BOOT_START 02000 /* start */
#define BOOT_ENTRY (BOOT_START + 002) /* entry */
#define BOOT_UNIT (BOOT_START + 010) /* unit number */
#define BOOT_CSR (BOOT_START + 014) /* CSR */
#define BOOT_LEN (sizeof (boot_rom) / sizeof (uint16))
static const uint16 boot_rom[] = {
0042123, /* "SD" */
0012706, BOOT_START, /* mov #boot_start, sp */
0012700, 0000000, /* mov #unit, r0 */
0012701, 0172040, /* mov #RSCS1, r1 */
0012761, 0000040, 0000010, /* mov #CS2_CLR, 10(r1) ; reset */
0010061, 0000010, /* mov r0, 10(r1) ; set unit */
0012761, 0177000, 0000002, /* mov #-512., 2(r1) ; set wc */
0005061, 0000004, /* clr 4(r1) ; clr ba */
0005061, 0000006, /* clr 6(r1) ; clr da */
0012711, 0000071, /* mov #READ+GO, (r1) ; read */
0105711, /* tstb (r1) ; wait */
0100376, /* bpl .-2 */
0005002, /* clr R2 */
0005003, /* clr R3 */
0012704, BOOT_START+020, /* mov #start+020, r4 */
0005005, /* clr R5 */
0105011, /* clrb (r1) */
0005007 /* clr PC */
};
t_stat rs_boot (int32 unitno, DEVICE *dptr)
{
int32 i;
extern int32 saved_PC;
extern uint16 *M;
UNIT *uptr = rs_dev.units + unitno;
for (i = 0; i < BOOT_LEN; i++)
M[(BOOT_START >> 1) + i] = boot_rom[i];
M[BOOT_UNIT >> 1] = unitno & (RS_NUMDR - 1);
M[BOOT_CSR >> 1] = mba_get_csr (rs_dib.ba) & DMASK;
saved_PC = BOOT_ENTRY;
return SCPE_OK;
}

View File

@@ -1,6 +1,6 @@
/* pdp11_rx.c: RX11/RX01 floppy disk simulator
Copyright (c) 1993-2008, Robert M Supnik
Copyright (c) 1993-2013, 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"),
@@ -25,6 +25,7 @@
rx RX11/RX01 floppy disk
03-Sep-13 RMS Added explicit void * cast
07-Jul-05 RMS Removed extraneous externs
12-Oct-02 RMS Added autoconfigure support
08-Oct-02 RMS Added variable address support to bootstrap
@@ -330,7 +331,7 @@ t_stat rx_svc (UNIT *uptr)
{
int32 i, func;
uint32 da;
int8 *fbuf = uptr->filebuf;
int8 *fbuf = (int8 *) uptr->filebuf;
func = RXCS_GETFNC (rx_csr); /* get function */
switch (rx_state) { /* case on state */

View File

@@ -1,6 +1,6 @@
/* pdp11_ry.c: RX211/RXV21/RX02 floppy disk simulator
Copyright (c) 1993-2008, Robert M Supnik
Copyright (c) 1993-2013, 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"),
@@ -25,6 +25,7 @@
ry RX211/RXV21/RX02 floppy disk
03-Sep-13 RMS Added explicit void * cast
15-May-06 RMS Fixed bug in autosize attach (David Gesswein)
07-Jul-05 RMS Removed extraneous externs
18-Feb-05 RMS Fixed bug in boot code (Graham Toal)
@@ -374,7 +375,7 @@ t_stat ry_svc (UNIT *uptr)
int32 i, t, func, bps;
static uint8 estat[8];
uint32 ba, da;
int8 *fbuf = uptr->filebuf;
int8 *fbuf = (int8 *) uptr->filebuf;
func = RYCS_GETFNC (ry_csr); /* get function */
bps = (ry_csr & RYCS_DEN)? RY_NUMBY: RX_NUMBY; /* get sector size */

View File

@@ -1,6 +1,6 @@
/* pdp11_sys.c: PDP-11 simulator interface
Copyright (c) 1993-2012, Robert M Supnik
Copyright (c) 1993-2013, 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"),
@@ -23,6 +23,7 @@
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
02-Sep-13 RMS Added third Massbus, RS03/RS04
29-Apr-12 RMS Fixed compiler warning (Mark Pizzolato)
19-Nov-08 RMS Moved I/O support routines to I/O library
15-May-08 RMS Added KE11-A, DC11 support
@@ -92,6 +93,7 @@ extern DEVICE rx_dev;
extern DEVICE ry_dev;
extern DEVICE mba_dev[];
extern DEVICE rp_dev;
extern DEVICE rs_dev;
extern DEVICE rq_dev, rqb_dev, rqc_dev, rqd_dev;
extern DEVICE tm_dev;
extern DEVICE tq_dev;
@@ -128,6 +130,7 @@ DEVICE *sim_devices[] = {
&sys_dev,
&mba_dev[0],
&mba_dev[1],
&mba_dev[2],
&clk_dev,
&pclk_dev,
&ptr_dev,
@@ -150,6 +153,7 @@ DEVICE *sim_devices[] = {
&rx_dev,
&ry_dev,
&rp_dev,
&rs_dev,
&rq_dev,
&rqb_dev,
&rqc_dev,

View File

@@ -1,6 +1,6 @@
/* pdp11_ta.c: PDP-11 cassette tape simulator
Copyright (c) 2007-2008, Robert M Supnik
Copyright (c) 2007-2013, 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"),
@@ -24,7 +24,9 @@
in this Software without prior written authorization from Robert M Supnik.
ta TA11/TU60 cassette tape
06-Jun-13 RMS Reset must set RDY (Ian Hammond)
Added CAPS-11 bootstrap (Ian Hammond)
06-Aug-07 RMS Foward op at BOT skips initial file gap
Magnetic tapes are represented as a series of variable records
@@ -130,6 +132,7 @@ t_stat ta_svc (UNIT *uptr);
t_stat ta_reset (DEVICE *dptr);
t_stat ta_attach (UNIT *uptr, char *cptr);
t_stat ta_detach (UNIT *uptr);
t_stat ta_boot (int32 unitno, DEVICE *dptr);
void ta_go (void);
t_stat ta_map_err (UNIT *uptr, t_stat st);
UNIT *ta_busy (void);
@@ -196,8 +199,8 @@ DEVICE ta_dev = {
"TA", ta_unit, ta_reg, ta_mod,
TA_NUMDR, 10, 31, 1, 8, 8,
NULL, NULL, &ta_reset,
NULL, &ta_attach, &ta_detach,
&ta_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG
&ta_boot, &ta_attach, &ta_detach,
&ta_dib, DEV_DISABLE | DEV_DIS | DEV_DEBUG | DEV_UBUS
};
/* I/O dispatch routines, I/O addresses 17777500 - 17777503
@@ -444,8 +447,8 @@ switch (uptr->FNC) { /* case on function */
ta_cs |= TACS_RDY; /* set ready */
ta_updsta (uptr); /* update status */
if (DEBUG_PRS (ta_dev))
fprintf (sim_deb, ">>TA done: op=%o, status = %o, pos=%d\n",
uptr->FNC, ta_cs, uptr->pos);
fprintf (sim_deb, ">>TA done: op=%o, status = %o, dstatus = %o, pos=%d\n",
uptr->FNC, ta_cs, uptr->UST, uptr->pos);
return r;
}
@@ -564,7 +567,7 @@ t_stat ta_reset (DEVICE *dptr)
uint32 u;
UNIT *uptr;
ta_cs = 0;
ta_cs = TACS_RDY; /* init sets RDY */
ta_idb = 0;
ta_odb = 0;
ta_write = 0;
@@ -610,3 +613,54 @@ ta_updsta (NULL);
uptr->UST = 0;
return r;
}
/* Bootstrap routine */
#define BOOT_START 01000 /* start */
#define BOOT_ENTRY (BOOT_START)
#define BOOT_CSR (BOOT_START + 002) /* CSR */
#define BOOT_LEN (sizeof (boot_rom) / sizeof (uint16))
static const uint16 boot_rom[] = {
0012700, /* mov #tacs,r0 */
0177500,
0005010, /* clr (r0) */
0010701, /* 3$: mov pc,r1 */
0062701, /* add #20-here,r1 */
0000052,
0012702, /* mov #375,r2 */
0000375,
0112103, /* movb (r1)+,r3 */
0112110, /* 5$: movb (r1)+,(r0) */
0100413, /* bmi 15$ */
0130310, /* 10$: bitb r3,(r0) */
0001776, /* beq 10$ */
0105202, /* incb r2 */
0100772, /* bmi 5$ */
0116012, /* movb 2(r0),r2 */
0000002,
0120337, /* cmpb r3,@#0 */
0000000,
0001767, /* beq 10$ */
0000000, /* 12$: halt */
0000755, /* br 3$ */
0005710, /* 15$: tst (r0) */
0100774, /* bmi 12$ */
0005007, /* clr pc */
0017640, /* $20: (data) */
0002415,
0112024
};
t_stat ta_boot (int32 unitno, DEVICE *dptr)
{
int32 i;
extern int32 saved_PC;
extern uint16 *M;
for (i = 0; i < BOOT_LEN; i++)
M[(BOOT_START >> 1) + i] = boot_rom[i];
M[BOOT_CSR >> 1] = ta_dib.ba & DMASK;
saved_PC = BOOT_ENTRY;
return SCPE_OK;
}

View File

@@ -1,6 +1,6 @@
/* pdp11_tq.c: TMSCP tape controller simulator
Copyright (c) 2002-2011, Robert M Supnik
Copyright (c) 2002-2013, 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"),
@@ -25,6 +25,7 @@
tq TQK50 tape controller
17-Mar-13 RMS Fixed bug in ABORT link walk loop (Dave Bryan)
17-Aug-11 RMS Added CAPACITY modifier
14-Jan-11 MP Various fixes discovered while exploring Ultrix issue:
- Set UNIT_SXC flag when a tape mark is encountered
@@ -877,6 +878,7 @@ if (uptr = tq_getucb (lu)) { /* get unit */
tq_pkt[prv].link = tq_pkt[tpkt].link; /* unlink */
break;
}
prv = tpkt; /* no match, next */
}
}
if (tpkt) { /* found target? */