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