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