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