1*55143Storek /* 2*55143Storek * Copyright (c) 1992 The Regents of the University of California. 3*55143Storek * All rights reserved. 4*55143Storek * 5*55143Storek * This software was developed by the Computer Systems Engineering group 6*55143Storek * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 7*55143Storek * contributed to Berkeley. 8*55143Storek * 9*55143Storek * %sccs.include.redist.c% 10*55143Storek * 11*55143Storek * @(#)autoconf.c 7.1 (Berkeley) 07/13/92 12*55143Storek * 13*55143Storek * from: $Header: autoconf.c,v 1.23 92/07/10 22:35:23 torek Exp $ (LBL) 14*55143Storek */ 15*55143Storek 16*55143Storek #include "sys/param.h" 17*55143Storek #include "sys/map.h" 18*55143Storek #include "sys/buf.h" 19*55143Storek #include "sys/disklabel.h" 20*55143Storek #include "sys/device.h" 21*55143Storek #include "sys/dkstat.h" 22*55143Storek #include "sys/conf.h" 23*55143Storek #include "sys/dmap.h" 24*55143Storek #include "sys/reboot.h" 25*55143Storek #include "sys/socket.h" 26*55143Storek #include "sys/systm.h" 27*55143Storek 28*55143Storek #include "net/if.h" 29*55143Storek 30*55143Storek #include "machine/autoconf.h" 31*55143Storek #include "machine/bsd_openprom.h" 32*55143Storek #include "machine/cpu.h" 33*55143Storek 34*55143Storek #ifndef FS_NFS /* XXX */ 35*55143Storek #define FS_NFS 100 /* XXX */ 36*55143Storek #endif /* XXX */ 37*55143Storek 38*55143Storek /* 39*55143Storek * The following several variables are related to 40*55143Storek * the configuration process, and are used in initializing 41*55143Storek * the machine. 42*55143Storek */ 43*55143Storek int cold; /* if 1, still working on cold-start */ 44*55143Storek int dkn; /* number of iostat dk numbers assigned so far */ 45*55143Storek int cpuspeed = 10; /* relative cpu speed */ 46*55143Storek int fbnode; /* node ID of ROM's console frame buffer */ 47*55143Storek int optionsnode; /* node ID of ROM's options */ 48*55143Storek 49*55143Storek extern struct promvec *promvec; 50*55143Storek 51*55143Storek static int rootnode; 52*55143Storek int findroot(); 53*55143Storek static struct bootinfo *findbootdev(); 54*55143Storek 55*55143Storek static struct bootinfo { 56*55143Storek char name[16]; /* device name */ 57*55143Storek int val[3]; /* up to 3 values */ 58*55143Storek int type; /* FS type */ 59*55143Storek caddr_t data; /* FS dependant info */ 60*55143Storek } bootinfo; 61*55143Storek 62*55143Storek 63*55143Storek /* 64*55143Storek * Most configuration on the SPARC is done by matching OPENPROM Forth 65*55143Storek * device names with our internal names. 66*55143Storek */ 67*55143Storek int 68*55143Storek matchbyname(parent, cf, aux) 69*55143Storek struct device *parent; 70*55143Storek struct cfdata *cf; 71*55143Storek void *aux; 72*55143Storek { 73*55143Storek 74*55143Storek return (strcmp(cf->cf_driver->cd_name, *(char **)aux) == 0); 75*55143Storek } 76*55143Storek 77*55143Storek /* 78*55143Storek * Convert hex ASCII string to a value. Returns updated pointer. 79*55143Storek * Depends on ASCII order (this *is* machine-dependent code, you know). 80*55143Storek */ 81*55143Storek static char * 82*55143Storek str2hex(str, vp) 83*55143Storek register char *str; 84*55143Storek register int *vp; 85*55143Storek { 86*55143Storek register int v, c; 87*55143Storek 88*55143Storek for (v = 0;; v = v * 16 + c, str++) { 89*55143Storek c = *(u_char *)str; 90*55143Storek if (c <= '9') { 91*55143Storek if ((c -= '0') < 0) 92*55143Storek break; 93*55143Storek } else if (c <= 'F') { 94*55143Storek if ((c -= 'A' - 10) < 10) 95*55143Storek break; 96*55143Storek } else if (c <= 'f') { 97*55143Storek if ((c -= 'a' - 10) < 10) 98*55143Storek break; 99*55143Storek } else 100*55143Storek break; 101*55143Storek } 102*55143Storek *vp = v; 103*55143Storek return (str); 104*55143Storek } 105*55143Storek 106*55143Storek /* 107*55143Storek * locore.s code calls bootstrap() just before calling main(), after double 108*55143Storek * mapping the kernel to high memory and setting up the trap base register. 109*55143Storek * We must finish mapping the kernel properly and glean any bootstrap info. 110*55143Storek */ 111*55143Storek void 112*55143Storek bootstrap() 113*55143Storek { 114*55143Storek register char *cp, *bp, *ep; 115*55143Storek register int i; 116*55143Storek int nmmu, ncontext, node; 117*55143Storek #ifdef KGDB 118*55143Storek extern int kgdb_debug_panic; 119*55143Storek #endif 120*55143Storek extern char *rindex(const char *, int); 121*55143Storek 122*55143Storek node = findroot(); 123*55143Storek nmmu = getpropint(node, "mmu-npmg", 128); 124*55143Storek ncontext = getpropint(node, "mmu-nctx", 8); 125*55143Storek pmap_bootstrap(nmmu, ncontext); 126*55143Storek #ifdef KGDB 127*55143Storek zs_kgdb_init(); /* XXX */ 128*55143Storek #endif 129*55143Storek /* 130*55143Storek * On SS1s, promvec->pv_v0bootargs->ba_argv[1] contains the flags 131*55143Storek * that were given after the boot command. On SS2s, pv_v0bootargs 132*55143Storek * is NULL but *promvec->pv_v2bootargs.v2_bootargs points to 133*55143Storek * "vmunix -s" or whatever. 134*55143Storek * ### DO THIS BEFORE pmap_boostrap? 135*55143Storek */ 136*55143Storek if (promvec->pv_romvec_vers < 2) { 137*55143Storek /* Grab boot device name and values. */ 138*55143Storek cp = (*promvec->pv_v0bootargs)->ba_argv[0]; 139*55143Storek if (cp != NULL) { 140*55143Storek bp = bootinfo.name; 141*55143Storek ep = &bootinfo.name[sizeof(bootinfo.name)]; 142*55143Storek while (*cp != '(' && *cp != '\0' && bp < ep - 1) 143*55143Storek *bp++ = *cp++; 144*55143Storek *bp = '\0'; 145*55143Storek 146*55143Storek if (*cp == '(' && 147*55143Storek *(cp = str2hex(++cp, &bootinfo.val[0])) == ',' && 148*55143Storek *(cp = str2hex(++cp, &bootinfo.val[1])) == ',') 149*55143Storek (void)str2hex(++cp, &bootinfo.val[2]); 150*55143Storek } 151*55143Storek 152*55143Storek /* Setup pointer to boot flags */ 153*55143Storek cp = (*promvec->pv_v0bootargs)->ba_argv[1]; 154*55143Storek if (cp == NULL || *cp != '-') 155*55143Storek return; 156*55143Storek } else { 157*55143Storek /* Grab boot device name and values. */ 158*55143Storek cp = *promvec->pv_v2bootargs.v2_bootpath; 159*55143Storek if (cp != NULL && (cp = rindex(cp, '/')) != NULL) { 160*55143Storek ++cp; 161*55143Storek bp = bootinfo.name; 162*55143Storek ep = &bootinfo.name[sizeof(bootinfo.name)]; 163*55143Storek while (*cp != '@' && *cp != '\0' && bp < ep - 1) 164*55143Storek *bp++ = *cp++; 165*55143Storek *bp = '\0'; 166*55143Storek 167*55143Storek if (*cp == '@' && 168*55143Storek *(cp = str2hex(++cp, &bootinfo.val[0])) == ',' && 169*55143Storek *(cp = str2hex(++cp, &bootinfo.val[1])) == ',') 170*55143Storek (void)str2hex(++cp, &bootinfo.val[2]); 171*55143Storek } 172*55143Storek 173*55143Storek /* Setup pointer to boot flags */ 174*55143Storek cp = *promvec->pv_v2bootargs.v2_bootargs; 175*55143Storek if (cp == NULL) 176*55143Storek return; 177*55143Storek while (*cp != '-') 178*55143Storek if (*cp++ == '\0') 179*55143Storek return; 180*55143Storek } 181*55143Storek for (;;) { 182*55143Storek switch (*++cp) { 183*55143Storek 184*55143Storek case '\0': 185*55143Storek return; 186*55143Storek 187*55143Storek case 'a': 188*55143Storek boothowto |= RB_ASKNAME; 189*55143Storek break; 190*55143Storek 191*55143Storek case 'b': 192*55143Storek boothowto |= RB_DFLTROOT; 193*55143Storek break; 194*55143Storek 195*55143Storek case 'd': /* kgdb - always on zs XXX */ 196*55143Storek #ifdef KGDB 197*55143Storek boothowto |= RB_KDB; /* XXX unused */ 198*55143Storek kgdb_debug_panic = 1; 199*55143Storek kgdb_connect(1); 200*55143Storek #else 201*55143Storek printf("kernel not compiled with KGDB\n"); 202*55143Storek #endif 203*55143Storek break; 204*55143Storek 205*55143Storek case 's': 206*55143Storek boothowto |= RB_SINGLE; 207*55143Storek break; 208*55143Storek } 209*55143Storek } 210*55143Storek } 211*55143Storek 212*55143Storek /* 213*55143Storek * Determine mass storage and memory configuration for a machine. 214*55143Storek * We get the PROM's root device and make sure we understand it, then 215*55143Storek * attach it as `mainbus0'. We also set up to handle the PROM `sync' 216*55143Storek * command. 217*55143Storek */ 218*55143Storek configure() 219*55143Storek { 220*55143Storek register int node; 221*55143Storek register char *cp; 222*55143Storek struct romaux ra; 223*55143Storek void sync_crash(); 224*55143Storek #ifdef NFS 225*55143Storek register struct bootinfo *bi; 226*55143Storek extern int (*mountroot)(), nfs_mountroot(); 227*55143Storek #endif 228*55143Storek 229*55143Storek node = findroot(); 230*55143Storek cp = getpropstring(node, "device_type"); 231*55143Storek if (strcmp(cp, "cpu") != 0) { 232*55143Storek printf("PROM root device type = %s\n", cp); 233*55143Storek panic("need CPU as root"); 234*55143Storek } 235*55143Storek *promvec->pv_synchook = sync_crash; 236*55143Storek ra.ra_node = node; 237*55143Storek ra.ra_name = cp = "mainbus"; 238*55143Storek if (!config_rootfound(cp, (void *)&ra)) 239*55143Storek panic("mainbus not configured"); 240*55143Storek (void) spl0(); 241*55143Storek cold = 0; 242*55143Storek #ifdef NFS 243*55143Storek if (boothowto & RB_ASKNAME) { 244*55143Storek char ans[100]; 245*55143Storek 246*55143Storek printf("nfs root? (y/n) [n] "); 247*55143Storek gets(ans); 248*55143Storek if (ans[0] == 'y') 249*55143Storek mountroot = nfs_mountroot; 250*55143Storek } else if ((bi = findbootdev()) != NULL && bi->type == FS_NFS) { 251*55143Storek mountroot = nfs_mountroot; 252*55143Storek #ifdef LBL 253*55143Storek lbl_diskless_setup(); 254*55143Storek #endif /* LBL */ 255*55143Storek } 256*55143Storek #endif /* NFS */ 257*55143Storek #if GENERIC 258*55143Storek if ((boothowto & RB_ASKNAME) == 0) 259*55143Storek setroot(); 260*55143Storek setconf(); 261*55143Storek #else 262*55143Storek setroot(); 263*55143Storek #endif 264*55143Storek swapconf(); 265*55143Storek } 266*55143Storek 267*55143Storek /* 268*55143Storek * Console `sync' command. SunOS just does a `panic: zero' so I guess 269*55143Storek * no one really wants anything fancy... 270*55143Storek */ 271*55143Storek void 272*55143Storek sync_crash() 273*55143Storek { 274*55143Storek 275*55143Storek panic("PROM sync command"); 276*55143Storek } 277*55143Storek 278*55143Storek char * 279*55143Storek clockfreq(freq) 280*55143Storek register int freq; 281*55143Storek { 282*55143Storek register char *p; 283*55143Storek static char buf[10]; 284*55143Storek 285*55143Storek freq /= 1000; 286*55143Storek sprintf(buf, "%d", freq / 1000); 287*55143Storek freq %= 1000; 288*55143Storek if (freq) { 289*55143Storek freq += 1000; /* now in 1000..1999 */ 290*55143Storek p = buf + strlen(buf); 291*55143Storek sprintf(p, "%d", freq); 292*55143Storek *p = '.'; /* now buf = %d.%3d */ 293*55143Storek } 294*55143Storek return (buf); 295*55143Storek } 296*55143Storek 297*55143Storek /* ARGSUSED */ 298*55143Storek static int 299*55143Storek mbprint(aux, name) 300*55143Storek void *aux; 301*55143Storek char *name; 302*55143Storek { 303*55143Storek register struct romaux *ra = aux; 304*55143Storek 305*55143Storek if (name) 306*55143Storek printf("%s at %s", ra->ra_name, name); 307*55143Storek if (ra->ra_paddr) 308*55143Storek printf(" %saddr 0x%x", ra->ra_iospace ? "io" : "", 309*55143Storek (int)ra->ra_paddr); 310*55143Storek return (UNCONF); 311*55143Storek } 312*55143Storek 313*55143Storek int 314*55143Storek findroot() 315*55143Storek { 316*55143Storek register int node; 317*55143Storek 318*55143Storek if ((node = rootnode) == 0 && (node = nextsibling(0)) == 0) 319*55143Storek panic("no PROM root device"); 320*55143Storek rootnode = node; 321*55143Storek return (node); 322*55143Storek } 323*55143Storek 324*55143Storek /* 325*55143Storek * Given a `first child' node number, locate the node with the given name. 326*55143Storek * Return the node number, or 0 if not found. 327*55143Storek */ 328*55143Storek int 329*55143Storek findnode(first, name) 330*55143Storek int first; 331*55143Storek register char *name; 332*55143Storek { 333*55143Storek register int node; 334*55143Storek 335*55143Storek for (node = first; node; node = nextsibling(node)) 336*55143Storek if (strcmp(getpropstring(node, "name"), name) == 0) 337*55143Storek return (node); 338*55143Storek return (0); 339*55143Storek } 340*55143Storek 341*55143Storek /* 342*55143Storek * Fill in a romaux. Returns 1 on success, 0 if the register property 343*55143Storek * was not the right size. 344*55143Storek */ 345*55143Storek int 346*55143Storek romprop(rp, cp, node) 347*55143Storek register struct romaux *rp; 348*55143Storek const char *cp; 349*55143Storek register int node; 350*55143Storek { 351*55143Storek register int len; 352*55143Storek union { char regbuf[64]; int ireg[3]; } u; 353*55143Storek static const char pl[] = "property length"; 354*55143Storek 355*55143Storek len = getprop(node, "reg", (void *)u.regbuf, sizeof u.regbuf); 356*55143Storek if (len < 12) { 357*55143Storek printf("%s \"reg\" %s = %d (need 12)\n", cp, pl, len); 358*55143Storek return (0); 359*55143Storek } 360*55143Storek if (len > 12) 361*55143Storek printf("warning: %s \"reg\" %s %d > 12, excess ignored\n", 362*55143Storek cp, pl, len); 363*55143Storek rp->ra_node = node; 364*55143Storek rp->ra_name = cp; 365*55143Storek rp->ra_iospace = u.ireg[0]; 366*55143Storek rp->ra_paddr = (caddr_t)u.ireg[1]; 367*55143Storek rp->ra_len = u.ireg[2]; 368*55143Storek rp->ra_vaddr = (caddr_t)getpropint(node, "address", 0); 369*55143Storek len = getprop(node, "intr", (void *)&rp->ra_intr, sizeof rp->ra_intr); 370*55143Storek if (len == -1) 371*55143Storek len = 0; 372*55143Storek if (len & 7) { 373*55143Storek printf("%s \"intr\" %s = %d (need multiple of 8)\n", 374*55143Storek cp, pl, len); 375*55143Storek len = 0; 376*55143Storek } 377*55143Storek rp->ra_nintr = len >>= 3; 378*55143Storek /* SPARCstation interrupts are not hardware-vectored */ 379*55143Storek while (--len >= 0) { 380*55143Storek if (rp->ra_intr[len].int_vec) { 381*55143Storek printf("WARNING: %s interrupt %d has nonzero vector\n", 382*55143Storek cp, len); 383*55143Storek break; 384*55143Storek } 385*55143Storek } 386*55143Storek return (1); 387*55143Storek } 388*55143Storek 389*55143Storek /* 390*55143Storek * Attach the mainbus. 391*55143Storek * 392*55143Storek * Our main job is to attach the CPU (the root node we got in configure()) 393*55143Storek * and iterate down the list of `mainbus devices' (children of that node). 394*55143Storek * We also record the `node id' of the default frame buffer, if any. 395*55143Storek */ 396*55143Storek static void 397*55143Storek mainbus_attach(parent, dev, aux) 398*55143Storek struct device *parent, *dev; 399*55143Storek void *aux; 400*55143Storek { 401*55143Storek register int node0, node; 402*55143Storek register const char *cp, *const *ssp, *sp; 403*55143Storek #define L1A_HACK /* XXX hack to allow L1-A during autoconf */ 404*55143Storek #ifdef L1A_HACK 405*55143Storek int nzs = 0, audio = 0; 406*55143Storek #endif 407*55143Storek struct romaux ra; 408*55143Storek static const char *const special[] = { 409*55143Storek /* find these first (end with empty string) */ 410*55143Storek "memory-error", "eeprom", "counter-timer", "", 411*55143Storek 412*55143Storek /* ignore these (end with NULL) */ 413*55143Storek "options", "packages", "openprom", "memory", "virtual-memory", 414*55143Storek "interrupt-enable", NULL 415*55143Storek }; 416*55143Storek 417*55143Storek printf("\n"); 418*55143Storek 419*55143Storek /* configure the cpu */ 420*55143Storek node = ((struct romaux *)aux)->ra_node; 421*55143Storek ra.ra_node = node; 422*55143Storek ra.ra_name = cp = "cpu"; 423*55143Storek ra.ra_paddr = 0; 424*55143Storek config_found(dev, (void *)&ra, mbprint); 425*55143Storek 426*55143Storek /* remember which frame buffer, if any, is to be /dev/fb */ 427*55143Storek fbnode = getpropint(node, "fb", 0); 428*55143Storek 429*55143Storek /* Find the "options" node */ 430*55143Storek node0 = firstchild(node); 431*55143Storek optionsnode = findnode(node0, "options"); 432*55143Storek if (optionsnode == 0) 433*55143Storek panic("no options in OPENPROM"); 434*55143Storek 435*55143Storek /* 436*55143Storek * Locate and configure the ``early'' devices. These must be 437*55143Storek * configured before we can do the rest. For instance, the 438*55143Storek * EEPROM contains the Ethernet address for the LANCE chip. 439*55143Storek * If the device cannot be located or configured, panic. 440*55143Storek */ 441*55143Storek for (ssp = special; *(sp = *ssp) != 0; ssp++) { 442*55143Storek if ((node = findnode(node0, sp)) == 0) { 443*55143Storek printf("could not find %s in OPENPROM\n", sp); 444*55143Storek panic(sp); 445*55143Storek } 446*55143Storek if (!romprop(&ra, sp, node) || 447*55143Storek !config_found(dev, (void *)&ra, mbprint)) 448*55143Storek panic(sp); 449*55143Storek } 450*55143Storek 451*55143Storek /* 452*55143Storek * Configure the rest of the devices, in PROM order. Skip 453*55143Storek * PROM entries that are not for devices, or which must be 454*55143Storek * done before we get here. 455*55143Storek */ 456*55143Storek for (node = node0; node; node = nextsibling(node)) { 457*55143Storek cp = getpropstring(node, "name"); 458*55143Storek for (ssp = special; (sp = *ssp) != NULL; ssp++) 459*55143Storek if (strcmp(cp, sp) == 0) 460*55143Storek break; 461*55143Storek if (sp == NULL && romprop(&ra, cp, node)) { 462*55143Storek #ifdef L1A_HACK 463*55143Storek if (strcmp(cp, "audio") == 0) 464*55143Storek audio = 1; 465*55143Storek if (strcmp(cp, "zs") == 0) 466*55143Storek nzs++; 467*55143Storek if (audio && nzs >= 2) 468*55143Storek (void) splx(11 << 8); /* XXX */ 469*55143Storek #endif 470*55143Storek (void) config_found(dev, (void *)&ra, mbprint); 471*55143Storek } 472*55143Storek } 473*55143Storek } 474*55143Storek 475*55143Storek struct cfdriver mainbuscd = 476*55143Storek { NULL, "mainbus", matchbyname, mainbus_attach, 477*55143Storek DV_DULL, sizeof(struct device) }; 478*55143Storek 479*55143Storek /* 480*55143Storek * findzs() is called from the zs driver (which is, at least in theory, 481*55143Storek * generic to any machine with a Zilog ZSCC chip). It should return the 482*55143Storek * address of the corresponding zs channel. It may not fail, and it 483*55143Storek * may be called before the VM code can be used. Here we count on the 484*55143Storek * FORTH PROM to map in the required zs chips. 485*55143Storek */ 486*55143Storek void * 487*55143Storek findzs(zs) 488*55143Storek int zs; 489*55143Storek { 490*55143Storek register int node, addr; 491*55143Storek 492*55143Storek node = firstchild(findroot()); 493*55143Storek while ((node = findnode(node, "zs")) != 0) { 494*55143Storek if (getpropint(node, "slave", -1) == zs) { 495*55143Storek if ((addr = getpropint(node, "address", 0)) == 0) 496*55143Storek panic("findzs: zs%d not mapped by PROM", zs); 497*55143Storek return ((void *)addr); 498*55143Storek } 499*55143Storek node = nextsibling(node); 500*55143Storek } 501*55143Storek panic("findzs: cannot find zs%d", zs); 502*55143Storek /* NOTREACHED */ 503*55143Storek } 504*55143Storek 505*55143Storek int 506*55143Storek makememarr(ap, max, which) 507*55143Storek register struct memarr *ap; 508*55143Storek int max, which; 509*55143Storek { 510*55143Storek struct v2rmi { 511*55143Storek int zero; 512*55143Storek int addr; 513*55143Storek int len; 514*55143Storek } v2rmi[200]; /* version 2 rom meminfo layout */ 515*55143Storek #define MAXMEMINFO (sizeof(v2rmi) / sizeof(*v2rmi)) 516*55143Storek register struct v0mlist *mp; 517*55143Storek register int i, node, len; 518*55143Storek char *prop; 519*55143Storek 520*55143Storek switch (i = promvec->pv_romvec_vers) { 521*55143Storek 522*55143Storek case 0: 523*55143Storek /* 524*55143Storek * Version 0 PROMs use a linked list to describe these 525*55143Storek * guys. 526*55143Storek */ 527*55143Storek switch (which) { 528*55143Storek 529*55143Storek case MEMARR_AVAILPHYS: 530*55143Storek mp = *promvec->pv_v0mem.v0_physavail; 531*55143Storek break; 532*55143Storek 533*55143Storek case MEMARR_TOTALPHYS: 534*55143Storek mp = *promvec->pv_v0mem.v0_phystot; 535*55143Storek break; 536*55143Storek 537*55143Storek default: 538*55143Storek panic("makememarr"); 539*55143Storek } 540*55143Storek for (i = 0; mp != NULL; mp = mp->next, i++) { 541*55143Storek if (i >= max) 542*55143Storek goto overflow; 543*55143Storek ap->addr = (u_int)mp->addr; 544*55143Storek ap->len = mp->nbytes; 545*55143Storek ap++; 546*55143Storek } 547*55143Storek break; 548*55143Storek 549*55143Storek default: 550*55143Storek printf("makememarr: hope version %d PROM is like version 2\n", 551*55143Storek i); 552*55143Storek /* FALLTHROUGH */ 553*55143Storek 554*55143Storek case 2: 555*55143Storek /* 556*55143Storek * Version 2 PROMs use a property array to describe them. 557*55143Storek */ 558*55143Storek if (max > MAXMEMINFO) { 559*55143Storek printf("makememarr: limited to %d\n", MAXMEMINFO); 560*55143Storek max = MAXMEMINFO; 561*55143Storek } 562*55143Storek if ((node = findnode(firstchild(findroot()), "memory")) == 0) 563*55143Storek panic("makememarr: cannot find \"memory\" node"); 564*55143Storek switch (which) { 565*55143Storek 566*55143Storek case MEMARR_AVAILPHYS: 567*55143Storek prop = "available"; 568*55143Storek break; 569*55143Storek 570*55143Storek case MEMARR_TOTALPHYS: 571*55143Storek prop = "reg"; 572*55143Storek break; 573*55143Storek 574*55143Storek default: 575*55143Storek panic("makememarr"); 576*55143Storek } 577*55143Storek len = getprop(node, prop, (void *)v2rmi, sizeof v2rmi) / 578*55143Storek sizeof(struct v2rmi); 579*55143Storek for (i = 0; i < len; i++) { 580*55143Storek if (i >= max) 581*55143Storek goto overflow; 582*55143Storek ap->addr = v2rmi[i].addr; 583*55143Storek ap->len = v2rmi[i].len; 584*55143Storek ap++; 585*55143Storek } 586*55143Storek break; 587*55143Storek } 588*55143Storek 589*55143Storek /* 590*55143Storek * Success! (Hooray) 591*55143Storek */ 592*55143Storek if (i == 0) 593*55143Storek panic("makememarr: no memory found"); 594*55143Storek return (i); 595*55143Storek 596*55143Storek overflow: 597*55143Storek /* 598*55143Storek * Oops, there are more things in the PROM than our caller 599*55143Storek * provided space for. Truncate any extras. 600*55143Storek */ 601*55143Storek printf("makememarr: WARNING: lost some memory\n"); 602*55143Storek return (i); 603*55143Storek } 604*55143Storek 605*55143Storek /* 606*55143Storek * Internal form of getprop(). Returns the actual length. 607*55143Storek */ 608*55143Storek int 609*55143Storek getprop(node, name, buf, bufsiz) 610*55143Storek int node; 611*55143Storek char *name; 612*55143Storek void *buf; 613*55143Storek register int bufsiz; 614*55143Storek { 615*55143Storek register struct nodeops *no; 616*55143Storek register int len; 617*55143Storek 618*55143Storek no = promvec->pv_nodeops; 619*55143Storek len = no->no_proplen(node, name); 620*55143Storek if (len > bufsiz) { 621*55143Storek printf("node %x property %s length %d > %d\n", 622*55143Storek node, name, len, bufsiz); 623*55143Storek #ifdef DEBUG 624*55143Storek panic("getprop"); 625*55143Storek #else 626*55143Storek return (0); 627*55143Storek #endif 628*55143Storek } 629*55143Storek no->no_getprop(node, name, buf); 630*55143Storek return (len); 631*55143Storek } 632*55143Storek 633*55143Storek /* 634*55143Storek * Return a string property. There is a (small) limit on the length; 635*55143Storek * the string is fetched into a static buffer which is overwritten on 636*55143Storek * subsequent calls. 637*55143Storek */ 638*55143Storek char * 639*55143Storek getpropstring(node, name) 640*55143Storek int node; 641*55143Storek char *name; 642*55143Storek { 643*55143Storek register int len; 644*55143Storek static char stringbuf[32]; 645*55143Storek 646*55143Storek len = getprop(node, name, (void *)stringbuf, sizeof stringbuf - 1); 647*55143Storek stringbuf[len] = '\0'; /* usually unnecessary */ 648*55143Storek return (stringbuf); 649*55143Storek } 650*55143Storek 651*55143Storek /* 652*55143Storek * Fetch an integer (or pointer) property. 653*55143Storek * The return value is the property, or the default if there was none. 654*55143Storek */ 655*55143Storek int 656*55143Storek getpropint(node, name, deflt) 657*55143Storek int node; 658*55143Storek char *name; 659*55143Storek int deflt; 660*55143Storek { 661*55143Storek register int len; 662*55143Storek char intbuf[16]; 663*55143Storek 664*55143Storek len = getprop(node, name, (void *)intbuf, sizeof intbuf); 665*55143Storek if (len != 4) 666*55143Storek return (deflt); 667*55143Storek return (*(int *)intbuf); 668*55143Storek } 669*55143Storek 670*55143Storek /* 671*55143Storek * OPENPROM functions. These are here mainly to hide the OPENPROM interface 672*55143Storek * from the rest of the kernel. 673*55143Storek */ 674*55143Storek int 675*55143Storek firstchild(node) 676*55143Storek int node; 677*55143Storek { 678*55143Storek 679*55143Storek return (promvec->pv_nodeops->no_child(node)); 680*55143Storek } 681*55143Storek 682*55143Storek int 683*55143Storek nextsibling(node) 684*55143Storek int node; 685*55143Storek { 686*55143Storek 687*55143Storek return (promvec->pv_nodeops->no_nextnode(node)); 688*55143Storek } 689*55143Storek 690*55143Storek /* Pass a string to the FORTH PROM to be interpreted */ 691*55143Storek void 692*55143Storek rominterpret(s) 693*55143Storek register char *s; 694*55143Storek { 695*55143Storek 696*55143Storek if (promvec->pv_romvec_vers < 2) 697*55143Storek promvec->pv_fortheval.v0_eval(strlen(s), s); 698*55143Storek else 699*55143Storek promvec->pv_fortheval.v2_eval(s); 700*55143Storek } 701*55143Storek 702*55143Storek volatile void 703*55143Storek romhalt() 704*55143Storek { 705*55143Storek 706*55143Storek promvec->pv_halt(); 707*55143Storek panic("PROM exit failed"); 708*55143Storek } 709*55143Storek 710*55143Storek volatile void 711*55143Storek romboot(str) 712*55143Storek char *str; 713*55143Storek { 714*55143Storek 715*55143Storek promvec->pv_reboot(str); 716*55143Storek panic("PROM boot failed"); 717*55143Storek } 718*55143Storek 719*55143Storek callrom() 720*55143Storek { 721*55143Storek 722*55143Storek #ifdef notdef /* sun4c FORTH PROMs do this for us */ 723*55143Storek fb_unblank(); 724*55143Storek #endif 725*55143Storek promvec->pv_abort(); 726*55143Storek } 727*55143Storek 728*55143Storek /* 729*55143Storek * Configure swap space and related parameters. 730*55143Storek */ 731*55143Storek swapconf() 732*55143Storek { 733*55143Storek register struct swdevt *swp; 734*55143Storek register int nblks; 735*55143Storek 736*55143Storek for (swp = swdevt; swp->sw_dev; swp++) 737*55143Storek if (bdevsw[major(swp->sw_dev)].d_psize) { 738*55143Storek nblks = 739*55143Storek (*bdevsw[major(swp->sw_dev)].d_psize)(swp->sw_dev); 740*55143Storek if (nblks != -1 && 741*55143Storek (swp->sw_nblks == 0 || swp->sw_nblks > nblks)) 742*55143Storek swp->sw_nblks = nblks; 743*55143Storek } 744*55143Storek dumpconf(); 745*55143Storek } 746*55143Storek 747*55143Storek #define DOSWAP /* Change swdevt, argdev, and dumpdev too */ 748*55143Storek u_long bootdev; /* should be dev_t, but not until 32 bits */ 749*55143Storek 750*55143Storek static char devname[][2] = { 751*55143Storek 0,0, /* 0 = xx */ 752*55143Storek }; 753*55143Storek 754*55143Storek #define PARTITIONMASK 0x7 755*55143Storek #define PARTITIONSHIFT 3 756*55143Storek 757*55143Storek /* 758*55143Storek * Attempt to find the device from which we were booted. 759*55143Storek * If we can do so, and not instructed not to do so, 760*55143Storek * change rootdev to correspond to the load device. 761*55143Storek */ 762*55143Storek setroot() 763*55143Storek { 764*55143Storek #ifdef notyet 765*55143Storek struct swdevt *swp; 766*55143Storek 767*55143Storek if (boothowto & RB_DFLTROOT || 768*55143Storek (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC) 769*55143Storek return; 770*55143Storek majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK; 771*55143Storek if (majdev > sizeof(devname) / sizeof(devname[0])) 772*55143Storek return; 773*55143Storek adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK; 774*55143Storek part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK; 775*55143Storek unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK; 776*55143Storek /* 777*55143Storek * First, find the controller type which support this device. 778*55143Storek */ 779*55143Storek for (hd = hp_dinit; hd->hp_driver; hd++) 780*55143Storek if (hd->hp_driver->d_name[0] == devname[majdev][0] && 781*55143Storek hd->hp_driver->d_name[1] == devname[majdev][1]) 782*55143Storek break; 783*55143Storek if (hd->hp_driver == 0) 784*55143Storek return; 785*55143Storek /* 786*55143Storek * Next, find the controller of that type corresponding to 787*55143Storek * the adaptor number. 788*55143Storek */ 789*55143Storek for (hc = hp_cinit; hc->hp_driver; hc++) 790*55143Storek if (hc->hp_alive && hc->hp_unit == adaptor && 791*55143Storek hc->hp_driver == hd->hp_cdriver) 792*55143Storek break; 793*55143Storek if (hc->hp_driver == 0) 794*55143Storek return; 795*55143Storek /* 796*55143Storek * Finally, find the device in question attached to that controller. 797*55143Storek */ 798*55143Storek for (hd = hp_dinit; hd->hp_driver; hd++) 799*55143Storek if (hd->hp_alive && hd->hp_slave == unit && 800*55143Storek hd->hp_cdriver == hc->hp_driver && 801*55143Storek hd->hp_ctlr == hc->hp_unit) 802*55143Storek break; 803*55143Storek if (hd->hp_driver == 0) 804*55143Storek return; 805*55143Storek mindev = hd->hp_unit; 806*55143Storek /* 807*55143Storek * Form a new rootdev 808*55143Storek */ 809*55143Storek mindev = (mindev << PARTITIONSHIFT) + part; 810*55143Storek orootdev = rootdev; 811*55143Storek rootdev = makedev(majdev, mindev); 812*55143Storek /* 813*55143Storek * If the original rootdev is the same as the one 814*55143Storek * just calculated, don't need to adjust the swap configuration. 815*55143Storek */ 816*55143Storek if (rootdev == orootdev) 817*55143Storek return; 818*55143Storek 819*55143Storek printf("Changing root device to %c%c%d%c\n", 820*55143Storek devname[majdev][0], devname[majdev][1], 821*55143Storek mindev >> PARTITIONSHIFT, part + 'a'); 822*55143Storek 823*55143Storek #ifdef DOSWAP 824*55143Storek mindev &= ~PARTITIONMASK; 825*55143Storek for (swp = swdevt; swp->sw_dev; swp++) { 826*55143Storek if (majdev == major(swp->sw_dev) && 827*55143Storek mindev == (minor(swp->sw_dev) & ~PARTITIONMASK)) { 828*55143Storek temp = swdevt[0].sw_dev; 829*55143Storek swdevt[0].sw_dev = swp->sw_dev; 830*55143Storek swp->sw_dev = temp; 831*55143Storek break; 832*55143Storek } 833*55143Storek } 834*55143Storek if (swp->sw_dev == 0) 835*55143Storek return; 836*55143Storek 837*55143Storek /* 838*55143Storek * If argdev and dumpdev were the same as the old primary swap 839*55143Storek * device, move them to the new primary swap device. 840*55143Storek */ 841*55143Storek if (temp == dumpdev) 842*55143Storek dumpdev = swdevt[0].sw_dev; 843*55143Storek if (temp == argdev) 844*55143Storek argdev = swdevt[0].sw_dev; 845*55143Storek #endif 846*55143Storek #endif 847*55143Storek } 848*55143Storek 849*55143Storek /* 850*55143Storek * Return pointer to device we booted from. Return NULL if we can't 851*55143Storek * figure this out. 852*55143Storek * XXX currently only works for network devices. 853*55143Storek */ 854*55143Storek 855*55143Storek static struct bootinfo * 856*55143Storek findbootdev() 857*55143Storek { 858*55143Storek register struct bootinfo *bi; 859*55143Storek register char *bp; 860*55143Storek register int unit, controller; 861*55143Storek register struct ifnet *ifp; 862*55143Storek 863*55143Storek bi = &bootinfo; 864*55143Storek bp = bi->name; 865*55143Storek printf("findbootdev: (v%d rom) trying \"%s(%x,%x,%x)\"... ", 866*55143Storek promvec->pv_romvec_vers, bp, bi->val[0], bi->val[1], bi->val[2]); 867*55143Storek 868*55143Storek /* Try network devices first */ 869*55143Storek unit = bi->val[0]; 870*55143Storek for (ifp = ifnet; ifp; ifp = ifp->if_next) 871*55143Storek if (unit == ifp->if_unit && strcmp(bp, ifp->if_name) == 0) { 872*55143Storek printf("found \"%s%d\"\n", ifp->if_name, ifp->if_unit); 873*55143Storek bi->type = FS_NFS; 874*55143Storek bi->data = (caddr_t)ifp; 875*55143Storek return (bi); 876*55143Storek } 877*55143Storek printf("not found\n"); 878*55143Storek return (NULL); 879*55143Storek } 880*55143Storek 881*55143Storek gets(cp) 882*55143Storek register char *cp; 883*55143Storek { 884*55143Storek register char *lp; 885*55143Storek register int c; 886*55143Storek 887*55143Storek lp = cp; 888*55143Storek for (;;) { 889*55143Storek c = cngetc(); 890*55143Storek switch (c) { 891*55143Storek case '\n': 892*55143Storek case '\r': 893*55143Storek printf("\n"); 894*55143Storek *lp++ = '\0'; 895*55143Storek return; 896*55143Storek case '\b': 897*55143Storek case '\177': 898*55143Storek case '#': 899*55143Storek if (lp > cp) { 900*55143Storek lp--; 901*55143Storek printf(" \b "); 902*55143Storek } 903*55143Storek continue; 904*55143Storek case '@': 905*55143Storek case 'u'&037: 906*55143Storek lp = cp; 907*55143Storek cnputc('\n'); 908*55143Storek continue; 909*55143Storek default: 910*55143Storek if (c < ' ') 911*55143Storek continue; 912*55143Storek cnputc(c); 913*55143Storek *lp++ = c; 914*55143Storek } 915*55143Storek } 916*55143Storek } 917