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