1 /* $NetBSD: autoconf.c,v 1.273 2025/10/13 04:04:52 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1996 5 * The President and Fellows of Harvard College. All rights reserved. 6 * Copyright (c) 1992, 1993 7 * The Regents of the University of California. All rights reserved. 8 * 9 * This software was developed by the Computer Systems Engineering group 10 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 11 * contributed to Berkeley. 12 * 13 * All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Harvard University. 16 * This product includes software developed by the University of 17 * California, Lawrence Berkeley Laboratory. 18 * 19 * Redistribution and use in source and binary forms, with or without 20 * modification, are permitted provided that the following conditions 21 * are met: 22 * 1. Redistributions of source code must retain the above copyright 23 * notice, this list of conditions and the following disclaimer. 24 * 2. Redistributions in binary form must reproduce the above copyright 25 * notice, this list of conditions and the following disclaimer in the 26 * documentation and/or other materials provided with the distribution. 27 * 3. All advertising materials mentioning features or use of this software 28 * must display the following acknowledgement: 29 * This product includes software developed by the University of 30 * California, Berkeley and its contributors. 31 * 4. Neither the name of the University nor the names of its contributors 32 * may be used to endorse or promote products derived from this software 33 * without specific prior written permission. 34 * 35 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 36 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 38 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 39 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 40 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 41 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 42 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 43 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 44 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 45 * SUCH DAMAGE. 46 * 47 * @(#)autoconf.c 8.4 (Berkeley) 10/1/93 48 */ 49 50 #include <sys/cdefs.h> 51 __KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.273 2025/10/13 04:04:52 thorpej Exp $"); 52 53 #include "opt_ddb.h" 54 #include "opt_kgdb.h" 55 #include "opt_modular.h" 56 #include "opt_multiprocessor.h" 57 #include "opt_sparc_arch.h" 58 59 #include "scsibus.h" 60 61 #include <sys/param.h> 62 #include <sys/kernel.h> 63 #include <sys/systm.h> 64 #include <sys/endian.h> 65 #include <sys/proc.h> 66 #include <sys/buf.h> 67 #include <sys/disklabel.h> 68 #include <sys/device.h> 69 #include <sys/disk.h> 70 #include <sys/conf.h> 71 #include <sys/reboot.h> 72 #include <sys/socket.h> 73 #include <sys/queue.h> 74 #include <sys/msgbuf.h> 75 #include <sys/boot_flag.h> 76 #include <sys/ksyms.h> 77 #include <sys/userconf.h> 78 #include <sys/kgdb.h> 79 80 #include <net/if.h> 81 #include <net/if_ether.h> 82 #include <net/ether_calls.h> 83 84 #include <dev/cons.h> 85 86 #include <uvm/uvm_extern.h> 87 88 #include <machine/pcb.h> 89 #include <sys/bus.h> 90 #include <machine/promlib.h> 91 #include <machine/autoconf.h> 92 #include <machine/bootinfo.h> 93 #include <machine/locore.h> 94 95 #include <sparc/sparc/memreg.h> 96 #include <machine/cpu.h> 97 #include <machine/ctlreg.h> 98 #include <sparc/sparc/asm.h> 99 #include <sparc/sparc/cpuvar.h> 100 #include <sparc/sparc/timerreg.h> 101 #include <sparc/dev/cons.h> 102 103 #include <dev/pci/pcireg.h> 104 #include <dev/pci/pcidevs.h> 105 #include <dev/pci/pcivar.h> 106 #include <sparc/sparc/msiiepreg.h> 107 108 #ifdef DDB 109 #include <machine/db_machdep.h> 110 #include <ddb/db_sym.h> 111 #include <ddb/db_extern.h> 112 #include <ddb/ddbvar.h> 113 #endif 114 115 #include "ksyms.h" 116 117 /* 118 * The following several variables are related to 119 * the configuration process, and are used in initializing 120 * the machine. 121 */ 122 123 #if !NKSYMS && !defined(DDB) && !defined(MODULAR) 124 void bootinfo_relocate(void *); 125 #endif 126 127 static const char *str2hex(const char *, int *); 128 static int mbprint(void *, const char *); 129 static void crazymap(const char *, int *); 130 int st_crazymap(int); 131 int sd_crazymap(int); 132 void sync_crash(void); 133 int mainbus_match(device_t, cfdata_t, void *); 134 static void mainbus_attach(device_t, device_t, void *); 135 136 struct bootpath bootpath[8]; 137 int nbootpath; 138 static void bootpath_build(void); 139 static void bootpath_fake(struct bootpath *, const char *); 140 static void bootpath_print(struct bootpath *); 141 static struct bootpath *bootpath_store(int, struct bootpath *); 142 static int find_cpus(void); 143 char machine_model[100]; 144 145 #ifdef DEBUG 146 #define ACDB_BOOTDEV 0x1 147 #define ACDB_PROBE 0x2 148 int autoconf_debug = 0; 149 #define DPRINTF(l, s) do { if (autoconf_debug & l) printf s; } while (0) 150 #else 151 #define DPRINTF(l, s) 152 #endif 153 154 /* 155 * Most configuration on the SPARC is done by matching OPENPROM Forth 156 * device names with our internal names. 157 */ 158 int 159 matchbyname(device_t parent, cfdata_t cf, void *aux) 160 { 161 162 printf("%s: WARNING: matchbyname\n", cf->cf_name); 163 return (0); 164 } 165 166 /* 167 * Set machine_model[] to something useful. If late is set, then 168 * have now probed the sun4 class and can finish it. Other systems 169 * are complete with the first call with late=false out of bootstrap. 170 */ 171 static void 172 set_machine_model(bool late) 173 { 174 char namebuf[32]; 175 176 if (!CPU_ISSUN4) { 177 if (late) { 178 KASSERT(machine_model[0] != '\0'); 179 } else { 180 snprintf(machine_model, sizeof machine_model, "%s", 181 prom_getpropstringA(findroot(), "name", namebuf, 182 sizeof(namebuf))); 183 } 184 return; 185 } 186 if (late) 187 snprintf(machine_model, sizeof machine_model, "SUN-4/%d series", 188 cpuinfo.classlvl); 189 else 190 snprintf(machine_model, sizeof machine_model, "SUN-4 series"); 191 } 192 193 /* 194 * Get the number of CPUs in the system and the CPUs' SPARC architecture 195 * version. We need this information early in the boot process. 196 * 197 * This also sets cpu_arch to 8 on sun4m and sun4d. 198 */ 199 static int 200 find_cpus(void) 201 { 202 int n; 203 #if defined(SUN4M) || defined(SUN4D) 204 int node; 205 #endif 206 /* 207 * Set default processor architecture version 208 * 209 * All sun4 and sun4c platforms have v7 CPUs; 210 * sun4m may have v7 (Cyrus CY7C601 modules) or v8 CPUs (all 211 * other models, presumably). 212 */ 213 cpu_arch = 7; 214 215 /* Initialise machine_model, early phase. */ 216 set_machine_model(false); 217 218 /* On sun4 and sun4c we support only one CPU */ 219 if (!CPU_ISSUN4M && !CPU_ISSUN4D) 220 return (1); 221 222 n = 0; 223 #if defined(SUN4M) 224 node = findroot(); 225 for (node = firstchild(node); node; node = nextsibling(node)) { 226 if (strcmp(prom_getpropstring(node, "device_type"), "cpu") != 0) 227 continue; 228 if (n++ == 0) 229 cpu_arch = prom_getpropint(node, "sparc-version", 7); 230 } 231 #endif /* SUN4M */ 232 #if defined(SUN4D) 233 node = findroot(); 234 for (node = firstchild(node); node; node = nextsibling(node)) { 235 int unode; 236 237 if (strcmp(prom_getpropstring(node, "name"), "cpu-unit") != 0) 238 continue; 239 for (unode = firstchild(node); unode; 240 unode = nextsibling(unode)) { 241 if (strcmp(prom_getpropstring(unode, "device_type"), 242 "cpu") != 0) 243 continue; 244 if (n++ == 0) 245 cpu_arch = prom_getpropint(unode, 246 "sparc-version", 7); 247 } 248 } 249 #endif 250 251 return (n); 252 } 253 254 /* 255 * Convert hex ASCII string to a value. Returns updated pointer. 256 * Depends on ASCII order (this *is* machine-dependent code, you know). 257 */ 258 static const char * 259 str2hex(const char *str, int *vp) 260 { 261 int v, c; 262 263 for (v = 0;; v = v * 16 + c, str++) { 264 c = (u_char)*str; 265 if (c <= '9') { 266 if ((c -= '0') < 0) 267 break; 268 } else if (c <= 'F') { 269 if ((c -= 'A' - 10) < 10) 270 break; 271 } else if (c <= 'f') { 272 if ((c -= 'a' - 10) < 10) 273 break; 274 } else 275 break; 276 } 277 *vp = v; 278 return (str); 279 } 280 281 282 #if defined(SUN4M) 283 #if !defined(MSIIEP) 284 static void bootstrap4m(void); 285 #else 286 static void bootstrapIIep(void); 287 #endif 288 #endif /* SUN4M */ 289 290 /* 291 * locore.s code calls bootstrap() just before calling main(), after double 292 * mapping the kernel to high memory and setting up the trap base register. 293 * We must finish mapping the kernel properly and glean any bootstrap info. 294 */ 295 void 296 bootstrap(void) 297 { 298 #if NKSYMS || defined(DDB) || defined(MODULAR) 299 struct btinfo_symtab *bi_sym; 300 #endif 301 struct btinfo_boothowto *bi_howto; 302 303 cn_tab = &consdev_prom; 304 prom_init(); 305 306 /* Find the number of CPUs as early as possible */ 307 sparc_ncpus = find_cpus(); 308 uvm_lwp_setuarea(&lwp0, (vaddr_t)u0); 309 310 cpuinfo.master = 1; 311 getcpuinfo(&cpuinfo, 0); 312 curlwp = &lwp0; 313 314 #if defined(SUN4M) || defined(SUN4D) 315 /* Switch to sparc v8 multiply/divide functions on v8 machines */ 316 if (cpu_arch == 8) { 317 sparc_v8_muldiv(); 318 } 319 #endif /* SUN4M || SUN4D */ 320 321 #if !NKSYMS && !defined(DDB) && !defined(MODULAR) 322 /* 323 * We want to reuse the memory where the symbols were stored 324 * by the loader. Relocate the bootinfo array which is loaded 325 * above the symbols (we assume) to the start of BSS. Then 326 * adjust kernel_top accordingly. 327 */ 328 329 bootinfo_relocate((void *)ALIGN((u_int)end)); 330 #endif 331 332 pmap_bootstrap(cpuinfo.mmu_ncontext, 333 cpuinfo.mmu_nregion, 334 cpuinfo.mmu_nsegment); 335 336 #if !defined(MSGBUFSIZE) || MSGBUFSIZE == 8192 337 /* 338 * Now that the kernel map has been set up, we can enable 339 * the message buffer at the first physical page in the 340 * memory bank where we were loaded. There are 8192 341 * bytes available for the buffer at this location (see the 342 * comment in locore.s at the top of the .text segment). 343 */ 344 initmsgbuf((void *)KERNBASE, 8192); 345 #endif 346 347 #if defined(SUN4M) 348 /* 349 * sun4m bootstrap is complex and is totally different for "normal" 4m 350 * and for microSPARC-IIep - so it's split into separate functions. 351 */ 352 if (CPU_ISSUN4M) { 353 #if !defined(MSIIEP) 354 bootstrap4m(); 355 #else 356 bootstrapIIep(); 357 #endif 358 } 359 #endif /* SUN4M */ 360 361 #if defined(SUN4) || defined(SUN4C) 362 if (CPU_ISSUN4 || CPU_ISSUN4C) { 363 /* Map Interrupt Enable Register */ 364 pmap_kenter_pa(INTRREG_VA, 365 INT_ENABLE_REG_PHYSADR | PMAP_NC | PMAP_OBIO, 366 VM_PROT_READ | VM_PROT_WRITE, 0); 367 pmap_update(pmap_kernel()); 368 /* Disable all interrupts */ 369 *((unsigned char *)INTRREG_VA) = 0; 370 } 371 #endif /* SUN4 || SUN4C */ 372 373 #if NKSYMS || defined(DDB) || defined(MODULAR) 374 if ((bi_sym = lookup_bootinfo(BTINFO_SYMTAB)) != NULL) { 375 if (bi_sym->ssym < KERNBASE) { 376 /* Assume low-loading boot loader */ 377 bi_sym->ssym += KERNBASE; 378 bi_sym->esym += KERNBASE; 379 } 380 ksyms_addsyms_elf(bi_sym->nsym, (void*)bi_sym->ssym, 381 (void*)bi_sym->esym); 382 } 383 #endif 384 385 if ((bi_howto = lookup_bootinfo(BTINFO_BOOTHOWTO)) != NULL) { 386 boothowto = bi_howto->boothowto; 387 } 388 } 389 390 #if defined(SUN4M) && !defined(MSIIEP) 391 /* 392 * On sun4ms we have to do some nasty stuff here. We need to map 393 * in the interrupt registers (since we need to find out where 394 * they are from the PROM, since they aren't in a fixed place), and 395 * disable all interrupts. We can't do this easily from locore 396 * since the PROM is ugly to use from assembly. We also need to map 397 * in the counter registers because we can't disable the level 14 398 * (statclock) interrupt, so we need a handler early on (ugh). 399 * 400 * NOTE: We *demand* the psl to stay at splhigh() at least until 401 * we get here. The system _cannot_ take interrupts until we map 402 * the interrupt registers. 403 */ 404 static void 405 bootstrap4m(void) 406 { 407 int node; 408 int nvaddrs, *vaddrs, vstore[10]; 409 u_int pte; 410 int i; 411 412 if ((node = prom_opennode("/obio/interrupt")) == 0 413 && (node = prom_finddevice("/obio/interrupt")) == 0) 414 panic("bootstrap: could not get interrupt " 415 "node from prom"); 416 417 vaddrs = vstore; 418 nvaddrs = sizeof(vstore)/sizeof(vstore[0]); 419 if (prom_getprop(node, "address", sizeof(int), 420 &nvaddrs, &vaddrs) != 0) { 421 printf("bootstrap: could not get interrupt properties"); 422 prom_halt(); 423 } 424 if (nvaddrs < 2 || nvaddrs > 5) { 425 printf("bootstrap: cannot handle %d interrupt regs\n", 426 nvaddrs); 427 prom_halt(); 428 } 429 430 for (i = 0; i < nvaddrs - 1; i++) { 431 pte = getpte4m((u_int)vaddrs[i]); 432 if ((pte & SRMMU_TETYPE) != SRMMU_TEPTE) { 433 panic("bootstrap: PROM has invalid mapping for " 434 "processor interrupt register %d",i); 435 prom_halt(); 436 } 437 pte |= PPROT_S; 438 439 /* Duplicate existing mapping */ 440 setpte4m(PI_INTR_VA + (_MAXNBPG * i), pte); 441 } 442 cpuinfo.intreg_4m = (struct icr_pi *) 443 (PI_INTR_VA + (_MAXNBPG * CPU_MID2CPUNO(bootmid))); 444 445 /* 446 * That was the processor register...now get system register; 447 * it is the last returned by the PROM 448 */ 449 pte = getpte4m((u_int)vaddrs[i]); 450 if ((pte & SRMMU_TETYPE) != SRMMU_TEPTE) 451 panic("bootstrap: PROM has invalid mapping for system " 452 "interrupt register"); 453 pte |= PPROT_S; 454 455 setpte4m(SI_INTR_VA, pte); 456 457 /* Now disable interrupts */ 458 icr_si_bis(SINTR_MA); 459 460 /* Send all interrupts to primary processor */ 461 *((u_int *)ICR_ITR) = CPU_MID2CPUNO(bootmid); 462 463 #ifdef DEBUG 464 /* printf("SINTR: mask: 0x%x, pend: 0x%x\n", *(int*)ICR_SI_MASK, 465 *(int*)ICR_SI_PEND); 466 */ 467 #endif 468 } 469 #endif /* SUN4M && !MSIIEP */ 470 471 472 #if defined(SUN4M) && defined(MSIIEP) 473 /* 474 * On ms-IIep all the interrupt registers, counters etc 475 * are PCIC registers, so we need to map it early. 476 */ 477 static void 478 bootstrapIIep(void) 479 { 480 int node; 481 bus_space_handle_t bh; 482 pcireg_t id; 483 484 if ((node = prom_opennode("/pci")) == 0 485 && (node = prom_finddevice("/pci")) == 0) 486 panic("bootstrap: could not get pci " 487 "node from prom"); 488 489 if (bus_space_map2(&mainbus_space_tag, 490 (bus_addr_t)MSIIEP_PCIC_PA, 491 (bus_size_t)sizeof(struct msiiep_pcic_reg), 492 BUS_SPACE_MAP_LINEAR, 493 MSIIEP_PCIC_VA, &bh) != 0) 494 panic("bootstrap: unable to map ms-IIep pcic registers"); 495 496 /* verify that it's PCIC */ 497 id = mspcic_read_4(pcic_id); 498 499 if (PCI_VENDOR(id) != PCI_VENDOR_SUN 500 && PCI_PRODUCT(id) != PCI_PRODUCT_SUN_MS_IIep) 501 panic("bootstrap: PCI id %08x", id); 502 } 503 504 #undef msiiep 505 #endif /* SUN4M && MSIIEP */ 506 507 508 /* 509 * bootpath_build: build a bootpath. Used when booting a generic 510 * kernel to find our root device. Newer proms give us a bootpath, 511 * for older proms we have to create one. An element in a bootpath 512 * has 4 fields: name (device name), val[0], val[1], and val[2]. Note that: 513 * Interpretation of val[] is device-dependent. Some examples: 514 * 515 * if (val[0] == -1) { 516 * val[1] is a unit number (happens most often with old proms) 517 * } else { 518 * [sbus device] val[0] is a sbus slot, and val[1] is an sbus offset 519 * [scsi disk] val[0] is target, val[1] is lun, val[2] is partition 520 * [scsi tape] val[0] is target, val[1] is lun, val[2] is file # 521 * } 522 * 523 */ 524 525 static void 526 bootpath_build(void) 527 { 528 const char *cp; 529 char *pp; 530 struct bootpath *bp; 531 int fl; 532 533 /* 534 * Grab boot path from PROM and split into `bootpath' components. 535 */ 536 memset(bootpath, 0, sizeof(bootpath)); 537 bp = bootpath; 538 cp = prom_getbootpath(); 539 switch (prom_version()) { 540 case PROM_OLDMON: 541 case PROM_OBP_V0: 542 /* 543 * Build fake bootpath. 544 */ 545 if (cp != NULL) 546 bootpath_fake(bp, cp); 547 break; 548 case PROM_OBP_V2: 549 case PROM_OBP_V3: 550 case PROM_OPENFIRM: 551 while (cp != NULL && *cp == '/') { 552 /* Step over '/' */ 553 ++cp; 554 /* Extract name */ 555 pp = bp->name; 556 while (*cp != '@' && *cp != '/' && *cp != '\0') 557 *pp++ = *cp++; 558 *pp = '\0'; 559 #if defined(SUN4M) 560 /* 561 * JS1/OF does not have iommu node in the device 562 * tree, so bootpath will start with the sbus entry. 563 * Add entry for iommu to match attachment. See also 564 * mainbus_attach and iommu_attach. 565 */ 566 if (CPU_ISSUN4M && bp == bootpath 567 && strcmp(bp->name, "sbus") == 0) { 568 printf("bootpath_build: inserting iommu entry\n"); 569 strcpy(bootpath[0].name, "iommu"); 570 bootpath[0].val[0] = 0; 571 bootpath[0].val[1] = 0x10000000; 572 bootpath[0].val[2] = 0; 573 ++nbootpath; 574 575 strcpy(bootpath[1].name, "sbus"); 576 if (*cp == '/') { 577 /* complete sbus entry */ 578 bootpath[1].val[0] = 0; 579 bootpath[1].val[1] = 0x10001000; 580 bootpath[1].val[2] = 0; 581 ++nbootpath; 582 bp = &bootpath[2]; 583 continue; 584 } else 585 bp = &bootpath[1]; 586 } 587 #endif /* SUN4M */ 588 if (*cp == '@') { 589 cp = str2hex(++cp, &bp->val[0]); 590 if (*cp == ',') 591 cp = str2hex(++cp, &bp->val[1]); 592 if (*cp == ':') { 593 /* XXX - we handle just one char */ 594 /* skip remainder of paths */ 595 /* like "ledma@f,400010:tpe" */ 596 bp->val[2] = *++cp - 'a'; 597 while (*++cp != '/' && *cp != '\0') 598 /*void*/; 599 } 600 } else { 601 bp->val[0] = -1; /* no #'s: assume unit 0, no 602 sbus offset/address */ 603 } 604 ++bp; 605 ++nbootpath; 606 } 607 bp->name[0] = 0; 608 break; 609 } 610 611 bootpath_print(bootpath); 612 613 /* Setup pointer to boot flags */ 614 cp = prom_getbootargs(); 615 if (cp == NULL) 616 return; 617 618 /* Skip any whitespace */ 619 while (*cp != '-') 620 if (*cp++ == '\0') 621 return; 622 623 for (;*++cp;) { 624 fl = 0; 625 BOOT_FLAG(*cp, fl); 626 if (!fl) { 627 printf("unknown option `%c'\n", *cp); 628 continue; 629 } 630 boothowto |= fl; 631 632 /* specialties */ 633 if (*cp == 'd') { 634 #if defined(KGDB) 635 kgdb_debug_panic = 1; 636 kgdb_connect(1); 637 #elif defined(DDB) 638 Debugger(); 639 #else 640 printf("kernel has no debugger\n"); 641 #endif 642 } 643 } 644 } 645 646 /* 647 * Fake a ROM generated bootpath. 648 * The argument `cp' points to a string such as "xd(0,0,0)netbsd" 649 */ 650 651 static void 652 bootpath_fake(struct bootpath *bp, const char *cp) 653 { 654 const char *pp; 655 int v0val[3]; 656 657 #define BP_APPEND(BP,N,V0,V1,V2) { \ 658 strcpy((BP)->name, N); \ 659 (BP)->val[0] = (V0); \ 660 (BP)->val[1] = (V1); \ 661 (BP)->val[2] = (V2); \ 662 (BP)++; \ 663 nbootpath++; \ 664 } 665 666 #if defined(SUN4) 667 if (CPU_ISSUN4M) { 668 printf("twas brillig..\n"); 669 return; 670 } 671 #endif 672 673 pp = cp + 2; 674 v0val[0] = v0val[1] = v0val[2] = 0; 675 if (*pp == '(' /* for vi: ) */ 676 && *(pp = str2hex(++pp, &v0val[0])) == ',' 677 && *(pp = str2hex(++pp, &v0val[1])) == ',') 678 (void)str2hex(++pp, &v0val[2]); 679 680 #if defined(SUN4) 681 if (CPU_ISSUN4) { 682 char tmpname[8]; 683 684 /* 685 * xylogics VME dev: xd, xy, xt 686 * fake looks like: /vme0/xdc0/xd@1,0 687 */ 688 if (cp[0] == 'x') { 689 if (cp[1] == 'd') {/* xd? */ 690 BP_APPEND(bp, "vme", -1, 0, 0); 691 } else { 692 BP_APPEND(bp, "vme", -1, 0, 0); 693 } 694 /* e.g. `xdc' */ 695 snprintf(tmpname, sizeof(tmpname), "x%cc", cp[1]); 696 BP_APPEND(bp, tmpname, -1, v0val[0], 0); 697 /* e.g. `xd' */ 698 snprintf(tmpname, sizeof(tmpname), "x%c", cp[1]); 699 BP_APPEND(bp, tmpname, v0val[1], v0val[2], 0); 700 return; 701 } 702 703 /* 704 * ethernet: ie, le (rom supports only obio?) 705 * fake looks like: /obio0/le0 706 */ 707 if ((cp[0] == 'i' || cp[0] == 'l') && cp[1] == 'e') { 708 BP_APPEND(bp, "obio", -1, 0, 0); 709 snprintf(tmpname, sizeof(tmpname), "%c%c", cp[0], cp[1]); 710 BP_APPEND(bp, tmpname, -1, 0, 0); 711 return; 712 } 713 714 /* 715 * scsi: sd, st, sr 716 * assume: 4/100 = sw: /obio0/sw0/sd@0,0:a 717 * 4/200 & 4/400 = si/sc: /vme0/si0/sd@0,0:a 718 * 4/300 = esp: /obio0/esp0/sd@0,0:a 719 * (note we expect sc to mimic an si...) 720 */ 721 if (cp[0] == 's' && 722 (cp[1] == 'd' || cp[1] == 't' || cp[1] == 'r')) { 723 724 int target, lun; 725 726 switch (cpuinfo.cpu_type) { 727 case CPUTYP_4_200: 728 case CPUTYP_4_400: 729 BP_APPEND(bp, "vme", -1, 0, 0); 730 BP_APPEND(bp, "si", -1, v0val[0], 0); 731 break; 732 case CPUTYP_4_100: 733 BP_APPEND(bp, "obio", -1, 0, 0); 734 BP_APPEND(bp, "sw", -1, v0val[0], 0); 735 break; 736 case CPUTYP_4_300: 737 BP_APPEND(bp, "obio", -1, 0, 0); 738 BP_APPEND(bp, "esp", -1, v0val[0], 0); 739 break; 740 default: 741 panic("bootpath_fake: unknown system type %d", 742 cpuinfo.cpu_type); 743 } 744 /* 745 * Deal with target/lun encodings. 746 * Note: more special casing in dk_establish(). 747 * 748 * We happen to know how `prom_revision' is 749 * constructed from `monID[]' on sun4 proms... 750 */ 751 if (prom_revision() > '1') { 752 target = v0val[1] >> 3; /* new format */ 753 lun = v0val[1] & 0x7; 754 } else { 755 target = v0val[1] >> 2; /* old format */ 756 lun = v0val[1] & 0x3; 757 } 758 snprintf(tmpname, sizeof(tmpname), 759 "%c%c", cp[0], cp[1]); 760 BP_APPEND(bp, tmpname, target, lun, v0val[2]); 761 return; 762 } 763 764 return; /* didn't grok bootpath, no change */ 765 } 766 #endif /* SUN4 */ 767 768 #if defined(SUN4C) 769 /* 770 * sun4c stuff 771 */ 772 773 /* 774 * floppy: fd 775 * fake looks like: /fd@0,0:a 776 */ 777 if (cp[0] == 'f' && cp[1] == 'd') { 778 /* 779 * Assume `fd(c,u,p)' means: 780 * partition `p' on floppy drive `u' on controller `c' 781 * Yet, for the purpose of determining the boot device, 782 * we support only one controller, so we encode the 783 * bootpath component by unit number, as on a v2 prom. 784 */ 785 BP_APPEND(bp, "fd", -1, v0val[1], v0val[2]); 786 return; 787 } 788 789 /* 790 * ethernet: le 791 * fake looks like: /sbus0/le0 792 */ 793 if (cp[0] == 'l' && cp[1] == 'e') { 794 BP_APPEND(bp, "sbus", -1, 0, 0); 795 BP_APPEND(bp, "le", -1, v0val[0], 0); 796 return; 797 } 798 799 /* 800 * scsi: sd, st, sr 801 * fake looks like: /sbus0/esp0/sd@3,0:a 802 */ 803 if (cp[0] == 's' && (cp[1] == 'd' || cp[1] == 't' || cp[1] == 'r')) { 804 char tmpname[8]; 805 int target, lun; 806 807 BP_APPEND(bp, "sbus", -1, 0, 0); 808 BP_APPEND(bp, "esp", -1, v0val[0], 0); 809 if (cp[1] == 'r') 810 snprintf(tmpname, sizeof(tmpname), "cd"); /* netbsd uses 'cd', not 'sr'*/ 811 else 812 snprintf(tmpname, sizeof(tmpname), "%c%c", cp[0], cp[1]); 813 /* XXX - is TARGET/LUN encoded in v0val[1]? */ 814 target = v0val[1]; 815 lun = 0; 816 BP_APPEND(bp, tmpname, target, lun, v0val[2]); 817 return; 818 } 819 #endif /* SUN4C */ 820 821 822 /* 823 * unknown; return 824 */ 825 826 #undef BP_APPEND 827 } 828 829 /* 830 * print out the bootpath 831 * the %x isn't 0x%x because the Sun EPROMs do it this way, and 832 * consistency with the EPROMs is probably better here. 833 */ 834 835 static void 836 bootpath_print(struct bootpath *bp) 837 { 838 printf("bootpath: "); 839 while (bp->name[0]) { 840 if (bp->val[0] == -1) 841 printf("/%s%x", bp->name, bp->val[1]); 842 else 843 printf("/%s@%x,%x", bp->name, bp->val[0], bp->val[1]); 844 if (bp->val[2] != 0) 845 printf(":%c", bp->val[2] + 'a'); 846 bp++; 847 } 848 printf("\n"); 849 } 850 851 852 /* 853 * save or read a bootpath pointer from the boothpath store. 854 */ 855 struct bootpath * 856 bootpath_store(int storep, struct bootpath *bp) 857 { 858 static struct bootpath *save; 859 struct bootpath *retval; 860 861 retval = save; 862 if (storep) 863 save = bp; 864 865 return (retval); 866 } 867 868 /* 869 * Set up the sd target mappings for non SUN4 PROMs. 870 * Find out about the real SCSI target, given the PROM's idea of the 871 * target of the (boot) device (i.e., the value in bp->v0val[0]). 872 */ 873 static void 874 crazymap(const char *prop, int *map) 875 { 876 int i; 877 char propval[8+2]; 878 879 if (!CPU_ISSUN4 && prom_version() < 2) { 880 /* 881 * Machines with real v0 proms have an `s[dt]-targets' property 882 * which contains the mapping for us to use. v2 proms do not 883 * require remapping. 884 */ 885 if (prom_getoption(prop, propval, sizeof propval) != 0 || 886 propval[0] == '\0' || strlen(propval) != 8) { 887 build_default_map: 888 printf("WARNING: %s map is bogus, using default\n", 889 prop); 890 for (i = 0; i < 8; ++i) 891 map[i] = i; 892 i = map[0]; 893 map[0] = map[3]; 894 map[3] = i; 895 return; 896 } 897 for (i = 0; i < 8; ++i) { 898 map[i] = propval[i] - '0'; 899 if (map[i] < 0 || 900 map[i] >= 8) 901 goto build_default_map; 902 } 903 } else { 904 /* 905 * Set up the identity mapping for old sun4 monitors 906 * and v[2-] OpenPROMs. Note: dkestablish() does the 907 * SCSI-target juggling for sun4 monitors. 908 */ 909 for (i = 0; i < 8; ++i) 910 map[i] = i; 911 } 912 } 913 914 int 915 sd_crazymap(int n) 916 { 917 static int prom_sd_crazymap[8]; /* static: compute only once! */ 918 static int init = 0; 919 920 if (init == 0) { 921 crazymap("sd-targets", prom_sd_crazymap); 922 init = 1; 923 } 924 return prom_sd_crazymap[n]; 925 } 926 927 int 928 st_crazymap(int n) 929 { 930 static int prom_st_crazymap[8]; /* static: compute only once! */ 931 static int init = 0; 932 933 if (init == 0) { 934 crazymap("st-targets", prom_st_crazymap); 935 init = 1; 936 } 937 return prom_st_crazymap[n]; 938 } 939 940 941 /* 942 * Determine mass storage and memory configuration for a machine. 943 * We get the PROM's root device and make sure we understand it, then 944 * attach it as `mainbus0'. We also set up to handle the PROM `sync' 945 * command. 946 */ 947 void 948 cpu_configure(void) 949 { 950 struct pcb *pcb0; 951 bool userconf = (boothowto & RB_USERCONF) != 0; 952 953 /* initialise the softintr system */ 954 sparc_softintr_init(); 955 956 /* build the bootpath */ 957 bootpath_build(); 958 if (((boothowto & RB_USERCONF) != 0) && !userconf) 959 /* 960 * Old bootloaders do not pass boothowto, and MI code 961 * has already handled userconfig before we get here 962 * and finally fetch the right options. So if we missed 963 * it, just do it here. 964 */ 965 userconf_prompt(); 966 967 #if defined(SUN4) 968 if (CPU_ISSUN4) { 969 #define MEMREG_PHYSADDR 0xf4000000 970 bus_space_handle_t bh; 971 bus_addr_t paddr = MEMREG_PHYSADDR; 972 973 if (cpuinfo.cpu_type == CPUTYP_4_100) 974 /* Clear top bits of physical address on 4/100 */ 975 paddr &= ~0xf0000000; 976 977 if (obio_find_rom_map(paddr, PAGE_SIZE, &bh) != 0) 978 panic("configure: ROM hasn't mapped memreg!"); 979 980 par_err_reg = (volatile int *)bh; 981 } 982 #endif 983 #if defined(SUN4C) 984 if (CPU_ISSUN4C) { 985 char *cp, buf[32]; 986 int node = findroot(); 987 cp = prom_getpropstringA(node, "device_type", buf, sizeof buf); 988 if (strcmp(cp, "cpu") != 0) 989 panic("PROM root device type = %s (need CPU)", cp); 990 } 991 #endif 992 993 prom_setcallback(sync_crash); 994 995 /* Enable device interrupts */ 996 #if defined(SUN4M) 997 #if !defined(MSIIEP) 998 if (CPU_ISSUN4M) 999 icr_si_bic(SINTR_MA); 1000 #else 1001 if (CPU_ISSUN4M) 1002 /* nothing for ms-IIep so far */; 1003 #endif /* MSIIEP */ 1004 #endif /* SUN4M */ 1005 1006 #if defined(SUN4) || defined(SUN4C) 1007 if (CPU_ISSUN4 || CPU_ISSUN4C) 1008 ienab_bis(IE_ALLIE); 1009 #endif 1010 1011 if (config_rootfound("mainbus", NULL) == NULL) 1012 panic("mainbus not configured"); 1013 1014 /* 1015 * XXX Re-zero lwp0's pcb, to nullify the effect of the 1016 * XXX stack running into it during auto-configuration. 1017 * XXX - should fix stack usage. 1018 */ 1019 pcb0 = lwp_getpcb(&lwp0); 1020 memset(pcb0, 0, sizeof(struct pcb)); 1021 1022 spl0(); 1023 } 1024 1025 void 1026 cpu_rootconf(void) 1027 { 1028 struct bootpath *bp; 1029 1030 bp = nbootpath == 0 ? NULL : &bootpath[nbootpath-1]; 1031 if (bp == NULL) 1032 booted_partition = 0; 1033 else if (booted_device != bp->dev) 1034 booted_partition = 0; 1035 else 1036 booted_partition = bp->val[2]; 1037 rootconf(); 1038 } 1039 1040 /* 1041 * Console `sync' command. SunOS just does a `panic: zero' so I guess 1042 * no one really wants anything fancy... 1043 */ 1044 void 1045 sync_crash(void) 1046 { 1047 1048 panic("PROM sync command"); 1049 } 1050 1051 char * 1052 clockfreq(int freq) 1053 { 1054 static char buf[10]; 1055 size_t len; 1056 1057 freq /= 1000; 1058 len = snprintf(buf, sizeof(buf), "%d", freq / 1000); 1059 freq %= 1000; 1060 if (freq) 1061 snprintf(buf + len, sizeof(buf) - len, ".%03d", freq); 1062 return buf; 1063 } 1064 1065 /* ARGSUSED */ 1066 static int 1067 mbprint(void *aux, const char *name) 1068 { 1069 struct mainbus_attach_args *ma = aux; 1070 1071 if (name) 1072 aprint_normal("%s at %s", ma->ma_name, name); 1073 if (ma->ma_paddr) 1074 aprint_normal(" %saddr 0x%lx", 1075 BUS_ADDR_IOSPACE(ma->ma_paddr) ? "io" : "", 1076 (u_long)BUS_ADDR_PADDR(ma->ma_paddr)); 1077 if (ma->ma_pri) 1078 aprint_normal(" ipl %d", ma->ma_pri); 1079 return (UNCONF); 1080 } 1081 1082 int 1083 mainbus_match(device_t parent, cfdata_t cf, void *aux) 1084 { 1085 1086 return (1); 1087 } 1088 1089 /* 1090 * Helper routines to get some of the more common properties. These 1091 * only get the first item in case the property value is an array. 1092 * Drivers that "need to know it all" can call prom_getprop() directly. 1093 */ 1094 #if defined(SUN4C) || defined(SUN4M) || defined(SUN4D) 1095 static int prom_getprop_reg1(int, struct openprom_addr *); 1096 static int prom_getprop_intr1(int, int *); 1097 static int prom_getprop_address1(int, void **); 1098 #endif 1099 1100 /* 1101 * Attach the mainbus. 1102 * 1103 * Our main job is to attach the CPU (the root node we got in configure()) 1104 * and iterate down the list of `mainbus devices' (children of that node). 1105 * We also record the `node id' of the default frame buffer, if any. 1106 */ 1107 static void 1108 mainbus_attach(device_t parent, device_t dev, void *aux) 1109 { 1110 struct boot_special { 1111 const char *const dev; 1112 #define BS_EARLY 1 /* attach device early */ 1113 #define BS_IGNORE 2 /* ignore root device */ 1114 #define BS_OPTIONAL 4 /* device not always present */ 1115 unsigned int flags; 1116 }; 1117 1118 struct mainbus_attach_args ma; 1119 #if defined(SUN4C) || defined(SUN4M) || defined(SUN4D) 1120 char namebuf[32]; 1121 const char *sp = NULL; 1122 int node0, node; 1123 const struct boot_special *openboot_special, *ssp; 1124 #endif 1125 1126 #if defined(SUN4C) 1127 static const struct boot_special openboot_special4c[] = { 1128 /* find these first */ 1129 { "memory-error", BS_EARLY }, 1130 /* as early as convenient, in case of error */ 1131 { "eeprom", BS_EARLY }, 1132 { "counter-timer", BS_EARLY }, 1133 { "auxiliary-io", BS_EARLY }, 1134 1135 /* ignore these */ 1136 { "aliases", BS_IGNORE }, 1137 { "interrupt-enable", BS_IGNORE }, 1138 { "memory", BS_IGNORE }, 1139 { "openprom", BS_IGNORE }, 1140 { "options", BS_IGNORE }, 1141 { "packages", BS_IGNORE }, 1142 { "virtual-memory", BS_IGNORE }, 1143 1144 /* sentinel */ 1145 { NULL, 0 } 1146 }; 1147 #else 1148 #define openboot_special4c ((void *)0) 1149 #endif 1150 #if defined(SUN4M) 1151 static const struct boot_special openboot_special4m[] = { 1152 /* find these first */ 1153 { "SUNW,sx", BS_EARLY|BS_OPTIONAL }, 1154 { "obio", BS_EARLY|BS_OPTIONAL }, 1155 /* smart enough to get eeprom/etc mapped */ 1156 { "pci", BS_EARLY|BS_OPTIONAL }, /* ms-IIep */ 1157 1158 /* 1159 * These are _root_ devices to ignore. Others must be handled 1160 * elsewhere. 1161 */ 1162 { "virtual-memory", BS_IGNORE }, 1163 { "aliases", BS_IGNORE }, 1164 { "chosen", BS_IGNORE }, /* OpenFirmware */ 1165 { "memory", BS_IGNORE }, 1166 { "openprom", BS_IGNORE }, 1167 { "options", BS_IGNORE }, 1168 { "packages", BS_IGNORE }, 1169 { "udp", BS_IGNORE }, /* OFW in Krups */ 1170 /* we also skip any nodes with device_type == "cpu" */ 1171 1172 { NULL, 0 } 1173 }; 1174 #else 1175 #define openboot_special4m ((void *)0) 1176 #endif 1177 #if defined(SUN4D) 1178 static const struct boot_special openboot_special4d[] = { 1179 /* 1180 * These are _root_ devices to ignore. Others must be handled 1181 * elsewhere. 1182 */ 1183 { "mem-unit", BS_IGNORE }, 1184 /* XXX might need this for memory errors */ 1185 { "boards", BS_IGNORE }, 1186 { "openprom", BS_IGNORE }, 1187 { "virtual-memory", BS_IGNORE }, 1188 { "memory", BS_IGNORE }, 1189 { "aliases", BS_IGNORE }, 1190 { "options", BS_IGNORE }, 1191 { "packages", BS_IGNORE }, 1192 1193 { NULL, 0 } 1194 }; 1195 #else 1196 #define openboot_special4d ((void *)0) 1197 #endif 1198 1199 set_machine_model(true); 1200 1201 prom_getidprom(); 1202 printf(": %s: hostid %lx\n", machine_model, hostid); 1203 1204 /* Establish the first component of the boot path */ 1205 bootpath_store(1, bootpath); 1206 1207 /* 1208 * Locate and configure the ``early'' devices. These must be 1209 * configured before we can do the rest. For instance, the 1210 * EEPROM contains the Ethernet address for the LANCE chip. 1211 * If the device cannot be located or configured, panic. 1212 */ 1213 1214 #if defined(SUN4) 1215 if (CPU_ISSUN4) { 1216 1217 memset(&ma, 0, sizeof(ma)); 1218 /* Configure the CPU. */ 1219 ma.ma_bustag = &mainbus_space_tag; 1220 ma.ma_dmatag = &mainbus_dma_tag; 1221 ma.ma_name = "cpu"; 1222 if (config_found(dev, (void *)&ma, mbprint, CFARGS_NONE) == NULL) 1223 panic("cpu missing"); 1224 1225 ma.ma_bustag = &mainbus_space_tag; 1226 ma.ma_dmatag = &mainbus_dma_tag; 1227 ma.ma_name = "obio"; 1228 if (config_found(dev, (void *)&ma, mbprint, CFARGS_NONE) == NULL) 1229 panic("obio missing"); 1230 1231 ma.ma_bustag = &mainbus_space_tag; 1232 ma.ma_dmatag = &mainbus_dma_tag; 1233 ma.ma_name = "vme"; 1234 (void)config_found(dev, (void *)&ma, mbprint, CFARGS_NONE); 1235 return; 1236 } 1237 #endif 1238 1239 /* 1240 * The rest of this routine is for OBP machines exclusively. 1241 */ 1242 #if defined(SUN4C) || defined(SUN4M) || defined(SUN4D) 1243 devhandle_t selfh = device_handle(dev); 1244 1245 if (CPU_ISSUN4D) 1246 openboot_special = openboot_special4d; 1247 else if (CPU_ISSUN4M) 1248 openboot_special = openboot_special4m; 1249 else 1250 openboot_special = openboot_special4c; 1251 1252 node0 = firstchild(findroot()); 1253 1254 /* The first early device to be configured is the cpu */ 1255 if (CPU_ISSUN4M) { 1256 const char *cp; 1257 int mid, bootnode = 0; 1258 1259 /* 1260 * Configure all CPUs. 1261 * Make sure to configure the boot CPU as cpu0. 1262 */ 1263 rescan: 1264 for (node = node0; node; node = nextsibling(node)) { 1265 cp = prom_getpropstringA(node, "device_type", 1266 namebuf, sizeof namebuf); 1267 if (strcmp(cp, "cpu") != 0) 1268 continue; 1269 1270 mid = prom_getpropint(node, "mid", -1); 1271 if (bootnode == 0) { 1272 /* We're looking for the boot CPU */ 1273 if (bootmid != 0 && mid != bootmid) 1274 continue; 1275 bootnode = node; 1276 } else { 1277 if (node == bootnode) 1278 continue; 1279 } 1280 1281 memset(&ma, 0, sizeof(ma)); 1282 ma.ma_bustag = &mainbus_space_tag; 1283 ma.ma_dmatag = &mainbus_dma_tag; 1284 ma.ma_node = node; 1285 ma.ma_name = "cpu"; 1286 config_found(dev, (void *)&ma, mbprint, 1287 CFARGS(.devhandle = prom_node_to_devhandle(selfh, 1288 node))); 1289 if (node == bootnode && bootmid != 0) { 1290 /* Re-enter loop to find all remaining CPUs */ 1291 goto rescan; 1292 } 1293 } 1294 } else if (CPU_ISSUN4C) { 1295 memset(&ma, 0, sizeof(ma)); 1296 ma.ma_bustag = &mainbus_space_tag; 1297 ma.ma_dmatag = &mainbus_dma_tag; 1298 ma.ma_node = findroot(); 1299 ma.ma_name = "cpu"; 1300 config_found(dev, (void *)&ma, mbprint, 1301 CFARGS(.devhandle = prom_node_to_devhandle(selfh, 1302 ma.ma_node))); 1303 } 1304 1305 for (ssp = openboot_special; (sp = ssp->dev) != NULL; ssp++) { 1306 struct openprom_addr romreg; 1307 1308 if (!(ssp->flags & BS_EARLY)) continue; 1309 if ((node = findnode(node0, sp)) == 0) { 1310 if (ssp->flags & BS_OPTIONAL) continue; 1311 printf("could not find %s in OPENPROM\n", sp); 1312 panic("%s", sp); 1313 } 1314 1315 memset(&ma, 0, sizeof ma); 1316 ma.ma_bustag = &mainbus_space_tag; 1317 ma.ma_dmatag = &mainbus_dma_tag; 1318 ma.ma_name = prom_getpropstringA(node, "name", 1319 namebuf, sizeof namebuf); 1320 ma.ma_node = node; 1321 if (prom_getprop_reg1(node, &romreg) != 0) 1322 continue; 1323 1324 ma.ma_paddr = (bus_addr_t) 1325 BUS_ADDR(romreg.oa_space, romreg.oa_base); 1326 ma.ma_size = romreg.oa_size; 1327 if (prom_getprop_intr1(node, &ma.ma_pri) != 0) 1328 continue; 1329 if (prom_getprop_address1(node, &ma.ma_promvaddr) != 0) 1330 continue; 1331 1332 if (config_found(dev, (void *)&ma, mbprint, 1333 CFARGS(.devhandle = 1334 prom_node_to_devhandle(selfh, 1335 node))) == NULL) { 1336 if (ssp->flags & BS_OPTIONAL) continue; 1337 panic("%s", sp); 1338 } 1339 } 1340 1341 /* 1342 * Configure the rest of the devices, in PROM order. Skip 1343 * PROM entries that are not for devices, or which must be 1344 * done before we get here. 1345 */ 1346 for (node = node0; node; node = nextsibling(node)) { 1347 const char *cp; 1348 struct openprom_addr romreg; 1349 1350 DPRINTF(ACDB_PROBE, ("Node: %x", node)); 1351 #if defined(SUN4M) 1352 if (CPU_ISSUN4M) { /* skip the CPUs */ 1353 if (strcmp(prom_getpropstringA(node, "device_type", 1354 namebuf, sizeof namebuf), 1355 "cpu") == 0) 1356 continue; 1357 } 1358 #endif 1359 cp = prom_getpropstringA(node, "name", namebuf, sizeof namebuf); 1360 DPRINTF(ACDB_PROBE, (" name %s\n", namebuf)); 1361 for (ssp = openboot_special; (sp = ssp->dev) != NULL; ssp++) { 1362 if (!(ssp->flags & (BS_EARLY|BS_IGNORE))) continue; 1363 if (strcmp(cp, sp) == 0) 1364 break; 1365 } 1366 if (sp != NULL) 1367 continue; 1368 /* an "early" device already configured, or an 1369 ignored device */ 1370 1371 memset(&ma, 0, sizeof ma); 1372 ma.ma_bustag = &mainbus_space_tag; 1373 ma.ma_dmatag = &mainbus_dma_tag; 1374 ma.ma_name = prom_getpropstringA(node, "name", 1375 namebuf, sizeof namebuf); 1376 ma.ma_node = node; 1377 1378 #if defined(SUN4M) 1379 /* 1380 * JS1/OF does not have iommu node in the device tree, 1381 * so if on sun4m we see sbus node under root - attach 1382 * implicit iommu. See also bootpath_build where we 1383 * adjust bootpath accordingly and iommu_attach where 1384 * we arrange for this sbus node to be attached. 1385 */ 1386 if (CPU_ISSUN4M && strcmp(ma.ma_name, "sbus") == 0) { 1387 printf("mainbus_attach: sbus node under root on sun4m - assuming iommu\n"); 1388 ma.ma_name = "iommu"; 1389 ma.ma_paddr = (bus_addr_t)BUS_ADDR(0, 0x10000000); 1390 ma.ma_size = 0x300; 1391 ma.ma_pri = 0; 1392 ma.ma_promvaddr = 0; 1393 1394 config_found(dev, (void *)&ma, mbprint, 1395 CFARGS(.devhandle = prom_node_to_devhandle(selfh, 1396 node))); 1397 continue; 1398 } 1399 #endif /* SUN4M */ 1400 1401 if (prom_getprop_reg1(node, &romreg) != 0) 1402 continue; 1403 1404 ma.ma_paddr = BUS_ADDR(romreg.oa_space, romreg.oa_base); 1405 ma.ma_size = romreg.oa_size; 1406 1407 if (prom_getprop_intr1(node, &ma.ma_pri) != 0) 1408 continue; 1409 1410 if (prom_getprop_address1(node, &ma.ma_promvaddr) != 0) 1411 continue; 1412 1413 config_found(dev, (void *)&ma, mbprint, 1414 CFARGS(.devhandle = prom_node_to_devhandle(selfh, node))); 1415 } 1416 #endif /* SUN4C || SUN4M || SUN4D */ 1417 } 1418 1419 CFATTACH_DECL_NEW(mainbus, 0, mainbus_match, mainbus_attach, NULL, NULL); 1420 1421 1422 #if defined(SUN4C) || defined(SUN4M) || defined(SUN4D) 1423 int 1424 prom_getprop_reg1(int node, struct openprom_addr *rrp) 1425 { 1426 int error, n; 1427 struct openprom_addr *rrp0 = NULL; 1428 char buf[32]; 1429 1430 error = prom_getprop(node, "reg", sizeof(struct openprom_addr), 1431 &n, &rrp0); 1432 if (error != 0) { 1433 if (error == ENOENT && 1434 strcmp(prom_getpropstringA(node, "device_type", buf, sizeof buf), 1435 "hierarchical") == 0) { 1436 memset(rrp, 0, sizeof(struct openprom_addr)); 1437 error = 0; 1438 } 1439 return (error); 1440 } 1441 1442 *rrp = rrp0[0]; 1443 free(rrp0, M_DEVBUF); 1444 return (0); 1445 } 1446 1447 int 1448 prom_getprop_intr1(int node, int *ip) 1449 { 1450 int error, n; 1451 struct rom_intr *rip = NULL; 1452 1453 error = prom_getprop(node, "intr", sizeof(struct rom_intr), 1454 &n, &rip); 1455 if (error != 0) { 1456 if (error == ENOENT) { 1457 *ip = 0; 1458 error = 0; 1459 } 1460 return (error); 1461 } 1462 1463 *ip = rip[0].int_pri & 0xf; 1464 free(rip, M_DEVBUF); 1465 return (0); 1466 } 1467 1468 int 1469 prom_getprop_address1(int node, void **vpp) 1470 { 1471 int error, n; 1472 void **vp = NULL; 1473 1474 error = prom_getprop(node, "address", sizeof(uint32_t), &n, &vp); 1475 if (error != 0) { 1476 if (error == ENOENT) { 1477 *vpp = 0; 1478 error = 0; 1479 } 1480 return (error); 1481 } 1482 1483 *vpp = vp[0]; 1484 free(vp, M_DEVBUF); 1485 return (0); 1486 } 1487 #endif /* SUN4C || SUN4M || SUN4D */ 1488 1489 #ifdef RASTERCONSOLE 1490 /* 1491 * Try to figure out where the PROM stores the cursor row & column 1492 * variables. Returns nonzero on error. 1493 */ 1494 int 1495 romgetcursoraddr(int **rowp, int **colp) 1496 { 1497 char buf[100]; 1498 1499 /* 1500 * line# and column# are global in older proms (rom vector < 2) 1501 * and in some newer proms. They are local in version 2.9. The 1502 * correct cutoff point is unknown, as yet; we use 2.9 here. 1503 */ 1504 if (prom_version() < 2 || prom_revision() < 0x00020009) 1505 snprintf(buf, sizeof(buf), 1506 "' line# >body >user %lx ! ' column# >body >user %lx !", 1507 (u_long)rowp, (u_long)colp); 1508 else 1509 snprintf(buf, sizeof(buf), 1510 "stdout @ is my-self addr line# %lx ! addr column# %lx !", 1511 (u_long)rowp, (u_long)colp); 1512 *rowp = *colp = NULL; 1513 prom_interpret(buf); 1514 return (*rowp == NULL || *colp == NULL); 1515 } 1516 #endif /* RASTERCONSOLE */ 1517 1518 /* 1519 * Device registration used to determine the boot device. 1520 */ 1521 #include <dev/scsipi/scsi_all.h> 1522 #include <dev/scsipi/scsipi_all.h> 1523 #include <dev/scsipi/scsiconf.h> 1524 #include <sparc/sparc/iommuvar.h> 1525 1526 #define BUSCLASS_NONE 0 1527 #define BUSCLASS_MAINBUS 1 1528 #define BUSCLASS_IOMMU 2 1529 #define BUSCLASS_OBIO 3 1530 #define BUSCLASS_SBUS 4 1531 #define BUSCLASS_VME 5 1532 #define BUSCLASS_XDC 6 1533 #define BUSCLASS_XYC 7 1534 #define BUSCLASS_FDC 8 1535 #define BUSCLASS_PCIC 9 1536 #define BUSCLASS_PCI 10 1537 1538 static int bus_class(device_t); 1539 static const char *bus_compatible(const char *); 1540 static int instance_match(device_t, void *, struct bootpath *); 1541 static void nail_bootdev(device_t, struct bootpath *); 1542 1543 static struct { 1544 const char *name; 1545 int class; 1546 } bus_class_tab[] = { 1547 { "mainbus", BUSCLASS_MAINBUS }, 1548 { "obio", BUSCLASS_OBIO }, 1549 { "iommu", BUSCLASS_IOMMU }, 1550 { "sbus", BUSCLASS_SBUS }, 1551 { "xbox", BUSCLASS_SBUS }, 1552 { "dma", BUSCLASS_SBUS }, 1553 { "esp", BUSCLASS_SBUS }, 1554 { "espdma", BUSCLASS_SBUS }, 1555 { "isp", BUSCLASS_SBUS }, 1556 { "ledma", BUSCLASS_SBUS }, 1557 { "lebuffer", BUSCLASS_SBUS }, 1558 { "vme", BUSCLASS_VME }, 1559 { "si", BUSCLASS_VME }, 1560 { "sw", BUSCLASS_OBIO }, 1561 { "xdc", BUSCLASS_XDC }, 1562 { "xyc", BUSCLASS_XYC }, 1563 { "fdc", BUSCLASS_FDC }, 1564 { "mspcic", BUSCLASS_PCIC }, 1565 { "pci", BUSCLASS_PCI }, 1566 }; 1567 1568 /* 1569 * A list of PROM device names that differ from our NetBSD 1570 * device names. 1571 */ 1572 static struct { 1573 const char *bpname; 1574 const char *cfname; 1575 } dev_compat_tab[] = { 1576 { "espdma", "dma" }, 1577 { "SUNW,fas", "esp" }, 1578 { "QLGC,isp", "isp" }, 1579 { "PTI,isp", "isp" }, 1580 { "ptisp", "isp" }, 1581 { "SUNW,fdtwo", "fdc" }, 1582 { "network", "hme" }, /* Krups */ 1583 { "SUNW,hme", "hme" }, 1584 { "SUNW,qfe", "hme" }, 1585 }; 1586 1587 static const char * 1588 bus_compatible(const char *bpname) 1589 { 1590 int i; 1591 1592 for (i = sizeof(dev_compat_tab)/sizeof(dev_compat_tab[0]); i-- > 0;) { 1593 if (strcmp(bpname, dev_compat_tab[i].bpname) == 0) 1594 return (dev_compat_tab[i].cfname); 1595 } 1596 1597 return (bpname); 1598 } 1599 1600 static int 1601 bus_class(device_t dev) 1602 { 1603 int i, class; 1604 1605 class = BUSCLASS_NONE; 1606 if (dev == NULL) 1607 return (class); 1608 1609 for (i = sizeof(bus_class_tab)/sizeof(bus_class_tab[0]); i-- > 0;) { 1610 if (device_is_a(dev, bus_class_tab[i].name)) { 1611 class = bus_class_tab[i].class; 1612 break; 1613 } 1614 } 1615 1616 /* sun4m obio special case */ 1617 if (CPU_ISSUN4M && class == BUSCLASS_OBIO) 1618 class = BUSCLASS_SBUS; 1619 1620 return (class); 1621 } 1622 1623 static int 1624 sparc_ether_get_mac_address(device_t dev, devhandle_t call_handle, void *v) 1625 { 1626 struct ether_get_mac_address_args *args = v; 1627 int node; 1628 1629 /* 1630 * If we're called with a valid OpenBoot node, then use it. 1631 * Otherwise, assume we're using a handle-less old-world PROM 1632 * and use the global MAC address in the ID PROM. 1633 */ 1634 if (devhandle_type(call_handle) == DEVHANDLE_TYPE_OPENBOOT) { 1635 node = prom_devhandle_to_node(call_handle); 1636 } else { 1637 node = 0; 1638 } 1639 1640 prom_getether(node, args->enaddr); 1641 return 0; 1642 } 1643 SYSDFLT_DEVICE_CALL_REGISTER(ETHER_GET_MAC_ADDRESS_STR, 1644 sparc_ether_get_mac_address) 1645 1646 int 1647 instance_match(device_t dev, void *aux, struct bootpath *bp) 1648 { 1649 struct mainbus_attach_args *ma; 1650 struct sbus_attach_args *sa; 1651 struct iommu_attach_args *iom; 1652 struct pcibus_attach_args *pba; 1653 struct pci_attach_args *pa; 1654 1655 /* 1656 * Several devices are represented on bootpaths in one of 1657 * two formats, e.g.: 1658 * (1) ../sbus (at) .../esp@<offset>,<slot>/sd@.. (PROM v3 style) 1659 * (2) /sbus0/esp0/sd@.. (PROM v2 style) 1660 * 1661 * hence we fall back on a `unit number' check if the bus-specific 1662 * instance parameter check does not produce a match. 1663 */ 1664 1665 /* 1666 * Rank parent bus so we know which locators to check. 1667 */ 1668 switch (bus_class(device_parent(dev))) { 1669 case BUSCLASS_MAINBUS: 1670 ma = aux; 1671 DPRINTF(ACDB_BOOTDEV, ("instance_match: mainbus device, " 1672 "want space %#x addr %#x have space %#x addr %#llx\n", 1673 bp->val[0], bp->val[1], (int)BUS_ADDR_IOSPACE(ma->ma_paddr), 1674 (unsigned long long)BUS_ADDR_PADDR(ma->ma_paddr))); 1675 if ((u_long)bp->val[0] == BUS_ADDR_IOSPACE(ma->ma_paddr) && 1676 (bus_addr_t)(u_long)bp->val[1] == 1677 BUS_ADDR_PADDR(ma->ma_paddr)) 1678 return (1); 1679 break; 1680 case BUSCLASS_SBUS: 1681 sa = aux; 1682 DPRINTF(ACDB_BOOTDEV, ("instance_match: sbus device, " 1683 "want slot %#x offset %#x have slot %#x offset %#x\n", 1684 bp->val[0], bp->val[1], sa->sa_slot, sa->sa_offset)); 1685 if ((uint32_t)bp->val[0] == sa->sa_slot && 1686 (uint32_t)bp->val[1] == sa->sa_offset) 1687 return (1); 1688 break; 1689 case BUSCLASS_IOMMU: 1690 iom = aux; 1691 DPRINTF(ACDB_BOOTDEV, ("instance_match: iommu device, " 1692 "want space %#x pa %#x have space %#x pa %#x\n", 1693 bp->val[0], bp->val[1], iom->iom_reg[0].oa_space, 1694 iom->iom_reg[0].oa_base)); 1695 if ((uint32_t)bp->val[0] == iom->iom_reg[0].oa_space && 1696 (uint32_t)bp->val[1] == iom->iom_reg[0].oa_base) 1697 return (1); 1698 break; 1699 case BUSCLASS_XDC: 1700 case BUSCLASS_XYC: 1701 { 1702 /* 1703 * XXX - x[dy]c attach args are not exported right now.. 1704 * XXX we happen to know they look like this: 1705 */ 1706 struct xxxx_attach_args { int driveno; } *aap = aux; 1707 1708 DPRINTF(ACDB_BOOTDEV, 1709 ("instance_match: x[dy]c device, want drive %#x have %#x\n", 1710 bp->val[0], aap->driveno)); 1711 if (aap->driveno == bp->val[0]) 1712 return (1); 1713 1714 } 1715 break; 1716 case BUSCLASS_PCIC: 1717 pba = aux; 1718 DPRINTF(ACDB_BOOTDEV, ("instance_match: pci bus " 1719 "want bus %d pa %#x have bus %d pa %#lx\n", 1720 bp->val[0], bp->val[1], pba->pba_bus, MSIIEP_PCIC_PA)); 1721 if ((int)bp->val[0] == pba->pba_bus 1722 && (bus_addr_t)bp->val[1] == MSIIEP_PCIC_PA) 1723 return (1); 1724 break; 1725 case BUSCLASS_PCI: 1726 pa = aux; 1727 DPRINTF(ACDB_BOOTDEV, ("instance_match: pci device " 1728 "want dev %d function %d have dev %d function %d\n", 1729 bp->val[0], bp->val[1], pa->pa_device, pa->pa_function)); 1730 if ((u_int)bp->val[0] == pa->pa_device 1731 && (u_int)bp->val[1] == pa->pa_function) 1732 return (1); 1733 break; 1734 default: 1735 break; 1736 } 1737 1738 if (bp->val[0] == -1 && bp->val[1] == device_unit(dev)) 1739 return (1); 1740 1741 return (0); 1742 } 1743 1744 void 1745 nail_bootdev(device_t dev, struct bootpath *bp) 1746 { 1747 1748 if (bp->dev != NULL) 1749 panic("device_register: already got a boot device: %s", 1750 device_xname(bp->dev)); 1751 1752 /* 1753 * Mark this bootpath component by linking it to the matched 1754 * device. We pick up the device pointer in cpu_rootconf(). 1755 */ 1756 booted_device = bp->dev = dev; 1757 1758 /* 1759 * Then clear the current bootpath component, so we don't spuriously 1760 * match similar instances on other busses, e.g. a disk on 1761 * another SCSI bus with the same target. 1762 */ 1763 bootpath_store(1, NULL); 1764 } 1765 1766 /* 1767 * We use device_register() to: 1768 * set device properties on PCI devices 1769 * find the bootpath 1770 */ 1771 void 1772 device_register(device_t dev, void *aux) 1773 { 1774 struct bootpath *bp = bootpath_store(0, NULL); 1775 const char *bpname; 1776 1777 /* 1778 * If device name does not match current bootpath component 1779 * then there's nothing interesting to consider. 1780 */ 1781 if (bp == NULL) 1782 return; 1783 1784 /* 1785 * Translate PROM name in case our drivers are named differently 1786 */ 1787 bpname = bus_compatible(bp->name); 1788 1789 DPRINTF(ACDB_BOOTDEV, 1790 ("\n%s: device_register: dvname %s(%s) bpname %s(%s)\n", 1791 device_xname(dev), device_cfdata(dev)->cf_name, 1792 device_xname(dev), bpname, bp->name)); 1793 1794 /* First, match by name */ 1795 if (!device_is_a(dev, bpname)) 1796 return; 1797 1798 if (bus_class(dev) != BUSCLASS_NONE) { 1799 /* 1800 * A bus or controller device of sorts. Check instance 1801 * parameters and advance boot path on match. 1802 */ 1803 if (instance_match(dev, aux, bp) != 0) { 1804 if (device_is_a(dev, "fdc")) { 1805 /* 1806 * XXX - HACK ALERT 1807 * Sun PROMs don't really seem to support 1808 * multiple floppy drives. So we aren't 1809 * going to, either. Since the PROM 1810 * only provides a node for the floppy 1811 * controller, we sneakily add a drive to 1812 * the bootpath here. 1813 */ 1814 strcpy(bootpath[nbootpath].name, "fd"); 1815 nbootpath++; 1816 } 1817 booted_device = bp->dev = dev; 1818 bootpath_store(1, bp + 1); 1819 DPRINTF(ACDB_BOOTDEV, ("\t-- found bus controller %s\n", 1820 device_xname(dev))); 1821 return; 1822 } 1823 } else if (device_class(dev) == DV_IFNET) { 1824 /* 1825 * LANCE, Happy Meal, or BigMac ethernet device 1826 */ 1827 if (instance_match(dev, aux, bp) != 0) { 1828 nail_bootdev(dev, bp); 1829 DPRINTF(ACDB_BOOTDEV, ("\t-- found ethernet controller %s\n", 1830 device_xname(dev))); 1831 return; 1832 } 1833 } else if (device_is_a(dev, "sd") || 1834 device_is_a(dev, "cd")) { 1835 #if NSCSIBUS > 0 1836 /* 1837 * A SCSI disk or cd; retrieve target/lun information 1838 * from parent and match with current bootpath component. 1839 * Note that we also have look back past the `scsibus' 1840 * device to determine whether this target is on the 1841 * correct controller in our boot path. 1842 */ 1843 struct scsipibus_attach_args *sa = aux; 1844 struct scsipi_periph *periph = sa->sa_periph; 1845 struct scsipi_channel *chan = periph->periph_channel; 1846 struct scsibus_softc *sbsc = 1847 device_private(device_parent(dev)); 1848 u_int target = bp->val[0]; 1849 u_int lun = bp->val[1]; 1850 1851 /* Check the controller that this scsibus is on */ 1852 if ((bp-1)->dev != device_parent(sbsc->sc_dev)) 1853 return; 1854 1855 /* 1856 * Bounds check: we know the target and lun widths. 1857 */ 1858 if (target >= chan->chan_ntargets || lun >= chan->chan_nluns) { 1859 printf("SCSI disk bootpath component not accepted: " 1860 "target %u; lun %u\n", target, lun); 1861 return; 1862 } 1863 1864 if (CPU_ISSUN4 && device_is_a(dev, "sd") && 1865 target == 0 && 1866 scsipi_lookup_periph(chan, target, lun) == NULL) { 1867 /* 1868 * disk unit 0 is magic: if there is actually no 1869 * target 0 scsi device, the PROM will call 1870 * target 3 `sd0'. 1871 * XXX - what if someone puts a tape at target 0? 1872 */ 1873 target = 3; /* remap to 3 */ 1874 lun = 0; 1875 } 1876 1877 if (CPU_ISSUN4C && device_is_a(dev, "sd")) 1878 target = sd_crazymap(target); 1879 1880 if (periph->periph_target == target && 1881 periph->periph_lun == lun) { 1882 nail_bootdev(dev, bp); 1883 DPRINTF(ACDB_BOOTDEV, ("\t-- found [cs]d disk %s\n", 1884 device_xname(dev))); 1885 return; 1886 } 1887 #endif /* NSCSIBUS */ 1888 } else if (device_is_a(dev, "xd") || 1889 device_is_a(dev, "xy")) { 1890 1891 /* A Xylogic disk */ 1892 if (instance_match(dev, aux, bp) != 0) { 1893 nail_bootdev(dev, bp); 1894 DPRINTF(ACDB_BOOTDEV, ("\t-- found x[dy] disk %s\n", 1895 device_xname(dev))); 1896 return; 1897 } 1898 1899 } else if (device_is_a(dev, "fd")) { 1900 /* 1901 * Sun PROMs don't really seem to support multiple 1902 * floppy drives. So we aren't going to, either. 1903 * If we get this far, the `fdc controller' has 1904 * already matched and has appended a fake `fd' entry 1905 * to the bootpath, so just accept that as the boot device. 1906 */ 1907 nail_bootdev(dev, bp); 1908 DPRINTF(ACDB_BOOTDEV, ("\t-- found floppy drive %s\n", 1909 device_xname(dev))); 1910 return; 1911 } else { 1912 /* 1913 * Generic match procedure. 1914 */ 1915 if (instance_match(dev, aux, bp) != 0) { 1916 nail_bootdev(dev, bp); 1917 return; 1918 } 1919 } 1920 } 1921 1922 /* 1923 * lookup_bootinfo: 1924 * Look up information in bootinfo of boot loader. 1925 */ 1926 void * 1927 lookup_bootinfo(int type) 1928 { 1929 struct btinfo_common *bt; 1930 char *help = bootinfo; 1931 1932 /* Check for a bootinfo record first. */ 1933 if (help == NULL) 1934 return (NULL); 1935 1936 do { 1937 bt = (struct btinfo_common *)help; 1938 if (bt->type == type) 1939 return ((void *)help); 1940 help += bt->next; 1941 } while (bt->next != 0 && 1942 (size_t)help < (size_t)bootinfo + BOOTINFO_SIZE); 1943 1944 return (NULL); 1945 } 1946 1947 #if !NKSYMS && !defined(DDB) && !defined(MODULAR) 1948 /* 1949 * Move bootinfo from the current kernel top to the proposed 1950 * location. As a side-effect, `kernel_top' is adjusted to point 1951 * at the first free location after the relocated bootinfo array. 1952 */ 1953 void 1954 bootinfo_relocate(void *newloc) 1955 { 1956 int bi_size; 1957 struct btinfo_common *bt; 1958 char *cp, *dp; 1959 1960 if (bootinfo == NULL) { 1961 kernel_top = newloc; 1962 return; 1963 } 1964 1965 /* 1966 * Find total size of bootinfo array. 1967 * The array is terminated with a `nul' record (size == 0); 1968 * we account for that up-front by initializing `bi_size' 1969 * to size of a `btinfo_common' record. 1970 */ 1971 bi_size = sizeof(struct btinfo_common); 1972 cp = bootinfo; 1973 do { 1974 bt = (struct btinfo_common *)cp; 1975 bi_size += bt->next; 1976 cp += bt->next; 1977 } while (bt->next != 0 && 1978 (size_t)cp < (size_t)bootinfo + BOOTINFO_SIZE); 1979 1980 /* 1981 * Check prospective gains. 1982 */ 1983 if ((int)bootinfo - (int)newloc < bi_size) 1984 /* Don't bother */ 1985 return; 1986 1987 /* 1988 * Relocate the bits 1989 */ 1990 cp = bootinfo; 1991 dp = newloc; 1992 do { 1993 bt = (struct btinfo_common *)cp; 1994 memcpy(dp, cp, bt->next); 1995 cp += bt->next; 1996 dp += bt->next; 1997 } while (bt->next != 0 && 1998 (size_t)cp < (size_t)bootinfo + BOOTINFO_SIZE); 1999 2000 /* Write the terminating record */ 2001 bt = (struct btinfo_common *)dp; 2002 bt->next = bt->type = 0; 2003 2004 /* Set new bootinfo location and adjust kernel_top */ 2005 bootinfo = newloc; 2006 kernel_top = (char *)newloc + ALIGN(bi_size); 2007 } 2008 #endif /* !NKSYMS && !defined(DDB) && !defined(MODULAR) */ 2009