xref: /original-bsd/sys/vax/vax/autoconf.c (revision 1f3a482a)
1 /*	autoconf.c	4.31	81/07/05	*/
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_TYPE) == MBDT_TU78) {
235 			printf("tm04/tu78 unsupported\n");
236 			continue;
237 		}
238 		if (dt == MBDT_MOH)
239 			continue;
240 		fnd.mi_drive = dn;
241 		if ((mi = mbaconfig(&fnd, dt)) && (dt & MBDT_TAP)) {
242 			for (ms = mbsinit; ms->ms_driver; ms++)
243 			if (ms->ms_driver == mi->mi_driver && ms->ms_alive == 0 &&
244 			    (ms->ms_ctlr == mi->mi_unit || ms->ms_ctlr=='?')) {
245 				mbd->mbd_tc = ms->ms_slave;
246 				dt = mbd->mbd_dt;
247 				if (dt & MBDT_SPR) {
248 					printf("%s%d at %s%d slave %d\n",
249 					    ms->ms_driver->md_sname,
250 					    ms->ms_unit,
251 					    mi->mi_driver->md_dname,
252 					    mi->mi_unit,
253 					    ms->ms_slave);
254 					ms->ms_alive = 1;
255 					ms->ms_ctlr = mi->mi_unit;
256 					(*ms->ms_driver->md_slave)
257 					    (mi, ms);
258 				}
259 			}
260 		}
261 	}
262 	mdp->mba_cr = MBCR_INIT;
263 	mdp->mba_cr = MBCR_IE;
264 }
265 
266 /*
267  * Have found a massbus device;
268  * see if it is in the configuration table.
269  * If so, fill in its data.
270  */
271 struct mba_device *
272 mbaconfig(ni, type)
273 	register struct mba_device *ni;
274 	register int type;
275 {
276 	register struct mba_device *mi;
277 	register short *tp;
278 	register struct mba_hd *mh;
279 
280 	for (mi = mbdinit; mi->mi_driver; mi++) {
281 		if (mi->mi_alive)
282 			continue;
283 		tp = mi->mi_driver->md_type;
284 		for (mi->mi_type = 0; *tp; tp++, mi->mi_type++)
285 			if (*tp == (type&MBDT_TYPE))
286 				goto found;
287 		continue;
288 found:
289 #define	match(fld)	(ni->fld == mi->fld || mi->fld == '?')
290 		if (!match(mi_drive) || !match(mi_mbanum))
291 			continue;
292 		printf("%s%d at mba%d drive %d",
293 		    mi->mi_driver->md_dname, mi->mi_unit,
294 		    ni->mi_mbanum, ni->mi_drive);
295 		printf("\n");
296 		mi->mi_alive = 1;
297 		mh = &mba_hd[ni->mi_mbanum];
298 		mi->mi_hd = mh;
299 		mh->mh_mbip[ni->mi_drive] = mi;
300 		mh->mh_ndrive++;
301 		mi->mi_mba = ni->mi_mba;
302 		mi->mi_drv = &mi->mi_mba->mba_drv[ni->mi_drive];
303 		mi->mi_driver->md_info[mi->mi_unit] = mi;
304 		mi->mi_mbanum = ni->mi_mbanum;
305 		mi->mi_drive = ni->mi_drive;
306 		if (mi->mi_dk && dkn < DK_NDRIVE)
307 			mi->mi_dk = dkn++;
308 		else
309 			mi->mi_dk = -1;
310 		(*mi->mi_driver->md_attach)(mi);
311 		return (mi);
312 	}
313 	return (0);
314 }
315 #endif
316 
317 /*
318  * Fixctlrmask fixes the masks of the driver ctlr routines
319  * which otherwise save r10 and r11 where the interrupt and br
320  * level are passed through.
321  */
322 fixctlrmask()
323 {
324 	register struct uba_ctlr *um;
325 	register struct uba_device *ui;
326 	register struct uba_driver *ud;
327 #define	phys(a,b) ((b)(((int)(a))&0x7fffffff))
328 
329 	for (um = ubminit; ud = phys(um->um_driver, struct uba_driver *); um++)
330 		*phys(ud->ud_probe, short *) &= ~0xc00;
331 	for (ui = ubdinit; ud = phys(ui->ui_driver, struct uba_driver *); ui++)
332 		*phys(ud->ud_probe, short *) &= ~0xc00;
333 }
334 
335 /*
336  * Find devices on a UNIBUS.
337  * Uses per-driver routine to set <br,cvec> into <r11,r10>,
338  * and then fills in the tables, with help from a per-driver
339  * slave initialization routine.
340  */
341 unifind(vubp, pubp, vumem, pumem, memmap)
342 	struct uba_regs *vubp, *pubp;
343 	caddr_t vumem, pumem;
344 	struct pte *memmap;
345 {
346 #ifndef lint
347 	register int br, cvec;			/* MUST BE r11, r10 */
348 #else
349 	/*
350 	 * Lint doesn't realize that these
351 	 * can be initialized asynchronously
352 	 * when devices interrupt.
353 	 */
354 	register int br = 0, cvec = 0;
355 #endif
356 	register struct uba_device *ui;
357 	register struct uba_ctlr *um;
358 	u_short *reg, addr;
359 	struct uba_hd *uhp;
360 	struct uba_driver *udp;
361 	int i, (**ivec)(), haveubasr = 0;
362 
363 	/*
364 	 * Initialize the UNIBUS, by freeing the map
365 	 * registers and the buffered data path registers
366 	 */
367 	uhp = &uba_hd[numuba];
368 	uhp->uh_map = (struct map *)calloc(UAMSIZ * sizeof (struct map));
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 	/* THIS IS A CHEAT: USING THE FACT THAT UMEM and NEXI ARE SAME SIZE */
404 	nxaccess((struct nexus *)pumem, memmap);
405 #if VAX780
406 	if (haveubasr) {
407 		vubp->uba_sr = vubp->uba_sr;
408 		vubp->uba_cr = UBACR_IFS|UBACR_BRIE;
409 	}
410 #endif
411 	/*
412 	 * Map the first page of UNIBUS i/o
413 	 * space to the first page of memory
414 	 * for devices which will need to dma
415 	 * output to produce an interrupt.
416 	 */
417 	*(int *)(&vubp->uba_map[0]) = UBAMR_MRV;
418 
419 #define	ubaddr(off)	(u_short *)((int)vumem + ((off)&0x1fff))
420 	/*
421 	 * Check each unibus mass storage controller.
422 	 * For each one which is potentially on this uba,
423 	 * see if it is really there, and if it is record it and
424 	 * then go looking for slaves.
425 	 */
426 	for (um = ubminit; udp = um->um_driver; um++) {
427 		if (um->um_ubanum != numuba && um->um_ubanum != '?')
428 			continue;
429 		addr = (u_short)um->um_addr;
430 		reg = ubaddr(addr);
431 		if (badaddr((caddr_t)reg, 2))
432 			continue;
433 #if VAX780
434 		if (haveubasr && vubp->uba_sr) {
435 			vubp->uba_sr = vubp->uba_sr;
436 			continue;
437 		}
438 #endif
439 		cvec = 0x200;
440 		i = (*udp->ud_probe)(reg);
441 #if VAX780
442 		if (haveubasr && vubp->uba_sr) {
443 			vubp->uba_sr = vubp->uba_sr;
444 			continue;
445 		}
446 #endif
447 		if (i == 0)
448 			continue;
449 		printf("%s%d at uba%d csr %o ",
450 		    udp->ud_mname, um->um_ctlr, numuba, addr);
451 		if (cvec == 0) {
452 			printf("zero vector\n");
453 			continue;
454 		}
455 		if (cvec == 0x200) {
456 			printf("didn't interrupt\n");
457 			continue;
458 		}
459 		printf("vec %o, ipl %x\n", cvec, br);
460 		um->um_alive = 1;
461 		um->um_ubanum = numuba;
462 		um->um_hd = &uba_hd[numuba];
463 		um->um_addr = (caddr_t)reg;
464 		udp->ud_minfo[um->um_ctlr] = um;
465 		for (ivec = um->um_intr; *ivec; ivec++) {
466 			um->um_hd->uh_vec[cvec/4] =
467 			    scbentry(*ivec, SCB_ISTACK);
468 			cvec += 4;
469 		}
470 		for (ui = ubdinit; ui->ui_driver; ui++) {
471 			if (ui->ui_driver != udp || ui->ui_alive ||
472 			    ui->ui_ctlr != um->um_ctlr && ui->ui_ctlr != '?' ||
473 			    ui->ui_ubanum != numuba && ui->ui_ubanum != '?')
474 				continue;
475 			if ((*udp->ud_slave)(ui, reg)) {
476 				ui->ui_alive = 1;
477 				ui->ui_ctlr = um->um_ctlr;
478 				ui->ui_ubanum = numuba;
479 				ui->ui_hd = &uba_hd[numuba];
480 				ui->ui_addr = (caddr_t)reg;
481 				ui->ui_physaddr = pumem + (addr&0x1fff);
482 				if (ui->ui_dk && dkn < DK_NDRIVE)
483 					ui->ui_dk = dkn++;
484 				else
485 					ui->ui_dk = -1;
486 				ui->ui_mi = um;
487 				/* ui_type comes from driver */
488 				udp->ud_dinfo[ui->ui_unit] = ui;
489 				printf("%s%d at %s%d slave %d\n",
490 				    udp->ud_dname, ui->ui_unit,
491 				    udp->ud_mname, um->um_ctlr, ui->ui_slave);
492 				(*udp->ud_attach)(ui);
493 			}
494 		}
495 	}
496 	/*
497 	 * Now look for non-mass storage peripherals.
498 	 */
499 	for (ui = ubdinit; udp = ui->ui_driver; ui++) {
500 		if (ui->ui_ubanum != numuba && ui->ui_ubanum != '?' ||
501 		    ui->ui_alive || ui->ui_slave != -1)
502 			continue;
503 		addr = (u_short)ui->ui_addr;
504 		reg = ubaddr(addr);
505 		if (badaddr((caddr_t)reg, 2))
506 			continue;
507 #if VAX780
508 		if (haveubasr && vubp->uba_sr) {
509 			vubp->uba_sr = vubp->uba_sr;
510 			continue;
511 		}
512 #endif
513 		cvec = 0x200;
514 		i = (*udp->ud_probe)(reg);
515 #if VAX780
516 		if (haveubasr && vubp->uba_sr) {
517 			vubp->uba_sr = vubp->uba_sr;
518 			continue;
519 		}
520 #endif
521 		if (i == 0)
522 			continue;
523 		printf("%s%d at uba%d csr %o ",
524 		    ui->ui_driver->ud_dname, ui->ui_unit, numuba, addr);
525 		if (cvec == 0) {
526 			printf("zero vector\n");
527 			continue;
528 		}
529 		if (cvec == 0x200) {
530 			printf("didn't interrupt\n");
531 			continue;
532 		}
533 		printf("vec %o, ipl %x\n", cvec, br);
534 		ui->ui_hd = &uba_hd[numuba];
535 		for (ivec = ui->ui_intr; *ivec; ivec++) {
536 			ui->ui_hd->uh_vec[cvec/4] =
537 			    scbentry(*ivec, SCB_ISTACK);
538 			cvec += 4;
539 		}
540 		ui->ui_alive = 1;
541 		ui->ui_ubanum = numuba;
542 		ui->ui_addr = (caddr_t)reg;
543 		ui->ui_physaddr = pumem + (addr&0x1fff);
544 		ui->ui_dk = -1;
545 		/* ui_type comes from driver */
546 		udp->ud_dinfo[ui->ui_unit] = ui;
547 		(*udp->ud_attach)(ui);
548 	}
549 }
550 
551 setscbnex(fn)
552 	int (*fn)();
553 {
554 	register struct scb *scbp = &scb;
555 
556 	scbp->scb_ipl14[nexnum] = scbp->scb_ipl15[nexnum] =
557 	    scbp->scb_ipl16[nexnum] = scbp->scb_ipl17[nexnum] =
558 		scbentry(fn, SCB_ISTACK);
559 }
560 
561 /*
562  * Make a nexus accessible at physical address phys
563  * by mapping kernel ptes starting at pte.
564  *
565  * WE LEAVE ALL NEXI MAPPED; THIS IS PERHAPS UNWISE
566  * SINCE MISSING NEXI DONT RESPOND.  BUT THEN AGAIN
567  * PRESENT NEXI DONT RESPOND TO ALL OF THEIR ADDRESS SPACE.
568  */
569 nxaccess(physa, pte)
570 	struct nexus *physa;
571 	register struct pte *pte;
572 {
573 	register int i = btop(sizeof (struct nexus));
574 	register unsigned v = btop(physa);
575 
576 	do
577 		*(int *)pte++ = PG_V|PG_KW|v++;
578 	while (--i > 0);
579 	mtpr(TBIA, 0);
580 }
581