xref: /original-bsd/sys/luna68k/luna68k/autoconf.c (revision 8c7fbc72)
1 /*
2  * Copyright (c) 1988 University of Utah.
3  * Copyright (c) 1992 OMRON Corporation.
4  * Copyright (c) 1982, 1986, 1990, 1992 The Regents of the University of California.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * the Systems Programming Group of the University of Utah Computer
9  * Science Department.
10  *
11  * %sccs.include.redist.c%
12  *
13  * from:hp300/hp300/autoconf.c	7.9 (Berkeley) 12/27/92
14  *
15  *	@(#)autoconf.c	7.8 (Berkeley) 05/02/93
16  */
17 
18 /*
19  * autoconf.c --  for auto configration
20  * remade by A.Fujita, MAR-24-1992
21  */
22 
23 
24 /*
25  * Setup the system to run on the current machine.
26  *
27  * Configure() is called at boot time.  Available
28  * devices are determined (from possibilities mentioned in ioconf.c),
29  * and the drivers are initialized.
30  */
31 
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/dkstat.h>
35 #include <sys/conf.h>
36 #include <sys/reboot.h>
37 
38 #include <machine/cpu.h>
39 #include <luna68k/dev/device.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	dkn;		    /* number of iostat dk numbers assigned so far */
48 struct	hp_hw sc_table[MAXCTLRS];
49 
50 #ifdef DEBUG
51 int	acdebug = 0;
52 #endif
53 
54 /*
55  * Determine mass storage and memory configuration for a machine.
56  */
57 configure()
58 {
59 	register struct hp_hw *hw;
60 	int found;
61 
62 	/*
63 	 * Look over each hardware device actually found and attempt
64 	 * to match it with an ioconf.c table entry.
65 	 */
66 	for (hw = sc_table; hw->hw_type; hw++) {
67 		if (HW_ISCTLR(hw))
68 			found = find_controller(hw);
69 		else
70 			found = find_device(hw);
71 #ifdef DEBUG
72 		if (!found) {
73 			printf("unconfigured card id %x ", hw->hw_id);
74 			printf("at 0x%x\n", hw->hw_pa);
75 		}
76 #endif
77 	}
78 
79 #if GENERIC
80 	if ((boothowto & RB_ASKNAME) == 0)
81 		setroot();
82 	setconf();
83 #else
84 	setroot();
85 #endif
86 	showroot();
87 	swapconf();
88 	cold = 0;
89 }
90 
91 #define dr_type(d, s)	\
92 	(strcmp((d)->d_name, (s)) == 0)
93 
94 #define same_hw_ctlr(hw, hc) \
95 	 HW_ISSCSI(hw) && dr_type((hc)->hp_driver, "sc")
96 
97 find_controller(hw)
98 	register struct hp_hw *hw;
99 {
100 	register struct hp_ctlr *hc;
101 	struct hp_ctlr *match_c;
102 	caddr_t oaddr;
103 	int sc;
104 
105 #ifdef DEBUG
106 	if (acdebug)
107 		printf("find_controller: hw: id%x at sc%d (%x), type %x...",
108 		       hw->hw_id, hw->hw_sc, hw->hw_kva, hw->hw_type);
109 #endif
110 	sc = hw->hw_sc;
111 	match_c = NULL;
112 	for (hc = hp_cinit; hc->hp_driver; hc++) {
113 		if (hc->hp_alive)
114 			continue;
115 		/*
116 		 * Make sure we are looking at the right
117 		 * controller type.
118 		 */
119 		if (!same_hw_ctlr(hw, hc))
120 			continue;
121 		/*
122 		 * Exact match; all done
123 		 */
124 		if ((int)hc->hp_addr == sc) {
125 			match_c = hc;
126 			break;
127 		}
128 		/*
129 		 * Wildcard; possible match so remember first instance
130 		 * but continue looking for exact match.
131 		 */
132 		if (hc->hp_addr == NULL && match_c == NULL)
133 			match_c = hc;
134 	}
135 #ifdef DEBUG
136 	if (acdebug) {
137 		if (match_c)
138 			printf("found %s%d\n",
139 			       match_c->hp_driver->d_name,
140 			       match_c->hp_unit);
141 		else
142 			printf("not found\n");
143 	}
144 #endif
145 	/*
146 	 * Didn't find an ioconf entry for this piece of hardware,
147 	 * just ignore it.
148 	 */
149 	if (match_c == NULL)
150 		return(0);
151 	/*
152 	 * Found a match, attempt to initialize and configure all attached
153 	 * slaves.  Note, we can still fail if HW won't initialize.
154 	 */
155 	hc = match_c;
156 	oaddr = hc->hp_addr;
157 	hc->hp_addr = hw->hw_kva;
158 	if ((*hc->hp_driver->d_init)(hc)) {
159 		hc->hp_alive = 1;
160 		printf("%s%d", hc->hp_driver->d_name, hc->hp_unit);
161 		printf(" at 0x%x,", hw->hw_pa);
162 		printf(" ipl %d", hc->hp_ipl);
163 		if (hc->hp_flags)
164 			printf(" flags 0x%x", hc->hp_flags);
165 		printf("\n");
166 		find_slaves(hc);
167 	} else
168 		hc->hp_addr = oaddr;
169 	return(1);
170 }
171 
172 find_device(hw)
173 	register struct hp_hw *hw;
174 {
175 	register struct hp_device *hd;
176 	struct hp_device *match_d;
177 	caddr_t oaddr;
178 	int sc;
179 
180 #ifdef DEBUG
181 	if (acdebug)
182 		printf("find_device: hw: id%x at sc%d (%x), type %x...",
183 		       hw->hw_id, hw->hw_sc, hw->hw_kva, hw->hw_type);
184 #endif
185 	match_d = NULL;
186 	for (hd = hp_dinit; hd->hp_driver; hd++) {
187 		if (hd->hp_alive)
188 			continue;
189 		/* Must not be a slave */
190 		if (hd->hp_cdriver)
191 			continue;
192 		sc = (int) hd->hp_addr;
193 		/*
194 		 * Exact match; all done.
195 		 */
196 		if (sc > 0 && sc == hw->hw_sc) {
197 			match_d = hd;
198 			break;
199 		}
200 		/*
201 		 * Wildcard; possible match so remember first instance
202 		 * but continue looking for exact match.
203 		 */
204 		if (sc == 0 && same_hw_device(hw, hd) && match_d == NULL)
205 			match_d = hd;
206 	}
207 #ifdef DEBUG
208 	if (acdebug) {
209 		if (match_d)
210 			printf("found %s%d\n",
211 			       match_d->hp_driver->d_name,
212 			       match_d->hp_unit);
213 		else
214 			printf("not found\n");
215 	}
216 #endif
217 	/*
218 	 * Didn't find an ioconf entry for this piece
219 	 * of hardware, just ignore it.
220 	 */
221 	if (match_d == NULL)
222 		return(0);
223 	/*
224 	 * Found a match, attempt to initialize.
225 	 * Note, we can still fail if HW won't initialize.
226 	 */
227 	hd = match_d;
228 	oaddr = hd->hp_addr;
229 	hd->hp_addr = hw->hw_kva;
230 	if ((*hd->hp_driver->d_init)(hd)) {
231 		hd->hp_alive = 1;
232 		printf("%s%d", hd->hp_driver->d_name, hd->hp_unit);
233 		printf(" at 0x%x", hw->hw_pa);
234 		if (hd->hp_ipl)
235 			printf(", ipl %d", hd->hp_ipl);
236 		if (hd->hp_flags)
237 			printf(", flags 0x%x", hd->hp_flags);
238 		printf("\n");
239 	} else
240 		hd->hp_addr = oaddr;
241 	return(1);
242 }
243 
244 /*
245  * Search each BUS controller found for slaves attached to it.
246  * The bad news is that we don't know how to uniquely identify all slaves
247  * (e.g. PPI devices on HP-IB).  The good news is that we can at least
248  * differentiate those from slaves we can identify.  At worst (a totally
249  * wildcarded entry) this will cause us to locate such a slave at the first
250  * unused position instead of where it really is.  To save grief, non-
251  * identifing devices should always be fully qualified.
252  */
253 find_slaves(hc)
254 	register struct hp_ctlr *hc;
255 {
256 	register int s;
257 	register struct hp_device *hd;
258 	struct hp_device *match_s;
259 	int maxslaves = MAXSLAVES - 1;
260 	int new_s, new_c, old_s, old_c;
261 	int rescan;
262 
263 #ifdef DEBUG
264 	if (acdebug)
265 		printf("find_busslaves: for %s%d\n",
266 		       hc->hp_driver->d_name, hc->hp_unit);
267 #endif
268 	for (s = 0; s < maxslaves; s++) {
269 		rescan = 1;
270 		match_s = NULL;
271 		for (hd = hp_dinit; hd->hp_driver; hd++) {
272 			/*
273 			 * Rule out the easy ones:
274 			 * 1. slave already assigned or not a slave
275 			 * 2. not of the proper type
276 			 * 3. controller specified but not this one
277 			 * 4. slave specified but not this one
278 			 */
279 			if (hd->hp_alive || hd->hp_cdriver == NULL)
280 				continue;
281 			if (!dr_type(hc->hp_driver, hd->hp_cdriver->d_name))
282 				continue;
283 			if (hd->hp_ctlr >= 0 && hd->hp_ctlr != hc->hp_unit)
284 				continue;
285 			if (hd->hp_slave >= 0 && hd->hp_slave != s)
286 				continue;
287 			/*
288 			 * Case 0: first possible match.
289 			 * Remember it and keep looking for better.
290 			 */
291 			if (match_s == NULL) {
292 				match_s = hd;
293 				new_c = hc->hp_unit;
294 				new_s = s;
295 				continue;
296 			}
297 			/*
298 			 * Case 1: exact match.
299 			 * All done.  Note that we do not attempt any other
300 			 * matches if this one fails.  This allows us to
301 			 * "reserve" locations for dynamic addition of
302 			 * disk/tape drives by fully qualifing the location.
303 			 */
304 			if (hd->hp_slave == s && hd->hp_ctlr == hc->hp_unit) {
305 				match_s = hd;
306 				rescan = 0;
307 				break;
308 			}
309 			/*
310 			 * Case 2: right controller, wildcarded slave.
311 			 * Remember first and keep looking for an exact match.
312 			 */
313 			if (hd->hp_ctlr == hc->hp_unit &&
314 			    match_s->hp_ctlr < 0) {
315 				match_s = hd;
316 				new_s = s;
317 				continue;
318 			}
319 			/*
320 			 * Case 3: right slave, wildcarded controller.
321 			 * Remember and keep looking for a better match.
322 			 */
323 			if (hd->hp_slave == s &&
324 			    match_s->hp_ctlr < 0 && match_s->hp_slave < 0) {
325 				match_s = hd;
326 				new_c = hc->hp_unit;
327 				continue;
328 			}
329 			/*
330 			 * OW: we had a totally wildcarded spec.
331 			 * If we got this far, we have found a possible
332 			 * match already (match_s != NULL) so there is no
333 			 * reason to remember this one.
334 			 */
335 			continue;
336 		}
337 		/*
338 		 * Found a match.  We need to set hp_ctlr/hp_slave properly
339 		 * for the init routines but we also need to remember all
340 		 * the old values in case this doesn't pan out.
341 		 */
342 		if (match_s) {
343 			hd = match_s;
344 			old_c = hd->hp_ctlr;
345 			old_s = hd->hp_slave;
346 			if (hd->hp_ctlr < 0)
347 				hd->hp_ctlr = new_c;
348 			if (hd->hp_slave < 0)
349 				hd->hp_slave = new_s;
350 #ifdef DEBUG
351 			if (acdebug)
352 				printf("looking for %s%d at slave %d...",
353 				       hd->hp_driver->d_name,
354 				       hd->hp_unit, hd->hp_slave);
355 #endif
356 
357 			if ((*hd->hp_driver->d_init)(hd)) {
358 #ifdef DEBUG
359 				if (acdebug)
360 					printf("found\n");
361 #endif
362 				printf("%s%d at %s%d, slave %d",
363 				       hd->hp_driver->d_name, hd->hp_unit,
364 				       hc->hp_driver->d_name, hd->hp_ctlr,
365 				       hd->hp_slave);
366 				if (hd->hp_flags)
367 					printf(" flags 0x%x", hd->hp_flags);
368 				printf("\n");
369 				hd->hp_alive = 1;
370 				if (hd->hp_dk && dkn < DK_NDRIVE)
371 					hd->hp_dk = dkn++;
372 				else
373 					hd->hp_dk = -1;
374 				rescan = 1;
375 			} else {
376 #ifdef DEBUG
377 				if (acdebug)
378 					printf("not found\n");
379 #endif
380 				hd->hp_ctlr = old_c;
381 				hd->hp_slave = old_s;
382 			}
383 			/*
384 			 * XXX: This should be handled better.
385 			 * Re-scan a slave.  There are two reasons to do this.
386 			 * 1. It is possible to have both a tape and disk
387 			 *    (e.g. 7946) or two disks (e.g. 9122) at the
388 			 *    same slave address.  Here we need to rescan
389 			 *    looking only at entries with a different
390 			 *    physical unit number (hp_flags).
391 			 * 2. It is possible that an init failed because the
392 			 *    slave was there but of the wrong type.  In this
393 			 *    case it may still be possible to match the slave
394 			 *    to another ioconf entry of a different type.
395 			 *    Here we need to rescan looking only at entries
396 			 *    of different types.
397 			 * In both cases we avoid looking at undesirable
398 			 * ioconf entries of the same type by setting their
399 			 * alive fields to -1.
400 			 */
401 			if (rescan) {
402 				for (hd = hp_dinit; hd->hp_driver; hd++) {
403 					if (hd->hp_alive)
404 						continue;
405 					if (match_s->hp_alive == 1) {	/* 1 */
406 						if (hd->hp_flags == match_s->hp_flags)
407 							hd->hp_alive = -1;
408 					} else {			/* 2 */
409 						if (hd->hp_driver == match_s->hp_driver)
410 							hd->hp_alive = -1;
411 					}
412 				}
413 				s--;
414 				continue;
415 			}
416 		}
417 		/*
418 		 * Reset bogon alive fields prior to attempting next slave
419 		 */
420 		for (hd = hp_dinit; hd->hp_driver; hd++)
421 			if (hd->hp_alive == -1)
422 				hd->hp_alive = 0;
423 	}
424 }
425 
426 same_hw_device(hw, hd)
427 	struct hp_hw *hw;
428 	struct hp_device *hd;
429 {
430 	int found = 0;
431 
432 	switch (hw->hw_type & ~B_MASK) {
433 	case C_SCSI:
434 		found = dr_type(hd->hp_driver, "sc");
435 		break;
436 	case D_LAN:
437 		found = dr_type(hd->hp_driver, "le");
438 		break;
439 	case D_SIO:
440 		found = dr_type(hd->hp_driver, "sio");
441 		break;
442 	case D_BMC:
443 		found = dr_type(hd->hp_driver, "bmc");
444 		break;
445 	default:
446 		break;
447 	}
448 	return(found);
449 }
450 
451 /*
452  * Scan the IO space looking for devices.
453  */
454 
455 #define setup_hw(hw, addr, sc, type, id) \
456 	(hw)->hw_pa   = addr; \
457 	(hw)->hw_kva  = addr; \
458 	(hw)->hw_id   = id; \
459 	(hw)->hw_type = type; \
460 	(hw)->hw_sc   = sc
461 
462 find_devs()
463 {
464 	register struct hp_hw *hw = sc_table;
465 
466 	setup_hw(hw, (char *) 0x51000004, 0x5, D_BMC,      0x5);
467 	hw->hw_secid = 0; hw++;
468 
469 	setup_hw(hw, (char *) 0x51000000, 0x5, D_SIO,      0x5);
470 	hw->hw_secid = 0; hw++;
471 
472 	setup_hw(hw, (char *) 0xe1000000, 0xe, C_SCSI,     0xe);
473 	hw++;
474 
475 	if (!badaddr((caddr_t) 0xf1000000)) {
476 		setup_hw(hw, (char *) 0xf1000000, 0xf, D_LAN,      0xf);
477 		hw++;
478 	}
479 }
480 
481 /*
482  * Configure swap space and related parameters.
483  */
484 swapconf()
485 {
486 	register struct swdevt *swp;
487 	register int nblks;
488 
489 	for (swp = swdevt; swp->sw_dev != NODEV; swp++)
490 		if (bdevsw[major(swp->sw_dev)].d_psize) {
491 			nblks =
492 			  (*bdevsw[major(swp->sw_dev)].d_psize)(swp->sw_dev);
493 			if (nblks != -1 &&
494 			    (swp->sw_nblks == 0 || swp->sw_nblks > nblks))
495 				swp->sw_nblks = nblks;
496 		}
497 	dumpconf();
498 }
499 
500 #define	DOSWAP			/* Change swdevt and dumpdev too */
501 u_long	bootdev;		/* should be dev_t, but not until 32 bits */
502 
503 static	char devname[][2] = {
504 	0,0,		/* 0 = ct */
505 	0,0,		/* 1 = xx */
506 	'r','d',	/* 2 = rd */
507 	0,0,		/* 3 = sw */
508 	's','d',	/* 4 = rd */
509 };
510 
511 #define	PARTITIONMASK	0x7
512 #define	PARTITIONSHIFT	3
513 
514 /*
515  * Attempt to find the device from which we were booted.
516  * If we can do so, and not instructed not to do so,
517  * change rootdev to correspond to the load device.
518  */
519 setroot()
520 {
521 	register struct hp_ctlr *hc;
522 	register struct hp_device *hd;
523 	int  majdev, mindev, unit, part, controller, adaptor;
524 	dev_t temp, orootdev;
525 	struct swdevt *swp;
526 
527 	if (boothowto & RB_DFLTROOT ||
528 	    (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC) {
529 		printf("Wrong B_DEVMAGIC\n");
530 		return;
531 	}
532 	majdev = B_TYPE(bootdev);
533 	if (majdev > sizeof(devname) / sizeof(devname[0])) {
534 		printf("Wrong Major Number: %d", majdev);
535 		return;
536 	}
537 	adaptor = B_ADAPTOR(bootdev);
538 	controller = B_CONTROLLER(bootdev);
539 	part = B_PARTITION(bootdev);
540 	unit = B_UNIT(bootdev);
541 	/*
542 	 * First, find the controller type which supports this device.
543 	 */
544 	for (hd = hp_dinit; hd->hp_driver; hd++)
545 		if (hd->hp_driver->d_name[0] == devname[majdev][0] &&
546 		    hd->hp_driver->d_name[1] == devname[majdev][1])
547 			break;
548 	if (hd->hp_driver == 0) {
549 		printf("Device type mismatch: %c%c\n",
550 		       devname[majdev][0], devname[majdev][1]);
551 		return;
552 	}
553 	/*
554 	 * Next, find the "controller" (bus adaptor) of that type
555 	 * corresponding to the adaptor number.
556 	 */
557 	for (hc = hp_cinit; hc->hp_driver; hc++)
558 		if (hc->hp_alive && hc->hp_unit == adaptor &&
559 		    hc->hp_driver == hd->hp_cdriver)
560 			break;
561 	if (hc->hp_driver == 0) {
562 		printf("Controller is not available\n");
563 		return;
564 	}
565 	/*
566 	 * Finally, find the "device" (controller or slave) in question
567 	 * attached to that "controller".
568 	 */
569 	for (hd = hp_dinit; hd->hp_driver; hd++)
570 		if (hd->hp_alive && hd->hp_slave == controller &&
571 		    hd->hp_cdriver == hc->hp_driver &&
572 		    hd->hp_ctlr == hc->hp_unit)
573 			break;
574 	if (hd->hp_driver == 0) {
575 		printf("Device not found\n");
576 		return;
577 	}
578 
579 	mindev = hd->hp_unit;
580 	/*
581 	 * Form a new rootdev
582 	 */
583 	mindev = (mindev << PARTITIONSHIFT) + part;
584 	orootdev = rootdev;
585 	rootdev = makedev(majdev, mindev);
586 	/*
587 	 * If the original rootdev is the same as the one
588 	 * just calculated, don't need to adjust the swap configuration.
589 	 */
590 	if (rootdev == orootdev)
591 		return;
592 
593 	printf("Changing root device to %c%c%d%c\n",
594 		devname[majdev][0], devname[majdev][1],
595 		mindev >> PARTITIONSHIFT, part + 'a');
596 
597 #ifdef DOSWAP
598 	mindev &= ~PARTITIONMASK;
599 	for (swp = swdevt; swp->sw_dev != NODEV; swp++) {
600 		if (majdev == major(swp->sw_dev) &&
601 		    mindev == (minor(swp->sw_dev) & ~PARTITIONMASK)) {
602 			temp = swdevt[0].sw_dev;
603 			swdevt[0].sw_dev = swp->sw_dev;
604 			swp->sw_dev = temp;
605 			break;
606 		}
607 	}
608 	if (swp->sw_dev == NODEV)
609 		return;
610 
611 	/*
612 	 * If dumpdev was the same as the old primary swap
613 	 * device, move it to the new primary swap device.
614 	 */
615 	if (temp == dumpdev)
616 		dumpdev = swdevt[0].sw_dev;
617 #endif
618 }
619 
620 showroot()
621 {
622 	register int majdev, mindev;
623 	register struct swdevt *swp;
624 
625 	majdev = major(rootdev);
626 	mindev = minor(rootdev);
627 	printf("root on %c%c%d%c  ",
628 		devname[majdev][0], devname[majdev][1],
629 		mindev >> PARTITIONSHIFT, (mindev & PARTITIONMASK) + 'a');
630 
631 	swp = swdevt;
632 	majdev = major(swp->sw_dev);
633 	mindev = minor(swp->sw_dev);
634 	printf("swap on %c%c%d%c ",
635 		devname[majdev][0], devname[majdev][1],
636 		mindev >> PARTITIONSHIFT, (mindev & PARTITIONMASK) + 'a');
637 
638 	swp++;
639 	for (; swp->sw_dev != NODEV; swp++) {
640 		majdev = major(swp->sw_dev);
641 		mindev = minor(swp->sw_dev);
642 		printf("and %c%c%d%c ",
643 		       devname[majdev][0], devname[majdev][1],
644 		       mindev >> PARTITIONSHIFT, (mindev & PARTITIONMASK) + 'a');
645 	}
646 
647 	majdev = major(dumpdev);
648 	mindev = minor(dumpdev);
649 	printf(" dump on %c%c%d%c\n",
650 		devname[majdev][0], devname[majdev][1],
651 		mindev >> PARTITIONSHIFT, (mindev & PARTITIONMASK) + 'a');
652 }
653 strcmp(s1, s2)
654 	register char *s1, *s2;
655 {
656 	while (*s1 == *s2++)
657 		if (*s1++=='\0')
658 			return (0);
659 	return (*s1 - *--s2);
660 }
661 
662 strncmp(s1, s2, n)
663 	register char *s1, *s2;
664 	register unsigned int n;
665 {
666 
667 	if (n == 0)
668 		return (0);
669 	do {
670 		if (*s1 != *s2++)
671 			return (*(unsigned char *)s1 - *(unsigned char *)--s2);
672 		if (*s1++ == 0)
673 			break;
674 	} while (--n != 0);
675 	return (0);
676 }
677