1 /* $NetBSD: autoconf.c,v 1.61 2002/10/02 05:15:56 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 1996, 1997, 2002 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * Copyright (c) 1988 University of Utah. 41 * Copyright (c) 1982, 1986, 1990, 1993 42 * The Regents of the University of California. All rights reserved. 43 * 44 * This code is derived from software contributed to Berkeley by 45 * the Systems Programming Group of the University of Utah Computer 46 * Science Department. 47 * 48 * Copyright (c) 1992, 1993 49 * The Regents of the University of California. All rights reserved. 50 * 51 * This software was developed by the Computer Systems Engineering group 52 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 53 * contributed to Berkeley. 54 * 55 * All advertising materials mentioning features or use of this software 56 * must display the following acknowledgement: 57 * This product includes software developed by the University of 58 * California, Lawrence Berkeley Laboratory. 59 * 60 * Redistribution and use in source and binary forms, with or without 61 * modification, are permitted provided that the following conditions 62 * are met: 63 * 1. Redistributions of source code must retain the above copyright 64 * notice, this list of conditions and the following disclaimer. 65 * 2. Redistributions in binary form must reproduce the above copyright 66 * notice, this list of conditions and the following disclaimer in the 67 * documentation and/or other materials provided with the distribution. 68 * 3. All advertising materials mentioning features or use of this software 69 * must display the following acknowledgement: 70 * This product includes software developed by the University of 71 * California, Berkeley and its contributors. 72 * 4. Neither the name of the University nor the names of its contributors 73 * may be used to endorse or promote products derived from this software 74 * without specific prior written permission. 75 * 76 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 77 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 78 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 79 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 80 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 81 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 82 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 83 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 84 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 85 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 86 * SUCH DAMAGE. 87 * 88 * from: Utah $Hdr: autoconf.c 1.36 92/12/20$ 89 * 90 * @(#)autoconf.c 8.2 (Berkeley) 1/12/94 91 */ 92 93 /* 94 * Setup the system to run on the current machine. 95 * 96 * Configure() is called at boot time. Available 97 * devices are determined (from possibilities mentioned in ioconf.c), 98 * and the drivers are initialized. 99 */ 100 101 #include <sys/cdefs.h> 102 __KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.61 2002/10/02 05:15:56 thorpej Exp $"); 103 104 #include "hil.h" 105 #include "dvbox.h" 106 #include "gbox.h" 107 #include "hyper.h" 108 #include "rbox.h" 109 #include "rbox.h" 110 #include "topcat.h" 111 #include "dca.h" 112 #include "dcm.h" 113 #include "apci.h" 114 #include "ite.h" 115 116 #include <sys/param.h> 117 #include <sys/systm.h> 118 #include <sys/buf.h> 119 #include <sys/conf.h> 120 #include <sys/device.h> 121 #include <sys/device.h> 122 #include <sys/disklabel.h> 123 #include <sys/malloc.h> 124 #include <sys/extent.h> 125 #include <sys/mount.h> 126 #include <sys/queue.h> 127 #include <sys/reboot.h> 128 #include <sys/tty.h> 129 130 #include <uvm/uvm_extern.h> 131 132 #include <dev/cons.h> 133 134 #include <machine/autoconf.h> 135 #include <machine/vmparam.h> 136 #include <machine/cpu.h> 137 #include <machine/hp300spu.h> 138 #include <machine/intr.h> 139 #include <machine/pte.h> 140 141 #include <hp300/dev/dioreg.h> 142 #include <hp300/dev/diovar.h> 143 #include <hp300/dev/diodevs.h> 144 145 #include <hp300/dev/dmavar.h> 146 #include <hp300/dev/grfreg.h> 147 #include <hp300/dev/hilreg.h> 148 #include <hp300/dev/hilioctl.h> 149 #include <hp300/dev/hilvar.h> 150 151 #include <hp300/dev/hpibvar.h> 152 #include <hp300/dev/scsivar.h> 153 154 155 /* should go away with a cleanup */ 156 extern int dcacnattach(bus_space_tag_t, bus_addr_t, int); 157 extern int dcmcnattach(bus_space_tag_t, bus_addr_t, int); 158 extern int apcicnattach(bus_space_tag_t, bus_addr_t, int); 159 extern int dvboxcnattach(bus_space_tag_t, bus_addr_t, int); 160 extern int gboxcnattach(bus_space_tag_t, bus_addr_t, int); 161 extern int rboxcnattach(bus_space_tag_t, bus_addr_t, int); 162 extern int hypercnattach(bus_space_tag_t, bus_addr_t, int); 163 extern int topcatcnattach(bus_space_tag_t, bus_addr_t, int); 164 extern int hilkbdcnattach(bus_space_tag_t, bus_addr_t); 165 extern int dnkbdcnattach(bus_space_tag_t, bus_addr_t); 166 167 int dio_scan(int (*func)(bus_space_tag_t, bus_addr_t, int)); 168 int dio_scode_probe(int, int (*func)(bus_space_tag_t, bus_addr_t, int)); 169 170 extern caddr_t internalhpib; 171 extern char *extiobase; 172 173 /* The boot device. */ 174 struct device *booted_device; 175 int booted_partition; 176 177 /* How we were booted. */ 178 u_int bootdev; 179 180 /* 181 * Extent map to manage the external I/O (DIO/DIO-II) space. We 182 * allocate storate for 8 regions in the map. extio_ex_malloc_safe 183 * will indicate that it's safe to use malloc() to dynamically allocate 184 * region descriptors in case we run out. 185 */ 186 static long extio_ex_storage[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)]; 187 struct extent *extio_ex; 188 int extio_ex_malloc_safe; 189 190 /* 191 * This information is built during the autoconfig process. 192 * A little explanation about the way this works is in order. 193 * 194 * device_register() links all devices into dev_data_list. 195 * If the device is an hpib controller, it is also linked 196 * into dev_data_list_hpib. If the device is a scsi controller, 197 * it is also linked into dev_data_list_scsi. 198 * 199 * dev_data_list_hpib and dev_data_list_scsi are sorted 200 * by select code, from lowest to highest. 201 * 202 * After autoconfiguration is complete, we need to determine 203 * which device was the boot device. The boot block assigns 204 * controller unit numbers in order of select code. Thus, 205 * providing the controller is configured in the kernel, we 206 * can determine our version of controller unit number from 207 * the sorted hpib/scsi list. 208 * 209 * At this point, we know the controller (device type 210 * encoded in bootdev tells us "scsi disk", or "hpib tape", 211 * etc.). The next step is to find the device which 212 * has the following properties: 213 * 214 * - A child of the boot controller. 215 * - Same slave as encoded in bootdev. 216 * - Same physical unit as encoded in bootdev. 217 * 218 * Later, after we've set the root device in stone, we 219 * reverse the process to re-encode bootdev so it can be 220 * passed back to the boot block. 221 */ 222 struct dev_data { 223 LIST_ENTRY(dev_data) dd_list; /* dev_data_list */ 224 LIST_ENTRY(dev_data) dd_clist; /* ctlr list */ 225 struct device *dd_dev; /* device described by this entry */ 226 int dd_scode; /* select code of device */ 227 int dd_slave; /* ...or slave */ 228 int dd_punit; /* and punit... */ 229 }; 230 typedef LIST_HEAD(, dev_data) ddlist_t; 231 ddlist_t dev_data_list; /* all dev_datas */ 232 ddlist_t dev_data_list_hpib; /* hpib controller dev_datas */ 233 ddlist_t dev_data_list_scsi; /* scsi controller dev_datas */ 234 235 void findbootdev __P((void)); 236 void findbootdev_slave __P((ddlist_t *, int, int, int)); 237 void setbootdev __P((void)); 238 239 static struct dev_data *dev_data_lookup __P((struct device *)); 240 static void dev_data_insert __P((struct dev_data *, ddlist_t *)); 241 242 int mainbusmatch __P((struct device *, struct cfdata *, void *)); 243 void mainbusattach __P((struct device *, struct device *, void *)); 244 int mainbussearch __P((struct device *, struct cfdata *, void *)); 245 246 CFATTACH_DECL(mainbus, sizeof(struct device), 247 mainbusmatch, mainbusattach, NULL, NULL); 248 249 int 250 mainbusmatch(parent, match, aux) 251 struct device *parent; 252 struct cfdata *match; 253 void *aux; 254 { 255 static int mainbus_matched = 0; 256 257 /* Allow only one instance. */ 258 if (mainbus_matched) 259 return (0); 260 261 mainbus_matched = 1; 262 return (1); 263 } 264 265 void 266 mainbusattach(parent, self, aux) 267 struct device *parent, *self; 268 void *aux; 269 { 270 271 printf("\n"); 272 273 /* Search for and attach children. */ 274 config_search(mainbussearch, self, NULL); 275 } 276 277 int 278 mainbussearch(parent, cf, aux) 279 struct device *parent; 280 struct cfdata *cf; 281 void *aux; 282 { 283 284 if (config_match(parent, cf, NULL) > 0) 285 config_attach(parent, cf, NULL, NULL); 286 return (0); 287 } 288 289 /* 290 * Determine the device configuration for the running system. 291 */ 292 void 293 cpu_configure() 294 { 295 296 /* 297 * Initialize the dev_data_lists. 298 */ 299 LIST_INIT(&dev_data_list); 300 LIST_INIT(&dev_data_list_hpib); 301 LIST_INIT(&dev_data_list_scsi); 302 303 /* Kick off autoconfiguration. */ 304 (void)splhigh(); 305 306 softintr_init(); 307 308 if (config_rootfound("mainbus", "mainbus") == NULL) 309 panic("no mainbus found"); 310 311 /* Configuration is finished, turn on interrupts. */ 312 (void)spl0(); 313 314 intr_printlevels(); 315 } 316 317 /********************************************************************** 318 * Code to find and set the boot device 319 **********************************************************************/ 320 321 void 322 cpu_rootconf() 323 { 324 struct dev_data *dd; 325 struct device *dv; 326 struct vfsops *vops; 327 328 /* 329 * Find boot device. 330 */ 331 if ((bootdev & B_MAGICMASK) != B_DEVMAGIC) { 332 printf("WARNING: boot program didn't supply boot device.\n"); 333 printf("Please update your boot program.\n"); 334 } else { 335 findbootdev(); 336 if (booted_device == NULL) { 337 printf("WARNING: can't find match for bootdev:\n"); 338 printf( 339 "type = %d, ctlr = %d, slave = %d, punit = %d, part = %d\n", 340 B_TYPE(bootdev), B_ADAPTOR(bootdev), 341 B_CONTROLLER(bootdev), B_UNIT(bootdev), 342 B_PARTITION(bootdev)); 343 bootdev = 0; /* invalidate bootdev */ 344 } else { 345 printf("boot device: %s\n", booted_device->dv_xname); 346 } 347 } 348 349 dv = booted_device; 350 351 /* 352 * If wild carded root device and wired down NFS root file system, 353 * pick the network interface device to use. 354 */ 355 if (rootspec == NULL) { 356 vops = vfs_getopsbyname("nfs"); 357 if (vops != NULL && vops->vfs_mountroot == mountroot) { 358 for (dd = dev_data_list.lh_first; 359 dd != NULL; dd = dd->dd_list.le_next) { 360 if (dd->dd_dev->dv_class == DV_IFNET) { 361 /* Got it! */ 362 dv = dd->dd_dev; 363 break; 364 } 365 } 366 if (dd == NULL) { 367 printf("no network interface for NFS root"); 368 dv = NULL; 369 } 370 } 371 } 372 373 /* 374 * If bootdev is bogus, ask the user anyhow. 375 */ 376 if (bootdev == 0) 377 boothowto |= RB_ASKNAME; 378 379 /* 380 * If we booted from tape, ask the user. 381 */ 382 if (booted_device != NULL && booted_device->dv_class == DV_TAPE) 383 boothowto |= RB_ASKNAME; 384 385 setroot(dv, booted_partition); 386 387 /* 388 * Set bootdev based on what we found as the root. 389 * This is given to the boot program when we reboot. 390 */ 391 setbootdev(); 392 393 } 394 395 /* 396 * Register a device. We're passed the device and the arguments 397 * used to attach it. This is used to find the boot device. 398 */ 399 void 400 device_register(dev, aux) 401 struct device *dev; 402 void *aux; 403 { 404 struct dev_data *dd; 405 static int seen_netdevice = 0; 406 407 /* 408 * Allocate a dev_data structure and fill it in. 409 * This means making some tests twice, but we don't 410 * care; this doesn't really have to be fast. 411 * 412 * Note that we only really care about devices that 413 * we can mount as root. 414 */ 415 416 MALLOC(dd, struct dev_data *, sizeof(struct dev_data), 417 M_DEVBUF, M_NOWAIT | M_ZERO); 418 if (dd == NULL) 419 panic("device_register: can't allocate dev_data"); 420 421 dd->dd_dev = dev; 422 423 /* 424 * BOOTROM and boot program can really only understand 425 * using the lowest select code network interface, 426 * so we ignore all but the first. 427 */ 428 if (dev->dv_class == DV_IFNET && seen_netdevice == 0) { 429 struct dio_attach_args *da = aux; 430 431 seen_netdevice = 1; 432 dd->dd_scode = da->da_scode; 433 goto linkup; 434 } 435 436 if (memcmp(dev->dv_xname, "fhpib", 5) == 0 || 437 memcmp(dev->dv_xname, "nhpib", 5) == 0 || 438 memcmp(dev->dv_xname, "oscsi", 5) == 0) { 439 struct dio_attach_args *da = aux; 440 441 dd->dd_scode = da->da_scode; 442 goto linkup; 443 } 444 445 if (memcmp(dev->dv_xname, "rd", 2) == 0) { 446 struct hpibbus_attach_args *ha = aux; 447 448 dd->dd_slave = ha->ha_slave; 449 dd->dd_punit = ha->ha_punit; 450 goto linkup; 451 } 452 453 if (memcmp(dev->dv_xname, "sd", 2) == 0) { 454 struct oscsi_attach_args *osa = aux; 455 456 dd->dd_slave = osa->osa_target; 457 dd->dd_punit = osa->osa_lun; 458 goto linkup; 459 } 460 461 /* 462 * Didn't need the dev_data. 463 */ 464 free(dd, M_DEVBUF); 465 return; 466 467 linkup: 468 LIST_INSERT_HEAD(&dev_data_list, dd, dd_list); 469 470 if (memcmp(dev->dv_xname, "fhpib", 5) == 0 || 471 memcmp(dev->dv_xname, "nhpib", 5) == 0) { 472 dev_data_insert(dd, &dev_data_list_hpib); 473 return; 474 } 475 476 if (memcmp(dev->dv_xname, "oscsi", 5) == 0) { 477 dev_data_insert(dd, &dev_data_list_scsi); 478 return; 479 } 480 } 481 482 void 483 findbootdev() 484 { 485 int type, ctlr, slave, punit, part; 486 int scsiboot, hpibboot, netboot; 487 struct dev_data *dd; 488 489 booted_device = NULL; 490 booted_partition = 0; 491 492 if ((bootdev & B_MAGICMASK) != B_DEVMAGIC) 493 return; 494 495 type = B_TYPE(bootdev); 496 ctlr = B_ADAPTOR(bootdev); 497 slave = B_CONTROLLER(bootdev); 498 punit = B_UNIT(bootdev); 499 part = B_PARTITION(bootdev); 500 501 scsiboot = (type == 4); /* sd major */ 502 hpibboot = (type == 0 || type == 2); /* ct/rd major */ 503 netboot = (type == 6); /* le - special */ 504 505 /* 506 * Check for network boot first, since it's a little 507 * different. The BOOTROM/boot program can only boot 508 * off of the first (lowest select code) ethernet 509 * device. device_register() knows this and only 510 * registers one DV_IFNET. This is a safe assumption 511 * since the code that finds devices on the DIO bus 512 * always starts at scode 0 and works its way up. 513 */ 514 if (netboot) { 515 for (dd = dev_data_list.lh_first; dd != NULL; 516 dd = dd->dd_list.le_next) { 517 if (dd->dd_dev->dv_class == DV_IFNET) { 518 /* 519 * Found it! 520 */ 521 booted_device = dd->dd_dev; 522 break; 523 } 524 } 525 return; 526 } 527 528 /* 529 * Check for HP-IB boots next. 530 */ 531 if (hpibboot) { 532 findbootdev_slave(&dev_data_list_hpib, ctlr, 533 slave, punit); 534 if (booted_device == NULL) 535 return; 536 537 /* 538 * Sanity check. 539 */ 540 if ((type == 0 && memcmp(booted_device->dv_xname, "ct", 2)) || 541 (type == 2 && memcmp(booted_device->dv_xname, "rd", 2))) { 542 printf("WARNING: boot device/type mismatch!\n"); 543 printf("device = %s, type = %d\n", 544 booted_device->dv_xname, type); 545 booted_device = NULL; 546 } 547 goto out; 548 } 549 550 /* 551 * Check for SCSI boots last. 552 */ 553 if (scsiboot) { 554 findbootdev_slave(&dev_data_list_scsi, ctlr, 555 slave, punit); 556 if (booted_device == NULL) 557 return; 558 559 /* 560 * Sanity check. 561 */ 562 if ((type == 4 && memcmp(booted_device->dv_xname, "sd", 2))) { 563 printf("WARNING: boot device/type mismatch!\n"); 564 printf("device = %s, type = %d\n", 565 booted_device->dv_xname, type); 566 booted_device = NULL; 567 } 568 goto out; 569 } 570 571 /* Oof! */ 572 printf("WARNING: UNKNOWN BOOT DEVICE TYPE = %d\n", type); 573 574 out: 575 if (booted_device != NULL) 576 booted_partition = part; 577 } 578 579 void 580 findbootdev_slave(ddlist, ctlr, slave, punit) 581 ddlist_t *ddlist; 582 int ctlr, slave, punit; 583 { 584 struct dev_data *cdd, *dd; 585 586 /* 587 * Find the booted controller. 588 */ 589 for (cdd = ddlist->lh_first; ctlr != 0 && cdd != NULL; 590 cdd = cdd->dd_clist.le_next) 591 ctlr--; 592 if (cdd == NULL) { 593 /* 594 * Oof, couldn't find it... 595 */ 596 return; 597 } 598 599 /* 600 * Now find the device with the right slave/punit 601 * that's a child of the controller. 602 */ 603 for (dd = dev_data_list.lh_first; dd != NULL; 604 dd = dd->dd_list.le_next) { 605 /* 606 * XXX We don't yet have the extra bus indirection 607 * XXX for SCSI, so we have to do a little bit of 608 * XXX extra work. 609 */ 610 if (memcmp(dd->dd_dev->dv_xname, "sd", 2) == 0) { 611 /* 612 * "sd" -> "oscsi" 613 */ 614 if (dd->dd_dev->dv_parent != cdd->dd_dev) 615 continue; 616 } else { 617 /* 618 * "rd" -> "hpibbus" -> "fhpib" 619 */ 620 if (dd->dd_dev->dv_parent->dv_parent != cdd->dd_dev) 621 continue; 622 } 623 624 if (dd->dd_slave == slave && 625 dd->dd_punit == punit) { 626 /* 627 * Found it! 628 */ 629 booted_device = dd->dd_dev; 630 break; 631 } 632 } 633 } 634 635 void 636 setbootdev() 637 { 638 struct dev_data *cdd, *dd; 639 int type, ctlr; 640 641 /* 642 * Note our magic numbers for type: 643 * 644 * 0 == ct 645 * 2 == rd 646 * 4 == sd 647 * 6 == le 648 * 649 * Allare bdevsw major numbers, except for le, which 650 * is just special. 651 * 652 * We can't mount root on a tape, so we ignore those. 653 */ 654 655 /* 656 * Start with a clean slate. 657 */ 658 bootdev = 0; 659 660 /* 661 * If the root device is network, we're done 662 * early. 663 */ 664 if (root_device->dv_class == DV_IFNET) { 665 bootdev = MAKEBOOTDEV(6, 0, 0, 0, 0); 666 goto out; 667 } 668 669 /* 670 * Determine device type. 671 */ 672 if (memcmp(root_device->dv_xname, "rd", 2) == 0) 673 type = 2; 674 else if (memcmp(root_device->dv_xname, "sd", 2) == 0) 675 type = 4; 676 else if (memcmp(root_device->dv_xname, "md", 2) == 0) 677 goto out; 678 else { 679 printf("WARNING: strange root device!\n"); 680 goto out; 681 } 682 683 dd = dev_data_lookup(root_device); 684 685 /* 686 * Get parent's info. 687 */ 688 switch (type) { 689 case 2: 690 /* 691 * "rd" -> "hpibbus" -> "fhpib" 692 */ 693 for (cdd = dev_data_list_hpib.lh_first, ctlr = 0; 694 cdd != NULL; cdd = cdd->dd_clist.le_next, ctlr++) { 695 if (cdd->dd_dev == root_device->dv_parent->dv_parent) { 696 /* 697 * Found it! 698 */ 699 bootdev = MAKEBOOTDEV(type, 700 ctlr, dd->dd_slave, dd->dd_punit, 701 DISKPART(rootdev)); 702 break; 703 } 704 } 705 break; 706 707 case 4: 708 /* 709 * "sd" -> "oscsi" 710 */ 711 for (cdd = dev_data_list_scsi.lh_first, ctlr = 0; 712 cdd != NULL; cdd = cdd->dd_clist.le_next, ctlr++) { 713 if (cdd->dd_dev == root_device->dv_parent) { 714 /* 715 * Found it! 716 */ 717 bootdev = MAKEBOOTDEV(type, 718 ctlr, dd->dd_slave, dd->dd_punit, 719 DISKPART(rootdev)); 720 break; 721 } 722 } 723 break; 724 } 725 726 out: 727 /* Don't need this anymore. */ 728 for (dd = dev_data_list.lh_first; dd != NULL; ) { 729 cdd = dd; 730 dd = dd->dd_list.le_next; 731 free(cdd, M_DEVBUF); 732 } 733 } 734 735 /* 736 * Return the dev_data corresponding to the given device. 737 */ 738 static struct dev_data * 739 dev_data_lookup(dev) 740 struct device *dev; 741 { 742 struct dev_data *dd; 743 744 for (dd = dev_data_list.lh_first; dd != NULL; dd = dd->dd_list.le_next) 745 if (dd->dd_dev == dev) 746 return (dd); 747 748 panic("dev_data_lookup"); 749 } 750 751 /* 752 * Insert a dev_data into the provided list, sorted by select code. 753 */ 754 static void 755 dev_data_insert(dd, ddlist) 756 struct dev_data *dd; 757 ddlist_t *ddlist; 758 { 759 struct dev_data *de; 760 761 #ifdef DIAGNOSTIC 762 if (dd->dd_scode < 0 || dd->dd_scode > 255) { 763 printf("bogus select code for %s\n", dd->dd_dev->dv_xname); 764 panic("dev_data_insert"); 765 } 766 #endif 767 768 de = ddlist->lh_first; 769 770 /* 771 * Just insert at head if list is empty. 772 */ 773 if (de == NULL) { 774 LIST_INSERT_HEAD(ddlist, dd, dd_clist); 775 return; 776 } 777 778 /* 779 * Traverse the list looking for a device who's select code 780 * is greater than ours. When we find it, insert ourselves 781 * into the list before it. 782 */ 783 for (; de->dd_clist.le_next != NULL; de = de->dd_clist.le_next) { 784 if (de->dd_scode > dd->dd_scode) { 785 LIST_INSERT_BEFORE(de, dd, dd_clist); 786 return; 787 } 788 } 789 790 /* 791 * Our select code is greater than everyone else's. We go 792 * onto the end. 793 */ 794 LIST_INSERT_AFTER(de, dd, dd_clist); 795 } 796 797 /********************************************************************** 798 * Code to find and initialize the console 799 **********************************************************************/ 800 801 void 802 hp300_cninit() 803 { 804 /* 805 * Look for serial consoles first. 806 */ 807 #if NAPCI > 0 808 if (!apcicnattach(HP300_BUS_SPACE_INTIO, 0x1c020, -1)) 809 return; 810 #endif 811 #if NDCA > 0 812 if (!dio_scan(dcacnattach)) 813 return; 814 #endif 815 #if NDCM > 0 816 if (!dio_scan(dcmcnattach)) 817 return; 818 #endif 819 820 #if NITE > 0 821 #ifndef CONSCODE 822 /* 823 * Look for internal framebuffers. 824 */ 825 #if NDVBOX > 0 826 if (!dvboxcnattach(HP300_BUS_SPACE_INTIO, 0x160000,-1)) 827 goto find_kbd; 828 #endif 829 #if NGBOX > 0 830 if (!gboxcnattach(HP300_BUS_SPACE_INTIO, 0x160000,-1)) 831 goto find_kbd; 832 #endif 833 #if NRBOX > 0 834 if (!rboxcnattach(HP300_BUS_SPACE_INTIO, 0x160000,-1)) 835 goto find_kbd; 836 #endif 837 #if NTOPCAT > 0 838 if (!topcatcnattach(HP300_BUS_SPACE_INTIO, 0x160000,-1)) 839 goto find_kbd; 840 #endif 841 #endif /* CONSCODE */ 842 843 /* 844 * Look for external framebuffers. 845 */ 846 #if NDVBOX > 0 847 if (!dio_scan(dvboxcnattach)) 848 goto find_kbd; 849 #endif 850 #if NGBOX > 0 851 if (!dio_scan(gboxcnattach)) 852 goto find_kbd; 853 #endif 854 #if NHYPER > 0 855 if (!dio_scan(hypercnattach)) 856 goto find_kbd; 857 #endif 858 #if NRBOX > 0 859 if (!dio_scan(rboxcnattach)) 860 goto find_kbd; 861 #endif 862 #if NTOPCAT > 0 863 if (!dio_scan(topcatcnattach)) 864 goto find_kbd; 865 #endif 866 867 find_kbd: 868 869 #if NDNKBD > 0 870 dnkbdcnattach(HP300_BUS_SPACE_INTIO, 0x1c000) 871 #endif 872 873 #if NHIL > 0 874 hilkbdcnattach(HP300_BUS_SPACE_INTIO, 0x28000); 875 #endif 876 #endif /* NITE */ 877 } 878 879 int 880 dio_scan(func) 881 int (*func)(bus_space_tag_t, bus_addr_t, int); 882 { 883 #ifndef CONSCODE 884 int scode, sctop; 885 886 sctop = DIO_SCMAX(machineid); 887 for (scode = 0; scode < sctop; ++scode) { 888 if (DIO_INHOLE(scode) || ((scode == 7) && internalhpib)) 889 continue; 890 if (!dio_scode_probe(scode, func)) 891 return (0); 892 } 893 #else 894 if (!dio_scode_probe(CONSCODE, func)) 895 return (0); 896 #endif 897 898 return (1); 899 } 900 901 int 902 dio_scode_probe(scode, func) 903 int scode; 904 int (*func)(bus_space_tag_t, bus_addr_t, int); 905 { 906 caddr_t pa, va; 907 908 pa = dio_scodetopa(scode); 909 va = iomap(pa, NBPG); 910 if (va == 0) 911 return (1); 912 if (badaddr(va)) { 913 iounmap(va, NBPG); 914 return (1); 915 } 916 iounmap(va, NBPG); 917 918 return ((*func)(HP300_BUS_SPACE_DIO, (bus_addr_t)pa, scode)); 919 } 920 921 922 /********************************************************************** 923 * Mapping functions 924 **********************************************************************/ 925 926 /* 927 * Initialize the external I/O extent map. 928 */ 929 void 930 iomap_init(void) 931 { 932 933 /* extiobase is initialized by pmap_bootstrap(). */ 934 extio_ex = extent_create("extio", (u_long) extiobase, 935 (u_long) extiobase + (ptoa(EIOMAPSIZE) - 1), M_DEVBUF, 936 (caddr_t) extio_ex_storage, sizeof(extio_ex_storage), 937 EX_NOCOALESCE|EX_NOWAIT); 938 } 939 940 /* 941 * Allocate/deallocate a cache-inhibited range of kernel virtual address 942 * space mapping the indicated physical address range [pa - pa+size) 943 */ 944 caddr_t 945 iomap(pa, size) 946 caddr_t pa; 947 int size; 948 { 949 u_long kva; 950 int error; 951 952 #ifdef DEBUG 953 if (((int)pa & PGOFSET) || (size & PGOFSET)) 954 panic("iomap: unaligned"); 955 #endif 956 957 error = extent_alloc(extio_ex, size, PAGE_SIZE, 0, 958 EX_FAST | EX_NOWAIT | (extio_ex_malloc_safe ? EX_MALLOCOK : 0), 959 &kva); 960 if (error) 961 return (0); 962 963 physaccess((caddr_t) kva, pa, size, PG_RW|PG_CI); 964 return ((caddr_t) kva); 965 } 966 967 /* 968 * Unmap a previously mapped device. 969 */ 970 void 971 iounmap(kva, size) 972 caddr_t kva; 973 int size; 974 { 975 976 #ifdef DEBUG 977 if (((int)kva & PGOFSET) || (size & PGOFSET)) 978 panic("iounmap: unaligned"); 979 if (kva < extiobase || kva >= extiobase + ptoa(EIOMAPSIZE)) 980 panic("iounmap: bad address"); 981 #endif 982 physunaccess(kva, size); 983 if (extent_free(extio_ex, (u_long) kva, size, 984 EX_NOWAIT | (extio_ex_malloc_safe ? EX_MALLOCOK : 0))) 985 printf("iounmap: kva %p size 0x%x: can't free region\n", 986 kva, size); 987 } 988