xref: /original-bsd/sys/luna68k/luna68k/autoconf.c (revision 044d1bee)
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.6 (Berkeley) 01/13/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 	default:
443 		break;
444 	}
445 	return(found);
446 }
447 
448 /*
449  * Scan the IO space looking for devices.
450  */
451 
452 #define setup_hw(hw, addr, sc, type, id) \
453 	(hw)->hw_pa   = addr; \
454 	(hw)->hw_kva  = addr; \
455 	(hw)->hw_id   = id; \
456 	(hw)->hw_type = type; \
457 	(hw)->hw_sc   = sc
458 
459 find_devs()
460 {
461 	register struct hp_hw *hw = sc_table;
462 
463 	setup_hw(hw, (char *) 0x51000000, 0x5, D_SIO,      0x5);
464 	hw->hw_secid = 0; hw++;
465 
466 	setup_hw(hw, (char *) 0xe1000000, 0xe, C_SCSI,     0xe);
467 	hw++;
468 
469 	if (!badaddr((caddr_t) 0xf1000000)) {
470 		setup_hw(hw, (char *) 0xf1000000, 0xf, D_LAN,      0xf);
471 		hw++;
472 	}
473 }
474 
475 /*
476  * Configure swap space and related parameters.
477  */
478 swapconf()
479 {
480 	register struct swdevt *swp;
481 	register int nblks;
482 
483 	for (swp = swdevt; swp->sw_dev; swp++)
484 		if (bdevsw[major(swp->sw_dev)].d_psize) {
485 			nblks =
486 			  (*bdevsw[major(swp->sw_dev)].d_psize)(swp->sw_dev);
487 			if (nblks != -1 &&
488 			    (swp->sw_nblks == 0 || swp->sw_nblks > nblks))
489 				swp->sw_nblks = nblks;
490 		}
491 	dumpconf();
492 }
493 
494 #define	DOSWAP			/* Change swdevt and dumpdev too */
495 u_long	bootdev;		/* should be dev_t, but not until 32 bits */
496 
497 static	char devname[][2] = {
498 	0,0,		/* 0 = ct */
499 	0,0,		/* 1 = xx */
500 	'r','d',	/* 2 = rd */
501 	0,0,		/* 3 = sw */
502 	's','d',	/* 4 = rd */
503 };
504 
505 #define	PARTITIONMASK	0x7
506 #define	PARTITIONSHIFT	3
507 
508 /*
509  * Attempt to find the device from which we were booted.
510  * If we can do so, and not instructed not to do so,
511  * change rootdev to correspond to the load device.
512  */
513 setroot()
514 {
515 	register struct hp_ctlr *hc;
516 	register struct hp_device *hd;
517 	int  majdev, mindev, unit, part, controller, adaptor;
518 	dev_t temp, orootdev;
519 	struct swdevt *swp;
520 
521 	if (boothowto & RB_DFLTROOT ||
522 	    (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC) {
523 		printf("Wrong B_DEVMAGIC\n");
524 		return;
525 	}
526 	majdev = B_TYPE(bootdev);
527 	if (majdev > sizeof(devname) / sizeof(devname[0])) {
528 		printf("Wrong Major Number: %d", majdev);
529 		return;
530 	}
531 	adaptor = B_ADAPTOR(bootdev);
532 	controller = B_CONTROLLER(bootdev);
533 	part = B_PARTITION(bootdev);
534 	unit = B_UNIT(bootdev);
535 	/*
536 	 * First, find the controller type which supports this device.
537 	 */
538 	for (hd = hp_dinit; hd->hp_driver; hd++)
539 		if (hd->hp_driver->d_name[0] == devname[majdev][0] &&
540 		    hd->hp_driver->d_name[1] == devname[majdev][1])
541 			break;
542 	if (hd->hp_driver == 0) {
543 		printf("Device type mismatch: %c%c\n",
544 		       devname[majdev][0], devname[majdev][1]);
545 		return;
546 	}
547 	/*
548 	 * Next, find the "controller" (bus adaptor) of that type
549 	 * corresponding to the adaptor number.
550 	 */
551 	for (hc = hp_cinit; hc->hp_driver; hc++)
552 		if (hc->hp_alive && hc->hp_unit == adaptor &&
553 		    hc->hp_driver == hd->hp_cdriver)
554 			break;
555 	if (hc->hp_driver == 0) {
556 		printf("Controller is not available\n");
557 		return;
558 	}
559 	/*
560 	 * Finally, find the "device" (controller or slave) in question
561 	 * attached to that "controller".
562 	 */
563 	for (hd = hp_dinit; hd->hp_driver; hd++)
564 		if (hd->hp_alive && hd->hp_slave == controller &&
565 		    hd->hp_cdriver == hc->hp_driver &&
566 		    hd->hp_ctlr == hc->hp_unit)
567 			break;
568 	if (hd->hp_driver == 0) {
569 		printf("Device not found\n");
570 		return;
571 	}
572 
573 	mindev = hd->hp_unit;
574 	/*
575 	 * Form a new rootdev
576 	 */
577 	mindev = (mindev << PARTITIONSHIFT) + part;
578 	orootdev = rootdev;
579 	rootdev = makedev(majdev, mindev);
580 	/*
581 	 * If the original rootdev is the same as the one
582 	 * just calculated, don't need to adjust the swap configuration.
583 	 */
584 	if (rootdev == orootdev)
585 		return;
586 
587 	printf("Changing root device to %c%c%d%c\n",
588 		devname[majdev][0], devname[majdev][1],
589 		mindev >> PARTITIONSHIFT, part + 'a');
590 
591 #ifdef DOSWAP
592 	mindev &= ~PARTITIONMASK;
593 	for (swp = swdevt; swp->sw_dev; swp++) {
594 		if (majdev == major(swp->sw_dev) &&
595 		    mindev == (minor(swp->sw_dev) & ~PARTITIONMASK)) {
596 			temp = swdevt[0].sw_dev;
597 			swdevt[0].sw_dev = swp->sw_dev;
598 			swp->sw_dev = temp;
599 			break;
600 		}
601 	}
602 	if (swp->sw_dev == 0)
603 		return;
604 
605 	/*
606 	 * If dumpdev was the same as the old primary swap
607 	 * device, move it to the new primary swap device.
608 	 */
609 	if (temp == dumpdev)
610 		dumpdev = swdevt[0].sw_dev;
611 #endif
612 }
613 
614 showroot()
615 {
616 	register int majdev, mindev;
617 	register struct swdevt *swp;
618 
619 	majdev = major(rootdev);
620 	mindev = minor(rootdev);
621 	printf("root on %c%c%d%c  ",
622 		devname[majdev][0], devname[majdev][1],
623 		mindev >> PARTITIONSHIFT, (mindev & PARTITIONMASK) + 'a');
624 
625 	swp = swdevt;
626 	majdev = major(swp->sw_dev);
627 	mindev = minor(swp->sw_dev);
628 	printf("swap on %c%c%d%c ",
629 		devname[majdev][0], devname[majdev][1],
630 		mindev >> PARTITIONSHIFT, (mindev & PARTITIONMASK) + 'a');
631 
632 	swp++;
633 	for (; swp->sw_dev; swp++) {
634 		majdev = major(swp->sw_dev);
635 		mindev = minor(swp->sw_dev);
636 		printf("and %c%c%d%c ",
637 		       devname[majdev][0], devname[majdev][1],
638 		       mindev >> PARTITIONSHIFT, (mindev & PARTITIONMASK) + 'a');
639 	}
640 
641 	majdev = major(dumpdev);
642 	mindev = minor(dumpdev);
643 	printf(" dump on %c%c%d%c\n",
644 		devname[majdev][0], devname[majdev][1],
645 		mindev >> PARTITIONSHIFT, (mindev & PARTITIONMASK) + 'a');
646 }
647 strcmp(s1, s2)
648 	register char *s1, *s2;
649 {
650 	while (*s1 == *s2++)
651 		if (*s1++=='\0')
652 			return (0);
653 	return (*s1 - *--s2);
654 }
655 
656 strncmp(s1, s2, n)
657 	register char *s1, *s2;
658 	register unsigned int n;
659 {
660 
661 	if (n == 0)
662 		return (0);
663 	do {
664 		if (*s1 != *s2++)
665 			return (*(unsigned char *)s1 - *(unsigned char *)--s2);
666 		if (*s1++ == 0)
667 			break;
668 	} while (--n != 0);
669 	return (0);
670 }
671