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 */
configure()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
find_controller(hw)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
find_device(hw)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 */
find_slaves(hc)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
find_devs()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 */
swapconf()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 */
setroot()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
showroot()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 }
strcmp(s1,s2)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
strncmp(s1,s2,n)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