155143Storek /* 255143Storek * Copyright (c) 1992 The Regents of the University of California. 355143Storek * All rights reserved. 455143Storek * 555143Storek * This software was developed by the Computer Systems Engineering group 655143Storek * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 755143Storek * contributed to Berkeley. 855143Storek * 9*55504Sbostic * All advertising materials mentioning features or use of this software 10*55504Sbostic * must display the following acknowledgement: 11*55504Sbostic * This product includes software developed by the University of 12*55504Sbostic * California, Lawrence Berkeley Laboratories. 13*55504Sbostic * 1455143Storek * %sccs.include.redist.c% 1555143Storek * 16*55504Sbostic * @(#)autoconf.c 7.2 (Berkeley) 07/21/92 1755143Storek * 1855143Storek * from: $Header: autoconf.c,v 1.23 92/07/10 22:35:23 torek Exp $ (LBL) 1955143Storek */ 2055143Storek 2155143Storek #include "sys/param.h" 2255143Storek #include "sys/map.h" 2355143Storek #include "sys/buf.h" 2455143Storek #include "sys/disklabel.h" 2555143Storek #include "sys/device.h" 2655143Storek #include "sys/dkstat.h" 2755143Storek #include "sys/conf.h" 2855143Storek #include "sys/dmap.h" 2955143Storek #include "sys/reboot.h" 3055143Storek #include "sys/socket.h" 3155143Storek #include "sys/systm.h" 3255143Storek 3355143Storek #include "net/if.h" 3455143Storek 3555143Storek #include "machine/autoconf.h" 3655143Storek #include "machine/bsd_openprom.h" 3755143Storek #include "machine/cpu.h" 3855143Storek 3955143Storek #ifndef FS_NFS /* XXX */ 4055143Storek #define FS_NFS 100 /* XXX */ 4155143Storek #endif /* XXX */ 4255143Storek 4355143Storek /* 4455143Storek * The following several variables are related to 4555143Storek * the configuration process, and are used in initializing 4655143Storek * the machine. 4755143Storek */ 4855143Storek int cold; /* if 1, still working on cold-start */ 4955143Storek int dkn; /* number of iostat dk numbers assigned so far */ 5055143Storek int cpuspeed = 10; /* relative cpu speed */ 5155143Storek int fbnode; /* node ID of ROM's console frame buffer */ 5255143Storek int optionsnode; /* node ID of ROM's options */ 5355143Storek 5455143Storek extern struct promvec *promvec; 5555143Storek 5655143Storek static int rootnode; 5755143Storek int findroot(); 5855143Storek static struct bootinfo *findbootdev(); 5955143Storek 6055143Storek static struct bootinfo { 6155143Storek char name[16]; /* device name */ 6255143Storek int val[3]; /* up to 3 values */ 6355143Storek int type; /* FS type */ 6455143Storek caddr_t data; /* FS dependant info */ 6555143Storek } bootinfo; 6655143Storek 6755143Storek 6855143Storek /* 6955143Storek * Most configuration on the SPARC is done by matching OPENPROM Forth 7055143Storek * device names with our internal names. 7155143Storek */ 7255143Storek int 7355143Storek matchbyname(parent, cf, aux) 7455143Storek struct device *parent; 7555143Storek struct cfdata *cf; 7655143Storek void *aux; 7755143Storek { 7855143Storek 7955143Storek return (strcmp(cf->cf_driver->cd_name, *(char **)aux) == 0); 8055143Storek } 8155143Storek 8255143Storek /* 8355143Storek * Convert hex ASCII string to a value. Returns updated pointer. 8455143Storek * Depends on ASCII order (this *is* machine-dependent code, you know). 8555143Storek */ 8655143Storek static char * 8755143Storek str2hex(str, vp) 8855143Storek register char *str; 8955143Storek register int *vp; 9055143Storek { 9155143Storek register int v, c; 9255143Storek 9355143Storek for (v = 0;; v = v * 16 + c, str++) { 9455143Storek c = *(u_char *)str; 9555143Storek if (c <= '9') { 9655143Storek if ((c -= '0') < 0) 9755143Storek break; 9855143Storek } else if (c <= 'F') { 9955143Storek if ((c -= 'A' - 10) < 10) 10055143Storek break; 10155143Storek } else if (c <= 'f') { 10255143Storek if ((c -= 'a' - 10) < 10) 10355143Storek break; 10455143Storek } else 10555143Storek break; 10655143Storek } 10755143Storek *vp = v; 10855143Storek return (str); 10955143Storek } 11055143Storek 11155143Storek /* 11255143Storek * locore.s code calls bootstrap() just before calling main(), after double 11355143Storek * mapping the kernel to high memory and setting up the trap base register. 11455143Storek * We must finish mapping the kernel properly and glean any bootstrap info. 11555143Storek */ 11655143Storek void 11755143Storek bootstrap() 11855143Storek { 11955143Storek register char *cp, *bp, *ep; 12055143Storek register int i; 12155143Storek int nmmu, ncontext, node; 12255143Storek #ifdef KGDB 12355143Storek extern int kgdb_debug_panic; 12455143Storek #endif 12555143Storek extern char *rindex(const char *, int); 12655143Storek 12755143Storek node = findroot(); 12855143Storek nmmu = getpropint(node, "mmu-npmg", 128); 12955143Storek ncontext = getpropint(node, "mmu-nctx", 8); 13055143Storek pmap_bootstrap(nmmu, ncontext); 13155143Storek #ifdef KGDB 13255143Storek zs_kgdb_init(); /* XXX */ 13355143Storek #endif 13455143Storek /* 13555143Storek * On SS1s, promvec->pv_v0bootargs->ba_argv[1] contains the flags 13655143Storek * that were given after the boot command. On SS2s, pv_v0bootargs 13755143Storek * is NULL but *promvec->pv_v2bootargs.v2_bootargs points to 13855143Storek * "vmunix -s" or whatever. 13955143Storek * ### DO THIS BEFORE pmap_boostrap? 14055143Storek */ 14155143Storek if (promvec->pv_romvec_vers < 2) { 14255143Storek /* Grab boot device name and values. */ 14355143Storek cp = (*promvec->pv_v0bootargs)->ba_argv[0]; 14455143Storek if (cp != NULL) { 14555143Storek bp = bootinfo.name; 14655143Storek ep = &bootinfo.name[sizeof(bootinfo.name)]; 14755143Storek while (*cp != '(' && *cp != '\0' && bp < ep - 1) 14855143Storek *bp++ = *cp++; 14955143Storek *bp = '\0'; 15055143Storek 15155143Storek if (*cp == '(' && 15255143Storek *(cp = str2hex(++cp, &bootinfo.val[0])) == ',' && 15355143Storek *(cp = str2hex(++cp, &bootinfo.val[1])) == ',') 15455143Storek (void)str2hex(++cp, &bootinfo.val[2]); 15555143Storek } 15655143Storek 15755143Storek /* Setup pointer to boot flags */ 15855143Storek cp = (*promvec->pv_v0bootargs)->ba_argv[1]; 15955143Storek if (cp == NULL || *cp != '-') 16055143Storek return; 16155143Storek } else { 16255143Storek /* Grab boot device name and values. */ 16355143Storek cp = *promvec->pv_v2bootargs.v2_bootpath; 16455143Storek if (cp != NULL && (cp = rindex(cp, '/')) != NULL) { 16555143Storek ++cp; 16655143Storek bp = bootinfo.name; 16755143Storek ep = &bootinfo.name[sizeof(bootinfo.name)]; 16855143Storek while (*cp != '@' && *cp != '\0' && bp < ep - 1) 16955143Storek *bp++ = *cp++; 17055143Storek *bp = '\0'; 17155143Storek 17255143Storek if (*cp == '@' && 17355143Storek *(cp = str2hex(++cp, &bootinfo.val[0])) == ',' && 17455143Storek *(cp = str2hex(++cp, &bootinfo.val[1])) == ',') 17555143Storek (void)str2hex(++cp, &bootinfo.val[2]); 17655143Storek } 17755143Storek 17855143Storek /* Setup pointer to boot flags */ 17955143Storek cp = *promvec->pv_v2bootargs.v2_bootargs; 18055143Storek if (cp == NULL) 18155143Storek return; 18255143Storek while (*cp != '-') 18355143Storek if (*cp++ == '\0') 18455143Storek return; 18555143Storek } 18655143Storek for (;;) { 18755143Storek switch (*++cp) { 18855143Storek 18955143Storek case '\0': 19055143Storek return; 19155143Storek 19255143Storek case 'a': 19355143Storek boothowto |= RB_ASKNAME; 19455143Storek break; 19555143Storek 19655143Storek case 'b': 19755143Storek boothowto |= RB_DFLTROOT; 19855143Storek break; 19955143Storek 20055143Storek case 'd': /* kgdb - always on zs XXX */ 20155143Storek #ifdef KGDB 20255143Storek boothowto |= RB_KDB; /* XXX unused */ 20355143Storek kgdb_debug_panic = 1; 20455143Storek kgdb_connect(1); 20555143Storek #else 20655143Storek printf("kernel not compiled with KGDB\n"); 20755143Storek #endif 20855143Storek break; 20955143Storek 21055143Storek case 's': 21155143Storek boothowto |= RB_SINGLE; 21255143Storek break; 21355143Storek } 21455143Storek } 21555143Storek } 21655143Storek 21755143Storek /* 21855143Storek * Determine mass storage and memory configuration for a machine. 21955143Storek * We get the PROM's root device and make sure we understand it, then 22055143Storek * attach it as `mainbus0'. We also set up to handle the PROM `sync' 22155143Storek * command. 22255143Storek */ 22355143Storek configure() 22455143Storek { 22555143Storek register int node; 22655143Storek register char *cp; 22755143Storek struct romaux ra; 22855143Storek void sync_crash(); 22955143Storek #ifdef NFS 23055143Storek register struct bootinfo *bi; 23155143Storek extern int (*mountroot)(), nfs_mountroot(); 23255143Storek #endif 23355143Storek 23455143Storek node = findroot(); 23555143Storek cp = getpropstring(node, "device_type"); 23655143Storek if (strcmp(cp, "cpu") != 0) { 23755143Storek printf("PROM root device type = %s\n", cp); 23855143Storek panic("need CPU as root"); 23955143Storek } 24055143Storek *promvec->pv_synchook = sync_crash; 24155143Storek ra.ra_node = node; 24255143Storek ra.ra_name = cp = "mainbus"; 24355143Storek if (!config_rootfound(cp, (void *)&ra)) 24455143Storek panic("mainbus not configured"); 24555143Storek (void) spl0(); 24655143Storek cold = 0; 24755143Storek #ifdef NFS 24855143Storek if (boothowto & RB_ASKNAME) { 24955143Storek char ans[100]; 25055143Storek 25155143Storek printf("nfs root? (y/n) [n] "); 25255143Storek gets(ans); 25355143Storek if (ans[0] == 'y') 25455143Storek mountroot = nfs_mountroot; 25555143Storek } else if ((bi = findbootdev()) != NULL && bi->type == FS_NFS) { 25655143Storek mountroot = nfs_mountroot; 25755143Storek #ifdef LBL 25855143Storek lbl_diskless_setup(); 25955143Storek #endif /* LBL */ 26055143Storek } 26155143Storek #endif /* NFS */ 26255143Storek #if GENERIC 26355143Storek if ((boothowto & RB_ASKNAME) == 0) 26455143Storek setroot(); 26555143Storek setconf(); 26655143Storek #else 26755143Storek setroot(); 26855143Storek #endif 26955143Storek swapconf(); 27055143Storek } 27155143Storek 27255143Storek /* 27355143Storek * Console `sync' command. SunOS just does a `panic: zero' so I guess 27455143Storek * no one really wants anything fancy... 27555143Storek */ 27655143Storek void 27755143Storek sync_crash() 27855143Storek { 27955143Storek 28055143Storek panic("PROM sync command"); 28155143Storek } 28255143Storek 28355143Storek char * 28455143Storek clockfreq(freq) 28555143Storek register int freq; 28655143Storek { 28755143Storek register char *p; 28855143Storek static char buf[10]; 28955143Storek 29055143Storek freq /= 1000; 29155143Storek sprintf(buf, "%d", freq / 1000); 29255143Storek freq %= 1000; 29355143Storek if (freq) { 29455143Storek freq += 1000; /* now in 1000..1999 */ 29555143Storek p = buf + strlen(buf); 29655143Storek sprintf(p, "%d", freq); 29755143Storek *p = '.'; /* now buf = %d.%3d */ 29855143Storek } 29955143Storek return (buf); 30055143Storek } 30155143Storek 30255143Storek /* ARGSUSED */ 30355143Storek static int 30455143Storek mbprint(aux, name) 30555143Storek void *aux; 30655143Storek char *name; 30755143Storek { 30855143Storek register struct romaux *ra = aux; 30955143Storek 31055143Storek if (name) 31155143Storek printf("%s at %s", ra->ra_name, name); 31255143Storek if (ra->ra_paddr) 31355143Storek printf(" %saddr 0x%x", ra->ra_iospace ? "io" : "", 31455143Storek (int)ra->ra_paddr); 31555143Storek return (UNCONF); 31655143Storek } 31755143Storek 31855143Storek int 31955143Storek findroot() 32055143Storek { 32155143Storek register int node; 32255143Storek 32355143Storek if ((node = rootnode) == 0 && (node = nextsibling(0)) == 0) 32455143Storek panic("no PROM root device"); 32555143Storek rootnode = node; 32655143Storek return (node); 32755143Storek } 32855143Storek 32955143Storek /* 33055143Storek * Given a `first child' node number, locate the node with the given name. 33155143Storek * Return the node number, or 0 if not found. 33255143Storek */ 33355143Storek int 33455143Storek findnode(first, name) 33555143Storek int first; 33655143Storek register char *name; 33755143Storek { 33855143Storek register int node; 33955143Storek 34055143Storek for (node = first; node; node = nextsibling(node)) 34155143Storek if (strcmp(getpropstring(node, "name"), name) == 0) 34255143Storek return (node); 34355143Storek return (0); 34455143Storek } 34555143Storek 34655143Storek /* 34755143Storek * Fill in a romaux. Returns 1 on success, 0 if the register property 34855143Storek * was not the right size. 34955143Storek */ 35055143Storek int 35155143Storek romprop(rp, cp, node) 35255143Storek register struct romaux *rp; 35355143Storek const char *cp; 35455143Storek register int node; 35555143Storek { 35655143Storek register int len; 35755143Storek union { char regbuf[64]; int ireg[3]; } u; 35855143Storek static const char pl[] = "property length"; 35955143Storek 36055143Storek len = getprop(node, "reg", (void *)u.regbuf, sizeof u.regbuf); 36155143Storek if (len < 12) { 36255143Storek printf("%s \"reg\" %s = %d (need 12)\n", cp, pl, len); 36355143Storek return (0); 36455143Storek } 36555143Storek if (len > 12) 36655143Storek printf("warning: %s \"reg\" %s %d > 12, excess ignored\n", 36755143Storek cp, pl, len); 36855143Storek rp->ra_node = node; 36955143Storek rp->ra_name = cp; 37055143Storek rp->ra_iospace = u.ireg[0]; 37155143Storek rp->ra_paddr = (caddr_t)u.ireg[1]; 37255143Storek rp->ra_len = u.ireg[2]; 37355143Storek rp->ra_vaddr = (caddr_t)getpropint(node, "address", 0); 37455143Storek len = getprop(node, "intr", (void *)&rp->ra_intr, sizeof rp->ra_intr); 37555143Storek if (len == -1) 37655143Storek len = 0; 37755143Storek if (len & 7) { 37855143Storek printf("%s \"intr\" %s = %d (need multiple of 8)\n", 37955143Storek cp, pl, len); 38055143Storek len = 0; 38155143Storek } 38255143Storek rp->ra_nintr = len >>= 3; 38355143Storek /* SPARCstation interrupts are not hardware-vectored */ 38455143Storek while (--len >= 0) { 38555143Storek if (rp->ra_intr[len].int_vec) { 38655143Storek printf("WARNING: %s interrupt %d has nonzero vector\n", 38755143Storek cp, len); 38855143Storek break; 38955143Storek } 39055143Storek } 39155143Storek return (1); 39255143Storek } 39355143Storek 39455143Storek /* 39555143Storek * Attach the mainbus. 39655143Storek * 39755143Storek * Our main job is to attach the CPU (the root node we got in configure()) 39855143Storek * and iterate down the list of `mainbus devices' (children of that node). 39955143Storek * We also record the `node id' of the default frame buffer, if any. 40055143Storek */ 40155143Storek static void 40255143Storek mainbus_attach(parent, dev, aux) 40355143Storek struct device *parent, *dev; 40455143Storek void *aux; 40555143Storek { 40655143Storek register int node0, node; 40755143Storek register const char *cp, *const *ssp, *sp; 40855143Storek #define L1A_HACK /* XXX hack to allow L1-A during autoconf */ 40955143Storek #ifdef L1A_HACK 41055143Storek int nzs = 0, audio = 0; 41155143Storek #endif 41255143Storek struct romaux ra; 41355143Storek static const char *const special[] = { 41455143Storek /* find these first (end with empty string) */ 41555143Storek "memory-error", "eeprom", "counter-timer", "", 41655143Storek 41755143Storek /* ignore these (end with NULL) */ 41855143Storek "options", "packages", "openprom", "memory", "virtual-memory", 41955143Storek "interrupt-enable", NULL 42055143Storek }; 42155143Storek 42255143Storek printf("\n"); 42355143Storek 42455143Storek /* configure the cpu */ 42555143Storek node = ((struct romaux *)aux)->ra_node; 42655143Storek ra.ra_node = node; 42755143Storek ra.ra_name = cp = "cpu"; 42855143Storek ra.ra_paddr = 0; 42955143Storek config_found(dev, (void *)&ra, mbprint); 43055143Storek 43155143Storek /* remember which frame buffer, if any, is to be /dev/fb */ 43255143Storek fbnode = getpropint(node, "fb", 0); 43355143Storek 43455143Storek /* Find the "options" node */ 43555143Storek node0 = firstchild(node); 43655143Storek optionsnode = findnode(node0, "options"); 43755143Storek if (optionsnode == 0) 43855143Storek panic("no options in OPENPROM"); 43955143Storek 44055143Storek /* 44155143Storek * Locate and configure the ``early'' devices. These must be 44255143Storek * configured before we can do the rest. For instance, the 44355143Storek * EEPROM contains the Ethernet address for the LANCE chip. 44455143Storek * If the device cannot be located or configured, panic. 44555143Storek */ 44655143Storek for (ssp = special; *(sp = *ssp) != 0; ssp++) { 44755143Storek if ((node = findnode(node0, sp)) == 0) { 44855143Storek printf("could not find %s in OPENPROM\n", sp); 44955143Storek panic(sp); 45055143Storek } 45155143Storek if (!romprop(&ra, sp, node) || 45255143Storek !config_found(dev, (void *)&ra, mbprint)) 45355143Storek panic(sp); 45455143Storek } 45555143Storek 45655143Storek /* 45755143Storek * Configure the rest of the devices, in PROM order. Skip 45855143Storek * PROM entries that are not for devices, or which must be 45955143Storek * done before we get here. 46055143Storek */ 46155143Storek for (node = node0; node; node = nextsibling(node)) { 46255143Storek cp = getpropstring(node, "name"); 46355143Storek for (ssp = special; (sp = *ssp) != NULL; ssp++) 46455143Storek if (strcmp(cp, sp) == 0) 46555143Storek break; 46655143Storek if (sp == NULL && romprop(&ra, cp, node)) { 46755143Storek #ifdef L1A_HACK 46855143Storek if (strcmp(cp, "audio") == 0) 46955143Storek audio = 1; 47055143Storek if (strcmp(cp, "zs") == 0) 47155143Storek nzs++; 47255143Storek if (audio && nzs >= 2) 47355143Storek (void) splx(11 << 8); /* XXX */ 47455143Storek #endif 47555143Storek (void) config_found(dev, (void *)&ra, mbprint); 47655143Storek } 47755143Storek } 47855143Storek } 47955143Storek 48055143Storek struct cfdriver mainbuscd = 48155143Storek { NULL, "mainbus", matchbyname, mainbus_attach, 48255143Storek DV_DULL, sizeof(struct device) }; 48355143Storek 48455143Storek /* 48555143Storek * findzs() is called from the zs driver (which is, at least in theory, 48655143Storek * generic to any machine with a Zilog ZSCC chip). It should return the 48755143Storek * address of the corresponding zs channel. It may not fail, and it 48855143Storek * may be called before the VM code can be used. Here we count on the 48955143Storek * FORTH PROM to map in the required zs chips. 49055143Storek */ 49155143Storek void * 49255143Storek findzs(zs) 49355143Storek int zs; 49455143Storek { 49555143Storek register int node, addr; 49655143Storek 49755143Storek node = firstchild(findroot()); 49855143Storek while ((node = findnode(node, "zs")) != 0) { 49955143Storek if (getpropint(node, "slave", -1) == zs) { 50055143Storek if ((addr = getpropint(node, "address", 0)) == 0) 50155143Storek panic("findzs: zs%d not mapped by PROM", zs); 50255143Storek return ((void *)addr); 50355143Storek } 50455143Storek node = nextsibling(node); 50555143Storek } 50655143Storek panic("findzs: cannot find zs%d", zs); 50755143Storek /* NOTREACHED */ 50855143Storek } 50955143Storek 51055143Storek int 51155143Storek makememarr(ap, max, which) 51255143Storek register struct memarr *ap; 51355143Storek int max, which; 51455143Storek { 51555143Storek struct v2rmi { 51655143Storek int zero; 51755143Storek int addr; 51855143Storek int len; 51955143Storek } v2rmi[200]; /* version 2 rom meminfo layout */ 52055143Storek #define MAXMEMINFO (sizeof(v2rmi) / sizeof(*v2rmi)) 52155143Storek register struct v0mlist *mp; 52255143Storek register int i, node, len; 52355143Storek char *prop; 52455143Storek 52555143Storek switch (i = promvec->pv_romvec_vers) { 52655143Storek 52755143Storek case 0: 52855143Storek /* 52955143Storek * Version 0 PROMs use a linked list to describe these 53055143Storek * guys. 53155143Storek */ 53255143Storek switch (which) { 53355143Storek 53455143Storek case MEMARR_AVAILPHYS: 53555143Storek mp = *promvec->pv_v0mem.v0_physavail; 53655143Storek break; 53755143Storek 53855143Storek case MEMARR_TOTALPHYS: 53955143Storek mp = *promvec->pv_v0mem.v0_phystot; 54055143Storek break; 54155143Storek 54255143Storek default: 54355143Storek panic("makememarr"); 54455143Storek } 54555143Storek for (i = 0; mp != NULL; mp = mp->next, i++) { 54655143Storek if (i >= max) 54755143Storek goto overflow; 54855143Storek ap->addr = (u_int)mp->addr; 54955143Storek ap->len = mp->nbytes; 55055143Storek ap++; 55155143Storek } 55255143Storek break; 55355143Storek 55455143Storek default: 55555143Storek printf("makememarr: hope version %d PROM is like version 2\n", 55655143Storek i); 55755143Storek /* FALLTHROUGH */ 55855143Storek 55955143Storek case 2: 56055143Storek /* 56155143Storek * Version 2 PROMs use a property array to describe them. 56255143Storek */ 56355143Storek if (max > MAXMEMINFO) { 56455143Storek printf("makememarr: limited to %d\n", MAXMEMINFO); 56555143Storek max = MAXMEMINFO; 56655143Storek } 56755143Storek if ((node = findnode(firstchild(findroot()), "memory")) == 0) 56855143Storek panic("makememarr: cannot find \"memory\" node"); 56955143Storek switch (which) { 57055143Storek 57155143Storek case MEMARR_AVAILPHYS: 57255143Storek prop = "available"; 57355143Storek break; 57455143Storek 57555143Storek case MEMARR_TOTALPHYS: 57655143Storek prop = "reg"; 57755143Storek break; 57855143Storek 57955143Storek default: 58055143Storek panic("makememarr"); 58155143Storek } 58255143Storek len = getprop(node, prop, (void *)v2rmi, sizeof v2rmi) / 58355143Storek sizeof(struct v2rmi); 58455143Storek for (i = 0; i < len; i++) { 58555143Storek if (i >= max) 58655143Storek goto overflow; 58755143Storek ap->addr = v2rmi[i].addr; 58855143Storek ap->len = v2rmi[i].len; 58955143Storek ap++; 59055143Storek } 59155143Storek break; 59255143Storek } 59355143Storek 59455143Storek /* 59555143Storek * Success! (Hooray) 59655143Storek */ 59755143Storek if (i == 0) 59855143Storek panic("makememarr: no memory found"); 59955143Storek return (i); 60055143Storek 60155143Storek overflow: 60255143Storek /* 60355143Storek * Oops, there are more things in the PROM than our caller 60455143Storek * provided space for. Truncate any extras. 60555143Storek */ 60655143Storek printf("makememarr: WARNING: lost some memory\n"); 60755143Storek return (i); 60855143Storek } 60955143Storek 61055143Storek /* 61155143Storek * Internal form of getprop(). Returns the actual length. 61255143Storek */ 61355143Storek int 61455143Storek getprop(node, name, buf, bufsiz) 61555143Storek int node; 61655143Storek char *name; 61755143Storek void *buf; 61855143Storek register int bufsiz; 61955143Storek { 62055143Storek register struct nodeops *no; 62155143Storek register int len; 62255143Storek 62355143Storek no = promvec->pv_nodeops; 62455143Storek len = no->no_proplen(node, name); 62555143Storek if (len > bufsiz) { 62655143Storek printf("node %x property %s length %d > %d\n", 62755143Storek node, name, len, bufsiz); 62855143Storek #ifdef DEBUG 62955143Storek panic("getprop"); 63055143Storek #else 63155143Storek return (0); 63255143Storek #endif 63355143Storek } 63455143Storek no->no_getprop(node, name, buf); 63555143Storek return (len); 63655143Storek } 63755143Storek 63855143Storek /* 63955143Storek * Return a string property. There is a (small) limit on the length; 64055143Storek * the string is fetched into a static buffer which is overwritten on 64155143Storek * subsequent calls. 64255143Storek */ 64355143Storek char * 64455143Storek getpropstring(node, name) 64555143Storek int node; 64655143Storek char *name; 64755143Storek { 64855143Storek register int len; 64955143Storek static char stringbuf[32]; 65055143Storek 65155143Storek len = getprop(node, name, (void *)stringbuf, sizeof stringbuf - 1); 65255143Storek stringbuf[len] = '\0'; /* usually unnecessary */ 65355143Storek return (stringbuf); 65455143Storek } 65555143Storek 65655143Storek /* 65755143Storek * Fetch an integer (or pointer) property. 65855143Storek * The return value is the property, or the default if there was none. 65955143Storek */ 66055143Storek int 66155143Storek getpropint(node, name, deflt) 66255143Storek int node; 66355143Storek char *name; 66455143Storek int deflt; 66555143Storek { 66655143Storek register int len; 66755143Storek char intbuf[16]; 66855143Storek 66955143Storek len = getprop(node, name, (void *)intbuf, sizeof intbuf); 67055143Storek if (len != 4) 67155143Storek return (deflt); 67255143Storek return (*(int *)intbuf); 67355143Storek } 67455143Storek 67555143Storek /* 67655143Storek * OPENPROM functions. These are here mainly to hide the OPENPROM interface 67755143Storek * from the rest of the kernel. 67855143Storek */ 67955143Storek int 68055143Storek firstchild(node) 68155143Storek int node; 68255143Storek { 68355143Storek 68455143Storek return (promvec->pv_nodeops->no_child(node)); 68555143Storek } 68655143Storek 68755143Storek int 68855143Storek nextsibling(node) 68955143Storek int node; 69055143Storek { 69155143Storek 69255143Storek return (promvec->pv_nodeops->no_nextnode(node)); 69355143Storek } 69455143Storek 69555143Storek /* Pass a string to the FORTH PROM to be interpreted */ 69655143Storek void 69755143Storek rominterpret(s) 69855143Storek register char *s; 69955143Storek { 70055143Storek 70155143Storek if (promvec->pv_romvec_vers < 2) 70255143Storek promvec->pv_fortheval.v0_eval(strlen(s), s); 70355143Storek else 70455143Storek promvec->pv_fortheval.v2_eval(s); 70555143Storek } 70655143Storek 70755143Storek volatile void 70855143Storek romhalt() 70955143Storek { 71055143Storek 71155143Storek promvec->pv_halt(); 71255143Storek panic("PROM exit failed"); 71355143Storek } 71455143Storek 71555143Storek volatile void 71655143Storek romboot(str) 71755143Storek char *str; 71855143Storek { 71955143Storek 72055143Storek promvec->pv_reboot(str); 72155143Storek panic("PROM boot failed"); 72255143Storek } 72355143Storek 72455143Storek callrom() 72555143Storek { 72655143Storek 72755143Storek #ifdef notdef /* sun4c FORTH PROMs do this for us */ 72855143Storek fb_unblank(); 72955143Storek #endif 73055143Storek promvec->pv_abort(); 73155143Storek } 73255143Storek 73355143Storek /* 73455143Storek * Configure swap space and related parameters. 73555143Storek */ 73655143Storek swapconf() 73755143Storek { 73855143Storek register struct swdevt *swp; 73955143Storek register int nblks; 74055143Storek 74155143Storek for (swp = swdevt; swp->sw_dev; swp++) 74255143Storek if (bdevsw[major(swp->sw_dev)].d_psize) { 74355143Storek nblks = 74455143Storek (*bdevsw[major(swp->sw_dev)].d_psize)(swp->sw_dev); 74555143Storek if (nblks != -1 && 74655143Storek (swp->sw_nblks == 0 || swp->sw_nblks > nblks)) 74755143Storek swp->sw_nblks = nblks; 74855143Storek } 74955143Storek dumpconf(); 75055143Storek } 75155143Storek 75255143Storek #define DOSWAP /* Change swdevt, argdev, and dumpdev too */ 75355143Storek u_long bootdev; /* should be dev_t, but not until 32 bits */ 75455143Storek 75555143Storek static char devname[][2] = { 75655143Storek 0,0, /* 0 = xx */ 75755143Storek }; 75855143Storek 75955143Storek #define PARTITIONMASK 0x7 76055143Storek #define PARTITIONSHIFT 3 76155143Storek 76255143Storek /* 76355143Storek * Attempt to find the device from which we were booted. 76455143Storek * If we can do so, and not instructed not to do so, 76555143Storek * change rootdev to correspond to the load device. 76655143Storek */ 76755143Storek setroot() 76855143Storek { 76955143Storek #ifdef notyet 77055143Storek struct swdevt *swp; 77155143Storek 77255143Storek if (boothowto & RB_DFLTROOT || 77355143Storek (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC) 77455143Storek return; 77555143Storek majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK; 77655143Storek if (majdev > sizeof(devname) / sizeof(devname[0])) 77755143Storek return; 77855143Storek adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK; 77955143Storek part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK; 78055143Storek unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK; 78155143Storek /* 78255143Storek * First, find the controller type which support this device. 78355143Storek */ 78455143Storek for (hd = hp_dinit; hd->hp_driver; hd++) 78555143Storek if (hd->hp_driver->d_name[0] == devname[majdev][0] && 78655143Storek hd->hp_driver->d_name[1] == devname[majdev][1]) 78755143Storek break; 78855143Storek if (hd->hp_driver == 0) 78955143Storek return; 79055143Storek /* 79155143Storek * Next, find the controller of that type corresponding to 79255143Storek * the adaptor number. 79355143Storek */ 79455143Storek for (hc = hp_cinit; hc->hp_driver; hc++) 79555143Storek if (hc->hp_alive && hc->hp_unit == adaptor && 79655143Storek hc->hp_driver == hd->hp_cdriver) 79755143Storek break; 79855143Storek if (hc->hp_driver == 0) 79955143Storek return; 80055143Storek /* 80155143Storek * Finally, find the device in question attached to that controller. 80255143Storek */ 80355143Storek for (hd = hp_dinit; hd->hp_driver; hd++) 80455143Storek if (hd->hp_alive && hd->hp_slave == unit && 80555143Storek hd->hp_cdriver == hc->hp_driver && 80655143Storek hd->hp_ctlr == hc->hp_unit) 80755143Storek break; 80855143Storek if (hd->hp_driver == 0) 80955143Storek return; 81055143Storek mindev = hd->hp_unit; 81155143Storek /* 81255143Storek * Form a new rootdev 81355143Storek */ 81455143Storek mindev = (mindev << PARTITIONSHIFT) + part; 81555143Storek orootdev = rootdev; 81655143Storek rootdev = makedev(majdev, mindev); 81755143Storek /* 81855143Storek * If the original rootdev is the same as the one 81955143Storek * just calculated, don't need to adjust the swap configuration. 82055143Storek */ 82155143Storek if (rootdev == orootdev) 82255143Storek return; 82355143Storek 82455143Storek printf("Changing root device to %c%c%d%c\n", 82555143Storek devname[majdev][0], devname[majdev][1], 82655143Storek mindev >> PARTITIONSHIFT, part + 'a'); 82755143Storek 82855143Storek #ifdef DOSWAP 82955143Storek mindev &= ~PARTITIONMASK; 83055143Storek for (swp = swdevt; swp->sw_dev; swp++) { 83155143Storek if (majdev == major(swp->sw_dev) && 83255143Storek mindev == (minor(swp->sw_dev) & ~PARTITIONMASK)) { 83355143Storek temp = swdevt[0].sw_dev; 83455143Storek swdevt[0].sw_dev = swp->sw_dev; 83555143Storek swp->sw_dev = temp; 83655143Storek break; 83755143Storek } 83855143Storek } 83955143Storek if (swp->sw_dev == 0) 84055143Storek return; 84155143Storek 84255143Storek /* 84355143Storek * If argdev and dumpdev were the same as the old primary swap 84455143Storek * device, move them to the new primary swap device. 84555143Storek */ 84655143Storek if (temp == dumpdev) 84755143Storek dumpdev = swdevt[0].sw_dev; 84855143Storek if (temp == argdev) 84955143Storek argdev = swdevt[0].sw_dev; 85055143Storek #endif 85155143Storek #endif 85255143Storek } 85355143Storek 85455143Storek /* 85555143Storek * Return pointer to device we booted from. Return NULL if we can't 85655143Storek * figure this out. 85755143Storek * XXX currently only works for network devices. 85855143Storek */ 85955143Storek 86055143Storek static struct bootinfo * 86155143Storek findbootdev() 86255143Storek { 86355143Storek register struct bootinfo *bi; 86455143Storek register char *bp; 86555143Storek register int unit, controller; 86655143Storek register struct ifnet *ifp; 86755143Storek 86855143Storek bi = &bootinfo; 86955143Storek bp = bi->name; 87055143Storek printf("findbootdev: (v%d rom) trying \"%s(%x,%x,%x)\"... ", 87155143Storek promvec->pv_romvec_vers, bp, bi->val[0], bi->val[1], bi->val[2]); 87255143Storek 87355143Storek /* Try network devices first */ 87455143Storek unit = bi->val[0]; 87555143Storek for (ifp = ifnet; ifp; ifp = ifp->if_next) 87655143Storek if (unit == ifp->if_unit && strcmp(bp, ifp->if_name) == 0) { 87755143Storek printf("found \"%s%d\"\n", ifp->if_name, ifp->if_unit); 87855143Storek bi->type = FS_NFS; 87955143Storek bi->data = (caddr_t)ifp; 88055143Storek return (bi); 88155143Storek } 88255143Storek printf("not found\n"); 88355143Storek return (NULL); 88455143Storek } 88555143Storek 88655143Storek gets(cp) 88755143Storek register char *cp; 88855143Storek { 88955143Storek register char *lp; 89055143Storek register int c; 89155143Storek 89255143Storek lp = cp; 89355143Storek for (;;) { 89455143Storek c = cngetc(); 89555143Storek switch (c) { 89655143Storek case '\n': 89755143Storek case '\r': 89855143Storek printf("\n"); 89955143Storek *lp++ = '\0'; 90055143Storek return; 90155143Storek case '\b': 90255143Storek case '\177': 90355143Storek case '#': 90455143Storek if (lp > cp) { 90555143Storek lp--; 90655143Storek printf(" \b "); 90755143Storek } 90855143Storek continue; 90955143Storek case '@': 91055143Storek case 'u'&037: 91155143Storek lp = cp; 91255143Storek cnputc('\n'); 91355143Storek continue; 91455143Storek default: 91555143Storek if (c < ' ') 91655143Storek continue; 91755143Storek cnputc(c); 91855143Storek *lp++ = c; 91955143Storek } 92055143Storek } 92155143Storek } 922