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