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