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