1 /* $NetBSD: autoconf.c,v 1.57 2002/04/17 20:40:30 gmcgarry Exp $ */ 2 3 /*- 4 * Copyright (c) 1996, 1997 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.57 2002/04/17 20:40:30 gmcgarry 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/map.h> 125 #include <sys/mount.h> 126 #include <sys/queue.h> 127 #include <sys/reboot.h> 128 #include <sys/tty.h> 129 130 #include <dev/cons.h> 131 132 #include <machine/autoconf.h> 133 #include <machine/vmparam.h> 134 #include <machine/cpu.h> 135 #include <machine/hp300spu.h> 136 #include <machine/intr.h> 137 #include <machine/pte.h> 138 139 #include <hp300/dev/dioreg.h> 140 #include <hp300/dev/diovar.h> 141 #include <hp300/dev/diodevs.h> 142 143 #include <hp300/dev/dmavar.h> 144 #include <hp300/dev/grfreg.h> 145 #include <hp300/dev/hilreg.h> 146 #include <hp300/dev/hilioctl.h> 147 #include <hp300/dev/hilvar.h> 148 149 #include <hp300/dev/hpibvar.h> 150 #include <hp300/dev/scsivar.h> 151 152 153 /* should go away with a cleanup */ 154 extern int dcacnattach(bus_space_tag_t, bus_addr_t, int); 155 extern int dcmcnattach(bus_space_tag_t, bus_addr_t, int); 156 extern int apcicnattach(bus_space_tag_t, bus_addr_t, int); 157 extern int dvboxcnattach(bus_space_tag_t, bus_addr_t, int); 158 extern int gboxcnattach(bus_space_tag_t, bus_addr_t, int); 159 extern int rboxcnattach(bus_space_tag_t, bus_addr_t, int); 160 extern int hypercnattach(bus_space_tag_t, bus_addr_t, int); 161 extern int topcatcnattach(bus_space_tag_t, bus_addr_t, int); 162 extern int hilkbdcnattach(bus_space_tag_t, bus_addr_t); 163 extern int dnkbdcnattach(bus_space_tag_t, bus_addr_t); 164 165 int dio_scan(int (*func)(bus_space_tag_t, bus_addr_t, int)); 166 int dio_scode_probe(int, int (*func)(bus_space_tag_t, bus_addr_t, int)); 167 168 /* XXX must be allocated statically because of early console init */ 169 struct map extiomap[EIOMAPSIZE/16]; 170 171 extern caddr_t internalhpib; 172 extern char *extiobase; 173 174 /* The boot device. */ 175 struct device *booted_device; 176 int booted_partition; 177 178 /* How we were booted. */ 179 u_int bootdev; 180 181 /* 182 * This information is built during the autoconfig process. 183 * A little explanation about the way this works is in order. 184 * 185 * device_register() links all devices into dev_data_list. 186 * If the device is an hpib controller, it is also linked 187 * into dev_data_list_hpib. If the device is a scsi controller, 188 * it is also linked into dev_data_list_scsi. 189 * 190 * dev_data_list_hpib and dev_data_list_scsi are sorted 191 * by select code, from lowest to highest. 192 * 193 * After autoconfiguration is complete, we need to determine 194 * which device was the boot device. The boot block assigns 195 * controller unit numbers in order of select code. Thus, 196 * providing the controller is configured in the kernel, we 197 * can determine our version of controller unit number from 198 * the sorted hpib/scsi list. 199 * 200 * At this point, we know the controller (device type 201 * encoded in bootdev tells us "scsi disk", or "hpib tape", 202 * etc.). The next step is to find the device which 203 * has the following properties: 204 * 205 * - A child of the boot controller. 206 * - Same slave as encoded in bootdev. 207 * - Same physical unit as encoded in bootdev. 208 * 209 * Later, after we've set the root device in stone, we 210 * reverse the process to re-encode bootdev so it can be 211 * passed back to the boot block. 212 */ 213 struct dev_data { 214 LIST_ENTRY(dev_data) dd_list; /* dev_data_list */ 215 LIST_ENTRY(dev_data) dd_clist; /* ctlr list */ 216 struct device *dd_dev; /* device described by this entry */ 217 int dd_scode; /* select code of device */ 218 int dd_slave; /* ...or slave */ 219 int dd_punit; /* and punit... */ 220 }; 221 typedef LIST_HEAD(, dev_data) ddlist_t; 222 ddlist_t dev_data_list; /* all dev_datas */ 223 ddlist_t dev_data_list_hpib; /* hpib controller dev_datas */ 224 ddlist_t dev_data_list_scsi; /* scsi controller dev_datas */ 225 226 void findbootdev __P((void)); 227 void findbootdev_slave __P((ddlist_t *, int, int, int)); 228 void setbootdev __P((void)); 229 230 static struct dev_data *dev_data_lookup __P((struct device *)); 231 static void dev_data_insert __P((struct dev_data *, ddlist_t *)); 232 233 int mainbusmatch __P((struct device *, struct cfdata *, void *)); 234 void mainbusattach __P((struct device *, struct device *, void *)); 235 int mainbussearch __P((struct device *, struct cfdata *, void *)); 236 237 struct cfattach mainbus_ca = { 238 sizeof(struct device), mainbusmatch, mainbusattach 239 }; 240 241 int 242 mainbusmatch(parent, match, aux) 243 struct device *parent; 244 struct cfdata *match; 245 void *aux; 246 { 247 static int mainbus_matched = 0; 248 249 /* Allow only one instance. */ 250 if (mainbus_matched) 251 return (0); 252 253 mainbus_matched = 1; 254 return (1); 255 } 256 257 void 258 mainbusattach(parent, self, aux) 259 struct device *parent, *self; 260 void *aux; 261 { 262 263 printf("\n"); 264 265 /* Search for and attach children. */ 266 config_search(mainbussearch, self, NULL); 267 } 268 269 int 270 mainbussearch(parent, cf, aux) 271 struct device *parent; 272 struct cfdata *cf; 273 void *aux; 274 { 275 276 if ((*cf->cf_attach->ca_match)(parent, cf, NULL) > 0) 277 config_attach(parent, cf, NULL, NULL); 278 return (0); 279 } 280 281 /* 282 * Determine the device configuration for the running system. 283 */ 284 void 285 cpu_configure() 286 { 287 288 /* 289 * Initialize the dev_data_lists. 290 */ 291 LIST_INIT(&dev_data_list); 292 LIST_INIT(&dev_data_list_hpib); 293 LIST_INIT(&dev_data_list_scsi); 294 295 /* Kick off autoconfiguration. */ 296 (void)splhigh(); 297 298 softintr_init(); 299 300 if (config_rootfound("mainbus", "mainbus") == NULL) 301 panic("no mainbus found"); 302 303 /* Configuration is finished, turn on interrupts. */ 304 (void)spl0(); 305 306 intr_printlevels(); 307 } 308 309 /********************************************************************** 310 * Code to find and set the boot device 311 **********************************************************************/ 312 313 void 314 cpu_rootconf() 315 { 316 struct dev_data *dd; 317 struct device *dv; 318 struct vfsops *vops; 319 320 /* 321 * Find boot device. 322 */ 323 if ((bootdev & B_MAGICMASK) != B_DEVMAGIC) { 324 printf("WARNING: boot program didn't supply boot device.\n"); 325 printf("Please update your boot program.\n"); 326 } else { 327 findbootdev(); 328 if (booted_device == NULL) { 329 printf("WARNING: can't find match for bootdev:\n"); 330 printf( 331 "type = %d, ctlr = %d, slave = %d, punit = %d, part = %d\n", 332 B_TYPE(bootdev), B_ADAPTOR(bootdev), 333 B_CONTROLLER(bootdev), B_UNIT(bootdev), 334 B_PARTITION(bootdev)); 335 bootdev = 0; /* invalidate bootdev */ 336 } else { 337 printf("boot device: %s\n", booted_device->dv_xname); 338 } 339 } 340 341 dv = booted_device; 342 343 /* 344 * If wild carded root device and wired down NFS root file system, 345 * pick the network interface device to use. 346 */ 347 if (rootspec == NULL) { 348 vops = vfs_getopsbyname("nfs"); 349 if (vops != NULL && vops->vfs_mountroot == mountroot) { 350 for (dd = dev_data_list.lh_first; 351 dd != NULL; dd = dd->dd_list.le_next) { 352 if (dd->dd_dev->dv_class == DV_IFNET) { 353 /* Got it! */ 354 dv = dd->dd_dev; 355 break; 356 } 357 } 358 if (dd == NULL) { 359 printf("no network interface for NFS root"); 360 dv = NULL; 361 } 362 } 363 } 364 365 /* 366 * If bootdev is bogus, ask the user anyhow. 367 */ 368 if (bootdev == 0) 369 boothowto |= RB_ASKNAME; 370 371 /* 372 * If we booted from tape, ask the user. 373 */ 374 if (booted_device != NULL && booted_device->dv_class == DV_TAPE) 375 boothowto |= RB_ASKNAME; 376 377 setroot(dv, booted_partition); 378 379 /* 380 * Set bootdev based on what we found as the root. 381 * This is given to the boot program when we reboot. 382 */ 383 setbootdev(); 384 385 } 386 387 /* 388 * Register a device. We're passed the device and the arguments 389 * used to attach it. This is used to find the boot device. 390 */ 391 void 392 device_register(dev, aux) 393 struct device *dev; 394 void *aux; 395 { 396 struct dev_data *dd; 397 static int seen_netdevice = 0; 398 399 /* 400 * Allocate a dev_data structure and fill it in. 401 * This means making some tests twice, but we don't 402 * care; this doesn't really have to be fast. 403 * 404 * Note that we only really care about devices that 405 * we can mount as root. 406 */ 407 408 MALLOC(dd, struct dev_data *, sizeof(struct dev_data), 409 M_DEVBUF, M_NOWAIT | M_ZERO); 410 if (dd == NULL) 411 panic("device_register: can't allocate dev_data"); 412 413 dd->dd_dev = dev; 414 415 /* 416 * BOOTROM and boot program can really only understand 417 * using the lowest select code network interface, 418 * so we ignore all but the first. 419 */ 420 if (dev->dv_class == DV_IFNET && seen_netdevice == 0) { 421 struct dio_attach_args *da = aux; 422 423 seen_netdevice = 1; 424 dd->dd_scode = da->da_scode; 425 goto linkup; 426 } 427 428 if (memcmp(dev->dv_xname, "fhpib", 5) == 0 || 429 memcmp(dev->dv_xname, "nhpib", 5) == 0 || 430 memcmp(dev->dv_xname, "oscsi", 5) == 0) { 431 struct dio_attach_args *da = aux; 432 433 dd->dd_scode = da->da_scode; 434 goto linkup; 435 } 436 437 if (memcmp(dev->dv_xname, "rd", 2) == 0) { 438 struct hpibbus_attach_args *ha = aux; 439 440 dd->dd_slave = ha->ha_slave; 441 dd->dd_punit = ha->ha_punit; 442 goto linkup; 443 } 444 445 if (memcmp(dev->dv_xname, "sd", 2) == 0) { 446 struct oscsi_attach_args *osa = aux; 447 448 dd->dd_slave = osa->osa_target; 449 dd->dd_punit = osa->osa_lun; 450 goto linkup; 451 } 452 453 /* 454 * Didn't need the dev_data. 455 */ 456 free(dd, M_DEVBUF); 457 return; 458 459 linkup: 460 LIST_INSERT_HEAD(&dev_data_list, dd, dd_list); 461 462 if (memcmp(dev->dv_xname, "fhpib", 5) == 0 || 463 memcmp(dev->dv_xname, "nhpib", 5) == 0) { 464 dev_data_insert(dd, &dev_data_list_hpib); 465 return; 466 } 467 468 if (memcmp(dev->dv_xname, "oscsi", 5) == 0) { 469 dev_data_insert(dd, &dev_data_list_scsi); 470 return; 471 } 472 } 473 474 void 475 findbootdev() 476 { 477 int type, ctlr, slave, punit, part; 478 int scsiboot, hpibboot, netboot; 479 struct dev_data *dd; 480 481 booted_device = NULL; 482 booted_partition = 0; 483 484 if ((bootdev & B_MAGICMASK) != B_DEVMAGIC) 485 return; 486 487 type = B_TYPE(bootdev); 488 ctlr = B_ADAPTOR(bootdev); 489 slave = B_CONTROLLER(bootdev); 490 punit = B_UNIT(bootdev); 491 part = B_PARTITION(bootdev); 492 493 scsiboot = (type == 4); /* sd major */ 494 hpibboot = (type == 0 || type == 2); /* ct/rd major */ 495 netboot = (type == 6); /* le - special */ 496 497 /* 498 * Check for network boot first, since it's a little 499 * different. The BOOTROM/boot program can only boot 500 * off of the first (lowest select code) ethernet 501 * device. device_register() knows this and only 502 * registers one DV_IFNET. This is a safe assumption 503 * since the code that finds devices on the DIO bus 504 * always starts at scode 0 and works its way up. 505 */ 506 if (netboot) { 507 for (dd = dev_data_list.lh_first; dd != NULL; 508 dd = dd->dd_list.le_next) { 509 if (dd->dd_dev->dv_class == DV_IFNET) { 510 /* 511 * Found it! 512 */ 513 booted_device = dd->dd_dev; 514 break; 515 } 516 } 517 return; 518 } 519 520 /* 521 * Check for HP-IB boots next. 522 */ 523 if (hpibboot) { 524 findbootdev_slave(&dev_data_list_hpib, ctlr, 525 slave, punit); 526 if (booted_device == NULL) 527 return; 528 529 /* 530 * Sanity check. 531 */ 532 if ((type == 0 && memcmp(booted_device->dv_xname, "ct", 2)) || 533 (type == 2 && memcmp(booted_device->dv_xname, "rd", 2))) { 534 printf("WARNING: boot device/type mismatch!\n"); 535 printf("device = %s, type = %d\n", 536 booted_device->dv_xname, type); 537 booted_device = NULL; 538 } 539 goto out; 540 } 541 542 /* 543 * Check for SCSI boots last. 544 */ 545 if (scsiboot) { 546 findbootdev_slave(&dev_data_list_scsi, ctlr, 547 slave, punit); 548 if (booted_device == NULL) 549 return; 550 551 /* 552 * Sanity check. 553 */ 554 if ((type == 4 && memcmp(booted_device->dv_xname, "sd", 2))) { 555 printf("WARNING: boot device/type mismatch!\n"); 556 printf("device = %s, type = %d\n", 557 booted_device->dv_xname, type); 558 booted_device = NULL; 559 } 560 goto out; 561 } 562 563 /* Oof! */ 564 printf("WARNING: UNKNOWN BOOT DEVICE TYPE = %d\n", type); 565 566 out: 567 if (booted_device != NULL) 568 booted_partition = part; 569 } 570 571 void 572 findbootdev_slave(ddlist, ctlr, slave, punit) 573 ddlist_t *ddlist; 574 int ctlr, slave, punit; 575 { 576 struct dev_data *cdd, *dd; 577 578 /* 579 * Find the booted controller. 580 */ 581 for (cdd = ddlist->lh_first; ctlr != 0 && cdd != NULL; 582 cdd = cdd->dd_clist.le_next) 583 ctlr--; 584 if (cdd == NULL) { 585 /* 586 * Oof, couldn't find it... 587 */ 588 return; 589 } 590 591 /* 592 * Now find the device with the right slave/punit 593 * that's a child of the controller. 594 */ 595 for (dd = dev_data_list.lh_first; dd != NULL; 596 dd = dd->dd_list.le_next) { 597 /* 598 * XXX We don't yet have the extra bus indirection 599 * XXX for SCSI, so we have to do a little bit of 600 * XXX extra work. 601 */ 602 if (memcmp(dd->dd_dev->dv_xname, "sd", 2) == 0) { 603 /* 604 * "sd" -> "oscsi" 605 */ 606 if (dd->dd_dev->dv_parent != cdd->dd_dev) 607 continue; 608 } else { 609 /* 610 * "rd" -> "hpibbus" -> "fhpib" 611 */ 612 if (dd->dd_dev->dv_parent->dv_parent != cdd->dd_dev) 613 continue; 614 } 615 616 if (dd->dd_slave == slave && 617 dd->dd_punit == punit) { 618 /* 619 * Found it! 620 */ 621 booted_device = dd->dd_dev; 622 break; 623 } 624 } 625 } 626 627 void 628 setbootdev() 629 { 630 struct dev_data *cdd, *dd; 631 int type, ctlr; 632 633 /* 634 * Note our magic numbers for type: 635 * 636 * 0 == ct 637 * 2 == rd 638 * 4 == sd 639 * 6 == le 640 * 641 * Allare bdevsw major numbers, except for le, which 642 * is just special. 643 * 644 * We can't mount root on a tape, so we ignore those. 645 */ 646 647 /* 648 * Start with a clean slate. 649 */ 650 bootdev = 0; 651 652 /* 653 * If the root device is network, we're done 654 * early. 655 */ 656 if (root_device->dv_class == DV_IFNET) { 657 bootdev = MAKEBOOTDEV(6, 0, 0, 0, 0); 658 goto out; 659 } 660 661 /* 662 * Determine device type. 663 */ 664 if (memcmp(root_device->dv_xname, "rd", 2) == 0) 665 type = 2; 666 else if (memcmp(root_device->dv_xname, "sd", 2) == 0) 667 type = 4; 668 else if (memcmp(root_device->dv_xname, "md", 2) == 0) 669 goto out; 670 else { 671 printf("WARNING: strange root device!\n"); 672 goto out; 673 } 674 675 dd = dev_data_lookup(root_device); 676 677 /* 678 * Get parent's info. 679 */ 680 switch (type) { 681 case 2: 682 /* 683 * "rd" -> "hpibbus" -> "fhpib" 684 */ 685 for (cdd = dev_data_list_hpib.lh_first, ctlr = 0; 686 cdd != NULL; cdd = cdd->dd_clist.le_next, ctlr++) { 687 if (cdd->dd_dev == root_device->dv_parent->dv_parent) { 688 /* 689 * Found it! 690 */ 691 bootdev = MAKEBOOTDEV(type, 692 ctlr, dd->dd_slave, dd->dd_punit, 693 DISKPART(rootdev)); 694 break; 695 } 696 } 697 break; 698 699 case 4: 700 /* 701 * "sd" -> "oscsi" 702 */ 703 for (cdd = dev_data_list_scsi.lh_first, ctlr = 0; 704 cdd != NULL; cdd = cdd->dd_clist.le_next, ctlr++) { 705 if (cdd->dd_dev == root_device->dv_parent) { 706 /* 707 * Found it! 708 */ 709 bootdev = MAKEBOOTDEV(type, 710 ctlr, dd->dd_slave, dd->dd_punit, 711 DISKPART(rootdev)); 712 break; 713 } 714 } 715 break; 716 } 717 718 out: 719 /* Don't need this anymore. */ 720 for (dd = dev_data_list.lh_first; dd != NULL; ) { 721 cdd = dd; 722 dd = dd->dd_list.le_next; 723 free(cdd, M_DEVBUF); 724 } 725 } 726 727 /* 728 * Return the dev_data corresponding to the given device. 729 */ 730 static struct dev_data * 731 dev_data_lookup(dev) 732 struct device *dev; 733 { 734 struct dev_data *dd; 735 736 for (dd = dev_data_list.lh_first; dd != NULL; dd = dd->dd_list.le_next) 737 if (dd->dd_dev == dev) 738 return (dd); 739 740 panic("dev_data_lookup"); 741 } 742 743 /* 744 * Insert a dev_data into the provided list, sorted by select code. 745 */ 746 static void 747 dev_data_insert(dd, ddlist) 748 struct dev_data *dd; 749 ddlist_t *ddlist; 750 { 751 struct dev_data *de; 752 753 #ifdef DIAGNOSTIC 754 if (dd->dd_scode < 0 || dd->dd_scode > 255) { 755 printf("bogus select code for %s\n", dd->dd_dev->dv_xname); 756 panic("dev_data_insert"); 757 } 758 #endif 759 760 de = ddlist->lh_first; 761 762 /* 763 * Just insert at head if list is empty. 764 */ 765 if (de == NULL) { 766 LIST_INSERT_HEAD(ddlist, dd, dd_clist); 767 return; 768 } 769 770 /* 771 * Traverse the list looking for a device who's select code 772 * is greater than ours. When we find it, insert ourselves 773 * into the list before it. 774 */ 775 for (; de->dd_clist.le_next != NULL; de = de->dd_clist.le_next) { 776 if (de->dd_scode > dd->dd_scode) { 777 LIST_INSERT_BEFORE(de, dd, dd_clist); 778 return; 779 } 780 } 781 782 /* 783 * Our select code is greater than everyone else's. We go 784 * onto the end. 785 */ 786 LIST_INSERT_AFTER(de, dd, dd_clist); 787 } 788 789 /********************************************************************** 790 * Code to find and initialize the console 791 **********************************************************************/ 792 793 void 794 hp300_cninit() 795 { 796 /* 797 * Look for serial consoles first. 798 */ 799 #if NAPCI > 0 800 if (!apcicnattach(HP300_BUS_SPACE_INTIO, 0x1c020, -1)) 801 return; 802 #endif 803 #if NDCA > 0 804 if (!dio_scan(dcacnattach)) 805 return; 806 #endif 807 #if NDCM > 0 808 if (!dio_scan(dcmcnattach)) 809 return; 810 #endif 811 812 #if NITE > 0 813 #ifndef CONSCODE 814 /* 815 * Look for internal framebuffers. 816 */ 817 #if NDVBOX > 0 818 if (!dvboxcnattach(HP300_BUS_SPACE_INTIO, 0x160000,-1)) 819 goto find_kbd; 820 #endif 821 #if NGBOX > 0 822 if (!gboxcnattach(HP300_BUS_SPACE_INTIO, 0x160000,-1)) 823 goto find_kbd; 824 #endif 825 #if NRBOX > 0 826 if (!rboxcnattach(HP300_BUS_SPACE_INTIO, 0x160000,-1)) 827 goto find_kbd; 828 #endif 829 #if NTOPCAT > 0 830 if (!topcatcnattach(HP300_BUS_SPACE_INTIO, 0x160000,-1)) 831 goto find_kbd; 832 #endif 833 #endif /* CONSCODE */ 834 835 /* 836 * Look for external framebuffers. 837 */ 838 #if NDVBOX > 0 839 if (!dio_scan(dvboxcnattach)) 840 goto find_kbd; 841 #endif 842 #if NGBOX > 0 843 if (!dio_scan(gboxcnattach)) 844 goto find_kbd; 845 #endif 846 #if NHYPER > 0 847 if (!dio_scan(hypercnattach)) 848 goto find_kbd; 849 #endif 850 #if NRBOX > 0 851 if (!dio_scan(rboxcnattach)) 852 goto find_kbd; 853 #endif 854 #if NTOPCAT > 0 855 if (!dio_scan(topcatcnattach)) 856 goto find_kbd; 857 #endif 858 859 find_kbd: 860 861 #if NDNKBD > 0 862 dnkbdcnattach(HP300_BUS_SPACE_INTIO, 0x1c000) 863 #endif 864 865 #if NHIL > 0 866 hilkbdcnattach(HP300_BUS_SPACE_INTIO, 0x28000); 867 #endif 868 #endif /* NITE */ 869 } 870 871 int 872 dio_scan(func) 873 int (*func)(bus_space_tag_t, bus_addr_t, int); 874 { 875 #ifndef CONSCODE 876 int scode, sctop; 877 878 sctop = DIO_SCMAX(machineid); 879 for (scode = 0; scode < sctop; ++scode) { 880 if (DIO_INHOLE(scode) || ((scode == 7) && internalhpib)) 881 continue; 882 if (!dio_scode_probe(scode, func)) 883 return (0); 884 } 885 #else 886 if (!dio_scode_probe(CONSCODE, func)) 887 return (0); 888 #endif 889 890 return (1); 891 } 892 893 int 894 dio_scode_probe(scode, func) 895 int scode; 896 int (*func)(bus_space_tag_t, bus_addr_t, int); 897 { 898 caddr_t pa, va; 899 900 pa = dio_scodetopa(scode); 901 va = iomap(pa, NBPG); 902 if (va == 0) 903 return (1); 904 if (badaddr(va)) { 905 iounmap(va, NBPG); 906 return (1); 907 } 908 iounmap(va, NBPG); 909 910 return ((*func)(HP300_BUS_SPACE_DIO, (bus_addr_t)pa, scode)); 911 } 912 913 914 /********************************************************************** 915 * Mapping functions 916 **********************************************************************/ 917 918 /* 919 * Allocate/deallocate a cache-inhibited range of kernel virtual address 920 * space mapping the indicated physical address range [pa - pa+size) 921 */ 922 caddr_t 923 iomap(pa, size) 924 caddr_t pa; 925 int size; 926 { 927 int ix, npf; 928 caddr_t kva; 929 930 #ifdef DEBUG 931 if (((int)pa & PGOFSET) || (size & PGOFSET)) 932 panic("iomap: unaligned"); 933 #endif 934 npf = btoc(size); 935 ix = rmalloc(extiomap, npf); 936 if (ix == 0) 937 return(0); 938 kva = extiobase + ctob(ix-1); 939 physaccess(kva, pa, size, PG_RW|PG_CI); 940 return(kva); 941 } 942 943 /* 944 * Unmap a previously mapped device. 945 */ 946 void 947 iounmap(kva, size) 948 caddr_t kva; 949 int size; 950 { 951 int ix; 952 953 #ifdef DEBUG 954 if (((int)kva & PGOFSET) || (size & PGOFSET)) 955 panic("iounmap: unaligned"); 956 if (kva < extiobase || kva >= extiobase + ctob(EIOMAPSIZE)) 957 panic("iounmap: bad address"); 958 #endif 959 physunaccess(kva, size); 960 ix = btoc(kva - extiobase) + 1; 961 rmfree(extiomap, btoc(size), ix); 962 } 963