Commit | Line | Data |
---|---|---|
196ba1fc PH |
1 | /* vax780_sbi.c: VAX 11/780 SBI\r |
2 | \r | |
3 | Copyright (c) 2004-2008, Robert M Supnik\r | |
4 | \r | |
5 | Permission is hereby granted, free of charge, to any person obtaining a\r | |
6 | copy of this software and associated documentation files (the "Software"),\r | |
7 | to deal in the Software without restriction, including without limitation\r | |
8 | the rights to use, copy, modify, merge, publish, distribute, sublicense,\r | |
9 | and/or sell copies of the Software, and to permit persons to whom the\r | |
10 | Software is furnished to do so, subject to the following conditions:\r | |
11 | \r | |
12 | The above copyright notice and this permission notice shall be included in\r | |
13 | all copies or substantial portions of the Software.\r | |
14 | \r | |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r | |
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r | |
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\r | |
18 | ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r | |
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r | |
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r | |
21 | \r | |
22 | Except as contained in this notice, the name of Robert M Supnik shall not be\r | |
23 | used in advertising or otherwise to promote the sale, use or other dealings\r | |
24 | in this Software without prior written authorization from Robert M Supnik.\r | |
25 | \r | |
26 | This module contains the VAX 11/780 system-specific registers and devices.\r | |
27 | \r | |
28 | sbi bus controller\r | |
29 | \r | |
30 | 31-May-2008 RMS Fixed machine_check calling sequence (found by Peter Schorn)\r | |
31 | 03-May-2006 RMS Fixed writes to ACCS\r | |
32 | 28-May-08 RMS Inlined physical memory routines\r | |
33 | */\r | |
34 | \r | |
35 | #include "vax_defs.h"\r | |
36 | \r | |
37 | /* 11/780 specific IPRs */\r | |
38 | \r | |
39 | /* Writeable control store */\r | |
40 | \r | |
41 | #define WCSA_RW 0xFFFF /* writeable */\r | |
42 | #define WCSA_ADDR 0x1FFF /* addr */\r | |
43 | #define WCSA_CTR 0x6000 /* counter */\r | |
44 | #define WCSA_CTR_INC 0x2000 /* increment */\r | |
45 | #define WCSA_CTR_MAX 0x6000 /* max value */\r | |
46 | #define WCSD_RD_VAL 0xFF /* fixed read val */\r | |
47 | #define WCSD_WR 0xFFFFFFFF /* write */\r | |
48 | #define MBRK_RW 0x1FFF /* microbreak */\r | |
49 | \r | |
50 | /* System registers */\r | |
51 | \r | |
52 | #define SBIFS_RD (0x031F0000|SBI_FAULTS) /* SBI faults */\r | |
53 | #define SBIFS_WR 0x03140000\r | |
54 | #define SBIFS_W1C 0x00080000\r | |
55 | \r | |
56 | #define SBISC_RD 0xFFFF0000 /* SBI silo comp */\r | |
57 | #define SBISC_WR 0x7FFF0000\r | |
58 | #define SBISC_LOCK 0x80000000 /* lock */\r | |
59 | \r | |
60 | #define SBIMT_RD 0xFFFFFF00 /* SBI maint */\r | |
61 | #define SBIMT_WR 0xFFFFF900\r | |
62 | \r | |
63 | #define SBIER_CRDIE 0x00008000 /* SBI error, CRD IE */\r | |
64 | #define SBIER_CRD 0x00004000 /* CRD */\r | |
65 | #define SBIER_RDS 0x00002000 /* RDS */\r | |
66 | #define SBIER_TMO 0x00001000 /* timeout */\r | |
67 | #define SBIER_STA 0x00000C00 /* timeout status (0) */\r | |
68 | #define SBIER_CNF 0x00000100 /* error confirm */\r | |
69 | #define SBIER_IBRDS 0x00000080\r | |
70 | #define SBIER_IBTMO 0x00000040\r | |
71 | #define SBIER_IBSTA 0x00000030\r | |
72 | #define SBIER_IBCNF 0x00000008\r | |
73 | #define SBIER_MULT 0x00000004 /* multiple errors */\r | |
74 | #define SBIER_FREE 0x00000002 /* SBI free */\r | |
75 | #define SBIER_RD 0x0000FDFE\r | |
76 | #define SBIER_WR 0x00008000\r | |
77 | #define SBIER_W1C 0x000070C0\r | |
78 | #define SBIER_TMOW1C (SBIER_TMO|SBIER_STA|SBIER_CNF|SBIER_MULT)\r | |
79 | #define SBIER_IBTW1C (SBIER_IBTMO|SBIER_STA|SBIER_IBCNF)\r | |
80 | \r | |
81 | #define SBITMO_V_MODE 30 /* mode */\r | |
82 | #define SBITMO_VIRT 0x20000000 /* physical */\r | |
83 | \r | |
84 | #define SBIQC_MBZ 0xC0000007 /* MBZ */\r | |
85 | \r | |
86 | /* VAX-11/780 boot device definitions */\r | |
87 | \r | |
88 | struct boot_dev {\r | |
89 | char *name;\r | |
90 | int32 code;\r | |
91 | int32 let;\r | |
92 | };\r | |
93 | \r | |
94 | uint32 wcs_addr = 0;\r | |
95 | uint32 wcs_data = 0;\r | |
96 | uint32 wcs_mbrk = 0;\r | |
97 | uint32 nexus_req[NEXUS_HLVL]; /* nexus int req */\r | |
98 | uint32 sbi_fs = 0; /* SBI fault status */\r | |
99 | uint32 sbi_sc = 0; /* SBI silo comparator */\r | |
100 | uint32 sbi_mt = 0; /* SBI maintenance */\r | |
101 | uint32 sbi_er = 0; /* SBI error status */\r | |
102 | uint32 sbi_tmo = 0; /* SBI timeout addr */\r | |
103 | \r | |
104 | static t_stat (*nexusR[NEXUS_NUM])(int32 *dat, int32 ad, int32 md);\r | |
105 | static t_stat (*nexusW[NEXUS_NUM])(int32 dat, int32 ad, int32 md);\r | |
106 | \r | |
107 | static struct boot_dev boot_tab[] = {\r | |
108 | { "RP", BOOT_MB, 0 },\r | |
109 | { "HK", BOOT_HK, 0 },\r | |
110 | { "RL", BOOT_RL, 0 },\r | |
111 | { "RQ", BOOT_UDA, 1 << 24 },\r | |
112 | { "TQ", BOOT_TK, 1 << 24 },\r | |
113 | { NULL }\r | |
114 | };\r | |
115 | \r | |
116 | extern int32 R[16];\r | |
117 | extern int32 PSL;\r | |
118 | extern int32 ASTLVL, SISR;\r | |
119 | extern int32 mapen, pme, trpirq;\r | |
120 | extern int32 in_ie;\r | |
121 | extern int32 mchk_va, mchk_ref;\r | |
122 | extern int32 crd_err, mem_err, hlt_pin;\r | |
123 | extern int32 tmr_int, tti_int, tto_int;\r | |
124 | extern jmp_buf save_env;\r | |
125 | extern int32 p1;\r | |
126 | extern int32 sim_switches;\r | |
127 | extern DEVICE *sim_devices[];\r | |
128 | extern FILE *sim_log;\r | |
129 | extern CTAB *sim_vm_cmd;\r | |
130 | \r | |
131 | t_stat sbi_reset (DEVICE *dptr);\r | |
132 | void sbi_set_tmo (int32 pa);\r | |
133 | void uba_eval_int (void);\r | |
134 | t_stat vax780_boot (int32 flag, char *ptr);\r | |
135 | \r | |
136 | extern t_stat vax780_fload (int flag, char *cptr);\r | |
137 | extern int32 intexc (int32 vec, int32 cc, int32 ipl, int ei);\r | |
138 | extern int32 iccs_rd (void);\r | |
139 | extern int32 nicr_rd (void);\r | |
140 | extern int32 icr_rd (t_bool interp);\r | |
141 | extern int32 todr_rd (void);\r | |
142 | extern int32 rxcs_rd (void);\r | |
143 | extern int32 rxdb_rd (void);\r | |
144 | extern int32 txcs_rd (void);\r | |
145 | extern void iccs_wr (int32 dat);\r | |
146 | extern void nicr_wr (int32 dat);\r | |
147 | extern void todr_wr (int32 dat);\r | |
148 | extern void rxcs_wr (int32 dat);\r | |
149 | extern void txcs_wr (int32 dat);\r | |
150 | extern void txdb_wr (int32 dat);\r | |
151 | extern void init_mbus_tab (void);\r | |
152 | extern void init_ubus_tab (void);\r | |
153 | extern t_stat build_mbus_tab (DEVICE *dptr, DIB *dibp);\r | |
154 | extern t_stat build_ubus_tab (DEVICE *dptr, DIB *dibp);\r | |
155 | \r | |
156 | /* SBI data structures\r | |
157 | \r | |
158 | sbi_dev SBI device descriptor\r | |
159 | sbi_unit SBI unit\r | |
160 | sbi_reg SBI register list\r | |
161 | */\r | |
162 | \r | |
163 | UNIT sbi_unit = { UDATA (NULL, 0, 0) };\r | |
164 | \r | |
165 | REG sbi_reg[] = {\r | |
166 | { HRDATA (NREQ14, nexus_req[0], 16) },\r | |
167 | { HRDATA (NREQ15, nexus_req[1], 16) },\r | |
168 | { HRDATA (NREQ16, nexus_req[2], 16) },\r | |
169 | { HRDATA (NREQ17, nexus_req[3], 16) },\r | |
170 | { HRDATA (WCSA, wcs_addr, 16) },\r | |
171 | { HRDATA (WCSD, wcs_data, 32) },\r | |
172 | { HRDATA (MBRK, wcs_mbrk, 13) },\r | |
173 | { HRDATA (SBIFS, sbi_fs, 32) },\r | |
174 | { HRDATA (SBISC, sbi_sc, 32) },\r | |
175 | { HRDATA (SBIMT, sbi_mt, 32) },\r | |
176 | { HRDATA (SBIER, sbi_er, 32) },\r | |
177 | { HRDATA (SBITMO, sbi_tmo, 32) },\r | |
178 | { NULL }\r | |
179 | };\r | |
180 | \r | |
181 | DEVICE sbi_dev = {\r | |
182 | "SBI", &sbi_unit, sbi_reg, NULL,\r | |
183 | 1, 16, 16, 1, 16, 8,\r | |
184 | NULL, NULL, &sbi_reset,\r | |
185 | NULL, NULL, NULL,\r | |
186 | NULL, 0\r | |
187 | };\r | |
188 | \r | |
189 | /* Special boot command, overrides regular boot */\r | |
190 | \r | |
191 | CTAB vax780_cmd[] = {\r | |
192 | { "BOOT", &vax780_boot, RU_BOOT,\r | |
193 | "bo{ot} <device>{/R5:flg} boot device\n" },\r | |
194 | { "FLOAD", &vax780_fload, 0,\r | |
195 | "fl{oad} <file> {<start>} load file from console floppy\n" },\r | |
196 | { NULL }\r | |
197 | };\r | |
198 | \r | |
199 | /* The VAX 11/780 has three sources of interrupts\r | |
200 | \r | |
201 | - internal device interrupts (CPU, console, clock)\r | |
202 | - nexus interupts (e.g., memory controller, MBA, UBA)\r | |
203 | - external device interrupts (Unibus)\r | |
204 | \r | |
205 | Internal devices vector to fixed SCB locations.\r | |
206 | \r | |
207 | Nexus interrupts vector to an SCB location based on this\r | |
208 | formula: SCB_NEXUS + ((IPL - 0x14) * 0x40) + (TR# * 0x4)\r | |
209 | \r | |
210 | External device interrupts do not vector directly.\r | |
211 | Instead, the interrupt handler for a given UBA IPL\r | |
212 | reads a vector register that contains the Unibus vector\r | |
213 | for that IPL.\r | |
214 | \r | |
215 | /* Find highest priority vectorable interrupt */\r | |
216 | \r | |
217 | int32 eval_int (void)\r | |
218 | {\r | |
219 | int32 ipl = PSL_GETIPL (PSL);\r | |
220 | int32 i, t;\r | |
221 | \r | |
222 | static const int32 sw_int_mask[IPL_SMAX] = {\r | |
223 | 0xFFFE, 0xFFFC, 0xFFF8, 0xFFF0, /* 0 - 3 */\r | |
224 | 0xFFE0, 0xFFC0, 0xFF80, 0xFF00, /* 4 - 7 */\r | |
225 | 0xFE00, 0xFC00, 0xF800, 0xF000, /* 8 - B */\r | |
226 | 0xE000, 0xC000, 0x8000 /* C - E */\r | |
227 | };\r | |
228 | \r | |
229 | if (hlt_pin) return IPL_HLTPIN; /* hlt pin int */\r | |
230 | if ((ipl < IPL_MEMERR) && mem_err) return IPL_MEMERR; /* mem err int */\r | |
231 | if ((ipl < IPL_CRDERR) && crd_err) return IPL_CRDERR; /* crd err int */\r | |
232 | if ((ipl < IPL_CLKINT) && tmr_int) return IPL_CLKINT; /* clock int */\r | |
233 | uba_eval_int (); /* update UBA */\r | |
234 | for (i = IPL_HMAX; i >= IPL_HMIN; i--) { /* chk hwre int */\r | |
235 | if (i <= ipl) return 0; /* at ipl? no int */\r | |
236 | if (nexus_req[i - IPL_HMIN]) return i; /* req != 0? int */\r | |
237 | }\r | |
238 | if ((ipl < IPL_TTINT) && (tti_int || tto_int)) /* console int */\r | |
239 | return IPL_TTINT;\r | |
240 | if (ipl >= IPL_SMAX) return 0; /* ipl >= sw max? */\r | |
241 | if ((t = SISR & sw_int_mask[ipl]) == 0) return 0; /* eligible req */\r | |
242 | for (i = IPL_SMAX; i > ipl; i--) { /* check swre int */\r | |
243 | if ((t >> i) & 1) return i; /* req != 0? int */\r | |
244 | }\r | |
245 | return 0;\r | |
246 | }\r | |
247 | \r | |
248 | /* Return vector for highest priority hardware interrupt at IPL lvl */\r | |
249 | \r | |
250 | int32 get_vector (int32 lvl)\r | |
251 | {\r | |
252 | int32 i, l;\r | |
253 | \r | |
254 | if (lvl == IPL_MEMERR) { /* mem error? */\r | |
255 | mem_err = 0;\r | |
256 | return SCB_MEMERR;\r | |
257 | }\r | |
258 | if (lvl == IPL_CRDERR) { /* CRD error? */\r | |
259 | crd_err = 0;\r | |
260 | return SCB_CRDERR;\r | |
261 | }\r | |
262 | if (lvl == IPL_CLKINT) { /* clock? */\r | |
263 | tmr_int = 0; /* clear req */\r | |
264 | return SCB_INTTIM; /* return vector */\r | |
265 | }\r | |
266 | if (lvl > IPL_HMAX) { /* error req lvl? */\r | |
267 | ABORT (STOP_UIPL); /* unknown intr */\r | |
268 | }\r | |
269 | if ((lvl <= IPL_HMAX) && (lvl >= IPL_HMIN)) { /* nexus? */\r | |
270 | l = lvl - IPL_HMIN;\r | |
271 | for (i = 0; nexus_req[l] && (i < NEXUS_NUM); i++) {\r | |
272 | if ((nexus_req[l] >> i) & 1) {\r | |
273 | nexus_req[l] = nexus_req[l] & ~(1u << i);\r | |
274 | return SCB_NEXUS + (l << 6) + (i << 2); /* return vector */\r | |
275 | }\r | |
276 | }\r | |
277 | }\r | |
278 | if (lvl == IPL_TTINT) { /* console? */\r | |
279 | if (tti_int) { /* input? */\r | |
280 | tti_int = 0; /* clear req */\r | |
281 | return SCB_TTI; /* return vector */\r | |
282 | }\r | |
283 | if (tto_int) { /* output? */\r | |
284 | tto_int = 0; /* clear req */\r | |
285 | return SCB_TTO; /* return vector */\r | |
286 | }\r | |
287 | }\r | |
288 | return 0;\r | |
289 | }\r | |
290 | \r | |
291 | /* Read 780-specific IPR's */\r | |
292 | \r | |
293 | int32 ReadIPR (int32 rg)\r | |
294 | {\r | |
295 | int32 val;\r | |
296 | \r | |
297 | switch (rg) {\r | |
298 | \r | |
299 | case MT_ICCS: /* ICCS */\r | |
300 | val = iccs_rd ();\r | |
301 | break;\r | |
302 | \r | |
303 | case MT_NICR: /* NICR */\r | |
304 | val = nicr_rd ();\r | |
305 | break;\r | |
306 | \r | |
307 | case MT_ICR: /* ICR */\r | |
308 | val = icr_rd (FALSE);\r | |
309 | break;\r | |
310 | \r | |
311 | case MT_TODR: /* TODR */\r | |
312 | val = todr_rd ();\r | |
313 | break;\r | |
314 | \r | |
315 | case MT_ACCS: /* ACCS (not impl) */\r | |
316 | val = 0;\r | |
317 | break;\r | |
318 | \r | |
319 | case MT_WCSA: /* WCSA */\r | |
320 | val = wcs_addr & WCSA_RW;\r | |
321 | break;\r | |
322 | \r | |
323 | case MT_WCSD: /* WCSD */\r | |
324 | val = WCSD_RD_VAL;\r | |
325 | break;\r | |
326 | \r | |
327 | case MT_RXCS: /* RXCS */\r | |
328 | val = rxcs_rd ();\r | |
329 | break;\r | |
330 | \r | |
331 | case MT_RXDB: /* RXDB */\r | |
332 | val = rxdb_rd ();\r | |
333 | break;\r | |
334 | \r | |
335 | case MT_TXCS: /* TXCS */\r | |
336 | val = txcs_rd ();\r | |
337 | break;\r | |
338 | \r | |
339 | case MT_SBIFS: /* SBIFS */\r | |
340 | val = sbi_fs & SBIFS_RD;\r | |
341 | break;\r | |
342 | \r | |
343 | case MT_SBIS: /* SBIS */\r | |
344 | val = 0;\r | |
345 | break;\r | |
346 | \r | |
347 | case MT_SBISC: /* SBISC */\r | |
348 | val = sbi_sc & SBISC_RD;\r | |
349 | break;\r | |
350 | \r | |
351 | case MT_SBIMT: /* SBIMT */\r | |
352 | val = sbi_mt & SBIMT_RD;\r | |
353 | break;\r | |
354 | \r | |
355 | case MT_SBIER: /* SBIER */\r | |
356 | val = sbi_er & SBIER_RD;\r | |
357 | break;\r | |
358 | \r | |
359 | case MT_SBITA: /* SBITA */\r | |
360 | val = sbi_tmo;\r | |
361 | break;\r | |
362 | \r | |
363 | case MT_MBRK: /* MBRK */\r | |
364 | val = wcs_mbrk & MBRK_RW;\r | |
365 | break;\r | |
366 | \r | |
367 | case MT_SID: /* SID */\r | |
368 | val = VAX780_SID | VAX780_ECO | VAX780_PLANT | VAX780_SN;\r | |
369 | break;\r | |
370 | \r | |
371 | default:\r | |
372 | RSVD_OPND_FAULT;\r | |
373 | }\r | |
374 | \r | |
375 | return val;\r | |
376 | }\r | |
377 | \r | |
378 | /* Write 780-specific IPR's */\r | |
379 | \r | |
380 | void WriteIPR (int32 rg, int32 val)\r | |
381 | {\r | |
382 | switch (rg) {\r | |
383 | \r | |
384 | case MT_ICCS: /* ICCS */\r | |
385 | iccs_wr (val);\r | |
386 | break;\r | |
387 | \r | |
388 | case MT_NICR: /* NICR */\r | |
389 | nicr_wr (val);\r | |
390 | break;\r | |
391 | \r | |
392 | case MT_TODR: /* TODR */\r | |
393 | todr_wr (val);\r | |
394 | break;\r | |
395 | \r | |
396 | case MT_ACCS: /* ACCS (not impl) */\r | |
397 | break;\r | |
398 | \r | |
399 | case MT_WCSA: /* WCSA */\r | |
400 | wcs_addr = val & WCSA_RW;\r | |
401 | break;\r | |
402 | \r | |
403 | case MT_WCSD: /* WCSD */\r | |
404 | wcs_data = val & WCSD_WR;\r | |
405 | wcs_addr = (wcs_addr & ~WCSA_CTR) |\r | |
406 | ((wcs_addr + WCSA_CTR_INC) & WCSA_CTR);\r | |
407 | if ((wcs_addr & WCSA_CTR) == WCSA_CTR_MAX)\r | |
408 | wcs_addr = (wcs_addr & ~WCSA_ADDR) |\r | |
409 | ((wcs_addr + 1) & WCSA_ADDR);\r | |
410 | break;\r | |
411 | \r | |
412 | case MT_RXCS: /* RXCS */\r | |
413 | rxcs_wr (val);\r | |
414 | break;\r | |
415 | \r | |
416 | case MT_TXCS: /* TXCS */\r | |
417 | txcs_wr (val);\r | |
418 | break;\r | |
419 | \r | |
420 | case MT_TXDB: /* TXDB */\r | |
421 | txdb_wr (val);\r | |
422 | break;\r | |
423 | \r | |
424 | case MT_SBIFS: /* SBIFS */\r | |
425 | sbi_fs = (sbi_fs & ~SBIFS_WR) | (val & SBIFS_WR);\r | |
426 | sbi_fs = sbi_fs & ~(val & SBIFS_W1C);\r | |
427 | break;\r | |
428 | \r | |
429 | case MT_SBISC: /* SBISC */\r | |
430 | sbi_sc = (sbi_sc & ~(SBISC_LOCK|SBISC_WR)) | (val & SBISC_WR);\r | |
431 | break;\r | |
432 | \r | |
433 | case MT_SBIMT: /* SBIMT */\r | |
434 | sbi_mt = (sbi_mt & ~SBIMT_WR) | (val & SBIMT_WR);\r | |
435 | break;\r | |
436 | \r | |
437 | case MT_SBIER: /* SBIER */\r | |
438 | sbi_er = (sbi_er & ~SBIER_WR) | (val & SBIER_WR);\r | |
439 | sbi_er = sbi_er & ~(val & SBIER_W1C);\r | |
440 | if (val & SBIER_TMO) sbi_er = sbi_er & ~SBIER_TMOW1C;\r | |
441 | if (val & SBIER_IBTMO) sbi_er = sbi_er & ~SBIER_IBTW1C;\r | |
442 | if ((sbi_er & SBIER_CRDIE) && (sbi_er & SBIER_CRD))\r | |
443 | crd_err = 1;\r | |
444 | else crd_err = 0;\r | |
445 | break;\r | |
446 | \r | |
447 | case MT_SBIQC: /* SBIQC */\r | |
448 | if (val & SBIQC_MBZ) { RSVD_OPND_FAULT; }\r | |
449 | WriteLP (val, 0);\r | |
450 | WriteLP (val + 4, 0);\r | |
451 | break;\r | |
452 | \r | |
453 | case MT_MBRK: /* MBRK */\r | |
454 | wcs_mbrk = val & MBRK_RW;\r | |
455 | break;\r | |
456 | \r | |
457 | default:\r | |
458 | RSVD_OPND_FAULT;\r | |
459 | }\r | |
460 | \r | |
461 | return;\r | |
462 | }\r | |
463 | \r | |
464 | /* ReadReg - read register space\r | |
465 | \r | |
466 | Inputs:\r | |
467 | pa = physical address\r | |
468 | lnt = length (BWLQ)\r | |
469 | Output:\r | |
470 | longword of data\r | |
471 | */\r | |
472 | \r | |
473 | int32 ReadReg (int32 pa, int32 lnt)\r | |
474 | {\r | |
475 | int32 nexus, val;\r | |
476 | \r | |
477 | if (ADDR_IS_REG (pa)) { /* reg space? */\r | |
478 | nexus = NEXUS_GETNEX (pa); /* get nexus */\r | |
479 | if (nexusR[nexus] && /* valid? */\r | |
480 | (nexusR[nexus] (&val, pa, lnt) == SCPE_OK)) {\r | |
481 | SET_IRQL;\r | |
482 | return val;\r | |
483 | }\r | |
484 | }\r | |
485 | sbi_set_tmo (pa); /* timeout */\r | |
486 | MACH_CHECK (MCHK_RD_F); /* machine check */\r | |
487 | return 0;\r | |
488 | } \r | |
489 | \r | |
490 | /* WriteReg - write register space\r | |
491 | \r | |
492 | Inputs:\r | |
493 | pa = physical address\r | |
494 | val = data to write, right justified in 32b longword\r | |
495 | lnt = length (BWLQ)\r | |
496 | Outputs:\r | |
497 | none\r | |
498 | */\r | |
499 | \r | |
500 | void WriteReg (int32 pa, int32 val, int32 lnt)\r | |
501 | {\r | |
502 | int32 nexus;\r | |
503 | \r | |
504 | if (ADDR_IS_REG (pa)) { /* reg space? */\r | |
505 | nexus = NEXUS_GETNEX (pa); /* get nexus */\r | |
506 | if (nexusW[nexus] && /* valid? */\r | |
507 | (nexusW[nexus] (val, pa, lnt) == SCPE_OK)) {\r | |
508 | SET_IRQL;\r | |
509 | return;\r | |
510 | }\r | |
511 | }\r | |
512 | sbi_set_tmo (pa); /* timeout */\r | |
513 | mem_err = 1; /* interrupt */\r | |
514 | eval_int ();\r | |
515 | return;\r | |
516 | }\r | |
517 | \r | |
518 | /* Set SBI timeout - machine checks only on reads */\r | |
519 | \r | |
520 | void sbi_set_tmo (int32 pa)\r | |
521 | {\r | |
522 | if ((sbi_er & SBIER_TMO) == 0) { /* not yet set? */\r | |
523 | sbi_tmo = pa >> 2; /* save addr */\r | |
524 | if (mchk_ref == REF_V) sbi_tmo |= SBITMO_VIRT | /* virt? add mode */\r | |
525 | (PSL_GETCUR (PSL) << SBITMO_V_MODE);\r | |
526 | sbi_er |= SBIER_TMO; /* set tmo flag */\r | |
527 | }\r | |
528 | else sbi_er |= SBIER_MULT; /* yes, multiple */\r | |
529 | return;\r | |
530 | }\r | |
531 | \r | |
532 | /* Set SBI error confirmation - always machine checks */\r | |
533 | \r | |
534 | void sbi_set_errcnf (void)\r | |
535 | {\r | |
536 | if (sbi_er & SBIER_CNF) sbi_er |= SBIER_MULT;\r | |
537 | else sbi_er |= SBIER_CNF;\r | |
538 | MACH_CHECK (MCHK_RD_F);\r | |
539 | return;\r | |
540 | }\r | |
541 | \r | |
542 | /* Machine check\r | |
543 | \r | |
544 | Error status word format\r | |
545 | <2:0> = ASTLVL\r | |
546 | <3> = PME\r | |
547 | <6:4> = arith trap code\r | |
548 | Rest will be zero\r | |
549 | */\r | |
550 | \r | |
551 | int32 machine_check (int32 p1, int32 opc, int32 cc, int32 delta)\r | |
552 | {\r | |
553 | int32 acc, err;\r | |
554 | \r | |
555 | err = (GET_TRAP (trpirq) << 4) | (pme << 3) | ASTLVL; /* error word */\r | |
556 | cc = intexc (SCB_MCHK, cc, 0, IE_SVE); /* take exception */\r | |
557 | acc = ACC_MASK (KERN); /* in kernel mode */\r | |
558 | in_ie = 1;\r | |
559 | SP = SP - 44; /* push 11 words */\r | |
560 | Write (SP, 40, L_LONG, WA); /* # bytes */\r | |
561 | Write (SP + 4, p1, L_LONG, WA); /* mcheck type */\r | |
562 | Write (SP + 8, err, L_LONG, WA); /* CPU error status */\r | |
563 | Write (SP + 12, 0, L_LONG, WA); /* uPC */\r | |
564 | Write (SP + 16, mchk_va, L_LONG, WA); /* VA */\r | |
565 | Write (SP + 20, 0, L_LONG, WA); /* D register */\r | |
566 | Write (SP + 24, mapen, L_LONG, WA); /* TB status 1 */\r | |
567 | Write (SP + 28, 0, L_LONG, WA); /* TB status 2 */\r | |
568 | Write (SP + 32, sbi_tmo, L_LONG, WA); /* SBI timeout addr */\r | |
569 | Write (SP + 36, 0, L_LONG, WA); /* cache status */\r | |
570 | Write (SP + 40, sbi_er, L_LONG, WA); /* SBI error */\r | |
571 | in_ie = 0;\r | |
572 | sbi_er = sbi_er & ~SBIER_TMOW1C; /* clr SBIER<tmo> etc */\r | |
573 | return cc;\r | |
574 | }\r | |
575 | \r | |
576 | /* Console entry */\r | |
577 | \r | |
578 | int32 con_halt (int32 code, int32 cc)\r | |
579 | {\r | |
580 | ABORT (STOP_HALT);\r | |
581 | return cc;\r | |
582 | }\r | |
583 | \r | |
584 | /* Special boot command - linked into SCP by initial reset\r | |
585 | \r | |
586 | Syntax: BOOT <device>{/R5:val}\r | |
587 | \r | |
588 | Sets up R0-R5, calls SCP boot processor with effective BOOT CPU\r | |
589 | */\r | |
590 | \r | |
591 | t_stat vax780_boot (int32 flag, char *ptr)\r | |
592 | {\r | |
593 | char gbuf[CBUFSIZE];\r | |
594 | char *slptr, *regptr;\r | |
595 | int32 i, r5v, unitno;\r | |
596 | DEVICE *dptr;\r | |
597 | UNIT *uptr;\r | |
598 | DIB *dibp;\r | |
599 | t_stat r;\r | |
600 | \r | |
601 | regptr = get_glyph (ptr, gbuf, 0); /* get glyph */\r | |
602 | if (slptr = strchr (gbuf, '/')) { /* found slash? */\r | |
603 | regptr = strchr (ptr, '/'); /* locate orig */\r | |
604 | *slptr = 0; /* zero in string */\r | |
605 | }\r | |
606 | dptr = find_unit (gbuf, &uptr); /* find device */\r | |
607 | if ((dptr == NULL) || (uptr == NULL)) return SCPE_ARG;\r | |
608 | dibp = (DIB *) dptr->ctxt; /* get DIB */\r | |
609 | if (dibp == NULL) return SCPE_ARG;\r | |
610 | unitno = (int32) (uptr - dptr->units);\r | |
611 | r5v = 0;\r | |
612 | if ((strncmp (regptr, "/R5:", 4) == 0) ||\r | |
613 | (strncmp (regptr, "/R5=", 4) == 0) ||\r | |
614 | (strncmp (regptr, "/r5:", 4) == 0) ||\r | |
615 | (strncmp (regptr, "/r5=", 4) == 0)) {\r | |
616 | r5v = (int32) get_uint (regptr + 4, 16, LMASK, &r);\r | |
617 | if (r != SCPE_OK) return r;\r | |
618 | }\r | |
619 | else if (*regptr != 0) return SCPE_ARG;\r | |
620 | for (i = 0; boot_tab[i].name != NULL; i++) {\r | |
621 | if (strcmp (dptr->name, boot_tab[i].name) == 0) {\r | |
622 | R[0] = boot_tab[i].code;\r | |
623 | if (dptr->flags & DEV_MBUS) {\r | |
624 | R[1] = dibp->ba + TR_MBA0;\r | |
625 | R[2] = unitno;\r | |
626 | }\r | |
627 | else {\r | |
628 | R[1] = TR_UBA;\r | |
629 | R[2] = boot_tab[i].let | (dibp->ba & UBADDRMASK);\r | |
630 | }\r | |
631 | R[3] = unitno;\r | |
632 | R[4] = 0;\r | |
633 | R[5] = r5v;\r | |
634 | return run_cmd (flag, "CPU");\r | |
635 | }\r | |
636 | }\r | |
637 | return SCPE_NOFNC;\r | |
638 | }\r | |
639 | \r | |
640 | /* Bootstrap - finish up bootstrap process */\r | |
641 | \r | |
642 | t_stat cpu_boot (int32 unitno, DEVICE *dptr)\r | |
643 | {\r | |
644 | t_stat r;\r | |
645 | \r | |
646 | printf ("Loading boot code from vmb.exe\n");\r | |
647 | if (sim_log) fprintf (sim_log, \r | |
648 | "Loading boot code from vmb.exe\n");\r | |
649 | r = load_cmd (0, "-O vmb.exe 200");\r | |
650 | if (r != SCPE_OK) return r;\r | |
651 | SP = PC = 512;\r | |
652 | return SCPE_OK;\r | |
653 | }\r | |
654 | \r | |
655 | /* SBI reset */\r | |
656 | \r | |
657 | t_stat sbi_reset (DEVICE *dptr)\r | |
658 | {\r | |
659 | wcs_addr = 0;\r | |
660 | wcs_data = 0;\r | |
661 | wcs_mbrk = 0;\r | |
662 | sbi_fs = 0;\r | |
663 | sbi_sc = 0;\r | |
664 | sbi_mt = 0;\r | |
665 | sbi_er = 0;\r | |
666 | sbi_tmo = 0;\r | |
667 | sim_vm_cmd = vax780_cmd;\r | |
668 | return SCPE_OK;\r | |
669 | }\r | |
670 | \r | |
671 | /* Show nexus */\r | |
672 | \r | |
673 | t_stat show_nexus (FILE *st, UNIT *uptr, int32 val, void *desc)\r | |
674 | {\r | |
675 | fprintf (st, "nexus=%d", val);\r | |
676 | return SCPE_OK;\r | |
677 | }\r | |
678 | \r | |
679 | /* Init nexus tables */\r | |
680 | \r | |
681 | void init_nexus_tab (void)\r | |
682 | {\r | |
683 | uint32 i;\r | |
684 | \r | |
685 | for (i = 0; i < NEXUS_NUM; i++) {\r | |
686 | nexusR[i] = NULL;\r | |
687 | nexusW[i] = NULL;\r | |
688 | }\r | |
689 | return;\r | |
690 | }\r | |
691 | \r | |
692 | /* Build nexus tables\r | |
693 | \r | |
694 | Inputs:\r | |
695 | dptr = pointer to device\r | |
696 | dibp = pointer to DIB\r | |
697 | Outputs:\r | |
698 | status\r | |
699 | */\r | |
700 | \r | |
701 | \r | |
702 | t_stat build_nexus_tab (DEVICE *dptr, DIB *dibp)\r | |
703 | {\r | |
704 | uint32 idx;\r | |
705 | \r | |
706 | if ((dptr == NULL) || (dibp == NULL)) return SCPE_IERR;\r | |
707 | idx = dibp->ba;\r | |
708 | if (idx >= NEXUS_NUM) return SCPE_IERR;\r | |
709 | if ((nexusR[idx] && dibp->rd && /* conflict? */\r | |
710 | (nexusR[idx] != dibp->rd)) ||\r | |
711 | (nexusW[idx] && dibp->wr &&\r | |
712 | (nexusW[idx] != dibp->wr))) {\r | |
713 | printf ("Nexus %s conflict at %d\n", sim_dname (dptr), dibp->ba);\r | |
714 | if (sim_log) fprintf (sim_log,\r | |
715 | "Nexus %s conflict at %d\n", sim_dname (dptr), dibp->ba);\r | |
716 | return SCPE_STOP;\r | |
717 | }\r | |
718 | if (dibp->rd) nexusR[idx] = dibp->rd; /* set rd dispatch */\r | |
719 | if (dibp->wr) nexusW[idx] = dibp->wr; /* set wr dispatch */\r | |
720 | return SCPE_OK;\r | |
721 | }\r | |
722 | \r | |
723 | /* Build dib_tab from device list */\r | |
724 | \r | |
725 | t_stat build_dib_tab (void)\r | |
726 | {\r | |
727 | uint32 i;\r | |
728 | DEVICE *dptr;\r | |
729 | DIB *dibp;\r | |
730 | t_stat r;\r | |
731 | \r | |
732 | init_nexus_tab ();\r | |
733 | init_ubus_tab ();\r | |
734 | init_mbus_tab ();\r | |
735 | for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { /* loop thru dev */\r | |
736 | dibp = (DIB *) dptr->ctxt; /* get DIB */\r | |
737 | if (dibp && !(dptr->flags & DEV_DIS)) { /* defined, enabled? */\r | |
738 | if (dptr->flags & DEV_NEXUS) { /* Nexus? */\r | |
739 | if (r = build_nexus_tab (dptr, dibp)) /* add to dispatch table */\r | |
740 | return r;\r | |
741 | }\r | |
742 | else if (dptr->flags & DEV_MBUS) { /* Massbus? */\r | |
743 | if (r = build_mbus_tab (dptr, dibp))\r | |
744 | return r;\r | |
745 | }\r | |
746 | else { /* no, Unibus device */\r | |
747 | if (r = build_ubus_tab (dptr, dibp)) /* add to dispatch tab */\r | |
748 | return r;\r | |
749 | } /* end else */\r | |
750 | } /* end if enabled */\r | |
751 | } /* end for */\r | |
752 | return SCPE_OK;\r | |
753 | }\r |