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