First Commit of my working state
[simh.git] / VAX / vax780_sbi.c
CommitLineData
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
88struct boot_dev {\r
89 char *name;\r
90 int32 code;\r
91 int32 let;\r
92 };\r
93\r
94uint32 wcs_addr = 0;\r
95uint32 wcs_data = 0;\r
96uint32 wcs_mbrk = 0;\r
97uint32 nexus_req[NEXUS_HLVL]; /* nexus int req */\r
98uint32 sbi_fs = 0; /* SBI fault status */\r
99uint32 sbi_sc = 0; /* SBI silo comparator */\r
100uint32 sbi_mt = 0; /* SBI maintenance */\r
101uint32 sbi_er = 0; /* SBI error status */\r
102uint32 sbi_tmo = 0; /* SBI timeout addr */\r
103\r
104static t_stat (*nexusR[NEXUS_NUM])(int32 *dat, int32 ad, int32 md);\r
105static t_stat (*nexusW[NEXUS_NUM])(int32 dat, int32 ad, int32 md);\r
106\r
107static 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
116extern int32 R[16];\r
117extern int32 PSL;\r
118extern int32 ASTLVL, SISR;\r
119extern int32 mapen, pme, trpirq;\r
120extern int32 in_ie;\r
121extern int32 mchk_va, mchk_ref;\r
122extern int32 crd_err, mem_err, hlt_pin;\r
123extern int32 tmr_int, tti_int, tto_int;\r
124extern jmp_buf save_env;\r
125extern int32 p1;\r
126extern int32 sim_switches;\r
127extern DEVICE *sim_devices[];\r
128extern FILE *sim_log;\r
129extern CTAB *sim_vm_cmd;\r
130\r
131t_stat sbi_reset (DEVICE *dptr);\r
132void sbi_set_tmo (int32 pa);\r
133void uba_eval_int (void);\r
134t_stat vax780_boot (int32 flag, char *ptr);\r
135\r
136extern t_stat vax780_fload (int flag, char *cptr);\r
137extern int32 intexc (int32 vec, int32 cc, int32 ipl, int ei);\r
138extern int32 iccs_rd (void);\r
139extern int32 nicr_rd (void);\r
140extern int32 icr_rd (t_bool interp);\r
141extern int32 todr_rd (void);\r
142extern int32 rxcs_rd (void);\r
143extern int32 rxdb_rd (void);\r
144extern int32 txcs_rd (void);\r
145extern void iccs_wr (int32 dat);\r
146extern void nicr_wr (int32 dat);\r
147extern void todr_wr (int32 dat);\r
148extern void rxcs_wr (int32 dat);\r
149extern void txcs_wr (int32 dat);\r
150extern void txdb_wr (int32 dat);\r
151extern void init_mbus_tab (void);\r
152extern void init_ubus_tab (void);\r
153extern t_stat build_mbus_tab (DEVICE *dptr, DIB *dibp);\r
154extern 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
163UNIT sbi_unit = { UDATA (NULL, 0, 0) };\r
164\r
165REG 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
181DEVICE 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
191CTAB 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
217int32 eval_int (void)\r
218{\r
219int32 ipl = PSL_GETIPL (PSL);\r
220int32 i, t;\r
221\r
222static 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
229if (hlt_pin) return IPL_HLTPIN; /* hlt pin int */\r
230if ((ipl < IPL_MEMERR) && mem_err) return IPL_MEMERR; /* mem err int */\r
231if ((ipl < IPL_CRDERR) && crd_err) return IPL_CRDERR; /* crd err int */\r
232if ((ipl < IPL_CLKINT) && tmr_int) return IPL_CLKINT; /* clock int */\r
233uba_eval_int (); /* update UBA */\r
234for (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
238if ((ipl < IPL_TTINT) && (tti_int || tto_int)) /* console int */\r
239 return IPL_TTINT;\r
240if (ipl >= IPL_SMAX) return 0; /* ipl >= sw max? */\r
241if ((t = SISR & sw_int_mask[ipl]) == 0) return 0; /* eligible req */\r
242for (i = IPL_SMAX; i > ipl; i--) { /* check swre int */\r
243 if ((t >> i) & 1) return i; /* req != 0? int */\r
244 }\r
245return 0;\r
246}\r
247\r
248/* Return vector for highest priority hardware interrupt at IPL lvl */\r
249\r
250int32 get_vector (int32 lvl)\r
251{\r
252int32 i, l;\r
253\r
254if (lvl == IPL_MEMERR) { /* mem error? */\r
255 mem_err = 0;\r
256 return SCB_MEMERR;\r
257 }\r
258if (lvl == IPL_CRDERR) { /* CRD error? */\r
259 crd_err = 0;\r
260 return SCB_CRDERR;\r
261 }\r
262if (lvl == IPL_CLKINT) { /* clock? */\r
263 tmr_int = 0; /* clear req */\r
264 return SCB_INTTIM; /* return vector */\r
265 }\r
266if (lvl > IPL_HMAX) { /* error req lvl? */\r
267 ABORT (STOP_UIPL); /* unknown intr */\r
268 }\r
269if ((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
278if (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
288return 0;\r
289}\r
290\r
291/* Read 780-specific IPR's */\r
292\r
293int32 ReadIPR (int32 rg)\r
294{\r
295int32 val;\r
296\r
297switch (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
375return val;\r
376}\r
377\r
378/* Write 780-specific IPR's */\r
379\r
380void WriteIPR (int32 rg, int32 val)\r
381{\r
382switch (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
461return;\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
473int32 ReadReg (int32 pa, int32 lnt)\r
474{\r
475int32 nexus, val;\r
476\r
477if (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
485sbi_set_tmo (pa); /* timeout */\r
486MACH_CHECK (MCHK_RD_F); /* machine check */\r
487return 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
500void WriteReg (int32 pa, int32 val, int32 lnt)\r
501{\r
502int32 nexus;\r
503\r
504if (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
512sbi_set_tmo (pa); /* timeout */\r
513mem_err = 1; /* interrupt */\r
514eval_int ();\r
515return;\r
516}\r
517\r
518/* Set SBI timeout - machine checks only on reads */\r
519\r
520void sbi_set_tmo (int32 pa)\r
521{\r
522if ((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
528else sbi_er |= SBIER_MULT; /* yes, multiple */\r
529return;\r
530}\r
531\r
532/* Set SBI error confirmation - always machine checks */\r
533\r
534void sbi_set_errcnf (void)\r
535{\r
536if (sbi_er & SBIER_CNF) sbi_er |= SBIER_MULT;\r
537else sbi_er |= SBIER_CNF;\r
538MACH_CHECK (MCHK_RD_F);\r
539return;\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
551int32 machine_check (int32 p1, int32 opc, int32 cc, int32 delta)\r
552{\r
553int32 acc, err;\r
554\r
555err = (GET_TRAP (trpirq) << 4) | (pme << 3) | ASTLVL; /* error word */\r
556cc = intexc (SCB_MCHK, cc, 0, IE_SVE); /* take exception */\r
557acc = ACC_MASK (KERN); /* in kernel mode */\r
558in_ie = 1;\r
559SP = SP - 44; /* push 11 words */\r
560Write (SP, 40, L_LONG, WA); /* # bytes */\r
561Write (SP + 4, p1, L_LONG, WA); /* mcheck type */\r
562Write (SP + 8, err, L_LONG, WA); /* CPU error status */\r
563Write (SP + 12, 0, L_LONG, WA); /* uPC */\r
564Write (SP + 16, mchk_va, L_LONG, WA); /* VA */\r
565Write (SP + 20, 0, L_LONG, WA); /* D register */\r
566Write (SP + 24, mapen, L_LONG, WA); /* TB status 1 */\r
567Write (SP + 28, 0, L_LONG, WA); /* TB status 2 */\r
568Write (SP + 32, sbi_tmo, L_LONG, WA); /* SBI timeout addr */\r
569Write (SP + 36, 0, L_LONG, WA); /* cache status */\r
570Write (SP + 40, sbi_er, L_LONG, WA); /* SBI error */\r
571in_ie = 0;\r
572sbi_er = sbi_er & ~SBIER_TMOW1C; /* clr SBIER<tmo> etc */\r
573return cc;\r
574}\r
575\r
576/* Console entry */\r
577\r
578int32 con_halt (int32 code, int32 cc)\r
579{\r
580ABORT (STOP_HALT);\r
581return 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
591t_stat vax780_boot (int32 flag, char *ptr)\r
592{\r
593char gbuf[CBUFSIZE];\r
594char *slptr, *regptr;\r
595int32 i, r5v, unitno;\r
596DEVICE *dptr;\r
597UNIT *uptr;\r
598DIB *dibp;\r
599t_stat r;\r
600\r
601regptr = get_glyph (ptr, gbuf, 0); /* get glyph */\r
602if (slptr = strchr (gbuf, '/')) { /* found slash? */\r
603 regptr = strchr (ptr, '/'); /* locate orig */\r
604 *slptr = 0; /* zero in string */\r
605 }\r
606dptr = find_unit (gbuf, &uptr); /* find device */\r
607if ((dptr == NULL) || (uptr == NULL)) return SCPE_ARG;\r
608dibp = (DIB *) dptr->ctxt; /* get DIB */\r
609if (dibp == NULL) return SCPE_ARG;\r
610unitno = (int32) (uptr - dptr->units);\r
611r5v = 0;\r
612if ((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
619else if (*regptr != 0) return SCPE_ARG;\r
620for (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
637return SCPE_NOFNC;\r
638}\r
639\r
640/* Bootstrap - finish up bootstrap process */\r
641\r
642t_stat cpu_boot (int32 unitno, DEVICE *dptr)\r
643{\r
644t_stat r;\r
645\r
646printf ("Loading boot code from vmb.exe\n");\r
647if (sim_log) fprintf (sim_log, \r
648 "Loading boot code from vmb.exe\n");\r
649r = load_cmd (0, "-O vmb.exe 200");\r
650if (r != SCPE_OK) return r;\r
651SP = PC = 512;\r
652return SCPE_OK;\r
653}\r
654\r
655/* SBI reset */\r
656\r
657t_stat sbi_reset (DEVICE *dptr)\r
658{\r
659wcs_addr = 0;\r
660wcs_data = 0;\r
661wcs_mbrk = 0;\r
662sbi_fs = 0;\r
663sbi_sc = 0;\r
664sbi_mt = 0;\r
665sbi_er = 0;\r
666sbi_tmo = 0;\r
667sim_vm_cmd = vax780_cmd;\r
668return SCPE_OK;\r
669}\r
670\r
671/* Show nexus */\r
672\r
673t_stat show_nexus (FILE *st, UNIT *uptr, int32 val, void *desc)\r
674{\r
675fprintf (st, "nexus=%d", val);\r
676return SCPE_OK;\r
677}\r
678\r
679/* Init nexus tables */\r
680\r
681void init_nexus_tab (void)\r
682{\r
683uint32 i;\r
684\r
685for (i = 0; i < NEXUS_NUM; i++) {\r
686 nexusR[i] = NULL;\r
687 nexusW[i] = NULL;\r
688 }\r
689return;\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
702t_stat build_nexus_tab (DEVICE *dptr, DIB *dibp)\r
703{\r
704uint32 idx;\r
705\r
706if ((dptr == NULL) || (dibp == NULL)) return SCPE_IERR;\r
707idx = dibp->ba;\r
708if (idx >= NEXUS_NUM) return SCPE_IERR;\r
709if ((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
718if (dibp->rd) nexusR[idx] = dibp->rd; /* set rd dispatch */\r
719if (dibp->wr) nexusW[idx] = dibp->wr; /* set wr dispatch */\r
720return SCPE_OK;\r
721}\r
722\r
723/* Build dib_tab from device list */\r
724\r
725t_stat build_dib_tab (void)\r
726{\r
727uint32 i;\r
728DEVICE *dptr;\r
729DIB *dibp;\r
730t_stat r;\r
731\r
732init_nexus_tab ();\r
733init_ubus_tab ();\r
734init_mbus_tab ();\r
735for (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
752return SCPE_OK;\r
753}\r