1 /* pdp10_ksio.c: PDP-10 KS10 I/O subsystem simulator
3 Copyright (c) 1993-2005, Robert M Supnik
5 Permission is hereby granted, free of charge, to any person obtaining a
6 copy of this software and associated documentation files (the "Software"),
7 to deal in the Software without restriction, including without limitation
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 and/or sell copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following conditions:
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 Except as contained in this notice, the name of Robert M Supnik shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from Robert M Supnik.
28 22-Sep-05 RMS Fixed declarations (from Sterling Garwood)
29 25-Jan-04 RMS Added stub floating address routine
30 12-Mar-03 RMS Added logical name support
31 10-Oct-02 RMS Revised for dynamic table generation
32 Added SHOW IOSPACE routine
33 29-Sep-02 RMS Added variable vector, central map support
34 25-Jan-02 RMS Revised for multiple DZ11's
35 06-Jan-02 RMS Revised enable/disable support
36 23-Sep-01 RMS New IO page address constants
37 07-Sep-01 RMS Revised device disable mechanism
38 25-Aug-01 RMS Enabled DZ11
39 21-Aug-01 RMS Updated DZ11 disable
40 01-Jun-01 RMS Updated DZ11 vectors
41 12-May-01 RMS Fixed typo
43 The KS10 uses the PDP-11 Unibus for its I/O, via adapters. While
44 nominally four adapters are supported, in practice only 1 and 3
45 are implemented. The disks are placed on adapter 1, the rest of
46 the I/O devices on adapter 3.
48 In theory, we should maintain completely separate Unibuses, with
49 distinct PI systems. In practice, this simulator has so few devices
50 that we can get away with a single PI system, masking for which
51 devices are on adapter 1, and which on adapter 3. The Unibus
52 implementation is modeled on the Qbus in the PDP-11 simulator and
55 The I/O subsystem is programmed by I/O instructions which create
56 Unibus operations (read, read pause, write, write byte). DMA is
57 the responsibility of the I/O device simulators, which also implement
58 Unibus to physical memory mapping.
60 The priority interrupt subsystem (and other privileged functions)
61 is programmed by I/O instructions with internal devices codes
62 (opcodes 700-702). These are dispatched here, although many are
63 handled in the memory management unit or elsewhere.
65 The ITS instructions are significantly different from the TOPS-10/20
66 instructions. They do not use the extended address calculation but
67 instead provide instruction variants (Q for Unibus adapter 1, I for
68 Unibus adapter 3) which insert the Unibus adapter number into the
72 #include "pdp10_defs.h"
75 #define XBA_MBZ 0400000 /* ba mbz */
76 #define eaRB (ea & ~1)
77 #define GETBYTE(ea,x) ((((ea) & 1)? (x) >> 8: (x)) & 0377)
78 #define UBNXM_FAIL(pa,op) \
79 n = iocmap[GET_IOUBA (pa)]; \
80 if (n >= 0) ubcs[n] = ubcs[n] | UBCS_TMO | UBCS_NXD; \
81 pager_word = PF_HARD | PF_VIRT | PF_IO | \
82 ((op == WRITEB)? PF_BYTE: 0) | \
83 (TSTF (F_USR)? PF_USER: 0) | (pa); \
86 /* Unibus adapter data */
88 int32 ubcs
[UBANUM
] = { 0 }; /* status registers */
89 int32 ubmap
[UBANUM
][UMAP_MEMSIZE
] = { 0 }; /* Unibus maps */
90 int32 int_req
= 0; /* interrupt requests */
92 /* Map IO controller numbers to Unibus adapters: -1 = non-existent */
94 static int iocmap
[IO_N_UBA
] = { /* map I/O ext to UBA # */
95 -1, 0, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
98 static const int32 ubabr76
[UBANUM
] = {
99 INT_UB1
& (INT_IPL7
| INT_IPL6
), INT_UB3
& (INT_IPL7
| INT_IPL6
)
101 static const int32 ubabr54
[UBANUM
] = {
102 INT_UB1
& (INT_IPL5
| INT_IPL4
), INT_UB3
& (INT_IPL5
| INT_IPL4
)
104 static const int32 ubashf
[4] = { 18, 26, 0, 8 };
106 extern d10
*M
; /* main memory */
108 extern d10 pager_word
;
110 extern const int32 pi_l2bit
[8];
111 extern UNIT cpu_unit
;
112 extern FILE *sim_log
;
113 extern jmp_buf save_env
;
114 extern DEVICE
*sim_devices
[];
116 extern int32
pi_eval (void);
117 extern int32
rp_inta (void);
118 extern int32
tu_inta (void);
119 extern int32
lp20_inta (void);
120 extern int32
dz_rxinta (void);
121 extern int32
dz_txinta (void);
123 t_stat
ubmap_rd (int32
*data
, int32 addr
, int32 access
);
124 t_stat
ubmap_wr (int32 data
, int32 addr
, int32 access
);
125 t_stat
ubs_rd (int32
*data
, int32 addr
, int32 access
);
126 t_stat
ubs_wr (int32 data
, int32 addr
, int32 access
);
127 t_stat
rd_zro (int32
*data
, int32 addr
, int32 access
);
128 t_stat
wr_nop (int32 data
, int32 addr
, int32 access
);
129 t_stat
uba_ex (t_value
*vptr
, t_addr addr
, UNIT
*uptr
, int32 sw
);
130 t_stat
uba_dep (t_value val
, t_addr addr
, UNIT
*uptr
, int32 sw
);
131 t_stat
uba_reset (DEVICE
*dptr
);
133 void WriteIO (a10 ea
, d10 val
, int32 mode
);
135 /* Unibus adapter data structures
137 uba_dev UBA device descriptor
139 uba_reg UBA register list
142 DIB ubmp1_dib
= { IOBA_UBMAP1
, IOLN_UBMAP1
, &ubmap_rd
, &ubmap_wr
, 0 };
143 DIB ubmp3_dib
= { IOBA_UBMAP3
, IOLN_UBMAP3
, &ubmap_rd
, &ubmap_wr
, 0 };
144 DIB ubcs1_dib
= { IOBA_UBCS1
, IOLN_UBCS1
, &ubs_rd
, &ubs_wr
, 0 };
145 DIB ubcs3_dib
= { IOBA_UBCS3
, IOLN_UBCS3
, &ubs_rd
, &ubs_wr
, 0 };
146 DIB ubmn1_dib
= { IOBA_UBMNT1
, IOLN_UBMNT1
, &rd_zro
, &wr_nop
, 0 };
147 DIB ubmn3_dib
= { IOBA_UBMNT3
, IOLN_UBMNT3
, &rd_zro
, &wr_nop
, 0 };
148 DIB msys_dib
= { 00100000, 1, &rd_zro
, &wr_nop
, 0 };
151 { UDATA (NULL
, UNIT_FIX
, UMAP_MEMSIZE
) },
152 { UDATA (NULL
, UNIT_FIX
, UMAP_MEMSIZE
) }
156 { ORDATA (INTREQ
, int_req
, 32), REG_RO
},
157 { ORDATA (UB1CS
, ubcs
[0], 18) },
158 { ORDATA (UB3CS
, ubcs
[1], 18) },
163 "UBA", uba_unit
, uba_reg
, NULL
,
164 UBANUM
, 8, UMAP_ASIZE
, 1, 8, 32,
165 &uba_ex
, &uba_dep
, &uba_reset
,
170 /* PDP-11 I/O structures */
172 DIB
*dib_tab
[DIB_MAX
]; /* run-time DIBs */
174 int32 (*int_ack
[32])(void); /* int ack routines */
176 int32 int_vec
[32]; /* int vectors */
178 DIB
*std_dib
[] = { /* standard DIBs */
189 /* IO 710 (DEC) TIOE - test I/O word, skip if zero
190 (ITS) IORDI - read word from Unibus 3
191 returns TRUE if skip, FALSE otherwise
194 t_bool
io710 (int32 ac
, a10 ea
)
198 if (Q_ITS
) AC(ac
) = ReadIO (IO_UBA3
| ea
); /* IORDI */
200 val
= ReadIO (ea
); /* read word */
201 if ((AC(ac
) & val
) == 0) return TRUE
;
206 /* IO 711 (DEC) TION - test I/O word, skip if non-zero
207 (ITS) IORDQ - read word from Unibus 1
208 returns TRUE if skip, FALSE otherwise
211 t_bool
io711 (int32 ac
, a10 ea
)
215 if (Q_ITS
) AC(ac
) = ReadIO (IO_UBA1
| ea
); /* IORDQ */
217 val
= ReadIO (ea
); /* read word */
218 if ((AC(ac
) & val
) != 0) return TRUE
;
223 /* IO 712 (DEC) RDIO - read I/O word, addr in ea
224 (ITS) IORD - read I/O word, addr in M[ea]
229 return ReadIO (ea
); /* RDIO, IORD */
232 /* IO 713 (DEC) WRIO - write I/O word, addr in ea
233 (ITS) IOWR - write I/O word, addr in M[ea]
236 void io713 (d10 val
, a10 ea
)
238 WriteIO (ea
, val
& 0177777, WRITE
); /* WRIO, IOWR */
242 /* IO 714 (DEC) BSIO - set bit in I/O address
243 (ITS) IOWRI - write word to Unibus 3
246 void io714 (d10 val
, a10 ea
)
251 if (Q_ITS
) WriteIO (IO_UBA3
| ea
, val
, WRITE
); /* IOWRI */
253 temp
= ReadIO (ea
); /* BSIO */
255 WriteIO (ea
, temp
, WRITE
);
260 /* IO 715 (DEC) BCIO - clear bit in I/O address
261 (ITS) IOWRQ - write word to Unibus 1
264 void io715 (d10 val
, a10 ea
)
269 if (Q_ITS
) WriteIO (IO_UBA1
| ea
, val
, WRITE
); /* IOWRQ */
271 temp
= ReadIO (ea
); /* BCIO */
273 WriteIO (ea
, temp
, WRITE
);
278 /* IO 720 (DEC) TIOEB - test I/O byte, skip if zero
279 (ITS) IORDBI - read byte from Unibus 3
280 returns TRUE if skip, FALSE otherwise
283 t_bool
io720 (int32 ac
, a10 ea
)
287 if (Q_ITS
) { /* IORDBI */
288 val
= ReadIO (IO_UBA3
| eaRB
);
289 AC(ac
) = GETBYTE (ea
, val
);
293 val
= GETBYTE (ea
, val
);
294 if ((AC(ac
) & val
) == 0) return TRUE
;
299 /* IO 721 (DEC) TIONB - test I/O word, skip if non-zero
300 (ITS) IORDBQ - read word from Unibus 1
301 returns TRUE if skip, FALSE otherwise
304 t_bool
io721 (int32 ac
, a10 ea
)
308 if (Q_ITS
) { /* IORDBQ */
309 val
= ReadIO (IO_UBA1
| eaRB
);
310 AC(ac
) = GETBYTE (ea
, val
);
314 val
= GETBYTE (ea
, val
);
315 if ((AC(ac
) & val
) != 0) return TRUE
;
320 /* IO 722 (DEC) RDIOB - read I/O byte, addr in ea
321 (ITS) IORDB - read I/O byte, addr in M[ea]
328 val
= ReadIO (eaRB
); /* RDIOB, IORDB */
329 return GETBYTE (ea
, val
);
332 /* IO 723 (DEC) WRIOB - write I/O byte, addr in ea
333 (ITS) IOWRB - write I/O byte, addr in M[ea]
336 void io723 (d10 val
, a10 ea
)
338 WriteIO (ea
, val
& 0377, WRITEB
); /* WRIOB, IOWRB */
342 /* IO 724 (DEC) BSIOB - set bit in I/O byte address
343 (ITS) IOWRBI - write byte to Unibus 3
346 void io724 (d10 val
, a10 ea
)
351 if (Q_ITS
) WriteIO (IO_UBA3
| ea
, val
, WRITEB
); /* IOWRBI */
353 temp
= ReadIO (eaRB
); /* BSIOB */
354 temp
= GETBYTE (ea
, temp
);
356 WriteIO (ea
, temp
, WRITEB
);
361 /* IO 725 (DEC) BCIOB - clear bit in I/O byte address
362 (ITS) IOWRBQ - write byte to Unibus 1
365 void io725 (d10 val
, a10 ea
)
370 if (Q_ITS
) WriteIO (IO_UBA1
| ea
, val
, WRITEB
); /* IOWRBQ */
372 temp
= ReadIO (eaRB
); /* BCIOB */
373 temp
= GETBYTE (ea
, temp
);
375 WriteIO (ea
, temp
, WRITEB
);
380 /* Read and write I/O devices.
381 These routines are the linkage between the 64b world of the main
382 simulator and the 32b world of the device simulators.
387 uint32 pa
= (uint32
) ea
;
391 for (i
= 0; dibp
= dib_tab
[i
]; i
++ ) {
392 if ((pa
>= dibp
->ba
) &&
393 (pa
< (dibp
->ba
+ dibp
->lnt
))) {
394 dibp
->rd (&val
, pa
, READ
);
399 UBNXM_FAIL (pa
, READ
);
402 void WriteIO (a10 ea
, d10 val
, int32 mode
)
404 uint32 pa
= (uint32
) ea
;
408 for (i
= 0; dibp
= dib_tab
[i
]; i
++ ) {
409 if ((pa
>= dibp
->ba
) &&
410 (pa
< (dibp
->ba
+ dibp
->lnt
))) {
411 dibp
->wr ((int32
) val
, pa
, mode
);
416 UBNXM_FAIL (pa
, mode
);
419 /* Mapped read and write routines - used by standard Unibus devices on Unibus 1 */
421 a10
Map_Addr10 (a10 ba
, int32 ub
)
424 int32 vpn
= PAG_GETVPN (ba
>> 2); /* get PDP-10 page number */
426 if ((vpn
>= UMAP_MEMSIZE
) || (ba
& XBA_MBZ
) ||
427 ((ubmap
[ub
][vpn
] & UMAP_VLD
) == 0)) return -1; /* invalid map? */
428 pa10
= (ubmap
[ub
][vpn
] + PAG_GETOFF (ba
>> 2)) & PAMASK
;
432 int32
Map_ReadB (uint32 ba
, int32 bc
, uint8
*buf
)
438 for ( ; ba
< lim
; ba
++) { /* by bytes */
439 pa10
= Map_Addr10 (ba
, 1); /* map addr */
440 if ((pa10
< 0) || MEM_ADDR_NXM (pa10
)) { /* inv map or NXM? */
441 ubcs
[1] = ubcs
[1] | UBCS_TMO
; /* UBA times out */
442 return (lim
- ba
); /* return bc */
444 *buf
++ = (uint8
) ((M
[pa10
] >> ubashf
[ba
& 3]) & 0377);
449 int32
Map_ReadW (uint32 ba
, int32 bc
, uint16
*buf
)
454 ba
= ba
& ~01; /* align start */
455 lim
= ba
+ (bc
& ~01);
456 for ( ; ba
< lim
; ba
= ba
+ 2) { /* by words */
457 pa10
= Map_Addr10 (ba
, 1); /* map addr */
458 if ((pa10
< 0) || MEM_ADDR_NXM (pa10
)) { /* inv map or NXM? */
459 ubcs
[1] = ubcs
[1] | UBCS_TMO
; /* UBA times out */
460 return (lim
- ba
); /* return bc */
462 *buf
++ = (uint16
) ((M
[pa10
] >> ((ba
& 2)? 0: 18)) & 0177777);
467 int32
Map_WriteB (uint32 ba
, int32 bc
, uint8
*buf
)
474 for ( ; ba
< lim
; ba
++) { /* by bytes */
475 pa10
= Map_Addr10 (ba
, 1); /* map addr */
476 if ((pa10
< 0) || MEM_ADDR_NXM (pa10
)) { /* inv map or NXM? */
477 ubcs
[1] = ubcs
[1] | UBCS_TMO
; /* UBA times out */
478 return (lim
- ba
); /* return bc */
481 M
[pa10
] = (M
[pa10
] & ~(mask
<< ubashf
[ba
& 3])) |
482 (((d10
) *buf
++) << ubashf
[ba
& 3]);
487 int32
Map_WriteW (uint32 ba
, int32 bc
, uint16
*buf
)
493 ba
= ba
& ~01; /* align start */
494 lim
= ba
+ (bc
& ~01);
495 for ( ; ba
< lim
; ba
++) { /* by bytes */
496 pa10
= Map_Addr10 (ba
, 1); /* map addr */
497 if ((pa10
< 0) || MEM_ADDR_NXM (pa10
)) { /* inv map or NXM? */
498 ubcs
[1] = ubcs
[1] | UBCS_TMO
; /* UBA times out */
499 return (lim
- ba
); /* return bc */
501 val
= *buf
++; /* get data */
502 if (ba
& 2) M
[pa10
] = (M
[pa10
] & 0777777600000) | val
;
503 else M
[pa10
] = (M
[pa10
] & 0600000777777) | (val
<< 18);
508 /* Evaluate Unibus priority interrupts */
514 for (i
= lvl
= 0; i
< UBANUM
; i
++) {
515 if (int_req
& ubabr76
[i
])
516 lvl
= lvl
| pi_l2bit
[UBCS_GET_HI (ubcs
[i
])];
517 if (int_req
& ubabr54
[i
])
518 lvl
= lvl
| pi_l2bit
[UBCS_GET_LO (ubcs
[i
])];
523 /* Return Unibus device vector
525 Takes as input the request level calculated by pi_eval
526 If there is an interrupting Unibus device at that level, return its vector,
530 int32
pi_ub_vec (int32 rlvl
, int32
*uba
)
534 for (i
= masked_irq
= 0; i
< UBANUM
; i
++) {
535 if ((rlvl
== UBCS_GET_HI (ubcs
[i
])) && /* req on hi level? */
536 (masked_irq
= int_req
& ubabr76
[i
])) break;
537 if ((rlvl
== UBCS_GET_LO (ubcs
[i
])) && /* req on lo level? */
538 (masked_irq
= int_req
& ubabr54
[i
])) break;
540 *uba
= (i
<< 1) + 1; /* store uba # */
541 for (i
= 0; (i
< 32) && masked_irq
; i
++) { /* find hi pri req */
542 if ((masked_irq
>> i
) & 1) {
543 int_req
= int_req
& ~(1u << i
); /* clear req */
544 if (int_ack
[i
]) return int_ack
[i
]();
545 return int_vec
[i
]; /* return vector */
551 /* Unibus adapter map routines */
553 t_stat
ubmap_rd (int32
*val
, int32 pa
, int32 mode
)
555 int32 n
= iocmap
[GET_IOUBA (pa
)];
557 if (n
< 0) ABORT (STOP_ILLIOC
);
558 *val
= ubmap
[n
][pa
& UMAP_AMASK
];
562 t_stat
ubmap_wr (int32 val
, int32 pa
, int32 mode
)
564 int32 n
= iocmap
[GET_IOUBA (pa
)];
566 if (n
< 0) ABORT (STOP_ILLIOC
);
567 ubmap
[n
][pa
& UMAP_AMASK
] = UMAP_POSFL (val
) | UMAP_POSPN (val
);
571 /* Unibus adapter control/status routines */
573 t_stat
ubs_rd (int32
*val
, int32 pa
, int32 mode
)
575 int32 n
= iocmap
[GET_IOUBA (pa
)];
577 if (n
< 0) ABORT (STOP_ILLIOC
);
578 if (int_req
& ubabr76
[n
]) ubcs
[n
] = ubcs
[n
] | UBCS_HI
;
579 if (int_req
& ubabr54
[n
]) ubcs
[n
] = ubcs
[n
] | UBCS_LO
;
580 *val
= ubcs
[n
] = ubcs
[n
] & ~UBCS_RDZ
;
584 t_stat
ubs_wr (int32 val
, int32 pa
, int32 mode
)
586 int32 n
= iocmap
[GET_IOUBA (pa
)];
588 if (n
< 0) ABORT (STOP_ILLIOC
);
589 if (val
& UBCS_INI
) {
590 reset_all (5); /* start after UBA */
591 ubcs
[n
] = val
& UBCS_DXF
;
593 else ubcs
[n
] = val
& UBCS_RDW
;
594 if (int_req
& ubabr76
[n
]) ubcs
[n
] = ubcs
[n
] | UBCS_HI
;
595 if (int_req
& ubabr54
[n
]) ubcs
[n
] = ubcs
[n
] | UBCS_LO
;
599 /* Unibus adapter read zero/write ignore routines */
601 t_stat
rd_zro (int32
*val
, int32 pa
, int32 mode
)
607 t_stat
wr_nop (int32 val
, int32 pa
, int32 mode
)
612 /* Simulator interface routines */
614 t_stat
uba_ex (t_value
*vptr
, t_addr addr
, UNIT
*uptr
, int32 sw
)
616 int32 uba
= uptr
- uba_unit
;
618 if (addr
>= UMAP_MEMSIZE
) return SCPE_NXM
;
619 *vptr
= ubmap
[uba
][addr
];
623 t_stat
uba_dep (t_value val
, t_addr addr
, UNIT
*uptr
, int32 sw
)
625 int32 uba
= uptr
- uba_unit
;
627 if (addr
>= UMAP_MEMSIZE
) return SCPE_NXM
;
628 ubmap
[uba
][addr
] = (int32
) val
& UMAP_MASK
;
632 t_stat
uba_reset (DEVICE
*dptr
)
637 for (uba
= 0; uba
< UBANUM
; uba
++) {
639 for (i
= 0; i
< UMAP_MEMSIZE
; i
++) ubmap
[uba
][i
] = 0;
645 /* Change device address */
647 t_stat
set_addr (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
654 if (cptr
== NULL
) return SCPE_ARG
;
655 if ((val
== 0) || (uptr
== NULL
)) return SCPE_IERR
;
656 dptr
= find_dev_from_unit (uptr
);
657 if (dptr
== NULL
) return SCPE_IERR
;
658 dibp
= (DIB
*) dptr
->ctxt
;
659 if (dibp
== NULL
) return SCPE_IERR
;
660 newba
= (uint32
) get_uint (cptr
, 8, PAMASK
, &r
); /* get new */
661 if ((r
!= SCPE_OK
) || (newba
== dibp
->ba
)) return r
;
662 if (GET_IOUBA (newba
) != GET_IOUBA (dibp
->ba
)) return SCPE_ARG
;
663 if (newba
% ((uint32
) val
)) return SCPE_ARG
; /* check modulus */
664 if (GET_IOUBA (newba
) != GET_IOUBA (dibp
->ba
)) return SCPE_ARG
;
665 dibp
->ba
= newba
; /* store */
669 /* Show device address */
671 t_stat
show_addr (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
)
676 if (uptr
== NULL
) return SCPE_IERR
;
677 dptr
= find_dev_from_unit (uptr
);
678 if (dptr
== NULL
) return SCPE_IERR
;
679 dibp
= (DIB
*) dptr
->ctxt
;
680 if ((dibp
== NULL
) || (dibp
->ba
<= IOPAGEBASE
)) return SCPE_IERR
;
681 fprintf (st
, "address=%07o", dibp
->ba
);
683 fprintf (st
, "-%07o", dibp
->ba
+ dibp
->lnt
- 1);
687 /* Change device vector */
689 t_stat
set_vec (UNIT
*uptr
, int32 arg
, char *cptr
, void *desc
)
696 if (cptr
== NULL
) return SCPE_ARG
;
697 if (uptr
== NULL
) return SCPE_IERR
;
698 dptr
= find_dev_from_unit (uptr
);
699 if (dptr
== NULL
) return SCPE_IERR
;
700 dibp
= (DIB
*) dptr
->ctxt
;
701 if (dibp
== NULL
) return SCPE_IERR
;
702 newvec
= (uint32
) get_uint (cptr
, 8, VEC_Q
+ 01000, &r
);
703 if ((r
!= SCPE_OK
) || (newvec
== VEC_Q
) ||
704 ((newvec
+ (dibp
->vnum
* 4)) >= (VEC_Q
+ 01000)) ||
705 (newvec
& ((dibp
->vnum
> 1)? 07: 03))) return SCPE_ARG
;
710 /* Show device vector */
712 t_stat
show_vec (FILE *st
, UNIT
*uptr
, int32 arg
, void *desc
)
718 if (uptr
== NULL
) return SCPE_IERR
;
719 dptr
= find_dev_from_unit (uptr
);
720 if (dptr
== NULL
) return SCPE_IERR
;
721 dibp
= (DIB
*) dptr
->ctxt
;
722 if (dibp
== NULL
) return SCPE_IERR
;
724 if (arg
) numvec
= arg
;
725 else numvec
= dibp
->vnum
;
726 if (vec
== 0) fprintf (st
, "no vector");
728 fprintf (st
, "vector=%o", vec
);
729 if (numvec
> 1) fprintf (st
, "-%o", vec
+ (4 * (numvec
- 1)));
734 /* Test for conflict in device addresses */
736 t_bool
dev_conflict (DIB
*curr
)
742 end
= curr
->ba
+ curr
->lnt
- 1; /* get end */
743 for (i
= 0; (dptr
= sim_devices
[i
]) != NULL
; i
++) { /* loop thru dev */
744 dibp
= (DIB
*) dptr
->ctxt
; /* get DIB */
745 if ((dibp
== NULL
) || (dibp
== curr
) ||
746 (dptr
->flags
& DEV_DIS
)) continue;
747 if (((curr
->ba
>= dibp
->ba
) && /* overlap start? */
748 (curr
->ba
< (dibp
->ba
+ dibp
->lnt
))) ||
749 ((end
>= dibp
->ba
) && /* overlap end? */
750 (end
< (dibp
->ba
+ dibp
->lnt
)))) {
751 printf ("Device %s address conflict at %08o\n",
752 sim_dname (dptr
), dibp
->ba
);
753 if (sim_log
) fprintf (sim_log
,
754 "Device %s address conflict at %08o\n",
755 sim_dname (dptr
), dibp
->ba
);
762 /* Build interrupt tables */
764 void build_int_vec (int32 vloc
, int32 ivec
, int32 (*iack
)(void) )
766 if (iack
!= NULL
) int_ack
[vloc
] = iack
;
767 else int_vec
[vloc
] = ivec
;
771 /* Build dib_tab from device list */
773 t_bool
build_dib_tab (void)
779 for (i
= 0; i
< 32; i
++) { /* clear intr tables */
783 for (i
= j
= 0; (dptr
= sim_devices
[i
]) != NULL
; i
++) { /* loop thru dev */
784 dibp
= (DIB
*) dptr
->ctxt
; /* get DIB */
785 if (dibp
&& !(dptr
->flags
& DEV_DIS
)) { /* defined, enabled? */
786 if (dibp
->vnum
> VEC_DEVMAX
) return SCPE_IERR
;
787 for (k
= 0; k
< dibp
->vnum
; k
++) /* loop thru vec */
788 build_int_vec (dibp
->vloc
+ k
, /* add vector */
789 dibp
->vec
+ (k
* 4), dibp
->ack
[k
]);
790 if (dibp
->lnt
!= 0) { /* I/O addresses? */
791 dib_tab
[j
++] = dibp
; /* add DIB to dib_tab */
792 if (j
>= DIB_MAX
) return SCPE_IERR
; /* too many? */
794 } /* end if enabled */
796 for (i
= 0; (dibp
= std_dib
[i
]) != NULL
; i
++) { /* loop thru std */
797 dib_tab
[j
++] = dibp
; /* add to dib_tab */
798 if (j
>= DIB_MAX
) return SCPE_IERR
; /* too many? */
800 dib_tab
[j
] = NULL
; /* end with NULL */
801 for (i
= 0; (dibp
= dib_tab
[i
]) != NULL
; i
++) { /* test built dib_tab */
802 if (dev_conflict (dibp
)) return SCPE_STOP
; /* for conflicts */
809 t_stat
show_iospace (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
)
811 int32 i
, j
, done
= 0;
815 build_dib_tab (); /* build table */
816 while (done
== 0) { /* sort ascending */
817 done
= 1; /* assume done */
818 for (i
= 0; dib_tab
[i
+ 1] != NULL
; i
++) { /* check table */
819 if (dib_tab
[i
]->ba
> dib_tab
[i
+ 1]->ba
) { /* out of order? */
820 dibt
= dib_tab
[i
]; /* interchange */
821 dib_tab
[i
] = dib_tab
[i
+ 1];
822 dib_tab
[i
+ 1] = dibt
;
823 done
= 0; /* not done */
827 for (i
= 0; dib_tab
[i
] != NULL
; i
++) { /* print table */
828 for (j
= 0, dptr
= NULL
; sim_devices
[j
] != NULL
; j
++) {
829 if (((DIB
*) sim_devices
[j
]->ctxt
) == dib_tab
[i
]) {
830 dptr
= sim_devices
[j
];
834 fprintf (st
, "%07o - %07o\t%s\n", dib_tab
[i
]->ba
,
835 dib_tab
[i
]->ba
+ dib_tab
[i
]->lnt
- 1,
836 dptr
? sim_dname (dptr
): "CPU");
841 /* Stub auto-configure */
843 t_stat
auto_config (char *name
, int32 num
)
848 /* Stub floating address */
850 t_stat
set_addr_flt (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)