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