xref: /original-bsd/sys/luna68k/luna68k/autoconf.c (revision 95ecee29)
1 /*
2  * Copyright (c) 1988 University of Utah.
3  * Copyright (c) 1992 OMRON Corporation.
4  * Copyright (c) 1982, 1986, 1990, 1992, 1993
5  *	The Regents of the University of California.  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.11 (Berkeley) 5/9/93
14  *
15  *	@(#)autoconf.c	8.2 (Berkeley) 12/06/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 #include "bmc.h"
467 #if NBMC > 0
468 	setup_hw(hw, (char *) 0x51000004, 0x5, D_BMC,      0x5);
469 	hw->hw_secid = 0; hw++;
470 #endif
471 	setup_hw(hw, (char *) 0x51000000, 0x5, D_SIO,      0x5);
472 	hw->hw_secid = 0; hw++;
473 #if NBMC == 0
474 #if NSIO > 1
475 	setup_hw(hw, (char *) 0x51000004, 0x5, D_SIO,      0x5);
476 	hw->hw_secid = 0; hw++;
477 #endif
478 #endif
479 
480 	setup_hw(hw, (char *) 0xe1000000, 0xe, C_SCSI,     0xe);
481 	hw++;
482 
483 	if (!badaddr((caddr_t) 0xf1000000)) {
484 		setup_hw(hw, (char *) 0xf1000000, 0xf, D_LAN,      0xf);
485 		hw++;
486 	}
487 
488 #if defined(LUNA2) && defined(notyet)
489 	if (machineid == LUNA_II) {
490 		setup_hw(hw, (char *) 0xe1000040, 0xe, C_SCSI,     0xe);
491 		hw++;
492 
493 		if (!badaddr((caddr_t) 0xf1000008)) {
494 			setup_hw(hw, (char *) 0xf1000008, 0xf, D_LAN,      0xf);
495 			hw++;
496 		}
497 	}
498 #endif
499 }
500 
501 /*
502  * Configure swap space and related parameters.
503  */
504 swapconf()
505 {
506 	register struct swdevt *swp;
507 	register int nblks;
508 
509 	for (swp = swdevt; swp->sw_dev != NODEV; swp++)
510 		if (bdevsw[major(swp->sw_dev)].d_psize) {
511 			nblks =
512 			  (*bdevsw[major(swp->sw_dev)].d_psize)(swp->sw_dev);
513 			if (nblks != -1 &&
514 			    (swp->sw_nblks == 0 || swp->sw_nblks > nblks))
515 				swp->sw_nblks = nblks;
516 		}
517 	dumpconf();
518 }
519 
520 #define	DOSWAP			/* Change swdevt and dumpdev too */
521 u_long	bootdev;		/* should be dev_t, but not until 32 bits */
522 
523 static	char devname[][2] = {
524 	0,0,		/* 0 = ct */
525 	0,0,		/* 1 = xx */
526 	'r','d',	/* 2 = rd */
527 	0,0,		/* 3 = sw */
528 	's','d',	/* 4 = rd */
529 };
530 
531 #define	PARTITIONMASK	0x7
532 #define	PARTITIONSHIFT	3
533 
534 /*
535  * Attempt to find the device from which we were booted.
536  * If we can do so, and not instructed not to do so,
537  * change rootdev to correspond to the load device.
538  */
539 setroot()
540 {
541 	register struct hp_ctlr *hc;
542 	register struct hp_device *hd;
543 	int  majdev, mindev, unit, part, controller, adaptor;
544 	dev_t temp, orootdev;
545 	struct swdevt *swp;
546 
547 	if (boothowto & RB_DFLTROOT ||
548 	    (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC) {
549 		printf("Wrong B_DEVMAGIC\n");
550 		return;
551 	}
552 	majdev = B_TYPE(bootdev);
553 	if (majdev > sizeof(devname) / sizeof(devname[0])) {
554 		printf("Wrong Major Number: %d", majdev);
555 		return;
556 	}
557 	adaptor = B_ADAPTOR(bootdev);
558 	controller = B_CONTROLLER(bootdev);
559 	part = B_PARTITION(bootdev);
560 	unit = B_UNIT(bootdev);
561 	/*
562 	 * First, find the controller type which supports this device.
563 	 */
564 	for (hd = hp_dinit; hd->hp_driver; hd++)
565 		if (hd->hp_driver->d_name[0] == devname[majdev][0] &&
566 		    hd->hp_driver->d_name[1] == devname[majdev][1])
567 			break;
568 	if (hd->hp_driver == 0) {
569 		printf("Device type mismatch: %c%c\n",
570 		       devname[majdev][0], devname[majdev][1]);
571 		return;
572 	}
573 	/*
574 	 * Next, find the "controller" (bus adaptor) of that type
575 	 * corresponding to the adaptor number.
576 	 */
577 	for (hc = hp_cinit; hc->hp_driver; hc++)
578 		if (hc->hp_alive && hc->hp_unit == adaptor &&
579 		    hc->hp_driver == hd->hp_cdriver)
580 			break;
581 	if (hc->hp_driver == 0) {
582 		printf("Controller is not available\n");
583 		return;
584 	}
585 	/*
586 	 * Finally, find the "device" (controller or slave) in question
587 	 * attached to that "controller".
588 	 */
589 	for (hd = hp_dinit; hd->hp_driver; hd++)
590 		if (hd->hp_alive && hd->hp_slave == controller &&
591 		    hd->hp_cdriver == hc->hp_driver &&
592 		    hd->hp_ctlr == hc->hp_unit)
593 			break;
594 	if (hd->hp_driver == 0) {
595 		printf("Device not found\n");
596 		return;
597 	}
598 
599 	mindev = hd->hp_unit;
600 	/*
601 	 * Form a new rootdev
602 	 */
603 	mindev = (mindev << PARTITIONSHIFT) + part;
604 	orootdev = rootdev;
605 	rootdev = makedev(majdev, mindev);
606 	/*
607 	 * If the original rootdev is the same as the one
608 	 * just calculated, don't need to adjust the swap configuration.
609 	 */
610 	if (rootdev == orootdev)
611 		return;
612 
613 	printf("Changing root device to %c%c%d%c\n",
614 		devname[majdev][0], devname[majdev][1],
615 		mindev >> PARTITIONSHIFT, part + 'a');
616 
617 #ifdef DOSWAP
618 	mindev &= ~PARTITIONMASK;
619 	for (swp = swdevt; swp->sw_dev != NODEV; swp++) {
620 		if (majdev == major(swp->sw_dev) &&
621 		    mindev == (minor(swp->sw_dev) & ~PARTITIONMASK)) {
622 			temp = swdevt[0].sw_dev;
623 			swdevt[0].sw_dev = swp->sw_dev;
624 			swp->sw_dev = temp;
625 			break;
626 		}
627 	}
628 	if (swp->sw_dev == NODEV)
629 		return;
630 
631 	/*
632 	 * If dumpdev was the same as the old primary swap
633 	 * device, move it to the new primary swap device.
634 	 */
635 	if (temp == dumpdev)
636 		dumpdev = swdevt[0].sw_dev;
637 #endif
638 }
639 
640 showroot()
641 {
642 	register int majdev, mindev;
643 	register struct swdevt *swp;
644 
645 	majdev = major(rootdev);
646 	mindev = minor(rootdev);
647 	printf("root on %c%c%d%c  ",
648 		devname[majdev][0], devname[majdev][1],
649 		mindev >> PARTITIONSHIFT, (mindev & PARTITIONMASK) + 'a');
650 
651 	swp = swdevt;
652 	majdev = major(swp->sw_dev);
653 	mindev = minor(swp->sw_dev);
654 	printf("swap on %c%c%d%c ",
655 		devname[majdev][0], devname[majdev][1],
656 		mindev >> PARTITIONSHIFT, (mindev & PARTITIONMASK) + 'a');
657 
658 	swp++;
659 	for (; swp->sw_dev != NODEV; swp++) {
660 		majdev = major(swp->sw_dev);
661 		mindev = minor(swp->sw_dev);
662 		printf("and %c%c%d%c ",
663 		       devname[majdev][0], devname[majdev][1],
664 		       mindev >> PARTITIONSHIFT, (mindev & PARTITIONMASK) + 'a');
665 	}
666 
667 	majdev = major(dumpdev);
668 	mindev = minor(dumpdev);
669 	printf(" dump on %c%c%d%c\n",
670 		devname[majdev][0], devname[majdev][1],
671 		mindev >> PARTITIONSHIFT, (mindev & PARTITIONMASK) + 'a');
672 }
673 strcmp(s1, s2)
674 	register char *s1, *s2;
675 {
676 	while (*s1 == *s2++)
677 		if (*s1++=='\0')
678 			return (0);
679 	return (*s1 - *--s2);
680 }
681 
682 strncmp(s1, s2, n)
683 	register char *s1, *s2;
684 	register unsigned int n;
685 {
686 
687 	if (n == 0)
688 		return (0);
689 	do {
690 		if (*s1 != *s2++)
691 			return (*(unsigned char *)s1 - *(unsigned char *)--s2);
692 		if (*s1++ == 0)
693 			break;
694 	} while (--n != 0);
695 	return (0);
696 }
697