1/* $OpenBSD: autoconf.c,v 1.151 2024/05/17 20:05:08 miod Exp $ */ 2/* $NetBSD: autoconf.c,v 1.51 2001/07/24 19:32:11 eeh Exp $ */ 3 4/* 5 * Copyright (c) 1996 6 * The President and Fellows of Harvard College. All rights reserved. 7 * Copyright (c) 1992, 1993 8 * The Regents of the University of California. All rights reserved. 9 * 10 * This software was developed by the Computer Systems Engineering group 11 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 12 * contributed to Berkeley. 13 * 14 * All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Harvard University. 17 * This product includes software developed by the University of 18 * California, Lawrence Berkeley Laboratory. 19 * 20 * Redistribution and use in source and binary forms, with or without 21 * modification, are permitted provided that the following conditions 22 * are met: 23 * 1. Redistributions of source code must retain the above copyright 24 * notice, this list of conditions and the following disclaimer. 25 * 2. Redistributions in binary form must reproduce the above copyright 26 * notice, this list of conditions and the following disclaimer in the 27 * documentation and/or other materials provided with the distribution. 28 * 3. Neither the name of the University nor the names of its contributors 29 * may be used to endorse or promote products derived from this software 30 * without specific prior written permission. 31 * 32 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 36 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 40 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 41 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 42 * SUCH DAMAGE. 43 * 44 * @(#)autoconf.c 8.4 (Berkeley) 10/1/93 45 */ 46 47#include "mpath.h" 48 49#include <sys/param.h> 50#include <sys/systm.h> 51#include <sys/buf.h> 52#include <sys/disklabel.h> 53#include <sys/device.h> 54#include <sys/disk.h> 55#include <sys/conf.h> 56#include <sys/reboot.h> 57#include <sys/socket.h> 58#include <sys/malloc.h> 59#include <sys/queue.h> 60#include <sys/msgbuf.h> 61 62#include <net/if.h> 63 64#include <dev/cons.h> 65#include <dev/clock_subr.h> 66 67#include <uvm/uvm_extern.h> 68 69#include <machine/bus.h> 70#include <machine/boot_flag.h> 71#include <machine/autoconf.h> 72#include <machine/hypervisor.h> 73#include <machine/mdesc.h> 74#include <machine/openfirm.h> 75#include <machine/sparc64.h> 76#include <machine/cpu.h> 77#include <machine/pmap.h> 78#include <machine/trap.h> 79#include <sparc64/sparc64/cache.h> 80#include <sparc64/dev/vbusvar.h> 81#include <sparc64/dev/cbusvar.h> 82 83#include <stand/boot/bootarg.h> 84 85#include <dev/ata/atavar.h> 86#include <dev/pci/pcivar.h> 87#include <dev/sbus/sbusvar.h> 88 89#include <scsi/scsi_all.h> 90#include <scsi/scsiconf.h> 91#if NMPATH > 0 92#include <scsi/mpathvar.h> 93#endif 94 95#ifdef DDB 96#include <machine/db_machdep.h> 97#include <ddb/db_sym.h> 98#include <ddb/db_extern.h> 99#endif 100 101#include "softraid.h" 102#if NSOFTRAID > 0 103#include <sys/sensors.h> 104#include <dev/softraidvar.h> 105 106/* XXX */ 107#undef DPRINTF 108#undef DNPRINTF 109#endif 110 111int printspl = 0; 112 113/* 114 * The following several variables are related to 115 * the configuration process, and are used in initializing 116 * the machine. 117 */ 118int stdinnode; /* node ID of ROM's console input device */ 119int fbnode; /* node ID of ROM's console output device */ 120int optionsnode; /* node ID of ROM's options */ 121 122static int rootnode; 123 124static char *str2hex(char *, long *); 125static int mbprint(void *, const char *); 126int mainbus_match(struct device *, void *, void *); 127static void mainbus_attach(struct device *, struct device *, void *); 128int get_ncpus(void); 129 130struct device *booted_device; 131struct bootpath bootpath[16]; 132int nbootpath; 133int bootnode; 134static void bootpath_build(void); 135static void bootpath_print(struct bootpath *); 136void bootpath_nodes(struct bootpath *, int); 137 138struct openbsd_bootdata obd __attribute__((section(".openbsd.bootdata"))); 139 140void nail_bootdev(struct device *, struct bootpath *); 141 142/* Global interrupt mappings for all device types. Match against the OBP 143 * 'device_type' property. 144 */ 145struct intrmap intrmap[] = { 146 { "block", PIL_FD }, /* Floppy disk */ 147 { "serial", PIL_SER }, /* zs */ 148 { "scsi", PIL_SCSI }, 149 { "scsi-2", PIL_SCSI }, 150 { "network", PIL_NET }, 151 { "display", PIL_VIDEO }, 152 { "audio", PIL_AUD }, 153 { "ide", PIL_SCSI }, 154/* The following devices don't have device types: */ 155 { "SUNW,CS4231", PIL_AUD }, 156 { NULL, 0 } 157}; 158 159#ifdef SUN4V 160void sun4v_soft_state_init(void); 161void sun4v_set_soft_state(int, const char *); 162 163#define __align32 __attribute__((__aligned__(32))) 164char sun4v_soft_state_booting[] __align32 = "OpenBSD booting"; 165char sun4v_soft_state_running[] __align32 = "OpenBSD running"; 166 167void sun4v_interrupt_init(void); 168void sun4v_sdio_init(void); 169#endif 170 171extern void us_tlb_flush_pte(vaddr_t, uint64_t); 172extern void us3_tlb_flush_pte(vaddr_t, uint64_t); 173extern void sun4v_tlb_flush_pte(vaddr_t, uint64_t); 174extern void us_tlb_flush_ctx(uint64_t); 175extern void us3_tlb_flush_ctx(uint64_t); 176extern void sun4v_tlb_flush_ctx(uint64_t); 177 178void (*sp_tlb_flush_pte)(vaddr_t, uint64_t) = us_tlb_flush_pte; 179void (*sp_tlb_flush_ctx)(uint64_t) = us_tlb_flush_ctx; 180 181#ifdef DEBUG 182#define ACDB_BOOTDEV 0x1 183#define ACDB_PROBE 0x2 184int autoconf_debug = 0x0; 185#define DPRINTF(l, s) do { if (autoconf_debug & l) printf s; } while (0) 186#else 187#define DPRINTF(l, s) 188#endif 189 190/* 191 * Convert hex ASCII string to a value. Returns updated pointer. 192 * Depends on ASCII order (this *is* machine-dependent code, you know). 193 */ 194static char * 195str2hex(char *str, long *vp) 196{ 197 long v; 198 int c; 199 200 if (*str == 'w') { 201 for (v = 1;; v++) { 202 if (str[v] >= '0' && str[v] <= '9') 203 continue; 204 if (str[v] >= 'a' && str[v] <= 'f') 205 continue; 206 if (str[v] >= 'A' && str[v] <= 'F') 207 continue; 208 if (str[v] == '\0' || str[v] == ',') 209 break; 210 *vp = 0; 211 return (str + v); 212 } 213 str++; 214 } 215 216 for (v = 0;; v = v * 16 + c, str++) { 217 c = *(u_char *)str; 218 if (c <= '9') { 219 if ((c -= '0') < 0) 220 break; 221 } else if (c <= 'F') { 222 if ((c -= 'A' - 10) < 10) 223 break; 224 } else if (c <= 'f') { 225 if ((c -= 'a' - 10) < 10) 226 break; 227 } else 228 break; 229 } 230 *vp = v; 231 return (str); 232} 233 234/* 235 * Hunt through the device tree for CPUs. There should be no need to 236 * go more than four levels deep; an UltraSPARC-IV on Seregeti shows 237 * up as /ssm@0,0/cmp@0,0/cpu@0 and a SPARC64-VI will show up as 238 * /cmp@0,0/core@0/cpu@0. 239 */ 240int 241get_ncpus(void) 242{ 243 int node, child, stack[4], depth, ncpus; 244 char buf[32]; 245 246 stack[0] = findroot(); 247 depth = 0; 248 249 ncpus = 0; 250 for (;;) { 251 node = stack[depth]; 252 253 if (node == 0 || node == -1) { 254 if (--depth < 0) 255 goto done; 256 257 stack[depth] = OF_peer(stack[depth]); 258 continue; 259 } 260 261 if (OF_getprop(node, "device_type", buf, sizeof(buf)) > 0 && 262 strcmp(buf, "cpu") == 0) 263 ncpus++; 264 265 child = OF_child(node); 266 if (child != 0 && child != -1 && depth < 3) 267 stack[++depth] = child; 268 else 269 stack[depth] = OF_peer(stack[depth]); 270 } 271 272done: 273 ncpusfound = ncpus; 274#ifdef MULTIPROCESSOR 275 return (ncpus); 276#else 277 return (1); 278#endif 279} 280 281/* 282 * locore.s code calls bootstrap() just before calling main(). 283 * 284 * What we try to do is as follows: 285 * 286 * 1) We will try to re-allocate the old message buffer. 287 * 288 * 2) We will then get the list of the total and available 289 * physical memory and available virtual memory from the 290 * prom. 291 * 292 * 3) We will pass the list to pmap_bootstrap to manage them. 293 * 294 * We will try to run out of the prom until we get to cpu_init(). 295 */ 296void 297bootstrap(int nctx) 298{ 299 extern int end; /* End of kernel */ 300 struct trapvec *romtba; 301#if defined(SUN4US) || defined(SUN4V) 302 char buf[32]; 303#endif 304 int impl = 0; 305 int ncpus; 306 307 /* Initialize the PROM console so printf will not panic. */ 308 (*cn_tab->cn_init)(cn_tab); 309 310 /* 311 * Initialize ddb first and register OBP callbacks. 312 * We can do this because ddb_init() does not allocate anything, 313 * just initializes some pointers to important things 314 * like the symtab. 315 * 316 * By doing this first and installing the OBP callbacks 317 * we get to do symbolic debugging of pmap_bootstrap(). 318 */ 319#ifdef DDB 320 db_machine_init(); 321 ddb_init(); 322 /* This can only be installed on an 64-bit system cause otherwise our stack is screwed */ 323 OF_set_symbol_lookup(OF_sym2val, OF_val2sym); 324#endif 325 326#if defined (SUN4US) || defined(SUN4V) 327 if (OF_getprop(findroot(), "compatible", buf, sizeof(buf)) > 0) { 328 if (strcmp(buf, "sun4us") == 0) 329 cputyp = CPU_SUN4US; 330 if (strcmp(buf, "sun4v") == 0) 331 cputyp = CPU_SUN4V; 332 } 333#endif 334 335 /* We cannot read %ver on sun4v systems. */ 336 if (CPU_ISSUN4U || CPU_ISSUN4US) 337 impl = (getver() & VER_IMPL) >> VER_IMPL_SHIFT; 338 339 if (impl >= IMPL_CHEETAH) { 340 extern vaddr_t dlflush_start; 341 vaddr_t *pva; 342 u_int32_t insn; 343 344 for (pva = &dlflush_start; *pva; pva++) { 345 insn = *(u_int32_t *)(*pva); 346 insn &= ~(ASI_DCACHE_TAG << 5); 347 insn |= (ASI_DCACHE_INVALIDATE << 5); 348 *(u_int32_t *)(*pva) = insn; 349 flush((void *)(*pva)); 350 } 351 352 cacheinfo.c_dcache_flush_page = us3_dcache_flush_page; 353 sp_tlb_flush_pte = us3_tlb_flush_pte; 354 sp_tlb_flush_ctx = us3_tlb_flush_ctx; 355 } 356 357 if ((impl >= IMPL_ZEUS && impl <= IMPL_JUPITER) || CPU_ISSUN4V) { 358 extern vaddr_t dlflush_start; 359 vaddr_t *pva; 360 361 for (pva = &dlflush_start; *pva; pva++) { 362 *(u_int32_t *)(*pva) = 0x01000000; /* nop */ 363 flush((void *)(*pva)); 364 } 365 366 cacheinfo.c_dcache_flush_page = no_dcache_flush_page; 367 } 368 369#ifdef MULTIPROCESSOR 370 if (impl >= IMPL_OLYMPUS_C && impl <= IMPL_JUPITER) { 371 struct sun4u_patch { 372 u_int32_t addr; 373 u_int32_t insn; 374 } *p; 375 376 extern struct sun4u_patch sun4u_mtp_patch; 377 extern struct sun4u_patch sun4u_mtp_patch_end; 378 379 for (p = &sun4u_mtp_patch; p < &sun4u_mtp_patch_end; p++) { 380 *(u_int32_t *)(vaddr_t)p->addr = p->insn; 381 flush((void *)(vaddr_t)p->addr); 382 } 383 } 384#endif 385 386#ifdef SUN4V 387 if (CPU_ISSUN4V) { 388 struct sun4v_patch { 389 u_int32_t addr; 390 u_int32_t insn; 391 } *p; 392 393 extern struct sun4v_patch sun4v_patch; 394 extern struct sun4v_patch sun4v_patch_end; 395 396 for (p = &sun4v_patch; p < &sun4v_patch_end; p++) { 397 *(u_int32_t *)(vaddr_t)p->addr = p->insn; 398 flush((void *)(vaddr_t)p->addr); 399 } 400 401#ifdef MULTIPROCESSOR 402 extern struct sun4v_patch sun4v_mp_patch; 403 extern struct sun4v_patch sun4v_mp_patch_end; 404 405 for (p = &sun4v_mp_patch; p < &sun4v_mp_patch_end; p++) { 406 *(u_int32_t *)(vaddr_t)p->addr = p->insn; 407 flush((void *)(vaddr_t)p->addr); 408 } 409#endif 410 411 sp_tlb_flush_pte = sun4v_tlb_flush_pte; 412 sp_tlb_flush_ctx = sun4v_tlb_flush_ctx; 413 } 414#endif 415 416 /* 417 * Copy over the OBP breakpoint trap vector; OpenFirmware 5.x 418 * needs it to be able to return to the ok prompt. 419 */ 420 romtba = (struct trapvec *)sparc_rdpr(tba); 421 bcopy(&romtba[T_MON_BREAKPOINT], &trapbase[T_MON_BREAKPOINT], 422 sizeof(struct trapvec)); 423 flush((void *)trapbase); 424 425 ncpus = get_ncpus(); 426 pmap_bootstrap(KERNBASE, (u_long)&end, nctx, ncpus); 427 428 if (obd.version == BOOTDATA_VERSION && 429 obd.len >= BOOTDATA_LEN_BOOTHOWTO) 430 boothowto = obd.boothowto; 431 432#ifdef SUN4V 433 if (CPU_ISSUN4V) { 434 sun4v_soft_state_init(); 435 sun4v_set_soft_state(SIS_TRANSITION, sun4v_soft_state_booting); 436 sun4v_interrupt_init(); 437 sun4v_sdio_init(); 438 } 439#endif 440} 441 442void 443bootpath_nodes(struct bootpath *bp, int nbp) 444{ 445 int chosen; 446 int i; 447 char buf[128], *cp, c; 448 449 chosen = OF_finddevice("/chosen"); 450 OF_getprop(chosen, "bootpath", buf, sizeof(buf)); 451 cp = buf; 452 453 for (i = 0; i < nbp; i++, bp++) { 454 if (*cp == '\0') 455 return; 456 while (*cp != '\0' && *cp == '/') 457 cp++; 458 while (*cp && *cp != '/') 459 cp++; 460 c = *cp; 461 *cp = '\0'; 462 bootnode = bp->node = OF_finddevice(buf); 463 *cp = c; 464 } 465} 466 467/* 468 * bootpath_build: build a bootpath. Used when booting a generic 469 * kernel to find our root device. Newer proms give us a bootpath, 470 * for older proms we have to create one. An element in a bootpath 471 * has 4 fields: name (device name), val[0], val[1], and val[2]. Note that: 472 * Interpretation of val[] is device-dependent. Some examples: 473 * 474 * if (val[0] == -1) { 475 * val[1] is a unit number (happens most often with old proms) 476 * } else { 477 * [sbus device] val[0] is a sbus slot, and val[1] is an sbus offset 478 * [scsi disk] val[0] is target, val[1] is lun, val[2] is partition 479 * [scsi tape] val[0] is target, val[1] is lun, val[2] is file # 480 * [pci device] val[0] is device, val[1] is function, val[2] might be partition 481 * } 482 * 483 */ 484 485static void 486bootpath_build(void) 487{ 488 register char *cp, *pp; 489 register struct bootpath *bp; 490 register long chosen; 491 char buf[128]; 492 493 bzero((void *)bootpath, sizeof(bootpath)); 494 bp = bootpath; 495 496 /* 497 * Grab boot path from PROM 498 */ 499 chosen = OF_finddevice("/chosen"); 500 OF_getprop(chosen, "bootpath", buf, sizeof(buf)); 501 cp = buf; 502 while (cp != NULL && *cp == '/') { 503 /* Step over '/' */ 504 ++cp; 505 /* Extract name */ 506 pp = bp->name; 507 while (*cp != '@' && *cp != '/' && *cp != '\0') 508 *pp++ = *cp++; 509 *pp = '\0'; 510 if (*cp == '@') { 511 cp = str2hex(++cp, &bp->val[0]); 512 if (*cp == ',') 513 cp = str2hex(++cp, &bp->val[1]); 514 if (*cp == ':') { 515 /* 516 * We only store one character here, as we will 517 * only use this field to compute a partition 518 * index for block devices. However, it might 519 * be an ethernet media specification, so be 520 * sure to skip all letters. 521 */ 522 bp->val[2] = *++cp - 'a'; 523 while (*cp != '\0' && *cp != '/') 524 cp++; 525 } 526 } else { 527 bp->val[0] = -1; /* no #'s: assume unit 0, no 528 sbus offset/address */ 529 } 530 ++bp; 531 ++nbootpath; 532 } 533 bp->name[0] = 0; 534 535 bootpath_nodes(bootpath, nbootpath); 536 537 /* Setup pointer to boot flags */ 538 OF_getprop(chosen, "bootargs", buf, sizeof(buf)); 539 cp = buf; 540 541 /* Find start of boot flags */ 542 while (*cp) { 543 while(*cp == ' ' || *cp == '\t') cp++; 544 if (*cp == '-' || *cp == '\0') 545 break; 546 while(*cp != ' ' && *cp != '\t' && *cp != '\0') cp++; 547 548 } 549 if (*cp != '-') 550 return; 551 552 for (;*++cp;) { 553 int fl; 554 555 fl = 0; 556 switch(*cp) { 557 case 'a': 558 fl |= RB_ASKNAME; 559 break; 560 case 'b': 561 fl |= RB_HALT; 562 break; 563 case 'c': 564 fl |= RB_CONFIG; 565 break; 566 case 'd': 567 fl |= RB_KDB; 568 break; 569 case 's': 570 fl |= RB_SINGLE; 571 break; 572 default: 573 break; 574 } 575 if (!fl) { 576 printf("unknown option `%c'\n", *cp); 577 continue; 578 } 579 boothowto |= fl; 580 581 /* specialties */ 582 if (*cp == 'd') { 583#if defined(DDB) 584 db_enter(); 585#else 586 printf("kernel has no debugger\n"); 587#endif 588 } 589 } 590} 591 592/* 593 * print out the bootpath 594 * the %x isn't 0x%x because the Sun EPROMs do it this way, and 595 * consistency with the EPROMs is probably better here. 596 */ 597 598static void 599bootpath_print(struct bootpath *bp) 600{ 601 printf("bootpath: "); 602 while (bp->name[0]) { 603 if (bp->val[0] == -1) 604 printf("/%s%lx", bp->name, bp->val[1]); 605 else 606 printf("/%s@%lx,%lx", bp->name, bp->val[0], bp->val[1]); 607 if (bp->val[2] != 0) 608 printf(":%c", (int)bp->val[2] + 'a'); 609 bp++; 610 } 611 printf("\n"); 612} 613 614 615/* 616 * save or read a bootpath pointer from the boothpath store. 617 * 618 * XXX. required because of SCSI... we don't have control over the "sd" 619 * device, so we can't set boot device there. we patch in with 620 * device_register(), and use this to recover the bootpath. 621 */ 622struct bootpath * 623bootpath_store(int storep, struct bootpath *bp) 624{ 625 static struct bootpath *save; 626 struct bootpath *retval; 627 628 retval = save; 629 if (storep) 630 save = bp; 631 632 return (retval); 633} 634 635/* 636 * Determine mass storage and memory configuration for a machine. 637 * We get the PROM's root device and make sure we understand it, then 638 * attach it as `mainbus0'. 639 */ 640void 641cpu_configure(void) 642{ 643#ifdef SUN4V 644 int pause = 0; 645 646 if (CPU_ISSUN4V) { 647 const char *prop; 648 size_t len; 649 int idx; 650 651 mdesc_init(); 652 idx = mdesc_find_node("cpu"); 653 prop = mdesc_get_prop_data(idx, "hwcap-list", &len); 654 if (prop) { 655 while (len > 0) { 656 if (strcmp(prop, "pause") == 0) 657 pause = 1; 658 len -= strlen(prop) + 1; 659 prop += strlen(prop) + 1; 660 } 661 } 662 } 663 664 if (pause) { 665 struct sun4v_patch { 666 u_int32_t addr; 667 u_int32_t insn; 668 } *p; 669 paddr_t pa; 670 671 extern struct sun4v_patch sun4v_pause_patch; 672 extern struct sun4v_patch sun4v_pause_patch_end; 673 674 /* 675 * Use physical addresses to patch since kernel .text 676 * is already mapped read-only at this point. 677 */ 678 for (p = &sun4v_pause_patch; p < &sun4v_pause_patch_end; p++) { 679 pmap_extract(pmap_kernel(), (vaddr_t)p->addr, &pa); 680 stwa(pa, ASI_PHYS_NON_CACHED, p->insn); 681 flush((void *)(vaddr_t)p->addr); 682 } 683 } 684#endif 685 686 if (obd.version == BOOTDATA_VERSION && 687 obd.len >= BOOTDATA_LEN_BOOTHOWTO) { 688#if NSOFTRAID > 0 689 memcpy(sr_bootuuid.sui_id, obd.sr_uuid, 690 sizeof(sr_bootuuid.sui_id)); 691 memcpy(sr_bootkey, obd.sr_maskkey, sizeof(sr_bootkey)); 692#endif 693 explicit_bzero(obd.sr_maskkey, sizeof(obd.sr_maskkey)); 694 } 695 696 /* build the bootpath */ 697 bootpath_build(); 698 699 if (boothowto & RB_CONFIG) { 700#ifdef BOOT_CONFIG 701 user_config(); 702#else 703 printf("kernel does not support -c; continuing..\n"); 704#endif 705 } 706 707 /* block clock interrupts and anything below */ 708 splclock(); 709 /* Enable device interrupts */ 710 setpstate(getpstate()|PSTATE_IE); 711 712 if (config_rootfound("mainbus", NULL) == NULL) 713 panic("mainbus not configured"); 714 715 /* Enable device interrupts */ 716 setpstate(getpstate()|PSTATE_IE); 717 718 (void)spl0(); 719 cold = 0; 720 721#ifdef SUN4V 722 if (CPU_ISSUN4V) 723 sun4v_set_soft_state(SIS_NORMAL, sun4v_soft_state_running); 724#endif 725} 726 727#ifdef SUN4V 728 729#define HSVC_GROUP_INTERRUPT 0x002 730#define HSVC_GROUP_SOFT_STATE 0x003 731#define HSVC_GROUP_SDIO 0x108 732 733int sun4v_soft_state_initialized = 0; 734 735void 736sun4v_soft_state_init(void) 737{ 738 uint64_t minor; 739 740 if (prom_set_sun4v_api_version(HSVC_GROUP_SOFT_STATE, 1, 0, &minor)) 741 return; 742 743 prom_sun4v_soft_state_supported(); 744 sun4v_soft_state_initialized = 1; 745} 746 747void 748sun4v_set_soft_state(int state, const char *desc) 749{ 750 paddr_t pa; 751 int err; 752 753 if (!sun4v_soft_state_initialized) 754 return; 755 756 if (!pmap_extract(pmap_kernel(), (vaddr_t)desc, &pa)) 757 panic("sun4v_set_soft_state: pmap_extract failed"); 758 759 err = hv_soft_state_set(state, pa); 760 if (err != H_EOK) 761 printf("soft_state_set: %d\n", err); 762} 763 764void 765sun4v_interrupt_init(void) 766{ 767 uint64_t minor; 768 769 if (prom_set_sun4v_api_version(HSVC_GROUP_INTERRUPT, 3, 0, &minor)) 770 return; 771 772 sun4v_group_interrupt_major = 3; 773} 774 775void 776sun4v_sdio_init(void) 777{ 778 uint64_t minor; 779 780 if (prom_set_sun4v_api_version(HSVC_GROUP_SDIO, 1, 0, &minor)) 781 return; 782 783 sun4v_group_sdio_major = 1; 784} 785 786#endif 787 788void 789diskconf(void) 790{ 791 struct bootpath *bp; 792 struct device *bootdv; 793 794 bootpath_print(bootpath); 795 796 bp = nbootpath == 0 ? NULL : &bootpath[nbootpath-1]; 797 bootdv = (bp == NULL) ? NULL : bp->dev; 798 799#if NMPATH > 0 800 if (bootdv != NULL) 801 bootdv = mpath_bootdv(bootdv); 802#endif 803 804 setroot(bootdv, bp->val[2], RB_USERREQ | RB_HALT); 805 dumpconf(); 806} 807 808char * 809clockfreq(long freq) 810{ 811 char *p; 812 static char buf[10]; 813 814 freq /= 1000; 815 snprintf(buf, sizeof buf, "%ld", freq / 1000); 816 freq %= 1000; 817 if (freq) { 818 freq += 1000; /* now in 1000..1999 */ 819 p = buf + strlen(buf); 820 snprintf(p, buf + sizeof buf - p, "%ld", freq); 821 *p = '.'; /* now buf = %d.%3d */ 822 } 823 return (buf); 824} 825 826static int 827mbprint(void *aux, const char *name) 828{ 829 struct mainbus_attach_args *ma = aux; 830 831 if (name) 832 printf("\"%s\" at %s", ma->ma_name, name); 833 if (ma->ma_address) 834 printf(" addr 0x%08lx", (u_long)ma->ma_address[0]); 835 if (ma->ma_pri) 836 printf(" ipl %d", ma->ma_pri); 837 return (UNCONF); 838} 839 840int 841findroot(void) 842{ 843 int node; 844 845 if ((node = rootnode) == 0 && (node = OF_peer(0)) == 0) 846 panic("no PROM root device"); 847 rootnode = node; 848 return (node); 849} 850 851/* 852 * Given a `first child' node number, locate the node with the given name. 853 * Return the node number, or 0 if not found. 854 */ 855int 856findnode(int first, const char *name) 857{ 858 int node; 859 char buf[32]; 860 861 for (node = first; node; node = OF_peer(node)) { 862 if ((OF_getprop(node, "name", buf, sizeof(buf)) > 0) && 863 (strcmp(buf, name) == 0)) 864 return (node); 865 } 866 return (0); 867} 868 869int 870mainbus_match(struct device *parent, void *cf, void *aux) 871{ 872 return (1); 873} 874 875/* 876 * Attach the mainbus. 877 * 878 * Our main job is to attach the CPU (the root node we got in cpu_configure()) 879 * and iterate down the list of `mainbus devices' (children of that node). 880 * We also record the `node id' of the default frame buffer, if any. 881 */ 882static void 883mainbus_attach(struct device *parent, struct device *dev, void *aux) 884{ 885extern struct sparc_bus_dma_tag mainbus_dma_tag; 886extern bus_space_tag_t mainbus_space_tag; 887 888 struct mainbus_attach_args ma; 889 char buf[64]; 890 const char *const *ssp, *sp = NULL; 891 int node0, node, rv, len; 892 893 static const char *const openboot_special[] = { 894 /* ignore these (end with NULL) */ 895 /* 896 * These are _root_ devices to ignore. Others must be handled 897 * elsewhere. 898 */ 899 "virtual-memory", 900 "aliases", 901 "memory", 902 "openprom", 903 "options", 904 "packages", 905 "chosen", 906 "counter-timer", 907 NULL 908 }; 909 910 /* 911 * Print the "banner-name" property in dmesg. It provides a 912 * description of the machine that is generally more 913 * informative than the "name" property. However, if the 914 * "banner-name" property is missing, fall back on the "name" 915 * property. 916 */ 917 if (OF_getprop(findroot(), "banner-name", buf, sizeof(buf)) > 0 || 918 OF_getprop(findroot(), "name", buf, sizeof(buf)) > 0) 919 printf(": %s\n", buf); 920 else 921 printf("\n"); 922 923 /* 924 * Base the hw.product and hw.vendor strings on the "name" 925 * property. They describe the hardware in a much more 926 * consistent way than the "banner-property". 927 */ 928 if ((len = OF_getprop(findroot(), "name", buf, sizeof(buf))) > 0) { 929 hw_prod = malloc(len, M_DEVBUF, M_NOWAIT); 930 if (hw_prod) 931 strlcpy(hw_prod, buf, len); 932 933 if (strncmp(buf, "SUNW,", 5) == 0) 934 hw_vendor = "Sun"; 935 if (strncmp(buf, "FJSV,", 5) == 0) 936 hw_vendor = "Fujitsu"; 937 if (strncmp(buf, "TAD,", 4) == 0) 938 hw_vendor = "Tadpole"; 939 if (strncmp(buf, "NATE,", 5) == 0) 940 hw_vendor = "Naturetech"; 941 if (strncmp(buf, "ORCL,", 5) == 0) 942 hw_vendor = "Oracle"; 943 944 /* 945 * The Momentum Leopard-V advertises itself as 946 * SUNW,UltraSPARC-IIi-Engine, but can be 947 * distinguished by looking at the "model" property. 948 */ 949 if (OF_getprop(findroot(), "model", buf, sizeof(buf)) > 0 && 950 strncmp(buf, "MOMENTUM,", 9) == 0) 951 hw_vendor = "Momentum"; 952 } 953 954 /* Establish the first component of the boot path */ 955 bootpath_store(1, bootpath); 956 957 /* We configure the CPUs first. */ 958 959 node = findroot(); 960 for (node0 = OF_child(node); node0; node0 = OF_peer(node0)) { 961 if (OF_getprop(node0, "name", buf, sizeof(buf)) <= 0) 962 continue; 963 } 964 965 for (node = OF_child(node); node; node = OF_peer(node)) { 966 if (!checkstatus(node)) 967 continue; 968 969 /* 970 * UltraSPARC-IV cpus appear as two "cpu" nodes below 971 * a "cmp" node. 972 */ 973 if (OF_getprop(node, "name", buf, sizeof(buf)) <= 0) 974 continue; 975 if (strcmp(buf, "cmp") == 0) { 976 bzero(&ma, sizeof(ma)); 977 ma.ma_node = node; 978 ma.ma_name = buf; 979 getprop(node, "reg", sizeof(*ma.ma_reg), 980 &ma.ma_nreg, (void **)&ma.ma_reg); 981 config_found(dev, &ma, mbprint); 982 continue; 983 } 984 985 if (OF_getprop(node, "device_type", buf, sizeof(buf)) <= 0) 986 continue; 987 if (strcmp(buf, "cpu") == 0) { 988 bzero(&ma, sizeof(ma)); 989 ma.ma_node = node; 990 OF_getprop(node, "name", buf, sizeof(buf)); 991 if (strcmp(buf, "cpu") == 0) 992 OF_getprop(node, "compatible", buf, sizeof(buf)); 993 ma.ma_name = buf; 994 getprop(node, "reg", sizeof(*ma.ma_reg), 995 &ma.ma_nreg, (void **)&ma.ma_reg); 996 config_found(dev, &ma, mbprint); 997 continue; 998 } 999 } 1000 1001 node = findroot(); /* re-init root node */ 1002 1003 /* Find the "options" node */ 1004 node0 = OF_child(node); 1005 optionsnode = findnode(node0, "options"); 1006 if (optionsnode == 0) 1007 panic("no options in OPENPROM"); 1008 1009 for (node0 = OF_child(node); node0; node0 = OF_peer(node0)) { 1010 if (OF_getprop(node0, "name", buf, sizeof(buf)) <= 0) 1011 continue; 1012 } 1013 1014 /* 1015 * Configure the devices, in PROM order. Skip 1016 * PROM entries that are not for devices, or which must be 1017 * done before we get here. 1018 */ 1019 for (node = OF_child(node); node; node = OF_peer(node)) { 1020 int portid; 1021 1022 DPRINTF(ACDB_PROBE, ("Node: %x", node)); 1023 if (OF_getprop(node, "device_type", buf, sizeof(buf)) > 0 && 1024 strcmp(buf, "cpu") == 0) 1025 continue; 1026 if (OF_getprop(node, "name", buf, sizeof(buf)) > 0 && 1027 strcmp(buf, "cmp") == 0) 1028 continue; 1029 DPRINTF(ACDB_PROBE, (" name %s\n", buf)); 1030 for (ssp = openboot_special; (sp = *ssp) != NULL; ssp++) 1031 if (strcmp(buf, sp) == 0) 1032 break; 1033 if (sp != NULL) 1034 continue; /* an "early" device already configured */ 1035 1036 if (!checkstatus(node)) 1037 continue; 1038 1039 bzero(&ma, sizeof ma); 1040 ma.ma_bustag = mainbus_space_tag; 1041 ma.ma_dmatag = &mainbus_dma_tag; 1042 ma.ma_name = buf; 1043 ma.ma_node = node; 1044 if (OF_getprop(node, "upa-portid", &portid, sizeof(portid)) != 1045 sizeof(portid)) { 1046 if (OF_getprop(node, "portid", &portid, 1047 sizeof(portid)) != sizeof(portid)) 1048 portid = -1; 1049 } 1050 ma.ma_upaid = portid; 1051 1052 if (getprop(node, "reg", sizeof(*ma.ma_reg), 1053 &ma.ma_nreg, (void **)&ma.ma_reg) != 0) 1054 continue; 1055#ifdef DEBUG 1056 if (autoconf_debug & ACDB_PROBE) { 1057 if (ma.ma_nreg) 1058 printf(" reg %08lx.%08lx\n", 1059 (long)ma.ma_reg->ur_paddr, 1060 (long)ma.ma_reg->ur_len); 1061 else 1062 printf(" no reg\n"); 1063 } 1064#endif 1065 rv = getprop(node, "interrupts", sizeof(*ma.ma_interrupts), 1066 &ma.ma_ninterrupts, (void **)&ma.ma_interrupts); 1067 if (rv != 0 && rv != ENOENT) { 1068 free(ma.ma_reg, M_DEVBUF, 0); 1069 continue; 1070 } 1071#ifdef DEBUG 1072 if (autoconf_debug & ACDB_PROBE) { 1073 if (ma.ma_interrupts) 1074 printf(" interrupts %08x\n", 1075 *ma.ma_interrupts); 1076 else 1077 printf(" no interrupts\n"); 1078 } 1079#endif 1080 rv = getprop(node, "address", sizeof(*ma.ma_address), 1081 &ma.ma_naddress, (void **)&ma.ma_address); 1082 if (rv != 0 && rv != ENOENT) { 1083 free(ma.ma_reg, M_DEVBUF, 0); 1084 free(ma.ma_interrupts, M_DEVBUF, 0); 1085 continue; 1086 } 1087#ifdef DEBUG 1088 if (autoconf_debug & ACDB_PROBE) { 1089 if (ma.ma_naddress) 1090 printf(" address %08x\n", 1091 *ma.ma_address); 1092 else 1093 printf(" no address\n"); 1094 } 1095#endif 1096 config_found(dev, &ma, mbprint); 1097 free(ma.ma_reg, M_DEVBUF, 0); 1098 free(ma.ma_interrupts, M_DEVBUF, 0); 1099 free(ma.ma_address, M_DEVBUF, 0); 1100 } 1101 1102 extern int prom_cngetc(dev_t); 1103 1104 /* Attach PROM console if no other console attached. */ 1105 if (cn_tab->cn_getc == prom_cngetc) { 1106 bzero(&ma, sizeof ma); 1107 ma.ma_name = "pcons"; 1108 config_found(dev, &ma, mbprint); 1109 } 1110 1111 extern todr_chip_handle_t todr_handle; 1112 1113 if (todr_handle == NULL) { 1114 bzero(&ma, sizeof ma); 1115 ma.ma_name = "prtc"; 1116 config_found(dev, &ma, mbprint); 1117 } 1118} 1119 1120const struct cfattach mainbus_ca = { 1121 sizeof(struct device), mainbus_match, mainbus_attach 1122}; 1123 1124int 1125getprop(int node, char *name, size_t size, int *nitem, void **bufp) 1126{ 1127 void *buf; 1128 long len; 1129 1130 *nitem = 0; 1131 len = getproplen(node, name); 1132 if (len <= 0) 1133 return (ENOENT); 1134 1135 if ((len % size) != 0) 1136 return (EINVAL); 1137 1138 buf = *bufp; 1139 if (buf == NULL) { 1140 /* No storage provided, so we allocate some */ 1141 buf = malloc(len + 1, M_DEVBUF, M_NOWAIT); 1142 if (buf == NULL) 1143 return (ENOMEM); 1144 } 1145 1146 OF_getprop(node, name, buf, len); 1147 *bufp = buf; 1148 *nitem = len / size; 1149 return (0); 1150} 1151 1152 1153/* 1154 * Internal form of proplen(). Returns the property length. 1155 */ 1156long 1157getproplen(int node, char *name) 1158{ 1159 return (OF_getproplen(node, name)); 1160} 1161 1162/* 1163 * Return a string property. There is a (small) limit on the length; 1164 * the string is fetched into a static buffer which is overwritten on 1165 * subsequent calls. 1166 */ 1167char * 1168getpropstring(int node, char *name) 1169{ 1170 static char stringbuf[32]; 1171 1172 return (getpropstringA(node, name, stringbuf)); 1173} 1174 1175/* Alternative getpropstring(), where caller provides the buffer */ 1176char * 1177getpropstringA(int node, char *name, char *buffer) 1178{ 1179 int blen; 1180 1181 if (getprop(node, name, 1, &blen, (void **)&buffer) != 0) 1182 blen = 0; 1183 1184 buffer[blen] = '\0'; /* usually unnecessary */ 1185 return (buffer); 1186} 1187 1188/* 1189 * Fetch an integer (or pointer) property. 1190 * The return value is the property, or the default if there was none. 1191 */ 1192int 1193getpropint(int node, char *name, int deflt) 1194{ 1195 int intbuf; 1196 1197 if (OF_getprop(node, name, &intbuf, sizeof(intbuf)) != sizeof(intbuf)) 1198 return (deflt); 1199 1200 return (intbuf); 1201} 1202 1203int 1204getpropspeed(int node, char *name) 1205{ 1206 char buf[128]; 1207 int i, speed = 0; 1208 1209 if (OF_getprop(node, name, buf, sizeof(buf)) != -1) { 1210 for (i = 0; i < sizeof(buf); i++) { 1211 if (buf[i] < '0' || buf[i] > '9') 1212 break; 1213 speed *= 10; 1214 speed += buf[i] - '0'; 1215 } 1216 } 1217 1218 if (speed == 0) 1219 speed = 9600; 1220 1221 return (speed); 1222} 1223 1224/* 1225 * OPENPROM functions. These are here mainly to hide the OPENPROM interface 1226 * from the rest of the kernel. 1227 */ 1228int 1229firstchild(int node) 1230{ 1231 1232 return OF_child(node); 1233} 1234 1235int 1236nextsibling(int node) 1237{ 1238 1239 return OF_peer(node); 1240} 1241 1242int 1243checkstatus(int node) 1244{ 1245 char buf[32]; 1246 1247 /* If there is no "status" property, assume everything is fine. */ 1248 if (OF_getprop(node, "status", buf, sizeof(buf)) <= 0) 1249 return 1; 1250 1251 /* 1252 * If OpenBoot Diagnostics discovers a problem with a device 1253 * it will mark it with "fail" or "fail-xxx", where "xxx" is 1254 * additional human-readable information about the particular 1255 * fault-condition. 1256 */ 1257 if (strcmp(buf, "disabled") == 0 || strncmp(buf, "fail", 4) == 0) 1258 return 0; 1259 1260 return 1; 1261} 1262 1263/* returns 1 if node has given property */ 1264int 1265node_has_property(int node, const char *prop) 1266{ 1267 return (OF_getproplen(node, (caddr_t)prop) != -1); 1268} 1269 1270/* 1271 * Try to figure out where the PROM stores the cursor row & column 1272 * variables. Returns nonzero on error. 1273 */ 1274int 1275romgetcursoraddr(int **rowp, int **colp) 1276{ 1277 cell_t row = 0, col = 0; 1278 1279 OF_interpret("stdout @ is my-self addr line# addr column# ", 1280 2, &col, &row); 1281 1282 /* 1283 * We are running on a 64-bit big-endian machine, so these things 1284 * point to 64-bit big-endian values. To convert them to pointers 1285 * to int, add 4 to the address. 1286 */ 1287 if (row == 0 || col == 0) 1288 return (-1); 1289 *rowp = (int *)(row + 4); 1290 *colp = (int *)(col + 4); 1291 return (0); 1292} 1293 1294void 1295callrom(void) 1296{ 1297 1298 __asm volatile("wrpr %%g0, 0, %%tl" : ); 1299 OF_enter(); 1300} 1301 1302/* 1303 * find a device matching "name" and unit number 1304 */ 1305struct device * 1306getdevunit(const char *name, int unit) 1307{ 1308 struct device *dev = TAILQ_FIRST(&alldevs); 1309 char num[10], fullname[16]; 1310 int lunit; 1311 1312 /* compute length of name and decimal expansion of unit number */ 1313 snprintf(num, sizeof num, "%d", unit); 1314 lunit = strlen(num); 1315 if (strlen(name) + lunit >= sizeof(fullname) - 1) 1316 panic("config_attach: device name too long"); 1317 1318 strlcpy(fullname, name, sizeof fullname); 1319 strlcat(fullname, num, sizeof fullname); 1320 1321 while (strcmp(dev->dv_xname, fullname) != 0) { 1322 if ((dev = TAILQ_NEXT(dev, dv_list)) == NULL) 1323 return NULL; 1324 } 1325 return dev; 1326} 1327 1328void 1329device_register(struct device *dev, void *aux) 1330{ 1331 struct mainbus_attach_args *ma = aux; 1332 struct pci_attach_args *pa = aux; 1333 struct sbus_attach_args *sa = aux; 1334 struct vbus_attach_args *va = aux; 1335 struct cbus_attach_args *ca = aux; 1336 struct bootpath *bp = bootpath_store(0, NULL); 1337 struct device *busdev = dev->dv_parent; 1338 const char *devname = dev->dv_cfdata->cf_driver->cd_name; 1339 const char *busname; 1340 int node = -1; 1341 1342 /* 1343 * There is no point in continuing if we've exhausted all 1344 * bootpath components. 1345 */ 1346 if (bp == NULL) 1347 return; 1348 1349 DPRINTF(ACDB_BOOTDEV, 1350 ("\n%s: device_register: devname %s(%s) component %s\n", 1351 dev->dv_xname, devname, dev->dv_xname, bp->name)); 1352 1353 /* 1354 * Ignore mainbus0 itself, it certainly is not a boot device. 1355 */ 1356 if (busdev == NULL) 1357 return; 1358 1359 /* 1360 * We don't know the type of 'aux'; it depends on the bus this 1361 * device attaches to. We are only interested in certain bus 1362 * types; this is only used to find the boot device. 1363 */ 1364 busname = busdev->dv_cfdata->cf_driver->cd_name; 1365 if (strcmp(busname, "mainbus") == 0 || 1366 strcmp(busname, "ssm") == 0 || strcmp(busname, "upa") == 0) 1367 node = ma->ma_node; 1368 else if (strcmp(busname, "sbus") == 0 || 1369 strcmp(busname, "dma") == 0 || strcmp(busname, "ledma") == 0) 1370 node = sa->sa_node; 1371 else if (strcmp(busname, "vbus") == 0) 1372 node = va->va_node; 1373 else if (strcmp(busname, "cbus") == 0) 1374 node = ca->ca_node; 1375 else if (strcmp(busname, "pci") == 0) 1376 node = PCITAG_NODE(pa->pa_tag); 1377 1378 if (node == bootnode) { 1379 if (strcmp(devname, "vdsk") == 0) { 1380 /* 1381 * For virtual disks, don't nail the boot 1382 * device just yet. Instead, we add fake a 1383 * SCSI target/lun, such that we match it the 1384 * next time around. 1385 */ 1386 bp->dev = dev; 1387 (bp + 1)->val[0] = 0; 1388 (bp + 1)->val[1] = 0; 1389 nbootpath++; 1390 bootpath_store(1, bp + 1); 1391 return; 1392 } 1393 1394 nail_bootdev(dev, bp); 1395 return; 1396 } 1397 1398 if (node == bp->node) { 1399 bp->dev = dev; 1400 DPRINTF(ACDB_BOOTDEV, ("\t-- matched component %s to %s\n", 1401 bp->name, dev->dv_xname)); 1402 bootpath_store(1, bp + 1); 1403 return; 1404 } 1405 1406 if (strcmp(devname, "scsibus") == 0) { 1407 /* 1408 * Booting from anything but the first (physical) port 1409 * isn't supported by OBP. 1410 */ 1411 if (strcmp(bp->name, "fp") == 0 && bp->val[0] == 0) { 1412 DPRINTF(ACDB_BOOTDEV, ("\t-- matched component %s to %s\n", 1413 bp->name, dev->dv_xname)); 1414 bootpath_store(1, bp + 1); 1415 return; 1416 } 1417 } 1418 1419 if (strcmp(busname, "scsibus") == 0) { 1420 /* 1421 * A SCSI disk or cd; retrieve target/lun information 1422 * from parent and match with current bootpath component. 1423 * Note that we also have look back past the `scsibus' 1424 * device to determine whether this target is on the 1425 * correct controller in our boot path. 1426 */ 1427 struct scsi_attach_args *sa = aux; 1428 struct scsi_link *sl = sa->sa_sc_link; 1429 u_int target = bp->val[0]; 1430 u_int lun = bp->val[1]; 1431 1432 if (bp->val[0] & 0xffffffff00000000 && bp->val[0] != -1) { 1433 /* Hardware RAID or Fibre channel? */ 1434 if (bp->val[0] == sl->port_wwn && lun == sl->lun) { 1435 nail_bootdev(dev, bp); 1436 } 1437 1438 /* 1439 * sata devices on some controllers don't get 1440 * port_wwn filled in, so look at devid too. 1441 */ 1442 if (sl->id && sl->id->d_len == 8 && 1443 sl->id->d_type == DEVID_NAA && 1444 memcmp(sl->id + 1, &bp->val[0], 8) == 0) 1445 nail_bootdev(dev, bp); 1446 return; 1447 } 1448 1449 /* Check the controller that this scsibus is on. */ 1450 if ((bp-1)->dev != sl->bus->sc_dev.dv_parent) 1451 return; 1452 1453 /* 1454 * Bounds check: we know the target and lun widths. 1455 */ 1456 if (target >= sl->bus->sb_adapter_buswidth || 1457 lun >= sl->bus->sb_luns) { 1458 printf("SCSI disk bootpath component not accepted: " 1459 "target %u; lun %u\n", target, lun); 1460 return; 1461 } 1462 1463 if (target == sl->target && lun == sl->lun) { 1464 nail_bootdev(dev, bp); 1465 return; 1466 } 1467 } 1468 1469 if (strcmp("wd", devname) == 0) { 1470 /* IDE disks. */ 1471 struct ata_atapi_attach *aa = aux; 1472 u_int channel, drive; 1473 1474 if (strcmp(bp->name, "ata") == 0 && 1475 bp->val[0] == aa->aa_channel) { 1476 channel = bp->val[0]; bp++; 1477 drive = bp->val[0]; 1478 } else { 1479 channel = bp->val[0] / 2; 1480 drive = bp->val[0] % 2; 1481 } 1482 1483 if (channel == aa->aa_channel && 1484 drive == aa->aa_drv_data->drive) { 1485 nail_bootdev(dev, bp); 1486 return; 1487 } 1488 } 1489} 1490 1491void 1492nail_bootdev(struct device *dev, struct bootpath *bp) 1493{ 1494 1495 if (bp->dev != NULL) 1496 panic("device_register: already got a boot device: %s", 1497 bp->dev->dv_xname); 1498 1499 /* 1500 * Mark this bootpath component by linking it to the matched 1501 * device. We pick up the device pointer in cpu_rootconf(). 1502 */ 1503 booted_device = bp->dev = dev; 1504 DPRINTF(ACDB_BOOTDEV, ("\t-- found bootdevice: %s\n",dev->dv_xname)); 1505 1506 /* 1507 * Then clear the current bootpath component, so we don't spuriously 1508 * match similar instances on other busses, e.g. a disk on 1509 * another SCSI bus with the same target. 1510 */ 1511 bootpath_store(1, NULL); 1512} 1513 1514const struct nam2blk nam2blk[] = { 1515 { "rd", 5 }, 1516 { "sd", 7 }, 1517 { "vnd", 8 }, 1518 { "wd", 12 }, 1519 { "fd", 16 }, 1520 { "cd", 18 }, 1521 { NULL, -1 } 1522}; 1523