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