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