|
|
1.1 root 1: /* autoconf.c 1.3 81/10/07 */
2: /* autoconf.c 4.31 81/07/05 */
3:
4: /*
5: * Setup the system to run on the current machine.
6: *
7: * Configure() is called at boot time and initializes the uba and mba
8: * device tables and the memory controller monitoring. Available
9: * devices are determined (from possibilities mentioned in ioconf.c),
10: * and the drivers are initialized.
11: *
12: * N.B.: A lot of the conditionals based on processor type say
13: * #if VAX780
14: * and
15: * #if VAX750
16: * which may be incorrect after more processors are introduced if they
17: * are like either of these machines.
18: *
19: * TODO:
20: * use pcpu info about whether a ubasr exists
21: */
22:
23: #include "mba.h"
24:
25: #include "../h/param.h"
26: #include "../h/systm.h"
27: #include "../h/map.h"
28: #include "../h/nexus.h"
29: #include "../h/pte.h"
30: #include "../h/buf.h"
31: #include "../h/mbareg.h"
32: #include "../h/mbavar.h"
33: #include "../h/dk.h"
34: #include "../h/vm.h"
35: #include "../h/ubareg.h"
36: #include "../h/ubavar.h"
37: #include "../h/mtpr.h"
38: #include "../h/cpu.h"
39: #include "../h/scb.h"
40: #include "../h/mem.h"
41:
42: /*
43: * The following several variables are related to
44: * the configuration process, and are used in initializing
45: * the machine.
46: */
47: int cold; /* if 1, still working on cold-start */
48: int nexnum; /* current nexus number */
49: int dkn; /* number of iostat dk numbers assigned so far */
50:
51: /*
52: * Addresses of the (locore) routines which bootstrap us from
53: * hardware traps to C code. Filled into the system control block
54: * as necessary.
55: */
56: #if NMBA > 0
57: int (*mbaintv[4])() = { Xmba0int, Xmba1int, Xmba2int, Xmba3int };
58: #endif
59: #if VAX780
60: int (*ubaintv[4])() = { Xua0int, Xua1int, Xua2int, Xua3int };
61: #endif
62:
63: /*
64: * This allocates the space for the per-uba information,
65: * such as buffered data path usage.
66: */
67: struct uba_hd uba_hd[MAXNUBA];
68:
69: /*
70: * Determine mass storage and memory configuration for a machine.
71: * Get cpu type, and then switch out to machine specific procedures
72: * which will probe adaptors to see what is out there.
73: */
74: configure()
75: {
76: union cpusid cpusid;
77: register struct percpu *ocp;
78: register int *ip;
79: extern char Sysbase[];
80:
81: cpusid.cpusid = mfpr(SID);
82: for (ocp = percpu; ocp->pc_cputype; ocp++)
83: if (ocp->pc_cputype == cpusid.cpuany.cp_type) {
84: probenexus(ocp);
85: /*
86: * Write protect the scb. It is strange
87: * that this code is here, but this is as soon
88: * as we are done mucking with it, and the
89: * write-enable was done in assembly language
90: * to which we will never return.
91: */
92: ip = (int *)Sysmap; *ip &= ~PG_PROT; *ip |= PG_KR;
93: mtpr(TBIS, Sysbase);
94: #if GENERIC
95: setconf();
96: #endif
97: cold = 0;
98: memenable();
99: return;
100: }
101: printf("cpu type %d not configured\n", cpusid.cpuany.cp_type);
102: asm("halt");
103: }
104:
105: /*
106: * Probe nexus space, finding the interconnects
107: * and setting up and probing mba's and uba's for devices.
108: */
109: /*ARGSUSED*/
110: probenexus(pcpu)
111: register struct percpu *pcpu;
112: {
113: register struct nexus *nxv;
114: struct nexus *nxp = pcpu->pc_nexbase;
115: union nexcsr nexcsr;
116: int i;
117:
118: nexnum = 0, nxv = nexus;
119: for (; nexnum < pcpu->pc_nnexus; nexnum++, nxp++, nxv++) {
120: nxaccess(nxp, Nexmap[nexnum]);
121: if (badaddr((caddr_t)nxv, 4))
122: continue;
123: if (pcpu->pc_nextype && pcpu->pc_nextype[nexnum] != NEX_ANY)
124: nexcsr.nex_csr = pcpu->pc_nextype[nexnum];
125: else
126: nexcsr = nxv->nexcsr;
127: if (nexcsr.nex_csr&NEX_APD)
128: continue;
129: switch (nexcsr.nex_type) {
130:
131: case NEX_MBA:
132: printf("mba%d at tr%d\n", nummba, nexnum);
133: if (nummba >= NMBA) {
134: printf("%d mba's", nummba);
135: goto unconfig;
136: }
137: #if NMBA > 0
138: mbafind(nxv, nxp);
139: nummba++;
140: #endif
141: break;
142:
143: case NEX_UBA0:
144: case NEX_UBA1:
145: case NEX_UBA2:
146: case NEX_UBA3:
147: printf("uba%d at tr%d\n", numuba, nexnum);
148: #if VAX750 /* temp until this is fixed right */
149: if (numuba > 0) {
150: #else
151: if (numuba >= 4) {
152: #endif
153: printf("%d uba's", numuba);
154: goto unsupp;
155: }
156: #if VAX780
157: if (cpu == VAX_780)
158: setscbnex(ubaintv[numuba]);
159: #endif
160: i = nexcsr.nex_type - NEX_UBA0;
161: unifind((struct uba_regs *)nxv, (struct uba_regs *)nxp,
162: umem[i], pcpu->pc_umaddr[i], UMEMmap[i]);
163: #if VAX780
164: if (cpu == VAX_780)
165: ((struct uba_regs *)nxv)->uba_cr =
166: UBACR_IFS|UBACR_BRIE|
167: UBACR_USEFIE|UBACR_SUEFIE;
168: #endif
169: numuba++;
170: break;
171:
172: case NEX_DR32:
173: /* there can be more than one... are there other codes??? */
174: printf("dr32");
175: goto unsupp;
176:
177: case NEX_MEM4:
178: case NEX_MEM4I:
179: case NEX_MEM16:
180: case NEX_MEM16I:
181: printf("mcr%d at tr%d\n", nmcr, nexnum);
182: if (nmcr >= 4) {
183: printf("5 mcr's");
184: goto unsupp;
185: }
186: mcraddr[nmcr++] = (struct mcr *)nxv;
187: break;
188:
189: case NEX_MPM0:
190: case NEX_MPM1:
191: case NEX_MPM2:
192: case NEX_MPM3:
193: printf("mpm");
194: goto unsupp;
195:
196: default:
197: printf("nexus type %x", nexcsr.nex_type);
198: unsupp:
199: printf(" unsupported (at tr %d)\n", nexnum);
200: continue;
201: unconfig:
202: printf(" not configured\n");
203: continue;
204: }
205: }
206: #if VAX780
207: if (cpu == VAX_780)
208: { int ubawatch(); timeout(ubawatch, (caddr_t)0, hz); }
209: #endif
210: }
211:
212: #if NMBA > 0
213: struct mba_device *mbaconfig();
214: /*
215: * Find devices attached to a particular mba
216: * and look for each device found in the massbus
217: * initialization tables.
218: */
219: mbafind(nxv, nxp)
220: struct nexus *nxv, *nxp;
221: {
222: register struct mba_regs *mdp;
223: register struct mba_drv *mbd;
224: register struct mba_device *mi;
225: register struct mba_slave *ms;
226: int dn, dt;
227: struct mba_device fnd;
228:
229: mdp = (struct mba_regs *)nxv;
230: mba_hd[nummba].mh_mba = mdp;
231: mba_hd[nummba].mh_physmba = (struct mba_regs *)nxp;
232: setscbnex(mbaintv[nummba]);
233: fnd.mi_mba = mdp;
234: fnd.mi_mbanum = nummba;
235: for (mbd = mdp->mba_drv, dn = 0; mbd < &mdp->mba_drv[8]; mbd++, dn++) {
236: dt = mbd->mbd_dt & 0xffff;
237: if (dt == 0)
238: continue;
239: if (dt == MBDT_MOH)
240: continue;
241: fnd.mi_drive = dn;
242: if ((mi = mbaconfig(&fnd, dt)) && (dt & MBDT_TAP)) {
243: for (ms = mbsinit; ms->ms_driver; ms++)
244: if (ms->ms_driver == mi->mi_driver && ms->ms_alive == 0 &&
245: (ms->ms_ctlr == mi->mi_unit || ms->ms_ctlr=='?')) {
246: if ((*ms->ms_driver->md_slave)(mi, ms)) {
247: printf("%s%d at %s%d slave %d\n",
248: ms->ms_driver->md_sname,
249: ms->ms_unit,
250: mi->mi_driver->md_dname,
251: mi->mi_unit,
252: ms->ms_slave);
253: ms->ms_alive = 1;
254: ms->ms_ctlr = mi->mi_unit;
255: }
256: }
257: }
258: }
259: mdp->mba_cr = MBCR_INIT;
260: mdp->mba_cr = MBCR_IE;
261: }
262:
263: /*
264: * Have found a massbus device;
265: * see if it is in the configuration table.
266: * If so, fill in its data.
267: */
268: struct mba_device *
269: mbaconfig(ni, type)
270: register struct mba_device *ni;
271: register int type;
272: {
273: register struct mba_device *mi;
274: register short *tp;
275: register struct mba_hd *mh;
276:
277: for (mi = mbdinit; mi->mi_driver; mi++) {
278: if (mi->mi_alive)
279: continue;
280: tp = mi->mi_driver->md_type;
281: for (mi->mi_type = 0; *tp; tp++, mi->mi_type++)
282: if (*tp == (type&MBDT_TYPE))
283: goto found;
284: continue;
285: found:
286: #define match(fld) (ni->fld == mi->fld || mi->fld == '?')
287: if (!match(mi_drive) || !match(mi_mbanum))
288: continue;
289: printf("%s%d at mba%d drive %d",
290: mi->mi_driver->md_dname, mi->mi_unit,
291: ni->mi_mbanum, ni->mi_drive);
292: printf("\n");
293: mi->mi_alive = 1;
294: mh = &mba_hd[ni->mi_mbanum];
295: mi->mi_hd = mh;
296: mh->mh_mbip[ni->mi_drive] = mi;
297: mh->mh_ndrive++;
298: mi->mi_mba = ni->mi_mba;
299: mi->mi_drv = &mi->mi_mba->mba_drv[ni->mi_drive];
300: mi->mi_driver->md_info[mi->mi_unit] = mi;
301: mi->mi_mbanum = ni->mi_mbanum;
302: mi->mi_drive = ni->mi_drive;
303: if (mi->mi_dk && dkn < DK_NDRIVE)
304: mi->mi_dk = dkn++;
305: else
306: mi->mi_dk = -1;
307: (*mi->mi_driver->md_attach)(mi);
308: return (mi);
309: }
310: return (0);
311: }
312: #endif
313:
314: /*
315: * Fixctlrmask fixes the masks of the driver ctlr routines
316: * which otherwise save r10 and r11 where the interrupt and br
317: * level are passed through.
318: */
319: fixctlrmask()
320: {
321: register struct uba_ctlr *um;
322: register struct uba_device *ui;
323: register struct uba_driver *ud;
324: #define phys(a,b) ((b)(((int)(a))&0x7fffffff))
325:
326: for (um = ubminit; ud = phys(um->um_driver, struct uba_driver *); um++)
327: *phys(ud->ud_probe, short *) &= ~0xc00;
328: for (ui = ubdinit; ud = phys(ui->ui_driver, struct uba_driver *); ui++)
329: *phys(ud->ud_probe, short *) &= ~0xc00;
330: }
331:
332: /*
333: * Find devices on a UNIBUS.
334: * Uses per-driver routine to set <br,cvec> into <r11,r10>,
335: * and then fills in the tables, with help from a per-driver
336: * slave initialization routine.
337: */
338: unifind(vubp, pubp, vumem, pumem, memmap)
339: struct uba_regs *vubp, *pubp;
340: caddr_t vumem, pumem;
341: struct pte *memmap;
342: {
343: #ifndef lint
344: register int br, cvec; /* MUST BE r11, r10 */
345: #else
346: /*
347: * Lint doesn't realize that these
348: * can be initialized asynchronously
349: * when devices interrupt.
350: */
351: register int br = 0, cvec = 0;
352: #endif
353: register struct uba_device *ui;
354: register struct uba_ctlr *um;
355: u_short *reg, addr;
356: struct uba_hd *uhp;
357: struct uba_driver *udp;
358: int i, (**ivec)(), haveubasr = 0;
359:
360: /*
361: * Initialize the UNIBUS, by freeing the map
362: * registers and the buffered data path registers
363: */
364: uhp = &uba_hd[numuba];
365: uhp->uh_map = (struct map *)calloc(UAMSIZ * sizeof (struct map));
366: #ifdef ETHERNET
367: rminit(uhp->uh_map, NUBMREG-64, 1, "uba", UAMSIZ);
368: #endif ETHERNET
369: rminit(uhp->uh_map, NUBMREG, 1, "uba", UAMSIZ);
370: switch (cpu) {
371: #if VAX780
372: case VAX_780:
373: uhp->uh_bdpfree = (1<<NBDP780) - 1;
374: haveubasr = 1;
375: break;
376: #endif
377: #if VAX750
378: case VAX_750:
379: uhp->uh_bdpfree = (1<<NBDP750) - 1;
380: break;
381: #endif
382: #if VAX7ZZ
383: case VAX_7ZZ:
384: break;
385: #endif
386: }
387:
388: /*
389: * Save virtual and physical addresses
390: * of adaptor, and allocate and initialize
391: * the UNIBUS interrupt vector.
392: */
393: uhp->uh_uba = vubp;
394: uhp->uh_physuba = pubp;
395: /* HAVE TO DO SOMETHING SPECIAL FOR SECOND UNIBUS ON COMETS HERE */
396: if (numuba == 0)
397: uhp->uh_vec = UNIvec;
398: else
399: uhp->uh_vec = (int(**)())calloc(512);
400: for (i = 0; i < 128; i++)
401: uhp->uh_vec[i] =
402: scbentry(&catcher[i*2], SCB_ISTACK);
403: /*
404: * Set last free interrupt vector for devices with
405: * programmable interrupt vectors. Use is to decrement
406: * this number and use result as interrupt vector.
407: */
408: uhp->uh_lastiv = 0x200;
409:
410: /* THIS IS A CHEAT: USING THE FACT THAT UMEM and NEXI ARE SAME SIZE */
411: nxaccess((struct nexus *)pumem, memmap);
412: #ifdef ETHERNET
413: if(numuba == 0) { /*****EC ON UBA0 ONLY!!!*****/
414: extern struct pte ECmap[];
415: ecaccess((struct nexus *)(pumem-(24*1024)), ECmap);
416: }
417: #endif ETHERNET
418: #if VAX780
419: if (haveubasr) {
420: vubp->uba_sr = vubp->uba_sr;
421: vubp->uba_cr = UBACR_IFS|UBACR_BRIE;
422: }
423: #endif
424:
425: /*
426: * Map the first page of UNIBUS i/o
427: * space to the first page of memory
428: * for devices which will need to dma
429: * output to produce an interrupt.
430: */
431: *(int *)(&vubp->uba_map[0]) = UBAMR_MRV;
432:
433: #define ubaddr(off) (u_short *)((int)vumem + ((off)&0x1fff))
434: /*
435: * Check each unibus mass storage controller.
436: * For each one which is potentially on this uba,
437: * see if it is really there, and if it is record it and
438: * then go looking for slaves.
439: */
440: for (um = ubminit; udp = um->um_driver; um++) {
441: if (um->um_ubanum != numuba && um->um_ubanum != '?')
442: continue;
443: addr = (u_short)um->um_addr;
444: reg = ubaddr(addr);
445: if (badaddr((caddr_t)reg, 2)) {
446: printf("uba%d %s%d badaddr\n", numuba, udp->ud_mname,
447: um->um_ctlr);
448: continue;
449: }
450: #if VAX780
451: if (haveubasr && vubp->uba_sr) {
452: vubp->uba_sr = vubp->uba_sr;
453: continue;
454: }
455: #endif
456: cvec = 0x200;
457: i = (*udp->ud_probe)(reg, um->um_ctlr);
458: #ifdef CHAOS
459: /*
460: ** Since the cold-boot-time stray interrupt catcher in
461: ** locore.s leaves the processor at the priority level
462: ** of the interrupt (yes, even after the rei), we must
463: ** restore it here.
464: */
465: (void) spl0();
466: #endif CHAOS
467: #if VAX780
468: if (haveubasr && vubp->uba_sr) {
469: vubp->uba_sr = vubp->uba_sr;
470: continue;
471: }
472: #endif
473: if (i == 0)
474: continue;
475: printf("%s%d uba%d csr %o ",
476: udp->ud_mname, um->um_ctlr, numuba, addr);
477: if (cvec == 0) {
478: printf("zero vector\n");
479: continue;
480: }
481: if (cvec == 0x200) {
482: printf("didn't interrupt\n");
483: continue;
484: }
485: printf("vec 0%o ipl x%x\n", cvec, br);
486: um->um_alive = 1;
487: um->um_ubanum = numuba;
488: um->um_hd = &uba_hd[numuba];
489: um->um_addr = (caddr_t)reg;
490: udp->ud_minfo[um->um_ctlr] = um;
491: for (ivec = um->um_intr; *ivec; ivec++) {
492: um->um_hd->uh_vec[cvec/4] =
493: scbentry(*ivec, SCB_ISTACK);
494: cvec += 4;
495: }
496: for (ui = ubdinit; ui->ui_driver; ui++) {
497: if (ui->ui_driver != udp || ui->ui_alive ||
498: ui->ui_ctlr != um->um_ctlr && ui->ui_ctlr != '?' ||
499: ui->ui_ubanum != numuba && ui->ui_ubanum != '?')
500: continue;
501: if ((*udp->ud_slave)(ui, reg)) {
502: ui->ui_alive = 1;
503: ui->ui_ctlr = um->um_ctlr;
504: ui->ui_ubanum = numuba;
505: ui->ui_hd = &uba_hd[numuba];
506: ui->ui_addr = (caddr_t)reg;
507: ui->ui_physaddr = pumem + (addr&0x1fff);
508: if (ui->ui_dk && dkn < DK_NDRIVE)
509: ui->ui_dk = dkn++;
510: else
511: ui->ui_dk = -1;
512: ui->ui_mi = um;
513: /* ui_type comes from driver */
514: udp->ud_dinfo[ui->ui_unit] = ui;
515: printf("%s%d at %s%d sl%d ",
516: udp->ud_dname, ui->ui_unit,
517: udp->ud_mname, um->um_ctlr, ui->ui_slave);
518: (*udp->ud_attach)(ui);
519: }
520: }
521: }
522: /*
523: * Now look for non-mass storage peripherals.
524: */
525: for (ui = ubdinit; udp = ui->ui_driver; ui++) {
526: if (ui->ui_ubanum != numuba && ui->ui_ubanum != '?' ||
527: ui->ui_alive || ui->ui_slave != -1)
528: continue;
529: addr = (u_short)ui->ui_addr;
530: reg = ubaddr(addr);
531: if (badaddr((caddr_t)reg, 2)) {
532: printf("%s%d not found at uba%d csr %o\n",
533: ui->ui_driver->ud_dname, ui->ui_unit, numuba, addr);
534: continue;
535: }
536: #if VAX780
537: if (haveubasr && vubp->uba_sr) {
538: vubp->uba_sr = vubp->uba_sr;
539: continue;
540: }
541: #endif
542: cvec = 0x200;
543: i = (*udp->ud_probe)(reg, um->um_ctlr);
544: #ifdef CHAOS
545: /*
546: ** Since the cold-boot-time stray interrupt catcher in
547: ** locore.s leaves the processor at the priority level
548: ** of the interrupt (yes, even after the rei), we must
549: ** restore it here.
550: */
551: (void) spl0();
552: #endif CHAOS
553: #if VAX780
554: if (haveubasr && vubp->uba_sr) {
555: vubp->uba_sr = vubp->uba_sr;
556: continue;
557: }
558: #endif
559: if (i == 0)
560: continue;
561: printf("%s%d at uba%d csr %o ",
562: ui->ui_driver->ud_dname, ui->ui_unit, numuba, addr);
563: if (cvec == 0) {
564: printf("zero vector\n");
565: continue;
566: }
567: if (cvec == 0x200) {
568: printf("didn't interrupt\n");
569: continue;
570: }
571: printf("vec 0%o ipl x%x\n", cvec, br);
572: ui->ui_hd = &uba_hd[numuba];
573: for (ivec = ui->ui_intr; *ivec; ivec++) {
574: ui->ui_hd->uh_vec[cvec/4] =
575: scbentry(*ivec, SCB_ISTACK);
576: cvec += 4;
577: }
578: ui->ui_alive = 1;
579: ui->ui_ubanum = numuba;
580: ui->ui_addr = (caddr_t)reg;
581: ui->ui_physaddr = pumem + (addr&0x1fff);
582: ui->ui_dk = -1;
583: /* ui_type comes from driver */
584: udp->ud_dinfo[ui->ui_unit] = ui;
585: (*udp->ud_attach)(ui);
586: }
587: }
588:
589: setscbnex(fn)
590: int (*fn)();
591: {
592: register struct scb *scbp = &scb;
593:
594: scbp->scb_ipl14[nexnum] = scbp->scb_ipl15[nexnum] =
595: scbp->scb_ipl16[nexnum] = scbp->scb_ipl17[nexnum] =
596: scbentry(fn, SCB_ISTACK);
597: }
598:
599: /*
600: * Make a nexus accessible at physical address phys
601: * by mapping kernel ptes starting at pte.
602: *
603: * WE LEAVE ALL NEXI MAPPED; THIS IS PERHAPS UNWISE
604: * SINCE MISSING NEXI DONT RESPOND. BUT THEN AGAIN
605: * PRESENT NEXI DONT RESPOND TO ALL OF THEIR ADDRESS SPACE.
606: */
607: nxaccess(physa, pte)
608: struct nexus *physa;
609: register struct pte *pte;
610: {
611: register int i = btop(sizeof (struct nexus));
612: register unsigned v = btop(physa);
613:
614: do
615: *(int *)pte++ = PG_V|PG_KW|v++;
616: while (--i > 0);
617: mtpr(TBIA, 0);
618: }
619: #ifdef ETHERNET
620: ecaccess(physa, pte)
621: struct nexus *physa;
622: register struct pte *pte;
623: {
624: register int i = 64;
625: register unsigned v = btop(physa);
626:
627: do
628: *(int *)pte++ = PG_V | PG_KW | v++;
629: while(--i);
630: }
631: #endif ETHERNET
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.