206e059a204847fdf7de6f31414f26552fc04497
1 /* vax780_uba.c: VAX 11/780 Unibus adapter
3 Copyright (c) 2004-2008, 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.
26 uba DW780 Unibus adapter
28 28-May-08 RMS Inlined physical memory routines
29 25-Jan-08 RMS Fixed declarations (from Mark Pizzolato)
36 #define UBA_NDPATH 16 /* number of data paths */
37 #define UBA_NMAPR 496 /* number of map reg */
39 /* Unibus configuration register */
41 #define UBACNF_OF 0x00
42 #define UBACNF_ADPDN 0x00800000 /* adap pdn - ni */
43 #define UBACNF_ADPUP 0x00400000 /* adap pup - ni */
44 #define UBACNF_UBINIT 0x00040000 /* UB INIT - ni */
45 #define UBACNF_UBPDN 0x00020000 /* UB pdn */
46 #define UBACNF_UBIC 0x00010000 /* UB init done */
47 #define UBACNF_CODE 0x00000028 /* adapter code */
48 #define UBACNF_RD (SBI_FAULTS|UBACNF_W1C)
49 #define UBACNF_W1C 0x00C70000
51 /* Control register */
54 #define UBACR_V_DSB 26 /* map disable */
55 #define UBACR_M_DSB 0x1F
56 #define UBACR_GETDSB(x) (((x) >> (UBACR_V_DSB - 4)) & (UBACR_M_DSB << 4))
57 #define UBACR_IFS 0x00000040 /* SBI field intr */
58 #define UBACR_BRIE 0x00000020 /* BR int enable */
59 #define UBACR_USEFIE 0x00000010 /* UB to SBI int enb */
60 #define UBACR_SUEFIE 0x00000008 /* SBI to UB int enb */
61 #define UBACR_CNFIE 0x00000004 /* config int enb */
62 #define UBACR_UPF 0x00000002 /* power fail UB */
63 #define UBACR_ADINIT 0x00000001 /* adapter init */
64 #define UBACR_RD ((UBACR_M_DSB << UBACR_V_DSB) | 0x0000007E)
65 #define UBACR_WR (UBACR_RD)
67 #define UBA_USEFIE_SR (UBASR_RDTO|UBASR_RDS|UBASR_CRD|UBASR_CXTER| \
68 UBASR_CXTO|UBASR_DPPE|UBASR_IVMR|UBASR_MRPF)
69 #define UBA_SUEFIE_SR (UBASR_UBSTO|UBASR_UBTMO)
70 #define UBA_CNFIE_CR (UBACNF_ADPDN|UBACNF_ADPUP|UBACNF_UBINIT|\
71 UBACNF_UBPDN|UBACNF_UBIC)
76 #define UBASR_V_BR4 24 /* filled br's - ni */
77 #define UBASR_RDTO 0x00000400 /* read tmo - ni */
78 #define UBASR_RDS 0x00000200 /* read sub - ni */
79 #define UBASR_CRD 0x00000100 /* read crd - ni */
80 #define UBASR_CXTER 0x00000080 /* cmd xfr err - ni */
81 #define UBASR_CXTO 0x00000040 /* cmd xfr tmo - ni */
82 #define UBASR_DPPE 0x00000020 /* parity err - ni */
83 #define UBASR_IVMR 0x00000010 /* invalid map reg */
84 #define UBASR_MRPF 0x00000008 /* map reg par - ni */
85 #define UBASR_LEB 0x00000004 /* locked err */
86 #define UBASR_UBSTO 0x00000002 /* UB select tmo - ni */
87 #define UBASR_UBTMO 0x00000001 /* UB nxm */
88 #define UBASR_RD 0x0F0007FF
89 #define UBASR_W1C 0x000007FF
91 /* Diagnostic register */
94 #define UBADR_SPARE 0x80000000 /* spare */
95 #define UBADR_DINTR 0x40000000 /* disable intr */
96 #define UBADR_DMP 0x20000000
97 #define UBADR_DDPP 0x10000000
98 #define UBADR_MICOK 0x08000000 /* microseq ok */
99 #define UBADR_RD 0xF8000000
100 #define UBADR_WR 0xF0000000
101 #define UBADR_CNF_RD 0x07FFFFFF
103 /* Failing map entry - read only */
105 #define UBAFMER_OF 0x04
106 #define UBAFMER_OF1 0x06
107 #define UBAFMER_RD 0x1FF
109 /* Failing Unibus address - read only */
111 #define UBAFUBAR_OF 0x05
112 #define UBAFUBAR_OF1 0x07
113 #define UBAFUBAR_RD 0xFFFF
115 /* Spare registers - read/write */
117 #define UBABRSVR_OF 0x08
119 /* Vector registers - read only */
121 #define UBABRRVR_OF 0x0C
122 #define UBA_UVEC 0x80000000
124 /* Data path registers */
126 #define UBADPR_OF 0x010
127 #define UBADPR_BNE 0x80000000 /* buf not empty - ni */
128 #define UBADPR_BTE 0x40000000 /* buf xfr err - ni */
129 #define UBADPR_DIR 0x20000000 /* buf rd/wr */
130 #define UBADPR_STATE 0x00FF0000 /* byte full state - ni */
131 #define UBADPR_UA 0x0000FFFF /* Unibus addr<17:2> */
132 #define UBADPR_UA 0x0000FFFF /* last UB addr */
133 #define UBADPR_RD 0xC0FFFFFF
134 #define UBADPR_W1C 0xC0000000
138 #define UBAMAP_OF 0x200
139 #define UBAMAP_VLD 0x80000000 /* valid */
140 #define UBAMAP_LWAE 0x04000000 /* LW access enb - ni */
141 #define UBAMAP_ODD 0x02000000 /* odd byte */
142 #define UBAMAP_V_DP 21 /* data path */
143 #define UBAMAP_M_DP 0xF
144 #define UBAMAP_DP (UBAMAP_M_DP << UBAMAP_V_DP)
145 #define UBAMAP_GETDP(x) (((x) >> UBAMAP_V_DP) & UBAMAP_M_DP)
146 #define UBAMAP_PAG 0x001FFFFF
147 #define UBAMAP_RD (0x86000000 | UBAMAP_DP | UBAMAP_PAG)
148 #define UBAMAP_WR (UBAMAP_RD)
152 #define UBA_DEB_RRD 0x01 /* reg reads */
153 #define UBA_DEB_RWR 0x02 /* reg writes */
154 #define UBA_DEB_MRD 0x04 /* map reads */
155 #define UBA_DEB_MWR 0x08 /* map writes */
156 #define UBA_DEB_XFR 0x10 /* transfers */
157 #define UBA_DEB_ERR 0x20 /* errors */
159 int32 int_req
[IPL_HLVL
] = { 0 }; /* intr, IPL 14-17 */
160 uint32 uba_cnf
= 0; /* config reg */
161 uint32 uba_cr
= 0; /* control reg */
162 uint32 uba_sr
= 0; /* status reg */
163 uint32 uba_dr
= 0; /* diag ctrl */
164 uint32 uba_int
= 0; /* UBA interrupt */
165 uint32 uba_fmer
= 0; /* failing map reg */
166 uint32 uba_fubar
= 0; /* failing Unibus addr */
167 uint32 uba_svr
[4] = { 0 }; /* diag registers */
168 uint32 uba_rvr
[4] = { 0 }; /* vector reg */
169 uint32 uba_dpr
[UBA_NDPATH
] = { 0 }; /* number data paths */
170 uint32 uba_map
[UBA_NMAPR
] = { 0 }; /* map registers */
171 uint32 uba_aiip
= 0; /* adapter init in prog */
172 uint32 uba_uiip
= 0; /* Unibus init in prog */
173 uint32 uba_aitime
= 250; /* adapter init time */
174 uint32 uba_uitime
= 12250; /* Unibus init time */
175 int32 autcon_enb
= 1; /* autoconfig enable */
178 extern int32 autcon_enb
;
179 extern jmp_buf save_env
;
180 extern DEVICE
*sim_devices
[];
181 extern UNIT cpu_unit
;
182 extern uint32 nexus_req
[NEXUS_HLVL
];
183 extern int32 sim_switches
;
184 extern FILE *sim_log
, *sim_deb
;
186 t_stat
uba_svc (UNIT
*uptr
);
187 t_stat
uba_reset (DEVICE
*dptr
);
188 t_stat
uba_ex (t_value
*vptr
, t_addr exta
, UNIT
*uptr
, int32 sw
);
189 t_stat
uba_dep (t_value val
, t_addr exta
, UNIT
*uptr
, int32 sw
);
190 t_stat
uba_rdreg (int32
*val
, int32 pa
, int32 mode
);
191 t_stat
uba_wrreg (int32 val
, int32 pa
, int32 lnt
);
192 int32
uba_get_ubvector (int32 lvl
);
193 void uba_ub_nxm (int32 ua
);
194 void uba_inv_map (int32 ublk
);
195 void uba_eval_int (void);
196 void uba_adap_set_int (int32 flg
);
197 void uba_adap_clr_int ();
198 void uba_set_dpr (uint32 ua
, t_bool wr
);
199 void uba_ubpdn (int32 time
);
200 t_bool
uba_map_addr (uint32 ua
, uint32
*ma
);
201 t_stat
set_autocon (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
);
202 t_stat
show_autocon (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
);
203 t_stat
show_iospace (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
);
204 t_stat
uba_show_virt (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
);
206 extern int32
eval_int (void);
207 extern t_stat
build_dib_tab (void);
209 /* Unibus IO page dispatches */
211 static t_stat (*iodispR
[IOPAGESIZE
>> 1])(int32
*dat
, int32 ad
, int32 md
);
212 static t_stat (*iodispW
[IOPAGESIZE
>> 1])(int32 dat
, int32 ad
, int32 md
);
213 static DIB
*iodibp
[IOPAGESIZE
>> 1];
215 /* Unibus interrupt request to interrupt action map */
217 int32 (*int_ack
[IPL_HLVL
][32])(); /* int ack routines */
219 /* Unibus interrupt request to vector map */
221 int32 int_vec
[IPL_HLVL
][32]; /* int req to vector */
223 /* Unibus adapter data structures
225 uba_dev UBA device descriptor
227 uba_reg UBA register list
230 DIB uba_dib
= { TR_UBA
, 0, &uba_rdreg
, &uba_wrreg
, 0, 0 };
232 UNIT uba_unit
= { UDATA (&uba_svc
, 0, 0) };
235 { HRDATA (IPL14
, int_req
[0], 32), REG_RO
},
236 { HRDATA (IPL15
, int_req
[1], 32), REG_RO
},
237 { HRDATA (IPL16
, int_req
[2], 32), REG_RO
},
238 { HRDATA (IPL17
, int_req
[3], 32), REG_RO
},
239 { HRDATA (CNFR
, uba_cnf
, 32) },
240 { HRDATA (CR
, uba_cr
, 32) },
241 { HRDATA (SR
, uba_sr
, 32) },
242 { HRDATA (DR
, uba_dr
, 32) },
243 { FLDATA (INT
, uba_int
, 0) },
244 { FLDATA (NEXINT
, nexus_req
[IPL_UBA
], TR_UBA
) },
245 { FLDATA (AIIP
, uba_aiip
, 0) },
246 { FLDATA (UIIP
, uba_uiip
, 0) },
247 { HRDATA (FMER
, uba_fmer
, 32) },
248 { HRDATA (FUBAR
, uba_fubar
, 32) },
249 { HRDATA (BRSVR0
, uba_svr
[0], 32) },
250 { HRDATA (BRSVR1
, uba_svr
[1], 32) },
251 { HRDATA (BRSVR2
, uba_svr
[2], 32) },
252 { HRDATA (BRSVR3
, uba_svr
[3], 32) },
253 { HRDATA (BRRVR4
, uba_rvr
[0], 32) },
254 { HRDATA (BRRVR5
, uba_rvr
[1], 32) },
255 { HRDATA (BRRVR6
, uba_rvr
[2], 32) },
256 { HRDATA (BRRVR7
, uba_rvr
[3], 32) },
257 { BRDATA (DPR
, uba_dpr
, 16, 32, 16) },
258 { BRDATA (MAP
, uba_map
, 16, 32, 496) },
259 { DRDATA (AITIME
, uba_aitime
, 24), PV_LEFT
+ REG_NZ
},
260 { DRDATA (UITIME
, uba_uitime
, 24), PV_LEFT
+ REG_NZ
},
261 { FLDATA (AUTOCON
, autcon_enb
, 0), REG_HRO
},
266 { MTAB_XTD
|MTAB_VDV
, TR_UBA
, "NEXUS", NULL
,
268 { MTAB_XTD
|MTAB_VDV
|MTAB_NMO
, 0, "IOSPACE", NULL
,
269 NULL
, &show_iospace
},
270 { MTAB_XTD
|MTAB_VDV
, 1, "AUTOCONFIG", "AUTOCONFIG",
271 &set_autocon
, &show_autocon
},
272 { MTAB_XTD
|MTAB_VDV
, 0, NULL
, "NOAUTOCONFIG",
273 &set_autocon
, NULL
},
274 { MTAB_XTD
|MTAB_VDV
|MTAB_NMO
|MTAB_SHP
, 0, "VIRTUAL", NULL
,
275 NULL
, &uba_show_virt
},
280 { "REGREAD", UBA_DEB_RRD
},
281 { "REGWRITE", UBA_DEB_RWR
},
282 { "MAPREAD", UBA_DEB_MRD
},
283 { "MAPWRITE", UBA_DEB_MWR
},
284 { "XFER", UBA_DEB_XFR
},
285 { "ERROR", UBA_DEB_ERR
},
290 "UBA", &uba_unit
, uba_reg
, uba_mod
,
291 1, 16, UBADDRWIDTH
, 2, 16, 16,
292 &uba_ex
, &uba_dep
, &uba_reset
,
294 &uba_dib
, DEV_NEXUS
| DEV_DEBUG
, 0,
298 /* Read Unibus adapter register - aligned lw only */
300 t_stat
uba_rdreg (int32
*val
, int32 pa
, int32 lnt
)
304 if ((pa
& 3) || (lnt
!= L_LONG
)) { /* unaligned or not lw? */
305 printf (">>UBA: invalid adapter read mask, pa = %X, lnt = %d\r\n", pa
, lnt
);
306 sbi_set_errcnf (); /* err confirmation */
309 ofs
= NEXUS_GETOFS (pa
); /* get offset */
310 if (uba_aiip
&& (ofs
!= UBACNF_OF
) /* init in prog? */
311 && (ofs
!= UBADR_OF
)) return SCPE_NXM
; /* only cnf, dr */
312 if (ofs
>= UBAMAP_OF
) { /* map? */
313 idx
= ofs
- UBAMAP_OF
;
314 if (idx
>= UBA_NMAPR
) return SCPE_NXM
; /* valid? */
315 *val
= uba_map
[idx
] & UBAMAP_RD
;
316 if (DEBUG_PRI (uba_dev
, UBA_DEB_MRD
))
317 fprintf (sim_deb
, ">>UBA: map %d read, value = %X\n", idx
, *val
);
321 switch (ofs
) { /* case on offset */
323 case UBACNF_OF
: /* CNF */
324 *val
= (uba_cnf
& UBACNF_RD
) | UBACNF_CODE
;
327 case UBACR_OF
: /* CR */
328 *val
= uba_cr
& UBACR_RD
;
331 case UBASR_OF
: /* SR */
332 *val
= uba_sr
& UBASR_RD
;
335 case UBADR_OF
: /* DR */
336 *val
= (uba_dr
& UBADR_RD
) | UBADR_MICOK
|
337 ((uba_cnf
& UBADR_CNF_RD
) | UBACNF_CODE
);
340 case UBAFMER_OF
: case UBAFMER_OF1
: /* FMER */
341 *val
= uba_fmer
& UBAFMER_RD
;
344 case UBAFUBAR_OF
: case UBAFUBAR_OF1
: /* FUBAR */
345 *val
= uba_fubar
& UBAFUBAR_RD
;
348 case UBABRSVR_OF
+ 0: case UBABRSVR_OF
+ 1: /* BRSVR */
349 case UBABRSVR_OF
+ 2: case UBABRSVR_OF
+ 3:
350 idx
= ofs
- UBABRSVR_OF
;
354 case UBABRRVR_OF
+ 0: case UBABRRVR_OF
+ 1: /* BRRVR */
355 case UBABRRVR_OF
+ 2: case UBABRRVR_OF
+ 3:
356 idx
= ofs
- UBABRRVR_OF
;
357 uba_rvr
[idx
] = uba_get_ubvector (idx
);
361 case UBADPR_OF
+ 0: /* DPR */
362 *val
= 0; /* direct */
366 case UBADPR_OF
+ 2: case UBADPR_OF
+ 3:
367 case UBADPR_OF
+ 4: case UBADPR_OF
+ 5:
368 case UBADPR_OF
+ 6: case UBADPR_OF
+ 7:
369 case UBADPR_OF
+ 8: case UBADPR_OF
+ 9:
370 case UBADPR_OF
+ 10: case UBADPR_OF
+ 11:
371 case UBADPR_OF
+ 12: case UBADPR_OF
+ 13:
372 case UBADPR_OF
+ 14: case UBADPR_OF
+ 15:
373 idx
= ofs
- UBADPR_OF
;
374 *val
= uba_dpr
[idx
] & UBADPR_RD
;
381 if (DEBUG_PRI (uba_dev
, UBA_DEB_RRD
))
382 fprintf (sim_deb
, ">>UBA: reg %d read, value = %X\n", ofs
, *val
);
386 /* Write Unibus adapter register */
388 t_stat
uba_wrreg (int32 val
, int32 pa
, int32 lnt
)
390 int32 idx
, ofs
, old_cr
;
392 if ((pa
& 3) || (lnt
!= L_LONG
)) { /* unaligned or not lw? */
393 printf (">>UBA: invalid adapter write mask, pa = %X, lnt = %d\r\n", pa
, lnt
);
394 sbi_set_errcnf (); /* err confirmation */
397 ofs
= NEXUS_GETOFS (pa
); /* get offset */
398 if (uba_aiip
&& (ofs
!= UBACNF_OF
) && (ofs
!= UBADR_OF
) &&
399 (ofs
!= UBACR_OF
) && (ofs
!= UBASR_OF
)) return SCPE_NXM
;
400 if (ofs
>= UBAMAP_OF
) { /* map? */
401 idx
= ofs
- UBAMAP_OF
;
402 if (idx
>= UBA_NMAPR
) return SCPE_NXM
; /* valid? */
403 uba_map
[idx
] = val
& UBAMAP_WR
;
404 if (DEBUG_PRI (uba_dev
, UBA_DEB_MWR
))
405 fprintf (sim_deb
, ">>UBA: map %d write, value = %X\n", idx
, val
);
409 switch (ofs
) { /* case on offset */
411 case UBACNF_OF
: /* CNF */
412 uba_cnf
= uba_cnf
& ~(val
& UBACNF_W1C
); /* W1C bits */
413 uba_adap_clr_int (); /* possible clr int */
416 case UBACR_OF
: /* CR */
418 if (val
& UBACR_ADINIT
) { /* adapter init */
419 uba_reset (&uba_dev
); /* reset adapter */
420 uba_aiip
= 1; /* set init in prog */
421 uba_ubpdn (uba_aitime
); /* power fail UB */
423 if ((val
& UBACR_UPF
) && !(old_cr
& UBACR_UPF
) /* Unibus power clear */
424 && !sim_is_active (&uba_unit
))
425 uba_ubpdn (uba_aitime
+ uba_uitime
); /* power fail UB */
426 uba_cr
= (uba_cr
& ~UBACR_WR
) | (val
& UBACR_WR
);
427 uba_adap_set_int (uba_cr
& ~old_cr
); /* possible int set */
428 uba_adap_clr_int (); /* possible int clr */
431 case UBASR_OF
: /* SR */
432 uba_sr
= uba_sr
& ~(val
& UBASR_W1C
); /* W1C bits */
433 uba_adap_clr_int (); /* possible clr int */
436 case UBADR_OF
: /* DR */
437 uba_dr
= (uba_dr
& ~UBADR_WR
) | (val
& UBADR_WR
);
438 uba_cnf
= uba_cnf
& ~(val
& UBACNF_W1C
);
439 uba_adap_clr_int (); /* possible clr int */
442 case UBABRSVR_OF
+ 0: case UBABRSVR_OF
+ 1: /* BRSVR */
443 case UBABRSVR_OF
+ 2: case UBABRSVR_OF
+ 3:
444 idx
= ofs
- UBABRSVR_OF
;
448 case UBADPR_OF
+ 0: /* DPR */
452 case UBADPR_OF
+ 2: case UBADPR_OF
+ 3:
453 case UBADPR_OF
+ 4: case UBADPR_OF
+ 5:
454 case UBADPR_OF
+ 6: case UBADPR_OF
+ 7:
455 case UBADPR_OF
+ 8: case UBADPR_OF
+ 9:
456 case UBADPR_OF
+ 10: case UBADPR_OF
+ 11:
457 case UBADPR_OF
+ 12: case UBADPR_OF
+ 13:
458 case UBADPR_OF
+ 14: case UBADPR_OF
+ 15:
459 idx
= ofs
- UBADPR_OF
;
460 uba_dpr
[idx
] = uba_dpr
[idx
] & ~(val
& UBADPR_W1C
);
467 if (DEBUG_PRI (uba_dev
, UBA_DEB_RWR
))
468 fprintf (sim_deb
, ">>UBA: reg %d write, value = %X\n", ofs
, val
);
472 /* Read and write Unibus I/O space */
474 int32
ReadUb (uint32 pa
)
478 if (ADDR_IS_IOP (pa
) && !uba_uiip
) { /* iopage,!init */
479 idx
= (pa
& IOPAGEMASK
) >> 1;
481 iodispR
[idx
] (&val
, pa
, READ
);
485 uba_ub_nxm (pa
); /* UB nxm */
489 void WriteUb (uint32 pa
, int32 val
, int32 mode
)
493 if (ADDR_IS_IOP (pa
) && !uba_uiip
) { /* iopage,!init */
494 idx
= (pa
& IOPAGEMASK
) >> 1;
496 iodispW
[idx
] (val
, pa
, mode
);
500 uba_ub_nxm (pa
); /* UB nxm */
504 /* ReadIO - read from IO - UBA only responds to byte, aligned word
507 pa = physical address
513 int32
ReadIO (uint32 pa
, int32 lnt
)
517 if ((lnt
== L_BYTE
) || /* byte? */
518 ((lnt
== L_WORD
) && ((pa
& 1) == 0))) { /* aligned word? */
519 iod
= ReadUb (pa
); /* DATI from Unibus */
520 if (pa
& 2) iod
= iod
<< 16; /* position */
523 printf (">>UBA: invalid read mask, pa = %x, lnt = %d\n", pa
, lnt
);
524 sbi_set_errcnf (); /* err confirmation */
531 /* WriteIO - write to IO - UBA only responds to byte, aligned word
534 pa = physical address
535 val = data to write, right justified in 32b longword
541 void WriteIO (uint32 pa
, int32 val
, int32 lnt
)
543 if (lnt
== L_BYTE
) WriteUb (pa
, val
, WRITEB
); /* byte? DATOB */
544 else if ((lnt
== L_WORD
) && ((pa
& 1) == 0)) /* aligned word? */
545 WriteUb (pa
, val
, WRITE
); /* DATO */
547 printf (">>UBA: invalid write mask, pa = %x, lnt = %d\n", pa
, lnt
);
548 sbi_set_errcnf (); /* err confirmation */
550 SET_IRQL
; /* update ints */
554 /* Update UBA nexus interrupts */
556 void uba_eval_int (void)
560 for (i
= 0; i
< (IPL_HMAX
- IPL_HMIN
); i
++) /* clear all UBA req */
561 nexus_req
[i
] &= ~(1 << TR_UBA
);
562 if (((uba_dr
& UBADR_DINTR
) == 0) && !uba_uiip
&& /* intr enabled? */
563 (uba_cr
& UBACR_IFS
) && (uba_cr
& UBACR_BRIE
)) {
564 for (i
= 0; i
< (IPL_HMAX
- IPL_HMIN
); i
++) {
565 if (int_req
[i
]) nexus_req
[i
] |= (1 << TR_UBA
);
568 if (uba_int
) SET_NEXUS_INT (UBA
); /* adapter int? */
572 /* Return vector for Unibus interrupt at relative IPL level [0-3] */
574 int32
uba_get_ubvector (int32 lvl
)
579 if ((lvl
== (IPL_UBA
- IPL_HMIN
)) && uba_int
) { /* UBA lvl, int? */
580 vec
= UBA_UVEC
; /* set flag */
581 uba_int
= 0; /* clear int */
583 if (((uba_dr
& UBADR_DINTR
) == 0) && !uba_uiip
&& /* intr enabled? */
584 (uba_cr
& UBACR_IFS
) && (uba_cr
& UBACR_BRIE
)) {
585 for (i
= 0; int_req
[lvl
] && (i
< 32); i
++) {
586 if ((int_req
[lvl
] >> i
) & 1) {
587 int_req
[lvl
] = int_req
[lvl
] & ~(1u << i
);
588 if (int_ack
[lvl
][i
]) return (vec
| int_ack
[lvl
][i
]());
589 return (vec
| int_vec
[lvl
][i
]);
596 /* Unibus I/O buffer routines
598 Map_ReadB - fetch byte buffer from memory
599 Map_ReadW - fetch word buffer from memory
600 Map_WriteB - store byte buffer into memory
601 Map_WriteW - store word buffer into memory
604 int32
Map_ReadB (uint32 ba
, int32 bc
, uint8
*buf
)
609 ba
= ba
& UBADDRMASK
; /* mask UB addr */
610 for (i
= 0; i
< bc
; i
= i
+ pbc
) { /* loop by pages */
611 if (!uba_map_addr (ba
+ i
, &ma
)) return (bc
- i
); /* page inv or NXM? */
612 pbc
= VA_PAGSIZE
- VA_GETOFF (ma
); /* left in page */
613 if (pbc
> (bc
- i
)) pbc
= bc
- i
; /* limit to rem xfr */
614 if (DEBUG_PRI (uba_dev
, UBA_DEB_XFR
))
615 fprintf (sim_deb
, ">>UBA: 8b read, ma = %X, bc = %X\n", ma
, pbc
);
616 if ((ma
| pbc
) & 3) { /* aligned LW? */
617 for (j
= 0; j
< pbc
; ma
++, j
++) { /* no, do by bytes */
621 else { /* yes, do by LW */
622 for (j
= 0; j
< pbc
; ma
= ma
+ 4, j
= j
+ 4) {
623 dat
= ReadL (ma
); /* get lw */
624 *buf
++ = dat
& BMASK
; /* low 8b */
625 *buf
++ = (dat
>> 8) & BMASK
; /* next 8b */
626 *buf
++ = (dat
>> 16) & BMASK
; /* next 8b */
627 *buf
++ = (dat
>> 24) & BMASK
;
630 uba_set_dpr (ba
+ i
+ pbc
- L_BYTE
, FALSE
);
635 int32
Map_ReadW (uint32 ba
, int32 bc
, uint16
*buf
)
640 ba
= ba
& UBADDRMASK
; /* mask UB addr */
642 for (i
= 0; i
< bc
; i
= i
+ pbc
) { /* loop by pages */
643 if (!uba_map_addr (ba
+ i
, &ma
)) return (bc
- i
); /* page inv or NXM? */
644 pbc
= VA_PAGSIZE
- VA_GETOFF (ma
); /* left in page */
645 if (pbc
> (bc
- i
)) pbc
= bc
- i
; /* limit to rem xfr */
646 if (DEBUG_PRI (uba_dev
, UBA_DEB_XFR
))
647 fprintf (sim_deb
, ">>UBA: 16b read, ma = %X, bc = %X\n", ma
, pbc
);
648 if ((ma
| pbc
) & 1) { /* aligned word? */
649 for (j
= 0; j
< pbc
; ma
++, j
++) { /* no, do by bytes */
650 if ((i
+ j
) & 1) { /* odd byte? */
651 *buf
= (*buf
& BMASK
) | (ReadB (ma
) << 8);
654 else *buf
= (*buf
& ~BMASK
) | ReadB (ma
);
657 else if ((ma
| pbc
) & 3) { /* aligned LW? */
658 for (j
= 0; j
< pbc
; ma
= ma
+ 2, j
= j
+ 2) { /* no, words */
659 *buf
++ = ReadW (ma
); /* get word */
662 else { /* yes, do by LW */
663 for (j
= 0; j
< pbc
; ma
= ma
+ 4, j
= j
+ 4) {
664 dat
= ReadL (ma
); /* get lw */
665 *buf
++ = dat
& WMASK
; /* low 16b */
666 *buf
++ = (dat
>> 16) & WMASK
; /* high 16b */
669 uba_set_dpr (ba
+ i
+ pbc
- L_WORD
, FALSE
);
674 int32
Map_WriteB (uint32 ba
, int32 bc
, uint8
*buf
)
679 ba
= ba
& UBADDRMASK
; /* mask UB addr */
680 for (i
= 0; i
< bc
; i
= i
+ pbc
) { /* loop by pages */
681 if (!uba_map_addr (ba
+ i
, &ma
)) return (bc
- i
); /* page inv or NXM? */
682 pbc
= VA_PAGSIZE
- VA_GETOFF (ma
); /* left in page */
683 if (pbc
> (bc
- i
)) pbc
= bc
- i
; /* limit to rem xfr */
684 if (DEBUG_PRI (uba_dev
, UBA_DEB_XFR
))
685 fprintf (sim_deb
, ">>UBA: 8b write, ma = %X, bc = %X\n", ma
, pbc
);
686 if ((ma
| pbc
) & 3) { /* aligned LW? */
687 for (j
= 0; j
< pbc
; ma
++, j
++) { /* no, do by bytes */
692 else { /* yes, do by LW */
693 for (j
= 0; j
< pbc
; ma
= ma
+ 4, j
= j
+ 4) {
694 dat
= (uint32
) *buf
++; /* get low 8b */
695 dat
= dat
| (((uint32
) *buf
++) << 8); /* merge next 8b */
696 dat
= dat
| (((uint32
) *buf
++) << 16); /* merge next 8b */
697 dat
= dat
| (((uint32
) *buf
++) << 24); /* merge hi 8b */
698 WriteL (ma
, dat
); /* store lw */
701 uba_set_dpr (ba
+ i
+ pbc
- L_BYTE
, TRUE
);
706 int32
Map_WriteW (uint32 ba
, int32 bc
, uint16
*buf
)
711 ba
= ba
& UBADDRMASK
; /* mask UB addr */
713 for (i
= 0; i
< bc
; i
= i
+ pbc
) { /* loop by pages */
714 if (!uba_map_addr (ba
+ i
, &ma
)) return (bc
- i
); /* page inv or NXM? */
715 pbc
= VA_PAGSIZE
- VA_GETOFF (ma
); /* left in page */
716 if (pbc
> (bc
- i
)) pbc
= bc
- i
; /* limit to rem xfr */
717 if (DEBUG_PRI (uba_dev
, UBA_DEB_XFR
))
718 fprintf (sim_deb
, ">>UBA: 16b write, ma = %X, bc = %X\n", ma
, pbc
);
719 if ((ma
| pbc
) & 1) { /* aligned word? */
720 for (j
= 0; j
< pbc
; ma
++, j
++) { /* no, bytes */
722 WriteB (ma
, (*buf
>> 8) & BMASK
);
725 else WriteB (ma
, *buf
& BMASK
);
728 else if ((ma
| pbc
) & 3) { /* aligned LW? */
729 for (j
= 0; j
< pbc
; ma
= ma
+ 2, j
= j
+ 2) { /* no, words */
730 WriteW (ma
, *buf
); /* write word */
734 else { /* yes, do by LW */
735 for (j
= 0; j
< pbc
; ma
= ma
+ 4, j
= j
+ 4) {
736 dat
= (uint32
) *buf
++; /* get low 16b */
737 dat
= dat
| (((uint32
) *buf
++) << 16); /* merge hi 16b */
738 WriteL (ma
, dat
); /* store LW */
741 uba_set_dpr (ba
+ i
+ pbc
- L_WORD
, TRUE
);
746 /* Map an address via the translation map */
748 t_bool
uba_map_addr (uint32 ua
, uint32
*ma
)
752 ublk
= ua
>> VA_V_VPN
; /* Unibus blk */
753 if ((ublk
< UBACR_GETDSB (uba_cr
)) || /* map disabled? */
754 (ublk
>= UBA_NMAPR
)) return FALSE
; /* unimplemented? */
755 umap
= uba_map
[ublk
]; /* get map */
756 if (umap
& UBAMAP_VLD
) { /* valid? */
757 *ma
= ((umap
& UBAMAP_PAG
) << VA_V_VPN
) + VA_GETOFF (ua
);
758 if ((umap
& UBAMAP_DP
) && (umap
& UBAMAP_ODD
)) /* buffered dp? */
759 *ma
= *ma
+ 1; /* byte offset? */
760 return (ADDR_IS_MEM (*ma
)); /* legit addr */
762 uba_inv_map (ua
); /* invalid map */
766 /* Map an address via the translation map - console version (no status changes) */
768 t_bool
uba_map_addr_c (uint32 ua
, uint32
*ma
)
772 ublk
= ua
>> VA_V_VPN
; /* Unibus blk */
773 if ((ublk
< UBACR_GETDSB (uba_cr
)) || /* map disabled? */
774 (ublk
>= UBA_NMAPR
)) return FALSE
; /* unimplemented? */
775 umap
= uba_map
[ublk
]; /* get map */
776 if (umap
& UBAMAP_VLD
) { /* valid? */
777 *ma
= ((umap
& UBAMAP_PAG
) << VA_V_VPN
) + VA_GETOFF (ua
);
778 if ((umap
& UBAMAP_DP
) && (umap
& UBAMAP_ODD
)) /* buffered dp? */
779 *ma
= *ma
+ 1; /* byte offset? */
780 return TRUE
; /* legit addr */
785 /* At end of page or transfer, update DPR register, in case next page
788 void uba_set_dpr (uint32 ua
, t_bool wr
)
790 uint32 ublk
, umap
, dpr
;
792 ublk
= ua
>> VA_V_VPN
; /* Unibus blk */
793 if (ublk
>= UBA_NMAPR
) return; /* paranoia */
794 umap
= uba_map
[ublk
]; /* get map */
795 dpr
= UBAMAP_GETDP (umap
); /* get bdp */
796 if (dpr
) uba_dpr
[dpr
] = (uba_dpr
[dpr
] & ~(UBADPR_UA
|UBADPR_DIR
)) |
797 (wr
? UBADPR_DIR
: 0) |
798 (((ua
>> 2) + ((umap
& UBAMAP_ODD
)? 1: 0)) & UBADPR_UA
);
804 uba_ub_nxm SBI read/write to nx Unibus address
805 uba_inv_map Unibus reference to invalid map reg
808 void uba_ub_nxm (int32 ua
)
810 if ((uba_sr
& UBASR_UBTMO
) == 0) {
811 uba_sr
|= UBASR_UBTMO
;
812 uba_adap_set_int (uba_cr
& UBACR_SUEFIE
);
813 uba_fubar
= (ua
>> 2) & UBAFUBAR_RD
;
815 else uba_sr
|= UBASR_LEB
;
816 if (DEBUG_PRI (uba_dev
, UBA_DEB_ERR
))
817 fprintf (sim_deb
, ">>UBA: nxm error, ua = %X\n", ua
);
821 void uba_inv_map (int32 ublk
)
823 if ((uba_sr
& UBASR_IVMR
) == 0) {
824 uba_sr
|= UBASR_IVMR
;
825 uba_adap_set_int (uba_cr
& UBACR_USEFIE
);
826 uba_fmer
= ublk
& UBAFMER_RD
;
828 else uba_sr
|= UBASR_LEB
;
829 if (DEBUG_PRI (uba_dev
, UBA_DEB_ERR
))
830 fprintf (sim_deb
, ">>UBA: inv map error, ublk = %X\n", ublk
);
834 /* Unibus power fail routines */
836 void uba_ubpdn (int32 time
)
841 uba_cnf
= (uba_cnf
& ~UBACNF_UBIC
) | UBACNF_UBPDN
; /* update cnf */
842 sim_activate (&uba_unit
, time
); /* schedule */
843 uba_uiip
= 1; /* UB init in prog */
844 for (i
= 0; sim_devices
[i
] != NULL
; i
++) { /* reset Unibus */
845 dptr
= sim_devices
[i
];
846 if (dptr
->reset
&& (dptr
->flags
& DEV_UBUS
))
852 /* Init timeout service routine */
854 t_stat
uba_svc (UNIT
*uptr
)
856 if (uba_aiip
) { /* adapter init? */
857 uba_aiip
= 0; /* clear in prog */
858 sim_activate (uptr
, uba_uitime
); /* schedule UB */
861 uba_uiip
= 0; /* no, UB */
862 uba_cnf
= (uba_cnf
& ~UBACNF_UBPDN
) | UBACNF_UBIC
;
863 uba_adap_set_int (uba_cr
& UBACR_CNFIE
); /* possible int */
868 /* Interrupt routines */
870 void uba_adap_set_int (int32 flg
)
872 if (((flg
& UBACR_SUEFIE
) && (uba_sr
& UBA_SUEFIE_SR
)) ||
873 ((flg
& UBACR_USEFIE
) && (uba_sr
& UBA_USEFIE_SR
)) ||
874 ((flg
& UBACR_CNFIE
) && (uba_cr
& UBA_CNFIE_CR
))) {
876 if (DEBUG_PRI (uba_dev
, UBA_DEB_ERR
)) fprintf (sim_deb
,
877 ">>UBA: adapter int req, sr = %X, cr = %X\n", uba_sr
, uba_cr
);
882 void uba_adap_clr_int ()
884 if ((!(uba_cr
& UBACR_SUEFIE
) || !(uba_sr
& UBA_SUEFIE_SR
)) &&
885 (!(uba_cr
& UBACR_USEFIE
) || !(uba_sr
& UBA_USEFIE_SR
)) &&
886 (!(uba_cr
& UBACR_CNFIE
) || !(uba_cr
& UBA_CNFIE_CR
)))
891 /* Reset Unibus adapter */
893 t_stat
uba_reset (DEVICE
*dptr
)
898 uba_aiip
= uba_uiip
= 0;
899 sim_cancel (&uba_unit
);
900 for (i
= 0; i
< IPL_HLVL
; i
++) {
901 nexus_req
[i
] &= ~(1 << TR_UBA
);
906 for (i
= 0; i
< UBA_NMAPR
; i
++) uba_map
[i
] = 0;
907 for (i
= 0; i
< UBA_NDPATH
; i
++) uba_dpr
[i
] = 0;
911 uba_cnf
= UBACNF_UBIC
;
915 /* Memory examine via map (word only) */
917 t_stat
uba_ex (t_value
*vptr
, t_addr exta
, UNIT
*uptr
, int32 sw
)
919 uint32 ua
= (uint32
) exta
, pa
;
921 if ((vptr
== NULL
) || (ua
>= UBADDRSIZE
)) return SCPE_ARG
;
922 if (uba_map_addr_c (ua
, &pa
) && ADDR_IS_MEM (pa
)) {
923 *vptr
= (uint32
) ReadW (pa
);
929 /* Memory deposit via map (word only) */
931 t_stat
uba_dep (t_value val
, t_addr exta
, UNIT
*uptr
, int32 sw
)
933 uint32 ua
= (uint32
) exta
, pa
;
935 if (ua
>= UBADDRSIZE
) return SCPE_ARG
;
936 if (uba_map_addr_c (ua
, &pa
) && ADDR_IS_MEM (pa
)) {
937 WriteW (pa
, (int32
) val
);
943 /* Enable/disable autoconfiguration */
945 t_stat
set_autocon (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
947 if (cptr
!= NULL
) return SCPE_ARG
;
949 return auto_config (NULL
, 0);
952 /* Show autoconfiguration status */
954 t_stat
show_autocon (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
)
956 fprintf (st
, "autoconfiguration ");
957 fprintf (st
, autcon_enb
? "enabled": "disabled");
961 /* Change device address */
963 t_stat
set_addr (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
970 if (cptr
== NULL
) return SCPE_ARG
;
971 if ((val
== 0) || (uptr
== NULL
)) return SCPE_IERR
;
972 dptr
= find_dev_from_unit (uptr
);
973 if (dptr
== NULL
) return SCPE_IERR
;
974 dibp
= (DIB
*) dptr
->ctxt
;
975 if (dibp
== NULL
) return SCPE_IERR
;
976 newba
= (uint32
) get_uint (cptr
, 16, IOPAGEBASE
+IOPAGEMASK
, &r
);
977 if (r
!= SCPE_OK
) return r
;
978 if ((newba
<= IOPAGEBASE
) || /* must be > 0 */
979 (newba
% ((uint32
) val
))) return SCPE_ARG
; /* check modulus */
980 dibp
->ba
= newba
; /* store */
981 dptr
->flags
= dptr
->flags
& ~DEV_FLTA
; /* not floating */
982 autcon_enb
= 0; /* autoconfig off */
986 /* Show device address */
988 t_stat
show_addr (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
)
993 if (uptr
== NULL
) return SCPE_IERR
;
994 dptr
= find_dev_from_unit (uptr
);
995 if (dptr
== NULL
) return SCPE_IERR
;
996 dibp
= (DIB
*) dptr
->ctxt
;
997 if ((dibp
== NULL
) || (dibp
->ba
<= IOPAGEBASE
)) return SCPE_IERR
;
998 fprintf (st
, "address=%08X", dibp
->ba
);
1000 fprintf (st
, "-%08X", dibp
->ba
+ dibp
->lnt
- 1);
1001 if (dptr
->flags
& DEV_FLTA
) fprintf (st
, "*");
1005 /* Set address floating */
1007 t_stat
set_addr_flt (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
1011 if (cptr
== NULL
) return SCPE_ARG
;
1012 if ((val
== 0) || (uptr
== NULL
)) return SCPE_IERR
;
1013 dptr
= find_dev_from_unit (uptr
);
1014 if (dptr
== NULL
) return SCPE_IERR
;
1015 dptr
->flags
= dptr
->flags
| DEV_FLTA
; /* floating */
1016 return auto_config (NULL
, 0); /* autoconfigure */
1019 /* Change device vector */
1021 t_stat
set_vec (UNIT
*uptr
, int32 arg
, char *cptr
, void *desc
)
1028 if (cptr
== NULL
) return SCPE_ARG
;
1029 if (uptr
== NULL
) return SCPE_IERR
;
1030 dptr
= find_dev_from_unit (uptr
);
1031 if (dptr
== NULL
) return SCPE_IERR
;
1032 dibp
= (DIB
*) dptr
->ctxt
;
1033 if (dibp
== NULL
) return SCPE_IERR
;
1034 newvec
= (uint32
) get_uint (cptr
, 16, 01000, &r
);
1035 if ((r
!= SCPE_OK
) ||
1036 ((newvec
+ (dibp
->vnum
* 4)) >= 01000) ||
1037 (newvec
& ((dibp
->vnum
> 1)? 07: 03))) return SCPE_ARG
;
1039 dptr
->flags
= dptr
->flags
& ~DEV_FLTA
; /* not floating */
1040 autcon_enb
= 0; /* autoconfig off */
1044 /* Show device vector */
1046 t_stat
show_vec (FILE *st
, UNIT
*uptr
, int32 arg
, void *desc
)
1052 if (uptr
== NULL
) return SCPE_IERR
;
1053 dptr
= find_dev_from_unit (uptr
);
1054 if (dptr
== NULL
) return SCPE_IERR
;
1055 dibp
= (DIB
*) dptr
->ctxt
;
1056 if (dibp
== NULL
) return SCPE_IERR
;
1058 if (arg
) numvec
= arg
;
1059 else numvec
= dibp
->vnum
;
1060 if (vec
== 0) fprintf (st
, "no vector");
1062 fprintf (st
, "vector=%X", vec
);
1063 if (numvec
> 1) fprintf (st
, "-%X", vec
+ (4 * (numvec
- 1)));
1068 /* Init Unibus tables */
1070 void init_ubus_tab (void)
1074 for (i
= 0; i
< IPL_HLVL
; i
++) { /* clear int tables */
1075 for (j
= 0; j
< 32; j
++) {
1077 int_ack
[i
][j
] = NULL
;
1080 for (i
= 0; i
< (IOPAGESIZE
>> 1); i
++) { /* clear dispatch tab */
1088 /* Build Unibus tables */
1090 t_stat
build_ubus_tab (DEVICE
*dptr
, DIB
*dibp
)
1092 int32 i
, idx
, vec
, ilvl
, ibit
;
1094 if ((dptr
== NULL
) || (dibp
== NULL
)) return SCPE_IERR
; /* validate args */
1095 if (dibp
->vnum
> VEC_DEVMAX
) return SCPE_IERR
;
1096 for (i
= 0; i
< dibp
->vnum
; i
++) { /* loop thru vec */
1097 idx
= dibp
->vloc
+ i
; /* vector index */
1098 vec
= dibp
->vec
? (dibp
->vec
+ (i
* 4)): 0; /* vector addr */
1101 if ((int_ack
[ilvl
][ibit
] && dibp
->ack
[i
] && /* conflict? */
1102 (int_ack
[ilvl
][ibit
] != dibp
->ack
[i
])) ||
1103 (int_vec
[ilvl
][ibit
] && vec
&&
1104 (int_vec
[ilvl
][ibit
] != vec
))) {
1105 printf ("Device %s interrupt slot conflict at %d\n",
1106 sim_dname (dptr
), idx
);
1107 if (sim_log
) fprintf (sim_log
,
1108 "Device %s interrupt slot conflict at %d\n",
1109 sim_dname (dptr
), idx
);
1112 if (dibp
->ack
[i
]) int_ack
[ilvl
][ibit
] = dibp
->ack
[i
];
1113 else if (vec
) int_vec
[ilvl
][ibit
] = vec
;
1115 for (i
= 0; i
< (int32
) dibp
->lnt
; i
= i
+ 2) { /* create entries */
1116 idx
= ((dibp
->ba
+ i
) & IOPAGEMASK
) >> 1; /* index into disp */
1117 if ((iodispR
[idx
] && dibp
->rd
&& /* conflict? */
1118 (iodispR
[idx
] != dibp
->rd
)) ||
1119 (iodispW
[idx
] && dibp
->wr
&&
1120 (iodispW
[idx
] != dibp
->wr
))) {
1121 printf ("Device %s address conflict at %08o\n",
1122 sim_dname (dptr
), dibp
->ba
);
1123 if (sim_log
) fprintf (sim_log
,
1124 "Device %s address conflict at %08o\n",
1125 sim_dname (dptr
), dibp
->ba
);
1128 if (dibp
->rd
) iodispR
[idx
] = dibp
->rd
; /* set rd dispatch */
1129 if (dibp
->wr
) iodispW
[idx
] = dibp
->wr
; /* set wr dispatch */
1130 iodibp
[idx
] = dibp
; /* remember DIB */
1137 t_stat
show_iospace (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
)
1143 if (build_dib_tab ()) return SCPE_OK
; /* build IO page */
1144 for (i
= 0, dibp
= NULL
; i
< (IOPAGESIZE
>> 1); i
++) { /* loop thru entries */
1145 if (iodibp
[i
] && (iodibp
[i
] != dibp
)) { /* new block? */
1146 dibp
= iodibp
[i
]; /* DIB for block */
1147 for (j
= 0, dptr
= NULL
; sim_devices
[j
] != NULL
; j
++) {
1148 if (((DIB
*) sim_devices
[j
]->ctxt
) == dibp
) {
1149 dptr
= sim_devices
[j
]; /* locate device */
1153 fprintf (st
, "%08X - %08X%c\t%s\n", dibp
->ba
,
1154 dibp
->ba
+ dibp
->lnt
- 1,
1155 (dptr
&& (dptr
->flags
& DEV_FLTA
))? '*': ' ',
1156 dptr
? sim_dname (dptr
): "CPU");
1162 /* Show UBA virtual address */
1164 t_stat
uba_show_virt (FILE *of
, UNIT
*uptr
, int32 val
, void *desc
)
1167 char *cptr
= (char *) desc
;
1171 ua
= (uint32
) get_uint (cptr
, 16, UBADDRSIZE
- 1, &r
);
1173 if (uba_map_addr_c (ua
, &pa
))
1174 fprintf (of
, "Unibus %-X = physical %-X\n", ua
, pa
);
1175 else fprintf (of
, "Unibus %-X: invalid mapping\n", ua
);
1179 fprintf (of
, "Invalid argument\n");
1183 /* Autoconfiguration
1185 The table reflects the MicroVAX 3900 microcode, with one addition - the
1186 number of controllers field handles devices where multiple instances
1187 are simulated through a single DEVICE structure (e.g., DZ, VH).
1189 A minus number of vectors indicates a field that should be calculated
1190 but not placed in the DIB (RQ, TQ dynamic vectors) */
1193 #define AUTO_CSRBASE 0010
1194 #define AUTO_VECBASE 0300
1197 char *dnam
[AUTO_MAXC
];
1202 uint32 fixa
[AUTO_MAXC
];
1203 uint32 fixv
[AUTO_MAXC
];
1206 AUTO_CON auto_tab
[] = {
1207 { { NULL
}, 1, 2, 0, 8, { 0 } }, /* DLV11J - fx CSRs */
1208 { { NULL
}, 1, 2, 8, 8 }, /* DJ11 */
1209 { { NULL
}, 1, 2, 16, 8 }, /* DH11 */
1210 { { NULL
}, 1, 2, 8, 8 }, /* DQ11 */
1211 { { NULL
}, 1, 2, 8, 8 }, /* DU11 */
1212 { { NULL
}, 1, 2, 8, 8 }, /* DUP11 */
1213 { { NULL
}, 10, 2, 8, 8 }, /* LK11A */
1214 { { NULL
}, 1, 2, 8, 8 }, /* DMC11 */
1215 { { "DZ" }, DZ_MUXES
, 2, 8, 8 }, /* DZ11 */
1216 { { NULL
}, 1, 2, 8, 8 }, /* KMC11 */
1217 { { NULL
}, 1, 2, 8, 8 }, /* LPP11 */
1218 { { NULL
}, 1, 2, 8, 8 }, /* VMV21 */
1219 { { NULL
}, 1, 2, 16, 8 }, /* VMV31 */
1220 { { NULL
}, 1, 2, 8, 8 }, /* DWR70 */
1221 { { "RL", "RLB" }, 1, 1, 8, 4, {IOBA_RL
}, {VEC_RL
} }, /* RL11 */
1222 { { "TS", "TSB", "TSC", "TSD" }, 1, 1, 0, 4, /* TS11 */
1223 {IOBA_TS
, IOBA_TS
+ 4, IOBA_TS
+ 8, IOBA_TS
+ 12},
1225 { { NULL
}, 1, 2, 16, 8 }, /* LPA11K */
1226 { { NULL
}, 1, 2, 8, 8 }, /* KW11C */
1227 { { NULL
}, 1, 1, 8, 8 }, /* reserved */
1228 { { "RX", "RY" }, 1, 1, 8, 4, {IOBA_RX
} , {VEC_RX
} }, /* RX11/RX211 */
1229 { { NULL
}, 1, 1, 8, 4 }, /* DR11W */
1230 { { NULL
}, 1, 1, 8, 4, { 0, 0 }, { 0 } }, /* DR11B - fx CSRs,vec */
1231 { { NULL
}, 1, 2, 8, 8 }, /* DMP11 */
1232 { { NULL
}, 1, 2, 8, 8 }, /* DPV11 */
1233 { { NULL
}, 1, 2, 8, 8 }, /* ISB11 */
1234 { { NULL
}, 1, 2, 16, 8 }, /* DMV11 */
1235 { { "XU", "XUB" }, 1, 1, 8, 4, {IOBA_XU
}, {VEC_XU
} }, /* DEUNA */
1236 { { "XQ", "XQB" }, 1, 1, 0, 4, /* DEQNA */
1237 {IOBA_XQ
,IOBA_XQB
}, {VEC_XQ
} }, /* */
1238 { { "RQ", "RQB", "RQC", "RQD" }, 1, -1, 4, 4, /* RQDX3 */
1239 {IOBA_RQ
}, {VEC_RQ
} },
1240 { { NULL
}, 1, 8, 32, 4 }, /* DMF32 */
1241 { { NULL
}, 1, 2, 16, 8 }, /* KMS11 */
1242 { { NULL
}, 1, 1, 16, 4 }, /* VS100 */
1243 { { "TQ", "TQB" }, 1, -1, 4, 4, {IOBA_TQ
}, {VEC_TQ
} }, /* TQK50 */
1244 { { NULL
}, 1, 2, 16, 8 }, /* KMV11 */
1245 { { "VH" }, VH_MUXES
, 2, 16, 8 }, /* DHU11/DHQ11 */
1246 { { NULL
}, 1, 6, 32, 4 }, /* DMZ32 */
1247 { { NULL
}, 1, 6, 32, 4 }, /* CP132 */
1248 { { NULL
}, 1, 2, 64, 8, { 0 } }, /* QVSS - fx CSR */
1249 { { NULL
}, 1, 1, 8, 4 }, /* VS31 */
1250 { { NULL
}, 1, 1, 0, 4, { 0 } }, /* LNV11 - fx CSR */
1251 { { NULL
}, 1, 1, 16, 4 }, /* LNV21/QPSS */
1252 { { NULL
}, 1, 1, 8, 4, { 0 } }, /* QTA - fx CSR */
1253 { { NULL
}, 1, 1, 8, 4 }, /* DSV11 */
1254 { { NULL
}, 1, 2, 8, 8 }, /* CSAM */
1255 { { NULL
}, 1, 2, 8, 8 }, /* ADV11C */
1256 { { NULL
}, 1, 0, 8, 0 }, /* AAV11C */
1257 { { NULL
}, 1, 2, 8, 8, { 0 }, { 0 } }, /* AXV11C - fx CSR,vec */
1258 { { NULL
}, 1, 2, 4, 8, { 0 } }, /* KWV11C - fx CSR */
1259 { { NULL
}, 1, 2, 8, 8, { 0 } }, /* ADV11D - fx CSR */
1260 { { NULL
}, 1, 2, 8, 8, { 0 } }, /* AAV11D - fx CSR */
1261 { { "QDSS" }, 1, 3, 0, 16, {IOBA_QDSS
} }, /* QDSS - fx CSR */
1262 { { NULL
}, -1 } /* end table */
1265 t_stat
auto_config (char *name
, int32 nctrl
)
1267 uint32 csr
= IOPAGEBASE
+ AUTO_CSRBASE
;
1268 uint32 vec
= VEC_Q
+ AUTO_VECBASE
;
1272 uint32 j
, k
, vmask
, amask
;
1274 if (autcon_enb
== 0) return SCPE_OK
; /* enabled? */
1275 if (name
) { /* updating? */
1276 if (nctrl
< 0) return SCPE_ARG
;
1277 for (autp
= auto_tab
; autp
->numc
>= 0; autp
++) {
1278 for (j
= 0; (j
< AUTO_MAXC
) && autp
->dnam
[j
]; j
++) {
1279 if (strcmp (name
, autp
->dnam
[j
]) == 0)
1284 for (autp
= auto_tab
; autp
->numc
>= 0; autp
++) { /* loop thru table */
1285 if (autp
->amod
) { /* floating csr? */
1286 amask
= autp
->amod
- 1;
1287 csr
= (csr
+ amask
) & ~amask
; /* align csr */
1289 for (j
= k
= 0; (j
< AUTO_MAXC
) && autp
->dnam
[j
]; j
++) {
1290 dptr
= find_dev (autp
->dnam
[j
]); /* find ctrl */
1291 if ((dptr
== NULL
) || (dptr
->flags
& DEV_DIS
) ||
1292 !(dptr
->flags
& DEV_FLTA
)) continue; /* enabled, floating? */
1293 dibp
= (DIB
*) dptr
->ctxt
; /* get DIB */
1294 if (dibp
== NULL
) return SCPE_IERR
; /* not there??? */
1295 if (autp
->amod
) { /* dyn csr needed? */
1296 if (autp
->fixa
[k
]) /* fixed csr avail? */
1297 dibp
->ba
= autp
->fixa
[k
]; /* use it */
1298 else { /* no fixed left */
1299 dibp
->ba
= csr
; /* set CSR */
1300 csr
+= (autp
->numc
* autp
->amod
); /* next CSR */
1302 } /* end if dyn csr */
1303 if (autp
->numv
&& autp
->vmod
) { /* dyn vec needed? */
1304 uint32 numv
= abs (autp
->numv
); /* get num vec */
1305 if (autp
->fixv
[k
]) { /* fixed vec avail? */
1307 dibp
->vec
= autp
->fixv
[k
]; /* use it */
1309 else { /* no fixed left */
1310 vmask
= autp
->vmod
- 1;
1311 vec
= (vec
+ vmask
) & ~vmask
; /* align vector */
1313 dibp
->vec
= vec
; /* set vector */
1314 vec
+= (autp
->numc
* numv
* 4);
1316 } /* end if dyn vec */
1317 k
++; /* next instance */
1319 if (autp
->amod
) csr
= csr
+ 2; /* flt CSR? gap */