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