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