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