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:
862
PDP11/old/pdp11_defs.h
Normal file
862
PDP11/old/pdp11_defs.h
Normal 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
856
PDP11/old/pdp11_rh.c
Normal 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
1089
PDP11/old/pdp11_sys.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
260
PDP11/pdp11_hk.c
260
PDP11/pdp11_hk.c
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
699
PDP11/pdp11_rs.c
Normal 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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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? */
|
||||
|
||||
Reference in New Issue
Block a user